@lblod/graph-rdfa-processor 2.1.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.
@@ -0,0 +1,1156 @@
1
+ import URIResolver from "./uri-resolver";
2
+ import Node from "./node";
3
+
4
+ export default class RDFaProcessor extends URIResolver {
5
+ constructor(targetObject) {
6
+ super();
7
+
8
+ if (targetObject) {
9
+ this.target = targetObject;
10
+ } else {
11
+ this.target = {
12
+ graph: {
13
+ subjects: {},
14
+ prefixes: {},
15
+ terms: {},
16
+ },
17
+ };
18
+ }
19
+ this.theOne = "_:" + new Date().getTime();
20
+ this.language = null;
21
+ this.vocabulary = null;
22
+ this.blankCounter = 0;
23
+ this.langAttributes = [
24
+ {
25
+ namespaceURI: "http://www.w3.org/XML/1998/namespace",
26
+ localName: "lang",
27
+ },
28
+ ];
29
+ this.inXHTMLMode = false;
30
+ this.absURIRE = /[\w\_\-]+:\S+/;
31
+ this.finishedHandlers = [];
32
+ this.init();
33
+ }
34
+
35
+ newBlankNode() {
36
+ this.blankCounter++;
37
+ return "_:" + this.blankCounter;
38
+ }
39
+
40
+ tokenize(str) {
41
+ return RDFaProcessor.trim(str).split(/\s+/);
42
+ }
43
+
44
+ parseSafeCURIEOrCURIEOrURI(value, prefixes, base) {
45
+ value = RDFaProcessor.trim(value);
46
+ if (value.charAt(0) == "[" && value.charAt(value.length - 1) == "]") {
47
+ value = value.substring(1, value.length - 1);
48
+ value = value.trim(value);
49
+ if (value.length == 0) {
50
+ return null;
51
+ }
52
+ if (value == "_:") {
53
+ // the one node
54
+ return this.theOne;
55
+ }
56
+ return this.parseCURIE(value, prefixes, base);
57
+ } else {
58
+ return this.parseCURIEOrURI(value, prefixes, base);
59
+ }
60
+ }
61
+
62
+ parseCURIE(value, prefixes, base) {
63
+ var colon = value.indexOf(":");
64
+ if (colon >= 0) {
65
+ var prefix = value.substring(0, colon);
66
+ if (prefix == "") {
67
+ // default prefix
68
+ var uri = prefixes[""];
69
+ return uri ? uri + value.substring(colon + 1) : null;
70
+ } else if (prefix == "_") {
71
+ // blank node
72
+ return "_:" + value.substring(colon + 1);
73
+ } else if (RDFaProcessor.NCNAME.test(prefix)) {
74
+ var uri = prefixes[prefix];
75
+ if (uri) {
76
+ return uri + value.substring(colon + 1);
77
+ }
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+
83
+ parseCURIEOrURI(value, prefixes, base) {
84
+ var curie = this.parseCURIE(value, prefixes, base);
85
+ if (curie) {
86
+ return curie;
87
+ }
88
+ return this.resolveAndNormalize(base, value);
89
+ }
90
+
91
+ parsePredicate(value, defaultVocabulary, terms, prefixes, base, ignoreTerms) {
92
+ if (value == "") {
93
+ return null;
94
+ }
95
+ var predicate = this.parseTermOrCURIEOrAbsURI(
96
+ value,
97
+ defaultVocabulary,
98
+ ignoreTerms ? null : terms,
99
+ prefixes,
100
+ base,
101
+ );
102
+ if (predicate && predicate.indexOf("_:") == 0) {
103
+ return null;
104
+ }
105
+ return predicate;
106
+ }
107
+
108
+ parseTermOrCURIEOrURI(value, defaultVocabulary, terms, prefixes, base) {
109
+ //alert("Parsing "+value+" with default vocab "+defaultVocabulary);
110
+ value = RDFaProcessor.trim(value);
111
+ var curie = this.parseCURIE(value, prefixes, base);
112
+ if (curie) {
113
+ return curie;
114
+ } else {
115
+ var term = terms[value];
116
+ if (term) {
117
+ return term;
118
+ }
119
+ var lcvalue = value.toLowerCase();
120
+ term = terms[lcvalue];
121
+ if (term) {
122
+ return term;
123
+ }
124
+ if (defaultVocabulary && !this.absURIRE.exec(value)) {
125
+ return defaultVocabulary + value;
126
+ }
127
+ }
128
+ return this.resolveAndNormalize(base, value);
129
+ }
130
+
131
+ parseTermOrCURIEOrAbsURI(value, defaultVocabulary, terms, prefixes, base) {
132
+ //alert("Parsing "+value+" with default vocab "+defaultVocabulary);
133
+ value = RDFaProcessor.trim(value);
134
+ var curie = this.parseCURIE(value, prefixes, base);
135
+ if (curie) {
136
+ return curie;
137
+ } else if (terms) {
138
+ if (defaultVocabulary && !this.absURIRE.exec(value)) {
139
+ return defaultVocabulary + value;
140
+ }
141
+ var term = terms[value];
142
+ if (term) {
143
+ return term;
144
+ }
145
+ var lcvalue = value.toLowerCase();
146
+ term = terms[lcvalue];
147
+ if (term) {
148
+ return term;
149
+ }
150
+ }
151
+ if (this.absURIRE.exec(value)) {
152
+ return this.resolveAndNormalize(base, value);
153
+ }
154
+ return null;
155
+ }
156
+
157
+ resolveAndNormalize(base, href) {
158
+ var u = base.resolve(href);
159
+ var parsed = this.parseURI(u);
160
+ parsed.normalize();
161
+ return parsed.spec;
162
+ }
163
+
164
+ parsePrefixMappings(str, target) {
165
+ var values = this.tokenize(str);
166
+ var prefix = null;
167
+ var uri = null;
168
+ for (var i = 0; i < values.length; i++) {
169
+ if (values[i][values[i].length - 1] == ":") {
170
+ prefix = values[i].substring(0, values[i].length - 1);
171
+ } else if (prefix) {
172
+ target[prefix] = this.target.baseURI
173
+ ? this.target.baseURI.resolve(values[i])
174
+ : values[i];
175
+ prefix = null;
176
+ }
177
+ }
178
+ }
179
+
180
+ copyMappings(mappings) {
181
+ var newMappings = {};
182
+ for (var k in mappings) {
183
+ newMappings[k] = mappings[k];
184
+ }
185
+ return newMappings;
186
+ }
187
+
188
+ ancestorPath(node) {
189
+ var path = "";
190
+ while (node && node.nodeType != Node.DOCUMENT_NODE) {
191
+ path = "/" + node.localName + path;
192
+ node = node.parentNode;
193
+ }
194
+ return path;
195
+ }
196
+
197
+ setContext(node) {
198
+ // We only recognized XHTML+RDFa 1.1 if the version is set propertyly
199
+ if (
200
+ node.localName == "html" &&
201
+ node.getAttribute("version") == "XHTML+RDFa 1.1"
202
+ ) {
203
+ this.setXHTMLContext();
204
+ } else if (
205
+ node.localName == "html" ||
206
+ node.namespaceURI == "http://www.w3.org/1999/xhtml"
207
+ ) {
208
+ if (node.ownerDocument.doctype) {
209
+ if (
210
+ node.ownerDocument.doctype.publicId ==
211
+ "-//W3C//DTD XHTML+RDFa 1.0//EN" &&
212
+ node.ownerDocument.doctype.systemId ==
213
+ "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"
214
+ ) {
215
+ console.log(
216
+ "WARNING: RDF 1.0 is not supported. Defaulting to HTML5 mode.",
217
+ );
218
+ this.setHTMLContext();
219
+ } else if (
220
+ node.ownerDocument.doctype.publicId ==
221
+ "-//W3C//DTD XHTML+RDFa 1.1//EN" &&
222
+ node.ownerDocument.doctype.systemId ==
223
+ "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd"
224
+ ) {
225
+ this.setXHTMLContext();
226
+ } else {
227
+ this.setHTMLContext();
228
+ }
229
+ } else {
230
+ this.setHTMLContext();
231
+ }
232
+ } else {
233
+ this.setXMLContext();
234
+ }
235
+ }
236
+
237
+ setInitialContext() {
238
+ this.vocabulary = null;
239
+ // By default, the prefixes are terms are loaded to the RDFa 1.1. standard within the graph constructor
240
+ this.langAttributes = [
241
+ {
242
+ namespaceURI: "http://www.w3.org/XML/1998/namespace",
243
+ localName: "lang",
244
+ },
245
+ ];
246
+ }
247
+
248
+ setXMLContext() {
249
+ this.setInitialContext();
250
+ this.inXHTMLMode = false;
251
+ this.inHTMLMode = false;
252
+ }
253
+
254
+ setHTMLContext() {
255
+ this.setInitialContext();
256
+ this.langAttributes = [
257
+ {
258
+ namespaceURI: "http://www.w3.org/XML/1998/namespace",
259
+ localName: "lang",
260
+ },
261
+ { namespaceURI: null, localName: "lang" },
262
+ ];
263
+ this.inXHTMLMode = false;
264
+ this.inHTMLMode = true;
265
+ }
266
+
267
+ setXHTMLContext() {
268
+ this.setInitialContext();
269
+
270
+ this.inXHTMLMode = true;
271
+ this.inHTMLMode = false;
272
+
273
+ this.langAttributes = [
274
+ {
275
+ namespaceURI: "http://www.w3.org/XML/1998/namespace",
276
+ localName: "lang",
277
+ },
278
+ { namespaceURI: null, localName: "lang" },
279
+ ];
280
+
281
+ // From http://www.w3.org/2011/rdfa-context/xhtml-rdfa-1.1
282
+ this.target.graph.terms["alternate"] =
283
+ "http://www.w3.org/1999/xhtml/vocab#alternate";
284
+ this.target.graph.terms["appendix"] =
285
+ "http://www.w3.org/1999/xhtml/vocab#appendix";
286
+ this.target.graph.terms["bookmark"] =
287
+ "http://www.w3.org/1999/xhtml/vocab#bookmark";
288
+ this.target.graph.terms["cite"] = "http://www.w3.org/1999/xhtml/vocab#cite";
289
+ this.target.graph.terms["chapter"] =
290
+ "http://www.w3.org/1999/xhtml/vocab#chapter";
291
+ this.target.graph.terms["contents"] =
292
+ "http://www.w3.org/1999/xhtml/vocab#contents";
293
+ this.target.graph.terms["copyright"] =
294
+ "http://www.w3.org/1999/xhtml/vocab#copyright";
295
+ this.target.graph.terms["first"] =
296
+ "http://www.w3.org/1999/xhtml/vocab#first";
297
+ this.target.graph.terms["glossary"] =
298
+ "http://www.w3.org/1999/xhtml/vocab#glossary";
299
+ this.target.graph.terms["help"] = "http://www.w3.org/1999/xhtml/vocab#help";
300
+ this.target.graph.terms["icon"] = "http://www.w3.org/1999/xhtml/vocab#icon";
301
+ this.target.graph.terms["index"] =
302
+ "http://www.w3.org/1999/xhtml/vocab#index";
303
+ this.target.graph.terms["last"] = "http://www.w3.org/1999/xhtml/vocab#last";
304
+ this.target.graph.terms["license"] =
305
+ "http://www.w3.org/1999/xhtml/vocab#license";
306
+ this.target.graph.terms["meta"] = "http://www.w3.org/1999/xhtml/vocab#meta";
307
+ this.target.graph.terms["next"] = "http://www.w3.org/1999/xhtml/vocab#next";
308
+ this.target.graph.terms["prev"] = "http://www.w3.org/1999/xhtml/vocab#prev";
309
+ this.target.graph.terms["previous"] =
310
+ "http://www.w3.org/1999/xhtml/vocab#previous";
311
+ this.target.graph.terms["section"] =
312
+ "http://www.w3.org/1999/xhtml/vocab#section";
313
+ this.target.graph.terms["stylesheet"] =
314
+ "http://www.w3.org/1999/xhtml/vocab#stylesheet";
315
+ this.target.graph.terms["subsection"] =
316
+ "http://www.w3.org/1999/xhtml/vocab#subsection";
317
+ this.target.graph.terms["start"] =
318
+ "http://www.w3.org/1999/xhtml/vocab#start";
319
+ this.target.graph.terms["top"] = "http://www.w3.org/1999/xhtml/vocab#top";
320
+ this.target.graph.terms["up"] = "http://www.w3.org/1999/xhtml/vocab#up";
321
+ this.target.graph.terms["p3pv1"] =
322
+ "http://www.w3.org/1999/xhtml/vocab#p3pv1";
323
+
324
+ // other
325
+ this.target.graph.terms["related"] =
326
+ "http://www.w3.org/1999/xhtml/vocab#related";
327
+ this.target.graph.terms["role"] = "http://www.w3.org/1999/xhtml/vocab#role";
328
+ this.target.graph.terms["transformation"] =
329
+ "http://www.w3.org/1999/xhtml/vocab#transformation";
330
+ }
331
+
332
+ init() { }
333
+
334
+ newSubjectOrigin(origin, subject) { }
335
+
336
+ addTriple(origin, subject, predicate, object) { }
337
+
338
+ process(node, options) {
339
+ if (node.nodeType == Node.DOCUMENT_NODE) {
340
+ node = node.documentElement;
341
+ this.setContext(node);
342
+ } else if (node.parentNode.nodeType == Node.DOCUMENT_NODE) {
343
+ this.setContext(node);
344
+ }
345
+ var queue = [];
346
+ // Fix for Firefox that includes the hash in the base URI
347
+ var removeHash = function(baseURI) {
348
+ var hash = baseURI.indexOf("#");
349
+ if (hash >= 0) {
350
+ baseURI = baseURI.substring(0, hash);
351
+ }
352
+ if (options && options.baseURIMap) {
353
+ baseURI = options.baseURIMap(baseURI);
354
+ }
355
+ return baseURI;
356
+ };
357
+ queue.push({
358
+ current: node,
359
+ context: this.push(null, removeHash(node.baseURI)),
360
+ });
361
+ while (queue.length > 0) {
362
+ var item = queue.shift();
363
+ if (item.parent) {
364
+ // Sequence Step 14: list triple generation
365
+ if (
366
+ item.context.parent &&
367
+ item.context.parent.listMapping == item.listMapping
368
+ ) {
369
+ // Skip a child context with exactly the same mapping
370
+ continue;
371
+ }
372
+ //console.log("Generating lists for "+item.subject+", tag "+item.parent.localName);
373
+ for (var predicate in item.listMapping) {
374
+ var list = item.listMapping[predicate];
375
+ if (list.length == 0) {
376
+ this.addTriple(item.parent, item.subject, predicate, {
377
+ type: RDFaProcessor.objectURI,
378
+ value: "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil",
379
+ });
380
+ continue;
381
+ }
382
+ var bnodes = [];
383
+ for (var i = 0; i < list.length; i++) {
384
+ bnodes.push(this.newBlankNode());
385
+ //this.newSubject(item.parent,bnodes[i]);
386
+ }
387
+ for (var i = 0; i < bnodes.length; i++) {
388
+ this.addTriple(
389
+ item.parent,
390
+ bnodes[i],
391
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#first",
392
+ list[i],
393
+ );
394
+ this.addTriple(
395
+ item.parent,
396
+ bnodes[i],
397
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest",
398
+ {
399
+ type: RDFaProcessor.objectURI,
400
+ value:
401
+ i + 1 < bnodes.length
402
+ ? bnodes[i + 1]
403
+ : "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil",
404
+ },
405
+ );
406
+ }
407
+ this.addTriple(item.parent, item.subject, predicate, {
408
+ type: RDFaProcessor.objectURI,
409
+ value: bnodes[0],
410
+ });
411
+ }
412
+ continue;
413
+ }
414
+ var current = item.current;
415
+ var context = item.context;
416
+
417
+ //console.log("Tag: "+current.localName+", listMapping="+JSON.stringify(context.listMapping));
418
+
419
+ // Sequence Step 1
420
+ var skip = false;
421
+ var newSubject = null;
422
+ var currentObjectResource = null;
423
+ var typedResource = null;
424
+ var prefixes = context.prefixes;
425
+ var prefixesCopied = false;
426
+ var incomplete = [];
427
+ var listMapping = context.listMapping;
428
+ var listMappingDifferent = context.parent ? false : true;
429
+ var language = context.language;
430
+ var vocabulary = context.vocabulary;
431
+
432
+ // TODO: the "base" element may be used for HTML+RDFa 1.1
433
+ var base;
434
+ if (!current.baseURI) {
435
+ if (this.target.baseURI) {
436
+ base = this.target.baseURI;
437
+ } else {
438
+ throw new Error(
439
+ "node.baseURI was null as baseURI must be specified as an option",
440
+ );
441
+ }
442
+ } else if (current.baseURI === "about:blank") {
443
+ if (this.target.baseURI) {
444
+ base = this.target.baseURI;
445
+ } else {
446
+ throw new Error(
447
+ "node.baseURI is about:blank a valid URL must be provided with the baseURI option. If you use JSDOM call it with an `url` parameter or, set the baseURI option of this library",
448
+ );
449
+ }
450
+ } else {
451
+ base = this.parseURI(removeHash(current.baseURI));
452
+ }
453
+
454
+ current.item = null;
455
+
456
+ // Sequence Step 2: set the default vocabulary
457
+ var vocabAtt = current.getAttributeNode("vocab");
458
+ if (vocabAtt) {
459
+ var value = RDFaProcessor.trim(vocabAtt.value);
460
+ if (value.length > 0) {
461
+ vocabulary = value;
462
+ var baseSubject = base.spec;
463
+ //this.newSubject(current,baseSubject);
464
+ this.addTriple(
465
+ current,
466
+ baseSubject,
467
+ "http://www.w3.org/ns/rdfa#usesVocabulary",
468
+ { type: RDFaProcessor.objectURI, value: vocabulary },
469
+ );
470
+ } else {
471
+ vocabulary = this.vocabulary;
472
+ }
473
+ }
474
+
475
+ // Sequence Step 3: IRI mappings
476
+ // handle xmlns attributes
477
+ for (var i = 0; i < current.attributes.length; i++) {
478
+ var att = current.attributes[i];
479
+ //if (att.namespaceURI=="http://www.w3.org/2000/xmlns/") {
480
+ if (att.name.charAt(0) == "x" && att.name.indexOf("xmlns:") == 0) {
481
+ if (!prefixesCopied) {
482
+ prefixes = this.copyMappings(prefixes);
483
+ prefixesCopied = true;
484
+ }
485
+ var prefix = att.name.substring(6);
486
+ // TODO: resolve relative?
487
+ var ref = RDFaProcessor.trim(att.value);
488
+ prefixes[prefix] = this.target.baseURI
489
+ ? this.target.baseURI.resolve(ref)
490
+ : ref;
491
+ }
492
+ }
493
+ // Handle prefix mappings (@prefix)
494
+ var prefixAtt = current.getAttributeNode("prefix");
495
+ if (prefixAtt) {
496
+ if (!prefixesCopied) {
497
+ prefixes = this.copyMappings(prefixes);
498
+ prefixesCopied = true;
499
+ }
500
+ this.parsePrefixMappings(prefixAtt.value, prefixes);
501
+ }
502
+
503
+ // Sequence Step 4: language
504
+ var xmlLangAtt = null;
505
+ for (var i = 0; !xmlLangAtt && i < this.langAttributes.length; i++) {
506
+ xmlLangAtt = current.getAttributeNodeNS(
507
+ this.langAttributes[i].namespaceURI,
508
+ this.langAttributes[i].localName,
509
+ );
510
+ }
511
+ if (xmlLangAtt) {
512
+ var value = RDFaProcessor.trim(xmlLangAtt.value);
513
+ if (value.length > 0) {
514
+ language = value;
515
+ } else {
516
+ language = null;
517
+ }
518
+ }
519
+
520
+ var relAtt = current.getAttributeNode("rel");
521
+ var revAtt = current.getAttributeNode("rev");
522
+ var typeofAtt = current.getAttributeNode("typeof");
523
+ var propertyAtt = current.getAttributeNode("property");
524
+ var datatypeAtt = current.getAttributeNode("datatype");
525
+ var datetimeAtt = this.inHTMLMode
526
+ ? current.getAttributeNode("datetime")
527
+ : null;
528
+ var contentAtt = current.getAttributeNode("content");
529
+ var aboutAtt = current.getAttributeNode("about");
530
+ var srcAtt = current.getAttributeNode("src");
531
+ var resourceAtt = current.getAttributeNode("resource");
532
+ var hrefAtt = current.getAttributeNode("href");
533
+ var inlistAtt = current.getAttributeNode("inlist");
534
+
535
+ var relAttPredicates = [];
536
+ if (relAtt) {
537
+ var values = this.tokenize(relAtt.value);
538
+ for (var i = 0; i < values.length; i++) {
539
+ var predicate = this.parsePredicate(
540
+ values[i],
541
+ vocabulary,
542
+ context.terms,
543
+ prefixes,
544
+ base,
545
+ this.inHTMLMode && propertyAtt != null,
546
+ );
547
+ if (predicate) {
548
+ relAttPredicates.push(predicate);
549
+ }
550
+ }
551
+ }
552
+ var revAttPredicates = [];
553
+ if (revAtt) {
554
+ var values = this.tokenize(revAtt.value);
555
+ for (var i = 0; i < values.length; i++) {
556
+ var predicate = this.parsePredicate(
557
+ values[i],
558
+ vocabulary,
559
+ context.terms,
560
+ prefixes,
561
+ base,
562
+ this.inHTMLMode && propertyAtt != null,
563
+ );
564
+ if (predicate) {
565
+ revAttPredicates.push(predicate);
566
+ }
567
+ }
568
+ }
569
+
570
+ // Section 3.1, bullet 7
571
+ if (
572
+ this.inHTMLMode &&
573
+ (relAtt != null || revAtt != null) &&
574
+ propertyAtt != null
575
+ ) {
576
+ if (relAttPredicates.length == 0) {
577
+ relAtt = null;
578
+ }
579
+ if (revAttPredicates.length == 0) {
580
+ revAtt = null;
581
+ }
582
+ }
583
+
584
+ if (relAtt || revAtt) {
585
+ // Sequence Step 6: establish new subject and value
586
+ if (aboutAtt) {
587
+ newSubject = this.parseSafeCURIEOrCURIEOrURI(
588
+ aboutAtt.value,
589
+ prefixes,
590
+ base,
591
+ );
592
+ }
593
+ if (typeofAtt) {
594
+ typedResource = newSubject;
595
+ }
596
+ if (!newSubject) {
597
+ if (current.parentNode.nodeType == Node.DOCUMENT_NODE) {
598
+ newSubject = removeHash(current.baseURI);
599
+ } else if (context.parentObject) {
600
+ // TODO: Verify: If the xml:base has been set and the parentObject is the baseURI of the parent, then the subject needs to be the new base URI
601
+ newSubject =
602
+ removeHash(current.parentNode.baseURI) == context.parentObject
603
+ ? removeHash(current.baseURI)
604
+ : context.parentObject;
605
+ }
606
+ }
607
+ if (resourceAtt) {
608
+ currentObjectResource = this.parseSafeCURIEOrCURIEOrURI(
609
+ resourceAtt.value,
610
+ prefixes,
611
+ base,
612
+ );
613
+ }
614
+
615
+ if (!currentObjectResource) {
616
+ if (hrefAtt) {
617
+ currentObjectResource = this.resolveAndNormalize(
618
+ base,
619
+ encodeURI(hrefAtt.value),
620
+ );
621
+ } else if (srcAtt) {
622
+ currentObjectResource = this.resolveAndNormalize(
623
+ base,
624
+ encodeURI(srcAtt.value),
625
+ );
626
+ } else if (
627
+ typeofAtt &&
628
+ !aboutAtt &&
629
+ !(
630
+ this.inXHTMLMode &&
631
+ (current.localName == "head" || current.localName == "body")
632
+ )
633
+ ) {
634
+ currentObjectResource = this.newBlankNode();
635
+ }
636
+ }
637
+ if (
638
+ typeofAtt &&
639
+ !aboutAtt &&
640
+ this.inXHTMLMode &&
641
+ (current.localName == "head" || current.localName == "body")
642
+ ) {
643
+ typedResource = newSubject;
644
+ } else if (typeofAtt && !aboutAtt) {
645
+ typedResource = currentObjectResource;
646
+ }
647
+ } else if (propertyAtt && !contentAtt && !datatypeAtt) {
648
+ // Sequence Step 5.1: establish a new subject
649
+ if (aboutAtt) {
650
+ newSubject = this.parseSafeCURIEOrCURIEOrURI(
651
+ aboutAtt.value,
652
+ prefixes,
653
+ base,
654
+ );
655
+ if (typeofAtt) {
656
+ typedResource = newSubject;
657
+ }
658
+ }
659
+ if (!newSubject && current.parentNode.nodeType == Node.DOCUMENT_NODE) {
660
+ newSubject = removeHash(current.baseURI);
661
+ if (typeofAtt) {
662
+ typedResource = newSubject;
663
+ }
664
+ } else if (!newSubject && context.parentObject) {
665
+ // TODO: Verify: If the xml:base has been set and the parentObject is the baseURI of the parent, then the subject needs to be the new base URI
666
+ newSubject =
667
+ removeHash(current.parentNode.baseURI) == context.parentObject
668
+ ? removeHash(current.baseURI)
669
+ : context.parentObject;
670
+ }
671
+ if (typeofAtt && !typedResource) {
672
+ if (resourceAtt) {
673
+ typedResource = this.parseSafeCURIEOrCURIEOrURI(
674
+ resourceAtt.value,
675
+ prefixes,
676
+ base,
677
+ );
678
+ }
679
+ if (!typedResource && hrefAtt) {
680
+ typedResource = this.resolveAndNormalize(
681
+ base,
682
+ encodeURI(hrefAtt.value),
683
+ );
684
+ }
685
+ if (!typedResource && srcAtt) {
686
+ typedResource = this.resolveAndNormalize(
687
+ base,
688
+ encodeURI(srcAtt.value),
689
+ );
690
+ }
691
+ if (
692
+ !typedResource &&
693
+ (this.inXHTMLMode || this.inHTMLMode) &&
694
+ (current.localName == "head" || current.localName == "body")
695
+ ) {
696
+ typedResource = newSubject;
697
+ }
698
+ if (!typedResource) {
699
+ typedResource = this.newBlankNode();
700
+ }
701
+ currentObjectResource = typedResource;
702
+ }
703
+ //console.log(current.localName+", newSubject="+newSubject+", typedResource="+typedResource+", currentObjectResource="+currentObjectResource);
704
+ } else {
705
+ // Sequence Step 5.2: establish a new subject
706
+ if (aboutAtt) {
707
+ newSubject = this.parseSafeCURIEOrCURIEOrURI(
708
+ aboutAtt.value,
709
+ prefixes,
710
+ base,
711
+ );
712
+ }
713
+ if (!newSubject && resourceAtt) {
714
+ newSubject = this.parseSafeCURIEOrCURIEOrURI(
715
+ resourceAtt.value,
716
+ prefixes,
717
+ base,
718
+ );
719
+ }
720
+ if (!newSubject && hrefAtt) {
721
+ newSubject = this.resolveAndNormalize(base, encodeURI(hrefAtt.value));
722
+ }
723
+ if (!newSubject && srcAtt) {
724
+ newSubject = this.resolveAndNormalize(base, encodeURI(srcAtt.value));
725
+ }
726
+ if (!newSubject) {
727
+ if (current.parentNode.nodeType == Node.DOCUMENT_NODE) {
728
+ newSubject = removeHash(current.baseURI);
729
+ } else if (
730
+ (this.inXHTMLMode || this.inHTMLMode) &&
731
+ (current.localName == "head" || current.localName == "body")
732
+ ) {
733
+ newSubject =
734
+ removeHash(current.parentNode.baseURI) == context.parentObject
735
+ ? removeHash(current.baseURI)
736
+ : context.parentObject;
737
+ } else if (typeofAtt) {
738
+ newSubject = this.newBlankNode();
739
+ } else if (context.parentObject) {
740
+ // TODO: Verify: If the xml:base has been set and the parentObject is the baseURI of the parent, then the subject needs to be the new base URI
741
+ newSubject =
742
+ removeHash(current.parentNode.baseURI) == context.parentObject
743
+ ? removeHash(current.baseURI)
744
+ : context.parentObject;
745
+ if (!propertyAtt) {
746
+ skip = true;
747
+ }
748
+ }
749
+ }
750
+ if (typeofAtt) {
751
+ typedResource = newSubject;
752
+ }
753
+ }
754
+
755
+ //console.log(current.tagName+": newSubject="+newSubject+", currentObjectResource="+currentObjectResource+", typedResource="+typedResource+", skip="+skip);
756
+
757
+ var rdfaData = null;
758
+ if (newSubject) {
759
+ //this.newSubject(current,newSubject);
760
+ if (aboutAtt || resourceAtt || typedResource) {
761
+ var id = newSubject;
762
+ if (typeofAtt && !aboutAtt && !resourceAtt && currentObjectResource) {
763
+ id = currentObjectResource;
764
+ }
765
+ //console.log("Setting data attribute for "+current.localName+" for subject "+id);
766
+ this.newSubjectOrigin(current, id);
767
+ }
768
+ }
769
+
770
+ // Sequence Step 7: generate type triple
771
+ if (typedResource) {
772
+ var values = this.tokenize(typeofAtt.value);
773
+ for (var i = 0; i < values.length; i++) {
774
+ var object = this.parseTermOrCURIEOrAbsURI(
775
+ values[i],
776
+ vocabulary,
777
+ context.terms,
778
+ prefixes,
779
+ base,
780
+ );
781
+ if (object) {
782
+ this.addTriple(current, typedResource, RDFaProcessor.typeURI, {
783
+ type: RDFaProcessor.objectURI,
784
+ value: object,
785
+ });
786
+ }
787
+ }
788
+ }
789
+
790
+ // Sequence Step 8: new list mappings if there is a new subject
791
+ //console.log("Step 8: newSubject="+newSubject+", context.parentObject="+context.parentObject);
792
+ if (newSubject && newSubject != context.parentObject) {
793
+ //console.log("Generating new list mapping for "+newSubject);
794
+ listMapping = {};
795
+ listMappingDifferent = true;
796
+ }
797
+
798
+ // Sequence Step 9: generate object triple
799
+ if (currentObjectResource) {
800
+ if (relAtt && inlistAtt) {
801
+ for (var i = 0; i < relAttPredicates.length; i++) {
802
+ var list = listMapping[relAttPredicates[i]];
803
+ if (!list) {
804
+ list = [];
805
+ listMapping[relAttPredicates[i]] = list;
806
+ }
807
+ list.push({
808
+ type: RDFaProcessor.objectURI,
809
+ value: currentObjectResource,
810
+ });
811
+ }
812
+ } else if (relAtt) {
813
+ for (var i = 0; i < relAttPredicates.length; i++) {
814
+ this.addTriple(current, newSubject, relAttPredicates[i], {
815
+ type: RDFaProcessor.objectURI,
816
+ value: currentObjectResource,
817
+ });
818
+ }
819
+ }
820
+ if (revAtt) {
821
+ for (var i = 0; i < revAttPredicates.length; i++) {
822
+ this.addTriple(
823
+ current,
824
+ currentObjectResource,
825
+ revAttPredicates[i],
826
+ { type: RDFaProcessor.objectURI, value: newSubject },
827
+ );
828
+ }
829
+ }
830
+ } else {
831
+ // Sequence Step 10: incomplete triples
832
+ if (newSubject && !currentObjectResource && (relAtt || revAtt)) {
833
+ currentObjectResource = this.newBlankNode();
834
+ //alert(current.tagName+": generated blank node, newSubject="+newSubject+" currentObjectResource="+currentObjectResource);
835
+ }
836
+ if (relAtt && inlistAtt) {
837
+ for (var i = 0; i < relAttPredicates.length; i++) {
838
+ var list = listMapping[relAttPredicates[i]];
839
+ if (!list) {
840
+ list = [];
841
+ listMapping[predicate] = list;
842
+ }
843
+ //console.log("Adding incomplete list for "+predicate);
844
+ incomplete.push({ predicate: relAttPredicates[i], list: list });
845
+ }
846
+ } else if (relAtt) {
847
+ for (var i = 0; i < relAttPredicates.length; i++) {
848
+ incomplete.push({ predicate: relAttPredicates[i], forward: true });
849
+ }
850
+ }
851
+ if (revAtt) {
852
+ for (var i = 0; i < revAttPredicates.length; i++) {
853
+ incomplete.push({ predicate: revAttPredicates[i], forward: false });
854
+ }
855
+ }
856
+ }
857
+
858
+ // Step 11: Current property values
859
+ if (propertyAtt) {
860
+ var datatype = null;
861
+ var content = null;
862
+ if (datatypeAtt) {
863
+ datatype =
864
+ datatypeAtt.value == ""
865
+ ? RDFaProcessor.PlainLiteralURI
866
+ : this.parseTermOrCURIEOrAbsURI(
867
+ datatypeAtt.value,
868
+ vocabulary,
869
+ context.terms,
870
+ prefixes,
871
+ base,
872
+ );
873
+ if (datetimeAtt && !contentAtt) {
874
+ content = datetimeAtt.value;
875
+ } else {
876
+ content =
877
+ datatype == RDFaProcessor.XMLLiteralURI ||
878
+ datatype == RDFaProcessor.HTMLLiteralURI
879
+ ? null
880
+ : contentAtt
881
+ ? contentAtt.value
882
+ : current.textContent;
883
+ }
884
+ } else if (contentAtt) {
885
+ datatype = RDFaProcessor.PlainLiteralURI;
886
+ content = contentAtt.value;
887
+ } else if (datetimeAtt) {
888
+ content = datetimeAtt.value;
889
+ datatype = RDFaProcessor.deriveDateTimeType(content);
890
+ if (!datatype) {
891
+ datatype = RDFaProcessor.PlainLiteralURI;
892
+ }
893
+ } else if (!relAtt && !revAtt) {
894
+ if (resourceAtt) {
895
+ content = this.parseSafeCURIEOrCURIEOrURI(
896
+ resourceAtt.value,
897
+ prefixes,
898
+ base,
899
+ );
900
+ }
901
+ if (!content && hrefAtt) {
902
+ content = this.resolveAndNormalize(base, encodeURI(hrefAtt.value));
903
+ } else if (!content && srcAtt) {
904
+ content = this.resolveAndNormalize(base, encodeURI(srcAtt.value));
905
+ }
906
+ if (content) {
907
+ datatype = RDFaProcessor.objectURI;
908
+ }
909
+ }
910
+ if (!datatype) {
911
+ if (typeofAtt && !aboutAtt) {
912
+ datatype = RDFaProcessor.objectURI;
913
+ content = typedResource;
914
+ } else {
915
+ content = current.textContent;
916
+ if (this.inHTMLMode && current.localName == "time") {
917
+ datatype = RDFaProcessor.deriveDateTimeType(content);
918
+ }
919
+ if (!datatype) {
920
+ datatype = RDFaProcessor.PlainLiteralURI;
921
+ }
922
+ }
923
+ }
924
+ var values = this.tokenize(propertyAtt.value);
925
+ for (var i = 0; i < values.length; i++) {
926
+ var predicate = this.parsePredicate(
927
+ values[i],
928
+ vocabulary,
929
+ context.terms,
930
+ prefixes,
931
+ base,
932
+ );
933
+ if (predicate) {
934
+ if (inlistAtt) {
935
+ var list = listMapping[predicate];
936
+ if (!list) {
937
+ list = [];
938
+ listMapping[predicate] = list;
939
+ }
940
+ list.push(
941
+ datatype == RDFaProcessor.XMLLiteralURI ||
942
+ datatype == RDFaProcessor.HTMLLiteralURI
943
+ ? { type: datatype, value: current.childNodes }
944
+ : {
945
+ type: datatype ? datatype : RDFaProcessor.PlainLiteralURI,
946
+ value: content,
947
+ language: language,
948
+ },
949
+ );
950
+ } else {
951
+ if (
952
+ datatype == RDFaProcessor.XMLLiteralURI ||
953
+ datatype == RDFaProcessor.HTMLLiteralURI
954
+ ) {
955
+ this.addTriple(current, newSubject, predicate, {
956
+ type: datatype,
957
+ value: current.childNodes,
958
+ });
959
+ } else {
960
+ this.addTriple(current, newSubject, predicate, {
961
+ type: datatype ? datatype : RDFaProcessor.PlainLiteralURI,
962
+ value: content,
963
+ language: language,
964
+ });
965
+ const specialPredicate = this.target.specialHtmlPredicates.find(
966
+ (sp) => sp.source === predicate,
967
+ );
968
+ if (specialPredicate) {
969
+ this.addTriple(current, newSubject, specialPredicate.target, {
970
+ type: RDFaProcessor.HTMLLiteralURI,
971
+ value: current.childNodes,
972
+ });
973
+ }
974
+ //console.log(newSubject+" "+predicate+"="+content);
975
+ }
976
+ }
977
+ }
978
+ }
979
+ }
980
+
981
+ // Sequence Step 12: complete incomplete triples with new subject
982
+ if (newSubject && !skip) {
983
+ for (var i = 0; i < context.incomplete.length; i++) {
984
+ if (context.incomplete[i].list) {
985
+ //console.log("Adding subject "+newSubject+" to list for "+context.incomplete[i].predicate);
986
+ // TODO: it is unclear what to do here
987
+ context.incomplete[i].list.push({
988
+ type: RDFaProcessor.objectURI,
989
+ value: newSubject,
990
+ });
991
+ } else if (context.incomplete[i].forward) {
992
+ //console.log(current.tagName+": completing forward triple "+context.incomplete[i].predicate+" with object="+newSubject);
993
+ this.addTriple(
994
+ current,
995
+ context.subject,
996
+ context.incomplete[i].predicate,
997
+ { type: RDFaProcessor.objectURI, value: newSubject },
998
+ );
999
+ } else {
1000
+ //console.log(current.tagName+": completing reverse triple with object="+context.subject);
1001
+ this.addTriple(
1002
+ current,
1003
+ newSubject,
1004
+ context.incomplete[i].predicate,
1005
+ { type: RDFaProcessor.objectURI, value: context.subject },
1006
+ );
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ var childContext = null;
1012
+ var listSubject = newSubject;
1013
+ if (skip) {
1014
+ // TODO: should subject be null?
1015
+ childContext = this.push(context, context.subject);
1016
+ // TODO: should the entObject be passed along? If not, then intermediary children will keep properties from being associated with incomplete triples.
1017
+ // TODO: Verify: if the current baseURI has changed and the parentObject is the parent's base URI, then the baseURI should change
1018
+ childContext.parentObject =
1019
+ removeHash(current.parentNode.baseURI) == context.parentObject
1020
+ ? removeHash(current.baseURI)
1021
+ : context.parentObject;
1022
+ childContext.incomplete = context.incomplete;
1023
+ childContext.language = language;
1024
+ childContext.prefixes = prefixes;
1025
+ childContext.vocabulary = vocabulary;
1026
+ } else {
1027
+ childContext = this.push(context, newSubject);
1028
+ childContext.parentObject = currentObjectResource
1029
+ ? currentObjectResource
1030
+ : newSubject
1031
+ ? newSubject
1032
+ : context.subject;
1033
+ childContext.prefixes = prefixes;
1034
+ childContext.incomplete = incomplete;
1035
+ if (currentObjectResource) {
1036
+ //console.log("Generating new list mapping for "+currentObjectResource);
1037
+ listSubject = currentObjectResource;
1038
+ listMapping = {};
1039
+ listMappingDifferent = true;
1040
+ }
1041
+ childContext.listMapping = listMapping;
1042
+ childContext.language = language;
1043
+ childContext.vocabulary = vocabulary;
1044
+ }
1045
+ if (listMappingDifferent) {
1046
+ //console.log("Pushing list parent "+current.localName);
1047
+ queue.unshift({
1048
+ parent: current,
1049
+ context: context,
1050
+ subject: listSubject,
1051
+ listMapping: listMapping,
1052
+ });
1053
+ }
1054
+ for (
1055
+ var child = current.lastChild;
1056
+ child;
1057
+ child = child.previousSibling
1058
+ ) {
1059
+ if (child.nodeType == Node.ELEMENT_NODE) {
1060
+ //console.log("Pushing child "+child.localName);
1061
+ queue.unshift({ current: child, context: childContext });
1062
+ }
1063
+ }
1064
+ }
1065
+
1066
+ if (this.inHTMLMode) {
1067
+ this.copyProperties();
1068
+ }
1069
+
1070
+ for (var i = 0; i < this.finishedHandlers.length; i++) {
1071
+ this.finishedHandlers[i](node);
1072
+ }
1073
+ }
1074
+
1075
+ copyProperties() { }
1076
+
1077
+ push(parent, subject) {
1078
+ return {
1079
+ parent: parent,
1080
+ subject: subject ? subject : parent ? parent.subject : null,
1081
+ parentObject: null,
1082
+ incomplete: [],
1083
+ listMapping: parent ? parent.listMapping : {},
1084
+ language: parent ? parent.language : this.language,
1085
+ prefixes: parent ? parent.prefixes : this.target.graph.prefixes,
1086
+ terms: parent ? parent.terms : this.target.graph.terms,
1087
+ vocabulary: parent ? parent.vocabulary : this.vocabulary,
1088
+ };
1089
+ }
1090
+ }
1091
+
1092
+ RDFaProcessor.XMLLiteralURI =
1093
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral";
1094
+ RDFaProcessor.HTMLLiteralURI =
1095
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML";
1096
+ RDFaProcessor.PlainLiteralURI =
1097
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral";
1098
+ RDFaProcessor.objectURI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#object";
1099
+ RDFaProcessor.typeURI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
1100
+
1101
+ RDFaProcessor.nameChar =
1102
+ "[-A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u10000-\uEFFFF.0-9\u00B7\u0300-\u036F\u203F-\u2040]";
1103
+ RDFaProcessor.nameStartChar =
1104
+ "[\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3\u4E00-\u9FA5\u3007\u3021-\u3029_]";
1105
+
1106
+ RDFaProcessor.NCNAME = new RegExp(
1107
+ "^" + RDFaProcessor.nameStartChar + RDFaProcessor.nameChar + "*$",
1108
+ );
1109
+
1110
+ RDFaProcessor.trim = function(str) {
1111
+ return str.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
1112
+ };
1113
+
1114
+ RDFaProcessor.dateTimeTypes = [
1115
+ {
1116
+ pattern:
1117
+ /-?P(?:[0-9]+Y)?(?:[0-9]+M)?(?:[0-9]+D)?(?:T(?:[0-9]+H)?(?:[0-9]+M)?(?:[0-9]+(?:\.[0-9]+)?S)?)?/,
1118
+ type: "http://www.w3.org/2001/XMLSchema#duration",
1119
+ },
1120
+ {
1121
+ pattern:
1122
+ /-?(?:[1-9][0-9][0-9][0-9]|0[1-9][0-9][0-9]|00[1-9][0-9]|000[1-9])-[0-9][0-9]-[0-9][0-9]T(?:[0-1][0-9]|2[0-4]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?(?:Z|[+\-][0-9][0-9]:[0-9][0-9])?/,
1123
+ type: "http://www.w3.org/2001/XMLSchema#dateTime",
1124
+ },
1125
+ {
1126
+ pattern:
1127
+ /-?(?:[1-9][0-9][0-9][0-9]|0[1-9][0-9][0-9]|00[1-9][0-9]|000[1-9])-[0-9][0-9]-[0-9][0-9](?:Z|[+\-][0-9][0-9]:[0-9][0-9])?/,
1128
+ type: "http://www.w3.org/2001/XMLSchema#date",
1129
+ },
1130
+ {
1131
+ pattern:
1132
+ /(?:[0-1][0-9]|2[0-4]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?(?:Z|[+\-][0-9][0-9]:[0-9][0-9])?/,
1133
+ type: "http://www.w3.org/2001/XMLSchema#time",
1134
+ },
1135
+ {
1136
+ pattern:
1137
+ /-?(?:[1-9][0-9][0-9][0-9]|0[1-9][0-9][0-9]|00[1-9][0-9]|000[1-9])-[0-9][0-9]/,
1138
+ type: "http://www.w3.org/2001/XMLSchema#gYearMonth",
1139
+ },
1140
+ {
1141
+ pattern: /-?[1-9][0-9][0-9][0-9]|0[1-9][0-9][0-9]|00[1-9][0-9]|000[1-9]/,
1142
+ type: "http://www.w3.org/2001/XMLSchema#gYear",
1143
+ },
1144
+ ];
1145
+
1146
+ RDFaProcessor.deriveDateTimeType = function(value) {
1147
+ for (var i = 0; i < RDFaProcessor.dateTimeTypes.length; i++) {
1148
+ //console.log("Checking "+value+" against "+RDFaProcessor.dateTimeTypes[i].type);
1149
+ var matched = RDFaProcessor.dateTimeTypes[i].pattern.exec(value);
1150
+ if (matched && matched[0].length == value.length) {
1151
+ //console.log("Matched!");
1152
+ return RDFaProcessor.dateTimeTypes[i].type;
1153
+ }
1154
+ }
1155
+ return null;
1156
+ };