@ramathibodi/nuxt-commons 0.1.74 → 0.1.75
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 +115 -115
- package/dist/module.json +1 -1
- package/dist/runtime/components/Alert.vue +58 -58
- package/dist/runtime/components/BarcodeReader.vue +130 -130
- package/dist/runtime/components/ExportCSV.vue +110 -110
- package/dist/runtime/components/FileBtn.vue +79 -79
- package/dist/runtime/components/ImportCSV.vue +151 -151
- package/dist/runtime/components/MrzReader.vue +168 -168
- package/dist/runtime/components/SplitterPanel.vue +67 -67
- package/dist/runtime/components/TabsGroup.vue +39 -39
- package/dist/runtime/components/TextBarcode.vue +66 -66
- package/dist/runtime/components/device/IdCardButton.vue +95 -95
- package/dist/runtime/components/device/IdCardWebSocket.vue +207 -207
- package/dist/runtime/components/device/Scanner.vue +350 -350
- package/dist/runtime/components/dialog/Confirm.vue +112 -112
- package/dist/runtime/components/dialog/Host.vue +88 -88
- package/dist/runtime/components/dialog/Index.vue +84 -84
- package/dist/runtime/components/dialog/Loading.vue +51 -51
- package/dist/runtime/components/dialog/default/Confirm.vue +112 -112
- package/dist/runtime/components/dialog/default/Loading.vue +60 -60
- package/dist/runtime/components/dialog/default/Notify.vue +82 -82
- package/dist/runtime/components/dialog/default/Printing.vue +46 -46
- package/dist/runtime/components/dialog/default/VerifyUser.vue +144 -144
- package/dist/runtime/components/document/Form.vue +50 -50
- package/dist/runtime/components/document/TemplateBuilder.vue +536 -536
- package/dist/runtime/components/form/ActionPad.vue +156 -156
- package/dist/runtime/components/form/Birthdate.vue +116 -116
- package/dist/runtime/components/form/CheckboxGroup.vue +99 -99
- package/dist/runtime/components/form/CodeEditor.vue +45 -45
- package/dist/runtime/components/form/Date.vue +270 -270
- package/dist/runtime/components/form/DateTime.vue +220 -220
- package/dist/runtime/components/form/Dialog.vue +178 -178
- package/dist/runtime/components/form/EditPad.vue +157 -157
- package/dist/runtime/components/form/File.vue +295 -295
- package/dist/runtime/components/form/Hidden.vue +44 -44
- package/dist/runtime/components/form/Iterator.vue +538 -538
- package/dist/runtime/components/form/Login.vue +143 -143
- package/dist/runtime/components/form/Pad.vue +399 -399
- package/dist/runtime/components/form/SignPad.vue +226 -226
- package/dist/runtime/components/form/System.vue +34 -34
- package/dist/runtime/components/form/Table.vue +391 -391
- package/dist/runtime/components/form/TableData.vue +236 -236
- package/dist/runtime/components/form/Time.vue +177 -177
- package/dist/runtime/components/form/images/Capture.vue +245 -245
- package/dist/runtime/components/form/images/Edit.vue +133 -133
- package/dist/runtime/components/form/images/Field.vue +331 -331
- package/dist/runtime/components/form/images/Pad.vue +54 -54
- package/dist/runtime/components/label/Date.vue +37 -37
- package/dist/runtime/components/label/DateAgo.vue +102 -102
- package/dist/runtime/components/label/DateCount.vue +152 -152
- package/dist/runtime/components/label/Field.vue +111 -111
- package/dist/runtime/components/label/FormatMoney.vue +37 -37
- package/dist/runtime/components/label/Mask.vue +46 -46
- package/dist/runtime/components/label/Object.vue +21 -21
- package/dist/runtime/components/master/Autocomplete.vue +89 -89
- package/dist/runtime/components/master/Combobox.vue +88 -88
- package/dist/runtime/components/master/RadioGroup.vue +90 -90
- package/dist/runtime/components/master/Select.vue +70 -70
- package/dist/runtime/components/master/label.vue +55 -55
- package/dist/runtime/components/model/Autocomplete.vue +91 -91
- package/dist/runtime/components/model/Combobox.vue +90 -90
- package/dist/runtime/components/model/Pad.vue +114 -114
- package/dist/runtime/components/model/Select.vue +78 -84
- package/dist/runtime/components/model/Table.vue +370 -370
- package/dist/runtime/components/model/iterator.vue +497 -497
- package/dist/runtime/components/model/label.vue +58 -58
- package/dist/runtime/components/pdf/Print.vue +75 -75
- package/dist/runtime/components/pdf/View.vue +146 -146
- package/dist/runtime/composables/dialog.d.ts +1 -1
- package/dist/runtime/composables/graphql.d.ts +1 -1
- package/dist/runtime/composables/graphqlModel.d.ts +9 -9
- package/dist/runtime/composables/graphqlModelItem.d.ts +7 -7
- package/dist/runtime/composables/graphqlModelOperation.d.ts +6 -6
- package/dist/runtime/composables/userPermission.d.ts +1 -1
- package/dist/runtime/labs/Calendar.vue +99 -99
- package/dist/runtime/labs/form/EditMobile.vue +152 -152
- package/dist/runtime/labs/form/TextFieldMask.vue +43 -43
- package/dist/runtime/plugins/clientConfig.d.ts +1 -1
- package/dist/runtime/plugins/default.d.ts +1 -1
- package/dist/runtime/plugins/dialogManager.d.ts +1 -1
- package/dist/runtime/plugins/permission.d.ts +1 -1
- package/dist/runtime/types/alert.d.ts +11 -11
- package/dist/runtime/types/clientConfig.d.ts +13 -13
- package/dist/runtime/types/dialogManager.d.ts +35 -35
- package/dist/runtime/types/formDialog.d.ts +5 -5
- package/dist/runtime/types/graphqlOperation.d.ts +23 -23
- package/dist/runtime/types/menu.d.ts +31 -31
- package/dist/runtime/types/modules.d.ts +7 -7
- package/dist/runtime/types/permission.d.ts +13 -13
- package/package.json +131 -131
- package/scripts/enrich-vue-docs-from-ai.mjs +197 -197
- package/scripts/generate-ai-summary.mjs +321 -321
- package/scripts/generate-composables-md.mjs +129 -129
- package/scripts/postInstall.cjs +70 -70
- package/templates/.codegen/codegen.ts +32 -32
- package/templates/.codegen/plugin-schema-object.js +161 -161
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
const rootDir = process.cwd()
|
|
5
|
-
const aiPath = path.join(rootDir, 'docs/ai-summary.json')
|
|
6
|
-
const docsDir = path.join(rootDir, 'docs/components')
|
|
7
|
-
|
|
8
|
-
if (!fs.existsSync(aiPath) || !fs.existsSync(docsDir)) {
|
|
9
|
-
console.log('Skip enrich: required docs/ai-summary.json or docs/components missing.')
|
|
10
|
-
process.exit(0)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const ai = JSON.parse(fs.readFileSync(aiPath, 'utf8'))
|
|
14
|
-
const componentMap = new Map(ai.components.map((c) => [c.path, c]))
|
|
15
|
-
|
|
16
|
-
function toPosix(p) {
|
|
17
|
-
return p.split(path.sep).join('/')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function guessSourcePathFromDoc(docFile) {
|
|
21
|
-
const rel = toPosix(path.relative(docsDir, docFile))
|
|
22
|
-
const noExt = rel.replace(/\.md$/, '')
|
|
23
|
-
return `src/runtime/components/${noExt}.vue`
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function mdEscape(str) {
|
|
27
|
-
return String(str ?? '').replace(/\|/g, '\\|')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const propHints = {
|
|
31
|
-
modelName: { type: 'string', description: 'GraphQL model name used to resolve query/mutation operations.' },
|
|
32
|
-
modelBy: { type: 'Record<string, any>', description: 'Base filter object applied to read/search/create flows.' },
|
|
33
|
-
modelKey: { type: 'string', description: 'Unique key field used to identify and update existing rows/items.' },
|
|
34
|
-
fields: { type: 'Array<string | object>', description: 'Requested GraphQL fields used when loading records.' },
|
|
35
|
-
headers: { type: 'any[]', description: 'Column definitions used by table/iterator rendering.' },
|
|
36
|
-
itemTitle: { type: 'string', description: 'Item field used as display label.' },
|
|
37
|
-
itemValue: { type: 'string', description: 'Item field used as stored value.' },
|
|
38
|
-
filterKeys: { type: 'string | string[]', description: 'Keys used for client-side filtering/searching.' },
|
|
39
|
-
multiple: { type: 'boolean', description: 'Enables multi-select mode.' },
|
|
40
|
-
placeholder: { type: 'string', description: 'Placeholder text shown when input has no value.' },
|
|
41
|
-
noDataText: { type: 'string', description: 'Text shown when no matching data is available.' },
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function inferTypeFromDocDefault(defaultCell) {
|
|
45
|
-
const v = (defaultCell || '').trim().replace(/^`|`$/g, '')
|
|
46
|
-
if (!v || v === '-' || v === 'undefined') return undefined
|
|
47
|
-
if (v === 'true' || v === 'false') return 'boolean'
|
|
48
|
-
if (/^-?\d+(\.\d+)?$/.test(v)) return 'number'
|
|
49
|
-
if ((v.startsWith("'") && v.endsWith("'")) || (v.startsWith('"') && v.endsWith('"'))) return 'string'
|
|
50
|
-
if (v.includes('=> []') || v === '[]') return 'any[]'
|
|
51
|
-
if (v.includes('=> ({') || v === '{}' || v === 'null') return 'Record<string, any>'
|
|
52
|
-
return undefined
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function inferEventDescription(eventName, payload) {
|
|
56
|
-
if (eventName === 'update:modelValue') return 'Emitted when the bound model value changes.'
|
|
57
|
-
if (eventName === 'open:dialog') return 'Emitted when the component opens its dialog/form editor.'
|
|
58
|
-
if (eventName === 'close:dialog') return 'Emitted when the component closes its dialog/form editor.'
|
|
59
|
-
if (eventName === 'create') return 'Emitted after a create action completes.'
|
|
60
|
-
if (eventName === 'update') return 'Emitted after an update action completes.'
|
|
61
|
-
if (eventName === 'delete') return 'Emitted after a delete action completes.'
|
|
62
|
-
if (eventName === 'import') return 'Emitted after import data is parsed and ready.'
|
|
63
|
-
if (eventName === 'error') return 'Emitted when an operation fails.'
|
|
64
|
-
if (payload) return `Emits payload: \`${payload}\`.`
|
|
65
|
-
return 'Custom event emitted by this component.'
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function splitRow(line) {
|
|
69
|
-
const cols = line.split('|').slice(1, -1).map((c) => c.trim())
|
|
70
|
-
return cols
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function joinRow(cols) {
|
|
74
|
-
return `| ${cols.join(' | ')} |`
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function updatePropsTable(lines, sectionStartIdx, component) {
|
|
78
|
-
// table starts after "## Props", header and separator rows
|
|
79
|
-
let i = sectionStartIdx + 1
|
|
80
|
-
while (i < lines.length && !lines[i].startsWith('|')) i++
|
|
81
|
-
if (i + 1 >= lines.length) return 0
|
|
82
|
-
|
|
83
|
-
const propsByName = new Map((component.props || []).map((p) => [p.name, p]))
|
|
84
|
-
let changed = 0
|
|
85
|
-
|
|
86
|
-
// skip header + separator
|
|
87
|
-
for (let r = i + 2; r < lines.length; r++) {
|
|
88
|
-
const line = lines[r]
|
|
89
|
-
if (!line.startsWith('|')) break
|
|
90
|
-
const cols = splitRow(line)
|
|
91
|
-
if (cols.length < 5) continue
|
|
92
|
-
|
|
93
|
-
const propName = cols[0].replace(/`/g, '').trim()
|
|
94
|
-
const meta = propsByName.get(propName)
|
|
95
|
-
const hint = propHints[propName]
|
|
96
|
-
|
|
97
|
-
const desc = cols[1]
|
|
98
|
-
const type = cols[2]
|
|
99
|
-
const def = cols[4]
|
|
100
|
-
|
|
101
|
-
if ((!desc || desc === '-') && meta?.description) cols[1] = mdEscape(meta.description)
|
|
102
|
-
else if ((!desc || desc === '-') && hint?.description) cols[1] = mdEscape(hint.description)
|
|
103
|
-
|
|
104
|
-
if ((type === '-' || !type) && meta?.type) cols[2] = `\`${mdEscape(meta.type)}\``
|
|
105
|
-
else if ((type === '-' || !type) && hint?.type) cols[2] = `\`${mdEscape(hint.type)}\``
|
|
106
|
-
else if ((type === '-' || !type)) {
|
|
107
|
-
const inferred = inferTypeFromDocDefault(def)
|
|
108
|
-
if (inferred) cols[2] = `\`${mdEscape(inferred)}\``
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if ((!def || def === '-') && meta?.default !== undefined) cols[4] = `\`${mdEscape(meta.default)}\``
|
|
112
|
-
|
|
113
|
-
const next = joinRow(cols)
|
|
114
|
-
if (next !== line) {
|
|
115
|
-
lines[r] = next
|
|
116
|
-
changed++
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return changed
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function updateEventsTable(lines, sectionStartIdx, component) {
|
|
124
|
-
let i = sectionStartIdx + 1
|
|
125
|
-
while (i < lines.length && !lines[i].startsWith('|')) i++
|
|
126
|
-
if (i + 1 >= lines.length) return 0
|
|
127
|
-
|
|
128
|
-
const emitsByName = new Map((component.emits || []).map((e) => [e.event, e]))
|
|
129
|
-
let changed = 0
|
|
130
|
-
|
|
131
|
-
// skip header + separator
|
|
132
|
-
for (let r = i + 2; r < lines.length; r++) {
|
|
133
|
-
const line = lines[r]
|
|
134
|
-
if (!line.startsWith('|')) break
|
|
135
|
-
const cols = splitRow(line)
|
|
136
|
-
while (cols.length < 3) cols.push('')
|
|
137
|
-
|
|
138
|
-
const eventName = cols[0].replace(/`/g, '').trim()
|
|
139
|
-
const meta = emitsByName.get(eventName)
|
|
140
|
-
if (!meta) continue
|
|
141
|
-
|
|
142
|
-
const propsCol = cols[1]
|
|
143
|
-
const descCol = cols[2]
|
|
144
|
-
|
|
145
|
-
if ((!propsCol || propsCol === '-') && meta.payload) cols[1] = `\`${mdEscape(meta.payload)}\``
|
|
146
|
-
if (!descCol || descCol === '-') cols[2] = mdEscape(inferEventDescription(eventName, meta.payload))
|
|
147
|
-
|
|
148
|
-
const next = joinRow(cols)
|
|
149
|
-
if (next !== line) {
|
|
150
|
-
lines[r] = next
|
|
151
|
-
changed++
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return changed
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function processDocFile(docFile) {
|
|
159
|
-
const sourcePath = guessSourcePathFromDoc(docFile)
|
|
160
|
-
const component = componentMap.get(sourcePath)
|
|
161
|
-
if (!component) return 0
|
|
162
|
-
|
|
163
|
-
const content = fs.readFileSync(docFile, 'utf8')
|
|
164
|
-
const lines = content.split('\n')
|
|
165
|
-
let changed = 0
|
|
166
|
-
|
|
167
|
-
for (let i = 0; i < lines.length; i++) {
|
|
168
|
-
if (lines[i].trim() === '## Props') changed += updatePropsTable(lines, i, component)
|
|
169
|
-
if (lines[i].trim() === '## Events') changed += updateEventsTable(lines, i, component)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (changed > 0) fs.writeFileSync(docFile, lines.join('\n'))
|
|
173
|
-
return changed
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function walkMd(dir) {
|
|
177
|
-
const out = []
|
|
178
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
179
|
-
const full = path.join(dir, entry.name)
|
|
180
|
-
if (entry.isDirectory()) out.push(...walkMd(full))
|
|
181
|
-
else if (entry.name.endsWith('.md')) out.push(full)
|
|
182
|
-
}
|
|
183
|
-
return out
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const mdFiles = walkMd(docsDir)
|
|
187
|
-
let changedFiles = 0
|
|
188
|
-
let changedRows = 0
|
|
189
|
-
for (const file of mdFiles) {
|
|
190
|
-
const changed = processDocFile(file)
|
|
191
|
-
if (changed > 0) {
|
|
192
|
-
changedFiles++
|
|
193
|
-
changedRows += changed
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
console.log(`Enriched ${changedRows} table rows across ${changedFiles} files.`)
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
const rootDir = process.cwd()
|
|
5
|
+
const aiPath = path.join(rootDir, 'docs/ai-summary.json')
|
|
6
|
+
const docsDir = path.join(rootDir, 'docs/components')
|
|
7
|
+
|
|
8
|
+
if (!fs.existsSync(aiPath) || !fs.existsSync(docsDir)) {
|
|
9
|
+
console.log('Skip enrich: required docs/ai-summary.json or docs/components missing.')
|
|
10
|
+
process.exit(0)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ai = JSON.parse(fs.readFileSync(aiPath, 'utf8'))
|
|
14
|
+
const componentMap = new Map(ai.components.map((c) => [c.path, c]))
|
|
15
|
+
|
|
16
|
+
function toPosix(p) {
|
|
17
|
+
return p.split(path.sep).join('/')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function guessSourcePathFromDoc(docFile) {
|
|
21
|
+
const rel = toPosix(path.relative(docsDir, docFile))
|
|
22
|
+
const noExt = rel.replace(/\.md$/, '')
|
|
23
|
+
return `src/runtime/components/${noExt}.vue`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function mdEscape(str) {
|
|
27
|
+
return String(str ?? '').replace(/\|/g, '\\|')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const propHints = {
|
|
31
|
+
modelName: { type: 'string', description: 'GraphQL model name used to resolve query/mutation operations.' },
|
|
32
|
+
modelBy: { type: 'Record<string, any>', description: 'Base filter object applied to read/search/create flows.' },
|
|
33
|
+
modelKey: { type: 'string', description: 'Unique key field used to identify and update existing rows/items.' },
|
|
34
|
+
fields: { type: 'Array<string | object>', description: 'Requested GraphQL fields used when loading records.' },
|
|
35
|
+
headers: { type: 'any[]', description: 'Column definitions used by table/iterator rendering.' },
|
|
36
|
+
itemTitle: { type: 'string', description: 'Item field used as display label.' },
|
|
37
|
+
itemValue: { type: 'string', description: 'Item field used as stored value.' },
|
|
38
|
+
filterKeys: { type: 'string | string[]', description: 'Keys used for client-side filtering/searching.' },
|
|
39
|
+
multiple: { type: 'boolean', description: 'Enables multi-select mode.' },
|
|
40
|
+
placeholder: { type: 'string', description: 'Placeholder text shown when input has no value.' },
|
|
41
|
+
noDataText: { type: 'string', description: 'Text shown when no matching data is available.' },
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function inferTypeFromDocDefault(defaultCell) {
|
|
45
|
+
const v = (defaultCell || '').trim().replace(/^`|`$/g, '')
|
|
46
|
+
if (!v || v === '-' || v === 'undefined') return undefined
|
|
47
|
+
if (v === 'true' || v === 'false') return 'boolean'
|
|
48
|
+
if (/^-?\d+(\.\d+)?$/.test(v)) return 'number'
|
|
49
|
+
if ((v.startsWith("'") && v.endsWith("'")) || (v.startsWith('"') && v.endsWith('"'))) return 'string'
|
|
50
|
+
if (v.includes('=> []') || v === '[]') return 'any[]'
|
|
51
|
+
if (v.includes('=> ({') || v === '{}' || v === 'null') return 'Record<string, any>'
|
|
52
|
+
return undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function inferEventDescription(eventName, payload) {
|
|
56
|
+
if (eventName === 'update:modelValue') return 'Emitted when the bound model value changes.'
|
|
57
|
+
if (eventName === 'open:dialog') return 'Emitted when the component opens its dialog/form editor.'
|
|
58
|
+
if (eventName === 'close:dialog') return 'Emitted when the component closes its dialog/form editor.'
|
|
59
|
+
if (eventName === 'create') return 'Emitted after a create action completes.'
|
|
60
|
+
if (eventName === 'update') return 'Emitted after an update action completes.'
|
|
61
|
+
if (eventName === 'delete') return 'Emitted after a delete action completes.'
|
|
62
|
+
if (eventName === 'import') return 'Emitted after import data is parsed and ready.'
|
|
63
|
+
if (eventName === 'error') return 'Emitted when an operation fails.'
|
|
64
|
+
if (payload) return `Emits payload: \`${payload}\`.`
|
|
65
|
+
return 'Custom event emitted by this component.'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function splitRow(line) {
|
|
69
|
+
const cols = line.split('|').slice(1, -1).map((c) => c.trim())
|
|
70
|
+
return cols
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function joinRow(cols) {
|
|
74
|
+
return `| ${cols.join(' | ')} |`
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function updatePropsTable(lines, sectionStartIdx, component) {
|
|
78
|
+
// table starts after "## Props", header and separator rows
|
|
79
|
+
let i = sectionStartIdx + 1
|
|
80
|
+
while (i < lines.length && !lines[i].startsWith('|')) i++
|
|
81
|
+
if (i + 1 >= lines.length) return 0
|
|
82
|
+
|
|
83
|
+
const propsByName = new Map((component.props || []).map((p) => [p.name, p]))
|
|
84
|
+
let changed = 0
|
|
85
|
+
|
|
86
|
+
// skip header + separator
|
|
87
|
+
for (let r = i + 2; r < lines.length; r++) {
|
|
88
|
+
const line = lines[r]
|
|
89
|
+
if (!line.startsWith('|')) break
|
|
90
|
+
const cols = splitRow(line)
|
|
91
|
+
if (cols.length < 5) continue
|
|
92
|
+
|
|
93
|
+
const propName = cols[0].replace(/`/g, '').trim()
|
|
94
|
+
const meta = propsByName.get(propName)
|
|
95
|
+
const hint = propHints[propName]
|
|
96
|
+
|
|
97
|
+
const desc = cols[1]
|
|
98
|
+
const type = cols[2]
|
|
99
|
+
const def = cols[4]
|
|
100
|
+
|
|
101
|
+
if ((!desc || desc === '-') && meta?.description) cols[1] = mdEscape(meta.description)
|
|
102
|
+
else if ((!desc || desc === '-') && hint?.description) cols[1] = mdEscape(hint.description)
|
|
103
|
+
|
|
104
|
+
if ((type === '-' || !type) && meta?.type) cols[2] = `\`${mdEscape(meta.type)}\``
|
|
105
|
+
else if ((type === '-' || !type) && hint?.type) cols[2] = `\`${mdEscape(hint.type)}\``
|
|
106
|
+
else if ((type === '-' || !type)) {
|
|
107
|
+
const inferred = inferTypeFromDocDefault(def)
|
|
108
|
+
if (inferred) cols[2] = `\`${mdEscape(inferred)}\``
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if ((!def || def === '-') && meta?.default !== undefined) cols[4] = `\`${mdEscape(meta.default)}\``
|
|
112
|
+
|
|
113
|
+
const next = joinRow(cols)
|
|
114
|
+
if (next !== line) {
|
|
115
|
+
lines[r] = next
|
|
116
|
+
changed++
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return changed
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function updateEventsTable(lines, sectionStartIdx, component) {
|
|
124
|
+
let i = sectionStartIdx + 1
|
|
125
|
+
while (i < lines.length && !lines[i].startsWith('|')) i++
|
|
126
|
+
if (i + 1 >= lines.length) return 0
|
|
127
|
+
|
|
128
|
+
const emitsByName = new Map((component.emits || []).map((e) => [e.event, e]))
|
|
129
|
+
let changed = 0
|
|
130
|
+
|
|
131
|
+
// skip header + separator
|
|
132
|
+
for (let r = i + 2; r < lines.length; r++) {
|
|
133
|
+
const line = lines[r]
|
|
134
|
+
if (!line.startsWith('|')) break
|
|
135
|
+
const cols = splitRow(line)
|
|
136
|
+
while (cols.length < 3) cols.push('')
|
|
137
|
+
|
|
138
|
+
const eventName = cols[0].replace(/`/g, '').trim()
|
|
139
|
+
const meta = emitsByName.get(eventName)
|
|
140
|
+
if (!meta) continue
|
|
141
|
+
|
|
142
|
+
const propsCol = cols[1]
|
|
143
|
+
const descCol = cols[2]
|
|
144
|
+
|
|
145
|
+
if ((!propsCol || propsCol === '-') && meta.payload) cols[1] = `\`${mdEscape(meta.payload)}\``
|
|
146
|
+
if (!descCol || descCol === '-') cols[2] = mdEscape(inferEventDescription(eventName, meta.payload))
|
|
147
|
+
|
|
148
|
+
const next = joinRow(cols)
|
|
149
|
+
if (next !== line) {
|
|
150
|
+
lines[r] = next
|
|
151
|
+
changed++
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return changed
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function processDocFile(docFile) {
|
|
159
|
+
const sourcePath = guessSourcePathFromDoc(docFile)
|
|
160
|
+
const component = componentMap.get(sourcePath)
|
|
161
|
+
if (!component) return 0
|
|
162
|
+
|
|
163
|
+
const content = fs.readFileSync(docFile, 'utf8')
|
|
164
|
+
const lines = content.split('\n')
|
|
165
|
+
let changed = 0
|
|
166
|
+
|
|
167
|
+
for (let i = 0; i < lines.length; i++) {
|
|
168
|
+
if (lines[i].trim() === '## Props') changed += updatePropsTable(lines, i, component)
|
|
169
|
+
if (lines[i].trim() === '## Events') changed += updateEventsTable(lines, i, component)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (changed > 0) fs.writeFileSync(docFile, lines.join('\n'))
|
|
173
|
+
return changed
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function walkMd(dir) {
|
|
177
|
+
const out = []
|
|
178
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
179
|
+
const full = path.join(dir, entry.name)
|
|
180
|
+
if (entry.isDirectory()) out.push(...walkMd(full))
|
|
181
|
+
else if (entry.name.endsWith('.md')) out.push(full)
|
|
182
|
+
}
|
|
183
|
+
return out
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const mdFiles = walkMd(docsDir)
|
|
187
|
+
let changedFiles = 0
|
|
188
|
+
let changedRows = 0
|
|
189
|
+
for (const file of mdFiles) {
|
|
190
|
+
const changed = processDocFile(file)
|
|
191
|
+
if (changed > 0) {
|
|
192
|
+
changedFiles++
|
|
193
|
+
changedRows += changed
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.log(`Enriched ${changedRows} table rows across ${changedFiles} files.`)
|