5c0abc07b58188b15adb2f0409919eabc8205353cf179ca362d861ca35ce852ddcf91e0cfc9c1f276f5c198505d2182d5f9135f0207434cccc7b312486c0b0 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. 'use strict';
  2. const { visit } = require('../xast.js');
  3. /**
  4. * Plugins engine.
  5. *
  6. * @module plugins
  7. *
  8. * @param {Object} ast input ast
  9. * @param {Object} info extra information
  10. * @param {Array} plugins plugins object from config
  11. * @return {Object} output ast
  12. */
  13. const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => {
  14. for (const plugin of plugins) {
  15. const override = overrides == null ? null : overrides[plugin.name];
  16. if (override === false) {
  17. continue;
  18. }
  19. const params = { ...plugin.params, ...globalOverrides, ...override };
  20. if (plugin.type === 'perItem') {
  21. ast = perItem(ast, info, plugin, params);
  22. }
  23. if (plugin.type === 'perItemReverse') {
  24. ast = perItem(ast, info, plugin, params, true);
  25. }
  26. if (plugin.type === 'full') {
  27. if (plugin.active) {
  28. ast = plugin.fn(ast, params, info);
  29. }
  30. }
  31. if (plugin.type === 'visitor') {
  32. if (plugin.active) {
  33. const visitor = plugin.fn(ast, params, info);
  34. if (visitor != null) {
  35. visit(ast, visitor);
  36. }
  37. }
  38. }
  39. }
  40. return ast;
  41. };
  42. exports.invokePlugins = invokePlugins;
  43. /**
  44. * Direct or reverse per-item loop.
  45. *
  46. * @param {Object} data input data
  47. * @param {Object} info extra information
  48. * @param {Array} plugins plugins list to process
  49. * @param {boolean} [reverse] reverse pass?
  50. * @return {Object} output data
  51. */
  52. function perItem(data, info, plugin, params, reverse) {
  53. function monkeys(items) {
  54. items.children = items.children.filter(function (item) {
  55. // reverse pass
  56. if (reverse && item.children) {
  57. monkeys(item);
  58. }
  59. // main filter
  60. let kept = true;
  61. if (plugin.active) {
  62. kept = plugin.fn(item, params, info) !== false;
  63. }
  64. // direct pass
  65. if (!reverse && item.children) {
  66. monkeys(item);
  67. }
  68. return kept;
  69. });
  70. return items;
  71. }
  72. return monkeys(data);
  73. }
  74. const createPreset = ({ name, plugins }) => {
  75. return {
  76. name,
  77. type: 'full',
  78. fn: (ast, params, info) => {
  79. const { floatPrecision, overrides } = params;
  80. const globalOverrides = {};
  81. if (floatPrecision != null) {
  82. globalOverrides.floatPrecision = floatPrecision;
  83. }
  84. if (overrides) {
  85. for (const [pluginName, override] of Object.entries(overrides)) {
  86. if (override === true) {
  87. console.warn(
  88. `You are trying to enable ${pluginName} which is not part of preset.\n` +
  89. `Try to put it before or after preset, for example\n\n` +
  90. `plugins: [\n` +
  91. ` {\n` +
  92. ` name: 'preset-default',\n` +
  93. ` },\n` +
  94. ` 'cleanupListOfValues'\n` +
  95. `]\n`
  96. );
  97. }
  98. }
  99. }
  100. return invokePlugins(ast, info, plugins, overrides, globalOverrides);
  101. },
  102. };
  103. };
  104. exports.createPreset = createPreset;