Added back SVG optimization

This commit is contained in:
squidfunk 2021-02-21 14:34:17 +01:00
parent 45cfb1024e
commit 4d462c1667
7 changed files with 157 additions and 40 deletions

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
import "~/integrations/search/worker/main"

View File

@ -355,7 +355,7 @@
"base": base_url,
"features": features,
"translations": {},
"search": "assets/javascripts/worker/search.js" | url,
"search": "assets/javascripts/workers/search.js" | url,
} -%}
<!-- Translations -->

View File

@ -34,11 +34,12 @@ import { mkdir, resolve } from "../resolve"
/**
* Copy transform function
*
* @param content - Content
* @param data - File data
* @param name - File name
*
* @returns Transformed content
* @returns Transformed file data
*/
type CopyTransformFn = (content: string) => Promise<string>
type CopyTransformFn = (data: string, name: string) => Promise<string>
/* ------------------------------------------------------------------------- */
@ -71,8 +72,8 @@ export function copy(
? from(fs.copyFile(src, out))
: from(fs.readFile(src, "utf8"))
.pipe(
switchMap(content => transform(content)),
switchMap(content => fs.writeFile(out, content))
switchMap(data => transform(data, src)),
switchMap(data => fs.writeFile(out, data))
)
),
mapTo(out)

View File

@ -22,8 +22,9 @@
import { minify as minhtml } from "html-minifier"
import * as path from "path"
import { concat, merge } from "rxjs"
import { concatMap } from "rxjs/operators"
import { concat, defer, merge } from "rxjs"
import { concatMap, tap } from "rxjs/operators"
import { extendDefaultPlugins, optimize } from "svgo"
import { copyAll } from "./copy"
import { base, resolve } from "./resolve"
@ -48,6 +49,26 @@ function ext(file: string, extension: string): string {
return file.replace(path.extname(file), extension)
}
/**
* Optimize SVG data
*
* This function will just pass-through non-SVG data, which makes the pipeline
* much simpler, as we can reuse it for the license texts.
*
* @param data - SVG data
*
* @returns Minified SVG data
*/
function minsvg(data: string): string {
const result = optimize(data, {
plugins: extendDefaultPlugins([
{ name: "removeDimensions", active: true },
{ name: "removeViewBox", active: false }
])
})
return result.data || data
}
/* ----------------------------------------------------------------------------
* Program
* ------------------------------------------------------------------------- */
@ -59,28 +80,30 @@ const dependencies$ = concat(
...["*.svg", "../LICENSE"]
.map(pattern => copyAll(pattern, {
src: "node_modules/@mdi/svg/svg",
out: `${base}/.icons/material`
out: `${base}/.icons/material`,
...process.argv.includes("--optimize") && {
transform: async data => minsvg(data)
}
})),
/* Copy GitHub octicons */
...["*.svg", "../../LICENSE"]
.map(pattern => copyAll(pattern, {
src: "node_modules/@primer/octicons/build/svg",
out: `${base}/.icons/octicons`
out: `${base}/.icons/octicons`,
...process.argv.includes("--optimize") && {
transform: async data => minsvg(data)
}
})),
/* Copy FontAwesome icons */
...["**/*.svg", "../LICENSE.txt"]
.map(pattern => copyAll(pattern, {
src: "node_modules/@fortawesome/fontawesome-free/svgs",
out: `${base}/.icons/fontawesome`
})),
/* Copy Lunr.js search stemmers and segmenter */
...["min/*.js", "tinyseg.js"]
.map(pattern => copyAll(pattern, {
src: "node_modules/lunr-languages",
out: `${base}/assets/javascripts/lunr`
out: `${base}/.icons/fontawesome`,
...process.argv.includes("--optimize") && {
transform: async data => minsvg(data)
}
}))
)
@ -98,7 +121,7 @@ const assets$ = concat(
copyAll("**/*.html", {
src: "src",
out: base,
transform: async content => {
transform: async data => {
const metadata = require("../package.json")
const banner =
"{#-\n" +
@ -106,7 +129,7 @@ const assets$ = concat(
"-#}\n"
/* Normalize line feeds and minify HTML */
const html = content.replace(/\r\n/gm, "\n")
const html = data.replace(/\r\n/gm, "\n")
return banner + minhtml(html, {
collapseBooleanAttributes: true,
includeAutoGeneratedTags: false,
@ -136,36 +159,38 @@ const stylesheets$ = resolve("**/[!_]*.scss", { cwd: "src" })
}))
)
/* Transform scripts with ESBuild */
const javascripts$ = merge(
/* Transform stylesheets with SASS and PostCSS */
const javascripts$ = resolve("**/{bundle,search}.ts", { cwd: "src" })
.pipe(
concatMap(file => transformScript({
src: `src/${file}`,
out: ext(`${base}/${file}`, ".js")
}))
)
/* Transform application */
transformScript({
src: "src/assets/javascripts/index.ts",
out: `${base}/assets/javascripts/bundle.js`
}),
/* Add content hashes to files and replace occurrences */
const manifest$ = defer(() => resolve("**/*.{css,js}", {cwd: base })
.pipe(tap(console.log)))
/* Transform application overrides */
transformScript({
src: "src/overrides/assets/javascripts/index.ts",
out: `${base}/overrides/assets/javascripts/bundle.js`
}),
/* Copy Lunr.js search stemmers and segmenter */
const stemmers$ = ["min/*.js", "tinyseg.js"]
.map(pattern => copyAll(pattern, {
src: "node_modules/lunr-languages",
out: `${base}/assets/javascripts/lunr`
}))
/* Transform search worker */
transformScript({
src: "src/assets/javascripts/integrations/search/worker/main/index.ts",
out: `${base}/assets/javascripts/worker/search.js`
})
)
/* ------------------------------------------------------------------------- */
/* Compile everything */
/* Put everything together */
concat(
dependencies$,
merge(
assets$,
stylesheets$,
javascripts$
)
),
manifest$,
stemmers$
)
.subscribe()
// .subscribe(console.log)

68
typings/svgo/index.d.ts vendored Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* ----------------------------------------------------------------------------
* Types
* ------------------------------------------------------------------------- */
declare module "svgo" {
/**
* Plugin
*/
interface Plugin {
name: string
active: boolean
}
/**
* Optimization configuration
*/
interface OptimizeConfig {
plugins: Plugin[]
}
/**
* Optimization result
*/
interface OptimizeResult {
data: string
}
/**
* Optimize SVG
*
* @param data - SVG data
*
* @returns Optimization result
*/
function optimize(data: string, config: OptimizeConfig): OptimizeResult
/**
* Extend the list of default plugins
*
* @param plugins - Plugins
*
* @returns Plugins
*/
function extendDefaultPlugins(plugins: Plugin[]): Plugin[]
}