1- let path = require ( "node:path" ) ;
2- let sharp = require ( "sharp" ) ;
3- let svgo = require ( "svgo" ) ;
4- let { readFile } = require ( "node:fs/promises" ) ;
5- let { buildProcessPipeline } = require ( "faucet-pipeline-static/lib/util.js" ) ;
6- let { abort } = require ( "faucet-pipeline-core/lib/util/index.js" ) ;
1+ import path from "node:path" ;
2+ import sharp from "sharp" ;
3+ import svgo from "svgo" ;
4+ import { readFile } from "node:fs/promises" ;
5+ import { buildProcessPipeline } from "faucet-pipeline-static/lib/util.js" ;
6+ import { abort , repr } from "faucet-pipeline-core/lib/util/index.js" ;
7+
8+ export const key = "images" ;
9+ export const bucket = "static" ;
10+
11+ export function plugin ( config , assetManager ) {
12+ let pipeline = config . map ( optimizerConfig => {
13+ let processFile = buildProcessFile ( optimizerConfig ) ;
14+ let { source, target } = optimizerConfig ;
15+ let filter = optimizerConfig . filter ||
16+ withFileExtension ( "avif" , "jpg" , "jpeg" , "png" , "webp" , "svg" ) ;
17+ return buildProcessPipeline ( source , target , processFile , assetManager , filter ) ;
18+ } ) ;
19+
20+ return filepaths => Promise . all ( pipeline . map ( optimize => optimize ( filepaths ) ) ) ;
21+ }
722
823// we can optimize the settings here, but some would require libvips
924// to be compiled with additional stuff
@@ -51,30 +66,8 @@ let settings = {
5166 avif : { }
5267} ;
5368
54- module . exports = {
55- key : "images" ,
56- bucket : "static" ,
57- plugin : faucetImages
58- } ;
59-
60- /** @type FaucetPlugin<Config> */
61- function faucetImages ( config , assetManager ) {
62- let pipeline = config . map ( optimizerConfig => {
63- let processFile = buildProcessFile ( optimizerConfig ) ;
64- let { source, target } = optimizerConfig ;
65- let filter = optimizerConfig . filter ||
66- withFileExtension ( "avif" , "jpg" , "jpeg" , "png" , "webp" , "svg" ) ;
67- return buildProcessPipeline ( source , target , processFile , assetManager , filter ) ;
68- } ) ;
69-
70- return filepaths => Promise . all ( pipeline . map ( optimize => optimize ( filepaths ) ) ) ;
71- }
72-
7369/**
7470 * Returns a function that processes a single file
75- *
76- * @param {Config } config
77- * @returns {ProcessFile }
7871 */
7972function buildProcessFile ( config ) {
8073 return async function ( filename ,
@@ -88,7 +81,6 @@ function buildProcessFile(config) {
8881 await optimizeSVG ( sourcePath ) :
8982 await optimizeBitmap ( sourcePath , format , config ) ;
9083
91- /** @type WriteFileOpts */
9284 let writeOptions = { targetDir } ;
9385 if ( config . fingerprint !== undefined ) {
9486 writeOptions . fingerprint = config . fingerprint ;
@@ -98,6 +90,8 @@ function buildProcessFile(config) {
9890}
9991
10092/**
93+ * Optimize a single SVG
94+ *
10195 * @param {string } sourcePath
10296 * @returns {Promise<string> }
10397 */
@@ -108,15 +102,16 @@ async function optimizeSVG(sourcePath) {
108102 let output = await svgo . optimize ( input , settings . svg ) ;
109103 return output . data ;
110104 } catch ( error ) {
111- abort ( `Only SVG can be converted to SVG: ${ sourcePath } ` ) ;
112- return "" ; // XXX: this is for typescript :joy:
105+ abort ( `Only SVG can be converted to SVG: ${ repr ( sourcePath ) } ` ) ;
113106 }
114107}
115108
116109/**
110+ * Optimize a single bitmap image
111+ *
117112 * @param {string } sourcePath
118113 * @param {string } format
119- * @param {ImageOptions } options
114+ * @param {Object } options
120115 * @returns {Promise<Buffer> }
121116 */
122117async function optimizeBitmap ( sourcePath , format ,
@@ -138,8 +133,6 @@ async function optimizeBitmap(sourcePath, format,
138133
139134 if ( width || height ) {
140135 let fit = crop ? "cover" : "inside" ;
141- // XXX: Fixme
142- // @ts -ignore
143136 image . resize ( { width, height, fit : sharp . fit [ fit ] } ) ;
144137 }
145138
@@ -158,15 +151,15 @@ async function optimizeBitmap(sourcePath, format,
158151 image . avif ( { ...settings . avif , quality } ) ;
159152 break ;
160153 default :
161- abort ( `unsupported format ${ format } . We support: AVIF, JPG, PNG, WebP, SVG` ) ;
154+ abort ( `unsupported format ${ repr ( format ) } . We support: AVIF, JPG, PNG, WebP, SVG` ) ;
162155 }
163156
164157 return image . toBuffer ( ) ;
165158}
166159
167160/**
168161 * @param {string } filepath
169- * @param {TargetPathOpts } opts
162+ * @param {Object } options
170163 * @returns {string }
171164 */
172165function determineTargetPath ( filepath , { format, suffix = "" } ) {
@@ -186,26 +179,11 @@ function withFileExtension(...extensions) {
186179}
187180
188181/**
189- * extname follows this annoying idea that the dot belongs to the extension
182+ * File extension of a filename without the dot
190183 *
191184 * @param {string } filename
192185 * @returns {string }
193186 */
194187function extname ( filename ) {
195188 return path . extname ( filename ) . slice ( 1 ) . toLowerCase ( ) ;
196189}
197-
198- /** @import {
199- * FaucetPlugin,
200- * FaucetPluginOptions,
201- * WriteFileOpts,
202- * Filter,
203- * ProcessFile
204- * } from "faucet-pipeline-static/lib/types.ts"
205- **/
206- /** @import {
207- * Config,
208- * ImageOptions,
209- * TargetPathOpts
210- * } from "./types.ts"
211- **/
0 commit comments