mdld-parse 0.6.2 โ†’ 0.7.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
@@ -4,87 +4,87 @@
4
4
 
5
5
  [![NPM](https://img.shields.io/npm/v/mdld-parse)](https://www.npmjs.com/package/mdld-parse)
6
6
 
7
- [Documentation](https://mdld.js.org) | [Repository](https://github.com/davay42/mdld-parse) | [Playground](https://mdld.js.org/playground)
7
+ [Demo](https://mdld.js.org) | [Repository](https://github.com/davay42/mdld-parse)
8
8
 
9
- ## What is MD-LD?
9
+ ## ๐Ÿš€ Quick Start
10
10
 
11
- MD-LD allows you to author RDF graphs directly in Markdown using explicit `{...}` annotations:
12
-
13
- ```markdown
14
- [my] <tag:alice@example.com,2026:>
15
-
16
- # 2024-07-18 {=my:journal-2024-07-18 .my:Event my:date ^^xsd:date}
11
+ ```bash
12
+ pnpm install mdld-parse
13
+ ```
17
14
 
18
- ## A good day {label}
15
+ ```javascript
16
+ import { parse } from 'mdld-parse';
19
17
 
20
- Mood: [Happy] {my:mood}
21
- Energy level: [8] {my:energyLevel ^^xsd:integer}
18
+ const result = parse(`
19
+ [ex] <http://example.org/>
22
20
 
23
- Met [Sam] {+my:sam .my:Person ?my:attendee} on my regular walk at [Central Park] {+my:central-park ?my:location .my:Place label @en} and talked about [Sunny] {my:weather} weather.
21
+ # Document {=ex:doc .ex:Article label}
24
22
 
25
- Activities:
23
+ [Alice] {?ex:author =ex:alice .prov:Person ex:firstName label}
24
+ [Smith] {ex:lastName}`);
26
25
 
27
- - **Walking** {+ex:walking ?my:hasActivity .my:Activity label}
28
- - **Reading** {+ex:reading ?my:hasActivity .my:Activity label}
26
+ console.log(result.quads);
27
+ // RDF/JS quads ready for n3.js, rdflib, etc.
28
+ // @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
29
+ // @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
30
+ // @prefix prov: <http://www.w3.org/ns/prov#>.
31
+ // @prefix ex: <http://example.org/>.
29
32
 
33
+ // ex:doc a ex:Article;
34
+ // rdfs:label "Document";
35
+ // ex:author ex:alice.
36
+ // ex:alice a prov:Person;
37
+ // rdfs:label "Alice";
38
+ // ex:firstName "Alice";
39
+ // ex:lastName "Smith".
30
40
  ```
31
41
 
32
- Generates valid RDF triples:
33
-
34
- ```turtle
35
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
36
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
37
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
38
- @prefix sh: <http://www.w3.org/ns/shacl#>.
39
- @prefix prov: <http://www.w3.org/ns/prov#>.
40
- @prefix ex: <http://example.org/>.
41
- @prefix my: <tag:alice@example.com,2026:>.
42
-
43
- my:journal-2024-07-18 a my:Event;
44
- my:date "2024-07-18"^^xsd:date;
45
- rdfs:label "A good day";
46
- my:mood "Happy";
47
- my:energyLevel 8;
48
- my:attendee my:sam;
49
- my:location my:central-park;
50
- my:weather "Sunny";
51
- my:hasActivity <tag:alice@example.com,2026:journal-2024-07-18#walking>, <tag:alice@example.com,2026:journal-2024-07-18#reading>.
52
- my:sam a my:Person.
53
- my:central-park a my:Place;
54
- rdfs:label "Central Park"@en.
55
- <tag:alice@example.com,2026:journal-2024-07-18#walking> a my:Activity;
56
- rdfs:label "Walking".
57
- <tag:alice@example.com,2026:journal-2024-07-18#reading> a my:Activity;
58
- rdfs:label "Reading".
42
+ ## ๐Ÿ“š Documentation Hub
59
43
 
60
- ```
44
+ - **๐Ÿ“– [Documentation](./docs/index.md)** - Complete documentation with guides and references
45
+ - **๐ŸŽฏ [Examples](./examples/index.md)** - Real-world MD-LD examples and use cases
46
+ - **๐Ÿ“‹ [Specification](./spec/index.md)** - Formal specification and test suite
61
47
 
62
- Read the [FULL SPEC](./spec/Spec.md).
48
+ ## โœจ Core Features
63
49
 
64
- ## Core Features
50
+ - **๐Ÿ”— Prefix folding** - Build hierarchical namespaces with lightweight IRI authoring
51
+ - **๐Ÿ“ Subject declarations** - `{=IRI}` and `{=#fragment}` for context setting
52
+ - **๐ŸŽฏ Object IRIs** - `{+IRI}` and `{+#fragment}` for temporary object declarations
53
+ - **๐Ÿ”„ Three predicate forms** - `p` (Sโ†’L), `?p` (Sโ†’O), `!p` (Oโ†’S)
54
+ - **๐Ÿท๏ธ Type declarations** - `.Class` for rdf:type triples
55
+ - **๐Ÿ“… Datatypes & language** - `^^xsd:date` and `@en` support
56
+ - **๐Ÿงฉ Fragments** - Document structuring with `{=#fragment}`
57
+ - **โšก Polarity system** - Sophisticated diff authoring with `+` and `-` prefixes
58
+ - **๐Ÿ“ Origin tracking** - Complete provenance with lean quad-to-source mapping
59
+ - **๐ŸŽฏ Elevated statements** - Automatic rdf:Statement pattern detection for "golden" graph extraction
65
60
 
66
- - **Prefix folding**: Build hierarchical namespaces with lightweight IRI authoring
67
- - **Subject declarations**: `{=IRI}` and `{=#fragment}` for context setting
68
- - **Object IRIs**: `{+IRI}` and `{+#fragment}` for temporary object declarations
69
- - **Four predicate forms**: `p` (Sโ†’L), `?p` (Sโ†’O), `!p` (Oโ†’S)
70
- - **Type declarations**: `.Class` for rdf:type triples
71
- - **Datatypes & language**: `^^xsd:date` and `@en` support
72
- - **Fragments**: Built-in document structuring with `{=#fragment}`
73
- - **Round-trip serialization**: Markdown โ†” RDF โ†” Markdown preserves structure
61
+ ## ๐ŸŒŸ What is MD-LD?
74
62
 
75
- ## Installation
63
+ MD-LD allows you to author RDF graphs directly in Markdown using explicit `{...}` annotations:
76
64
 
77
- ```bash
78
- npm install mdld-parse
65
+ ```markdown
66
+ [my] <tag:alice@example.com,2026:>
67
+ # 2024-07-18 {=my:journal-2024-07-18 .my:Event my:date ^^xsd:date}
68
+ ## A good day {label}
69
+ Mood: [Happy] {my:mood}
70
+ Energy level: [8] {my:energyLevel ^^xsd:integer}
71
+ Met [Sam] {+my:sam .my:Person ?my:attendee} on my regular walk at [Central Park] {+my:central-park ?my:location .my:Place label @en} and talked about [Sunny] {my:weather} weather.
79
72
  ```
80
73
 
74
+ Generates valid RDF triples with complete provenance tracking.
75
+
76
+ ## ๐Ÿ“ฆ Installation
77
+
81
78
  ### Node.js
82
79
 
80
+ ```bash
81
+ pnpm install mdld-parse
82
+ ```
83
+
83
84
  ```javascript
84
85
  import { parse } from 'mdld-parse';
85
86
 
86
87
  const markdown = `# Document {=ex:doc .Article}
87
-
88
88
  [Alice] {author}`;
89
89
 
90
90
  const result = parse(markdown, {
@@ -101,11 +101,11 @@ console.log(result.quads);
101
101
  <script type="module">
102
102
  import { parse } from 'https://cdn.jsdelivr.net/npm/mdld-parse/+esm';
103
103
 
104
- const result = parse('# Hello {=ex:hello}');
104
+ const result = parse('# Hello {=ex:hello label}');
105
105
  </script>
106
106
  ```
107
107
 
108
- ## Semantic Model
108
+ ## ๐Ÿง  Semantic Model
109
109
 
110
110
  MD-LD encodes a directed labeled multigraph where three nodes may be in scope:
111
111
 
@@ -123,399 +123,148 @@ Each predicate form determines the graph edge:
123
123
  | `?p` | S โ†’ O | `[NASA] {=ex:nasa ?org}` | object property |
124
124
  | `!p` | O โ†’ S | `[Parent] {=ex:p !hasPart}` | reverse object |
125
125
 
126
- ## Syntax Reference
126
+ ## ๏ฟฝ Elevated Statements
127
127
 
128
- ### Subject Declaration
128
+ MD-LD automatically detects `rdf:Statement` patterns during parsing and extracts elevated SPO quads for convenient consumption by applications.
129
129
 
130
- Set current subject (emits no quads):
130
+ ### Pattern Detection
131
+
132
+ When the parser encounters a complete `rdf:Statement` pattern with `rdf:subject`, `rdf:predicate`, and `rdf:object`, it automatically adds the corresponding SPO quad to the `statements` array:
131
133
 
134
+ ```markdown
135
+ [ex] <http://example.org/>
136
+
137
+ ## Elevated statement {=ex:stmt1 .rdf:Statement}
138
+ **Alice** {+ex:alice ?rdf:subject} *knows* {+ex:knows ?rdf:predicate} **Bob** {+ex:bob ?rdf:object}
139
+
140
+ Direct statement:**Alice** {=ex:alice} knows **Bob** {?ex:knows +ex:bob}
141
+ ``
142
+
143
+ ## ๏ฟฝ๐ŸŽจ Syntax Quick Reference
144
+
145
+ ### Subject Declaration
146
+ Set current subject (emits no quads):
132
147
  ```markdown
133
148
  ## Apollo 11 {=ex:apollo11}
134
149
  ```
135
150
 
136
- #### Fragment Syntax
137
-
151
+ ### Fragment Syntax
138
152
  Create fragment IRIs relative to current subject:
139
-
140
153
  ```markdown
141
154
  # Document {=ex:document}
142
155
  {=#summary}
143
156
  [Content] {label}
144
157
  ```
145
-
146
- ```turtle
147
- ex:document#summary rdfs:label "Content" .
148
- ```
149
-
150
158
  Fragments replace any existing fragment and require a current subject.
151
159
 
152
- Subject remains in scope until reset with `{=}` or new subject declared.
153
-
154
160
  ### Type Declaration
155
-
156
161
  Emit `rdf:type` triple:
157
-
158
162
  ```markdown
159
163
  ## Apollo 11 {=ex:apollo11 .ex:SpaceMission .ex:Event}
160
164
  ```
161
165
 
162
- ```turtle
163
- ex:apollo11 a ex:SpaceMission, ex:Event .
164
- ```
165
-
166
166
  ### Literal Properties
167
-
168
167
  Inline value carriers emit literal properties:
169
-
170
168
  ```markdown
171
169
  # Mission {=ex:apollo11}
172
-
173
170
  [Neil Armstrong] {ex:commander}
174
171
  [1969] {ex:year ^^xsd:gYear}
175
172
  [Historic mission] {ex:description @en}
176
173
  ```
177
174
 
178
- ```turtle
179
- ex:apollo11 ex:commander "Neil Armstrong" ;
180
- ex:year "1969"^^xsd:gYear ;
181
- ex:description "Historic mission"@en .
182
- ```
183
-
184
175
  ### Object Properties
185
-
186
176
  Links create relationships (use `?` prefix):
187
-
188
177
  ```markdown
189
178
  # Mission {=ex:apollo11}
190
-
191
179
  [NASA] {=ex:nasa ?ex:organizer}
192
180
  ```
193
181
 
194
- ```turtle
195
- ex:apollo11 ex:organizer ex:nasa .
196
- ```
197
-
198
182
  ### Resource Declaration
199
-
200
183
  Declare resources inline with `{=iri}`:
201
-
202
184
  ```markdown
203
185
  # Mission {=ex:apollo11}
204
-
205
186
  [Neil Armstrong] {=ex:armstrong ?ex:commander .prov:Person}
206
187
  ```
207
188
 
208
- ```turtle
209
- ex:apollo11 ex:commander ex:armstrong .
210
- ex:armstrong a prov:Person .
211
- ```
212
-
213
- ### Lists
214
-
215
- Lists are pure Markdown structure. Each list item requires explicit annotations:
216
-
217
- ```markdown
218
- # Recipe {=ex:recipe}
219
-
220
- Ingredients:
221
-
222
- - **Flour** {+ex:flour ?ex:ingredient .ex:Ingredient label}
223
- - **Water** {+ex:water ?ex:ingredient .ex:Ingredient label}
224
- ```
225
-
226
- ```turtle
227
- ex:recipe ex:ingredient ex:flour, ex:water .
228
- ex:flour a ex:Ingredient ; rdfs:label "Flour" .
229
- ex:water a ex:Ingredient ; rdfs:label "Water" .
230
- ```
231
-
232
- **Key Rules:**
233
- - No semantic propagation from list scope
234
- - Each item must have explicit annotations
235
- - Use `+IRI` to maintain subject chaining for repeated object properties
236
-
237
- ### Code Blocks
238
-
239
- Code blocks are value carriers:
240
-
241
- ````markdown
242
- # Example {=ex:example}
243
-
244
- ```javascript {=ex:code .ex:SoftwareSourceCode ex:text}
245
- console.log("hello");
246
- ```
247
- ````
248
-
249
- ```turtle
250
- ex:code a ex:SoftwareSourceCode ;
251
- ex:text "console.log(\"hello\")" .
252
- ```
253
-
254
- ### Blockquotes
255
-
256
- ```markdown
257
- # Article {=ex:article}
258
-
259
- > MD-LD bridges Markdown and RDF. {comment}
260
- ```
261
-
262
- ```turtle
263
- ex:article rdfs:comment "MD-LD bridges Markdown and RDF." .
264
- ```
265
-
266
- ### Reverse Relations
267
-
268
- Reverse the relationship direction:
269
-
270
- ```markdown
271
- # Part {=ex:part}
272
-
273
- Part of: {!ex:hasPart}
274
-
275
- - Book {=ex:book}
276
- ```
277
-
278
- ```turtle
279
- ex:book ex:hasPart ex:part .
280
- ```
281
-
282
- ### Prefix Declarations
283
-
284
- ```markdown
285
- [ex] <http://example.org/>
286
- [foaf] <http://xmlns.com/foaf/0.1/>
287
-
288
- # Person {=ex:alice .foaf:Person}
289
- ```
290
-
291
- ### Prefix Folding: Lightweight IRI Authoring
292
-
293
- Build hierarchical namespaces by referencing previously defined prefixes:
294
-
295
- ```markdown
296
- # Create your domain authority
297
- [my] <tag:mymail@domain.com,2026:>
298
-
299
- # Build namespace hierarchy
300
- [j] <my:journal:>
301
- [p] <my:property:>
302
- [c] <my:class:>
303
- [person] <my:people:>
304
-
305
- # Use in content
306
- # 2026-01-27 {=j:2026-01-27 .c:Event p:date ^^xsd:date}
307
-
308
- ## Harry {=person:harry p:name}
309
- ```
310
-
311
- **Resolves to absolute IRIs:**
312
- - `j:2026-01-27` โ†’ `tag:mymail@domain.com,2026:journal:2026-01-27`
313
- - `c:Event` โ†’ `tag:mymail@domain.com,2026:class:Event`
314
- - `p:date` โ†’ `tag:mymail@domain.com,2026:property:date`
315
- - `person:harry` โ†’ `tag:mymail@domain.com,2026:people:harry`
316
-
317
- **Benefits:**
318
- - **Lightweight**: No external ontology dependencies
319
- - **Domain authority**: Use `tag:` URIs for personal namespaces
320
- - **Hierarchical**: Build deep namespace structures
321
- - **Streaming-safe**: Forward-reference only, single-pass parsing
322
-
323
- ## API Reference
189
+ ## ๐Ÿ”ง API Reference
324
190
 
325
191
  ### `parse(markdown, options)`
326
192
 
327
- Parse MD-LD markdown and return RDF quads with origin tracking.
193
+ Parse MD-LD markdown and return RDF quads with lean origin tracking.
328
194
 
329
195
  **Parameters:**
330
-
331
196
  - `markdown` (string) โ€” MD-LD formatted text
332
197
  - `options` (object, optional):
333
198
  - `context` (object) โ€” Prefix mappings (default: `{ '@vocab': 'http://www.w3.org/2000/01/rdf-schema#', rdf, rdfs, xsd, sh, prov }`)
334
199
  - `dataFactory` (object) โ€” Custom RDF/JS DataFactory
335
200
 
336
- **Returns:** `{ quads, origin, context }`
201
+ **Returns:** `{ quads, remove, statements, origin, context }`
337
202
 
338
- - `quads` โ€” Array of RDF/JS Quads
339
- - `origin` โ€” Origin tracking object with:
340
- - `blocks` โ€” Map of block IDs to source locations
341
- - `quadIndex` โ€” Map of quads to block IDs
203
+ - `quads` โ€” Array of RDF/JS Quads (final resolved graph state)
204
+ - `remove` โ€” Array of RDF/JS Quads (external retractions targeting prior state)
205
+ - `statements` โ€” Array of elevated RDF/JS Quads extracted from rdf:Statement patterns
206
+ - `origin` โ€” Lean origin tracking object with quadIndex for UI navigation
342
207
  - `context` โ€” Final context used (includes prefixes)
343
208
 
344
- **Example:**
345
-
346
- ```javascript
347
- const result = parse(
348
- `# Article {=ex:article .ex:Article}
349
-
350
- [Alice] {=ex:alice ?author}`,
351
- { context: { ex: 'http://example.org/' } }
352
- );
353
-
354
- console.log(result.quads);
355
- // [
356
- // {
357
- // subject: { termType: 'NamedNode', value: 'http://example.org/article' },
358
- // predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
359
- // object: { termType: 'NamedNode', value: 'http://example.org/Article' }
360
- // },
361
- // ...
362
- // ]
363
- ```
364
-
365
- ### `applyDiff({ text, diff, origin, options })`
209
+ ### `merge(docs, options)`
366
210
 
367
- Apply RDF changes back to markdown with proper positioning.
211
+ Merge multiple MDLD documents with diff polarity resolution.
368
212
 
369
213
  **Parameters:**
370
-
371
- - `text` (string) โ€” Original markdown
372
- - `diff` (object) โ€” Changes to apply:
373
- - `add` (array) โ€” Quads to add
374
- - `delete` (array) โ€” Quads to remove
375
- - `origin` (object) โ€” Origin from `parse()` result
214
+ - `docs` (array) โ€” Array of markdown strings or ParseResult objects
376
215
  - `options` (object, optional):
377
- - `context` (object) โ€” Context for IRI shortening
378
-
379
- **Returns:** `{ text, origin }`
380
-
381
- - `text` โ€” Updated markdown
382
- - `origin` โ€” Updated origin tracking vacant slots
383
-
384
- **Example:**
385
-
386
- ```javascript
387
- const original = `# Article {=ex:article}
216
+ - `context` (object) โ€” Prefix mappings (merged with DEFAULT_CONTEXT)
388
217
 
389
- [Alice] {ex:author}`;
390
-
391
- const result = parse(original, { context: { ex: 'http://example.org/' } });
392
-
393
- // Add a new property
394
- const newQuad = {
395
- subject: { termType: 'NamedNode', value: 'http://example.org/article' },
396
- predicate: { termType: 'NamedNode', value: 'http://example.org/datePublished' },
397
- object: { termType: 'Literal', value: '2024-01-01' }
398
- };
399
-
400
- const updated = applyDiff({
401
- text: original,
402
- diff: { add: [newQuad] },
403
- origin: result.origin,
404
- options: { context: result.context }
405
- });
406
-
407
- console.log(updated.text);
408
- // # Article {=ex:article}
409
- //
410
- // [Alice] {author}
411
- // [2024-01-01] {datePublished}
412
- ```
218
+ **Returns:** `{ quads, remove, origin, context }`
413
219
 
414
220
  ### `generate(quads, context)`
415
221
 
416
- Generate deterministic MDLD from RDF quads with origin tracking.
222
+ Generate deterministic MDLD from RDF quads.
417
223
 
418
224
  **Parameters:**
419
-
420
225
  - `quads` (array) โ€” Array of RDF/JS Quads to convert
421
226
  - `context` (object, optional) โ€” Prefix mappings (default: `{}`)
422
- - Merged with DEFAULT_CONTEXT for proper CURIE shortening
423
- - Only user-defined prefixes are rendered in output
424
-
425
- **Returns:** `{ text, origin, context }`
426
-
427
- - `text` โ€” Generated MDLD markdown
428
- - `origin` โ€” Origin tracking object with:
429
- - `blocks` โ€” Map of block IDs to source locations
430
- - `quadIndex` โ€” Map of quads to block IDs
431
- - `context` โ€” Final context used (includes defaults)
432
-
433
- **Example:**
434
-
435
- ```javascript
436
- const quads = [
437
- {
438
- subject: { termType: 'NamedNode', value: 'http://example.org/article' },
439
- predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
440
- object: { termType: 'NamedNode', value: 'http://example.org/Article' }
441
- },
442
- {
443
- subject: { termType: 'NamedNode', value: 'http://example.org/article' },
444
- predicate: { termType: 'NamedNode', value: 'http://example.org/author' },
445
- object: { termType: 'NamedNode', value: 'http://example.org/alice' }
446
- }
447
- ];
448
-
449
- const result = generate(quads, {
450
- ex: 'http://example.org/',
451
- });
452
227
 
453
- console.log(result.text);
454
- // # Article {=ex:article .ex:Article}
455
- //
456
- // > alice {+ex:alice ?ex:author}
457
- ```
228
+ **Returns:** `{ text, context }`
458
229
 
459
- ### `locate(quad, origin, text, context)`
230
+ ### `locate(quad, origin)`
460
231
 
461
- Locate the precise text range of a quad in MDLD text using origin tracking.
232
+ Locate the origin entry for a quad using the lean origin system.
462
233
 
463
234
  **Parameters:**
464
-
465
235
  - `quad` (object) โ€” The quad to locate (subject, predicate, object)
466
- - `origin` (object, optional) โ€” Origin object containing blocks and quadIndex
467
- - `text` (string, optional) โ€” MDLD text (auto-parsed if origin not provided)
468
- - `context` (object, optional) โ€” Context for parsing when text needs to be parsed
236
+ - `origin` (object) โ€” Origin object containing quadIndex
469
237
 
470
- **Returns:** `{ blockId, entryIndex, range, content, blockRange, carrierType, isVacant }` or `null`
238
+ **Returns:** `{ blockId, range, carrierType, subject, predicate, context, value, polarity }` or `null`
471
239
 
472
- - `blockId` โ€” ID of the containing block
473
- - `entryIndex` โ€” Position within block entries
474
- - `range` โ€” Precise character range of the quad content
475
- - `content` โ€” Actual text content at that range
476
- - `blockRange` โ€” Full range of the containing block
477
- - `carrierType` โ€” Type of carrier (heading, blockquote, list, span)
478
- - `isVacant` โ€” Whether the slot is marked as vacant
240
+ ### `render(quads, options)`
479
241
 
480
- **Example:**
242
+ Render RDF quads as HTML+RDFa for web display.
481
243
 
482
- ```javascript
483
- import { parse, locate } from './src/index.js';
484
-
485
- const result = parse(mdldText, { context: { ex: 'http://example.org/' } });
486
- const quad = result.quads[0]; // Find a quad to locate
244
+ **Parameters:**
245
+ - `quads` (array) โ€” Array of RDF/JS Quads to render
246
+ - `options` (object, optional):
247
+ - `context` (object) โ€” Prefix mappings for CURIE shortening
248
+ - `baseIRI` (string) โ€” Base IRI for resolving relative references
487
249
 
488
- // Pattern 1: With origin (most efficient)
489
- const location1 = locate(quad, result.origin, mdldText);
250
+ **Returns:** `{ html, context }`
490
251
 
491
- // Pattern 2: Auto-parse text (convenient)
492
- const location2 = locate(quad, null, mdldText, { ex: 'http://example.org/' });
252
+ ### Utility Functions
493
253
 
494
- console.log(location1.range); // { start: 38, end: 44 }
495
- console.log(location1.content); // " Alice"
496
- console.log(location1.carrierType); // "blockquote"
254
+ ```javascript
255
+ import {
256
+ DEFAULT_CONTEXT, // Default prefix mappings
257
+ DataFactory, // RDF/JS DataFactory instance
258
+ hash, // String hashing function
259
+ expandIRI, // IRI expansion with context
260
+ shortenIRI, // IRI shortening with context
261
+ parseSemanticBlock // Parse semantic block syntax
262
+ } from 'mdld-parse';
497
263
  ```
498
264
 
499
- ## Value Carriers
500
-
501
- Only specific markdown elements can carry semantic values:
502
-
503
- **Inline:**
504
- - `[text] {...}` โ€” span with annotation
505
- - `[text](url) {...}` โ€” link to external resource
506
- - `[text] {...}` โ€” inline resource declaration
507
- - `![alt text](image.png) {...}` โ€” embedding with annotation
508
-
509
- **Block:**
510
- - Headings (`# Title`)
511
- - List items (`- item`, `1. item`) โ€” pure Markdown structure
512
- - Blockquotes (`> quote`)
513
- - Code blocks (` ```lang `)
514
-
515
- ## Architecture
265
+ ## ๐Ÿ—๏ธ Architecture
516
266
 
517
267
  ### Design Principles
518
-
519
268
  - **Zero dependencies** โ€” Pure JavaScript, ~15KB minified
520
269
  - **Streaming-first** โ€” Single-pass parsing, O(n) complexity
521
270
  - **Standards-compliant** โ€” RDF/JS data model
@@ -523,107 +272,13 @@ Only specific markdown elements can carry semantic values:
523
272
  - **Explicit semantics** โ€” No guessing, inference, or heuristics
524
273
 
525
274
  ### RDF/JS Compatibility
526
-
527
275
  Quads are compatible with:
528
-
529
276
  - [`n3.js`](https://github.com/rdfjs/N3.js) โ€” Turtle/N-Triples serialization
530
277
  - [`rdflib.js`](https://github.com/linkeddata/rdflib.js) โ€” RDF store and reasoning
531
278
  - [`sparqljs`](https://github.com/RubenVerborgh/SPARQL.js) โ€” SPARQL queries
532
279
  - [`rdf-ext`](https://github.com/rdf-ext/rdf-ext) โ€” Extended RDF utilities
533
280
 
534
- ## Forbidden Constructs
535
-
536
- MD-LD explicitly forbids to ensure deterministic parsing:
537
-
538
- - โŒ Implicit semantics or structural inference
539
- - โŒ Auto-generated subjects or blank nodes
540
- - โŒ Predicate guessing from context
541
- - โŒ Multi-pass or backtracking parsers
542
-
543
- Below is a **tight, README-ready refinement** of the Algebra section.
544
- It keeps the math precise, examples exhaustive, and language compact.
545
-
546
- ---
547
-
548
- ## Algebra
549
-
550
- > Every RDF triple `(s, p, o)` can be authored **explicitly, deterministically, and locally**, with no inference, guessing, or reordering.
551
-
552
- MD-LD models RDF authoring as a **closed edge algebra** over a small, explicit state. To be algebraically complete for RDF triple construction, a syntax must support:
553
-
554
- * Binding a **subject** `S`
555
- * Binding an **object** `O`
556
- * Emitting predicates in **both directions**
557
- * Distinguishing **IRI nodes** from **literal nodes**
558
- * Operating with **no implicit state or inference**
559
-
560
- MD-LD satisfies these requirements with four explicit operators.
561
-
562
- Each predicate is partitioned by **direction** and **node kind**:
563
-
564
- | Predicate form | Emitted triple |
565
- | -------------- | -------------- |
566
- | `p` | `S โ”€pโ†’ L` |
567
- | `?p` | `S โ”€pโ†’ O` |
568
- | not allowed | `L โ”€pโ†’ S` |
569
- | `!p` | `O โ”€pโ†’ S` |
570
-
571
- This spans all **2 ร— 2** combinations of:
572
-
573
- * source โˆˆ {subject, object/literal}
574
- * target โˆˆ {subject, object/literal}
575
-
576
- Therefore, the algebra is **closed**.
577
-
578
- ## Use Cases
579
-
580
- ### Personal Knowledge Management
581
-
582
- ```markdown
583
- [alice] <tag:alice@example.com,2026:>
584
-
585
- # Meeting Notes {=alice:meeting-2024-01-15 .alice:Meeting}
586
-
587
- Attendees:
588
-
589
- - **Alice** {+alice:alice ?alice:attendee label}
590
- - **Bob** {+alice:bob ?alice:attendee label}
591
-
592
- Action items:
593
-
594
- - **Review proposal** {+alice:task-1 ?alice:actionItem label}
595
- ```
596
-
597
- ### Developer Documentation
598
-
599
- ````markdown
600
- # API Endpoint {=api:/users/:id .api:Endpoint}
601
-
602
- [GET] {api:method}
603
- [/users/:id] {api:path}
604
-
605
- Example:
606
-
607
- ```bash {=api:/users/:id#example .api:CodeExample api:code}
608
- curl https://api.example.com/users/123
609
- ```
610
- ````
611
-
612
- ### Academic Research
613
-
614
- ```markdown
615
- [alice] <tag:alice@example.com,2026:>
616
-
617
- # Paper {=alice:paper-semantic-markdown .alice:ScholarlyArticle}
618
-
619
- [Semantic Web] {label}
620
- [Alice Johnson] {=alice:alice-johnson ?alice:author}
621
- [2024-01] {alice:datePublished ^^xsd:gYearMonth}
622
-
623
- > This paper explores semantic markup in Markdown. {comment @en}
624
- ```
625
-
626
- ## Testing
281
+ ## ๐Ÿงช Testing
627
282
 
628
283
  The parser includes comprehensive tests covering all spec requirements:
629
284
 
@@ -639,7 +294,7 @@ Tests validate:
639
294
  - Code blocks and blockquotes
640
295
  - Round-trip serialization
641
296
 
642
- ## Contributing
297
+ ## ๐Ÿค Contributing
643
298
 
644
299
  Contributions welcome! Please:
645
300
 
@@ -648,15 +303,6 @@ Contributions welcome! Please:
648
303
  3. Ensure all tests pass
649
304
  4. Follow existing code style
650
305
 
651
- ## Acknowledgments
652
-
653
- Developed by [Denis Starov](https://github.com/davay42).
654
-
655
- Inspired by:
656
- - Thomas Francart's [Semantic Markdown](https://blog.sparna.fr/2020/02/20/semantic-markdown/) article
657
- - RDFa decades of structured data experience
658
- - CommonMark's rigorous parsing approach
659
-
660
- ## License
306
+ ## ๐Ÿ“„ License
661
307
 
662
- See [LICENCE](./LICENCE)
308
+ See [LICENCE](./LICENCE)