Skip to content

Commit

Permalink
✨ Output directory option (#24)
Browse files Browse the repository at this point in the history
Adds output directory option (-o or --outdir) as alternative to generating the declaration files alongside the source file.

Adds outdir unit tests and pipeline tests. Refactors pipeline tests to improve failure diagnosis.

+semver:minor
  • Loading branch information
connorjs authored Aug 3, 2024
1 parent 24713e7 commit 1875279
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 26 deletions.
59 changes: 48 additions & 11 deletions .github/workflows/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,58 @@ jobs:
- name: Build
run: npm run build

- name: Run css-typed (the test)
# `node dist/main.js` is executing local `css-typed` as if installed (same as `bin`)
# Use `-I '//.*'` to ignore the first line (comment) which has generated path and timestamp
# Test `--localsConvention` in both positions
# Run tests
#
# - Run from $RUNNER_TEMP for auto-cleanup.
# - `./dist/main.js` is executing local `css-typed` as if installed (same as `bin`).
# But it is `$GITHUB_WORKSPACE/dist/main.js` b/c we `cd $RUNNER_TEMP`.
# - Use `diff` to compare the files.
# Use `-I '//.*'` to ignore the first line (comment) which has generated path and timestamp.

- name: "Test 1: Default case"
run: |
cp src/fixtures/casing/casing.css "$RUNNER_TEMP/casing.css"
cp src/fixtures/casing/casing.css $RUNNER_TEMP/casing.css
cp src/fixtures/casing/dashesOnly.d.css.ts $RUNNER_TEMP/expected.d.css.ts
node dist/main.js "$RUNNER_TEMP/*.css"
diff --strip-trailing-cr -uI '//.*' src/fixtures/casing/dashesOnly.d.css.ts "$RUNNER_TEMP/casing.d.css.ts"
cd $RUNNER_TEMP
$GITHUB_WORKSPACE/dist/main.js '*.css'
diff --strip-trailing-cr -uI '//.*' expected.d.css.ts casing.d.css.ts
node dist/main.js "$RUNNER_TEMP/*.css" --localsConvention camelCaseOnly
diff --strip-trailing-cr -uI '//.*' src/fixtures/casing/camelCaseOnly.d.css.ts "$RUNNER_TEMP/casing.d.css.ts"
- name: "Test 2: localsConvention, second position"
run: |
cp src/fixtures/casing/casing.css $RUNNER_TEMP/casing.css
cp src/fixtures/casing/camelCaseOnly.d.css.ts $RUNNER_TEMP/expected.d.css.ts
cd $RUNNER_TEMP
$GITHUB_WORKSPACE/dist/main.js '*.css' --localsConvention camelCaseOnly
diff --strip-trailing-cr -uI '//.*' expected.d.css.ts casing.d.css.ts
- name: "Test 3: localsConvention, first position"
run: |
cp src/fixtures/casing/casing.css $RUNNER_TEMP/casing.css
cp src/fixtures/casing/camelCaseOnly.d.css.ts $RUNNER_TEMP/expected.d.css.ts
cd $RUNNER_TEMP
$GITHUB_WORKSPACE/dist/main.js --localsConvention camelCaseOnly '*.css'
diff --strip-trailing-cr -uI '//.*' expected.d.css.ts casing.d.css.ts
- name: "Test 4: relative outdir"
run: |
cp src/fixtures/casing/casing.css $RUNNER_TEMP/casing.css
cp src/fixtures/casing/dashesOnly.d.css.ts $RUNNER_TEMP/expected.d.css.ts
cd $RUNNER_TEMP
$GITHUB_WORKSPACE/dist/main.js '*.css' --outdir generated
diff --strip-trailing-cr -uI '//.*' expected.d.css.ts generated/casing.d.css.ts
- name: "Test 5: absolute outdir"
run: |
cp src/fixtures/casing/casing.css $RUNNER_TEMP/casing.css
cp src/fixtures/casing/dashesOnly.d.css.ts $RUNNER_TEMP/expected.d.css.ts
node dist/main.js --localsConvention camelCaseOnly "$RUNNER_TEMP/*.css"
diff --strip-trailing-cr -uI '//.*' src/fixtures/casing/camelCaseOnly.d.css.ts "$RUNNER_TEMP/casing.d.css.ts"
cd $RUNNER_TEMP
$GITHUB_WORKSPACE/dist/main.js '*.css' -o $GITHUB_WORKSPACE/generated
diff --strip-trailing-cr -uI '//.*' expected.d.css.ts $GITHUB_WORKSPACE/generated/casing.d.css.ts
Publish:
if: ${{ github.ref == 'refs/heads/main' }}
Expand Down
19 changes: 14 additions & 5 deletions src/logic.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readFileSync } from "node:fs";
import path from "node:path";
import * as process from "node:process";

import { describe, expect, it } from "vitest";

Expand Down Expand Up @@ -37,13 +38,21 @@ describe(`css-typed`, () => {
});
});

const cwd = process.cwd();
const cwdParent = path.resolve(cwd, `..`);
describe(`dtsPath`, () => {
it.each([
[`foo.css`, `foo.d.css.ts`],
[`foo.module.css`, `foo.module.d.css.ts`],
])(`%s should create file %s`, (input, expected) => {
expect(dtsPath(input)).toStrictEqual(expected);
});
[`src/foo.css`, `${cwd}/src/foo.d.css.ts`, undefined],
[`src/foo.module.css`, `${cwd}/src/foo.module.d.css.ts`, ``],
[`src/foo.css`, `${cwd}/generated/src/foo.d.css.ts`, `generated`],
[`src/foo.css`, `/absolute/src/foo.d.css.ts`, `/absolute`],
[`src/foo.css`, `${cwdParent}/relative/src/foo.d.css.ts`, `../relative`],
])(
`[%s] should create file [%s] with outdir [%s]`,
(input, expected, outdir) => {
expect(path.join(...dtsPath(input, outdir))).toStrictEqual(expected);
},
);
});
});

Expand Down
18 changes: 15 additions & 3 deletions src/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,19 @@ function dashesCamelCase(s: string) {
);
}

export function dtsPath(stylesheetPath: string) {
const { dir, name, ext } = path.parse(stylesheetPath);
return path.join(dir, `${name}.d${ext}.ts`);
export function dtsPath(
stylesheetPath: string,
outdir: string | undefined,
): [string, string] {
const { dir: originalDirectory, name, ext } = path.parse(stylesheetPath);

let directory;
if (outdir) {
const relative = path.relative(process.cwd(), originalDirectory);
directory = path.join(outdir, relative);
} else {
directory = originalDirectory;
}

return [path.resolve(directory), `${name}.d${ext}.ts`];
}
33 changes: 26 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env node

import { writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { mkdir, writeFile } from "node:fs/promises";
import path from "node:path";

import { Command, Option } from "@commander-js/extra-typings";
import { glob } from "glob";
Expand All @@ -24,14 +26,18 @@ await new Command()
.choices(localsConventionChoices)
.default(`dashesOnly` as const),
)
.option(
`-o, --outdir <outDirectory>`,
`Root directory for generated CSS declaration files.`,
)
.action(async function (pattern, options) {
const files = await glob(pattern);

const time = new Date().toISOString();
await Promise.all(
files.map((file) =>
generateDeclaration(file, time, options).then((ts) =>
writeDeclarationFile(file, ts),
writeDeclarationFile(file, options.outdir, ts),
),
),
);
Expand All @@ -41,12 +47,25 @@ await new Command()
/**
* Writes the TypeScript declaration content to file. Handles the output path.
*
* @param path - Path to the original stylesheet file. NOT the path to write.
* @param file - Path to the original stylesheet file. NOT the path to write.
* @param outdir - Output directory to which to write.
* @param ts - The TypeScript declaration content to write.
* @returns Empty promise indicating when writing has completed.
*/
async function writeDeclarationFile(path: string, ts: string | undefined) {
if (!ts) return undefined;
await writeFile(dtsPath(path), ts, `utf8`);
return undefined;
async function writeDeclarationFile(
file: string,
outdir: string | undefined,
ts: string | undefined,
) {
if (!ts) {
return undefined;
}

const [directoryToWrite, fileToWrite] = dtsPath(file, outdir);
if (!existsSync(directoryToWrite)) {
await mkdir(directoryToWrite, { recursive: true });
}

const pathToWrite = path.join(directoryToWrite, fileToWrite);
await writeFile(pathToWrite, ts, { encoding: `utf8` });
}

0 comments on commit 1875279

Please sign in to comment.