rdflib 2.3.9 → 2.4.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/README.md +47 -1
- package/dist/rdflib.min.js +1 -1
- package/dist/rdflib.min.js.map +1 -1
- package/esm/fetcher.js +42 -16
- package/esm/index.js +1 -2
- package/esm/parse.js +4 -3
- package/esm/serializer.js +2 -2
- package/lib/fetcher.d.ts +1 -0
- package/lib/fetcher.js +42 -16
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -10
- package/lib/parse.js +3 -2
- package/lib/serialize.d.ts +1 -1
- package/lib/serializer.js +2 -2
- package/lib/types.d.ts +1 -1
- package/package.json +2 -3
- package/src/fetcher.ts +55 -18
- package/src/index.ts +0 -2
- package/src/parse.ts +4 -3
- package/src/serialize.ts +1 -1
- package/src/serializer.js +2 -2
- package/src/types.ts +1 -0
- package/esm/jsonparser.js +0 -53
- package/lib/jsonparser.d.ts +0 -4
- package/lib/jsonparser.js +0 -59
- package/src/jsonparser.js +0 -53
package/esm/fetcher.js
CHANGED
|
@@ -674,16 +674,42 @@ export default class Fetcher {
|
|
|
674
674
|
// if metadata flaged clear cache and removeDocument
|
|
675
675
|
const meta = this.appNode;
|
|
676
676
|
const kb = this.store;
|
|
677
|
-
|
|
677
|
+
// The recorded URI is stored as a string literal, not as a node (see
|
|
678
|
+
// saveRequestMetadata and linkeddata/rdflib.js#427): matching it with
|
|
679
|
+
// kb.sym() never found the request, so a flagged document was answered from
|
|
680
|
+
// the cache instead of being refetched (#870).
|
|
681
|
+
const requests = kb.statementsMatching(undefined, this.ns.link('requestedURI'), kb.rdfFactory.literal(docuri), meta).map(st => st.subject);
|
|
682
|
+
let answered = false;
|
|
683
|
+
let usableAnswer = false;
|
|
678
684
|
for (const request of requests) {
|
|
679
685
|
const response = kb.any(request, this.ns.link('response'), null, meta);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
options.clearPreviousData = true;
|
|
686
|
+
// any() returns null (never undefined) when nothing matches: keep the
|
|
687
|
+
// loose check so a request that has no recorded answer yet is not
|
|
688
|
+
// counted as answered.
|
|
689
|
+
if (response == null) {
|
|
690
|
+
continue;
|
|
686
691
|
}
|
|
692
|
+
answered = true;
|
|
693
|
+
// Every recorded answer that is flagged out-of-date is unusable: the
|
|
694
|
+
// answer of a previous identity/authorization (flagAuthorizationMetadata).
|
|
695
|
+
// Read the mark with anyJS, as update-manager.editable does: it is stored
|
|
696
|
+
// as an xsd:boolean literal and the object position has to stay a
|
|
697
|
+
// wildcard - any() returns null when all four positions are given, even
|
|
698
|
+
// when the statement exists.
|
|
699
|
+
const outOfDate = kb.anyJS(response, this.ns.link('outOfDate'), null, meta);
|
|
700
|
+
if (!outOfDate) {
|
|
701
|
+
usableAnswer = true;
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (answered && !usableAnswer) {
|
|
706
|
+
// Refetch instead of answering from the cache, and keep the marks: an
|
|
707
|
+
// answer of the previous authorization stays excluded, so it cannot win
|
|
708
|
+
// over the fresh one — and if the refetch fails the state stays
|
|
709
|
+
// "unknown" instead of becoming definitive again. Once a fresh answer is
|
|
710
|
+
// recorded the loop above finds it and later loads are cache hits again.
|
|
711
|
+
options.force = true;
|
|
712
|
+
options.clearPreviousData = true;
|
|
687
713
|
}
|
|
688
714
|
const initialisedOptions = this.initFetchOptions(docuri, options);
|
|
689
715
|
return this.pendingFetchPromise(docuri, initialisedOptions.baseURI, initialisedOptions);
|
|
@@ -977,27 +1003,27 @@ export default class Fetcher {
|
|
|
977
1003
|
linkData(originalUri, rel, uri, why, reverse) {
|
|
978
1004
|
if (!uri) return;
|
|
979
1005
|
let kb = this.store;
|
|
980
|
-
let predicate;
|
|
981
1006
|
// See http://www.w3.org/TR/powder-dr/#httplink for describedby 2008-12-10
|
|
982
1007
|
let obj = kb.rdfFactory.namedNode(Uri.join(uri, originalUri.value));
|
|
1008
|
+
let predicates;
|
|
983
1009
|
if (rel === 'alternate' || rel === 'seeAlso' || rel === 'meta' || rel === 'describedby') {
|
|
984
1010
|
if (obj.value === originalUri.value) {
|
|
985
1011
|
return;
|
|
986
1012
|
}
|
|
987
|
-
predicate
|
|
1013
|
+
// Also emit the IANA relation predicate triple (issue #741)
|
|
1014
|
+
predicates = [kb.rdfFactory.namedNode(this.ianaLinkRelation(rel)), this.ns.rdfs('seeAlso')];
|
|
988
1015
|
} else if (rel === 'type') {
|
|
989
|
-
|
|
1016
|
+
predicates = [kb.rdfFactory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')];
|
|
990
1017
|
} else {
|
|
991
1018
|
// See https://www.iana.org/assignments/link-relations/link-relations.xml
|
|
992
1019
|
// Alas not yet in RDF yet for each predicate
|
|
993
1020
|
// encode space in e.g. rel="shortcut icon"
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
if (reverse) {
|
|
997
|
-
kb.add(obj, predicate, originalUri, why);
|
|
998
|
-
} else {
|
|
999
|
-
kb.add(originalUri, predicate, obj, why);
|
|
1021
|
+
predicates = [kb.rdfFactory.namedNode(this.ianaLinkRelation(rel))];
|
|
1000
1022
|
}
|
|
1023
|
+
kb.addAll(predicates.map(predicate => reverse ? kb.rdfFactory.quad(obj, predicate, originalUri, why) : kb.rdfFactory.quad(originalUri, predicate, obj, why)));
|
|
1024
|
+
}
|
|
1025
|
+
ianaLinkRelation(rel) {
|
|
1026
|
+
return Uri.join(encodeURIComponent(rel), 'http://www.iana.org/assignments/link-relations/');
|
|
1001
1027
|
}
|
|
1002
1028
|
parseLinkHeader(linkHeader, originalUri, reqNode) {
|
|
1003
1029
|
if (!linkHeader) {
|
package/esm/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import Empty from './empty';
|
|
|
5
5
|
import Fetcher from './fetcher';
|
|
6
6
|
import Formula from './formula';
|
|
7
7
|
import Store from './store';
|
|
8
|
-
import jsonParser from './jsonparser';
|
|
9
8
|
import Literal from './literal';
|
|
10
9
|
import log from './log';
|
|
11
10
|
import N3Parser from './n3parser';
|
|
@@ -56,7 +55,7 @@ const term = Node.fromValue;
|
|
|
56
55
|
// it exports the _current_ value of nextId, which is always 0
|
|
57
56
|
const NextId = BlankNode.nextId;
|
|
58
57
|
export * from './utils/terms';
|
|
59
|
-
export { BlankNode, Collection, DataFactory, Empty, Fetcher, Formula, Store,
|
|
58
|
+
export { BlankNode, Collection, DataFactory, Empty, Fetcher, Formula, Store, Literal, log, N3Parser, NamedNode, Namespace, Node, parse, Query, queryToSPARQL, RDFaProcessor, RDFParser, serialize, Serializer, SPARQLToQuery, sparqlUpdateParser, Statement, term, UpdateManager, UpdatesSocket, UpdatesVia, uri, Util, Variable, Store as IndexedFormula,
|
|
60
59
|
// Alias
|
|
61
60
|
|
|
62
61
|
NextId, fromNT, fetcher, graph, lit, st, namedNode as sym,
|
package/esm/parse.js
CHANGED
|
@@ -7,7 +7,7 @@ import { parseRDFaDOM } from './rdfaparser';
|
|
|
7
7
|
import RDFParser from './rdfxmlparser';
|
|
8
8
|
import sparqlUpdateParser from './patch-parser';
|
|
9
9
|
import * as Util from './utils-js';
|
|
10
|
-
import { TurtleContentType, N3ContentType, RDFXMLContentType, XHTMLContentType, HTMLContentType, SPARQLUpdateContentType, SPARQLUpdateSingleMatchContentType, JSONLDContentType, NQuadsContentType, NQuadsAltContentType } from './types';
|
|
10
|
+
import { TurtleContentType, N3ContentType, NTriplesContentType, RDFXMLContentType, XHTMLContentType, HTMLContentType, SPARQLUpdateContentType, SPARQLUpdateSingleMatchContentType, JSONLDContentType, NQuadsContentType, NQuadsAltContentType } from './types';
|
|
11
11
|
/**
|
|
12
12
|
* Parse a string and put the result into the graph kb.
|
|
13
13
|
* Normal method is sync.
|
|
@@ -23,7 +23,7 @@ export default function parse(str, kb, base, contentType = 'text/turtle', callba
|
|
|
23
23
|
contentType = contentType || TurtleContentType;
|
|
24
24
|
contentType = contentType.split(';')[0];
|
|
25
25
|
try {
|
|
26
|
-
if (contentType === N3ContentType || contentType === TurtleContentType) {
|
|
26
|
+
if (contentType === N3ContentType || contentType === TurtleContentType || contentType === NTriplesContentType) {
|
|
27
27
|
var p = N3Parser(kb, kb, base, base, null, null, '', null);
|
|
28
28
|
p.loadBuf(str);
|
|
29
29
|
executeCallback();
|
|
@@ -74,7 +74,8 @@ export default function parse(str, kb, base, contentType = 'text/turtle', callba
|
|
|
74
74
|
'application/sparql-update-single-match': true,
|
|
75
75
|
'application/ld+json': true,
|
|
76
76
|
'application/nquads': true,
|
|
77
|
-
'application/n-quads': true
|
|
77
|
+
'application/n-quads': true,
|
|
78
|
+
'application/n-triples': true
|
|
78
79
|
};
|
|
79
80
|
function executeCallback() {
|
|
80
81
|
if (callback) {
|
package/esm/serializer.js
CHANGED
|
@@ -295,7 +295,7 @@ export class Serializer {
|
|
|
295
295
|
return self.atomicTermToN3(x);
|
|
296
296
|
}
|
|
297
297
|
var list = x.elements;
|
|
298
|
-
var rest = kb.sym(rdfns + '
|
|
298
|
+
var rest = kb.sym(rdfns + 'nil');
|
|
299
299
|
for (var i = list.length - 1; i >= 0; i--) {
|
|
300
300
|
var bnode = factory.blankNode();
|
|
301
301
|
str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'first')) + ' ' + termToNT(list[i]) + '.\n';
|
|
@@ -656,7 +656,7 @@ export class Serializer {
|
|
|
656
656
|
if (canSplit) {
|
|
657
657
|
if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
|
|
658
658
|
// d -> suppress default
|
|
659
|
-
if (this.flags.indexOf('k') >= 0 && this.
|
|
659
|
+
if (this.flags.indexOf('k') >= 0 && this.keywords.indexOf(localid) < 0) {
|
|
660
660
|
return localid;
|
|
661
661
|
}
|
|
662
662
|
return ':' + localid;
|
package/lib/fetcher.d.ts
CHANGED
|
@@ -340,6 +340,7 @@ export default class Fetcher implements CallbackifyInterface {
|
|
|
340
340
|
original: Quad_Subject;
|
|
341
341
|
} & Options, errorMessage: string, statusCode: StatusValues, response?: ExtendedResponse): Promise<FetchError>;
|
|
342
342
|
linkData(originalUri: NamedNode, rel: string, uri: string, why: Quad_Graph, reverse?: boolean): void;
|
|
343
|
+
private ianaLinkRelation;
|
|
343
344
|
parseLinkHeader(linkHeader: string, originalUri: NamedNode, reqNode: Quad_Graph): void;
|
|
344
345
|
doneFetch(options: {
|
|
345
346
|
req: Quad_Subject;
|
package/lib/fetcher.js
CHANGED
|
@@ -683,16 +683,42 @@ class Fetcher {
|
|
|
683
683
|
// if metadata flaged clear cache and removeDocument
|
|
684
684
|
const meta = this.appNode;
|
|
685
685
|
const kb = this.store;
|
|
686
|
-
|
|
686
|
+
// The recorded URI is stored as a string literal, not as a node (see
|
|
687
|
+
// saveRequestMetadata and linkeddata/rdflib.js#427): matching it with
|
|
688
|
+
// kb.sym() never found the request, so a flagged document was answered from
|
|
689
|
+
// the cache instead of being refetched (#870).
|
|
690
|
+
const requests = kb.statementsMatching(undefined, this.ns.link('requestedURI'), kb.rdfFactory.literal(docuri), meta).map(st => st.subject);
|
|
691
|
+
let answered = false;
|
|
692
|
+
let usableAnswer = false;
|
|
687
693
|
for (const request of requests) {
|
|
688
694
|
const response = kb.any(request, this.ns.link('response'), null, meta);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
options.clearPreviousData = true;
|
|
695
|
+
// any() returns null (never undefined) when nothing matches: keep the
|
|
696
|
+
// loose check so a request that has no recorded answer yet is not
|
|
697
|
+
// counted as answered.
|
|
698
|
+
if (response == null) {
|
|
699
|
+
continue;
|
|
695
700
|
}
|
|
701
|
+
answered = true;
|
|
702
|
+
// Every recorded answer that is flagged out-of-date is unusable: the
|
|
703
|
+
// answer of a previous identity/authorization (flagAuthorizationMetadata).
|
|
704
|
+
// Read the mark with anyJS, as update-manager.editable does: it is stored
|
|
705
|
+
// as an xsd:boolean literal and the object position has to stay a
|
|
706
|
+
// wildcard - any() returns null when all four positions are given, even
|
|
707
|
+
// when the statement exists.
|
|
708
|
+
const outOfDate = kb.anyJS(response, this.ns.link('outOfDate'), null, meta);
|
|
709
|
+
if (!outOfDate) {
|
|
710
|
+
usableAnswer = true;
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
if (answered && !usableAnswer) {
|
|
715
|
+
// Refetch instead of answering from the cache, and keep the marks: an
|
|
716
|
+
// answer of the previous authorization stays excluded, so it cannot win
|
|
717
|
+
// over the fresh one — and if the refetch fails the state stays
|
|
718
|
+
// "unknown" instead of becoming definitive again. Once a fresh answer is
|
|
719
|
+
// recorded the loop above finds it and later loads are cache hits again.
|
|
720
|
+
options.force = true;
|
|
721
|
+
options.clearPreviousData = true;
|
|
696
722
|
}
|
|
697
723
|
const initialisedOptions = this.initFetchOptions(docuri, options);
|
|
698
724
|
return this.pendingFetchPromise(docuri, initialisedOptions.baseURI, initialisedOptions);
|
|
@@ -986,27 +1012,27 @@ class Fetcher {
|
|
|
986
1012
|
linkData(originalUri, rel, uri, why, reverse) {
|
|
987
1013
|
if (!uri) return;
|
|
988
1014
|
let kb = this.store;
|
|
989
|
-
let predicate;
|
|
990
1015
|
// See http://www.w3.org/TR/powder-dr/#httplink for describedby 2008-12-10
|
|
991
1016
|
let obj = kb.rdfFactory.namedNode(Uri.join(uri, originalUri.value));
|
|
1017
|
+
let predicates;
|
|
992
1018
|
if (rel === 'alternate' || rel === 'seeAlso' || rel === 'meta' || rel === 'describedby') {
|
|
993
1019
|
if (obj.value === originalUri.value) {
|
|
994
1020
|
return;
|
|
995
1021
|
}
|
|
996
|
-
predicate
|
|
1022
|
+
// Also emit the IANA relation predicate triple (issue #741)
|
|
1023
|
+
predicates = [kb.rdfFactory.namedNode(this.ianaLinkRelation(rel)), this.ns.rdfs('seeAlso')];
|
|
997
1024
|
} else if (rel === 'type') {
|
|
998
|
-
|
|
1025
|
+
predicates = [kb.rdfFactory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')];
|
|
999
1026
|
} else {
|
|
1000
1027
|
// See https://www.iana.org/assignments/link-relations/link-relations.xml
|
|
1001
1028
|
// Alas not yet in RDF yet for each predicate
|
|
1002
1029
|
// encode space in e.g. rel="shortcut icon"
|
|
1003
|
-
|
|
1004
|
-
}
|
|
1005
|
-
if (reverse) {
|
|
1006
|
-
kb.add(obj, predicate, originalUri, why);
|
|
1007
|
-
} else {
|
|
1008
|
-
kb.add(originalUri, predicate, obj, why);
|
|
1030
|
+
predicates = [kb.rdfFactory.namedNode(this.ianaLinkRelation(rel))];
|
|
1009
1031
|
}
|
|
1032
|
+
kb.addAll(predicates.map(predicate => reverse ? kb.rdfFactory.quad(obj, predicate, originalUri, why) : kb.rdfFactory.quad(originalUri, predicate, obj, why)));
|
|
1033
|
+
}
|
|
1034
|
+
ianaLinkRelation(rel) {
|
|
1035
|
+
return Uri.join(encodeURIComponent(rel), 'http://www.iana.org/assignments/link-relations/');
|
|
1010
1036
|
}
|
|
1011
1037
|
parseLinkHeader(linkHeader, originalUri, reqNode) {
|
|
1012
1038
|
if (!linkHeader) {
|
package/lib/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import Empty from './empty';
|
|
|
4
4
|
import Fetcher from './fetcher';
|
|
5
5
|
import Formula from './formula';
|
|
6
6
|
import Store from './store';
|
|
7
|
-
import jsonParser from './jsonparser';
|
|
8
7
|
import Literal from './literal';
|
|
9
8
|
import log from './log';
|
|
10
9
|
import N3Parser from './n3parser';
|
|
@@ -34,7 +33,7 @@ declare const term: <T extends import("./types").FromValueReturns>(value: import
|
|
|
34
33
|
declare const NextId: number;
|
|
35
34
|
export * from './utils/terms';
|
|
36
35
|
export type { AutoInitOptions, ExtendedResponse, FetchError } from './fetcher';
|
|
37
|
-
export { BlankNode, Collection, DataFactory, Empty, Fetcher, Formula, Store,
|
|
36
|
+
export { BlankNode, Collection, DataFactory, Empty, Fetcher, Formula, Store, Literal, log, N3Parser, NamedNode, Namespace, Node, parse, Query, queryToSPARQL, RDFaProcessor, RDFParser, serialize, Serializer, SPARQLToQuery, sparqlUpdateParser, Statement, term, UpdateManager, UpdatesSocket, UpdatesVia, uri, Util, Variable, Store as IndexedFormula, // Alias
|
|
38
37
|
NextId, fromNT, fetcher, graph, lit, st, namedNode as sym, blankNode, defaultGraph, literal, namedNode, quad, triple, variable, };
|
|
39
38
|
export { termValue } from './utils/termValue';
|
|
40
39
|
export declare class ConnectedStore extends Store {
|
package/lib/index.js
CHANGED
|
@@ -29,7 +29,6 @@ var _exportNames = {
|
|
|
29
29
|
Formula: true,
|
|
30
30
|
Store: true,
|
|
31
31
|
IndexedFormula: true,
|
|
32
|
-
jsonParser: true,
|
|
33
32
|
Literal: true,
|
|
34
33
|
log: true,
|
|
35
34
|
N3Parser: true,
|
|
@@ -197,14 +196,7 @@ Object.defineProperty(exports, "Variable", {
|
|
|
197
196
|
return _variable.default;
|
|
198
197
|
}
|
|
199
198
|
});
|
|
200
|
-
exports.graph = exports.fromNT = exports.fetcher = exports.defaultGraph = exports.blankNode = void 0;
|
|
201
|
-
Object.defineProperty(exports, "jsonParser", {
|
|
202
|
-
enumerable: true,
|
|
203
|
-
get: function () {
|
|
204
|
-
return _jsonparser.default;
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
exports.literal = exports.lit = void 0;
|
|
199
|
+
exports.literal = exports.lit = exports.graph = exports.fromNT = exports.fetcher = exports.defaultGraph = exports.blankNode = void 0;
|
|
208
200
|
Object.defineProperty(exports, "log", {
|
|
209
201
|
enumerable: true,
|
|
210
202
|
get: function () {
|
|
@@ -252,7 +244,6 @@ var _empty = _interopRequireDefault(require("./empty"));
|
|
|
252
244
|
var _fetcher = _interopRequireDefault(require("./fetcher"));
|
|
253
245
|
var _formula = _interopRequireDefault(require("./formula"));
|
|
254
246
|
var _store = _interopRequireDefault(require("./store"));
|
|
255
|
-
var _jsonparser = _interopRequireDefault(require("./jsonparser"));
|
|
256
247
|
var _literal = _interopRequireDefault(require("./literal"));
|
|
257
248
|
var _log = _interopRequireDefault(require("./log"));
|
|
258
249
|
var _n3parser = _interopRequireDefault(require("./n3parser"));
|
package/lib/parse.js
CHANGED
|
@@ -33,7 +33,7 @@ function parse(str, kb, base, contentType = 'text/turtle', callback) {
|
|
|
33
33
|
contentType = contentType || _types.TurtleContentType;
|
|
34
34
|
contentType = contentType.split(';')[0];
|
|
35
35
|
try {
|
|
36
|
-
if (contentType === _types.N3ContentType || contentType === _types.TurtleContentType) {
|
|
36
|
+
if (contentType === _types.N3ContentType || contentType === _types.TurtleContentType || contentType === _types.NTriplesContentType) {
|
|
37
37
|
var p = (0, _n3parser.default)(kb, kb, base, base, null, null, '', null);
|
|
38
38
|
p.loadBuf(str);
|
|
39
39
|
executeCallback();
|
|
@@ -84,7 +84,8 @@ function parse(str, kb, base, contentType = 'text/turtle', callback) {
|
|
|
84
84
|
'application/sparql-update-single-match': true,
|
|
85
85
|
'application/ld+json': true,
|
|
86
86
|
'application/nquads': true,
|
|
87
|
-
'application/n-quads': true
|
|
87
|
+
'application/n-quads': true,
|
|
88
|
+
'application/n-triples': true
|
|
88
89
|
};
|
|
89
90
|
function executeCallback() {
|
|
90
91
|
if (callback) {
|
package/lib/serialize.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { BlankNode, NamedNode } from './tf-types';
|
|
|
6
6
|
*/
|
|
7
7
|
export default function serialize(
|
|
8
8
|
/** The graph or nodes that should be serialized */
|
|
9
|
-
target: Formula | NamedNode | BlankNode | null,
|
|
9
|
+
target: Formula | NamedNode | BlankNode | null | undefined,
|
|
10
10
|
/** The store */
|
|
11
11
|
kb: Formula, base?: unknown,
|
|
12
12
|
/**
|
package/lib/serializer.js
CHANGED
|
@@ -305,7 +305,7 @@ class Serializer {
|
|
|
305
305
|
return self.atomicTermToN3(x);
|
|
306
306
|
}
|
|
307
307
|
var list = x.elements;
|
|
308
|
-
var rest = kb.sym(rdfns + '
|
|
308
|
+
var rest = kb.sym(rdfns + 'nil');
|
|
309
309
|
for (var i = list.length - 1; i >= 0; i--) {
|
|
310
310
|
var bnode = factory.blankNode();
|
|
311
311
|
str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'first')) + ' ' + termToNT(list[i]) + '.\n';
|
|
@@ -666,7 +666,7 @@ class Serializer {
|
|
|
666
666
|
if (canSplit) {
|
|
667
667
|
if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
|
|
668
668
|
// d -> suppress default
|
|
669
|
-
if (this.flags.indexOf('k') >= 0 && this.
|
|
669
|
+
if (this.flags.indexOf('k') >= 0 && this.keywords.indexOf(localid) < 0) {
|
|
670
670
|
return localid;
|
|
671
671
|
}
|
|
672
672
|
return ':' + localid;
|
package/lib/types.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export declare const XHTMLContentType: "application/xhtml+xml";
|
|
|
36
36
|
/**
|
|
37
37
|
* A valid mime type header
|
|
38
38
|
*/
|
|
39
|
-
export type ContentType = typeof RDFXMLContentType | typeof HTMLContentType | typeof JSONLDContentType | typeof N3ContentType | typeof N3LegacyContentType | typeof NQuadsAltContentType | typeof NQuadsContentType | typeof SPARQLUpdateContentType | typeof SPARQLUpdateSingleMatchContentType | typeof TurtleContentType | typeof TurtleLegacyContentType | typeof XHTMLContentType;
|
|
39
|
+
export type ContentType = typeof RDFXMLContentType | typeof HTMLContentType | typeof JSONLDContentType | typeof N3ContentType | typeof N3LegacyContentType | typeof NQuadsAltContentType | typeof NQuadsContentType | typeof NTriplesContentType | typeof SPARQLUpdateContentType | typeof SPARQLUpdateSingleMatchContentType | typeof TurtleContentType | typeof TurtleLegacyContentType | typeof XHTMLContentType;
|
|
40
40
|
/** A type for values that serves as inputs */
|
|
41
41
|
export type ValueType = Term | Node | Date | string | number | boolean | undefined | null | Collection;
|
|
42
42
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdflib",
|
|
3
3
|
"description": "an RDF library for node.js. Suitable for client and server side.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"browserslist": [
|
|
7
7
|
"> 0.5%"
|
|
@@ -51,8 +51,6 @@
|
|
|
51
51
|
"cross-fetch": "^4.1.0",
|
|
52
52
|
"jsonld": "^9.0.0",
|
|
53
53
|
"n3": "^2.0.3",
|
|
54
|
-
"package-lock.json": "^1.0.0",
|
|
55
|
-
"package.json": "^2.0.1",
|
|
56
54
|
"solid-namespace": "^0.5.4"
|
|
57
55
|
},
|
|
58
56
|
"devDependencies": {
|
|
@@ -101,6 +99,7 @@
|
|
|
101
99
|
"doc": "typedoc --out ./doc ./src/index.ts --excludePrivate --excludeInternal --tsconfig ./tsconfig.json",
|
|
102
100
|
"lint": "eslint src tests",
|
|
103
101
|
"lint:fix": "eslint src tests --fix",
|
|
102
|
+
"prepare": "npm run build",
|
|
104
103
|
"ignore:prepublishOnly": "npm ci && npm run build:all && npm run doc && npm run test",
|
|
105
104
|
"postversion": "case \"$npm_package_version\" in *-*) git push ;; *) git push --follow-tags ;; esac",
|
|
106
105
|
"start": "webpack serve --port 4800",
|
package/src/fetcher.ts
CHANGED
|
@@ -979,16 +979,43 @@ export default class Fetcher implements CallbackifyInterface {
|
|
|
979
979
|
// if metadata flaged clear cache and removeDocument
|
|
980
980
|
const meta = this.appNode
|
|
981
981
|
const kb = this.store
|
|
982
|
-
|
|
982
|
+
// The recorded URI is stored as a string literal, not as a node (see
|
|
983
|
+
// saveRequestMetadata and linkeddata/rdflib.js#427): matching it with
|
|
984
|
+
// kb.sym() never found the request, so a flagged document was answered from
|
|
985
|
+
// the cache instead of being refetched (#870).
|
|
986
|
+
const requests = kb.statementsMatching(undefined, this.ns.link('requestedURI'), kb.rdfFactory.literal(docuri), meta).map(st => st.subject)
|
|
987
|
+
let answered = false
|
|
988
|
+
let usableAnswer = false
|
|
983
989
|
for (const request of requests) {
|
|
984
990
|
const response = kb.any(request, this.ns.link('response'), null, meta) as Quad_Subject
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
991
|
+
// any() returns null (never undefined) when nothing matches: keep the
|
|
992
|
+
// loose check so a request that has no recorded answer yet is not
|
|
993
|
+
// counted as answered.
|
|
994
|
+
if (response == null) {
|
|
995
|
+
continue
|
|
996
|
+
}
|
|
997
|
+
answered = true
|
|
998
|
+
// Every recorded answer that is flagged out-of-date is unusable: the
|
|
999
|
+
// answer of a previous identity/authorization (flagAuthorizationMetadata).
|
|
1000
|
+
// Read the mark with anyJS, as update-manager.editable does: it is stored
|
|
1001
|
+
// as an xsd:boolean literal and the object position has to stay a
|
|
1002
|
+
// wildcard - any() returns null when all four positions are given, even
|
|
1003
|
+
// when the statement exists.
|
|
1004
|
+
const outOfDate = kb.anyJS(response, this.ns.link('outOfDate'), null, meta)
|
|
1005
|
+
if (!outOfDate) {
|
|
1006
|
+
usableAnswer = true
|
|
1007
|
+
break
|
|
990
1008
|
}
|
|
991
1009
|
}
|
|
1010
|
+
if (answered && !usableAnswer) {
|
|
1011
|
+
// Refetch instead of answering from the cache, and keep the marks: an
|
|
1012
|
+
// answer of the previous authorization stays excluded, so it cannot win
|
|
1013
|
+
// over the fresh one — and if the refetch fails the state stays
|
|
1014
|
+
// "unknown" instead of becoming definitive again. Once a fresh answer is
|
|
1015
|
+
// recorded the loop above finds it and later loads are cache hits again.
|
|
1016
|
+
options.force = true
|
|
1017
|
+
options.clearPreviousData = true
|
|
1018
|
+
}
|
|
992
1019
|
|
|
993
1020
|
const initialisedOptions = this.initFetchOptions(docuri, options)
|
|
994
1021
|
|
|
@@ -1346,30 +1373,40 @@ export default class Fetcher implements CallbackifyInterface {
|
|
|
1346
1373
|
) {
|
|
1347
1374
|
if (!uri) return
|
|
1348
1375
|
let kb = this.store
|
|
1349
|
-
let predicate
|
|
1350
1376
|
// See http://www.w3.org/TR/powder-dr/#httplink for describedby 2008-12-10
|
|
1351
1377
|
let obj = kb.rdfFactory.namedNode(Uri.join(uri, originalUri.value))
|
|
1352
1378
|
|
|
1379
|
+
let predicates: Quad_Predicate[]
|
|
1353
1380
|
if (rel === 'alternate' || rel === 'seeAlso' || rel === 'meta' ||
|
|
1354
1381
|
rel === 'describedby') {
|
|
1355
1382
|
if (obj.value === originalUri.value) { return }
|
|
1356
|
-
predicate
|
|
1383
|
+
// Also emit the IANA relation predicate triple (issue #741)
|
|
1384
|
+
predicates = [
|
|
1385
|
+
kb.rdfFactory.namedNode(this.ianaLinkRelation(rel)),
|
|
1386
|
+
this.ns.rdfs('seeAlso')
|
|
1387
|
+
]
|
|
1357
1388
|
} else if (rel === 'type') {
|
|
1358
|
-
|
|
1389
|
+
predicates = [kb.rdfFactory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')]
|
|
1359
1390
|
} else {
|
|
1360
1391
|
// See https://www.iana.org/assignments/link-relations/link-relations.xml
|
|
1361
1392
|
// Alas not yet in RDF yet for each predicate
|
|
1362
1393
|
// encode space in e.g. rel="shortcut icon"
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1394
|
+
predicates = [kb.rdfFactory.namedNode(
|
|
1395
|
+
this.ianaLinkRelation(rel)
|
|
1396
|
+
)]
|
|
1397
|
+
}
|
|
1398
|
+
kb.addAll(
|
|
1399
|
+
predicates.map(predicate =>
|
|
1400
|
+
reverse
|
|
1401
|
+
? kb.rdfFactory.quad(obj, predicate, originalUri, why)
|
|
1402
|
+
: kb.rdfFactory.quad(originalUri, predicate, obj, why)
|
|
1366
1403
|
)
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1404
|
+
)
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
private ianaLinkRelation(rel: string) {
|
|
1408
|
+
return Uri.join(encodeURIComponent(rel),
|
|
1409
|
+
'http://www.iana.org/assignments/link-relations/');
|
|
1373
1410
|
}
|
|
1374
1411
|
|
|
1375
1412
|
parseLinkHeader (
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,6 @@ import Empty from './empty'
|
|
|
6
6
|
import Fetcher from './fetcher'
|
|
7
7
|
import Formula from './formula'
|
|
8
8
|
import Store from './store'
|
|
9
|
-
import jsonParser from './jsonparser'
|
|
10
9
|
import Literal from './literal'
|
|
11
10
|
import log from './log'
|
|
12
11
|
import N3Parser from './n3parser'
|
|
@@ -70,7 +69,6 @@ export {
|
|
|
70
69
|
Fetcher,
|
|
71
70
|
Formula,
|
|
72
71
|
Store,
|
|
73
|
-
jsonParser,
|
|
74
72
|
Literal,
|
|
75
73
|
log,
|
|
76
74
|
N3Parser,
|
package/src/parse.ts
CHANGED
|
@@ -8,7 +8,7 @@ import RDFParser from './rdfxmlparser'
|
|
|
8
8
|
import sparqlUpdateParser from './patch-parser'
|
|
9
9
|
import * as Util from './utils-js'
|
|
10
10
|
import Formula from './formula'
|
|
11
|
-
import { ContentType, TurtleContentType, N3ContentType, RDFXMLContentType, XHTMLContentType, HTMLContentType, SPARQLUpdateContentType, SPARQLUpdateSingleMatchContentType, JSONLDContentType, NQuadsContentType, NQuadsAltContentType } from './types'
|
|
11
|
+
import { ContentType, TurtleContentType, N3ContentType, NTriplesContentType, RDFXMLContentType, XHTMLContentType, HTMLContentType, SPARQLUpdateContentType, SPARQLUpdateSingleMatchContentType, JSONLDContentType, NQuadsContentType, NQuadsAltContentType } from './types'
|
|
12
12
|
import { Quad } from './tf-types'
|
|
13
13
|
import type { Document as XmldomDocument } from '@xmldom/xmldom'
|
|
14
14
|
|
|
@@ -35,7 +35,7 @@ export default function parse (
|
|
|
35
35
|
contentType = contentType || TurtleContentType
|
|
36
36
|
contentType = contentType.split(';')[0] as ContentType
|
|
37
37
|
try {
|
|
38
|
-
if (contentType === N3ContentType || contentType === TurtleContentType) {
|
|
38
|
+
if (contentType === N3ContentType || contentType === TurtleContentType || contentType === NTriplesContentType) {
|
|
39
39
|
var p = N3Parser(kb, kb, base, base, null, null, '', null)
|
|
40
40
|
p.loadBuf(str)
|
|
41
41
|
executeCallback()
|
|
@@ -83,7 +83,8 @@ export default function parse (
|
|
|
83
83
|
'application/sparql-update-single-match': true,
|
|
84
84
|
'application/ld+json': true,
|
|
85
85
|
'application/nquads' : true,
|
|
86
|
-
'application/n-quads' : true
|
|
86
|
+
'application/n-quads' : true,
|
|
87
|
+
'application/n-triples' : true
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
function executeCallback () {
|
package/src/serialize.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { BlankNode, NamedNode } from './tf-types'
|
|
|
20
20
|
*/
|
|
21
21
|
export default function serialize (
|
|
22
22
|
/** The graph or nodes that should be serialized */
|
|
23
|
-
target: Formula | NamedNode | BlankNode | null,
|
|
23
|
+
target: Formula | NamedNode | BlankNode | null | undefined,
|
|
24
24
|
/** The store */
|
|
25
25
|
kb: Formula,
|
|
26
26
|
base?: unknown,
|
package/src/serializer.js
CHANGED
|
@@ -306,7 +306,7 @@ export class Serializer {
|
|
|
306
306
|
return self.atomicTermToN3(x)
|
|
307
307
|
}
|
|
308
308
|
var list = x.elements
|
|
309
|
-
var rest = kb.sym(rdfns + '
|
|
309
|
+
var rest = kb.sym(rdfns + 'nil')
|
|
310
310
|
for (var i = list.length - 1; i >= 0; i--) {
|
|
311
311
|
var bnode = factory.blankNode()
|
|
312
312
|
str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'first')) + ' ' + termToNT(list[i]) + '.\n'
|
|
@@ -679,7 +679,7 @@ export class Serializer {
|
|
|
679
679
|
if (this.defaultNamespace && this.defaultNamespace === namesp &&
|
|
680
680
|
this.flags.indexOf('d') < 0) { // d -> suppress default
|
|
681
681
|
if (this.flags.indexOf('k') >= 0 &&
|
|
682
|
-
this.
|
|
682
|
+
this.keywords.indexOf(localid) < 0) {
|
|
683
683
|
return localid
|
|
684
684
|
}
|
|
685
685
|
return ':' + localid
|
package/src/types.ts
CHANGED
|
@@ -55,6 +55,7 @@ export type ContentType = typeof RDFXMLContentType
|
|
|
55
55
|
| typeof N3LegacyContentType
|
|
56
56
|
| typeof NQuadsAltContentType
|
|
57
57
|
| typeof NQuadsContentType
|
|
58
|
+
| typeof NTriplesContentType
|
|
58
59
|
| typeof SPARQLUpdateContentType
|
|
59
60
|
| typeof SPARQLUpdateSingleMatchContentType
|
|
60
61
|
| typeof TurtleContentType
|
package/esm/jsonparser.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
export default (function () {
|
|
2
|
-
return {
|
|
3
|
-
parseJSON: function (data, source, store) {
|
|
4
|
-
var subject, predicate, object;
|
|
5
|
-
var bnodes = {};
|
|
6
|
-
var why = store.sym(source);
|
|
7
|
-
for (var x in data) {
|
|
8
|
-
if (x.indexOf('_:') === 0) {
|
|
9
|
-
if (bnodes[x]) {
|
|
10
|
-
subject = bnodes[x];
|
|
11
|
-
} else {
|
|
12
|
-
subject = store.bnode(x);
|
|
13
|
-
bnodes[x] = subject;
|
|
14
|
-
}
|
|
15
|
-
} else {
|
|
16
|
-
subject = store.sym(x);
|
|
17
|
-
}
|
|
18
|
-
var preds = data[x];
|
|
19
|
-
for (var y in preds) {
|
|
20
|
-
var objects = preds[y];
|
|
21
|
-
predicate = store.sym(y);
|
|
22
|
-
for (var z in objects) {
|
|
23
|
-
var obj = objects[z];
|
|
24
|
-
if (obj.type === 'uri') {
|
|
25
|
-
object = store.sym(obj.value);
|
|
26
|
-
store.add(subject, predicate, object, why);
|
|
27
|
-
} else if (obj.type === 'BlankNode') {
|
|
28
|
-
if (bnodes[obj.value]) {
|
|
29
|
-
object = bnodes[obj.value];
|
|
30
|
-
} else {
|
|
31
|
-
object = store.bnode(obj.value);
|
|
32
|
-
bnodes[obj.value] = object;
|
|
33
|
-
}
|
|
34
|
-
store.add(subject, predicate, object, why);
|
|
35
|
-
} else if (obj.type === 'Literal') {
|
|
36
|
-
// var datatype
|
|
37
|
-
if (obj.datatype) {
|
|
38
|
-
object = store.literal(obj.value, undefined, store.sym(obj.datatype));
|
|
39
|
-
} else if (obj.lang) {
|
|
40
|
-
object = store.literal(obj.value, obj.lang);
|
|
41
|
-
} else {
|
|
42
|
-
object = store.literal(obj.value);
|
|
43
|
-
}
|
|
44
|
-
store.add(subject, predicate, object, why);
|
|
45
|
-
} else {
|
|
46
|
-
throw new Error('error: unexpected termtype: ' + z.type);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
})();
|
package/lib/jsonparser.d.ts
DELETED