//--------------------------------------------------------------------------- // @syndicate-lang/driver-browser-ui, Browser-based UI for Syndicate // Copyright (C) 2016-2018 Tony Garnock-Jones // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . //--------------------------------------------------------------------------- assertion type htmlTag(label, properties, children); assertion type htmlProperty(key, value); assertion type htmlFragment(children); assertion type htmlLiteral(text); export function html(tag, props, ...kids) { if (tag === htmlFragment) { // JSX short syntax for fragments doesn't allow properties, so // props will never have any defined. return htmlFragment(kids); } else { let properties = [] for (let k in props) { properties.push(htmlProperty(k, props[k])); } return htmlTag(tag, properties, kids); } } //--------------------------------------------------------------------------- export function escapeHtml(s) { return s .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } export const emptyHtmlElements = {}; for (let e of "area base br col embed hr img input keygen link meta param source track wbr".split(/ +/)) { emptyHtmlElements[e] = true; } export function htmlToString(j) { let pieces = []; function walk(j) { if (htmlTag.isClassOf(j)) { pieces.push('<', htmlTag._label(j)); htmlTag._properties(j).forEach( (p) => pieces.push(' ', escapeHtml(htmlProperty._key(p)), '="', escapeHtml(htmlProperty._value(p)), '"')); pieces.push('>'); htmlTag._children(j).forEach(walk); if (!(htmlTag._label(j) in emptyHtmlElements)) { pieces.push(''); } } else if (htmlFragment.isClassOf(j)) { htmlFragment._children(j).forEach(walk); } else if (htmlLiteral.isClassOf(j)) { pieces.push(htmlLiteral._text(j)); } else if (typeof j === 'object' && j && typeof j[Symbol.iterator] === 'function') { for (let k of j) { walk(k); } } else { pieces.push(escapeHtml("" + j)); } } walk(j); return pieces.join(''); } export function htmlToNode(j) { var node = document.createElement('div'); node.innerHTML = htmlToString(j); return node.firstChild; }