mdld-parse 0.2.2 → 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 +345 -190
- package/index.js +264 -248
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,300 +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}`;
|
|
56
|
+
|
|
57
|
+
const result = parse(markdown, {
|
|
58
|
+
context: { ex: 'http://example.org/' }
|
|
59
|
+
});
|
|
26
60
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<urn:mdld:my-note-20251231> <http://schema.org/author> <http://example.org/alice> .
|
|
30
|
-
<http://example.org/alice> <http://schema.org/name> "Alice" .
|
|
31
|
-
<http://example.org/alice> <http://schema.org/worksFor> <http://example.org/tech-corp> .
|
|
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
|
+
```
|
|
149
|
+
|
|
150
|
+
### Resource Declaration
|
|
151
|
+
|
|
152
|
+
Declare resources inline with `(=iri)`:
|
|
153
|
+
|
|
154
|
+
```markdown
|
|
155
|
+
# Mission {=ex:apollo11}
|
|
121
156
|
|
|
122
|
-
|
|
123
|
-
const result = parse(markdown);
|
|
124
|
-
const quads = result.quads;
|
|
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");
|
|
193
|
+
```
|
|
194
|
+
````
|
|
195
|
+
|
|
196
|
+
```turtle
|
|
197
|
+
ex:code a schema:SoftwareSourceCode ;
|
|
198
|
+
schema:text "console.log(\"hello\")" .
|
|
142
199
|
```
|
|
143
200
|
|
|
144
|
-
|
|
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)
|
|
175
|
-
- `context` (object) — Context for IRI shortening
|
|
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
|
|
293
|
+
|
|
294
|
+
**Returns:** `{ text, origin }`
|
|
295
|
+
|
|
296
|
+
- `text` — Updated markdown
|
|
297
|
+
- `origin` — Updated origin tracking
|
|
176
298
|
|
|
177
|
-
**
|
|
178
|
-
- `text` — Updated markdown text
|
|
179
|
-
- `origin` — Updated origin object
|
|
299
|
+
**Example:**
|
|
180
300
|
|
|
181
301
|
```javascript
|
|
182
|
-
const
|
|
183
|
-
`
|
|
184
|
-
# Article Title {=ex:article .Article}
|
|
185
|
-
|
|
186
|
-
Written by [Alice](ex:alice) {ex:author}
|
|
187
|
-
`,
|
|
188
|
-
{
|
|
189
|
-
baseIRI: "http://example.org/doc",
|
|
190
|
-
context: {
|
|
191
|
-
'@vocab': 'http://schema.org/',
|
|
192
|
-
},
|
|
193
|
-
}
|
|
194
|
-
);
|
|
302
|
+
const original = `# Article {=ex:article}
|
|
195
303
|
|
|
196
|
-
|
|
197
|
-
// subject: { termType: 'NamedNode', value: 'http://example.org/doc#article' },
|
|
198
|
-
// predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
|
|
199
|
-
// object: { termType: 'NamedNode', value: 'http://schema.org/Article' },
|
|
200
|
-
// graph: { termType: 'DefaultGraph' }
|
|
201
|
-
// }
|
|
304
|
+
[Alice] {author}`;
|
|
202
305
|
|
|
203
|
-
|
|
306
|
+
const result = parse(original, { context: { ex: 'http://example.org/' } });
|
|
307
|
+
|
|
308
|
+
// Add a new property
|
|
204
309
|
const newQuad = {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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' }
|
|
208
313
|
};
|
|
209
314
|
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
315
|
+
const updated = serialize({
|
|
316
|
+
text: original,
|
|
317
|
+
diff: { add: [newQuad] },
|
|
318
|
+
origin: result.origin,
|
|
319
|
+
options: { context: result.context }
|
|
215
320
|
});
|
|
216
321
|
|
|
217
|
-
|
|
322
|
+
console.log(updated.text);
|
|
323
|
+
// # Article {=ex:article}
|
|
324
|
+
//
|
|
325
|
+
// [Alice] {author}
|
|
326
|
+
// [2024-01-01] {datePublished}
|
|
218
327
|
```
|
|
219
328
|
|
|
220
|
-
##
|
|
329
|
+
## Value Carriers
|
|
221
330
|
|
|
222
|
-
|
|
331
|
+
Only specific markdown elements can carry semantic values:
|
|
223
332
|
|
|
224
|
-
|
|
333
|
+
**Inline:**
|
|
334
|
+
- `[text]` — span with annotation
|
|
335
|
+
- `[text](url)` — link to external resource
|
|
336
|
+
- `[text](=iri)` — inline resource declaration
|
|
225
337
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
338
|
+
**Block:**
|
|
339
|
+
- Headings (`# Title`)
|
|
340
|
+
- List items (`- item`)
|
|
341
|
+
- Blockquotes (`> quote`)
|
|
342
|
+
- Code blocks (` ```lang `)
|
|
230
343
|
|
|
231
|
-
|
|
232
|
-
|
|
344
|
+
**Non-carriers:**
|
|
345
|
+
- Plain paragraphs without `[...]`
|
|
346
|
+
- Images (future)
|
|
347
|
+
- Tables (future)
|
|
233
348
|
|
|
234
|
-
##
|
|
349
|
+
## Architecture
|
|
235
350
|
|
|
236
|
-
|
|
351
|
+
### Design Principles
|
|
237
352
|
|
|
238
|
-
|
|
239
|
-
|
|
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
|
|
240
358
|
|
|
241
|
-
###
|
|
359
|
+
### RDF/JS Compatibility
|
|
242
360
|
|
|
243
|
-
|
|
244
|
-
- Item 1
|
|
245
|
-
- Item 2
|
|
246
|
-
```
|
|
361
|
+
Quads are compatible with:
|
|
247
362
|
|
|
248
|
-
|
|
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
|
|
249
367
|
|
|
250
|
-
|
|
251
|
-
<subject> schema:item "Item 1" .
|
|
252
|
-
<subject> schema:item "Item 2" .
|
|
253
|
-
```
|
|
368
|
+
## Forbidden Constructs
|
|
254
369
|
|
|
255
|
-
|
|
370
|
+
MD-LD explicitly forbids to ensure deterministic parsing:
|
|
256
371
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
```
|
|
372
|
+
- ❌ Implicit semantics or structural inference
|
|
373
|
+
- ❌ Auto-generated subjects or blank nodes
|
|
374
|
+
- ❌ Predicate guessing from context
|
|
375
|
+
- ❌ Multi-pass or backtracking parsers
|
|
262
376
|
|
|
263
|
-
|
|
377
|
+
## Use Cases
|
|
264
378
|
|
|
265
|
-
|
|
266
|
-
- `schema:programmingLanguage` from the info string (`sparql`)
|
|
267
|
-
- `schema:text` with the raw source code
|
|
268
|
-
- `schema:hasPart` link from the surrounding section
|
|
379
|
+
### Personal Knowledge Management
|
|
269
380
|
|
|
270
|
-
|
|
381
|
+
```markdown
|
|
382
|
+
# Meeting Notes {=urn:note:2024-01-15 .Meeting}
|
|
271
383
|
|
|
272
|
-
|
|
384
|
+
Attendees: {?attendee}
|
|
273
385
|
|
|
274
|
-
|
|
386
|
+
- [Alice](=urn:person:alice) {name}
|
|
387
|
+
- [Bob](=urn:person:bob) {name}
|
|
275
388
|
|
|
276
|
-
|
|
389
|
+
Action items: {?actionItem}
|
|
277
390
|
|
|
278
|
-
|
|
279
|
-
## Alice Johnson {=ex:alice .Person}
|
|
391
|
+
- [Review proposal](=urn:task:1) {name}
|
|
280
392
|
```
|
|
281
393
|
|
|
282
|
-
|
|
394
|
+
### Developer Documentation
|
|
283
395
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
287
406
|
```
|
|
407
|
+
````
|
|
288
408
|
|
|
289
|
-
|
|
409
|
+
### Academic Research
|
|
290
410
|
|
|
291
411
|
```markdown
|
|
292
|
-
|
|
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}
|
|
293
419
|
```
|
|
294
420
|
|
|
295
|
-
|
|
421
|
+
## Testing
|
|
296
422
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
423
|
+
The parser includes comprehensive tests covering all spec requirements:
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
npm test
|
|
300
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)
|