-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add DOM Parser #2
base: task/typedefs
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,9 +24,9 @@ | |
* POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
import sax from "sax"; | ||
import { reportError, reportFatal, reportWarning } from "./error.js"; | ||
import { ns_ebutts, ns_ittp, ns_itts, ns_tt, ns_ttp, ns_tts } from "./names.js"; | ||
import { createDOMParser } from "./parser.js"; | ||
import { byName, byQName } from "./styles.js"; | ||
import { ComputedLength, hasOwnProperty, parseLength } from "./utils.js"; | ||
|
||
|
@@ -36,10 +36,8 @@ import { ComputedLength, hasOwnProperty, parseLength } from "./utils.js"; | |
|
||
/** | ||
* @typedef {import("./error").ErrorHandler} ErrorHandler | ||
*/ | ||
|
||
/** | ||
* @typedef {sax.Tag | sax.QualifiedTag} Node | ||
* @typedef {import("./parser").Node} Node | ||
* @typedef {import("./parser").Parser} Parser | ||
*/ | ||
|
||
/** | ||
|
@@ -80,18 +78,18 @@ import { ComputedLength, hasOwnProperty, parseLength } from "./utils.js"; | |
* @param {string} xmlstring XML document | ||
* @param {ErrorHandler} errorHandler Error callback | ||
* @param {?MetadataHandler} metadataHandler Callback for <Metadata> elements | ||
* @param {?Parser} parser XML parser | ||
* @returns {?TT} Opaque in-memory representation of an IMSC1 document | ||
*/ | ||
|
||
export function fromXML(xmlstring, errorHandler, metadataHandler) { | ||
const p = sax.parser(true, { xmlns: true }); | ||
export function fromXML(xmlstring, errorHandler, metadataHandler, parser = createDOMParser()) { | ||
Comment on lines
+81
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allow the parser to be passed in as long as it adheres to the interface. The also changes the default to the |
||
const estack = []; | ||
const xmllangstack = []; | ||
const xmlspacestack = []; | ||
let metadata_depth = 0; | ||
let doc = null; | ||
|
||
p.onclosetag = function () { | ||
parser.onclosetag = function () { | ||
|
||
if (estack[0] instanceof Region) { | ||
|
||
|
@@ -191,7 +189,7 @@ export function fromXML(xmlstring, errorHandler, metadataHandler) { | |
estack.shift(); | ||
}; | ||
|
||
p.ontext = function (str) { | ||
parser.ontext = function (str) { | ||
|
||
if (estack[0] === undefined) { | ||
|
||
|
@@ -234,7 +232,7 @@ export function fromXML(xmlstring, errorHandler, metadataHandler) { | |
|
||
}; | ||
|
||
p.onopentag = function (node) { | ||
parser.onopentag = function (node) { | ||
|
||
// maintain the xml:space stack | ||
|
||
|
@@ -604,7 +602,7 @@ export function fromXML(xmlstring, errorHandler, metadataHandler) { | |
|
||
// parse the document | ||
|
||
p.write(xmlstring).close(); | ||
parser.write(xmlstring).close(); | ||
|
||
// all referential styling has been flatten, so delete styles | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import sax from "sax"; | ||
|
||
/** | ||
* @typedef {sax.Tag | sax.QualifiedTag} Node | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} Parser | ||
* @property {(xml: string) => Parser} write | ||
* @property {() => Parser} close | ||
* @property {(node: Node) => void} onopentag | ||
* @property {(text: string) => void} ontext | ||
* @property {() => void} onclosetag | ||
*/ | ||
|
||
export class XMLParser { | ||
Comment on lines
+7
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid a massive refactor of |
||
/** | ||
* @param {Element} element | ||
* @returns {SAX} | ||
*/ | ||
static toNode(element) { | ||
const attrs = element.attributes; | ||
const node = XMLParser.toNS(element); | ||
node.attributes = {}; | ||
|
||
for (let i = 0, len = attrs.length; i < len; i++) { | ||
const attr = attrs[i]; | ||
node.attributes[attr.name] = XMLParser.toNS(attr); | ||
} | ||
|
||
return node; | ||
} | ||
|
||
static toNS(node) { | ||
return { | ||
name: node.nodeName, | ||
prefix: node.prefix, | ||
local: node.localName, | ||
uri: node.namespaceURI, | ||
value: node.value, | ||
}; | ||
} | ||
|
||
onopentag = (node) => { console.log(node); } | ||
ontext = (str) => { console.log(str); } | ||
onclosetag = () => { } | ||
|
||
write(xmlstring) { | ||
const parser = new DOMParser(); | ||
const doc = parser.parseFromString(xmlstring, "application/xml"); | ||
const errorNode = doc.querySelector("parsererror"); | ||
|
||
if (errorNode) { | ||
throw new Error("XML parsing error: " + errorNode.textContent); | ||
} | ||
|
||
this.process(doc.firstChild); | ||
|
||
return this; | ||
} | ||
|
||
process(element) { | ||
const node = XMLParser.toNode(element); | ||
this.onopentag(node); | ||
|
||
const children = element.childNodes; | ||
|
||
for (let i = 0, len = children.length; i < len; i++) { | ||
const child = children[i]; | ||
|
||
if (child.nodeType === Node.TEXT_NODE) { | ||
this.ontext(child.textContent); | ||
} else if (child.nodeType === Node.ELEMENT_NODE) { | ||
this.process(child); | ||
} | ||
} | ||
|
||
this.onclosetag(); | ||
} | ||
|
||
close() { | ||
return this; | ||
} | ||
} | ||
|
||
/** | ||
* @returns {Parser} | ||
*/ | ||
export function createDOMParser() { | ||
return new XMLParser(); | ||
} | ||
|
||
/** | ||
* @returns {Parser} | ||
*/ | ||
export function createSAXParser() { | ||
return sax.parser(true, { xmlns: true }); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,10 +20,14 @@ | |
<div id="main"> | ||
|
||
<section id="start"> | ||
<button id="start-rendering" onclick="generateRenders('imsc-tests/imsc1')">Generate IMSC 1 reference | ||
renders</button> | ||
<button id="start-rendering" onclick="generateRenders('imsc-tests/imsc1_1')">Generate IMSC 1.1 reference | ||
renders</button> | ||
<button onclick="generateRenders('imsc-tests/imsc1', true)">Generate IMSC 1 reference | ||
renders - SAX</button> | ||
<button onclick="generateRenders('imsc-tests/imsc1_1', true)">Generate IMSC 1.1 reference | ||
renders - SAX</button> | ||
<button onclick="generateRenders('imsc-tests/imsc1', false)">Generate IMSC 1 reference | ||
renders - DOM</button> | ||
<button onclick="generateRenders('imsc-tests/imsc1_1', false)">Generate IMSC 1.1 reference | ||
renders- DOM</button> | ||
Comment on lines
+23
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added buttons for both parsers and made sure the generated files match. |
||
</section> | ||
|
||
<section id="visual"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added granular file imports for anyone installing
imscJs
via npm. This wayfromXML
can be imported directly, and avoid bundlingsax
unlesscreateSAXParser
is explicitly imported.