@krakenjs/jsx-pragmatic
Advanced tools
Comparing version 3.0.0 to 3.1.0
@@ -5,2 +5,22 @@ # Changelog | ||
## [3.1.0](https://github.com/krakenjs/jsx-pragmatic/compare/v3.0.0...v3.1.0) (2024-09-23) | ||
### Features | ||
* commit flow-typed folder ([#37](https://github.com/krakenjs/jsx-pragmatic/issues/37)) ([170604c](https://github.com/krakenjs/jsx-pragmatic/commit/170604ca9c383308b2ce284b3806393577df1f20)) | ||
* upgrade to grumbler scripts 8 ([#33](https://github.com/krakenjs/jsx-pragmatic/issues/33)) ([e8e202e](https://github.com/krakenjs/jsx-pragmatic/commit/e8e202e3ea2978b125145dd3563097ab37e15ef8)) | ||
### Bug Fixes | ||
* **iframe:** add empty srcdoc attribute to iframe elem if not exist ([#36](https://github.com/krakenjs/jsx-pragmatic/issues/36)) ([b21a468](https://github.com/krakenjs/jsx-pragmatic/commit/b21a46826fe3369ded96cbba6dfd44b955a87a34)) | ||
* **docs:** update github actions badge url ([3b4ed67](https://github.com/krakenjs/jsx-pragmatic/commit/3b4ed67cb0a95c06a6e4c6c10355ce1579eae10f)) | ||
* move devDependencies to [@krakenjs](https://github.com/krakenjs) scope ([#28](https://github.com/krakenjs/jsx-pragmatic/issues/28)) ([c21fe35](https://github.com/krakenjs/jsx-pragmatic/commit/c21fe356071e76e9e70d5ce220ccd41cb9f0fef4)) | ||
* remove quotes from publish ([d7d154a](https://github.com/krakenjs/jsx-pragmatic/commit/d7d154aaafc968c563c83ac8bd12dab3de4aa0ea)) | ||
* remove token from publish action ([00b0073](https://github.com/krakenjs/jsx-pragmatic/commit/00b0073e42aa4968ebe0ef7fe6400efd1f2be8aa)) | ||
* use prettier ([#30](https://github.com/krakenjs/jsx-pragmatic/issues/30)) ([4826e52](https://github.com/krakenjs/jsx-pragmatic/commit/4826e521d3b0c886a2c6063671ecd96d8cb9b66a)) | ||
## [3.0.0](https://github.com/krakenjs/jsx-pragmatic/compare/v2.0.22...v3.0.0) (2022-02-28) | ||
@@ -7,0 +27,0 @@ |
@@ -197,2 +197,3 @@ !function(root, factory) { | ||
}))); | ||
"iframe" !== el.tagName.toLowerCase() || props.srcdoc || props.src || el.setAttribute("srcdoc", ""); | ||
} | ||
@@ -211,24 +212,25 @@ var ADD_CHILDREN = ((_ADD_CHILDREN = {}).iframe = function(el, node) { | ||
var _opts$doc = opts.doc, doc = void 0 === _opts$doc ? document : _opts$doc; | ||
return function domRenderer(node) { | ||
if ("component" === node.type) return node.renderComponent(domRenderer); | ||
var _xmlNamespaceDomRenderer = function(node, xmlNamespace) { | ||
if ("component" === node.type) return node.renderComponent((function(childNode) { | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
if ("text" === node.type) return createTextElement(doc, node); | ||
if ("element" === node.type) { | ||
var el = function(doc, node, xmlNamespace) { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
}(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, (function(childNode) { | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
var _domRenderer = function(node) { | ||
if ("component" === node.type) return node.renderComponent(_domRenderer); | ||
if ("text" === node.type) return createTextElement(doc, node); | ||
if ("element" === node.type) { | ||
var xmlNamespace = ELEMENT_DEFAULT_XML_NAMESPACE[node.name.toLowerCase()]; | ||
if (xmlNamespace) return function xmlNamespaceDomRenderer(node, xmlNamespace) { | ||
if ("component" === node.type) return node.renderComponent((function(childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
if ("text" === node.type) return createTextElement(doc, node); | ||
if ("element" === node.type) { | ||
var el = function(doc, node, xmlNamespace) { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
}(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, (function(childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}(node, xmlNamespace); | ||
if (xmlNamespace) return _xmlNamespaceDomRenderer(node, xmlNamespace); | ||
var el = function(doc, node) { | ||
@@ -238,3 +240,3 @@ return node.props.el ? node.props.el : doc.createElement(node.name); | ||
addProps(el, node); | ||
addChildren(el, node, doc, domRenderer); | ||
addChildren(el, node, doc, _domRenderer); | ||
return el; | ||
@@ -244,2 +246,3 @@ } | ||
}; | ||
return _domRenderer; | ||
}({ | ||
@@ -280,9 +283,11 @@ doc: doc | ||
function regex() { | ||
var regexRenderer = _textRenderer = function(node) { | ||
if ("component" === node.type) return [].concat(node.renderComponent(_textRenderer)).join(""); | ||
if ("element" === node.type) throw new Error("Text renderer does not support basic elements"); | ||
if ("text" === node.type) return node.text; | ||
throw new TypeError("Unhandleable node: " + node.type); | ||
}; | ||
var _textRenderer; | ||
return function(nodeInstance) { | ||
return new RegExp(function textRenderer(node) { | ||
if ("component" === node.type) return [].concat(node.renderComponent(textRenderer)).join(""); | ||
if ("element" === node.type) throw new Error("Text renderer does not support basic elements"); | ||
if ("text" === node.type) return node.text; | ||
throw new TypeError("Unhandleable node: " + node.type); | ||
}(nodeInstance)); | ||
return new RegExp(regexRenderer(nodeInstance)); | ||
}; | ||
@@ -289,0 +294,0 @@ } |
@@ -243,4 +243,4 @@ !function(root, factory) { | ||
function text_text() { | ||
return function textRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return [].concat(node.renderComponent(textRenderer)).join(""); | ||
var _textRenderer = function(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return [].concat(node.renderComponent(_textRenderer)).join(""); | ||
if (node.type === NODE_TYPE.ELEMENT) throw new Error("Text renderer does not support basic elements"); | ||
@@ -250,2 +250,3 @@ if (node.type === NODE_TYPE.TEXT) return node.text; | ||
}; | ||
return _textRenderer; | ||
} | ||
@@ -276,2 +277,3 @@ function isDefined(val) { | ||
}))); | ||
"iframe" !== el.tagName.toLowerCase() || props.srcdoc || props.src || el.setAttribute("srcdoc", ""); | ||
} | ||
@@ -324,24 +326,25 @@ var ADD_CHILDREN = ((_ADD_CHILDREN = {}).iframe = function(el, node) { | ||
var _opts$doc = opts.doc, doc = void 0 === _opts$doc ? document : _opts$doc; | ||
return function domRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return node.renderComponent(domRenderer); | ||
var _xmlNamespaceDomRenderer = function(node, xmlNamespace) { | ||
if (node.type === NODE_TYPE.COMPONENT) return node.renderComponent((function(childNode) { | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
if (node.type === NODE_TYPE.TEXT) return createTextElement(doc, node); | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
var el = function(doc, node, xmlNamespace) { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
}(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, (function(childNode) { | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
var _domRenderer = function(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return node.renderComponent(_domRenderer); | ||
if (node.type === NODE_TYPE.TEXT) return createTextElement(doc, node); | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
var xmlNamespace = ELEMENT_DEFAULT_XML_NAMESPACE[node.name.toLowerCase()]; | ||
if (xmlNamespace) return function xmlNamespaceDomRenderer(node, xmlNamespace) { | ||
if (node.type === NODE_TYPE.COMPONENT) return node.renderComponent((function(childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
if (node.type === NODE_TYPE.TEXT) return createTextElement(doc, node); | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
var el = function(doc, node, xmlNamespace) { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
}(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, (function(childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
})); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}(node, xmlNamespace); | ||
if (xmlNamespace) return _xmlNamespaceDomRenderer(node, xmlNamespace); | ||
var el = function(doc, node) { | ||
@@ -351,3 +354,3 @@ return node.props.el ? node.props.el : doc.createElement(node.name); | ||
addProps(el, node); | ||
addChildren(el, node, doc, domRenderer); | ||
addChildren(el, node, doc, _domRenderer); | ||
return el; | ||
@@ -357,2 +360,3 @@ } | ||
}; | ||
return _domRenderer; | ||
} | ||
@@ -380,6 +384,6 @@ function _extends() { | ||
if (!React) throw new Error("Must pass React library to react renderer"); | ||
return function reactRenderer(node) { | ||
var _reactRenderer = function(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return React.createElement.apply(React, [ function() { | ||
return node.renderComponent(reactRenderer) || null; | ||
}, node.props ].concat(node.renderChildren(reactRenderer))); | ||
return node.renderComponent(_reactRenderer) || null; | ||
}, node.props ].concat(node.renderChildren(_reactRenderer))); | ||
if (node.type === NODE_TYPE.ELEMENT) return React.createElement.apply(React, [ node.name, (props = node.props, | ||
@@ -391,3 +395,3 @@ innerHTML = props.innerHTML, _extends({ | ||
className: props.class | ||
}, _objectWithoutPropertiesLoose(props, _excluded))) ].concat(node.renderChildren(reactRenderer))); | ||
}, _objectWithoutPropertiesLoose(props, _excluded))) ].concat(node.renderChildren(_reactRenderer))); | ||
var props, innerHTML; | ||
@@ -397,2 +401,3 @@ if (node.type === NODE_TYPE.TEXT) return node.text; | ||
}; | ||
return _reactRenderer; | ||
} | ||
@@ -406,4 +411,4 @@ var SELF_CLOSING_TAGS = { | ||
function html() { | ||
return function htmlRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return [].concat(node.renderComponent(htmlRenderer)).join(""); | ||
var _htmlRenderer = function(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return [].concat(node.renderComponent(_htmlRenderer)).join(""); | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
@@ -420,3 +425,3 @@ var renderedProps = (props = node.props, (keys = Object.keys(props).filter((function(key) { | ||
if (SELF_CLOSING_TAGS[node.name]) return "<" + node.name + renderedProps + " />"; | ||
var renderedChildren = "string" == typeof node.props.innerHTML ? node.props.innerHTML : node.renderChildren(htmlRenderer).join(""); | ||
var renderedChildren = "string" == typeof node.props.innerHTML ? node.props.innerHTML : node.renderChildren(_htmlRenderer).join(""); | ||
return "<" + node.name + renderedProps + ">" + renderedChildren + "</" + node.name + ">"; | ||
@@ -428,2 +433,3 @@ } | ||
}; | ||
return _htmlRenderer; | ||
} | ||
@@ -434,6 +440,6 @@ var preact_excluded = [ "innerHTML" ]; | ||
if (!Preact) throw new Error("Must pass Preact library to react renderer"); | ||
return function reactRenderer(node) { | ||
var _reactRenderer = function(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) return Preact.h.apply(Preact, [ function() { | ||
return node.renderComponent(reactRenderer) || null; | ||
}, node.props ].concat(node.renderChildren(reactRenderer))); | ||
return node.renderComponent(_reactRenderer) || null; | ||
}, node.props ].concat(node.renderChildren(_reactRenderer))); | ||
if (node.type === NODE_TYPE.ELEMENT) return Preact.h.apply(Preact, [ node.name, (props = node.props, | ||
@@ -444,3 +450,3 @@ innerHTML = props.innerHTML, _extends({ | ||
} : null | ||
}, _objectWithoutPropertiesLoose(props, preact_excluded))) ].concat(node.renderChildren(reactRenderer))); | ||
}, _objectWithoutPropertiesLoose(props, preact_excluded))) ].concat(node.renderChildren(_reactRenderer))); | ||
var props, innerHTML; | ||
@@ -450,2 +456,3 @@ if (node.type === NODE_TYPE.TEXT) return node.text; | ||
}; | ||
return _reactRenderer; | ||
} | ||
@@ -452,0 +459,0 @@ function regex() { |
@@ -1,2 +0,2 @@ | ||
!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define("pragmatic",[],r):"object"==typeof exports?exports.pragmatic=r():e.pragmatic=r()}("undefined"!=typeof self?self:this,(function(){return function(e){var r={};function n(t){if(r[t])return r[t].exports;var o=r[t]={i:t,l:!1,exports:{}};return e[t].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=r,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,r){if(1&r&&(e=n(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)n.d(t,o,function(r){return e[r]}.bind(null,o));return t},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,r){return{}.hasOwnProperty.call(e,r)},n.p="",n(n.s=0)}([function(e,r,n){"use strict";n.r(r),n.d(r,"ElementNode",(function(){return i})),n.d(r,"FragmentNode",(function(){return u})),n.d(r,"TextNode",(function(){return p})),n.d(r,"ComponentNode",(function(){return c})),n.d(r,"node",(function(){return s})),n.d(r,"Fragment",(function(){return h})),n.d(r,"text",(function(){return y})),n.d(r,"dom",(function(){return M})),n.d(r,"react",(function(){return O})),n.d(r,"html",(function(){return j})),n.d(r,"preact",(function(){return A})),n.d(r,"regex",(function(){return H})),n.d(r,"NODE_TYPE",(function(){return t})),n.d(r,"Style",(function(){return S})),n.d(r,"Regex",(function(){return U})),n.d(r,"RegexText",(function(){return G})),n.d(r,"RegexWord",(function(){return k})),n.d(r,"RegexCharacters",(function(){return F})),n.d(r,"RegexGroup",(function(){return W})),n.d(r,"RegexUnion",(function(){return $}));var t={ELEMENT:"element",TEXT:"text",COMPONENT:"component",FRAGMENT:"fragment"};function o(e,r){for(var n=[],t=0;t<e.length;t++){var o=e[t].render(r);if(o)if(Array.isArray(o))for(var i=0;i<o.length;i++){var u=o[i];u&&n.push(u)}else n.push(o)}return n}var i=function(){function e(e,r,n){this.type=t.ELEMENT,this.name=void 0,this.props=void 0,this.children=void 0,this.onRender=void 0,this.name=e,this.props=r||{},this.children=n;var o=this.props.onRender;"function"==typeof o&&(this.onRender=o,delete r.onRender)}var r=e.prototype;return r.render=function(e){var r=e(this);return this.onRender&&this.onRender(r),r},r.renderChildren=function(e){return o(this.children,e)},e}(),u=function(){function e(e){this.type=t.FRAGMENT,this.children=void 0,this.children=e}return e.prototype.render=function(e){return o(this.children,e)},e}(),p=function(){function e(e){this.type=t.TEXT,this.text=void 0,this.text=e}return e.prototype.render=function(e){return e(this)},e}(),c=function(){function e(e,r,n){this.type=t.COMPONENT,this.component=void 0,this.props=void 0,this.children=void 0,this.component=e,this.props=r||{},this.children=n,this.props.children=n}var r=e.prototype;return r.renderComponent=function(e){var r=function(e){var r=a(Array.isArray(e)?e:[e]);return 1===r.length?r[0]:r.length>1?new u(r):void 0}(this.component(this.props,this.children));if(r)return r.render(e)},r.render=function(e){return e(this)},r.renderChildren=function(e){return o(this.children,e)},e}();function a(e){for(var r=[],n=0;n<e.length;n++){var o=e[n];if(o)if("string"==typeof o||"number"==typeof o)r.push(new p(o.toString()));else{if("boolean"==typeof o)continue;if(Array.isArray(o))for(var i=0,u=a(o);i<u.length;i++)r.push(u[i]);else{if(!o||o.type!==t.ELEMENT&&o.type!==t.TEXT&&o.type!==t.COMPONENT)throw new TypeError("Unrecognized node type: "+typeof o);r.push(o)}}}return r}var f,d,l,s=function(e,r){for(var n=arguments.length,t=new Array(n>2?n-2:0),o=2;o<n;o++)t[o-2]=arguments[o];if(t=a(t),"string"==typeof e)return new i(e,r,t);if("function"==typeof e)return new c(e,r,t);throw new TypeError("Expected jsx element to be a string or a function")},h=function(e,r){return r};function y(){return function e(r){if(r.type===t.COMPONENT)return[].concat(r.renderComponent(e)).join("");if(r.type===t.ELEMENT)throw new Error("Text renderer does not support basic elements");if(r.type===t.TEXT)return r.text;throw new TypeError("Unhandleable node: "+r.type)}}function v(e){return null!=e}var E=((f={}).svg="http://www.w3.org/2000/svg",f),m=((d={})["xlink:href"]="http://www.w3.org/1999/xlink",d);function g(e,r){return e.createTextNode(r.text)}function T(e,r){for(var n=r.props,t=0,o=Object.keys(n);t<o.length;t++){var i=o[t],u=n[i];if(null!=u&&"el"!==i&&"innerHTML"!==i)if(i.match(/^on[A-Z][a-z]/)&&"function"==typeof u)e.addEventListener(i.slice(2).toLowerCase(),u);else if("string"==typeof u||"number"==typeof u){var p=m[i];p?e.setAttributeNS(p,i,u.toString()):e.setAttribute(i,u.toString())}else"boolean"==typeof u&&!0===u&&e.setAttribute(i,"")}"iframe"!==e.tagName.toLowerCase()||n.id||e.setAttribute("id","jsx-iframe-"+"xxxxxxxxxx".replace(/./g,(function(){return"0123456789abcdef".charAt(Math.floor(Math.random()*"0123456789abcdef".length))})))}var w=((l={}).iframe=function(e,r){var n=r.children[0];if(1!==r.children.length||!n||n.type!==t.ELEMENT||"html"!==n.name)throw new Error("Expected only single html element node as child of iframe element");e.addEventListener("load",(function(){var r=e.contentWindow;if(!r)throw new Error("Expected frame to have contentWindow");for(var t=r.document,o=t.documentElement;o.children&&o.children.length;)o.removeChild(o.children[0]);for(var i=n.render(M({doc:t}));i.children.length;)o.appendChild(i.children[0])}))},l.script=function(e,r){var n=r.children[0];if(1!==r.children.length||!n||n.type!==t.TEXT)throw new Error("Expected only single text node as child of script element");e.text=n.text},l.default=function(e,r,n){for(var t=0,o=r.renderChildren(n);t<o.length;t++)e.appendChild(o[t])},l);function x(e,r,n,t){if(r.props.hasOwnProperty("innerHTML")){if(r.children.length)throw new Error("Expected no children to be passed when innerHTML prop is set");var o=r.props.innerHTML;if("string"!=typeof o)throw new TypeError("innerHTML prop must be string");"script"===r.name?e.text=o:(e.innerHTML=o,function(e,r){void 0===r&&(r=window.document);for(var n=0,t=e.querySelectorAll("script");n<t.length;n++){var o=t[n],i=o.parentNode;if(i){var u=r.createElement("script");u.text=o.textContent,i.replaceChild(u,o)}}}(e,n))}else(w[r.name]||w.default)(e,r,t)}function M(e){void 0===e&&(e={});var r=e.doc,n=void 0===r?document:r;return function e(r){if(r.type===t.COMPONENT)return r.renderComponent(e);if(r.type===t.TEXT)return g(n,r);if(r.type===t.ELEMENT){var o=E[r.name.toLowerCase()];if(o)return function e(r,o){if(r.type===t.COMPONENT)return r.renderComponent((function(r){return e(r,o)}));if(r.type===t.TEXT)return g(n,r);if(r.type===t.ELEMENT){var i=function(e,r,n){return e.createElementNS(n,r.name)}(n,r,o);return T(i,r),x(i,r,n,(function(r){return e(r,o)})),i}throw new TypeError("Unhandleable node")}(r,o);var i=function(e,r){return r.props.el?r.props.el:e.createElement(r.name)}(n,r);return T(i,r),x(i,r,n,e),i}throw new TypeError("Unhandleable node")}}function b(){return(b=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var t in n)({}).hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e}).apply(this,arguments)}function N(e,r){if(null==e)return{};var n,t,o={},i=Object.keys(e);for(t=0;t<i.length;t++)r.indexOf(n=i[t])>=0||(o[n]=e[n]);return o}var C=["innerHTML","class"];function O(e){var r=(void 0===e?{}:e).React;if(!r)throw new Error("Must pass React library to react renderer");return function e(n){if(n.type===t.COMPONENT)return r.createElement.apply(r,[function(){return n.renderComponent(e)||null},n.props].concat(n.renderChildren(e)));if(n.type===t.ELEMENT)return r.createElement.apply(r,[n.name,(o=n.props,i=o.innerHTML,b({dangerouslySetInnerHTML:i?{__html:i}:null,className:o.class},N(o,C)))].concat(n.renderChildren(e)));var o,i;if(n.type===t.TEXT)return n.text;throw new TypeError("Unhandleable node")}}var L={br:!0};function R(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}function j(){return function e(r){if(r.type===t.COMPONENT)return[].concat(r.renderComponent(e)).join("");if(r.type===t.ELEMENT){var n=(i=r.props,(u=Object.keys(i).filter((function(e){var r=i[e];return"innerHTML"!==e&&("string"==typeof r||"number"==typeof r||!0===r)}))).length?" "+u.map((function(e){var r=i[e];if(!0===r)return""+R(e);if("string"!=typeof r&&"number"!=typeof r)throw new TypeError("Unexpected prop type: "+typeof r);return""===r?R(e):R(e)+'="'+R(r.toString())+'"'})).join(" "):"");if(L[r.name])return"<"+r.name+n+" />";var o="string"==typeof r.props.innerHTML?r.props.innerHTML:r.renderChildren(e).join("");return"<"+r.name+n+">"+o+"</"+r.name+">"}var i,u;if(r.type===t.TEXT)return R(r.text);throw new TypeError("Unhandleable node: "+r.type)}}var P=["innerHTML"];function A(e){var r=(void 0===e?{}:e).Preact;if(!r)throw new Error("Must pass Preact library to react renderer");return function e(n){if(n.type===t.COMPONENT)return r.h.apply(r,[function(){return n.renderComponent(e)||null},n.props].concat(n.renderChildren(e)));if(n.type===t.ELEMENT)return r.h.apply(r,[n.name,(o=n.props,i=o.innerHTML,b({dangerouslySetInnerHTML:i?{__html:i}:null},N(o,P)))].concat(n.renderChildren(e)));var o,i;if(n.type===t.TEXT)return n.text;throw new TypeError("Unhandleable node")}}function H(){var e=y();return function(r){return new RegExp(e(r))}}function S(e){var r=e.css,n=e.nonce,t=e.children;return s(h,null,s("style",{innerHTML:"string"==typeof r?r:r._getCss(),nonce:n}),t)}H.node=function(e,r){for(var n=arguments.length,t=new Array(n>2?n-2:0),o=2;o<n;o++)t[o-2]=arguments[o];var i=s.apply(void 0,[e,r].concat(t));return e.renderer?i.render(e.renderer()):i};var _=function(e){return e.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&")},X=function(e,r){return(r=function(e,r){if(!r)throw new Error("Must pass children to "+e);return r}(e,r)).map((function(e){return e.type===t.TEXT?new p(_(e.text)):e}))};function U(e,r){var n=e.exact,t=void 0===n||n;return r=X("RegexGroup",r),t?["^"].concat(r,["$"]):r}function G(e,r){return X("RegexText",r)}function k(e,r){return function(e,r){if(r&&r.length)throw new Error("Must not pass children to RegexWord")}(0,r),"\\w+"}function F(e,r){return["["].concat(X("RegexText",r),["]"])}function W(e,r){var n=e.repeat,t=e.repeatMin,o=e.repeatMax,i=e.name,u=e.optional,c=void 0!==u&&u,a=e.capture,f=void 0===a||a,d=e.union,l=void 0!==d&&d;if(r=X("RegexGroup",r),v(n)&&(v(t)||v(o)))throw new Error("repeat can not be used with repeatMin or repeatMax");if(i&&!f)throw new Error("Named groups must be captured");if(l){for(var s=[],h=0,y=r;h<y.length;h++)s.push(y[h]),s.push(new p("|"));s.pop(),r=s}var E=[];return E.push(f?"(":"(?:"),i&&E.push("?<"+_(i)+">"),E.push.apply(E,r),E.push(")"),v(n)&&("number"==typeof n?E.push("{"+n+"}"):!0===n&&E.push("+")),(v(t)||v(o))&&E.push("{"+(t||"")+","+(o||"")+"}"),c&&E.push("?"),E}function $(e,r){for(var n=[],t=0,o=r=X("RegexGroup",r);t<o.length;t++)n.push(o[t]),n.push("|");return n.pop(),n}U.renderer=H}])})); | ||
!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define("pragmatic",[],r):"object"==typeof exports?exports.pragmatic=r():e.pragmatic=r()}("undefined"!=typeof self?self:this,(function(){return function(e){var r={};function n(t){if(r[t])return r[t].exports;var o=r[t]={i:t,l:!1,exports:{}};return e[t].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=r,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,r){if(1&r&&(e=n(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)n.d(t,o,function(r){return e[r]}.bind(null,o));return t},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,r){return{}.hasOwnProperty.call(e,r)},n.p="",n(n.s=0)}([function(e,r,n){"use strict";n.r(r),n.d(r,"ElementNode",(function(){return i})),n.d(r,"FragmentNode",(function(){return u})),n.d(r,"TextNode",(function(){return c})),n.d(r,"ComponentNode",(function(){return a})),n.d(r,"node",(function(){return s})),n.d(r,"Fragment",(function(){return h})),n.d(r,"text",(function(){return y})),n.d(r,"dom",(function(){return M})),n.d(r,"react",(function(){return L})),n.d(r,"html",(function(){return j})),n.d(r,"preact",(function(){return A})),n.d(r,"regex",(function(){return H})),n.d(r,"NODE_TYPE",(function(){return t})),n.d(r,"Style",(function(){return S})),n.d(r,"Regex",(function(){return U})),n.d(r,"RegexText",(function(){return G})),n.d(r,"RegexWord",(function(){return k})),n.d(r,"RegexCharacters",(function(){return F})),n.d(r,"RegexGroup",(function(){return W})),n.d(r,"RegexUnion",(function(){return $}));var t={ELEMENT:"element",TEXT:"text",COMPONENT:"component",FRAGMENT:"fragment"};function o(e,r){for(var n=[],t=0;t<e.length;t++){var o=e[t].render(r);if(o)if(Array.isArray(o))for(var i=0;i<o.length;i++){var u=o[i];u&&n.push(u)}else n.push(o)}return n}var i=function(){function e(e,r,n){this.type=t.ELEMENT,this.name=void 0,this.props=void 0,this.children=void 0,this.onRender=void 0,this.name=e,this.props=r||{},this.children=n;var o=this.props.onRender;"function"==typeof o&&(this.onRender=o,delete r.onRender)}var r=e.prototype;return r.render=function(e){var r=e(this);return this.onRender&&this.onRender(r),r},r.renderChildren=function(e){return o(this.children,e)},e}(),u=function(){function e(e){this.type=t.FRAGMENT,this.children=void 0,this.children=e}return e.prototype.render=function(e){return o(this.children,e)},e}(),c=function(){function e(e){this.type=t.TEXT,this.text=void 0,this.text=e}return e.prototype.render=function(e){return e(this)},e}(),a=function(){function e(e,r,n){this.type=t.COMPONENT,this.component=void 0,this.props=void 0,this.children=void 0,this.component=e,this.props=r||{},this.children=n,this.props.children=n}var r=e.prototype;return r.renderComponent=function(e){var r=function(e){var r=p(Array.isArray(e)?e:[e]);return 1===r.length?r[0]:r.length>1?new u(r):void 0}(this.component(this.props,this.children));if(r)return r.render(e)},r.render=function(e){return e(this)},r.renderChildren=function(e){return o(this.children,e)},e}();function p(e){for(var r=[],n=0;n<e.length;n++){var o=e[n];if(o)if("string"==typeof o||"number"==typeof o)r.push(new c(o.toString()));else{if("boolean"==typeof o)continue;if(Array.isArray(o))for(var i=0,u=p(o);i<u.length;i++)r.push(u[i]);else{if(!o||o.type!==t.ELEMENT&&o.type!==t.TEXT&&o.type!==t.COMPONENT)throw new TypeError("Unrecognized node type: "+typeof o);r.push(o)}}}return r}var f,d,l,s=function(e,r){for(var n=arguments.length,t=new Array(n>2?n-2:0),o=2;o<n;o++)t[o-2]=arguments[o];if(t=p(t),"string"==typeof e)return new i(e,r,t);if("function"==typeof e)return new a(e,r,t);throw new TypeError("Expected jsx element to be a string or a function")},h=function(e,r){return r};function y(){var e=function(r){if(r.type===t.COMPONENT)return[].concat(r.renderComponent(e)).join("");if(r.type===t.ELEMENT)throw new Error("Text renderer does not support basic elements");if(r.type===t.TEXT)return r.text;throw new TypeError("Unhandleable node: "+r.type)};return e}function v(e){return null!=e}var E=((f={}).svg="http://www.w3.org/2000/svg",f),m=((d={})["xlink:href"]="http://www.w3.org/1999/xlink",d);function g(e,r){return e.createTextNode(r.text)}function T(e,r){for(var n=r.props,t=0,o=Object.keys(n);t<o.length;t++){var i=o[t],u=n[i];if(null!=u&&"el"!==i&&"innerHTML"!==i)if(i.match(/^on[A-Z][a-z]/)&&"function"==typeof u)e.addEventListener(i.slice(2).toLowerCase(),u);else if("string"==typeof u||"number"==typeof u){var c=m[i];c?e.setAttributeNS(c,i,u.toString()):e.setAttribute(i,u.toString())}else"boolean"==typeof u&&!0===u&&e.setAttribute(i,"")}"iframe"!==e.tagName.toLowerCase()||n.id||e.setAttribute("id","jsx-iframe-"+"xxxxxxxxxx".replace(/./g,(function(){return"0123456789abcdef".charAt(Math.floor(Math.random()*"0123456789abcdef".length))}))),"iframe"!==e.tagName.toLowerCase()||n.srcdoc||n.src||e.setAttribute("srcdoc","")}var w=((l={}).iframe=function(e,r){var n=r.children[0];if(1!==r.children.length||!n||n.type!==t.ELEMENT||"html"!==n.name)throw new Error("Expected only single html element node as child of iframe element");e.addEventListener("load",(function(){var r=e.contentWindow;if(!r)throw new Error("Expected frame to have contentWindow");for(var t=r.document,o=t.documentElement;o.children&&o.children.length;)o.removeChild(o.children[0]);for(var i=n.render(M({doc:t}));i.children.length;)o.appendChild(i.children[0])}))},l.script=function(e,r){var n=r.children[0];if(1!==r.children.length||!n||n.type!==t.TEXT)throw new Error("Expected only single text node as child of script element");e.text=n.text},l.default=function(e,r,n){for(var t=0,o=r.renderChildren(n);t<o.length;t++)e.appendChild(o[t])},l);function x(e,r,n,t){if(r.props.hasOwnProperty("innerHTML")){if(r.children.length)throw new Error("Expected no children to be passed when innerHTML prop is set");var o=r.props.innerHTML;if("string"!=typeof o)throw new TypeError("innerHTML prop must be string");"script"===r.name?e.text=o:(e.innerHTML=o,function(e,r){void 0===r&&(r=window.document);for(var n=0,t=e.querySelectorAll("script");n<t.length;n++){var o=t[n],i=o.parentNode;if(i){var u=r.createElement("script");u.text=o.textContent,i.replaceChild(u,o)}}}(e,n))}else(w[r.name]||w.default)(e,r,t)}function M(e){void 0===e&&(e={});var r=e.doc,n=void 0===r?document:r,o=function(e,r){if(e.type===t.COMPONENT)return e.renderComponent((function(e){return o(e,r)}));if(e.type===t.TEXT)return g(n,e);if(e.type===t.ELEMENT){var i=function(e,r,n){return e.createElementNS(n,r.name)}(n,e,r);return T(i,e),x(i,e,n,(function(e){return o(e,r)})),i}throw new TypeError("Unhandleable node")},i=function(e){if(e.type===t.COMPONENT)return e.renderComponent(i);if(e.type===t.TEXT)return g(n,e);if(e.type===t.ELEMENT){var r=E[e.name.toLowerCase()];if(r)return o(e,r);var u=function(e,r){return r.props.el?r.props.el:e.createElement(r.name)}(n,e);return T(u,e),x(u,e,n,i),u}throw new TypeError("Unhandleable node")};return i}function b(){return(b=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var t in n)({}).hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e}).apply(this,arguments)}function N(e,r){if(null==e)return{};var n,t,o={},i=Object.keys(e);for(t=0;t<i.length;t++)r.indexOf(n=i[t])>=0||(o[n]=e[n]);return o}var C=["innerHTML","class"];function L(e){var r=(void 0===e?{}:e).React;if(!r)throw new Error("Must pass React library to react renderer");var n=function(e){if(e.type===t.COMPONENT)return r.createElement.apply(r,[function(){return e.renderComponent(n)||null},e.props].concat(e.renderChildren(n)));if(e.type===t.ELEMENT)return r.createElement.apply(r,[e.name,(o=e.props,i=o.innerHTML,b({dangerouslySetInnerHTML:i?{__html:i}:null,className:o.class},N(o,C)))].concat(e.renderChildren(n)));var o,i;if(e.type===t.TEXT)return e.text;throw new TypeError("Unhandleable node")};return n}var O={br:!0};function R(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}function j(){var e=function(r){if(r.type===t.COMPONENT)return[].concat(r.renderComponent(e)).join("");if(r.type===t.ELEMENT){var n=(i=r.props,(u=Object.keys(i).filter((function(e){var r=i[e];return"innerHTML"!==e&&("string"==typeof r||"number"==typeof r||!0===r)}))).length?" "+u.map((function(e){var r=i[e];if(!0===r)return""+R(e);if("string"!=typeof r&&"number"!=typeof r)throw new TypeError("Unexpected prop type: "+typeof r);return""===r?R(e):R(e)+'="'+R(r.toString())+'"'})).join(" "):"");if(O[r.name])return"<"+r.name+n+" />";var o="string"==typeof r.props.innerHTML?r.props.innerHTML:r.renderChildren(e).join("");return"<"+r.name+n+">"+o+"</"+r.name+">"}var i,u;if(r.type===t.TEXT)return R(r.text);throw new TypeError("Unhandleable node: "+r.type)};return e}var P=["innerHTML"];function A(e){var r=(void 0===e?{}:e).Preact;if(!r)throw new Error("Must pass Preact library to react renderer");var n=function(e){if(e.type===t.COMPONENT)return r.h.apply(r,[function(){return e.renderComponent(n)||null},e.props].concat(e.renderChildren(n)));if(e.type===t.ELEMENT)return r.h.apply(r,[e.name,(o=e.props,i=o.innerHTML,b({dangerouslySetInnerHTML:i?{__html:i}:null},N(o,P)))].concat(e.renderChildren(n)));var o,i;if(e.type===t.TEXT)return e.text;throw new TypeError("Unhandleable node")};return n}function H(){var e=y();return function(r){return new RegExp(e(r))}}function S(e){var r=e.css,n=e.nonce,t=e.children;return s(h,null,s("style",{innerHTML:"string"==typeof r?r:r._getCss(),nonce:n}),t)}H.node=function(e,r){for(var n=arguments.length,t=new Array(n>2?n-2:0),o=2;o<n;o++)t[o-2]=arguments[o];var i=s.apply(void 0,[e,r].concat(t));return e.renderer?i.render(e.renderer()):i};var _=function(e){return e.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&")},X=function(e,r){return(r=function(e,r){if(!r)throw new Error("Must pass children to "+e);return r}(e,r)).map((function(e){return e.type===t.TEXT?new c(_(e.text)):e}))};function U(e,r){var n=e.exact,t=void 0===n||n;return r=X("RegexGroup",r),t?["^"].concat(r,["$"]):r}function G(e,r){return X("RegexText",r)}function k(e,r){return function(e,r){if(r&&r.length)throw new Error("Must not pass children to RegexWord")}(0,r),"\\w+"}function F(e,r){return["["].concat(X("RegexText",r),["]"])}function W(e,r){var n=e.repeat,t=e.repeatMin,o=e.repeatMax,i=e.name,u=e.optional,a=void 0!==u&&u,p=e.capture,f=void 0===p||p,d=e.union,l=void 0!==d&&d;if(r=X("RegexGroup",r),v(n)&&(v(t)||v(o)))throw new Error("repeat can not be used with repeatMin or repeatMax");if(i&&!f)throw new Error("Named groups must be captured");if(l){for(var s=[],h=0,y=r;h<y.length;h++)s.push(y[h]),s.push(new c("|"));s.pop(),r=s}var E=[];return E.push(f?"(":"(?:"),i&&E.push("?<"+_(i)+">"),E.push.apply(E,r),E.push(")"),v(n)&&("number"==typeof n?E.push("{"+n+"}"):!0===n&&E.push("+")),(v(t)||v(o))&&E.push("{"+(t||"")+","+(o||"")+"}"),a&&E.push("?"),E}function $(e,r){for(var n=[],t=0,o=r=X("RegexGroup",r);t<o.length;t++)n.push(o[t]),n.push("|");return n.pop(),n}U.renderer=H}])})); | ||
//# sourceMappingURL=jsx-pragmatic.min.js.map |
@@ -1,2 +0,2 @@ | ||
export * from './style'; | ||
export * from './regex'; | ||
export * from "./style"; | ||
export * from "./regex"; |
@@ -1,11 +0,8 @@ | ||
/** @jsx node */ | ||
import { TextNode } from '../node'; | ||
import { isDefined } from '../util'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { regex } from '../renderers'; | ||
import { TextNode } from "../node"; | ||
import { isDefined } from "../util"; | ||
import { NODE_TYPE } from "../constants"; | ||
import { regex } from "../renderers"; | ||
var escapeRegex = function escapeRegex(text) { | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&'); | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); | ||
}; | ||
var validateChildren = function validateChildren(name, children) { | ||
@@ -15,6 +12,4 @@ if (!children) { | ||
} | ||
return children; | ||
}; | ||
var validateNoChildren = function validateNoChildren(name, children) { | ||
@@ -25,3 +20,2 @@ if (children && children.length) { | ||
}; | ||
var validateAndEscapeChildren = function validateAndEscapeChildren(name, children) { | ||
@@ -33,78 +27,62 @@ children = validateChildren(name, children); | ||
} | ||
return child; | ||
}); | ||
}; | ||
export function Regex(_ref, children) { | ||
var _ref$exact = _ref.exact, | ||
exact = _ref$exact === void 0 ? true : _ref$exact; | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
exact = _ref$exact === void 0 ? true : _ref$exact; | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
if (!exact) { | ||
return children; | ||
} | ||
return ['^'].concat(children, ['$']); | ||
return ["^"].concat(children, ["$"]); | ||
} | ||
Regex.renderer = regex; | ||
export function RegexText(props, children) { | ||
return validateAndEscapeChildren('RegexText', children); | ||
return validateAndEscapeChildren("RegexText", children); | ||
} | ||
export function RegexWord(props, children) { | ||
validateNoChildren('RegexWord', children); | ||
return '\\w+'; | ||
validateNoChildren("RegexWord", children); | ||
return "\\w+"; | ||
} | ||
export function RegexCharacters(props, children) { | ||
return ['['].concat(validateAndEscapeChildren('RegexText', children), [']']); | ||
return ["["].concat(validateAndEscapeChildren("RegexText", children), ["]"]); | ||
} | ||
export function RegexGroup(_ref2, children) { | ||
var repeat = _ref2.repeat, | ||
repeatMin = _ref2.repeatMin, | ||
repeatMax = _ref2.repeatMax, | ||
name = _ref2.name, | ||
_ref2$optional = _ref2.optional, | ||
optional = _ref2$optional === void 0 ? false : _ref2$optional, | ||
_ref2$capture = _ref2.capture, | ||
capture = _ref2$capture === void 0 ? true : _ref2$capture, | ||
_ref2$union = _ref2.union, | ||
union = _ref2$union === void 0 ? false : _ref2$union; | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
repeatMin = _ref2.repeatMin, | ||
repeatMax = _ref2.repeatMax, | ||
name = _ref2.name, | ||
_ref2$optional = _ref2.optional, | ||
optional = _ref2$optional === void 0 ? false : _ref2$optional, | ||
_ref2$capture = _ref2.capture, | ||
capture = _ref2$capture === void 0 ? true : _ref2$capture, | ||
_ref2$union = _ref2.union, | ||
union = _ref2$union === void 0 ? false : _ref2$union; | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
if (isDefined(repeat) && (isDefined(repeatMin) || isDefined(repeatMax))) { | ||
throw new Error("repeat can not be used with repeatMin or repeatMax"); | ||
} | ||
if (name && !capture) { | ||
throw new Error("Named groups must be captured"); | ||
} | ||
if (union) { | ||
var _result = []; | ||
for (var _i2 = 0, _children2 = children; _i2 < _children2.length; _i2++) { | ||
var child = _children2[_i2]; | ||
_result.push(child); | ||
_result.push(new TextNode('|')); | ||
_result.push(new TextNode("|")); | ||
} | ||
_result.pop(); | ||
children = _result; | ||
} | ||
var result = []; | ||
result.push(capture ? '(' : '(?:'); | ||
result.push(capture ? "(" : "(?:"); | ||
if (name) { | ||
result.push("?<" + escapeRegex(name) + ">"); | ||
} | ||
result.push.apply(result, children); | ||
result.push(')'); | ||
result.push(")"); | ||
if (isDefined(repeat)) { | ||
if (typeof repeat === 'number') { | ||
if (typeof repeat === "number") { | ||
result.push("{" + repeat + "}"); | ||
@@ -115,25 +93,20 @@ } else if (repeat === true) { | ||
} | ||
if (isDefined(repeatMin) || isDefined(repeatMax)) { | ||
result.push("{" + (repeatMin || '') + "," + (repeatMax || '') + "}"); | ||
result.push("{" + (repeatMin || "") + "," + (repeatMax || "") + "}"); | ||
} | ||
if (optional) { | ||
result.push('?'); | ||
result.push("?"); | ||
} | ||
return result; | ||
} | ||
export function RegexUnion(props, children) { | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
var result = []; | ||
for (var _i4 = 0, _children4 = children; _i4 < _children4.length; _i4++) { | ||
var child = _children4[_i4]; | ||
result.push(child); | ||
result.push('|'); | ||
result.push("|"); | ||
} | ||
result.pop(); | ||
return result; | ||
} |
@@ -1,11 +0,10 @@ | ||
/** @jsx node */ | ||
import { Fragment, node } from '../node'; | ||
import { Fragment, node } from "../node"; | ||
export function Style(_ref) { | ||
var css = _ref.css, | ||
nonce = _ref.nonce, | ||
children = _ref.children; | ||
nonce = _ref.nonce, | ||
children = _ref.children; | ||
return node(Fragment, null, node("style", { | ||
innerHTML: typeof css === 'string' ? css : css._getCss(), | ||
innerHTML: typeof css === "string" ? css : css._getCss(), | ||
nonce: nonce | ||
}), children); | ||
} |
export var NODE_TYPE = { | ||
ELEMENT: 'element', | ||
TEXT: 'text', | ||
COMPONENT: 'component', | ||
FRAGMENT: 'fragment' | ||
ELEMENT: "element", | ||
TEXT: "text", | ||
COMPONENT: "component", | ||
FRAGMENT: "fragment" | ||
}; |
@@ -1,4 +0,4 @@ | ||
export * from './node'; | ||
export * from './renderers'; | ||
export * from './constants'; | ||
export * from './component'; | ||
export * from "./node"; | ||
export * from "./renderers"; | ||
export * from "./constants"; | ||
export * from "./component"; |
@@ -1,11 +0,7 @@ | ||
import { NODE_TYPE } from './constants'; | ||
import { NODE_TYPE } from "./constants"; | ||
function _renderChildren(children, renderer) { | ||
// eslint-disable-line no-use-before-define | ||
var result = []; | ||
for (var _i2 = 0; _i2 < children.length; _i2++) { | ||
var child = children[_i2]; | ||
var renderedChild = child.render(renderer); | ||
if (!renderedChild) { | ||
@@ -16,3 +12,2 @@ continue; | ||
var subchild = renderedChild[_i4]; | ||
if (subchild) { | ||
@@ -26,9 +21,5 @@ result.push(subchild); | ||
} | ||
return result; | ||
} | ||
export var ElementNode = /*#__PURE__*/function () { | ||
// eslint-disable-line no-use-before-define | ||
// eslint-disable-line no-undef | ||
export var ElementNode = function () { | ||
function ElementNode(name, props, children) { | ||
@@ -40,3 +31,2 @@ this.type = NODE_TYPE.ELEMENT; | ||
this.onRender = void 0; | ||
// eslint-disable-line no-use-before-define | ||
this.name = name; | ||
@@ -46,4 +36,3 @@ this.props = props || {}; | ||
var onRender = this.props.onRender; | ||
if (typeof onRender === 'function') { | ||
if (typeof onRender === "function") { | ||
this.onRender = onRender; | ||
@@ -53,39 +42,28 @@ delete props.onRender; | ||
} | ||
var _proto = ElementNode.prototype; | ||
_proto.render = function render(renderer) { | ||
var el = renderer(this); | ||
if (this.onRender) { | ||
this.onRender(el); | ||
} | ||
return el; | ||
}; | ||
_proto.renderChildren = function renderChildren(renderer) { | ||
return _renderChildren(this.children, renderer); | ||
}; | ||
return ElementNode; | ||
}(); | ||
export var FragmentNode = /*#__PURE__*/function () { | ||
// eslint-disable-line no-use-before-define | ||
export var FragmentNode = function () { | ||
function FragmentNode(children) { | ||
this.type = NODE_TYPE.FRAGMENT; | ||
this.children = void 0; | ||
// eslint-disable-line no-use-before-define | ||
this.children = children; | ||
} | ||
var _proto2 = FragmentNode.prototype; | ||
_proto2.render = function render(renderer) { | ||
return _renderChildren(this.children, renderer); | ||
}; | ||
return FragmentNode; | ||
}(); | ||
export var TextNode = /*#__PURE__*/function () { | ||
export var TextNode = function () { | ||
function TextNode(text) { | ||
@@ -96,14 +74,9 @@ this.type = NODE_TYPE.TEXT; | ||
} | ||
var _proto3 = TextNode.prototype; | ||
_proto3.render = function render(renderer) { | ||
return renderer(this); | ||
}; | ||
return TextNode; | ||
}(); // eslint-disable-next-line no-unused-vars | ||
export var ComponentNode = /*#__PURE__*/function () { | ||
// eslint-disable-next-line no-use-before-define | ||
}(); | ||
export var ComponentNode = function () { | ||
function ComponentNode(component, props, children) { | ||
@@ -119,8 +92,5 @@ this.type = NODE_TYPE.COMPONENT; | ||
} | ||
var _proto4 = ComponentNode.prototype; | ||
_proto4.renderComponent = function renderComponent(renderer) { | ||
var child = normalizeChild(this.component(this.props, this.children)); // eslint-disable-line no-use-before-define | ||
var child = normalizeChild(this.component(this.props, this.children)); | ||
if (child) { | ||
@@ -130,25 +100,19 @@ return child.render(renderer); | ||
}; | ||
_proto4.render = function render(renderer) { | ||
return renderer(this); | ||
}; | ||
_proto4.renderChildren = function renderChildren(renderer) { | ||
return _renderChildren(this.children, renderer); | ||
}; | ||
return ComponentNode; | ||
}(); | ||
function normalizeChildren(children) { | ||
var result = []; | ||
for (var _i6 = 0; _i6 < children.length; _i6++) { | ||
var child = children[_i6]; | ||
if (!child) { | ||
continue; | ||
} else if (typeof child === 'string' || typeof child === 'number') { | ||
} else if (typeof child === "string" || typeof child === "number") { | ||
result.push(new TextNode(child.toString())); | ||
} else if (typeof child === 'boolean') { | ||
} else if (typeof child === "boolean") { | ||
continue; | ||
@@ -166,9 +130,6 @@ } else if (Array.isArray(child)) { | ||
} | ||
return result; | ||
} | ||
function normalizeChild(child) { | ||
var children = normalizeChildren(Array.isArray(child) ? child : [child]); | ||
if (children.length === 1) { | ||
@@ -180,3 +141,2 @@ return children[0]; | ||
} | ||
export var node = function node(element, props) { | ||
@@ -186,15 +146,9 @@ for (var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
} | ||
children = normalizeChildren(children); | ||
if (typeof element === 'string') { | ||
// $FlowFixMe | ||
if (typeof element === "string") { | ||
return new ElementNode(element, props, children); | ||
} | ||
if (typeof element === 'function') { | ||
// $FlowFixMe | ||
if (typeof element === "function") { | ||
return new ComponentNode(element, props, children); | ||
} | ||
throw new TypeError("Expected jsx element to be a string or a function"); | ||
@@ -201,0 +155,0 @@ }; |
var _ELEMENT_DEFAULT_XML_, _ATTRIBUTE_DEFAULT_XM, _ADD_CHILDREN; | ||
import { ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { uniqueID } from '../util'; | ||
import { ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
import { uniqueID } from "../util"; | ||
var ELEMENT_TAG = { | ||
HTML: 'html', | ||
IFRAME: 'iframe', | ||
SCRIPT: 'script', | ||
SVG: 'svg', | ||
DEFAULT: 'default' | ||
HTML: "html", | ||
IFRAME: "iframe", | ||
SCRIPT: "script", | ||
SVG: "svg", | ||
DEFAULT: "default" | ||
}; | ||
var ELEMENT_PROP = { | ||
ID: 'id', | ||
INNER_HTML: 'innerHTML', | ||
EL: 'el', | ||
XLINK_HREF: 'xlink:href' | ||
ID: "id", | ||
INNER_HTML: "innerHTML", | ||
EL: "el", | ||
XLINK_HREF: "xlink:href" | ||
}; | ||
var ELEMENT_DEFAULT_XML_NAMESPACE = (_ELEMENT_DEFAULT_XML_ = {}, _ELEMENT_DEFAULT_XML_[ELEMENT_TAG.SVG] = 'http://www.w3.org/2000/svg', _ELEMENT_DEFAULT_XML_); | ||
var ATTRIBUTE_DEFAULT_XML_NAMESPACE = (_ATTRIBUTE_DEFAULT_XM = {}, _ATTRIBUTE_DEFAULT_XM[ELEMENT_PROP.XLINK_HREF] = 'http://www.w3.org/1999/xlink', _ATTRIBUTE_DEFAULT_XM); | ||
var ELEMENT_DEFAULT_XML_NAMESPACE = (_ELEMENT_DEFAULT_XML_ = {}, _ELEMENT_DEFAULT_XML_[ELEMENT_TAG.SVG] = "http://www.w3.org/2000/svg", _ELEMENT_DEFAULT_XML_); | ||
var ATTRIBUTE_DEFAULT_XML_NAMESPACE = (_ATTRIBUTE_DEFAULT_XM = {}, _ATTRIBUTE_DEFAULT_XM[ELEMENT_PROP.XLINK_HREF] = "http://www.w3.org/1999/xlink", _ATTRIBUTE_DEFAULT_XM); | ||
function fixScripts(el, doc) { | ||
@@ -26,12 +24,9 @@ if (doc === void 0) { | ||
} | ||
for (var _i2 = 0, _el$querySelectorAll2 = el.querySelectorAll('script'); _i2 < _el$querySelectorAll2.length; _i2++) { | ||
for (var _i2 = 0, _el$querySelectorAll2 = el.querySelectorAll("script"); _i2 < _el$querySelectorAll2.length; _i2++) { | ||
var script = _el$querySelectorAll2[_i2]; | ||
var parentNode = script.parentNode; | ||
if (!parentNode) { | ||
continue; | ||
} | ||
var newScript = doc.createElement('script'); | ||
var newScript = doc.createElement("script"); | ||
newScript.text = script.textContent; | ||
@@ -41,3 +36,2 @@ parentNode.replaceChild(newScript, script); | ||
} | ||
function createElement(doc, node) { | ||
@@ -50,27 +44,20 @@ if (node.props[ELEMENT_PROP.EL]) { | ||
} | ||
function createElementWithXMLNamespace(doc, node, xmlNamespace) { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
} | ||
function createTextElement(doc, node) { | ||
return doc.createTextNode(node.text); | ||
} | ||
function addProps(el, node) { | ||
var props = node.props; | ||
for (var _i4 = 0, _Object$keys2 = Object.keys(props); _i4 < _Object$keys2.length; _i4++) { | ||
var prop = _Object$keys2[_i4]; | ||
var val = props[prop]; | ||
if (val === null || typeof val === 'undefined' || prop === ELEMENT_PROP.EL || prop === ELEMENT_PROP.INNER_HTML) { | ||
if (val === null || typeof val === "undefined" || prop === ELEMENT_PROP.EL || prop === ELEMENT_PROP.INNER_HTML) { | ||
continue; | ||
} | ||
if (prop.match(/^on[A-Z][a-z]/) && typeof val === 'function') { | ||
if (prop.match(/^on[A-Z][a-z]/) && typeof val === "function") { | ||
el.addEventListener(prop.slice(2).toLowerCase(), val); | ||
} else if (typeof val === 'string' || typeof val === 'number') { | ||
} else if (typeof val === "string" || typeof val === "number") { | ||
var xmlNamespace = ATTRIBUTE_DEFAULT_XML_NAMESPACE[prop]; | ||
if (xmlNamespace) { | ||
@@ -81,41 +68,33 @@ el.setAttributeNS(xmlNamespace, prop, val.toString()); | ||
} | ||
} else if (typeof val === 'boolean') { | ||
} else if (typeof val === "boolean") { | ||
if (val === true) { | ||
el.setAttribute(prop, ''); | ||
el.setAttribute(prop, ""); | ||
} | ||
} | ||
} | ||
if (el.tagName.toLowerCase() === ELEMENT_TAG.IFRAME && !props.id) { | ||
el.setAttribute(ELEMENT_PROP.ID, "jsx-iframe-" + uniqueID()); | ||
} | ||
if (el.tagName.toLowerCase() === ELEMENT_TAG.IFRAME && !props.srcdoc && !props.src) { | ||
el.setAttribute("srcdoc", ""); | ||
} | ||
} | ||
var ADD_CHILDREN = (_ADD_CHILDREN = {}, _ADD_CHILDREN[ELEMENT_TAG.IFRAME] = function (el, node) { | ||
var firstChild = node.children[0]; | ||
if (node.children.length !== 1 || !(firstChild && firstChild.type === NODE_TYPE.ELEMENT) || firstChild.name !== ELEMENT_TAG.HTML) { | ||
throw new Error("Expected only single html element node as child of " + ELEMENT_TAG.IFRAME + " element"); | ||
} | ||
el.addEventListener('load', function () { | ||
// $FlowFixMe | ||
el.addEventListener("load", function () { | ||
var win = el.contentWindow; | ||
if (!win) { | ||
throw new Error("Expected frame to have contentWindow"); | ||
} | ||
var doc = win.document; | ||
var docElement = doc.documentElement; | ||
while (docElement.children && docElement.children.length) { | ||
docElement.removeChild(docElement.children[0]); | ||
} // eslint-disable-next-line no-use-before-define | ||
} | ||
var child = firstChild.render(dom({ | ||
doc: doc | ||
})); | ||
while (child.children.length) { | ||
@@ -127,8 +106,5 @@ docElement.appendChild(child.children[0]); | ||
var firstChild = node.children[0]; | ||
if (node.children.length !== 1 || !(firstChild && firstChild.type === NODE_TYPE.TEXT)) { | ||
throw new Error("Expected only single text node as child of " + ELEMENT_TAG.SCRIPT + " element"); | ||
} // $FlowFixMe | ||
} | ||
el.text = firstChild.text; | ||
@@ -141,3 +117,2 @@ }, _ADD_CHILDREN[ELEMENT_TAG.DEFAULT] = function (el, node, renderer) { | ||
}, _ADD_CHILDREN); | ||
function addChildren(el, node, doc, renderer) { | ||
@@ -148,11 +123,7 @@ if (node.props.hasOwnProperty(ELEMENT_PROP.INNER_HTML)) { | ||
} | ||
var html = node.props[ELEMENT_PROP.INNER_HTML]; | ||
if (typeof html !== 'string') { | ||
if (typeof html !== "string") { | ||
throw new TypeError(ELEMENT_PROP.INNER_HTML + " prop must be string"); | ||
} | ||
if (node.name === ELEMENT_TAG.SCRIPT) { | ||
// $FlowFixMe | ||
el.text = html; | ||
@@ -168,8 +139,5 @@ } else { | ||
} | ||
var getDefaultDomOptions = function getDefaultDomOptions() { | ||
// $FlowFixMe | ||
return {}; | ||
}; | ||
export function dom(opts) { | ||
@@ -179,19 +147,14 @@ if (opts === void 0) { | ||
} | ||
var _opts = opts, | ||
_opts$doc = _opts.doc, | ||
doc = _opts$doc === void 0 ? document : _opts$doc; | ||
var xmlNamespaceDomRenderer = function xmlNamespaceDomRenderer(node, xmlNamespace) { | ||
_opts$doc = _opts.doc, | ||
doc = _opts$doc === void 0 ? document : _opts$doc; | ||
var _xmlNamespaceDomRenderer = function xmlNamespaceDomRenderer(node, xmlNamespace) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent(function (childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
}); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
@@ -201,40 +164,28 @@ var el = createElementWithXMLNamespace(doc, node, xmlNamespace); | ||
addChildren(el, node, doc, function (childNode) { | ||
return xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
}); // $FlowFixMe | ||
return _xmlNamespaceDomRenderer(childNode, xmlNamespace); | ||
}); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
var domRenderer = function domRenderer(node) { | ||
var _domRenderer = function domRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent(domRenderer); | ||
return node.renderComponent(_domRenderer); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
var xmlNamespace = ELEMENT_DEFAULT_XML_NAMESPACE[node.name.toLowerCase()]; | ||
if (xmlNamespace) { | ||
// $FlowFixMe | ||
return xmlNamespaceDomRenderer(node, xmlNamespace); | ||
return _xmlNamespaceDomRenderer(node, xmlNamespace); | ||
} | ||
var el = createElement(doc, node); | ||
addProps(el, node); | ||
addChildren(el, node, doc, domRenderer); // $FlowFixMe | ||
addChildren(el, node, doc, _domRenderer); | ||
return el; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
return domRenderer; | ||
return _domRenderer; | ||
} |
@@ -1,6 +0,5 @@ | ||
/* eslint unicorn/prefer-spread: off */ | ||
import { ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
var ELEMENT_PROP = { | ||
INNER_HTML: 'innerHTML' | ||
INNER_HTML: "innerHTML" | ||
}; | ||
@@ -10,71 +9,54 @@ var SELF_CLOSING_TAGS = { | ||
}; | ||
function htmlEncode(text) { | ||
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); | ||
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'").replace(/\//g, "/"); | ||
} | ||
function propsToHTML(props) { | ||
var keys = Object.keys(props).filter(function (key) { | ||
var val = props[key]; | ||
if (key === ELEMENT_PROP.INNER_HTML) { | ||
return false; | ||
} | ||
if (typeof val === 'string' || typeof val === 'number' || val === true) { | ||
if (typeof val === "string" || typeof val === "number" || val === true) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
if (!keys.length) { | ||
return ''; | ||
return ""; | ||
} | ||
var pairs = keys.map(function (key) { | ||
var val = props[key]; | ||
if (val === true) { | ||
return "" + htmlEncode(key); | ||
} | ||
if (typeof val !== 'string' && typeof val !== 'number') { | ||
if (typeof val !== "string" && typeof val !== "number") { | ||
throw new TypeError("Unexpected prop type: " + typeof val); | ||
} | ||
if (val === '') { | ||
if (val === "") { | ||
return htmlEncode(key); | ||
} | ||
return htmlEncode(key) + "=\"" + htmlEncode(val.toString()) + "\""; | ||
}); | ||
return " " + pairs.join(' '); | ||
return " " + pairs.join(" "); | ||
} | ||
export function html() { | ||
var htmlRenderer = function htmlRenderer(node) { | ||
var _htmlRenderer = function htmlRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(htmlRenderer)).join(''); | ||
return [].concat(node.renderComponent(_htmlRenderer)).join(""); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
var renderedProps = propsToHTML(node.props); | ||
if (SELF_CLOSING_TAGS[node.name]) { | ||
return "<" + node.name + renderedProps + " />"; | ||
} else { | ||
var renderedChildren = typeof node.props[ELEMENT_PROP.INNER_HTML] === 'string' ? node.props[ELEMENT_PROP.INNER_HTML] : node.renderChildren(htmlRenderer).join(''); | ||
var renderedChildren = typeof node.props[ELEMENT_PROP.INNER_HTML] === "string" ? node.props[ELEMENT_PROP.INNER_HTML] : node.renderChildren(_htmlRenderer).join(""); | ||
return "<" + node.name + renderedProps + ">" + renderedChildren + "</" + node.name + ">"; | ||
} | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return htmlEncode(node.text); | ||
} | ||
throw new TypeError("Unhandleable node: " + node.type); | ||
}; | ||
return htmlRenderer; | ||
return _htmlRenderer; | ||
} |
@@ -1,6 +0,6 @@ | ||
export * from './text'; | ||
export * from './dom'; | ||
export * from './react'; | ||
export * from './html'; | ||
export * from './preact'; | ||
export * from './regex'; | ||
export * from "./text"; | ||
export * from "./dom"; | ||
export * from "./react"; | ||
export * from "./html"; | ||
export * from "./preact"; | ||
export * from "./regex"; |
import _extends from "@babel/runtime/helpers/esm/extends"; | ||
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; | ||
var _excluded = ["innerHTML"]; | ||
import { ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
function mapPreactProps(props) { | ||
var innerHTML = props.innerHTML, | ||
remainingProps = _objectWithoutPropertiesLoose(props, _excluded); | ||
remainingProps = _objectWithoutPropertiesLoose(props, _excluded); | ||
var dangerouslySetInnerHTML = innerHTML ? { | ||
__html: innerHTML | ||
} : null; // $FlowFixMe | ||
} : null; | ||
return _extends({ | ||
@@ -19,30 +16,23 @@ dangerouslySetInnerHTML: dangerouslySetInnerHTML | ||
} | ||
export function preact(_temp) { | ||
var _ref = _temp === void 0 ? {} : _temp, | ||
Preact = _ref.Preact; | ||
Preact = _ref.Preact; | ||
if (!Preact) { | ||
throw new Error("Must pass Preact library to react renderer"); | ||
} | ||
var reactRenderer = function reactRenderer(node) { | ||
var _reactRenderer = function reactRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return Preact.h.apply(Preact, [function () { | ||
return node.renderComponent(reactRenderer) || null; | ||
}, node.props].concat(node.renderChildren(reactRenderer))); | ||
return node.renderComponent(_reactRenderer) || null; | ||
}, node.props].concat(node.renderChildren(_reactRenderer))); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return Preact.h.apply(Preact, [node.name, mapPreactProps(node.props)].concat(node.renderChildren(reactRenderer))); | ||
return Preact.h.apply(Preact, [node.name, mapPreactProps(node.props)].concat(node.renderChildren(_reactRenderer))); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
return reactRenderer; | ||
return _reactRenderer; | ||
} |
import _extends from "@babel/runtime/helpers/esm/extends"; | ||
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; | ||
var _excluded = ["innerHTML", "class"]; | ||
import { ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
function mapReactProps(props) { | ||
var innerHTML = props.innerHTML, | ||
className = props.class, | ||
remainingProps = _objectWithoutPropertiesLoose(props, _excluded); | ||
className = props.class, | ||
remainingProps = _objectWithoutPropertiesLoose(props, _excluded); | ||
var dangerouslySetInnerHTML = innerHTML ? { | ||
__html: innerHTML | ||
} : null; // $FlowFixMe | ||
} : null; | ||
return _extends({ | ||
@@ -21,30 +18,23 @@ dangerouslySetInnerHTML: dangerouslySetInnerHTML, | ||
} | ||
export function react(_temp) { | ||
var _ref = _temp === void 0 ? {} : _temp, | ||
React = _ref.React; | ||
React = _ref.React; | ||
if (!React) { | ||
throw new Error("Must pass React library to react renderer"); | ||
} | ||
var reactRenderer = function reactRenderer(node) { | ||
var _reactRenderer = function reactRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return React.createElement.apply(React, [function () { | ||
return node.renderComponent(reactRenderer) || null; | ||
}, node.props].concat(node.renderChildren(reactRenderer))); | ||
return node.renderComponent(_reactRenderer) || null; | ||
}, node.props].concat(node.renderChildren(_reactRenderer))); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return React.createElement.apply(React, [node.name, mapReactProps(node.props)].concat(node.renderChildren(reactRenderer))); | ||
return React.createElement.apply(React, [node.name, mapReactProps(node.props)].concat(node.renderChildren(_reactRenderer))); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError("Unhandleable node"); | ||
}; | ||
return reactRenderer; | ||
return _reactRenderer; | ||
} |
@@ -1,11 +0,9 @@ | ||
import { node, ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { text } from './text'; | ||
import { node, ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { text } from "./text"; | ||
export function regex() { | ||
var regexRenderer = text(); // eslint-disable-next-line security/detect-non-literal-regexp | ||
var regexRenderer = text(); | ||
return function (nodeInstance) { | ||
return new RegExp(regexRenderer(nodeInstance)); | ||
}; | ||
} // $FlowFixMe | ||
} | ||
regex.node = function (el, props) { | ||
@@ -15,11 +13,7 @@ for (var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
} | ||
// $FlowFixMe | ||
var nodeInstance = node.apply(void 0, [el, props].concat(children)); | ||
if (el.renderer) { | ||
return nodeInstance.render(el.renderer()); | ||
} | ||
return nodeInstance; | ||
}; |
@@ -1,22 +0,17 @@ | ||
/* eslint unicorn/prefer-spread: off */ | ||
import { ComponentNode, TextNode, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { ComponentNode, TextNode, ElementNode } from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
export function text() { | ||
var textRenderer = function textRenderer(node) { | ||
var _textRenderer = function textRenderer(node) { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(textRenderer)).join(''); | ||
return [].concat(node.renderComponent(_textRenderer)).join(""); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
throw new Error("Text renderer does not support basic elements"); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError("Unhandleable node: " + node.type); | ||
}; | ||
return textRenderer; | ||
return _textRenderer; | ||
} |
@@ -1,2 +0,1 @@ | ||
// export something to force webpack to see this as an ES module | ||
export var TYPES = true; |
@@ -1,10 +0,9 @@ | ||
var ALPHA_CHARS = '0123456789abcdef'; | ||
var ALPHA_CHARS = "0123456789abcdef"; | ||
export function uniqueID() { | ||
return 'xxxxxxxxxx'.replace(/./g, function () { | ||
return "xxxxxxxxxx".replace(/./g, function () { | ||
return ALPHA_CHARS.charAt(Math.floor(Math.random() * ALPHA_CHARS.length)); | ||
}); | ||
} // eslint-disable-next-line flowtype/no-weak-types | ||
} | ||
export function isDefined(val) { | ||
return val !== null && typeof val !== 'undefined'; | ||
return val !== null && typeof val !== "undefined"; | ||
} |
/* @flow */ | ||
// $FlowFixMe | ||
module.exports = require('./dist/jsx-pragmatic'); // eslint-disable-line import/no-commonjs | ||
module.exports = require("./dist/jsx-pragmatic"); // eslint-disable-line import/no-commonjs |
{ | ||
"name": "@krakenjs/jsx-pragmatic", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "Javascript module template.", | ||
@@ -8,13 +8,15 @@ "main": "index.js", | ||
"dev": "babel-node --plugins @babel/plugin-transform-modules-commonjs $(npm bin)/webpack-dev-server --config webpack.config.js --port 9000 --open-page demo/dev/index.htm --hot=false --inline=false", | ||
"setup": "npm install && npm run flow-typed", | ||
"setup": "npm install", | ||
"lint": "eslint src/ test/ *.js --ext .js,.jsx", | ||
"flow-typed": "rm -rf ./flow-typed && flow-typed install && flow-typed install react@6 && flow-typed install mocha@4", | ||
"flow": "flow", | ||
"format": "prettier --write --ignore-unknown .", | ||
"format:check": "prettier --check .", | ||
"karma": "cross-env NODE_ENV=test babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/karma start", | ||
"babel": "babel src/ --out-dir dist/module", | ||
"webpack": "babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/webpack --progress", | ||
"test": "npm run lint && npm run flow-typed && npm run flow && npm run karma", | ||
"test": "npm run format:check && npm run lint && npm run flow && npm run karma", | ||
"build": "npm run test && npm run babel && npm run webpack", | ||
"clean": "rimraf dist coverage", | ||
"reinstall": "rimraf flow-typed && rimraf node_modules && npm install && flow-typed install", | ||
"reinstall": "rimraf node_modules && npm install", | ||
"debug": "cross-env NODE_ENV=debug", | ||
@@ -94,8 +96,16 @@ "prepare": "husky install", | ||
"@commitlint/config-conventional": "^16.2.1", | ||
"flow-bin": "0.135.0", | ||
"grumbler-scripts": "^5.0.3", | ||
"@krakenjs/grumbler-scripts": "^8.0.4", | ||
"cross-env": "^7.0.3", | ||
"flow-bin": "^0.135.0", | ||
"flow-typed": "^3.9.0", | ||
"husky": "^7.0.4", | ||
"jest": "^29.3.1", | ||
"lint-staged": "^12.4.0", | ||
"mocha": "^4.1.0", | ||
"prettier": "^2.6.2", | ||
"standard-version": "^9.3.2" | ||
}, | ||
"lint-staged": { | ||
"*": "prettier --write --ignore-unknown" | ||
} | ||
} |
@@ -1,3 +0,2 @@ | ||
JSX Pragmatic | ||
------------- | ||
## JSX Pragmatic | ||
@@ -8,3 +7,3 @@ [![build status][build-badge]][build] | ||
[build-badge]: https://img.shields.io/github/workflow/status/krakenjs/jsx-pragmatic/build?logo=github&style=flat-square | ||
[build-badge]: https://img.shields.io/github/actions/workflow/status/krakenjs/jsx-pragmatic/main.yml?branch=main&logo=github&style=flat-square | ||
[build]: https://github.com/krakenjs/jsx-pragmatic/actions?query=workflow:build | ||
@@ -29,3 +28,3 @@ [coverage-badge]: https://img.shields.io/codecov/c/github/krakenjs/jsx-pragmatic.svg?style=flat-square | ||
import { node } from 'jsx-pragmatic'; | ||
import { node } from "jsx-pragmatic"; | ||
@@ -50,9 +49,7 @@ function Login({ prefilledEmail }) { | ||
import { node, html } from 'jsx-pragmatic'; | ||
import { Login } from './components' | ||
import { node, html } from "jsx-pragmatic"; | ||
import { Login } from "./components"; | ||
function render() { | ||
return ( | ||
<Login prefilledEmail='foo@bar.com' /> | ||
).render(html()); | ||
return (<Login prefilledEmail="foo@bar.com" />).render(html()); | ||
} | ||
@@ -68,9 +65,7 @@ ``` | ||
import { node, dom } from 'jsx-pragmatic'; | ||
import { Login } from './components' | ||
import { node, dom } from "jsx-pragmatic"; | ||
import { Login } from "./components"; | ||
function render() { | ||
return ( | ||
<Login prefilledEmail='foo@bar.com' /> | ||
).render(dom()); | ||
return (<Login prefilledEmail="foo@bar.com" />).render(dom()); | ||
} | ||
@@ -86,9 +81,7 @@ ``` | ||
import { node, react } from 'jsx-pragmatic'; | ||
import { Login } from './components' | ||
import { node, react } from "jsx-pragmatic"; | ||
import { Login } from "./components"; | ||
function render() { | ||
return ( | ||
<Login prefilledEmail='foo@bar.com' /> | ||
).render(react({ React })); | ||
return (<Login prefilledEmail="foo@bar.com" />).render(react({ React })); | ||
} | ||
@@ -104,9 +97,7 @@ ``` | ||
import { node, preact } from 'jsx-pragmatic'; | ||
import { Login } from './components' | ||
import { node, preact } from "jsx-pragmatic"; | ||
import { Login } from "./components"; | ||
function render() { | ||
return ( | ||
<Login prefilledEmail='foo@bar.com' /> | ||
).render(preact({ Preact })); | ||
return (<Login prefilledEmail="foo@bar.com" />).render(preact({ Preact })); | ||
} | ||
@@ -127,7 +118,6 @@ ``` | ||
import { node, NODE_TYPE } from 'jsx-pragmatic'; | ||
import { Login } from './components' | ||
import { node, NODE_TYPE } from "jsx-pragmatic"; | ||
import { Login } from "./components"; | ||
function customDom({ removeScriptTags } = { removeScriptTags: false }) { | ||
let domRenderer = (node) => { | ||
@@ -143,3 +133,3 @@ if (node.type === NODE_TYPE.COMPONENT) { | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
if (removeScriptTags && node.name === 'script') { | ||
if (removeScriptTags && node.name === "script") { | ||
return; | ||
@@ -150,3 +140,3 @@ } | ||
for (let [ key, val ] of Object.entries(node.props)) { | ||
for (let [key, val] of Object.entries(node.props)) { | ||
el.setAttribute(key, val); | ||
@@ -161,3 +151,3 @@ } | ||
} | ||
} | ||
}; | ||
@@ -172,5 +162,5 @@ return domRenderer; | ||
function render() { | ||
return ( | ||
<Login prefilledEmail='foo@bar.com' /> | ||
).render(customDom({ removeScriptTags: true })); | ||
return (<Login prefilledEmail="foo@bar.com" />).render( | ||
customDom({ removeScriptTags: true }) | ||
); | ||
} | ||
@@ -186,3 +176,3 @@ ``` | ||
import { node, Fragment } from 'jsx-pragmatic'; | ||
import { node, Fragment } from "jsx-pragmatic"; | ||
@@ -206,3 +196,3 @@ function Login({ prefilledEmail }) { | ||
import { node, Fragment } from 'jsx-pragmatic'; | ||
import { node, Fragment } from "jsx-pragmatic"; | ||
@@ -244,4 +234,3 @@ function Login({ prefilledEmail }) { | ||
Quick Start | ||
----------- | ||
## Quick Start | ||
@@ -248,0 +237,0 @@ #### Install |
/* @flow */ | ||
export * from './style'; | ||
export * from './regex'; | ||
export * from "./style"; | ||
export * from "./regex"; |
/* @flow */ | ||
/** @jsx node */ | ||
import { type ChildType, type ChildrenType, TextNode } from '../node'; | ||
import { isDefined } from '../util'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { regex } from '../renderers'; | ||
import { type ChildType, type ChildrenType, TextNode } from "../node"; | ||
import { isDefined } from "../util"; | ||
import { NODE_TYPE } from "../constants"; | ||
import { regex } from "../renderers"; | ||
const escapeRegex = (text : string) : string => { | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&'); | ||
const escapeRegex = (text: string): string => { | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); | ||
}; | ||
const validateChildren = (name : string, children : ?ChildrenType) : ChildrenType => { | ||
if (!children) { | ||
throw new Error(`Must pass children to ${ name }`); | ||
} | ||
const validateChildren = ( | ||
name: string, | ||
children: ?ChildrenType | ||
): ChildrenType => { | ||
if (!children) { | ||
throw new Error(`Must pass children to ${name}`); | ||
} | ||
return children; | ||
return children; | ||
}; | ||
const validateNoChildren = (name : string, children : ?ChildrenType) => { | ||
if (children && children.length) { | ||
throw new Error(`Must not pass children to ${ name }`); | ||
} | ||
const validateNoChildren = (name: string, children: ?ChildrenType) => { | ||
if (children && children.length) { | ||
throw new Error(`Must not pass children to ${name}`); | ||
} | ||
}; | ||
const validateAndEscapeChildren = (name : string, children : ?ChildrenType) : ChildrenType => { | ||
children = validateChildren(name, children); | ||
const validateAndEscapeChildren = ( | ||
name: string, | ||
children: ?ChildrenType | ||
): ChildrenType => { | ||
children = validateChildren(name, children); | ||
return children.map(child => { | ||
if (child.type === NODE_TYPE.TEXT) { | ||
return new TextNode(escapeRegex(child.text)); | ||
} | ||
return children.map((child) => { | ||
if (child.type === NODE_TYPE.TEXT) { | ||
return new TextNode(escapeRegex(child.text)); | ||
} | ||
return child; | ||
}); | ||
return child; | ||
}); | ||
}; | ||
export type RegexOptions = {| | ||
exact? : boolean | ||
exact?: boolean, | ||
|}; | ||
export function Regex({ exact = true } : RegexOptions, children? : ChildrenType) : ChildType { | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
export function Regex( | ||
{ exact = true }: RegexOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
if (!exact) { | ||
return children; | ||
} | ||
if (!exact) { | ||
return children; | ||
} | ||
return [ | ||
'^', | ||
...children, | ||
'$' | ||
]; | ||
return ["^", ...children, "$"]; | ||
} | ||
@@ -59,114 +64,123 @@ | ||
type RegexTextOptions = {| | ||
|}; | ||
type RegexTextOptions = {||}; | ||
export function RegexText(props : RegexTextOptions, children? : ChildrenType) : ChildType { | ||
return validateAndEscapeChildren('RegexText', children); | ||
export function RegexText( | ||
props: RegexTextOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
return validateAndEscapeChildren("RegexText", children); | ||
} | ||
type RegexWordOptions = {| | ||
|}; | ||
type RegexWordOptions = {||}; | ||
export function RegexWord(props : RegexWordOptions, children? : ChildrenType) : ChildType { | ||
validateNoChildren('RegexWord', children); | ||
export function RegexWord( | ||
props: RegexWordOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
validateNoChildren("RegexWord", children); | ||
return '\\w+'; | ||
return "\\w+"; | ||
} | ||
type RegexCharactersOptions = {||}; | ||
type RegexCharactersOptions = {| | ||
|}; | ||
export function RegexCharacters(props : RegexCharactersOptions, children? : ChildrenType) : ChildType { | ||
return [ | ||
'[', | ||
...validateAndEscapeChildren('RegexText', children), | ||
']' | ||
]; | ||
export function RegexCharacters( | ||
props: RegexCharactersOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
return ["[", ...validateAndEscapeChildren("RegexText", children), "]"]; | ||
} | ||
type RegexGroupOptions = {| | ||
optional? : boolean, | ||
repeat? : boolean | number, | ||
repeatMin? : number, | ||
repeatMax? : number, | ||
capture? : boolean, | ||
union? : boolean, | ||
name? : string | ||
optional?: boolean, | ||
repeat?: boolean | number, | ||
repeatMin?: number, | ||
repeatMax?: number, | ||
capture?: boolean, | ||
union?: boolean, | ||
name?: string, | ||
|}; | ||
export function RegexGroup({ repeat, repeatMin, repeatMax, name, optional = false, capture = true, union = false } : RegexGroupOptions, children? : ChildrenType) : ChildType { | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
export function RegexGroup( | ||
{ | ||
repeat, | ||
repeatMin, | ||
repeatMax, | ||
name, | ||
optional = false, | ||
capture = true, | ||
union = false, | ||
}: RegexGroupOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
if (isDefined(repeat) && (isDefined(repeatMin) || isDefined(repeatMax))) { | ||
throw new Error(`repeat can not be used with repeatMin or repeatMax`); | ||
} | ||
if (isDefined(repeat) && (isDefined(repeatMin) || isDefined(repeatMax))) { | ||
throw new Error(`repeat can not be used with repeatMin or repeatMax`); | ||
} | ||
if (name && !capture) { | ||
throw new Error(`Named groups must be captured`); | ||
} | ||
if (name && !capture) { | ||
throw new Error(`Named groups must be captured`); | ||
} | ||
if (union) { | ||
const result = []; | ||
if (union) { | ||
const result = []; | ||
for (const child of children) { | ||
result.push(child); | ||
result.push(new TextNode('|')); | ||
} | ||
result.pop(); | ||
children = result; | ||
for (const child of children) { | ||
result.push(child); | ||
result.push(new TextNode("|")); | ||
} | ||
const result = []; | ||
result.pop(); | ||
children = result; | ||
} | ||
result.push(capture ? '(' : '(?:'); | ||
const result = []; | ||
if (name) { | ||
result.push(`?<${ escapeRegex(name) }>`); | ||
} | ||
result.push(capture ? "(" : "(?:"); | ||
result.push(...children); | ||
result.push(')'); | ||
if (name) { | ||
result.push(`?<${escapeRegex(name)}>`); | ||
} | ||
if (isDefined(repeat)) { | ||
if (typeof repeat === 'number') { | ||
result.push(`{${ repeat }}`); | ||
} else if (repeat === true) { | ||
result.push(`+`); | ||
} | ||
} | ||
result.push(...children); | ||
result.push(")"); | ||
if (isDefined(repeatMin) || isDefined(repeatMax)) { | ||
result.push(`{${ repeatMin || '' },${ repeatMax || '' }}`); | ||
if (isDefined(repeat)) { | ||
if (typeof repeat === "number") { | ||
result.push(`{${repeat}}`); | ||
} else if (repeat === true) { | ||
result.push(`+`); | ||
} | ||
} | ||
if (optional) { | ||
result.push('?'); | ||
} | ||
if (isDefined(repeatMin) || isDefined(repeatMax)) { | ||
result.push(`{${repeatMin || ""},${repeatMax || ""}}`); | ||
} | ||
return result; | ||
if (optional) { | ||
result.push("?"); | ||
} | ||
return result; | ||
} | ||
type RegexUnionOptions = {| | ||
type RegexUnionOptions = {||}; | ||
|}; | ||
export function RegexUnion( | ||
props: RegexUnionOptions, | ||
children?: ChildrenType | ||
): ChildType { | ||
children = validateAndEscapeChildren("RegexGroup", children); | ||
export function RegexUnion(props : RegexUnionOptions, children? : ChildrenType) : ChildType { | ||
children = validateAndEscapeChildren('RegexGroup', children); | ||
const result = []; | ||
const result = []; | ||
for (const child of children) { | ||
result.push(child); | ||
result.push("|"); | ||
} | ||
for (const child of children) { | ||
result.push(child); | ||
result.push('|'); | ||
} | ||
result.pop(); | ||
result.pop(); | ||
return result; | ||
return result; | ||
} |
/* @flow */ | ||
/** @jsx node */ | ||
import { Fragment, node, type ChildType, type NullableChildrenType } from '../node'; | ||
import { | ||
Fragment, | ||
node, | ||
type ChildType, | ||
type NullableChildrenType, | ||
} from "../node"; | ||
type StyleProps = {| | ||
css : string | {| _getCss : () => string |}, | ||
nonce? : ?string, | ||
children? : ?NullableChildrenType | ||
css: string | {| _getCss: () => string |}, | ||
nonce?: ?string, | ||
children?: ?NullableChildrenType, | ||
|}; | ||
export function Style({ css, nonce, children } : StyleProps) : ChildType { | ||
return ( | ||
<Fragment> | ||
<style innerHTML={ typeof css === 'string' ? css : css._getCss() } nonce={ nonce } /> | ||
{ children } | ||
</Fragment> | ||
); | ||
export function Style({ css, nonce, children }: StyleProps): ChildType { | ||
return ( | ||
<Fragment> | ||
<style | ||
innerHTML={typeof css === "string" ? css : css._getCss()} | ||
nonce={nonce} | ||
/> | ||
{children} | ||
</Fragment> | ||
); | ||
} |
/* @flow */ | ||
export const NODE_TYPE = { | ||
ELEMENT: ('element' : 'element'), | ||
TEXT: ('text' : 'text'), | ||
COMPONENT: ('component' : 'component'), | ||
FRAGMENT: ('fragment' : 'fragment') | ||
ELEMENT: ("element": "element"), | ||
TEXT: ("text": "text"), | ||
COMPONENT: ("component": "component"), | ||
FRAGMENT: ("fragment": "fragment"), | ||
}; |
/* @flow */ | ||
export * from './node'; | ||
export * from './renderers'; | ||
export * from './constants'; | ||
export * from './component'; | ||
export * from "./node"; | ||
export * from "./renderers"; | ||
export * from "./constants"; | ||
export * from "./component"; |
292
src/node.js
/* @flow */ | ||
/* eslint no-use-before-define: off, no-undef: off*/ | ||
// Need to update to babel-eslint that is aware of flow generics | ||
import { NODE_TYPE } from './constants'; | ||
import { NODE_TYPE } from "./constants"; | ||
export type NodePropsType = { | ||
[string] : any // eslint-disable-line flowtype/no-weak-types | ||
[string]: any, // eslint-disable-line flowtype/no-weak-types | ||
}; | ||
@@ -17,98 +19,126 @@ | ||
export type NodeType = ElementNode | TextNode | FragmentNode | ComponentNode<*>; // eslint-disable-line no-use-before-define | ||
export type ChildNodeType = ElementNode | TextNode | ComponentNode<*>; // eslint-disable-line no-use-before-define | ||
export type NodeType = ElementNode | TextNode | FragmentNode | ComponentNode<*>; | ||
export type ChildNodeType = ElementNode | TextNode | ComponentNode<*>; | ||
export type ChildType = ChildNodeType | Primitive | $ReadOnlyArray<ChildType>; | ||
export type ChildrenType = $ReadOnlyArray<ChildNodeType>; | ||
export type NullableChildType = $ReadOnlyArray<ChildType> | ChildNodeType | NullablePrimitive; | ||
export type NullableChildrenType = $ReadOnlyArray<NullableChildrenType | ChildNodeType | NullablePrimitive>; | ||
export type NullableChildType = | ||
| $ReadOnlyArray<ChildType> | ||
| ChildNodeType | ||
| NullablePrimitive; | ||
export type NullableChildrenType = $ReadOnlyArray< | ||
NullableChildrenType | ChildNodeType | NullablePrimitive | ||
>; | ||
export type ComponentFunctionType<P> = (P, ChildrenType) => NullableChildType; | ||
export type CreateElementNode = <P>(string, P, ...NullableChildrenType) => ElementNode; // eslint-disable-line no-undef, no-use-before-define | ||
export type CreateComponentNode = <P>(ComponentFunctionType<P>, P, ...NullableChildrenType) => ComponentNode<*>; // eslint-disable-line no-undef, no-use-before-define | ||
export type CreateNullComponentNode = <P>(ComponentFunctionType<P>, null, ...NullableChildrenType) => ComponentNode<*>; // eslint-disable-line no-undef, no-use-before-define | ||
export type CreateElementNode = <P>( | ||
string, | ||
P, | ||
...NullableChildrenType | ||
) => ElementNode; | ||
export type CreateComponentNode = <P>( | ||
ComponentFunctionType<P>, | ||
P, | ||
...NullableChildrenType | ||
) => ComponentNode<*>; | ||
export type CreateNullComponentNode = <P>( | ||
ComponentFunctionType<P>, | ||
null, | ||
...NullableChildrenType | ||
) => ComponentNode<*>; | ||
export type CreateNode = CreateNullComponentNode & CreateComponentNode & CreateElementNode; | ||
export type CreateNode = CreateNullComponentNode & | ||
CreateComponentNode & | ||
CreateElementNode; | ||
function renderChildren<T>(children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>, renderer : NodeRenderer<*, *>) : $ReadOnlyArray<T> { // eslint-disable-line no-use-before-define | ||
const result = []; | ||
function renderChildren<T>( | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>, | ||
renderer: NodeRenderer<*, *> | ||
): $ReadOnlyArray<T> { | ||
const result = []; | ||
for (const child of children) { | ||
const renderedChild = child.render(renderer); | ||
for (const child of children) { | ||
const renderedChild = child.render(renderer); | ||
if (!renderedChild) { | ||
continue; | ||
} else if (Array.isArray(renderedChild)) { | ||
for (const subchild of renderedChild) { | ||
if (subchild) { | ||
result.push(subchild); | ||
} | ||
} | ||
} else { | ||
result.push(renderedChild); | ||
if (!renderedChild) { | ||
continue; | ||
} else if (Array.isArray(renderedChild)) { | ||
for (const subchild of renderedChild) { | ||
if (subchild) { | ||
result.push(subchild); | ||
} | ||
} | ||
} else { | ||
result.push(renderedChild); | ||
} | ||
} | ||
return result; | ||
return result; | ||
} | ||
export class ElementNode { | ||
type : (typeof NODE_TYPE.ELEMENT) = NODE_TYPE.ELEMENT; | ||
type: typeof NODE_TYPE.ELEMENT = NODE_TYPE.ELEMENT; | ||
name : string; | ||
props : NodePropsType; | ||
children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; // eslint-disable-line no-use-before-define | ||
onRender : ?<T>(T) => void; // eslint-disable-line no-undef | ||
name: string; | ||
props: NodePropsType; | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; | ||
onRender: ?<T>(T) => void; | ||
constructor(name : string, props : NodePropsType, children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>) { // eslint-disable-line no-use-before-define | ||
this.name = name; | ||
this.props = props || {}; | ||
this.children = children; | ||
constructor( | ||
name: string, | ||
props: NodePropsType, | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>> | ||
) { | ||
this.name = name; | ||
this.props = props || {}; | ||
this.children = children; | ||
const onRender = this.props.onRender; | ||
if (typeof onRender === 'function') { | ||
this.onRender = onRender; | ||
delete props.onRender; | ||
} | ||
const onRender = this.props.onRender; | ||
if (typeof onRender === "function") { | ||
this.onRender = onRender; | ||
delete props.onRender; | ||
} | ||
} | ||
render<T>(renderer : NodeRenderer<*, *>) : T { | ||
const el = renderer(this); | ||
if (this.onRender) { | ||
this.onRender(el); | ||
} | ||
return el; | ||
render<T>(renderer: NodeRenderer<*, *>): T { | ||
const el = renderer(this); | ||
if (this.onRender) { | ||
this.onRender(el); | ||
} | ||
return el; | ||
} | ||
renderChildren<T>(renderer : NodeRenderer<*, *>) : $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
renderChildren<T>(renderer: NodeRenderer<*, *>): $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
} | ||
export class FragmentNode { | ||
type : (typeof NODE_TYPE.FRAGMENT) = NODE_TYPE.FRAGMENT; | ||
type: typeof NODE_TYPE.FRAGMENT = NODE_TYPE.FRAGMENT; | ||
children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; // eslint-disable-line no-use-before-define | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; | ||
constructor(children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>) { // eslint-disable-line no-use-before-define | ||
this.children = children; | ||
} | ||
constructor( | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>> | ||
) { | ||
this.children = children; | ||
} | ||
render<T>(renderer : NodeRenderer<*, *>) : $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
render<T>(renderer: NodeRenderer<*, *>): $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
} | ||
export class TextNode { | ||
type : (typeof NODE_TYPE.TEXT) = NODE_TYPE.TEXT; | ||
type: typeof NODE_TYPE.TEXT = NODE_TYPE.TEXT; | ||
text : string; | ||
text: string; | ||
constructor(text : string) { | ||
this.text = text; | ||
} | ||
constructor(text: string) { | ||
this.text = text; | ||
} | ||
render<T>(renderer : NodeRenderer<*, *>) : T { | ||
return renderer(this); | ||
} | ||
render<T>(renderer: NodeRenderer<*, *>): T { | ||
return renderer(this); | ||
} | ||
} | ||
@@ -118,85 +148,97 @@ | ||
export class ComponentNode<P = null> { | ||
type : (typeof NODE_TYPE.COMPONENT) = NODE_TYPE.COMPONENT; | ||
type: typeof NODE_TYPE.COMPONENT = NODE_TYPE.COMPONENT; | ||
component : ComponentFunctionType<NodePropsType>; | ||
props : NodePropsType; | ||
// eslint-disable-next-line no-use-before-define | ||
children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; | ||
component: ComponentFunctionType<NodePropsType>; | ||
props: NodePropsType; | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>; | ||
constructor(component : ComponentFunctionType<NodePropsType>, props : NodePropsType, children : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>>) { | ||
this.component = component; | ||
this.props = props || {}; | ||
this.children = children; | ||
constructor( | ||
component: ComponentFunctionType<NodePropsType>, | ||
props: NodePropsType, | ||
children: $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>> | ||
) { | ||
this.component = component; | ||
this.props = props || {}; | ||
this.children = children; | ||
this.props.children = children; | ||
} | ||
this.props.children = children; | ||
} | ||
renderComponent(renderer : NodeRenderer<*, *>) : * { | ||
const child = normalizeChild(this.component(this.props, this.children)); // eslint-disable-line no-use-before-define | ||
if (child) { | ||
return child.render(renderer); | ||
} | ||
renderComponent(renderer: NodeRenderer<*, *>): * { | ||
const child = normalizeChild(this.component(this.props, this.children)); | ||
if (child) { | ||
return child.render(renderer); | ||
} | ||
} | ||
render<T>(renderer : NodeRenderer<*, *>) : T { | ||
return renderer(this); | ||
} | ||
render<T>(renderer: NodeRenderer<*, *>): T { | ||
return renderer(this); | ||
} | ||
renderChildren<T>(renderer : NodeRenderer<*, *>) : $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
renderChildren<T>(renderer: NodeRenderer<*, *>): $ReadOnlyArray<T> { | ||
return renderChildren(this.children, renderer); | ||
} | ||
} | ||
function normalizeChildren(children : NullableChildrenType) : $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>> { | ||
const result = []; | ||
function normalizeChildren( | ||
children: NullableChildrenType | ||
): $ReadOnlyArray<ElementNode | TextNode | ComponentNode<*>> { | ||
const result = []; | ||
for (const child of children) { | ||
if (!child) { | ||
continue; | ||
} else if (typeof child === 'string' || typeof child === 'number') { | ||
result.push(new TextNode(child.toString())); | ||
} else if (typeof child === 'boolean') { | ||
continue; | ||
} else if (Array.isArray(child)) { | ||
for (const subchild of normalizeChildren(child)) { | ||
result.push(subchild); | ||
} | ||
} else if (child && (child.type === NODE_TYPE.ELEMENT || child.type === NODE_TYPE.TEXT || child.type === NODE_TYPE.COMPONENT)) { | ||
result.push(child); | ||
} else { | ||
throw new TypeError(`Unrecognized node type: ${ typeof child }`); | ||
} | ||
for (const child of children) { | ||
if (!child) { | ||
continue; | ||
} else if (typeof child === "string" || typeof child === "number") { | ||
result.push(new TextNode(child.toString())); | ||
} else if (typeof child === "boolean") { | ||
continue; | ||
} else if (Array.isArray(child)) { | ||
for (const subchild of normalizeChildren(child)) { | ||
result.push(subchild); | ||
} | ||
} else if ( | ||
child && | ||
(child.type === NODE_TYPE.ELEMENT || | ||
child.type === NODE_TYPE.TEXT || | ||
child.type === NODE_TYPE.COMPONENT) | ||
) { | ||
result.push(child); | ||
} else { | ||
throw new TypeError(`Unrecognized node type: ${typeof child}`); | ||
} | ||
} | ||
return result; | ||
return result; | ||
} | ||
function normalizeChild(child) : ElementNode | TextNode | ComponentNode<*> | FragmentNode | void { | ||
const children = normalizeChildren(Array.isArray(child) ? child : [ child ]); | ||
function normalizeChild( | ||
child | ||
): ElementNode | TextNode | ComponentNode<*> | FragmentNode | void { | ||
const children = normalizeChildren(Array.isArray(child) ? child : [child]); | ||
if (children.length === 1) { | ||
return children[0]; | ||
} else if (children.length > 1) { | ||
return new FragmentNode(children); | ||
} | ||
if (children.length === 1) { | ||
return children[0]; | ||
} else if (children.length > 1) { | ||
return new FragmentNode(children); | ||
} | ||
} | ||
export const node : CreateNode = <P>(element, props : P, ...children) => { | ||
children = normalizeChildren(children); | ||
export const node: CreateNode = <P>(element, props: P, ...children) => { | ||
children = normalizeChildren(children); | ||
if (typeof element === 'string') { | ||
// $FlowFixMe | ||
return new ElementNode(element, props, children); | ||
} | ||
if (typeof element === "string") { | ||
// $FlowFixMe | ||
return new ElementNode(element, props, children); | ||
} | ||
if (typeof element === 'function') { | ||
// $FlowFixMe | ||
return new ComponentNode<*>(element, props, children); | ||
} | ||
if (typeof element === "function") { | ||
// $FlowFixMe | ||
return new ComponentNode<*>(element, props, children); | ||
} | ||
throw new TypeError(`Expected jsx element to be a string or a function`); | ||
throw new TypeError(`Expected jsx element to be a string or a function`); | ||
}; | ||
export const Fragment : ComponentFunctionType<null> = (props, children) => { | ||
return children; | ||
export const Fragment: ComponentFunctionType<null> = (props, children) => { | ||
return children; | ||
}; |
/* @flow */ | ||
import { ComponentNode, TextNode, type NodeRenderer, ElementNode } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { uniqueID } from '../util'; | ||
import { | ||
ComponentNode, | ||
TextNode, | ||
type NodeRenderer, | ||
ElementNode, | ||
} from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
import { uniqueID } from "../util"; | ||
type DomNodeRenderer = NodeRenderer<ElementNode, HTMLElement>; | ||
type DomTextRenderer = NodeRenderer<TextNode, Text>; | ||
type DomComponentRenderer = NodeRenderer<ComponentNode<*>, HTMLElement | TextNode | $ReadOnlyArray<HTMLElement | TextNode> | void>; | ||
type DomComponentRenderer = NodeRenderer< | ||
ComponentNode<*>, | ||
HTMLElement | TextNode | $ReadOnlyArray<HTMLElement | TextNode> | void | ||
>; | ||
type DomRenderer = DomComponentRenderer & DomNodeRenderer & DomTextRenderer; | ||
const ELEMENT_TAG = { | ||
HTML: 'html', | ||
IFRAME: 'iframe', | ||
SCRIPT: 'script', | ||
SVG: 'svg', | ||
DEFAULT: 'default' | ||
HTML: "html", | ||
IFRAME: "iframe", | ||
SCRIPT: "script", | ||
SVG: "svg", | ||
DEFAULT: "default", | ||
}; | ||
const ELEMENT_PROP = { | ||
ID: 'id', | ||
INNER_HTML: 'innerHTML', | ||
EL: 'el', | ||
XLINK_HREF: 'xlink:href' | ||
ID: "id", | ||
INNER_HTML: "innerHTML", | ||
EL: "el", | ||
XLINK_HREF: "xlink:href", | ||
}; | ||
const ELEMENT_DEFAULT_XML_NAMESPACE : {| [$Values<typeof ELEMENT_TAG>] : string |} = { | ||
[ ELEMENT_TAG.SVG ]: 'http://www.w3.org/2000/svg' | ||
const ELEMENT_DEFAULT_XML_NAMESPACE: {| | ||
[$Values<typeof ELEMENT_TAG>]: string, | ||
|} = { | ||
[ELEMENT_TAG.SVG]: "http://www.w3.org/2000/svg", | ||
}; | ||
const ATTRIBUTE_DEFAULT_XML_NAMESPACE : {| [$Values<typeof ELEMENT_PROP>] : string |} = { | ||
[ ELEMENT_PROP.XLINK_HREF ]: 'http://www.w3.org/1999/xlink' | ||
const ATTRIBUTE_DEFAULT_XML_NAMESPACE: {| | ||
[$Values<typeof ELEMENT_PROP>]: string, | ||
|} = { | ||
[ELEMENT_PROP.XLINK_HREF]: "http://www.w3.org/1999/xlink", | ||
}; | ||
function fixScripts(el : HTMLElement | Element, doc : Document = window.document) { | ||
for (const script of el.querySelectorAll('script')) { | ||
const parentNode = script.parentNode; | ||
function fixScripts( | ||
el: HTMLElement | Element, | ||
doc: Document = window.document | ||
) { | ||
for (const script of el.querySelectorAll("script")) { | ||
const parentNode = script.parentNode; | ||
if (!parentNode) { | ||
continue; | ||
} | ||
if (!parentNode) { | ||
continue; | ||
} | ||
const newScript = doc.createElement('script'); | ||
newScript.text = script.textContent; | ||
parentNode.replaceChild(newScript, script); | ||
} | ||
const newScript = doc.createElement("script"); | ||
newScript.text = script.textContent; | ||
parentNode.replaceChild(newScript, script); | ||
} | ||
} | ||
function createElement(doc : Document, node : ElementNode) : HTMLElement | Element { | ||
if (node.props[ELEMENT_PROP.EL]) { | ||
return node.props[ELEMENT_PROP.EL]; | ||
} else { | ||
return doc.createElement(node.name); | ||
} | ||
function createElement( | ||
doc: Document, | ||
node: ElementNode | ||
): HTMLElement | Element { | ||
if (node.props[ELEMENT_PROP.EL]) { | ||
return node.props[ELEMENT_PROP.EL]; | ||
} else { | ||
return doc.createElement(node.name); | ||
} | ||
} | ||
function createElementWithXMLNamespace(doc : Document, node : ElementNode, xmlNamespace : string) : HTMLElement | Element { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
function createElementWithXMLNamespace( | ||
doc: Document, | ||
node: ElementNode, | ||
xmlNamespace: string | ||
): HTMLElement | Element { | ||
return doc.createElementNS(xmlNamespace, node.name); | ||
} | ||
function createTextElement(doc : Document, node : TextNode) : Text { | ||
return doc.createTextNode(node.text); | ||
function createTextElement(doc: Document, node: TextNode): Text { | ||
return doc.createTextNode(node.text); | ||
} | ||
function addProps(el : HTMLElement | Element, node) { | ||
const props = node.props; | ||
function addProps(el: HTMLElement | Element, node) { | ||
const props = node.props; | ||
for (const prop of Object.keys(props)) { | ||
const val = props[prop]; | ||
for (const prop of Object.keys(props)) { | ||
const val = props[prop]; | ||
if (val === null || typeof val === 'undefined' || prop === ELEMENT_PROP.EL || prop === ELEMENT_PROP.INNER_HTML) { | ||
continue; | ||
} | ||
if ( | ||
val === null || | ||
typeof val === "undefined" || | ||
prop === ELEMENT_PROP.EL || | ||
prop === ELEMENT_PROP.INNER_HTML | ||
) { | ||
continue; | ||
} | ||
if (prop.match(/^on[A-Z][a-z]/) && typeof val === 'function') { | ||
el.addEventListener(prop.slice(2).toLowerCase(), val); | ||
} else if (typeof val === 'string' || typeof val === 'number') { | ||
const xmlNamespace = ATTRIBUTE_DEFAULT_XML_NAMESPACE[prop]; | ||
if (xmlNamespace) { | ||
el.setAttributeNS(xmlNamespace, prop, val.toString()); | ||
} else { | ||
el.setAttribute(prop, val.toString()); | ||
} | ||
} else if (typeof val === 'boolean') { | ||
if (val === true) { | ||
el.setAttribute(prop, ''); | ||
} | ||
} | ||
if (prop.match(/^on[A-Z][a-z]/) && typeof val === "function") { | ||
el.addEventListener(prop.slice(2).toLowerCase(), val); | ||
} else if (typeof val === "string" || typeof val === "number") { | ||
const xmlNamespace = ATTRIBUTE_DEFAULT_XML_NAMESPACE[prop]; | ||
if (xmlNamespace) { | ||
el.setAttributeNS(xmlNamespace, prop, val.toString()); | ||
} else { | ||
el.setAttribute(prop, val.toString()); | ||
} | ||
} else if (typeof val === "boolean") { | ||
if (val === true) { | ||
el.setAttribute(prop, ""); | ||
} | ||
} | ||
} | ||
if (el.tagName.toLowerCase() === ELEMENT_TAG.IFRAME && !props.id) { | ||
el.setAttribute(ELEMENT_PROP.ID, `jsx-iframe-${ uniqueID() }`); | ||
} | ||
if (el.tagName.toLowerCase() === ELEMENT_TAG.IFRAME && !props.id) { | ||
el.setAttribute(ELEMENT_PROP.ID, `jsx-iframe-${uniqueID()}`); | ||
} | ||
// If the element is an iframe and it has no srcdoc or src, set the srcdoc to an empty string. | ||
// Content specified via srcdoc is treated as being from the same origin as the parent document. | ||
// In some browsers (like Safari 17+), empty iframes without src or srcdoc may be treated as "anonymous," potentially blocking certain content. | ||
if ( | ||
el.tagName.toLowerCase() === ELEMENT_TAG.IFRAME && | ||
!props.srcdoc && | ||
!props.src | ||
) { | ||
el.setAttribute("srcdoc", ""); | ||
} | ||
} | ||
const ADD_CHILDREN : { [string] : (HTMLElement | Element, ElementNode, DomNodeRenderer) => void } = { | ||
const ADD_CHILDREN: { | ||
[string]: (HTMLElement | Element, ElementNode, DomNodeRenderer) => void, | ||
} = { | ||
[ELEMENT_TAG.IFRAME]: (el, node) => { | ||
const firstChild = node.children[0]; | ||
[ ELEMENT_TAG.IFRAME ]: (el, node) => { | ||
const firstChild = node.children[0]; | ||
if ( | ||
node.children.length !== 1 || | ||
!(firstChild && firstChild.type === NODE_TYPE.ELEMENT) || | ||
firstChild.name !== ELEMENT_TAG.HTML | ||
) { | ||
throw new Error( | ||
`Expected only single html element node as child of ${ELEMENT_TAG.IFRAME} element` | ||
); | ||
} | ||
if (node.children.length !== 1 || !(firstChild && firstChild.type === NODE_TYPE.ELEMENT) || firstChild.name !== ELEMENT_TAG.HTML) { | ||
throw new Error(`Expected only single html element node as child of ${ ELEMENT_TAG.IFRAME } element`); | ||
} | ||
el.addEventListener('load', () => { | ||
el.addEventListener("load", () => { | ||
// $FlowFixMe | ||
const win = el.contentWindow; | ||
// $FlowFixMe | ||
const win = el.contentWindow; | ||
if (!win) { | ||
throw new Error(`Expected frame to have contentWindow`); | ||
} | ||
if (!win) { | ||
throw new Error(`Expected frame to have contentWindow`); | ||
} | ||
const doc = win.document; | ||
const docElement = doc.documentElement; | ||
const doc = win.document; | ||
const docElement = doc.documentElement; | ||
while (docElement.children && docElement.children.length) { | ||
docElement.removeChild(docElement.children[0]); | ||
} | ||
while (docElement.children && docElement.children.length) { | ||
docElement.removeChild(docElement.children[0]); | ||
} | ||
// eslint-disable-next-line no-use-before-define | ||
const child : HTMLElement = firstChild.render(dom({ doc })); | ||
while (child.children.length) { | ||
docElement.appendChild(child.children[0]); | ||
} | ||
}); | ||
}, | ||
// eslint-disable-next-line no-use-before-define | ||
const child: HTMLElement = firstChild.render(dom({ doc })); | ||
[ ELEMENT_TAG.SCRIPT ]: (el, node) => { | ||
const firstChild = node.children[0]; | ||
while (child.children.length) { | ||
docElement.appendChild(child.children[0]); | ||
} | ||
}); | ||
}, | ||
if (node.children.length !== 1 || !(firstChild && firstChild.type === NODE_TYPE.TEXT)) { | ||
throw new Error(`Expected only single text node as child of ${ ELEMENT_TAG.SCRIPT } element`); | ||
} | ||
// $FlowFixMe | ||
el.text = firstChild.text; | ||
}, | ||
[ELEMENT_TAG.SCRIPT]: (el, node) => { | ||
const firstChild = node.children[0]; | ||
[ ELEMENT_TAG.DEFAULT ]: (el, node, renderer) => { | ||
for (const child of node.renderChildren(renderer)) { | ||
el.appendChild(child); | ||
} | ||
if ( | ||
node.children.length !== 1 || | ||
!(firstChild && firstChild.type === NODE_TYPE.TEXT) | ||
) { | ||
throw new Error( | ||
`Expected only single text node as child of ${ELEMENT_TAG.SCRIPT} element` | ||
); | ||
} | ||
}; | ||
function addChildren(el : HTMLElement | Element, node : ElementNode, doc : Document, renderer : DomNodeRenderer) { | ||
if (node.props.hasOwnProperty(ELEMENT_PROP.INNER_HTML)) { | ||
// $FlowFixMe | ||
el.text = firstChild.text; | ||
}, | ||
if (node.children.length) { | ||
throw new Error(`Expected no children to be passed when ${ ELEMENT_PROP.INNER_HTML } prop is set`); | ||
} | ||
[ELEMENT_TAG.DEFAULT]: (el, node, renderer) => { | ||
for (const child of node.renderChildren(renderer)) { | ||
el.appendChild(child); | ||
} | ||
}, | ||
}; | ||
const html = node.props[ELEMENT_PROP.INNER_HTML]; | ||
function addChildren( | ||
el: HTMLElement | Element, | ||
node: ElementNode, | ||
doc: Document, | ||
renderer: DomNodeRenderer | ||
) { | ||
if (node.props.hasOwnProperty(ELEMENT_PROP.INNER_HTML)) { | ||
if (node.children.length) { | ||
throw new Error( | ||
`Expected no children to be passed when ${ELEMENT_PROP.INNER_HTML} prop is set` | ||
); | ||
} | ||
if (typeof html !== 'string') { | ||
throw new TypeError(`${ ELEMENT_PROP.INNER_HTML } prop must be string`); | ||
} | ||
const html = node.props[ELEMENT_PROP.INNER_HTML]; | ||
if (node.name === ELEMENT_TAG.SCRIPT) { | ||
// $FlowFixMe | ||
el.text = html; | ||
} else { | ||
el.innerHTML = html; | ||
fixScripts(el, doc); | ||
} | ||
if (typeof html !== "string") { | ||
throw new TypeError(`${ELEMENT_PROP.INNER_HTML} prop must be string`); | ||
} | ||
if (node.name === ELEMENT_TAG.SCRIPT) { | ||
// $FlowFixMe | ||
el.text = html; | ||
} else { | ||
const addChildrenToElement = ADD_CHILDREN[node.name] || ADD_CHILDREN[ELEMENT_TAG.DEFAULT]; | ||
addChildrenToElement(el, node, renderer); | ||
el.innerHTML = html; | ||
fixScripts(el, doc); | ||
} | ||
} else { | ||
const addChildrenToElement = | ||
ADD_CHILDREN[node.name] || ADD_CHILDREN[ELEMENT_TAG.DEFAULT]; | ||
addChildrenToElement(el, node, renderer); | ||
} | ||
} | ||
type DomOptions = {| | ||
doc? : Document | ||
doc?: Document, | ||
|}; | ||
const getDefaultDomOptions = () : DomOptions => { | ||
// $FlowFixMe | ||
return {}; | ||
const getDefaultDomOptions = (): DomOptions => { | ||
// $FlowFixMe | ||
return {}; | ||
}; | ||
export function dom(opts? : DomOptions = getDefaultDomOptions()) : DomRenderer { | ||
const { doc = document } = opts; | ||
const xmlNamespaceDomRenderer = (node : ElementNode, xmlNamespace : string) : HTMLElement => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent(childNode => xmlNamespaceDomRenderer(childNode, xmlNamespace)); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const el = createElementWithXMLNamespace(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, childNode => xmlNamespaceDomRenderer(childNode, xmlNamespace)); | ||
// $FlowFixMe | ||
return el; | ||
} | ||
export function dom(opts?: DomOptions = getDefaultDomOptions()): DomRenderer { | ||
const { doc = document } = opts; | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
const domRenderer : DomRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent(domRenderer); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const xmlNamespace = ELEMENT_DEFAULT_XML_NAMESPACE[node.name.toLowerCase()]; | ||
const xmlNamespaceDomRenderer = ( | ||
node: ElementNode, | ||
xmlNamespace: string | ||
): HTMLElement => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent((childNode) => | ||
xmlNamespaceDomRenderer(childNode, xmlNamespace) | ||
); | ||
} | ||
if (xmlNamespace) { | ||
// $FlowFixMe | ||
return xmlNamespaceDomRenderer(node, xmlNamespace); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
const el = createElement(doc, node); | ||
addProps(el, node); | ||
addChildren(el, node, doc, domRenderer); | ||
// $FlowFixMe | ||
return el; | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const el = createElementWithXMLNamespace(doc, node, xmlNamespace); | ||
addProps(el, node); | ||
addChildren(el, node, doc, (childNode) => | ||
xmlNamespaceDomRenderer(childNode, xmlNamespace) | ||
); | ||
// $FlowFixMe | ||
return el; | ||
} | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
return domRenderer; | ||
const domRenderer: DomRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return node.renderComponent(domRenderer); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
// $FlowFixMe | ||
return createTextElement(doc, node); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const xmlNamespace = | ||
ELEMENT_DEFAULT_XML_NAMESPACE[node.name.toLowerCase()]; | ||
if (xmlNamespace) { | ||
// $FlowFixMe | ||
return xmlNamespaceDomRenderer(node, xmlNamespace); | ||
} | ||
const el = createElement(doc, node); | ||
addProps(el, node); | ||
addChildren(el, node, doc, domRenderer); | ||
// $FlowFixMe | ||
return el; | ||
} | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
return domRenderer; | ||
} |
/* @flow */ | ||
/* eslint unicorn/prefer-spread: off */ | ||
import { ComponentNode, TextNode, ElementNode, type NodePropsType, type NodeRenderer } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { | ||
ComponentNode, | ||
TextNode, | ||
ElementNode, | ||
type NodePropsType, | ||
type NodeRenderer, | ||
} from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
type HTMLRenderer = NodeRenderer<ElementNode | TextNode | ComponentNode<*>, string>; | ||
type HTMLRenderer = NodeRenderer< | ||
ElementNode | TextNode | ComponentNode<*>, | ||
string | ||
>; | ||
const ELEMENT_PROP = { | ||
INNER_HTML: 'innerHTML' | ||
INNER_HTML: "innerHTML", | ||
}; | ||
const SELF_CLOSING_TAGS = { | ||
br: true | ||
br: true, | ||
}; | ||
function htmlEncode(text : string) : string { | ||
return text | ||
.replace(/&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, ''') | ||
.replace(/\//g, '/'); | ||
function htmlEncode(text: string): string { | ||
return text | ||
.replace(/&/g, "&") | ||
.replace(/</g, "<") | ||
.replace(/>/g, ">") | ||
.replace(/"/g, """) | ||
.replace(/'/g, "'") | ||
.replace(/\//g, "/"); | ||
} | ||
function propsToHTML(props : NodePropsType) : string { | ||
const keys = Object.keys(props).filter(key => { | ||
const val = props[key]; | ||
function propsToHTML(props: NodePropsType): string { | ||
const keys = Object.keys(props).filter((key) => { | ||
const val = props[key]; | ||
if (key === ELEMENT_PROP.INNER_HTML) { | ||
return false; | ||
} | ||
if (key === ELEMENT_PROP.INNER_HTML) { | ||
return false; | ||
} | ||
if (typeof val === 'string' || typeof val === 'number' || val === true) { | ||
return true; | ||
} | ||
if (typeof val === "string" || typeof val === "number" || val === true) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return false; | ||
}); | ||
if (!keys.length) { | ||
return ''; | ||
} | ||
if (!keys.length) { | ||
return ""; | ||
} | ||
const pairs = keys.map(key => { | ||
const val = props[key]; | ||
const pairs = keys.map((key) => { | ||
const val = props[key]; | ||
if (val === true) { | ||
return `${ htmlEncode(key) }`; | ||
} | ||
if (val === true) { | ||
return `${htmlEncode(key)}`; | ||
} | ||
if (typeof val !== 'string' && typeof val !== 'number') { | ||
throw new TypeError(`Unexpected prop type: ${ typeof val }`); | ||
} | ||
if (typeof val !== "string" && typeof val !== "number") { | ||
throw new TypeError(`Unexpected prop type: ${typeof val}`); | ||
} | ||
if (val === '') { | ||
return htmlEncode(key); | ||
} | ||
if (val === "") { | ||
return htmlEncode(key); | ||
} | ||
return `${ htmlEncode(key) }="${ htmlEncode(val.toString()) }"`; | ||
}); | ||
return `${htmlEncode(key)}="${htmlEncode(val.toString())}"`; | ||
}); | ||
return ` ${ pairs.join(' ') }`; | ||
return ` ${pairs.join(" ")}`; | ||
} | ||
export function html() : HTMLRenderer { | ||
export function html(): HTMLRenderer { | ||
const htmlRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(htmlRenderer)).join(""); | ||
} | ||
const htmlRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(htmlRenderer)).join(''); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const renderedProps = propsToHTML(node.props); | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
const renderedProps = propsToHTML(node.props); | ||
if (SELF_CLOSING_TAGS[node.name]) { | ||
return `<${node.name}${renderedProps} />`; | ||
} else { | ||
const renderedChildren = | ||
typeof node.props[ELEMENT_PROP.INNER_HTML] === "string" | ||
? node.props[ELEMENT_PROP.INNER_HTML] | ||
: node.renderChildren(htmlRenderer).join(""); | ||
if (SELF_CLOSING_TAGS[node.name]) { | ||
return `<${ node.name }${ renderedProps } />`; | ||
} else { | ||
const renderedChildren = (typeof node.props[ELEMENT_PROP.INNER_HTML] === 'string') | ||
? node.props[ELEMENT_PROP.INNER_HTML] | ||
: node.renderChildren(htmlRenderer).join(''); | ||
return `<${node.name}${renderedProps}>${renderedChildren}</${node.name}>`; | ||
} | ||
} | ||
return `<${ node.name }${ renderedProps }>${ renderedChildren }</${ node.name }>`; | ||
} | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return htmlEncode(node.text); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return htmlEncode(node.text); | ||
} | ||
throw new TypeError(`Unhandleable node: ${node.type}`); | ||
}; | ||
throw new TypeError(`Unhandleable node: ${ node.type }`); | ||
}; | ||
return htmlRenderer; | ||
return htmlRenderer; | ||
} |
/* @flow */ | ||
export * from './text'; | ||
export * from './dom'; | ||
export * from './react'; | ||
export * from './html'; | ||
export * from './preact'; | ||
export * from './regex'; | ||
export * from "./text"; | ||
export * from "./dom"; | ||
export * from "./react"; | ||
export * from "./html"; | ||
export * from "./preact"; | ||
export * from "./regex"; |
/* @flow */ | ||
import { ComponentNode, TextNode, ElementNode, type NodeRenderer, type NodePropsType } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { | ||
ComponentNode, | ||
TextNode, | ||
ElementNode, | ||
type NodeRenderer, | ||
type NodePropsType, | ||
} from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
type PreactType = {| | ||
h : Function | ||
h: Function, | ||
|}; | ||
@@ -12,40 +18,51 @@ | ||
type PreactRenderer = NodeRenderer<ElementNode | TextNode | ComponentNode<*>, PreactNode | string | null>; | ||
type PreactRenderer = NodeRenderer< | ||
ElementNode | TextNode | ComponentNode<*>, | ||
PreactNode | string | null | ||
>; | ||
function mapPreactProps(props : NodePropsType) : NodePropsType { | ||
const { innerHTML, ...remainingProps } = props; | ||
function mapPreactProps(props: NodePropsType): NodePropsType { | ||
const { innerHTML, ...remainingProps } = props; | ||
const dangerouslySetInnerHTML = innerHTML | ||
? { __html: innerHTML } | ||
: null; | ||
const dangerouslySetInnerHTML = innerHTML ? { __html: innerHTML } : null; | ||
// $FlowFixMe | ||
return { | ||
dangerouslySetInnerHTML, | ||
...remainingProps | ||
}; | ||
// $FlowFixMe | ||
return { | ||
dangerouslySetInnerHTML, | ||
...remainingProps, | ||
}; | ||
} | ||
export function preact({ Preact } : {| Preact : PreactType |} = {}) : PreactRenderer { | ||
if (!Preact) { | ||
throw new Error(`Must pass Preact library to react renderer`); | ||
export function preact({ | ||
Preact, | ||
}: {| Preact: PreactType |} = {}): PreactRenderer { | ||
if (!Preact) { | ||
throw new Error(`Must pass Preact library to react renderer`); | ||
} | ||
const reactRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return Preact.h( | ||
() => node.renderComponent(reactRenderer) || null, | ||
node.props, | ||
...node.renderChildren(reactRenderer) | ||
); | ||
} | ||
const reactRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return Preact.h(() => (node.renderComponent(reactRenderer) || null), node.props, ...node.renderChildren(reactRenderer)); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return Preact.h(node.name, mapPreactProps(node.props), ...node.renderChildren(reactRenderer)); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return Preact.h( | ||
node.name, | ||
mapPreactProps(node.props), | ||
...node.renderChildren(reactRenderer) | ||
); | ||
} | ||
return reactRenderer; | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
return reactRenderer; | ||
} |
/* @flow */ | ||
import type { Node } from 'react'; | ||
import type { Node } from "react"; | ||
import { ComponentNode, TextNode, ElementNode, type NodeRenderer, type NodePropsType } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { | ||
ComponentNode, | ||
TextNode, | ||
ElementNode, | ||
type NodeRenderer, | ||
type NodePropsType, | ||
} from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
type ReactType = {| | ||
createElement : Function | ||
createElement: Function, | ||
|}; | ||
type ReactRenderer = NodeRenderer<ElementNode | TextNode | ComponentNode<*>, Node | string | null>; | ||
type ReactRenderer = NodeRenderer< | ||
ElementNode | TextNode | ComponentNode<*>, | ||
Node | string | null | ||
>; | ||
function mapReactProps(props : NodePropsType) : NodePropsType { | ||
const { innerHTML, class: className, ...remainingProps } = props; | ||
function mapReactProps(props: NodePropsType): NodePropsType { | ||
const { innerHTML, class: className, ...remainingProps } = props; | ||
const dangerouslySetInnerHTML = innerHTML | ||
? { __html: innerHTML } | ||
: null; | ||
const dangerouslySetInnerHTML = innerHTML ? { __html: innerHTML } : null; | ||
// $FlowFixMe | ||
return { | ||
dangerouslySetInnerHTML, | ||
className, | ||
...remainingProps | ||
}; | ||
// $FlowFixMe | ||
return { | ||
dangerouslySetInnerHTML, | ||
className, | ||
...remainingProps, | ||
}; | ||
} | ||
export function react({ React } : {| React : ReactType |} = {}) : ReactRenderer { | ||
if (!React) { | ||
throw new Error(`Must pass React library to react renderer`); | ||
export function react({ React }: {| React: ReactType |} = {}): ReactRenderer { | ||
if (!React) { | ||
throw new Error(`Must pass React library to react renderer`); | ||
} | ||
const reactRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return React.createElement( | ||
() => node.renderComponent(reactRenderer) || null, | ||
node.props, | ||
...node.renderChildren(reactRenderer) | ||
); | ||
} | ||
const reactRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return React.createElement(() => (node.renderComponent(reactRenderer) || null), node.props, ...node.renderChildren(reactRenderer)); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return React.createElement( | ||
node.name, | ||
mapReactProps(node.props), | ||
...node.renderChildren(reactRenderer) | ||
); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
return React.createElement(node.name, mapReactProps(node.props), ...node.renderChildren(reactRenderer)); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
throw new TypeError(`Unhandleable node`); | ||
}; | ||
return reactRenderer; | ||
return reactRenderer; | ||
} |
/* @flow */ | ||
import { node, ComponentNode, TextNode, ElementNode, type NodeRenderer } from '../node'; | ||
import { | ||
node, | ||
ComponentNode, | ||
TextNode, | ||
ElementNode, | ||
type NodeRenderer, | ||
} from "../node"; | ||
import { text } from './text'; | ||
import { text } from "./text"; | ||
type RegexRenderer = NodeRenderer<ElementNode | TextNode | ComponentNode<*>, RegExp>; | ||
type RegexRenderer = NodeRenderer< | ||
ElementNode | TextNode | ComponentNode<*>, | ||
RegExp | ||
>; | ||
export function regex() : RegexRenderer { | ||
const regexRenderer = text(); | ||
export function regex(): RegexRenderer { | ||
const regexRenderer = text(); | ||
// eslint-disable-next-line security/detect-non-literal-regexp | ||
return (nodeInstance) => new RegExp(regexRenderer(nodeInstance)); | ||
// eslint-disable-next-line security/detect-non-literal-regexp | ||
return (nodeInstance) => new RegExp(regexRenderer(nodeInstance)); | ||
} | ||
@@ -18,10 +27,10 @@ | ||
regex.node = (el, props, ...children) => { | ||
// $FlowFixMe | ||
const nodeInstance = node(el, props, ...children); | ||
// $FlowFixMe | ||
const nodeInstance = node(el, props, ...children); | ||
if (el.renderer) { | ||
return nodeInstance.render(el.renderer()); | ||
} | ||
if (el.renderer) { | ||
return nodeInstance.render(el.renderer()); | ||
} | ||
return nodeInstance; | ||
return nodeInstance; | ||
}; |
/* @flow */ | ||
/* eslint unicorn/prefer-spread: off */ | ||
import { ComponentNode, TextNode, ElementNode, type NodeRenderer } from '../node'; | ||
import { NODE_TYPE } from '../constants'; | ||
import { | ||
ComponentNode, | ||
TextNode, | ||
ElementNode, | ||
type NodeRenderer, | ||
} from "../node"; | ||
import { NODE_TYPE } from "../constants"; | ||
type TextRenderer = NodeRenderer<ElementNode | TextNode | ComponentNode<*>, string>; | ||
type TextRenderer = NodeRenderer< | ||
ElementNode | TextNode | ComponentNode<*>, | ||
string | ||
>; | ||
export function text() : TextRenderer { | ||
export function text(): TextRenderer { | ||
const textRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(textRenderer)).join(""); | ||
} | ||
const textRenderer = (node) => { | ||
if (node.type === NODE_TYPE.COMPONENT) { | ||
return [].concat(node.renderComponent(textRenderer)).join(''); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
throw new Error(`Text renderer does not support basic elements`); | ||
} | ||
if (node.type === NODE_TYPE.ELEMENT) { | ||
throw new Error(`Text renderer does not support basic elements`); | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
if (node.type === NODE_TYPE.TEXT) { | ||
return node.text; | ||
} | ||
throw new TypeError(`Unhandleable node: ${node.type}`); | ||
}; | ||
throw new TypeError(`Unhandleable node: ${ node.type }`); | ||
}; | ||
return textRenderer; | ||
return textRenderer; | ||
} |
/* @flow */ | ||
const ALPHA_CHARS = '0123456789abcdef'; | ||
const ALPHA_CHARS = "0123456789abcdef"; | ||
export function uniqueID() : string { | ||
return 'xxxxxxxxxx'.replace(/./g, () => ALPHA_CHARS.charAt(Math.floor(Math.random() * ALPHA_CHARS.length))); | ||
export function uniqueID(): string { | ||
return "xxxxxxxxxx".replace(/./g, () => | ||
ALPHA_CHARS.charAt(Math.floor(Math.random() * ALPHA_CHARS.length)) | ||
); | ||
} | ||
// eslint-disable-next-line flowtype/no-weak-types | ||
export function isDefined(val : any) : boolean %checks { | ||
return (val !== null && typeof val !== 'undefined'); | ||
export function isDefined(val: any): boolean %checks { | ||
return val !== null && typeof val !== "undefined"; | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2458
177550
12
279
1