diff options
Diffstat (limited to 'client/simple/tools/jinja_svg_catalog.ts')
| -rw-r--r-- | client/simple/tools/jinja_svg_catalog.ts | 120 |
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); +}; |