"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 }; }); }; };