forked from wdw21/songbook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
save.js
104 lines (89 loc) · 3.28 KB
/
save.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import {loadXMLDoc, nbsp} from './utils.js';
function escapeText(unsafe) {
return unsafe
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, """)
.replace(/'/g, "'");
}
function escapeAttrib(unsafe) {
return escapeText(unsafe)
}
function serializeElement(indent, elem, sep) { // returns { out: ' ', breakClosing: true/false}
if (elem.nodeName=='#text'){
return { out: escapeText(elem.parentNode.nodeName != 'row' ? elem.nodeValue.trim() : elem.nodeValue), breakClosing: false};
} else {
let attrs=''
for (const a of elem.attributes) {
if (a.nodeName != 'xmlns:xhtml') {
attrs = `${attrs} ${a.nodeName}="${escapeAttrib(a.nodeValue)}"`
}
}
if (elem.nodeName=='song' && !attrs.includes('xmlns:xsi=')) {
attrs=` xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"` + attrs
}
if (elem.nodeName=='song' && !attrs.includes('xmlns=\"'+elem.namespaceURI)) {
attrs=` xmlns="${elem.namespaceURI}"` + attrs
}
if (elem.nodeName==='ch') {
return { out: `<${elem.nodeName}${attrs}/>`, breakClosing: false }
} else {
const {out, breakClosing} = serializeElements(indent + sep, elem.childNodes, sep)
if (out!="") {
return { out: `\n${indent}<${elem.nodeName}${attrs}>${out}${breakClosing ? "\n"+indent : ""}</${elem.nodeName}>`, breakClosing: true }
} else {
return { out: `\n${indent}<${elem.nodeName}${attrs}/>`, breakClosing: true }
}
}
}
}
function serializeElements(indent, children, sep) {
let o="";
let br = false;
for (let child of children) {
const {out, breakClosing} = serializeElement(indent, child, sep)
o += out;
br |= breakClosing
}
return {out: o, breakClosing: br};
}
function serializeDocument(doc, sep) {
return `<?xml version="1.0" encoding="utf-8"?>${serializeElements("", doc.childNodes, sep).out}`
}
export function Serialize(songeditor) {
let xsltProcessor = new XSLTProcessor()
let xslt = loadXMLDoc('./save.xslt');
console.log(xslt);
xsltProcessor.importStylesheet(xslt);
const src = document.implementation.createDocument("", "", null);
const clonedNode = src.importNode(songeditor, true);
src.appendChild(clonedNode);
let resultDocument = xsltProcessor.transformToDocument(src);
if (!resultDocument) {
alert("XSLT transformation failed")
}
// Does not work well on Mozilla:
// https://stackoverflow.com/questions/51989864/undefined-undefined-error-when-calling-xsltprocessor-prototype-importstylesheet
//new XMLSerializer().serializeToString(resultDocument);;
let txt=serializeDocument(resultDocument, songeditor.tabs ? "\t" : " ")
txt = txt.replaceAll(nbsp," ") + "\n";
if (songeditor.shadow.getElementById("lastSerialized")) {
songeditor.shadow.getElementById("lastSerialized").innerText=txt;
}
return txt;
}
export function Save(songeditor) {
let txt = Serialize(songeditor);
let download = window.document.createElement('a');
download.id="download";
download.text="[download]";
let title = songeditor.getAttribute("title");
if (!title || title.trim()==='') {
title='song';
}
let url=window.URL.createObjectURL(new Blob([txt]), {type: 'text/xml'});
download.href=url;
download.download=title+".xml";
download.click();
}