mdld-parse 0.2.1 → 0.2.3
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/LICENCE +167 -0
- package/README.md +352 -180
- package/index.js +290 -247
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,283 +1,455 @@
|
|
|
1
|
-
# MD-LD Parse
|
|
1
|
+
# MD-LD Parse v0.2
|
|
2
2
|
|
|
3
|
-
**Markdown-Linked Data (MD-LD)** — a
|
|
3
|
+
**Markdown-Linked Data (MD-LD)** — a deterministic, streaming-friendly RDF authoring format that extends Markdown with explicit `{}` annotations.
|
|
4
4
|
|
|
5
|
-
[NPM](https://www.npmjs.com/package/mdld-parse)
|
|
5
|
+
[](https://www.npmjs.com/package/mdld-parse)
|
|
6
|
+
[](https://github.com/mdld-js/mdld-parse)
|
|
6
7
|
|
|
7
|
-
[
|
|
8
|
+
[Documentation](https://mdld.js.org) | [Specification](https://mdld.js.org/spec) | [Playground](https://mdld.js.org/playground)
|
|
8
9
|
|
|
9
10
|
## What is MD-LD?
|
|
10
11
|
|
|
11
|
-
MD-LD allows you to author RDF graphs directly in Markdown using
|
|
12
|
+
MD-LD allows you to author RDF graphs directly in Markdown using explicit `{}` annotations:
|
|
12
13
|
|
|
13
14
|
```markdown
|
|
14
|
-
#
|
|
15
|
+
# Apollo 11 {=ex:apollo11 .SpaceMission}
|
|
15
16
|
|
|
16
|
-
[
|
|
17
|
+
Launch: [1969-07-16] {startDate ^^xsd:date}
|
|
18
|
+
Crew: [Neil Armstrong](ex:armstrong) {?crewMember}
|
|
19
|
+
Description: [First crewed Moon landing] {description}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Generates valid RDF triples:
|
|
23
|
+
|
|
24
|
+
```turtle
|
|
25
|
+
ex:apollo11 a schema:SpaceMission ;
|
|
26
|
+
schema:startDate "1969-07-16"^^xsd:date ;
|
|
27
|
+
schema:crewMember ex:armstrong ;
|
|
28
|
+
schema:description "First crewed Moon landing" .
|
|
29
|
+
```
|
|
17
30
|
|
|
18
|
-
|
|
31
|
+
## Core Guarantees
|
|
19
32
|
|
|
20
|
-
|
|
33
|
+
MD-LD v0.2 provides strict semantic guarantees:
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
1. **CommonMark-preserving** — Removing `{}` yields valid Markdown
|
|
36
|
+
2. **Explicit semantics** — Every quad originates from explicit `{}`
|
|
37
|
+
3. **Single-pass parsing** — Streaming-friendly, deterministic
|
|
38
|
+
4. **No blank nodes** — All subjects are stable IRIs
|
|
39
|
+
5. **Complete traceability** — Every quad maps to source location
|
|
40
|
+
6. **Round-trip capable** — Markdown ↔ RDF ↔ Markdown preserves structure
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install mdld-parse
|
|
23
46
|
```
|
|
24
47
|
|
|
25
|
-
|
|
48
|
+
### Node.js
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import { parse } from 'mdld-parse';
|
|
52
|
+
|
|
53
|
+
const markdown = `# Document {=ex:doc .Article}
|
|
54
|
+
|
|
55
|
+
[Alice] {author}`;
|
|
26
56
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
57
|
+
const result = parse(markdown, {
|
|
58
|
+
context: { ex: 'http://example.org/' }
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
console.log(result.quads);
|
|
62
|
+
// RDF/JS quads ready for n3.js, rdflib, etc.
|
|
32
63
|
```
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
### Browser (ES Modules)
|
|
35
66
|
|
|
36
|
-
|
|
67
|
+
```html
|
|
68
|
+
<script type="module">
|
|
69
|
+
import { parse } from 'https://cdn.jsdelivr.net/npm/mdld-parse/+esm';
|
|
70
|
+
|
|
71
|
+
const result = parse('# Hello {=ex:hello}');
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
37
74
|
|
|
38
|
-
|
|
39
|
-
2. **Zero Dependencies** — Pure JavaScript, runs in Node.js and browsers
|
|
40
|
-
3. **Standards Compliant** — Outputs RDF quads compatible with RDFa semantics
|
|
41
|
-
4. **Markdown Native** — Plain Markdown yields minimal but valid RDF
|
|
42
|
-
5. **Progressive Enhancement** — Add semantics incrementally via attributes
|
|
43
|
-
6. **BaseIRI Inference** — Automatically infers baseIRI from document structure
|
|
44
|
-
7. **Default Vocabulary** — Provides default vocabulary for common properties, extensible via options
|
|
75
|
+
## Semantic Model
|
|
45
76
|
|
|
46
|
-
|
|
77
|
+
MD-LD encodes a directed labeled multigraph where three nodes may be in scope:
|
|
47
78
|
|
|
48
|
-
|
|
79
|
+
- **S** — current subject (IRI)
|
|
80
|
+
- **O** — object resource (IRI from link/image)
|
|
81
|
+
- **L** — literal value (string + optional datatype/language)
|
|
49
82
|
|
|
50
|
-
|
|
83
|
+
### Predicate Routing (§8.1)
|
|
51
84
|
|
|
52
|
-
|
|
53
|
-
- **Inline attribute parser** — Pandoc-style `{=iri .class key="value"}` attribute extraction
|
|
54
|
-
- **RDF quad generator** — Direct mapping from tokens to RDF/JS quads
|
|
85
|
+
Each predicate form determines the graph edge:
|
|
55
86
|
|
|
56
|
-
|
|
87
|
+
| Form | Edge | Example | Meaning |
|
|
88
|
+
|-------|---------|------------------------------|------------------|
|
|
89
|
+
| `p` | S → L | `[Alice] {name}` | literal property |
|
|
90
|
+
| `?p` | S → O | `[NASA](ex:nasa) {?org}` | object property |
|
|
91
|
+
| `^p` | *(none)*| *(literals can't be subjects)* | reverse literal |
|
|
92
|
+
| `^?p` | O → S | `[Parent](ex:p) {^?hasPart}` | reverse object |
|
|
57
93
|
|
|
58
|
-
|
|
59
|
-
- **Lightweight** — ~15KB minified, no AST overhead
|
|
60
|
-
- **Focused** — Optimized specifically for MD-LD semantics
|
|
61
|
-
- **Transparent** — Easy to understand and extend
|
|
62
|
-
- **Fast** — Single-pass parsing with minimal allocations
|
|
94
|
+
## Syntax Reference
|
|
63
95
|
|
|
64
|
-
|
|
96
|
+
### Subject Declaration
|
|
65
97
|
|
|
66
|
-
|
|
98
|
+
Set the current subject (emits no quads):
|
|
67
99
|
|
|
68
|
-
```
|
|
69
|
-
{
|
|
70
|
-
termType: 'NamedNode' | 'BlankNode' | 'Literal',
|
|
71
|
-
value: string,
|
|
72
|
-
language?: string,
|
|
73
|
-
datatype?: NamedNode
|
|
74
|
-
}
|
|
100
|
+
```markdown
|
|
101
|
+
## Apollo 11 {=ex:apollo11}
|
|
75
102
|
```
|
|
76
103
|
|
|
77
|
-
|
|
104
|
+
Subject remains in scope until reset with `{=}` or new subject declared.
|
|
78
105
|
|
|
79
|
-
|
|
80
|
-
- `rdflib.js` — RDF store and reasoning
|
|
81
|
-
- `sparqljs` — SPARQL query parsing
|
|
82
|
-
- `rdf-ext` — Extended RDF utilities
|
|
106
|
+
### Type Declaration
|
|
83
107
|
|
|
84
|
-
|
|
108
|
+
Emit `rdf:type` triple:
|
|
85
109
|
|
|
110
|
+
```markdown
|
|
111
|
+
## Apollo 11 {=ex:apollo11 .SpaceMission .Event}
|
|
86
112
|
```
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
↓
|
|
91
|
-
[Attribute Parser] — Parse {=iri .class key="value"} from tokens
|
|
92
|
-
↓
|
|
93
|
-
[Inline Parser] — Extract [text](url){attrs} spans
|
|
94
|
-
↓
|
|
95
|
-
[RDF Quad Generator] — Map tokens to RDF/JS quads
|
|
96
|
-
↓
|
|
97
|
-
RDF Quads (RDF/JS format)
|
|
98
|
-
↓
|
|
99
|
-
[Optional] n3.js Writer → Turtle/N-Triples
|
|
113
|
+
|
|
114
|
+
```turtle
|
|
115
|
+
ex:apollo11 a schema:SpaceMission, schema:Event .
|
|
100
116
|
```
|
|
101
117
|
|
|
102
|
-
###
|
|
118
|
+
### Literal Properties
|
|
103
119
|
|
|
104
|
-
|
|
120
|
+
Inline value carriers emit literal properties:
|
|
105
121
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
3. **Predictable performance** — Linear time complexity, bounded memory
|
|
109
|
-
4. **Easy integration** — Works in Node.js, browsers, and edge runtimes
|
|
122
|
+
```markdown
|
|
123
|
+
# Mission {=ex:apollo11}
|
|
110
124
|
|
|
111
|
-
|
|
125
|
+
[Neil Armstrong] {commander}
|
|
126
|
+
[1969] {year ^^xsd:gYear}
|
|
127
|
+
[Historic mission] {description @en}
|
|
128
|
+
```
|
|
112
129
|
|
|
113
|
-
|
|
130
|
+
```turtle
|
|
131
|
+
ex:apollo11 schema:commander "Neil Armstrong" ;
|
|
132
|
+
schema:year "1969"^^xsd:gYear ;
|
|
133
|
+
schema:description "Historic mission"@en .
|
|
134
|
+
```
|
|
114
135
|
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
### Object Properties
|
|
137
|
+
|
|
138
|
+
Links create relationships (use `?` prefix):
|
|
139
|
+
|
|
140
|
+
```markdown
|
|
141
|
+
# Mission {=ex:apollo11}
|
|
142
|
+
|
|
143
|
+
[NASA](ex:nasa) {?organizer}
|
|
117
144
|
```
|
|
118
145
|
|
|
119
|
-
```
|
|
120
|
-
|
|
146
|
+
```turtle
|
|
147
|
+
ex:apollo11 schema:organizer ex:nasa .
|
|
148
|
+
```
|
|
121
149
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
150
|
+
### Resource Declaration
|
|
151
|
+
|
|
152
|
+
Declare resources inline with `(=iri)`:
|
|
153
|
+
|
|
154
|
+
```markdown
|
|
155
|
+
# Mission {=ex:apollo11}
|
|
156
|
+
|
|
157
|
+
[Neil Armstrong](=ex:armstrong) {?commander .Person}
|
|
125
158
|
```
|
|
126
159
|
|
|
127
|
-
|
|
160
|
+
```turtle
|
|
161
|
+
ex:apollo11 schema:commander ex:armstrong .
|
|
162
|
+
ex:armstrong a schema:Person .
|
|
163
|
+
```
|
|
128
164
|
|
|
129
|
-
|
|
130
|
-
<script type="importmap">
|
|
131
|
-
{
|
|
132
|
-
"imports": {
|
|
133
|
-
"mdld-parse": "https://cdn.jsdelivr.net/npm/mdld-parse/+esm"
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
</script>
|
|
165
|
+
### Lists
|
|
137
166
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
167
|
+
Lists require explicit subjects per item:
|
|
168
|
+
|
|
169
|
+
```markdown
|
|
170
|
+
# Recipe {=ex:recipe}
|
|
171
|
+
|
|
172
|
+
Ingredients: {?ingredient .Ingredient}
|
|
173
|
+
|
|
174
|
+
- [Flour](=ex:flour) {name}
|
|
175
|
+
- [Water](=ex:water) {name}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```turtle
|
|
179
|
+
ex:recipe schema:ingredient ex:flour, ex:water .
|
|
180
|
+
ex:flour a schema:Ingredient ; schema:name "Flour" .
|
|
181
|
+
ex:water a schema:Ingredient ; schema:name "Water" .
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Code Blocks
|
|
185
|
+
|
|
186
|
+
Code blocks are value carriers:
|
|
187
|
+
|
|
188
|
+
````markdown
|
|
189
|
+
# Example {=ex:example}
|
|
190
|
+
|
|
191
|
+
```javascript {=ex:code .SoftwareSourceCode text}
|
|
192
|
+
console.log("hello");
|
|
142
193
|
```
|
|
194
|
+
````
|
|
143
195
|
|
|
144
|
-
|
|
196
|
+
```turtle
|
|
197
|
+
ex:code a schema:SoftwareSourceCode ;
|
|
198
|
+
schema:text "console.log(\"hello\")" .
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Blockquotes
|
|
202
|
+
|
|
203
|
+
```markdown
|
|
204
|
+
# Article {=ex:article}
|
|
205
|
+
|
|
206
|
+
> MD-LD bridges Markdown and RDF. {abstract}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```turtle
|
|
210
|
+
ex:article schema:abstract "MD-LD bridges Markdown and RDF." .
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Reverse Relations
|
|
214
|
+
|
|
215
|
+
Reverse the relationship direction:
|
|
216
|
+
|
|
217
|
+
```markdown
|
|
218
|
+
# Part {=ex:part}
|
|
219
|
+
|
|
220
|
+
Part of: {^?hasPart}
|
|
221
|
+
|
|
222
|
+
- [Book](=ex:book) {}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
```turtle
|
|
226
|
+
ex:book schema:hasPart ex:part .
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Prefix Declarations
|
|
230
|
+
|
|
231
|
+
```markdown
|
|
232
|
+
[ex] {: http://example.org/}
|
|
233
|
+
[foaf] {: http://xmlns.com/foaf/0.1/}
|
|
234
|
+
|
|
235
|
+
# Person {=ex:alice .foaf:Person}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## API Reference
|
|
145
239
|
|
|
146
240
|
### `parse(markdown, options)`
|
|
147
241
|
|
|
148
|
-
Parse MD-LD markdown and return
|
|
242
|
+
Parse MD-LD markdown and return RDF quads with origin tracking.
|
|
149
243
|
|
|
150
244
|
**Parameters:**
|
|
151
245
|
|
|
152
246
|
- `markdown` (string) — MD-LD formatted text
|
|
153
247
|
- `options` (object, optional):
|
|
154
|
-
- `
|
|
155
|
-
- `
|
|
156
|
-
|
|
248
|
+
- `context` (object) — Prefix mappings (default: `{ '@vocab': 'http://schema.org/', rdf, rdfs, xsd, schema }`)
|
|
249
|
+
- `dataFactory` (object) — Custom RDF/JS DataFactory
|
|
250
|
+
|
|
251
|
+
**Returns:** `{ quads, origin, context }`
|
|
157
252
|
|
|
158
|
-
**Returns:** Object containing:
|
|
159
253
|
- `quads` — Array of RDF/JS Quads
|
|
160
|
-
- `origin` —
|
|
161
|
-
- `
|
|
254
|
+
- `origin` — Origin tracking object with:
|
|
255
|
+
- `blocks` — Map of block IDs to source locations
|
|
256
|
+
- `quadIndex` — Map of quads to block IDs
|
|
257
|
+
- `context` — Final context used (includes prefixes)
|
|
258
|
+
|
|
259
|
+
**Example:**
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
const result = parse(
|
|
263
|
+
`# Article {=ex:article .Article}
|
|
264
|
+
|
|
265
|
+
[Alice](ex:alice) {?author}`,
|
|
266
|
+
{ context: { ex: 'http://example.org/' } }
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
console.log(result.quads);
|
|
270
|
+
// [
|
|
271
|
+
// {
|
|
272
|
+
// subject: { termType: 'NamedNode', value: 'http://example.org/article' },
|
|
273
|
+
// predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
|
|
274
|
+
// object: { termType: 'NamedNode', value: 'http://schema.org/Article' }
|
|
275
|
+
// },
|
|
276
|
+
// ...
|
|
277
|
+
// ]
|
|
278
|
+
```
|
|
162
279
|
|
|
163
280
|
### `serialize({ text, diff, origin, options })`
|
|
164
281
|
|
|
165
|
-
|
|
282
|
+
Apply RDF changes back to markdown with proper positioning.
|
|
166
283
|
|
|
167
284
|
**Parameters:**
|
|
168
285
|
|
|
169
|
-
- `text` (string) — Original markdown
|
|
286
|
+
- `text` (string) — Original markdown
|
|
170
287
|
- `diff` (object) — Changes to apply:
|
|
171
|
-
- `add` —
|
|
172
|
-
- `delete` —
|
|
173
|
-
- `origin` (object) — Origin
|
|
174
|
-
- `options` (object, optional)
|
|
288
|
+
- `add` (array) — Quads to add
|
|
289
|
+
- `delete` (array) — Quads to remove
|
|
290
|
+
- `origin` (object) — Origin from `parse()` result
|
|
291
|
+
- `options` (object, optional):
|
|
292
|
+
- `context` (object) — Context for IRI shortening
|
|
175
293
|
|
|
176
|
-
**Returns:**
|
|
177
|
-
- `text` — Updated markdown text
|
|
178
|
-
- `origin` — Updated origin object
|
|
294
|
+
**Returns:** `{ text, origin }`
|
|
179
295
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Written by [Alice](ex:alice) {ex:author}
|
|
186
|
-
`,
|
|
187
|
-
{
|
|
188
|
-
baseIRI: "http://example.org/doc",
|
|
189
|
-
context: {
|
|
190
|
-
'@vocab': 'http://schema.org/',
|
|
191
|
-
},
|
|
192
|
-
}
|
|
193
|
-
);
|
|
296
|
+
- `text` — Updated markdown
|
|
297
|
+
- `origin` — Updated origin tracking
|
|
298
|
+
|
|
299
|
+
**Example:**
|
|
194
300
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
301
|
+
```javascript
|
|
302
|
+
const original = `# Article {=ex:article}
|
|
303
|
+
|
|
304
|
+
[Alice] {author}`;
|
|
305
|
+
|
|
306
|
+
const result = parse(original, { context: { ex: 'http://example.org/' } });
|
|
307
|
+
|
|
308
|
+
// Add a new property
|
|
309
|
+
const newQuad = {
|
|
310
|
+
subject: { termType: 'NamedNode', value: 'http://example.org/article' },
|
|
311
|
+
predicate: { termType: 'NamedNode', value: 'http://schema.org/datePublished' },
|
|
312
|
+
object: { termType: 'Literal', value: '2024-01-01' }
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const updated = serialize({
|
|
316
|
+
text: original,
|
|
317
|
+
diff: { add: [newQuad] },
|
|
318
|
+
origin: result.origin,
|
|
319
|
+
options: { context: result.context }
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
console.log(updated.text);
|
|
323
|
+
// # Article {=ex:article}
|
|
324
|
+
//
|
|
325
|
+
// [Alice] {author}
|
|
326
|
+
// [2024-01-01] {datePublished}
|
|
201
327
|
```
|
|
202
328
|
|
|
203
|
-
##
|
|
329
|
+
## Value Carriers
|
|
204
330
|
|
|
205
|
-
|
|
331
|
+
Only specific markdown elements can carry semantic values:
|
|
206
332
|
|
|
207
|
-
|
|
333
|
+
**Inline:**
|
|
334
|
+
- `[text]` — span with annotation
|
|
335
|
+
- `[text](url)` — link to external resource
|
|
336
|
+
- `[text](=iri)` — inline resource declaration
|
|
208
337
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
338
|
+
**Block:**
|
|
339
|
+
- Headings (`# Title`)
|
|
340
|
+
- List items (`- item`)
|
|
341
|
+
- Blockquotes (`> quote`)
|
|
342
|
+
- Code blocks (` ```lang `)
|
|
213
343
|
|
|
214
|
-
|
|
215
|
-
|
|
344
|
+
**Non-carriers:**
|
|
345
|
+
- Plain paragraphs without `[...]`
|
|
346
|
+
- Images (future)
|
|
347
|
+
- Tables (future)
|
|
216
348
|
|
|
217
|
-
##
|
|
349
|
+
## Architecture
|
|
218
350
|
|
|
219
|
-
|
|
351
|
+
### Design Principles
|
|
220
352
|
|
|
221
|
-
|
|
222
|
-
|
|
353
|
+
- **Zero dependencies** — Pure JavaScript, ~15KB minified
|
|
354
|
+
- **Streaming-first** — Single-pass parsing, O(n) complexity
|
|
355
|
+
- **Standards-compliant** — RDF/JS data model
|
|
356
|
+
- **Origin tracking** — Full round-trip support with source maps
|
|
357
|
+
- **Explicit semantics** — No guessing, inference, or heuristics
|
|
223
358
|
|
|
224
|
-
###
|
|
359
|
+
### RDF/JS Compatibility
|
|
225
360
|
|
|
226
|
-
|
|
227
|
-
- Item 1
|
|
228
|
-
- Item 2
|
|
229
|
-
```
|
|
361
|
+
Quads are compatible with:
|
|
230
362
|
|
|
231
|
-
|
|
363
|
+
- [`n3.js`](https://github.com/rdfjs/N3.js) — Turtle/N-Triples serialization
|
|
364
|
+
- [`rdflib.js`](https://github.com/linkeddata/rdflib.js) — RDF store and reasoning
|
|
365
|
+
- [`sparqljs`](https://github.com/RubenVerborgh/SPARQL.js) — SPARQL queries
|
|
366
|
+
- [`rdf-ext`](https://github.com/rdf-ext/rdf-ext) — Extended RDF utilities
|
|
232
367
|
|
|
233
|
-
|
|
234
|
-
<subject> schema:item "Item 1" .
|
|
235
|
-
<subject> schema:item "Item 2" .
|
|
236
|
-
```
|
|
368
|
+
## Forbidden Constructs
|
|
237
369
|
|
|
238
|
-
|
|
370
|
+
MD-LD explicitly forbids to ensure deterministic parsing:
|
|
239
371
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
```
|
|
372
|
+
- ❌ Implicit semantics or structural inference
|
|
373
|
+
- ❌ Auto-generated subjects or blank nodes
|
|
374
|
+
- ❌ Predicate guessing from context
|
|
375
|
+
- ❌ Multi-pass or backtracking parsers
|
|
245
376
|
|
|
246
|
-
|
|
377
|
+
## Use Cases
|
|
247
378
|
|
|
248
|
-
|
|
249
|
-
- `schema:programmingLanguage` from the info string (`sparql`)
|
|
250
|
-
- `schema:text` with the raw source code
|
|
251
|
-
- `schema:hasPart` link from the surrounding section
|
|
379
|
+
### Personal Knowledge Management
|
|
252
380
|
|
|
253
|
-
|
|
381
|
+
```markdown
|
|
382
|
+
# Meeting Notes {=urn:note:2024-01-15 .Meeting}
|
|
254
383
|
|
|
255
|
-
|
|
384
|
+
Attendees: {?attendee}
|
|
256
385
|
|
|
257
|
-
|
|
386
|
+
- [Alice](=urn:person:alice) {name}
|
|
387
|
+
- [Bob](=urn:person:bob) {name}
|
|
258
388
|
|
|
259
|
-
|
|
389
|
+
Action items: {?actionItem}
|
|
260
390
|
|
|
261
|
-
|
|
262
|
-
## Alice Johnson {=ex:alice .Person}
|
|
391
|
+
- [Review proposal](=urn:task:1) {name}
|
|
263
392
|
```
|
|
264
393
|
|
|
265
|
-
|
|
394
|
+
### Developer Documentation
|
|
266
395
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
396
|
+
````markdown
|
|
397
|
+
# API Endpoint {=api:/users/:id .APIEndpoint}
|
|
398
|
+
|
|
399
|
+
[GET] {method}
|
|
400
|
+
[/users/:id] {path}
|
|
401
|
+
|
|
402
|
+
Example:
|
|
403
|
+
|
|
404
|
+
```bash {=api:/users/:id/example .CodeExample programmingLanguage}
|
|
405
|
+
curl https://api.example.com/users/123
|
|
270
406
|
```
|
|
407
|
+
````
|
|
271
408
|
|
|
272
|
-
|
|
409
|
+
### Academic Research
|
|
273
410
|
|
|
274
411
|
```markdown
|
|
275
|
-
|
|
412
|
+
# Paper {=doi:10.1234/example .ScholarlyArticle}
|
|
413
|
+
|
|
414
|
+
[Semantic Web] {about}
|
|
415
|
+
[Alice Johnson](=orcid:0000-0001-2345-6789) {?author .Person}
|
|
416
|
+
[2024-01] {datePublished ^^xsd:gYearMonth}
|
|
417
|
+
|
|
418
|
+
> This paper explores semantic markup in Markdown. {abstract @en}
|
|
276
419
|
```
|
|
277
420
|
|
|
278
|
-
|
|
421
|
+
## Testing
|
|
279
422
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
423
|
+
The parser includes comprehensive tests covering all spec requirements:
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
npm test
|
|
283
427
|
```
|
|
428
|
+
|
|
429
|
+
Tests validate:
|
|
430
|
+
- Subject declaration and context
|
|
431
|
+
- All predicate forms (p, ?p, ^p, ^?p)
|
|
432
|
+
- Datatypes and language tags
|
|
433
|
+
- List processing
|
|
434
|
+
- Code blocks and blockquotes
|
|
435
|
+
- Round-trip serialization
|
|
436
|
+
|
|
437
|
+
## Contributing
|
|
438
|
+
|
|
439
|
+
Contributions welcome! Please:
|
|
440
|
+
|
|
441
|
+
1. Read the [specification](https://mdld.js.org/spec)
|
|
442
|
+
2. Add tests for new features
|
|
443
|
+
3. Ensure all tests pass
|
|
444
|
+
4. Follow existing code style
|
|
445
|
+
|
|
446
|
+
## Acknowledgments
|
|
447
|
+
|
|
448
|
+
Inspired by:
|
|
449
|
+
- Thomas Francart's [Semantic Markdown](https://blog.sparna.fr/2020/02/20/semantic-markdown/)
|
|
450
|
+
- RDFa decades of structured data experience
|
|
451
|
+
- CommonMark's rigorous parsing approach
|
|
452
|
+
|
|
453
|
+
## License
|
|
454
|
+
|
|
455
|
+
See [LICENCE](./LICENCE)
|