compmark-vue 0.2.3 → 0.2.5
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 +259 -28
- package/dist/cli.mjs +8 -5
- package/dist/index.mjs +8 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,25 +17,64 @@ npx compmark-vue ./src/components/Button.vue
|
|
|
17
17
|
|
|
18
18
|
This parses the component and creates `Button.md` in your current directory.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## Features
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
- [Props](#props) — runtime and TypeScript generic syntax
|
|
23
|
+
- [Emits](#emits) — array, TypeScript property, and call signature syntax
|
|
24
|
+
- [Slots](#slots) — `defineSlots` with typed bindings, template `<slot>` fallback
|
|
25
|
+
- [Expose](#expose) — `defineExpose` with JSDoc descriptions
|
|
26
|
+
- [Composables](#composables) — auto-detects `useX()` calls in `<script setup>`
|
|
27
|
+
- [JSDoc tags](#jsdoc-tags) — `@deprecated`, `@since`, `@example`, `@see`, `@default`
|
|
28
|
+
- [`@internal`](#internal-components) — exclude components from output
|
|
29
|
+
- [Options API](#options-api) — `export default { props, emits }` support
|
|
30
|
+
- Empty sections are skipped cleanly — no placeholder noise
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Props
|
|
35
|
+
|
|
36
|
+
Runtime syntax, TypeScript generics, and `withDefaults` are all supported:
|
|
23
37
|
|
|
24
38
|
```vue
|
|
25
|
-
<script setup>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
const props = withDefaults(
|
|
41
|
+
defineProps<{
|
|
42
|
+
/** The label text */
|
|
43
|
+
label: string;
|
|
44
|
+
/** Visual theme */
|
|
45
|
+
theme?: "filled" | "outline";
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
}>(),
|
|
48
|
+
{
|
|
49
|
+
theme: "filled",
|
|
50
|
+
disabled: false,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
31
55
|
|
|
32
|
-
|
|
56
|
+
Output:
|
|
57
|
+
|
|
58
|
+
```md
|
|
59
|
+
## Props
|
|
60
|
+
|
|
61
|
+
| Name | Type | Required | Default | Description |
|
|
62
|
+
| -------- | --------------------- | -------- | ---------- | -------------- |
|
|
63
|
+
| label | string | Yes | - | The label text |
|
|
64
|
+
| theme | 'filled' \| 'outline' | No | `"filled"` | Visual theme |
|
|
65
|
+
| disabled | boolean | No | `false` | - |
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Runtime object syntax is also supported:
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<script setup>
|
|
72
|
+
defineProps({
|
|
33
73
|
/** Title of the dialog */
|
|
34
74
|
title: {
|
|
35
75
|
type: String,
|
|
36
76
|
required: true,
|
|
37
77
|
},
|
|
38
|
-
/** Whether the dialog is visible */
|
|
39
78
|
visible: {
|
|
40
79
|
type: Boolean,
|
|
41
80
|
default: false,
|
|
@@ -44,24 +83,224 @@ const props = defineProps({
|
|
|
44
83
|
</script>
|
|
45
84
|
```
|
|
46
85
|
|
|
47
|
-
|
|
86
|
+
### Emits
|
|
87
|
+
|
|
88
|
+
TypeScript generic syntax with payloads:
|
|
89
|
+
|
|
90
|
+
```vue
|
|
91
|
+
<script setup lang="ts">
|
|
92
|
+
const emit = defineEmits<{
|
|
93
|
+
/** Emitted on save */
|
|
94
|
+
save: [data: Record<string, unknown>];
|
|
95
|
+
/** Emitted on cancel */
|
|
96
|
+
cancel: [];
|
|
97
|
+
}>();
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Output:
|
|
102
|
+
|
|
103
|
+
```md
|
|
104
|
+
## Emits
|
|
105
|
+
|
|
106
|
+
| Name | Payload | Description |
|
|
107
|
+
| ------ | ----------------------------- | ----------------- |
|
|
108
|
+
| save | data: Record<string, unknown> | Emitted on save |
|
|
109
|
+
| cancel | - | Emitted on cancel |
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Call signature syntax is also supported:
|
|
113
|
+
|
|
114
|
+
```vue
|
|
115
|
+
<script setup lang="ts">
|
|
116
|
+
defineEmits<{
|
|
117
|
+
(e: "click", payload: MouseEvent): void;
|
|
118
|
+
(e: "submit"): void;
|
|
119
|
+
}>();
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Array syntax works too: `defineEmits(["click", "submit"])`.
|
|
124
|
+
|
|
125
|
+
### Slots
|
|
126
|
+
|
|
127
|
+
`defineSlots` provides typed bindings:
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
defineSlots<{
|
|
132
|
+
/** Main content */
|
|
133
|
+
default(props: { msg: string }): any;
|
|
134
|
+
/** Header area */
|
|
135
|
+
header(props: { title: string; count: number }): any;
|
|
136
|
+
}>();
|
|
137
|
+
</script>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Output:
|
|
48
141
|
|
|
49
142
|
```md
|
|
50
|
-
|
|
143
|
+
## Slots
|
|
144
|
+
|
|
145
|
+
| Name | Bindings | Description |
|
|
146
|
+
| ------- | ---------------------------- | ------------ |
|
|
147
|
+
| default | msg: string | Main content |
|
|
148
|
+
| header | title: string, count: number | Header area |
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
If `defineSlots` is not used, slots are extracted from template `<slot>` elements as a fallback:
|
|
152
|
+
|
|
153
|
+
```vue
|
|
154
|
+
<template>
|
|
155
|
+
<div>
|
|
156
|
+
<slot />
|
|
157
|
+
<slot name="header" :title="title" />
|
|
158
|
+
<slot name="footer" />
|
|
159
|
+
</div>
|
|
160
|
+
</template>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Expose
|
|
164
|
+
|
|
165
|
+
```vue
|
|
166
|
+
<script setup lang="ts">
|
|
167
|
+
defineExpose({
|
|
168
|
+
/** Focus the component */
|
|
169
|
+
focus,
|
|
170
|
+
/** Reset the component state */
|
|
171
|
+
reset,
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
```
|
|
51
175
|
|
|
176
|
+
Output:
|
|
177
|
+
|
|
178
|
+
```md
|
|
179
|
+
## Exposed
|
|
180
|
+
|
|
181
|
+
| Name | Type | Description |
|
|
182
|
+
| ----- | ------- | ------------------------- |
|
|
183
|
+
| focus | unknown | Focus the component |
|
|
184
|
+
| reset | unknown | Reset the component state |
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Composables
|
|
188
|
+
|
|
189
|
+
Any `useX()` calls in `<script setup>` are automatically detected:
|
|
190
|
+
|
|
191
|
+
```vue
|
|
192
|
+
<script setup lang="ts">
|
|
193
|
+
import { useRouter } from "vue-router";
|
|
194
|
+
import { useMouse } from "@vueuse/core";
|
|
195
|
+
|
|
196
|
+
const router = useRouter();
|
|
197
|
+
const { x, y } = useMouse();
|
|
198
|
+
</script>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Output:
|
|
202
|
+
|
|
203
|
+
```md
|
|
204
|
+
## Composables Used
|
|
205
|
+
|
|
206
|
+
- `useRouter`
|
|
207
|
+
- `useMouse`
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### JSDoc Tags
|
|
211
|
+
|
|
212
|
+
Props support `@deprecated`, `@since`, `@example`, and `@see`:
|
|
213
|
+
|
|
214
|
+
```vue
|
|
215
|
+
<script setup lang="ts">
|
|
216
|
+
defineProps<{
|
|
217
|
+
/**
|
|
218
|
+
* The label text
|
|
219
|
+
* @deprecated Use `text` instead
|
|
220
|
+
* @since 1.0.0
|
|
221
|
+
* @example "Hello World"
|
|
222
|
+
* @see https://example.com/docs
|
|
223
|
+
*/
|
|
224
|
+
label: string;
|
|
225
|
+
}>();
|
|
226
|
+
</script>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Output:
|
|
230
|
+
|
|
231
|
+
````md
|
|
52
232
|
## Props
|
|
53
233
|
|
|
54
|
-
| Name
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
234
|
+
| Name | Type | Required | Default | Description |
|
|
235
|
+
| ----- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------- |
|
|
236
|
+
| label | string | Yes | - | The label text **Deprecated**: Use `text` instead _(since 1.0.0)_ See: https://example.com/docs |
|
|
237
|
+
|
|
238
|
+
**`label` example:**
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
"Hello World"
|
|
242
|
+
```
|
|
243
|
+
````
|
|
244
|
+
|
|
245
|
+
### Internal Components
|
|
246
|
+
|
|
247
|
+
Mark a component with `@internal` to skip it during generation:
|
|
248
|
+
|
|
249
|
+
```vue
|
|
250
|
+
<script setup lang="ts">
|
|
251
|
+
/**
|
|
252
|
+
* @internal
|
|
253
|
+
*/
|
|
254
|
+
defineProps<{
|
|
255
|
+
value: string;
|
|
256
|
+
}>();
|
|
257
|
+
</script>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
$ compmark InternalHelper.vue
|
|
262
|
+
Skipped InternalHelper.vue (marked @internal)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Options API
|
|
266
|
+
|
|
267
|
+
Components using `export default {}` are supported:
|
|
268
|
+
|
|
269
|
+
```vue
|
|
270
|
+
<script>
|
|
271
|
+
export default {
|
|
272
|
+
props: {
|
|
273
|
+
/** The title text */
|
|
274
|
+
title: {
|
|
275
|
+
type: String,
|
|
276
|
+
required: true,
|
|
277
|
+
},
|
|
278
|
+
count: {
|
|
279
|
+
type: Number,
|
|
280
|
+
default: 10,
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
emits: ["click", "update"],
|
|
284
|
+
};
|
|
285
|
+
</script>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Output:
|
|
289
|
+
|
|
290
|
+
```md
|
|
291
|
+
## Props
|
|
292
|
+
|
|
293
|
+
| Name | Type | Required | Default | Description |
|
|
294
|
+
| ----- | ------ | -------- | ------- | -------------- |
|
|
295
|
+
| title | String | Yes | - | The title text |
|
|
296
|
+
| count | Number | No | `10` | - |
|
|
58
297
|
|
|
59
298
|
## Emits
|
|
60
299
|
|
|
61
|
-
| Name | Description
|
|
62
|
-
| ------ |
|
|
63
|
-
|
|
|
64
|
-
|
|
|
300
|
+
| Name | Description |
|
|
301
|
+
| ------ | ----------- |
|
|
302
|
+
| click | - |
|
|
303
|
+
| update | - |
|
|
65
304
|
```
|
|
66
305
|
|
|
67
306
|
## Programmatic API
|
|
@@ -86,14 +325,6 @@ const doc = parseSFC(source, "Button.vue");
|
|
|
86
325
|
const md = generateMarkdown(doc);
|
|
87
326
|
```
|
|
88
327
|
|
|
89
|
-
## Supported Syntax
|
|
90
|
-
|
|
91
|
-
- `defineProps({ ... })` — shorthand (`String`), array type (`[String, Number]`), and full object syntax
|
|
92
|
-
- `defineEmits([...])` — array syntax
|
|
93
|
-
- JSDoc comments on props and emits (`/** ... */`)
|
|
94
|
-
- `const props = defineProps(...)` variable assignment pattern
|
|
95
|
-
- Default value extraction (string, number, boolean literals, arrow functions)
|
|
96
|
-
|
|
97
328
|
## Development
|
|
98
329
|
|
|
99
330
|
<details>
|
package/dist/cli.mjs
CHANGED
|
@@ -445,6 +445,9 @@ function stringifyDefault(node, source) {
|
|
|
445
445
|
}
|
|
446
446
|
//#endregion
|
|
447
447
|
//#region src/markdown.ts
|
|
448
|
+
function esc(value) {
|
|
449
|
+
return value.replaceAll("|", "\\|");
|
|
450
|
+
}
|
|
448
451
|
function generateMarkdown(doc) {
|
|
449
452
|
const sections = [`# ${doc.name}`];
|
|
450
453
|
if (doc.description) sections.push("", doc.description);
|
|
@@ -469,7 +472,7 @@ function generateMarkdown(doc) {
|
|
|
469
472
|
if (p.since) desc += ` *(since ${p.since})*`;
|
|
470
473
|
if (p.see) desc += ` See: ${p.see}`;
|
|
471
474
|
const req = p.required ? "Yes" : "No";
|
|
472
|
-
sections.push(`| ${p.name} | ${p.type} | ${req} | ${def} | ${desc} |`);
|
|
475
|
+
sections.push(`| ${esc(p.name)} | ${esc(p.type)} | ${req} | ${esc(def)} | ${esc(desc)} |`);
|
|
473
476
|
if (p.example) examples.push({
|
|
474
477
|
name: p.name,
|
|
475
478
|
example: p.example
|
|
@@ -484,7 +487,7 @@ function generateMarkdown(doc) {
|
|
|
484
487
|
for (const e of doc.emits) {
|
|
485
488
|
const desc = e.description || "-";
|
|
486
489
|
const payload = e.payload || "-";
|
|
487
|
-
sections.push(`| ${e.name} | ${payload} | ${desc} |`);
|
|
490
|
+
sections.push(`| ${esc(e.name)} | ${esc(payload)} | ${esc(desc)} |`);
|
|
488
491
|
}
|
|
489
492
|
} else {
|
|
490
493
|
sections.push("", "## Emits", "");
|
|
@@ -492,7 +495,7 @@ function generateMarkdown(doc) {
|
|
|
492
495
|
sections.push("| --- | --- |");
|
|
493
496
|
for (const e of doc.emits) {
|
|
494
497
|
const desc = e.description || "-";
|
|
495
|
-
sections.push(`| ${e.name} | ${desc} |`);
|
|
498
|
+
sections.push(`| ${esc(e.name)} | ${esc(desc)} |`);
|
|
496
499
|
}
|
|
497
500
|
}
|
|
498
501
|
if (hasSlots) {
|
|
@@ -502,7 +505,7 @@ function generateMarkdown(doc) {
|
|
|
502
505
|
for (const s of doc.slots) {
|
|
503
506
|
const desc = s.description || "-";
|
|
504
507
|
const bindings = s.bindings.length > 0 ? s.bindings.join(", ") : "-";
|
|
505
|
-
sections.push(`| ${s.name} | ${bindings} | ${desc} |`);
|
|
508
|
+
sections.push(`| ${esc(s.name)} | ${esc(bindings)} | ${esc(desc)} |`);
|
|
506
509
|
}
|
|
507
510
|
}
|
|
508
511
|
if (hasExposes) {
|
|
@@ -511,7 +514,7 @@ function generateMarkdown(doc) {
|
|
|
511
514
|
sections.push("| --- | --- | --- |");
|
|
512
515
|
for (const e of doc.exposes) {
|
|
513
516
|
const desc = e.description || "-";
|
|
514
|
-
sections.push(`| ${e.name} | ${e.type} | ${desc} |`);
|
|
517
|
+
sections.push(`| ${esc(e.name)} | ${esc(e.type)} | ${esc(desc)} |`);
|
|
515
518
|
}
|
|
516
519
|
}
|
|
517
520
|
if (hasComposables) {
|
package/dist/index.mjs
CHANGED
|
@@ -444,6 +444,9 @@ function stringifyDefault(node, source) {
|
|
|
444
444
|
}
|
|
445
445
|
//#endregion
|
|
446
446
|
//#region src/markdown.ts
|
|
447
|
+
function esc(value) {
|
|
448
|
+
return value.replaceAll("|", "\\|");
|
|
449
|
+
}
|
|
447
450
|
function generateMarkdown(doc) {
|
|
448
451
|
const sections = [`# ${doc.name}`];
|
|
449
452
|
if (doc.description) sections.push("", doc.description);
|
|
@@ -468,7 +471,7 @@ function generateMarkdown(doc) {
|
|
|
468
471
|
if (p.since) desc += ` *(since ${p.since})*`;
|
|
469
472
|
if (p.see) desc += ` See: ${p.see}`;
|
|
470
473
|
const req = p.required ? "Yes" : "No";
|
|
471
|
-
sections.push(`| ${p.name} | ${p.type} | ${req} | ${def} | ${desc} |`);
|
|
474
|
+
sections.push(`| ${esc(p.name)} | ${esc(p.type)} | ${req} | ${esc(def)} | ${esc(desc)} |`);
|
|
472
475
|
if (p.example) examples.push({
|
|
473
476
|
name: p.name,
|
|
474
477
|
example: p.example
|
|
@@ -483,7 +486,7 @@ function generateMarkdown(doc) {
|
|
|
483
486
|
for (const e of doc.emits) {
|
|
484
487
|
const desc = e.description || "-";
|
|
485
488
|
const payload = e.payload || "-";
|
|
486
|
-
sections.push(`| ${e.name} | ${payload} | ${desc} |`);
|
|
489
|
+
sections.push(`| ${esc(e.name)} | ${esc(payload)} | ${esc(desc)} |`);
|
|
487
490
|
}
|
|
488
491
|
} else {
|
|
489
492
|
sections.push("", "## Emits", "");
|
|
@@ -491,7 +494,7 @@ function generateMarkdown(doc) {
|
|
|
491
494
|
sections.push("| --- | --- |");
|
|
492
495
|
for (const e of doc.emits) {
|
|
493
496
|
const desc = e.description || "-";
|
|
494
|
-
sections.push(`| ${e.name} | ${desc} |`);
|
|
497
|
+
sections.push(`| ${esc(e.name)} | ${esc(desc)} |`);
|
|
495
498
|
}
|
|
496
499
|
}
|
|
497
500
|
if (hasSlots) {
|
|
@@ -501,7 +504,7 @@ function generateMarkdown(doc) {
|
|
|
501
504
|
for (const s of doc.slots) {
|
|
502
505
|
const desc = s.description || "-";
|
|
503
506
|
const bindings = s.bindings.length > 0 ? s.bindings.join(", ") : "-";
|
|
504
|
-
sections.push(`| ${s.name} | ${bindings} | ${desc} |`);
|
|
507
|
+
sections.push(`| ${esc(s.name)} | ${esc(bindings)} | ${esc(desc)} |`);
|
|
505
508
|
}
|
|
506
509
|
}
|
|
507
510
|
if (hasExposes) {
|
|
@@ -510,7 +513,7 @@ function generateMarkdown(doc) {
|
|
|
510
513
|
sections.push("| --- | --- | --- |");
|
|
511
514
|
for (const e of doc.exposes) {
|
|
512
515
|
const desc = e.description || "-";
|
|
513
|
-
sections.push(`| ${e.name} | ${e.type} | ${desc} |`);
|
|
516
|
+
sections.push(`| ${esc(e.name)} | ${esc(e.type)} | ${esc(desc)} |`);
|
|
514
517
|
}
|
|
515
518
|
}
|
|
516
519
|
if (hasComposables) {
|