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.

67 lines
2.2 KiB
JavaScript

"use strict";
const Promise = require("bluebird");
const postcss = require("postcss");
const defaultValue = require("default-value");
const objectFromEntries = require("object.fromentries");
const icssParser = require("./postcss-icss-parser");
module.exports = function createFilePostprocessor(options) {
let allExports = new Map(); // url -> (remoteKey -> mangledName)
return function processFile(item) {
return Promise.try(() => {
// TODO: Reuse instance, figure out how to pass the file metadata to the callback for an individual `process` call
let postcssInstance = postcss([
icssParser({
keyReplacer: ({ url, remoteKey }) => {
let resolvedSourcePath = item.deps[url];
if (resolvedSourcePath == null) {
throw new Error(`Referenced file '${sourceFile}' not resolved. This should never happen; please file a bug!`);
}
let sourceFile = allExports.get(resolvedSourcePath);
if (sourceFile == null) {
throw new Error(`Referenced file '${sourceFile}' not processed. This should never happen; please file a bug!`);
}
let mangledName = sourceFile.get(remoteKey);
if (mangledName == null) {
// TODO: Error type
throw new Error(`No export named '${remoteKey}' found in file ${url}`);
}
/* The replacement is to deal with the difference in multiple-class notation between CSS and HTML; in CSS they are dot-delimited, but in HTML (which the ICSS spec targets) they are space-delimited. We need the CSS notation here. */
return mangledName.replace(/ /g, ".");
}
}),
... defaultValue(options.after, [])
]);
return postcssInstance.process(item.source, {
from: item.file,
... options
});
}).then((result) => {
let exportMessages = result.messages.filter((message) => {
return (message.pluginName === "postcss-icss-parser" && message.type === "icss-export");
});
let exportEntries = exportMessages.map((message) => {
return [ message.item.name, message.item.value ];
});
let exportMap = new Map(exportEntries);
let exportObject = objectFromEntries(exportEntries);
allExports.set(item.file, exportMap);
return { result, icssExports: exportObject };
});
};
};