├── .npmrc ├── test ├── index.js ├── package.json ├── js │ ├── bundle.js │ ├── inner.js │ └── reactive-props.js ├── uce-template-head.jpg ├── resolve.js ├── min │ ├── my-counter │ │ ├── my-counter.js │ │ ├── index.html │ │ └── my-counter.uce │ ├── partial.html │ ├── index.html │ ├── complex.html │ └── slots.html ├── my-counter │ ├── my-counter.js │ ├── index.html │ └── my-counter.uce ├── wc.html ├── my-btn.uce ├── spaces.html ├── setup.html ├── refs.html ├── csp │ └── index.html ├── unicorn.html ├── resolve-lazy.html ├── resolve.html ├── this.html ├── nested.html ├── wc.js ├── partial.html ├── loader.html ├── index.html ├── slots.html ├── dbmonster.css ├── complex.html ├── dbmonster.html └── dbmonster.js ├── bin ├── package.json └── index.js ├── cjs ├── package.json ├── partial.js └── index.js ├── _config.yml ├── nonce.txt ├── .gitignore ├── .npmignore ├── rollup ├── babel.config.js └── es.config.js ├── esm ├── partial.js └── index.js ├── LICENSE ├── package.json ├── extra-details.md ├── es.js ├── min.js └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('../cjs'); -------------------------------------------------------------------------------- /bin/package.json: -------------------------------------------------------------------------------- 1 | {"type":"commonjs"} -------------------------------------------------------------------------------- /cjs/package.json: -------------------------------------------------------------------------------- 1 | {"type":"commonjs"} -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | {"type":"commonjs"} -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /nonce.txt: -------------------------------------------------------------------------------- 1 | ijeLM8+5uwZ7ZXFmK+H2dwIWdiKJ1A4zhZIsq2Ffqqo= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .nyc_output 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /test/js/bundle.js: -------------------------------------------------------------------------------- 1 | export default 'Bundle loaded OK'; 2 | -------------------------------------------------------------------------------- /test/js/inner.js: -------------------------------------------------------------------------------- 1 | module.exports = 'Inner loaded OK'; 2 | -------------------------------------------------------------------------------- /test/uce-template-head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebReflection/uce-template/HEAD/test/uce-template-head.jpg -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .npmrc 3 | .nyc_output 4 | .travis.yml 5 | _config.yml 6 | node_modules/ 7 | rollup/ 8 | test/ 9 | -------------------------------------------------------------------------------- /test/resolve.js: -------------------------------------------------------------------------------- 1 | const {resolve} = customElements.get('uce-template'); 2 | 3 | // let's pretend this is a polyfill 4 | resolve('promise-helper', Promise); 5 | -------------------------------------------------------------------------------- /test/min/my-counter/my-counter.js: -------------------------------------------------------------------------------- 1 | Promise.all([ 2 | customElements.whenDefined('uce-template'), 3 | fetch('my-counter.uce').then((b) => b.text()) 4 | ]).then(([Template, parts]) => { 5 | document.body.appendChild(Template.from(parts)); 6 | }); 7 | -------------------------------------------------------------------------------- /test/my-counter/my-counter.js: -------------------------------------------------------------------------------- 1 | Promise.all([ 2 | customElements.whenDefined('uce-template'), 3 | fetch('my-counter.uce').then((b) => b.text()) 4 | ]).then(([Template = customElements.get('uce-template'), parts]) => { 5 | document.body.appendChild(Template.from(parts)); 6 | }); 7 | -------------------------------------------------------------------------------- /test/wc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /rollup/babel.config.js: -------------------------------------------------------------------------------- 1 | import {nodeResolve} from '@rollup/plugin-node-resolve'; 2 | import babel from '@rollup/plugin-babel'; 3 | 4 | export default { 5 | input: './esm/index.js', 6 | plugins: [ 7 | nodeResolve(), 8 | babel({ 9 | presets: ['@babel/preset-env'], 10 | babelHelpers: 'bundled' 11 | }) 12 | ], 13 | 14 | output: { 15 | esModule: false, 16 | exports: 'named', 17 | file: './index.js', 18 | format: 'iife' 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /test/my-btn.uce: -------------------------------------------------------------------------------- 1 | 4 | 5 | 22 | -------------------------------------------------------------------------------- /test/min/my-counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template - My Counter Example 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /test/min/my-counter/my-counter.uce: -------------------------------------------------------------------------------- 1 | 2 | 5 | {{state.count}} 6 | 9 | 10 | 14 | -------------------------------------------------------------------------------- /test/min/partial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | {{state.count}} 7 | 10 | 11 | -------------------------------------------------------------------------------- /esm/partial.js: -------------------------------------------------------------------------------- 1 | export default html => { 2 | const template = []; 3 | const values = []; 4 | const {length} = html; 5 | let s = 0, e = 0, p = 0; 6 | while ( 7 | s < length && 8 | -1 < (s = html.indexOf('{{', p)) && 9 | -1 < (e = html.indexOf('}}', s + 2)) 10 | ) { 11 | template.push(html.slice(p, s)); 12 | values.push(html.slice(s + 2, e)); 13 | p = e + 2; 14 | } 15 | template.push(html.slice(p)); 16 | const args = [template]; 17 | const rest = Function( 18 | 'return function(){with(arguments[0])return[' + values + ']}' 19 | )(); 20 | return function (object) { 21 | return args.concat(rest.call(this, object)); 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /test/js/reactive-props.js: -------------------------------------------------------------------------------- 1 | var stateHandler=function(t){"use strict";var n=Object.defineProperties,e=Object.keys,r=function(t,n,e,r,o){return{configurable:!0,get:function(){return r},set:function(u){(t||u!==r||n&&"object"==typeof u&&u)&&(r=u,e?o.call(this,r):o.call(this))}}},o=function(t,n,o,i,c,a){for(var l={},f=c!==u,s=[o,i,f],v=e(t),d=0;d0&&void 0!==arguments[0]?arguments[0]:{},e=t.all,r=void 0!==e&&e,c=t.shallow,a=void 0===c||c,l=t.useState,f=void 0===l?u:l;return function(t,e){return n({},o(t,i,r,a,f,e))}}}(); -------------------------------------------------------------------------------- /cjs/partial.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = html => { 3 | const template = []; 4 | const values = []; 5 | const {length} = html; 6 | let s = 0, e = 0, p = 0; 7 | while ( 8 | s < length && 9 | -1 < (s = html.indexOf('{{', p)) && 10 | -1 < (e = html.indexOf('}}', s + 2)) 11 | ) { 12 | template.push(html.slice(p, s)); 13 | values.push(html.slice(s + 2, e)); 14 | p = e + 2; 15 | } 16 | template.push(html.slice(p)); 17 | const args = [template]; 18 | const rest = Function( 19 | 'return function(){with(arguments[0])return[' + values + ']}' 20 | )(); 21 | return function (object) { 22 | return args.concat(rest.call(this, object)); 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /test/my-counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template - My Counter Example 7 | 20 | 21 | 22 | 23 | 24 |
25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /test/spaces.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | -------------------------------------------------------------------------------- /test/setup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | script setup 7 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /rollup/es.config.js: -------------------------------------------------------------------------------- 1 | import {nodeResolve} from '@rollup/plugin-node-resolve'; 2 | import {terser} from 'rollup-plugin-terser'; 3 | import includePaths from 'rollup-plugin-includepaths'; 4 | 5 | export default { 6 | input: './esm/index.js', 7 | plugins: [ 8 | includePaths({ 9 | include: { 10 | '@webreflection/lie': 'node_modules/@ungap/degap/promise.js', 11 | '@ungap/create-content': 'node_modules/@ungap/degap/create-content.js', 12 | '@ungap/custom-elements': 'node_modules/@ungap/degap/custom-elements.js' 13 | }, 14 | }), 15 | nodeResolve(), 16 | terser() 17 | ], 18 | 19 | output: { 20 | esModule: false, 21 | exports: 'named', 22 | file: './es.js', 23 | format: 'iife' 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /test/refs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template slots 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/csp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | uce-template + CSP 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 27 | 28 | -------------------------------------------------------------------------------- /test/unicorn.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template is a unicorn 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 28 | 29 | -------------------------------------------------------------------------------- /test/resolve-lazy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 26 | 27 | -------------------------------------------------------------------------------- /test/resolve.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2020, Andrea Giammarchi, @WebReflection 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /test/this.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template is a unicorn 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 30 | 31 | -------------------------------------------------------------------------------- /test/my-counter/my-counter.uce: -------------------------------------------------------------------------------- 1 | 2 | 5 | {{state.count}} 6 | 9 | 10 | 11 | 22 | 23 | -------------------------------------------------------------------------------- /test/nested.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template nested elements 7 | 8 | 9 | 10 | 26 |
27 |

Outer

28 |
29 |
30 |

Inner

31 |
32 | Content 33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /test/min/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WIP: uce-template 7 | 8 | 9 | 10 | 11 | 27 |
28 | 29 |
30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /test/wc.js: -------------------------------------------------------------------------------- 1 | const template = ` 2 | 3 | 6 | {{state.count}} 7 | 10 | 11 | 12 | 27 | 28 | `; 48 | 49 | customElements 50 | .whenDefined("uce-template") 51 | .then(Template => 52 | document.body.insertAdjacentElement("beforeend", Template.from(template)) 53 | ); -------------------------------------------------------------------------------- /test/partial.html: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 25 | {{state.count}} 26 | 29 | 30 | 31 | 62 | -------------------------------------------------------------------------------- /test/min/complex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WIP: uce-template 7 | 8 | 9 | 10 | 33 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /test/loader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /test/min/slots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template slots 7 | 8 | 9 | 10 |

11 | Original example @MDN 12 |

13 |
14 | 15 | slot 16 | A placeholder inside a web component that users can fill with their own markup, with the effect of composing different DOM trees together. 17 |
18 |
name
19 |
The name of the slot.
20 |
21 |
22 | 23 | template 24 | A mechanism for holding client- side content that is not to be rendered when a page is loaded but may subsequently be instantiated during runtime using JavaScript. 25 | 26 | 46 | 47 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WIP: uce-template 7 | 8 | 14 | 15 | 16 | 81 | 82 |
83 | 84 |
85 | 86 |
87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /test/slots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uce-template slots 7 | 8 | 9 | 10 |

11 | Original example @MDN 12 |

13 |
14 | 15 | slot 16 | A placeholder inside a web 17 | component that users can fill with their own markup, 18 | with the effect of composing different DOM trees 19 | together. 20 |
21 |
name
22 |
The name of the slot.
23 |
24 |
25 | 26 | 27 | template 28 | A mechanism for holding client- 29 | side content that is not to be rendered when a page is 30 | loaded but may subsequently be instantiated during 31 | runtime using JavaScript. 32 | 33 | 34 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /test/dbmonster.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | font-size: 14px; 5 | line-height: 1.42857143; 6 | margin: 0; 7 | } 8 | 9 | label { 10 | display: inline-block; 11 | font-weight: 700; 12 | margin-bottom: 5px; 13 | } 14 | 15 | #range { 16 | display: flex; 17 | } 18 | 19 | input[type=range] { 20 | display: block; 21 | width: 100%; 22 | margin-bottom: 10px; 23 | margin-top: 5px; 24 | } 25 | 26 | table { 27 | border-collapse: collapse; 28 | border-spacing: 0; 29 | } 30 | 31 | :before, 32 | :after { 33 | box-sizing: border-box; 34 | } 35 | 36 | .table > thead > tr > th, 37 | .table > tbody > tr > th, 38 | .table > tfoot > tr > th, 39 | .table > thead > tr > td, 40 | .table > tbody > tr > td, 41 | .table > tfoot > tr > td { 42 | border-top: 1px solid #ddd; 43 | line-height: 1.42857143; 44 | padding: 8px; 45 | vertical-align: top; 46 | } 47 | 48 | .table { 49 | width: 100%; 50 | } 51 | 52 | .table-striped > tbody > tr:nth-child(odd) > td, 53 | .table-striped > tbody > tr:nth-child(odd) > th { 54 | background: #f9f9f9; 55 | } 56 | 57 | .label { 58 | border-radius: .25em; 59 | color: #fff; 60 | display: inline; 61 | font-size: 75%; 62 | font-weight: 700; 63 | line-height: 1; 64 | padding: .2em .6em .3em; 65 | text-align: center; 66 | vertical-align: baseline; 67 | white-space: nowrap; 68 | } 69 | 70 | .label-success { 71 | background-color: #5cb85c; 72 | } 73 | 74 | .label-warning { 75 | background-color: #f0ad4e; 76 | } 77 | 78 | .popover { 79 | background-color: #fff; 80 | background-clip: padding-box; 81 | border: 1px solid #ccc; 82 | border: 1px solid rgba(0, 0, 0, .2); 83 | border-radius: 6px; 84 | box-shadow: 0 5px 10px rgba(0, 0, 0, .2); 85 | display: none; 86 | left: 0; 87 | max-width: 276px; 88 | padding: 1px; 89 | position: absolute; 90 | text-align: left; 91 | top: 0; 92 | white-space: normal; 93 | z-index: 1010; 94 | } 95 | 96 | .popover>.arrow:after { 97 | border-width: 10px; 98 | content: ""; 99 | } 100 | 101 | .popover.left { 102 | margin-left: -10px; 103 | } 104 | 105 | .popover.left > .arrow { 106 | border-right-width: 0; 107 | border-left-color: rgba(0, 0, 0, .25); 108 | margin-top: -11px; 109 | right: -11px; 110 | top: 50%; 111 | } 112 | 113 | .popover.left > .arrow:after { 114 | border-left-color: #fff; 115 | border-right-width: 0; 116 | bottom: -10px; 117 | content: " "; 118 | right: 1px; 119 | } 120 | 121 | .popover > .arrow { 122 | border-width: 11px; 123 | } 124 | 125 | .popover > .arrow, 126 | .popover>.arrow:after { 127 | border-color: transparent; 128 | border-style: solid; 129 | display: block; 130 | height: 0; 131 | position: absolute; 132 | width: 0; 133 | } 134 | 135 | .popover-content { 136 | padding: 9px 14px; 137 | } 138 | 139 | .Query { 140 | position: relative; 141 | } 142 | 143 | .Query:hover .popover { 144 | display: block; 145 | left: -100%; 146 | width: 100%; 147 | } -------------------------------------------------------------------------------- /test/complex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WIP: uce-template 8 | 9 | 10 | 11 | 12 | 13 | 18 | 108 | 109 | 110 | 111 |
112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uce-template", 3 | "version": "0.7.1", 4 | "description": "A tiny toolless library with tools included", 5 | "bin": { 6 | "uce-template": "bin/index.js" 7 | }, 8 | "main": "./cjs/index.js", 9 | "scripts": { 10 | "uce": "node -e 'require(`fs`).writeFileSync(`esm/uce.js`,require(`fs`).readFileSync(`node_modules/uce/esm/index.js`).toString().replace(/NOPE\\/\\/ \\[props\\][\\S\\s]+?\\/\\/ \\[\\/props\\]/, ``))'", 11 | "build": "npm run graph && npm run cjs && npm run rollup:es && npm run rollup:babel && drop-babel-typeof index.js && npm run min && npm run integrity && npm run size", 12 | "cjs": "ascjs --no-default esm cjs", 13 | "graph": "cp node_modules/reactive-props/state.js test/js/reactive-props.js", 14 | "integrity": "cat min.js | openssl dgst -sha256 -binary | openssl base64 -A > nonce.txt && node -e 'const {readFileSync,writeFileSync}=require(`fs`),nonce=readFileSync(`nonce.txt`);writeFileSync(`README.md`,readFileSync(`README.md`).toString().replace(/(integrity)=\"[^\"]*?\"/g,`$1=\"sha256-${nonce}\"`).replace(/(__nonce__ )`[^`]*?`/g,\"$1`\"+nonce+\"`\"))'", 15 | "rollup:es": "rollup --config rollup/es.config.js && sed -i.bck 's/^var /self./' es.js && rm -rf es.js.bck", 16 | "rollup:babel": "rollup --config rollup/babel.config.js && sed -i.bck 's/^var /self./' index.js && rm -rf index.js.bck", 17 | "min": "terser index.js --comments='/^!/' -c -m -o min.js", 18 | "size": "echo 'JS';echo \" gzip $(cat min.js | gzip | wc -c)\" && echo \" brotli $(cat min.js | brotli | wc -c)\" && echo 'ES';echo \" gzip $(cat es.js | gzip | wc -c)\" && echo \" brotli $(cat es.js | brotli | wc -c)\"" 19 | }, 20 | "keywords": [ 21 | "custom", 22 | "elements", 23 | "template", 24 | "uce" 25 | ], 26 | "author": "Andrea Giammarchi", 27 | "license": "ISC", 28 | "devDependencies": { 29 | "@rollup/plugin-babel": "^5.3.0", 30 | "@rollup/plugin-node-resolve": "^13.0.0", 31 | "@ungap/degap": "^0.2.7", 32 | "ascjs": "^5.0.1", 33 | "drop-babel-typeof": "^1.0.3", 34 | "rollup": "^2.52.7", 35 | "rollup-plugin-includepaths": "^0.2.4", 36 | "rollup-plugin-terser": "^7.0.2" 37 | }, 38 | "module": "./esm/index.js", 39 | "type": "module", 40 | "exports": { 41 | ".": { 42 | "import": "./esm/index.js", 43 | "default": "./cjs/index.js" 44 | }, 45 | "./package.json": "./package.json" 46 | }, 47 | "unpkg": "min.js", 48 | "dependencies": { 49 | "@babel/core": "^7.14.6", 50 | "@babel/preset-env": "^7.14.7", 51 | "@ungap/create-content": "^0.3.1", 52 | "@ungap/custom-elements": "^1.0.0", 53 | "@webreflection/lie": "^0.1.1", 54 | "csso": "^4.2.0", 55 | "html-minifier-terser": "^5.1.1", 56 | "qsa-observer": "^2.0.2", 57 | "reactive-props": "^0.2.2", 58 | "terser": "^5.7.1", 59 | "uce": "^1.16.2", 60 | "uce-helpers": "^0.1.1", 61 | "uce-require": "^0.1.9", 62 | "uhooks": "^0.2.8" 63 | }, 64 | "repository": { 65 | "type": "git", 66 | "url": "git+https://github.com/WebReflection/uce-template.git" 67 | }, 68 | "bugs": { 69 | "url": "https://github.com/WebReflection/uce-template/issues" 70 | }, 71 | "homepage": "https://github.com/WebReflection/uce-template#readme" 72 | } 73 | -------------------------------------------------------------------------------- /test/dbmonster.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | uhtml dbmonster 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 20 | 21 | 61 | 62 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /extra-details.md: -------------------------------------------------------------------------------- 1 | ## How does uce-template work? 2 | 3 | Based on [uce](https://github.com/WebReflection/uce#readme) and the latest [custom-elements polyfill](https://github.com/ungap/custom-elements#readme), this module glues most modern Web development patterns in a standard way that yet feels like magic. 4 | 5 | The *HTML* content of each component is handled by [tag-params](https://github.com/WebReflection/tag-params#readme) *partial* utility, while the *JS* content is normalized as lightweight *CommonJS* environment, where anyone can feed the module system as they need. 6 | 7 | As strawberry on top, *hooks* are provided behind the scene via the `@uce/reactive` utility and thanks to [augmentor](https://github.com/WebReflection/augmentor#readme). 8 | 9 | The *JS* environment is likely the most complex part to grasp though, so here some extra detail on how it works. 10 | 11 | 12 | ### The module JS environment 13 | 14 | The component script definition happens in a virtual `Function` sandbox, where all *imports* and *exports* are normalized as *CommonJS*, and a `require(module)` utility is provided. 15 | 16 | Like it is for *CommonJS*, the `require` utility always returns the same module, once such module has been provided. 17 | 18 | In the previous example, the `@uce/reactive` is virtually predefined in *uce-template*, but there are other modules too: 19 | 20 | * [augmentor](https://github.com/WebReflection/augmentor#readme) to create any *hooked* wizardry we like 21 | * [qsa-observer](https://github.com/WebReflection/qsa-observer#readme) to monitor nodes if needed 22 | * [reactive-props](https://github.com/WebReflection/reactive-props#readme) to create any reactive alchemy, even if this is provided already via `@uce/reactive` 23 | * [uce](https://github.com/WebReflection/uce#readme) to eventually import `html`, `svg`, or `render` utilities from [uhtml](https://github.com/WebReflection/uce#readme) 24 | * [@webreflection/lie](https://github.com/WebReflection/lie#readme) to have basic *Promise* support in IE11 (resolves only) 25 | 26 | While `import {html} from 'uce'`, and *uce* in general, is very helpful to compose inner nodes of a defined component, every other module is there only because this library uses these modules to work, and it wouldn't make sense to not provide what's already included in *uce-template*. 27 | 28 | However, it is possible to **define any module** using the `resolve(name, module)` utility: 29 | 30 | ```js 31 | import {resolve} from 'uce-template'; 32 | 33 | import MyLibrary from 'MyLibrary'; 34 | resolve('my-library', MyLibrary); 35 | ``` 36 | 37 | Alternatively, it is also possible to define modules via the `uce-template` class itself: 38 | 39 | ```js 40 | customElements.whenDefined('uce-template').then({resolve} => { 41 | resolve('my-utility', {any(){}, module: 'really'}); 42 | }); 43 | ``` 44 | 45 | Please note that modules are unique so it is encouraged to use real module names to avoid clashing within third parts libraries. 46 | 47 | 48 | ### The lazy JS environment 49 | 50 | Modules can also be **loaded at runtime**, but only if *relative* or if the *CDN* supports Cross Origin Requests. 51 | 52 | ```js 53 | // provided by uce-template 54 | import reactive from '@uce/reactive'; 55 | 56 | import doubleRainbow from './js/rainbow.js'; 57 | 58 | export default { 59 | setup(element) { 60 | const state = reactive({ count: 0 }); 61 | const inc = () => { state.count++ }; 62 | const dec = () => { state.count-- }; 63 | console.log(doubleRainbow); // 🌈🌈 64 | return {state, inc, dec}; 65 | } 66 | }; 67 | ``` 68 | 69 | The `js/rainbow.js` in example should be reachable, and contain some export either via *ESM* syntax, or *CJS*, so that `export default '🌈🌈'` or `module.exports = '🌈🌈'` would be both valid and accepted. 70 | 71 | It is *our duty* to be sure that lazily loaded modules can run within our target browsers, so in case *IE11* is one of these targets, it's our duty to transpile those file in a compatible way via *Babel* or others, as the `require` utility only cares about *imports* and *exports*. 72 | 73 | The **advantage** of having *lazy* modules resolution is that a component defined via `