Skip to content

✨ Output directory option #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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` });
}