forked from external-repos/squoosh
CSS plugin
This commit is contained in:
@@ -19,7 +19,6 @@ import postcss from 'postcss';
|
||||
import postCSSNested from 'postcss-nested';
|
||||
import postCSSUrl from 'postcss-url';
|
||||
import postCSSModules from 'postcss-modules';
|
||||
import postCSSImport from 'postcss-import';
|
||||
import postCSSSimpleVars from 'postcss-simple-vars';
|
||||
import cssNano from 'cssnano';
|
||||
import camelCase from 'lodash.camelcase';
|
||||
@@ -28,9 +27,19 @@ import glob from 'glob';
|
||||
const globP = promisify(glob);
|
||||
|
||||
const moduleSuffix = '.css';
|
||||
const prefix = 'css-bundle:';
|
||||
const sourcePrefix = 'css:';
|
||||
const addPrefix = 'add-css:';
|
||||
const assetRe = new RegExp('/fake/path/to/asset/([^/]+)/', 'g');
|
||||
|
||||
const appendCssModule = '\0appendCss';
|
||||
const appendCssSource = `
|
||||
export default function appendCss(css) {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = css;
|
||||
document.head.append(style);
|
||||
}
|
||||
`;
|
||||
|
||||
export default function (resolveFileUrl) {
|
||||
/** @type {string[]} */
|
||||
let emittedCSSIds;
|
||||
@@ -39,61 +48,6 @@ export default function (resolveFileUrl) {
|
||||
/** @type {Map<string, { module: string, css: string }>} */
|
||||
let pathToResult;
|
||||
|
||||
async function loadBundledCSS(path, rollupContext) {
|
||||
const parsedPath = parsePath(path);
|
||||
|
||||
if (!pathToResult.has(path)) {
|
||||
throw Error(`Cannot find ${path} in pathToResult`);
|
||||
}
|
||||
|
||||
const file = pathToResult.get(path).css;
|
||||
|
||||
const cssResult = await postcss([
|
||||
postCSSImport({
|
||||
path: ['./', 'static-build/'],
|
||||
load(path) {
|
||||
if (!pathToResult.has(path)) {
|
||||
throw Error(`Cannot find ${path} in pathToResult`);
|
||||
}
|
||||
return pathToResult.get(path).css;
|
||||
},
|
||||
}),
|
||||
postCSSUrl({
|
||||
url: ({ relativePath, url }) => {
|
||||
if (/^https?:\/\//.test(url)) return url;
|
||||
const parsedPath = parsePath(relativePath);
|
||||
const source = readFileSync(resolvePath(dirname(path), relativePath));
|
||||
const fileId = rollupContext.emitFile({
|
||||
type: 'asset',
|
||||
name: parsedPath.base,
|
||||
source,
|
||||
});
|
||||
const hash = createHash('md5');
|
||||
hash.update(source);
|
||||
const md5 = hash.digest('hex');
|
||||
hashToId.set(md5, fileId);
|
||||
return `/fake/path/to/asset/${md5}/`;
|
||||
},
|
||||
}),
|
||||
cssNano,
|
||||
]).process(file, {
|
||||
from: path,
|
||||
});
|
||||
|
||||
const fileId = rollupContext.emitFile({
|
||||
type: 'asset',
|
||||
source: cssResult.css,
|
||||
name: parsedPath.base,
|
||||
});
|
||||
|
||||
emittedCSSIds.push(fileId);
|
||||
|
||||
return [
|
||||
`export default import.meta.ROLLUP_FILE_URL_${fileId}`,
|
||||
`export const inline = ${JSON.stringify(cssResult.css)}`,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'css',
|
||||
async buildStart() {
|
||||
@@ -120,8 +74,28 @@ export default function (resolveFileUrl) {
|
||||
moduleJSON = json;
|
||||
},
|
||||
}),
|
||||
postCSSUrl({
|
||||
url: ({ relativePath, url }) => {
|
||||
if (/^https?:\/\//.test(url)) return url;
|
||||
const parsedPath = parsePath(relativePath);
|
||||
const source = readFileSync(
|
||||
resolvePath(dirname(path), relativePath),
|
||||
);
|
||||
const fileId = this.emitFile({
|
||||
type: 'asset',
|
||||
name: parsedPath.base,
|
||||
source,
|
||||
});
|
||||
const hash = createHash('md5');
|
||||
hash.update(source);
|
||||
const md5 = hash.digest('hex');
|
||||
hashToId.set(md5, fileId);
|
||||
return `/fake/path/to/asset/${md5}/`;
|
||||
},
|
||||
}),
|
||||
cssNano,
|
||||
]).process(file, {
|
||||
from: undefined,
|
||||
from: path,
|
||||
});
|
||||
|
||||
const cssClassExports = Object.entries(moduleJSON).map(
|
||||
@@ -152,14 +126,45 @@ export default function (resolveFileUrl) {
|
||||
);
|
||||
},
|
||||
async resolveId(id, importer) {
|
||||
if (!id.startsWith(prefix)) return;
|
||||
if (id === appendCssModule) return id;
|
||||
|
||||
const prefix = id.startsWith(sourcePrefix)
|
||||
? sourcePrefix
|
||||
: id.startsWith(addPrefix)
|
||||
? addPrefix
|
||||
: undefined;
|
||||
|
||||
if (!prefix) return;
|
||||
|
||||
const resolved = await this.resolve(id.slice(prefix.length), importer);
|
||||
if (!resolved) throw Error(`Couldn't resolve ${id} from ${importer}`);
|
||||
|
||||
return prefix + resolved.id;
|
||||
},
|
||||
async load(id) {
|
||||
if (id.startsWith(prefix)) {
|
||||
return loadBundledCSS(id.slice(prefix.length), this);
|
||||
if (id === appendCssModule) return appendCssSource;
|
||||
if (id.startsWith(sourcePrefix)) {
|
||||
const path = id.slice(sourcePrefix.length);
|
||||
|
||||
if (!pathToResult.has(path)) {
|
||||
throw Error(`Cannot find ${path} in pathToResult`);
|
||||
}
|
||||
|
||||
const cssStr = JSON.stringify(pathToResult.get(path).css).replace(
|
||||
assetRe,
|
||||
(match, hash) =>
|
||||
`" + import.meta.ROLLUP_FILE_URL_${hashToId.get(hash)} + "`,
|
||||
);
|
||||
|
||||
return `export default ${cssStr};`;
|
||||
}
|
||||
if (id.startsWith(addPrefix)) {
|
||||
const path = id.slice(addPrefix.length);
|
||||
return (
|
||||
`import css from 'css:${path}';\n` +
|
||||
`import appendCss from '${appendCssModule}';\n` +
|
||||
`appendCss(css);\n`
|
||||
);
|
||||
}
|
||||
if (id.endsWith(moduleSuffix)) {
|
||||
if (!pathToResult.has(id)) {
|
||||
@@ -169,27 +174,5 @@ export default function (resolveFileUrl) {
|
||||
return pathToResult.get(id).module;
|
||||
}
|
||||
},
|
||||
async generateBundle(options, bundle) {
|
||||
const cssAssets = emittedCSSIds.map((id) => this.getFileName(id));
|
||||
|
||||
for (const cssAsset of cssAssets) {
|
||||
bundle[cssAsset].source = bundle[cssAsset].source.replace(
|
||||
assetRe,
|
||||
(_, p1) =>
|
||||
resolveFileUrl({
|
||||
fileName: this.getFileName(hashToId.get(p1)),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
for (const item of Object.values(bundle)) {
|
||||
if (item.type === 'asset') continue;
|
||||
item.code = item.code.replace(assetRe, (match, p1) =>
|
||||
resolveFileUrl({
|
||||
fileName: this.getFileName(hashToId.get(p1)),
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user