You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
3.3 KiB
JavaScript
72 lines
3.3 KiB
JavaScript
"use strict";
|
|
|
|
const Promise = require("bluebird");
|
|
const path = require("path");
|
|
const mapObj = require("map-obj");
|
|
|
|
const stream = require("../stream");
|
|
const createFilePostprocessor = require("../postcss/postprocess");
|
|
const loaderShimPath = require("../loader-shim-path");
|
|
|
|
// NOTE: This stream is inserted directly after the 'dedupe' phase, and *not* before the 'pack' phase like in postcssify-icss, because that would break `extract-css` - which inserts itself before the 'label' phase that comes after the 'dedupe' phase, and by which time all the CSS needs to be prepared.
|
|
|
|
module.exports = function (state) {
|
|
const isCss = require("../is-css")(state);
|
|
|
|
return function createDedupeBundleCssStream(options) {
|
|
// TODO: Reuse instance?
|
|
let processFile = createFilePostprocessor(options);
|
|
let allCss = "";
|
|
let loaderItem;
|
|
|
|
let entryPoint = (options._flags != null && options._flags.entries != null)
|
|
// Get the (absolute!) path of the folder containing the initial entry file, as a reference point for relative paths in the output
|
|
? path.dirname(path.resolve(options._flags.entries[0]))
|
|
// ... or, if no entry file is specified, go off the current working directory
|
|
: process.cwd();
|
|
|
|
return stream((item) => {
|
|
// And the same for the loader shim path. All this relative-path stuff is to prevent absolute filesystem URLs from leaking into the output, as those might contain sensitive information.
|
|
let relativeLoaderPath = path.relative(path.dirname(item.file), loaderShimPath);
|
|
|
|
if (isCss(item)) {
|
|
return Promise.try(() => {
|
|
return processFile(item);
|
|
}).then(({ result, icssExports }) => {
|
|
// NOTE: This is a workaround, until we find a more robust solution to this. While composed classes should be delimited by dots in CSS, they should be delimited by *spaces* in HTML. In "double compose" cases, ie. when one class composes another class which was already composed with a third class, we can get a class string like "foo bar.baz" which is wrong; this replaces all the erroneous dots with spaces.
|
|
let icssExportsHTML = mapObj(icssExports, (key, value) => {
|
|
return [ key, value.replace(/\./g, " ") ];
|
|
});
|
|
|
|
allCss += `/* from ${path.relative(entryPoint, item.file)} */\n\n${result.css}\n\n`;
|
|
|
|
if (!item.__icssify__discardable) {
|
|
return {
|
|
... item,
|
|
source: `require(${JSON.stringify(relativeLoaderPath)}); module.exports = ${JSON.stringify(icssExportsHTML)};`
|
|
};
|
|
}
|
|
});
|
|
} else if (item.file === loaderShimPath) {
|
|
// Stockpile this item, to emit at the very end, right before the browser-pack operation (because by that time, we'll have processed and therefore concatenated all the CSS files)
|
|
loaderItem = item;
|
|
return null;
|
|
} else {
|
|
return item;
|
|
}
|
|
}, () => {
|
|
if (allCss.length > 0) {
|
|
if (loaderItem != null) {
|
|
return {
|
|
... loaderItem,
|
|
source: loaderItem.source.replace('"## CONTENT MARKER ##"', JSON.stringify(allCss))
|
|
};
|
|
} else {
|
|
// FIXME: Can occur if some dependency also gets processed and require()s a CSS file, but does not specify icssify as a transform (but the using project does) -- like with ui-lib + site-builder
|
|
throw new Error("Processed CSS, but global loader was not encountered. This should never happen, please report it as a bug!");
|
|
}
|
|
}
|
|
});
|
|
};
|
|
};
|