summaryrefslogtreecommitdiff
path: root/client/simple/tools/jinja_svg_catalog.ts
diff options
context:
space:
mode:
Diffstat (limited to 'client/simple/tools/jinja_svg_catalog.ts')
-rw-r--r--client/simple/tools/jinja_svg_catalog.ts120
1 files changed, 120 insertions, 0 deletions
diff --git a/client/simple/tools/jinja_svg_catalog.ts b/client/simple/tools/jinja_svg_catalog.ts
new file mode 100644
index 000000000..1fa1a6676
--- /dev/null
+++ b/client/simple/tools/jinja_svg_catalog.ts
@@ -0,0 +1,120 @@
+import fs from "node:fs";
+import { dirname, resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+import { Edge } from "edge.js";
+import { type Config as SvgoConfig, optimize as svgo } from "svgo";
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const __jinja_class_placeholder__ = "__jinja_class_placeholder__";
+
+// A set of icons
+export type IconSet = {
+ // Object of SVG icons, where property name is the name of the icon and value is the src of the SVG (relative to base)
+ set: Record<string, string>;
+ // Folder in which the SVG src files are located
+ base: string;
+ // svgo options for this set
+ svgo_opts: SvgoConfig;
+};
+
+// Mapping of icon name to SVG source file
+type IconSVG = {
+ // Name of the icon isource file
+ name: string;
+ // Name of the destination file
+ src: string;
+ // Options passed to svgo
+ svgo_opts: SvgoConfig;
+};
+
+// Arguments to create a jinja macro
+export type JinjaMacro = {
+ // Name of the jinja macro
+ name: string;
+ // SVG's class name (value of XML class attribute)
+ class: string;
+};
+
+/**
+ * Generate a jinja template with a catalog of SVG icons that can be
+ * used in other HTML jinja templates.
+ *
+ * @param dest - filename of the generate jinja template.
+ * @param macros - Jinja macros to create.
+ * @param items - Array of SVG items.
+ */
+export const jinja_svg_catalog = (dest: string, macros: JinjaMacro[], items: IconSVG[]) => {
+ const svg_catalog: Record<string, string> = {};
+ const edge_template = resolve(__dirname, "jinja_svg_catalog.html.edge");
+
+ for (const item of items) {
+ // JSON.stringify & JSON.parse are used to create a deep copy of the item.svgo_opts object
+ const svgo_opts: SvgoConfig = 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 dest - filename of the generate jinja template.
+ * @param macros - Jinja macros to create.
+ * @param sets - Array of SVG sets.
+ */
+export const jinja_svg_sets = (dest: string, macros: JinjaMacro[], sets: IconSet[]) => {
+ const items: IconSVG[] = [];
+ const all: string[] = [];
+
+ 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`);
+ }
+
+ all.push(name);
+ items.push({
+ name: name,
+ src: resolve(obj.base, file),
+ svgo_opts: obj.svgo_opts
+ });
+ }
+ }
+
+ jinja_svg_catalog(dest, macros, items);
+};