postcss-url
Advanced tools
Comparing version 6.1.0 to 6.3.1
@@ -0,1 +1,7 @@ | ||
# 6.3.0 - 2017-06-04 | ||
Added: `multi` property for `custom` | ||
Added: option to include fragment identifiers on inline data URIs | ||
Added: support ignoring SVG fragment inlining warning | ||
# 6.1.0 - 2017-05-13 | ||
@@ -2,0 +8,0 @@ |
{ | ||
"name": "postcss-url", | ||
"version": "6.1.0", | ||
"version": "6.3.1", | ||
"description": "PostCSS plugin to rebase or inline on url().", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -118,2 +118,5 @@ # postcss-url | ||
process first matched option by default. | ||
```multi: true``` in `custom` will processing with other options | ||
```js | ||
@@ -139,4 +142,6 @@ const options = [ | ||
* `encodeType` - `base64`, `encodeURI`, `encodeURIComponent` | ||
* `includeUriFragment` - include the fragment identifer at the end of the URI | ||
* `maxSize` - file size in kbytes | ||
* `fallback` - `copy` or custom function for files > `maxSize` | ||
* `ignoreFragmentWarning` - do not warn when an SVG URL with a fragment is inlined | ||
* `copy` | ||
@@ -148,2 +153,3 @@ * `basePath` - path or array of paths to search assets (relative to `from`, or absolute) | ||
* `custom {Function}` | ||
* `multi` - processing with other options | ||
@@ -185,2 +191,10 @@ ### Options list | ||
#### `ignoreFragmentWarning` | ||
_(default: `false`)_ | ||
Do not warn when an SVG URL with a fragment is inlined. | ||
PostCSS-URL does not support partial inlining. The entire SVG file will be inlined. By default a warning will be issued when this occurs. | ||
**NOTE:** Only files less than the maximum size will be inlined. | ||
#### `filter` | ||
@@ -195,2 +209,8 @@ | ||
#### `includeUriFragment` | ||
_(default: `false`)_ | ||
Specifies whether the URL's fragment identifer value, if present, will be added | ||
to the inlined data URI. | ||
#### `basePath` | ||
@@ -197,0 +217,0 @@ |
121
src/index.js
@@ -6,105 +6,6 @@ 'use strict'; | ||
const paths = require('./lib/paths'); | ||
const declProcessor = require('./lib/decl-processor').declProcessor; | ||
const getPathDeclFile = paths.getPathDeclFile; | ||
const getDirDeclFile = paths.getDirDeclFile; | ||
const prepareAsset = paths.prepareAsset; | ||
const isUrlShouldBeIgnored = paths.isUrlShouldBeIgnored; | ||
const matchOptions = require('./lib/match-options'); | ||
/** | ||
* @typedef UrlRegExp | ||
* @name UrlRegExp | ||
* @desc A regex for match url with parentheses: | ||
* (before url)(the url)(after url). | ||
* (the url) will be replace with new url, and before and after will remain | ||
* @type RegExp | ||
*/ | ||
/** | ||
* @type {UrlRegExp[]} | ||
*/ | ||
const URL_PATTERNS = [ | ||
/(url\(\s*['"]?)([^"')]+)(["']?\s*\))/g, | ||
/(AlphaImageLoader\(\s*src=['"]?)([^"')]+)(["'])/g | ||
]; | ||
/** | ||
* Restricted modes | ||
* | ||
* @type {String[]} | ||
*/ | ||
const PROCESS_TYPES = ['rebase', 'inline', 'copy', 'custom']; | ||
/** | ||
* @param {String} mode=copy|custom|inline|rebase | ||
* @returns {PostcssUrl~UrlProcessor} | ||
*/ | ||
function getUrlProcessor(mode) { | ||
if (~PROCESS_TYPES.indexOf(mode)) { | ||
return require(`./type/${mode}`); | ||
} | ||
throw new Error(`Unknown mode for postcss-url: ${mode}`); | ||
} | ||
/** | ||
* @param {Decl} decl | ||
* @returns {RegExp} | ||
*/ | ||
const getPattern = (decl) => | ||
URL_PATTERNS.find((pattern) => pattern.test(decl.value)); | ||
/** | ||
* @param {String} url | ||
* @param {Dir} dir | ||
* @param {Options} options | ||
* @param {Result} result | ||
* @param {Decl} decl | ||
* @returns {String|undefined} | ||
*/ | ||
const replaceUrl = (url, dir, options, result, decl) => { | ||
const asset = prepareAsset(url, dir, decl); | ||
const matchedOptions = matchOptions(asset, options); | ||
if (!matchedOptions) return; | ||
const isFunction = typeof matchedOptions.url === 'function'; | ||
if (!isFunction && isUrlShouldBeIgnored(url, matchedOptions)) return; | ||
const mode = isFunction ? 'custom' : (matchedOptions.url || 'rebase'); | ||
const urlProcessor = getUrlProcessor(mode); | ||
const warn = (message) => decl.warn(result, message); | ||
const addDependency = (file) => result.messages.push({ | ||
type: 'dependency', | ||
file, | ||
parent: getPathDeclFile(decl) | ||
}); | ||
return urlProcessor(asset, dir, matchedOptions, decl, warn, result, addDependency); | ||
}; | ||
/** | ||
* @param {PostcssUrl~Options} options | ||
* @param {Result} result | ||
* @param {PostcssUrl~Dir} dir | ||
* @param {Decl} decl | ||
* @returns {PostcssUrl~DeclProcessor} | ||
*/ | ||
const declProcessor = (options, result, dir, decl) => { | ||
const pattern = getPattern(decl); | ||
if (!pattern) return; | ||
decl.value = decl.value | ||
.replace(pattern, (matched, before, url, after) => { | ||
const newUrl = replaceUrl(url, dir, options, result, decl); | ||
return newUrl ? `${before}${newUrl}${after}` : matched; | ||
}); | ||
}; | ||
/** | ||
* | ||
* @type {Plugin} | ||
@@ -120,7 +21,5 @@ */ | ||
styles.walkDecls((decl) => { | ||
const dir = { from, to, file: getDirDeclFile(decl) }; | ||
return declProcessor(options, result, dir, decl); | ||
}); | ||
styles.walkDecls((decl) => | ||
declProcessor(from, to, options, result, decl) | ||
); | ||
}; | ||
@@ -141,14 +40,2 @@ }); | ||
/** | ||
* @typedef {Object} PostcssUrl~Options - postcss-url Options | ||
* @property {String} [url=^rebase|inline|copy|custom] - processing mode | ||
* @property {Minimatch|RegExp|Function} [filter] - filter assets by relative pathname | ||
* @property {String} [assetsPath] - absolute or relative path to copy assets | ||
* @property {String|String[]} [basePath] - absolute or relative paths to search, when copy or inline | ||
* @property {Number} [maxSize] - max file size in kbytes for inline mode | ||
* @property {String} [fallback] - fallback mode if file exceeds maxSize | ||
* @property {Boolean} [useHash] - use file hash instead filename | ||
* @property {HashOptions} [hashOptions] - params for generating hash name | ||
*/ | ||
/** | ||
* @typedef {Object} PostcssUrl~HashOptions | ||
@@ -155,0 +42,0 @@ * @property {Function|String} [method=^xxhash32|xxhash64] - hash name or custom function, accepting file content |
@@ -6,2 +6,6 @@ 'use strict'; | ||
const paths = require('./paths'); | ||
const isUrlShouldBeIgnored = paths.isUrlShouldBeIgnored; | ||
/** | ||
@@ -38,5 +42,23 @@ * Returns whether the given asset matches the given pattern | ||
/** | ||
* Matching options by filter property | ||
* Matching single option | ||
* | ||
* @param {PostcssUrl~Asset} asset | ||
* @param {PostcssUrl~Options} option | ||
* @returns {Boolean} | ||
*/ | ||
const matchOption = (asset, option) => { | ||
const matched = matchesFilter(asset, option.filter); | ||
if (!matched) return false; | ||
return typeof option.url === 'function' || !isUrlShouldBeIgnored(asset.url, option); | ||
}; | ||
const isMultiOption = (option) => | ||
option.multi && typeof option.url === 'function'; | ||
/** | ||
* Matching options by asset | ||
* | ||
* @param {PostcssUrl~Asset} asset | ||
* @param {PostcssUrl~Options|PostcssUrl~Options[]} options | ||
@@ -49,10 +71,25 @@ * @returns {PostcssUrl~Options|undefined} | ||
if (Array.isArray(options)) { | ||
return options.find((option) => matchesFilter(asset, option.filter)); | ||
const optionIndex = options.findIndex((option) => matchOption(asset, option)); | ||
if (optionIndex < 0) return; | ||
const matchedOption = options[optionIndex]; | ||
// if founded option is last | ||
if (optionIndex === options.length - 1) return matchedOption; | ||
const extendOptions = options | ||
.slice(optionIndex + 1) | ||
.filter((option) => | ||
(isMultiOption(matchedOption) || isMultiOption(option)) && matchOption(asset, option) | ||
); | ||
return extendOptions.length | ||
? [matchedOption].concat(extendOptions) | ||
: matchedOption; | ||
} | ||
if (!matchesFilter(asset, options.filter)) return; | ||
return options; | ||
if (matchOption(asset, options)) return options; | ||
}; | ||
module.exports = matchOptions; |
@@ -116,2 +116,3 @@ 'use strict'; | ||
url: assetUrl, | ||
originUrl: assetUrl, | ||
pathname, | ||
@@ -118,0 +119,0 @@ absolutePath: absolutePath || dir.from, |
@@ -69,3 +69,3 @@ 'use strict'; | ||
// Warn for svg with hashes/fragments | ||
if (isSvg && asset.hash) { | ||
if (isSvg && asset.hash && !options.ignoreFragmentWarning) { | ||
// eslint-disable-next-line max-len | ||
@@ -79,3 +79,3 @@ warn(`Image type is svg and link contains #. Postcss-url cant handle svg fragments. SVG file fully inlined. ${file.path}`); | ||
return asset.hash ? encodedStr + asset.hash : encodedStr; | ||
return (options.includeUriFragment && asset.hash) ? encodedStr + asset.hash : encodedStr; | ||
}; |
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
33683
15
604
257