Skip to content
This repository was archived by the owner on Dec 12, 2025. It is now read-only.

Commit d12111e

Browse files
committed
feat: twoslash
1 parent 1c66f28 commit d12111e

23 files changed

+776
-131
lines changed

docs/.vitepress/config/shared.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import { transformerTwoslash } from "@shikijs/vitepress-twoslash";
2+
import { createFileSystemTypesCache } from "@shikijs/vitepress-twoslash/cache-fs";
13
import UnoCSS from "unocss/vite";
24
import { defineConfig } from "vitepress";
35
import {
46
groupIconMdPlugin,
57
groupIconVitePlugin,
68
} from "vitepress-plugin-group-icons";
79

10+
import { MarkdownTransform, clercImports } from "../plugins/markdownTransform";
11+
812
export const sharedConfig = defineConfig({
913
title: "Clerc",
10-
appearance: "dark",
14+
// appearance: "dark",
1115
lastUpdated: true,
1216
head: [["link", { rel: "icon", href: "/logo.webp", type: "image/webp" }]],
1317
themeConfig: {
@@ -30,8 +34,25 @@ export const sharedConfig = defineConfig({
3034
config(md) {
3135
md.use(groupIconMdPlugin);
3236
},
37+
codeTransformers: [
38+
transformerTwoslash({
39+
twoslashOptions: {
40+
handbookOptions: {
41+
noErrors: true,
42+
},
43+
},
44+
includesMap: new Map([
45+
[
46+
"imports",
47+
`// ---cut-start---\nimport { ${clercImports.join(", ")} } from "clerc";\n// ---cut-end---`,
48+
],
49+
]),
50+
typesCache: createFileSystemTypesCache(),
51+
}),
52+
],
53+
languages: ["js", "jsx", "ts", "tsx"],
3354
},
3455
vite: {
35-
plugins: [groupIconVitePlugin(), UnoCSS()],
56+
plugins: [groupIconVitePlugin(), UnoCSS(), MarkdownTransform()],
3657
},
3758
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { Plugin } from "vitepress";
2+
3+
const TAB_SIZE = 2;
4+
5+
// @keep-sorted
6+
export const clercImports = [
7+
"Clerc",
8+
"completionsPlugin",
9+
"friendlyErrorPlugin",
10+
"helpPlugin",
11+
"notFoundPlugin",
12+
"strictFlagsPlugin",
13+
"versionPlugin",
14+
];
15+
16+
export const MarkdownTransform = (): Plugin => ({
17+
name: "clerc-markdown-transform",
18+
enforce: "pre",
19+
transform(code, id) {
20+
if (!id.endsWith(".md")) {
21+
return;
22+
}
23+
24+
return code
25+
.replace(/```(ts|typescript)([^\n]*)\n/g, (match, lang, attrs) => {
26+
if (!attrs.includes("twoslash")) {
27+
attrs += " twoslash";
28+
}
29+
30+
return `\`\`\`${lang}${attrs}\n// @include: imports\n`;
31+
})
32+
.replace(/\t/g, " ".repeat(TAB_SIZE));
33+
},
34+
});

docs/.vitepress/theme/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import TwoslashFloatingVue from "@shikijs/vitepress-twoslash/client";
2+
import type { EnhanceAppContext } from "vitepress";
13
import Theme from "vitepress/theme";
24

35
import "./style.css";
46
import "virtual:uno.css";
57
import "virtual:group-icons.css";
8+
import "@shikijs/vitepress-twoslash/style.css";
69

710
export default {
811
extends: Theme,
12+
enhanceApp({ app }: EnhanceAppContext) {
13+
app.use(TwoslashFloatingVue);
14+
},
915
};

docs/commands.md

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ This creates a CLI application named `foo-cli` with a command called `foo`. When
2626

2727
You can add an alias for your command:
2828

29-
```js
30-
import { Clerc } from "clerc";
31-
29+
```ts
3230
const cli = Clerc.create()
3331
.scriptName("foo-cli")
3432
.description("A simple CLI")
@@ -46,9 +44,7 @@ Now both `foo-cli foo` and `foo-cli bar` will output "It works!".
4644

4745
You can add more aliases:
4846

49-
```js
50-
import { Clerc } from "clerc";
51-
47+
```ts
5248
const cli = Clerc.create()
5349
.scriptName("foo-cli")
5450
.description("A simple CLI")
@@ -66,9 +62,7 @@ const cli = Clerc.create()
6662

6763
You can define subcommands by using spaces in the command name:
6864

69-
```js
70-
import { Clerc } from "clerc";
71-
65+
```ts
7266
const cli = Clerc.create()
7367
.scriptName("foo-cli")
7468
.description("A simple CLI")
@@ -84,9 +78,7 @@ const cli = Clerc.create()
8478

8579
You can define a root command (a command with no name) to handle cases when no subcommand is specified:
8680

87-
```js
88-
import { Clerc } from "clerc";
89-
81+
```ts
9082
const cli = Clerc.create()
9183
.scriptName("foo-cli")
9284
.description("A simple CLI")
@@ -120,7 +112,6 @@ Example:
120112

121113
```ts
122114
// $ node ./foo-cli.mjs a b c d
123-
import { Clerc } from "clerc";
124115

125116
const cli = Clerc.create()
126117
.scriptName("foo-cli")
@@ -134,16 +125,18 @@ const cli = Clerc.create()
134125
],
135126
})
136127
.on("foo", (ctx) => {
137-
ctx.parameters.requiredParameter; // => "a" (string)
138-
ctx.parameters.optionalParameter; // => "b" (string | undefined)
139-
ctx.parameters.optionalSpread; // => ["c", "d"] (string[])
128+
ctx.parameters;
129+
// ^?
130+
ctx.parameters.requiredParameter; // => "a"
131+
ctx.parameters.optionalParameter; // => "b"
132+
ctx.parameters.optionalSpread; // => ["c", "d"]
140133
})
141134
.parse();
142135
```
143136

144-
### End Flag
137+
### End-of-file
145138

146-
The end flag (`--`) (also known as _option terminator_) allows users to pass a portion of arguments. This is useful for arguments that should be parsed separately from other arguments or arguments that look like options.
139+
The end-of-file (`--`) (also known as _flag terminator_) allows users to pass a portion of arguments. This is useful for arguments that should be parsed separately from other arguments or arguments that look like flags.
147140

148141
An example is [`npm run`](https://docs.npmjs.com/cli/v8/commands/npm-run-script):
149142

@@ -153,13 +146,12 @@ $ npm run <script> -- <script arguments>
153146

154147
The `--` indicates that all arguments after it should be passed to the _script_ rather than _npm_.
155148

156-
You can specify `--` in the `parameters` array to parse option terminator arguments.
149+
You can specify `--` in the `parameters` array to parse flag terminator arguments.
157150

158151
Example:
159152

160153
```ts
161154
// $ node ./foo-cli.mjs echo -- hello world
162-
import { Clerc } from "clerc";
163155

164156
const cli = Clerc.create()
165157
.scriptName("foo-cli")
@@ -169,36 +161,37 @@ const cli = Clerc.create()
169161
parameters: ["<script>", "--", "[arguments...]"],
170162
})
171163
.on("echo", (ctx) => {
172-
ctx.parameters.script; // => "echo" (string)
173-
ctx.parameters.arguments; // => ["hello", "world"] (string[])
164+
ctx.parameters;
165+
// ^?
166+
ctx.parameters.script; // => "echo"
167+
ctx.parameters.arguments; // => ["hello", "world"]
174168
})
175169
.parse();
176170
```
177171

178-
## Options
172+
## Flags
179173

180-
_Clerc_'s option parsing is powered by [`@clerc/parser`](https://github.com/clercjs/clerc/blob/main/packages/parser) and has many features:
174+
_Clerc_'s flag parsing is powered by [`@clerc/parser`](https://github.com/clercjs/clerc/blob/main/packages/parser) and has many features:
181175

182176
- Array and custom types
183-
- Option delimiters: `--flag value`, `--flag=value`, `--flag:value` and `--flag.value`
177+
- Flag delimiters: `--flag value`, `--flag=value`, `--flag:value` and `--flag.value`
184178
- Combined aliases: `-abcd 2``-a -b -c -d 2`
185-
- [Option terminator](https://unix.stackexchange.com/a/11382): pass `--` to end option parsing
179+
- [End-of-file](https://unix.stackexchange.com/a/11382): pass `--` to end parsing
186180

187-
Options can be specified in the `flags` object property, where the key is the option name and the value is either an option type function or an object describing the option.
181+
Flags can be specified in the `flags` object property, where the key is the flag name and the value is either an flag type function or an object describing the flag.
188182

189-
It's recommended to use camelCase for option names as it will be interpreted as parsing the equivalent kebab-case option.
183+
It's recommended to use camelCase for flag names as it will be interpreted as parsing the equivalent kebab-case flag.
190184

191-
The option type function can be any function that accepts a string and returns the parsed value. The default JavaScript constructors should cover most use cases: [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/String), [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/Number), [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/Boolean), etc.
185+
The flag type function can be any function that accepts a string and returns the parsed value. The default JavaScript constructors should cover most use cases: [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/String), [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/Number), [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/Boolean), etc.
192186

193-
The option description object can be used to store additional information about the option, such as `alias`, `default`, and `description`. To accept multiple values for an option, wrap the type function in an array.
187+
The flag description object can be used to store additional information about the flag, such as `alias`, `default`, and `description`. To accept multiple values for a flag, wrap the type function in an array.
194188

195189
All provided information will be used to generate better help documentation.
196190

197191
Example:
198192

199193
```ts
200194
// $ node ./foo-cli.mjs echo --some-boolean --some-string hello --some-number 1 -n 2
201-
import { Clerc } from "clerc";
202195

203196
const cli = Clerc.create()
204197
.scriptName("foo-cli")
@@ -208,12 +201,12 @@ const cli = Clerc.create()
208201
flags: {
209202
someBoolean: {
210203
type: Boolean,
211-
description: "Some boolean option",
204+
description: "Some boolean flag",
212205
},
213206

214207
someString: {
215208
type: String,
216-
description: "Some string option",
209+
description: "Some string flag",
217210
default: "n/a",
218211
},
219212

@@ -225,37 +218,39 @@ const cli = Clerc.create()
225218
},
226219

227220
object: {
228-
type: object,
229-
description: "An object option. (e.g. --object.key value)",
221+
type: Object,
222+
description: "An object flag. (e.g. --object.key value)",
230223
},
231224

232225
counter: {
233226
type: [Boolean],
234-
description: "A counter option. (e.g. -c -c -c)",
227+
description: "A counter flag. (e.g. -c -c -c)",
235228
},
236229
},
237230
})
238231
.on("echo", (ctx) => {
239-
ctx.flags.someBoolean; // => true (boolean | undefined)
240-
ctx.flags.someString; // => "hello" (string)
241-
ctx.flags.someNumber; // => [1, 2] (number[])
242-
ctx.flags.object; // => { key: "value" } (Record<string, string | boolean>)
243-
ctx.flags.counter; // => 2 (number)
232+
ctx.flags;
233+
// ^?
234+
ctx.flags.someBoolean; // => true
235+
ctx.flags.someString; // => "hello"
236+
ctx.flags.someNumber; // => [1, 2]
237+
ctx.flags.object; // => { key: "value" }
238+
ctx.flags.counter; // => 2
244239
})
245240
.parse();
246241
```
247242

248243
## Ignore
249244

250-
Sometimes, you may want to ignore certain arguments or options in the command line input. For example, this usage of `deno`:
245+
Sometimes, you may want to ignore certain arguments or flags in the command line input. For example, this usage of `deno`:
251246

252247
```sh
253248
deno run --allow-read script.ts --flag
254249
```
255250

256251
Where `--flag` is passed directly to the script, not to `deno`.
257252

258-
You can achieve this usage by using the `ignore` property to specify which arguments or options to ignore.
253+
You can achieve this usage by using the `ignore` property to specify which arguments or flags to ignore.
259254

260255
```ts
261256
import { Clerc, PARAMETER } from "clerc";
@@ -287,7 +282,8 @@ const cli = Clerc.create()
287282
})
288283
.on("run", (ctx) => {
289284
// Handle script execution
290-
ctx.ignored; // => ["--flag"] (string[])
285+
ctx.ignored; // => ["--flag"]
286+
// ^?
291287
})
292288
.parse();
293289
```

docs/getting-started.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ $ pnpm add clerc
3939
Install clerc, and create a file named `cli.mjs`:
4040

4141
```ts
42-
import { Clerc } from "clerc";
43-
4442
Clerc.create() // Create a new Clerc instance
4543
.scriptName("foo") // CLI script name
4644
.description("A foo CLI") // CLI description

docs/interceptors.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ Attention! When calling `next`, make sure to use `await`, otherwise errors might
3939
The `interceptor` method accepts either a function or an object:
4040

4141
```ts
42-
import { Clerc } from "clerc";
43-
4442
const cli = Clerc.create()
4543
.scriptName("foo-cli")
4644
.description("A simple CLI")
@@ -70,8 +68,6 @@ Therefore, the execution order is as follows:
7068
By performing operations after calling `next()`, you can execute some actions after the command handler is called:
7169

7270
```ts
73-
import { Clerc } from "clerc";
74-
7571
const cli = Clerc.create()
7672
.scriptName("foo-cli")
7773
.description("A simple CLI")

docs/official-plugins/plugin-completions.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ $ pnpm add @clerc/plugin-completions
2626

2727
## 🚀 Usage
2828

29-
### Basic Usage
29+
### Import
3030

3131
```ts
32-
import { completionsPlugin } from "@clerc/plugin-completions"; // or import directly from clerc
33-
import { Clerc } from "clerc";
32+
import { completionsPlugin } from "@clerc/plugin-completions";
33+
// or import directly from clerc
34+
import { completionsPlugin } from "clerc";
35+
```
36+
37+
### Basic Usage
3438

39+
```ts
3540
const cli = Clerc.create()
3641
.scriptName("my-cli")
3742
.description("My CLI application")
@@ -95,8 +100,6 @@ The plugin automatically generates complete auto-completion scripts for your CLI
95100
### Advanced Configuration
96101

97102
```ts
98-
import { completionsPlugin } from "@clerc/plugin-completions"; // or import directly from clerc
99-
100103
const cli = Clerc.create()
101104
.scriptName("my-cli")
102105
.description("My CLI application")

docs/official-plugins/plugin-friendly-error.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ $ pnpm add @clerc/plugin-friendly-error
2626

2727
## 🚀 Usage
2828

29-
### Basic Usage
29+
### Import
3030

3131
```ts
32-
import { friendlyErrorPlugin } from "@clerc/plugin-friendly-error"; // or import directly from clerc
33-
import { Clerc } from "clerc";
32+
import { friendlyErrorPlugin } from "@clerc/plugin-friendly-error";
33+
// or import directly from clerc
34+
import { friendlyErrorPlugin } from "clerc";
35+
```
3436

37+
### Basic Usage
38+
39+
```ts
3540
const cli = Clerc.create()
3641
.scriptName("my-cli")
3742
.description("My CLI application")

0 commit comments

Comments
 (0)