functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
62 lines (61 loc) • 1.9 kB
JavaScript
import { map, flatMap, flat, concat as listConcat } from "../types/list/module.f.js";
import { concat as stringConcat } from "../types/string/module.f.js";
import { compose } from "../types/function/module.f.js";
import { stringToList } from "../text/utf16/module.f.js";
const { fromCharCode } = String;
const { entries } = Object;
/**
* Void Elements
*
* https://developer.mozilla.org/en-US/docs/Glossary/Void_element
*/
const voidTagList = [
'area',
'base',
'br',
'col',
'embed',
'hr',
'img',
'input',
'link',
'meta',
'param',
'source',
'track',
'wbr',
];
/**
* https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html
*/
const escapeCharCode = (code) => {
switch (code) {
case 0x22: return '"';
case 0x26: return '&';
case 0x3C: return '<';
case 0x3E: return '>';
default: return fromCharCode(code);
}
};
const escape = compose(stringToList)(map(escapeCharCode));
const node = (n) => typeof n === 'string' ? escape(n) : element(n);
const nodes = flatMap(node);
const attribute = ([name, value]) => flat([[' ', name, '="'], escape(value), ['"']]);
const attributes = compose(entries)(flatMap(attribute));
const parseElement = (e) => {
const [tag, item1, ...list] = e;
return item1 === undefined ?
[tag, {}, []] :
typeof item1 === 'object' && !(item1 instanceof Array) ?
[tag, item1, list] :
[tag, {}, [item1, ...list]];
};
export const element = (e) => {
const [tag, a, n] = parseElement(e);
const open = flat([[`<`, tag], attributes(a), [`>`]]);
return voidTagList.includes(tag) ?
open :
flat([open, nodes(n), ['</', tag, '>']]);
};
export const html = compose(element)(listConcat(['<!DOCTYPE html>']));
export const htmlToString = compose(html)(stringConcat);