n3 2.9.2 → 2.10.1
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/browser/n3.esm.min.js +5 -5
- package/browser/n3.min.js +5 -5
- package/lib/N3DataFactory.js +10 -2
- package/lib/N3Store.js +22 -8
- package/package.json +7 -3
- package/src/N3DataFactory.js +10 -2
- package/src/N3Store.js +28 -9
package/lib/N3DataFactory.js
CHANGED
|
@@ -23,6 +23,8 @@ const {
|
|
|
23
23
|
// eslint-disable-next-line prefer-const
|
|
24
24
|
let DEFAULTGRAPH;
|
|
25
25
|
let _blankNodeCounter = 0;
|
|
26
|
+
// The ID of the empty IRI, which cannot be '' as that is the ID of the default graph
|
|
27
|
+
const EMPTY_IRI_ID = '<>';
|
|
26
28
|
const escapedLiteral = /^"(.*".*)(?="[^"]*$)/;
|
|
27
29
|
|
|
28
30
|
// ## DataFactory singleton
|
|
@@ -82,7 +84,10 @@ class NamedNode extends Term {
|
|
|
82
84
|
* the constructor assumes an already-validated IRI.
|
|
83
85
|
*/
|
|
84
86
|
constructor(iri) {
|
|
85
|
-
super(iri);
|
|
87
|
+
super(iri === '' ? EMPTY_IRI_ID : iri);
|
|
88
|
+
if (iri === '') Object.defineProperty(this, 'value', {
|
|
89
|
+
value: ''
|
|
90
|
+
});
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
// ### The term type of this term
|
|
@@ -291,6 +296,9 @@ function termFromId(id, factory, nested) {
|
|
|
291
296
|
case '[':
|
|
292
297
|
id = JSON.parse(id);
|
|
293
298
|
break;
|
|
299
|
+
case '<':
|
|
300
|
+
if (id === EMPTY_IRI_ID) return factory.namedNode('');
|
|
301
|
+
// falls through
|
|
294
302
|
default:
|
|
295
303
|
if (!nested || !Array.isArray(id)) {
|
|
296
304
|
return factory.namedNode(id);
|
|
@@ -312,7 +320,7 @@ function termToId(term, nested) {
|
|
|
312
320
|
// Term instantiated with another library
|
|
313
321
|
switch (term.termType) {
|
|
314
322
|
case 'NamedNode':
|
|
315
|
-
return term.value;
|
|
323
|
+
return term.value || EMPTY_IRI_ID;
|
|
316
324
|
case 'BlankNode':
|
|
317
325
|
return `_:${term.value}`;
|
|
318
326
|
case 'Variable':
|
package/lib/N3Store.js
CHANGED
|
@@ -866,9 +866,14 @@ class N3Store {
|
|
|
866
866
|
|
|
867
867
|
// ### `extractLists` finds and removes all list triples
|
|
868
868
|
// and returns the items per list.
|
|
869
|
+
// With `allowExtraArcs`, lists whose nodes carry arcs other than
|
|
870
|
+
// rdf:first/rdf:rest are returned as well,
|
|
871
|
+
// but left intact when `remove` is set. Ambiguous unreferenced list heads
|
|
872
|
+
// with multiple non-list arcs remain errors.
|
|
869
873
|
extractLists({
|
|
870
874
|
remove = false,
|
|
871
|
-
ignoreErrors = false
|
|
875
|
+
ignoreErrors = false,
|
|
876
|
+
allowExtraArcs = false
|
|
872
877
|
} = {}) {
|
|
873
878
|
// Keys are the list heads' term values, so a null-prototype map keeps
|
|
874
879
|
// them from colliding with inherited Object members such as `toString`
|
|
@@ -879,13 +884,15 @@ class N3Store {
|
|
|
879
884
|
|
|
880
885
|
// Traverse each list from its tail
|
|
881
886
|
const tails = this.getQuads(null, _IRIs.default.rdf.rest, _IRIs.default.rdf.nil, null);
|
|
882
|
-
const toRemove =
|
|
887
|
+
const toRemove = [];
|
|
883
888
|
tails.forEach(tailQuad => {
|
|
884
889
|
const items = []; // the members found as objects of rdf:first quads
|
|
885
890
|
let malformed = false; // signals whether the current list is malformed
|
|
891
|
+
let extraArcs = false; // signals whether the current list has extra arcs
|
|
886
892
|
let head; // the head of the list (_:b1 in above example)
|
|
887
893
|
let headPos; // set to subject or object when head is set
|
|
888
894
|
const graph = tailQuad.graph; // make sure list is in exactly one graph
|
|
895
|
+
const listQuads = []; // rdf:first/rdf:rest quads of this list
|
|
889
896
|
|
|
890
897
|
// Traverse the list from tail to end
|
|
891
898
|
let current = tailQuad.subject;
|
|
@@ -904,16 +911,20 @@ class N3Store {
|
|
|
904
911
|
|
|
905
912
|
// one rdf:first
|
|
906
913
|
else if (quad.predicate.value === _IRIs.default.rdf.first) {
|
|
907
|
-
if (first) malformed = onError(current, 'has multiple rdf:first arcs');else
|
|
914
|
+
if (first) malformed = onError(current, 'has multiple rdf:first arcs');else first = quad;
|
|
915
|
+
if (remove && first === quad) listQuads.push(quad);
|
|
908
916
|
}
|
|
909
917
|
|
|
910
918
|
// one rdf:rest
|
|
911
919
|
else if (quad.predicate.value === _IRIs.default.rdf.rest) {
|
|
912
|
-
if (rest) malformed = onError(current, 'has multiple rdf:rest arcs');else
|
|
920
|
+
if (rest) malformed = onError(current, 'has multiple rdf:rest arcs');else rest = quad;
|
|
921
|
+
if (remove && rest === quad) listQuads.push(quad);
|
|
913
922
|
}
|
|
914
923
|
|
|
915
924
|
// alien triple
|
|
916
|
-
else if (objectQuads.length)
|
|
925
|
+
else if (objectQuads.length) {
|
|
926
|
+
if (allowExtraArcs) extraArcs = true;else malformed = onError(current, `has non-list arc ${quad.predicate.value}`);
|
|
927
|
+
} else {
|
|
917
928
|
head = quad; // e.g. { (1 2 3) :p :o }
|
|
918
929
|
headPos = 'subject';
|
|
919
930
|
}
|
|
@@ -939,9 +950,12 @@ class N3Store {
|
|
|
939
950
|
}
|
|
940
951
|
|
|
941
952
|
// Don't remove any quads if the list is malformed
|
|
942
|
-
if (malformed) remove = false;
|
|
943
|
-
|
|
944
|
-
|
|
953
|
+
if (malformed) remove = false;else {
|
|
954
|
+
// Store the list under the value of its head
|
|
955
|
+
if (head) lists[head[headPos].value] = items;
|
|
956
|
+
// Leave lists with extra arcs fully intact; otherwise queue this list once.
|
|
957
|
+
if (remove && !extraArcs) toRemove.push(...listQuads);
|
|
958
|
+
}
|
|
945
959
|
});
|
|
946
960
|
|
|
947
961
|
// Remove list quads if requested
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
|
|
5
5
|
"author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"test": "jest",
|
|
61
61
|
"lint": "eslint src perf test spec",
|
|
62
62
|
"prepare": "npm run build",
|
|
63
|
-
"spec": "npm run spec-1-1 && npm run spec-1-2",
|
|
63
|
+
"spec": "npm run spec-1-1 && npm run spec-1-2 && npm run spec-n3",
|
|
64
64
|
"spec-1-1": "npm run spec-1-1-turtle && npm run spec-1-1-ntriples && npm run spec-1-1-nquads && npm run spec-1-1-trig",
|
|
65
65
|
"spec-1-1-earl": "npm run spec-1-1-earl-turtle && npm run spec-1-1-earl-ntriples && npm run spec-1-1-earl-nquads && npm run spec-1-1-earl-trig",
|
|
66
66
|
"spec-1-1-ntriples": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-triples/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/",
|
|
@@ -81,7 +81,11 @@
|
|
|
81
81
|
"spec-1-2-earl-nquads": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-n-quads/syntax/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-nquads.ttl",
|
|
82
82
|
"spec-1-2-earl-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-turtle/syntax/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-turtle.ttl",
|
|
83
83
|
"spec-1-2-earl-trig": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-trig/syntax/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-trig.ttl",
|
|
84
|
-
"spec-
|
|
84
|
+
"spec-n3": "npm run spec-n3-parser && npm run spec-n3-extended",
|
|
85
|
+
"spec-n3-fetch": "sh scripts/fetch-n3-tests.sh",
|
|
86
|
+
"spec-n3-parser": "npm run spec-n3-fetch && rdf-test-suite spec/parser.js https://w3c-cg.github.io/N3/tests/N3Tests/manifest-parser.ttl -i '{ \"format\": \"text/n3\" }' -m 'https://w3c-cg.github.io/N3/tests/~.n3-tests/tests/'",
|
|
87
|
+
"spec-n3-extended": "npm run spec-n3-fetch && rdf-test-suite spec/parser.js https://w3c-cg.github.io/N3/tests/N3Tests/manifest-extended.ttl -i '{ \"format\": \"text/n3\" }' -m 'https://w3c-cg.github.io/N3/tests/~.n3-tests/tests/'",
|
|
88
|
+
"spec-clean": "rm -rf .rdf-test-suite-cache/ .n3-tests/",
|
|
85
89
|
"docs": "cd src && docco *.js -o ../docs && cd .."
|
|
86
90
|
},
|
|
87
91
|
"repository": {
|
package/src/N3DataFactory.js
CHANGED
|
@@ -8,6 +8,8 @@ const { rdf, xsd } = namespaces;
|
|
|
8
8
|
// eslint-disable-next-line prefer-const
|
|
9
9
|
let DEFAULTGRAPH;
|
|
10
10
|
let _blankNodeCounter = 0;
|
|
11
|
+
// The ID of the empty IRI, which cannot be '' as that is the ID of the default graph
|
|
12
|
+
const EMPTY_IRI_ID = '<>';
|
|
11
13
|
|
|
12
14
|
const escapedLiteral = /^"(.*".*)(?="[^"]*$)/;
|
|
13
15
|
|
|
@@ -72,7 +74,9 @@ export class NamedNode extends Term {
|
|
|
72
74
|
* the constructor assumes an already-validated IRI.
|
|
73
75
|
*/
|
|
74
76
|
constructor(iri) {
|
|
75
|
-
super(iri);
|
|
77
|
+
super(iri === '' ? EMPTY_IRI_ID : iri);
|
|
78
|
+
if (iri === '')
|
|
79
|
+
Object.defineProperty(this, 'value', { value: '' });
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
// ### The term type of this term
|
|
@@ -285,6 +289,10 @@ export function termFromId(id, factory, nested) {
|
|
|
285
289
|
case '[':
|
|
286
290
|
id = JSON.parse(id);
|
|
287
291
|
break;
|
|
292
|
+
case '<':
|
|
293
|
+
if (id === EMPTY_IRI_ID)
|
|
294
|
+
return factory.namedNode('');
|
|
295
|
+
// falls through
|
|
288
296
|
default:
|
|
289
297
|
if (!nested || !Array.isArray(id)) {
|
|
290
298
|
return factory.namedNode(id);
|
|
@@ -313,7 +321,7 @@ export function termToId(term, nested) {
|
|
|
313
321
|
|
|
314
322
|
// Term instantiated with another library
|
|
315
323
|
switch (term.termType) {
|
|
316
|
-
case 'NamedNode': return term.value;
|
|
324
|
+
case 'NamedNode': return term.value || EMPTY_IRI_ID;
|
|
317
325
|
case 'BlankNode': return `_:${term.value}`;
|
|
318
326
|
case 'Variable': return `?${term.value}`;
|
|
319
327
|
case 'DefaultGraph': return '';
|
package/src/N3Store.js
CHANGED
|
@@ -916,7 +916,11 @@ export default class N3Store {
|
|
|
916
916
|
|
|
917
917
|
// ### `extractLists` finds and removes all list triples
|
|
918
918
|
// and returns the items per list.
|
|
919
|
-
|
|
919
|
+
// With `allowExtraArcs`, lists whose nodes carry arcs other than
|
|
920
|
+
// rdf:first/rdf:rest are returned as well,
|
|
921
|
+
// but left intact when `remove` is set. Ambiguous unreferenced list heads
|
|
922
|
+
// with multiple non-list arcs remain errors.
|
|
923
|
+
extractLists({ remove = false, ignoreErrors = false, allowExtraArcs = false } = {}) {
|
|
920
924
|
// Keys are the list heads' term values, so a null-prototype map keeps
|
|
921
925
|
// them from colliding with inherited Object members such as `toString`
|
|
922
926
|
const lists = Object.create(null);
|
|
@@ -925,13 +929,15 @@ export default class N3Store {
|
|
|
925
929
|
|
|
926
930
|
// Traverse each list from its tail
|
|
927
931
|
const tails = this.getQuads(null, namespaces.rdf.rest, namespaces.rdf.nil, null);
|
|
928
|
-
const toRemove =
|
|
932
|
+
const toRemove = [];
|
|
929
933
|
tails.forEach(tailQuad => {
|
|
930
934
|
const items = []; // the members found as objects of rdf:first quads
|
|
931
935
|
let malformed = false; // signals whether the current list is malformed
|
|
936
|
+
let extraArcs = false; // signals whether the current list has extra arcs
|
|
932
937
|
let head; // the head of the list (_:b1 in above example)
|
|
933
938
|
let headPos; // set to subject or object when head is set
|
|
934
939
|
const graph = tailQuad.graph; // make sure list is in exactly one graph
|
|
940
|
+
const listQuads = []; // rdf:first/rdf:rest quads of this list
|
|
935
941
|
|
|
936
942
|
// Traverse the list from tail to end
|
|
937
943
|
let current = tailQuad.subject;
|
|
@@ -953,7 +959,9 @@ export default class N3Store {
|
|
|
953
959
|
if (first)
|
|
954
960
|
malformed = onError(current, 'has multiple rdf:first arcs');
|
|
955
961
|
else
|
|
956
|
-
|
|
962
|
+
first = quad;
|
|
963
|
+
if (remove && first === quad)
|
|
964
|
+
listQuads.push(quad);
|
|
957
965
|
}
|
|
958
966
|
|
|
959
967
|
// one rdf:rest
|
|
@@ -961,12 +969,18 @@ export default class N3Store {
|
|
|
961
969
|
if (rest)
|
|
962
970
|
malformed = onError(current, 'has multiple rdf:rest arcs');
|
|
963
971
|
else
|
|
964
|
-
|
|
972
|
+
rest = quad;
|
|
973
|
+
if (remove && rest === quad)
|
|
974
|
+
listQuads.push(quad);
|
|
965
975
|
}
|
|
966
976
|
|
|
967
977
|
// alien triple
|
|
968
|
-
else if (objectQuads.length)
|
|
969
|
-
|
|
978
|
+
else if (objectQuads.length) {
|
|
979
|
+
if (allowExtraArcs)
|
|
980
|
+
extraArcs = true;
|
|
981
|
+
else
|
|
982
|
+
malformed = onError(current, `has non-list arc ${quad.predicate.value}`);
|
|
983
|
+
}
|
|
970
984
|
else {
|
|
971
985
|
head = quad; // e.g. { (1 2 3) :p :o }
|
|
972
986
|
headPos = 'subject';
|
|
@@ -1003,9 +1017,14 @@ export default class N3Store {
|
|
|
1003
1017
|
// Don't remove any quads if the list is malformed
|
|
1004
1018
|
if (malformed)
|
|
1005
1019
|
remove = false;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1020
|
+
else {
|
|
1021
|
+
// Store the list under the value of its head
|
|
1022
|
+
if (head)
|
|
1023
|
+
lists[head[headPos].value] = items;
|
|
1024
|
+
// Leave lists with extra arcs fully intact; otherwise queue this list once.
|
|
1025
|
+
if (remove && !extraArcs)
|
|
1026
|
+
toRemove.push(...listQuads);
|
|
1027
|
+
}
|
|
1009
1028
|
});
|
|
1010
1029
|
|
|
1011
1030
|
// Remove list quads if requested
|