stylesheet-loader
Version:
Stylesheet loader.
139 lines • 6.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFontFaceContent = exports.parse = void 0;
var css = require("css");
var loaderUtils = require("loader-utils");
var transformer_1 = require("./transformer");
var globalCSSVariable_1 = require("./globalCSSVariable");
var promptMessage_1 = require("./promptMessage");
var processPrefersColorScheme_1 = require("./processPrefersColorScheme");
var RULE = 'rule';
var FONT_FACE_RULE = 'font-face';
var MEDIA_RULE = 'media';
var QUOTES_REG = /['|"]/g;
// example "color: var(--name);" search string "var(" and ")"
var VAR_KEY_VAL_REG = /"(.*?)"\s*:\s*"var\((.*)\)"/g;
var GLOBAL_CSS_VAR = '__CSSVariables';
var CSS_VAR_NAME = ':root';
function styleSheetLoader(source) {
var self = typeof this === 'object' ? this : {};
self.cacheable && self.cacheable();
var stylesheet = css.parse(source).stylesheet;
if (stylesheet.parsingErrors.length) {
throw new Error('StyleSheet Parsing Error occured.');
}
// getOptions can return null if no query passed.
var parsedQuery = loaderUtils.getOptions(self) || {};
// Compatible with string true.
if (parsedQuery.log === 'true') {
parsedQuery.log = true;
}
var parsedData = exports.parse(parsedQuery, stylesheet);
return genStyleContent(parsedData, parsedQuery);
}
// export for test case
exports.parse = function (parsedQuery, stylesheet) {
var styles = {};
var fontFaceRules = [];
var mediaRules = [];
var transformDescendantCombinator = parsedQuery.transformDescendantCombinator;
stylesheet.rules.forEach(function (rule) {
var style = {};
// normal rule
if (rule.type === RULE) {
style = transformer_1.default.convert(rule, parsedQuery);
rule.selectors.forEach(function (selector) {
var sanitizedSelector = transformer_1.default.sanitizeSelector(selector, transformDescendantCombinator, rule.position, parsedQuery.log);
if (sanitizedSelector) {
// handle pseudo class
var pseudoIndex = sanitizedSelector.indexOf(':');
if (pseudoIndex > -1 && !parsedQuery.theme) {
var pseudoStyle_1 = {};
var pseudoName_1 = selector.slice(pseudoIndex + 1);
sanitizedSelector = sanitizedSelector.slice(0, pseudoIndex);
Object.keys(style).forEach(function (prop) {
pseudoStyle_1[prop + pseudoName_1] = style[prop];
});
style = pseudoStyle_1;
}
// eslint-disable-next-line eqeqeq
if (sanitizedSelector == CSS_VAR_NAME && parsedQuery.theme) {
sanitizedSelector = GLOBAL_CSS_VAR;
}
styles[sanitizedSelector] = Object.assign(styles[sanitizedSelector] || {}, style);
}
});
}
// font face rule
if (rule.type === FONT_FACE_RULE) {
var font_1 = {};
rule.declarations.forEach(function (declaration) {
font_1[declaration.property] = declaration.value;
});
fontFaceRules.push(font_1);
}
// media rule
if (rule.type === MEDIA_RULE) {
mediaRules.push({
key: rule.media,
data: exports.parse(parsedQuery, rule).styles,
});
}
});
return {
styles: styles,
fontFaceRules: fontFaceRules,
mediaRules: mediaRules,
};
};
var genStyleContent = function (parsedData, parsedQuery) {
var fontFaceRules = parsedData.fontFaceRules, mediaRules = parsedData.mediaRules;
var styles = processPrefersColorScheme_1.processPrefersColorScheme(mediaRules, parsedData.styles, parsedQuery.taskName);
var fontFaceContent = exports.getFontFaceContent(fontFaceRules);
var mediaContent = getMediaContent(mediaRules, parsedQuery);
var warnMessageOutput = parsedQuery.log ? getWarnMessageOutput() : '';
promptMessage_1.resetMessage();
return (parsedQuery.theme ? globalCSSVariable_1.default({ styles: styles, globalCSSVarName: GLOBAL_CSS_VAR }) : '') + "\n var _styles = " + stringifyData(styles, parsedQuery.theme) + ";\n" + fontFaceContent + "\n" + mediaContent + "\n" + warnMessageOutput + "\n module.exports = _styles;\n ";
};
var getWarnMessageOutput = function () {
var errorMessages = promptMessage_1.getErrorMessages();
var warnMessages = promptMessage_1.getWarnMessages();
var output = '';
if (errorMessages) {
output += "\n if (process.env.NODE_ENV !== 'production') {\n console.error('" + errorMessages + "');\n }\n ";
}
if (warnMessages) {
output += "\n if (process.env.NODE_ENV !== 'production') {\n console.warn('" + warnMessages + "');\n }\n ";
}
return output;
};
var getMediaContent = function (mediaRules, parsedQuery) {
var content = '';
mediaRules.forEach(function (rule) {
// Weex no need to process prefers-color-scheme media
if (parsedQuery.taskName !== 'weex' || !processPrefersColorScheme_1.isPrefersColorScheme(rule.key)) {
content += "\n if (window.matchMedia && window.matchMedia('" + rule.key + "').matches) {\n var ruleData = " + stringifyData(rule.data) + ";\n for(var key in ruleData) {\n _styles[key] = Object.assign(_styles[key] || {}, ruleData[key]);\n }\n }\n ";
}
});
return content;
};
// export for test case
exports.getFontFaceContent = function (rules) {
var content = '';
if (rules.length > 0) {
content += "\n if (typeof FontFace === 'function') {\n ";
}
rules.forEach(function (rule, index) {
content += "\n var fontFace" + index + " = new FontFace('" + rule['font-family'].replace(QUOTES_REG, '') + "', '" + rule.src.replace(QUOTES_REG, '"') + "');\n document.fonts.add(fontFace" + index + ");\n ";
});
if (rules.length > 0) {
content += "\n }\n ";
}
return content;
};
var stringifyData = function (data, theme) {
var str = JSON.stringify(data, undefined, ' ');
return !theme ? str : str.replace(VAR_KEY_VAL_REG, 'get $1(){return __getValue("$2")}');
};
exports.default = styleSheetLoader;
//# sourceMappingURL=index.js.map