Browse Source

[web-client] simple theme: vite plugins plg_svg2png & plg_svg2svg

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Markus Heiser 2 months ago
parent
commit
30ee34d3ea

File diff suppressed because it is too large
+ 403 - 136
client/simple/package-lock.json


+ 2 - 0
client/simple/package.json

@@ -17,11 +17,13 @@
     "less": "^4.2.2",
     "less-loader": "^12.2.0",
     "normalize.css": "^8.0.1",
+    "sharp": "^0.33.5",
     "style-loader": "^4.0.0",
     "stylelint": "^16.14.1",
     "stylelint-config-standard": "^37.0.0",
     "stylelint-config-standard-less": "^3.0.1",
     "stylelint-prettier": "^5.0.3",
+    "svgo": "^3.3.2",
     "vite": "^6.0.7",
     "vite-plugin-static-copy": "^2.2.0",
     "vite-plugin-stylelint": "^6.0.0",

+ 78 - 0
client/simple/tools/img.js

@@ -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 };

+ 41 - 0
client/simple/tools/plg.js

@@ -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 };

+ 48 - 2
client/simple/vite.config.js

@@ -6,6 +6,8 @@ import { resolve } from "node:path";
 import { defineConfig } from "vite";
 import stylelint from "vite-plugin-stylelint";
 import { viteStaticCopy } from "vite-plugin-static-copy";
+import { plg_svg2png } from "./tools/plg.js";
+import { plg_svg2svg } from "./tools/plg.js";
 
 
 const ROOT = "../..";  // root of the git reposetory
@@ -23,7 +25,19 @@ const PATH = {
   templates: resolve(ROOT, "searx/templates/simple"),
 };
 
+const svg2svg_opts = {
+  plugins: [
+    { name: "preset-default" },
+    "sortAttrs",
+    "convertStyleToAttrs",
+  ]
+};
 
+const svg2svg_favicon_opts = {
+  plugins: [
+    { name: "preset-default" },
+    "sortAttrs",
+  ]
 };
 
 
@@ -121,8 +135,40 @@ export default defineConfig({
         { src: PATH.leaflet + "/*.{css,css.map}", dest: PATH.dist + "/css" },
         { src: PATH.static + "/**/*", dest: PATH.dist },
       ]
-    })
-  ],
+    }),
+
+    // SearXNG brand (static)
+
+    plg_svg2png(
+      [
+        { src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.png" },
+        { src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.png" },
+      ],
+    ),
+
+    // -- svg
+    plg_svg2svg(
+      [
+        { src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.svg" },
+        { src: PATH.brand + "/img_load_error.svg", dest: PATH.dist + "/img/img_load_error.svg" },
+      ],
+      svg2svg_opts,
+    ),
+
+    // -- favicon
+    plg_svg2svg(
+      [ { src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.svg" } ],
+      svg2svg_favicon_opts,
+    ),
+
+    // -- simple templates
+    plg_svg2svg(
+      [
+        { src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.templates + "/searxng-wordmark.min.svg" },
+      ],
+      svg2svg_opts
+    ),
+
   ] // end: plugins
 
 });

Some files were not shown because too many files changed in this diff