Skip to content

Commit

Permalink
refine emit dts
Browse files Browse the repository at this point in the history
  • Loading branch information
indooorsman committed Aug 25, 2023
1 parent 53040d7 commit 5461f68
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 38 deletions.
12 changes: 9 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ declare interface BuildOptions {
force?: boolean;
/** inline images imported in css as data url even if `bundle` is false */
forceInlineImages?: boolean;
emitDeclarationFile?: boolean;
/**
* emit typescript declaration file for css modules class names
* - `.css.d.ts` : emit `xxx.css.d.ts`
* - `.d.css.ts` : emit `xxx.d.css.ts` (from typescript@5, see https://www.typescriptlang.org/tsconfig#allowArbitraryExtensions)
* - `true` : emit both `xxx.css.d.ts` and `xxx.d.css.ts`
*/
emitDeclarationFile?: boolean | '.d.css.ts' | '.css.d.ts';
inject?: boolean | string | ((css: string, digest: string) => string);
filter?: RegExp;
/**
Expand Down Expand Up @@ -52,8 +58,8 @@ declare interface BuildOptions {
declare function CssModulesPlugin(options?: BuildOptions): Plugin;

declare namespace CssModulesPlugin {
export interface Options extends BuildOptions {};
export interface Options extends BuildOptions {}

export interface BuildContext {
options: Options;
buildId: string;
Expand Down
77 changes: 49 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
validateOptions
} from './lib/utils.js';
import { compact } from 'lodash-es';
import { readFile, writeFile } from 'node:fs/promises';
import { readFile, rename, writeFile } from 'node:fs/promises';
import { patchContext } from './lib/context.js';

/**
Expand All @@ -39,7 +39,7 @@ export const setup = (build, _options) => {
const jsLoader = patchedBuild.initialOptions.loader?.['.js'] ?? 'js';
const outJsExt = patchedBuild.initialOptions.outExtension?.['.js'] ?? '.js';
const forceInlineImages = !!options.forceInlineImages;
const emitDts = !!options.emitDeclarationFile;
const emitDts = options.emitDeclarationFile;

patchedBuild.onLoad({ filter: /.+/, namespace: pluginCssNamespace }, (args) => {
const { path } = args;
Expand Down Expand Up @@ -85,42 +85,52 @@ export const setup = (build, _options) => {
);

patchedBuild.onLoad({ filter: modulesCssRegExp, namespace: 'file' }, async (args) => {
if (!emitDts && !bundle && !forceBuild) {
return undefined;
}

log('[file] on load:', args);
const { path } = args;
const rpath = relative(buildRoot, path);

const prefix = basename(rpath, extname(path))
.replace(/[^a-zA-Z0-9]/g, '-')
.replace(/^\-*/, '');
const suffix = patchedBuild.context.packageVersion?.replace(/[^a-zA-Z0-9]/g, '') ?? '';
CSSTransformer.getInstance(patchedBuild).bundle(path, {

const buildResult = CSSTransformer.getInstance(patchedBuild).bundle(path, {
prefix,
suffix,
forceInlineImages,
emitDeclarationFile: emitDts
emitDeclarationFile: !!emitDts
});

if (!bundle && !forceBuild) {
return undefined;
} else if (!bundle && forceBuild) {
log('force build modules css:', rpath);
const buildResult = CSSTransformer.getInstance(patchedBuild).getCachedResult(path);

if (emitDts) {
const outdir = resolve(buildRoot, patchedBuild.initialOptions.outdir ?? '');
const outbase = patchedBuild.initialOptions.outbase;
let outDtsfile = resolve(outdir, rpath) + '.d.ts';
if (emitDts) {
const dtsExts = [];
if (emitDts === '.d.css.ts' || emitDts === '.css.d.ts') {
dtsExts.push(emitDts);
} else {
dtsExts.push('.d.css.ts', '.css.d.ts');
}
const outdir = resolve(buildRoot, patchedBuild.initialOptions.outdir ?? '');
const outbase = patchedBuild.initialOptions.outbase;
dtsExts.forEach(async (dtsExt) => {
let outDtsfile = resolve(outdir, rpath).replace(/\.css$/i, dtsExt);
if (outbase) {
let normalized = normalize(outbase);
if (normalized.endsWith(sep)) {
normalized = compact(normalized.split(sep)).join(sep);
}
outDtsfile = resolve(outDtsfile.replace(normalized, ''));
if (normalized !== '.') {
outDtsfile = resolve(outDtsfile.replace(normalized, ''));
}
}
log(`emit typescript declarations file:`, patchedBuild.context.relative(outDtsfile));
await ensureFile(outDtsfile, buildResult?.dts ?? '');
});
}

ensureFile(outDtsfile, buildResult?.dts ?? '');
}

if (!bundle && forceBuild) {
log('force build modules css:', rpath);
if (injectCss) {
const anotherBuildOptions = { ...patchedBuild.initialOptions };
delete anotherBuildOptions.entryPoints;
Expand Down Expand Up @@ -192,11 +202,10 @@ export const setup = (build, _options) => {
};
}
} else if (bundle) {
const bundleResult = CSSTransformer.getInstance(patchedBuild).getCachedResult(path);
return {
contents: bundleResult?.js,
contents: buildResult?.js,
loader: jsLoader,
watchFiles: [path, ...(bundleResult?.composedFiles ?? [])],
watchFiles: [path, ...(buildResult?.composedFiles ?? [])],
resolveDir: dirname(path),
pluginData: {
originCssPath: path
Expand All @@ -214,17 +223,22 @@ export const setup = (build, _options) => {
if (!bundle && forceBuild) {
/** @type {[string, Record<string, string>][]} */
const jsFiles = [];
/** @type {Record<string, string>} */
/** @type {[string, string][]} */
const moduleJsFiles = [];

Object.entries(r.metafile?.outputs ?? {}).forEach(([js, meta]) => {
if (meta.entryPoint && modulesCssRegExp.test(meta.entryPoint)) {
moduleJsFiles.push([meta.entryPoint, js]);
}

if (meta.entryPoint && !modulesCssRegExp.test(meta.entryPoint)) {
let shouldPush = false;
/** @type {Record<string, string>} */
const defines = {};
meta.imports?.forEach((imp) => {
if (modulesCssRegExp.test(imp.path)) {
shouldPush = true;
const impExt = extname(imp.path);
defines[imp.path] = imp.path.replace(new RegExp(`${impExt}$`), `${outJsExt}`);
defines[imp.path] = imp.path + outJsExt;
}
});
if (shouldPush) {
Expand All @@ -233,8 +247,15 @@ export const setup = (build, _options) => {
}
});

await Promise.all(
jsFiles.map(([js, places]) => {
await Promise.all([
...(moduleJsFiles.map(([src, dist]) => {
const fp = resolve(buildRoot, dist);
const filename = basename(src) + outJsExt;
const finalPath = resolve(dirname(fp), filename);
log(`rename ${dist} to ${filename}`);
return rename(fp, finalPath);
})),
...jsFiles.map(([js, places]) => {
const fulljs = resolve(buildRoot, js);
return readFile(fulljs, { encoding: 'utf8' })
.then((content) => {
Expand All @@ -249,7 +270,7 @@ export const setup = (build, _options) => {
return writeFile(fulljs, nc, { encoding: 'utf8' });
});
})
);
]);

return dispose();
}
Expand Down
8 changes: 4 additions & 4 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createHash } from 'node:crypto';
import { accessSync, constants } from 'node:fs';
import { createRequire } from 'node:module';
import { omit } from 'lodash-es';
import { appendFile, mkdir } from 'node:fs/promises';
import { writeFile, mkdir } from 'node:fs/promises';

const require = createRequire(import.meta.url);

Expand Down Expand Up @@ -213,13 +213,13 @@ const simpleMinifyCss = (
* @param {string} filepath
* @param {string} data
*/
const ensureFile = async (filepath, data) => {
if (!data) {
const ensureFile = async (filepath, data = '') => {
if (!filepath) {
return;
}
const dir = dirname(filepath);
await mkdir(dir, { recursive: true });
await appendFile(filepath, data.trim(), { encoding: 'utf8' });
await writeFile(filepath, `${data}`.trim(), { encoding: 'utf8' });
};

export {
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "esbuild-css-modules-plugin",
"version": "3.0.0-dev.19",
"version": "3.0.0-dev.20",
"description": "A esbuild plugin to bundle css modules into js(x)/ts(x).",
"main": "./index.cjs",
"module": "./index.js",
Expand Down Expand Up @@ -34,13 +34,13 @@
"devDependencies": {
"@types/lodash-es": "^4.17.7",
"@types/node": "^17.0.23",
"esbuild": "^0.18.19"
"esbuild": "^0.19.2"
},
"peerDependencies": {
"esbuild": "*"
},
"dependencies": {
"lightningcss": "^1.21.5",
"lightningcss": "^1.21.7",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21"
},
Expand Down

0 comments on commit 5461f68

Please sign in to comment.