From 8f2eace7a06741b5b90ae312e6b9aabe0ee0df0b Mon Sep 17 00:00:00 2001 From: indooorsman Date: Wed, 29 Nov 2023 14:53:56 +0800 Subject: [PATCH] v3.1.0 (#64) --- changelog.md | 6 ++++++ index.d.ts | 27 +++++++++++++++++++++++++-- index.js | 22 +++++++++++++++++++++- lib/context.js | 1 - lib/css.helper.js | 24 ++++++++++++++++++++---- lib/utils.js | 9 +++++++++ package.json | 15 +++++++++------ test/test.js | 15 +++++++++++++++ tsconfig.json | 3 ++- 9 files changed, 107 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index d030717..3cc542b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,9 @@ +## V3.1.0 +- fix [issue#61](https://github.com/indooorsman/esbuild-css-modules-plugin/issues/61) +- fix [issue#59](https://github.com/indooorsman/esbuild-css-modules-plugin/issues/59) +- do not modify user's configuration, throw warning if configuration is no valid for css modules plugin +- support more options of `lightningcss`, see [index.d.ts](https://github.com/indooorsman/esbuild-css-modules-plugin/blob/main/index.d.ts) for details + ## V3.0.3 - Fix sourcemap diff --git a/index.d.ts b/index.d.ts index 77a3eb1..f471fcb 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,8 +1,21 @@ import type { Plugin, PluginBuild } from 'esbuild'; +import type { BundleOptions, CustomAtRules, TransformOptions } from 'lightningcss'; declare type EmitDtsConfig = Partial>; -declare interface BuildOptions { +declare interface BuildOptions + extends Partial< + Pick< + BundleOptions, + | 'targets' + | 'drafts' + | 'nonStandard' + | 'pseudoClasses' + | 'errorRecovery' + | 'visitor' + | 'customAtRules' + > + > { /** * force to build css modules files even if `bundle` is disabled in esbuild * @default false @@ -46,7 +59,7 @@ declare interface BuildOptions { * ``` * the plugin will try to get `shadowRoot` of the found element, and append css to the * `shadowRoot`, if no shadowRoot then append to the found element, if no element found then append to `document.head`. - * + * * could be a function with params content & digest (return a string of js code to inject css into page), * e.g. * @@ -84,6 +97,16 @@ declare interface BuildOptions { * @default "camelCaseOnly" */ localsConvention?: 'camelCase' | 'pascalCase' | 'camelCaseOnly' | 'pascalCaseOnly'; + /** + * Features that should always be compiled, even when supported by targets. + * @see https://lightningcss.dev/transpilation.html#feature-flags + */ + featuresInclude?: BundleOptions['include']; + /** + * Features that should never be compiled, even when unsupported by targets. + * @see https://lightningcss.dev/transpilation.html#feature-flags + */ + featuresExclude?: BundleOptions['exclude']; /** * namedExports * e.g.: diff --git a/index.js b/index.js index a41bd2e..3c33a4d 100644 --- a/index.js +++ b/index.js @@ -22,7 +22,6 @@ import { patchContext } from './lib/context.js'; * @param {import('./index.js').Options} _options */ export const setup = (build, _options) => { - build.initialOptions.metafile = true; const options = _options || {}; validateOptions(options); @@ -41,6 +40,25 @@ export const setup = (build, _options) => { const forceInlineImages = !!options.forceInlineImages; const emitDts = options.emitDeclarationFile; + const warnMetafile = () => { + if (patchedBuild.initialOptions.metafile) { + return; + } + const warnings = patchedBuild.esbuild.formatMessagesSync( + [ + { + text: '`metafile` is not enabled, it may not work properly, please consider to set `metafile` to true is your esbuild configuration.', + pluginName: pluginName + } + ], + { + kind: 'warning', + color: true + } + ); + console.log(warnings.join('\n')); + } + patchedBuild.onLoad({ filter: /.+/, namespace: pluginCssNamespace }, (args) => { const { path } = args; log(`[${pluginCssNamespace}] on load:`, args); @@ -245,6 +263,7 @@ export const setup = (build, _options) => { /** @type {[string, string][]} */ const moduleJsFiles = []; + warnMetafile(); Object.entries(r.metafile?.outputs ?? {}).forEach(([js, meta]) => { if (meta.entryPoint && modulesCssRegExp.test(meta.entryPoint)) { moduleJsFiles.push([meta.entryPoint, js]); @@ -300,6 +319,7 @@ export const setup = (build, _options) => { /** @type {[string, string][]} */ const filesToBuild = []; + warnMetafile(); Object.entries(r.metafile?.outputs ?? {}).forEach(([outfile, meta]) => { if (meta.cssBundle) { filesToBuild.push([outfile, meta.cssBundle]); diff --git a/lib/context.js b/lib/context.js index 7c976fd..debcfd2 100644 --- a/lib/context.js +++ b/lib/context.js @@ -10,7 +10,6 @@ export const patchContext = (_build, options = {}) => { /** @type {import('../index.js').Build} */ // @ts-ignore const build = _build; - build.initialOptions.metafile = true; build.initialOptions.outbase ??= '.'; const buildId = getBuildId(build); diff --git a/lib/css.helper.js b/lib/css.helper.js index edc407a..f527b34 100644 --- a/lib/css.helper.js +++ b/lib/css.helper.js @@ -3,13 +3,24 @@ import { dirname, relative, resolve } from 'node:path'; import { contentPlaceholder, digestPlaceholder, + fixImportPath, pluginCssNamespace, validateNamedExport } from './utils.js'; -import { camelCase, sortBy, uniqBy, upperFirst } from 'lodash-es'; +import { camelCase, sortBy, uniqBy, upperFirst, pick } from 'lodash-es'; import { injectorVirtualPath, pluginJsNamespace } from './utils.js'; import { readFileSync } from 'node:fs'; +const lightningcssOptions = [ + 'targets', + 'drafts', + 'nonStandard', + 'pseudoClasses', + 'errorRecovery', + 'visitor', + 'customAtRules' +]; + export class CSSInjector { /** @type {Map} */ static __instances__ = new Map(); @@ -106,7 +117,9 @@ ${isEsbuildBundleMode ? 'export { inject };' : ''} genImportCode(cssPath = '') { const isEsbuildBundleMode = this.build.initialOptions.bundle ?? false; return isEsbuildBundleMode - ? `import { inject } from "${pluginJsNamespace}:${cssPath}:${injectorVirtualPath}";` + ? `import { inject } from "${pluginJsNamespace}:${fixImportPath( + cssPath + )}:${injectorVirtualPath}";` : this.libCode; } @@ -154,7 +167,9 @@ export class CSSTransformer { const isEsbuildBundleMode = this.build.initialOptions.bundle ?? false; /** @type {string[]} */ - const jsLines = isEsbuildBundleMode ? [`import "${pluginCssNamespace}:${relativePath}";`] : []; + const jsLines = isEsbuildBundleMode + ? [`import "${pluginCssNamespace}:${fixImportPath(relativePath)}";`] + : []; /** @type {string[]} */ const dtsLines = []; @@ -268,7 +283,8 @@ ${uniqNames.map(([o, l]) => ` "${o}": ${l}`).join(',\n')} projectRoot: this.build.context.buildRoot, targets: { chrome: 112 << 16 - } + }, + ...pick(options, lightningcssOptions) }; /** @type {{code: Buffer, exports: import('lightningcss').CSSModuleExports}} */ // @ts-ignore diff --git a/lib/utils.js b/lib/utils.js index 47f52bd..4d273ae 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,5 @@ import { isAbsolute, resolve, sep, relative, basename, dirname } from 'node:path'; +import { sep as posixSep } from 'node:path/posix' import { createHash } from 'node:crypto'; import { accessSync, constants } from 'node:fs'; import { createRequire } from 'node:module'; @@ -241,3 +242,11 @@ export { simpleMinifyCss, ensureFile }; + +/** + * @param {string} p import path + * @return {string} + */ +export const fixImportPath = (p) => { + return p.split(sep).join(posixSep); +} \ No newline at end of file diff --git a/package.json b/package.json index ea75e6f..d3ccfa6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "esbuild-css-modules-plugin", - "version": "3.0.3", + "version": "3.1.0", "description": "A esbuild plugin to bundle css modules into js(x)/ts(x), based on extremely fast [Lightning CSS](https://lightningcss.dev/)", "main": "./index.cjs", "module": "./index.js", @@ -29,22 +29,25 @@ }, "author": "indooorsman@gmail.com", "license": "MIT", - "repository": "https://github.com/indooorsman/esbuild-css-modules-plugin.git", + "repository": { + "type": "git", + "url": "git+https://github.com/indooorsman/esbuild-css-modules-plugin.git" + }, "scripts": { "test": "cd ./test && rm -rf ./dist && node test.js", "test:cjs": "cd ./test && rm -rf ./dist && node test.cjs", "pub": "npm_config_registry=https://registry.npmjs.org/ npm publish --userconfig ~/.pubnpmrc --access public --tag latest" }, "devDependencies": { - "@types/lodash-es": "^4.17.7", - "@types/node": "^17.0.23", - "esbuild": "^0.19.4" + "@types/lodash-es": "^4.17.12", + "@types/node": "^20.10.0", + "esbuild": "^0.19.8" }, "peerDependencies": { "esbuild": "*" }, "dependencies": { - "lightningcss": "^1.22.0", + "lightningcss": "^1.22.1", "lodash-es": "^4.17.21" }, "publishConfig": { diff --git a/test/test.js b/test/test.js index 0447834..ce87f3c 100644 --- a/test/test.js +++ b/test/test.js @@ -148,4 +148,19 @@ import cssModulesPlugin from '../index.js'; await esbuild.build(buildOptions); console.log('[test][esbuild:no:bundle] done, please check `test/dist/no-bundle`', '\n'); + + // testing no metafile & write false + const r = await esbuild.build({ + ...buildOptions, + entryPoints: ['./app.jsx'], + bundle: true, + packages: 'external', + metafile: false, + write: false, + loader: { + '.jpg': 'file' + }, + outdir: '__virtual_path__' + }); + console.log('\nbuild result with metafile: false & write: false', r); })(); diff --git a/tsconfig.json b/tsconfig.json index 6410e8a..ff6b3aa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ }, "include": [ "index.js", - "lib/**/*" + "lib/**/*", + "index.d.ts" ] } \ No newline at end of file