compmark-vue 0.3.2 → 0.4.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
@@ -54,14 +54,15 @@ yarn add -D compmark-vue
54
54
  compmark <files/dirs/globs> [options]
55
55
  ```
56
56
 
57
- | Option | Description | Default |
58
- | --------------------- | ------------------------------- | ------- |
59
- | `--out <dir>` | Output directory | `.` |
60
- | `--format <md\|json>` | Output format | `md` |
61
- | `--join` | Combine into a single file | |
62
- | `--ignore <patterns>` | Comma-separated ignore patterns | |
63
- | `--watch` | Watch for changes and rebuild | |
64
- | `--silent` | Suppress non-error output | |
57
+ | Option | Description | Default |
58
+ | ---------------------- | ---------------------------------- | ------- |
59
+ | `--out <dir>` | Output directory | `.` |
60
+ | `--format <md\|json>` | Output format | `md` |
61
+ | `--join` | Combine into a single file | |
62
+ | `--ignore <patterns>` | Comma-separated ignore patterns | |
63
+ | `--preserve-structure` | Mirror input folder tree in output | |
64
+ | `--watch` | Watch for changes and rebuild | |
65
+ | `--silent` | Suppress non-error output | |
65
66
 
66
67
  ### Examples
67
68
 
@@ -90,6 +91,11 @@ compmark src/components --format json --join --out docs
90
91
  # Ignore patterns
91
92
  compmark src/components --ignore "internal,*.test"
92
93
 
94
+ # Preserve folder structure in output
95
+ compmark src --out docs --preserve-structure
96
+ # src/components/Button.vue → docs/components/Button.md
97
+ # src/views/Home.vue → docs/views/Home.md
98
+
93
99
  # Watch mode
94
100
  compmark src/components --out docs --watch
95
101
 
@@ -103,10 +109,17 @@ The summary line shows what happened:
103
109
  ✓ 24 components documented, 2 skipped, 0 errors
104
110
  ```
105
111
 
112
+ Skipped count includes both `@internal` components and files matching `--ignore` patterns.
113
+
106
114
  Exit code is `1` when errors occur (except in watch mode).
107
115
 
116
+ In watch mode, individual file changes are processed incrementally — only the changed file is re-parsed and re-written. If a file is deleted or becomes `@internal`, its output is automatically removed.
117
+
108
118
  ## Features
109
119
 
120
+ - [Component description](#component-description) — JSDoc on the first statement becomes a component summary
121
+ - [Refs](#refs) — `ref()`, `shallowRef()`, `reactive()`, `shallowReactive()` with type inference
122
+ - [Computed](#computed) — `computed()` with generic and return-type inference
110
123
  - [Props](#props) — runtime and TypeScript generic syntax, including imported types
111
124
  - [Emits](#emits) — array, TypeScript property, and call signature syntax
112
125
  - [Slots](#slots) — `defineSlots` with typed bindings, template `<slot>` fallback
@@ -114,12 +127,183 @@ Exit code is `1` when errors occur (except in watch mode).
114
127
  - [Composables](#composables) — auto-detects `useX()` calls in `<script setup>`
115
128
  - [JSDoc tags](#jsdoc-tags) — `@deprecated`, `@since`, `@example`, `@see`, `@default`
116
129
  - [`@internal`](#internal-components) — exclude components from output
117
- - [Options API](#options-api) — `export default { props, emits }` support
130
+ - [Options API](#options-api) — `export default { props, emits, data(), computed }` support
118
131
  - [Output formats](#output-formats) — Markdown (individual or joined), JSON
132
+ - [Preserve structure](#preserve-structure) — mirror input folder tree in `--out`
119
133
  - Empty sections are skipped cleanly — no placeholder noise
120
134
 
121
135
  ## Examples
122
136
 
137
+ ### Component Description
138
+
139
+ A JSDoc comment at the top of `<script setup>` is extracted as the component description and included in the generated `.md` file:
140
+
141
+ ```vue
142
+ <!-- ConfirmDialog.vue -->
143
+ <template>
144
+ <dialog :open="open">
145
+ <slot />
146
+ <button @click="$emit('confirm')">OK</button>
147
+ <button @click="$emit('cancel')">Cancel</button>
148
+ </dialog>
149
+ </template>
150
+
151
+ <script setup lang="ts">
152
+ /**
153
+ * A dialog for confirming destructive user actions such as deletions.
154
+ */
155
+ import { ref } from "vue";
156
+
157
+ const props = defineProps<{
158
+ /** Whether the dialog is visible */
159
+ open: boolean;
160
+ /** Dialog title */
161
+ title?: string;
162
+ }>();
163
+
164
+ const emit = defineEmits<{
165
+ /** Emitted when the user confirms the action */
166
+ confirm: [];
167
+ /** Emitted when the user cancels */
168
+ cancel: [];
169
+ }>();
170
+
171
+ const loading = ref(false);
172
+ </script>
173
+ ```
174
+
175
+ Running `compmark ConfirmDialog.vue` produces `ConfirmDialog.md`:
176
+
177
+ ```md
178
+ # ConfirmDialog
179
+
180
+ A dialog for confirming destructive user actions such as deletions.
181
+
182
+ **Note:** Uses `<script setup>` syntax.
183
+
184
+ ## Refs
185
+
186
+ | Name | Type | Description |
187
+ | ------- | ------------------ | ----------- |
188
+ | loading | Ref&lt;boolean&gt; | - |
189
+
190
+ ## Props
191
+
192
+ | Name | Type | Required | Default | Description |
193
+ | ----- | ------- | -------- | ------- | ----------------------------- |
194
+ | open | boolean | Yes | - | Whether the dialog is visible |
195
+ | title | string | No | - | Dialog title |
196
+
197
+ ## Emits
198
+
199
+ | Name | Description |
200
+ | ------- | ----------------------------------------- |
201
+ | confirm | Emitted when the user confirms the action |
202
+ | cancel | Emitted when the user cancels |
203
+
204
+ ## Slots
205
+
206
+ | Name | Bindings | Description |
207
+ | ------- | -------- | ----------- |
208
+ | default | - | - |
209
+ ```
210
+
211
+ The description is picked up automatically when the JSDoc comment is on:
212
+
213
+ - An `import` statement (most common — put the comment at the top of the script)
214
+ - A `defineProps` / `defineEmits` call (bare or `const props = defineProps(...)`)
215
+ - A `withDefaults(...)` call
216
+
217
+ If the first statement is a plain variable (like `const count = ref(0)`), use the `@component` tag so the comment isn't mistaken for a variable description:
218
+
219
+ ```vue
220
+ <script setup lang="ts">
221
+ /**
222
+ * @component
223
+ * A tooltip that appears on hover.
224
+ */
225
+ const visible = ref(false);
226
+ </script>
227
+ ```
228
+
229
+ ### Refs
230
+
231
+ `ref()`, `shallowRef()`, `reactive()`, and `shallowReactive()` in `<script setup>` are automatically documented with inferred types:
232
+
233
+ ```vue
234
+ <script setup lang="ts">
235
+ import { ref, shallowRef, reactive, computed } from "vue";
236
+
237
+ /**
238
+ * The counter value
239
+ * @since 1.0.0
240
+ */
241
+ const count = ref(0);
242
+
243
+ /** The user's name */
244
+ const name = ref<string>("");
245
+
246
+ /** @deprecated Use shallowData instead */
247
+ const data = shallowRef<string[]>([]);
248
+
249
+ const state = reactive({ count: 0, name: "" });
250
+ </script>
251
+ ```
252
+
253
+ Output:
254
+
255
+ ```md
256
+ ## Refs
257
+
258
+ | Name | Type | Description |
259
+ | ----- | -------------------------- | ----------------------------------------- |
260
+ | count | Ref&lt;number&gt; | The counter value _(since 1.0.0)_ |
261
+ | name | Ref&lt;string&gt; | The user's name |
262
+ | data | ShallowRef&lt;string[]&gt; | - **Deprecated**: Use shallowData instead |
263
+ | state | Object | - |
264
+ ```
265
+
266
+ Type inference priority:
267
+
268
+ 1. Explicit TS annotation: `const x: Ref<string[]> = ref([])` → `Ref<string[]>`
269
+ 2. Generic type parameter: `ref<string>("")` → `Ref<string>`
270
+ 3. Literal argument: `ref(0)` → `Ref<number>`, `ref("")` → `Ref<string>`, `ref(true)` → `Ref<boolean>`
271
+ 4. Fallback: `Ref` (no type parameter)
272
+
273
+ ### Computed
274
+
275
+ `computed()` calls are documented with type inference from generics or getter return types:
276
+
277
+ ```vue
278
+ <script setup lang="ts">
279
+ import { ref, computed } from "vue";
280
+
281
+ const count = ref(0);
282
+
283
+ /**
284
+ * The full display name
285
+ * @since 2.0.0
286
+ */
287
+ const fullName = computed(() => "John Smith");
288
+
289
+ const total = computed<number>(() => count.value * 2);
290
+
291
+ const doubled = computed((): number => count.value * 2);
292
+ </script>
293
+ ```
294
+
295
+ Output:
296
+
297
+ ```md
298
+ ## Computed
299
+
300
+ | Name | Type | Description |
301
+ | -------- | ------------------------- | ------------------------------------- |
302
+ | fullName | ComputedRef | The full display name _(since 2.0.0)_ |
303
+ | total | ComputedRef&lt;number&gt; | - |
304
+ | doubled | ComputedRef&lt;number&gt; | - |
305
+ ```
306
+
123
307
  ### Props
124
308
 
125
309
  Runtime syntax, TypeScript generics, and `withDefaults` are all supported:
@@ -401,7 +585,7 @@ $ compmark InternalHelper.vue
401
585
 
402
586
  ### Options API
403
587
 
404
- Components using `export default {}` are supported:
588
+ Components using `export default {}` are supported. Props, emits, `data()`, and `computed` are all extracted:
405
589
 
406
590
  ```vue
407
591
  <script>
@@ -418,6 +602,22 @@ export default {
418
602
  },
419
603
  },
420
604
  emits: ["click", "update"],
605
+ data() {
606
+ return {
607
+ /** The greeting message */
608
+ message: "Hello",
609
+ isActive: true,
610
+ };
611
+ },
612
+ computed: {
613
+ /**
614
+ * The full display name
615
+ * @since 1.0.0
616
+ */
617
+ fullName() {
618
+ return this.title + " Smith";
619
+ },
620
+ },
421
621
  };
422
622
  </script>
423
623
  ```
@@ -425,6 +625,19 @@ export default {
425
625
  Output:
426
626
 
427
627
  ```md
628
+ ## Refs
629
+
630
+ | Name | Type | Description |
631
+ | -------- | ------- | -------------------- |
632
+ | message | string | The greeting message |
633
+ | isActive | boolean | - |
634
+
635
+ ## Computed
636
+
637
+ | Name | Type | Description |
638
+ | -------- | ------- | ------------------------------------- |
639
+ | fullName | unknown | The full display name _(since 1.0.0)_ |
640
+
428
641
  ## Props
429
642
 
430
643
  | Name | Type | Required | Default | Description |
@@ -440,6 +653,8 @@ Output:
440
653
  | update | - |
441
654
  ```
442
655
 
656
+ `data()` return properties are documented as refs with literal type inference. Computed properties support both simple getters and get/set object syntax.
657
+
443
658
  ### Output Formats
444
659
 
445
660
  **Individual markdown** (default) — one `.md` file per component:
@@ -470,6 +685,24 @@ compmark src/components --format json --join --out docs
470
685
  # Creates: docs/components.json with { generated, components: [...] }
471
686
  ```
472
687
 
688
+ ### Preserve Structure
689
+
690
+ By default, all output files are placed flat in the `--out` directory. Use `--preserve-structure` to mirror the input folder hierarchy:
691
+
692
+ ```sh
693
+ compmark src --out docs/api --preserve-structure
694
+ ```
695
+
696
+ ```
697
+ src/components/Button.vue → docs/api/components/Button.md
698
+ src/components/Dialog.vue → docs/api/components/Dialog.md
699
+ src/views/Home.vue → docs/api/views/Home.md
700
+ ```
701
+
702
+ Without `--preserve-structure`, components with the same name in different directories get a numeric suffix (`Button.md`, `Button-2.md`). With `--preserve-structure`, they live in separate subdirectories.
703
+
704
+ `--join` mode ignores `--preserve-structure` (single output file).
705
+
473
706
  ## Programmatic API
474
707
 
475
708
  ```sh
@@ -497,7 +730,7 @@ Multi-file processing:
497
730
  ```ts
498
731
  import { discoverFiles, processFiles } from "compmark-vue";
499
732
 
500
- const files = await discoverFiles(["src/components"], ["dist"]);
733
+ const { files, ignoredCount, basePath } = await discoverFiles(["src/components"], ["dist"]);
501
734
  const summary = processFiles(files, { silent: false });
502
735
  // summary.files, summary.documented, summary.skipped, summary.errors
503
736
  ```