inline-source
Advanced tools
Comparing version 7.2.0 to 8.0.0
@@ -0,15 +1,70 @@ | ||
export type Handler = ( | ||
source: Source, | ||
context: Context | ||
) => Promise<void> | void; | ||
export interface Context { | ||
attribute: string | boolean; | ||
compress: boolean; | ||
fs: typeof import('node:fs'); | ||
html: string; | ||
htmlpath: string; | ||
ignore: Array<string>; | ||
pretty: boolean; | ||
rootpath: string; | ||
re: RegExp; | ||
saveRemote: boolean; | ||
sources: Array<Source>; | ||
stack: Array<Handler>; | ||
swallowErrors: boolean; | ||
svgAsImage: boolean; | ||
} | ||
export interface Source { | ||
attributes: Record<string, string | boolean>; | ||
compress: boolean; | ||
content: null | string; | ||
errored: boolean; | ||
extension: string; | ||
fileContent: string; | ||
filepath: string; | ||
filepathAnchor: string; | ||
format: string; | ||
isRemote: boolean; | ||
match: string; | ||
padding: string; | ||
parentContext: Context; | ||
props: Record<string, string | boolean>; | ||
replace: string; | ||
sourcepath: string | boolean; | ||
stack: Array<Handler>; | ||
svgAsImage: boolean; | ||
tag: string; | ||
type: string; | ||
} | ||
export interface Options { | ||
attribute: string | boolean; | ||
compress: boolean; | ||
fs: any; // like MemoryFileSystem | ||
preHandlers: [(source: any, context: any) => Promise<any>]; | ||
handlers: [(source: any, context: any) => Promise<any>]; | ||
ignore: string[] | { [key: string]: string }; | ||
pretty: boolean; | ||
rootpath: string; | ||
saveRemote: boolean; | ||
svgAsImage: boolean; | ||
swallowErrors: boolean; | ||
attribute?: string | boolean; | ||
compress?: boolean; | ||
fs?: typeof import('node:fs'); | ||
preHandlers?: Array<Handler>; | ||
handlers?: Array<Handler>; | ||
ignore?: Array<string> | Record<string, string>; | ||
pretty?: boolean; | ||
rootpath?: string; | ||
saveRemote?: boolean; | ||
svgAsImage?: boolean; | ||
swallowErrors?: boolean; | ||
} | ||
export function inlineSource(htmlpath: string, options?: Partial<Options>): Promise<string>; | ||
/** | ||
* Parse `htmlpath` content for tags containing an `inline` attribute, | ||
* and replace with (optionally compressed) file contents. | ||
*/ | ||
export function inlineSource( | ||
/** | ||
* Path to html file or raw string of html | ||
*/ | ||
htmlpath: string, | ||
options?: Options | ||
): Promise<string>; |
610
index.js
@@ -1,52 +0,582 @@ | ||
'use strict'; | ||
// src/css.js | ||
import { minify } from "csso"; | ||
async function css(source) { | ||
if (source.fileContent && !source.content && source.type == "css") { | ||
source.content = source.compress ? minify(source.fileContent).css : source.fileContent; | ||
source.tag = "style"; | ||
} | ||
} | ||
const { isFilepath } = require('./lib/utils'); | ||
const context = require('./lib/context'); | ||
const path = require('path'); | ||
const parse = require('./lib/parse'); | ||
const run = require('./lib/run'); | ||
// src/context.js | ||
import fs from "node:fs"; | ||
/** | ||
* Inline sources found in 'htmlpath' | ||
* @param {String} htmlpath | ||
* @param {Object} options | ||
* - {String} attribute | ||
* - {Boolean} compress | ||
* - {Object} fs | ||
* - {Array} handlers | ||
* - {Array} ignore | ||
* - {Boolean} pretty | ||
* - {String} rootpath | ||
* - {Boolean} swallowErrors | ||
* - {Boolean} svgAsImage | ||
* @returns {Promise<String>} | ||
*/ | ||
exports.inlineSource = function inlineSource(htmlpath, options = {}) { | ||
return new Promise(async (resolve, reject) => { | ||
const ctx = context.create(options); | ||
// src/utils.js | ||
import { URL } from "node:url"; | ||
import path from "node:path"; | ||
var ATTRIBUTE_BLACKLIST = [ | ||
"href", | ||
"rel", | ||
"src", | ||
"data", | ||
"xmlns", | ||
"xmlns:xlink", | ||
"version", | ||
"baseprofile" | ||
]; | ||
var RE_ANY = /<(script|link|img|object)\s?[^>]*?>(?:<\/\1\s?>)?/gm; | ||
var RE_ESCAPE = /[-/\\^$*+?.()|[\]{}]/g; | ||
var RE_NOT_FILEPATH = /[\r\n<>]|^data:/gm; | ||
var RE_QUERY = /\?[^#]*/g; | ||
var RE_REMOTE = /^https?:\/\//; | ||
var RE_FORWARD_SLASH = /\//g; | ||
function escape(str) { | ||
return str.replace(RE_ESCAPE, "\\$&"); | ||
} | ||
function getAttributeString(attributes, prefix, strict) { | ||
prefix = String(prefix); | ||
let str = ""; | ||
for (const prop in attributes) { | ||
const include = strict ? prop.indexOf(prefix) != 0 && !ATTRIBUTE_BLACKLIST.includes(prop) : prop.indexOf(prefix) != 0; | ||
if (include) { | ||
str += attributes[prop] === true ? ` ${prop}` : ` ${prop}="${attributes[prop]}"`; | ||
} | ||
} | ||
return str; | ||
} | ||
function getFormatFromExtension(extension) { | ||
switch (extension) { | ||
case "js": | ||
return "js"; | ||
case "json": | ||
return "json"; | ||
case "css": | ||
return "css"; | ||
case "gif": | ||
return "gif"; | ||
case "png": | ||
return "png"; | ||
case "jpeg": | ||
case "jpg": | ||
return "jpeg"; | ||
case "svg": | ||
return "svg+xml"; | ||
} | ||
return extension; | ||
} | ||
function getPadding(source, html) { | ||
const re = new RegExp(`^([\\t ]+)${escape(source)}`, "gm"); | ||
const match = re.exec(html); | ||
return match ? match[1] : ""; | ||
} | ||
function getSourcepath(filepath, htmlpath, rootpath) { | ||
let sourcepath = filepath; | ||
if (!sourcepath) { | ||
return ["", ""]; | ||
} | ||
if (isRemoteFilepath(sourcepath)) { | ||
const url = new URL(sourcepath); | ||
sourcepath = `./${url.pathname.slice(1).replace(RE_FORWARD_SLASH, "_")}`; | ||
} | ||
sourcepath = sourcepath.replace(RE_QUERY, ""); | ||
if (htmlpath && isRelativeFilepath(sourcepath)) { | ||
sourcepath = path.resolve(path.dirname(htmlpath), sourcepath); | ||
} else if (sourcepath.indexOf("/") == 0) { | ||
sourcepath = sourcepath.slice(1); | ||
} | ||
if (sourcepath.includes("#")) { | ||
sourcepath = sourcepath.split("#"); | ||
} | ||
return Array.isArray(sourcepath) ? [path.resolve(rootpath, sourcepath[0]), sourcepath[1]] : [path.resolve(rootpath, sourcepath), ""]; | ||
} | ||
function getTagRegExp(attribute) { | ||
if (attribute) { | ||
return new RegExp( | ||
"<([a-zA-Z]+)\\b[^>]*?\\s(?:" + attribute + "\\b[^>]*?|" + attribute + "|" + attribute + `=([\\'\\"])(?:true|` + attribute + ")\\2[^>]*?)>(?:<\\/\\1\\s?>)?", | ||
"gm" | ||
); | ||
} | ||
return RE_ANY; | ||
} | ||
function getTypeFromType(type) { | ||
switch (type) { | ||
case "application/javascript": | ||
case "application/x-javascript": | ||
case "application/ecmascript": | ||
case "text/javascript": | ||
case "text/form-script": | ||
case "text/ecmascript": | ||
case "javascript": | ||
case "js": | ||
case "ecmascript": | ||
case "module": | ||
return "js"; | ||
case "text/css": | ||
case "css": | ||
return "css"; | ||
case "image/png": | ||
case "image/gif": | ||
case "image/jpeg": | ||
case "image/jpg": | ||
case "image/svg+xml": | ||
case "image/svg": | ||
case "png": | ||
case "gif": | ||
case "jpeg": | ||
case "jpg": | ||
case "svg": | ||
case "image": | ||
return "image"; | ||
case "application/json": | ||
case "text/json": | ||
case "json": | ||
return "json"; | ||
} | ||
return type; | ||
} | ||
function getTypeFromTag(tag) { | ||
switch (tag) { | ||
case "script": | ||
return "js"; | ||
case "link": | ||
return "css"; | ||
case "img": | ||
case "object": | ||
return "image"; | ||
} | ||
return ""; | ||
} | ||
function isFilepath(str) { | ||
RE_NOT_FILEPATH.lastIndex = 0; | ||
if (str && typeof str === "string") { | ||
return !RE_NOT_FILEPATH.test(str); | ||
} | ||
return false; | ||
} | ||
function isIgnored(ignore, tag, type, format) { | ||
const formatAlt = format && format.indexOf("+") ? format.split("+")[0] : null; | ||
if (!Array.isArray(ignore)) { | ||
ignore = [ignore]; | ||
} | ||
return Boolean( | ||
ignore.includes(tag) || ignore.includes(type) || ignore.includes(format) || formatAlt && ignore.includes(formatAlt) | ||
); | ||
} | ||
function isRelativeFilepath(str) { | ||
if (str) { | ||
return isFilepath(str) && (str.indexOf("./") == 0 || str.indexOf("../") == 0); | ||
} | ||
return false; | ||
} | ||
function isRemoteFilepath(str) { | ||
if (str && typeof str === "string") { | ||
return isFilepath(str) && RE_REMOTE.test(str); | ||
} | ||
return false; | ||
} | ||
function parseAttributes(attributes) { | ||
for (const prop in attributes) { | ||
if (attributes[prop] === "") { | ||
attributes[prop] = true; | ||
} | ||
} | ||
return attributes; | ||
} | ||
function parseProps(attributes, prefix) { | ||
const props = {}; | ||
if (typeof prefix === "string") { | ||
prefix += "-"; | ||
for (const prop in attributes) { | ||
if (prop.indexOf(prefix) == 0) { | ||
let value = attributes[prop]; | ||
if (value === "false") { | ||
value = false; | ||
} | ||
if (value === "true") { | ||
value = true; | ||
} | ||
props[prop.slice(prefix.length)] = value; | ||
} | ||
} | ||
} | ||
return props; | ||
} | ||
// Load html content | ||
if (isFilepath(htmlpath)) { | ||
ctx.htmlpath = path.resolve(htmlpath); | ||
try { | ||
ctx.html = ctx.fs.readFileSync(ctx.htmlpath, 'utf8'); | ||
} catch (err) { | ||
return reject(err); | ||
// src/inline.js | ||
function inline(source, context) { | ||
if (source.replace) { | ||
context.html = context.html.replace(source.match, () => source.replace); | ||
} | ||
} | ||
// src/js.js | ||
import { minify as minify2 } from "terser"; | ||
var RE_SCRIPT = /(<)(\/script>)/gi; | ||
async function js(source) { | ||
if (source.fileContent && !source.content && source.type == "js") { | ||
let content; | ||
if (!source.compress) { | ||
content = source.fileContent; | ||
} else { | ||
const compressed = await minify2(source.fileContent); | ||
content = compressed.code; | ||
} | ||
if (RE_SCRIPT.test(content)) { | ||
content = content.replace(RE_SCRIPT, "\\x3C$2"); | ||
} | ||
source.content = content; | ||
} | ||
} | ||
// src/imgSVG.js | ||
import { DefaultHandler, Parser } from "htmlparser2"; | ||
import { optimize } from "svgo"; | ||
var DEFAULT_SVG_ATTR = { | ||
x: "0", | ||
y: "0", | ||
viewBox: "0 0 100 100" | ||
}; | ||
var RE_SVG_CONTENT = /<svg[^>]+>([\S\s]*?)<\/\s?svg>/gm; | ||
var RE_SYMBOL = /<symbol\sid=['"]([^'"]+)[\S\s]*?<\/\s?symbol>/gm; | ||
async function imgSVG(source, context, svgoConfig) { | ||
RE_SVG_CONTENT.lastIndex = 0; | ||
const svgContent = RE_SVG_CONTENT.exec(source.fileContent) || source.fileContent; | ||
const defaultAttributes = Array.isArray(svgContent) ? {} : DEFAULT_SVG_ATTR; | ||
let attributes = {}; | ||
const parser = new Parser( | ||
new DefaultHandler((err, dom) => { | ||
if (err) { | ||
throw err; | ||
} | ||
// Passed file content instead of path | ||
dom = dom.filter((item) => item.type == "tag" && item.name == "svg"); | ||
if (dom.length) { | ||
attributes = parseAttributes( | ||
dom[0].attribs | ||
); | ||
if ("viewbox" in attributes) { | ||
attributes.viewBox = attributes.viewbox; | ||
delete attributes.viewbox; | ||
} | ||
} | ||
}) | ||
); | ||
parser.parseComplete(source.fileContent); | ||
source.content = Array.isArray(svgContent) ? svgContent[1] : svgContent; | ||
source.attributes = Object.assign( | ||
{}, | ||
defaultAttributes, | ||
attributes, | ||
source.attributes | ||
); | ||
if ("alt" in source.attributes) { | ||
delete source.attributes.alt; | ||
} | ||
source.tag = "svg"; | ||
if (source.filepathAnchor) { | ||
RE_SYMBOL.lastIndex = 0; | ||
const includedIds = source.filepathAnchor.split(","); | ||
let content = source.content; | ||
let match; | ||
while (match = RE_SYMBOL.exec(source.content)) { | ||
if (!includedIds.includes(match[1])) { | ||
content = content.replace(match[0], ""); | ||
} | ||
} | ||
source.content = content; | ||
} | ||
if (source.compress) { | ||
const attrs = getAttributeString( | ||
source.attributes, | ||
context.attribute, | ||
false | ||
); | ||
const content = `<svg${attrs}>${source.content}</svg>`; | ||
const result = await optimize(content, svgoConfig); | ||
if ("data" in result) { | ||
RE_SVG_CONTENT.lastIndex = 0; | ||
const rematch = RE_SVG_CONTENT.exec(result.data); | ||
if (rematch) { | ||
source.content = rematch[1]; | ||
} else { | ||
source.replace = result.data; | ||
} | ||
} else { | ||
ctx.html = htmlpath; | ||
} | ||
} | ||
} | ||
// src/img.js | ||
import { optimize as optimize2 } from "svgo"; | ||
var RE_XML_TAG = /<\?xml.+?\?>\s+/g; | ||
var SVGO_CONFIG = { | ||
plugins: [ | ||
"removeDoctype", | ||
"removeXMLProcInst", | ||
"removeComments", | ||
"removeMetadata", | ||
"removeEditorsNSData", | ||
"cleanupAttrs", | ||
"mergeStyles", | ||
"inlineStyles", | ||
"minifyStyles", | ||
"cleanupNumericValues", | ||
"convertColors", | ||
"removeNonInheritableGroupAttrs", | ||
"removeUselessStrokeAndFill", | ||
"removeViewBox", | ||
"cleanupEnableBackground", | ||
"removeHiddenElems", | ||
"removeEmptyText", | ||
"convertShapeToPath", | ||
"convertEllipseToCircle", | ||
"moveElemsAttrsToGroup", | ||
"moveGroupAttrsToElems", | ||
"collapseGroups", | ||
"convertPathData", | ||
"convertTransform", | ||
"removeEmptyContainers", | ||
"mergePaths", | ||
"removeUnusedNS", | ||
"sortDefsChildren", | ||
"removeTitle", | ||
"removeDesc" | ||
] | ||
}; | ||
async function img(source, context) { | ||
if (source.fileContent && !source.content && source.type == "image") { | ||
const attributeType = source.attributes.type; | ||
let strict = !source.errored; | ||
let sourceProp = "src"; | ||
let data, encoding; | ||
delete source.attributes.type; | ||
const isIcon = source.attributes.rel == "icon"; | ||
if (source.format == "svg+xml" && !isIcon) { | ||
if (!source.svgAsImage) { | ||
await imgSVG(source, context, SVGO_CONFIG); | ||
return; | ||
} | ||
source.tag = "img"; | ||
source.content = source.fileContent.replace(RE_XML_TAG, ""); | ||
if (source.compress) { | ||
const result = await optimize2(source.content, SVGO_CONFIG); | ||
if ("data" in result) { | ||
source.content = result.data; | ||
} else { | ||
} | ||
} | ||
data = encodeURIComponent(source.content); | ||
encoding = "charset=utf8"; | ||
} else { | ||
data = Buffer.from(source.fileContent).toString("base64"); | ||
encoding = "base64"; | ||
if (source.tag == "link") { | ||
source.attributes.type = attributeType; | ||
sourceProp = "href"; | ||
strict = false; | ||
delete source.attributes.href; | ||
} | ||
} | ||
const src = `data:image/${source.format};${encoding},${data}`; | ||
let attrs = getAttributeString( | ||
source.attributes, | ||
context.attribute, | ||
strict | ||
); | ||
attrs += ` ${sourceProp}="${src}"`; | ||
source.content = src; | ||
source.replace = `<${source.tag}${attrs}/>`; | ||
} | ||
} | ||
// src/load.js | ||
import fetch from "node-fetch"; | ||
async function load(source, context) { | ||
if (!source.fileContent && source.filepath) { | ||
const encoding = source.type == "image" && source.format != "svg+xml" ? null : "utf8"; | ||
try { | ||
await parse(ctx); | ||
if (ctx.sources.length > 0) { | ||
await run(ctx, ctx.sources, ctx.swallowErrors); | ||
source.fileContent = context.fs.readFileSync(source.filepath, encoding); | ||
} catch (err) { | ||
if (!source.isRemote) { | ||
throw err; | ||
} | ||
} catch (err) { | ||
return reject(err); | ||
} | ||
if (source.isRemote) { | ||
const res = await fetch(source.sourcepath); | ||
if (!res.ok) { | ||
throw Error( | ||
res.status === 404 ? "Not found" : `Fetch error: ${res.status}` | ||
); | ||
} | ||
const text = await res.text(); | ||
if (context.saveRemote) { | ||
try { | ||
context.fs.writeFileSync(source.filepath, text, "utf8"); | ||
} catch (err) { | ||
} | ||
} | ||
source.fileContent = text; | ||
} | ||
} | ||
} | ||
resolve(ctx.html); | ||
}); | ||
// src/context.js | ||
import path2 from "node:path"; | ||
// src/wrap.js | ||
var RE_BEGIN_LINE = /^./gm; | ||
function wrap(source, context) { | ||
if (source.content !== null && !source.replace) { | ||
const attrs = getAttributeString( | ||
source.attributes, | ||
context.attribute, | ||
!source.errored | ||
); | ||
const closing = source.tag != "link" ? `</${source.tag}>` : ""; | ||
const content = context.pretty ? ` | ||
${source.content.replace(RE_BEGIN_LINE, source.padding + "$&")} | ||
${source.padding}` : source.content; | ||
source.replace = `<${source.tag + attrs}>${content}${closing}`; | ||
} | ||
} | ||
// src/context.js | ||
var DEFAULT = { | ||
compress: true, | ||
fs, | ||
html: "", | ||
htmlpath: "", | ||
ignore: [], | ||
pretty: false, | ||
saveRemote: true, | ||
swallowErrors: false, | ||
svgAsImage: false | ||
}; | ||
function createContext(options = {}) { | ||
const { attribute = "inline", handlers = [], preHandlers = [] } = options; | ||
const context = Object.assign( | ||
{ | ||
attribute, | ||
re: getTagRegExp(attribute), | ||
rootpath: process.cwd(), | ||
sources: [], | ||
stack: [...preHandlers, load, ...handlers, js, css, img, wrap, inline] | ||
}, | ||
DEFAULT, | ||
options | ||
); | ||
if (options.rootpath) { | ||
context.rootpath = path2.resolve(options.rootpath); | ||
} | ||
if (options.pretty == true && context.compress == false) { | ||
context.pretty = true; | ||
} | ||
return context; | ||
} | ||
// src/index.js | ||
import path4 from "node:path"; | ||
// src/parse.js | ||
import { DefaultHandler as DefaultHandler2, Parser as Parser2 } from "htmlparser2"; | ||
import path3 from "node:path"; | ||
var RE_COMMENT = /(<!--[^[i][\S\s]+?--\s?>)/gm; | ||
async function parse(context) { | ||
const html = context.html.replace(RE_COMMENT, ""); | ||
let match; | ||
const parser = new Parser2( | ||
new DefaultHandler2((err, dom) => { | ||
if (err) { | ||
throw err; | ||
} | ||
const parsed = dom[0]; | ||
if (parsed) { | ||
const [matching, tag] = match; | ||
const attributes = parseAttributes(parsed.attribs); | ||
const props = parseProps(attributes, context.attribute); | ||
const type = getTypeFromType(attributes.type) || getTypeFromTag(tag); | ||
const sourcepath = attributes.src || attributes.href || attributes.data; | ||
if (sourcepath === true || tag === "link" && attributes.rel && attributes.rel !== "stylesheet" && attributes.rel !== "icon") { | ||
return; | ||
} | ||
if (sourcepath === void 0 || isFilepath(sourcepath)) { | ||
const filepath = getSourcepath( | ||
sourcepath, | ||
context.htmlpath, | ||
context.rootpath | ||
); | ||
const extension = path3.extname(filepath[0]).slice(1); | ||
const format = getFormatFromExtension(extension); | ||
if (!isIgnored(context.ignore, tag, type, format)) { | ||
context.sources.push({ | ||
attributes, | ||
compress: "compress" in props ? props.compress : context.compress, | ||
content: null, | ||
errored: false, | ||
extension, | ||
fileContent: "", | ||
filepath: filepath[0], | ||
filepathAnchor: filepath[1], | ||
format, | ||
isRemote: isRemoteFilepath(sourcepath), | ||
match: matching, | ||
padding: context.pretty ? getPadding(matching, context.html) : "", | ||
parentContext: context, | ||
props, | ||
replace: "", | ||
sourcepath, | ||
stack: context.stack, | ||
svgAsImage: "svgasimage" in props ? props.svgasimage : context.svgAsImage, | ||
tag, | ||
type | ||
}); | ||
} | ||
} | ||
} | ||
}) | ||
); | ||
while (match = context.re.exec(html)) { | ||
parser.parseComplete(match[0]); | ||
} | ||
} | ||
// src/run.js | ||
var isTest = process.env.NODE_ENV === "test"; | ||
async function run(context, sources = [], swallowErrors) { | ||
await Promise.all( | ||
sources.map(async (source) => { | ||
for (const handler of source.stack) { | ||
try { | ||
await handler(source, context); | ||
} catch (err) { | ||
if (!swallowErrors) { | ||
throw err; | ||
} | ||
if (!isTest) { | ||
console.warn(err.message); | ||
} | ||
source.content = ""; | ||
source.errored = true; | ||
} | ||
} | ||
}) | ||
); | ||
return context.html; | ||
} | ||
// src/index.js | ||
async function inlineSource(htmlpath, options = {}) { | ||
const ctx = createContext(options); | ||
if (isFilepath(htmlpath)) { | ||
ctx.htmlpath = path4.resolve(htmlpath); | ||
ctx.html = ctx.fs.readFileSync(ctx.htmlpath, "utf8"); | ||
} else { | ||
ctx.html = htmlpath; | ||
} | ||
await parse(ctx); | ||
if (ctx.sources.length > 0) { | ||
await run(ctx, ctx.sources, ctx.swallowErrors); | ||
} | ||
return ctx.html; | ||
} | ||
export { | ||
inlineSource | ||
}; |
{ | ||
"name": "inline-source", | ||
"description": "Inline all flagged js, css, image source files", | ||
"version": "7.2.0", | ||
"author": "popeindustries <alex@pope-industries.com>", | ||
"version": "8.0.0", | ||
"license": "MIT", | ||
"author": "Alexander Pope <alex@pope.industries>", | ||
"keywords": [ | ||
@@ -13,45 +14,47 @@ "inline", | ||
], | ||
"type": "module", | ||
"repository": "git://github.com/popeindustries/inline-source.git", | ||
"main": "index.js", | ||
"exports": { | ||
"types": "./index.d.ts", | ||
"import": "./index.js", | ||
"require": "./index.cjs" | ||
}, | ||
"dependencies": { | ||
"csso": "^4.0.2", | ||
"htmlparser2": "^4.0.0", | ||
"superagent": "^5.1.0", | ||
"svgo": "^1.3.0", | ||
"terser": "^4.1.0" | ||
"csso": "^5.0.5", | ||
"htmlparser2": "^8.0.1", | ||
"node-fetch": "^3.2.10", | ||
"svgo": "^2.8.0", | ||
"terser": "^5.15.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.10.0", | ||
"eslint-plugin-prettier": "^3.1.2", | ||
"handlebars": "^4.7.3", | ||
"husky": "^3.1.0", | ||
"lint-staged": "^9.5.0", | ||
"@types/csso": "5.0.0", | ||
"@types/mocha": "^9.1.1", | ||
"@types/node": "^18.7.18", | ||
"@types/svgo": "^2.6.4", | ||
"@typescript-eslint/eslint-plugin": "^5.37.0", | ||
"@typescript-eslint/parser": "^5.37.0", | ||
"chai": "^4.3.6", | ||
"esbuild": "^0.15.7", | ||
"eslint": "^8.23.1", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"handlebars": "^4.7.7", | ||
"husky": "^8.0.1", | ||
"lint-staged": "^13.0.3", | ||
"memory-fs": "*", | ||
"mocha": "^6.2.2", | ||
"nock": "^11.9.1", | ||
"prettier": "^1.19.1" | ||
"mocha": "^10.0.0", | ||
"nock": "^13.2.9", | ||
"prettier": "^2.7.1", | ||
"typescript": "^4.8.3" | ||
}, | ||
"main": "index.js", | ||
"scripts": { | ||
"format": "prettier --write './{lib,test}/**/*.{js,json,css}'", | ||
"lint": "eslint './{lib,test}/**/*.js'", | ||
"test": "NODE_ENV=test mocha --reporter spec --bail" | ||
}, | ||
"engines": { | ||
"node": ">=8.3.0" | ||
"node": ">=16.0.0" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"prettier --write", | ||
"eslint", | ||
"git add" | ||
"eslint" | ||
], | ||
"*.json": [ | ||
"prettier --write", | ||
"git add" | ||
"*.{js,json,md}": [ | ||
"prettier --write" | ||
] | ||
@@ -61,9 +64,20 @@ }, | ||
"arrowParens": "always", | ||
"htmlWhitespaceSensitivity": "strict", | ||
"printWidth": 80, | ||
"singleQuote": true | ||
"singleQuote": true, | ||
"trailingComma": "all" | ||
}, | ||
"repository": "git://github.com/popeindustries/inline-source.git", | ||
"readmeFilename": "README.md", | ||
"license": "MIT" | ||
} | ||
"files": [ | ||
"*.d.ts", | ||
"*.js", | ||
"README.MD" | ||
], | ||
"scripts": { | ||
"build": "node ./scripts/build.js", | ||
"clean": "git clean -x -f", | ||
"format": "prettier --write './{src,test}/**/*.{js,json,css}'", | ||
"lint": "pnpm run lint:eslint && pnpm run lint:typescript", | ||
"lint:eslint": "eslint 'src/**/*.js'", | ||
"lint:typescript": "tsc --noEmit --skipLibCheck", | ||
"test": "NODE_ENV=test mocha --reporter spec --bail 'test/*-test.js'" | ||
} | ||
} |
[![NPM Version](https://img.shields.io/npm/v/inline-source.svg?style=flat)](https://npmjs.org/package/inline-source) | ||
[![Build Status](https://img.shields.io/travis/popeindustries/inline-source.svg?style=flat)](https://travis-ci.org/popeindustries/inline-source) | ||
[![Build Status](https://img.shields.io/github/workflow/status/popeindustries/inline-source/test/master)](https://github.com/popeindustries/inline-source/actions) | ||
[![Downloads](https://img.shields.io/npm/dm/inline-source.svg?style=flat)](https://npmjs.org/package/inline-source) | ||
@@ -9,4 +9,2 @@ | ||
**NOTE**: since version 6, the API is now Promise based, and compatible with `async/await`, requiring a minimum Node version of 7.6 | ||
> You can use [inline-source-cli](https://github.com/developit/inline-source-cli) to run `inline-source` from the command line or NPM Scripts. | ||
@@ -16,3 +14,3 @@ | ||
**`inlineSource(htmlpath, [options]): Promise<string>`**: parse `htmlpath` content for tags containing an `inline` attribute, and replace with (optionally compressed) file contents. | ||
**`inlineSource(htmlpath: string, [options: Options]): Promise<string>`**: parse `htmlpath` content for tags containing an `inline` attribute, and replace with (optionally compressed) file contents. | ||
@@ -59,5 +57,6 @@ `htmlpath` can be either a filepath _or_ a string of html content. | ||
```javascript | ||
const { inlineSource } = require('inline-source'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
import { inlineSource } from 'inline-source'; | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
const htmlpath = path.resolve('project/src/html/index.html'); | ||
@@ -69,3 +68,3 @@ | ||
// Skip all css types and png formats | ||
ignore: ['css', 'png'] | ||
ignore: ['css', 'png'], | ||
}) | ||
@@ -83,14 +82,14 @@ .then((html) => { | ||
```javascript | ||
const { inlineSource } = require('inline-source'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
import { inlineSource } from 'inline-source'; | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
const htmlpath = path.resolve('project/src/html/index.html'); | ||
let html; | ||
try { | ||
html = await inlineSource(htmlpath, { | ||
const html = await inlineSource(htmlpath, { | ||
compress: true, | ||
rootpath: path.resolve('www'), | ||
// Skip all css types and png formats | ||
ignore: ['css', 'png'] | ||
ignore: ['css', 'png'], | ||
}); | ||
@@ -105,3 +104,3 @@ // Do something with html | ||
Custom handlers are simple middleware-type functions that enable you to provide new, or override existing, inlining behaviour. All handlers have the following signature: `(source, context) => Promise` | ||
Custom handlers are simple middleware-type functions that enable you to provide new, or override existing, inlining behaviour. All handlers have the following signature: `(source: Source, context: Context) => Promise<void> | void` | ||
@@ -132,7 +131,7 @@ - `source`: the current source object to act upon | ||
```js | ||
module.exports = function handler(source, context) { | ||
export function handler(source, context) { | ||
if (source.fileContent && !source.content && source.type == 'js') { | ||
source.content = "Hey! I'm overriding the file's content!"; | ||
} | ||
}; | ||
} | ||
``` | ||
@@ -144,3 +143,3 @@ | ||
Custom pre handlers are the same as custom handlers only they run before loading the file. All handlers have the following signature: `(source, context) => Promise` | ||
Custom pre handlers are the same as custom handlers only they run before loading the file. All handlers have the following signature: `(source: Source, context: Context) => Promise<void> | void` | ||
@@ -150,6 +149,6 @@ With custom Pre handlers you can make changes to the file name | ||
```js | ||
module.exports = function handler(source, context) { | ||
const { version } = require('../package.json'); | ||
export function prehandler(source, context) { | ||
const { version } = getVersionFromSomewhere(); | ||
source.filepath = source.filepath.replace('.js', `_${version}.js`); | ||
}; | ||
} | ||
``` | ||
@@ -171,3 +170,3 @@ | ||
```js | ||
module.exports = function handler(source, context) { | ||
export function handler(source, context) { | ||
if (source.fileContent && !source.content && source.type == 'js') { | ||
@@ -182,4 +181,3 @@ // The `inline-compress` attribute automatically overrides the global flag | ||
} | ||
return Promise.resolve(); | ||
}; | ||
} | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Yes
27214
19
5
634
173
2
+ Addednode-fetch@^3.2.10
+ Added@jridgewell/gen-mapping@0.3.5(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/set-array@1.2.1(transitive)
+ Added@jridgewell/source-map@0.3.6(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Added@trysound/sax@0.2.0(transitive)
+ Addedacorn@8.14.0(transitive)
+ Addedcommander@7.2.0(transitive)
+ Addedcss-select@4.3.0(transitive)
+ Addedcss-tree@2.2.1(transitive)
+ Addedcss-what@6.1.0(transitive)
+ Addedcsso@5.0.5(transitive)
+ Addeddata-uri-to-buffer@4.0.1(transitive)
+ Addeddom-serializer@2.0.0(transitive)
+ Addeddomhandler@5.0.3(transitive)
+ Addeddomutils@3.1.0(transitive)
+ Addedentities@4.5.0(transitive)
+ Addedfetch-blob@3.2.0(transitive)
+ Addedformdata-polyfill@4.0.10(transitive)
+ Addedhtmlparser2@8.0.2(transitive)
+ Addedmdn-data@2.0.28(transitive)
+ Addednode-domexception@1.0.0(transitive)
+ Addednode-fetch@3.3.2(transitive)
+ Addednth-check@2.1.1(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedsource-map-js@1.2.1(transitive)
+ Addedsvgo@2.8.0(transitive)
+ Addedterser@5.36.0(transitive)
+ Addedweb-streams-polyfill@3.3.3(transitive)
- Removedsuperagent@^5.1.0
- Removed@types/q@1.5.8(transitive)
- Removedansi-styles@3.2.1(transitive)
- Removedargparse@1.0.10(transitive)
- Removedarray-buffer-byte-length@1.0.1(transitive)
- Removedarray.prototype.reduce@1.0.7(transitive)
- Removedarraybuffer.prototype.slice@1.0.3(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedavailable-typed-arrays@1.0.7(transitive)
- Removedcall-bind@1.0.7(transitive)
- Removedchalk@2.4.2(transitive)
- Removedcoa@2.0.2(transitive)
- Removedcolor-convert@1.9.3(transitive)
- Removedcolor-name@1.1.3(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcomponent-emitter@1.3.1(transitive)
- Removedcookiejar@2.1.4(transitive)
- Removedcss-select@2.1.0(transitive)
- Removedcss-select-base-adapter@0.1.1(transitive)
- Removedcss-tree@1.0.0-alpha.37(transitive)
- Removedcss-what@3.4.2(transitive)
- Removeddata-view-buffer@1.0.1(transitive)
- Removeddata-view-byte-length@1.0.1(transitive)
- Removeddata-view-byte-offset@1.0.0(transitive)
- Removeddebug@4.3.7(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removeddom-serializer@0.2.2(transitive)
- Removeddomelementtype@1.3.1(transitive)
- Removeddomhandler@3.3.0(transitive)
- Removeddomutils@1.7.0(transitive)
- Removedes-abstract@1.23.5(transitive)
- Removedes-array-method-boxes-properly@1.0.0(transitive)
- Removedes-define-property@1.0.0(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-object-atoms@1.0.0(transitive)
- Removedes-set-tostringtag@2.0.3(transitive)
- Removedes-to-primitive@1.2.1(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedesprima@4.0.1(transitive)
- Removedfast-safe-stringify@2.1.1(transitive)
- Removedfor-each@0.3.3(transitive)
- Removedform-data@3.0.2(transitive)
- Removedformidable@1.2.6(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedfunction.prototype.name@1.1.6(transitive)
- Removedfunctions-have-names@1.2.3(transitive)
- Removedget-intrinsic@1.2.4(transitive)
- Removedget-symbol-description@1.0.2(transitive)
- Removedglobalthis@1.0.4(transitive)
- Removedgopd@1.0.1(transitive)
- Removedhas-bigints@1.0.2(transitive)
- Removedhas-flag@3.0.0(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.0.3(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedhtmlparser2@4.1.0(transitive)
- Removedinherits@2.0.4(transitive)
- Removedinternal-slot@1.0.7(transitive)
- Removedis-array-buffer@3.0.4(transitive)
- Removedis-bigint@1.0.4(transitive)
- Removedis-boolean-object@1.1.2(transitive)
- Removedis-callable@1.2.7(transitive)
- Removedis-data-view@1.0.1(transitive)
- Removedis-date-object@1.0.5(transitive)
- Removedis-negative-zero@2.0.3(transitive)
- Removedis-number-object@1.0.7(transitive)
- Removedis-regex@1.1.4(transitive)
- Removedis-shared-array-buffer@1.0.3(transitive)
- Removedis-string@1.0.7(transitive)
- Removedis-symbol@1.0.4(transitive)
- Removedis-typed-array@1.1.13(transitive)
- Removedis-weakref@1.0.2(transitive)
- Removedisarray@2.0.5(transitive)
- Removedjs-yaml@3.14.1(transitive)
- Removedmdn-data@2.0.4(transitive)
- Removedmethods@1.1.2(transitive)
- Removedmime@2.6.0(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedms@2.1.3(transitive)
- Removednth-check@1.0.2(transitive)
- Removedobject-inspect@1.13.3(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedobject.assign@4.1.5(transitive)
- Removedobject.getownpropertydescriptors@2.1.8(transitive)
- Removedobject.values@1.2.0(transitive)
- Removedpossible-typed-array-names@1.0.0(transitive)
- Removedq@1.5.1(transitive)
- Removedqs@6.13.0(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedregexp.prototype.flags@1.5.3(transitive)
- Removedsafe-array-concat@1.1.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedsafe-regex-test@1.0.3(transitive)
- Removedsax@1.2.4(transitive)
- Removedsemver@7.6.3(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedset-function-name@2.0.2(transitive)
- Removedside-channel@1.0.6(transitive)
- Removedsprintf-js@1.0.3(transitive)
- Removedstring.prototype.trim@1.2.9(transitive)
- Removedstring.prototype.trimend@1.0.8(transitive)
- Removedstring.prototype.trimstart@1.0.8(transitive)
- Removedstring_decoder@1.3.0(transitive)
- Removedsuperagent@5.3.1(transitive)
- Removedsupports-color@5.5.0(transitive)
- Removedsvgo@1.3.2(transitive)
- Removedterser@4.8.1(transitive)
- Removedtyped-array-buffer@1.0.2(transitive)
- Removedtyped-array-byte-length@1.0.1(transitive)
- Removedtyped-array-byte-offset@1.0.2(transitive)
- Removedtyped-array-length@1.0.6(transitive)
- Removedunbox-primitive@1.0.2(transitive)
- Removedunquote@1.1.1(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedutil.promisify@1.0.1(transitive)
- Removedwhich-boxed-primitive@1.0.2(transitive)
- Removedwhich-typed-array@1.1.15(transitive)
Updatedcsso@^5.0.5
Updatedhtmlparser2@^8.0.1
Updatedsvgo@^2.8.0
Updatedterser@^5.15.0