kanban-lite 1.0.21 → 1.0.22

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/dist/cli.js CHANGED
@@ -2714,7 +2714,7 @@ function renamed(from, to) {
2714
2714
  throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
2715
2715
  };
2716
2716
  }
2717
- var isNothing_1, isObject_1, toArray_1, repeat_1, isNegativeZero_1, extend_1, common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type, schema, str, seq, map, failsafe, _null, bool, int, YAML_FLOAT_PATTERN, SCIENTIFIC_WITHOUT_DOT, float, json, core, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestamp, merge, BASE64_MAP, binary, _hasOwnProperty$3, _toString$2, omap, _toString$1, pairs, _hasOwnProperty$2, set, _default, _hasOwnProperty$1, CONTEXT_FLOW_IN, CONTEXT_FLOW_OUT, CONTEXT_BLOCK_IN, CONTEXT_BLOCK_OUT, CHOMPING_CLIP, CHOMPING_STRIP, CHOMPING_KEEP, PATTERN_NON_PRINTABLE, PATTERN_NON_ASCII_LINE_BREAKS, PATTERN_FLOW_INDICATORS, PATTERN_TAG_HANDLE, PATTERN_TAG_URI, simpleEscapeCheck, simpleEscapeMap, i, directiveHandlers, loadAll_1, load_1, loader, _toString, _hasOwnProperty, CHAR_BOM, CHAR_TAB, CHAR_LINE_FEED, CHAR_CARRIAGE_RETURN, CHAR_SPACE, CHAR_EXCLAMATION, CHAR_DOUBLE_QUOTE, CHAR_SHARP, CHAR_PERCENT, CHAR_AMPERSAND, CHAR_SINGLE_QUOTE, CHAR_ASTERISK, CHAR_COMMA, CHAR_MINUS, CHAR_COLON, CHAR_EQUALS, CHAR_GREATER_THAN, CHAR_QUESTION, CHAR_COMMERCIAL_AT, CHAR_LEFT_SQUARE_BRACKET, CHAR_RIGHT_SQUARE_BRACKET, CHAR_GRAVE_ACCENT, CHAR_LEFT_CURLY_BRACKET, CHAR_VERTICAL_LINE, CHAR_RIGHT_CURLY_BRACKET, ESCAPE_SEQUENCES, DEPRECATED_BOOLEANS_SYNTAX, DEPRECATED_BASE60_SYNTAX, QUOTING_TYPE_SINGLE, QUOTING_TYPE_DOUBLE, STYLE_PLAIN, STYLE_SINGLE, STYLE_LITERAL, STYLE_FOLDED, STYLE_DOUBLE, dump_1, dumper, load, loadAll, dump, safeLoad, safeLoadAll, safeDump;
2717
+ var isNothing_1, isObject_1, toArray_1, repeat_1, isNegativeZero_1, extend_1, common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type, schema, str, seq, map, failsafe, _null, bool, int, YAML_FLOAT_PATTERN, SCIENTIFIC_WITHOUT_DOT, float, json, core, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestamp, merge, BASE64_MAP, binary, _hasOwnProperty$3, _toString$2, omap, _toString$1, pairs, _hasOwnProperty$2, set, _default, _hasOwnProperty$1, CONTEXT_FLOW_IN, CONTEXT_FLOW_OUT, CONTEXT_BLOCK_IN, CONTEXT_BLOCK_OUT, CHOMPING_CLIP, CHOMPING_STRIP, CHOMPING_KEEP, PATTERN_NON_PRINTABLE, PATTERN_NON_ASCII_LINE_BREAKS, PATTERN_FLOW_INDICATORS, PATTERN_TAG_HANDLE, PATTERN_TAG_URI, simpleEscapeCheck, simpleEscapeMap, i, directiveHandlers, loadAll_1, load_1, loader, _toString, _hasOwnProperty, CHAR_BOM, CHAR_TAB, CHAR_LINE_FEED, CHAR_CARRIAGE_RETURN, CHAR_SPACE, CHAR_EXCLAMATION, CHAR_DOUBLE_QUOTE, CHAR_SHARP, CHAR_PERCENT, CHAR_AMPERSAND, CHAR_SINGLE_QUOTE, CHAR_ASTERISK, CHAR_COMMA, CHAR_MINUS, CHAR_COLON, CHAR_EQUALS, CHAR_GREATER_THAN, CHAR_QUESTION, CHAR_COMMERCIAL_AT, CHAR_LEFT_SQUARE_BRACKET, CHAR_RIGHT_SQUARE_BRACKET, CHAR_GRAVE_ACCENT, CHAR_LEFT_CURLY_BRACKET, CHAR_VERTICAL_LINE, CHAR_RIGHT_CURLY_BRACKET, ESCAPE_SEQUENCES, DEPRECATED_BOOLEANS_SYNTAX, DEPRECATED_BASE60_SYNTAX, QUOTING_TYPE_SINGLE, QUOTING_TYPE_DOUBLE, STYLE_PLAIN, STYLE_SINGLE, STYLE_LITERAL, STYLE_FOLDED, STYLE_DOUBLE, dump_1, dumper, JSON_SCHEMA, load, loadAll, dump, safeLoad, safeLoadAll, safeDump;
2718
2718
  var init_js_yaml = __esm({
2719
2719
  "node_modules/js-yaml/dist/js-yaml.mjs"() {
2720
2720
  isNothing_1 = isNothing;
@@ -3115,6 +3115,7 @@ var init_js_yaml = __esm({
3115
3115
  dumper = {
3116
3116
  dump: dump_1
3117
3117
  };
3118
+ JSON_SCHEMA = json;
3118
3119
  load = loader.load;
3119
3120
  loadAll = loader.loadAll;
3120
3121
  dump = dumper.dump;
@@ -3155,48 +3156,26 @@ function parseFeatureFile(content, filePath) {
3155
3156
  return null;
3156
3157
  const frontmatter = frontmatterMatch[1];
3157
3158
  const rest = frontmatterMatch[2] || "";
3158
- const getValue = (key) => {
3159
- const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
3160
- if (!match)
3159
+ let parsed;
3160
+ try {
3161
+ const loaded = load(frontmatter, { schema: JSON_SCHEMA });
3162
+ if (!loaded || typeof loaded !== "object" || Array.isArray(loaded))
3163
+ return null;
3164
+ parsed = loaded;
3165
+ } catch {
3166
+ return null;
3167
+ }
3168
+ const str2 = (key) => {
3169
+ const val = parsed[key];
3170
+ if (val == null)
3161
3171
  return "";
3162
- const value = match[1].trim().replace(/^["']|["']$/g, "");
3163
- return value === "null" ? "" : value;
3172
+ return String(val);
3164
3173
  };
3165
- const getArrayValue = (key) => {
3166
- const match = frontmatter.match(new RegExp(`^${key}:\\s*\\[([^\\]]*)\\]`, "m"));
3167
- if (!match)
3174
+ const arr = (key) => {
3175
+ const val = parsed[key];
3176
+ if (!Array.isArray(val))
3168
3177
  return [];
3169
- return match[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
3170
- };
3171
- const getMetadata = () => {
3172
- const lines = frontmatter.split("\n");
3173
- let metaStart = -1;
3174
- for (let j = 0; j < lines.length; j++) {
3175
- if (/^metadata:\s*$/.test(lines[j])) {
3176
- metaStart = j + 1;
3177
- break;
3178
- }
3179
- }
3180
- if (metaStart === -1)
3181
- return void 0;
3182
- const indentedLines = [];
3183
- for (let j = metaStart; j < lines.length; j++) {
3184
- if (/^\s/.test(lines[j]) || lines[j].trim() === "") {
3185
- indentedLines.push(lines[j]);
3186
- } else {
3187
- break;
3188
- }
3189
- }
3190
- if (indentedLines.length === 0)
3191
- return void 0;
3192
- try {
3193
- const parsed = load(indentedLines.join("\n"));
3194
- if (parsed && typeof parsed === "object")
3195
- return parsed;
3196
- return void 0;
3197
- } catch {
3198
- return void 0;
3199
- }
3178
+ return val.filter((v) => v != null).map(String);
3200
3179
  };
3201
3180
  const sections = rest.split(/\n---\n/);
3202
3181
  let body = sections[0] || "";
@@ -3217,22 +3196,23 @@ ${section}`;
3217
3196
  i += 1;
3218
3197
  }
3219
3198
  }
3220
- const meta = getMetadata();
3221
- const actions = getArrayValue("actions");
3199
+ const actions = arr("actions");
3200
+ const rawMeta = parsed.metadata;
3201
+ const meta = rawMeta != null && typeof rawMeta === "object" && !Array.isArray(rawMeta) ? rawMeta : void 0;
3222
3202
  return {
3223
- version: parseInt(getValue("version"), 10) || 0,
3224
- id: getValue("id") || extractIdFromFilename(filePath),
3225
- status: getValue("status") || "backlog",
3226
- priority: getValue("priority") || "medium",
3227
- assignee: getValue("assignee") || null,
3228
- dueDate: getValue("dueDate") || null,
3229
- created: getValue("created") || (/* @__PURE__ */ new Date()).toISOString(),
3230
- modified: getValue("modified") || (/* @__PURE__ */ new Date()).toISOString(),
3231
- completedAt: getValue("completedAt") || null,
3232
- labels: getArrayValue("labels"),
3233
- attachments: getArrayValue("attachments"),
3203
+ version: typeof parsed.version === "number" ? parsed.version : parseInt(str2("version"), 10) || 0,
3204
+ id: str2("id") || extractIdFromFilename(filePath),
3205
+ status: str2("status") || "backlog",
3206
+ priority: str2("priority") || "medium",
3207
+ assignee: parsed.assignee != null ? String(parsed.assignee) : null,
3208
+ dueDate: parsed.dueDate != null ? String(parsed.dueDate) : null,
3209
+ created: str2("created") || (/* @__PURE__ */ new Date()).toISOString(),
3210
+ modified: str2("modified") || (/* @__PURE__ */ new Date()).toISOString(),
3211
+ completedAt: parsed.completedAt != null ? String(parsed.completedAt) : null,
3212
+ labels: arr("labels"),
3213
+ attachments: arr("attachments"),
3234
3214
  comments,
3235
- order: getValue("order") || "a0",
3215
+ order: str2("order") || "a0",
3236
3216
  content: body.trim(),
3237
3217
  ...meta ? { metadata: meta } : {},
3238
3218
  ...actions.length > 0 ? { actions } : {},
@@ -3240,37 +3220,28 @@ ${section}`;
3240
3220
  };
3241
3221
  }
3242
3222
  function serializeFeature(feature) {
3243
- const lines = [
3244
- "---",
3245
- `version: ${feature.version ?? CARD_FORMAT_VERSION}`,
3246
- `id: "${feature.id}"`,
3247
- `status: "${feature.status}"`,
3248
- `priority: "${feature.priority}"`,
3249
- `assignee: ${feature.assignee ? `"${feature.assignee}"` : "null"}`,
3250
- `dueDate: ${feature.dueDate ? `"${feature.dueDate}"` : "null"}`,
3251
- `created: "${feature.created}"`,
3252
- `modified: "${feature.modified}"`,
3253
- `completedAt: ${feature.completedAt ? `"${feature.completedAt}"` : "null"}`,
3254
- `labels: [${feature.labels.map((l) => `"${l}"`).join(", ")}]`,
3255
- `attachments: [${(feature.attachments || []).map((a) => `"${a}"`).join(", ")}]`,
3256
- `order: "${feature.order}"`
3257
- ];
3258
- if (feature.actions && feature.actions.length > 0) {
3259
- lines.push(`actions: [${feature.actions.map((a) => `"${a}"`).join(", ")}]`);
3260
- }
3261
- if (feature.metadata && Object.keys(feature.metadata).length > 0) {
3262
- const metaYaml = dump(feature.metadata, { indent: 2, lineWidth: -1 });
3263
- lines.push("metadata:");
3264
- for (const line of metaYaml.trimEnd().split("\n")) {
3265
- lines.push(" " + line);
3266
- }
3267
- }
3268
- lines.push("---");
3269
- lines.push("");
3270
- const frontmatter = lines.join("\n");
3271
- let result = frontmatter + feature.content;
3272
- const comments = feature.comments || [];
3273
- for (const comment of comments) {
3223
+ const frontmatterObj = {
3224
+ version: feature.version ?? CARD_FORMAT_VERSION,
3225
+ id: feature.id,
3226
+ status: feature.status,
3227
+ priority: feature.priority,
3228
+ assignee: feature.assignee ?? null,
3229
+ dueDate: feature.dueDate ?? null,
3230
+ created: feature.created,
3231
+ modified: feature.modified,
3232
+ completedAt: feature.completedAt ?? null,
3233
+ labels: feature.labels,
3234
+ attachments: feature.attachments || [],
3235
+ order: feature.order,
3236
+ ...feature.actions?.length ? { actions: feature.actions } : {},
3237
+ ...feature.metadata && Object.keys(feature.metadata).length > 0 ? { metadata: feature.metadata } : {}
3238
+ };
3239
+ const yamlStr = dump(frontmatterObj, { lineWidth: -1, quotingType: '"', forceQuotes: true });
3240
+ let result = `---
3241
+ ${yamlStr}---
3242
+
3243
+ ${feature.content}`;
3244
+ for (const comment of feature.comments || []) {
3274
3245
  result += "\n\n---\n";
3275
3246
  result += `comment: true
3276
3247
  `;
package/dist/extension.js CHANGED
@@ -6859,6 +6859,7 @@ function renamed(from, to) {
6859
6859
  throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
6860
6860
  };
6861
6861
  }
6862
+ var JSON_SCHEMA = json;
6862
6863
  var load = loader.load;
6863
6864
  var loadAll = loader.loadAll;
6864
6865
  var dump = dumper.dump;
@@ -6898,48 +6899,26 @@ function parseFeatureFile(content, filePath) {
6898
6899
  return null;
6899
6900
  const frontmatter = frontmatterMatch[1];
6900
6901
  const rest = frontmatterMatch[2] || "";
6901
- const getValue = (key) => {
6902
- const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
6903
- if (!match)
6902
+ let parsed;
6903
+ try {
6904
+ const loaded = load(frontmatter, { schema: JSON_SCHEMA });
6905
+ if (!loaded || typeof loaded !== "object" || Array.isArray(loaded))
6906
+ return null;
6907
+ parsed = loaded;
6908
+ } catch {
6909
+ return null;
6910
+ }
6911
+ const str2 = (key) => {
6912
+ const val = parsed[key];
6913
+ if (val == null)
6904
6914
  return "";
6905
- const value = match[1].trim().replace(/^["']|["']$/g, "");
6906
- return value === "null" ? "" : value;
6915
+ return String(val);
6907
6916
  };
6908
- const getArrayValue = (key) => {
6909
- const match = frontmatter.match(new RegExp(`^${key}:\\s*\\[([^\\]]*)\\]`, "m"));
6910
- if (!match)
6917
+ const arr = (key) => {
6918
+ const val = parsed[key];
6919
+ if (!Array.isArray(val))
6911
6920
  return [];
6912
- return match[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
6913
- };
6914
- const getMetadata = () => {
6915
- const lines = frontmatter.split("\n");
6916
- let metaStart = -1;
6917
- for (let j = 0; j < lines.length; j++) {
6918
- if (/^metadata:\s*$/.test(lines[j])) {
6919
- metaStart = j + 1;
6920
- break;
6921
- }
6922
- }
6923
- if (metaStart === -1)
6924
- return void 0;
6925
- const indentedLines = [];
6926
- for (let j = metaStart; j < lines.length; j++) {
6927
- if (/^\s/.test(lines[j]) || lines[j].trim() === "") {
6928
- indentedLines.push(lines[j]);
6929
- } else {
6930
- break;
6931
- }
6932
- }
6933
- if (indentedLines.length === 0)
6934
- return void 0;
6935
- try {
6936
- const parsed = load(indentedLines.join("\n"));
6937
- if (parsed && typeof parsed === "object")
6938
- return parsed;
6939
- return void 0;
6940
- } catch {
6941
- return void 0;
6942
- }
6921
+ return val.filter((v) => v != null).map(String);
6943
6922
  };
6944
6923
  const sections = rest.split(/\n---\n/);
6945
6924
  let body = sections[0] || "";
@@ -6960,22 +6939,23 @@ ${section}`;
6960
6939
  i += 1;
6961
6940
  }
6962
6941
  }
6963
- const meta = getMetadata();
6964
- const actions = getArrayValue("actions");
6942
+ const actions = arr("actions");
6943
+ const rawMeta = parsed.metadata;
6944
+ const meta = rawMeta != null && typeof rawMeta === "object" && !Array.isArray(rawMeta) ? rawMeta : void 0;
6965
6945
  return {
6966
- version: parseInt(getValue("version"), 10) || 0,
6967
- id: getValue("id") || extractIdFromFilename(filePath),
6968
- status: getValue("status") || "backlog",
6969
- priority: getValue("priority") || "medium",
6970
- assignee: getValue("assignee") || null,
6971
- dueDate: getValue("dueDate") || null,
6972
- created: getValue("created") || (/* @__PURE__ */ new Date()).toISOString(),
6973
- modified: getValue("modified") || (/* @__PURE__ */ new Date()).toISOString(),
6974
- completedAt: getValue("completedAt") || null,
6975
- labels: getArrayValue("labels"),
6976
- attachments: getArrayValue("attachments"),
6946
+ version: typeof parsed.version === "number" ? parsed.version : parseInt(str2("version"), 10) || 0,
6947
+ id: str2("id") || extractIdFromFilename(filePath),
6948
+ status: str2("status") || "backlog",
6949
+ priority: str2("priority") || "medium",
6950
+ assignee: parsed.assignee != null ? String(parsed.assignee) : null,
6951
+ dueDate: parsed.dueDate != null ? String(parsed.dueDate) : null,
6952
+ created: str2("created") || (/* @__PURE__ */ new Date()).toISOString(),
6953
+ modified: str2("modified") || (/* @__PURE__ */ new Date()).toISOString(),
6954
+ completedAt: parsed.completedAt != null ? String(parsed.completedAt) : null,
6955
+ labels: arr("labels"),
6956
+ attachments: arr("attachments"),
6977
6957
  comments,
6978
- order: getValue("order") || "a0",
6958
+ order: str2("order") || "a0",
6979
6959
  content: body.trim(),
6980
6960
  ...meta ? { metadata: meta } : {},
6981
6961
  ...actions.length > 0 ? { actions } : {},
@@ -6983,37 +6963,28 @@ ${section}`;
6983
6963
  };
6984
6964
  }
6985
6965
  function serializeFeature(feature) {
6986
- const lines = [
6987
- "---",
6988
- `version: ${feature.version ?? CARD_FORMAT_VERSION}`,
6989
- `id: "${feature.id}"`,
6990
- `status: "${feature.status}"`,
6991
- `priority: "${feature.priority}"`,
6992
- `assignee: ${feature.assignee ? `"${feature.assignee}"` : "null"}`,
6993
- `dueDate: ${feature.dueDate ? `"${feature.dueDate}"` : "null"}`,
6994
- `created: "${feature.created}"`,
6995
- `modified: "${feature.modified}"`,
6996
- `completedAt: ${feature.completedAt ? `"${feature.completedAt}"` : "null"}`,
6997
- `labels: [${feature.labels.map((l) => `"${l}"`).join(", ")}]`,
6998
- `attachments: [${(feature.attachments || []).map((a) => `"${a}"`).join(", ")}]`,
6999
- `order: "${feature.order}"`
7000
- ];
7001
- if (feature.actions && feature.actions.length > 0) {
7002
- lines.push(`actions: [${feature.actions.map((a) => `"${a}"`).join(", ")}]`);
7003
- }
7004
- if (feature.metadata && Object.keys(feature.metadata).length > 0) {
7005
- const metaYaml = dump(feature.metadata, { indent: 2, lineWidth: -1 });
7006
- lines.push("metadata:");
7007
- for (const line of metaYaml.trimEnd().split("\n")) {
7008
- lines.push(" " + line);
7009
- }
7010
- }
7011
- lines.push("---");
7012
- lines.push("");
7013
- const frontmatter = lines.join("\n");
7014
- let result = frontmatter + feature.content;
7015
- const comments = feature.comments || [];
7016
- for (const comment of comments) {
6966
+ const frontmatterObj = {
6967
+ version: feature.version ?? CARD_FORMAT_VERSION,
6968
+ id: feature.id,
6969
+ status: feature.status,
6970
+ priority: feature.priority,
6971
+ assignee: feature.assignee ?? null,
6972
+ dueDate: feature.dueDate ?? null,
6973
+ created: feature.created,
6974
+ modified: feature.modified,
6975
+ completedAt: feature.completedAt ?? null,
6976
+ labels: feature.labels,
6977
+ attachments: feature.attachments || [],
6978
+ order: feature.order,
6979
+ ...feature.actions?.length ? { actions: feature.actions } : {},
6980
+ ...feature.metadata && Object.keys(feature.metadata).length > 0 ? { metadata: feature.metadata } : {}
6981
+ };
6982
+ const yamlStr = dump(frontmatterObj, { lineWidth: -1, quotingType: '"', forceQuotes: true });
6983
+ let result = `---
6984
+ ${yamlStr}---
6985
+
6986
+ ${feature.content}`;
6987
+ for (const comment of feature.comments || []) {
7017
6988
  result += "\n\n---\n";
7018
6989
  result += `comment: true
7019
6990
  `;
@@ -3099,6 +3099,7 @@ function renamed(from, to) {
3099
3099
  throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
3100
3100
  };
3101
3101
  }
3102
+ var JSON_SCHEMA = json;
3102
3103
  var load = loader.load;
3103
3104
  var loadAll = loader.loadAll;
3104
3105
  var dump = dumper.dump;
@@ -3137,48 +3138,26 @@ function parseFeatureFile(content, filePath) {
3137
3138
  return null;
3138
3139
  const frontmatter = frontmatterMatch[1];
3139
3140
  const rest = frontmatterMatch[2] || "";
3140
- const getValue = (key) => {
3141
- const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
3142
- if (!match)
3141
+ let parsed;
3142
+ try {
3143
+ const loaded = load(frontmatter, { schema: JSON_SCHEMA });
3144
+ if (!loaded || typeof loaded !== "object" || Array.isArray(loaded))
3145
+ return null;
3146
+ parsed = loaded;
3147
+ } catch {
3148
+ return null;
3149
+ }
3150
+ const str2 = (key) => {
3151
+ const val = parsed[key];
3152
+ if (val == null)
3143
3153
  return "";
3144
- const value = match[1].trim().replace(/^["']|["']$/g, "");
3145
- return value === "null" ? "" : value;
3154
+ return String(val);
3146
3155
  };
3147
- const getArrayValue = (key) => {
3148
- const match = frontmatter.match(new RegExp(`^${key}:\\s*\\[([^\\]]*)\\]`, "m"));
3149
- if (!match)
3156
+ const arr = (key) => {
3157
+ const val = parsed[key];
3158
+ if (!Array.isArray(val))
3150
3159
  return [];
3151
- return match[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
3152
- };
3153
- const getMetadata = () => {
3154
- const lines = frontmatter.split("\n");
3155
- let metaStart = -1;
3156
- for (let j = 0; j < lines.length; j++) {
3157
- if (/^metadata:\s*$/.test(lines[j])) {
3158
- metaStart = j + 1;
3159
- break;
3160
- }
3161
- }
3162
- if (metaStart === -1)
3163
- return void 0;
3164
- const indentedLines = [];
3165
- for (let j = metaStart; j < lines.length; j++) {
3166
- if (/^\s/.test(lines[j]) || lines[j].trim() === "") {
3167
- indentedLines.push(lines[j]);
3168
- } else {
3169
- break;
3170
- }
3171
- }
3172
- if (indentedLines.length === 0)
3173
- return void 0;
3174
- try {
3175
- const parsed = load(indentedLines.join("\n"));
3176
- if (parsed && typeof parsed === "object")
3177
- return parsed;
3178
- return void 0;
3179
- } catch {
3180
- return void 0;
3181
- }
3160
+ return val.filter((v) => v != null).map(String);
3182
3161
  };
3183
3162
  const sections = rest.split(/\n---\n/);
3184
3163
  let body = sections[0] || "";
@@ -3199,22 +3178,23 @@ ${section}`;
3199
3178
  i += 1;
3200
3179
  }
3201
3180
  }
3202
- const meta = getMetadata();
3203
- const actions = getArrayValue("actions");
3181
+ const actions = arr("actions");
3182
+ const rawMeta = parsed.metadata;
3183
+ const meta = rawMeta != null && typeof rawMeta === "object" && !Array.isArray(rawMeta) ? rawMeta : void 0;
3204
3184
  return {
3205
- version: parseInt(getValue("version"), 10) || 0,
3206
- id: getValue("id") || extractIdFromFilename(filePath),
3207
- status: getValue("status") || "backlog",
3208
- priority: getValue("priority") || "medium",
3209
- assignee: getValue("assignee") || null,
3210
- dueDate: getValue("dueDate") || null,
3211
- created: getValue("created") || (/* @__PURE__ */ new Date()).toISOString(),
3212
- modified: getValue("modified") || (/* @__PURE__ */ new Date()).toISOString(),
3213
- completedAt: getValue("completedAt") || null,
3214
- labels: getArrayValue("labels"),
3215
- attachments: getArrayValue("attachments"),
3185
+ version: typeof parsed.version === "number" ? parsed.version : parseInt(str2("version"), 10) || 0,
3186
+ id: str2("id") || extractIdFromFilename(filePath),
3187
+ status: str2("status") || "backlog",
3188
+ priority: str2("priority") || "medium",
3189
+ assignee: parsed.assignee != null ? String(parsed.assignee) : null,
3190
+ dueDate: parsed.dueDate != null ? String(parsed.dueDate) : null,
3191
+ created: str2("created") || (/* @__PURE__ */ new Date()).toISOString(),
3192
+ modified: str2("modified") || (/* @__PURE__ */ new Date()).toISOString(),
3193
+ completedAt: parsed.completedAt != null ? String(parsed.completedAt) : null,
3194
+ labels: arr("labels"),
3195
+ attachments: arr("attachments"),
3216
3196
  comments,
3217
- order: getValue("order") || "a0",
3197
+ order: str2("order") || "a0",
3218
3198
  content: body.trim(),
3219
3199
  ...meta ? { metadata: meta } : {},
3220
3200
  ...actions.length > 0 ? { actions } : {},
@@ -3222,37 +3202,28 @@ ${section}`;
3222
3202
  };
3223
3203
  }
3224
3204
  function serializeFeature(feature) {
3225
- const lines = [
3226
- "---",
3227
- `version: ${feature.version ?? CARD_FORMAT_VERSION}`,
3228
- `id: "${feature.id}"`,
3229
- `status: "${feature.status}"`,
3230
- `priority: "${feature.priority}"`,
3231
- `assignee: ${feature.assignee ? `"${feature.assignee}"` : "null"}`,
3232
- `dueDate: ${feature.dueDate ? `"${feature.dueDate}"` : "null"}`,
3233
- `created: "${feature.created}"`,
3234
- `modified: "${feature.modified}"`,
3235
- `completedAt: ${feature.completedAt ? `"${feature.completedAt}"` : "null"}`,
3236
- `labels: [${feature.labels.map((l) => `"${l}"`).join(", ")}]`,
3237
- `attachments: [${(feature.attachments || []).map((a) => `"${a}"`).join(", ")}]`,
3238
- `order: "${feature.order}"`
3239
- ];
3240
- if (feature.actions && feature.actions.length > 0) {
3241
- lines.push(`actions: [${feature.actions.map((a) => `"${a}"`).join(", ")}]`);
3242
- }
3243
- if (feature.metadata && Object.keys(feature.metadata).length > 0) {
3244
- const metaYaml = dump(feature.metadata, { indent: 2, lineWidth: -1 });
3245
- lines.push("metadata:");
3246
- for (const line of metaYaml.trimEnd().split("\n")) {
3247
- lines.push(" " + line);
3248
- }
3249
- }
3250
- lines.push("---");
3251
- lines.push("");
3252
- const frontmatter = lines.join("\n");
3253
- let result = frontmatter + feature.content;
3254
- const comments = feature.comments || [];
3255
- for (const comment of comments) {
3205
+ const frontmatterObj = {
3206
+ version: feature.version ?? CARD_FORMAT_VERSION,
3207
+ id: feature.id,
3208
+ status: feature.status,
3209
+ priority: feature.priority,
3210
+ assignee: feature.assignee ?? null,
3211
+ dueDate: feature.dueDate ?? null,
3212
+ created: feature.created,
3213
+ modified: feature.modified,
3214
+ completedAt: feature.completedAt ?? null,
3215
+ labels: feature.labels,
3216
+ attachments: feature.attachments || [],
3217
+ order: feature.order,
3218
+ ...feature.actions?.length ? { actions: feature.actions } : {},
3219
+ ...feature.metadata && Object.keys(feature.metadata).length > 0 ? { metadata: feature.metadata } : {}
3220
+ };
3221
+ const yamlStr = dump(frontmatterObj, { lineWidth: -1, quotingType: '"', forceQuotes: true });
3222
+ let result = `---
3223
+ ${yamlStr}---
3224
+
3225
+ ${feature.content}`;
3226
+ for (const comment of feature.comments || []) {
3256
3227
  result += "\n\n---\n";
3257
3228
  result += `comment: true
3258
3229
  `;