@lblod/graph-rdfa-processor 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ };