jinja_svg_catalog.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import fs from "fs";
  2. import { resolve, dirname } from "path";
  3. import { Edge } from 'edge.js';
  4. import { optimize as svgo } from "svgo";
  5. import { fileURLToPath } from 'url';
  6. const __dirname = dirname(fileURLToPath(import.meta.url));
  7. const __jinja_class_placeholder__ = "__jinja_class_placeholder__";
  8. // -- types
  9. /**
  10. * @typedef {object} IconSet - A set of icons
  11. * @property {object[]} set - Array of SVG icons, where property name is the
  12. * name of the icon and value is the src of the SVG (relative to base).
  13. * @property {string} base - Folder in which the SVG src files are located.
  14. * @property {import("svgo").Config} svgo_opts - svgo options for this set.
  15. */
  16. /**
  17. * @typedef {object} IconSVG - Mapping of icon name to SVG source file.
  18. * @property {string} name - Name of the icon isource file.
  19. * @property {string} src - Name of the destination file.
  20. * @property {import("svgo").Config} svgo_opts - Options passed to svgo.
  21. */
  22. /**
  23. * @typedef {object} JinjaMacro - Arguments to create a jinja macro
  24. * @property {string} name - Name of the jinja macro.
  25. * @property {string} class - SVG's class name (value of XML class attribute)
  26. */
  27. // -- functions
  28. /**
  29. * Generate a jinja template with a catalog of SVG icons that can be
  30. * used in in other HTML jinja templates.
  31. *
  32. * @param {string} dest - filename of the generate jinja template.
  33. * @param {JinjaMacro} macros - Jinja macros to create.
  34. * @param {IconSVG[]} items - Array of SVG items.
  35. */
  36. function jinja_svg_catalog(dest, macros, items) {
  37. const svg_catalog = {};
  38. const edge_template = resolve(__dirname, "jinja_svg_catalog.html.edge");
  39. items.forEach(
  40. (item) => {
  41. /** @type {import("svgo").Config} */
  42. // JSON.stringify & JSON.parse are used to create a deep copy of the
  43. // item.svgo_opts object
  44. const svgo_opts = JSON.parse(JSON.stringify(item.svgo_opts));
  45. svgo_opts.plugins.push({
  46. name: "addClassesToSVGElement",
  47. params: {
  48. classNames: [__jinja_class_placeholder__]
  49. }}
  50. );
  51. try {
  52. const raw = fs.readFileSync(item.src, "utf8");
  53. const opt = svgo(raw, svgo_opts);
  54. svg_catalog[item.name] = opt.data;
  55. } catch (err) {
  56. console.error(`ERROR: jinja_svg_catalog processing ${item.name} src: ${item.src} -- ${err}`);
  57. throw(err);
  58. }
  59. }
  60. );
  61. fs.mkdir(dirname(dest), { recursive: true }, (err) => {
  62. if (err) throw err;
  63. });
  64. const ctx = {
  65. svg_catalog: svg_catalog,
  66. macros: macros,
  67. edge_template: edge_template,
  68. __jinja_class_placeholder__: __jinja_class_placeholder__,
  69. // see https://github.com/edge-js/edge/issues/162
  70. open_curly_brace : "{{",
  71. close_curly_brace : "}}"
  72. };
  73. const jinjatmpl = Edge.create().renderRawSync(
  74. fs.readFileSync(edge_template, "utf-8"),
  75. ctx
  76. );
  77. fs.writeFileSync(dest, jinjatmpl);
  78. console.log(`[jinja_svg_catalog] created: ${dest}`);
  79. }
  80. /**
  81. * Calls jinja_svg_catalog for a collection of icon sets where each set has its
  82. * own parameters.
  83. *
  84. * @param {string} dest - filename of the generate jinja template.
  85. * @param {JinjaMacro} macros - Jinja macros to create.
  86. * @param {IconSet[]} sets - Array of SVG sets.
  87. */
  88. function jinja_svg_sets(dest, macros, sets) {
  89. /** @type IconSVG[] */
  90. const items = [];
  91. const all = [];
  92. for (const obj of sets) {
  93. for (const [name, file] of Object.entries(obj.set)) {
  94. if (all.includes(name)) {
  95. throw new Error(`ERROR: ${name} has already been defined`);
  96. }
  97. items.push({
  98. name: name,
  99. src: resolve(obj.base, file),
  100. svgo_opts: obj.svgo_opts,
  101. });
  102. }
  103. jinja_svg_catalog(dest, macros, items);
  104. }
  105. }
  106. // -- exports
  107. export {
  108. jinja_svg_sets,
  109. jinja_svg_catalog,
  110. };