summaryrefslogtreecommitdiff
path: root/client/simple/tools/jinja_svg_catalog.js
blob: b7b0347b5d9b9466437f89e433844f6377dafe94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import fs from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { Edge } from "edge.js";
import { optimize as svgo } from "svgo";

const __dirname = dirname(fileURLToPath(import.meta.url));
const __jinja_class_placeholder__ = "__jinja_class_placeholder__";

// -- types

/**
 * @typedef {object} IconSet - A set of icons
 * @property {object} set - Object of SVG icons, where property name is the
 * name of the icon and value is the src of the SVG (relative to base).
 * @property {string} base - Folder in which the SVG src files are located.
 * @property {import("svgo").Config} svgo_opts - svgo options for this set.
 */

/**
 * @typedef {object} IconSVG - Mapping of icon name to SVG source file.
 * @property {string} name - Name of the icon isource file.
 * @property {string} src - Name of the destination file.
 * @property {import("svgo").Config} svgo_opts - Options passed to svgo.
 */

/**
 * @typedef {object} JinjaMacro - Arguments to create a jinja macro
 * @property {string} name - Name of the jinja macro.
 * @property {string} class - SVG's class name (value of XML class attribute)
 */

// -- functions

/**
 * Generate a jinja template with a catalog of SVG icons that can be
 * used in in other HTML jinja templates.
 *
 * @param {string} dest - filename of the generate jinja template.
 * @param {JinjaMacro} macros - Jinja macros to create.
 * @param {IconSVG[]} items - Array of SVG items.
 */

function jinja_svg_catalog(dest, macros, items) {
  const svg_catalog = {};
  const edge_template = resolve(__dirname, "jinja_svg_catalog.html.edge");

  items.forEach((item) => {
    /** @type {import("svgo").Config} */
    // JSON.stringify & JSON.parse are used to create a deep copy of the
    // item.svgo_opts object
    const svgo_opts = JSON.parse(JSON.stringify(item.svgo_opts));
    svgo_opts.plugins.push({
      name: "addClassesToSVGElement",
      params: {
        classNames: [__jinja_class_placeholder__]
      }
    });

    try {
      const raw = fs.readFileSync(item.src, "utf8");
      const opt = svgo(raw, svgo_opts);
      svg_catalog[item.name] = opt.data;
    } catch (err) {
      console.error(`ERROR: jinja_svg_catalog processing ${item.name} src: ${item.src} -- ${err}`);
      throw err;
    }
  });

  fs.mkdir(dirname(dest), { recursive: true }, (err) => {
    if (err) throw err;
  });

  const ctx = {
    svg_catalog: svg_catalog,
    macros: macros,
    edge_template: edge_template,
    __jinja_class_placeholder__: __jinja_class_placeholder__,
    // see https://github.com/edge-js/edge/issues/162
    open_curly_brace: "{{",
    close_curly_brace: "}}"
  };

  const jinjatmpl = Edge.create().renderRawSync(fs.readFileSync(edge_template, "utf-8"), ctx);

  fs.writeFileSync(dest, jinjatmpl);
  console.log(`[jinja_svg_catalog] created: ${dest}`);
}

/**
 * Calls jinja_svg_catalog for a collection of icon sets where each set has its
 * own parameters.
 *
 * @param {string} dest - filename of the generate jinja template.
 * @param {JinjaMacro} macros - Jinja macros to create.
 * @param {IconSet[]} sets - Array of SVG sets.
 */
function jinja_svg_sets(dest, macros, sets) {
  /** @type IconSVG[] */
  const items = [];
  const all = [];
  for (const obj of sets) {
    for (const [name, file] of Object.entries(obj.set)) {
      if (all.includes(name)) {
        throw new Error(`ERROR: ${name} has already been defined`);
      }
      items.push({
        name: name,
        src: resolve(obj.base, file),
        svgo_opts: obj.svgo_opts
      });
    }
    jinja_svg_catalog(dest, macros, items);
  }
}

// -- exports

export { jinja_svg_sets, jinja_svg_catalog };