@equationalapplications/core-okf 4.13.1 → 4.15.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
@@ -1,3 +1,74 @@
1
1
  # @equationalapplications/core-okf
2
2
 
3
- Zero-dependency primitives for producing [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md) (OKF v0.1) bundles: YAML frontmatter serialization, concept document assembly, and `index.md`/`log.md` builders. No knowledge of any specific data model — bring your own mapping from your domain objects to `OkfFrontmatter` + body strings.
3
+ [![npm version](https://img.shields.io/npm/v/%40equationalapplications%2Fcore-okf?label=core-okf)](https://www.npmjs.com/package/@equationalapplications/core-okf) [![npm downloads](https://img.shields.io/npm/dm/%40equationalapplications%2Fcore-okf?label=downloads)](https://www.npmjs.com/package/@equationalapplications/core-okf)
4
+
5
+ ## Overview
6
+
7
+ A zero-dependency library for parsing and producing [Open Knowledge Format (OKF) v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) bundles. This package provides the raw primitives to work with OKF frontmatter, concept documents, and index/log files, completely decoupled from any specific database or data model.
8
+
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
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @equationalapplications/core-okf
15
+ ```
16
+
17
+ ## API Reference
18
+
19
+ ### `serializeFrontmatter` / `parseFrontmatter`
20
+
21
+ Produces and parses YAML frontmatter for OKF concept documents.
22
+
23
+ ```typescript
24
+ const yaml = serializeFrontmatter({ type: 'fact', id: 'fact_123' });
25
+ const { frontmatter, rest } = parseFrontmatter(fileContent);
26
+ ```
27
+
28
+ ### `buildConceptDocument` / `parseConcept`
29
+
30
+ Combines frontmatter and markdown body into a single string, or splits an existing OKF file into its component parts.
31
+
32
+ ```typescript
33
+ const markdown = buildConceptDocument({ type: 'task', id: 'task_1' }, '# Buy groceries');
34
+ const { frontmatter, body } = parseConcept(markdown);
35
+ ```
36
+
37
+ ### `buildIndexMd` / `buildRootIndexMd`
38
+
39
+ Generates directory index lists or root OKF catalog manifests.
40
+
41
+ ```typescript
42
+ const sections = [{ heading: 'Facts', entries: [{ path: 'facts/fact_123.md', title: 'Fact 123' }] }];
43
+ const dirIndex = buildIndexMd(sections);
44
+ const rootIndex = buildRootIndexMd('0.1', sections);
45
+ ```
46
+
47
+ ### `buildLogMd` / `parseLogMd`
48
+
49
+ Serializes chronological append-only events or parses them back into discrete entries.
50
+
51
+ ```typescript
52
+ const log = buildLogMd([{ date: '2026-06-23', text: 'Observation made' }]);
53
+ const events = parseLogMd(logContent);
54
+ ```
55
+
56
+ ### `extractMarkdownLinks`
57
+
58
+ Parses relative markdown cross-links to map knowledge graph edges.
59
+
60
+ ```typescript
61
+ const links = extractMarkdownLinks('See [preferences](facts/fact_abc.md) for more.');
62
+ // links: [{ text: 'preferences', path: 'facts/fact_abc.md' }]
63
+ ```
64
+
65
+ ## Monorepo Ecosystem
66
+
67
+ | Package | Purpose |
68
+ | --- | --- |
69
+ | [@equationalapplications/core-llm-wiki](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/core/README.md) | Persistent episodic memory |
70
+ | [@equationalapplications/expo-llm-wiki](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/expo/README.md) | Persistent episodic memory for Expo/React Native |
71
+ | [@equationalapplications/react-llm-wiki](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/react/README.md) | Persistent episodic memory for Web |
72
+ | [@equationalapplications/prisma-outbox](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/prisma-outbox/README.md) | Sync SQLite outbox events to Prisma |
73
+ | [@equationalapplications/core-llm-tools](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/core-llm-tools/README.md) | Gemini tool schemas and capability injector |
74
+ | **@equationalapplications/core-okf** | Zero-dependency Open Knowledge Format (OKF) v0.1 primitives — parse and produce interoperable knowledge bundles. |
package/dist/index.d.mts CHANGED
@@ -26,14 +26,52 @@ interface OkfFile {
26
26
  path: string;
27
27
  content: string;
28
28
  }
29
+ interface OkfMarkdownLink {
30
+ text: string;
31
+ path: string;
32
+ }
29
33
 
30
34
  declare function serializeFrontmatter(fm: OkfFrontmatter): string;
35
+ /**
36
+ * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:
37
+ * scalar string/number/boolean/null values, quoted strings, and block string-lists.
38
+ * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block
39
+ * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match
40
+ * a recognized shape are silently skipped rather than throwing, so a foreign bundle
41
+ * never crashes
42
+ * the import — it just loses fidelity on the unrecognized line.
43
+ */
44
+ declare function parseFrontmatter(content: string): {
45
+ frontmatter: OkfFrontmatter;
46
+ rest: string;
47
+ };
31
48
 
32
49
  declare function buildConceptDocument(fm: OkfFrontmatter, body: string): string;
50
+ /** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */
51
+ declare function parseConcept(content: string): {
52
+ frontmatter: OkfFrontmatter;
53
+ body: string;
54
+ };
33
55
 
34
56
  declare function buildIndexMd(sections: OkfIndexSection[]): string;
35
57
  declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string;
36
58
 
37
59
  declare function buildLogMd(entries: OkfLogEntry[]): string;
60
+ /**
61
+ * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact
62
+ * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,
63
+ * not thrown — a foreign log.md in a different format degrades to fewer entries
64
+ * rather than failing the import.
65
+ */
66
+ declare function parseLogMd(content: string): OkfLogEntry[];
67
+
68
+ /**
69
+ * Extracts inline markdown links (`[text](path)`) from a concept body.
70
+ * Single-line regex, not a CommonMark parser — reference-style links, links
71
+ * split across lines, and links inside code fences are not recognized.
72
+ * `http(s):` and `mailto:` targets are excluded; only relative/local paths
73
+ * are candidates for graph edges.
74
+ */
75
+ declare function extractMarkdownLinks(body: string): OkfMarkdownLink[];
38
76
 
39
- export { type OkfFile, type OkfFrontmatter, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, serializeFrontmatter };
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 };
package/dist/index.d.ts CHANGED
@@ -26,14 +26,52 @@ interface OkfFile {
26
26
  path: string;
27
27
  content: string;
28
28
  }
29
+ interface OkfMarkdownLink {
30
+ text: string;
31
+ path: string;
32
+ }
29
33
 
30
34
  declare function serializeFrontmatter(fm: OkfFrontmatter): string;
35
+ /**
36
+ * Parses the subset of YAML frontmatter that {@link serializeFrontmatter} produces:
37
+ * scalar string/number/boolean/null values, quoted strings, and block string-lists.
38
+ * NOT a general YAML parser — flow collections (`[...]`/`{...}`), multi-line block
39
+ * scalars (`|`/`>`), anchors, and aliases are not recognized. Lines that don't match
40
+ * a recognized shape are silently skipped rather than throwing, so a foreign bundle
41
+ * never crashes
42
+ * the import — it just loses fidelity on the unrecognized line.
43
+ */
44
+ declare function parseFrontmatter(content: string): {
45
+ frontmatter: OkfFrontmatter;
46
+ rest: string;
47
+ };
31
48
 
32
49
  declare function buildConceptDocument(fm: OkfFrontmatter, body: string): string;
50
+ /** Reverse of {@link buildConceptDocument}: strips the single leading blank-line separator. */
51
+ declare function parseConcept(content: string): {
52
+ frontmatter: OkfFrontmatter;
53
+ body: string;
54
+ };
33
55
 
34
56
  declare function buildIndexMd(sections: OkfIndexSection[]): string;
35
57
  declare function buildRootIndexMd(okfVersion: string, sections: OkfIndexSection[]): string;
36
58
 
37
59
  declare function buildLogMd(entries: OkfLogEntry[]): string;
60
+ /**
61
+ * Reverse of {@link buildLogMd}. Best-effort: lines that don't match the exact
62
+ * `## YYYY-MM-DD` heading or `- text` bullet shape buildLogMd emits are skipped,
63
+ * not thrown — a foreign log.md in a different format degrades to fewer entries
64
+ * rather than failing the import.
65
+ */
66
+ declare function parseLogMd(content: string): OkfLogEntry[];
67
+
68
+ /**
69
+ * Extracts inline markdown links (`[text](path)`) from a concept body.
70
+ * Single-line regex, not a CommonMark parser — reference-style links, links
71
+ * split across lines, and links inside code fences are not recognized.
72
+ * `http(s):` and `mailto:` targets are excluded; only relative/local paths
73
+ * are candidates for graph edges.
74
+ */
75
+ declare function extractMarkdownLinks(body: string): OkfMarkdownLink[];
38
76
 
39
- export { type OkfFile, type OkfFrontmatter, type OkfIndexEntry, type OkfIndexSection, type OkfLogEntry, buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, serializeFrontmatter };
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 };
package/dist/index.js CHANGED
@@ -63,12 +63,135 @@ function serializeFrontmatter(fm) {
63
63
  lines.push("---");
64
64
  return lines.join("\n") + "\n";
65
65
  }
66
+ function unescapeFrontmatterString(escaped) {
67
+ let result = "";
68
+ for (let i = 0; i < escaped.length; i++) {
69
+ const ch = escaped[i];
70
+ if (ch === "\\" && i + 1 < escaped.length) {
71
+ const next = escaped[i + 1];
72
+ if (next === "n") {
73
+ result += "\n";
74
+ i++;
75
+ continue;
76
+ }
77
+ if (next === "r") {
78
+ result += "\r";
79
+ i++;
80
+ continue;
81
+ }
82
+ if (next === "t") {
83
+ result += " ";
84
+ i++;
85
+ continue;
86
+ }
87
+ if (next === '"') {
88
+ result += '"';
89
+ i++;
90
+ continue;
91
+ }
92
+ if (next === "\\") {
93
+ result += "\\";
94
+ i++;
95
+ continue;
96
+ }
97
+ }
98
+ result += ch;
99
+ }
100
+ return result;
101
+ }
102
+ function unescapeSingleQuotedString(escaped) {
103
+ return escaped.replace(/''/g, "'");
104
+ }
105
+ function parseQuotedScalar(raw) {
106
+ const trimmed = raw.trim();
107
+ if (trimmed.length < 2) return null;
108
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
109
+ return unescapeFrontmatterString(trimmed.slice(1, -1));
110
+ }
111
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
112
+ return unescapeSingleQuotedString(trimmed.slice(1, -1));
113
+ }
114
+ return null;
115
+ }
116
+ function parseKey(raw) {
117
+ return parseQuotedScalar(raw) ?? raw.trim();
118
+ }
119
+ function parseScalarValue(raw) {
120
+ const quoted = parseQuotedScalar(raw);
121
+ if (quoted !== null) return quoted;
122
+ const trimmed = raw.trim();
123
+ if (trimmed === "null") return null;
124
+ if (trimmed === "true") return true;
125
+ if (trimmed === "false") return false;
126
+ if (/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(trimmed)) return Number(trimmed);
127
+ return trimmed;
128
+ }
129
+ function matchFrontmatterKeyValue(line) {
130
+ const keyMatch = /^(?:"(?:\\.|[^"\\])*"|'(?:''|[^'])*'|[^:]+)/.exec(line);
131
+ if (!keyMatch) return null;
132
+ const key = keyMatch[0];
133
+ if (line[key.length] !== ":") return null;
134
+ const tail = line.slice(key.length + 1);
135
+ return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };
136
+ }
137
+ function parseFrontmatter(content) {
138
+ const lines = content.split(/\r?\n/);
139
+ const fallback = { frontmatter: { type: "" }, rest: content };
140
+ if (lines[0]?.trim() !== "---") return fallback;
141
+ let closingIndex = -1;
142
+ for (let i2 = 1; i2 < lines.length; i2++) {
143
+ if (lines[i2].trim() === "---") {
144
+ closingIndex = i2;
145
+ break;
146
+ }
147
+ }
148
+ if (closingIndex === -1) return fallback;
149
+ const frontmatter = {};
150
+ let i = 1;
151
+ while (i < closingIndex) {
152
+ const line = lines[i];
153
+ const kv = matchFrontmatterKeyValue(line);
154
+ if (!kv) {
155
+ i++;
156
+ continue;
157
+ }
158
+ if (kv.value.trim() === "[]") {
159
+ frontmatter[parseKey(kv.key)] = [];
160
+ i++;
161
+ continue;
162
+ }
163
+ if (!kv.hasValue) {
164
+ const key = parseKey(kv.key);
165
+ const items = [];
166
+ i++;
167
+ while (i < closingIndex && /^\s*-\s/.test(lines[i])) {
168
+ items.push(parseScalarValue(lines[i].replace(/^\s*-\s/, "")));
169
+ i++;
170
+ }
171
+ frontmatter[key] = items;
172
+ continue;
173
+ }
174
+ frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);
175
+ i++;
176
+ }
177
+ if (typeof frontmatter["type"] !== "string") {
178
+ frontmatter["type"] = "";
179
+ }
180
+ const restLines = lines.slice(closingIndex + 1);
181
+ const rest = restLines.length > 0 ? restLines.join("\n") : "";
182
+ return { frontmatter, rest };
183
+ }
66
184
 
67
185
  // src/concept.ts
68
186
  function buildConceptDocument(fm, body) {
69
187
  return `${serializeFrontmatter(fm)}
70
188
  ${body}`;
71
189
  }
190
+ function parseConcept(content) {
191
+ const { frontmatter, rest } = parseFrontmatter(content);
192
+ const body = rest.startsWith("\n") ? rest.slice(1) : rest;
193
+ return { frontmatter, body };
194
+ }
72
195
 
73
196
  // src/index-md.ts
74
197
  function renderEntry(entry) {
@@ -123,11 +246,49 @@ function buildLogMd(entries) {
123
246
  if (lines.length === 0) return "";
124
247
  return lines.join("\n").trimEnd() + "\n";
125
248
  }
249
+ var DATE_HEADING = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
250
+ var BULLET = /^-\s+(.*)$/;
251
+ function parseLogMd(content) {
252
+ const entries = [];
253
+ let currentDate = null;
254
+ for (const line of content.split(/\r?\n/)) {
255
+ const headingMatch = DATE_HEADING.exec(line);
256
+ if (headingMatch) {
257
+ currentDate = headingMatch[1];
258
+ continue;
259
+ }
260
+ const bulletMatch = BULLET.exec(line);
261
+ if (bulletMatch && currentDate) {
262
+ entries.push({ date: currentDate, text: bulletMatch[1] });
263
+ }
264
+ }
265
+ return entries;
266
+ }
267
+
268
+ // src/markdown-links.ts
269
+ var EXCLUDED_SCHEME = /^(https?:|mailto:)/i;
270
+ var FENCED_CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
271
+ function extractMarkdownLinks(body) {
272
+ const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, "");
273
+ const linkPattern = /\[([^\]]*)\]\(([^)\s]+)\)/g;
274
+ const links = [];
275
+ let match;
276
+ while ((match = linkPattern.exec(searchableBody)) !== null) {
277
+ const [, text, path] = match;
278
+ if (EXCLUDED_SCHEME.test(path)) continue;
279
+ links.push({ text, path });
280
+ }
281
+ return links;
282
+ }
126
283
 
127
284
  exports.buildConceptDocument = buildConceptDocument;
128
285
  exports.buildIndexMd = buildIndexMd;
129
286
  exports.buildLogMd = buildLogMd;
130
287
  exports.buildRootIndexMd = buildRootIndexMd;
288
+ exports.extractMarkdownLinks = extractMarkdownLinks;
289
+ exports.parseConcept = parseConcept;
290
+ exports.parseFrontmatter = parseFrontmatter;
291
+ exports.parseLogMd = parseLogMd;
131
292
  exports.serializeFrontmatter = serializeFrontmatter;
132
293
  //# sourceMappingURL=index.js.map
133
294
  //# 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"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { OkfFrontmatter } 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","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${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"]}
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"]}
package/dist/index.mjs CHANGED
@@ -61,12 +61,135 @@ function serializeFrontmatter(fm) {
61
61
  lines.push("---");
62
62
  return lines.join("\n") + "\n";
63
63
  }
64
+ function unescapeFrontmatterString(escaped) {
65
+ let result = "";
66
+ for (let i = 0; i < escaped.length; i++) {
67
+ const ch = escaped[i];
68
+ if (ch === "\\" && i + 1 < escaped.length) {
69
+ const next = escaped[i + 1];
70
+ if (next === "n") {
71
+ result += "\n";
72
+ i++;
73
+ continue;
74
+ }
75
+ if (next === "r") {
76
+ result += "\r";
77
+ i++;
78
+ continue;
79
+ }
80
+ if (next === "t") {
81
+ result += " ";
82
+ i++;
83
+ continue;
84
+ }
85
+ if (next === '"') {
86
+ result += '"';
87
+ i++;
88
+ continue;
89
+ }
90
+ if (next === "\\") {
91
+ result += "\\";
92
+ i++;
93
+ continue;
94
+ }
95
+ }
96
+ result += ch;
97
+ }
98
+ return result;
99
+ }
100
+ function unescapeSingleQuotedString(escaped) {
101
+ return escaped.replace(/''/g, "'");
102
+ }
103
+ function parseQuotedScalar(raw) {
104
+ const trimmed = raw.trim();
105
+ if (trimmed.length < 2) return null;
106
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
107
+ return unescapeFrontmatterString(trimmed.slice(1, -1));
108
+ }
109
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
110
+ return unescapeSingleQuotedString(trimmed.slice(1, -1));
111
+ }
112
+ return null;
113
+ }
114
+ function parseKey(raw) {
115
+ return parseQuotedScalar(raw) ?? raw.trim();
116
+ }
117
+ function parseScalarValue(raw) {
118
+ const quoted = parseQuotedScalar(raw);
119
+ if (quoted !== null) return quoted;
120
+ const trimmed = raw.trim();
121
+ if (trimmed === "null") return null;
122
+ if (trimmed === "true") return true;
123
+ if (trimmed === "false") return false;
124
+ if (/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(trimmed)) return Number(trimmed);
125
+ return trimmed;
126
+ }
127
+ function matchFrontmatterKeyValue(line) {
128
+ const keyMatch = /^(?:"(?:\\.|[^"\\])*"|'(?:''|[^'])*'|[^:]+)/.exec(line);
129
+ if (!keyMatch) return null;
130
+ const key = keyMatch[0];
131
+ if (line[key.length] !== ":") return null;
132
+ const tail = line.slice(key.length + 1);
133
+ return { key, value: tail.trimStart(), hasValue: tail.trim().length > 0 };
134
+ }
135
+ function parseFrontmatter(content) {
136
+ const lines = content.split(/\r?\n/);
137
+ const fallback = { frontmatter: { type: "" }, rest: content };
138
+ if (lines[0]?.trim() !== "---") return fallback;
139
+ let closingIndex = -1;
140
+ for (let i2 = 1; i2 < lines.length; i2++) {
141
+ if (lines[i2].trim() === "---") {
142
+ closingIndex = i2;
143
+ break;
144
+ }
145
+ }
146
+ if (closingIndex === -1) return fallback;
147
+ const frontmatter = {};
148
+ let i = 1;
149
+ while (i < closingIndex) {
150
+ const line = lines[i];
151
+ const kv = matchFrontmatterKeyValue(line);
152
+ if (!kv) {
153
+ i++;
154
+ continue;
155
+ }
156
+ if (kv.value.trim() === "[]") {
157
+ frontmatter[parseKey(kv.key)] = [];
158
+ i++;
159
+ continue;
160
+ }
161
+ if (!kv.hasValue) {
162
+ const key = parseKey(kv.key);
163
+ const items = [];
164
+ i++;
165
+ while (i < closingIndex && /^\s*-\s/.test(lines[i])) {
166
+ items.push(parseScalarValue(lines[i].replace(/^\s*-\s/, "")));
167
+ i++;
168
+ }
169
+ frontmatter[key] = items;
170
+ continue;
171
+ }
172
+ frontmatter[parseKey(kv.key)] = parseScalarValue(kv.value);
173
+ i++;
174
+ }
175
+ if (typeof frontmatter["type"] !== "string") {
176
+ frontmatter["type"] = "";
177
+ }
178
+ const restLines = lines.slice(closingIndex + 1);
179
+ const rest = restLines.length > 0 ? restLines.join("\n") : "";
180
+ return { frontmatter, rest };
181
+ }
64
182
 
65
183
  // src/concept.ts
66
184
  function buildConceptDocument(fm, body) {
67
185
  return `${serializeFrontmatter(fm)}
68
186
  ${body}`;
69
187
  }
188
+ function parseConcept(content) {
189
+ const { frontmatter, rest } = parseFrontmatter(content);
190
+ const body = rest.startsWith("\n") ? rest.slice(1) : rest;
191
+ return { frontmatter, body };
192
+ }
70
193
 
71
194
  // src/index-md.ts
72
195
  function renderEntry(entry) {
@@ -121,7 +244,41 @@ function buildLogMd(entries) {
121
244
  if (lines.length === 0) return "";
122
245
  return lines.join("\n").trimEnd() + "\n";
123
246
  }
247
+ var DATE_HEADING = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
248
+ var BULLET = /^-\s+(.*)$/;
249
+ function parseLogMd(content) {
250
+ const entries = [];
251
+ let currentDate = null;
252
+ for (const line of content.split(/\r?\n/)) {
253
+ const headingMatch = DATE_HEADING.exec(line);
254
+ if (headingMatch) {
255
+ currentDate = headingMatch[1];
256
+ continue;
257
+ }
258
+ const bulletMatch = BULLET.exec(line);
259
+ if (bulletMatch && currentDate) {
260
+ entries.push({ date: currentDate, text: bulletMatch[1] });
261
+ }
262
+ }
263
+ return entries;
264
+ }
265
+
266
+ // src/markdown-links.ts
267
+ var EXCLUDED_SCHEME = /^(https?:|mailto:)/i;
268
+ var FENCED_CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
269
+ function extractMarkdownLinks(body) {
270
+ const searchableBody = body.replace(FENCED_CODE_BLOCK_PATTERN, "");
271
+ const linkPattern = /\[([^\]]*)\]\(([^)\s]+)\)/g;
272
+ const links = [];
273
+ let match;
274
+ while ((match = linkPattern.exec(searchableBody)) !== null) {
275
+ const [, text, path] = match;
276
+ if (EXCLUDED_SCHEME.test(path)) continue;
277
+ links.push({ text, path });
278
+ }
279
+ return links;
280
+ }
124
281
 
125
- export { buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, serializeFrontmatter };
282
+ export { buildConceptDocument, buildIndexMd, buildLogMd, buildRootIndexMd, extractMarkdownLinks, parseConcept, parseFrontmatter, parseLogMd, serializeFrontmatter };
126
283
  //# sourceMappingURL=index.mjs.map
127
284
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frontmatter.ts","../src/concept.ts","../src/index-md.ts","../src/log-md.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { OkfFrontmatter } 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","import type { OkfFrontmatter } from './types';\nimport { serializeFrontmatter } from './frontmatter';\n\nexport function buildConceptDocument(fm: OkfFrontmatter, body: string): string {\n return `${serializeFrontmatter(fm)}\\n${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"]}
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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equationalapplications/core-okf",
3
- "version": "4.13.1",
3
+ "version": "4.15.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",
@@ -12,13 +12,6 @@
12
12
  "import": "./dist/index.mjs"
13
13
  }
14
14
  },
15
- "scripts": {
16
- "build": "tsup",
17
- "dev": "tsup --watch",
18
- "typecheck": "tsc --noEmit",
19
- "test": "vitest run",
20
- "test:watch": "vitest"
21
- },
22
15
  "files": [
23
16
  "dist",
24
17
  "LICENSE",
@@ -53,5 +46,12 @@
53
46
  "tsup": "^8.0.0",
54
47
  "typescript": "^5.4.0",
55
48
  "vitest": "4.1.5"
49
+ },
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "dev": "tsup --watch",
53
+ "typecheck": "tsc --noEmit",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest"
56
56
  }
57
- }
57
+ }