From 9f97a117db92bf1bf51fac9320e10f3d422598b6 Mon Sep 17 00:00:00 2001 From: Vincent Calame Date: Mon, 8 Aug 2022 21:52:15 +0200 Subject: [PATCH] version 1.0 --- dist/html2ods.js | 1956 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1956 insertions(+) create mode 100644 dist/html2ods.js diff --git a/dist/html2ods.js b/dist/html2ods.js new file mode 100644 index 0000000..f80bcfd --- /dev/null +++ b/dist/html2ods.js @@ -0,0 +1,1956 @@ +/* version: v1.0 */ + + +var Html2Ods = function (output, table, options) { + +function Currency (code, symbol, fractionDigit, symbolBefore, formatFunction) { + this.code = code; + this.symbol = symbol; + this.fractionDigit = fractionDigit; + this.symbolBefore = symbolBefore; + var multiplicator = 1; + for(var i = 0; i < fractionDigit; i++) { + multiplicator = multiplicator * 10; + } + this.subunitMultiplicator = multiplicator; + if (formatFunction) { + this.formatFunction = formatFunction; + } +}; +Currency.prototype.formatAmount = function (moneyLong, locale) { + var decimalValue = moneyLong / (this.subunitMultiplicator); + if (this.formatFunction) { + return this.formatFunction(decimalValue, locale); + } else { + return decimalValue.toLocaleString(locale, { + style: "currency", + currency: this.code + }); + } +}; +Currency.prototype.toDecimalValue = function (moneyLong) { + return moneyLong / (this.subunitMultiplicator); +}; +Currency.MAP = {}; +Currency.formatAmount = function (moneyLong, currencyCode, locale) { + var currency = Currency.get(currencyCode); + return currency.formatAmount(moneyLong, locale); +}; +Currency.toDecimalValue = function (moneyLong, currencyCode) { + var currency = Currency.get(currencyCode); + return currency.toDecimalValue(moneyLong); +}; +Currency.get = function (code) { + if (Currency.MAP.hasOwnProperty(code)) { + return Currency.MAP[code]; + } + var currency; + var symbolBefore = _isSymbolBefore(code); + if (code === 'CFA') { + currency = new Currency("CFA", "CFA", 0, symbolBefore, function(decimalValue, locale) { + return decimalValue.toLocaleString(locale, { + style: "decimal", + maximumFractionDigits: 0 + }) + " CFA"; + }); + } else { + var numberFormat = new Intl.NumberFormat('en', { style: 'currency', currency: code }); + var options = numberFormat.resolvedOptions(); + var fractionDigit = options.maximumFractionDigits; + var format = numberFormat.format(987); + var idx = format.indexOf(9); + var symbol = format.substring(0, idx); + currency = new Currency(code, symbol, fractionDigit, symbolBefore); + } + Currency.MAP[code] = currency; + return currency; + function _isSymbolBefore (code) { + switch(code) { + case "USD": + case "GBP": + return true; + default: + return false; + } + } +}; +XmlWriter = function (options) { + this.xml = ""; + this.indentLength = -999999; + if (options) { + if (options.indentLength) { + this.indentLength = options.indentLength; + } else if (options.prettyXml) { + this.indentLength = 0; + } + } +}; +XmlWriter.prototype.appendXMLDeclaration = function () { + this.write(''); + if (this.indentLength < 0) { + this.write('\n'); + } + return this; +}; +XmlWriter.prototype.startOpenTag = function (tagName, indentBefore) { + if (indentBefore === undefined) { + indentBefore = true; + } + if (indentBefore) { + this.appendIndent(); + } + this.write('<'); + this.write(tagName); + return this; +}; +XmlWriter.prototype.endOpenTag = function () { + this.write('>'); + this.increaseIndentValue(); + return this; +}; +XmlWriter.prototype.closeEmptyTag = function () { + this.write('/'); + this.write('>'); + return this; +}; +XmlWriter.prototype.openTag = function (tagName, indentBefore) { + if (indentBefore === undefined) { + indentBefore = true; + } + if (indentBefore) { + this.appendIndent(); + } + this.write('<'); + this.write(tagName); + this.write('>'); + this.increaseIndentValue(); + return this; +}; +XmlWriter.prototype.closeTag = function (tagName, indentBefore) { + if (indentBefore === undefined) { + indentBefore = true; + } + this.decreaseIndentValue(); + if (indentBefore) { + this.appendIndent(); + } + this.write('<'); + this.write('/'); + this.write(tagName); + this.write('>'); + return this; +}; +XmlWriter.prototype.addText = function (text) { + if (text) { + this.escape(text); + } + return this; +}; +XmlWriter.prototype.addCData = function (text) { + this.write(""); + this.write("]]"); + this.write(""); + return this; +}; +XmlWriter.prototype.addAttribute = function (attributeName, value) { + if ((value === 0) || (value)) { + this.write(' '); + this.write(attributeName); + this.write('='); + this.write('\"'); + this.escape(value.toString()); + this.write('\"'); + } + return this; +}; +XmlWriter.prototype.addSimpleElement = function (tagName, value) { + if (value) { + this.startOpenTag(tagName); + this.endOpenTag(); + this.addText(value); + this.closeTag(tagName, false); + } + return this; +}; +XmlWriter.prototype.addEmptyElement = function (tagName) { + this.startOpenTag(tagName); + this.closeEmptyTag(); + return this; +}; +XmlWriter.prototype.write = function (text) { + this.xml += text; + return this; +}; +XmlWriter.prototype.escape = function (text) { + var carac; + for(let i = 0, len = text.length; i < len; i++) { + carac = text.charAt(i); + switch (carac) { + case '&': + this.write("&"); + break; + case '"': + this.write("""); + break; + case '<': + this.write("<"); + break; + case '>': + this.write(">"); + break; + case '\'': + this.write("'"); + break; + case '\u00A0': + this.write(" "); + break; + default: + this.write(carac); + } + } + return this; +}; +XmlWriter.prototype.appendIndent = function () { + if (this.indentLength > -1) { + this.write('\n'); + for(let i = 0, len = this.indentLength; i < len; i++) { + this.write('\t'); + } + } + return this; +}; +XmlWriter.prototype.increaseIndentValue = function () { + this.indentLength = this.indentLength + 1; + return this; +}; +XmlWriter.prototype.decreaseIndentValue = function () { + this.indentLength = this.indentLength - 1; + return this; +}; +var OpenDocument = {}; +OpenDocument.DEFAULT_CELLSTYLE_NAME = "Default"; +OpenDocument.COLUMNSTYLE_PREFIX = "co"; +OpenDocument.CELLSTYLE_PREFIX = "ce"; +OpenDocument.DATASTYLE_PREFIX = "N"; +OpenDocument.SPREADSHEET_MIMETYPE = "application/vnd.oasis.opendocument.spreadsheet"; +OpenDocument.checkSheetName = function (name) { + var result = ""; + var carac; + for (let i = 0, len = name.length; i < len; i++) { + carac = name.charAt(i); + switch (carac) { + case '[': + carac = '('; + break; + case ']': + carac = ')'; + break; + case '*': + case ':': + case '/': + case '?': + case '\\': + carac = '-'; + break; + } + result += carac; + } + return result; +}; +OpenDocument.checkHiddenValue = function (element) { + let odHidden = element.dataset["odHidden"]; + if (!odHidden) { + return 0; + } + switch(odHidden.toLowerCase()) { + case 'true': + case '1': + case 'yes': + return 1; + case 'false': + case '0': + case '-1': + case 'no': + return -1; + default: + return 0; + } +}; +OpenDocument.toChar = function (columnNumber) { + return (columnNumber + 64); +}; +OpenDocument.Elements = {}; +OpenDocument.Elements.Cell = function (value, styleName, rowSpan, colSpan) { + this.value = value; + this.styleName = styleName; + this.rowSpan = rowSpan; + this.colSpan = colSpan; +}; +OpenDocument.Elements.TableColumn = function (styleName, columnsRepeated, defaultCellStyleName) { + this.styleName = styleName; + this.columnsRepeated = columnsRepeated; + if (defaultCellStyleName) { + this.defaultCellStyleName = defaultCellStyleName; + } else { + this.defaultCellStyleName = "Default"; + } +}; +OpenDocument.CellCounter = function () { + this.row = 0; + this.column = 0; + this.rowMap = new Map(); +}; +OpenDocument.CellCounter.prototype.reinit = function () { + this.row = 0; + this.column = 0; + this.rowMap.clear(); +}; +OpenDocument.CellCounter.prototype.newRow = function () { + this.row = this.row + 1; + this.column = 1; +}; +OpenDocument.CellCounter.prototype.newCell = function (rowSpan, colSpan) { + let currentRow = this.row; + let currentColumn = this.column; + let jump = 0; + let coveredCellArray = this.rowMap.get(currentRow); + if (coveredCellArray) { + while(true) { + if (coveredCellArray.indexOf(currentColumn) !== -1) { + currentColumn++; + jump++; + } else { + break; + } + } + } + if (rowSpan > 1) { + for(let i = 1; i < rowSpan; i++) { + for(let j = 0; j < colSpan; j++) { + this.putCoveredCell(currentRow + i, currentColumn + j); + } + } + } + if (colSpan > 1) { + currentColumn += (colSpan - 1); + } + this.column = currentColumn + 1; + return jump; +}; +OpenDocument.CellCounter.prototype.putCoveredCell = function (row, column) { + if (this.rowMap.has(row)) { + this.rowMap.get(row).push(column); + } else { + let array = new Array(); + array.push(column); + this.rowMap.set(row, array); + } +}; +OpenDocument.XmlWriter = function (options) { + XmlWriter.call(this, options); + this.cellCounter = new OpenDocument.CellCounter(); +}; +OpenDocument.XmlWriter.prototype = Object.create(XmlWriter.prototype); +OpenDocument.XmlWriter.prototype.constructor = OpenDocument.XmlWriter; +OpenDocument.XmlWriter.prototype.openDocument = function (mimetype) { + this + .startOpenTag("office:document") + .addXmlnsAttributes() + .addAttribute("office:mimetype", mimetype) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeDocument = function () { + this + .closeTag("office:document"); + return this; +}; +OpenDocument.XmlWriter.prototype.openDocumentContent = function () { + this + .startOpenTag("office:document-content") + .addXmlnsAttributes() + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.addXmlnsAttributes = function () { + this + .addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0") + .addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0") + .addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0") + .addAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0") + .addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0") + .addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0") + .addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0") + .addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink") + .addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/") + .addAttribute("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0") + .addAttribute("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") + .addAttribute("xmlns:presentation", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0") + .addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0") + .addAttribute("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0") + .addAttribute("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0") + .addAttribute("xmlns:math", "http://www.w3.org/1998/Math/MathML") + .addAttribute("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0") + .addAttribute("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0") + .addAttribute("xmlns:ooo", "http://openoffice.org/2004/office") + .addAttribute("xmlns:ooow", "http://openoffice.org/2004/writer") + .addAttribute("xmlns:oooc", "http://openoffice.org/2004/calc") + .addAttribute("xmlns:dom", "http://www.w3.org/2001/xml-events") + .addAttribute("xmlns:xforms", "http://www.w3.org/2002/xforms") + .addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema") + .addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + .addAttribute("xmlns:rpt", "http://openoffice.org/2005/report") + .addAttribute("xmlns:of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2") + .addAttribute("xmlns:xhtml", "http://www.w3.org/1999/xhtml") + .addAttribute("xmlns:grddl", "http://www.w3.org/2003/g/data-view#") + .addAttribute("xmlns:tableooo", "http://openoffice.org/2009/table") + .addAttribute("xmlns:vdrawooo", "http://openoffice.org/2010/draw") + .addAttribute("xmlns:calcext", "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0") + .addAttribute("xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0") + .addAttribute("xmlns:field", "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0") + .addAttribute("xmlns:formx", "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0") + .addAttribute("xmlns:css3t", "http://www.w3.org/TR/css3-text/") + .addAttribute("office:version", "1.2"); + return this; +}; +OpenDocument.XmlWriter.prototype.openDocumentContentVersion1 = function () { + this + .startOpenTag("office:document-content") + .addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0") + .addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0") + .addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0") + .addAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0") + .addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0") + .addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0") + .addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink") + .addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/") + .addAttribute("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0") + .addAttribute("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") + .addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0") + .addAttribute("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0") + .addAttribute("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0") + .addAttribute("xmlns:math", "http://www.w3.org/1998/Math/MathML") + .addAttribute("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0") + .addAttribute("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0") + .addAttribute("xmlns:ooo", "http://openoffice.org/2004/office") + .addAttribute("xmlns:ooow", "http://openoffice.org/2004/writer") + .addAttribute("xmlns:oooc", "http://openoffice.org/2004/calc") + .addAttribute("xmlns:dom", "http://www.w3.org/2001/xml-events") + .addAttribute("xmlns:xforms", "http://www.w3.org/2002/xforms") + .addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema") + .addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + .addAttribute("office:version", "1.0") + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeDocumentContent = function () { + this + .closeTag("office:document-content"); + return this; +}; +OpenDocument.XmlWriter.prototype.openStyles = function () { + this + .openTag("office:styles"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeStyles = function () { + this + .closeTag("office:styles"); + return this; +}; +OpenDocument.XmlWriter.prototype.openAutomaticStyles = function () { + this + .openTag("office:automatic-styles"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeAutomaticStyles = function () { + this + .closeTag("office:automatic-styles"); + return this; +}; +OpenDocument.XmlWriter.prototype.openBody = function () { + this + .openTag("office:body"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeBody = function () { + this + .closeTag("office:body"); + return this; +}; +OpenDocument.XmlWriter.prototype.openSpreadsheet = function () { + this + .openTag("office:spreadsheet"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeSpreadsheet = function () { + this + .closeTag("office:spreadsheet"); + return this; +}; +OpenDocument.XmlWriter.prototype.openStyle = function (styleName, styleFamily, parentStyleName) { + this + .startStyleOpenTag(styleName, styleFamily, parentStyleName) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.startStyleOpenTag = function (styleName, styleFamily, parentStyleName) { + this + .startOpenTag("style:style") + .addAttribute("style:name", styleName); + if (styleName.indexOf("_20_") > -1) { + let displayName = styleName.replace("_20_", " "); + this + .addAttribute("style:display-name", displayName); + } + this + .addAttribute("style:family", styleFamily) + .addAttribute("style:parent-style-name", parentStyleName); + return this; +}; +OpenDocument.XmlWriter.prototype.closeStyle = function () { + this + .closeTag("style:style"); + return this; +}; +OpenDocument.XmlWriter.prototype.addDateStyle = function (datePattern, dataStyleName) { + var xmlWriter = this; + var length = datePattern.length; + var buffer = ""; + xmlWriter + .startOpenTag("number:date-style") + .addAttribute("style:name", dataStyleName) + .endOpenTag(); + for(let i = 0; i < length; i++) { + let char = datePattern.charAt(i); + let jump = 0; + switch(char) { + case 'M': + jump = _parseMonth(i); + break; + case 'D': + jump = _parseDay(i); + break; + case 'Y': + jump = _parseYear(i); + if (jump === 0) { + _buf(char); + } + break; + default: + _buf(char); + } + i = i + jump; + } + _flush(); + xmlWriter + .closeTag("number:date-style"); + return this; + function _buf(char) { + buffer = buffer + char; + } + function _parseMonth(index) { + _flush(); + let jump = 0; + let next = index + 1; + if ((next < length) && (datePattern.charAt(next) === 'M')) { + jump = 1; + } + _addNumberElement("number:month", (jump === 1)); + return jump; + } + function _parseDay(index) { + _flush(); + let jump = 0; + let next = index + 1; + if ((next < length) && (datePattern.charAt(next) === 'D')) { + jump = 1; + } + _addNumberElement("number:day", (jump === 1)); + return jump; + } + function _parseYear(index) { + let next = index + 1; + if ((next === length) || (datePattern.charAt(next) !== 'Y')) { + return 0; + } + _flush(); + let jump = 1; + if (next < (length -2)) { + if ((datePattern.charAt(next + 1) === 'Y') && (datePattern.charAt(next + 2) === 'Y')) { + jump = 3; + } + } + _addNumberElement("number:year", (jump === 3)); + return jump; + } + function _flush() { + if (buffer) { + xmlWriter.addSimpleElement("number:text", buffer); + buffer = ""; + } + } + function _addNumberElement(name, isLong) { + xmlWriter + .startOpenTag(name); + if (isLong) { + xmlWriter + .addAttribute("number:style", "long"); + } + xmlWriter + .closeEmptyTag(); + } +}; +OpenDocument.XmlWriter.prototype.addCurrencyStyle = function (currencyCode, dataStyleName) { + var currency = Currency.get(currencyCode); + this + .startOpenTag("number:currency-style") + .addAttribute("style:name", dataStyleName + "P0") + .addAttribute("style:volatile", "true") + .endOpenTag(); + if (currency.symbolBefore) { + this + .addSimpleElement("number:currency-symbol", currency.symbol); + } + this + .startOpenTag("number:number") + .addAttribute("number:decimal-places", currency.fractionDigits) + .addAttribute("number:min-integer-digits", "1") + .addAttribute("number:grouping", "true") + .closeEmptyTag(); + if (!currency.symbolBefore) { + this + .addSimpleElement("number:text", " ") + .addSimpleElement("number:currency-symbol", currency.symbol); + } + this + .closeTag("number:currency-style") + .startOpenTag("number:currency-style") + .addAttribute("style:name", dataStyleName) + .endOpenTag() + .startOpenTag("style:text-properties") + .addAttribute("fo:color", "#ff0000") + .closeEmptyTag() + .addSimpleElement("number:text", "-"); + if (currency.symbolBefore) { + this + .addSimpleElement("number:currency-symbol", currency.symbol); + } + this + .startOpenTag("number:number") + .addAttribute("number:decimal-places", currency.fractionDigits) + .addAttribute("number:min-integer-digits", "1") + .addAttribute("number:grouping", "true") + .closeEmptyTag(); + if (!currency.symbolBefore) { + this + .addSimpleElement("number:text", " ") + .addSimpleElement("number:currency-symbol", currency.symbol); + } + this + .startOpenTag("style:map") + .addAttribute("style:condition", "value()>=0") + .addAttribute("style:apply-style-name", dataStyleName + "P0") + .closeEmptyTag() + .closeTag("number:currency-style"); + return this; +}; +OpenDocument.XmlWriter.prototype.openNamedExpressions = function () { + this + .openTag("table:named-expressions"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeNamedExpressions = function () { + this + .closeTag("table:named-expressions"); + return this; +}; +OpenDocument.XmlWriter.prototype.addNamedRange = function (name, address) { + this + .startOpenTag("table:named-range") + .addAttribute("table:name", name) + .addAttribute("table:base-cell-address", address) + .addAttribute("table:cell-range-address", address) + .closeEmptyTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.openTable = function (name) { + this.cellCounter.reinit(); + this + .startOpenTag("table:table") + .addAttribute("table:name", OpenDocument.checkSheetName(name)) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeTable = function () { + this + .closeTag("table:table"); + return this; +}; +OpenDocument.XmlWriter.prototype.addTableColumn = function (tableColumn) { + this + .startOpenTag("table:table-column") + .addAttribute("table:style-name", tableColumn.styleName); + if (tableColumn.columnsRepeated > 1) { + this + .addAttribute("table:number-columns-repeated", tableColumn.columnsRepeated); + } + this + .addAttribute("table:default-cell-style-name", tableColumn.defaultCellStyleName) + .closeEmptyTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.openTableRow = function (rowStyleName) { + this.cellCounter.newRow(); + this + .startOpenTag("table:table-row") + .addAttribute("table:style-name", rowStyleName) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeTableRow = function () { + this + .closeTag("table:table-row"); + return this; +}; +OpenDocument.XmlWriter.prototype.addEmptyTableCell = function (cell) { + this + .startCell(cell) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.addNumberTableCell = function (cell) { + this + .startCell(cell) + .addAttribute("office:value-type", "float") + .addAttribute("office:value", cell.value) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.addPercentageTableCell = function (cell) { + this + .startCell(cell) + .addAttribute("office:value-type", "percentage") + .addAttribute("office:value", cell.value) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.addDateTableCell = function (cell) { + this + .startCell(cell) + .addAttribute("office:value-type", "date") + .addAttribute("office:date-value", cell.value) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.addCurrencyTableCell = function (cell, currency) { + this + .startCell(cell) + .addAttribute("office:value-type", "currency") + .addAttribute("office:currency", currency) + .addAttribute("office:value", cell.value) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.addLinkStringTableCell = function (cell, linkString) { + this + .startCell(cell) + .addAttribute("office:value-type", "string") + .endOpenTag(); + if ((linkString) && (linkString.length > 0)) { + this + .startOpenTag("text:p") + .endOpenTag() + .XmlWriter.prototype.addLink(linkString) + .closeTag("text:p", false); + } + this + .endCell(cell, false); + return this; +}; +OpenDocument.XmlWriter.prototype.addStringTableCell = function (cell) { + this + .startCell(cell) + .addAttribute("office:value-type", "string") + .endOpenTag() + .splitText(cell.value) + .endCell(cell, false); + return this; +}; +OpenDocument.XmlWriter.prototype.addFormulaTableCell = function (cell, valueType) { + this + .startCell(cell) + .addAttribute("table:formula", cell.value) + .addAttribute("office:value-type", valueType) + .endCell(cell, true); + return this; +}; +OpenDocument.XmlWriter.prototype.splitText = function (value) { + if (value) { + var tokens = value.split('\n'); + for (let token of tokens) { + this + .startOpenTag("text:p") + .endOpenTag() + .addText(token) + .closeTag("text:p", false); + } + } + return this; +}; +OpenDocument.XmlWriter.prototype.addLink = function (link) { + this + .startOpenTag("text:a", false) + .addAttribute("xlink:href", link) + .endOpenTag() + .addText(link) + .closeTag("text:a", false); + return this; +}; +OpenDocument.XmlWriter.prototype.startCell = function (cell) { + var jump = this.cellCounter.newCell(cell.rowSpan, cell.colSpan); + if (jump > 0) { + this + .startOpenTag("table:covered-table-cell"); + if (jump > 1) { + this + .addAttribute("table:number-columns-repeated", jump) + } + this + .closeEmptyTag(); + } + this + .startOpenTag("table:table-cell") + .addAttribute("table:style-name", cell.styleName); + if (cell.rowSpan > 1) { + this.addAttribute("table:number-rows-spanned", cell.rowSpan); + } + if (cell.colSpan > 1) { + this + .addAttribute("table:number-columns-spanned", cell.colSpan); + } + return this; +}; +OpenDocument.XmlWriter.prototype.endCell = function (cell, emptyTag) { + if (emptyTag) { + this + .closeEmptyTag(); + } else { + this + .closeTag("table:table-cell"); + } + if (cell.colSpan > 1) { + this + .startOpenTag("table:covered-table-cell"); + if (cell.colSpan > 2) { + this + .addAttribute("table:number-columns-repeated", (cell.colSpan - 1)); + } + this + .closeEmptyTag(); + } + return this; +}; +OpenDocument.XmlWriter.prototype.openSettings = function () { + this + .openTag("office:settings"); + return this; +}; +OpenDocument.XmlWriter.prototype.closeSettings = function () { + this + .closeTag("office:settings"); + return this; +}; +OpenDocument.XmlWriter.prototype.openConfigItemSet = function (name) { + this + .startOpenTag("config:config-item-set") + .addAttribute("config:name", name) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeConfigItemSet = function () { + this + .closeTag("config:config-item-set"); + return this; +}; +OpenDocument.XmlWriter.prototype.openConfigItemMapIndexed = function (name) { + this + .startOpenTag("config:config-item-map-indexed") + .addAttribute("config:name", name) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeConfigItemMapIndexed = function () { + this + .closeTag("config:config-item-map-indexed"); + return this; +}; +OpenDocument.XmlWriter.prototype.openConfigItemMapNamed = function (name) { + this + .startOpenTag("config:config-item-map-named") + .addAttribute("config:name", name) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeConfigItemMapNamed = function () { + this + .closeTag("config:config-item-map-named"); + return this; +}; +OpenDocument.XmlWriter.prototype.openConfigItemMapEntry = function (name) { + this + .startOpenTag("config:config-item-map-entry") + .addAttribute("config:name", name) + .endOpenTag(); + return this; +}; +OpenDocument.XmlWriter.prototype.closeConfigItemMapEntry = function () { + this + .closeTag("config:config-item-map-entry"); + return this; +}; +OpenDocument.XmlWriter.prototype.addConfigItem = function (name, type, value) { + this + .startOpenTag("config:config-item", true) + .addAttribute("config:name", name) + .addAttribute("config:type", type) + .endOpenTag() + .addText(value) + .closeTag("config:config-item", false); + return this; +}; +OpenDocument.Style = function (type, styleName) { + this.type = type; + this.styleName = styleName; + this.styleFamily = OpenDocument.Style.getMatchingStyleFamily(type); + this.parentStyleName = ""; + this.dataStyleName = ""; + this.propertiesMaps = new Map([ + ["paragraph", new Map()], + ["text", new Map()], + ["table-cell", new Map()], + ["table-row", new Map()], + ["table-column", new Map()] + ]); +}; +OpenDocument.Style.prototype.putStyleProperty = function (stylePropertyDef, value) { + var propertyName = stylePropertyDef.name; + switch(stylePropertyDef.format) { + case "color": + value = OpenDocument.Style.formatColor(value); + break; + case "wrap": + value = _convertWrap(); + break; + } + var property = { + name: propertyName, + value: value + }; + this.propertiesMaps.get(stylePropertyDef.category).set(propertyName, property); + function _convertWrap() { + switch(value) { + case "anywhere": + case "break-word": + return "wrap"; + default: + return "no-wrap"; + } + } +}; +OpenDocument.Style.prototype.setParent = function (parentStyleName) { + this.parentStyleName = parentStyleName; +}; +OpenDocument.Style.prototype.setDataStyle = function (dataStyleName) { + this.dataStyleName = dataStyleName; +}; +OpenDocument.Style.prototype.isEmpty = function () { + for(let map of this.propertiesMaps.values()) { + if (map.size > 0) { + return false; + } + } + return true; +}; +OpenDocument.Style.prototype.copyProperties = function (otherStyle) { + if (otherStyle.parentStyleName) { + this.setParent(otherStyle.parentStyleName); + } + for(let entry of otherStyle.propertiesMaps) { + let otherMap = entry[1]; + let thisMap = this.propertiesMaps.get(entry[0]); + for(let entry2 of otherMap) { + thisMap.set(entry2[0], entry2[1]); + } + } +}; +OpenDocument.Style.prototype.write = function (xmlWriter) { + xmlWriter + .startStyleOpenTag(this.styleName, this.styleFamily, this.parentStyleName) + .addAttribute("style:data-style-name", this.dataStyleName); + if (this.isEmpty()) { + xmlWriter + .closeEmptyTag(); + } else { + xmlWriter + .endOpenTag(); + for(let entry of this.propertiesMaps) { + let category = entry[0]; + let map = entry[1]; + if (map.size > 0) { + xmlWriter + .startOpenTag("style:" + category + "-properties"); + for(let property of map.values()) { + xmlWriter + .addAttribute(property.name, property.value); + } + xmlWriter + .closeEmptyTag(); + } + } + xmlWriter + .closeStyle(); + } +}; +OpenDocument.Style.getStylePropertyDef = function (type, name) { + name = _checkAlias(); + if (OpenDocument.Style.STYLEPROPERTYDEFS.hasOwnProperty(name)) { + let propertyDef = OpenDocument.Style.STYLEPROPERTYDEFS[name]; + if (propertyDef.categories) { + for(let propKey in propertyDef.categories) { + if (propKey === type) { + return Object.assign({}, propertyDef, {category: propertyDef.categories[propKey]}); + } + } + return null; + } else { + return propertyDef; + } + } else { + return null; + } + function _checkAlias() { + switch(type) { + case "row": + switch(name) { + case "height": + return "row-height"; + } + break; + case "column": + switch(name) { + case "width": + return "column-width"; + } + break; + case "cell": + switch(name) { + case "overflow-wrap": + return "wrap-option"; + } + break; + } + return name; + } +}; +OpenDocument.Style.getMatchingStyleFamily = function (type) { + switch(type) { + case "cell": + return "table-cell"; + case "row": + return "table-row"; + case "column": + return "table-column"; + } +}; +OpenDocument.Style.STYLEPROPERTYDEFS = { + "background-color": { + name: "fo:background-color", + categories: { + "cell": "table-cell", + "row": "table-row" + }, + format: "color" + }, + "border": { + name: "fo:border", + category: "table-cell" + }, + "border-bottom": { + name: "fo:border-bottom", + category: "table-cell" + }, + "border-left": { + name: "fo:border-left", + category: "table-cell" + }, + "border-right": { + name: "fo:border-right", + category: "table-cell" + }, + "border-top": { + name: "fo:border-top", + category: "table-cell" + }, + "color": { + name: "fo:color", + category: "text", + format: "color" + }, + "column-width": { + name: "style:column-width", + category: "table-column" + }, + "font-size": { + name: "fo:font-size", + category: "text" + }, + "font-style": { + name: "fo:font-style", + category: "text" + }, + "font-weight": { + name: "fo:font-weight", + category: "text" + }, + "padding": { + name: "fo:padding", + category: "table-cell" + }, + "padding-bottom": { + name: "fo:padding-bottom", + category: "table-cell" + }, + "padding-left": { + name: "fo:padding-left", + category: "table-cell" + }, + "padding-right": { + name: "fo:padding-right", + category: "table-cell" + }, + "padding-top": { + name: "fo:padding-top", + category: "table-cell" + }, + "row-height": { + name: "style:row-height", + category: "table-row" + }, + "text-align": { + name: "fo:text-align", + category: "paragraph" + }, + "use-optimal-row-height": { + name: "style:use-optimal-row-height", + category: "table-row" + }, + "vertical-align": { + name: "style:vertical-align", + category: "table-cell" + }, + "wrap-option": { + name: "fo:wrap-option", + category: "table-cell", + format: "wrap" + } +}; +OpenDocument.Style.formatColor = function (color) { + let colorList = color.match(/rgb\((.*)\)/); + if (colorList) { + let hexresult = "#"; + for(let token of colorList[1].split(",")) { + let hex = Number.parseInt(token.trim(), 10).toString(16); + if (hex.length === 1) { + hex = "0" + hex; + } + hexresult += hex; + } + color = hexresult; + } + return color; +}; +OpenDocument.StyleManager = function () { + this.maps = new Map([ + ["cell-named", new Map()], + ["row-named", new Map()], + ["cell-automatic", new Map()], + ["column-named", new Map()], + ["column-automatic", new Map()] + ]); + this.matchingClassMaps = new Map([ + ["cell", new Map()], + ["row", new Map()], + ["column", new Map()] + ]); + for(let object of OpenDocument.StyleManager.DEFAULT_STYLES ) { + this.putStyle(object.type + "-named", _buildDefault(object)); + } + this.automaticCellStyleNumber = 1; + this.dataStyleNumber = 1; + this.currencyDataStyleMap = new Map(); + this.dateDataStyleMap = new Map(); + OpenDocument.StyleManager.readDocumentStyleSheets(this); + function _buildDefault(object) { + let style = new OpenDocument.Style(object.type, object.name); + if (object.parent) { + style.setParent(object.parent); + } + for(let propertyName in object.properties) { + let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(object.type, propertyName); + if (stylePropertyDef) { + style.putStyleProperty(stylePropertyDef, object.properties[propertyName]); + } + } + return style; + } +}; +OpenDocument.StyleManager.prototype.putStyle = function (mapName, style, styleKey) { + if (!styleKey) { + styleKey = style.styleName; + } + var map = this.maps.get(mapName); + if (map.has(styleKey)) { + let existingStyle = map.get(styleKey); + existingStyle.copyProperties(style); + } else { + map.set(styleKey, style); + } +}; +OpenDocument.StyleManager.prototype.hasStyle = function (mapName, styleKey) { + var map = this.maps.get(mapName); + if (map) { + return map.has(styleKey); + } else { + return false; + } +}; +OpenDocument.StyleManager.prototype.getStyle = function (mapName, styleKey) { + var map = this.maps.get(mapName); + if (map) { + return map.get(styleKey); + } else { + return null; + } + return this.map.get(styleKey); +}; +OpenDocument.StyleManager.prototype.getAutomaticCellStyleName = function (type, parentStyleName, cellOption) { + var styleKey = _buildStyleKey(); + if (this.hasStyle("cell-automatic", styleKey)) { + return this.getStyle("cell-automatic", styleKey).styleName; + } + var automaticCellStyleName = this.getNewAutomaticeCellStyleName(); + var dataStyleName = null; + switch(type) { + case "date": + dataStyleName = this.getMatchingDateDataStyleName(cellOption); + break; + case "currency": + dataStyleName = this.getMatchingCurrencyDataStyleName(cellOption); + break; + } + var cellStyle = new OpenDocument.Style("cell", automaticCellStyleName); + if (parentStyleName) { + cellStyle.setParent(parentStyleName); + } else { + cellStyle.setParent(OpenDocument.DEFAULT_CELLSTYLE_NAME); + } + if (dataStyleName) { + cellStyle.setDataStyle(dataStyleName); + } + this.putStyle("cell-automatic", cellStyle, styleKey); + return automaticCellStyleName; + function _buildStyleKey() { + let key = type + ":"; + if (cellOption) { + key += cellOption + ":"; + } + key += parentStyleName; + return key; + } +}; +OpenDocument.StyleManager.prototype.getNewAutomaticeCellStyleName = function () { + var name = OpenDocument.CELLSTYLE_PREFIX + this.automaticCellStyleNumber; + this.automaticCellStyleNumber++; + return name; +}; +OpenDocument.StyleManager.prototype.getMatchingCurrencyDataStyleName = function (currencyCode) { + if (this.currencyDataStyleMap.has(currencyCode)) { + return this.currencyDataStyleMap.get(currencyCode); + } else { + let dataStyleName = OpenDocument.DATASTYLE_PREFIX + this.dataStyleNumber; + this.dataStyleNumber++; + this.currencyDataStyleMap.set(currencyCode, dataStyleName); + return dataStyleName; + } +}; +OpenDocument.StyleManager.prototype.getMatchingDateDataStyleName = function (datePattern) { + if (this.dateDataStyleMap.has(datePattern)) { + return this.dateDataStyleMap.get(datePattern); + } else { + let dataStyleName = OpenDocument.DATASTYLE_PREFIX + this.dataStyleNumber; + this.dataStyleNumber++; + this.dateDataStyleMap.set(datePattern, dataStyleName); + return dataStyleName; + } +}; +OpenDocument.StyleManager.prototype.getMatchingStyleName = function (type, element) { + var map = this.matchingClassMaps.get(type); + if (map) { + for(let className of element.classList) { + if (map.has(className)) { + return map.get(className); + } + } + } + return ""; +}; +OpenDocument.StyleManager.prototype.writeStyles = function (mapName, xmlWriter) { + var map = this.maps.get(mapName); + if (map) { + for(let style of map.values()) { + style.write(xmlWriter); + } + } +}; +OpenDocument.StyleManager.prototype.writeDataStyles = function (xmlWriter) { + for(let entry of this.dateDataStyleMap) { + xmlWriter + .addDateStyle(entry[0], entry[1]); + } + for(let entry of this.currencyDataStyleMap) { + xmlWriter + .addCurrencyStyle(entry[0], entry[1]); + } +}; +OpenDocument.StyleManager.readDocumentStyleSheets = function (styleManager) { + var styleSheetList = document.styleSheets; + for(let i = 0, len = styleSheetList.length; i < len; i++) { + OpenDocument.StyleManager.readStyleSheet(styleManager, styleSheetList[i]); + } +}; +OpenDocument.StyleManager.readStyleSheet = function (styleManager, styleSheet) { + var ruleList = styleSheet.cssRules; + for(let i = 0, len = ruleList.length; i < len; i++) { + let rule = ruleList[i]; + if ((rule.selectorText) && (rule.style)) { + let selectorArray = _parseSelectorText(rule.selectorText); + for(let selector of selectorArray) { + _addStyle(selector, rule.style); + } + } + } + function _parseSelectorText(selectorText) { + let resultArray = new Array(); + for(let token of selectorText.split(',')) { + let result = __parseToken(token); + if (result) { + switch(result[0]) { + case "cell": + case "row": + case "column": + resultArray.push(result); + break; + } + } + } + return resultArray; + function __parseToken(token) { + token = token.trim(); + let idx = token.indexOf(' '); + let followingPart = ""; + if (idx !== -1) { + followingPart = token.substring(idx +1).trim(); + token = token.substring(0, idx); + } + let dotIndex = token.indexOf('.'); + if (dotIndex === -1) { + return null; + } + let type = token.substring(0, dotIndex); + let name = token.substring(dotIndex + 1); + return [type, name, followingPart]; + } + } + function _addStyle(selector, cssStyleDeclaration) { + let type = selector[0]; + let style = new OpenDocument.Style(type, selector[1]); + let borderBuffer = false; + if (type === "cell") { + borderBuffer = new OpenDocument.StyleManager.BorderBuffer(); + } + for(let i = 0, len = cssStyleDeclaration.length; i < len; i++) { + let propertyName = cssStyleDeclaration[i]; + let propertyValue = cssStyleDeclaration.getPropertyValue(propertyName); + if (borderBuffer) { + let borderTest = propertyName.match(/^border-([a-z]+)-([a-z]+)/); + if (borderTest) { + borderBuffer.putSubproperty(borderTest[1], borderTest[2], propertyValue); + continue; + } + } + if (propertyName === "content") { + __parseDeclarationText(propertyValue); + } else { + let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, propertyName); + if (stylePropertyDef) { + style.putStyleProperty(stylePropertyDef, propertyValue); + } + } + } + if (borderBuffer) { + borderBuffer.fillStyle(style); + } + _parseFollowingPart(selector[2]); + styleManager.putStyle(type + "-named", style); + function __parseDeclarationText(declarationText) { + let start = declarationText.indexOf('"'); + if (start === -1) { + return; + } + let end = declarationText.lastIndexOf('"'); + if (end === start) { + return; + } + let tokens = declarationText.substring(start + 1, end).split(';'); + for(let token of tokens) { + let paire = token.split(':'); + if (paire.length === 2) { + let name = paire[0].trim(); + let value = paire[1].trim(); + let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, name); + if (stylePropertyDef) { + style.putStyleProperty(stylePropertyDef, value); + } + } + } + } + function _parseFollowingPart(followingPart) { + if (!followingPart) { + return; + } + let tokens = new Array(); + for(let token of followingPart.split(" ")) { + token = token.trim(); + if (token.length > 0) { + tokens.push(token); + } + } + let index = 0; + let length = tokens.length - 1; + while(index < length) { + let operatorToken = tokens[index]; + switch(operatorToken) { + case '~': + for(let i = index +1; i <= length; i++) { + __addMatchingClasses(tokens[i]); + } + index = length; + break; + case '+': + __setParent(tokens[index +1]); + index ++; + break; + } + index ++; + } + } + function __addMatchingClasses(token) { + if (!token) { + return; + } + let map = styleManager.matchingClassMaps.get(type); + if (!map) { + return; + } + if (token.startsWith('.')) { + map.set(token.substring(1), style.styleName); + } + } + function __setParent(token) { + if (!token) { + return; + } + let dotIndex = token.indexOf('.'); + if (dotIndex !== -1) { + style.setParent(token.substring(dotIndex + 1)); + } + } + } +}; +OpenDocument.StyleManager.BorderBuffer = function () { + this.map = new Map([ + ["bottom", false], + ["left", false], + ["right", false], + ["top", false] + ]); +}; +OpenDocument.StyleManager.BorderBuffer.prototype.putSubproperty = function (position, subproperty, value) { + if (!this.map.has(position)) { + return; + } + let positionObject = this.map.get(position); + if (!positionObject) { + positionObject = { + width: "0.75pt", + color: "rgb(0, 0, 0)", + style: "solid" + }; + this.map.set(position, positionObject); + } + if (positionObject.hasOwnProperty(subproperty)) { + if (subproperty === "color") { + value = OpenDocument.Style.formatColor(value); + } + positionObject[subproperty] = value; + }; +}; +OpenDocument.StyleManager.BorderBuffer.prototype.fillStyle = function (style) { + for(let entry of this.map) { + let position = entry[0]; + let object = entry[1]; + if (object) { + let stylePropertyDef = OpenDocument.Style.getStylePropertyDef("type", "border-" + position); + if (stylePropertyDef) { + let value = object.width + " " + object.style + " " + object.color; + style.putStyleProperty(stylePropertyDef, value); + } + } + } +}; +OpenDocument.StyleManager.DEFAULT_STYLES = [ + { + type: "cell", + name: "Standard", + parent: "", + properties: { + } + }, + { + type: "cell", + name: "Bold", + parent: "Standard", + properties: { + "font-weight": "bold" + } + }, + { + type: "cell", + name: "Italic", + parent: "Standard", + properties: { + "font-weight": "italic" + } + }, + { + type: "cell", + name: "BoldItalic", + parent: "Standard", + properties: { + "font-weight": "bold", + "font-style": "italic" + } + }, + { + type: "cell", + name: "Header", + properties: { + "font-weight": "bold", + "text-align": "center", + "vertical-align": "middle" + } + }, + { + type: "row", + name: "Standard", + parent: "", + properties: { + } + }, + { + type: "row", + name: "Header", + parent: "", + properties: { + } + } +]; +OpenDocument.OdsConverter = function (xmlWriter, options) { + this.xmlWriter = xmlWriter; + this.sheetName = ""; + this.nameMap = {}; + this.flatOds = true; + this.styleManager = new OpenDocument.StyleManager(); + this.cellStyleNumber = 1; + this.currencyMap = {}; + this.fixedRows = 0; + this.fixedColumns = 0; + this.textDataAttribute = "text"; + this.defaultCurrencyCode = ""; + this.defaultDatePattern = "YYYY-MM-DD"; + if (options) { + if (options.datePattern) { + this.defaultDatePattern = options.datePattern; + } + if (options.currency) { + this.defaultCurrencyCode = options.currency; + } + if (options.textAlias) { + this.textDataAttribute = options.textAlias; + } + } +}; +OpenDocument.OdsConverter.convertToBlob = function (table, options) { + var xml = OpenDocument.OdsConverter.convertToXml(table, options); + return new Blob([xml], {type: OpenDocument.SPREADSHEET_MIMETYPE }); +}; +OpenDocument.OdsConverter.convertToXml = function (table, options) { + var xmlWriter = new OpenDocument.XmlWriter({prettyXml: true}); + var odsConverter = new OpenDocument.OdsConverter(xmlWriter, options); + odsConverter.convert(table); + return xmlWriter.xml; +}; +OpenDocument.OdsConverter.prototype.checkOdData = function (table) { + let odCurrency = table.dataset["odCurrency"]; + if (odCurrency) { + this.defaultCurrencyCode = odCurrency; + } + let sheetName = table.dataset["odSheetname"]; + if (sheetName) { + this.sheetName = sheetName; + } + let fixedRows = table.dataset["odFixedRows"]; + if (fixedRows) { + this.fixedRows = fixedRows; + } + let fixedColumns = table.dataset["odFixedColumns"]; + if (fixedColumns) { + this.fixedColumns = fixedColumns; + } + let odDatePattern = table.dataset["odDatePattern"]; + if (odDatePattern) { + this.defaultDatePattern = odDatePattern; + } +}; +OpenDocument.OdsConverter.prototype.convert = function (table) { + if (typeof table === "string") { + table = document.getElementById(table); + } + this.checkOdData(table); + var converter = this; + var styleManager = this.styleManager; + var _getRowStyleName = OpenDocument.OdsConverter.default_getRowStyleName; + var _getCellStyleName = OpenDocument.OdsConverter.default_getCellStyleName; + var columnArray = OpenDocument.OdsConverter.readTableColumns(table, styleManager); + var xw = new OpenDocument.XmlWriter({indentLength: 3}); + xw + .openTable(converter.sheetName); + for(let tableColumn of columnArray) { + xw + .addTableColumn(tableColumn); + } + for(let row of table.rows) { + let display = window.getComputedStyle(row).display; + let odHidden = OpenDocument.checkHiddenValue(row); + if (((display === "none") && (odHidden !== -1)) || (odHidden === 1)) { + continue; + } + xw + .openTableRow(_getRowStyleName(row, styleManager)); + for(let cell of row.cells) { + _addCell(cell); + } + xw + .closeTableRow(); + } + xw + .closeTable(xw); + this.ods(xw.xml); + function _addCell(cell) { + let text = _getCellText(cell); + let odCell = new OpenDocument.Elements.Cell(text, _getCellStyleName(cell, styleManager), cell.rowSpan, cell.colSpan); + if (!text) { + xw + .addEmptyTableCell(odCell); + return; + } + let type = cell.dataset["odType"]; + switch(type) { + case "number": + xw + .addNumberTableCell(odCell); + break; + case "date": + let datePattern = cell.dataset["odDatePattern"]; + if (!datePattern) { + datePattern = converter.defaultDatePattern; + } + odCell.styleName = styleManager.getAutomaticCellStyleName("date", odCell.styleName, datePattern); + xw + .addDateTableCell(odCell); + break; + case "currency": + let currencyCode = cell.dataset["odCurrency"]; + if (!currencyCode) { + currencyCode = converter.defaultCurrencyCode; + } + odCell.styleName = styleManager.getAutomaticCellStyleName("currency", odCell.styleName, currencyCode); + xw + .addCurrencyTableCell(odCell, currencyCode); + break; + default: + xw + .addStringTableCell(odCell); + } + } + function _getCellText(cellElement) { + let cellText = cellElement.dataset["odText"]; + if (cellText) { + return cellText; + } + cellText = cellElement.dataset[converter.textDataAttribute]; + if (cellText) { + return cellText; + } + cellText = ""; + let previousBlock = false; + for(let node of cellElement.childNodes) { + if (node.nodeType === Node.ELEMENT_NODE) { + let display = window.getComputedStyle(node).display; + let odHidden = OpenDocument.checkHiddenValue(node); + switch(display) { + case "none": + break; + case "block": + if (odHidden !== 1) { + __addText(node.innerText, true); + } + previousBlock = true; + break; + default: + if (odHidden !== 1) { + __addText(node.innerText, false); + } + } + } else { + if (node.textContent) { + let text = node.textContent; + text = text.replace(/[\s\uFEFF\xA0]/g, ' '); + __addText(text, false); + } + } + } + return cellText.trim().replace(/ +/g, ' '); + function __addText(text, isBlock) { + if (!text) { + return false; + } + if ((previousBlock) || (isBlock)) { + cellText = cellText.trimEnd() + "\n"; + previousBlock = false; + text = text.trimStart(); + } + cellText += text; + return true; + } + } +}; +OpenDocument.OdsConverter.prototype.ods = function (tableXml) { + var xw = this.xmlWriter; + xw.appendXMLDeclaration(); + if (this.flatOds) { + xw + .openDocument(OpenDocument.SPREADSHEET_MIMETYPE); + } else { + xw + .openDocumentContent(); + } + if ((this.fixedColumns > 0) || (this.fixedRows > 0)) { + xw + .openSettings() + .openConfigItemSet("ooo:view-settings") + .openConfigItemMapIndexed("Views") + .openConfigItemMapEntry( "") + .addConfigItem("ViewId", "string", "view1") + .openConfigItemMapNamed("Tables") + .openConfigItemMapEntry(this.sheetName); + if (this.fixedColumns > 0) { + xw + .addConfigItem("HorizontalSplitMode", "short", "2") + .addConfigItem("HorizontalSplitPosition", "int", this.fixedColumns) + .addConfigItem("PositionLeft", "int", "0") + .addConfigItem("PositionRight", "int", this.fixedColumns); + } + if (this.fixedRows > 0) { + xw + .addConfigItem("VerticalSplitMode", "short", "2") + .addConfigItem("VerticalSplitPosition", "int", this.fixedRows) + .addConfigItem("PositionTop", "int", "0") + .addConfigItem("PositionBottom", "int", this.fixedRows); + } + xw + .closeConfigItemMapEntry() + .closeConfigItemMapNamed() + .closeConfigItemMapEntry() + .closeConfigItemMapIndexed() + .closeConfigItemSet() + .closeSettings(); + } + xw + .openStyles() + this.styleManager.writeStyles("cell-named", xw); + xw + .closeStyles(); + xw + .openAutomaticStyles(); + this.styleManager.writeStyles("row-named", xw); + this.styleManager.writeStyles("column-automatic", xw); + this.styleManager.writeDataStyles(xw); + this.styleManager.writeStyles("cell-automatic", xw); + xw + .closeAutomaticStyles() + .openBody() + .openSpreadsheet(xw) + .write(tableXml) + .closeSpreadsheet() + .closeBody(); + if (this.flatOds) { + xw + .closeDocument(); + } else { + xw + .closeDocumentContent(); + } +}; +OpenDocument.OdsConverter.prototype.checkSheetName = function (name) { + if (!name) { + name = "sheet"; + } + name = OpenDocument.checkSheetName(name); + if (!this.nameMap.hasOwnProperty(name)) { + this.nameMap[name] = true; + return name; + } else { + var p = 2; + while (true) { + var newName = name + " (" + p + ")"; + if (!this.nameMap.hasOwnProperty(newName)) { + this.nameMap[newName] = true; + return newName; + } + p++; + } + } +}; +OpenDocument.OdsConverter.readTableColumns = function(table, styleManager) { + let colElementArray = new Array(); + let result = new Array(); + let colgroupList = table.getElementsByTagName("colgroup"); + for(let colgroup of colgroupList) { + let colList = colgroup.getElementsByTagName("col"); + if (colList.length > 0) { + for(let col of colList) { + colElementArray.push(col); + } + } else { + colElementArray.push(colgroup); + } + } + let columnNumber = 1; + for(let col of colElementArray) { + let columnName = OpenDocument.COLUMNSTYLE_PREFIX + columnNumber; + columnNumber++; + let columnStyle = new OpenDocument.Style("column", columnName); + let originalStyleName = _getColumnStyleName(col); + if (originalStyleName) { + let originalStyle = styleManager.getStyle("column-named", originalStyleName); + if (originalStyle) { + columnStyle.copyProperties(originalStyle); + } + } + let customWidth = col.dataset["odWidth"]; + if (customWidth) { + columnStyle.putStyleProperty(OpenDocument.Style.STYLEPROPERTYDEFS["column-width"], customWidth); + } + styleManager.putStyle("column-automatic", columnStyle); + result.push(new OpenDocument.Elements.TableColumn(columnName, col.span, "Standard")); + } + return result; + function _getColumnStyleName(col) { + let styleName = col.dataset["odStyle"];; + if (styleName) { + return styleName; + } + styleName = styleManager.getMatchingStyleName("column", col); + if (styleName) { + return styleName; + } + return ""; + } +}; +OpenDocument.OdsConverter.default_getRowStyleName = function (row, styleManager) { + let styleName = row.dataset["odStyle"]; + if (styleName) { + return styleName; + } + styleName = styleManager.getMatchingStyleName("row", row); + if (styleName) { + return styleName; + } + if ((row.parentNode.tagName) && (row.parentNode.tagName.toLowerCase() === "thead")) { + return "Header"; + } else { + return "Standard"; + } +}; +OpenDocument.OdsConverter.default_getCellStyleName = function (cell, styleManager) { + let styleName = cell.dataset["odStyle"]; + if (styleName) { + return styleName; + } + styleName = styleManager.getMatchingStyleName("cell", cell); + if (styleName) { + return styleName; + } + if (cell.tagName.toLowerCase() === "th") { + return "Header"; + } else { + return "Standard"; + } +}; + + + switch(output) { + case "blob": + return OpenDocument.OdsConverter.convertToBlob(table, options); + case "xml": + return OpenDocument.OdsConverter.convertToXml(table, options); + default: + return null; + } +}; + +Html2Ods.blob = function (table, options) { + return Html2Ods("blob", table, options); +}; + +Html2Ods.xml = function (table, options) { + return Html2Ods("xml", table, options); +};