UNPKG

malevic

Version:

Malevič.js - minimalistic reactive UI library

435 lines (414 loc) 15.7 kB
/* malevic@0.20.2 - Aug 10, 2024 */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.Malevic = global.Malevic || {}, global.Malevic.String = {}))); })(this, (function (exports) { 'use strict'; function createPluginsStore() { var plugins = []; return { add: function (plugin) { plugins.push(plugin); return this; }, apply: function (props) { var result; var plugin; var usedPlugins = new Set(); for (var i = plugins.length - 1; i >= 0; i--) { plugin = plugins[i]; if (usedPlugins.has(plugin)) { continue; } result = plugin(props); if (result != null) { return result; } usedPlugins.add(plugin); } return null; }, delete: function (plugin) { for (var i = plugins.length - 1; i >= 0; i--) { if (plugins[i] === plugin) { plugins.splice(i, 1); break; } } return this; }, empty: function () { return plugins.length === 0; }, }; } function iterateComponentPlugins(type, pairs, iterator) { pairs .filter(function (_a) { var key = _a[0]; return type[key]; }) .forEach(function (_a) { var key = _a[0], plugins = _a[1]; return type[key].forEach(function (plugin) { return iterator(plugins, plugin); }); }); } function addComponentPlugins(type, pairs) { iterateComponentPlugins(type, pairs, function (plugins, plugin) { return plugins.add(plugin); }); } function deleteComponentPlugins(type, pairs) { iterateComponentPlugins(type, pairs, function (plugins, plugin) { return plugins.delete(plugin); }); } function createPluginsAPI(key) { var api = { add: function (type, plugin) { if (!type[key]) { type[key] = []; } type[key].push(plugin); return api; }, }; return api; } function isObject(value) { return value != null && typeof value === 'object'; } function isSpec(x) { return isObject(x) && x.type != null && x.nodeType == null; } function isNodeSpec(x) { return isSpec(x) && typeof x.type === 'string'; } function isComponentSpec(x) { return isSpec(x) && typeof x.type === 'function'; } function classes() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var classes = []; var process = function (c) { if (!c) return; if (typeof c === 'string') { classes.push(c); } else if (Array.isArray(c)) { c.forEach(process); } else if (typeof c === 'object') { classes.push.apply(classes, Object.keys(c).filter(function (key) { return Boolean(c[key]); })); } }; args.forEach(process); return classes.join(' '); } function styles(declarations) { return Object.keys(declarations) .filter(function (cssProp) { return declarations[cssProp] != null; }) .map(function (cssProp) { return "".concat(cssProp, ": ").concat(declarations[cssProp], ";"); }) .join(' '); } function escapeHTML(s) { return s .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#039;'); } var PLUGINS_STRINGIFY_ATTRIBUTE = Symbol(); var pluginsStringifyAttribute = createPluginsStore(); function stringifyAttribute(attr, value) { if (!pluginsStringifyAttribute.empty()) { var result = pluginsStringifyAttribute.apply({ attr: attr, value: value }); if (result != null) { return result; } } if (attr === 'class' && isObject(value)) { var cls = Array.isArray(value) ? classes.apply(void 0, value) : classes(value); return escapeHTML(cls); } if (attr === 'style' && isObject(value)) { return escapeHTML(styles(value)); } if (value === true) { return ''; } return escapeHTML(String(value)); } var PLUGINS_SKIP_ATTRIBUTE = Symbol(); var pluginsSkipAttribute = createPluginsStore(); var specialAttrs = new Set([ 'key', 'oncreate', 'onupdate', 'onrender', 'onremove', ]); function shouldSkipAttribute(attr, value) { if (!pluginsSkipAttribute.empty()) { var result = pluginsSkipAttribute.apply({ attr: attr, value: value }); if (result != null) { return result; } } return (specialAttrs.has(attr) || attr.startsWith('on') || value == null || value === false); } /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; function processText(text) { return escapeHTML(text); } var PLUGINS_IS_VOID_TAG = Symbol(); var pluginsIsVoidTag = createPluginsStore(); function isVoidTag(tag) { if (!pluginsIsVoidTag.empty()) { var result = pluginsIsVoidTag.apply(tag); if (result != null) { return result; } } return voidTags.has(tag); } var voidTags = new Set([ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr', ]); var currentContext = null; function getStringifyContext() { return currentContext; } function unbox(spec) { var Component = spec.type; var props = spec.props, children = spec.children; var prevContext = currentContext; currentContext = {}; var result = Component.apply(void 0, __spreadArray([props], children, false)); currentContext = prevContext; return result; } var stringifyPlugins = [ [PLUGINS_STRINGIFY_ATTRIBUTE, pluginsStringifyAttribute], [PLUGINS_SKIP_ATTRIBUTE, pluginsSkipAttribute], [PLUGINS_IS_VOID_TAG, pluginsIsVoidTag], ]; var VNode = (function () { function VNode() { } return VNode; }()); function leftPad(indent, repeats) { return ''.padEnd(indent.length * repeats, indent); } var VElement = (function (_super) { __extends(VElement, _super); function VElement(spec) { var _this = _super.call(this) || this; _this.children = []; _this.tag = spec.type; _this.attrs = new Map(); Object.entries(spec.props) .filter(function (_a) { var attr = _a[0], value = _a[1]; return !shouldSkipAttribute(attr, value); }) .forEach(function (_a) { var attr = _a[0], value = _a[1]; return _this.attrs.set(attr, stringifyAttribute(attr, value)); }); _this.isVoid = isVoidTag(_this.tag); return _this; } VElement.prototype.stringify = function (_a) { var indent = _a.indent, depth = _a.depth, xmlSelfClosing = _a.xmlSelfClosing; var lines = []; var left = leftPad(indent, depth); var attrs = Array.from(this.attrs.entries()) .map(function (_a) { var attr = _a[0], value = _a[1]; return value === '' ? attr : "".concat(attr, "=\"").concat(value, "\""); }) .join(' '); var isEmptyXML = xmlSelfClosing && this.children.length === 0; var open = "".concat(left, "<").concat(this.tag).concat(attrs ? " ".concat(attrs) : '').concat(isEmptyXML ? '/>' : '>'); if (this.isVoid || isEmptyXML) { lines.push(open); } else { var close_1 = "</".concat(this.tag, ">"); if (this.children.length === 0) { lines.push("".concat(open).concat(close_1)); } else if (this.children.length === 1 && this.children[0] instanceof VText && !this.children[0].text.includes('\n')) { lines.push("".concat(open).concat(this.children[0].stringify({ indent: indent, depth: 0, xmlSelfClosing: xmlSelfClosing, })).concat(close_1)); } else { lines.push(open); this.children.forEach(function (child) { return lines.push(child.stringify({ indent: indent, depth: depth + 1, xmlSelfClosing: xmlSelfClosing, })); }); lines.push("".concat(left).concat(close_1)); } } return lines.join('\n'); }; return VElement; }(VNode)); var VText = (function (_super) { __extends(VText, _super); function VText(text) { var _this = _super.call(this) || this; _this.text = processText(text); return _this; } VText.prototype.stringify = function (_a) { var indent = _a.indent, depth = _a.depth; var left = leftPad(indent, depth); return "".concat(left).concat(this.text.replace(/\n/g, "\n".concat(left))); }; return VText; }(VNode)); var VComment = (function (_super) { __extends(VComment, _super); function VComment(text) { var _this = _super.call(this) || this; _this.text = escapeHTML(text); return _this; } VComment.prototype.stringify = function (_a) { var indent = _a.indent, depth = _a.depth; return "".concat(leftPad(indent, depth), "<!--").concat(this.text, "-->"); }; return VComment; }(VNode)); function addVNodes(spec, parent) { if (isNodeSpec(spec)) { var vnode_1 = new VElement(spec); parent.children.push(vnode_1); spec.children.forEach(function (s) { return addVNodes(s, vnode_1); }); } else if (isComponentSpec(spec)) { if (spec.type === Array) { spec.children.forEach(function (s) { return addVNodes(s, parent); }); } else { addComponentPlugins(spec.type, stringifyPlugins); var result = unbox(spec); addVNodes(result, parent); deleteComponentPlugins(spec.type, stringifyPlugins); } } else if (typeof spec === 'string') { var vnode = new VText(spec); parent.children.push(vnode); } else if (spec == null) { var vnode = new VComment(''); parent.children.push(vnode); } else if (Array.isArray(spec)) { spec.forEach(function (s) { return addVNodes(s, parent); }); } else { throw new Error('Unable to stringify spec'); } } function buildVDOM(spec) { var root = new VElement({ type: 'div', props: {}, children: [] }); addVNodes(spec, root); return root.children; } function stringify(spec, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.indent, indent = _c === void 0 ? ' ' : _c, _d = _b.depth, depth = _d === void 0 ? 0 : _d, _e = _b.xmlSelfClosing, xmlSelfClosing = _e === void 0 ? false : _e; if (isSpec(spec)) { var vnodes = buildVDOM(spec); return vnodes .map(function (vnode) { return vnode.stringify({ indent: indent, depth: depth, xmlSelfClosing: xmlSelfClosing }); }) .join('\n'); } throw new Error('Not a spec'); } var plugins = { stringifyAttribute: createPluginsAPI(PLUGINS_STRINGIFY_ATTRIBUTE), skipAttribute: createPluginsAPI(PLUGINS_SKIP_ATTRIBUTE), isVoidTag: createPluginsAPI(PLUGINS_IS_VOID_TAG), }; function isStringifying() { return getStringifyContext() != null; } exports.escapeHTML = escapeHTML; exports.isStringifying = isStringifying; exports.plugins = plugins; exports.stringify = stringify; }));