@equationalapplications/core-okf 4.17.3 → 4.18.1

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
@@ -8,6 +8,8 @@ A zero-dependency library for parsing and producing [Open Knowledge Format (OKF)
8
8
 
9
9
  For a ready-made `MemoryDump` ⇄ OKF bundle adapter, see the [OKF Import/Export section in `@equationalapplications/core-llm-wiki`](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/core/README.md#okf-importexport).
10
10
 
11
+ For the llm-wiki interoperability profile (llm-wiki/1), see [`docs/okf-profile.md`](https://github.com/equationalapplications/expo-llm-wiki/blob/main/docs/okf-profile.md). Conformance fixtures live in [`fixtures/`](./fixtures/).
12
+
11
13
  ## Installation
12
14
 
13
15
  ```bash
package/dist/index.d.mts CHANGED
@@ -54,9 +54,29 @@ declare function parseConcept(content: string): {
54
54
  };
55
55
 
56
56
  declare function buildIndexMd(sections: OkfIndexSection[]): string;
57
- declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string;
57
+ declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[], options?: {
58
+ profile?: string;
59
+ }): string;
60
+ declare function parseRootIndexMd(content: string): {
61
+ okf_version?: string;
62
+ profile?: string;
63
+ };
64
+
65
+ declare function buildEntityIndexMd(options: {
66
+ summary?: string;
67
+ sections: OkfIndexSection[];
68
+ }): string;
69
+ declare function parseEntityIndexMd(content: string): {
70
+ summary: string;
71
+ sections: OkfIndexSection[];
72
+ };
58
73
 
59
74
  declare function buildLogMd(entries: OkfLogEntry[]): string;
75
+ declare function appendEventIdComment(text: string, eventId: string): string;
76
+ declare function parseEventIdComment(text: string): {
77
+ text: string;
78
+ eventId?: string;
79
+ };
60
80
  /**
61
81
  * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact
62
82
  * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,
@@ -65,6 +85,17 @@ declare function buildLogMd(entries: OkfLogEntry[]): string;
65
85
  */
66
86
  declare function parseLogMd(content: string): OkfLogEntry[];
67
87
 
88
+ declare function appendRelatedSection(body: string, links: Array<{
89
+ edge_type: string;
90
+ path: string;
91
+ }>): string;
92
+ declare function splitRelatedSection(body: string): {
93
+ body: string;
94
+ relatedLinks: OkfMarkdownLink[];
95
+ };
96
+
97
+ declare function isAllowedOkfPath(filePath: string): boolean;
98
+
68
99
  /**
69
100
  * Extracts inline markdown links (`[text](path)`) from a concept body.
70
101
  * Single-line regex, not a CommonMark parser — reference-style links, links
@@ -74,4 +105,4 @@ declare function parseLogMd(content: string): OkfLogEntry[];
74
105
  */
75
106
  declare function extractMarkdownLinks(body: string): OkfMarkdownLink[];
76
107
 
77
- export { type OkfFile, type OkfFrontmatter, type OkfFrontmatterScalar, type OkfFrontmatterValue, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, type OkfMarkdownLink, buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, parseConcept, parseFrontmatter, parseLogMd, serializeFrontmatter };
108
+ export { type OkfFile, type OkfFrontmatter, type OkfFrontmatterScalar, type OkfFrontmatterValue, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, type OkfMarkdownLink, appendEventIdComment, appendRelatedSection, buildConceptDocument, buildEntityIndexMd, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, isAllowedOkfPath, parseConcept, parseEntityIndexMd, parseEventIdComment, parseFrontmatter, parseLogMd, parseRootIndexMd, serializeFrontmatter, splitRelatedSection };
package/dist/index.d.ts CHANGED
@@ -54,9 +54,29 @@ declare function parseConcept(content: string): {
54
54
  };
55
55
 
56
56
  declare function buildIndexMd(sections: OkfIndexSection[]): string;
57
- declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string;
57
+ declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[], options?: {
58
+ profile?: string;
59
+ }): string;
60
+ declare function parseRootIndexMd(content: string): {
61
+ okf_version?: string;
62
+ profile?: string;
63
+ };
64
+
65
+ declare function buildEntityIndexMd(options: {
66
+ summary?: string;
67
+ sections: OkfIndexSection[];
68
+ }): string;
69
+ declare function parseEntityIndexMd(content: string): {
70
+ summary: string;
71
+ sections: OkfIndexSection[];
72
+ };
58
73
 
59
74
  declare function buildLogMd(entries: OkfLogEntry[]): string;
75
+ declare function appendEventIdComment(text: string, eventId: string): string;
76
+ declare function parseEventIdComment(text: string): {
77
+ text: string;
78
+ eventId?: string;
79
+ };
60
80
  /**
61
81
  * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact
62
82
  * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,
@@ -65,6 +85,17 @@ declare function buildLogMd(entries: OkfLogEntry[]): string;
65
85
  */
66
86
  declare function parseLogMd(content: string): OkfLogEntry[];
67
87
 
88
+ declare function appendRelatedSection(body: string, links: Array<{
89
+ edge_type: string;
90
+ path: string;
91
+ }>): string;
92
+ declare function splitRelatedSection(body: string): {
93
+ body: string;
94
+ relatedLinks: OkfMarkdownLink[];
95
+ };
96
+
97
+ declare function isAllowedOkfPath(filePath: string): boolean;
98
+
68
99
  /**
69
100
  * Extracts inline markdown links (`[text](path)`) from a concept body.
70
101
  * Single-line regex, not a CommonMark parser — reference-style links, links
@@ -74,4 +105,4 @@ declare function parseLogMd(content: string): OkfLogEntry[];
74
105
  */
75
106
  declare function extractMarkdownLinks(body: string): OkfMarkdownLink[];
76
107
 
77
- export { type OkfFile, type OkfFrontmatter, type OkfFrontmatterScalar, type OkfFrontmatterValue, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, type OkfMarkdownLink, buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, parseConcept, parseFrontmatter, parseLogMd, serializeFrontmatter };
108
+ export { type OkfFile, type OkfFrontmatter, type OkfFrontmatterScalar, type OkfFrontmatterValue, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, type OkfMarkdownLink, appendEventIdComment, appendRelatedSection, buildConceptDocument, buildEntityIndexMd, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, isAllowedOkfPath, parseConcept, parseEntityIndexMd, parseEventIdComment, parseFrontmatter, parseLogMd, parseRootIndexMd, serializeFrontmatter, splitRelatedSection };
package/dist/index.js CHANGED
@@ -216,14 +216,87 @@ function renderSections(sections) {
216
216
  function buildIndexMd(sections) {
217
217
  return renderSections(sections);
218
218
  }
219
- function buildRootIndexMd(okfVersion, sections) {
220
- const frontmatter = `---
221
- okf_version: ${serializeScalarString(okfVersion)}
222
- ---
223
- `;
224
- return `${frontmatter}
219
+ function buildRootIndexMd(okfVersion, sections, options) {
220
+ const lines = ["---", `okf_version: ${serializeScalarString(okfVersion)}`];
221
+ if (options?.profile) {
222
+ lines.push(`profile: ${serializeScalarString(options.profile)}`);
223
+ }
224
+ lines.push("---", "");
225
+ return `${lines.join("\n")}
225
226
  ${renderSections(sections)}`;
226
227
  }
228
+ function parseRootIndexMd(content) {
229
+ const { frontmatter } = parseFrontmatter(content);
230
+ const okf = frontmatter.okf_version;
231
+ return {
232
+ okf_version: typeof okf === "string" ? okf : typeof okf === "number" && Number.isFinite(okf) ? String(okf) : void 0,
233
+ profile: typeof frontmatter.profile === "string" ? frontmatter.profile : void 0
234
+ };
235
+ }
236
+
237
+ // src/entity-index-md.ts
238
+ var EVENT_LOG_LINK = /^\[Event log\]\(\.\/log\.md\)\s*$/;
239
+ var TOP_LEVEL_H1 = /^#\s+.+\s*$/;
240
+ var SECTION_HEADING = /^##\s+(.+)\s*$/;
241
+ var INDEX_ENTRY = /^\*\s+\[((?:\\.|[^\]])*)\]\(([^)]+)\)(?:\s+-\s+(.*))?$/;
242
+ function unescapeIndexTitle(title) {
243
+ return title.replace(/\\\]/g, "]").replace(/\\\[/g, "[").replace(/\\\\/g, "\\");
244
+ }
245
+ function buildEntityIndexMd(options) {
246
+ const parts = [];
247
+ if (options.summary?.trim()) {
248
+ parts.push(options.summary.trimEnd(), "");
249
+ }
250
+ const sectionsMd = buildIndexMd(options.sections).trimEnd();
251
+ if (sectionsMd) {
252
+ parts.push(sectionsMd);
253
+ parts.push("");
254
+ }
255
+ parts.push("[Event log](./log.md)");
256
+ return `${parts.join("\n")}
257
+ `;
258
+ }
259
+ function parseEntityIndexMd(content) {
260
+ const lines = content.split(/\r?\n/);
261
+ let start = 0;
262
+ if (lines[0]?.trim() === "---") {
263
+ const closing = lines.findIndex((line, idx) => idx > 0 && line.trim() === "---");
264
+ if (closing !== -1) start = closing + 1;
265
+ }
266
+ const firstSectionIdx = lines.findIndex((line, idx) => idx >= start && SECTION_HEADING.test(line));
267
+ const summaryEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx;
268
+ const summaryLines = lines.slice(start, summaryEnd).filter((line) => !EVENT_LOG_LINK.test(line.trim()));
269
+ let summaryStart = 0;
270
+ while (summaryStart < summaryLines.length && summaryLines[summaryStart].trim() === "") {
271
+ summaryStart += 1;
272
+ }
273
+ if (summaryStart < summaryLines.length && TOP_LEVEL_H1.test(summaryLines[summaryStart].trim())) {
274
+ summaryStart += 1;
275
+ }
276
+ const summary = summaryLines.slice(summaryStart).join("\n").trim();
277
+ const sections = [];
278
+ if (firstSectionIdx === -1) return { summary, sections };
279
+ let current = null;
280
+ for (let i = Math.max(firstSectionIdx, start); i < lines.length; i += 1) {
281
+ const line = lines[i];
282
+ if (EVENT_LOG_LINK.test(line.trim())) continue;
283
+ const headingMatch = SECTION_HEADING.exec(line);
284
+ if (headingMatch) {
285
+ current = { heading: headingMatch[1], entries: [] };
286
+ sections.push(current);
287
+ continue;
288
+ }
289
+ if (!current) continue;
290
+ const entryMatch = INDEX_ENTRY.exec(line);
291
+ if (!entryMatch) continue;
292
+ current.entries.push({
293
+ title: unescapeIndexTitle(entryMatch[1]),
294
+ path: entryMatch[2],
295
+ description: entryMatch[3] ? unescapeIndexTitle(entryMatch[3]) : void 0
296
+ });
297
+ }
298
+ return { summary, sections };
299
+ }
227
300
 
228
301
  // src/log-md.ts
229
302
  function buildLogMd(entries) {
@@ -246,6 +319,19 @@ function buildLogMd(entries) {
246
319
  if (lines.length === 0) return "";
247
320
  return lines.join("\n").trimEnd() + "\n";
248
321
  }
322
+ var EVENT_ID_COMMENT = /\s*<!--\s*id:\s*(\S+)\s*-->\s*$/;
323
+ function appendEventIdComment(text, eventId) {
324
+ if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return text;
325
+ return `${text} <!-- id: ${eventId} -->`;
326
+ }
327
+ function parseEventIdComment(text) {
328
+ const match = EVENT_ID_COMMENT.exec(text);
329
+ if (!match) return { text };
330
+ const eventId = match[1];
331
+ const stripped = text.slice(0, match.index).trimEnd();
332
+ if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return { text: stripped };
333
+ return { text: stripped, eventId };
334
+ }
249
335
  var DATE_HEADING = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
250
336
  var BULLET = /^-\s+(.*)$/;
251
337
  function parseLogMd(content) {
@@ -265,6 +351,66 @@ function parseLogMd(content) {
265
351
  return entries;
266
352
  }
267
353
 
354
+ // src/related-section.ts
355
+ function escapeLinkLabel(label) {
356
+ return label.replace(/\\/g, "\\\\").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/\r?\n/g, " ");
357
+ }
358
+ function appendRelatedSection(body, links) {
359
+ if (links.length === 0) return body;
360
+ const prefix = body.length === 0 ? "" : body.endsWith("\n\n") ? body : body.endsWith("\n") ? `${body}
361
+ ` : `${body}
362
+
363
+ `;
364
+ const lines = ["## Related", ""];
365
+ for (const link of links) {
366
+ lines.push(`- [${escapeLinkLabel(link.edge_type)}](${link.path})`);
367
+ }
368
+ return `${prefix}${lines.join("\n")}
369
+ `;
370
+ }
371
+ function splitRelatedSection(body) {
372
+ const lines = body.split(/\r?\n/);
373
+ let end = lines.length;
374
+ while (end > 0 && lines[end - 1].trim() === "") end -= 1;
375
+ let scan = end - 1;
376
+ while (scan >= 0 && /^-\s+/.test(lines[scan])) scan -= 1;
377
+ while (scan >= 0 && lines[scan].trim() === "") scan -= 1;
378
+ if (scan < 0 || lines[scan].trim() !== "## Related") {
379
+ return { body, relatedLinks: [] };
380
+ }
381
+ const relatedStart = scan;
382
+ const contentBody = lines.slice(0, relatedStart).join("\n");
383
+ const relatedBlock = lines.slice(relatedStart, end).join("\n");
384
+ const relatedLinks = [];
385
+ for (const line of relatedBlock.split(/\r?\n/)) {
386
+ const bullet = /^-\s+(.*)$/.exec(line);
387
+ if (!bullet) continue;
388
+ const linkPattern = /\[((?:\\.|[^\]])*)\]\(([^)\s]+)\)/g;
389
+ let match;
390
+ while ((match = linkPattern.exec(bullet[1])) !== null) {
391
+ const linkPath = match[2];
392
+ if (/^(https?:|mailto:)/i.test(linkPath)) continue;
393
+ relatedLinks.push({
394
+ text: match[1].replace(/\\\]/g, "]").replace(/\\\[/g, "[").replace(/\\\\/g, "\\"),
395
+ path: linkPath
396
+ });
397
+ }
398
+ }
399
+ const normalizedBody = contentBody.length === 0 ? "" : contentBody.endsWith("\n") ? contentBody : `${contentBody}
400
+ `;
401
+ return { body: normalizedBody, relatedLinks };
402
+ }
403
+
404
+ // src/path-allowlist.ts
405
+ var ALLOWED = /^(index\.md|entities\/[^/]+\/(index\.md|log\.md|(facts|tasks)\/[^/]+\.md))$/;
406
+ function isAllowedOkfPath(filePath) {
407
+ const normalized = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
408
+ if (normalized.split("/").some((segment) => segment === "." || segment === "..")) {
409
+ return false;
410
+ }
411
+ return ALLOWED.test(normalized);
412
+ }
413
+
268
414
  // src/markdown-links.ts
269
415
  var EXCLUDED_SCHEME = /^(https?:|mailto:)/i;
270
416
  var FENCED_CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
@@ -281,14 +427,22 @@ function extractMarkdownLinks(body) {
281
427
  return links;
282
428
  }
283
429
 
430
+ exports.appendEventIdComment = appendEventIdComment;
431
+ exports.appendRelatedSection = appendRelatedSection;
284
432
  exports.buildConceptDocument = buildConceptDocument;
433
+ exports.buildEntityIndexMd = buildEntityIndexMd;
285
434
  exports.buildIndexMd = buildIndexMd;
286
435
  exports.buildLogMd = buildLogMd;
287
436
  exports.buildRootIndexMd = buildRootIndexMd;
288
437
  exports.extractMarkdownLinks = extractMarkdownLinks;
438
+ exports.isAllowedOkfPath = isAllowedOkfPath;
289
439
  exports.parseConcept = parseConcept;
440
+ exports.parseEntityIndexMd = parseEntityIndexMd;
441
+ exports.parseEventIdComment = parseEventIdComment;
290
442
  exports.parseFrontmatter = parseFrontmatter;
291
443
  exports.parseLogMd = parseLogMd;
444
+ exports.parseRootIndexMd = parseRootIndexMd;
292
445
  exports.serializeFrontmatter = serializeFrontmatter;
446
+ exports.splitRelatedSection = splitRelatedSection;
293
447
  //# sourceMappingURL=index.js.map
294
448
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frontmatter.ts","../src/concept.ts","../src/index-md.ts","../src/log-md.ts","../src/markdown-links.ts"],"names":["i"],"mappings":"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","file":"index.js","sourcesContent":["import type { OkfFrontmatter, OkfFrontmatterScalar, OkfFrontmatterValue } from './types';\n\nconst RESERVED_LITERALS = new Set(['true', 'false', 'yes', 'no', 'on', 'off', 'null', '~', '']);\n\nfunction looksLikeNumber(value: string): boolean {\n return /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(value);\n}\n\nfunction isIso8601Timestamp(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2})$/.test(value);\n}\n\nfunction needsQuoting(value: string): boolean {\n if (value !== value.trim()) return true;\n if (/[\\n\\r\\t]/.test(value)) return true;\n if (isIso8601Timestamp(value)) return false;\n\n // Quote strings that YAML could otherwise parse as collections/indicators.\n if (/^[-?:]\\s/.test(value)) return true;\n if (/^[\\[\\]{}&,*%!|>'\"@`]/.test(value)) return true;\n\n if (value.includes(':') || value.includes('#')) return true;\n if (RESERVED_LITERALS.has(value.toLowerCase())) return true;\n if (looksLikeNumber(value)) return true;\n return false;\n}\n\nfunction quoteString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n}\n\nexport function serializeScalarString(value: string): string {\n return needsQuoting(value) ? quoteString(value) : value;\n}\n\nfunction serializeKey(key: string): string {\n // needsQuoting() intentionally exempts ISO 8601 timestamps for *values*.\n // For keys, quote timestamp-like scalars to avoid YAML timestamp coercion in some parsers.\n if (/\\s/.test(key) || needsQuoting(key) || isIso8601Timestamp(key)) {\n return quoteString(key);\n }\n return key;\n}\n\nfunction serializeValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') return serializeScalarString(value);\n throw new Error(`Unsupported frontmatter value type: ${typeof value}`);\n}\n\nexport function serializeFrontmatter(fm: OkfFrontmatter): string {\n const lines: string[] = ['---'];\n for (const [key, value] of Object.entries(fm)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n if (value.length === 0) {\n lines.push(`${serializeKey(key)}: []`);\n } else {\n lines.push(`${serializeKey(key)}:`);\n for (const item of value as unknown[]) {\n if (typeof item === 'string') {\n lines.push(` - ${serializeScalarString(item)}`);\n } else {\n lines.push(` - ${serializeValue(item)}`);\n }\n }\n }\n } else {\n lines.push(`${serializeKey(key)}: ${serializeValue(value)}`);\n }\n }\n lines.push('---');\n return lines.join('\\n') + '\\n';\n}\n\nfunction unescapeFrontmatterString(escaped: string): string {\n let result = '';\n for (let i = 0; i < escaped.length; i++) {\n const ch = escaped[i];\n if (ch === '\\\\' && i + 1 < escaped.length) {\n const next = escaped[i + 1];\n if (next === 'n') { result += '\\n'; i++; continue; }\n if (next === 'r') { result += '\\r'; i++; continue; }\n if (next === 't') { result += '\\t'; i++; continue; }\n if (next === '\"') { result += '\"'; i++; continue; }\n if (next === '\\\\') { result += '\\\\'; i++; continue; }\n }\n result += ch;\n }\n return result;\n}\n\nfunction unescapeSingleQuotedString(escaped: string): string {\n return escaped.replace(/''/g, \"'\");\n}\n\nfunction parseQuotedScalar(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed.length < 2) return null;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeFrontmatterString(trimmed.slice(1, -1));\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return unescapeSingleQuotedString(trimmed.slice(1, -1));\n }\n return null;\n}\n\nfunction parseKey(raw: string): string {\n return parseQuotedScalar(raw) ?? raw.trim();\n}\n\nfunction parseScalarValue(raw: string): OkfFrontmatterScalar {\n const quoted = parseQuotedScalar(raw);\n if (quoted !== null) return quoted;\n const trimmed = raw.trim();\n if (trimmed === 'null') return null;\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(trimmed)) return Number(trimmed);\n return trimmed;\n}\n\nfunction matchFrontmatterKeyValue(\n line: string,\n): { key: string; value: string; hasValue: boolean } | null {\n const keyMatch = /^(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:''|[^'])*'|[^:]+)/.exec(line);\n if (!keyMatch) return null;\n const key = keyMatch[0];\n if (line[key.length] !== ':') return null;\n const tail = line.slice(key.length + 1);\n return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };\n}\n\n/**\n * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:\n * scalar string/number/boolean/null values, quoted strings, and block string-lists.\n * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block\n * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match\n * a recognized shape are silently skipped rather than throwing, so a foreign bundle\n * never crashes\n * the import — it just loses fidelity on the unrecognized line.\n */\nexport function parseFrontmatter(content: string): { frontmatter: OkfFrontmatter; rest: string } {\n const lines = content.split(/\\r?\\n/);\n const fallback = { frontmatter: { type: '' } as OkfFrontmatter, rest: content };\n\n if (lines[0]?.trim() !== '---') return fallback;\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i;\n break;\n }\n }\n if (closingIndex === -1) return fallback;\n\n const frontmatter: Record<string, OkfFrontmatterValue> = {};\n let i = 1;\n while (i < closingIndex) {\n const line = lines[i];\n const kv = matchFrontmatterKeyValue(line);\n if (!kv) {\n i++;\n continue;\n }\n if (kv.value.trim() === '[]') {\n frontmatter[parseKey(kv.key)] = [];\n i++;\n continue;\n }\n if (!kv.hasValue) {\n const key = parseKey(kv.key);\n const items: OkfFrontmatterScalar[] = [];\n i++;\n while (i < closingIndex && /^\\s*-\\s/.test(lines[i])) {\n items.push(parseScalarValue(lines[i].replace(/^\\s*-\\s/, '')));\n i++;\n }\n frontmatter[key] = items;\n continue;\n }\n frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);\n i++;\n }\n\n if (typeof frontmatter['type'] !== 'string') {\n frontmatter['type'] = '';\n }\n\n const restLines = lines.slice(closingIndex + 1);\n const rest = restLines.length > 0 ? restLines.join('\\n') : '';\n\n return { frontmatter: frontmatter as OkfFrontmatter, rest };\n}\n","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter, parseFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${body}`;\n}\n\n/** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */\nexport function parseConcept(content: string): { frontmatter: OkfFrontmatter; body: string } {\n const { frontmatter, rest } = parseFrontmatter(content);\n const body = rest.startsWith('\\n') ? rest.slice(1) : rest;\n return { frontmatter, body };\n}\n","import { serializeScalarString } from './frontmatter';\nimport type { OkfIndexEntry, OkfIndexSection } from './types';\n\nfunction renderEntry(entry: OkfIndexEntry): string {\n const esc = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n\n const title = esc(entry.title);\n const description = entry.description ? esc(entry.description) : undefined;\n\n return description\n ? `* [${title}](${entry.path}) - ${description}`\n : `* [${title}](${entry.path})`;\n}\n\nfunction renderSections(sections: OkfIndexSection[]): string {\n const lines: string[] = [];\n for (const section of sections) {\n lines.push(`## ${section.heading}`);\n lines.push('');\n for (const entry of section.entries) {\n lines.push(renderEntry(entry));\n }\n lines.push('');\n }\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nexport function buildIndexMd(sections: OkfIndexSection[]): string {\n return renderSections(sections);\n}\n\nexport function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string {\n const frontmatter = `---\\nokf_version: ${serializeScalarString(okfVersion)}\\n---\\n`;\n return `${frontmatter}\\n${renderSections(sections)}`;\n}\n","import type { OkfLogEntry } from './types';\n\nexport function buildLogMd(entries: OkfLogEntry[]): string {\n const groups = new Map<string, OkfLogEntry[]>();\n for (const entry of entries) {\n const group = groups.get(entry.date) ?? [];\n group.push(entry);\n groups.set(entry.date, group);\n }\n\n const dates = Array.from(groups.keys()).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\n const lines: string[] = [];\n for (const date of dates) {\n lines.push(`## ${date}`);\n lines.push('');\n for (const entry of groups.get(date)!) {\n lines.push(`- ${entry.text}`);\n }\n lines.push('');\n }\n\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nconst DATE_HEADING = /^##\\s+(\\d{4}-\\d{2}-\\d{2})\\s*$/;\nconst BULLET = /^-\\s+(.*)$/;\n\n/**\n * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact\n * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,\n * not thrown — a foreign log.md in a different format degrades to fewer entries\n * rather than failing the import.\n */\nexport function parseLogMd(content: string): OkfLogEntry[] {\n const entries: OkfLogEntry[] = [];\n let currentDate: string | null = null;\n\n for (const line of content.split(/\\r?\\n/)) {\n const headingMatch = DATE_HEADING.exec(line);\n if (headingMatch) {\n currentDate = headingMatch[1];\n continue;\n }\n const bulletMatch = BULLET.exec(line);\n if (bulletMatch && currentDate) {\n entries.push({ date: currentDate, text: bulletMatch[1] });\n }\n }\n\n return entries;\n}\n","import type { OkfMarkdownLink } from './types';\n\nconst EXCLUDED_SCHEME = /^(https?:|mailto:)/i;\nconst FENCED_CODE_BLOCK_PATTERN = /```[\\s\\S]*?```/g;\n\n/**\n * Extracts inline markdown links (`[text](path)`) from a concept body.\n * Single-line regex, not a CommonMark parser — reference-style links, links\n * split across lines, and links inside code fences are not recognized.\n * `http(s):` and `mailto:` targets are excluded; only relative/local paths\n * are candidates for graph edges.\n */\nexport function extractMarkdownLinks(body: string): OkfMarkdownLink[] {\n const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, '');\n const linkPattern = /\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g;\n const links: OkfMarkdownLink[] = [];\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(searchableBody)) !== null) {\n const [, text, path] = match;\n if (EXCLUDED_SCHEME.test(path)) continue;\n links.push({ text, path });\n }\n return links;\n}\n"]}
1
+ {"version":3,"sources":["../src/frontmatter.ts","../src/concept.ts","../src/index-md.ts","../src/entity-index-md.ts","../src/log-md.ts","../src/related-section.ts","../src/path-allowlist.ts","../src/markdown-links.ts"],"names":["i"],"mappings":"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","file":"index.js","sourcesContent":["import type { OkfFrontmatter, OkfFrontmatterScalar, OkfFrontmatterValue } from './types';\n\nconst RESERVED_LITERALS = new Set(['true', 'false', 'yes', 'no', 'on', 'off', 'null', '~', '']);\n\nfunction looksLikeNumber(value: string): boolean {\n return /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(value);\n}\n\nfunction isIso8601Timestamp(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2})$/.test(value);\n}\n\nfunction needsQuoting(value: string): boolean {\n if (value !== value.trim()) return true;\n if (/[\\n\\r\\t]/.test(value)) return true;\n if (isIso8601Timestamp(value)) return false;\n\n // Quote strings that YAML could otherwise parse as collections/indicators.\n if (/^[-?:]\\s/.test(value)) return true;\n if (/^[\\[\\]{}&,*%!|>'\"@`]/.test(value)) return true;\n\n if (value.includes(':') || value.includes('#')) return true;\n if (RESERVED_LITERALS.has(value.toLowerCase())) return true;\n if (looksLikeNumber(value)) return true;\n return false;\n}\n\nfunction quoteString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n}\n\nexport function serializeScalarString(value: string): string {\n return needsQuoting(value) ? quoteString(value) : value;\n}\n\nfunction serializeKey(key: string): string {\n // needsQuoting() intentionally exempts ISO 8601 timestamps for *values*.\n // For keys, quote timestamp-like scalars to avoid YAML timestamp coercion in some parsers.\n if (/\\s/.test(key) || needsQuoting(key) || isIso8601Timestamp(key)) {\n return quoteString(key);\n }\n return key;\n}\n\nfunction serializeValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') return serializeScalarString(value);\n throw new Error(`Unsupported frontmatter value type: ${typeof value}`);\n}\n\nexport function serializeFrontmatter(fm: OkfFrontmatter): string {\n const lines: string[] = ['---'];\n for (const [key, value] of Object.entries(fm)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n if (value.length === 0) {\n lines.push(`${serializeKey(key)}: []`);\n } else {\n lines.push(`${serializeKey(key)}:`);\n for (const item of value as unknown[]) {\n if (typeof item === 'string') {\n lines.push(` - ${serializeScalarString(item)}`);\n } else {\n lines.push(` - ${serializeValue(item)}`);\n }\n }\n }\n } else {\n lines.push(`${serializeKey(key)}: ${serializeValue(value)}`);\n }\n }\n lines.push('---');\n return lines.join('\\n') + '\\n';\n}\n\nfunction unescapeFrontmatterString(escaped: string): string {\n let result = '';\n for (let i = 0; i < escaped.length; i++) {\n const ch = escaped[i];\n if (ch === '\\\\' && i + 1 < escaped.length) {\n const next = escaped[i + 1];\n if (next === 'n') { result += '\\n'; i++; continue; }\n if (next === 'r') { result += '\\r'; i++; continue; }\n if (next === 't') { result += '\\t'; i++; continue; }\n if (next === '\"') { result += '\"'; i++; continue; }\n if (next === '\\\\') { result += '\\\\'; i++; continue; }\n }\n result += ch;\n }\n return result;\n}\n\nfunction unescapeSingleQuotedString(escaped: string): string {\n return escaped.replace(/''/g, \"'\");\n}\n\nfunction parseQuotedScalar(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed.length < 2) return null;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeFrontmatterString(trimmed.slice(1, -1));\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return unescapeSingleQuotedString(trimmed.slice(1, -1));\n }\n return null;\n}\n\nfunction parseKey(raw: string): string {\n return parseQuotedScalar(raw) ?? raw.trim();\n}\n\nfunction parseScalarValue(raw: string): OkfFrontmatterScalar {\n const quoted = parseQuotedScalar(raw);\n if (quoted !== null) return quoted;\n const trimmed = raw.trim();\n if (trimmed === 'null') return null;\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(trimmed)) return Number(trimmed);\n return trimmed;\n}\n\nfunction matchFrontmatterKeyValue(\n line: string,\n): { key: string; value: string; hasValue: boolean } | null {\n const keyMatch = /^(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:''|[^'])*'|[^:]+)/.exec(line);\n if (!keyMatch) return null;\n const key = keyMatch[0];\n if (line[key.length] !== ':') return null;\n const tail = line.slice(key.length + 1);\n return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };\n}\n\n/**\n * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:\n * scalar string/number/boolean/null values, quoted strings, and block string-lists.\n * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block\n * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match\n * a recognized shape are silently skipped rather than throwing, so a foreign bundle\n * never crashes\n * the import — it just loses fidelity on the unrecognized line.\n */\nexport function parseFrontmatter(content: string): { frontmatter: OkfFrontmatter; rest: string } {\n const lines = content.split(/\\r?\\n/);\n const fallback = { frontmatter: { type: '' } as OkfFrontmatter, rest: content };\n\n if (lines[0]?.trim() !== '---') return fallback;\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i;\n break;\n }\n }\n if (closingIndex === -1) return fallback;\n\n const frontmatter: Record<string, OkfFrontmatterValue> = {};\n let i = 1;\n while (i < closingIndex) {\n const line = lines[i];\n const kv = matchFrontmatterKeyValue(line);\n if (!kv) {\n i++;\n continue;\n }\n if (kv.value.trim() === '[]') {\n frontmatter[parseKey(kv.key)] = [];\n i++;\n continue;\n }\n if (!kv.hasValue) {\n const key = parseKey(kv.key);\n const items: OkfFrontmatterScalar[] = [];\n i++;\n while (i < closingIndex && /^\\s*-\\s/.test(lines[i])) {\n items.push(parseScalarValue(lines[i].replace(/^\\s*-\\s/, '')));\n i++;\n }\n frontmatter[key] = items;\n continue;\n }\n frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);\n i++;\n }\n\n if (typeof frontmatter['type'] !== 'string') {\n frontmatter['type'] = '';\n }\n\n const restLines = lines.slice(closingIndex + 1);\n const rest = restLines.length > 0 ? restLines.join('\\n') : '';\n\n return { frontmatter: frontmatter as OkfFrontmatter, rest };\n}\n","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter, parseFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${body}`;\n}\n\n/** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */\nexport function parseConcept(content: string): { frontmatter: OkfFrontmatter; body: string } {\n const { frontmatter, rest } = parseFrontmatter(content);\n const body = rest.startsWith('\\n') ? rest.slice(1) : rest;\n return { frontmatter, body };\n}\n","import { parseFrontmatter, serializeScalarString } from './frontmatter';\nimport type { OkfIndexEntry, OkfIndexSection } from './types';\n\nfunction renderEntry(entry: OkfIndexEntry): string {\n const esc = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n\n const title = esc(entry.title);\n const description = entry.description ? esc(entry.description) : undefined;\n\n return description\n ? `* [${title}](${entry.path}) - ${description}`\n : `* [${title}](${entry.path})`;\n}\n\nfunction renderSections(sections: OkfIndexSection[]): string {\n const lines: string[] = [];\n for (const section of sections) {\n lines.push(`## ${section.heading}`);\n lines.push('');\n for (const entry of section.entries) {\n lines.push(renderEntry(entry));\n }\n lines.push('');\n }\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nexport function buildIndexMd(sections: OkfIndexSection[]): string {\n return renderSections(sections);\n}\n\nexport function buildRootIndexMd(\n okfVersion: string,\n sections: OkfIndexSection[],\n options?: { profile?: string },\n): string {\n const lines = ['---', `okf_version: ${serializeScalarString(okfVersion)}`];\n if (options?.profile) {\n lines.push(`profile: ${serializeScalarString(options.profile)}`);\n }\n lines.push('---', '');\n return `${lines.join('\\n')}\\n${renderSections(sections)}`;\n}\n\nexport function parseRootIndexMd(content: string): { okf_version?: string; profile?: string } {\n const { frontmatter } = parseFrontmatter(content);\n const okf = frontmatter.okf_version;\n return {\n okf_version:\n typeof okf === 'string' ? okf : typeof okf === 'number' && Number.isFinite(okf) ? String(okf) : undefined,\n profile: typeof frontmatter.profile === 'string' ? frontmatter.profile : undefined,\n };\n}\n","import type { OkfIndexSection } from './types';\nimport { buildIndexMd } from './index-md';\n\nconst EVENT_LOG_LINK = /^\\[Event log\\]\\(\\.\\/log\\.md\\)\\s*$/;\nconst TOP_LEVEL_H1 = /^#\\s+.+\\s*$/;\nconst SECTION_HEADING = /^##\\s+(.+)\\s*$/;\nconst INDEX_ENTRY = /^\\*\\s+\\[((?:\\\\.|[^\\]])*)\\]\\(([^)]+)\\)(?:\\s+-\\s+(.*))?$/;\n\nfunction unescapeIndexTitle(title: string): string {\n return title.replace(/\\\\\\]/g, ']').replace(/\\\\\\[/g, '[').replace(/\\\\\\\\/g, '\\\\');\n}\n\nexport function buildEntityIndexMd(options: {\n summary?: string;\n sections: OkfIndexSection[];\n}): string {\n const parts: string[] = [];\n if (options.summary?.trim()) {\n parts.push(options.summary.trimEnd(), '');\n }\n const sectionsMd = buildIndexMd(options.sections).trimEnd();\n if (sectionsMd) {\n parts.push(sectionsMd);\n parts.push('');\n }\n parts.push('[Event log](./log.md)');\n return `${parts.join('\\n')}\\n`;\n}\n\nexport function parseEntityIndexMd(content: string): {\n summary: string;\n sections: OkfIndexSection[];\n} {\n const lines = content.split(/\\r?\\n/);\n\n // Optional frontmatter block (--- ... ---) per profile.\n let start = 0;\n if (lines[0]?.trim() === '---') {\n const closing = lines.findIndex((line, idx) => idx > 0 && line.trim() === '---');\n if (closing !== -1) start = closing + 1;\n }\n\n const firstSectionIdx = lines.findIndex((line, idx) => idx >= start && SECTION_HEADING.test(line));\n const summaryEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx;\n const summaryLines = lines\n .slice(start, summaryEnd)\n .filter(line => !EVENT_LOG_LINK.test(line.trim()));\n let summaryStart = 0;\n while (summaryStart < summaryLines.length && summaryLines[summaryStart].trim() === '') {\n summaryStart += 1;\n }\n if (summaryStart < summaryLines.length && TOP_LEVEL_H1.test(summaryLines[summaryStart].trim())) {\n summaryStart += 1;\n }\n const summary = summaryLines.slice(summaryStart).join('\\n').trim();\n\n const sections: OkfIndexSection[] = [];\n if (firstSectionIdx === -1) return { summary, sections };\n\n let current: OkfIndexSection | null = null;\n for (let i = Math.max(firstSectionIdx, start); i < lines.length; i += 1) {\n const line = lines[i];\n if (EVENT_LOG_LINK.test(line.trim())) continue;\n\n const headingMatch = SECTION_HEADING.exec(line);\n if (headingMatch) {\n current = { heading: headingMatch[1], entries: [] };\n sections.push(current);\n continue;\n }\n\n if (!current) continue;\n const entryMatch = INDEX_ENTRY.exec(line);\n if (!entryMatch) continue;\n\n current.entries.push({\n title: unescapeIndexTitle(entryMatch[1]),\n path: entryMatch[2],\n description: entryMatch[3] ? unescapeIndexTitle(entryMatch[3]) : undefined,\n });\n }\n return { summary, sections };\n}\n","import type { OkfLogEntry } from './types';\n\nexport function buildLogMd(entries: OkfLogEntry[]): string {\n const groups = new Map<string, OkfLogEntry[]>();\n for (const entry of entries) {\n const group = groups.get(entry.date) ?? [];\n group.push(entry);\n groups.set(entry.date, group);\n }\n\n const dates = Array.from(groups.keys()).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\n const lines: string[] = [];\n for (const date of dates) {\n lines.push(`## ${date}`);\n lines.push('');\n for (const entry of groups.get(date)!) {\n lines.push(`- ${entry.text}`);\n }\n lines.push('');\n }\n\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nconst EVENT_ID_COMMENT = /\\s*<!--\\s*id:\\s*(\\S+)\\s*-->\\s*$/;\n\nexport function appendEventIdComment(text: string, eventId: string): string {\n if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return text;\n return `${text} <!-- id: ${eventId} -->`;\n}\n\nexport function parseEventIdComment(text: string): { text: string; eventId?: string } {\n const match = EVENT_ID_COMMENT.exec(text);\n if (!match) return { text };\n const eventId = match[1];\n const stripped = text.slice(0, match.index).trimEnd();\n if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return { text: stripped };\n return { text: stripped, eventId };\n}\n\nconst DATE_HEADING = /^##\\s+(\\d{4}-\\d{2}-\\d{2})\\s*$/;\nconst BULLET = /^-\\s+(.*)$/;\n\n/**\n * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact\n * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,\n * not thrown — a foreign log.md in a different format degrades to fewer entries\n * rather than failing the import.\n */\nexport function parseLogMd(content: string): OkfLogEntry[] {\n const entries: OkfLogEntry[] = [];\n let currentDate: string | null = null;\n\n for (const line of content.split(/\\r?\\n/)) {\n const headingMatch = DATE_HEADING.exec(line);\n if (headingMatch) {\n currentDate = headingMatch[1];\n continue;\n }\n const bulletMatch = BULLET.exec(line);\n if (bulletMatch && currentDate) {\n entries.push({ date: currentDate, text: bulletMatch[1] });\n }\n }\n\n return entries;\n}\n","import type { OkfMarkdownLink } from './types';\n\nfunction escapeLinkLabel(label: string): string {\n return label\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n}\n\nexport function appendRelatedSection(\n body: string,\n links: Array<{ edge_type: string; path: string }>,\n): string {\n if (links.length === 0) return body;\n const prefix =\n body.length === 0\n ? ''\n : body.endsWith('\\n\\n')\n ? body\n : body.endsWith('\\n')\n ? `${body}\\n`\n : `${body}\\n\\n`;\n const lines = ['## Related', ''];\n for (const link of links) {\n lines.push(`- [${escapeLinkLabel(link.edge_type)}](${link.path})`);\n }\n return `${prefix}${lines.join('\\n')}\\n`;\n}\n\nexport function splitRelatedSection(body: string): { body: string; relatedLinks: OkfMarkdownLink[] } {\n const lines = body.split(/\\r?\\n/);\n let end = lines.length;\n while (end > 0 && lines[end - 1].trim() === '') end -= 1;\n\n let scan = end - 1;\n while (scan >= 0 && /^-\\s+/.test(lines[scan])) scan -= 1;\n while (scan >= 0 && lines[scan].trim() === '') scan -= 1;\n\n if (scan < 0 || lines[scan].trim() !== '## Related') {\n return { body, relatedLinks: [] };\n }\n\n const relatedStart = scan;\n const contentBody = lines.slice(0, relatedStart).join('\\n');\n const relatedBlock = lines.slice(relatedStart, end).join('\\n');\n const relatedLinks: OkfMarkdownLink[] = [];\n for (const line of relatedBlock.split(/\\r?\\n/)) {\n const bullet = /^-\\s+(.*)$/.exec(line);\n if (!bullet) continue;\n\n const linkPattern = /\\[((?:\\\\.|[^\\]])*)\\]\\(([^)\\s]+)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(bullet[1])) !== null) {\n const linkPath = match[2];\n if (/^(https?:|mailto:)/i.test(linkPath)) continue;\n relatedLinks.push({\n text: match[1].replace(/\\\\\\]/g, ']').replace(/\\\\\\[/g, '[').replace(/\\\\\\\\/g, '\\\\'),\n path: linkPath,\n });\n }\n }\n const normalizedBody =\n contentBody.length === 0 ? '' : contentBody.endsWith('\\n') ? contentBody : `${contentBody}\\n`;\n return { body: normalizedBody, relatedLinks };\n}\n","const ALLOWED =\n /^(index\\.md|entities\\/[^/]+\\/(index\\.md|log\\.md|(facts|tasks)\\/[^/]+\\.md))$/;\n\nexport function isAllowedOkfPath(filePath: string): boolean {\n const normalized = filePath.replace(/^\\.\\//, '').replace(/\\\\/g, '/');\n if (normalized.split('/').some(segment => segment === '.' || segment === '..')) {\n return false;\n }\n return ALLOWED.test(normalized);\n}\n","import type { OkfMarkdownLink } from './types';\n\nconst EXCLUDED_SCHEME = /^(https?:|mailto:)/i;\nconst FENCED_CODE_BLOCK_PATTERN = /```[\\s\\S]*?```/g;\n\n/**\n * Extracts inline markdown links (`[text](path)`) from a concept body.\n * Single-line regex, not a CommonMark parser — reference-style links, links\n * split across lines, and links inside code fences are not recognized.\n * `http(s):` and `mailto:` targets are excluded; only relative/local paths\n * are candidates for graph edges.\n */\nexport function extractMarkdownLinks(body: string): OkfMarkdownLink[] {\n const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, '');\n const linkPattern = /\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g;\n const links: OkfMarkdownLink[] = [];\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(searchableBody)) !== null) {\n const [, text, path] = match;\n if (EXCLUDED_SCHEME.test(path)) continue;\n links.push({ text, path });\n }\n return links;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -214,14 +214,87 @@ function renderSections(sections) {
214
214
  function buildIndexMd(sections) {
215
215
  return renderSections(sections);
216
216
  }
217
- function buildRootIndexMd(okfVersion, sections) {
218
- const frontmatter = `---
219
- okf_version: ${serializeScalarString(okfVersion)}
220
- ---
221
- `;
222
- return `${frontmatter}
217
+ function buildRootIndexMd(okfVersion, sections, options) {
218
+ const lines = ["---", `okf_version: ${serializeScalarString(okfVersion)}`];
219
+ if (options?.profile) {
220
+ lines.push(`profile: ${serializeScalarString(options.profile)}`);
221
+ }
222
+ lines.push("---", "");
223
+ return `${lines.join("\n")}
223
224
  ${renderSections(sections)}`;
224
225
  }
226
+ function parseRootIndexMd(content) {
227
+ const { frontmatter } = parseFrontmatter(content);
228
+ const okf = frontmatter.okf_version;
229
+ return {
230
+ okf_version: typeof okf === "string" ? okf : typeof okf === "number" && Number.isFinite(okf) ? String(okf) : void 0,
231
+ profile: typeof frontmatter.profile === "string" ? frontmatter.profile : void 0
232
+ };
233
+ }
234
+
235
+ // src/entity-index-md.ts
236
+ var EVENT_LOG_LINK = /^\[Event log\]\(\.\/log\.md\)\s*$/;
237
+ var TOP_LEVEL_H1 = /^#\s+.+\s*$/;
238
+ var SECTION_HEADING = /^##\s+(.+)\s*$/;
239
+ var INDEX_ENTRY = /^\*\s+\[((?:\\.|[^\]])*)\]\(([^)]+)\)(?:\s+-\s+(.*))?$/;
240
+ function unescapeIndexTitle(title) {
241
+ return title.replace(/\\\]/g, "]").replace(/\\\[/g, "[").replace(/\\\\/g, "\\");
242
+ }
243
+ function buildEntityIndexMd(options) {
244
+ const parts = [];
245
+ if (options.summary?.trim()) {
246
+ parts.push(options.summary.trimEnd(), "");
247
+ }
248
+ const sectionsMd = buildIndexMd(options.sections).trimEnd();
249
+ if (sectionsMd) {
250
+ parts.push(sectionsMd);
251
+ parts.push("");
252
+ }
253
+ parts.push("[Event log](./log.md)");
254
+ return `${parts.join("\n")}
255
+ `;
256
+ }
257
+ function parseEntityIndexMd(content) {
258
+ const lines = content.split(/\r?\n/);
259
+ let start = 0;
260
+ if (lines[0]?.trim() === "---") {
261
+ const closing = lines.findIndex((line, idx) => idx > 0 && line.trim() === "---");
262
+ if (closing !== -1) start = closing + 1;
263
+ }
264
+ const firstSectionIdx = lines.findIndex((line, idx) => idx >= start && SECTION_HEADING.test(line));
265
+ const summaryEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx;
266
+ const summaryLines = lines.slice(start, summaryEnd).filter((line) => !EVENT_LOG_LINK.test(line.trim()));
267
+ let summaryStart = 0;
268
+ while (summaryStart < summaryLines.length && summaryLines[summaryStart].trim() === "") {
269
+ summaryStart += 1;
270
+ }
271
+ if (summaryStart < summaryLines.length && TOP_LEVEL_H1.test(summaryLines[summaryStart].trim())) {
272
+ summaryStart += 1;
273
+ }
274
+ const summary = summaryLines.slice(summaryStart).join("\n").trim();
275
+ const sections = [];
276
+ if (firstSectionIdx === -1) return { summary, sections };
277
+ let current = null;
278
+ for (let i = Math.max(firstSectionIdx, start); i < lines.length; i += 1) {
279
+ const line = lines[i];
280
+ if (EVENT_LOG_LINK.test(line.trim())) continue;
281
+ const headingMatch = SECTION_HEADING.exec(line);
282
+ if (headingMatch) {
283
+ current = { heading: headingMatch[1], entries: [] };
284
+ sections.push(current);
285
+ continue;
286
+ }
287
+ if (!current) continue;
288
+ const entryMatch = INDEX_ENTRY.exec(line);
289
+ if (!entryMatch) continue;
290
+ current.entries.push({
291
+ title: unescapeIndexTitle(entryMatch[1]),
292
+ path: entryMatch[2],
293
+ description: entryMatch[3] ? unescapeIndexTitle(entryMatch[3]) : void 0
294
+ });
295
+ }
296
+ return { summary, sections };
297
+ }
225
298
 
226
299
  // src/log-md.ts
227
300
  function buildLogMd(entries) {
@@ -244,6 +317,19 @@ function buildLogMd(entries) {
244
317
  if (lines.length === 0) return "";
245
318
  return lines.join("\n").trimEnd() + "\n";
246
319
  }
320
+ var EVENT_ID_COMMENT = /\s*<!--\s*id:\s*(\S+)\s*-->\s*$/;
321
+ function appendEventIdComment(text, eventId) {
322
+ if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return text;
323
+ return `${text} <!-- id: ${eventId} -->`;
324
+ }
325
+ function parseEventIdComment(text) {
326
+ const match = EVENT_ID_COMMENT.exec(text);
327
+ if (!match) return { text };
328
+ const eventId = match[1];
329
+ const stripped = text.slice(0, match.index).trimEnd();
330
+ if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return { text: stripped };
331
+ return { text: stripped, eventId };
332
+ }
247
333
  var DATE_HEADING = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
248
334
  var BULLET = /^-\s+(.*)$/;
249
335
  function parseLogMd(content) {
@@ -263,6 +349,66 @@ function parseLogMd(content) {
263
349
  return entries;
264
350
  }
265
351
 
352
+ // src/related-section.ts
353
+ function escapeLinkLabel(label) {
354
+ return label.replace(/\\/g, "\\\\").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/\r?\n/g, " ");
355
+ }
356
+ function appendRelatedSection(body, links) {
357
+ if (links.length === 0) return body;
358
+ const prefix = body.length === 0 ? "" : body.endsWith("\n\n") ? body : body.endsWith("\n") ? `${body}
359
+ ` : `${body}
360
+
361
+ `;
362
+ const lines = ["## Related", ""];
363
+ for (const link of links) {
364
+ lines.push(`- [${escapeLinkLabel(link.edge_type)}](${link.path})`);
365
+ }
366
+ return `${prefix}${lines.join("\n")}
367
+ `;
368
+ }
369
+ function splitRelatedSection(body) {
370
+ const lines = body.split(/\r?\n/);
371
+ let end = lines.length;
372
+ while (end > 0 && lines[end - 1].trim() === "") end -= 1;
373
+ let scan = end - 1;
374
+ while (scan >= 0 && /^-\s+/.test(lines[scan])) scan -= 1;
375
+ while (scan >= 0 && lines[scan].trim() === "") scan -= 1;
376
+ if (scan < 0 || lines[scan].trim() !== "## Related") {
377
+ return { body, relatedLinks: [] };
378
+ }
379
+ const relatedStart = scan;
380
+ const contentBody = lines.slice(0, relatedStart).join("\n");
381
+ const relatedBlock = lines.slice(relatedStart, end).join("\n");
382
+ const relatedLinks = [];
383
+ for (const line of relatedBlock.split(/\r?\n/)) {
384
+ const bullet = /^-\s+(.*)$/.exec(line);
385
+ if (!bullet) continue;
386
+ const linkPattern = /\[((?:\\.|[^\]])*)\]\(([^)\s]+)\)/g;
387
+ let match;
388
+ while ((match = linkPattern.exec(bullet[1])) !== null) {
389
+ const linkPath = match[2];
390
+ if (/^(https?:|mailto:)/i.test(linkPath)) continue;
391
+ relatedLinks.push({
392
+ text: match[1].replace(/\\\]/g, "]").replace(/\\\[/g, "[").replace(/\\\\/g, "\\"),
393
+ path: linkPath
394
+ });
395
+ }
396
+ }
397
+ const normalizedBody = contentBody.length === 0 ? "" : contentBody.endsWith("\n") ? contentBody : `${contentBody}
398
+ `;
399
+ return { body: normalizedBody, relatedLinks };
400
+ }
401
+
402
+ // src/path-allowlist.ts
403
+ var ALLOWED = /^(index\.md|entities\/[^/]+\/(index\.md|log\.md|(facts|tasks)\/[^/]+\.md))$/;
404
+ function isAllowedOkfPath(filePath) {
405
+ const normalized = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
406
+ if (normalized.split("/").some((segment) => segment === "." || segment === "..")) {
407
+ return false;
408
+ }
409
+ return ALLOWED.test(normalized);
410
+ }
411
+
266
412
  // src/markdown-links.ts
267
413
  var EXCLUDED_SCHEME = /^(https?:|mailto:)/i;
268
414
  var FENCED_CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
@@ -279,6 +425,6 @@ function extractMarkdownLinks(body) {
279
425
  return links;
280
426
  }
281
427
 
282
- export { buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, parseConcept, parseFrontmatter, parseLogMd, serializeFrontmatter };
428
+ export { appendEventIdComment, appendRelatedSection, buildConceptDocument, buildEntityIndexMd, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, isAllowedOkfPath, parseConcept, parseEntityIndexMd, parseEventIdComment, parseFrontmatter, parseLogMd, parseRootIndexMd, serializeFrontmatter, splitRelatedSection };
283
429
  //# sourceMappingURL=index.mjs.map
284
430
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frontmatter.ts","../src/concept.ts","../src/index-md.ts","../src/log-md.ts","../src/markdown-links.ts"],"names":["i"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { OkfFrontmatter, OkfFrontmatterScalar, OkfFrontmatterValue } from './types';\n\nconst RESERVED_LITERALS = new Set(['true', 'false', 'yes', 'no', 'on', 'off', 'null', '~', '']);\n\nfunction looksLikeNumber(value: string): boolean {\n return /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(value);\n}\n\nfunction isIso8601Timestamp(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2})$/.test(value);\n}\n\nfunction needsQuoting(value: string): boolean {\n if (value !== value.trim()) return true;\n if (/[\\n\\r\\t]/.test(value)) return true;\n if (isIso8601Timestamp(value)) return false;\n\n // Quote strings that YAML could otherwise parse as collections/indicators.\n if (/^[-?:]\\s/.test(value)) return true;\n if (/^[\\[\\]{}&,*%!|>'\"@`]/.test(value)) return true;\n\n if (value.includes(':') || value.includes('#')) return true;\n if (RESERVED_LITERALS.has(value.toLowerCase())) return true;\n if (looksLikeNumber(value)) return true;\n return false;\n}\n\nfunction quoteString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n}\n\nexport function serializeScalarString(value: string): string {\n return needsQuoting(value) ? quoteString(value) : value;\n}\n\nfunction serializeKey(key: string): string {\n // needsQuoting() intentionally exempts ISO 8601 timestamps for *values*.\n // For keys, quote timestamp-like scalars to avoid YAML timestamp coercion in some parsers.\n if (/\\s/.test(key) || needsQuoting(key) || isIso8601Timestamp(key)) {\n return quoteString(key);\n }\n return key;\n}\n\nfunction serializeValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') return serializeScalarString(value);\n throw new Error(`Unsupported frontmatter value type: ${typeof value}`);\n}\n\nexport function serializeFrontmatter(fm: OkfFrontmatter): string {\n const lines: string[] = ['---'];\n for (const [key, value] of Object.entries(fm)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n if (value.length === 0) {\n lines.push(`${serializeKey(key)}: []`);\n } else {\n lines.push(`${serializeKey(key)}:`);\n for (const item of value as unknown[]) {\n if (typeof item === 'string') {\n lines.push(` - ${serializeScalarString(item)}`);\n } else {\n lines.push(` - ${serializeValue(item)}`);\n }\n }\n }\n } else {\n lines.push(`${serializeKey(key)}: ${serializeValue(value)}`);\n }\n }\n lines.push('---');\n return lines.join('\\n') + '\\n';\n}\n\nfunction unescapeFrontmatterString(escaped: string): string {\n let result = '';\n for (let i = 0; i < escaped.length; i++) {\n const ch = escaped[i];\n if (ch === '\\\\' && i + 1 < escaped.length) {\n const next = escaped[i + 1];\n if (next === 'n') { result += '\\n'; i++; continue; }\n if (next === 'r') { result += '\\r'; i++; continue; }\n if (next === 't') { result += '\\t'; i++; continue; }\n if (next === '\"') { result += '\"'; i++; continue; }\n if (next === '\\\\') { result += '\\\\'; i++; continue; }\n }\n result += ch;\n }\n return result;\n}\n\nfunction unescapeSingleQuotedString(escaped: string): string {\n return escaped.replace(/''/g, \"'\");\n}\n\nfunction parseQuotedScalar(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed.length < 2) return null;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeFrontmatterString(trimmed.slice(1, -1));\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return unescapeSingleQuotedString(trimmed.slice(1, -1));\n }\n return null;\n}\n\nfunction parseKey(raw: string): string {\n return parseQuotedScalar(raw) ?? raw.trim();\n}\n\nfunction parseScalarValue(raw: string): OkfFrontmatterScalar {\n const quoted = parseQuotedScalar(raw);\n if (quoted !== null) return quoted;\n const trimmed = raw.trim();\n if (trimmed === 'null') return null;\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(trimmed)) return Number(trimmed);\n return trimmed;\n}\n\nfunction matchFrontmatterKeyValue(\n line: string,\n): { key: string; value: string; hasValue: boolean } | null {\n const keyMatch = /^(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:''|[^'])*'|[^:]+)/.exec(line);\n if (!keyMatch) return null;\n const key = keyMatch[0];\n if (line[key.length] !== ':') return null;\n const tail = line.slice(key.length + 1);\n return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };\n}\n\n/**\n * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:\n * scalar string/number/boolean/null values, quoted strings, and block string-lists.\n * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block\n * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match\n * a recognized shape are silently skipped rather than throwing, so a foreign bundle\n * never crashes\n * the import — it just loses fidelity on the unrecognized line.\n */\nexport function parseFrontmatter(content: string): { frontmatter: OkfFrontmatter; rest: string } {\n const lines = content.split(/\\r?\\n/);\n const fallback = { frontmatter: { type: '' } as OkfFrontmatter, rest: content };\n\n if (lines[0]?.trim() !== '---') return fallback;\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i;\n break;\n }\n }\n if (closingIndex === -1) return fallback;\n\n const frontmatter: Record<string, OkfFrontmatterValue> = {};\n let i = 1;\n while (i < closingIndex) {\n const line = lines[i];\n const kv = matchFrontmatterKeyValue(line);\n if (!kv) {\n i++;\n continue;\n }\n if (kv.value.trim() === '[]') {\n frontmatter[parseKey(kv.key)] = [];\n i++;\n continue;\n }\n if (!kv.hasValue) {\n const key = parseKey(kv.key);\n const items: OkfFrontmatterScalar[] = [];\n i++;\n while (i < closingIndex && /^\\s*-\\s/.test(lines[i])) {\n items.push(parseScalarValue(lines[i].replace(/^\\s*-\\s/, '')));\n i++;\n }\n frontmatter[key] = items;\n continue;\n }\n frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);\n i++;\n }\n\n if (typeof frontmatter['type'] !== 'string') {\n frontmatter['type'] = '';\n }\n\n const restLines = lines.slice(closingIndex + 1);\n const rest = restLines.length > 0 ? restLines.join('\\n') : '';\n\n return { frontmatter: frontmatter as OkfFrontmatter, rest };\n}\n","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter, parseFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${body}`;\n}\n\n/** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */\nexport function parseConcept(content: string): { frontmatter: OkfFrontmatter; body: string } {\n const { frontmatter, rest } = parseFrontmatter(content);\n const body = rest.startsWith('\\n') ? rest.slice(1) : rest;\n return { frontmatter, body };\n}\n","import { serializeScalarString } from './frontmatter';\nimport type { OkfIndexEntry, OkfIndexSection } from './types';\n\nfunction renderEntry(entry: OkfIndexEntry): string {\n const esc = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n\n const title = esc(entry.title);\n const description = entry.description ? esc(entry.description) : undefined;\n\n return description\n ? `* [${title}](${entry.path}) - ${description}`\n : `* [${title}](${entry.path})`;\n}\n\nfunction renderSections(sections: OkfIndexSection[]): string {\n const lines: string[] = [];\n for (const section of sections) {\n lines.push(`## ${section.heading}`);\n lines.push('');\n for (const entry of section.entries) {\n lines.push(renderEntry(entry));\n }\n lines.push('');\n }\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nexport function buildIndexMd(sections: OkfIndexSection[]): string {\n return renderSections(sections);\n}\n\nexport function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string {\n const frontmatter = `---\\nokf_version: ${serializeScalarString(okfVersion)}\\n---\\n`;\n return `${frontmatter}\\n${renderSections(sections)}`;\n}\n","import type { OkfLogEntry } from './types';\n\nexport function buildLogMd(entries: OkfLogEntry[]): string {\n const groups = new Map<string, OkfLogEntry[]>();\n for (const entry of entries) {\n const group = groups.get(entry.date) ?? [];\n group.push(entry);\n groups.set(entry.date, group);\n }\n\n const dates = Array.from(groups.keys()).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\n const lines: string[] = [];\n for (const date of dates) {\n lines.push(`## ${date}`);\n lines.push('');\n for (const entry of groups.get(date)!) {\n lines.push(`- ${entry.text}`);\n }\n lines.push('');\n }\n\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nconst DATE_HEADING = /^##\\s+(\\d{4}-\\d{2}-\\d{2})\\s*$/;\nconst BULLET = /^-\\s+(.*)$/;\n\n/**\n * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact\n * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,\n * not thrown — a foreign log.md in a different format degrades to fewer entries\n * rather than failing the import.\n */\nexport function parseLogMd(content: string): OkfLogEntry[] {\n const entries: OkfLogEntry[] = [];\n let currentDate: string | null = null;\n\n for (const line of content.split(/\\r?\\n/)) {\n const headingMatch = DATE_HEADING.exec(line);\n if (headingMatch) {\n currentDate = headingMatch[1];\n continue;\n }\n const bulletMatch = BULLET.exec(line);\n if (bulletMatch && currentDate) {\n entries.push({ date: currentDate, text: bulletMatch[1] });\n }\n }\n\n return entries;\n}\n","import type { OkfMarkdownLink } from './types';\n\nconst EXCLUDED_SCHEME = /^(https?:|mailto:)/i;\nconst FENCED_CODE_BLOCK_PATTERN = /```[\\s\\S]*?```/g;\n\n/**\n * Extracts inline markdown links (`[text](path)`) from a concept body.\n * Single-line regex, not a CommonMark parser — reference-style links, links\n * split across lines, and links inside code fences are not recognized.\n * `http(s):` and `mailto:` targets are excluded; only relative/local paths\n * are candidates for graph edges.\n */\nexport function extractMarkdownLinks(body: string): OkfMarkdownLink[] {\n const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, '');\n const linkPattern = /\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g;\n const links: OkfMarkdownLink[] = [];\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(searchableBody)) !== null) {\n const [, text, path] = match;\n if (EXCLUDED_SCHEME.test(path)) continue;\n links.push({ text, path });\n }\n return links;\n}\n"]}
1
+ {"version":3,"sources":["../src/frontmatter.ts","../src/concept.ts","../src/index-md.ts","../src/entity-index-md.ts","../src/log-md.ts","../src/related-section.ts","../src/path-allowlist.ts","../src/markdown-links.ts"],"names":["i"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { OkfFrontmatter, OkfFrontmatterScalar, OkfFrontmatterValue } from './types';\n\nconst RESERVED_LITERALS = new Set(['true', 'false', 'yes', 'no', 'on', 'off', 'null', '~', '']);\n\nfunction looksLikeNumber(value: string): boolean {\n return /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(value);\n}\n\nfunction isIso8601Timestamp(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2})$/.test(value);\n}\n\nfunction needsQuoting(value: string): boolean {\n if (value !== value.trim()) return true;\n if (/[\\n\\r\\t]/.test(value)) return true;\n if (isIso8601Timestamp(value)) return false;\n\n // Quote strings that YAML could otherwise parse as collections/indicators.\n if (/^[-?:]\\s/.test(value)) return true;\n if (/^[\\[\\]{}&,*%!|>'\"@`]/.test(value)) return true;\n\n if (value.includes(':') || value.includes('#')) return true;\n if (RESERVED_LITERALS.has(value.toLowerCase())) return true;\n if (looksLikeNumber(value)) return true;\n return false;\n}\n\nfunction quoteString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n}\n\nexport function serializeScalarString(value: string): string {\n return needsQuoting(value) ? quoteString(value) : value;\n}\n\nfunction serializeKey(key: string): string {\n // needsQuoting() intentionally exempts ISO 8601 timestamps for *values*.\n // For keys, quote timestamp-like scalars to avoid YAML timestamp coercion in some parsers.\n if (/\\s/.test(key) || needsQuoting(key) || isIso8601Timestamp(key)) {\n return quoteString(key);\n }\n return key;\n}\n\nfunction serializeValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') return serializeScalarString(value);\n throw new Error(`Unsupported frontmatter value type: ${typeof value}`);\n}\n\nexport function serializeFrontmatter(fm: OkfFrontmatter): string {\n const lines: string[] = ['---'];\n for (const [key, value] of Object.entries(fm)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n if (value.length === 0) {\n lines.push(`${serializeKey(key)}: []`);\n } else {\n lines.push(`${serializeKey(key)}:`);\n for (const item of value as unknown[]) {\n if (typeof item === 'string') {\n lines.push(` - ${serializeScalarString(item)}`);\n } else {\n lines.push(` - ${serializeValue(item)}`);\n }\n }\n }\n } else {\n lines.push(`${serializeKey(key)}: ${serializeValue(value)}`);\n }\n }\n lines.push('---');\n return lines.join('\\n') + '\\n';\n}\n\nfunction unescapeFrontmatterString(escaped: string): string {\n let result = '';\n for (let i = 0; i < escaped.length; i++) {\n const ch = escaped[i];\n if (ch === '\\\\' && i + 1 < escaped.length) {\n const next = escaped[i + 1];\n if (next === 'n') { result += '\\n'; i++; continue; }\n if (next === 'r') { result += '\\r'; i++; continue; }\n if (next === 't') { result += '\\t'; i++; continue; }\n if (next === '\"') { result += '\"'; i++; continue; }\n if (next === '\\\\') { result += '\\\\'; i++; continue; }\n }\n result += ch;\n }\n return result;\n}\n\nfunction unescapeSingleQuotedString(escaped: string): string {\n return escaped.replace(/''/g, \"'\");\n}\n\nfunction parseQuotedScalar(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed.length < 2) return null;\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeFrontmatterString(trimmed.slice(1, -1));\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return unescapeSingleQuotedString(trimmed.slice(1, -1));\n }\n return null;\n}\n\nfunction parseKey(raw: string): string {\n return parseQuotedScalar(raw) ?? raw.trim();\n}\n\nfunction parseScalarValue(raw: string): OkfFrontmatterScalar {\n const quoted = parseQuotedScalar(raw);\n if (quoted !== null) return quoted;\n const trimmed = raw.trim();\n if (trimmed === 'null') return null;\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/.test(trimmed)) return Number(trimmed);\n return trimmed;\n}\n\nfunction matchFrontmatterKeyValue(\n line: string,\n): { key: string; value: string; hasValue: boolean } | null {\n const keyMatch = /^(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:''|[^'])*'|[^:]+)/.exec(line);\n if (!keyMatch) return null;\n const key = keyMatch[0];\n if (line[key.length] !== ':') return null;\n const tail = line.slice(key.length + 1);\n return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };\n}\n\n/**\n * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:\n * scalar string/number/boolean/null values, quoted strings, and block string-lists.\n * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block\n * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match\n * a recognized shape are silently skipped rather than throwing, so a foreign bundle\n * never crashes\n * the import — it just loses fidelity on the unrecognized line.\n */\nexport function parseFrontmatter(content: string): { frontmatter: OkfFrontmatter; rest: string } {\n const lines = content.split(/\\r?\\n/);\n const fallback = { frontmatter: { type: '' } as OkfFrontmatter, rest: content };\n\n if (lines[0]?.trim() !== '---') return fallback;\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i;\n break;\n }\n }\n if (closingIndex === -1) return fallback;\n\n const frontmatter: Record<string, OkfFrontmatterValue> = {};\n let i = 1;\n while (i < closingIndex) {\n const line = lines[i];\n const kv = matchFrontmatterKeyValue(line);\n if (!kv) {\n i++;\n continue;\n }\n if (kv.value.trim() === '[]') {\n frontmatter[parseKey(kv.key)] = [];\n i++;\n continue;\n }\n if (!kv.hasValue) {\n const key = parseKey(kv.key);\n const items: OkfFrontmatterScalar[] = [];\n i++;\n while (i < closingIndex && /^\\s*-\\s/.test(lines[i])) {\n items.push(parseScalarValue(lines[i].replace(/^\\s*-\\s/, '')));\n i++;\n }\n frontmatter[key] = items;\n continue;\n }\n frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);\n i++;\n }\n\n if (typeof frontmatter['type'] !== 'string') {\n frontmatter['type'] = '';\n }\n\n const restLines = lines.slice(closingIndex + 1);\n const rest = restLines.length > 0 ? restLines.join('\\n') : '';\n\n return { frontmatter: frontmatter as OkfFrontmatter, rest };\n}\n","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter, parseFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${body}`;\n}\n\n/** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */\nexport function parseConcept(content: string): { frontmatter: OkfFrontmatter; body: string } {\n const { frontmatter, rest } = parseFrontmatter(content);\n const body = rest.startsWith('\\n') ? rest.slice(1) : rest;\n return { frontmatter, body };\n}\n","import { parseFrontmatter, serializeScalarString } from './frontmatter';\nimport type { OkfIndexEntry, OkfIndexSection } from './types';\n\nfunction renderEntry(entry: OkfIndexEntry): string {\n const esc = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n\n const title = esc(entry.title);\n const description = entry.description ? esc(entry.description) : undefined;\n\n return description\n ? `* [${title}](${entry.path}) - ${description}`\n : `* [${title}](${entry.path})`;\n}\n\nfunction renderSections(sections: OkfIndexSection[]): string {\n const lines: string[] = [];\n for (const section of sections) {\n lines.push(`## ${section.heading}`);\n lines.push('');\n for (const entry of section.entries) {\n lines.push(renderEntry(entry));\n }\n lines.push('');\n }\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nexport function buildIndexMd(sections: OkfIndexSection[]): string {\n return renderSections(sections);\n}\n\nexport function buildRootIndexMd(\n okfVersion: string,\n sections: OkfIndexSection[],\n options?: { profile?: string },\n): string {\n const lines = ['---', `okf_version: ${serializeScalarString(okfVersion)}`];\n if (options?.profile) {\n lines.push(`profile: ${serializeScalarString(options.profile)}`);\n }\n lines.push('---', '');\n return `${lines.join('\\n')}\\n${renderSections(sections)}`;\n}\n\nexport function parseRootIndexMd(content: string): { okf_version?: string; profile?: string } {\n const { frontmatter } = parseFrontmatter(content);\n const okf = frontmatter.okf_version;\n return {\n okf_version:\n typeof okf === 'string' ? okf : typeof okf === 'number' && Number.isFinite(okf) ? String(okf) : undefined,\n profile: typeof frontmatter.profile === 'string' ? frontmatter.profile : undefined,\n };\n}\n","import type { OkfIndexSection } from './types';\nimport { buildIndexMd } from './index-md';\n\nconst EVENT_LOG_LINK = /^\\[Event log\\]\\(\\.\\/log\\.md\\)\\s*$/;\nconst TOP_LEVEL_H1 = /^#\\s+.+\\s*$/;\nconst SECTION_HEADING = /^##\\s+(.+)\\s*$/;\nconst INDEX_ENTRY = /^\\*\\s+\\[((?:\\\\.|[^\\]])*)\\]\\(([^)]+)\\)(?:\\s+-\\s+(.*))?$/;\n\nfunction unescapeIndexTitle(title: string): string {\n return title.replace(/\\\\\\]/g, ']').replace(/\\\\\\[/g, '[').replace(/\\\\\\\\/g, '\\\\');\n}\n\nexport function buildEntityIndexMd(options: {\n summary?: string;\n sections: OkfIndexSection[];\n}): string {\n const parts: string[] = [];\n if (options.summary?.trim()) {\n parts.push(options.summary.trimEnd(), '');\n }\n const sectionsMd = buildIndexMd(options.sections).trimEnd();\n if (sectionsMd) {\n parts.push(sectionsMd);\n parts.push('');\n }\n parts.push('[Event log](./log.md)');\n return `${parts.join('\\n')}\\n`;\n}\n\nexport function parseEntityIndexMd(content: string): {\n summary: string;\n sections: OkfIndexSection[];\n} {\n const lines = content.split(/\\r?\\n/);\n\n // Optional frontmatter block (--- ... ---) per profile.\n let start = 0;\n if (lines[0]?.trim() === '---') {\n const closing = lines.findIndex((line, idx) => idx > 0 && line.trim() === '---');\n if (closing !== -1) start = closing + 1;\n }\n\n const firstSectionIdx = lines.findIndex((line, idx) => idx >= start && SECTION_HEADING.test(line));\n const summaryEnd = firstSectionIdx === -1 ? lines.length : firstSectionIdx;\n const summaryLines = lines\n .slice(start, summaryEnd)\n .filter(line => !EVENT_LOG_LINK.test(line.trim()));\n let summaryStart = 0;\n while (summaryStart < summaryLines.length && summaryLines[summaryStart].trim() === '') {\n summaryStart += 1;\n }\n if (summaryStart < summaryLines.length && TOP_LEVEL_H1.test(summaryLines[summaryStart].trim())) {\n summaryStart += 1;\n }\n const summary = summaryLines.slice(summaryStart).join('\\n').trim();\n\n const sections: OkfIndexSection[] = [];\n if (firstSectionIdx === -1) return { summary, sections };\n\n let current: OkfIndexSection | null = null;\n for (let i = Math.max(firstSectionIdx, start); i < lines.length; i += 1) {\n const line = lines[i];\n if (EVENT_LOG_LINK.test(line.trim())) continue;\n\n const headingMatch = SECTION_HEADING.exec(line);\n if (headingMatch) {\n current = { heading: headingMatch[1], entries: [] };\n sections.push(current);\n continue;\n }\n\n if (!current) continue;\n const entryMatch = INDEX_ENTRY.exec(line);\n if (!entryMatch) continue;\n\n current.entries.push({\n title: unescapeIndexTitle(entryMatch[1]),\n path: entryMatch[2],\n description: entryMatch[3] ? unescapeIndexTitle(entryMatch[3]) : undefined,\n });\n }\n return { summary, sections };\n}\n","import type { OkfLogEntry } from './types';\n\nexport function buildLogMd(entries: OkfLogEntry[]): string {\n const groups = new Map<string, OkfLogEntry[]>();\n for (const entry of entries) {\n const group = groups.get(entry.date) ?? [];\n group.push(entry);\n groups.set(entry.date, group);\n }\n\n const dates = Array.from(groups.keys()).sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\n const lines: string[] = [];\n for (const date of dates) {\n lines.push(`## ${date}`);\n lines.push('');\n for (const entry of groups.get(date)!) {\n lines.push(`- ${entry.text}`);\n }\n lines.push('');\n }\n\n if (lines.length === 0) return '';\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\nconst EVENT_ID_COMMENT = /\\s*<!--\\s*id:\\s*(\\S+)\\s*-->\\s*$/;\n\nexport function appendEventIdComment(text: string, eventId: string): string {\n if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return text;\n return `${text} <!-- id: ${eventId} -->`;\n}\n\nexport function parseEventIdComment(text: string): { text: string; eventId?: string } {\n const match = EVENT_ID_COMMENT.exec(text);\n if (!match) return { text };\n const eventId = match[1];\n const stripped = text.slice(0, match.index).trimEnd();\n if (!/^[A-Za-z0-9._-]+$/.test(eventId)) return { text: stripped };\n return { text: stripped, eventId };\n}\n\nconst DATE_HEADING = /^##\\s+(\\d{4}-\\d{2}-\\d{2})\\s*$/;\nconst BULLET = /^-\\s+(.*)$/;\n\n/**\n * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact\n * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,\n * not thrown — a foreign log.md in a different format degrades to fewer entries\n * rather than failing the import.\n */\nexport function parseLogMd(content: string): OkfLogEntry[] {\n const entries: OkfLogEntry[] = [];\n let currentDate: string | null = null;\n\n for (const line of content.split(/\\r?\\n/)) {\n const headingMatch = DATE_HEADING.exec(line);\n if (headingMatch) {\n currentDate = headingMatch[1];\n continue;\n }\n const bulletMatch = BULLET.exec(line);\n if (bulletMatch && currentDate) {\n entries.push({ date: currentDate, text: bulletMatch[1] });\n }\n }\n\n return entries;\n}\n","import type { OkfMarkdownLink } from './types';\n\nfunction escapeLinkLabel(label: string): string {\n return label\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\\[/g, '\\\\[')\n .replace(/\\]/g, '\\\\]')\n .replace(/\\r?\\n/g, ' ');\n}\n\nexport function appendRelatedSection(\n body: string,\n links: Array<{ edge_type: string; path: string }>,\n): string {\n if (links.length === 0) return body;\n const prefix =\n body.length === 0\n ? ''\n : body.endsWith('\\n\\n')\n ? body\n : body.endsWith('\\n')\n ? `${body}\\n`\n : `${body}\\n\\n`;\n const lines = ['## Related', ''];\n for (const link of links) {\n lines.push(`- [${escapeLinkLabel(link.edge_type)}](${link.path})`);\n }\n return `${prefix}${lines.join('\\n')}\\n`;\n}\n\nexport function splitRelatedSection(body: string): { body: string; relatedLinks: OkfMarkdownLink[] } {\n const lines = body.split(/\\r?\\n/);\n let end = lines.length;\n while (end > 0 && lines[end - 1].trim() === '') end -= 1;\n\n let scan = end - 1;\n while (scan >= 0 && /^-\\s+/.test(lines[scan])) scan -= 1;\n while (scan >= 0 && lines[scan].trim() === '') scan -= 1;\n\n if (scan < 0 || lines[scan].trim() !== '## Related') {\n return { body, relatedLinks: [] };\n }\n\n const relatedStart = scan;\n const contentBody = lines.slice(0, relatedStart).join('\\n');\n const relatedBlock = lines.slice(relatedStart, end).join('\\n');\n const relatedLinks: OkfMarkdownLink[] = [];\n for (const line of relatedBlock.split(/\\r?\\n/)) {\n const bullet = /^-\\s+(.*)$/.exec(line);\n if (!bullet) continue;\n\n const linkPattern = /\\[((?:\\\\.|[^\\]])*)\\]\\(([^)\\s]+)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(bullet[1])) !== null) {\n const linkPath = match[2];\n if (/^(https?:|mailto:)/i.test(linkPath)) continue;\n relatedLinks.push({\n text: match[1].replace(/\\\\\\]/g, ']').replace(/\\\\\\[/g, '[').replace(/\\\\\\\\/g, '\\\\'),\n path: linkPath,\n });\n }\n }\n const normalizedBody =\n contentBody.length === 0 ? '' : contentBody.endsWith('\\n') ? contentBody : `${contentBody}\\n`;\n return { body: normalizedBody, relatedLinks };\n}\n","const ALLOWED =\n /^(index\\.md|entities\\/[^/]+\\/(index\\.md|log\\.md|(facts|tasks)\\/[^/]+\\.md))$/;\n\nexport function isAllowedOkfPath(filePath: string): boolean {\n const normalized = filePath.replace(/^\\.\\//, '').replace(/\\\\/g, '/');\n if (normalized.split('/').some(segment => segment === '.' || segment === '..')) {\n return false;\n }\n return ALLOWED.test(normalized);\n}\n","import type { OkfMarkdownLink } from './types';\n\nconst EXCLUDED_SCHEME = /^(https?:|mailto:)/i;\nconst FENCED_CODE_BLOCK_PATTERN = /```[\\s\\S]*?```/g;\n\n/**\n * Extracts inline markdown links (`[text](path)`) from a concept body.\n * Single-line regex, not a CommonMark parser — reference-style links, links\n * split across lines, and links inside code fences are not recognized.\n * `http(s):` and `mailto:` targets are excluded; only relative/local paths\n * are candidates for graph edges.\n */\nexport function extractMarkdownLinks(body: string): OkfMarkdownLink[] {\n const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, '');\n const linkPattern = /\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g;\n const links: OkfMarkdownLink[] = [];\n let match: RegExpExecArray | null;\n while ((match = linkPattern.exec(searchableBody)) !== null) {\n const [, text, path] = match;\n if (EXCLUDED_SCHEME.test(path)) continue;\n links.push({ text, path });\n }\n return links;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equationalapplications/core-okf",
3
- "version": "4.17.3",
3
+ "version": "4.18.1",
4
4
  "description": "Zero-dependency Open Knowledge Format (OKF) v0.1 primitives: frontmatter serialization, concept documents, index.md and log.md builders.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",