Last active
January 11, 2021 14:36
-
-
Save fhpriamo/54cbafe92aab44ff1877fd1a156f6baf 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
// | |
// src/lib/html | |
// | |
export const DOCTYPE_TAG = `<!DOCTYPE html>`; | |
const HTML_ESCAPES = { | |
'&': '&', | |
'<': '<', | |
'>': '>', | |
'"': '"', | |
"'": ''', | |
'/': '/', | |
}; | |
const htmlEscaper = /[&<>"'/]/g; | |
export function escape(text) { | |
return `${text}`.replace(htmlEscaper, (match) => { | |
return HTML_ESCAPES[match]; | |
}); | |
} | |
export function attrs(attributes = {}, pad = false) { | |
const attrsStr = Object.entries(attributes) | |
.map(([k, v]) => `${k}="${v}"`) | |
.join(' '); | |
return `${' '.repeat(+pad)}${attrsStr}`; | |
} | |
export function stag(name, attributes) { | |
return `<${name}${attrs(attributes, !!attributes)} />`; | |
} | |
export function ctag(name, content, attributes) { | |
return `<${name}${attrs(attributes, !!attributes)}>${content}</${name}>`; | |
} | |
export function tag(name, content, attributes) { | |
return content != null | |
? ctag(name, content, attributes) | |
: stag(name, attributes); | |
} | |
export function concat(...contents) { | |
return contents.join(''); | |
} | |
// | |
// src/lib/reporters/html-reporter/style.js | |
// | |
const REPORT_STYLE = ` | |
table {\ | |
table-layout: fixed;\ | |
width: 100%;\ | |
border-collapse: collapse;\ | |
border: 3px solid purple;\ | |
}\ | |
thead th:nth-child(1) {\ | |
width: 30%;\ | |
}\ | |
thead th:nth-child(2) {\ | |
width: 20%;\ | |
}\ | |
thead th:nth-child(3) {\ | |
width: 15%;\ | |
}\ | |
thead th:nth-child(4) {\ | |
width: 35%;\ | |
}\ | |
th, td {\ | |
padding: 20px;\ | |
}\ | |
html {\ | |
font-family: 'helvetica neue', helvetica, arial, sans-serif;\ | |
}\ | |
th {\ | |
letter-spacing: 2px;\ | |
}\ | |
td {\ | |
letter-spacing: 1px;\ | |
}\ | |
tbody td {\ | |
text-align: center;\ | |
}\ | |
tfoot th {\ | |
text-align: right;\ | |
}\ | |
thead, tfoot {\ | |
background: grey;\ | |
color: white;\ | |
}\ | |
thead th, tfoot th, tfoot td {\ | |
border: 1px solid black;\ | |
}\ | |
tbody tr:nth-child(odd) {\ | |
background-color: white;\ | |
}\ | |
tbody tr:nth-child(even) {\ | |
background-color: #E0E0E0;\ | |
}\ | |
table {\ | |
background-color: white;\ | |
border-width: 0px;\ | |
}`; | |
// | |
// src/lib/reporters/html-reporter/html.js | |
// | |
function formatTableCols(data) { | |
return data.map((d) => tag('td', escape(d))).join(''); | |
} | |
function formatTableRow(data) { | |
return tag('tr', formatTableCols(data)); | |
} | |
function formatTableRows(data) { | |
return data.map((r) => formatTableRow(r)).join(''); | |
} | |
function formatTableBody(data) { | |
return tag('tbody', formatTableRows(data)); | |
} | |
function formatTableHeaderRow(data) { | |
return tag('tr', formatHeaderCols(data)); | |
} | |
function formatTableHeader(content) { | |
return tag('thead', formatTableHeaderRow(content)); | |
} | |
function formatHeaderCols(data) { | |
return data.map((d) => tag('th', escape(d))).join(''); | |
} | |
function formatTable(header, body) { | |
const content = concat(formatTableHeader(header), formatTableBody(body)); | |
return tag('table', content); | |
} | |
function formatBody(data) { | |
const [header, ...body] = data; | |
return tag('body', formatTable(header, body)); | |
} | |
function formatHead(title, style) { | |
return tag( | |
'head', | |
concat( | |
tag('meta', null, { charset: 'utf-8' }), | |
tag('title', escape(title)), | |
tag('style', style) | |
) | |
); | |
} | |
export function createHtmlReportFormatter({ | |
style = REPORT_STYLE, | |
title = 'Report', | |
} = {}) { | |
return (data) => { | |
return concat( | |
DOCTYPE_TAG, | |
tag('html', concat(formatHead(title, style), formatBody(data))) | |
); | |
}; | |
} | |
// | |
// Exemplo: | |
// | |
const formatHtmlReport = createHtmlReportFormatter({ | |
title: 'Ocorrências 2018-20', | |
}); | |
/** | |
* Simulates data coming from a database or some other external source. | |
*/ | |
function getCrimeData() { | |
return [ | |
['ANO', 'MÊS', 'OCORRÊNCIA', 'DELEGACIA'], | |
[2018, 'Jun', 'Atentado ao pudor', 'DP 110-SP'], | |
[2018, 'Jun', 'Assalto à mão armada', 'DP 235-MG'], | |
[2019, 'Jul', 'Latrocínio', 'DP 522-MT'], | |
[2019, 'Ago', 'Latrocínio', 'DP 707-RJ'], | |
[2020, 'Fev', 'Tentativa de assasinato', 'DP 421-SP'], | |
[2020, 'Jan', 'Tentativa de assasinato', 'DP 235-MG'], | |
[2020, 'Out', 'Homicídio culposo', 'DP 002-MT'], | |
[2020, 'Out', 'Homicídio doloso', 'DP 231-GO'], | |
[2020, 'Out', 'Furto de veículo', 'DP 231-SP'], | |
]; | |
} | |
console.log(formatHtmlReport(getCrimeData())); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment