Appearance
API Reference
FreshComplete API documentation for MD-LD parser with tested examples.
Core Functions
parse({ text, context, dataFactory, graph })
Parse MD-LD markdown and return RDF quads.
Parameters (named object):
text(string, required) — MD-LD formatted textcontext(object, optional) — Prefix mappings (default:{})dataFactory(object, optional) — Custom RDF/JS DataFactorygraph(string, optional) — Named graph IRI
Returns: { quads, remove, statements, origin, context, primarySubject, primary, md }
quads— Array of RDF/JS Quads (final resolved graph state)remove— Array of RDF/JS Quads (external retractions targeting prior state)statements— Array of elevated rdf:Statement quads (golden graph)origin— Lean origin tracking object with quadIndex for UI navigationcontext— Final context used (includes prefixes)primarySubject— String IRI or null (canonical append identity)primary— Object containing primary metadata (semantic surface descriptor)md— Clean markdown without annotations
Dual-Layer Architecture:
| Layer | Field | Purpose | Use Cases |
|---|---|---|---|
| Canonical Identity | primarySubject | Append routing, storage, synchronization | append(), file placement, authority validation |
| Semantic Surface | primary | UI, indexing, navigation, agent orientation | Dashboards, search, previews, timelines |
Primary Object Structure:
javascript
primary: {
subject: string | null, // First non-fragment subject declaration
type: string | null, // First rdf:type declaration
label: string | null, // First rdfs:label literal
comment: string | null // First rdfs:comment literal
}Legacy signature
parse(text, options) is supported for backward compatibility but is deprecated. Use the named-object form.
Basic Example
javascript
import { parse } from 'mdld-parse';
const result = parse(`
[ex] <http://example.org/>
# Document {=ex:doc .ex:Article}
[Alice] {?ex:author =ex:alice .prov:Person ex:firstName label}
[Smith] {ex:lastName}`);
console.log(result.quads);
// [
// {
// subject: { termType: 'NamedNode', value: 'http://example.org/doc' },
// predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
// object: { termType: 'NamedNode', value: 'http://example.org/Article' }
// },
// {
// subject: { termType: 'NamedNode', value: 'http://example.org/doc' },
// predicate: { termType: 'NamedNode', value: 'http://example.org/author' },
// object: { termType: 'NamedNode', value: 'http://example.org/alice' }
// },
// {
// subject: { termType: 'NamedNode', value: 'http://example.org/alice' },
// predicate: { termType: 'NamedNode', value: 'http://www.w3.org/2000/01/rdf-schema#label' },
// object: { termType: 'Literal', value: 'Alice' }
// },
// ...
// ]Polarity Example
javascript
const result = parse({
text: `# Article {=ex:article .ex:Article}
[Bob] {+ex:bob -?ex:author} is not an author of this article, it's [Alice] {+ex:alice ?ex:author}.
`,
context: { ex: 'http://example.org/' }
});
console.log(result.quads);
// [ type triple + alice author triple ]
// Bob's author link was retracted in-stream
console.log(result.remove);
// [] - Empty because Bob author was cancelled in-streamExternal Retraction Example
javascript
const result2 = parse({
text: `# Article {=ex:article}
[Alice] {+ex:alice -?ex:author}`, // External retract (Alice not in current state)
context: { ex: 'http://example.org/' }
});
console.log(result2.remove);
// [
// {
// subject: { termType: 'NamedNode', value: 'http://example.org/article' },
// predicate: { termType: 'NamedNode', value: 'http://example.org/author' },
// object: { termType: 'NamedNode', value: 'http://example.org/alice' }
// }
// ]merge(docs, options)
Merge multiple MD-LD documents with diff polarity resolution.
Parameters:
docs(array) — Array of markdown strings or ParseResult objectsoptions(object, optional):context(object) — Prefix mappings (merged with DEFAULT_CONTEXT)
Returns: { quads, remove, statements, origin, context, primarySubjects, primary }
quads— Merged array of RDF/JS Quadsremove— Array of retractions from merge processstatements— Array of elevated rdf:Statement quads from all documentsorigin— Merge origin with document chain:documents— Array of document metadataquadIndex— Combined quad index from all documents
context— Final merged contextprimarySubjects— Array of string IRIs (canonical append identities, ordered by merge)primary— Array of primary objects (semantic surface descriptors, ordered by merge)
Use case: CRDT-style state management with append-only documents.
Basic Merge Example
javascript
import { merge } from 'mdld-parse';
const merged = merge([
`# Article {=ex:article}
[Bob] {author}`,
`# Article {=ex:article}
[Bob] {-author}
[Charlie] {author}`
], { context: { ex: 'http://example.org/' } });
console.log(merged.quads.length); // 2 (type + Charlie author)
console.log(merged.remove.length); // 1 (Bob author removal)Version Control Example
javascript
const v1 = `# Article {=ex:article .ex:Article}
[Alice] {author}
[Draft] {status}`;
const v2 = `# Article {=ex:article}
[Alice] {-author}
[Bob] {author}
[Draft] {-status}
[Published] {status}`;
const merged = merge([v1, v2]);
// quads: [article rdf:type Article, article author Bob, article status Published]
// All retractions resolved — remove is emptygenerate({ quads, context, primarySubject, compactInline, renderReverse, remove, lang })
Generate deterministic MD-LD from RDF quads.
Parameters (named object):
quads(array, required) — Array of RDF/JS Quads to convertcontext(object, optional) — Prefix mappings (default:{})primarySubject(string, optional) — IRI to place first in outputcompactInline(boolean, optional) — Enable inline type/label compaction for referenced subjects (default:false)renderReverse(boolean, optional) — Enable reverse connection rendering as!pannotations (default:false)remove(array, optional) — Array of RDF/JS Quads to retract (for diff generation)lang(string, optional) — Preferred language for labels (e.g.,'en','es','fr'). Priority: specified lang, untagged, English, any language
Returns: { text, context, compactStats }
text— Generated MD-LD markdowncontext— Final context used (includes defaults)compactStats— Compaction metrics:compactedSubjects(number) — Subjects compacted with inline types/labelsskippedHeadings(number) — Headings skipped due to compactioninlineAnnotations(number) — Inline type/label annotations rendered
Generate Example
javascript
import { generate } from 'mdld-parse';
const quads = [
{
subject: { termType: 'NamedNode', value: 'http://example.org/article' },
predicate: { termType: 'NamedNode', value: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' },
object: { termType: 'NamedNode', value: 'http://example.org/Article' }
},
{
subject: { termType: 'NamedNode', value: 'http://example.org/article' },
predicate: { termType: 'NamedNode', value: 'http://example.org/author' },
object: { termType: 'NamedNode', value: 'http://example.org/alice' }
}
];
const result = generate({
quads,
context: { ex: 'http://example.org/' }
});
console.log(result.text);
// # Article {=ex:article .ex:Article}
//
// > alice {+ex:alice ?ex:author}Generate with Language Preference
javascript
const { text } = generate({
quads: result.quads,
lang: 'es' // Prefer Spanish labels
});Diff Generation Example
javascript
import { generate, DataFactory } from 'mdld-parse';
const { namedNode, literal } = DataFactory;
const quads = [
DataFactory.quad(
namedNode('http://example.org/doc'),
namedNode('http://example.org/author'),
literal('Alice')
)
];
const remove = [
DataFactory.quad(
namedNode('http://example.org/doc'),
namedNode('http://example.org/author'),
literal('Smith')
)
];
const { text } = generate({
quads,
remove,
context: { ex: 'http://example.org/' }
});
console.log(text);
// [ex] <http://example.org/>
//
// # doc {=ex:doc}
// [Alice] {ex:author}
// [Smith] {-ex:author}generateNode({ quads, focusIRI, context, compactInline, renderReverse, lang })
Generate node-centric MD-LD for a specific IRI.
Parameters:
quads(array, required) — RDF/JS Quads to searchfocusIRI(string, required) — IRI to center view oncontext(object, optional) — Prefix mappingscompactInline(boolean, optional) — Inline compaction (default:true)renderReverse(boolean, optional) — Reverse connections (default:true)lang(string, optional) — Preferred language for labels
Returns: { text, context, compactStats }
Safety
Returns empty text if focusIRI is not found — prevents accidental full database rendering.
locate(quad, origin)
Locate the origin entry for a quad using the lean origin system.
Parameters:
quad(object) — The quad to locate (subject, predicate, object)origin(object) — Origin object from ParseResult containingquadIndex
Returns: { blockId, range, carrierType, subject, predicate, context, value, polarity } or null
blockId— ID of the containing blockrange— Character range of the carrier in the source textcarrierType— Type of carrier (heading, blockquote, span)subject— Subject IRI of the quadpredicate— Predicate IRI of the quadcontext— Context object inherited from parsingvalue— Raw carrier text contentpolarity—'+'for assertions,'-'for retractions
Locate Example
javascript
import { parse, locate } from 'mdld-parse';
const result = parse({ text: mdldText, context: { ex: 'http://example.org/' } });
const quad = result.quads[0];
const location = locate(quad, result.origin);
console.log(location.range); // { start: 38, end: 44 }
console.log(location.value); // "Alice"
console.log(location.carrierType); // "blockquote"updateValue({ text, quad, value, origin })
Update the carrier text of a literal quad in MD-LD text.
Parameters:
text(string) — Original MD-LD textquad(object) — Quad to updatevalue(string) — New carrier textorigin(object, optional) — ParseResult.origin
Returns: Updated MD-LD text (fail-safe)
Use case: Editor applications updating literal values in-place.
Utility Functions
javascript
import {
DEFAULT_CONTEXT, // Default prefix mappings
DataFactory, // RDF/JS DataFactory instance
hash, // String hashing function
expandIRI, // IRI expansion with context
shortenIRI, // IRI shortening with context
parseSemanticBlock // Parse semantic block syntax
} from 'mdld-parse';DEFAULT_CONTEXT
The built-in prefix mappings included in every parse:
javascript
{
'@vocab': 'http://www.w3.org/2000/01/rdf-schema#',
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
'xsd': 'http://www.w3.org/2001/XMLSchema#',
'sh': 'http://www.w3.org/ns/shacl#',
'prov': 'http://www.w3.org/ns/prov#'
}DataFactory
RDF/JS DataFactory instance for creating RDF terms:
javascript
DataFactory.namedNode('http://example.org/subject')
DataFactory.literal('value')
DataFactory.quad(subject, predicate, object, graph)Hash Function
Generate consistent hashes for identifiers:
javascript
hash('content') // Returns deterministic hash stringIRI Expansion/Shortening
Context-aware IRI manipulation:
javascript
const context = { ex: 'http://example.org/' };
expandIRI('ex:term', context) // 'http://example.org/term'
shortenIRI('http://example.org/term', context) // 'ex:term'Semantic Block Parser
Parse individual annotation blocks:
javascript
parseSemanticBlock('{author}', context) // Returns parsed annotation objectError Handling
Common Errors
- Invalid syntax — Malformed annotations or prefixes
- Missing context — Undefined prefixes in IRI expansion
- Type errors — Invalid datatype or language combinations
Error Messages
The parser provides clear error messages with line numbers:
javascript
try {
const result = parse({ text: invalidMarkdown });
} catch (error) {
console.error(error.message); // "Invalid annotation at line 5: ..."
}Performance Characteristics
- O(n) parsing — Single pass, linear time complexity
- Memory efficient — Streaming-friendly, minimal state
- Deterministic — Same input always produces same output
- Zero dependencies — Pure JavaScript implementation
RDF/JS Compatibility
Generated quads are standard RDF/JS Quad objects compatible with:
- n3.js — Turtle/N-Triples serialization
- rdflib.js — RDF store and reasoning
- sparqljs — SPARQL queries and updates
- rdf-ext — Extended RDF utilities
Browser Support
MD-LD works in modern browsers with ES module support:
html
<script type="module">
import { parse } from 'https://cdn.jsdelivr.net/npm/mdld-parse/+esm';
const result = parse('# Hello {=ex:hello label}');
</script>Node.js Support
Full Node.js support with CommonJS and ES modules:
javascript
// ES Modules
import { parse } from 'mdld-parse';
// CommonJS
const { parse } = require('mdld-parse');