n3 2.11.0 → 2.11.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/browser/n3.esm.min.js +12 -12
- package/browser/n3.min.js +12 -12
- package/lib/BaseIRI.js +6 -3
- package/lib/N3DataFactory.js +4 -1
- package/lib/N3Lexer.js +152 -130
- package/lib/N3Parser.js +40 -15
- package/lib/N3Store.js +10 -3
- package/package.json +24 -19
- package/src/BaseIRI.js +7 -3
- package/src/N3DataFactory.js +2 -1
- package/src/N3Lexer.js +168 -139
- package/src/N3Parser.js +42 -14
- package/src/N3Store.js +10 -4
package/lib/N3Parser.js
CHANGED
|
@@ -24,7 +24,7 @@ class N3Parser {
|
|
|
24
24
|
options.factory && initDataFactory(this, options.factory);
|
|
25
25
|
|
|
26
26
|
// Set supported features depending on the format
|
|
27
|
-
const format = typeof options.format === 'string' ? options.format.match(
|
|
27
|
+
const format = typeof options.format === 'string' ? options.format.match(/(?:^|\W)(\w*)$/)[1].toLowerCase() : '',
|
|
28
28
|
isTurtle = /turtle/.test(format),
|
|
29
29
|
isTriG = /trig/.test(format),
|
|
30
30
|
isNTriples = /triple/.test(format),
|
|
@@ -87,7 +87,9 @@ class N3Parser {
|
|
|
87
87
|
if (fragmentPos >= 0) baseIRI = baseIRI.substr(0, fragmentPos);
|
|
88
88
|
// Set base IRI and its components
|
|
89
89
|
this._base = baseIRI;
|
|
90
|
-
|
|
90
|
+
const queryPos = baseIRI.indexOf('?');
|
|
91
|
+
const path = queryPos < 0 ? baseIRI : baseIRI.substr(0, queryPos);
|
|
92
|
+
this._basePath = baseIRI.indexOf('/') < 0 ? baseIRI : path.substr(0, path.lastIndexOf('/') + 1);
|
|
91
93
|
baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i);
|
|
92
94
|
this._baseRoot = baseIRI[0];
|
|
93
95
|
this._baseScheme = baseIRI[1];
|
|
@@ -117,14 +119,15 @@ class N3Parser {
|
|
|
117
119
|
inverse: this._inversePredicate,
|
|
118
120
|
expectOf: this._expectOf,
|
|
119
121
|
blankPrefix: this._prefixes._,
|
|
120
|
-
|
|
122
|
+
prefixChanges: this._prefixChanges,
|
|
123
|
+
quantifiedChanges: this._quantifiedChanges,
|
|
121
124
|
emptyFormula: this._emptyFormula
|
|
122
125
|
};
|
|
123
|
-
// Prefix and base declarations are scoped to their formula
|
|
126
|
+
// Prefix and base declarations are scoped to their formula,
|
|
127
|
+
// so record prefix changes to undo them when the formula ends
|
|
124
128
|
if (type === 'formula') {
|
|
125
|
-
context.prefixes = this._prefixes;
|
|
126
129
|
context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme];
|
|
127
|
-
this.
|
|
130
|
+
this._prefixChanges = [];
|
|
128
131
|
}
|
|
129
132
|
this._contextStack.push(context);
|
|
130
133
|
// Every new scope resets the predicate direction
|
|
@@ -137,7 +140,7 @@ class N3Parser {
|
|
|
137
140
|
// Label the scope with the enclosing formula's blank node
|
|
138
141
|
// (using a dot as separator, as a blank node label cannot start with it)
|
|
139
142
|
this._prefixes._ = this._graph ? `${this._graph.value}.` : '.';
|
|
140
|
-
this.
|
|
143
|
+
this._quantifiedChanges = [];
|
|
141
144
|
}
|
|
142
145
|
// A formula starts empty and must not inherit its parent's subject
|
|
143
146
|
if (type === 'formula') {
|
|
@@ -163,11 +166,16 @@ class N3Parser {
|
|
|
163
166
|
if (this._n3Mode) {
|
|
164
167
|
this._inversePredicate = context.inverse;
|
|
165
168
|
this._expectOf = context.expectOf;
|
|
166
|
-
if (type === 'formula')
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
if (type === 'formula') [this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
|
|
170
|
+
if (this._prefixChanges !== context.prefixChanges) {
|
|
171
|
+
undoChanges(this._prefixes, this._prefixChanges);
|
|
172
|
+
this._prefixChanges = context.prefixChanges;
|
|
173
|
+
}
|
|
174
|
+
this._prefixes._ = context.blankPrefix;
|
|
175
|
+
if (this._quantifiedChanges !== context.quantifiedChanges) {
|
|
176
|
+
undoChanges(this._quantified, this._quantifiedChanges);
|
|
177
|
+
this._quantifiedChanges = context.quantifiedChanges;
|
|
178
|
+
}
|
|
171
179
|
this._emptyFormula = context.emptyFormula;
|
|
172
180
|
}
|
|
173
181
|
}
|
|
@@ -976,6 +984,7 @@ class N3Parser {
|
|
|
976
984
|
_readPrefixIRI(token) {
|
|
977
985
|
if (token.type !== 'IRI') return this._error(`Expected IRI to follow prefix "${this._prefix}:"`, token);
|
|
978
986
|
const prefixNode = this._readEntity(token);
|
|
987
|
+
if (this._prefixChanges !== null) this._prefixChanges.push(this._prefix, this._prefixes[this._prefix]);
|
|
979
988
|
this._prefixes[this._prefix] = prefixNode.value;
|
|
980
989
|
this._prefixCallback(this._prefix, prefixNode);
|
|
981
990
|
return this._readDeclarationPunctuation;
|
|
@@ -1046,7 +1055,10 @@ class N3Parser {
|
|
|
1046
1055
|
return this._error(`Unexpected ${token.type}`, token);
|
|
1047
1056
|
}
|
|
1048
1057
|
// Without explicit quantifiers, map entities to a quantified entity
|
|
1049
|
-
if (!this._explicitQuantifiers)
|
|
1058
|
+
if (!this._explicitQuantifiers) {
|
|
1059
|
+
if (this._quantifiedChanges !== null) this._quantifiedChanges.push(entity.id, this._quantified[entity.id]);
|
|
1060
|
+
this._quantified[entity.id] = this._factory[this._quantifier](this._factory.blankNode().value);
|
|
1061
|
+
}
|
|
1050
1062
|
// With explicit quantifiers, output the reified quantifier
|
|
1051
1063
|
else {
|
|
1052
1064
|
// If this is the first item, start a new quantifier list
|
|
@@ -1407,7 +1419,10 @@ class N3Parser {
|
|
|
1407
1419
|
return this._base + iri;
|
|
1408
1420
|
// Resolve relative query string IRIs by replacing the query string
|
|
1409
1421
|
case '?':
|
|
1410
|
-
|
|
1422
|
+
{
|
|
1423
|
+
const queryPos = this._base.indexOf('?');
|
|
1424
|
+
return (queryPos < 0 ? this._base : this._base.substr(0, queryPos)) + iri;
|
|
1425
|
+
}
|
|
1411
1426
|
// Resolve root-relative IRIs at the root of the base IRI
|
|
1412
1427
|
case '/':
|
|
1413
1428
|
// Resolve scheme-relative IRIs to the scheme
|
|
@@ -1513,6 +1528,9 @@ class N3Parser {
|
|
|
1513
1528
|
this._inversePredicate = false;
|
|
1514
1529
|
this._expectOf = false;
|
|
1515
1530
|
this._quantified = Object.create(null);
|
|
1531
|
+
// Changes to prefixes and quantifiers in nested scopes, to undo when leaving them
|
|
1532
|
+
this._prefixChanges = null;
|
|
1533
|
+
this._quantifiedChanges = null;
|
|
1516
1534
|
this._emptyFormula = false;
|
|
1517
1535
|
let readToken = token => {
|
|
1518
1536
|
return this._readCallback = this._readCallback(token);
|
|
@@ -1569,8 +1587,15 @@ class N3Parser {
|
|
|
1569
1587
|
}
|
|
1570
1588
|
}
|
|
1571
1589
|
|
|
1572
|
-
//
|
|
1590
|
+
// ### `undoChanges` restores the entries of a map from a list of key and previous value pairs
|
|
1573
1591
|
exports.default = N3Parser;
|
|
1592
|
+
function undoChanges(map, changes) {
|
|
1593
|
+
for (let i = changes.length - 2; i >= 0; i -= 2) {
|
|
1594
|
+
if (changes[i + 1] === undefined) delete map[changes[i]];else map[changes[i]] = changes[i + 1];
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// The empty function
|
|
1574
1599
|
function noop() {}
|
|
1575
1600
|
|
|
1576
1601
|
// Initializes the parser with the given data factory
|
package/lib/N3Store.js
CHANGED
|
@@ -37,7 +37,10 @@ function merge(target, source, depth = 4) {
|
|
|
37
37
|
if (!(key in target)) {
|
|
38
38
|
size++;
|
|
39
39
|
target[key] = depth === 0 ? null : merge(Object.create(null), source[key], depth - 1);
|
|
40
|
-
}
|
|
40
|
+
}
|
|
41
|
+
// Merge into the existing object in place,
|
|
42
|
+
// as graph objects are frozen and cannot be reassigned
|
|
43
|
+
else if (depth !== 0) merge(target[key], source[key], depth - 1);
|
|
41
44
|
}
|
|
42
45
|
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
43
46
|
if (depth <= 2) target[SIZE] = size;
|
|
@@ -945,16 +948,20 @@ class N3Store {
|
|
|
945
948
|
}
|
|
946
949
|
|
|
947
950
|
// Store the list item and continue with parent
|
|
948
|
-
if (!first) malformed = onError(current, 'has no list head');else items.
|
|
951
|
+
if (!first) malformed = onError(current, 'has no list head');else items.push(first.object);
|
|
949
952
|
current = parent && parent.subject;
|
|
950
953
|
}
|
|
951
954
|
|
|
952
955
|
// Don't remove any quads if the list is malformed
|
|
953
956
|
if (malformed) remove = false;else {
|
|
957
|
+
// Items were collected from the tail to the head
|
|
958
|
+
items.reverse();
|
|
954
959
|
// Store the list under the value of its head
|
|
955
960
|
if (head) lists[head[headPos].value] = items;
|
|
956
961
|
// Leave lists with extra arcs fully intact; otherwise queue this list once.
|
|
957
|
-
if (remove && !extraArcs)
|
|
962
|
+
if (remove && !extraArcs) {
|
|
963
|
+
for (let i = 0; i < listQuads.length; i++) toRemove.push(listQuads[i]);
|
|
964
|
+
}
|
|
958
965
|
}
|
|
959
966
|
});
|
|
960
967
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.2",
|
|
4
4
|
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
|
|
5
5
|
"author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -60,33 +60,17 @@
|
|
|
60
60
|
"test": "jest",
|
|
61
61
|
"lint": "eslint src perf test spec",
|
|
62
62
|
"prepare": "npm run build",
|
|
63
|
-
"spec": "
|
|
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",
|
|
63
|
+
"spec": "node spec/run.js",
|
|
65
64
|
"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
|
-
"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/",
|
|
67
|
-
"spec-1-1-nquads": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/",
|
|
68
|
-
"spec-1-1-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/ --skip \"(bad-numeric-escape|bareword_decimal)\"",
|
|
69
|
-
"spec-1-1-trig": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-trig/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/ --skip \"(bad-numeric-escape|IRI-resolution-01)\"",
|
|
70
65
|
"spec-1-1-earl-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/ -o earl -p spec/earl-meta.json > spec/earl-ntriples.ttl",
|
|
71
66
|
"spec-1-1-earl-nquads": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-nquads.ttl",
|
|
72
67
|
"spec-1-1-earl-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-turtle.ttl",
|
|
73
68
|
"spec-1-1-earl-trig": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-trig/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-trig.ttl",
|
|
74
|
-
"spec-1-2": "npm run spec-1-2-turtle && npm run spec-1-2-ntriples && npm run spec-1-2-nquads && npm run spec-1-2-trig && npm run spec-1-2-turtle-eval && npm run spec-1-2-trig-eval",
|
|
75
69
|
"spec-1-2-earl": "npm run spec-1-2-earl-turtle && npm run spec-1-2-earl-ntriples && npm run spec-1-2-earl-nquads && npm run spec-1-2-earl-trig",
|
|
76
|
-
"spec-1-2-ntriples": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-n-triples/syntax/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/",
|
|
77
|
-
"spec-1-2-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/",
|
|
78
|
-
"spec-1-2-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/",
|
|
79
|
-
"spec-1-2-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/",
|
|
80
|
-
"spec-1-2-turtle-eval": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-turtle/eval/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/",
|
|
81
|
-
"spec-1-2-trig-eval": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-trig/eval/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/",
|
|
82
70
|
"spec-1-2-earl-ntriples": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf12/rdf-n-triples/syntax/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-ntriples.ttl",
|
|
83
71
|
"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",
|
|
84
72
|
"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",
|
|
85
73
|
"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",
|
|
86
|
-
"spec-n3": "npm run spec-n3-parser && npm run spec-n3-extended",
|
|
87
|
-
"spec-n3-fetch": "sh scripts/fetch-n3-tests.sh",
|
|
88
|
-
"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/'",
|
|
89
|
-
"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/'",
|
|
90
74
|
"spec-clean": "rm -rf .rdf-test-suite-cache/ .n3-tests/",
|
|
91
75
|
"docs": "cd src && docco *.js -o ../docs && cd .."
|
|
92
76
|
},
|
|
@@ -126,7 +110,28 @@
|
|
|
126
110
|
},
|
|
127
111
|
"release": {
|
|
128
112
|
"branches": [
|
|
129
|
-
"main"
|
|
113
|
+
"main",
|
|
114
|
+
{
|
|
115
|
+
"name": "next-major",
|
|
116
|
+
"prerelease": "alpha",
|
|
117
|
+
"channel": "alpha"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"plugins": [
|
|
121
|
+
[
|
|
122
|
+
"@semantic-release/commit-analyzer",
|
|
123
|
+
{
|
|
124
|
+
"preset": "conventionalcommits"
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"@semantic-release/release-notes-generator",
|
|
129
|
+
{
|
|
130
|
+
"preset": "conventionalcommits"
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"@semantic-release/npm",
|
|
134
|
+
"@semantic-release/github"
|
|
130
135
|
]
|
|
131
136
|
},
|
|
132
137
|
"publishConfig": {
|
package/src/BaseIRI.js
CHANGED
|
@@ -4,7 +4,9 @@ import { escapeRegex } from './Util';
|
|
|
4
4
|
// - file: IRIs (which could also use backslashes)
|
|
5
5
|
// - IRIs containing /. or /.. or //
|
|
6
6
|
const BASE_UNSUPPORTED = /^:?[^:?#]*(?:[?#]|$)|^file:|^[^:]*:\/*[^?#]+?\/(?:\.\.?(?:\/|$)|\/)/i;
|
|
7
|
-
|
|
7
|
+
// Supported suffixes have a first path segment other than . or ..,
|
|
8
|
+
// and further path segments of at least 3 characters
|
|
9
|
+
const SUFFIX_SUPPORTED = /^(?:(?!\.\.?(?:[/?#]|$))[^/?#]+(?:\/[^/?#]{3,})*\/?)?(?:[?#]|$)/;
|
|
8
10
|
const CURRENT = './';
|
|
9
11
|
const PARENT = '../';
|
|
10
12
|
const QUERY = '?';
|
|
@@ -88,8 +90,10 @@ export default class BaseIRI {
|
|
|
88
90
|
// Don't abbreviate unsupported path
|
|
89
91
|
if (parentPath !== QUERY && !SUFFIX_SUPPORTED.test(suffix))
|
|
90
92
|
return iri;
|
|
91
|
-
// Omit ./ with fragment or query string
|
|
92
|
-
|
|
93
|
+
// Omit ./ with fragment or query string,
|
|
94
|
+
// unless the first segment has a colon and would be read as a scheme
|
|
95
|
+
if (parentPath === CURRENT && /^[^?#]/.test(suffix) &&
|
|
96
|
+
(suffix.indexOf(':') < 0 || !/^[^/?#]*:/.test(suffix)))
|
|
93
97
|
return suffix;
|
|
94
98
|
// Append suffix to relative parent path
|
|
95
99
|
return parentPath + suffix;
|
package/src/N3DataFactory.js
CHANGED
|
@@ -499,7 +499,8 @@ export function fromTerm(term) {
|
|
|
499
499
|
case 'BlankNode': return blankNode(term.value);
|
|
500
500
|
case 'Variable': return variable(term.value);
|
|
501
501
|
case 'DefaultGraph': return DEFAULTGRAPH;
|
|
502
|
-
case 'Literal': return literal(term.value, term.language
|
|
502
|
+
case 'Literal': return literal(term.value, !term.language ? term.datatype :
|
|
503
|
+
term.direction ? { language: term.language, direction: term.direction } : term.language);
|
|
503
504
|
case 'Quad': return fromQuad(term);
|
|
504
505
|
default: throw new Error(`Unexpected termType: ${term.termType}`);
|
|
505
506
|
}
|