dotmd-cli 0.27.1 → 0.28.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/package.json +1 -1
- package/src/frontmatter.mjs +47 -3
- package/src/new.mjs +9 -9
- package/src/validate.mjs +1 -1
package/package.json
CHANGED
package/src/frontmatter.mjs
CHANGED
|
@@ -29,7 +29,8 @@ export function replaceFrontmatter(raw, newFrontmatter) {
|
|
|
29
29
|
//
|
|
30
30
|
// Supports:
|
|
31
31
|
// inline scalars `key: value`
|
|
32
|
-
// arrays
|
|
32
|
+
// inline flow arrays `key: []` / `key: [a, b, "c, d"]`
|
|
33
|
+
// block arrays `key:\n - item\n - item`
|
|
33
34
|
// folded block scalar `key: >\n one line\n continues` → "one line continues"
|
|
34
35
|
// literal block scalar `key: |\n one\n two` → "one\ntwo"
|
|
35
36
|
// chomping indicators `>-`, `|-` (strip), `>+`, `|+` (keep), default (clip to one trailing \n)
|
|
@@ -73,10 +74,18 @@ export function parseSimpleFrontmatter(text, warnings) {
|
|
|
73
74
|
if (!trimmedValue) {
|
|
74
75
|
data[key] = [];
|
|
75
76
|
currentArrayKey = key;
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const flowArray = parseFlowArray(trimmedValue);
|
|
81
|
+
if (flowArray !== null) {
|
|
82
|
+
data[key] = flowArray;
|
|
78
83
|
currentArrayKey = null;
|
|
84
|
+
continue;
|
|
79
85
|
}
|
|
86
|
+
|
|
87
|
+
data[key] = parseScalar(trimmedValue);
|
|
88
|
+
currentArrayKey = null;
|
|
80
89
|
continue;
|
|
81
90
|
}
|
|
82
91
|
|
|
@@ -169,6 +178,41 @@ function collectBlockScalar(lines, startIdx, style, chomp) {
|
|
|
169
178
|
return { value, consumed: i - startIdx };
|
|
170
179
|
}
|
|
171
180
|
|
|
181
|
+
// Parses a YAML flow sequence like `[]`, `[a, b]`, `[a, "b, c", 'd']`.
|
|
182
|
+
// Returns an array on success, or null if the value isn't a well-formed
|
|
183
|
+
// `[…]` flow sequence (caller falls back to scalar parsing).
|
|
184
|
+
function parseFlowArray(value) {
|
|
185
|
+
if (!value.startsWith('[') || !value.endsWith(']')) return null;
|
|
186
|
+
const inner = value.slice(1, -1);
|
|
187
|
+
if (!inner.trim()) return [];
|
|
188
|
+
|
|
189
|
+
const items = [];
|
|
190
|
+
let current = '';
|
|
191
|
+
let quote = null;
|
|
192
|
+
for (let i = 0; i < inner.length; i++) {
|
|
193
|
+
const c = inner[i];
|
|
194
|
+
if (quote) {
|
|
195
|
+
current += c;
|
|
196
|
+
if (c === quote) quote = null;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (c === "'" || c === '"') {
|
|
200
|
+
quote = c;
|
|
201
|
+
current += c;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (c === ',') {
|
|
205
|
+
items.push(parseScalar(current.trim()));
|
|
206
|
+
current = '';
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
current += c;
|
|
210
|
+
}
|
|
211
|
+
if (quote !== null) return null; // unterminated quote — not a valid flow array
|
|
212
|
+
items.push(parseScalar(current.trim()));
|
|
213
|
+
return items;
|
|
214
|
+
}
|
|
215
|
+
|
|
172
216
|
function parseScalar(value) {
|
|
173
217
|
let unquoted = value;
|
|
174
218
|
if (value.length > 1 &&
|
package/src/new.mjs
CHANGED
|
@@ -17,12 +17,12 @@ const BUILTIN_TEMPLATES = {
|
|
|
17
17
|
`status: ${s}`,
|
|
18
18
|
`created: ${d}`,
|
|
19
19
|
`updated: ${d}`,
|
|
20
|
-
'modules:
|
|
21
|
-
'surfaces:
|
|
20
|
+
'modules:',
|
|
21
|
+
'surfaces:',
|
|
22
22
|
'domain:',
|
|
23
23
|
'audience: internal',
|
|
24
|
-
'related_plans:
|
|
25
|
-
'related_docs:
|
|
24
|
+
'related_plans:',
|
|
25
|
+
'related_docs:',
|
|
26
26
|
].join('\n'),
|
|
27
27
|
body: (t, ctx) => `
|
|
28
28
|
# ${t}
|
|
@@ -50,13 +50,13 @@ const BUILTIN_TEMPLATES = {
|
|
|
50
50
|
`status: ${s}`,
|
|
51
51
|
`created: ${d}`,
|
|
52
52
|
`updated: ${d}`,
|
|
53
|
-
'surfaces:
|
|
54
|
-
'modules:
|
|
53
|
+
'surfaces:',
|
|
54
|
+
'modules:',
|
|
55
55
|
'domain:',
|
|
56
56
|
'audience: internal',
|
|
57
57
|
'parent_plan:',
|
|
58
|
-
'related_plans:
|
|
59
|
-
'related_docs:
|
|
58
|
+
'related_plans:',
|
|
59
|
+
'related_docs:',
|
|
60
60
|
'current_state:',
|
|
61
61
|
'next_step:',
|
|
62
62
|
].join('\n'),
|
|
@@ -132,7 +132,7 @@ Status markers (put in heading text):
|
|
|
132
132
|
`created: ${d}`,
|
|
133
133
|
`dotmd_version: ${pkg.version}`,
|
|
134
134
|
`context: ${ctx?.title ? `"${ctx.title.replace(/"/g, '\\"')}"` : ''}`,
|
|
135
|
-
'related_plans:
|
|
135
|
+
'related_plans:',
|
|
136
136
|
].join('\n'),
|
|
137
137
|
body: (t, ctx) => `\n${ctx?.bodyInput ?? '<!-- prompt body -->'}\n`,
|
|
138
138
|
},
|
package/src/validate.mjs
CHANGED
|
@@ -29,7 +29,7 @@ export function validateDoc(doc, frontmatter, headingTitle, config) {
|
|
|
29
29
|
const rootSet = config.rootValidStatuses?.get(doc.root);
|
|
30
30
|
const combined = new Set([...(typeSet ?? []), ...(rootSet ?? config.validStatuses)]);
|
|
31
31
|
const hint = `valid: ${[...combined].join(', ')}`;
|
|
32
|
-
doc.
|
|
32
|
+
doc.errors.push({ path: doc.path, level: 'error', message: `Unknown status \`${doc.status}\`; ${hint}.` });
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const knownStatus = isValidStatus(doc.status, doc.root, config, doc.type);
|