@faubulous/mentor-rdf-serializers 1.0.0
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 +582 -0
- package/dist/base-serializer.d.ts +63 -0
- package/dist/base-serializer.d.ts.map +1 -0
- package/dist/base-serializer.js +144 -0
- package/dist/base-serializer.js.map +1 -0
- package/dist/base-token-formatter.d.ts +225 -0
- package/dist/base-token-formatter.d.ts.map +1 -0
- package/dist/base-token-formatter.js +521 -0
- package/dist/base-token-formatter.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonld/serializer.d.ts +99 -0
- package/dist/jsonld/serializer.d.ts.map +1 -0
- package/dist/jsonld/serializer.js +282 -0
- package/dist/jsonld/serializer.js.map +1 -0
- package/dist/n3/formatter.d.ts +105 -0
- package/dist/n3/formatter.d.ts.map +1 -0
- package/dist/n3/formatter.js +444 -0
- package/dist/n3/formatter.js.map +1 -0
- package/dist/n3/serializer.d.ts +103 -0
- package/dist/n3/serializer.d.ts.map +1 -0
- package/dist/n3/serializer.js +134 -0
- package/dist/n3/serializer.js.map +1 -0
- package/dist/nquads/formatter.d.ts +44 -0
- package/dist/nquads/formatter.d.ts.map +1 -0
- package/dist/nquads/formatter.js +116 -0
- package/dist/nquads/formatter.js.map +1 -0
- package/dist/nquads/serializer.d.ts +38 -0
- package/dist/nquads/serializer.d.ts.map +1 -0
- package/dist/nquads/serializer.js +70 -0
- package/dist/nquads/serializer.js.map +1 -0
- package/dist/ntriples/formatter.d.ts +44 -0
- package/dist/ntriples/formatter.d.ts.map +1 -0
- package/dist/ntriples/formatter.js +116 -0
- package/dist/ntriples/formatter.js.map +1 -0
- package/dist/ntriples/serializer.d.ts +38 -0
- package/dist/ntriples/serializer.d.ts.map +1 -0
- package/dist/ntriples/serializer.js +79 -0
- package/dist/ntriples/serializer.js.map +1 -0
- package/dist/sorting/index.d.ts +5 -0
- package/dist/sorting/index.d.ts.map +1 -0
- package/dist/sorting/index.js +5 -0
- package/dist/sorting/index.js.map +1 -0
- package/dist/sorting/strategies.d.ts +46 -0
- package/dist/sorting/strategies.d.ts.map +1 -0
- package/dist/sorting/strategies.js +259 -0
- package/dist/sorting/strategies.js.map +1 -0
- package/dist/sparql/formatter.d.ts +103 -0
- package/dist/sparql/formatter.d.ts.map +1 -0
- package/dist/sparql/formatter.js +764 -0
- package/dist/sparql/formatter.js.map +1 -0
- package/dist/token-serializer.d.ts +96 -0
- package/dist/token-serializer.d.ts.map +1 -0
- package/dist/token-serializer.js +456 -0
- package/dist/token-serializer.js.map +1 -0
- package/dist/trig/formatter.d.ts +99 -0
- package/dist/trig/formatter.d.ts.map +1 -0
- package/dist/trig/formatter.js +418 -0
- package/dist/trig/formatter.js.map +1 -0
- package/dist/trig/serializer.d.ts +39 -0
- package/dist/trig/serializer.d.ts.map +1 -0
- package/dist/trig/serializer.js +170 -0
- package/dist/trig/serializer.js.map +1 -0
- package/dist/turtle/formatter.d.ts +56 -0
- package/dist/turtle/formatter.d.ts.map +1 -0
- package/dist/turtle/formatter.js +325 -0
- package/dist/turtle/formatter.js.map +1 -0
- package/dist/turtle/serializer.d.ts +87 -0
- package/dist/turtle/serializer.d.ts.map +1 -0
- package/dist/turtle/serializer.js +343 -0
- package/dist/turtle/serializer.js.map +1 -0
- package/dist/types.d.ts +323 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +157 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +446 -0
- package/dist/utils.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { RdfSyntax } from '../types.js';
|
|
2
|
+
import { BaseSerializer } from '../base-serializer.js';
|
|
3
|
+
import { sortQuads } from '../utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Serializer for N-Triples format (RDF 1.2 compatible).
|
|
6
|
+
*
|
|
7
|
+
* N-Triples is a line-based, plain text format for encoding RDF graphs.
|
|
8
|
+
* Each line contains a single triple: subject predicate object .
|
|
9
|
+
*
|
|
10
|
+
* RDF 1.2 adds support for triple terms (quoted triples) as subjects or objects.
|
|
11
|
+
*
|
|
12
|
+
* @see https://www.w3.org/TR/rdf12-n-triples/
|
|
13
|
+
*/
|
|
14
|
+
export class NTriplesSerializer extends BaseSerializer {
|
|
15
|
+
syntax = RdfSyntax.NTriples;
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
// N-Triples does not support prefixes or shortcuts
|
|
19
|
+
this.supportsPrefixes = false;
|
|
20
|
+
this.supportsRdfTypeShorthand = false;
|
|
21
|
+
// N-Triples 1.2 supports triple terms
|
|
22
|
+
this.supportsRdf12 = true;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Serializes a single quad/triple to N-Triples format.
|
|
26
|
+
*
|
|
27
|
+
* @param quad The quad to serialize.
|
|
28
|
+
* @param options Serialization options.
|
|
29
|
+
* @returns The serialized N-Triple string.
|
|
30
|
+
*/
|
|
31
|
+
serializeQuad(quad, options) {
|
|
32
|
+
const opts = this.getOptions(options);
|
|
33
|
+
const subject = this.serializeTerm(quad.subject, opts);
|
|
34
|
+
const predicate = this.serializeTerm(quad.predicate, opts);
|
|
35
|
+
const object = this.serializeTerm(quad.object, opts);
|
|
36
|
+
return `${subject} ${predicate} ${object} .`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Serializes multiple quads/triples to N-Triples format.
|
|
40
|
+
*
|
|
41
|
+
* @param quads The quads to serialize.
|
|
42
|
+
* @param options Serialization options.
|
|
43
|
+
* @returns The serialized N-Triples string.
|
|
44
|
+
*/
|
|
45
|
+
serialize(quads, options) {
|
|
46
|
+
const opts = this.getOptions(options);
|
|
47
|
+
const quadArray = Array.from(quads);
|
|
48
|
+
// Sort if requested
|
|
49
|
+
const sortedQuads = opts.sort ? sortQuads(quadArray) : quadArray;
|
|
50
|
+
const lines = [];
|
|
51
|
+
for (const quad of sortedQuads) {
|
|
52
|
+
// Skip quads with graph (N-Triples doesn't support named graphs)
|
|
53
|
+
if (quad.graph && quad.graph.termType !== 'DefaultGraph') {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
lines.push(this.serializeQuad(quad, opts));
|
|
57
|
+
}
|
|
58
|
+
return lines.join(opts.lineEnd) + (lines.length > 0 ? opts.lineEnd : '');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Formats quads with detailed result information.
|
|
62
|
+
*/
|
|
63
|
+
format(quads, options) {
|
|
64
|
+
const warnings = [];
|
|
65
|
+
const quadArray = Array.from(quads);
|
|
66
|
+
// Check for unsupported features and add warnings
|
|
67
|
+
for (const quad of quadArray) {
|
|
68
|
+
if (quad.graph && quad.graph.termType !== 'DefaultGraph') {
|
|
69
|
+
warnings.push(`Named graph ignored: N-Triples does not support named graphs.`);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
output: this.serialize(quads, options),
|
|
75
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../src/ntriples/serializer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,OAAO,kBAAmB,SAAQ,cAAc;IACzC,MAAM,GAAkB,SAAS,CAAC,QAAQ,CAAC;IAEpD;QACI,KAAK,EAAE,CAAC;QACR,mDAAmD;QACnD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,wBAAwB,GAAG,KAAK,CAAC;QACtC,sCAAsC;QACtC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;;;;;OAMG;IACH,aAAa,CAAC,IAAsB,EAAE,OAA2B;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAErD,OAAO,GAAG,OAAO,IAAI,SAAS,IAAI,MAAM,IAAI,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,KAAiC,EAAE,OAA2B;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpC,oBAAoB;QACpB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEjE,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC7B,iEAAiE;YACjE,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,EAAE,CAAC;gBACvD,SAAS;YACb,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED;;OAEG;IACM,MAAM,CAAC,KAAiC,EAAE,OAA2B;QAC1E,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpC,kDAAkD;QAClD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,EAAE,CAAC;gBACvD,QAAQ,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;gBAC/E,MAAM;YACV,CAAC;QACL,CAAC;QAED,OAAO;YACH,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC;YACtC,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;SACvD,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sorting/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACH,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACvB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sorting/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACH,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACvB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sorting strategies for RDF quads.
|
|
3
|
+
*
|
|
4
|
+
* These strategies allow customizing the order of quads in serialized output,
|
|
5
|
+
* supporting use cases like grouping by type, semantic ordering (dependencies first),
|
|
6
|
+
* and custom priority ordering.
|
|
7
|
+
*/
|
|
8
|
+
import type { Quad } from '@rdfjs/types';
|
|
9
|
+
import type { Rdf12Quad, QuadComparator, SortingStrategy, PriorityStrategyConfig } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Alphabetical sorting by subject, predicate, object.
|
|
12
|
+
* This is the default sorting strategy.
|
|
13
|
+
*/
|
|
14
|
+
export declare const alphabeticalStrategy: SortingStrategy;
|
|
15
|
+
/**
|
|
16
|
+
* Strategy that groups quads by their rdf:type, then sorts alphabetically within each type.
|
|
17
|
+
* Resources without a type are placed according to unmatchedPosition.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createByTypeStrategy(config?: {
|
|
20
|
+
/** Where to place resources without rdf:type */
|
|
21
|
+
unmatchedPosition?: 'start' | 'end';
|
|
22
|
+
/** How to sort within each type group */
|
|
23
|
+
secondarySort?: 'alphabetical' | 'none';
|
|
24
|
+
}): SortingStrategy;
|
|
25
|
+
/**
|
|
26
|
+
* Semantic ordering: resources that are referenced by others come before their referents.
|
|
27
|
+
* Uses topological sort to ensure dependencies are defined before they are used.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createSemanticStrategy(config?: {
|
|
30
|
+
/** Where to place resources that form cycles (can't be fully ordered) */
|
|
31
|
+
cyclesPosition?: 'start' | 'end';
|
|
32
|
+
}): SortingStrategy;
|
|
33
|
+
/**
|
|
34
|
+
* Priority-based sorting: order resources by their type according to a priority list.
|
|
35
|
+
* Types earlier in the list appear first. Unmatched resources are placed according to config.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createPriorityStrategy(config: PriorityStrategyConfig): SortingStrategy;
|
|
38
|
+
/**
|
|
39
|
+
* Applies a sorting strategy to an array of quads.
|
|
40
|
+
*
|
|
41
|
+
* @param quads The quads to sort
|
|
42
|
+
* @param strategy The sorting strategy (strategy object, comparator function, or true for alphabetical)
|
|
43
|
+
* @returns A new sorted array of quads
|
|
44
|
+
*/
|
|
45
|
+
export declare function applySortingStrategy(quads: Array<Quad | Rdf12Quad>, strategy: boolean | SortingStrategy | QuadComparator): Array<Quad | Rdf12Quad>;
|
|
46
|
+
//# sourceMappingURL=strategies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies.d.ts","sourceRoot":"","sources":["../../src/sorting/strategies.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGtG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,eAWlC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE;IAC1C,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACpC,yCAAyC;IACzC,aAAa,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;CAC3C,GAAG,eAAe,CAgElB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE;IAC5C,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACpC,GAAG,eAAe,CAsGlB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,eAAe,CAyEtF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC,EAC9B,QAAQ,EAAE,OAAO,GAAG,eAAe,GAAG,cAAc,GACrD,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC,CAoBzB"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sorting strategies for RDF quads.
|
|
3
|
+
*
|
|
4
|
+
* These strategies allow customizing the order of quads in serialized output,
|
|
5
|
+
* supporting use cases like grouping by type, semantic ordering (dependencies first),
|
|
6
|
+
* and custom priority ordering.
|
|
7
|
+
*/
|
|
8
|
+
import { termToString, RDF_TYPE } from '../utils.js';
|
|
9
|
+
/**
|
|
10
|
+
* Alphabetical sorting by subject, predicate, object.
|
|
11
|
+
* This is the default sorting strategy.
|
|
12
|
+
*/
|
|
13
|
+
export const alphabeticalStrategy = {
|
|
14
|
+
name: 'alphabetical',
|
|
15
|
+
compare(a, b) {
|
|
16
|
+
const subjectCompare = termToString(a.subject).localeCompare(termToString(b.subject));
|
|
17
|
+
if (subjectCompare !== 0)
|
|
18
|
+
return subjectCompare;
|
|
19
|
+
const predicateCompare = termToString(a.predicate).localeCompare(termToString(b.predicate));
|
|
20
|
+
if (predicateCompare !== 0)
|
|
21
|
+
return predicateCompare;
|
|
22
|
+
return termToString(a.object).localeCompare(termToString(b.object));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Strategy that groups quads by their rdf:type, then sorts alphabetically within each type.
|
|
27
|
+
* Resources without a type are placed according to unmatchedPosition.
|
|
28
|
+
*/
|
|
29
|
+
export function createByTypeStrategy(config) {
|
|
30
|
+
const unmatchedPosition = config?.unmatchedPosition ?? 'end';
|
|
31
|
+
const secondarySort = config?.secondarySort ?? 'alphabetical';
|
|
32
|
+
return {
|
|
33
|
+
name: 'byType',
|
|
34
|
+
_typeIndex: new Map(),
|
|
35
|
+
_allTypes: new Set(),
|
|
36
|
+
prepare(quads) {
|
|
37
|
+
this._typeIndex.clear();
|
|
38
|
+
this._allTypes.clear();
|
|
39
|
+
for (const q of quads) {
|
|
40
|
+
if (q.predicate.value === RDF_TYPE && q.object.termType === 'NamedNode') {
|
|
41
|
+
const subj = termToString(q.subject);
|
|
42
|
+
const typeIri = q.object.value;
|
|
43
|
+
this._typeIndex.set(subj, typeIri);
|
|
44
|
+
this._allTypes.add(typeIri);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
compare(a, b) {
|
|
49
|
+
const typeIndex = this._typeIndex;
|
|
50
|
+
const allTypes = Array.from(this._allTypes).sort();
|
|
51
|
+
const subjA = termToString(a.subject);
|
|
52
|
+
const subjB = termToString(b.subject);
|
|
53
|
+
const typeA = typeIndex.get(subjA);
|
|
54
|
+
const typeB = typeIndex.get(subjB);
|
|
55
|
+
// Handle unmatched (no type)
|
|
56
|
+
const hasTypeA = typeA !== undefined;
|
|
57
|
+
const hasTypeB = typeB !== undefined;
|
|
58
|
+
if (!hasTypeA && hasTypeB) {
|
|
59
|
+
return unmatchedPosition === 'start' ? -1 : 1;
|
|
60
|
+
}
|
|
61
|
+
if (hasTypeA && !hasTypeB) {
|
|
62
|
+
return unmatchedPosition === 'start' ? 1 : -1;
|
|
63
|
+
}
|
|
64
|
+
// Both have types or both don't
|
|
65
|
+
if (hasTypeA && hasTypeB) {
|
|
66
|
+
const typeCompare = allTypes.indexOf(typeA).toString().localeCompare(allTypes.indexOf(typeB).toString());
|
|
67
|
+
if (typeCompare !== 0) {
|
|
68
|
+
return typeA.localeCompare(typeB);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Secondary sort
|
|
72
|
+
if (secondarySort === 'alphabetical') {
|
|
73
|
+
return subjA.localeCompare(subjB)
|
|
74
|
+
|| termToString(a.predicate).localeCompare(termToString(b.predicate))
|
|
75
|
+
|| termToString(a.object).localeCompare(termToString(b.object));
|
|
76
|
+
}
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Semantic ordering: resources that are referenced by others come before their referents.
|
|
83
|
+
* Uses topological sort to ensure dependencies are defined before they are used.
|
|
84
|
+
*/
|
|
85
|
+
export function createSemanticStrategy(config) {
|
|
86
|
+
const cyclesPosition = config?.cyclesPosition ?? 'end';
|
|
87
|
+
return {
|
|
88
|
+
name: 'semantic',
|
|
89
|
+
_subjectOrder: new Map(),
|
|
90
|
+
prepare(quads) {
|
|
91
|
+
const subjectOrder = this._subjectOrder;
|
|
92
|
+
subjectOrder.clear();
|
|
93
|
+
// Build dependency graph
|
|
94
|
+
const subjects = new Set();
|
|
95
|
+
const dependencies = new Map(); // subject → subjects it depends on
|
|
96
|
+
for (const q of quads) {
|
|
97
|
+
const subj = termToString(q.subject);
|
|
98
|
+
subjects.add(subj);
|
|
99
|
+
// If object is a resource that's also a subject, it's a dependency
|
|
100
|
+
if (q.object.termType === 'NamedNode' || q.object.termType === 'BlankNode') {
|
|
101
|
+
const obj = termToString(q.object);
|
|
102
|
+
if (!dependencies.has(subj)) {
|
|
103
|
+
dependencies.set(subj, new Set());
|
|
104
|
+
}
|
|
105
|
+
dependencies.get(subj).add(obj);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Topological sort using Kahn's algorithm
|
|
109
|
+
const inDegree = new Map();
|
|
110
|
+
const outEdges = new Map(); // points to dependents
|
|
111
|
+
for (const subj of subjects) {
|
|
112
|
+
inDegree.set(subj, 0);
|
|
113
|
+
outEdges.set(subj, new Set());
|
|
114
|
+
}
|
|
115
|
+
// Build in-degree counts and reverse edges
|
|
116
|
+
for (const [subj, deps] of dependencies) {
|
|
117
|
+
for (const dep of deps) {
|
|
118
|
+
if (subjects.has(dep)) {
|
|
119
|
+
inDegree.set(subj, (inDegree.get(subj) ?? 0) + 1);
|
|
120
|
+
outEdges.get(dep).add(subj);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Process nodes with no dependencies first
|
|
125
|
+
const queue = [];
|
|
126
|
+
for (const [subj, degree] of inDegree) {
|
|
127
|
+
if (degree === 0) {
|
|
128
|
+
queue.push(subj);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
queue.sort(); // Alphabetical within same level
|
|
132
|
+
let order = 0;
|
|
133
|
+
const ordered = [];
|
|
134
|
+
while (queue.length > 0) {
|
|
135
|
+
const current = queue.shift();
|
|
136
|
+
subjectOrder.set(current, order++);
|
|
137
|
+
ordered.push(current);
|
|
138
|
+
const dependents = Array.from(outEdges.get(current) ?? []).sort();
|
|
139
|
+
for (const dep of dependents) {
|
|
140
|
+
const newDegree = (inDegree.get(dep) ?? 1) - 1;
|
|
141
|
+
inDegree.set(dep, newDegree);
|
|
142
|
+
if (newDegree === 0) {
|
|
143
|
+
queue.push(dep);
|
|
144
|
+
queue.sort();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Handle cycles - remaining subjects not in ordered list
|
|
149
|
+
const cycleOrder = cyclesPosition === 'start' ? -1 : order;
|
|
150
|
+
for (const subj of subjects) {
|
|
151
|
+
if (!subjectOrder.has(subj)) {
|
|
152
|
+
subjectOrder.set(subj, cycleOrder);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
compare(a, b) {
|
|
157
|
+
const subjectOrder = this._subjectOrder;
|
|
158
|
+
const subjA = termToString(a.subject);
|
|
159
|
+
const subjB = termToString(b.subject);
|
|
160
|
+
const orderA = subjectOrder.get(subjA) ?? Infinity;
|
|
161
|
+
const orderB = subjectOrder.get(subjB) ?? Infinity;
|
|
162
|
+
if (orderA !== orderB) {
|
|
163
|
+
return orderA - orderB;
|
|
164
|
+
}
|
|
165
|
+
// Within same subject, sort by predicate then object
|
|
166
|
+
return termToString(a.predicate).localeCompare(termToString(b.predicate))
|
|
167
|
+
|| termToString(a.object).localeCompare(termToString(b.object));
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Priority-based sorting: order resources by their type according to a priority list.
|
|
173
|
+
* Types earlier in the list appear first. Unmatched resources are placed according to config.
|
|
174
|
+
*/
|
|
175
|
+
export function createPriorityStrategy(config) {
|
|
176
|
+
const { typeOrder = [], predicateOrder = [], unmatchedPosition = 'end', unmatchedSort = 'alphabetical' } = config;
|
|
177
|
+
const typeRank = new Map(typeOrder.map((t, i) => [t, i]));
|
|
178
|
+
const predicateRank = new Map(predicateOrder.map((p, i) => [p, i]));
|
|
179
|
+
const unmatchedRank = unmatchedPosition === 'start' ? -1 : typeOrder.length;
|
|
180
|
+
return {
|
|
181
|
+
name: 'priority',
|
|
182
|
+
_typeIndex: new Map(),
|
|
183
|
+
prepare(quads) {
|
|
184
|
+
const typeIndex = this._typeIndex;
|
|
185
|
+
typeIndex.clear();
|
|
186
|
+
for (const q of quads) {
|
|
187
|
+
if (q.predicate.value === RDF_TYPE && q.object.termType === 'NamedNode') {
|
|
188
|
+
const subj = termToString(q.subject);
|
|
189
|
+
const rank = typeRank.get(q.object.value);
|
|
190
|
+
if (rank !== undefined) {
|
|
191
|
+
// Use lowest rank if subject has multiple types
|
|
192
|
+
const existing = typeIndex.get(subj);
|
|
193
|
+
if (existing === undefined || rank < existing) {
|
|
194
|
+
typeIndex.set(subj, rank);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
compare(a, b) {
|
|
201
|
+
const typeIndex = this._typeIndex;
|
|
202
|
+
const subjA = termToString(a.subject);
|
|
203
|
+
const subjB = termToString(b.subject);
|
|
204
|
+
const rankA = typeIndex.get(subjA) ?? unmatchedRank;
|
|
205
|
+
const rankB = typeIndex.get(subjB) ?? unmatchedRank;
|
|
206
|
+
// Primary: by type rank
|
|
207
|
+
if (rankA !== rankB) {
|
|
208
|
+
return rankA - rankB;
|
|
209
|
+
}
|
|
210
|
+
// Secondary: by subject
|
|
211
|
+
const subjCompare = subjA.localeCompare(subjB);
|
|
212
|
+
if (subjCompare !== 0) {
|
|
213
|
+
return subjCompare;
|
|
214
|
+
}
|
|
215
|
+
// Tertiary: by predicate rank if configured
|
|
216
|
+
if (predicateOrder.length > 0) {
|
|
217
|
+
const predRankA = predicateRank.get(a.predicate.value) ?? predicateOrder.length;
|
|
218
|
+
const predRankB = predicateRank.get(b.predicate.value) ?? predicateOrder.length;
|
|
219
|
+
if (predRankA !== predRankB) {
|
|
220
|
+
return predRankA - predRankB;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Final: alphabetical within same rank
|
|
224
|
+
if (unmatchedSort === 'alphabetical') {
|
|
225
|
+
return termToString(a.predicate).localeCompare(termToString(b.predicate))
|
|
226
|
+
|| termToString(a.object).localeCompare(termToString(b.object));
|
|
227
|
+
}
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Applies a sorting strategy to an array of quads.
|
|
234
|
+
*
|
|
235
|
+
* @param quads The quads to sort
|
|
236
|
+
* @param strategy The sorting strategy (strategy object, comparator function, or true for alphabetical)
|
|
237
|
+
* @returns A new sorted array of quads
|
|
238
|
+
*/
|
|
239
|
+
export function applySortingStrategy(quads, strategy) {
|
|
240
|
+
if (strategy === false) {
|
|
241
|
+
return quads;
|
|
242
|
+
}
|
|
243
|
+
const sorted = [...quads];
|
|
244
|
+
if (strategy === true) {
|
|
245
|
+
// Default alphabetical
|
|
246
|
+
sorted.sort(alphabeticalStrategy.compare.bind(alphabeticalStrategy));
|
|
247
|
+
}
|
|
248
|
+
else if (typeof strategy === 'function') {
|
|
249
|
+
// Custom comparator function
|
|
250
|
+
sorted.sort(strategy);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
// Strategy object
|
|
254
|
+
strategy.prepare?.(sorted);
|
|
255
|
+
sorted.sort(strategy.compare.bind(strategy));
|
|
256
|
+
}
|
|
257
|
+
return sorted;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=strategies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies.js","sourceRoot":"","sources":["../../src/sorting/strategies.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { IToken } from 'chevrotain';
|
|
2
|
+
import type { ISparqlFormatter, SerializationResult, TokenSerializerOptions } from '../types.js';
|
|
3
|
+
import { BaseTokenFormatter, type BaseFormatterContext, type BaseFormatterOptions } from '../base-token-formatter.js';
|
|
4
|
+
/**
|
|
5
|
+
* SPARQL-specific formatting options.
|
|
6
|
+
*/
|
|
7
|
+
export interface SparqlFormatterOptions extends BaseFormatterOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Whether to uppercase SPARQL keywords (SELECT, WHERE, etc.).
|
|
10
|
+
* Default: true
|
|
11
|
+
*/
|
|
12
|
+
uppercaseKeywords?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to lowercase SPARQL keywords.
|
|
15
|
+
* Default: false (takes precedence if both are true)
|
|
16
|
+
*/
|
|
17
|
+
lowercaseKeywords?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Whether to align WHERE clause patterns.
|
|
20
|
+
* When true, triple patterns within blocks are aligned.
|
|
21
|
+
* Default: true
|
|
22
|
+
*/
|
|
23
|
+
alignPatterns?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to put opening braces on the same line as keywords.
|
|
26
|
+
* Default: true
|
|
27
|
+
*/
|
|
28
|
+
sameBraceLine?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to insert blank lines between major clauses.
|
|
31
|
+
* Default: true
|
|
32
|
+
*/
|
|
33
|
+
separateClauses?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Internal formatting context that tracks state during token processing.
|
|
37
|
+
*/
|
|
38
|
+
interface SparqlFormatterContext extends BaseFormatterContext {
|
|
39
|
+
opts: Required<SparqlFormatterOptions>;
|
|
40
|
+
justEndedPrefix: boolean;
|
|
41
|
+
inWhereBlock: boolean;
|
|
42
|
+
functionCallDepth: number;
|
|
43
|
+
hasFromClause: boolean;
|
|
44
|
+
isAskQuery: boolean;
|
|
45
|
+
/** Tracks if we just closed an inline block */
|
|
46
|
+
lastWasInlineBlock: boolean;
|
|
47
|
+
/** Index in parts[] where the last comment block started (for blank-line repositioning). */
|
|
48
|
+
lastCommentPartIndex: number;
|
|
49
|
+
/** Whether the last comment block already consumed a blank line (from source or clause separation). */
|
|
50
|
+
lastCommentHadBlankLine: boolean;
|
|
51
|
+
/** Whether we are inside a VALUES clause (between VALUES keyword and matching close brace). */
|
|
52
|
+
inValuesClause: boolean;
|
|
53
|
+
/** Depth of the VALUES scope (to match the correct closing brace). */
|
|
54
|
+
valuesDepth: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Formatter for SPARQL queries and updates.
|
|
58
|
+
*
|
|
59
|
+
* Uses the W3C-compliant SparqlLexer from mentor-rdf-parsers for tokenization.
|
|
60
|
+
*
|
|
61
|
+
* This formatter can:
|
|
62
|
+
* - Format SPARQL 1.1/1.2 queries and updates
|
|
63
|
+
* - Normalize keyword casing
|
|
64
|
+
* - Apply consistent indentation
|
|
65
|
+
* - Align triple patterns
|
|
66
|
+
* - Preserve comments
|
|
67
|
+
* - Preserve source newlines and blank lines
|
|
68
|
+
*
|
|
69
|
+
* @see https://www.w3.org/TR/sparql12-query/
|
|
70
|
+
*/
|
|
71
|
+
export declare class SparqlFormatter extends BaseTokenFormatter<SparqlFormatterContext, SparqlFormatterOptions> implements ISparqlFormatter {
|
|
72
|
+
private lexer;
|
|
73
|
+
formatFromText(query: string, options?: SparqlFormatterOptions): SerializationResult;
|
|
74
|
+
formatFromTokens(tokens: IToken[], options?: SparqlFormatterOptions & TokenSerializerOptions): SerializationResult;
|
|
75
|
+
protected getOptions(options?: SparqlFormatterOptions): Required<SparqlFormatterOptions>;
|
|
76
|
+
protected createContext(opts: Required<SparqlFormatterOptions>): SparqlFormatterContext;
|
|
77
|
+
protected formatTokenValue(token: IToken, opts: Required<SparqlFormatterOptions>): string;
|
|
78
|
+
/**
|
|
79
|
+
* Calculates the length of a block's content (from { to matching }).
|
|
80
|
+
* Returns -1 if the block should use multi-line formatting.
|
|
81
|
+
*/
|
|
82
|
+
private calculateBlockLength;
|
|
83
|
+
private shouldBlockBeInline;
|
|
84
|
+
private handleOpenBrace;
|
|
85
|
+
private handleCloseBrace;
|
|
86
|
+
private handleSparqlPeriod;
|
|
87
|
+
private handleSparqlSemicolon;
|
|
88
|
+
private handleSparqlComma;
|
|
89
|
+
private handleSparqlOpenParen;
|
|
90
|
+
private handleSparqlCloseParen;
|
|
91
|
+
private handleGroupComment;
|
|
92
|
+
private handleInlineComment;
|
|
93
|
+
private updateClauseState;
|
|
94
|
+
private handleClauseSeparation;
|
|
95
|
+
private handleTriplePosition;
|
|
96
|
+
private handleLineWrapping;
|
|
97
|
+
private handleSparqlTokenSpacing;
|
|
98
|
+
private detectBlankLines;
|
|
99
|
+
private handleSparqlPrefixIri;
|
|
100
|
+
private formatTokenStream;
|
|
101
|
+
}
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/sparql/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EACR,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC5B,MAAM,4BAA4B,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAChE;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,UAAU,sBAAuB,SAAQ,oBAAoB;IACzD,IAAI,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IACvC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,4FAA4F;IAC5F,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uGAAuG;IACvG,uBAAuB,EAAE,OAAO,CAAC;IACjC,+FAA+F;IAC/F,cAAc,EAAE,OAAO,CAAC;IACxB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eACT,SAAQ,kBAAkB,CAAC,sBAAsB,EAAE,sBAAsB,CACzE,YAAW,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAqB;IAMlC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,mBAAmB;IAWpF,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,GAAG,mBAAmB;IAUlH,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,QAAQ,CAAC,sBAAsB,CAAC;IAmBxF,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GAAG,sBAAsB;IAiBvF,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GAAG,MAAM;IAezF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAoG5B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,eAAe;IAoDvB,OAAO,CAAC,gBAAgB;IAsCxB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,qBAAqB;IA0C7B,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,qBAAqB;IAsC7B,OAAO,CAAC,sBAAsB;IAwD9B,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,sBAAsB;IAoC9B,OAAO,CAAC,oBAAoB;IAqC5B,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,wBAAwB;IA+ChC,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,qBAAqB;IAuB7B,OAAO,CAAC,iBAAiB;CAmG5B"}
|