@reactml/loader
Version:
Webpack loader for react markup language.
63 lines (54 loc) • 2.05 kB
JavaScript
const RuleSet = require('webpack/lib/RuleSet');
const loaderUtils = require('loader-utils');
const paths = require('./paths');
const { getResourcePart } = require('./parts');
module.exports = function styleLoader(styleContent) {
const { resourcePath, resourceQuery } = this;
const stringifyRequest = r => loaderUtils.stringifyRequest(this, r);
const style = getResourcePart(resourcePath, 'style');
// No style tag exists.
if (!style) return '';
// Use webpack's RuleSet utility to normalize user rules
const compiler = this._compiler;
const rawRules = compiler.options.module.rules;
const { rules } = new RuleSet(rawRules);
// Find the rule that applies to rml files
const lang = style.attrs.lang || 'css';
const styleRuleIndex = rawRules.findIndex(createMatcher(`foo.${lang}`));
const styleRule = rules[styleRuleIndex];
if (styleRule.oneOf) {
throw new Error(
'[RML Loader Error] Currently does not support style rules with oneOf.'
);
}
const genRequest = uses => {
const loaderStrings = uses.map(use => {
const query = typeof use.options === 'string'
? use.options
: use.options ? JSON.stringify(use.options) : '';
const loader = typeof use.loader === 'string' ? use.loader : use.loader.request;
return loader + (query ? '?' + query : '');
});
return stringifyRequest('-!' + [
...loaderStrings,
`${paths.partLoader}?part=style`,
resourcePath + resourceQuery
].join('!'));
};
// Get the normlized "use" for style files
const request = genRequest(styleRule.use.concat());
return `import mod from ${request}; export default mod; export * from ${request};`;
};
function createMatcher(fakeFile) {
return (rule, i) => {
// Skip the `include` check when locating the rml rule
const clone = Object.assign({}, rule);
delete clone.include;
const normalized = RuleSet.normalizeRule(clone, {}, '');
return (
!rule.enforce &&
normalized.resource &&
normalized.resource(fakeFile)
);
};
}