Fix code quality violations and exclude Manifest from checks
Document application modes (development/debug/production) Add global file drop handler, order column normalization, SPA hash fix Serve CDN assets via /_vendor/ URLs instead of merging into bundles Add production minification with license preservation Improve JSON formatting for debugging and production optimization Add CDN asset caching with CSS URL inlining for production builds Add three-mode system (development, debug, production) Update Manifest CLAUDE.md to reflect helper class architecture Refactor Manifest.php into helper classes for better organization Pre-manifest-refactor checkpoint: Add app_mode documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
57
node_modules/postcss-url/src/index.js
generated
vendored
Executable file
57
node_modules/postcss-url/src/index.js
generated
vendored
Executable file
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const declProcessor = require('./lib/decl-processor').declProcessor;
|
||||
|
||||
const plugin = (options) => {
|
||||
options = options || {};
|
||||
|
||||
return {
|
||||
postcssPlugin: 'postcss-url',
|
||||
Once(styles, { result }) {
|
||||
const promises = [];
|
||||
const opts = result.opts;
|
||||
const from = opts.from ? path.dirname(opts.from) : '.';
|
||||
const to = opts.to ? path.dirname(opts.to) : from;
|
||||
|
||||
styles.walkDecls((decl) =>
|
||||
promises.push(declProcessor(from, to, options, result, decl))
|
||||
);
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
plugin.postcss = true;
|
||||
|
||||
module.exports = plugin;
|
||||
|
||||
/**
|
||||
* @callback PostcssUrl~UrlProcessor
|
||||
* @param {String} from from
|
||||
* @param {String} dirname to dirname
|
||||
* @param {String} oldUrl url
|
||||
* @param {String} to destination
|
||||
* @param {Object} options plugin options
|
||||
* @param {Object} decl postcss declaration
|
||||
* @return {String|undefined} new url or undefined if url is old
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostcssUrl~HashOptions
|
||||
* @property {Function|String} [method=^xxhash32|xxhash64] - hash name or custom function, accepting file content
|
||||
* @see https://github.com/pierrec/js-xxhash
|
||||
* @property {Number} [shrink=8] - shrink hash string
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Decl - postcss decl
|
||||
* @see http://api.postcss.org/Declaration.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Result - postcss result
|
||||
* @see http://api.postcss.org/Result.html
|
||||
*/
|
||||
175
node_modules/postcss-url/src/lib/decl-processor.js
generated
vendored
Executable file
175
node_modules/postcss-url/src/lib/decl-processor.js
generated
vendored
Executable file
@@ -0,0 +1,175 @@
|
||||
'use strict';
|
||||
|
||||
const matchOptions = require('./match-options');
|
||||
const paths = require('./paths');
|
||||
|
||||
const getPathDeclFile = paths.getPathDeclFile;
|
||||
const getDirDeclFile = paths.getDirDeclFile;
|
||||
const prepareAsset = paths.prepareAsset;
|
||||
|
||||
/**
|
||||
* @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
|
||||
];
|
||||
|
||||
const WITH_QUOTES = /^['"]/;
|
||||
|
||||
/**
|
||||
* Restricted modes
|
||||
*
|
||||
* @type {String[]}
|
||||
*/
|
||||
const PROCESS_TYPES = ['rebase', 'inline', 'copy', 'custom'];
|
||||
|
||||
const getUrlProcessorType = (optionUrl) =>
|
||||
typeof optionUrl === 'function' ? 'custom' : (optionUrl || 'rebase');
|
||||
|
||||
/**
|
||||
* @param {String} optionUrl
|
||||
* @returns {PostcssUrl~UrlProcessor}
|
||||
*/
|
||||
function getUrlProcessor(optionUrl) {
|
||||
const mode = getUrlProcessorType(optionUrl);
|
||||
|
||||
if (PROCESS_TYPES.indexOf(mode) === -1) {
|
||||
throw new Error(`Unknown mode for postcss-url: ${mode}`);
|
||||
}
|
||||
|
||||
return require(`../type/${mode}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PostcssUrl~UrlProcessor} urlProcessor
|
||||
* @param {Result} result
|
||||
* @param {Decl} decl
|
||||
* @returns {Function}
|
||||
*/
|
||||
const wrapUrlProcessor = (urlProcessor, result, decl) => {
|
||||
const warn = (message) => decl.warn(result, message);
|
||||
const addDependency = (file) => result.messages.push({
|
||||
type: 'dependency',
|
||||
file,
|
||||
parent: getPathDeclFile(decl)
|
||||
});
|
||||
|
||||
return (asset, dir, option) =>
|
||||
urlProcessor(asset, dir, option, decl, warn, result, addDependency);
|
||||
};
|
||||
|
||||
/**
|
||||
* @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 {Promise<String|undefined>}
|
||||
*/
|
||||
const replaceUrl = (url, dir, options, result, decl) => {
|
||||
const asset = prepareAsset(url, dir, decl);
|
||||
|
||||
const matchedOptions = matchOptions(asset, options);
|
||||
|
||||
if (!matchedOptions) return Promise.resolve();
|
||||
|
||||
const process = (option) => {
|
||||
const wrappedUrlProcessor = wrapUrlProcessor(getUrlProcessor(option.url), result, decl);
|
||||
|
||||
return wrappedUrlProcessor(asset, dir, option);
|
||||
};
|
||||
|
||||
let resultPromise = Promise.resolve();
|
||||
|
||||
if (Array.isArray(matchedOptions)) {
|
||||
for (let i = 0; i < matchedOptions.length; i++) {
|
||||
resultPromise = resultPromise
|
||||
.then(() => process(matchedOptions[i]))
|
||||
.then((newUrl) => {
|
||||
asset.url = newUrl;
|
||||
|
||||
return newUrl;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
resultPromise = process(matchedOptions);
|
||||
}
|
||||
|
||||
return resultPromise.then((newUrl) => {
|
||||
asset.url = newUrl;
|
||||
|
||||
return newUrl;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} from
|
||||
* @param {String} to
|
||||
* @param {PostcssUrl~Options} options
|
||||
* @param {Result} result
|
||||
* @param {Decl} decl
|
||||
* @returns {Promise<PostcssUrl~DeclProcessor>}
|
||||
*/
|
||||
const declProcessor = (from, to, options, result, decl) => {
|
||||
const dir = { from, to, file: getDirDeclFile(decl) };
|
||||
const pattern = getPattern(decl);
|
||||
|
||||
if (!pattern) return Promise.resolve();
|
||||
|
||||
const promises = [];
|
||||
|
||||
decl.value = decl.value
|
||||
.replace(pattern, (matched, before, url, after) => {
|
||||
const newUrlPromise = replaceUrl(url, dir, options, result, decl);
|
||||
|
||||
promises.push(
|
||||
newUrlPromise
|
||||
.then((newUrl) => {
|
||||
if (!newUrl) return matched;
|
||||
|
||||
if (WITH_QUOTES.test(newUrl) && WITH_QUOTES.test(after)) {
|
||||
before = before.slice(0, -1);
|
||||
after = after.slice(1);
|
||||
}
|
||||
|
||||
decl.value = decl.value.replace(matched, `${before}${newUrl}${after}`);
|
||||
})
|
||||
);
|
||||
|
||||
return matched;
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
declProcessor
|
||||
};
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
55
node_modules/postcss-url/src/lib/encode.js
generated
vendored
Executable file
55
node_modules/postcss-url/src/lib/encode.js
generated
vendored
Executable file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Optimize encoding SVG files (IE9+, Android 3+)
|
||||
* @see https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
|
||||
*
|
||||
* @param {String} svgContent
|
||||
* @returns {String}
|
||||
*/
|
||||
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(/(%[0-9A-Z]{2})/g, (matched, AZ) => {
|
||||
return AZ.toLowerCase();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Encoding file contents to string
|
||||
*
|
||||
* @param {PostcssUrl~File} file
|
||||
* @param {String} [encodeType=base64|encodeURI|encodeURIComponent]
|
||||
* @param {Boolean} [shouldOptimizeURIEncode]
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
module.exports = (file, encodeType, shouldOptimizeSvgEncode) => {
|
||||
const dataMime = `data:${file.mimeType}`;
|
||||
|
||||
if (encodeType === 'base64') {
|
||||
return `${dataMime};base64,${file.contents.toString('base64')}`;
|
||||
}
|
||||
|
||||
const encodeFunc = encodeType === 'encodeURI' ? encodeURI : encodeURIComponent;
|
||||
|
||||
const content = file.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}`;
|
||||
};
|
||||
85
node_modules/postcss-url/src/lib/get-file.js
generated
vendored
Executable file
85
node_modules/postcss-url/src/lib/get-file.js
generated
vendored
Executable file
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const mime = require('mime');
|
||||
|
||||
const getPathByBasePath = require('./paths').getPathByBasePath;
|
||||
|
||||
const readFileAsync = (filePath) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(filePath, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const existFileAsync = (filePath) => {
|
||||
return new Promise((resolve) =>
|
||||
fs.access(filePath, (err) => {
|
||||
resolve(!err);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const findExistsPath = (paths) => {
|
||||
let resolved = false;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const findPromises = paths.map((path) => {
|
||||
return existFileAsync(path).then((isExists) => {
|
||||
if (!resolved && isExists) {
|
||||
resolved = true;
|
||||
resolve(path);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(findPromises).then(() => {
|
||||
if (!resolved) {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PostcssUrl~Asset} asset
|
||||
* @param {PostcssUrl~Options} options
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {Function} warn
|
||||
* @returns {Promise<PostcssUrl~File | Undefined>}
|
||||
*/
|
||||
const getFile = (asset, options, dir, warn) => {
|
||||
const paths = options.basePath
|
||||
? getPathByBasePath(options.basePath, dir.from, asset.pathname)
|
||||
: [asset.absolutePath];
|
||||
|
||||
return findExistsPath(paths)
|
||||
.then((path) => readFileAsync(path)
|
||||
.then((contents) => {
|
||||
return {
|
||||
path,
|
||||
contents,
|
||||
mimeType: mime.getType(path)
|
||||
};
|
||||
})
|
||||
)
|
||||
.catch(() => {
|
||||
warn(`Can't read file '${paths.join()}', ignoring`);
|
||||
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = getFile;
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostcssUrl~File
|
||||
* @property {String} path
|
||||
* @property {Buffer} contents
|
||||
* @property {String} mimeType
|
||||
*/
|
||||
54
node_modules/postcss-url/src/lib/hash.js
generated
vendored
Executable file
54
node_modules/postcss-url/src/lib/hash.js
generated
vendored
Executable file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
const xxh = require('xxhashjs');
|
||||
const HEXBASE = 16;
|
||||
|
||||
const defaultHashOptions = {
|
||||
method: 'xxhash32',
|
||||
shrink: 8,
|
||||
append: false
|
||||
};
|
||||
|
||||
const getxxhash = (content, options) => {
|
||||
const hashFunc = options.method === 'xxhash32' ? xxh.h32 : xxh.h64;
|
||||
const seed = 0;
|
||||
|
||||
return hashFunc(seed)
|
||||
.update(content)
|
||||
.digest()
|
||||
.toString(HEXBASE);
|
||||
};
|
||||
|
||||
const getHash = (content, options) => {
|
||||
if (options.method && typeof options.method === 'function') {
|
||||
return options.method(content);
|
||||
}
|
||||
|
||||
if (options.method && options.method.indexOf('xxhash') === 0) {
|
||||
return getxxhash(content, options);
|
||||
}
|
||||
|
||||
try {
|
||||
const hashFunc = crypto.createHash(options.method);
|
||||
|
||||
return hashFunc.update(content)
|
||||
.digest('hex');
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function(content, options) {
|
||||
options = options || defaultHashOptions;
|
||||
|
||||
let hash = getHash(content, options);
|
||||
|
||||
if (hash == null) {
|
||||
// bad hash method; fallback to defaults
|
||||
// TODO: warning/error reporting?
|
||||
hash = getHash(content, defaultHashOptions);
|
||||
}
|
||||
|
||||
return options.shrink ? hash.substr(0, options.shrink) : hash;
|
||||
};
|
||||
92
node_modules/postcss-url/src/lib/match-options.js
generated
vendored
Executable file
92
node_modules/postcss-url/src/lib/match-options.js
generated
vendored
Executable file
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
|
||||
const minimatch = require('minimatch');
|
||||
const path = require('path');
|
||||
|
||||
const paths = require('./paths');
|
||||
|
||||
const isUrlShouldBeIgnored = paths.isUrlShouldBeIgnored;
|
||||
|
||||
/**
|
||||
* Returns whether the given asset matches the given pattern
|
||||
* Allways returns true if the given pattern is empty
|
||||
*
|
||||
* @param {PostcssUrl~Asset} asset the processed asset
|
||||
* @param {String|RegExp|Function} pattern A minimatch string,
|
||||
* regular expression or function to test the asset
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
const matchesFilter = (asset, pattern) => {
|
||||
const relativeToRoot = path.relative(process.cwd(), asset.absolutePath);
|
||||
|
||||
if (typeof pattern === 'string') {
|
||||
pattern = minimatch.filter(pattern);
|
||||
|
||||
return pattern(relativeToRoot);
|
||||
}
|
||||
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(relativeToRoot);
|
||||
}
|
||||
|
||||
if (pattern instanceof Function) {
|
||||
return pattern(asset);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @returns {PostcssUrl~Options|undefined}
|
||||
*/
|
||||
const matchOptions = (asset, options) => {
|
||||
if (!options) return;
|
||||
|
||||
if (Array.isArray(options)) {
|
||||
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 (matchOption(asset, options)) return options;
|
||||
};
|
||||
|
||||
module.exports = matchOptions;
|
||||
155
node_modules/postcss-url/src/lib/paths.js
generated
vendored
Executable file
155
node_modules/postcss-url/src/lib/paths.js
generated
vendored
Executable file
@@ -0,0 +1,155 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
|
||||
/**
|
||||
* Normalazing result url, before replace decl value
|
||||
*
|
||||
* @param {String} assetUrl
|
||||
* @returns {String}
|
||||
*/
|
||||
const normalize = (assetUrl) => {
|
||||
assetUrl = path.normalize(assetUrl);
|
||||
|
||||
return path.sep === '\\' ? assetUrl.replace(/\\/g, '\/') : assetUrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} assetUrl
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
const isUrlWithoutPathname = (assetUrl) => {
|
||||
return assetUrl[0] === '#'
|
||||
|| assetUrl.indexOf('%23') === 0
|
||||
|| assetUrl.indexOf('data:') === 0
|
||||
|| /^[a-z]+:\/\//.test(assetUrl)
|
||||
|| /^\/\//.test(assetUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if url is absolute, hash or data-uri
|
||||
*
|
||||
* @param {String} assetUrl
|
||||
* @param {PostcssUrl~Options} options
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
const isUrlShouldBeIgnored = (assetUrl, options) => {
|
||||
const isAbsolutePath = assetUrl[0] === '/';
|
||||
const isStartsWithTilde = assetUrl[0] === '~';
|
||||
|
||||
return isUrlWithoutPathname(assetUrl) || ((isAbsolutePath || isStartsWithTilde) && !options.basePath);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} baseDir - absolute target path
|
||||
* @param {String} assetsPath - extend asset path, can be absolute path
|
||||
* @param {String} relative - current relative asset path
|
||||
* @returns {String}
|
||||
*/
|
||||
const getAssetsPath = (baseDir, assetsPath, relative) =>
|
||||
path.resolve(baseDir, assetsPath || '', relative || '');
|
||||
|
||||
/**
|
||||
* Target path, output base dir
|
||||
*
|
||||
* @param {Dir} dir
|
||||
* @returns {String}
|
||||
*/
|
||||
const getTargetDir = (dir) =>
|
||||
dir.to != null ? dir.to : process.cwd();
|
||||
|
||||
/**
|
||||
* Stylesheet file path from decl
|
||||
*
|
||||
* @param {Decl} decl
|
||||
* @returns {String}
|
||||
*/
|
||||
const getPathDeclFile = (decl) =>
|
||||
decl.source && decl.source.input && decl.source.input.file;
|
||||
|
||||
/**
|
||||
* Stylesheet file dir from decl
|
||||
*
|
||||
* @param {Decl} decl
|
||||
* @returns {String}
|
||||
*/
|
||||
const getDirDeclFile = (decl) => {
|
||||
const filename = getPathDeclFile(decl);
|
||||
|
||||
return filename ? path.dirname(filename) : process.cwd();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns paths list, where we can find assets file
|
||||
*
|
||||
* @param {String[]|String} basePath - base paths where trying search to assets file
|
||||
* @param {Dir} dirFrom
|
||||
* @param {String} relPath - relative asset path
|
||||
* @returns {String[]}
|
||||
*/
|
||||
const getPathByBasePath = (basePath, dirFrom, relPath) => {
|
||||
if (relPath[0] === '/') {
|
||||
relPath = `.${relPath}`;
|
||||
}
|
||||
|
||||
basePath = !Array.isArray(basePath) ? [basePath] : basePath;
|
||||
|
||||
return basePath.map((pathItem) =>
|
||||
getAssetsPath(dirFrom, pathItem, relPath)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Preparing asset paths and data
|
||||
*
|
||||
* @param {String} assetUrl
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {Decl} decl
|
||||
* @returns {PostcssUrl~Asset}
|
||||
*/
|
||||
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,
|
||||
absolutePath: absolutePath || dir.from,
|
||||
relativePath: absolutePath ? path.relative(dir.from, absolutePath) : '.',
|
||||
search: (parsedUrl.search || ''),
|
||||
hash: (parsedUrl.hash || '')
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
normalize,
|
||||
prepareAsset,
|
||||
getAssetsPath,
|
||||
getDirDeclFile,
|
||||
getPathDeclFile,
|
||||
getTargetDir,
|
||||
getPathByBasePath,
|
||||
isUrlShouldBeIgnored
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostcssUrl~Asset
|
||||
* @property {String} url - origin asset url
|
||||
* @property {String} name - parsed asset filename
|
||||
* @property {String} absolutePath - absolute asset path
|
||||
* @property {String} relativePath - relative asset path (relative to target dir)
|
||||
* @property {String} search - search from url, ex. ?query=1
|
||||
* @property {String} hash - hash from url
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostcssUrl~Dir
|
||||
* @property {String} from - dirname from postcss option 'from'
|
||||
* @property {String} to - dirname from postcss option 'to'
|
||||
* @property {String} file - decl file dirname (css file)
|
||||
*/
|
||||
79
node_modules/postcss-url/src/type/copy.js
generated
vendored
Executable file
79
node_modules/postcss-url/src/type/copy.js
generated
vendored
Executable file
@@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const makeDir = require('make-dir');
|
||||
|
||||
const calcHash = require('../lib/hash');
|
||||
const paths = require('../lib/paths');
|
||||
const getFile = require('../lib/get-file');
|
||||
|
||||
const getTargetDir = paths.getTargetDir;
|
||||
const getAssetsPath = paths.getAssetsPath;
|
||||
const normalize = paths.normalize;
|
||||
|
||||
const getHashName = (file, options) =>
|
||||
(options && options.append ? (`${path.basename(file.path, path.extname(file.path))}_`) : '')
|
||||
+ calcHash(file.contents, options)
|
||||
+ path.extname(file.path);
|
||||
|
||||
const writeFileAsync = (file, dest) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(dest, file.contents, { flag: 'wx' }, (err) => {
|
||||
if (err) {
|
||||
err.code === 'EEXIST' ? resolve() : reject(err);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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`)
|
||||
*
|
||||
* @type {PostcssUrl~UrlProcessor}
|
||||
* @param {PostcssUrl~Asset} asset
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {PostcssUrl~Option} options
|
||||
* @param {PostcssUrl~Decl} decl
|
||||
* @param {Function} warn
|
||||
* @param {Result} result
|
||||
* @param {Function} addDependency
|
||||
*
|
||||
* @returns {Promise<String|Undefined>}
|
||||
*/
|
||||
|
||||
module.exports = function processCopy(asset, dir, options, decl, warn, result, addDependency) {
|
||||
if (!options.assetsPath && dir.from === dir.to) {
|
||||
warn('Option `to` of postcss is required, ignoring');
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return getFile(asset, options, dir, warn)
|
||||
.then((file) => {
|
||||
if (!file) return;
|
||||
|
||||
const assetRelativePath = options.useHash
|
||||
? getHashName(file, options.hashOptions)
|
||||
: asset.relativePath;
|
||||
|
||||
const targetDir = getTargetDir(dir);
|
||||
const newAssetBaseDir = getAssetsPath(targetDir, options.assetsPath);
|
||||
const newAssetPath = path.join(newAssetBaseDir, assetRelativePath);
|
||||
const newRelativeAssetPath = normalize(path.relative(targetDir, newAssetPath));
|
||||
|
||||
return makeDir(path.dirname(newAssetPath))
|
||||
.then(() => writeFileAsync(file, newAssetPath))
|
||||
.then(() => {
|
||||
addDependency(file.path);
|
||||
|
||||
return `${newRelativeAssetPath}${asset.search}${asset.hash}`;
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
13
node_modules/postcss-url/src/type/custom.js
generated
vendored
Executable file
13
node_modules/postcss-url/src/type/custom.js
generated
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Transform url() based on a custom callback
|
||||
*
|
||||
* @type {PostcssUrl~UrlProcessor}
|
||||
* @param {PostcssUrl~Asset} asset
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {PostcssUrl~Option} options
|
||||
*
|
||||
* @returns {Promise<String|Undefined>}
|
||||
*/
|
||||
module.exports = function getCustomProcessor(asset, dir, options) {
|
||||
return Promise.resolve().then(() => options.url.apply(null, arguments));
|
||||
};
|
||||
91
node_modules/postcss-url/src/type/inline.js
generated
vendored
Executable file
91
node_modules/postcss-url/src/type/inline.js
generated
vendored
Executable file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
const processCopy = require('./copy');
|
||||
const processRebase = require('./rebase');
|
||||
|
||||
const encodeFile = require('../lib/encode');
|
||||
const getFile = require('../lib/get-file');
|
||||
|
||||
/**
|
||||
* @param {String} originUrl
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {PostcssUrl~Option} options
|
||||
*
|
||||
* @returns {String|Undefined}
|
||||
*/
|
||||
function processFallback(originUrl, dir, options) {
|
||||
if (typeof options.fallback === 'function') {
|
||||
return options.fallback.apply(null, arguments);
|
||||
}
|
||||
switch (options.fallback) {
|
||||
case 'copy':
|
||||
return processCopy.apply(null, arguments);
|
||||
case 'rebase':
|
||||
return processRebase.apply(null, arguments);
|
||||
default:
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
const inlineProcess = (file, asset, warn, addDependency, options) => {
|
||||
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-url cant handle svg fragments. SVG file fully inlined. ${file.path}`);
|
||||
}
|
||||
|
||||
addDependency(file.path);
|
||||
|
||||
const optimizeSvgEncode = isSvg && options.optimizeSvgEncode;
|
||||
const encodedStr = 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inline image in url()
|
||||
*
|
||||
* @type {PostcssUrl~UrlProcessor}
|
||||
* @param {PostcssUrl~Asset} asset
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {PostcssUrl~Options} options
|
||||
* @param {PostcssUrl~Decl} decl
|
||||
* @param {Function} warn
|
||||
* @param {Result} result
|
||||
* @param {Function} addDependency
|
||||
*
|
||||
* @returns {Promise<String|Undefined>}
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
module.exports = function(asset, dir, options, decl, warn, result, addDependency) {
|
||||
return getFile(asset, options, dir, warn)
|
||||
.then((file) => {
|
||||
if (!file) return;
|
||||
|
||||
if (!file.mimeType) {
|
||||
warn(`Unable to find asset mime-type for ${file.path}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const maxSize = (options.maxSize || 0) * 1024;
|
||||
|
||||
if (maxSize) {
|
||||
const size = Buffer.byteLength(file.contents);
|
||||
|
||||
if (size >= maxSize) {
|
||||
return processFallback.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
return inlineProcess(file, asset, warn, addDependency, options);
|
||||
});
|
||||
};
|
||||
25
node_modules/postcss-url/src/type/rebase.js
generated
vendored
Executable file
25
node_modules/postcss-url/src/type/rebase.js
generated
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const paths = require('../lib/paths');
|
||||
const normalize = paths.normalize;
|
||||
const getAssetsPath = paths.getAssetsPath;
|
||||
|
||||
/**
|
||||
* Fix url() according to source (`from`) or destination (`to`)
|
||||
*
|
||||
* @type {PostcssUrl~UrlProcessor}
|
||||
* @param {PostcssUrl~Asset} asset
|
||||
* @param {PostcssUrl~Dir} dir
|
||||
* @param {PostcssUrl~Option} options
|
||||
*
|
||||
* @returns {Promise<String>}
|
||||
*/
|
||||
module.exports = function(asset, dir, options) {
|
||||
const dest = getAssetsPath(dir.to, options && options.assetsPath || '');
|
||||
const rebasedUrl = normalize(
|
||||
path.relative(dest, asset.absolutePath)
|
||||
);
|
||||
|
||||
return Promise.resolve().then(() => `${rebasedUrl}${asset.search}${asset.hash}`);
|
||||
};
|
||||
Reference in New Issue
Block a user