mdld-parse 0.3.0 → 0.3.2
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 +12 -13
- package/index.js +40 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ ex:armstrong schema:name "Neil Armstrong" .
|
|
|
36
36
|
|
|
37
37
|
- **Subject declarations**: `{=IRI}` and `{=#fragment}` for context setting
|
|
38
38
|
- **Object IRIs**: `{+IRI}` and `{+#fragment}` for temporary object declarations
|
|
39
|
-
- **Four predicate forms**: `p` (S→L), `?p` (S→O),
|
|
39
|
+
- **Four predicate forms**: `p` (S→L), `?p` (S→O), `!p` (O→S)
|
|
40
40
|
- **Type declarations**: `.Class` for rdf:type triples
|
|
41
41
|
- **Datatypes & language**: `^^xsd:date` and `@en` support
|
|
42
42
|
- **Lists**: Explicit subject declarations for structured data
|
|
@@ -92,7 +92,6 @@ Each predicate form determines the graph edge:
|
|
|
92
92
|
|-------|---------|------------------------------|------------------|
|
|
93
93
|
| `p` | S → L | `[Alice] {name}` | literal property |
|
|
94
94
|
| `?p` | S → O | `[NASA](ex:nasa) {?org}` | object property |
|
|
95
|
-
| `^p` | *(none)*| *(literals can't be subjects)* | reverse literal |
|
|
96
95
|
| `!p` | O → S | `[Parent](ex:p) {!hasPart}` | reverse object |
|
|
97
96
|
|
|
98
97
|
## Syntax Reference
|
|
@@ -249,9 +248,9 @@ ex:book schema:hasPart ex:part .
|
|
|
249
248
|
### Prefix Declarations
|
|
250
249
|
|
|
251
250
|
```markdown
|
|
252
|
-
[ex]
|
|
253
|
-
[foaf]
|
|
254
|
-
[@vocab]
|
|
251
|
+
[ex] <http://example.org/>
|
|
252
|
+
[foaf] <http://xmlns.com/foaf/0.1/>
|
|
253
|
+
[@vocab] <http://schema.org/>
|
|
255
254
|
|
|
256
255
|
# Person {=ex:alice .foaf:Person}
|
|
257
256
|
```
|
|
@@ -416,8 +415,8 @@ Each predicate is partitioned by **direction** and **node kind**:
|
|
|
416
415
|
| -------------- | -------------- |
|
|
417
416
|
| `p` | `S ─p→ L` |
|
|
418
417
|
| `?p` | `S ─p→ O` |
|
|
419
|
-
|
|
|
420
|
-
| `!p`
|
|
418
|
+
| not allowed | `L ─p→ S` |
|
|
419
|
+
| `!p` | `O ─p→ S` |
|
|
421
420
|
|
|
422
421
|
This spans all **2 × 2** combinations of:
|
|
423
422
|
|
|
@@ -433,14 +432,14 @@ Therefore, the algebra is **closed**.
|
|
|
433
432
|
```markdown
|
|
434
433
|
# Meeting Notes {=urn:note:2024-01-15 .Meeting}
|
|
435
434
|
|
|
436
|
-
Attendees: {?attendee}
|
|
435
|
+
Attendees: {?attendee name}
|
|
437
436
|
|
|
438
|
-
- Alice {=urn:person:alice
|
|
439
|
-
- Bob {=urn:person:bob
|
|
437
|
+
- Alice {=urn:person:alice}
|
|
438
|
+
- Bob {=urn:person:bob}
|
|
440
439
|
|
|
441
|
-
Action items: {?actionItem}
|
|
440
|
+
Action items: {?actionItem name}
|
|
442
441
|
|
|
443
|
-
- Review proposal {=urn:task:1
|
|
442
|
+
- Review proposal {=urn:task:1}
|
|
444
443
|
```
|
|
445
444
|
|
|
446
445
|
### Developer Documentation
|
|
@@ -480,7 +479,7 @@ npm test
|
|
|
480
479
|
|
|
481
480
|
Tests validate:
|
|
482
481
|
- Subject declaration and context
|
|
483
|
-
- All predicate forms (p, ?p,
|
|
482
|
+
- All predicate forms (p, ?p, !p)
|
|
484
483
|
- Datatypes and language tags
|
|
485
484
|
- List processing
|
|
486
485
|
- Code blocks and blockquotes
|
package/index.js
CHANGED
|
@@ -198,7 +198,7 @@ function scanTokens(text) {
|
|
|
198
198
|
continue;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
const prefixMatch = line.match(/^\[([^\]]+)\]\s
|
|
201
|
+
const prefixMatch = line.match(/^\[([^\]]+)\]\s*<([^>]+)>/);
|
|
202
202
|
if (prefixMatch) {
|
|
203
203
|
tokens.push({ type: 'prefix', prefix: prefixMatch[1], iri: prefixMatch[2].trim() });
|
|
204
204
|
continue;
|
|
@@ -224,7 +224,7 @@ function scanTokens(text) {
|
|
|
224
224
|
continue;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
const listMatch = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+?)(?:\s*(\{[^}]+\}))
|
|
227
|
+
const listMatch = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+?)(?:\s*(\{[^}]+\}))?\s*$/);
|
|
228
228
|
if (listMatch) {
|
|
229
229
|
const attrs = listMatch[4] || null;
|
|
230
230
|
const attrsStartInLine = attrs ? line.lastIndexOf(attrs) : -1;
|
|
@@ -662,7 +662,7 @@ function processListContext(contextSem, listTokens, state, contextSubject = null
|
|
|
662
662
|
const P = state.df.namedNode(expandIRI(pred.iri, state.ctx));
|
|
663
663
|
|
|
664
664
|
// According to MD-LD spec: list predicates that connect to item subjects MUST use object predicate forms (?p or !p)
|
|
665
|
-
// Literal predicate forms (p
|
|
665
|
+
// Literal predicate forms (p) in list scope emit no quads
|
|
666
666
|
if (pred.form === '!') {
|
|
667
667
|
// Reverse object property: O —p→ S
|
|
668
668
|
emitQuad(state.quads, state.origin.quadIndex, 'list-context', itemSubject, P, contextSubject, state.df);
|
|
@@ -676,8 +676,44 @@ function processListContext(contextSem, listTokens, state, contextSubject = null
|
|
|
676
676
|
const prevSubject = state.currentSubject;
|
|
677
677
|
state.currentSubject = itemSubject;
|
|
678
678
|
|
|
679
|
+
// Check if item has its own predicates
|
|
680
|
+
let hasOwnPredicates = false;
|
|
681
|
+
let itemSem = null;
|
|
682
|
+
|
|
679
683
|
if (listToken.attrs) {
|
|
680
|
-
|
|
684
|
+
itemSem = parseSemanticBlock(listToken.attrs);
|
|
685
|
+
if (itemSem.predicates.length > 0) {
|
|
686
|
+
hasOwnPredicates = true;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (!hasOwnPredicates) {
|
|
691
|
+
// Check inline carriers for predicates
|
|
692
|
+
for (const carrier of carriers) {
|
|
693
|
+
if (carrier.attrs) {
|
|
694
|
+
const carrierSem = parseSemanticBlock(carrier.attrs);
|
|
695
|
+
if (carrierSem.predicates.length > 0) {
|
|
696
|
+
hasOwnPredicates = true;
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// If item has no predicates, inherit literal predicates from context
|
|
704
|
+
if (!hasOwnPredicates) {
|
|
705
|
+
const inheritedPredicates = contextSem.predicates.filter(p => p.form === '');
|
|
706
|
+
if (inheritedPredicates.length > 0 && listToken.text) {
|
|
707
|
+
// Create inherited annotation block
|
|
708
|
+
const inheritedTokens = inheritedPredicates.map(p => p.iri).join(' ');
|
|
709
|
+
const inheritedSem = parseSemanticBlock(`{${inheritedTokens}}`);
|
|
710
|
+
const carrier = { type: 'list', text: listToken.text, range: listToken.range, attrsRange: listToken.attrsRange || null, valueRange: listToken.valueRange || null };
|
|
711
|
+
processAnnotation(carrier, inheritedSem, state);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (listToken.attrs) {
|
|
716
|
+
if (!itemSem) itemSem = parseSemanticBlock(listToken.attrs);
|
|
681
717
|
const carrier = { type: 'list', text: listToken.text, range: listToken.range, attrsRange: listToken.attrsRange || null, valueRange: listToken.valueRange || null };
|
|
682
718
|
processAnnotation(carrier, itemSem, state);
|
|
683
719
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdld-parse",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "A standards-compliant parser for **MD-LD (Markdown-Linked Data)** — a human-friendly RDF authoring format that extends Markdown with semantic annotations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|