diff --git a/.changeset/ts-package-scripts.md b/.changeset/ts-package-scripts.md new file mode 100644 index 0000000..18e1dfb --- /dev/null +++ b/.changeset/ts-package-scripts.md @@ -0,0 +1,5 @@ +--- +'markdown-magic-package-scripts': minor +--- + +TypeScript: ship type declarations diff --git a/packages/package-scripts/README.md b/packages/package-scripts/README.md index 786313d..b313844 100644 --- a/packages/package-scripts/README.md +++ b/packages/package-scripts/README.md @@ -10,14 +10,14 @@ yarn add -D markdown-magic markdown-magic-package-scripts ## Adding the plugin -See `example.js` for usage. +See `example.ts` for usage. - + -```js +```ts import path from 'path'; import { markdownMagic } from 'markdown-magic'; -import SCRIPTS from './index.js'; +import SCRIPTS from './index.ts'; const config = { matchWord: 'AUTO-GENERATED-CONTENT', @@ -36,11 +36,14 @@ await markdownMagic(markdownPath, config); -| Script | Description | -| -------- | -------------------------------- | -| `docs` | generate docs | -| `empty` | `echo "this is just an example"` | -| `format` | format code | -| `test` | `vitest run` | +| Script | Description | +| ---------- | ----------------------------------- | +| `prebuild` | `rm -rf dist` | +| `build` | `tsc --project tsconfig.build.json` | +| `docs` | generate docs | +| `empty` | `echo "this is just an example"` | +| `format` | format code | +| `prepack` | `pnpm build` | +| `test` | `vitest run` | diff --git a/packages/package-scripts/__snapshots__/index.spec.js.snap b/packages/package-scripts/__snapshots__/index.spec.ts.snap similarity index 65% rename from packages/package-scripts/__snapshots__/index.spec.js.snap rename to packages/package-scripts/__snapshots__/index.spec.ts.snap index 356b2a4..3261a02 100644 --- a/packages/package-scripts/__snapshots__/index.spec.js.snap +++ b/packages/package-scripts/__snapshots__/index.spec.ts.snap @@ -3,8 +3,11 @@ exports[`markdown-magic-package-scripts > renders a table of scripts from the nearest package.json 1`] = ` "| Script | Description | |--------|-------------| -| \`docs\` | \`node example.js && prettier --write README.md\` | +| \`prebuild\` | \`rm -rf dist\` | +| \`build\` | \`tsc --project tsconfig.build.json\` | +| \`docs\` | \`node example.ts && prettier --write README.md\` | | \`empty\` | \`echo "this is just an example"\` | | \`format\` | \`prettier --write .\` | +| \`prepack\` | \`pnpm build\` | | \`test\` | \`vitest run\` |" `; diff --git a/packages/package-scripts/example.js b/packages/package-scripts/example.ts similarity index 89% rename from packages/package-scripts/example.js rename to packages/package-scripts/example.ts index 9cf399d..84d9285 100644 --- a/packages/package-scripts/example.js +++ b/packages/package-scripts/example.ts @@ -1,6 +1,6 @@ import path from 'path'; import { markdownMagic } from 'markdown-magic'; -import SCRIPTS from './index.js'; +import SCRIPTS from './index.ts'; const config = { matchWord: 'AUTO-GENERATED-CONTENT', diff --git a/packages/package-scripts/index.spec.js b/packages/package-scripts/index.spec.ts similarity index 97% rename from packages/package-scripts/index.spec.js rename to packages/package-scripts/index.spec.ts index 42c9499..f80fe6d 100644 --- a/packages/package-scripts/index.spec.js +++ b/packages/package-scripts/index.spec.ts @@ -1,6 +1,6 @@ import path from 'path'; import { describe, expect, it } from 'vitest'; -import format from './index.js'; +import format from './index.ts'; const srcPath = path.join(import.meta.dirname, 'README.md'); diff --git a/packages/package-scripts/index.js b/packages/package-scripts/index.ts similarity index 66% rename from packages/package-scripts/index.js rename to packages/package-scripts/index.ts index 11c08e8..c6ff1e7 100644 --- a/packages/package-scripts/index.js +++ b/packages/package-scripts/index.ts @@ -2,8 +2,11 @@ import { readFileSync } from 'fs'; import path from 'path'; import { findUpSync } from 'find-up'; import sortScripts from 'sort-scripts'; +import type { TransformArgs } from './types.ts'; -function findPkg(dir) { +export type { TransformArgs, TransformOptions } from './types.ts'; + +function findPkg(dir: string): string { const pkgPath = findUpSync('package.json', { cwd: dir }); if (!pkgPath) { @@ -13,8 +16,12 @@ function findPkg(dir) { return pkgPath; } -export default function SCRIPTS({ content, options = {}, srcPath }) { - let pkgPath; +export default function SCRIPTS({ + content, + options = {}, + srcPath, +}: TransformArgs): string { + let pkgPath: string; if (options && options.pkg) { pkgPath = path.resolve(path.dirname(srcPath), options.pkg); @@ -32,7 +39,9 @@ export default function SCRIPTS({ content, options = {}, srcPath }) { .map((s) => s.trim()); const headerIndex = rows.findIndex((row) => row.startsWith('|-')); - const details = (headerIndex !== -1 ? rows.slice(headerIndex + 1) : rows) + const details: Record = ( + headerIndex !== -1 ? rows.slice(headerIndex + 1) : rows + ) .map((row) => row .split('|') @@ -40,10 +49,13 @@ export default function SCRIPTS({ content, options = {}, srcPath }) { .filter((s) => !!s), ) .filter(([script]) => !!script) - .reduce((obj, [script, description]) => { - obj[script.replace(/`/g, '')] = description; - return obj; - }, {}); + .reduce( + (obj: Record, [script, description]) => { + obj[script.replace(/`/g, '')] = description; + return obj; + }, + {}, + ); return ['| Script | Description |', '|--------|-------------|'] .concat( diff --git a/packages/package-scripts/package.json b/packages/package-scripts/package.json index 9bff5cf..757aa66 100644 --- a/packages/package-scripts/package.json +++ b/packages/package-scripts/package.json @@ -3,17 +3,21 @@ "version": "2.0.0", "description": "Print list of scripts in package.json with descriptions", "type": "module", - "main": "index.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", "exports": { - ".": "./index.js", + ".": "./dist/index.js", "./package.json": "./package.json" }, "engines": { "node": ">=22.18.0" }, "scripts": { + "prebuild": "rm -rf dist", + "build": "tsc --project tsconfig.build.json", + "prepack": "pnpm build", "test": "vitest run", - "docs": "node example.js && prettier --write README.md", + "docs": "node example.ts && prettier --write README.md", "empty": "echo \"this is just an example\"", "format": "prettier --write ." }, @@ -40,8 +44,10 @@ "markdown-magic": "^4" }, "devDependencies": { + "@types/node": "^24.13.2", "markdown-magic": "catalog:", "prettier": "catalog:", + "typescript": "^6.0.3", "vitest": "catalog:" }, "homepage": "https://github.com/camacho/markdown-magic-plugins#readme", @@ -49,6 +55,6 @@ "url": "https://github.com/camacho/markdown-magic-plugins/issues" }, "files": [ - "index.js" + "dist" ] } diff --git a/packages/package-scripts/sort-scripts-shim.d.ts b/packages/package-scripts/sort-scripts-shim.d.ts new file mode 100644 index 0000000..6babec4 --- /dev/null +++ b/packages/package-scripts/sort-scripts-shim.d.ts @@ -0,0 +1,10 @@ +// Ambient shim for `sort-scripts`. Upstream ships no type declarations and +// no `@types/sort-scripts` package exists — smallest correct local +// declaration for the single default export actually used here (verified +// against node_modules/sort-scripts@1.0.1/index.js: takes a scripts map, +// returns `[name, script]` pairs sorted with pre/post ordering). +declare module 'sort-scripts' { + export default function sortScripts( + scripts: Record, + ): Array<[string, string]>; +} diff --git a/packages/package-scripts/tsconfig.build.json b/packages/package-scripts/tsconfig.build.json new file mode 100644 index 0000000..d7ec333 --- /dev/null +++ b/packages/package-scripts/tsconfig.build.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "noEmit": false, + "outDir": "dist", + "rootDir": ".", + "types": ["node"] + }, + "exclude": [ + "node_modules", + "dist", + "*.spec.ts", + "example.ts", + "__fixtures__", + "__snapshots__" + ], + "include": ["*.ts"] +} diff --git a/packages/package-scripts/types.ts b/packages/package-scripts/types.ts new file mode 100644 index 0000000..872b99a --- /dev/null +++ b/packages/package-scripts/types.ts @@ -0,0 +1,14 @@ +// Transform interface shared by markdown-magic plugins. Adapted from +// format-package's scripts/markdown-transformers.ts TransformArgs/TransformOptions +// (content: unknown -> content: string, the plugins' actual contract), plus +// this package's own `pkg` option. +export interface TransformOptions { + pkg?: string; + [key: string]: unknown; +} + +export interface TransformArgs { + content: string; + options: TransformOptions; + srcPath: string; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fd4556..12eb245 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -179,12 +179,18 @@ importers: specifier: ^1.0.1 version: 1.0.1 devDependencies: + '@types/node': + specifier: ^24.13.2 + version: 24.13.2 markdown-magic: specifier: 'catalog:' version: 4.10.5 prettier: specifier: 'catalog:' version: 3.9.1 + typescript: + specifier: ^6.0.3 + version: 6.0.3 vitest: specifier: 'catalog:' version: 4.1.9(@types/node@24.13.2)(vite@8.1.0(@types/node@24.13.2))