Created
April 11, 2019 17:29
-
-
Save friendlyanon/04e15b877c5a2ef7563247dc25962e77 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const csvEscape = function() { | |
const map = { | |
";": ",", | |
"\n": "\\n" | |
}; | |
const replacerRe = /./gsm; | |
const replacer = x => `\\x${x.charCodeAt(0).toString(16).padStart(2, 0)}`; | |
const escaped = Object.keys(map).map(x => x.replace(replacerRe, replacer)); | |
const escapeRe = new RegExp(escaped.join("|"), "g"); | |
const escape = x => map[x]; | |
return el => { | |
const span = el.getAttribute("colspan") | 0; | |
const escaped = el.textContent.trim().replace(escapeRe, escape); | |
return span < 2 ? escaped : Array(span).fill(escaped).join(";"); | |
}; | |
}(); | |
function processRow({ children: row }) { | |
const length = row.length; | |
if (!length) return ""; | |
const str = length > 50 ? Array(length) : []; | |
str[0] = csvEscape(row[0]); | |
for (let i = 1; i < length; ++i) { | |
str[i] = `;${csvEscape(row[i])}`; | |
} | |
return str.join(""); | |
} | |
function processHead(table, target) { | |
const { tHead } = table; | |
if (!tHead) return; | |
const { rows } = tHead; | |
switch (rows.length) { | |
case 0: return; | |
case 1: break; | |
default: throw new RangeError("can't have more than one head row"); | |
} | |
target.push(processRow(rows[0])); | |
} | |
function processBodies(table, target) { | |
for (const body of table.tBodies) { | |
for (const row of body.children) { | |
if (row.tagName === "TR") { | |
target.push(processRow(row)); | |
} | |
} | |
} | |
} | |
function processFoot(table, target) { | |
const { tFoot } = table; | |
if (!tFoot) return; | |
for (const row of tFoot.rows) { | |
target.push(processRow(row)); | |
} | |
} | |
export default function tableToCsv(table) { | |
if (table == null || table.tagName !== "TABLE") { | |
throw new TypeError("invalid argument"); | |
} | |
const result = []; | |
processHead(table, result); | |
processBodies(table, result); | |
processFoot(table, result); | |
return result.join("\n"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment