mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-13 01:07:18 +00:00
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)),
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
5
missing-types.d.ts
vendored
5
missing-types.d.ts
vendored
@@ -22,4 +22,9 @@ declare module 'omt:*' {
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module 'css:*' {
|
||||
const source: string;
|
||||
export default source;
|
||||
}
|
||||
|
||||
declare const __PRODUCTION__: boolean;
|
||||
|
||||
107
package-lock.json
generated
107
package-lock.json
generated
@@ -2795,12 +2795,6 @@
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||
"dev": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
@@ -3431,98 +3425,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-import": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
|
||||
"integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"postcss": "^7.0.1",
|
||||
"postcss-value-parser": "^3.2.3",
|
||||
"read-cache": "^1.0.0",
|
||||
"resolve": "^1.1.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "7.0.34",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz",
|
||||
"integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"source-map": "^0.6.1",
|
||||
"supports-color": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"postcss-value-parser": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
|
||||
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-merge-longhand": {
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz",
|
||||
@@ -5975,15 +5877,6 @@
|
||||
"strip-json-comments": "~2.0.1"
|
||||
}
|
||||
},
|
||||
"read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
"integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pify": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"registry-auth-token": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"lint-staged": "^10.4.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"postcss": "^8.0.8",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-modules": "^3.2.2",
|
||||
"postcss-nested": "^5.0.0",
|
||||
"postcss-simple-vars": "^6.0.0",
|
||||
|
||||
@@ -6,6 +6,7 @@ import { h, Component } from 'preact';
|
||||
|
||||
import { linkRef } from 'client/initial-app/util';
|
||||
import * as style from './style.css';
|
||||
import 'add-css:./style.css';
|
||||
import 'file-drop-element';
|
||||
import 'client/initial-app/custom-els/snack-bar';
|
||||
//import Intro from '../intro';
|
||||
|
||||
2
src/client/missing-types.d.ts
vendored
2
src/client/missing-types.d.ts
vendored
@@ -21,4 +21,6 @@ interface Navigator {
|
||||
readonly standalone: boolean;
|
||||
}
|
||||
|
||||
declare module 'add-css:*' {}
|
||||
|
||||
declare module 'preact/debug' {}
|
||||
|
||||
6
src/static-build/missing-types.d.ts
vendored
6
src/static-build/missing-types.d.ts
vendored
@@ -17,9 +17,3 @@ declare module 'client-bundle:*' {
|
||||
export default url;
|
||||
export const imports: string[];
|
||||
}
|
||||
|
||||
declare module 'css-bundle:*' {
|
||||
const url: string;
|
||||
export default url;
|
||||
export const inline: string;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
*/
|
||||
import { h, FunctionalComponent } from 'preact';
|
||||
|
||||
import styles from 'css-bundle:./all.css';
|
||||
import css from 'css:./all.css';
|
||||
import clientBundleURL, { imports } from 'client-bundle:client/initial-app';
|
||||
import favicon from 'url:static-build/assets/favicon.ico';
|
||||
import { escapeStyleScriptContent } from 'static-build/utils';
|
||||
|
||||
interface Props {}
|
||||
|
||||
@@ -35,7 +36,9 @@ const Index: FunctionalComponent<Props> = () => (
|
||||
<link rel="shortcut icon" href={favicon} />
|
||||
<meta name="theme-color" content="#f78f21" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="stylesheet" href={styles} />
|
||||
<style
|
||||
dangerouslySetInnerHTML={{ __html: escapeStyleScriptContent(css) }}
|
||||
/>
|
||||
<script src={clientBundleURL} defer />
|
||||
{imports.map((v) => (
|
||||
<link rel="preload" as="script" href={v} />
|
||||
|
||||
@@ -44,3 +44,15 @@ export function writeFiles(toOutput: OutputMap) {
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string for insertion in a style or script tag
|
||||
*/
|
||||
export function escapeStyleScriptContent(str: string): string {
|
||||
return str
|
||||
.replace(/<!--/g, '<\\!--')
|
||||
.replace(/<script/g, '<\\script')
|
||||
.replace(/<\/script/g, '<\\/script')
|
||||
.replace(/<style/g, '<\\style')
|
||||
.replace(/<\/style/g, '<\\/style');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user