esbuild-plugin-inline-image
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -7,2 +7,3 @@ import type { OnLoadArgs, Plugin } from "esbuild"; | ||
filter?: RegExp; | ||
namespace?: string; | ||
}; | ||
@@ -9,0 +10,0 @@ |
143
index.js
@@ -7,72 +7,81 @@ const { stat, readFile } = require("fs/promises"); | ||
} | ||
module.exports = (options = {}) => ({ | ||
name: "inline-image", | ||
setup(build) { | ||
const limit = | ||
typeof options.limit === "string" || typeof options.limit === "number" | ||
? options.limit === 0 || options.limit === "" | ||
? 0 | ||
: parseInt(options.limit, 10) || | ||
parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || defLimit, 10) || | ||
let initCounter = 0; | ||
module.exports = (options = {}) => { | ||
// if user initializes the plugin more than one times (ie. different size for every extension), | ||
// use different name to prevent collisions | ||
initCounter++; | ||
return { | ||
name: `inline-image${initCounter > 1 ? `#${initCounter - 1}` : ""}`, | ||
setup(build) { | ||
const limit = | ||
typeof options.limit === "string" || typeof options.limit === "number" | ||
? options.limit === 0 || options.limit === "" | ||
? 0 | ||
: parseInt(options.limit, 10) || | ||
parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || defLimit, 10) || | ||
parseInt(defLimit, 10) | ||
: typeof options.limit === "function" | ||
? options.limit | ||
: typeof options.limit === "undefined" | ||
? parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || defLimit, 10) || | ||
parseInt(defLimit, 10) | ||
: typeof options.limit === "function" | ||
? options.limit | ||
: typeof options.limit === "undefined" | ||
? parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || defLimit, 10) || | ||
parseInt(defLimit, 10) | ||
: 0; | ||
const extensions = | ||
typeof options.extensions === "object" && | ||
Array.isArray(options.extensions) | ||
? options.extensions | ||
: ["svg", "png", "jpeg", "jpg", "gif", "webp", "avif"]; | ||
const filter = | ||
typeof options.filter === "object" && options.filter instanceof RegExp | ||
? options.filter | ||
: extensions.length > 0 | ||
? new RegExp( | ||
`\\.(${extensions | ||
.map((x) => x && escapeRegExp(x.replace(".", ""))) | ||
.filter(Boolean) | ||
.join("|")})$` | ||
) | ||
: null; | ||
if (limit && filter) { | ||
build.onLoad({ filter }, async (args) => { | ||
let contents; | ||
let loader = "file"; | ||
if (typeof limit === "function") { | ||
const r = limit(args); | ||
if ( | ||
(typeof r === "object" && r instanceof Promise && (await r)) || | ||
(typeof r === "boolean" && r) | ||
) { | ||
contents = await readFile(args.path); | ||
loader = args.loader || "dataurl"; | ||
: 0; | ||
const extensions = | ||
typeof options.extensions === "object" && | ||
Array.isArray(options.extensions) | ||
? options.extensions | ||
: ["svg", "png", "jpeg", "jpg", "gif", "webp", "avif"]; | ||
const filter = | ||
typeof options.filter === "object" && options.filter instanceof RegExp | ||
? options.filter | ||
: extensions.length > 0 | ||
? new RegExp( | ||
`\\.(${extensions | ||
.map((x) => x && escapeRegExp(x.replace(".", ""))) | ||
.filter(Boolean) | ||
.join("|")})$` | ||
) | ||
: null; | ||
const namespace = | ||
typeof options.namespace === "string" ? options.namespace : undefined; | ||
if (limit && filter) { | ||
build.onLoad({ filter, namespace }, async (args) => { | ||
let contents; | ||
let loader = "file"; | ||
if (typeof limit === "function") { | ||
const r = limit(args); | ||
if ( | ||
(typeof r === "object" && r instanceof Promise && (await r)) || | ||
(typeof r === "boolean" && r) | ||
) { | ||
contents = await readFile(args.path); | ||
loader = args.loader || "dataurl"; | ||
} | ||
} else { | ||
const stats = await stat(args.path); | ||
if (stats && stats.size < limit) { | ||
contents = await readFile(args.path); | ||
loader = "dataurl"; | ||
} | ||
} | ||
} else { | ||
const stats = await stat(args.path); | ||
if (stats && stats.size < limit) { | ||
contents = await readFile(args.path); | ||
loader = "dataurl"; | ||
return { | ||
contents, | ||
loader, | ||
}; | ||
}); | ||
} | ||
if (extensions.length > 0) { | ||
const esbuildOptions = build.initialOptions; | ||
if (typeof esbuildOptions.loader !== "object") { | ||
esbuildOptions.loader = {}; | ||
} | ||
extensions.forEach((ext) => { | ||
if (ext) { | ||
esbuildOptions.loader[`.${ext.replace(".", "")}`] = "file"; | ||
} | ||
} | ||
return { | ||
contents, | ||
loader, | ||
}; | ||
}); | ||
} | ||
if (extensions.length > 0) { | ||
const esbuildOptions = build.initialOptions; | ||
if (typeof esbuildOptions.loader !== "object") { | ||
esbuildOptions.loader = {}; | ||
}); | ||
} | ||
extensions.forEach((ext) => { | ||
if (ext) { | ||
esbuildOptions.loader[`.${ext.replace(".", "")}`] = "file"; | ||
} | ||
}); | ||
} | ||
}, | ||
}); | ||
}, | ||
}; | ||
}; |
{ | ||
"name": "esbuild-plugin-inline-image", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"main": "index.js", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/natrim/esbuild-plugin-inline-image.git", |
# esbuild-plugin-inline-image | ||
`esbuild` plugin for inlining yout images conditionaly on size | ||
[esbuild](https://esbuild.github.io/) plugin for inlining yout images conditionaly on size | ||
@@ -61,8 +61,85 @@ Aka. switches loader for image between `file` and `dataurl` depending on size (as in Webpack) | ||
- in case you pass function, the image will be inlined if it returns `true` (or `Promise` that resolves to `true`) | ||
- the function get's passed `onLoad` [args](https://esbuild.github.io/plugins/#load-arguments) | ||
- `extensions`: an array of extensions to work on (default is `[` `"jpg"`, `"jpeg"`, `"png"`, `"gif"`, `"svg"`, `"webp"`, `"avif"` `]`) | ||
- `filter`: you can also pass filter for onLoad directly, but in this case you need to manually set `esbuild` `loader` option for the extensions to `file` | ||
- `filter`: you can also pass filter for onLoad directly, but in this case you need to manually set `esbuild` [loader](https://esbuild.github.io/api/#loader) option for the extensions to `file` | ||
- `namespace`: custom namespace for the plugin to operate on, default's to built-in `file` | ||
## Extras | ||
Use plugin multiple times to have different size for different extensions | ||
```js | ||
esbuild.build({ | ||
... | ||
plugins: [ | ||
... | ||
inlineImage({ | ||
extensions: ["svg", "webp", "avif"] | ||
}), | ||
inlineImage({ | ||
limit: 5000, | ||
extensions: ["jpg", "jpeg", "gif"] | ||
}), | ||
inlineImage({ | ||
limit: 2000, | ||
extensions: ["png"] | ||
}) | ||
] | ||
... | ||
}); | ||
``` | ||
Use function to decide inlining | ||
```js | ||
esbuild.build({ | ||
... | ||
plugins: [ | ||
... | ||
inlineImage({ | ||
limit: ({ path }) => { | ||
// inline only svg, other extensions get only loader set to file | ||
return path.endsWith(".svg"); | ||
} | ||
}), | ||
] | ||
... | ||
}); | ||
``` | ||
Use function to inline all images | ||
```js | ||
esbuild.build({ | ||
... | ||
plugins: [ | ||
... | ||
inlineImage({ | ||
limit: () => true | ||
}) | ||
] | ||
... | ||
}); | ||
``` | ||
Set limit to 0, to disable inlining (extensions will only get registed to `loader`) | ||
```js | ||
esbuild.build({ | ||
... | ||
plugins: [ | ||
... | ||
inlineImage({ | ||
limit: 0 | ||
}) | ||
] | ||
... | ||
}); | ||
``` | ||
## License | ||
Licensed as MIT open source. |
8161
94
145