Appearance
Generate: Quads to MD-LD
FreshThe generate() function converts RDF quads back to deterministic, human-readable MD-LD text. It is the second half of the round-trip: parse() turns text into quads, generate() turns quads back into text.
Basic Usage
javascript
import { generate } from 'mdld-parse';
const { text, context, compactStats } = generate({
quads,
context: { ex: 'http://example.org/' }
});
console.log(text);
// [ex] <http://example.org/>
//
// # article {=ex:article .ex:Article}
// ...Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
quads | array | required | RDF/JS Quads to convert |
context | object | {} | Prefix mappings |
primarySubject | string | null | IRI to place first in output |
compactInline | boolean | false | Enable inline type/label compaction |
renderReverse | boolean | false | Render reverse connections as !p annotations |
remove | array | [] | Quads to retract (for diff generation) |
lang | string | null | Preferred language for labels ('en', 'es', etc.) |
Returns
javascript
{
text: string, // Generated MD-LD markdown
context: object, // Final context with prefixes
compactStats: {
compactedSubjects: number, // Subjects compacted with inline types/labels
skippedHeadings: number, // Headings skipped due to compaction
inlineAnnotations: number // Inline type/label annotations rendered
}
}Round-Trip Safety
Generate is designed for deterministic output. The same quads always produce the same text:
javascript
const { text: first } = generate({ quads, context });
const { text: second } = generate({ quads, context });
console.log(first === second); // always trueThe round-trip is always safe:
javascript
const result = parse({ text: originalText });
const { text: regenerated } = generate({
quads: result.quads,
context: result.context
});
// regenerated is semantically equivalent to originalText
// (same quads when re-parsed, though formatting may differ)Primary Subject Positioning
Use primarySubject to control which node appears first in output:
javascript
const { text } = generate({
quads,
context,
primarySubject: 'http://example.org/main-entity'
});When renderReverse: true is also set, the primary subject's incoming connections are rendered as !p annotations.
Inline Compaction
When compactInline: true, subjects that have only a type and label (and appear as objects elsewhere) can be rendered inline rather than getting their own heading section:
javascript
// Without compaction (default):
// # alice {=ex:alice .prov:Person label}
// [Alice] {ex:name}
// ...
// [alice] {+ex:alice ?ex:author}
// With compactInline: true, if alice has only type+label:
// [Alice] {+ex:alice .prov:Person label ?ex:author}Language Preference
The lang parameter controls which language variant of labels and comments is preferred:
javascript
const { text } = generate({
quads,
lang: 'es' // Prefer Spanish labels
});Priority order: specified language, untagged literal, English, any available language.
Diff Generation
Pass remove alongside quads to generate a diff document that shows both additions and retractions:
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}Retractions appear as -predicate annotations. The diff document can be later parsed and merged to apply the changes.
Reverse Connections
When renderReverse: true, nodes that are objects of relationships get !predicate annotations showing what points to them:
javascript
const { text } = generate({
quads,
context,
renderReverse: true
});This is most useful in combination with primarySubject to render a node-centric view that includes all its incoming connections.
generateNode
For a node-centric view focused on a specific IRI:
javascript
import { generateNode } from 'mdld-parse';
const { text } = generateNode({
quads,
focusIRI: 'http://example.org/alice',
context,
compactInline: true, // default: true
renderReverse: true, // default: true
lang: 'en'
});Safety: returns empty string if focusIRI is not found in the quads — prevents accidental full-database rendering.
Integration with Parse
Full round-trip workflow:
javascript
import { parse, generate } from 'mdld-parse';
// Step 1: Parse document
const parseResult = parse({ text: mdldDocument });
// Step 2: Transform quads (filter, augment, etc.)
const filteredQuads = parseResult.quads.filter(q =>
q.subject.value.startsWith('http://example.org/person/')
);
// Step 3: Generate new document from transformed quads
const { text } = generate({
quads: filteredQuads,
context: parseResult.context
});CRDT-Style Workflow
Generate diffs between document versions:
javascript
import { parse, generate, merge } from 'mdld-parse';
const v1 = parse({ text: version1 });
const v2 = parse({ text: version2 });
// Generate a diff document showing what changed
const { text: diffDoc } = generate({
quads: v2.quads,
remove: v2.remove,
context: v2.context
});
// Later: merge v1 with the diff
const final = merge([version1, diffDoc]);
// final.quads contains the updated state