wishthis/node_modules/rework-import/index.js
2022-01-21 09:28:41 +01:00

194 lines
3.5 KiB
JavaScript

'use strict';
var fs = require('fs');
var path = require('path');
var css = require('css');
var globby = require('globby');
var parse = require('parse-import');
var urlRegex = require('url-regex');
/**
* Get options
*
* @param {Array} rules
* @param {Object} opts
* @api private
*/
function getOptions(rules, opts) {
var dir;
var obj = {
source: opts.source,
transform: opts.transform || function (val) {
return val;
}
};
obj.path = opts.path || [];
obj.path = Array.isArray(obj.path) ? obj.path : [obj.path];
if (rules.length && rules[0].position && rules[0].position.source) {
dir = path.dirname(rules[0].position.source);
}
if (dir && obj.path.indexOf(dir) === -1) {
obj.path.unshift(dir);
}
if (!obj.path.length) {
obj.path.push(process.cwd());
}
return obj;
}
/**
* Create error
*
* @param {String} file
* @param {String} src
* @param {Array} paths
* @api private
*/
function createError(file, src, paths) {
var err = ['Failed to find ' + file];
if (src) {
err.push('from ' + src);
}
err.push([
'in [',
' ' + paths.join(',\n '),
']'
].join('\n'));
return err.join(' ');
}
/**
* Create bad import rule error
*
* @param {String} rule
* @api private
*/
function createImportError(rule) {
var url = rule.import ? rule.import.replace(/\r?\n/g, '\\n') : '<no url>';
var err = ['Bad import url: @import ' + url];
if (rule.position) {
err.push(' starting at line ' + rule.position.start.line + ' column ' + rule.position.start.column);
err.push(' ending at line ' + rule.position.end.line + ' column ' + rule.position.end.column);
if (rule.position.source) {
err.push(' in ' + rule.position.source);
}
}
return err.join('\n');
}
/**
* Check if a file exists
*
* @param {String} file
* @param {String} src
* @param {Object} opts
* @api private
*/
function exists(file, src, opts) {
var files = opts.path.map(function (dir) {
return path.join(dir, file);
});
files = globby.sync(files);
if (!files.length) {
throw new Error(createError(file, src, opts.path));
}
return files[0];
}
/**
* Read the contents of a file
*
* @param {String} file
* @param {Object} opts
* @api private
*/
function read(file, opts) {
var encoding = opts.encoding || 'utf8';
var data = opts.transform(fs.readFileSync(file, encoding));
return css.parse(data, {source: file}).stylesheet;
}
/**
* Run
*
* @param {Object} style
* @param {Object} opts
* @api private
*/
function run(style, opts) {
opts = getOptions(style.rules, opts || {});
var rules = style.rules || [];
var ret = [];
rules.forEach(function (rule) {
if (rule.type !== 'import') {
ret.push(rule);
return;
}
var importRule = '@import ' + rule.import + ';';
var data = parse(importRule)[0];
var pos = rule.position ? rule.position.source : null;
if (!data) {
throw Error(createImportError(rule));
}
if (urlRegex({ exact: true }).test(data.path)) {
ret.push(rule);
return;
}
opts.source = exists(data.path, pos, opts);
if (opts.path.indexOf(path.dirname(opts.source)) === -1) {
opts.path.unshift(path.dirname(opts.source));
}
var content = read(opts.source, opts);
run(content, opts);
if (!data.condition || !data.condition.length) {
ret = ret.concat(content.rules);
return;
}
ret.push({
media: data.condition,
rules: content.rules,
type: 'media'
});
});
style.rules = ret;
}
/**
* Module exports
*/
module.exports = function (opts) {
return function (style) {
run(style, opts);
};
};