X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Ftemplate-helper.js;h=c983e80acd44329fc6c516ee874198fc2d2e6e58;hb=826ef55e1f8506012d627294c8225cf8b01a5a69;hp=c61958db9a31a67ae34b84dea72edfa6a4e125f0;hpb=885150f50a04b408bfadc3a818615da066908344;p=squeep-html-template-helper diff --git a/lib/template-helper.js b/lib/template-helper.js index c61958d..c983e80 100644 --- a/lib/template-helper.js +++ b/lib/template-helper.js @@ -4,6 +4,8 @@ * A bunch of shorthand to put together common parts of an HTML page. */ +const { lazy } = require('@squeep/lazy-property'); + /** * Some fields may have values outside normal dates, handle them here. * @param {Date} date @@ -25,6 +27,71 @@ const dateOrNot = (date, otherwise) => { }; +/** + * Why is rendering a Date as a string this complicated? + * We handle the infinities because pg-promise might provide those in + * lieu of a Date object from timestamp fields. + * @param {Date|Number|String} date + * @param {String=} pInf + * @param {String=} nInf + * @param {String=} otherwise + */ +const dateFormat = (date, pInf = 'Never', nInf = 'Forever', otherwise = '') => { + const isDatableType = ['number', 'string'].includes(typeof date); + switch (date) { + case Infinity: + return pInf; + case -Infinity: + return nInf; + default: + if (!date + || Number.isNaN(date.valueOf()) + || (!(date instanceof Date) && !isDatableType)) { + return otherwise; + } + } + if (isDatableType) { + date = new Date(date); + } + const parts = dateFormat._dtf.formatToParts(date); + return parts.map((p) => p.value).join(''); +}; +lazy(dateFormat, '_dtf', () => { + const dateTimeFormatOptions = { + dateStyle: 'medium', + timeStyle: 'long', + }; + return new Intl.DateTimeFormat(undefined, dateTimeFormatOptions); +}); + + +/** + * Wrap a Date in a ', + ].join(''); +} + + /** * Render a duration. * @param {Number} seconds @@ -53,6 +120,17 @@ const secondsToPeriod = (seconds) => { }; +/** + * Return array of strings prefixed with tabs. + * @param {Number} indent + * @param {String[]} list + */ +const indented = (indent, list) => { + const spacer = '\t'.repeat(indent); + return list.map((l) => `${spacer}${l}`); +}; + + /** * Render the preamble for an HTML page. * @param {Number} pagePathLevel number of paths below root this page is @@ -71,8 +149,8 @@ function htmlHead(pagePathLevel, ctx, options) { return `\t \t\t \t\t -\t\t -\t\t +\t\t +\t\t ${headElements.map((e) => '\t\t' + e).join('\n')} \t\t${pageTitle} \t`; @@ -315,6 +393,8 @@ function htmlPage(pagePathLevel, ctx, options, main = []) { module.exports = { dateOrNot, + dateFormat, + timeElement, secondsToPeriod, htmlHead, htmlBody, @@ -322,6 +402,7 @@ module.exports = { htmlHeader, htmlFooter, htmlMessages, + indented, renderNavLink, LI, UL,