2020-12-24 04:57:46 +00:00
|
|
|
import marked, { MarkedOptions } from 'marked';
|
|
|
|
import { Field } from "facilmap-types";
|
2021-02-28 22:17:26 +00:00
|
|
|
import { createDiv, $ } from './dom';
|
|
|
|
import { normalizeField } from './filter';
|
2021-03-06 08:11:34 +00:00
|
|
|
import { quoteHtml } from './utils';
|
2021-03-13 09:43:32 +00:00
|
|
|
import linkifyStr from 'linkifyjs/string';
|
2021-03-13 23:54:10 +00:00
|
|
|
import { sanitize } from 'dompurify';
|
2020-12-24 04:57:46 +00:00
|
|
|
|
|
|
|
marked.setOptions({
|
2021-03-13 23:54:10 +00:00
|
|
|
breaks: true
|
2020-12-24 04:57:46 +00:00
|
|
|
});
|
|
|
|
|
2021-01-23 11:38:26 +00:00
|
|
|
export function formatField(field: Field, value: string): string {
|
2020-12-24 04:57:46 +00:00
|
|
|
value = normalizeField(field, value, false);
|
|
|
|
switch(field.type) {
|
|
|
|
case "textarea":
|
|
|
|
return markdownBlock(value);
|
|
|
|
case "checkbox":
|
|
|
|
return value == "1" ? "✔" : "✘";
|
|
|
|
case "dropdown":
|
2021-03-06 08:11:34 +00:00
|
|
|
return quoteHtml(value) || "";
|
2020-12-24 04:57:46 +00:00
|
|
|
case "input":
|
|
|
|
default:
|
|
|
|
return markdownInline(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 11:38:26 +00:00
|
|
|
export function markdownBlock(string: string, options?: MarkedOptions): string {
|
2021-02-28 22:17:26 +00:00
|
|
|
const ret = createDiv();
|
2021-03-13 23:54:10 +00:00
|
|
|
ret.html(sanitize(marked(string, options)));
|
2021-02-28 22:17:26 +00:00
|
|
|
applyMarkdownModifications(ret);
|
2021-01-23 11:38:26 +00:00
|
|
|
return ret.html()!;
|
2020-12-24 04:57:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-23 11:38:26 +00:00
|
|
|
export function markdownInline(string: string, options?: MarkedOptions): string {
|
2021-02-28 22:17:26 +00:00
|
|
|
const ret = createDiv();
|
2021-03-13 23:54:10 +00:00
|
|
|
ret.html(sanitize(marked(string, options)));
|
2020-12-24 17:51:21 +00:00
|
|
|
$("p", ret).replaceWith(function(this: cheerio.Element) { return $(this).contents(); });
|
2021-02-28 22:17:26 +00:00
|
|
|
applyMarkdownModifications(ret);
|
2021-01-23 11:38:26 +00:00
|
|
|
return ret.html()!;
|
2020-12-24 04:57:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-23 11:38:26 +00:00
|
|
|
export function round(number: number, digits: number): number {
|
2020-12-24 04:57:46 +00:00
|
|
|
const fac = Math.pow(10, digits);
|
|
|
|
return Math.round(number*fac)/fac;
|
|
|
|
}
|
|
|
|
|
2021-01-23 11:38:26 +00:00
|
|
|
export function formatTime(seconds: number): string {
|
2020-12-24 04:57:46 +00:00
|
|
|
const hours = Math.floor(seconds/3600);
|
|
|
|
let minutes: string | number = Math.floor((seconds%3600)/60);
|
|
|
|
if(minutes < 10)
|
|
|
|
minutes = "0" + minutes;
|
|
|
|
return hours + ":" + minutes;
|
|
|
|
}
|
|
|
|
|
2021-02-28 22:17:26 +00:00
|
|
|
function applyMarkdownModifications($el: cheerio.Cheerio): void {
|
2020-12-24 04:57:46 +00:00
|
|
|
$("a[href]", $el).attr({
|
|
|
|
target: "_blank",
|
|
|
|
rel: "noopener noreferer"
|
|
|
|
});
|
|
|
|
|
2021-02-28 22:17:26 +00:00
|
|
|
|
2020-12-24 17:51:21 +00:00
|
|
|
$("a[href^='mailto:']", $el).each(function(this: cheerio.Element) {
|
2020-12-24 04:57:46 +00:00
|
|
|
const $a = $(this);
|
|
|
|
let m = $a.attr("href")!.match(/^mailto:(.*)@(.*)$/i);
|
|
|
|
if(m) {
|
|
|
|
$a.attr({
|
|
|
|
href: "#",
|
|
|
|
"data-u": m[1],
|
|
|
|
"data-d": m[2]
|
|
|
|
}).addClass("emobf");
|
|
|
|
}
|
|
|
|
|
|
|
|
m = $a.text().match(/^(.*)@(.*)$/);
|
|
|
|
if(m && $a.children().length == 0) {
|
|
|
|
$a.attr({
|
|
|
|
"data-u2": m[1],
|
|
|
|
"data-d2": m[2]
|
|
|
|
}).addClass("emobf2").html("<span>[obfuscated]</span>");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2021-03-13 09:43:32 +00:00
|
|
|
|
|
|
|
export function renderOsmTag(key: string, value: string): string {
|
|
|
|
if(key.match(/^wikipedia(:|$)/)) {
|
|
|
|
return value.split(";").map((it) => {
|
|
|
|
const m = it.match(/^(\s*)((([-a-z]+):)?(.*))(\s*)$/)!;
|
|
|
|
const url = "https://" + (m[4] || "en") + ".wikipedia.org/wiki/" + m[5];
|
|
|
|
return m?.[1] + '<a href="' + quoteHtml(url) + '" target="_blank">' + quoteHtml(m[2]) + '</a>' + m[6];
|
|
|
|
}).join(";");
|
|
|
|
} else if(key.match(/^wikidata(:|$)/)) {
|
|
|
|
return value.split(";").map((it) => {
|
|
|
|
const m = it.match(/^(\s*)(.*?)(\s*)$/)!;
|
|
|
|
return m[1] + '<a href="https://www.wikidata.org/wiki/' + quoteHtml(m[2]) + '" target="_blank">' + quoteHtml(m[2]) + '</a>' + m[3];
|
|
|
|
}).join(";");
|
|
|
|
} else if(key.match(/^wiki:symbol(:$)/)) {
|
|
|
|
return value.split(";").map(function(it) {
|
|
|
|
var m = it.match(/^(\s*)(.*?)(\s*)$/)!;
|
|
|
|
return m[1] + '<a href="https://wiki.openstreetmap.org/wiki/Image:' + quoteHtml(m[2]) + '" target="_blank">' + quoteHtml(m[2]) + '</a>' + m[3];
|
|
|
|
}).join(";");
|
|
|
|
} else {
|
|
|
|
return linkifyStr(value);
|
|
|
|
}
|
|
|
|
}
|