131 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			131 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import fs from "fs"; | ||
|  | import { resolve, dirname } from "path"; | ||
|  | import { Edge } from 'edge.js'; | ||
|  | import { optimize as svgo } from "svgo"; | ||
|  | import { fileURLToPath } from 'url'; | ||
|  | 
 | ||
|  | 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 - Array 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} */ | ||
|  |       const svgo_opts = JSON.parse(JSON.stringify(item.svgo_opts)); | ||
|  |       svgo_opts.plugins.push({ | ||
|  |         name: "addAttributesToSVGElement", | ||
|  |         params: { | ||
|  |           attributes: [{ "class": __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, | ||
|  | }; |