postcss-smart-asset
Advanced tools
Comparing version 3.0.0 to 3.0.1
@@ -1,2 +0,2 @@ | ||
/*! postcss-smart-asset v3.0.0 by Sebastian Software <s.werner@sebastian-software.de> */ | ||
/*! postcss-smart-asset v3.0.1 by Sebastian Software <s.werner@sebastian-software.de> */ | ||
'use strict'; | ||
@@ -7,31 +7,8 @@ | ||
var path = require('path'); | ||
require('core-js/modules/es.array.iterator.js'); | ||
require('core-js/modules/es.object.to-string.js'); | ||
require('core-js/modules/es.set.js'); | ||
require('core-js/modules/es.string.iterator.js'); | ||
require('core-js/modules/web.dom-collections.iterator.js'); | ||
require('core-js/modules/es.array.is-array.js'); | ||
require('core-js/modules/es.array.for-each.js'); | ||
require('core-js/modules/web.dom-collections.for-each.js'); | ||
require('core-js/modules/es.regexp.exec.js'); | ||
require('core-js/modules/es.array.slice.js'); | ||
require('core-js/modules/es.string.match.js'); | ||
require('core-js/modules/es.promise.js'); | ||
require('core-js/modules/es.array.map.js'); | ||
require('core-js/modules/es.string.replace.js'); | ||
require('core-js/modules/es.function.name.js'); | ||
require('core-js/modules/es.array.join.js'); | ||
require('core-js/modules/es.string.search.js'); | ||
require('postcss'); | ||
require('core-js/modules/es.error.cause.js'); | ||
var fs = require('fs'); | ||
var assetHash = require('asset-hash'); | ||
require('core-js/modules/es.array.find.js'); | ||
var mime = require('mime/lite'); | ||
require('core-js/modules/es.array.index-of.js'); | ||
var url = require('url'); | ||
require('core-js/modules/es.date.to-string.js'); | ||
require('core-js/modules/es.regexp.to-string.js'); | ||
require('core-js/modules/es.array.filter.js'); | ||
require('core-js/modules/es.regexp.constructor.js'); | ||
require('core-js/modules/es.array.find-index.js'); | ||
require('core-js/modules/es.array.concat.js'); | ||
var minimatch = require('minimatch'); | ||
@@ -47,3 +24,7 @@ | ||
var normalize = function normalize(assetUrl) { | ||
/** | ||
* Normalizing result url, before replace decl value | ||
*/ | ||
const normalize = assetUrl => { | ||
assetUrl = path__default.normalize(assetUrl); | ||
@@ -56,3 +37,3 @@ | ||
if (assetUrl.charAt(0) !== "." && assetUrl.charAt(0) !== "/") { | ||
assetUrl = "./" + assetUrl; | ||
assetUrl = `./${assetUrl}`; | ||
} | ||
@@ -62,39 +43,55 @@ | ||
}; | ||
var isUrlWithoutPathname = function isUrlWithoutPathname(assetUrl) { | ||
return assetUrl[0] === "#" || assetUrl.indexOf("%23") === 0 || assetUrl.indexOf("data:") === 0 || /^[a-z]+:\/\//.test(assetUrl); | ||
}; | ||
var isUrlShouldBeIgnored = function isUrlShouldBeIgnored(assetUrl, options) { | ||
return isUrlWithoutPathname(assetUrl) || assetUrl[0] === "/" && !options.basePath; | ||
}; | ||
var getAssetsPath = function getAssetsPath(baseDir, assetsPath, relative) { | ||
return path__default.resolve(baseDir, assetsPath || "", relative || ""); | ||
}; | ||
var getTargetDir = function getTargetDir(dir) { | ||
return dir.from !== dir.to ? dir.to : process.cwd(); | ||
}; | ||
var getPathDeclFile = function getPathDeclFile(decl) { | ||
return decl.source && decl.source.input && decl.source.input.file; | ||
}; | ||
var getDirDeclFile = function getDirDeclFile(decl) { | ||
var filename = getPathDeclFile(decl); | ||
const isUrlWithoutPathname = assetUrl => assetUrl[0] === "#" || assetUrl.indexOf("%23") === 0 || assetUrl.indexOf("data:") === 0 || /^[a-z]+:\/\//.test(assetUrl); | ||
/** | ||
* Check if url is absolute, hash or data-uri | ||
*/ | ||
const isUrlShouldBeIgnored = (assetUrl, options) => isUrlWithoutPathname(assetUrl) || assetUrl[0] === "/" && !options.basePath; | ||
const getAssetsPath = (baseDir, assetsPath, relative) => path__default.resolve(baseDir, assetsPath || "", relative || ""); | ||
/** | ||
* Target path, output base dir | ||
*/ | ||
const getTargetDir = dir => dir.from !== dir.to ? dir.to : process.cwd(); | ||
/** | ||
* Stylesheet file path from decl | ||
*/ | ||
const getPathDeclFile = decl => decl.source && decl.source.input && decl.source.input.file; | ||
/** | ||
* Stylesheet file dir from decl | ||
*/ | ||
const getDirDeclFile = decl => { | ||
const filename = getPathDeclFile(decl); | ||
return filename ? path__default.dirname(filename) : process.cwd(); | ||
}; | ||
var getPathByBasePath = function getPathByBasePath(basePath, dirFrom, relPath) { | ||
/** | ||
* Returns paths list, where we can find assets file | ||
* | ||
* @param basePath - base paths where trying search to assets file | ||
* @param dirFrom | ||
* @param relPath - relative asset path | ||
*/ | ||
const getPathByBasePath = (basePath, dirFrom, relPath) => { | ||
if (relPath[0] === "/") { | ||
relPath = "." + relPath; | ||
relPath = `.${relPath}`; | ||
} | ||
basePath = !Array.isArray(basePath) ? [basePath] : basePath; | ||
return basePath.map(function (pathItem) { | ||
return getAssetsPath(dirFrom, pathItem, relPath); | ||
}); | ||
return basePath.map(pathItem => getAssetsPath(dirFrom, pathItem, relPath)); | ||
}; | ||
var prepareAsset = function prepareAsset(assetUrl, dir, decl) { | ||
var parsedUrl = url__default.parse(assetUrl), | ||
pathname = !isUrlWithoutPathname(assetUrl) ? parsedUrl.pathname : null, | ||
absolutePath = pathname ? path__default.resolve(path__default.join(dir.file, pathname)) : getPathDeclFile(decl); | ||
/** | ||
* Preparing asset paths and data | ||
*/ | ||
const prepareAsset = (assetUrl, dir, decl) => { | ||
const parsedUrl = url__default.parse(assetUrl); | ||
const pathname = !isUrlWithoutPathname(assetUrl) ? parsedUrl.pathname : null; | ||
const absolutePath = pathname ? path__default.resolve(path__default.join(dir.file, pathname)) : getPathDeclFile(decl); | ||
return { | ||
url: assetUrl, | ||
originUrl: assetUrl, | ||
pathname: pathname, | ||
pathname, | ||
absolutePath: absolutePath || dir.from, | ||
@@ -107,8 +104,8 @@ relativePath: absolutePath ? path__default.relative(dir.from, absolutePath) : ".", | ||
var getFile = function getFile(asset, options, dir, warn) { | ||
var paths = options.basePath ? getPathByBasePath(options.basePath, dir.from, asset.pathname) : [asset.absolutePath], | ||
filePath = paths.find(fs__default.existsSync); | ||
const getFile = (asset, options, dir, warn) => { | ||
const paths = options.basePath ? getPathByBasePath(options.basePath, dir.from, asset.pathname) : [asset.absolutePath]; | ||
const filePath = paths.find(fs__default.existsSync); | ||
if (!filePath) { | ||
warn("Can't read file '" + paths.join() + "', ignoring"); | ||
warn(`Can't read file '${paths.join()}', ignoring`); | ||
return; | ||
@@ -123,66 +120,50 @@ } | ||
var getHashName = function getHashName(file, options) { | ||
return assetHash.getHashedName(file.path, options); | ||
}; | ||
const getHashName = (file, options) => assetHash.getHashedName(file.path, options); | ||
/** | ||
* Copy images from readed from url() to an specific assets destination | ||
* (`assetsPath`) and fix url() according to that path. | ||
* You can rename the assets by a hash or keep the real filename. | ||
* | ||
* Option assetsPath is require and is relative to the css destination (`to`) | ||
*/ | ||
function copyAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
return new Promise(function ($return, $error) { | ||
var file, assetRelativePath, pathObj, fileName, targetDir, newAssetBaseDir, newAssetPath, newRelativeAssetPath; | ||
if (!options.assetsPath && dir.from === dir.to) { | ||
warn("Option `to` of postcss is required, ignoring"); | ||
return $return(); | ||
} | ||
async function copyAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
if (!options.assetsPath && dir.from === dir.to) { | ||
warn("Option `to` of postcss is required, ignoring"); | ||
return; | ||
} | ||
file = getFile(asset, options, dir, warn); | ||
const file = getFile(asset, options, dir, warn); | ||
if (!file) { | ||
return $return(); | ||
} | ||
if (!file) { | ||
return; | ||
} | ||
addDependency(file.path); | ||
return Promise.resolve(new Promise(function ($return, $error) { | ||
if (options.useHash) { | ||
return Promise.resolve(getHashName(file, options.hashOptions)).then($return, $error); | ||
} | ||
addDependency(file.path); | ||
let assetRelativePath = options.useHash ? await getHashName(file, options.hashOptions) : asset.relativePath; | ||
return $return(asset.relativePath); | ||
})).then(function ($await_4) { | ||
try { | ||
assetRelativePath = $await_4; | ||
if (options.useHash && options.keepName) { | ||
const pathObj = path__default.parse(assetRelativePath); | ||
const fileName = path__default.parse(asset.relativePath).name; | ||
pathObj.name = `${fileName}~${pathObj.name}`; | ||
delete pathObj.base; // otherwise it would override name | ||
if (options.useHash && options.keepName) { | ||
pathObj = path__default.parse(assetRelativePath); | ||
fileName = path__default.parse(asset.relativePath).name; | ||
pathObj.name = fileName + "~" + pathObj.name; | ||
delete pathObj.base; | ||
assetRelativePath = path__default.format(pathObj); | ||
} | ||
assetRelativePath = path__default.format(pathObj); | ||
} | ||
targetDir = getTargetDir(dir); | ||
newAssetBaseDir = getAssetsPath(targetDir, options.assetsPath); | ||
newAssetPath = path__default.join(newAssetBaseDir, assetRelativePath); | ||
newRelativeAssetPath = normalize(path__default.relative(targetDir, newAssetPath)); | ||
return Promise.resolve(fs.promises.mkdir(path__default.dirname(newAssetPath), { | ||
recursive: true | ||
})).then(function () { | ||
try { | ||
return Promise.resolve(fs.promises.copyFile(file.path, newAssetPath)).then(function () { | ||
try { | ||
return $return("" + newRelativeAssetPath + asset.search + asset.hash); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
const targetDir = getTargetDir(dir); | ||
const newAssetBaseDir = getAssetsPath(targetDir, options.assetsPath); | ||
const newAssetPath = path__default.join(newAssetBaseDir, assetRelativePath); | ||
const newRelativeAssetPath = normalize(path__default.relative(targetDir, newAssetPath)); | ||
await fs.promises.mkdir(path__default.dirname(newAssetPath), { | ||
recursive: true | ||
}); | ||
await fs.promises.copyFile(file.path, newAssetPath); | ||
return `${newRelativeAssetPath}${asset.search}${asset.hash}`; | ||
} | ||
/** | ||
* Transform url() based on a custom callback | ||
*/ | ||
function customAsset(asset, dir, options) { | ||
@@ -192,40 +173,45 @@ return options.url.apply(null, arguments); | ||
var optimizedSvgEncode = function optimizedSvgEncode(svgContent) { | ||
var result = encodeURIComponent(svgContent).replace(/%3D/g, "=").replace(/%3A/g, ":").replace(/%2F/g, "/").replace(/%22/g, "'").replace(/%2C/g, ",").replace(/%3B/g, ";"); | ||
return result.replace(/(%[\dA-Z]{2})/g, function (matched, AZ) { | ||
return AZ.toLowerCase(); | ||
}); | ||
/** | ||
* Optimize encoding SVG files (IE9+, Android 3+) | ||
* | ||
* @see https://codepen.io/tigt/post/optimizing-svgs-in-data-uris | ||
*/ | ||
const optimizedSvgEncode = svgContent => { | ||
const result = encodeURIComponent(svgContent).replace(/%3D/g, "=").replace(/%3A/g, ":").replace(/%2F/g, "/").replace(/%22/g, "'").replace(/%2C/g, ",").replace(/%3B/g, ";"); // Lowercase the hex-escapes for better gzipping | ||
return result.replace(/(%[\dA-Z]{2})/g, (matched, AZ) => AZ.toLowerCase()); | ||
}; | ||
/** | ||
* Encoding file contents to string | ||
*/ | ||
var encodeFile = (function (file, encodeType, shouldOptimizeSvgEncode) { | ||
return new Promise(function ($return, $error) { | ||
var dataMime, contents, encodeFunc, content, encodedStr; | ||
dataMime = "data:" + file.mimeType; | ||
return Promise.resolve(fs.promises.readFile(file.path)).then(function ($await_1) { | ||
try { | ||
contents = $await_1; | ||
if (encodeType === "base64") { | ||
return $return(dataMime + ";base64," + contents.toString("base64")); | ||
} | ||
var encodeFile = (async (file, encodeType, shouldOptimizeSvgEncode) => { | ||
const dataMime = `data:${file.mimeType}`; | ||
const contents = await fs.promises.readFile(file.path); | ||
encodeFunc = encodeType === "encodeURI" ? encodeURI : encodeURIComponent; | ||
content = contents.toString("utf8").replace(/\n+/g, ""); | ||
encodedStr = shouldOptimizeSvgEncode && encodeType === "encodeURIComponent" ? optimizedSvgEncode(content) : encodeFunc(content); | ||
encodedStr = encodedStr.replace(/%20/g, " ").replace(/#/g, "%23"); | ||
return $return(dataMime + "," + encodedStr); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
}); | ||
if (encodeType === "base64") { | ||
return `${dataMime};base64,${contents.toString("base64")}`; | ||
} | ||
const encodeFunc = encodeType === "encodeURI" ? encodeURI : encodeURIComponent; | ||
const content = contents.toString("utf8") // removing new lines | ||
.replace(/\n+/g, ""); | ||
let encodedStr = shouldOptimizeSvgEncode && encodeType === "encodeURIComponent" ? optimizedSvgEncode(content) : encodeFunc(content); | ||
encodedStr = encodedStr.replace(/%20/g, " ").replace(/#/g, "%23"); | ||
return `${dataMime},${encodedStr}`; | ||
}); | ||
/** | ||
* Fix url() according to source (`from`) or destination (`to`) | ||
*/ | ||
function rebaseAsset(asset, dir) { | ||
var rebasedUrl = normalize(path__default.relative(dir.to, asset.absolutePath)); | ||
return "" + rebasedUrl + asset.search + asset.hash; | ||
const rebasedUrl = normalize(path__default.relative(dir.to, asset.absolutePath)); | ||
return `${rebasedUrl}${asset.search}${asset.hash}`; | ||
} | ||
function inlineFallback(originUrl, dir, options) { | ||
if (typeof options.fallback == "function") { | ||
if (typeof options.fallback === "function") { | ||
return options.fallback.apply(null, arguments); | ||
@@ -236,60 +222,69 @@ } | ||
case "copy": | ||
return copyAsset.apply(void 0, arguments); | ||
return copyAsset(...arguments); | ||
case "rebase": | ||
return rebaseAsset.apply(void 0, arguments); | ||
return rebaseAsset(...arguments); | ||
} | ||
} | ||
/** | ||
* Inline image in url() | ||
*/ | ||
function inlineAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
var $args = arguments; | ||
return new Promise(function ($return, $error) { | ||
var file, maxSize, stats, isSvg, defaultEncodeType, encodeType, optimizeSvgEncode, encodedStr, resultValue; | ||
file = getFile(asset, options, dir, warn); | ||
/* eslint-disable complexity */ | ||
if (!file) { | ||
return $return(); | ||
} | ||
if (!file.mimeType) { | ||
warn("Unable to find asset mime-type for " + file.path); | ||
return $return(); | ||
} | ||
async function inlineAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
const file = getFile(asset, options, dir, warn); | ||
maxSize = (options.maxSize || 0) * 1024; | ||
if (!file) { | ||
return; | ||
} | ||
if (maxSize) { | ||
stats = fs__default.statSync(file.path); | ||
if (!file.mimeType) { | ||
warn(`Unable to find asset mime-type for ${file.path}`); | ||
return; | ||
} | ||
if (stats.size >= maxSize) { | ||
return $return(inlineFallback.apply(this, $args)); | ||
} | ||
} | ||
const maxSize = (options.maxSize || 0) * 1024; | ||
isSvg = file.mimeType === "image/svg+xml"; | ||
defaultEncodeType = isSvg ? "encodeURIComponent" : "base64"; | ||
encodeType = options.encodeType || defaultEncodeType; | ||
if (maxSize) { | ||
const stats = fs__default.statSync(file.path); | ||
if (isSvg && asset.hash && !options.ignoreFragmentWarning) { | ||
warn("Image type is svg and link contains #.\n PostCSS Smart Asset can't handle SVG fragments.\n SVG file fully inlined. " + file.path); | ||
if (stats.size >= maxSize) { | ||
return inlineFallback.apply(this, arguments); | ||
} | ||
} | ||
addDependency(file.path); | ||
optimizeSvgEncode = isSvg && options.optimizeSvgEncode; | ||
return Promise.resolve(encodeFile(file, encodeType, optimizeSvgEncode)).then(function ($await_1) { | ||
try { | ||
encodedStr = $await_1; | ||
resultValue = options.includeUriFragment && asset.hash ? "" + encodedStr + asset.hash : encodedStr; | ||
return $return(isSvg && encodeType !== "base64" ? "\"" + resultValue + "\"" : resultValue); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
}.bind(this)); | ||
const isSvg = file.mimeType === "image/svg+xml"; | ||
const defaultEncodeType = isSvg ? "encodeURIComponent" : "base64"; | ||
const encodeType = options.encodeType || defaultEncodeType; // Warn for svg with hashes/fragments | ||
if (isSvg && asset.hash && !options.ignoreFragmentWarning) { | ||
// eslint-disable-next-line max-len | ||
warn(`Image type is svg and link contains #. | ||
PostCSS Smart Asset can't handle SVG fragments. | ||
SVG file fully inlined. ${file.path}`); | ||
} | ||
addDependency(file.path); | ||
const optimizeSvgEncode = isSvg && options.optimizeSvgEncode; | ||
const encodedStr = await encodeFile(file, encodeType, optimizeSvgEncode); | ||
const resultValue = options.includeUriFragment && asset.hash ? `${encodedStr}${asset.hash}` : encodedStr; // wrap url by quotes if percent-encoded svg | ||
return isSvg && encodeType !== "base64" ? `"${resultValue}"` : resultValue; | ||
} | ||
var matchesFilter = function matchesFilter(asset, pattern) { | ||
var relativeToRoot = path__default.relative(process.cwd(), asset.absolutePath); | ||
/** | ||
* Returns whether the given asset matches the given pattern | ||
Allways returns true if the given pattern is empty | ||
* | ||
* @param asset the processed asset | ||
* @param pattern A minimatch string, | ||
* regular expression or function to test the asset | ||
*/ | ||
if (typeof pattern == "string") { | ||
const matchesFilter = (asset, pattern) => { | ||
const relativeToRoot = path__default.relative(process.cwd(), asset.absolutePath); | ||
if (typeof pattern === "string") { | ||
pattern = minimatch__default.filter(pattern); | ||
@@ -308,6 +303,11 @@ return pattern(relativeToRoot); | ||
return true; | ||
}, | ||
matchOption = function matchOption(asset, option) { | ||
var matched = matchesFilter(asset, option.filter); | ||
}; | ||
/** | ||
* Matching single option | ||
*/ | ||
const matchOption = (asset, option) => { | ||
const matched = matchesFilter(asset, option.filter); | ||
if (!matched) { | ||
@@ -317,8 +317,12 @@ return false; | ||
return typeof option.url == "function" || !isUrlShouldBeIgnored(asset.url, option); | ||
}, | ||
isMultiOption = function isMultiOption(option) { | ||
return option.multi && typeof option.url == "function"; | ||
}, | ||
matchOptions = function matchOptions(asset, options) { | ||
return typeof option.url === "function" || !isUrlShouldBeIgnored(asset.url, option); | ||
}; | ||
const isMultiOption = option => option.multi && typeof option.url === "function"; | ||
/** | ||
* Matching options by asset | ||
*/ | ||
const matchOptions = (asset, options) => { | ||
if (!options) { | ||
@@ -329,5 +333,3 @@ return; | ||
if (Array.isArray(options)) { | ||
var optionIndex = options.findIndex(function (option) { | ||
return matchOption(asset, option); | ||
}); | ||
const optionIndex = options.findIndex(option => matchOption(asset, option)); | ||
@@ -338,3 +340,3 @@ if (optionIndex < 0) { | ||
var matchedOption = options[optionIndex]; | ||
const matchedOption = options[optionIndex]; // if founded option is last | ||
@@ -345,6 +347,4 @@ if (optionIndex === options.length - 1) { | ||
var extendOptions = options.slice(optionIndex + 1).filter(function (option) { | ||
return (isMultiOption(matchedOption) || isMultiOption(option)) && matchOption(asset, option); | ||
}); | ||
return extendOptions.length ? [matchedOption].concat(extendOptions) : matchedOption; | ||
const extendOptions = options.slice(optionIndex + 1).filter(option => (isMultiOption(matchedOption) || isMultiOption(option)) && matchOption(asset, option)); | ||
return extendOptions.length > 0 ? [matchedOption].concat(extendOptions) : matchedOption; | ||
} | ||
@@ -357,3 +357,3 @@ | ||
var modeMap = { | ||
const modeMap = { | ||
copy: copyAsset, | ||
@@ -363,13 +363,16 @@ custom: customAsset, | ||
rebase: rebaseAsset | ||
}, | ||
PROCESS_TYPES = new Set(["rebase", "inline", "copy", "custom"]), | ||
getUrlProcessorType = function getUrlProcessorType(optionUrl) { | ||
return typeof optionUrl == "function" ? "custom" : optionUrl || "rebase"; | ||
}; | ||
/** | ||
* Restricted modes | ||
*/ | ||
const PROCESS_TYPES = new Set(["rebase", "inline", "copy", "custom"]); | ||
const getUrlProcessorType = optionUrl => typeof optionUrl === "function" ? "custom" : optionUrl || "rebase"; | ||
function getUrlProcessor(optionUrl) { | ||
var mode = getUrlProcessorType(optionUrl); | ||
const mode = getUrlProcessorType(optionUrl); | ||
if (!PROCESS_TYPES.has(mode)) { | ||
throw new Error("Unknown mode for postcss-url: " + mode); | ||
throw new Error(`Unknown mode for postcss-url: ${mode}`); | ||
} | ||
@@ -380,22 +383,18 @@ | ||
var wrapUrlProcessor = function wrapUrlProcessor(urlProcessor, result, decl) { | ||
var warn = function warn(message) { | ||
return decl.warn(result, message); | ||
}, | ||
addDependency = function addDependency(file) { | ||
return result.messages.push({ | ||
type: "dependency", | ||
file: file, | ||
parent: getPathDeclFile(decl) | ||
}); | ||
}; | ||
const wrapUrlProcessor = (urlProcessor, result, decl) => { | ||
const warn = message => decl.warn(result, message); | ||
return function (asset, dir, option) { | ||
return urlProcessor(asset, dir, option, decl, warn, result, addDependency); | ||
}; | ||
}, | ||
replaceUrl = function replaceUrl(url, dir, options, result, decl) { | ||
var asset = prepareAsset(url, dir, decl), | ||
matchedOptions = matchOptions(asset, options); | ||
const addDependency = file => result.messages.push({ | ||
type: "dependency", | ||
file, | ||
parent: getPathDeclFile(decl) | ||
}); | ||
return (asset, dir, option) => urlProcessor(asset, dir, option, decl, warn, result, addDependency); | ||
}; | ||
const replaceUrl = (url, dir, options, result, decl) => { | ||
const asset = prepareAsset(url, dir, decl); | ||
const matchedOptions = matchOptions(asset, options); | ||
if (!matchedOptions) { | ||
@@ -405,4 +404,4 @@ return; | ||
var process = function process(option) { | ||
var wrappedUrlProcessor = wrapUrlProcessor(getUrlProcessor(option.url), result, decl); | ||
const process = option => { | ||
const wrappedUrlProcessor = wrapUrlProcessor(getUrlProcessor(option.url), result, decl); | ||
return wrappedUrlProcessor(asset, dir, option); | ||
@@ -412,3 +411,3 @@ }; | ||
if (Array.isArray(matchedOptions)) { | ||
matchedOptions.forEach(function (option) { | ||
matchedOptions.forEach(option => { | ||
asset.url = process(option); | ||
@@ -421,5 +420,6 @@ }); | ||
return asset.url; | ||
}, | ||
WITH_QUOTES = /^["']/; | ||
}; | ||
const WITH_QUOTES = /^["']/; | ||
function buildResult(newUrl, matched, before, after) { | ||
@@ -435,7 +435,8 @@ if (!newUrl) { | ||
return "" + before + newUrl + after; | ||
} | ||
return `${before}${newUrl}${after}`; | ||
} // Tracks visited declarations | ||
var processTracker = new Set(); | ||
var declProcessor = function declProcessor(from, to, options, result, decl) { | ||
const processTracker = new Set(); | ||
const declProcessor = (from, to, options, result, decl) => { | ||
if (processTracker.has(decl)) { | ||
@@ -445,8 +446,8 @@ return; | ||
var dir = { | ||
from: from, | ||
to: to, | ||
const dir = { | ||
from, | ||
to, | ||
file: getDirDeclFile(decl) | ||
}, | ||
pattern = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/g; | ||
}; | ||
const pattern = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/g; | ||
@@ -457,3 +458,3 @@ if (!pattern) { | ||
var matches = decl.value.match(pattern); | ||
const matches = decl.value.match(pattern); | ||
@@ -464,17 +465,14 @@ if (!matches) { | ||
return Promise.all(matches.map(function (singleMatch) { | ||
var _$exec = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/.exec(singleMatch); | ||
_$exec[0]; | ||
var before = _$exec[1], | ||
url = _$exec[2], | ||
after = _$exec[3], | ||
replacement = replaceUrl(url, dir, options, result, decl); | ||
return Promise.all(matches.map((singleMatch, index) => { | ||
const [matched, before, url, after] = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/.exec(singleMatch); | ||
const replacement = replaceUrl(url, dir, options, result, decl); | ||
if (replacement) { | ||
if (replacement.then) { | ||
return replacement.then(function (resolved) { | ||
return buildResult(resolved, singleMatch, before, after); | ||
}); | ||
} | ||
return replacement.then(resolved => // const fullReplacement = resolved == null ? null : `${before}${resolved}${after}` | ||
// return fullReplacement | ||
buildResult(resolved, singleMatch, before, after)); | ||
} // const fullReplacement = `${before}${replacement}${after}` | ||
return buildResult(replacement, singleMatch, before, after); | ||
@@ -484,6 +482,6 @@ } | ||
return null; | ||
})).then(function (values) { | ||
})).then(values => { | ||
processTracker.add(decl); | ||
decl.value = decl.value.replace(pattern, function (match) { | ||
var replacement = values.shift(); | ||
decl.value = decl.value.replace(pattern, match => { | ||
const replacement = values.shift(); | ||
return replacement == null ? match : replacement; | ||
@@ -494,22 +492,20 @@ }); | ||
var index = (function (options) { | ||
if (options === void 0) { | ||
options = {}; | ||
var index = ((options = {}) => ({ | ||
postcssPlugin: "postcss-smart-asset", | ||
Declaration(decl, { | ||
result | ||
}) { | ||
const opts = result.opts; | ||
const from = opts.from ? path__default.dirname(opts.from) : "."; | ||
const to = opts.to ? path__default.dirname(opts.to) : from; | ||
return declProcessor(from, to, options, result, decl); | ||
} | ||
return { | ||
postcssPlugin: "postcss-smart-asset", | ||
Declaration: function Declaration(decl, _ref) { | ||
var result = _ref.result, | ||
opts = result.opts, | ||
from = opts.from ? path__default.dirname(opts.from) : ".", | ||
to = opts.to ? path__default.dirname(opts.to) : from; | ||
return declProcessor(from, to, options, result, decl); | ||
} | ||
}; | ||
}); | ||
var postcss = true; | ||
})); // PostCSS v8 marker | ||
const postcss = true; | ||
exports["default"] = index; | ||
exports.postcss = postcss; | ||
//# sourceMappingURL=index.cjs.js.map |
@@ -1,35 +0,16 @@ | ||
/*! postcss-smart-asset v3.0.0 by Sebastian Software <s.werner@sebastian-software.de> */ | ||
/*! postcss-smart-asset v3.0.1 by Sebastian Software <s.werner@sebastian-software.de> */ | ||
import path from 'path'; | ||
import 'core-js/modules/es.array.iterator.js'; | ||
import 'core-js/modules/es.object.to-string.js'; | ||
import 'core-js/modules/es.set.js'; | ||
import 'core-js/modules/es.string.iterator.js'; | ||
import 'core-js/modules/web.dom-collections.iterator.js'; | ||
import 'core-js/modules/es.array.is-array.js'; | ||
import 'core-js/modules/es.array.for-each.js'; | ||
import 'core-js/modules/web.dom-collections.for-each.js'; | ||
import 'core-js/modules/es.regexp.exec.js'; | ||
import 'core-js/modules/es.array.slice.js'; | ||
import 'core-js/modules/es.string.match.js'; | ||
import 'core-js/modules/es.promise.js'; | ||
import 'core-js/modules/es.array.map.js'; | ||
import 'core-js/modules/es.string.replace.js'; | ||
import 'core-js/modules/es.function.name.js'; | ||
import 'core-js/modules/es.array.join.js'; | ||
import 'core-js/modules/es.string.search.js'; | ||
import 'postcss'; | ||
import 'core-js/modules/es.error.cause.js'; | ||
import fs, { promises } from 'fs'; | ||
import { getHashedName } from 'asset-hash'; | ||
import 'core-js/modules/es.array.find.js'; | ||
import mime from 'mime/lite'; | ||
import 'core-js/modules/es.array.index-of.js'; | ||
import url from 'url'; | ||
import 'core-js/modules/es.date.to-string.js'; | ||
import 'core-js/modules/es.regexp.to-string.js'; | ||
import 'core-js/modules/es.array.filter.js'; | ||
import 'core-js/modules/es.regexp.constructor.js'; | ||
import 'core-js/modules/es.array.find-index.js'; | ||
import 'core-js/modules/es.array.concat.js'; | ||
import minimatch from 'minimatch'; | ||
var normalize = function normalize(assetUrl) { | ||
/** | ||
* Normalizing result url, before replace decl value | ||
*/ | ||
const normalize = assetUrl => { | ||
assetUrl = path.normalize(assetUrl); | ||
@@ -42,3 +23,3 @@ | ||
if (assetUrl.charAt(0) !== "." && assetUrl.charAt(0) !== "/") { | ||
assetUrl = "./" + assetUrl; | ||
assetUrl = `./${assetUrl}`; | ||
} | ||
@@ -48,39 +29,55 @@ | ||
}; | ||
var isUrlWithoutPathname = function isUrlWithoutPathname(assetUrl) { | ||
return assetUrl[0] === "#" || assetUrl.indexOf("%23") === 0 || assetUrl.indexOf("data:") === 0 || /^[a-z]+:\/\//.test(assetUrl); | ||
}; | ||
var isUrlShouldBeIgnored = function isUrlShouldBeIgnored(assetUrl, options) { | ||
return isUrlWithoutPathname(assetUrl) || assetUrl[0] === "/" && !options.basePath; | ||
}; | ||
var getAssetsPath = function getAssetsPath(baseDir, assetsPath, relative) { | ||
return path.resolve(baseDir, assetsPath || "", relative || ""); | ||
}; | ||
var getTargetDir = function getTargetDir(dir) { | ||
return dir.from !== dir.to ? dir.to : process.cwd(); | ||
}; | ||
var getPathDeclFile = function getPathDeclFile(decl) { | ||
return decl.source && decl.source.input && decl.source.input.file; | ||
}; | ||
var getDirDeclFile = function getDirDeclFile(decl) { | ||
var filename = getPathDeclFile(decl); | ||
const isUrlWithoutPathname = assetUrl => assetUrl[0] === "#" || assetUrl.indexOf("%23") === 0 || assetUrl.indexOf("data:") === 0 || /^[a-z]+:\/\//.test(assetUrl); | ||
/** | ||
* Check if url is absolute, hash or data-uri | ||
*/ | ||
const isUrlShouldBeIgnored = (assetUrl, options) => isUrlWithoutPathname(assetUrl) || assetUrl[0] === "/" && !options.basePath; | ||
const getAssetsPath = (baseDir, assetsPath, relative) => path.resolve(baseDir, assetsPath || "", relative || ""); | ||
/** | ||
* Target path, output base dir | ||
*/ | ||
const getTargetDir = dir => dir.from !== dir.to ? dir.to : process.cwd(); | ||
/** | ||
* Stylesheet file path from decl | ||
*/ | ||
const getPathDeclFile = decl => decl.source && decl.source.input && decl.source.input.file; | ||
/** | ||
* Stylesheet file dir from decl | ||
*/ | ||
const getDirDeclFile = decl => { | ||
const filename = getPathDeclFile(decl); | ||
return filename ? path.dirname(filename) : process.cwd(); | ||
}; | ||
var getPathByBasePath = function getPathByBasePath(basePath, dirFrom, relPath) { | ||
/** | ||
* Returns paths list, where we can find assets file | ||
* | ||
* @param basePath - base paths where trying search to assets file | ||
* @param dirFrom | ||
* @param relPath - relative asset path | ||
*/ | ||
const getPathByBasePath = (basePath, dirFrom, relPath) => { | ||
if (relPath[0] === "/") { | ||
relPath = "." + relPath; | ||
relPath = `.${relPath}`; | ||
} | ||
basePath = !Array.isArray(basePath) ? [basePath] : basePath; | ||
return basePath.map(function (pathItem) { | ||
return getAssetsPath(dirFrom, pathItem, relPath); | ||
}); | ||
return basePath.map(pathItem => getAssetsPath(dirFrom, pathItem, relPath)); | ||
}; | ||
var prepareAsset = function prepareAsset(assetUrl, dir, decl) { | ||
var parsedUrl = url.parse(assetUrl), | ||
pathname = !isUrlWithoutPathname(assetUrl) ? parsedUrl.pathname : null, | ||
absolutePath = pathname ? path.resolve(path.join(dir.file, pathname)) : getPathDeclFile(decl); | ||
/** | ||
* Preparing asset paths and data | ||
*/ | ||
const prepareAsset = (assetUrl, dir, decl) => { | ||
const parsedUrl = url.parse(assetUrl); | ||
const pathname = !isUrlWithoutPathname(assetUrl) ? parsedUrl.pathname : null; | ||
const absolutePath = pathname ? path.resolve(path.join(dir.file, pathname)) : getPathDeclFile(decl); | ||
return { | ||
url: assetUrl, | ||
originUrl: assetUrl, | ||
pathname: pathname, | ||
pathname, | ||
absolutePath: absolutePath || dir.from, | ||
@@ -93,8 +90,8 @@ relativePath: absolutePath ? path.relative(dir.from, absolutePath) : ".", | ||
var getFile = function getFile(asset, options, dir, warn) { | ||
var paths = options.basePath ? getPathByBasePath(options.basePath, dir.from, asset.pathname) : [asset.absolutePath], | ||
filePath = paths.find(fs.existsSync); | ||
const getFile = (asset, options, dir, warn) => { | ||
const paths = options.basePath ? getPathByBasePath(options.basePath, dir.from, asset.pathname) : [asset.absolutePath]; | ||
const filePath = paths.find(fs.existsSync); | ||
if (!filePath) { | ||
warn("Can't read file '" + paths.join() + "', ignoring"); | ||
warn(`Can't read file '${paths.join()}', ignoring`); | ||
return; | ||
@@ -109,66 +106,50 @@ } | ||
var getHashName = function getHashName(file, options) { | ||
return getHashedName(file.path, options); | ||
}; | ||
const getHashName = (file, options) => getHashedName(file.path, options); | ||
/** | ||
* Copy images from readed from url() to an specific assets destination | ||
* (`assetsPath`) and fix url() according to that path. | ||
* You can rename the assets by a hash or keep the real filename. | ||
* | ||
* Option assetsPath is require and is relative to the css destination (`to`) | ||
*/ | ||
function copyAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
return new Promise(function ($return, $error) { | ||
var file, assetRelativePath, pathObj, fileName, targetDir, newAssetBaseDir, newAssetPath, newRelativeAssetPath; | ||
if (!options.assetsPath && dir.from === dir.to) { | ||
warn("Option `to` of postcss is required, ignoring"); | ||
return $return(); | ||
} | ||
async function copyAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
if (!options.assetsPath && dir.from === dir.to) { | ||
warn("Option `to` of postcss is required, ignoring"); | ||
return; | ||
} | ||
file = getFile(asset, options, dir, warn); | ||
const file = getFile(asset, options, dir, warn); | ||
if (!file) { | ||
return $return(); | ||
} | ||
if (!file) { | ||
return; | ||
} | ||
addDependency(file.path); | ||
return Promise.resolve(new Promise(function ($return, $error) { | ||
if (options.useHash) { | ||
return Promise.resolve(getHashName(file, options.hashOptions)).then($return, $error); | ||
} | ||
addDependency(file.path); | ||
let assetRelativePath = options.useHash ? await getHashName(file, options.hashOptions) : asset.relativePath; | ||
return $return(asset.relativePath); | ||
})).then(function ($await_4) { | ||
try { | ||
assetRelativePath = $await_4; | ||
if (options.useHash && options.keepName) { | ||
const pathObj = path.parse(assetRelativePath); | ||
const fileName = path.parse(asset.relativePath).name; | ||
pathObj.name = `${fileName}~${pathObj.name}`; | ||
delete pathObj.base; // otherwise it would override name | ||
if (options.useHash && options.keepName) { | ||
pathObj = path.parse(assetRelativePath); | ||
fileName = path.parse(asset.relativePath).name; | ||
pathObj.name = fileName + "~" + pathObj.name; | ||
delete pathObj.base; | ||
assetRelativePath = path.format(pathObj); | ||
} | ||
assetRelativePath = path.format(pathObj); | ||
} | ||
targetDir = getTargetDir(dir); | ||
newAssetBaseDir = getAssetsPath(targetDir, options.assetsPath); | ||
newAssetPath = path.join(newAssetBaseDir, assetRelativePath); | ||
newRelativeAssetPath = normalize(path.relative(targetDir, newAssetPath)); | ||
return Promise.resolve(promises.mkdir(path.dirname(newAssetPath), { | ||
recursive: true | ||
})).then(function () { | ||
try { | ||
return Promise.resolve(promises.copyFile(file.path, newAssetPath)).then(function () { | ||
try { | ||
return $return("" + newRelativeAssetPath + asset.search + asset.hash); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
const targetDir = getTargetDir(dir); | ||
const newAssetBaseDir = getAssetsPath(targetDir, options.assetsPath); | ||
const newAssetPath = path.join(newAssetBaseDir, assetRelativePath); | ||
const newRelativeAssetPath = normalize(path.relative(targetDir, newAssetPath)); | ||
await promises.mkdir(path.dirname(newAssetPath), { | ||
recursive: true | ||
}); | ||
await promises.copyFile(file.path, newAssetPath); | ||
return `${newRelativeAssetPath}${asset.search}${asset.hash}`; | ||
} | ||
/** | ||
* Transform url() based on a custom callback | ||
*/ | ||
function customAsset(asset, dir, options) { | ||
@@ -178,40 +159,45 @@ return options.url.apply(null, arguments); | ||
var optimizedSvgEncode = function optimizedSvgEncode(svgContent) { | ||
var result = encodeURIComponent(svgContent).replace(/%3D/g, "=").replace(/%3A/g, ":").replace(/%2F/g, "/").replace(/%22/g, "'").replace(/%2C/g, ",").replace(/%3B/g, ";"); | ||
return result.replace(/(%[\dA-Z]{2})/g, function (matched, AZ) { | ||
return AZ.toLowerCase(); | ||
}); | ||
/** | ||
* Optimize encoding SVG files (IE9+, Android 3+) | ||
* | ||
* @see https://codepen.io/tigt/post/optimizing-svgs-in-data-uris | ||
*/ | ||
const optimizedSvgEncode = svgContent => { | ||
const result = encodeURIComponent(svgContent).replace(/%3D/g, "=").replace(/%3A/g, ":").replace(/%2F/g, "/").replace(/%22/g, "'").replace(/%2C/g, ",").replace(/%3B/g, ";"); // Lowercase the hex-escapes for better gzipping | ||
return result.replace(/(%[\dA-Z]{2})/g, (matched, AZ) => AZ.toLowerCase()); | ||
}; | ||
/** | ||
* Encoding file contents to string | ||
*/ | ||
var encodeFile = (function (file, encodeType, shouldOptimizeSvgEncode) { | ||
return new Promise(function ($return, $error) { | ||
var dataMime, contents, encodeFunc, content, encodedStr; | ||
dataMime = "data:" + file.mimeType; | ||
return Promise.resolve(promises.readFile(file.path)).then(function ($await_1) { | ||
try { | ||
contents = $await_1; | ||
if (encodeType === "base64") { | ||
return $return(dataMime + ";base64," + contents.toString("base64")); | ||
} | ||
var encodeFile = (async (file, encodeType, shouldOptimizeSvgEncode) => { | ||
const dataMime = `data:${file.mimeType}`; | ||
const contents = await promises.readFile(file.path); | ||
encodeFunc = encodeType === "encodeURI" ? encodeURI : encodeURIComponent; | ||
content = contents.toString("utf8").replace(/\n+/g, ""); | ||
encodedStr = shouldOptimizeSvgEncode && encodeType === "encodeURIComponent" ? optimizedSvgEncode(content) : encodeFunc(content); | ||
encodedStr = encodedStr.replace(/%20/g, " ").replace(/#/g, "%23"); | ||
return $return(dataMime + "," + encodedStr); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
}); | ||
if (encodeType === "base64") { | ||
return `${dataMime};base64,${contents.toString("base64")}`; | ||
} | ||
const encodeFunc = encodeType === "encodeURI" ? encodeURI : encodeURIComponent; | ||
const content = contents.toString("utf8") // removing new lines | ||
.replace(/\n+/g, ""); | ||
let encodedStr = shouldOptimizeSvgEncode && encodeType === "encodeURIComponent" ? optimizedSvgEncode(content) : encodeFunc(content); | ||
encodedStr = encodedStr.replace(/%20/g, " ").replace(/#/g, "%23"); | ||
return `${dataMime},${encodedStr}`; | ||
}); | ||
/** | ||
* Fix url() according to source (`from`) or destination (`to`) | ||
*/ | ||
function rebaseAsset(asset, dir) { | ||
var rebasedUrl = normalize(path.relative(dir.to, asset.absolutePath)); | ||
return "" + rebasedUrl + asset.search + asset.hash; | ||
const rebasedUrl = normalize(path.relative(dir.to, asset.absolutePath)); | ||
return `${rebasedUrl}${asset.search}${asset.hash}`; | ||
} | ||
function inlineFallback(originUrl, dir, options) { | ||
if (typeof options.fallback == "function") { | ||
if (typeof options.fallback === "function") { | ||
return options.fallback.apply(null, arguments); | ||
@@ -222,60 +208,69 @@ } | ||
case "copy": | ||
return copyAsset.apply(void 0, arguments); | ||
return copyAsset(...arguments); | ||
case "rebase": | ||
return rebaseAsset.apply(void 0, arguments); | ||
return rebaseAsset(...arguments); | ||
} | ||
} | ||
/** | ||
* Inline image in url() | ||
*/ | ||
function inlineAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
var $args = arguments; | ||
return new Promise(function ($return, $error) { | ||
var file, maxSize, stats, isSvg, defaultEncodeType, encodeType, optimizeSvgEncode, encodedStr, resultValue; | ||
file = getFile(asset, options, dir, warn); | ||
/* eslint-disable complexity */ | ||
if (!file) { | ||
return $return(); | ||
} | ||
if (!file.mimeType) { | ||
warn("Unable to find asset mime-type for " + file.path); | ||
return $return(); | ||
} | ||
async function inlineAsset(asset, dir, options, decl, warn, result, addDependency) { | ||
const file = getFile(asset, options, dir, warn); | ||
maxSize = (options.maxSize || 0) * 1024; | ||
if (!file) { | ||
return; | ||
} | ||
if (maxSize) { | ||
stats = fs.statSync(file.path); | ||
if (!file.mimeType) { | ||
warn(`Unable to find asset mime-type for ${file.path}`); | ||
return; | ||
} | ||
if (stats.size >= maxSize) { | ||
return $return(inlineFallback.apply(this, $args)); | ||
} | ||
} | ||
const maxSize = (options.maxSize || 0) * 1024; | ||
isSvg = file.mimeType === "image/svg+xml"; | ||
defaultEncodeType = isSvg ? "encodeURIComponent" : "base64"; | ||
encodeType = options.encodeType || defaultEncodeType; | ||
if (maxSize) { | ||
const stats = fs.statSync(file.path); | ||
if (isSvg && asset.hash && !options.ignoreFragmentWarning) { | ||
warn("Image type is svg and link contains #.\n PostCSS Smart Asset can't handle SVG fragments.\n SVG file fully inlined. " + file.path); | ||
if (stats.size >= maxSize) { | ||
return inlineFallback.apply(this, arguments); | ||
} | ||
} | ||
addDependency(file.path); | ||
optimizeSvgEncode = isSvg && options.optimizeSvgEncode; | ||
return Promise.resolve(encodeFile(file, encodeType, optimizeSvgEncode)).then(function ($await_1) { | ||
try { | ||
encodedStr = $await_1; | ||
resultValue = options.includeUriFragment && asset.hash ? "" + encodedStr + asset.hash : encodedStr; | ||
return $return(isSvg && encodeType !== "base64" ? "\"" + resultValue + "\"" : resultValue); | ||
} catch ($boundEx) { | ||
return $error($boundEx); | ||
} | ||
}, $error); | ||
}.bind(this)); | ||
const isSvg = file.mimeType === "image/svg+xml"; | ||
const defaultEncodeType = isSvg ? "encodeURIComponent" : "base64"; | ||
const encodeType = options.encodeType || defaultEncodeType; // Warn for svg with hashes/fragments | ||
if (isSvg && asset.hash && !options.ignoreFragmentWarning) { | ||
// eslint-disable-next-line max-len | ||
warn(`Image type is svg and link contains #. | ||
PostCSS Smart Asset can't handle SVG fragments. | ||
SVG file fully inlined. ${file.path}`); | ||
} | ||
addDependency(file.path); | ||
const optimizeSvgEncode = isSvg && options.optimizeSvgEncode; | ||
const encodedStr = await encodeFile(file, encodeType, optimizeSvgEncode); | ||
const resultValue = options.includeUriFragment && asset.hash ? `${encodedStr}${asset.hash}` : encodedStr; // wrap url by quotes if percent-encoded svg | ||
return isSvg && encodeType !== "base64" ? `"${resultValue}"` : resultValue; | ||
} | ||
var matchesFilter = function matchesFilter(asset, pattern) { | ||
var relativeToRoot = path.relative(process.cwd(), asset.absolutePath); | ||
/** | ||
* Returns whether the given asset matches the given pattern | ||
Allways returns true if the given pattern is empty | ||
* | ||
* @param asset the processed asset | ||
* @param pattern A minimatch string, | ||
* regular expression or function to test the asset | ||
*/ | ||
if (typeof pattern == "string") { | ||
const matchesFilter = (asset, pattern) => { | ||
const relativeToRoot = path.relative(process.cwd(), asset.absolutePath); | ||
if (typeof pattern === "string") { | ||
pattern = minimatch.filter(pattern); | ||
@@ -294,6 +289,11 @@ return pattern(relativeToRoot); | ||
return true; | ||
}, | ||
matchOption = function matchOption(asset, option) { | ||
var matched = matchesFilter(asset, option.filter); | ||
}; | ||
/** | ||
* Matching single option | ||
*/ | ||
const matchOption = (asset, option) => { | ||
const matched = matchesFilter(asset, option.filter); | ||
if (!matched) { | ||
@@ -303,8 +303,12 @@ return false; | ||
return typeof option.url == "function" || !isUrlShouldBeIgnored(asset.url, option); | ||
}, | ||
isMultiOption = function isMultiOption(option) { | ||
return option.multi && typeof option.url == "function"; | ||
}, | ||
matchOptions = function matchOptions(asset, options) { | ||
return typeof option.url === "function" || !isUrlShouldBeIgnored(asset.url, option); | ||
}; | ||
const isMultiOption = option => option.multi && typeof option.url === "function"; | ||
/** | ||
* Matching options by asset | ||
*/ | ||
const matchOptions = (asset, options) => { | ||
if (!options) { | ||
@@ -315,5 +319,3 @@ return; | ||
if (Array.isArray(options)) { | ||
var optionIndex = options.findIndex(function (option) { | ||
return matchOption(asset, option); | ||
}); | ||
const optionIndex = options.findIndex(option => matchOption(asset, option)); | ||
@@ -324,3 +326,3 @@ if (optionIndex < 0) { | ||
var matchedOption = options[optionIndex]; | ||
const matchedOption = options[optionIndex]; // if founded option is last | ||
@@ -331,6 +333,4 @@ if (optionIndex === options.length - 1) { | ||
var extendOptions = options.slice(optionIndex + 1).filter(function (option) { | ||
return (isMultiOption(matchedOption) || isMultiOption(option)) && matchOption(asset, option); | ||
}); | ||
return extendOptions.length ? [matchedOption].concat(extendOptions) : matchedOption; | ||
const extendOptions = options.slice(optionIndex + 1).filter(option => (isMultiOption(matchedOption) || isMultiOption(option)) && matchOption(asset, option)); | ||
return extendOptions.length > 0 ? [matchedOption].concat(extendOptions) : matchedOption; | ||
} | ||
@@ -343,3 +343,3 @@ | ||
var modeMap = { | ||
const modeMap = { | ||
copy: copyAsset, | ||
@@ -349,13 +349,16 @@ custom: customAsset, | ||
rebase: rebaseAsset | ||
}, | ||
PROCESS_TYPES = new Set(["rebase", "inline", "copy", "custom"]), | ||
getUrlProcessorType = function getUrlProcessorType(optionUrl) { | ||
return typeof optionUrl == "function" ? "custom" : optionUrl || "rebase"; | ||
}; | ||
/** | ||
* Restricted modes | ||
*/ | ||
const PROCESS_TYPES = new Set(["rebase", "inline", "copy", "custom"]); | ||
const getUrlProcessorType = optionUrl => typeof optionUrl === "function" ? "custom" : optionUrl || "rebase"; | ||
function getUrlProcessor(optionUrl) { | ||
var mode = getUrlProcessorType(optionUrl); | ||
const mode = getUrlProcessorType(optionUrl); | ||
if (!PROCESS_TYPES.has(mode)) { | ||
throw new Error("Unknown mode for postcss-url: " + mode); | ||
throw new Error(`Unknown mode for postcss-url: ${mode}`); | ||
} | ||
@@ -366,22 +369,18 @@ | ||
var wrapUrlProcessor = function wrapUrlProcessor(urlProcessor, result, decl) { | ||
var warn = function warn(message) { | ||
return decl.warn(result, message); | ||
}, | ||
addDependency = function addDependency(file) { | ||
return result.messages.push({ | ||
type: "dependency", | ||
file: file, | ||
parent: getPathDeclFile(decl) | ||
}); | ||
}; | ||
const wrapUrlProcessor = (urlProcessor, result, decl) => { | ||
const warn = message => decl.warn(result, message); | ||
return function (asset, dir, option) { | ||
return urlProcessor(asset, dir, option, decl, warn, result, addDependency); | ||
}; | ||
}, | ||
replaceUrl = function replaceUrl(url, dir, options, result, decl) { | ||
var asset = prepareAsset(url, dir, decl), | ||
matchedOptions = matchOptions(asset, options); | ||
const addDependency = file => result.messages.push({ | ||
type: "dependency", | ||
file, | ||
parent: getPathDeclFile(decl) | ||
}); | ||
return (asset, dir, option) => urlProcessor(asset, dir, option, decl, warn, result, addDependency); | ||
}; | ||
const replaceUrl = (url, dir, options, result, decl) => { | ||
const asset = prepareAsset(url, dir, decl); | ||
const matchedOptions = matchOptions(asset, options); | ||
if (!matchedOptions) { | ||
@@ -391,4 +390,4 @@ return; | ||
var process = function process(option) { | ||
var wrappedUrlProcessor = wrapUrlProcessor(getUrlProcessor(option.url), result, decl); | ||
const process = option => { | ||
const wrappedUrlProcessor = wrapUrlProcessor(getUrlProcessor(option.url), result, decl); | ||
return wrappedUrlProcessor(asset, dir, option); | ||
@@ -398,3 +397,3 @@ }; | ||
if (Array.isArray(matchedOptions)) { | ||
matchedOptions.forEach(function (option) { | ||
matchedOptions.forEach(option => { | ||
asset.url = process(option); | ||
@@ -407,5 +406,6 @@ }); | ||
return asset.url; | ||
}, | ||
WITH_QUOTES = /^["']/; | ||
}; | ||
const WITH_QUOTES = /^["']/; | ||
function buildResult(newUrl, matched, before, after) { | ||
@@ -421,7 +421,8 @@ if (!newUrl) { | ||
return "" + before + newUrl + after; | ||
} | ||
return `${before}${newUrl}${after}`; | ||
} // Tracks visited declarations | ||
var processTracker = new Set(); | ||
var declProcessor = function declProcessor(from, to, options, result, decl) { | ||
const processTracker = new Set(); | ||
const declProcessor = (from, to, options, result, decl) => { | ||
if (processTracker.has(decl)) { | ||
@@ -431,8 +432,8 @@ return; | ||
var dir = { | ||
from: from, | ||
to: to, | ||
const dir = { | ||
from, | ||
to, | ||
file: getDirDeclFile(decl) | ||
}, | ||
pattern = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/g; | ||
}; | ||
const pattern = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/g; | ||
@@ -443,3 +444,3 @@ if (!pattern) { | ||
var matches = decl.value.match(pattern); | ||
const matches = decl.value.match(pattern); | ||
@@ -450,17 +451,14 @@ if (!matches) { | ||
return Promise.all(matches.map(function (singleMatch) { | ||
var _$exec = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/.exec(singleMatch); | ||
_$exec[0]; | ||
var before = _$exec[1], | ||
url = _$exec[2], | ||
after = _$exec[3], | ||
replacement = replaceUrl(url, dir, options, result, decl); | ||
return Promise.all(matches.map((singleMatch, index) => { | ||
const [matched, before, url, after] = /(url\(\s*["']?)([^"')]+)(["']?\s*\))/.exec(singleMatch); | ||
const replacement = replaceUrl(url, dir, options, result, decl); | ||
if (replacement) { | ||
if (replacement.then) { | ||
return replacement.then(function (resolved) { | ||
return buildResult(resolved, singleMatch, before, after); | ||
}); | ||
} | ||
return replacement.then(resolved => // const fullReplacement = resolved == null ? null : `${before}${resolved}${after}` | ||
// return fullReplacement | ||
buildResult(resolved, singleMatch, before, after)); | ||
} // const fullReplacement = `${before}${replacement}${after}` | ||
return buildResult(replacement, singleMatch, before, after); | ||
@@ -470,6 +468,6 @@ } | ||
return null; | ||
})).then(function (values) { | ||
})).then(values => { | ||
processTracker.add(decl); | ||
decl.value = decl.value.replace(pattern, function (match) { | ||
var replacement = values.shift(); | ||
decl.value = decl.value.replace(pattern, match => { | ||
const replacement = values.shift(); | ||
return replacement == null ? match : replacement; | ||
@@ -480,21 +478,19 @@ }); | ||
var index = (function (options) { | ||
if (options === void 0) { | ||
options = {}; | ||
var index = ((options = {}) => ({ | ||
postcssPlugin: "postcss-smart-asset", | ||
Declaration(decl, { | ||
result | ||
}) { | ||
const opts = result.opts; | ||
const from = opts.from ? path.dirname(opts.from) : "."; | ||
const to = opts.to ? path.dirname(opts.to) : from; | ||
return declProcessor(from, to, options, result, decl); | ||
} | ||
return { | ||
postcssPlugin: "postcss-smart-asset", | ||
Declaration: function Declaration(decl, _ref) { | ||
var result = _ref.result, | ||
opts = result.opts, | ||
from = opts.from ? path.dirname(opts.from) : ".", | ||
to = opts.to ? path.dirname(opts.to) : from; | ||
return declProcessor(from, to, options, result, decl); | ||
} | ||
}; | ||
}); | ||
var postcss = true; | ||
})); // PostCSS v8 marker | ||
const postcss = true; | ||
export { index as default, postcss }; | ||
//# sourceMappingURL=index.esm.js.map |
{ | ||
"name": "postcss-smart-asset", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "PostCSS plugin to rebase or inline on url().", | ||
@@ -35,3 +35,3 @@ "keywords": [ | ||
"dependencies": { | ||
"asset-hash": "^4.0.2", | ||
"asset-hash": "^4.0.4", | ||
"core-js": "^3.20.3", | ||
@@ -46,2 +46,4 @@ "mime": "^3.0.0", | ||
"@babel/core": "^7.16.10", | ||
"@babel/plugin-transform-runtime": "^7.16.10", | ||
"@babel/preset-env": "^7.16.10", | ||
"@effective/eslint-config": "^4.0.1", | ||
@@ -51,10 +53,9 @@ "@effective/prettier": "^4.3.4", | ||
"babel-jest": "^27.4.6", | ||
"babel-preset-edge": "^5.5.1", | ||
"eslint": "^8.7.0", | ||
"husky": "^7.0.4", | ||
"jest-cli": "^27.4.7", | ||
"jest": "^27.4.7", | ||
"lint-staged": "^12.2.1", | ||
"postcss": "^8.4.5", | ||
"postcss-import": "^14.0.2", | ||
"preppy": "^10.10.2", | ||
"preppy": "^11.0.1", | ||
"prettier": "^2.5.1", | ||
@@ -61,0 +62,0 @@ "release-it": "^14.12.3", |
@@ -1,12 +0,10 @@ | ||
# PostCSS Smart Asset<br/>[![Sponsored by][sponsor-img]][sponsor] [![Version][npm-version-img]][npm] [![Downloads][npm-downloads-img]][npm] [![Build Status Unix][travis-img]][travis] [![Build Status Windows][appveyor-img]][appveyor] | ||
# PostCSS Smart Asset<br/>[![Sponsored by][sponsor-img]][sponsor] [![Version][npm-version-img]][npm] [![Downloads][npm-downloads-img]][npm] [![Build Status][github-img]][github] | ||
[sponsor]: https://www.sebastian-software.de | ||
[npm]: https://www.npmjs.com/package/postcss-smart-asset | ||
[travis]: https://travis-ci.org/sebastian-software/postcss-smart-asset | ||
[appveyor]: https://ci.appveyor.com/project/swernerx/postcss-smart-asset/branch/master | ||
[sponsor-img]: https://badgen.net/badge/Sponsored%20by/Sebastian%20Software/692446 | ||
[npm-downloads-img]: https://badgen.net/npm/dm/postcss-smart-asset | ||
[npm-version-img]: https://badgen.net/npm/v/postcss-smart-asset | ||
[travis-img]: https://badgen.net/travis/sebastian-software/postcss-smart-asset?label=unix%20build | ||
[appveyor-img]: https://badgen.net/appveyor/ci/swernerx/postcss-smart-asset?label=windows%20build | ||
[github]: https://github.com/sebastian-software/postcss-smart-asset/actions | ||
[github-img]: https://badgen.net/github/status/sebastian-software/postcss-smart-asset?label=tests&icon=github | ||
@@ -13,0 +11,0 @@ [PostCSS](https://github.com/postcss/postcss) plugin to rebase, inline or copy on url(). |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
13
103552
18
801
287
1
Updatedasset-hash@^4.0.4