2020-02-21 20:05:52 -08:00
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
const fs = require('fs-extra');
|
|
|
|
const log = require('fancy-log');
|
2020-03-07 18:04:37 -08:00
|
|
|
const { resolve, readFile, ENGINE, TYPE } = require('./resolve');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
const handybars = require('handybars');
|
|
|
|
const Kit = require('handybars/kit');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-04-07 10:32:23 -07:00
|
|
|
const slugify = require('./lib/slugify');
|
2021-02-27 20:43:09 -08:00
|
|
|
const { stripHtml } = require('string-strip-html');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
const markdownIt = require('markdown-it');
|
2021-08-11 13:48:29 -07:00
|
|
|
const i18n = require('./lang');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2021-08-11 11:48:50 -07:00
|
|
|
const mAnchor = require('markdown-it-anchor');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2022-06-01 00:06:53 -03:00
|
|
|
const dateFNS = require('date-fns');
|
|
|
|
const dateFNSLocales = require('date-fns/locale');
|
|
|
|
const str2locale = {
|
|
|
|
'en': dateFNSLocales.enUS,
|
|
|
|
'zh': dateFNSLocales.zhCN,
|
|
|
|
'de': dateFNSLocales.de,
|
|
|
|
'fr': dateFNSLocales.fr,
|
|
|
|
'hu': dateFNSLocales.hu,
|
|
|
|
'pl': dateFNSLocales.pl,
|
2022-10-23 14:49:09 -03:00
|
|
|
'pt': dateFNSLocales.pt,
|
2022-06-22 15:45:08 -07:00
|
|
|
'es': dateFNSLocales.es,
|
2023-09-21 21:57:10 +02:00
|
|
|
'nl': dateFNSLocales.nl,
|
2024-10-06 11:02:18 -07:00
|
|
|
'ru': dateFNSLocales.ru,
|
2022-06-01 00:06:53 -03:00
|
|
|
};
|
|
|
|
|
2020-02-21 20:05:52 -08:00
|
|
|
const markdownEngines = {
|
|
|
|
full: markdownIt({
|
|
|
|
html: true,
|
|
|
|
linkify: true,
|
|
|
|
typographer: true,
|
|
|
|
})
|
|
|
|
.enable('image')
|
2021-03-25 14:04:43 -07:00
|
|
|
.use(require('markdown-it-link-attributes'), {
|
|
|
|
pattern: /^https?:/,
|
|
|
|
attrs: {
|
|
|
|
target: '_blank',
|
|
|
|
rel: 'noopener',
|
|
|
|
},
|
|
|
|
})
|
2021-08-11 11:48:50 -07:00
|
|
|
.use(mAnchor, {
|
2024-01-07 18:01:48 +00:00
|
|
|
slugify,
|
2021-08-27 11:53:38 -07:00
|
|
|
permalink: mAnchor.permalink.linkInsideHeader({
|
2021-08-11 11:48:50 -07:00
|
|
|
class: 'header-link',
|
|
|
|
symbol: '<img src="/images/svg/paragraph.svg">',
|
2021-08-27 11:53:38 -07:00
|
|
|
ariaHidden: true,
|
2021-08-11 11:48:50 -07:00
|
|
|
}),
|
2020-02-21 20:05:52 -08:00
|
|
|
})
|
2020-03-06 19:30:48 -08:00
|
|
|
.use(require('./lib/markdown-raw-html'), { debug: false }),
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
preview: markdownIt({
|
|
|
|
html: false,
|
|
|
|
linkify: false,
|
|
|
|
typographer: true,
|
|
|
|
})
|
2020-02-28 10:31:13 -08:00
|
|
|
.use(require('./lib/markdown-token-filter')),
|
2020-02-21 20:05:52 -08:00
|
|
|
};
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
function markdown (mode, input, data, hbs) {
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
if (mode === 'preview') {
|
2021-02-27 20:43:09 -08:00
|
|
|
input = stripHtml(input
|
2020-02-21 20:05:52 -08:00
|
|
|
.replace(/<!--\[[\s\S]*?\]-->/g, '')
|
2020-04-07 10:35:10 -07:00
|
|
|
.replace(/æææ[\s\S]*?æææ/gi, '')
|
2023-01-02 14:03:02 -08:00
|
|
|
.replace(/\{!\{([\s\S]*?)\}!\}/mg, '')
|
2020-10-12 13:30:50 -07:00
|
|
|
).result.trim();
|
2020-02-21 20:05:52 -08:00
|
|
|
if (input.length > 1000) input = input.slice(0, 1000) + '…';
|
2020-04-07 10:35:10 -07:00
|
|
|
|
2020-02-21 20:05:52 -08:00
|
|
|
} else {
|
2020-04-07 10:35:10 -07:00
|
|
|
|
|
|
|
input = input.replace(/\{!\{([\s\S]*?)\}!\}/mg, (match, contents) => {
|
2020-05-13 12:29:39 -07:00
|
|
|
const result = hbs(contents, data);
|
|
|
|
return 'æææ' + result + 'æææ';
|
2020-04-07 10:35:10 -07:00
|
|
|
});
|
|
|
|
|
2020-02-21 20:05:52 -08:00
|
|
|
input = input.replace(/<!--[[\]]-->/g, '');
|
|
|
|
}
|
|
|
|
|
2020-03-15 16:49:03 -07:00
|
|
|
try {
|
2020-05-13 11:45:26 -07:00
|
|
|
return input ? markdownEngines[mode].render(input, data) : '';
|
2020-03-15 16:49:03 -07:00
|
|
|
} catch (e) {
|
|
|
|
log(input);
|
|
|
|
throw e;
|
|
|
|
}
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
function stripIndent (input) {
|
|
|
|
const match = input.match(/^[^\S\n]*(?=\S)/gm);
|
|
|
|
const indent = match && Math.min(...match.map((el) => el.length));
|
|
|
|
|
|
|
|
if (indent) {
|
|
|
|
const regexp = new RegExp(`^.{${indent}}`, 'gm');
|
|
|
|
input = input.replace(regexp, '');
|
|
|
|
}
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
const HANDYBARS_PARTIALS = {
|
2020-02-21 20:05:52 -08:00
|
|
|
layout: 'templates/layout.hbs',
|
2020-05-13 11:45:26 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const HANDYBARS_TEMPLATES = {
|
2020-03-07 18:04:37 -08:00
|
|
|
page: 'templates/page.hbs',
|
|
|
|
post: 'templates/post.hbs',
|
2020-02-21 20:05:52 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = exports = async function (prod) {
|
2020-05-13 11:45:26 -07:00
|
|
|
|
|
|
|
const revManifest = prod && await fs.readJson(resolve('rev-manifest.json')).catch(() => {}).then((r) => r || {});
|
|
|
|
const injectables = new Injectables(prod, revManifest);
|
|
|
|
|
|
|
|
const env = { ...Kit, ...injectables.helpers() };
|
|
|
|
|
|
|
|
for (const [ name, file ] of Object.entries(HANDYBARS_PARTIALS)) {
|
2020-02-21 20:05:52 -08:00
|
|
|
try {
|
2020-02-25 19:37:10 -08:00
|
|
|
const contents = await readFile(file);
|
2020-05-13 11:45:26 -07:00
|
|
|
env[name] = handybars.partial(contents.toString('utf8'));
|
2020-02-21 20:05:52 -08:00
|
|
|
} catch (e) {
|
2020-05-13 11:45:26 -07:00
|
|
|
log.error('Could not load partial ' + file, e);
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
const templates = {};
|
|
|
|
for (const [ name, file ] of Object.entries(HANDYBARS_TEMPLATES)) {
|
|
|
|
try {
|
|
|
|
const contents = await readFile(file);
|
|
|
|
templates[name] = handybars(contents.toString('utf8'), env);
|
|
|
|
} catch (e) {
|
2020-05-13 12:29:39 -07:00
|
|
|
log.error('Could not load template ' + file, e);
|
2020-05-13 11:45:26 -07:00
|
|
|
}
|
|
|
|
}
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
const hbs = (source, data) => handybars(source, env)(data);
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
const result = {
|
2020-05-13 12:29:39 -07:00
|
|
|
[TYPE.HANDYBARS]: hbs,
|
2020-05-13 11:45:26 -07:00
|
|
|
[TYPE.MARKDOWN]: (source, data) => markdown('full', source, data, hbs),
|
2020-03-07 18:04:37 -08:00
|
|
|
[TYPE.OTHER]: (source) => source,
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
[ENGINE.PAGE]: (source, data) => templates.page({ ...data, contents: markdown('full', source, data, hbs) }),
|
|
|
|
[ENGINE.POST]: (source, data) => templates.post({ ...data, contents: markdown('full', source, data, hbs) }),
|
2020-04-07 10:35:10 -07:00
|
|
|
[ENGINE.HTML]: (source) => source,
|
2020-03-07 18:04:37 -08:00
|
|
|
[ENGINE.OTHER]: (source) => source,
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
preview: (source, data) => markdown('preview', source, data, hbs),
|
2020-02-21 20:05:52 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Injectables {
|
|
|
|
|
|
|
|
constructor (prod, revManifest) {
|
|
|
|
this.prod = prod;
|
|
|
|
this.revManifest = revManifest;
|
|
|
|
this.injections = {};
|
2021-08-11 11:23:59 -07:00
|
|
|
this.languages = {};
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
_parsePath (tpath, local, type) {
|
2020-02-25 19:37:10 -08:00
|
|
|
if (tpath[0] === '/') tpath = resolve(tpath.slice(1));
|
|
|
|
else if (tpath[0] === '~') tpath = resolve('templates', tpath.slice(2));
|
2020-02-21 20:05:52 -08:00
|
|
|
else tpath = path.resolve(local.cwd, tpath);
|
|
|
|
if (type && !tpath.endsWith(type)) tpath += '.' + type;
|
|
|
|
return tpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
_template (tpath, make) {
|
2020-02-27 18:57:39 -08:00
|
|
|
if (!tpath) throw new Error('Received an empty template path: ' + tpath);
|
2020-02-21 20:05:52 -08:00
|
|
|
if (this.injections[tpath]) return this.injections[tpath];
|
|
|
|
|
|
|
|
if (!fs.existsSync(tpath)) {
|
2020-02-27 18:57:39 -08:00
|
|
|
throw new Error('Injectable does not exist: ' + tpath);
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
let contents;
|
|
|
|
try {
|
|
|
|
contents = fs.readFileSync(tpath).toString('utf8');
|
|
|
|
if (make) contents = make(contents);
|
|
|
|
this.injections[tpath] = contents;
|
|
|
|
return contents;
|
|
|
|
} catch (e) {
|
2020-02-25 19:37:10 -08:00
|
|
|
log.error(e, 'An error occured while loading the injectable: ' + tpath);
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
helpers () {
|
|
|
|
return {
|
2022-06-01 00:06:53 -03:00
|
|
|
import: this.import(),
|
|
|
|
markdown: this.markdown(),
|
|
|
|
icon: this.icon(),
|
|
|
|
coalesce: this.coalesce(),
|
|
|
|
prod: this.production(),
|
|
|
|
rev: this.rev(),
|
|
|
|
lang: this.lang(),
|
|
|
|
date: this.date(),
|
2020-05-13 11:45:26 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-02-21 20:05:52 -08:00
|
|
|
rev () {
|
|
|
|
const self = this;
|
|
|
|
return function (url) {
|
|
|
|
if (!url) return '';
|
|
|
|
if (url[0] === '/') url = url.substr(1);
|
|
|
|
if (self.prod && self.revManifest[url]) return '/' + self.revManifest[url];
|
|
|
|
return '/' + url;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
production () {
|
|
|
|
const self = this;
|
2020-05-13 11:45:26 -07:00
|
|
|
return function ({ fn, inverse }) {
|
|
|
|
if (!fn) return self.prod;
|
|
|
|
return self.prod ? fn(this) : inverse && inverse(this);
|
2020-02-21 20:05:52 -08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
markdown () {
|
|
|
|
const self = this;
|
|
|
|
return function (...args) {
|
2020-05-13 11:45:26 -07:00
|
|
|
const { fn, data, resolve: rval } = args.pop();
|
|
|
|
const local = rval('@root.this.local');
|
2020-02-21 20:05:52 -08:00
|
|
|
let contents;
|
|
|
|
|
|
|
|
if (fn) {
|
2020-03-05 19:40:18 -08:00
|
|
|
contents = stripIndent(fn(data.root));
|
2020-02-21 20:05:52 -08:00
|
|
|
} else {
|
|
|
|
let tpath = args.shift();
|
2020-05-13 11:45:26 -07:00
|
|
|
tpath = self._parsePath(tpath, local, 'md');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
contents = self._template(tpath);
|
|
|
|
}
|
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
contents = markdown('full', contents, data, () => { throw new Error('You went too deep!'); });
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
return { value: contents };
|
2020-02-21 20:05:52 -08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
import () {
|
|
|
|
const self = this;
|
|
|
|
return function (tpath, ...args) {
|
2020-05-13 11:45:26 -07:00
|
|
|
const { hash, env, resolve: rval } = args.pop();
|
2020-04-07 10:35:10 -07:00
|
|
|
const value = args.shift() || this;
|
2020-05-13 11:45:26 -07:00
|
|
|
const frame = handybars.makeContext(value, env, { hash });
|
|
|
|
const local = rval('@root.this.local');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
tpath = self._parsePath(tpath, local, 'hbs');
|
2020-02-21 20:05:52 -08:00
|
|
|
|
|
|
|
try {
|
2020-05-13 11:45:26 -07:00
|
|
|
const contents = self._template(tpath, handybars.parse).evaluate(value, frame);
|
|
|
|
return handybars.safe(contents);
|
2020-02-21 20:05:52 -08:00
|
|
|
} catch (e) {
|
2020-02-27 18:57:39 -08:00
|
|
|
log.error('Could not execute import template ' + tpath, e);
|
2020-02-21 20:05:52 -08:00
|
|
|
return '';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
icon () {
|
|
|
|
const self = this;
|
|
|
|
return function (name, ...args) {
|
2020-05-13 11:45:26 -07:00
|
|
|
const { hash, env, resolve: rval } = args.pop();
|
|
|
|
const local = rval('@root.this.local');
|
|
|
|
const tpath = path.join(local.root, 'svg', name + '.svg');
|
2021-03-25 14:04:59 -07:00
|
|
|
if (hash.size && String(hash.size).match(/^\d+$/)) {
|
|
|
|
hash.size = hash.size + 'px';
|
|
|
|
}
|
2020-05-13 11:45:26 -07:00
|
|
|
const frame = handybars.makeContext(hash, env);
|
2020-02-21 20:05:52 -08:00
|
|
|
try {
|
|
|
|
const contents = self._template(tpath, (s) =>
|
2023-01-02 14:03:02 -08:00
|
|
|
handybars(`<span class="svg-icon" style="{{#if this.size}}width:{{this.size}};height:{{this.size}};{{/if}}{{this.style}}">${s}</span>`)
|
2020-05-13 11:45:26 -07:00
|
|
|
)(frame);
|
2020-02-21 20:05:52 -08:00
|
|
|
|
2020-05-13 11:45:26 -07:00
|
|
|
return handybars.safe(contents);
|
2020-02-21 20:05:52 -08:00
|
|
|
} catch (e) {
|
2020-02-27 18:57:39 -08:00
|
|
|
log.error('Could not execute import template ' + tpath, e);
|
2020-02-21 20:05:52 -08:00
|
|
|
return '';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-08-11 11:23:59 -07:00
|
|
|
lang () {
|
|
|
|
return function (key, ...args) {
|
|
|
|
const { resolve: rval } = args.pop();
|
|
|
|
const lang = rval('@root.this.page.lang').split('-')[0];
|
|
|
|
return i18n(lang, key, ...args);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-06-22 15:45:08 -07:00
|
|
|
// Given a list of arguments, returns the first that isn't undefined
|
2022-06-01 00:06:53 -03:00
|
|
|
coalesce () {
|
|
|
|
return function (...raw_args) {
|
|
|
|
const { arguments: args } = raw_args.pop();
|
2022-06-22 15:45:08 -07:00
|
|
|
|
|
|
|
for (const value of Object.values(args)) {
|
|
|
|
if (value !== undefined) {
|
|
|
|
return value;
|
2022-06-01 00:06:53 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Multi tool for printing dates
|
2022-06-22 15:45:08 -07:00
|
|
|
//
|
2022-06-01 00:06:53 -03:00
|
|
|
// {{date}} -> prints current date
|
|
|
|
// {{date datestr}} -> prints date in datestr
|
|
|
|
// {{date datestr datefmt}} -> prints date in datestr in format datefmt
|
2022-06-22 15:45:08 -07:00
|
|
|
// {{date datestr datefmt lang}} -> prints date in datestr in format datefmt according to conventions for language lang
|
|
|
|
//
|
2022-06-01 00:06:53 -03:00
|
|
|
// Datestr can be the string "now", `undefined`, and anything parsable by `new Date()`.
|
2022-06-22 15:45:08 -07:00
|
|
|
//
|
2022-06-01 00:06:53 -03:00
|
|
|
// If lang is not specified, it will be extracted from the page metadata. If that is not available, English will be assumed.
|
|
|
|
// In case of errors, the date will be returned as an ISO string if possible and its raw datestr input otherwise.
|
|
|
|
// Datefmt format is available at https://date-fns.org/v2.25.0/docs/format
|
2022-06-22 15:45:08 -07:00
|
|
|
//
|
2022-06-01 00:06:53 -03:00
|
|
|
// Common formats:
|
|
|
|
// - "h:mm aa - EEE, LLL do, yyyy" = 12 hour clock, e.g. '1:28 PM - Sat, Feb 15th, 2020' (en) or '1:28 PM - sam., 15/févr./2020' (fr)
|
|
|
|
// - "hh:mm - EEE, LLL do, yyyy" = 24 hour clock, e.g. '13:28 - Sat, Feb 15th, 2020' (en) or '13:28 - sam., 15/févr./2020' (fr)
|
|
|
|
// - "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" or "iso" = ISO 8601 format, e.g. '2020-02-15T13:28:02.000Z'
|
|
|
|
date () {
|
|
|
|
return function (...args) {
|
2022-06-22 15:45:08 -07:00
|
|
|
const extra = args.pop();
|
2022-06-01 00:06:53 -03:00
|
|
|
let datestr, dateobj, datefmt, lang;
|
|
|
|
|
|
|
|
const { resolve: rval } = extra;
|
|
|
|
const filename = rval('@value.input');
|
|
|
|
lang = (rval('@root.this.page.lang') || 'en').split('-')[0];
|
|
|
|
|
|
|
|
switch (args.length) {
|
|
|
|
case 0:
|
2022-06-22 15:45:08 -07:00
|
|
|
datestr = 'now';
|
2022-06-01 00:06:53 -03:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
datestr = args[0];
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
datestr = args[0];
|
|
|
|
datefmt = args[1];
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
datestr = args[0];
|
|
|
|
datefmt = args[1];
|
|
|
|
lang = args[2];
|
|
|
|
break;
|
|
|
|
default:
|
2022-06-22 15:45:08 -07:00
|
|
|
throw new Error('wrong number of arguments for {{date}}, got ' + args.length + ' maximum is 3');
|
2022-06-01 00:06:53 -03:00
|
|
|
}
|
|
|
|
|
2022-06-22 15:45:08 -07:00
|
|
|
if (datestr === 'now' || datestr === undefined) {
|
2022-06-01 00:06:53 -03:00
|
|
|
dateobj = new Date();
|
|
|
|
} else {
|
|
|
|
dateobj = new Date(datestr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dateFNS.isValid(dateobj)) {
|
2022-06-22 15:45:08 -07:00
|
|
|
log.error('Invalid input for date: ', { datestr, filename, args, extra });
|
2022-06-01 00:06:53 -03:00
|
|
|
return datestr.toString();
|
|
|
|
}
|
|
|
|
|
2022-06-22 15:45:08 -07:00
|
|
|
if (datefmt === 'iso') {
|
2022-06-01 00:06:53 -03:00
|
|
|
return dateobj.toISOString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lang === undefined) {
|
|
|
|
return dateobj.toISOString();
|
|
|
|
}
|
|
|
|
|
|
|
|
const locale = str2locale[lang];
|
|
|
|
if (locale === undefined) {
|
2022-06-22 15:45:08 -07:00
|
|
|
log.warn('Locale not found: ' + lang);
|
2022-06-01 00:06:53 -03:00
|
|
|
}
|
|
|
|
if (datefmt === undefined || locale === undefined) {
|
|
|
|
const options = {
|
|
|
|
weekday: 'short',
|
|
|
|
year: 'numeric',
|
|
|
|
month: 'short',
|
|
|
|
day: 'numeric',
|
|
|
|
timeZone: 'UTC',
|
|
|
|
timeZoneName: 'short',
|
|
|
|
hour: '2-digit',
|
|
|
|
minute: '2-digit',
|
2022-06-22 15:45:08 -07:00
|
|
|
second: '2-digit',
|
2022-06-01 00:06:53 -03:00
|
|
|
};
|
|
|
|
try {
|
|
|
|
return dateobj.toLocaleString(lang, options);
|
|
|
|
} catch (error) {
|
2022-06-22 15:45:08 -07:00
|
|
|
log.error('Something went horribly wrong while formating dates.', { error, filename, args, extra });
|
2022-06-01 00:06:53 -03:00
|
|
|
return dateobj.toISOString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2022-06-22 15:45:08 -07:00
|
|
|
return dateFNS.format(dateobj, datefmt, { locale });
|
2022-06-01 00:06:53 -03:00
|
|
|
} catch (error) {
|
2022-06-22 15:45:08 -07:00
|
|
|
log.error('Something went horribly wrong while formating dates.', { error, filename, args, extra });
|
2022-06-01 00:06:53 -03:00
|
|
|
return dateobj.toISOString();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-02-21 20:05:52 -08:00
|
|
|
}
|