From 18bc8c20b901546fc1b850b9a7c00a8153a5cc78 Mon Sep 17 00:00:00 2001 From: apple-yagi Date: Sun, 30 Jun 2024 12:33:07 +0900 Subject: [PATCH 1/8] Add support for `outputFolder` option --- packages/happy-css-modules/src/cli.ts | 6 ++++++ .../happy-css-modules/src/emitter/dts.test.ts | 8 +++---- packages/happy-css-modules/src/emitter/dts.ts | 21 +++++++++++++++---- .../src/emitter/index.test.ts | 1 + .../happy-css-modules/src/emitter/index.ts | 12 +++++++---- .../src/emitter/source-map.test.ts | 8 +++---- .../src/emitter/source-map.ts | 9 ++++++-- packages/happy-css-modules/src/runner.ts | 4 ++++ 8 files changed, 51 insertions(+), 18 deletions(-) diff --git a/packages/happy-css-modules/src/cli.ts b/packages/happy-css-modules/src/cli.ts index 416a7c0a..705bf5f7 100644 --- a/packages/happy-css-modules/src/cli.ts +++ b/packages/happy-css-modules/src/cli.ts @@ -78,6 +78,11 @@ export function parseArgv(argv: string[]): RunnerOptions { default: 'info' as RunnerOptions['logLevel'], describe: 'What level of logs to report.', }) + .option('outputFolder', { + type: 'string', + alias: 'o', + describe: 'Output folder for generated files.', + }) .alias('h', 'help') .alias('v', 'version') .version(pkgJson.version) @@ -116,5 +121,6 @@ export function parseArgv(argv: string[]): RunnerOptions { cache: parsedArgv.cache, cacheStrategy: parsedArgv.cacheStrategy, logLevel: parsedArgv.logLevel, + outputFolder: parsedArgv.outputFolder, }; } diff --git a/packages/happy-css-modules/src/emitter/dts.test.ts b/packages/happy-css-modules/src/emitter/dts.test.ts index 34bbd68d..06550c30 100644 --- a/packages/happy-css-modules/src/emitter/dts.test.ts +++ b/packages/happy-css-modules/src/emitter/dts.test.ts @@ -9,10 +9,10 @@ const locator = new Locator(); const isExternalFile = () => false; test('getDtsFilePath', () => { - expect(getDtsFilePath('/app/src/dir/1.css', false)).toBe('/app/src/dir/1.css.d.ts'); - expect(getDtsFilePath('/app/src/dir/1.scss', false)).toBe('/app/src/dir/1.scss.d.ts'); - expect(getDtsFilePath('/app/src/dir/1.css', true)).toBe('/app/src/dir/1.d.css.ts'); - expect(getDtsFilePath('/app/src/dir/1.scss', true)).toBe('/app/src/dir/1.d.scss.ts'); + expect(getDtsFilePath('/app/src/dir/1.css', false, undefined)).toBe('/app/src/dir/1.css.d.ts'); + expect(getDtsFilePath('/app/src/dir/1.scss', false, undefined)).toBe('/app/src/dir/1.scss.d.ts'); + expect(getDtsFilePath('/app/src/dir/1.css', true, undefined)).toBe('/app/src/dir/1.d.css.ts'); + expect(getDtsFilePath('/app/src/dir/1.scss', true, undefined)).toBe('/app/src/dir/1.d.scss.ts'); }); describe('generateDtsContentWithSourceMap', () => { diff --git a/packages/happy-css-modules/src/emitter/dts.ts b/packages/happy-css-modules/src/emitter/dts.ts index c603fe73..f1263950 100644 --- a/packages/happy-css-modules/src/emitter/dts.ts +++ b/packages/happy-css-modules/src/emitter/dts.ts @@ -1,23 +1,36 @@ import { EOL } from 'os'; -import { basename, parse, join } from 'path'; +import path, { basename, parse, join } from 'path'; import camelcase from 'camelcase'; import { SourceNode, type CodeWithSourceMap } from '../library/source-map/index.js'; import { type Token } from '../locator/index.js'; import { type LocalsConvention } from '../runner.js'; import { getRelativePath, type DtsFormatOptions } from './index.js'; +const CURRENT_WORKING_DIRECTORY = process.cwd(); + /** * Get .d.ts file path. * @param filePath The path to the source file (i.e. `/dir/foo.css`). It is absolute. * @param arbitraryExtensions Generate `.d.css.ts` instead of `.css.d.ts`. + * @param outputFolder Output folder for generated files. * @returns The path to the .d.ts file. It is absolute. */ -export function getDtsFilePath(filePath: string, arbitraryExtensions: boolean): string { +export function getDtsFilePath( + filePath: string, + arbitraryExtensions: boolean, + outputFolder: string | undefined, +): string { + let outputFilePath = filePath; + if (outputFolder) { + const relativePath = path.relative(CURRENT_WORKING_DIRECTORY, filePath); + outputFilePath = path.resolve(CURRENT_WORKING_DIRECTORY, outputFolder, relativePath); + } + if (arbitraryExtensions) { - const { dir, name, ext } = parse(filePath); + const { dir, name, ext } = parse(outputFilePath); return join(dir, `${name}.d${ext}.ts`); } else { - return `${filePath}.d.ts`; + return `${outputFilePath}.d.ts`; } } diff --git a/packages/happy-css-modules/src/emitter/index.test.ts b/packages/happy-css-modules/src/emitter/index.test.ts index 0a2c7360..b062e6a8 100644 --- a/packages/happy-css-modules/src/emitter/index.test.ts +++ b/packages/happy-css-modules/src/emitter/index.test.ts @@ -30,6 +30,7 @@ describe('emitGeneratedFiles', () => { dtsFormatOptions: undefined, cwd: getFixturePath('/test'), isExternalFile: () => false, + outputFolder: undefined, }; beforeEach(() => { createFixtures({ diff --git a/packages/happy-css-modules/src/emitter/index.ts b/packages/happy-css-modules/src/emitter/index.ts index 78289454..a49f3e0d 100644 --- a/packages/happy-css-modules/src/emitter/index.ts +++ b/packages/happy-css-modules/src/emitter/index.ts @@ -45,6 +45,8 @@ export type EmitterOptions = { dtsFormatOptions: DtsFormatOptions | undefined; /** Whether the file is from an external library or not. */ isExternalFile: (filePath: string) => boolean; + /** Output folder for generated files. */ + outputFolder: string | undefined; }; export async function emitGeneratedFiles({ @@ -53,10 +55,11 @@ export async function emitGeneratedFiles({ emitDeclarationMap, dtsFormatOptions, isExternalFile, + outputFolder, }: EmitterOptions): Promise { const arbitraryExtensions = dtsFormatOptions?.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS; - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outputFolder); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outputFolder); const { dtsContent, sourceMap } = generateDtsContentWithSourceMap( filePath, dtsFilePath, @@ -84,9 +87,10 @@ export async function isGeneratedFilesExist( filePath: string, emitDeclarationMap: boolean | undefined, arbitraryExtensions: boolean, + outputFolder: string | undefined, ): Promise { - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outputFolder); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outputFolder); if (emitDeclarationMap && !(await exists(sourceMapFilePath))) { return false; } diff --git a/packages/happy-css-modules/src/emitter/source-map.test.ts b/packages/happy-css-modules/src/emitter/source-map.test.ts index c8ff05ed..213f2407 100644 --- a/packages/happy-css-modules/src/emitter/source-map.test.ts +++ b/packages/happy-css-modules/src/emitter/source-map.test.ts @@ -2,10 +2,10 @@ import { EOL } from 'os'; import { getSourceMapFilePath, generateSourceMappingURLComment } from './source-map.js'; test('getSourceMapFilePath', () => { - expect(getSourceMapFilePath('/app/src/dir/1.css', false)).toBe('/app/src/dir/1.css.d.ts.map'); - expect(getSourceMapFilePath('/app/src/dir/1.scss', false)).toBe('/app/src/dir/1.scss.d.ts.map'); - expect(getSourceMapFilePath('/app/src/dir/1.css', true)).toBe('/app/src/dir/1.d.css.ts.map'); - expect(getSourceMapFilePath('/app/src/dir/1.scss', true)).toBe('/app/src/dir/1.d.scss.ts.map'); + expect(getSourceMapFilePath('/app/src/dir/1.css', false, undefined)).toBe('/app/src/dir/1.css.d.ts.map'); + expect(getSourceMapFilePath('/app/src/dir/1.scss', false, undefined)).toBe('/app/src/dir/1.scss.d.ts.map'); + expect(getSourceMapFilePath('/app/src/dir/1.css', true, undefined)).toBe('/app/src/dir/1.d.css.ts.map'); + expect(getSourceMapFilePath('/app/src/dir/1.scss', true, undefined)).toBe('/app/src/dir/1.d.scss.ts.map'); }); test('generateSourceMappingURLComment', () => { diff --git a/packages/happy-css-modules/src/emitter/source-map.ts b/packages/happy-css-modules/src/emitter/source-map.ts index fa179695..194d0a3f 100644 --- a/packages/happy-css-modules/src/emitter/source-map.ts +++ b/packages/happy-css-modules/src/emitter/source-map.ts @@ -6,10 +6,15 @@ import { getRelativePath } from './index.js'; * Get .d.ts.map file path. * @param filePath The path to the source file (i.e. `foo.css`). It is absolute. * @param arbitraryExtensions Generate `.d.css.ts` instead of `.css.d.ts`. + * @param outputFolder Output folder for generated files. * @returns The path to the .d.ts.map file. It is absolute. */ -export function getSourceMapFilePath(filePath: string, arbitraryExtensions: boolean): string { - return `${getDtsFilePath(filePath, arbitraryExtensions)}.map`; +export function getSourceMapFilePath( + filePath: string, + arbitraryExtensions: boolean, + outputFolder: string | undefined, +): string { + return `${getDtsFilePath(filePath, arbitraryExtensions, outputFolder)}.map`; } export function generateSourceMappingURLComment(dtsFilePath: string, sourceMapFilePath: string): string { diff --git a/packages/happy-css-modules/src/runner.ts b/packages/happy-css-modules/src/runner.ts index eb92eb05..3f74f499 100644 --- a/packages/happy-css-modules/src/runner.ts +++ b/packages/happy-css-modules/src/runner.ts @@ -79,6 +79,8 @@ export interface RunnerOptions { logLevel?: 'debug' | 'info' | 'silent' | undefined; /** Working directory path. */ cwd?: string | undefined; + /** Output folder for generated files. */ + outputFolder?: string | undefined; } type OverrideProp = Omit & { [P in K]: V }; @@ -140,6 +142,7 @@ export async function run(options: RunnerOptions): Promise { filePath, options.declarationMap, options.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS, + options.outputFolder, ); const _isChangedFile = await isChangedFile(filePath); // Generate .d.ts and .d.ts.map only when the file has been updated. @@ -159,6 +162,7 @@ export async function run(options: RunnerOptions): Promise { arbitraryExtensions: options.arbitraryExtensions, }, isExternalFile, + outputFolder: options.outputFolder, }); logger.info(chalk.green(`${relative(cwd, filePath)} (generated)`)); From 0c96314d12d787f6ff7650c6db7ead9202e8304a Mon Sep 17 00:00:00 2001 From: apple-yagi Date: Sun, 30 Jun 2024 12:33:14 +0900 Subject: [PATCH 2/8] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5044d520..873dec06 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Options: --cache Only generate .d.ts and .d.ts.map for changed files. [boolean] [default: true] --cacheStrategy Strategy for the cache to use for detecting changed files.[choices: "content", "metadata"] [default: "content"] --logLevel What level of logs to report. [choices: "debug", "info", "silent"] [default: "info"] + -o, --outputFolder Output folder for generated files. [string] -h, --help Show help [boolean] -v, --version Show version number [boolean] From 65313471395b996962329596add2fbe5c548fc75 Mon Sep 17 00:00:00 2001 From: apple-yagi Date: Mon, 4 Nov 2024 14:33:16 +0900 Subject: [PATCH 3/8] Rename option name from outputFolder to outDir --- packages/happy-css-modules/src/cli.ts | 6 +++--- packages/happy-css-modules/src/runner.ts | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/happy-css-modules/src/cli.ts b/packages/happy-css-modules/src/cli.ts index 705bf5f7..1c8121a4 100644 --- a/packages/happy-css-modules/src/cli.ts +++ b/packages/happy-css-modules/src/cli.ts @@ -78,10 +78,10 @@ export function parseArgv(argv: string[]): RunnerOptions { default: 'info' as RunnerOptions['logLevel'], describe: 'What level of logs to report.', }) - .option('outputFolder', { + .option('outDir', { type: 'string', alias: 'o', - describe: 'Output folder for generated files.', + describe: 'Output directory for generated files.', }) .alias('h', 'help') .alias('v', 'version') @@ -121,6 +121,6 @@ export function parseArgv(argv: string[]): RunnerOptions { cache: parsedArgv.cache, cacheStrategy: parsedArgv.cacheStrategy, logLevel: parsedArgv.logLevel, - outputFolder: parsedArgv.outputFolder, + outDir: parsedArgv.outDir, }; } diff --git a/packages/happy-css-modules/src/runner.ts b/packages/happy-css-modules/src/runner.ts index 3f74f499..459991f8 100644 --- a/packages/happy-css-modules/src/runner.ts +++ b/packages/happy-css-modules/src/runner.ts @@ -79,8 +79,8 @@ export interface RunnerOptions { logLevel?: 'debug' | 'info' | 'silent' | undefined; /** Working directory path. */ cwd?: string | undefined; - /** Output folder for generated files. */ - outputFolder?: string | undefined; + /** Output directory for generated files. */ + outDir?: string | undefined; } type OverrideProp = Omit & { [P in K]: V }; @@ -142,7 +142,7 @@ export async function run(options: RunnerOptions): Promise { filePath, options.declarationMap, options.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS, - options.outputFolder, + options.outDir, ); const _isChangedFile = await isChangedFile(filePath); // Generate .d.ts and .d.ts.map only when the file has been updated. @@ -162,7 +162,7 @@ export async function run(options: RunnerOptions): Promise { arbitraryExtensions: options.arbitraryExtensions, }, isExternalFile, - outputFolder: options.outputFolder, + outputFolder: options.outDir, }); logger.info(chalk.green(`${relative(cwd, filePath)} (generated)`)); From 047c625d64667da5f7050ea7819c9d3714785839 Mon Sep 17 00:00:00 2001 From: mizdra Date: Mon, 4 Nov 2024 14:54:16 +0900 Subject: [PATCH 4/8] add test cases for `outDir` and `cwd` options --- packages/happy-css-modules/src/runner.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/happy-css-modules/src/runner.test.ts b/packages/happy-css-modules/src/runner.test.ts index d6628441..f6f0302f 100644 --- a/packages/happy-css-modules/src/runner.test.ts +++ b/packages/happy-css-modules/src/runner.test.ts @@ -351,3 +351,17 @@ test('support symlink', async () => { `"{"version":3,"sources":["./1.css"],"names":["a"],"mappings":"AAAA;AAAA,E,aAAAA,G,WAAA;AAAA;AAAA","file":"1.css.d.ts","sourceRoot":""}"`, ); }); + +test('changes output directory by outDir', async () => { + createFixtures({ + '/test/1.css': '.a {}', + }); + + await run({ ...defaultOptions, outDir: getFixturePath('/dist'), cache: false, watch: false }); + + expect(await exists(getFixturePath('/dist/test/1.css.d.ts'))).toBe(true); + expect(await exists(getFixturePath('/dist/test/1.css.d.ts.map'))).toBe(true); + + expect(await readFile(getFixturePath('/dist/test/1.css.d.ts'), 'utf8')).toMatchInlineSnapshot(); + expect(await readFile(getFixturePath('/dist/test/1.css.d.ts.map'), 'utf8')).toMatchInlineSnapshot(); +}); From fc1fdd64b09b848037f80a1659dbd951d1519e1c Mon Sep 17 00:00:00 2001 From: apple-yagi Date: Mon, 4 Nov 2024 15:13:20 +0900 Subject: [PATCH 5/8] Refactor option name from outputFolder to outDir --- README.md | 2 +- packages/happy-css-modules/src/emitter/dts.ts | 12 ++++-------- .../happy-css-modules/src/emitter/index.test.ts | 2 +- packages/happy-css-modules/src/emitter/index.ts | 16 ++++++++-------- .../happy-css-modules/src/emitter/source-map.ts | 6 +++--- packages/happy-css-modules/src/runner.ts | 2 +- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 873dec06..f0f0bd8f 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Options: --cache Only generate .d.ts and .d.ts.map for changed files. [boolean] [default: true] --cacheStrategy Strategy for the cache to use for detecting changed files.[choices: "content", "metadata"] [default: "content"] --logLevel What level of logs to report. [choices: "debug", "info", "silent"] [default: "info"] - -o, --outputFolder Output folder for generated files. [string] + -o, --outDir Output directory for generated files. [string] -h, --help Show help [boolean] -v, --version Show version number [boolean] diff --git a/packages/happy-css-modules/src/emitter/dts.ts b/packages/happy-css-modules/src/emitter/dts.ts index f1263950..ffe9b68d 100644 --- a/packages/happy-css-modules/src/emitter/dts.ts +++ b/packages/happy-css-modules/src/emitter/dts.ts @@ -12,18 +12,14 @@ const CURRENT_WORKING_DIRECTORY = process.cwd(); * Get .d.ts file path. * @param filePath The path to the source file (i.e. `/dir/foo.css`). It is absolute. * @param arbitraryExtensions Generate `.d.css.ts` instead of `.css.d.ts`. - * @param outputFolder Output folder for generated files. + * @param outDir Output directory for generated files. * @returns The path to the .d.ts file. It is absolute. */ -export function getDtsFilePath( - filePath: string, - arbitraryExtensions: boolean, - outputFolder: string | undefined, -): string { +export function getDtsFilePath(filePath: string, arbitraryExtensions: boolean, outDir: string | undefined): string { let outputFilePath = filePath; - if (outputFolder) { + if (outDir) { const relativePath = path.relative(CURRENT_WORKING_DIRECTORY, filePath); - outputFilePath = path.resolve(CURRENT_WORKING_DIRECTORY, outputFolder, relativePath); + outputFilePath = path.resolve(CURRENT_WORKING_DIRECTORY, outDir, relativePath); } if (arbitraryExtensions) { diff --git a/packages/happy-css-modules/src/emitter/index.test.ts b/packages/happy-css-modules/src/emitter/index.test.ts index b062e6a8..e68effbc 100644 --- a/packages/happy-css-modules/src/emitter/index.test.ts +++ b/packages/happy-css-modules/src/emitter/index.test.ts @@ -30,7 +30,7 @@ describe('emitGeneratedFiles', () => { dtsFormatOptions: undefined, cwd: getFixturePath('/test'), isExternalFile: () => false, - outputFolder: undefined, + outDir: undefined, }; beforeEach(() => { createFixtures({ diff --git a/packages/happy-css-modules/src/emitter/index.ts b/packages/happy-css-modules/src/emitter/index.ts index a49f3e0d..0e371c57 100644 --- a/packages/happy-css-modules/src/emitter/index.ts +++ b/packages/happy-css-modules/src/emitter/index.ts @@ -45,8 +45,8 @@ export type EmitterOptions = { dtsFormatOptions: DtsFormatOptions | undefined; /** Whether the file is from an external library or not. */ isExternalFile: (filePath: string) => boolean; - /** Output folder for generated files. */ - outputFolder: string | undefined; + /** Output directory for generated files. */ + outDir: string | undefined; }; export async function emitGeneratedFiles({ @@ -55,11 +55,11 @@ export async function emitGeneratedFiles({ emitDeclarationMap, dtsFormatOptions, isExternalFile, - outputFolder, + outDir, }: EmitterOptions): Promise { const arbitraryExtensions = dtsFormatOptions?.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS; - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outputFolder); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outputFolder); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outDir); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outDir); const { dtsContent, sourceMap } = generateDtsContentWithSourceMap( filePath, dtsFilePath, @@ -87,10 +87,10 @@ export async function isGeneratedFilesExist( filePath: string, emitDeclarationMap: boolean | undefined, arbitraryExtensions: boolean, - outputFolder: string | undefined, + outDir: string | undefined, ): Promise { - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outputFolder); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outputFolder); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outDir); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outDir); if (emitDeclarationMap && !(await exists(sourceMapFilePath))) { return false; } diff --git a/packages/happy-css-modules/src/emitter/source-map.ts b/packages/happy-css-modules/src/emitter/source-map.ts index 194d0a3f..4a692a38 100644 --- a/packages/happy-css-modules/src/emitter/source-map.ts +++ b/packages/happy-css-modules/src/emitter/source-map.ts @@ -6,15 +6,15 @@ import { getRelativePath } from './index.js'; * Get .d.ts.map file path. * @param filePath The path to the source file (i.e. `foo.css`). It is absolute. * @param arbitraryExtensions Generate `.d.css.ts` instead of `.css.d.ts`. - * @param outputFolder Output folder for generated files. + * @param outDir Output directory for generated files. * @returns The path to the .d.ts.map file. It is absolute. */ export function getSourceMapFilePath( filePath: string, arbitraryExtensions: boolean, - outputFolder: string | undefined, + outDir: string | undefined, ): string { - return `${getDtsFilePath(filePath, arbitraryExtensions, outputFolder)}.map`; + return `${getDtsFilePath(filePath, arbitraryExtensions, outDir)}.map`; } export function generateSourceMappingURLComment(dtsFilePath: string, sourceMapFilePath: string): string { diff --git a/packages/happy-css-modules/src/runner.ts b/packages/happy-css-modules/src/runner.ts index 459991f8..23bbfe29 100644 --- a/packages/happy-css-modules/src/runner.ts +++ b/packages/happy-css-modules/src/runner.ts @@ -162,7 +162,7 @@ export async function run(options: RunnerOptions): Promise { arbitraryExtensions: options.arbitraryExtensions, }, isExternalFile, - outputFolder: options.outDir, + outDir: options.outDir, }); logger.info(chalk.green(`${relative(cwd, filePath)} (generated)`)); From d170ef86a46c3ad673099203117f0c86d304ad02 Mon Sep 17 00:00:00 2001 From: apple-yagi Date: Mon, 4 Nov 2024 15:32:53 +0900 Subject: [PATCH 6/8] Fixed to use the value of the cwd option --- packages/happy-css-modules/src/emitter/dts.ts | 19 +++++++++++-------- .../happy-css-modules/src/emitter/index.ts | 17 +++++++++++++---- .../src/emitter/source-map.ts | 5 +++-- packages/happy-css-modules/src/runner.test.ts | 13 +++++++++++-- packages/happy-css-modules/src/runner.ts | 2 ++ 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/happy-css-modules/src/emitter/dts.ts b/packages/happy-css-modules/src/emitter/dts.ts index ffe9b68d..4f4e633a 100644 --- a/packages/happy-css-modules/src/emitter/dts.ts +++ b/packages/happy-css-modules/src/emitter/dts.ts @@ -4,22 +4,25 @@ import camelcase from 'camelcase'; import { SourceNode, type CodeWithSourceMap } from '../library/source-map/index.js'; import { type Token } from '../locator/index.js'; import { type LocalsConvention } from '../runner.js'; -import { getRelativePath, type DtsFormatOptions } from './index.js'; - -const CURRENT_WORKING_DIRECTORY = process.cwd(); +import { getRelativePath } from './index.js'; +import type { OutDirOptions, DtsFormatOptions } from './index.js'; /** * Get .d.ts file path. * @param filePath The path to the source file (i.e. `/dir/foo.css`). It is absolute. * @param arbitraryExtensions Generate `.d.css.ts` instead of `.css.d.ts`. - * @param outDir Output directory for generated files. + * @param options Output directory options * @returns The path to the .d.ts file. It is absolute. */ -export function getDtsFilePath(filePath: string, arbitraryExtensions: boolean, outDir: string | undefined): string { +export function getDtsFilePath( + filePath: string, + arbitraryExtensions: boolean, + options: OutDirOptions | undefined, +): string { let outputFilePath = filePath; - if (outDir) { - const relativePath = path.relative(CURRENT_WORKING_DIRECTORY, filePath); - outputFilePath = path.resolve(CURRENT_WORKING_DIRECTORY, outDir, relativePath); + if (options?.outDir) { + const relativePath = path.relative(options.cwd, filePath); + outputFilePath = path.resolve(options.cwd, options.outDir, relativePath); } if (arbitraryExtensions) { diff --git a/packages/happy-css-modules/src/emitter/index.ts b/packages/happy-css-modules/src/emitter/index.ts index 0e371c57..13ae0593 100644 --- a/packages/happy-css-modules/src/emitter/index.ts +++ b/packages/happy-css-modules/src/emitter/index.ts @@ -47,6 +47,8 @@ export type EmitterOptions = { isExternalFile: (filePath: string) => boolean; /** Output directory for generated files. */ outDir: string | undefined; + /** Current working directory. */ + cwd: string; }; export async function emitGeneratedFiles({ @@ -56,10 +58,11 @@ export async function emitGeneratedFiles({ dtsFormatOptions, isExternalFile, outDir, + cwd, }: EmitterOptions): Promise { const arbitraryExtensions = dtsFormatOptions?.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS; - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outDir); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outDir); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, { outDir, cwd }); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, { outDir, cwd }); const { dtsContent, sourceMap } = generateDtsContentWithSourceMap( filePath, dtsFilePath, @@ -88,9 +91,10 @@ export async function isGeneratedFilesExist( emitDeclarationMap: boolean | undefined, arbitraryExtensions: boolean, outDir: string | undefined, + cwd: string, ): Promise { - const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, outDir); - const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, outDir); + const dtsFilePath = getDtsFilePath(filePath, arbitraryExtensions, { outDir, cwd }); + const sourceMapFilePath = getSourceMapFilePath(filePath, arbitraryExtensions, { outDir, cwd }); if (emitDeclarationMap && !(await exists(sourceMapFilePath))) { return false; } @@ -99,3 +103,8 @@ export async function isGeneratedFilesExist( } return true; } + +export type OutDirOptions = { + outDir: string | undefined; + cwd: string; +}; diff --git a/packages/happy-css-modules/src/emitter/source-map.ts b/packages/happy-css-modules/src/emitter/source-map.ts index 4a692a38..518654ce 100644 --- a/packages/happy-css-modules/src/emitter/source-map.ts +++ b/packages/happy-css-modules/src/emitter/source-map.ts @@ -1,5 +1,6 @@ import { EOL } from 'os'; import { getDtsFilePath } from './dts.js'; +import type { OutDirOptions } from './index.js'; import { getRelativePath } from './index.js'; /** @@ -12,9 +13,9 @@ import { getRelativePath } from './index.js'; export function getSourceMapFilePath( filePath: string, arbitraryExtensions: boolean, - outDir: string | undefined, + options: OutDirOptions | undefined, ): string { - return `${getDtsFilePath(filePath, arbitraryExtensions, outDir)}.map`; + return `${getDtsFilePath(filePath, arbitraryExtensions, options)}.map`; } export function generateSourceMappingURLComment(dtsFilePath: string, sourceMapFilePath: string): string { diff --git a/packages/happy-css-modules/src/runner.test.ts b/packages/happy-css-modules/src/runner.test.ts index f6f0302f..b428bdb8 100644 --- a/packages/happy-css-modules/src/runner.test.ts +++ b/packages/happy-css-modules/src/runner.test.ts @@ -362,6 +362,15 @@ test('changes output directory by outDir', async () => { expect(await exists(getFixturePath('/dist/test/1.css.d.ts'))).toBe(true); expect(await exists(getFixturePath('/dist/test/1.css.d.ts.map'))).toBe(true); - expect(await readFile(getFixturePath('/dist/test/1.css.d.ts'), 'utf8')).toMatchInlineSnapshot(); - expect(await readFile(getFixturePath('/dist/test/1.css.d.ts.map'), 'utf8')).toMatchInlineSnapshot(); + expect(await readFile(getFixturePath('/dist/test/1.css.d.ts'), 'utf8')).toMatchInlineSnapshot(` + "declare const styles: + & Readonly<{ "a": string }> + ; + export default styles; + //# sourceMappingURL=./1.css.d.ts.map + " + `); + expect(await readFile(getFixturePath('/dist/test/1.css.d.ts.map'), 'utf8')).toMatchInlineSnapshot( + `"{"version":3,"sources":["../../test/1.css"],"names":["a"],"mappings":"AAAA;AAAA,E,aAAAA,G,WAAA;AAAA;AAAA","file":"1.css.d.ts","sourceRoot":""}"`, + ); }); diff --git a/packages/happy-css-modules/src/runner.ts b/packages/happy-css-modules/src/runner.ts index 23bbfe29..bd8c71f3 100644 --- a/packages/happy-css-modules/src/runner.ts +++ b/packages/happy-css-modules/src/runner.ts @@ -143,6 +143,7 @@ export async function run(options: RunnerOptions): Promise { options.declarationMap, options.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS, options.outDir, + cwd, ); const _isChangedFile = await isChangedFile(filePath); // Generate .d.ts and .d.ts.map only when the file has been updated. @@ -163,6 +164,7 @@ export async function run(options: RunnerOptions): Promise { }, isExternalFile, outDir: options.outDir, + cwd, }); logger.info(chalk.green(`${relative(cwd, filePath)} (generated)`)); From b30712e4230fb2717bb42ca6ccf804eea643b533 Mon Sep 17 00:00:00 2001 From: mizdra Date: Mon, 4 Nov 2024 15:45:20 +0900 Subject: [PATCH 7/8] format --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0f0bd8f..a47974d5 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Options: --cache Only generate .d.ts and .d.ts.map for changed files. [boolean] [default: true] --cacheStrategy Strategy for the cache to use for detecting changed files.[choices: "content", "metadata"] [default: "content"] --logLevel What level of logs to report. [choices: "debug", "info", "silent"] [default: "info"] - -o, --outDir Output directory for generated files. [string] + -o, --outDir Output directory for generated files. [string] -h, --help Show help [boolean] -v, --version Show version number [boolean] From ef3040e698367f7386b712cc4f14f2f1a0706511 Mon Sep 17 00:00:00 2001 From: mizdra Date: Mon, 4 Nov 2024 15:52:38 +0900 Subject: [PATCH 8/8] add test cases --- packages/happy-css-modules/src/emitter/dts.test.ts | 3 +++ packages/happy-css-modules/src/emitter/index.test.ts | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/packages/happy-css-modules/src/emitter/dts.test.ts b/packages/happy-css-modules/src/emitter/dts.test.ts index 06550c30..0d3a3fa2 100644 --- a/packages/happy-css-modules/src/emitter/dts.test.ts +++ b/packages/happy-css-modules/src/emitter/dts.test.ts @@ -13,6 +13,9 @@ test('getDtsFilePath', () => { expect(getDtsFilePath('/app/src/dir/1.scss', false, undefined)).toBe('/app/src/dir/1.scss.d.ts'); expect(getDtsFilePath('/app/src/dir/1.css', true, undefined)).toBe('/app/src/dir/1.d.css.ts'); expect(getDtsFilePath('/app/src/dir/1.scss', true, undefined)).toBe('/app/src/dir/1.d.scss.ts'); + expect(getDtsFilePath('/app/src/dir/1.css', false, { cwd: '/app', outDir: 'dist' })).toBe( + '/app/dist/src/dir/1.css.d.ts', + ); }); describe('generateDtsContentWithSourceMap', () => { diff --git a/packages/happy-css-modules/src/emitter/index.test.ts b/packages/happy-css-modules/src/emitter/index.test.ts index e68effbc..c801ea17 100644 --- a/packages/happy-css-modules/src/emitter/index.test.ts +++ b/packages/happy-css-modules/src/emitter/index.test.ts @@ -76,4 +76,13 @@ describe('emitGeneratedFiles', () => { expect(mtimeForDts1).not.toEqual(mtimeForDts3); // not skipped expect(mtimeForSourceMap1).not.toEqual(mtimeForSourceMap3); // not skipped }); + test('changes output directory by outDir', async () => { + await emitGeneratedFiles({ ...defaultArgs, outDir: 'dist' }); + expect(await exists(getFixturePath('/test/dist/1.css.d.ts'))).toBeTruthy(); + // A link to the source map is not embedded. + expect(await readFile(getFixturePath('/test/dist/1.css.d.ts'), 'utf8')).toEqual( + expect.not.stringContaining('//# sourceMappingURL=1.css.d.ts.map'), + ); + expect(await exists(getFixturePath('/test/dist/1.css.d.ts.map'))).toBeTruthy(); + }); });