Skip to content

Commit

Permalink
feat: 从项目目录内加载 postcss 配置
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed May 12, 2024
1 parent 37d4fbb commit 10f75c9
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 41 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
"chalk": "^4.1.1",
"change-case": "^4.1.2",
"commander": "^11.0.0",
"cosmiconfig": "^9.0.0",
"fs-extra": "^10.0.0",
"os-locale": "^6.0.2",
"postcss": "^8.4.27",
"postcss": "^8.4.38",
"postcss-modules": "^6.0.0",
"postcss-sass": "^0.5.0",
"postcss-url": "^10.1.3",
Expand Down
84 changes: 49 additions & 35 deletions lib/compiler/css-loader.js → src/compiler/css-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,65 @@ import path from "path";
import postcss from "postcss";
import postcssUrl from "postcss-url";
import postcssModules from "postcss-modules";
import { LoaderContext, LoaderInput, ModuleMetadata } from "../types.js";
import { loadConfig } from "../utils.js";

/** @type {Loader} */
export default async function CSSLoader(content) {
export default async function CSSLoader(
this: LoaderContext,
content: LoaderInput
) {
const loader = this;
const { modules } = loader.getOptions();
const cssText = `${content}`;
const result = await postcss(
[
postcssUrl({
async url(asset) {
try {
const outputPath = (
await loader.importModule(path.resolve(loader.context, asset.url))
).default;
if (typeof outputPath === "string") {
return outputPath;
}
} catch (err) {
err.message = `url(${asset.url}):\n${err.message}`;
loader.emitError(err);
const processor = postcss().use(
postcssUrl({
async url(asset) {
try {
const outputPath = (
await loader.importModule(path.resolve(loader.context, asset.url))
).default;
if (typeof outputPath === "string") {
return outputPath;
}
loader.emitError(
new Error(
`url(${asset.url}): File does not exist or there is no matching loader`
)
);
return asset.url;
},
}),
modules &&
postcssModules({
exportGlobals: true,
getJSON() {},
}),
].filter(Boolean)
)
} catch (err) {
err.message = `url(${asset.url}):\n${err.message}`;
loader.emitError(err);
}
loader.emitError(
new Error(
`url(${asset.url}): File does not exist or there is no matching loader`
)
);
return asset.url;
},
})
);
if (modules) {
processor.use(
postcssModules({
exportGlobals: true,
getJSON() {},
})
);
}
const customConfig = (await loadConfig(loader, "postcss")) as null | {
plugins?: postcss.AcceptedPlugin[];
};
if (customConfig && Array.isArray(customConfig.plugins)) {
customConfig.plugins.forEach((plugin) => processor.use(plugin));
}
const result = await processor
.process(cssText, { from: loader.resourcePath })
.async();

const ident = `css_str_${path
.parse(this.resourcePath)
.name.replace(/[^a-zA-Z0-9]/g, "_")}`;

/** @type {ModuleMetadata} */
const metadata = {
const metadata: ModuleMetadata = {
type: "asset",
path: loader.resourcePath,
outputPath: loader.outputPath,
outputPath: loader.resourceOutputPath,
headerFiles: ["<ui.h>", `"${loader.resourceOutputPath}"`],
initCode: `ui_load_css_string(${ident}, ${JSON.stringify(
path.relative(loader.context, loader.resourcePath)
Expand Down Expand Up @@ -79,7 +90,10 @@ export default async function CSSLoader(content) {
.join("\\\n");

return [
`/** Generated from: ${path.relative(path.dirname(this.resourceOutputPath), this.resourcePath)} */`,
`/** Generated from: ${path.relative(
path.dirname(this.resourceOutputPath),
this.resourcePath
)} */`,
`static const char *${ident} = "\\`,
`${cssStr.substring(1, cssStr.length - 1)}\\`,
'";\n',
Expand Down
42 changes: 40 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import path from 'path';
import path from "path";
import { cosmiconfig } from "cosmiconfig";
import { LoaderContext } from "./types.js";

export function toIdent(str: string) {
return str.replace(/[^a-zA-Z0-9]/g, "_");
}

export function getResourceLoaderName(fileName: string, defaultComponentName?: string) {
export function getResourceLoaderName(
fileName: string,
defaultComponentName?: string
) {
const ident = toIdent(defaultComponentName || fileName);
return `ui_load_${ident}_resources`;
}
Expand All @@ -16,3 +21,36 @@ export function parsePageRoute(context: string, filePath: string) {
ident: toIdent(`${dir || "root"}_${name}`),
};
}

export async function loadConfig(loaderContext: LoaderContext, moduleName: string) {
/** @see https://github.com/webpack-contrib/postcss-loader/blob/b1aecd9b18ede38b0ad4e693a94dadd2b2531429/src/utils.js#L51 */
const searchPlaces = [
// Prefer popular format
"package.json",
`${moduleName}.config.js`,
`${moduleName}.config.mjs`,
`${moduleName}.config.cjs`,
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.js`,
`.${moduleName}rc.mjs`,
`.${moduleName}rc.cjs`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.config/${moduleName}rc`,
`.config/${moduleName}rc.json`,
`.config/${moduleName}rc.yaml`,
`.config/${moduleName}rc.yml`,
`.config/${moduleName}rc.js`,
`.config/${moduleName}rc.cjs`,
];
const explorer = await cosmiconfig(moduleName, {
searchStrategy: "global",
searchPlaces,
});
const result = await explorer.search(path.dirname(loaderContext.resourcePath));
if (!result || result.isEmpty) {
return null;
}
return result.config;
}
40 changes: 37 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,16 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"

cosmiconfig@^9.0.0:
version "9.0.0"
resolved "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d"
integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==
dependencies:
env-paths "^2.2.1"
import-fresh "^3.3.0"
js-yaml "^4.1.0"
parse-json "^5.2.0"

cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
Expand Down Expand Up @@ -1094,6 +1104,11 @@ [email protected]:
resolved "https://registry.npmmirror.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==

env-paths@^2.2.1:
version "2.2.1"
resolved "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==

error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
Expand Down Expand Up @@ -1570,7 +1585,7 @@ immutable@^4.0.0:
resolved "https://registry.npmmirror.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be"
integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==

import-fresh@^3.0.0, import-fresh@^3.2.1:
import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0:
version "3.3.0"
resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
Expand Down Expand Up @@ -2083,6 +2098,11 @@ nanoid@^3.3.6:
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==

nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==

natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
Expand Down Expand Up @@ -2271,7 +2291,7 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"

parse-json@^5.0.0:
parse-json@^5.0.0, parse-json@^5.2.0:
version "5.2.0"
resolved "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
Expand Down Expand Up @@ -2412,7 +2432,7 @@ postcss-value-parser@^4.1.0:
resolved "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==

postcss@^8.2.14, postcss@^8.4.27:
postcss@^8.2.14:
version "8.4.27"
resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
Expand All @@ -2421,6 +2441,15 @@ postcss@^8.2.14, postcss@^8.4.27:
picocolors "^1.0.0"
source-map-js "^1.0.2"

postcss@^8.4.38:
version "8.4.38"
resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.0"
source-map-js "^1.2.0"

prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
Expand Down Expand Up @@ -2707,6 +2736,11 @@ snake-case@^3.0.4:
resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==

source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==

source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
Expand Down

0 comments on commit 10f75c9

Please sign in to comment.