UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

125 lines (98 loc) 3.14 kB
var OReader = OReader || {}; OReader.Stitcher = {}; OReader.Stitcher.parsePart = function(partString) { var tokens = partString.split("["); // Split string into element and other var attributes = {}; var part = { "string" : partString, "attributes" : attributes, "node" : tokens[0], "offset" : 1 }; var attrString; var re = /\@([^=]+)=[\'\"]([^\'^\"]+)[\'\"]/g; var match; // Part muight have additional information such as id or offset if(tokens[1]){ // remove the last part attrString = tokens[1].replace(']', ''); // If there is an offset it will be numerical if(!isNaN(parseFloat(attrString)) && isFinite(attrString)){ // is a number part.offset = parseInt(attrString); } else { // Run through string looking for @key=value paris do { match = re.exec(attrString); if (match) { // Add pairs to attributes object attributes[match[1]] = match[2]; } } while (match); } } return part; }; OReader.Stitcher.parseXpath = function(_xpath){ // Split path into parts var parts = _xpath.substring(1).split("/"); var xpath = []; // Parse each part and add to xpath array parts.forEach(function(part){ var parsed = OReader.Stitcher.parsePart(part); xpath.push(parsed); }); return xpath; }; OReader.Stitcher.createElement = function(part, _doc){ var doc = _doc || document; var element = doc.createElement(part.node); for (var attribute in part.attributes){ if (part.attributes.hasOwnProperty(attribute)) { element.setAttribute(attribute, part.attributes[attribute]); } } return element; }; OReader.Stitcher.rebuild = function(_xpath, doc, payload){ var xpath = OReader.Stitcher.parseXpath(_xpath); var walked = []; var prevElement = doc.documentElement; var wrapper; var last = xpath.pop(); var wrapperPresent = doc.evaluate(_xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if(!wrapperPresent){ // Create the terminal element wrapper = OReader.Stitcher.createElement(last, doc); // wrap the current payload in element while (payload.childNodes.length > 0) { if(payload.childNodes[0] != prevElement){ wrapper.appendChild(payload.childNodes[0]); } } } else { // All elements in xpath already present in correct location return; } // Process xpath parts xpath.forEach(function(part){ var present; var element; walked.push(part.string); // Check if part is present in DOM present = doc.evaluate("//"+walked.join('/'), doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; // console.log(present, walked.join('/')) if(!present) { // Create the element, add attributes element = OReader.Stitcher.createElement(part, doc); // Add to previously created element prevElement.appendChild(element); // Continue prevElement = element; } else { // Continue prevElement = present; } }); // Add the wrapper last prevElement.appendChild(wrapper); };