CETEIcean 1.7.2 → 1.8.0-beta.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 +14 -0
- package/package.json +10 -3
- package/src/CETEI.js +61 -67
- package/src/defaultBehaviors.js +17 -12
- package/src/utilities.js +70 -11
- package/test/externalgetTest.html +0 -1
- package/test/nodeTest.js +24 -0
package/README.md
CHANGED
@@ -52,6 +52,20 @@ new CETEI({
|
|
52
52
|
})
|
53
53
|
```
|
54
54
|
|
55
|
+
### Usage with Node
|
56
|
+
|
57
|
+
CETEIcean can be used on the server by providing a DOM implementation, such as [JSDOM](https://github.com/jsdom/jsdom). You can pass a document object as an option when instantiating CETEIcean.
|
58
|
+
|
59
|
+
```js
|
60
|
+
import { JSDOM } from 'jsdom';
|
61
|
+
import CETEI from 'CETEIcean';
|
62
|
+
|
63
|
+
const jdom = new JSDOM(`<TEI xmlns="http://www.tei-c.org/ns/1.0" />`, {contentType: 'text/xml'});
|
64
|
+
new CETEI({
|
65
|
+
documentObject: jdom.window.document
|
66
|
+
})
|
67
|
+
```
|
68
|
+
|
55
69
|
### Other methods
|
56
70
|
|
57
71
|
#### getHTML5( url, callback, perElementFn )
|
package/package.json
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
{
|
2
2
|
"name": "CETEIcean",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.8.0-beta.1",
|
4
4
|
"description": "JavaScript library to load a TEI XML document and register it as HTML5 custom elements.",
|
5
5
|
"main": "src/CETEI.js",
|
6
|
+
"type": "module",
|
6
7
|
"keywords": [
|
7
8
|
"TEI",
|
8
9
|
"XML",
|
@@ -15,20 +16,26 @@
|
|
15
16
|
"type": "git",
|
16
17
|
"url": "https://github.com/TEIC/CETEIcean.git"
|
17
18
|
},
|
19
|
+
"exports": {
|
20
|
+
".": "./src/CETEI.js",
|
21
|
+
"./utilities.js": "./src/utilities.js"
|
22
|
+
},
|
18
23
|
"devDependencies": {
|
19
24
|
"@babel/core": "^7.15.5",
|
20
25
|
"@babel/preset-env": "7.15.6",
|
21
26
|
"@rollup/plugin-babel": "^5.3.0",
|
22
27
|
"babel-preset-env": "^1.7.0",
|
23
28
|
"http-server": "^14.1.1",
|
29
|
+
"jsdom": "^21.1.0",
|
24
30
|
"onchange": "^6.1.1",
|
25
31
|
"rollup": "^2.57.0",
|
26
32
|
"rollup-plugin-terser": "^7.0.2",
|
27
33
|
"terser": "^5.14.2"
|
28
34
|
},
|
29
35
|
"scripts": {
|
30
|
-
"build": "rollup -c rollup.config.js",
|
36
|
+
"build": "npm test && rollup -c rollup.config.js",
|
31
37
|
"build:tutorial": "npm run build && cp dist/CETEI.js tutorial/js/CETEI.js",
|
32
|
-
"dev": "npm run build && http-server -p 8888 & onchange src -- npm run build"
|
38
|
+
"dev": "npm run build && http-server -p 8888 & onchange src -- npm run build",
|
39
|
+
"test": "node test/nodeTest.js"
|
33
40
|
}
|
34
41
|
}
|
package/src/CETEI.js
CHANGED
@@ -7,6 +7,17 @@ class CETEI {
|
|
7
7
|
constructor(options){
|
8
8
|
this.options = options ? options : {}
|
9
9
|
|
10
|
+
// Set a local reference to the Document object
|
11
|
+
// Determine document in this order of preference: options, window, global
|
12
|
+
this.document = this.options.documentObject ? this.options.documentObject : undefined
|
13
|
+
if (this.document === undefined) {
|
14
|
+
if (typeof window !== 'undefined' && window.document) {
|
15
|
+
this.document = window.document
|
16
|
+
} else if (typeof global !== 'undefined' && global.document) {
|
17
|
+
this.document = global.document
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
10
21
|
// Bind methods
|
11
22
|
this.addBehaviors = addBehaviors.bind(this);
|
12
23
|
this.addBehavior = addBehavior.bind(this);
|
@@ -100,12 +111,7 @@ class CETEI {
|
|
100
111
|
return this.domToHTML5(this.XML_dom, callback, perElementFn);
|
101
112
|
}
|
102
113
|
|
103
|
-
|
104
|
-
Converts the supplied XML DOM into HTML5 Custom Elements. If a callback
|
105
|
-
function is supplied, calls it on the result.
|
106
|
-
*/
|
107
|
-
domToHTML5(XML_dom, callback, perElementFn){
|
108
|
-
|
114
|
+
preprocess(XML_dom, callback, perElementFn) {
|
109
115
|
this.els = learnElementNames(XML_dom, this.namespaces);
|
110
116
|
|
111
117
|
let convertEl = (el) => {
|
@@ -114,9 +120,9 @@ class CETEI {
|
|
114
120
|
let newElement;
|
115
121
|
if (this.namespaces.has(el.namespaceURI ? el.namespaceURI : "")) {
|
116
122
|
let prefix = this.namespaces.get(el.namespaceURI ? el.namespaceURI : "");
|
117
|
-
newElement = document.createElement(`${prefix}-${el.localName}`);
|
123
|
+
newElement = this.document.createElement(`${prefix}-${el.localName}`);
|
118
124
|
} else {
|
119
|
-
newElement = document.importNode(el, false);
|
125
|
+
newElement = this.document.importNode(el, false);
|
120
126
|
}
|
121
127
|
// Copy attributes; @xmlns, @xml:id, @xml:lang, and
|
122
128
|
// @rendition get special handling.
|
@@ -148,16 +154,18 @@ class CETEI {
|
|
148
154
|
}
|
149
155
|
// <head> elements need to know their level
|
150
156
|
if (el.localName == "head") {
|
157
|
+
// 1 is XPathResult.NUMBER_TYPE
|
151
158
|
let level = XML_dom.evaluate("count(ancestor::*[tei:head])", el, function(ns) {
|
152
159
|
if (ns == "tei") return "http://www.tei-c.org/ns/1.0";
|
153
|
-
},
|
160
|
+
}, 1, null);
|
154
161
|
newElement.setAttribute("data-level", level.numberValue);
|
155
162
|
}
|
156
163
|
// Turn <rendition scheme="css"> elements into HTML styles
|
157
164
|
if (el.localName == "tagsDecl") {
|
158
|
-
let style = document.createElement("style");
|
165
|
+
let style = this.document.createElement("style");
|
159
166
|
for (let node of Array.from(el.childNodes)){
|
160
|
-
|
167
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
168
|
+
if (node.nodeType == 1 && node.localName == "rendition" && node.getAttribute("scheme") == "css") {
|
161
169
|
let rule = "";
|
162
170
|
if (node.hasAttribute("selector")) {
|
163
171
|
//rewrite element names in selectors
|
@@ -168,7 +176,7 @@ class CETEI {
|
|
168
176
|
rule += node.textContent;
|
169
177
|
}
|
170
178
|
rule += "\n}\n";
|
171
|
-
style.appendChild(document.createTextNode(rule));
|
179
|
+
style.appendChild(this.document.createTextNode(rule));
|
172
180
|
}
|
173
181
|
}
|
174
182
|
if (style.childNodes.length > 0) {
|
@@ -185,7 +193,8 @@ class CETEI {
|
|
185
193
|
};
|
186
194
|
}
|
187
195
|
for (let node of Array.from(el.childNodes)) {
|
188
|
-
|
196
|
+
// Node.ELEMENT_NODE
|
197
|
+
if (node.nodeType == 1 ) {
|
189
198
|
newElement.appendChild(convertEl(node));
|
190
199
|
}
|
191
200
|
else {
|
@@ -201,6 +210,27 @@ class CETEI {
|
|
201
210
|
this.dom = convertEl(XML_dom.documentElement);
|
202
211
|
this.utilities.dom = this.dom;
|
203
212
|
|
213
|
+
if (callback) {
|
214
|
+
callback(this.dom, this);
|
215
|
+
if (window) {
|
216
|
+
window.dispatchEvent(ceteiceanLoad);
|
217
|
+
}
|
218
|
+
} else {
|
219
|
+
if (typeof window !== 'undefined') {
|
220
|
+
window.dispatchEvent(ceteiceanLoad);
|
221
|
+
}
|
222
|
+
return this.dom;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
/*
|
227
|
+
Converts the supplied XML DOM into HTML5 Custom Elements. If a callback
|
228
|
+
function is supplied, calls it on the result.
|
229
|
+
*/
|
230
|
+
domToHTML5(XML_dom, callback, perElementFn){
|
231
|
+
|
232
|
+
this.preprocess(XML_dom, null, perElementFn);
|
233
|
+
|
204
234
|
this.applyBehaviors();
|
205
235
|
this.done = true;
|
206
236
|
if (callback) {
|
@@ -209,7 +239,7 @@ class CETEI {
|
|
209
239
|
window.dispatchEvent(ceteiceanLoad);
|
210
240
|
}
|
211
241
|
} else {
|
212
|
-
if (window) {
|
242
|
+
if (typeof window !== 'undefined') {
|
213
243
|
window.dispatchEvent(ceteiceanLoad);
|
214
244
|
}
|
215
245
|
return this.dom;
|
@@ -223,7 +253,7 @@ class CETEI {
|
|
223
253
|
c.processPage();
|
224
254
|
*/
|
225
255
|
processPage() {
|
226
|
-
this.els = learnCustomElementNames(document);
|
256
|
+
this.els = learnCustomElementNames(this.document);
|
227
257
|
this.applyBehaviors();
|
228
258
|
}
|
229
259
|
|
@@ -348,7 +378,7 @@ getFallback(behaviors, fn) {
|
|
348
378
|
if (behaviors[fn] instanceof Function) {
|
349
379
|
return behaviors[fn];
|
350
380
|
} else {
|
351
|
-
return decorator(behaviors[fn]);
|
381
|
+
return this.decorator(behaviors[fn]);
|
352
382
|
}
|
353
383
|
}
|
354
384
|
}
|
@@ -368,9 +398,10 @@ getHandler(behaviors, fn) {
|
|
368
398
|
}
|
369
399
|
|
370
400
|
insert(elt, strings) {
|
371
|
-
let span = document.createElement("span");
|
401
|
+
let span = this.document.createElement("span");
|
372
402
|
for (let node of Array.from(elt.childNodes)) {
|
373
|
-
|
403
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
404
|
+
if (node.nodeType === 1 && !node.hasAttribute("data-processed")) {
|
374
405
|
this.processElement(node);
|
375
406
|
}
|
376
407
|
}
|
@@ -402,21 +433,13 @@ processElement(elt) {
|
|
402
433
|
}
|
403
434
|
}
|
404
435
|
for (let node of Array.from(elt.childNodes)) {
|
405
|
-
|
436
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
437
|
+
if (node.nodeType === 1) {
|
406
438
|
this.processElement(node);
|
407
439
|
}
|
408
440
|
}
|
409
441
|
}
|
410
442
|
|
411
|
-
// Given a qualified name (e.g. tei:text), return the element name
|
412
|
-
tagName(name) {
|
413
|
-
if (name.includes(":"), 1) {
|
414
|
-
return name.replace(/:/,"-").toLowerCase();
|
415
|
-
} else {
|
416
|
-
return "ceteicean-" + name.toLowerCase();
|
417
|
-
}
|
418
|
-
}
|
419
|
-
|
420
443
|
template(str, elt) {
|
421
444
|
let result = str;
|
422
445
|
if (str.search(/\$(\w*)(@([a-zA-Z:]+))/ )) {
|
@@ -439,7 +462,7 @@ template(str, elt) {
|
|
439
462
|
|
440
463
|
// Define or apply behaviors for the document
|
441
464
|
applyBehaviors() {
|
442
|
-
if (window.customElements) {
|
465
|
+
if (typeof window !== 'undefined' && window.customElements) {
|
443
466
|
this.define.call(this, this.els);
|
444
467
|
} else {
|
445
468
|
this.fallback.call(this, this.els);
|
@@ -453,37 +476,8 @@ applyBehaviors() {
|
|
453
476
|
*/
|
454
477
|
define(names) {
|
455
478
|
for (let name of names) {
|
456
|
-
|
457
|
-
|
458
|
-
window.customElements.define(this.tagName(name), class extends HTMLElement {
|
459
|
-
constructor() {
|
460
|
-
super();
|
461
|
-
if (!this.matches(":defined")) { // "Upgraded" undefined elements can have attributes & children; new elements can't
|
462
|
-
if (fn) {
|
463
|
-
fn.call(this);
|
464
|
-
}
|
465
|
-
// We don't want to double-process elements, so add a flag
|
466
|
-
this.setAttribute("data-processed", "");
|
467
|
-
}
|
468
|
-
}
|
469
|
-
// Process new elements when they are connected to the browser DOM
|
470
|
-
connectedCallback() {
|
471
|
-
if (!this.hasAttribute("data-processed")) {
|
472
|
-
if (fn) {
|
473
|
-
fn.call(this);
|
474
|
-
}
|
475
|
-
this.setAttribute("data-processed", "");
|
476
|
-
}
|
477
|
-
};
|
478
|
-
});
|
479
|
-
} catch (error) {
|
480
|
-
// When using the same CETEIcean instance for multiple TEI files, this error becomes very common.
|
481
|
-
// It's muted by default unless the debug option is set.
|
482
|
-
if (this.debug) {
|
483
|
-
console.log(this.tagName(name) + " couldn't be registered or is already registered.");
|
484
|
-
console.log(error);
|
485
|
-
}
|
486
|
-
}
|
479
|
+
const fn = this.getHandler(this.behaviors, name);
|
480
|
+
utilities.defineCustomElement(name, fn, this.debug);
|
487
481
|
}
|
488
482
|
}
|
489
483
|
|
@@ -496,15 +490,15 @@ define(names) {
|
|
496
490
|
*/
|
497
491
|
fallback(names) {
|
498
492
|
for (let name of names) {
|
499
|
-
let fn = getFallback(this.behaviors, name);
|
493
|
+
let fn = this.getFallback(this.behaviors, name);
|
500
494
|
if (fn) {
|
501
495
|
for (let elt of Array.from((
|
502
496
|
this.dom && !this.done
|
503
497
|
? this.dom
|
504
|
-
: document
|
505
|
-
).getElementsByTagName(tagName(name)))) {
|
498
|
+
: this.document
|
499
|
+
).getElementsByTagName(utilities.tagName(name)))) {
|
506
500
|
if (!elt.hasAttribute("data-processed")) {
|
507
|
-
append(fn, elt);
|
501
|
+
this.append(fn, elt);
|
508
502
|
}
|
509
503
|
}
|
510
504
|
}
|
@@ -530,7 +524,7 @@ fallback(names) {
|
|
530
524
|
}
|
531
525
|
} else {
|
532
526
|
setTimeout(function() {
|
533
|
-
let h = document.querySelector(window.decodeURI(window.location.hash));
|
527
|
+
let h = this.document.querySelector(window.decodeURI(window.location.hash));
|
534
528
|
if (h) {
|
535
529
|
h.scrollIntoView();
|
536
530
|
}
|
@@ -541,7 +535,7 @@ fallback(names) {
|
|
541
535
|
}
|
542
536
|
|
543
537
|
try {
|
544
|
-
if (window) {
|
538
|
+
if (typeof window !== 'undefined') {
|
545
539
|
window.CETEI = CETEI;
|
546
540
|
window.addEventListener("beforeunload", CETEI.savePosition);
|
547
541
|
var ceteiceanLoad = new Event("ceteiceanload");
|
@@ -551,4 +545,4 @@ try {
|
|
551
545
|
console.log(e);
|
552
546
|
}
|
553
547
|
|
554
|
-
export default CETEI
|
548
|
+
export default CETEI;
|
package/src/defaultBehaviors.js
CHANGED
@@ -27,16 +27,18 @@ export default {
|
|
27
27
|
"list": [
|
28
28
|
// will only run on a list where @type="gloss"
|
29
29
|
["[type=gloss]", function(elt) {
|
30
|
-
|
30
|
+
const doc = elt.ownerDocument;
|
31
|
+
let dl = doc.createElement("dl");
|
31
32
|
for (let child of Array.from(elt.children)) {
|
32
|
-
|
33
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
34
|
+
if (child.nodeType == 1) {
|
33
35
|
if (child.localName == "tei-label") {
|
34
|
-
let dt =
|
36
|
+
let dt = doc.createElement("dt");
|
35
37
|
dt.innerHTML = child.innerHTML;
|
36
38
|
dl.appendChild(dt);
|
37
39
|
}
|
38
40
|
if (child.localName == "tei-item") {
|
39
|
-
let dd =
|
41
|
+
let dd = doc.createElement("dd");
|
40
42
|
dd.innerHTML = child.innerHTML;
|
41
43
|
dl.appendChild(dd);
|
42
44
|
}
|
@@ -48,25 +50,26 @@ export default {
|
|
48
50
|
"note": [
|
49
51
|
// Make endnotes
|
50
52
|
["[place=end]", function(elt){
|
53
|
+
const doc = elt.ownerDocument;
|
51
54
|
if (!this.noteIndex){
|
52
55
|
this["noteIndex"] = 1;
|
53
56
|
} else {
|
54
57
|
this.noteIndex++;
|
55
58
|
}
|
56
59
|
let id = "_note_" + this.noteIndex;
|
57
|
-
let link =
|
60
|
+
let link = doc.createElement("a");
|
58
61
|
link.setAttribute("id", "src" + id);
|
59
62
|
link.setAttribute("href", "#" + id);
|
60
63
|
link.innerHTML = this.noteIndex;
|
61
|
-
let content =
|
64
|
+
let content = doc.createElement("sup");
|
62
65
|
content.appendChild(link);
|
63
|
-
let notes =
|
66
|
+
let notes = doc.querySelector("ol.notes");
|
64
67
|
if (!notes) {
|
65
|
-
notes =
|
68
|
+
notes = doc.createElement("ol");
|
66
69
|
notes.setAttribute("class", "notes");
|
67
70
|
this.dom.appendChild(notes);
|
68
71
|
}
|
69
|
-
let note =
|
72
|
+
let note = doc.createElement("li");
|
70
73
|
note.id = id;
|
71
74
|
note.innerHTML = elt.innerHTML
|
72
75
|
notes.appendChild(note);
|
@@ -79,15 +82,17 @@ export default {
|
|
79
82
|
},
|
80
83
|
"title": [
|
81
84
|
["tei-titlestmt>tei-title", function(elt) {
|
82
|
-
|
85
|
+
const doc = elt.ownerDocument;
|
86
|
+
let title = doc.createElement("title");
|
83
87
|
title.innerHTML = elt.innerText;
|
84
|
-
|
88
|
+
doc.querySelector("head").appendChild(title);
|
85
89
|
}]
|
86
90
|
],
|
87
91
|
},
|
88
92
|
"teieg": {
|
89
93
|
"egXML": function(elt) {
|
90
|
-
|
94
|
+
const doc = elt.ownerDocument;
|
95
|
+
let pre = doc.createElement("pre");
|
91
96
|
let content = this.serialize(elt, true).replace(/</g, "<");
|
92
97
|
let ws = content.match(/^[\t ]+/);
|
93
98
|
if (ws) {
|
package/src/utilities.js
CHANGED
@@ -16,8 +16,12 @@ export function getOrdinality(elt, name) {
|
|
16
16
|
out child elements introduced by CETEIcean.
|
17
17
|
*/
|
18
18
|
export function copyAndReset(node) {
|
19
|
+
const doc = node.ownerDocument;
|
19
20
|
let clone = (n) => {
|
20
|
-
|
21
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
22
|
+
let result = n.nodeType === 1
|
23
|
+
? doc.createElement(n.nodeName)
|
24
|
+
: n.cloneNode(true);
|
21
25
|
if (n.attributes) {
|
22
26
|
for (let att of Array.from(n.attributes)) {
|
23
27
|
if (att.name !== "data-processed") {
|
@@ -26,12 +30,14 @@ export function copyAndReset(node) {
|
|
26
30
|
}
|
27
31
|
}
|
28
32
|
for (let nd of Array.from(n.childNodes)){
|
29
|
-
|
33
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
34
|
+
if (nd.nodeType == 1) {
|
30
35
|
if (!n.hasAttribute("data-empty")) {
|
31
36
|
if (nd.hasAttribute("data-original")) {
|
32
37
|
for (let childNode of Array.from(nd.childNodes)) {
|
33
38
|
let child = result.appendChild(clone(childNode));
|
34
|
-
|
39
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
40
|
+
if (child.nodeType === 1 && child.hasAttribute("data-origid")) {
|
35
41
|
child.setAttribute("id", child.getAttribute("data-origid"));
|
36
42
|
child.removeAttribute("data-origid");
|
37
43
|
}
|
@@ -64,14 +70,16 @@ export function first(urls) {
|
|
64
70
|
with display set to "none".
|
65
71
|
*/
|
66
72
|
export function hideContent(elt, rewriteIds = true) {
|
73
|
+
const doc = elt.ownerDocument;
|
67
74
|
if (elt.childNodes.length > 0) {
|
68
|
-
let hidden =
|
75
|
+
let hidden = doc.createElement("span");
|
69
76
|
elt.appendChild(hidden);
|
70
77
|
hidden.setAttribute("hidden", "");
|
71
78
|
hidden.setAttribute("data-original", "");
|
72
79
|
for (let node of Array.from(elt.childNodes)) {
|
73
80
|
if (node !== hidden) {
|
74
|
-
|
81
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
82
|
+
if (node.nodeType === 1) {
|
75
83
|
node.setAttribute("data-processed", "");
|
76
84
|
for (let e of node.querySelectorAll("*")) {
|
77
85
|
e.setAttribute("data-processed", "");
|
@@ -148,7 +156,8 @@ export function serialize(el, stripElt, ws) {
|
|
148
156
|
let ignorable = (txt) => {
|
149
157
|
return !(/[^\t\n\r ]/.test(txt));
|
150
158
|
}
|
151
|
-
|
159
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
160
|
+
if (!stripElt && el.nodeType == 1) {
|
152
161
|
if ((typeof ws === "string") && ws !== "") {
|
153
162
|
str += "\n" + ws + "<";
|
154
163
|
} else {
|
@@ -173,18 +182,21 @@ export function serialize(el, stripElt, ws) {
|
|
173
182
|
}
|
174
183
|
//TODO: Be smarter about skipping generated content with hidden original
|
175
184
|
for (let node of Array.from(el.childNodes)) {
|
185
|
+
// nodeType 1 is Node.ELEMENT_NODE
|
186
|
+
// nodeType 7 is Node.PROCESSING_INSTRUCTION_NODE
|
187
|
+
// nodeType 8 is Node.COMMENT_NODE
|
176
188
|
switch (node.nodeType) {
|
177
|
-
case
|
189
|
+
case 1:
|
178
190
|
if (typeof ws === "string") {
|
179
|
-
str +=
|
191
|
+
str += serialize(node, false, ws + " ");
|
180
192
|
} else {
|
181
|
-
str +=
|
193
|
+
str += serialize(node, false, ws);
|
182
194
|
}
|
183
195
|
break;
|
184
|
-
case
|
196
|
+
case 7:
|
185
197
|
str += "<?" + node.nodeValue + "?>";
|
186
198
|
break;
|
187
|
-
case
|
199
|
+
case 8:
|
188
200
|
str += "<!--" + node.nodeValue + "-->";
|
189
201
|
break;
|
190
202
|
default:
|
@@ -214,3 +226,50 @@ export function unEscapeEntities(str) {
|
|
214
226
|
.replace(/'/, "'")
|
215
227
|
.replace(/&/, "&");
|
216
228
|
}
|
229
|
+
|
230
|
+
// Given a qualified name (e.g. tei:text), return the element name
|
231
|
+
export function tagName(name) {
|
232
|
+
if (name.includes(":"), 1) {
|
233
|
+
return name.replace(/:/,"-").toLowerCase();
|
234
|
+
} else {
|
235
|
+
return "ceteicean-" + name.toLowerCase();
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
export function defineCustomElement(name, behavior = null, debug = false) {
|
240
|
+
/*
|
241
|
+
Registers the list of elements provided with the browser.
|
242
|
+
Called by makeHTML5(), but can be called independently if, for example,
|
243
|
+
you've created Custom Elements via an XSLT transformation instead.
|
244
|
+
*/
|
245
|
+
try {
|
246
|
+
window.customElements.define(tagName(name), class extends HTMLElement {
|
247
|
+
constructor() {
|
248
|
+
super();
|
249
|
+
if (!this.matches(":defined")) { // "Upgraded" undefined elements can have attributes & children; new elements can't
|
250
|
+
if (behavior) {
|
251
|
+
behavior.call(this);
|
252
|
+
}
|
253
|
+
// We don't want to double-process elements, so add a flag
|
254
|
+
this.setAttribute("data-processed", "");
|
255
|
+
}
|
256
|
+
}
|
257
|
+
// Process new elements when they are connected to the browser DOM
|
258
|
+
connectedCallback() {
|
259
|
+
if (!this.hasAttribute("data-processed")) {
|
260
|
+
if (behavior) {
|
261
|
+
behavior.call(this);
|
262
|
+
}
|
263
|
+
this.setAttribute("data-processed", "");
|
264
|
+
}
|
265
|
+
};
|
266
|
+
});
|
267
|
+
} catch (error) {
|
268
|
+
// When using the same CETEIcean instance for multiple TEI files, this error becomes very common.
|
269
|
+
// It's muted by default unless the debug option is set.
|
270
|
+
if (debug) {
|
271
|
+
console.log(tagName(name) + " couldn't be registered or is already registered.");
|
272
|
+
console.log(error);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
}
|
package/test/nodeTest.js
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
import { JSDOM } from 'jsdom';
|
2
|
+
import CETEI from '../src/CETEI.js';
|
3
|
+
|
4
|
+
const jdom = new JSDOM(`<TEI xmlns="http://www.tei-c.org/ns/1.0"><div>test</div></TEI>`, {contentType: 'text/xml'});
|
5
|
+
const teiDoc = jdom.window.document;
|
6
|
+
|
7
|
+
const test = () => {
|
8
|
+
console.log('Get HTML5 from JSDOM');
|
9
|
+
const processedTEI = (new CETEI({documentObject: teiDoc})).domToHTML5(teiDoc);
|
10
|
+
if (processedTEI) {
|
11
|
+
console.log(' > pass');
|
12
|
+
} else {
|
13
|
+
console.log(' > fail');
|
14
|
+
return;
|
15
|
+
}
|
16
|
+
console.log('Check content');
|
17
|
+
if (processedTEI.querySelector("tei-div")) {
|
18
|
+
console.log(' > pass');
|
19
|
+
} else {
|
20
|
+
console.log(' > fail');
|
21
|
+
}
|
22
|
+
};
|
23
|
+
|
24
|
+
test();
|