@gunshi/plugin-renderer 0.27.0-alpha.9 → 0.27.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @gunshi/plugin-renderer
2
2
 
3
+ [![Version][npm-version-src]][npm-version-href]
4
+ [![InstallSize][install-size-src]][install-size-src]
5
+ [![JSR][jsr-src]][jsr-href]
6
+
3
7
  > usage renderer plugin for gunshi.
4
8
 
5
9
  This plugin provides customizable rendering for CLI help messages, usage information, and validation errors. It automatically formats command descriptions, arguments, options, examples, and error messages in a consistent and readable format.
@@ -26,8 +30,8 @@ bun add @gunshi/plugin-renderer
26
30
  ## 🚀 Usage
27
31
 
28
32
  ```ts
29
- import renderer from '@gunshi/plugin-renderer'
30
33
  import { cli, define } from 'gunshi'
34
+ import renderer from '@gunshi/plugin-renderer'
31
35
 
32
36
  const command = define({
33
37
  name: 'deploy',
@@ -80,7 +84,7 @@ This plugin automatically handles rendering for:
80
84
 
81
85
  The plugin provides smart text rendering with automatic fallback:
82
86
 
83
- - **With i18n plugin**: Uses translations from the i18n plugin
87
+ - **With i18n plugin**: Uses translations from the `@gunshi/plugin-i18n`
84
88
  - **Without i18n plugin**: Falls back to default English messages and descriptions
85
89
 
86
90
  ### Rendered Example
@@ -130,8 +134,8 @@ Available extensions:
130
134
  ### Usage Example
131
135
 
132
136
  ```ts
133
- import renderer from '@gunshi/plugin-renderer'
134
137
  import { cli, define } from 'gunshi'
138
+ import renderer, { pluginId as rendererId } from '@gunshi/plugin-renderer'
135
139
 
136
140
  const deploy = define({
137
141
  name: 'deploy',
@@ -153,7 +157,7 @@ const entry = define({
153
157
  name: 'tools',
154
158
  run: async ctx => {
155
159
  // Access renderer extensions
156
- const { text, loadCommands } = ctx.extensions['g:renderer']
160
+ const { text, loadCommands } = ctx.extensions[rendererId]
157
161
 
158
162
  // Render built-in message
159
163
  const usageHeader = await text('_:USAGE') // "USAGE" or translated
@@ -191,58 +195,21 @@ await cli(process.argv.slice(2), command, {
191
195
 
192
196
  ### Integration with i18n Plugin
193
197
 
194
- The renderer plugin has an optional dependency on the i18n plugin. When both plugins are used together, all rendered text automatically uses translations:
198
+ The renderer plugin has an optional dependency on the `@gunshi/plugin-i18n`. When both plugins are used together, all rendered text automatically uses translations:
195
199
 
196
200
  ```ts
197
- import renderer from '@gunshi/plugin-renderer'
198
- import i18n from '@gunshi/plugin-i18n'
199
- import resources from '@gunshi/resources'
200
201
  import { cli } from 'gunshi'
201
-
202
- await cli(args, command, {
203
- plugins: [
204
- i18n({
205
- locale: 'ja-JP',
206
- resources // Uses built-in resources from @gunshi/resources
207
- }),
208
- renderer() // Will use Japanese translations
209
- ]
210
- })
211
- ```
212
-
213
- #### With Custom Resources
214
-
215
- You can extend the built-in resources with your own translations:
216
-
217
- ```ts
218
202
  import renderer from '@gunshi/plugin-renderer'
219
203
  import i18n from '@gunshi/plugin-i18n'
220
204
  import resources from '@gunshi/resources'
221
- import { cli } from 'gunshi'
222
-
223
- // Extend built-in resources with custom messages
224
- const customResources = {
225
- 'en-US': {
226
- ...resources['en-US'],
227
- // Custom messages for your app
228
- APP_WELCOME: 'Welcome to My CLI Tool!',
229
- APP_PROCESSING: 'Processing your request...'
230
- },
231
- 'ja-JP': {
232
- ...resources['ja-JP'],
233
- // Custom messages in Japanese
234
- APP_WELCOME: '私のCLIツールへようこそ!',
235
- APP_PROCESSING: 'リクエストを処理しています...'
236
- }
237
- }
238
205
 
239
206
  await cli(args, command, {
240
207
  plugins: [
241
208
  i18n({
242
209
  locale: 'ja-JP',
243
- resources: customResources
210
+ resources // Uses built-in resources from `@gunshi/resources`
244
211
  }),
245
- renderer() // Will use Japanese translations including custom messages
212
+ renderer() // Will use Japanese translations
246
213
  ]
247
214
  })
248
215
  ```
@@ -286,4 +253,12 @@ See the [API References](./docs/index.md)
286
253
 
287
254
  ## ©️ License
288
255
 
289
- [MIT](http://opensource.org/licenses/MIT)T)
256
+ [MIT](http://opensource.org/licenses/MIT)
257
+
258
+ <!-- Badges -->
259
+
260
+ [npm-version-src]: https://img.shields.io/npm/v/@gunshi/plugin-renderer?style=flat
261
+ [npm-version-href]: https://npmjs.com/package/@gunshi/plugin-renderer@alpha
262
+ [jsr-src]: https://jsr.io/badges/@gunshi/plugin-renderer
263
+ [jsr-href]: https://jsr.io/@gunshi/plugin-renderer
264
+ [install-size-src]: https://pkg-size.dev/badge/install/101075
package/lib/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { Args, Command, CommandContext, DefaultGunshiParams, GunshiParams, PluginWithExtension } from "@gunshi/plugin";
2
2
  import { Args as Args$1 } from "args-tokens";
3
3
 
4
- //#region rolldown:runtime
5
- declare namespace constants_d_exports {
6
- export { ARG_NEGATABLE_PREFIX, ARG_PREFIX, ARG_PREFIX_AND_KEY_SEPARATOR, BUILD_IN_PREFIX_AND_KEY_SEPARATOR, BUILT_IN_KEY_SEPARATOR, BUILT_IN_PREFIX, COMMAND_BUILTIN_RESOURCE_KEYS, COMMON_ARGS, PLUGIN_PREFIX };
7
- }
4
+ //#region ../shared/src/constants.d.ts
5
+ /**
6
+ * @author kazuya kawaguchi (a.k.a. kazupon)
7
+ * @license MIT
8
+ */
8
9
  /**
9
10
  * @author kazuya kawaguchi (a.k.a. kazupon)
10
11
  * @license MIT
@@ -13,9 +14,6 @@ declare const BUILT_IN_PREFIX = "_";
13
14
  declare const PLUGIN_PREFIX = "g";
14
15
  declare const ARG_PREFIX = "arg";
15
16
  declare const BUILT_IN_KEY_SEPARATOR = ":";
16
- declare const BUILD_IN_PREFIX_AND_KEY_SEPARATOR: string;
17
- declare const ARG_PREFIX_AND_KEY_SEPARATOR: string;
18
- declare const ARG_NEGATABLE_PREFIX = "no-";
19
17
  type CommonArgType = {
20
18
  readonly help: {
21
19
  readonly type: 'boolean';
@@ -33,10 +31,17 @@ declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBC
33
31
  //#endregion
34
32
  //#region ../shared/src/types.d.ts
35
33
  type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K] };
34
+ /**
35
+ * Make all properties in T deeply writeable (not readonly)
36
+ */
37
+
36
38
  /**
37
39
  * Remove index signature from object or record type.
38
40
  */
39
41
  type RemovedIndex<T> = RemoveIndexSignature<{ [K in keyof T]: T[K] }>;
42
+ /**
43
+ * Resolve a key on {@link Args}.
44
+ */
40
45
  type KeyOfArgs<A extends Args$1> = keyof A | { [K in keyof A]: A[K]['type'] extends 'boolean' ? A[K]['negatable'] extends true ? `no-${Extract<K, string>}` : never : never }[keyof A];
41
46
  /**
42
47
  * Generate a namespaced key.
@@ -45,11 +50,11 @@ type GenerateNamespacedKey<Key extends string, Prefixed extends string = typeof
45
50
  /**
46
51
  * Command i18n built-in arguments keys.
47
52
  */
48
- type CommandBuiltinArgsKeys = keyof (typeof constants_d_exports)['COMMON_ARGS'];
53
+ type CommandBuiltinArgsKeys = keyof typeof COMMON_ARGS;
49
54
  /**
50
55
  * Command i18n built-in resource keys.
51
56
  */
52
- type CommandBuiltinResourceKeys = (typeof constants_d_exports)['COMMAND_BUILTIN_RESOURCE_KEYS'][number];
57
+ type CommandBuiltinResourceKeys = (typeof COMMAND_BUILTIN_RESOURCE_KEYS)[number];
53
58
  /**
54
59
  * Built-in resource keys.
55
60
  */
@@ -75,18 +80,33 @@ E extends Record<string, string> = {},
75
80
  R extends string = keyof RemovedIndex<E>, T extends string = (C extends {
76
81
  name: infer N;
77
82
  } ? N extends string ? GenerateNamespacedKey<R, N> : R : R | CommandBuiltinKeys), O = CommandArgKeys<A, C>> = CommandBuiltinKeys | O | T;
78
- /**
79
- * Translation function interface
80
- */
81
83
  //#endregion
82
84
  //#region src/types.d.ts
85
+ /**
86
+ * The unique identifier for usage renderer plugin.
87
+ */
88
+ declare const pluginId: GenerateNamespacedKey<'renderer', typeof PLUGIN_PREFIX>;
89
+ /**
90
+ * Type representing the unique identifier for usage renderer plugin.
91
+ */
92
+ type PluginId = typeof pluginId;
83
93
  /**
84
94
  * Extended command context which provides utilities via usage renderer plugin.
85
95
  * These utilities are available via `CommandContext.extensions['g:renderer']`.
96
+ *
97
+ * @typeParam G - A type extending {@link GunshiParams} to specify the shape of command parameters.
86
98
  */
87
- interface UsageRendererCommandContext<G extends GunshiParams<any> = DefaultGunshiParams> {
99
+ interface UsageRendererExtension<G extends GunshiParams<any> = DefaultGunshiParams> {
88
100
  /**
89
- * Render the text message
101
+ * Render the text message.
102
+ *
103
+ * @typeParam A - The type of {@linkcode Args | arguments} defined in the command parameters.
104
+ * @typeParam C - The type representing the command context.
105
+ * @typeParam E - The type representing extended resources for localization.
106
+ *
107
+ * @param key - The translation key to be resolved.
108
+ * @param values - An optional record of values to interpolate into the translation string.
109
+ * @returns The resolved translation string with interpolated values if provided.
90
110
  */
91
111
  text: <A extends Args = G['args'], C = {},
92
112
  // for CommandContext
@@ -95,7 +115,10 @@ interface UsageRendererCommandContext<G extends GunshiParams<any> = DefaultGunsh
95
115
  K = ResolveTranslationKeys<A, C, E>>(key: K, values?: Record<string, unknown>) => string;
96
116
  /**
97
117
  * Load commands
98
- * @returns A list of commands loaded from the usage renderert plugin.
118
+ *
119
+ * @typeParam G - A type extending {@link GunshiParams} to specify the shape of command parameters.
120
+ *
121
+ * @returns A list of commands loaded from the usage renderer plugin.
99
122
  */
100
123
  loadCommands: <G extends GunshiParams = DefaultGunshiParams>() => Promise<Command<G>[]>;
101
124
  }
@@ -103,7 +126,8 @@ interface UsageRendererCommandContext<G extends GunshiParams<any> = DefaultGunsh
103
126
  //#region src/header.d.ts
104
127
  /**
105
128
  * Render the header.
106
- * @param ctx A {@link CommandContext | command context}
129
+ *
130
+ * @param ctx - A {@link CommandContext | command context}
107
131
  * @returns A rendered header.
108
132
  */
109
133
  declare function renderHeader<G extends GunshiParams = DefaultGunshiParams>(ctx: Readonly<CommandContext<G>>): Promise<string>;
@@ -111,7 +135,8 @@ declare function renderHeader<G extends GunshiParams = DefaultGunshiParams>(ctx:
111
135
  //#region src/usage.d.ts
112
136
  /**
113
137
  * Render the usage.
114
- * @param ctx A {@link CommandContext | command context}
138
+ *
139
+ * @param ctx - A {@link CommandContext | command context}
115
140
  * @returns A rendered usage.
116
141
  */
117
142
  declare function renderUsage<G extends GunshiParams = DefaultGunshiParams>(ctx: Readonly<CommandContext<G>>): Promise<string>;
@@ -119,8 +144,9 @@ declare function renderUsage<G extends GunshiParams = DefaultGunshiParams>(ctx:
119
144
  //#region src/validation.d.ts
120
145
  /**
121
146
  * Render the validation errors.
122
- * @param ctx A {@link CommandContext | command context}
123
- * @param error An {@link AggregateError} of option in `args-token` validation
147
+ *
148
+ * @param _ctx - A {@link CommandContext | command context}
149
+ * @param error - An {@link AggregateError} of option in `args-token` validation
124
150
  * @returns A rendered validation error.
125
151
  */
126
152
  declare function renderValidationErrors<G extends GunshiParams = DefaultGunshiParams>(_ctx: CommandContext<G>, error: AggregateError): Promise<string>;
@@ -128,7 +154,9 @@ declare function renderValidationErrors<G extends GunshiParams = DefaultGunshiPa
128
154
  //#region src/index.d.ts
129
155
  /**
130
156
  * usage renderer plugin
157
+ *
158
+ * @returns A defined plugin as usage renderer
131
159
  */
132
- declare function renderer(): PluginWithExtension<UsageRendererCommandContext>;
160
+ declare function renderer(): PluginWithExtension<UsageRendererExtension>;
133
161
  //#endregion
134
- export { type UsageRendererCommandContext, renderer as default, renderHeader, renderUsage, renderValidationErrors };
162
+ export { PluginId, UsageRendererExtension, renderer as default, pluginId, renderHeader, renderUsage, renderValidationErrors };
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ANONYMOUS_COMMAND_NAME, plugin } from "@gunshi/plugin";
2
2
 
3
- //#region ../../node_modules/.pnpm/args-tokens@0.22.0/node_modules/args-tokens/lib/utils-N7UlhLbz.js
3
+ //#region ../../node_modules/.pnpm/args-tokens@0.23.0/node_modules/args-tokens/lib/utils-1LQrGCWG.js
4
4
  /**
5
5
  * Entry point of utils.
6
6
  *
@@ -12,15 +12,35 @@ import { ANONYMOUS_COMMAND_NAME, plugin } from "@gunshi/plugin";
12
12
  * @author kazuya kawaguchi (a.k.a. kazupon)
13
13
  * @license MIT
14
14
  */
15
+ /**
16
+ * Convert a string to kebab-case.
17
+ *
18
+ * @param str - A string to convert
19
+ * @returns Converted string into kebab-case.
20
+ */
15
21
  function kebabnize(str) {
16
22
  return str.replace(/[A-Z]/g, (match, offset) => (offset > 0 ? "-" : "") + match.toLowerCase());
17
23
  }
18
24
 
19
25
  //#endregion
20
26
  //#region ../gunshi/src/utils.ts
27
+ /**
28
+ * Check if the given command is a {@link LazyCommand}.
29
+ *
30
+ * @param cmd - A command to check
31
+ * @returns `true` if the command is a {@link LazyCommand}, otherwise `false
32
+ */
21
33
  function isLazyCommand(cmd) {
22
34
  return typeof cmd === "function" && "commandName" in cmd && !!cmd.commandName;
23
35
  }
36
+ /**
37
+ * Resolve a lazy command to a {@link Command}.
38
+ *
39
+ * @param cmd - A {@link Commandable} or {@link LazyCommand} to resolve
40
+ * @param name - Optional name of the command, if not provided, it will use the name from the command itself.
41
+ * @param needRunResolving - Whether to run the resolving function of the lazy command.
42
+ * @returns A resolved {@link Command}
43
+ */
24
44
  async function resolveLazyCommand(cmd, name, needRunResolving = false) {
25
45
  let command;
26
46
  if (isLazyCommand(cmd)) {
@@ -53,9 +73,22 @@ async function resolveLazyCommand(cmd, name, needRunResolving = false) {
53
73
  if (command.name == null && name) command.name = name;
54
74
  return deepFreeze(command);
55
75
  }
76
+ /**
77
+ * Create an object with the specified prototype. A shorthand for `Object.create`.
78
+ *
79
+ * @param obj - An object to use as the prototype for the new object. If `null`, it will create an object with no prototype.
80
+ * @returns A new object with the specified prototype
81
+ */
56
82
  function create(obj = null) {
57
83
  return Object.create(obj);
58
84
  }
85
+ /**
86
+ * Deep freeze an object, making it immutable.
87
+ *
88
+ * @param obj - The object to freeze
89
+ * @param ignores - Properties to ignore during freezing
90
+ * @returns A frozen object
91
+ */
59
92
  function deepFreeze(obj, ignores = []) {
60
93
  if (obj === null || typeof obj !== "object") return obj;
61
94
  for (const key of Object.keys(obj)) {
@@ -127,8 +160,12 @@ var en_US_default = {
127
160
  //#region ../shared/src/utils.ts
128
161
  /**
129
162
  * Resolve a namespaced key for built-in resources.
163
+ *
130
164
  * Built-in keys are prefixed with "_:".
131
- * @param key The built-in key to resolve.
165
+ *
166
+ * @typeParam K - The type of the built-in key to resolve. Defaults to command built-in argument and resource keys.
167
+ *
168
+ * @param key - The built-in key to resolve.
132
169
  * @returns Prefixed built-in key.
133
170
  */
134
171
  function resolveBuiltInKey(key) {
@@ -136,34 +173,66 @@ function resolveBuiltInKey(key) {
136
173
  }
137
174
  /**
138
175
  * Resolve a namespaced key for argument resources.
176
+ *
139
177
  * Argument keys are prefixed with "arg:".
140
178
  * If the command name is provided, it will be prefixed with the command name (e.g. "cmd1:arg:foo").
141
- * @param key The argument key to resolve.
142
- * @param ctx The command context.
179
+ *
180
+ * @typeParam A - The {@linkcode Args} type extracted from G
181
+ *
182
+ * @param key - The argument key to resolve.
183
+ * @param name - The command name.
143
184
  * @returns Prefixed argument key.
144
185
  */
145
- function resolveArgKey(key, ctx) {
146
- return `${ctx?.name ? `${ctx.name}${BUILT_IN_KEY_SEPARATOR}` : ""}${ARG_PREFIX}${BUILT_IN_KEY_SEPARATOR}${key}`;
186
+ function resolveArgKey(key, name) {
187
+ return `${name ? `${name}${BUILT_IN_KEY_SEPARATOR}` : ""}${ARG_PREFIX}${BUILT_IN_KEY_SEPARATOR}${key}`;
147
188
  }
148
189
  /**
149
190
  * Resolve a namespaced key for non-built-in resources.
191
+ *
150
192
  * Non-built-in keys are not prefixed with any special characters. If the command name is provided, it will be prefixed with the command name (e.g. "cmd1:foo").
151
- * @param key The non-built-in key to resolve.
152
- * @param ctx The command context.
193
+ *
194
+ * @typeParam T - The type of the non-built-in key to resolve. Defaults to string.
195
+ *
196
+ * @param key - The non-built-in key to resolve.
197
+ * @param name - The command name.
153
198
  * @returns Prefixed non-built-in key.
154
199
  */
155
- function resolveKey(key, ctx) {
156
- return `${ctx?.name ? `${ctx.name}${BUILT_IN_KEY_SEPARATOR}` : ""}${key}`;
200
+ function resolveKey(key, name) {
201
+ return `${name ? `${name}${BUILT_IN_KEY_SEPARATOR}` : ""}${key}`;
157
202
  }
158
- async function resolveExamples$1(ctx, examples) {
203
+ /**
204
+ * Resolve command examples.
205
+ *
206
+ * @typeParam G - Type parameter extending {@linkcode GunshiParams}
207
+ *
208
+ * @param ctx - A {@linkcode CommandContext | command context}.
209
+ * @param examples - The examples to resolve, which can be a string or a {@linkcode CommandExamplesFetcher | function} that returns a string.
210
+ * @returns A resolved string of examples.
211
+ */
212
+ async function resolveExamples(ctx, examples) {
159
213
  return typeof examples === "string" ? examples : typeof examples === "function" ? await examples(ctx) : "";
160
214
  }
215
+ /**
216
+ * Generate a namespaced key for a plugin.
217
+ *
218
+ * @typeParam K - The type of the plugin id to generate a namespaced key for.
219
+ *
220
+ * @param id - A plugin id to generate a namespaced key.
221
+ * @returns A namespaced key for the plugin.
222
+ */
161
223
  function namespacedId(id) {
162
224
  return `${PLUGIN_PREFIX}${BUILT_IN_KEY_SEPARATOR}${id}`;
163
225
  }
226
+ /**
227
+ * Generate a short and long option pair for command arguments.
228
+ *
229
+ * @param schema - The {@linkcode ArgSchema | argument schema} to generate the option pair.
230
+ * @param name - The name of the argument.
231
+ * @param toKebab - Whether to convert the name to kebab-case for display in help text.
232
+ * @returns A string representing the short and long option pair.
233
+ */
164
234
  function makeShortLongOptionPair(schema, name, toKebab) {
165
- const displayName = toKebab || schema.toKebab ? kebabnize(name) : name;
166
- let key = `--${displayName}`;
235
+ let key = `--${toKebab || schema.toKebab ? kebabnize(name) : name}`;
167
236
  if (schema.short) key = `-${schema.short}, ${key}`;
168
237
  return key;
169
238
  }
@@ -172,20 +241,23 @@ function makeShortLongOptionPair(schema, name, toKebab) {
172
241
  //#region ../shared/src/localization.ts
173
242
  /**
174
243
  * Create a localizable function for a command.
244
+ *
175
245
  * This function will resolve the translation key based on the command context and the provided translation function.
176
- * @param ctx Command context
177
- * @param cmd Command
178
- * @param translate Translation function
246
+ *
247
+ * @typeParam A - The {@linkcode Args} type extracted from Gunshi command.
248
+ * @typeParam C - Additional context type for command localization.
249
+ * @typeParam E - Extended resource keys type.
250
+ *
251
+ * @param ctx - Command context
252
+ * @param cmd - Command
253
+ * @param translate - Translation function
179
254
  * @returns Localizable function
180
255
  */
181
256
  function localizable(ctx, cmd, translate) {
182
257
  async function localize(key, values) {
183
258
  if (translate) return translate(key, values);
184
- if (key.startsWith(BUILD_IN_PREFIX_AND_KEY_SEPARATOR)) {
185
- const resKey = key.slice(BUILD_IN_PREFIX_AND_KEY_SEPARATOR.length);
186
- return en_US_default[resKey] || key;
187
- }
188
- const namaspacedArgKey = resolveKey(ARG_PREFIX_AND_KEY_SEPARATOR, ctx);
259
+ if (key.startsWith(BUILD_IN_PREFIX_AND_KEY_SEPARATOR)) return en_US_default[key.slice(BUILD_IN_PREFIX_AND_KEY_SEPARATOR.length)] || key;
260
+ const namaspacedArgKey = resolveKey(ARG_PREFIX_AND_KEY_SEPARATOR, ctx.name);
189
261
  if (key.startsWith(namaspacedArgKey)) {
190
262
  let argKey = key.slice(namaspacedArgKey.length);
191
263
  let negatable = false;
@@ -197,8 +269,8 @@ function localizable(ctx, cmd, translate) {
197
269
  if (!schema) return argKey;
198
270
  return negatable && schema.type === "boolean" && schema.negatable ? `${en_US_default["NEGATABLE"]} ${makeShortLongOptionPair(schema, argKey, ctx.toKebab)}` : schema.description || "";
199
271
  }
200
- if (key === resolveKey("description", ctx)) return "";
201
- else if (key === resolveKey("examples", ctx)) return await resolveExamples$1(ctx, cmd.examples);
272
+ if (key === resolveKey("description", ctx.name)) return "";
273
+ else if (key === resolveKey("examples", ctx.name)) return await resolveExamples(ctx, cmd.examples);
202
274
  else return key;
203
275
  }
204
276
  return localize;
@@ -208,7 +280,8 @@ function localizable(ctx, cmd, translate) {
208
280
  //#region src/header.ts
209
281
  /**
210
282
  * Render the header.
211
- * @param ctx A {@link CommandContext | command context}
283
+ *
284
+ * @param ctx - A {@link CommandContext | command context}
212
285
  * @returns A rendered header.
213
286
  */
214
287
  function renderHeader(ctx) {
@@ -228,7 +301,8 @@ const pluginId = namespacedId("renderer");
228
301
  const COMMON_ARGS_KEYS = Object.keys(COMMON_ARGS);
229
302
  /**
230
303
  * Render the usage.
231
- * @param ctx A {@link CommandContext | command context}
304
+ *
305
+ * @param ctx - A {@link CommandContext | command context}
232
306
  * @returns A rendered usage.
233
307
  */
234
308
  async function renderUsage(ctx) {
@@ -247,7 +321,8 @@ async function renderUsage(ctx) {
247
321
  }
248
322
  /**
249
323
  * Render the positional arguments section
250
- * @param ctx A {@link CommandContext | command context}
324
+ *
325
+ * @param ctx - A {@link CommandContext | command context}
251
326
  * @returns A rendered arguments section
252
327
  */
253
328
  async function renderPositionalArgsSection(ctx) {
@@ -258,7 +333,8 @@ async function renderPositionalArgsSection(ctx) {
258
333
  }
259
334
  /**
260
335
  * Render the optional arguments section
261
- * @param ctx A {@link CommandContext | command context}
336
+ *
337
+ * @param ctx - A {@link CommandContext | command context}
262
338
  * @returns A rendered options section
263
339
  */
264
340
  async function renderOptionalArgsSection(ctx) {
@@ -269,12 +345,13 @@ async function renderOptionalArgsSection(ctx) {
269
345
  }
270
346
  /**
271
347
  * Render the examples section
272
- * @param ctx A {@link CommandContext | command context}
348
+ *
349
+ * @param ctx - A {@link CommandContext | command context}
273
350
  * @returns A rendered examples section
274
351
  */
275
352
  async function renderExamplesSection(ctx) {
276
353
  const messages = [];
277
- const resolvedExamples = await resolveExamples(ctx);
354
+ const resolvedExamples = await resolveExamples$1(ctx);
278
355
  if (resolvedExamples) {
279
356
  const examples = resolvedExamples.split("\n").map((example) => example.padStart(ctx.env.leftMargin + example.length));
280
357
  messages.push(`${await ctx.extensions[pluginId].text(resolveBuiltInKey("EXAMPLES"))}:`, ...examples);
@@ -283,7 +360,8 @@ async function renderExamplesSection(ctx) {
283
360
  }
284
361
  /**
285
362
  * Render the usage section
286
- * @param ctx A {@link CommandContext | command context}
363
+ *
364
+ * @param ctx - A {@link CommandContext | command context}
287
365
  * @returns A rendered usage section
288
366
  */
289
367
  async function renderUsageSection(ctx) {
@@ -305,7 +383,8 @@ async function makeUsageSymbols(ctx) {
305
383
  }
306
384
  /**
307
385
  * Render the commands section
308
- * @param ctx A {@link CommandContext | command context}
386
+ *
387
+ * @param ctx - A {@link CommandContext | command context}
309
388
  * @returns A rendered commands section
310
389
  */
311
390
  async function renderCommandsSection(ctx) {
@@ -346,7 +425,8 @@ async function makeCommandSymbol(ctx, cmd) {
346
425
  }
347
426
  /**
348
427
  * Resolve the entry command name
349
- * @param ctx A {@link CommandContext | command context}
428
+ *
429
+ * @param ctx - A {@link CommandContext | command context}
350
430
  * @returns The entry command name
351
431
  */
352
432
  async function resolveEntry(ctx) {
@@ -354,7 +434,8 @@ async function resolveEntry(ctx) {
354
434
  }
355
435
  /**
356
436
  * Resolve the sub command name
357
- * @param ctx A {@link CommandContext | command context}
437
+ *
438
+ * @param ctx - A {@link CommandContext | command context}
358
439
  * @returns The sub command name
359
440
  */
360
441
  async function resolveSubCommand(ctx) {
@@ -362,35 +443,38 @@ async function resolveSubCommand(ctx) {
362
443
  }
363
444
  /**
364
445
  * Resolve the command description
365
- * @param ctx A {@link CommandContext | command context}
446
+ *
447
+ * @param ctx - A {@link CommandContext | command context}
366
448
  * @returns resolved command description
367
449
  */
368
450
  async function resolveDescription(ctx) {
369
- return await ctx.extensions[pluginId].text(resolveKey("description", ctx)) || ctx.description || "";
451
+ return await ctx.extensions[pluginId].text(resolveKey("description", ctx.name)) || ctx.description || "";
370
452
  }
371
453
  /**
372
454
  * Resolve the command examples
373
- * @param ctx A {@link CommandContext | command context}
455
+ *
456
+ * @param ctx - A {@link CommandContext | command context}
374
457
  * @returns resolved command examples, if not resolved, return empty string
375
458
  */
376
- async function resolveExamples(ctx) {
377
- const ret = await ctx.extensions[pluginId].text(resolveKey("examples", ctx));
459
+ async function resolveExamples$1(ctx) {
460
+ const ret = await ctx.extensions[pluginId].text(resolveKey("examples", ctx.name));
378
461
  if (ret) return ret;
379
462
  const command = ctx.env.subCommands?.get(ctx.name || "");
380
- return await resolveExamples$1(ctx, command?.examples);
463
+ return await resolveExamples(ctx, command?.examples);
381
464
  }
382
465
  /**
383
466
  * Check if the command has sub commands
384
- * @param ctx A {@link CommandContext | command context}
467
+ *
468
+ * @param ctx - A {@link CommandContext | command context}
385
469
  * @returns True if the command has sub commands
386
470
  */
387
471
  async function hasCommands(ctx) {
388
- const loadedCommands = await ctx.extensions?.[pluginId].loadCommands() || [];
389
- return loadedCommands.length > 1;
472
+ return (await ctx.extensions?.[pluginId].loadCommands() || []).length > 1;
390
473
  }
391
474
  /**
392
475
  * Check if the command has optional arguments
393
- * @param args A {@link Args | command optional arguments}
476
+ *
477
+ * @param args - A {@link Args | command optional arguments}
394
478
  * @returns True if the command has options
395
479
  */
396
480
  function hasOptionalArgs(args) {
@@ -398,7 +482,8 @@ function hasOptionalArgs(args) {
398
482
  }
399
483
  /**
400
484
  * Check if the command has positional arguments
401
- * @param args A {@link Args | command positional arguments}
485
+ *
486
+ * @param args - A {@link Args | command positional arguments}
402
487
  * @returns True if the command has options
403
488
  */
404
489
  function hasPositionalArgs(args) {
@@ -406,7 +491,8 @@ function hasPositionalArgs(args) {
406
491
  }
407
492
  /**
408
493
  * Check if all options have default values
409
- * @param args An {@link Args | command argument}
494
+ *
495
+ * @param args - An {@link Args | command argument}
410
496
  * @returns True if all options have default values
411
497
  */
412
498
  function hasAllDefaultOptions(args) {
@@ -414,7 +500,9 @@ function hasAllDefaultOptions(args) {
414
500
  }
415
501
  /**
416
502
  * Generate options symbols for usage
417
- * @param ctx A {@link CommandContext | command context}
503
+ *
504
+ * @param ctx - A {@link CommandContext | command context}
505
+ * @param args - {@link Args | command arguments}
418
506
  * @returns Options symbols for usage
419
507
  */
420
508
  async function generateOptionsSymbols(ctx, args) {
@@ -422,7 +510,8 @@ async function generateOptionsSymbols(ctx, args) {
422
510
  }
423
511
  /**
424
512
  * Get optional arguments pairs for usage
425
- * @param ctx A {@link CommandContext | command context}
513
+ *
514
+ * @param ctx - A {@link CommandContext | command context}
426
515
  * @returns Options pairs for usage
427
516
  */
428
517
  function getOptionalArgsPairs(ctx) {
@@ -453,7 +542,7 @@ async function resolveDisplayValue(ctx, key) {
453
542
  const schema = ctx.args[key];
454
543
  if ((schema.type === "boolean" || schema.type === "number" || schema.type === "string" || schema.type === "custom") && schema.default !== void 0) return `(${await generateDefaultDisplayValue(ctx, schema)})`;
455
544
  if (schema.type === "enum") {
456
- const _default = schema.default !== void 0 ? await generateDefaultDisplayValue(ctx, schema) : "";
545
+ const _default = schema.default === void 0 ? "" : await generateDefaultDisplayValue(ctx, schema);
457
546
  const choices = `${await ctx.extensions[pluginId].text(resolveBuiltInKey("CHOICES"))}: ${schema.choices.join(" | ")}`;
458
547
  return `(${_default ? `${_default}, ${choices}` : choices})`;
459
548
  }
@@ -461,15 +550,16 @@ async function resolveDisplayValue(ctx, key) {
461
550
  }
462
551
  /**
463
552
  * Generate optional arguments usage
464
- * @param ctx A {@link CommandContext | command context}
465
- * @param optionsPairs Options pairs for usage
553
+ *
554
+ * @param ctx - A {@link CommandContext | command context}
555
+ * @param optionsPairs - Options pairs for usage
466
556
  * @returns Generated options usage
467
557
  */
468
558
  async function generateOptionalArgsUsage(ctx, optionsPairs) {
469
559
  const optionsMaxLength = Math.max(...Object.entries(optionsPairs).map(([_, value]) => value.length));
470
560
  const optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...Object.entries(optionsPairs).map(([key]) => resolveNegatableType(key, ctx).length)) : 0;
471
- const usages = await Promise.all(Object.entries(optionsPairs).map(async ([key, value]) => {
472
- let rawDesc = await ctx.extensions[pluginId].text(resolveArgKey(key, ctx));
561
+ return (await Promise.all(Object.entries(optionsPairs).map(async ([key, value]) => {
562
+ let rawDesc = await ctx.extensions[pluginId].text(resolveArgKey(key, ctx.name));
473
563
  if (!rawDesc && key.startsWith(ARG_NEGATABLE_PREFIX)) {
474
564
  const name = resolveNegatableKey(key);
475
565
  const schema = ctx.args[name];
@@ -482,8 +572,7 @@ async function generateOptionalArgsUsage(ctx, optionsPairs) {
482
572
  const descLength = desc.length + valueDesc.length;
483
573
  const option = `${value.padEnd((descLength > 0 ? optionsMaxLength : 0) + ctx.env.middleMargin)}${desc}${valueDesc ? ` ${valueDesc}` : ""}`;
484
574
  return `${option.padStart(ctx.env.leftMargin + option.length)}`;
485
- }));
486
- return usages.join("\n");
575
+ }))).join("\n");
487
576
  }
488
577
  function getPositionalArgs(args) {
489
578
  return Object.entries(args).filter(([_, schema]) => schema.type === "positional");
@@ -491,12 +580,11 @@ function getPositionalArgs(args) {
491
580
  async function generatePositionalArgsUsage(ctx) {
492
581
  const positionals = getPositionalArgs(ctx.args);
493
582
  const argsMaxLength = Math.max(...positionals.map(([name]) => name.length));
494
- const usages = await Promise.all(positionals.map(async ([name]) => {
495
- const desc = await ctx.extensions[pluginId].text(resolveArgKey(name, ctx)) || ctx.args[name].description || "";
583
+ return (await Promise.all(positionals.map(async ([name]) => {
584
+ const desc = await ctx.extensions[pluginId].text(resolveArgKey(name, ctx.name)) || ctx.args[name].description || "";
496
585
  const arg = `${name.padEnd(argsMaxLength + ctx.env.middleMargin)} ${desc}`;
497
586
  return `${arg.padStart(ctx.env.leftMargin + arg.length)}`;
498
- }));
499
- return usages.join("\n");
587
+ }))).join("\n");
500
588
  }
501
589
  function generatePositionalSymbols(args) {
502
590
  return hasPositionalArgs(args) ? getPositionalArgs(args).map(([name]) => `<${name}>`).join(" ") : "";
@@ -506,8 +594,9 @@ function generatePositionalSymbols(args) {
506
594
  //#region src/validation.ts
507
595
  /**
508
596
  * Render the validation errors.
509
- * @param ctx A {@link CommandContext | command context}
510
- * @param error An {@link AggregateError} of option in `args-token` validation
597
+ *
598
+ * @param _ctx - A {@link CommandContext | command context}
599
+ * @param error - An {@link AggregateError} of option in `args-token` validation
511
600
  * @returns A rendered validation error.
512
601
  */
513
602
  function renderValidationErrors(_ctx, error) {
@@ -519,25 +608,27 @@ function renderValidationErrors(_ctx, error) {
519
608
  //#endregion
520
609
  //#region src/index.ts
521
610
  const i18nPluginId = namespacedId("i18n");
611
+ const dependencies = [{
612
+ id: i18nPluginId,
613
+ optional: true
614
+ }];
522
615
  /**
523
616
  * usage renderer plugin
617
+ *
618
+ * @returns A defined plugin as usage renderer
524
619
  */
525
620
  function renderer() {
526
621
  return plugin({
527
622
  id: pluginId,
528
623
  name: "usage renderer",
529
- dependencies: [{
530
- id: i18nPluginId,
531
- optional: true
532
- }],
533
- extension: (ctx, cmd) => {
534
- const { extensions: { [i18nPluginId]: i18n } } = ctx;
624
+ dependencies,
625
+ extension: async (ctx, cmd) => {
626
+ const i18n = ctx.extensions[i18nPluginId];
535
627
  let cachedCommands;
536
628
  async function loadCommands() {
537
629
  if (cachedCommands) return cachedCommands;
538
630
  const subCommands = [...ctx.env.subCommands || []];
539
- const allCommands = await Promise.all(subCommands.map(async ([name, cmd$1]) => await resolveLazyCommand(cmd$1, name)));
540
- cachedCommands = allCommands.filter((cmd$1) => !cmd$1.internal).filter(Boolean);
631
+ cachedCommands = (await Promise.all(subCommands.map(async ([name, cmd$1]) => await resolveLazyCommand(cmd$1, name)))).filter((cmd$1) => !cmd$1.internal).filter(Boolean);
541
632
  cachedCommands.sort((a, b) => {
542
633
  if (a.entry && !b.entry) return -1;
543
634
  if (!a.entry && b.entry) return 1;
@@ -562,4 +653,4 @@ function renderer() {
562
653
  }
563
654
 
564
655
  //#endregion
565
- export { renderer as default, renderHeader, renderUsage, renderValidationErrors };
656
+ export { renderer as default, pluginId, renderHeader, renderUsage, renderValidationErrors };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/plugin-renderer",
3
3
  "description": "usage renderer plugin for gunshi",
4
- "version": "0.27.0-alpha.9",
4
+ "version": "0.27.0-beta.0",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -53,20 +53,20 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@gunshi/plugin": "0.27.0-alpha.9"
56
+ "@gunshi/plugin": "0.27.0-beta.0"
57
57
  },
58
58
  "peerDependencies": {
59
- "@gunshi/plugin-i18n": "0.27.0-alpha.9"
59
+ "@gunshi/plugin-i18n": "0.27.0-beta.0"
60
60
  },
61
61
  "devDependencies": {
62
- "deno": "^2.4.2",
62
+ "deno": "^2.5.4",
63
63
  "jsr": "^0.13.5",
64
64
  "jsr-exports-lint": "^0.4.1",
65
- "publint": "^0.3.12",
66
- "tsdown": "^0.13.0",
67
- "typedoc": "^0.28.7",
68
- "typedoc-plugin-markdown": "^4.7.1",
69
- "@gunshi/shared": "0.27.0-alpha.9"
65
+ "publint": "^0.3.14",
66
+ "tsdown": "^0.15.6",
67
+ "typedoc": "^0.28.13",
68
+ "typedoc-plugin-markdown": "^4.9.0",
69
+ "@gunshi/shared": "0.27.0-beta.0"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsdown",