first commit
This commit is contained in:
78
client/simple/tools/img.js
Normal file
78
client/simple/tools/img.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import sharp from "sharp";
|
||||
import { optimize as svgo } from "svgo";
|
||||
|
||||
/**
|
||||
* @typedef {object} Src2Dest - Mapping of src to dest
|
||||
* @property {string} src - Name of the source file.
|
||||
* @property {string} dest - Name of the destination file.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Convert a list of SVG files to PNG.
|
||||
*
|
||||
* @param {Src2Dest[]} items - Array of SVG files (src: SVG, dest:PNG) to convert.
|
||||
*/
|
||||
|
||||
async function svg2png (items) {
|
||||
items.forEach(
|
||||
async (item) => {
|
||||
try {
|
||||
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
|
||||
const info = await sharp(item.src).png({
|
||||
force: true,
|
||||
compressionLevel: 9,
|
||||
palette: true,
|
||||
}).toFile(item.dest);
|
||||
|
||||
console.log(
|
||||
`[svg2png] created ${item.dest} -- bytes: ${info.size}, w:${info.width}px, h:${info.height}px`
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(`ERROR: ${item.dest} -- ${err}`);
|
||||
throw(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Optimize SVG images for WEB.
|
||||
*
|
||||
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
|
||||
* @param {Src2Dest[]} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
|
||||
*/
|
||||
|
||||
async function svg2svg(svgo_opts, items) {
|
||||
items.forEach(
|
||||
async (item) => {
|
||||
try {
|
||||
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
|
||||
const raw = fs.readFileSync(item.src, "utf8");
|
||||
const opt = svgo(raw, svgo_opts);
|
||||
fs.writeFileSync(item.dest, opt.data);
|
||||
console.log(
|
||||
`[svg2svg] optimized: ${item.dest} -- src: ${item.src}`
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
console.error(`ERROR: optimize src: ${item.src} -- ${err}`);
|
||||
throw(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export { svg2png, svg2svg };
|
||||
26
client/simple/tools/jinja_svg_catalog.html.edge
Normal file
26
client/simple/tools/jinja_svg_catalog.html.edge
Normal file
@@ -0,0 +1,26 @@
|
||||
{{--
|
||||
This is a EDGE https://edgejs.dev/ template to generate a HTML Jinja template
|
||||
for the backend. Example output of this EDGE template:
|
||||
- https://github.com/searxng/searxng/blob/master/searx/templates/simple/icons.html
|
||||
--}}
|
||||
{#
|
||||
Catalog of SVG symbols that can be inserted into the HTML output of a Jinja
|
||||
template. This file from:
|
||||
|
||||
client/simple/tools/icon_catalog.edge.html
|
||||
#}
|
||||
|
||||
{%-
|
||||
set catalog = {
|
||||
@each((svg, name) in svg_catalog)
|
||||
'{{{name}}}' : '{{{svg}}}',
|
||||
@end
|
||||
}
|
||||
-%}
|
||||
|
||||
@each(macro in macros)
|
||||
|
||||
{% macro {{ macro.name }}(action, alt) -%}
|
||||
{{ open_curly_brace }} catalog[action] | replace("{{__jinja_class_placeholder__}}", "{{ macro.class }}") | safe {{ close_curly_brace }}
|
||||
{%- endmacro %}
|
||||
@end
|
||||
132
client/simple/tools/jinja_svg_catalog.js
Normal file
132
client/simple/tools/jinja_svg_catalog.js
Normal file
@@ -0,0 +1,132 @@
|
||||
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} */
|
||||
// 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,
|
||||
};
|
||||
41
client/simple/tools/plg.js
Normal file
41
client/simple/tools/plg.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Custom vite plugins to build the web-client components of the simple theme.
|
||||
*
|
||||
* HINT:
|
||||
*
|
||||
* This is an inital implementation for the migration of the build process
|
||||
* from grunt to vite. For fully support (vite: build & serve) more work is
|
||||
* needed.
|
||||
*/
|
||||
|
||||
import { svg2png } from "./img.js";
|
||||
import { svg2svg } from "./img.js";
|
||||
|
||||
/**
|
||||
* Vite plugin to convert a list of SVG files to PNG.
|
||||
*
|
||||
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src: SVG, dest:PNG) to convert.
|
||||
*/
|
||||
function plg_svg2png(items) {
|
||||
return {
|
||||
name: 'searxng-simple-svg2png',
|
||||
apply: 'build', // or 'serve'
|
||||
async writeBundle() { svg2png(items); },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vite plugin to optimize SVG images for WEB.
|
||||
*
|
||||
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
|
||||
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
|
||||
*/
|
||||
function plg_svg2svg(svgo_opts, items) {
|
||||
return {
|
||||
name: 'searxng-simple-svg2png',
|
||||
apply: 'build', // or 'serve'
|
||||
async writeBundle() { svg2svg(items, svgo_opts); },
|
||||
};
|
||||
}
|
||||
|
||||
export { plg_svg2png, plg_svg2svg };
|
||||
Reference in New Issue
Block a user