Skip to content

Commit 7fe669a

Browse files
authored
Merge branch 'master' into clean
2 parents 074c331 + 61208f3 commit 7fe669a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+17986
-4498
lines changed

broken-frameworks/non-keyed/vue-jsx-vapor/package-lock.json

Lines changed: 0 additions & 1551 deletions
This file was deleted.

cli/zip.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ function addFrameworksToZip(frameworkType, frameworkDir, frameworkName) {
5555
}
5656

5757
switch (frameworkName) {
58+
case "deku":
5859
case "halogen": {
59-
addLocalFileIfExists(`${frameworkDir}/output/bundle.js`, `${zipFrameworkPath}/output`);
60+
addLocalFileIfExists(`${frameworkDir}/output-es/bundle.js`, `${zipFrameworkPath}/output-es`);
6061
break;
6162
}
6263
case "dojo": {

frameworks/keyed/angular-cf-nozone/src/app/app.component.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { NgFor } from '@angular/common';
2-
import { ChangeDetectorRef, Component, VERSION, inject } from '@angular/core';
1+
import { ApplicationRef, Component, VERSION, inject } from '@angular/core';
32

43
interface Data {
54
id: number;
@@ -12,11 +11,10 @@ const nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie"
1211

1312
@Component({
1413
selector: 'app-root',
15-
imports: [NgFor],
1614
templateUrl: './app.component.html'
1715
})
1816
export class AppComponent {
19-
private cdr = inject(ChangeDetectorRef);
17+
private applicationRef = inject(ApplicationRef);
2018

2119
data: Array<Data> = [];
2220
selected?: number = undefined;
@@ -44,7 +42,7 @@ export class AppComponent {
4442
select(item: Data, event: Event) {
4543
event.preventDefault();
4644
this.selected = item.id;
47-
this.cdr.detectChanges();
45+
this.applicationRef.tick();
4846
}
4947

5048
delete(item: Data, event: Event) {
@@ -55,41 +53,41 @@ export class AppComponent {
5553
break;
5654
}
5755
}
58-
this.cdr.detectChanges();
56+
this.applicationRef.tick();
5957
}
6058

6159
run() {
6260
this.data = this.buildData();
63-
this.cdr.detectChanges();
61+
this.applicationRef.tick();
6462
}
6563

6664
add() {
6765
this.data = this.data.concat(this.buildData(1000));
68-
this.cdr.detectChanges();
66+
this.applicationRef.tick();
6967
}
7068

7169
update() {
7270
for (let i = 0; i < this.data.length; i += 10) {
7371
this.data[i].label += ' !!!';
7472
}
75-
this.cdr.detectChanges();
73+
this.applicationRef.tick();
7674
}
7775
runLots() {
7876
this.data = this.buildData(10000);
7977
this.selected = undefined;
80-
this.cdr.detectChanges();
78+
this.applicationRef.tick();
8179
}
8280
clear() {
8381
this.data = [];
8482
this.selected = undefined;
85-
this.cdr.detectChanges();
83+
this.applicationRef.tick();
8684
}
8785
swapRows() {
8886
if (this.data.length > 998) {
8987
var a = this.data[1];
9088
this.data[1] = this.data[998];
9189
this.data[998] = a;
9290
}
93-
this.cdr.detectChanges();
91+
this.applicationRef.tick();
9492
}
9593
}

frameworks/keyed/angular-cf-signals-nozone/src/app/app.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { NgFor } from "@angular/common";
21
import { ChangeDetectionStrategy, Component, signal } from "@angular/core";
32

43
const adjectives = [
@@ -65,7 +64,6 @@ interface Data {
6564
@Component({
6665
selector: "app-root",
6766
changeDetection: ChangeDetectionStrategy.OnPush,
68-
imports: [NgFor],
6967
templateUrl: "./app.component.html"
7068
})
7169
export class AppComponent {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>DooHTML - Lite</title>
7+
<link rel="shortcut icon" type="image/png" href="./favicon.png" />
8+
<link href="/css/currentStyle.css" rel="preload" as="style"/>
9+
<link href="/css/currentStyle.css" rel="stylesheet"/>
10+
<script type="module" src="./src/main.js" defer ></script>
11+
<template id="table">
12+
<table class="table table-hover table-striped test-data">
13+
<tbody id="tbody"><tr data-bind="rows"><td class="col-md-1">{{id}}</td><td class="col-md-4"><a>{{label}}</a></td><td class="col-md-1"><a class="remove"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a></td><td class="col-md-6"></td></tr></tbody>
14+
</table>
15+
</template>
16+
</head>
17+
<body>
18+
<div id="main">
19+
<div class="container">
20+
<div class="jumbotron">
21+
<div class="row">
22+
<div class="col-md-6">
23+
<h1>DooHTML - Lite</h1><span class="ver"></span>
24+
</div>
25+
<div class="col-md-6">
26+
<div class="row">
27+
<div class="col-sm-6 smallpad">
28+
<button type="button" class="btn btn-primary btn-block" id="run">Create 1,000 rows</button>
29+
</div>
30+
<div class="col-sm-6 smallpad">
31+
<button type="button" class="btn btn-primary btn-block" id="runlots">Create 10,000 rows</button>
32+
</div>
33+
<div class="col-sm-6 smallpad">
34+
<button type="button" class="btn btn-primary btn-block" id="add">Append 1,000 rows</button>
35+
</div>
36+
<div class="col-sm-6 smallpad">
37+
<button type="button" class="btn btn-primary btn-block" id="update">Update every 10th row</button>
38+
</div>
39+
<div class="col-sm-6 smallpad">
40+
<button type="button" class="btn btn-primary btn-block" id="clear">Clear</button>
41+
</div>
42+
<div class="col-sm-6 smallpad">
43+
<button type="button" class="btn btn-primary btn-block" id="swaprows">Swap Rows</button>
44+
</div>
45+
</div>
46+
</div>
47+
</div>
48+
</div>
49+
<div
50+
data-template="table"
51+
data-has-html="false"
52+
data-key="key"
53+
>
54+
</div>
55+
56+
</div>
57+
<span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span>
58+
</div>
59+
</body>
60+
</html>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const Config={t:"DooHTML",o:"data-bind",l:"data-template",p:{i:-1,T:0,m:1},u:{BEG:"{{",END:"}}"},N:"data-key",A:"key"},version="v0.97.5",getItemValue=(e,t)=>t.includes(".")?t.split(".").reduce(((e,t)=>e&&void 0!==e[t]?e[t]:""),e):e[t]?e[t]:"",isTable=e=>["TABLE","TBODY","THEAD","TFOOT","TR","TH"].includes(e.tagName),render=(e,t,o=0)=>{0!==t.length?renderHTML(e,t,o):e.textContent=""},renderHTML=(e,t,o=0,a=null)=>{let l,n,d=t.length,s=e.place[0],c=a?o+d:d-o;c>d&&(c=d);let r=s.C.length;const p=(e,o)=>{for(let a=0;a<r;a++)n=getNode(e,s.C[a][1],0),n?"textContent"===s.C[a][2]?n.textContent=t[o][s.C[a][0]]:n.setAttribute(s.C[a][2],t[o][s.C[a][0]]):console.info("Field:"+s.C[a][0]+" does not exist")},i=s.h;for(let e=o;e<c;e++)l=s.D,p(l,e),s.appendChild(l.cloneNode(!0))[Config.A]=getItemValue(t[e],i)},getNode=(e,t,o)=>{let a=t[o];return e.childNodes[a]?getNode(e.childNodes[a],t,++o):e},append=(e,t,o=0)=>{renderHTML(e,t,o,t.length-o)},dooParse=e=>{let t=e.cloneNode(!0);t.removeAttribute(Config.o),t.removeAttribute("data-key");let o=t.outerHTML.replace(/\t/g,"").replace(/\n/g,""),a=o;["src","selected","checked","disabled","readonly"].forEach((e=>{o=o.replace(new RegExp(" "+e+'="{{(.+)}}"',"g")," doo-"+e+'="{{$1}}"')}));let l=a===o,n=document.createElement("template");n.innerHTML=o;let d=[];const s=(e,t,o)=>{let a=[],l=e;for(;l!==n.firstElementChild;){let e=l.previousSibling,t=0;for(;e;)t++,e=e.previousSibling;l=l.parentNode,l&&a.unshift(t)}d.push([t,a.slice(1),o])},c=document.createTreeWalker(n.content,NodeFilter.SHOW_TEXT,{acceptNode:()=>NodeFilter.FILTER_ACCEPT});let r=c.nextNode(),p=[];for(;r;){let e=r.wholeText.trim();if(0===e.indexOf("{{")&&e.lastIndexOf("}}")===e.length-2);else{let t=e.replace(/{{/g,"<span>{{").replace(/}}/g,"}}</span>");p.push({node:r.parentNode,L:e,v:t})}r=c.nextNode()}for(let e=0,t=p.length;e<t;e++)p[e].node.innerHTML=p[e].node.innerHTML.replace(p[e].L,p[e].v);let i=n.content.cloneNode(!0);const T=document.createTreeWalker(i,NodeFilter.SHOW_TEXT,{acceptNode:()=>NodeFilter.FILTER_ACCEPT});let m=T.nextNode();for(;m;){const e=m.nodeValue.match(/\{\{(.*?)\}\}/g);if(e){const t=m.parentNode;e.forEach((e=>{const o=e.replace(/\{\{|\}\}/g,"").trim(),a=document.createTextNode(o);m.textContent="";const l=t.appendChild(a);s(l,o,"textContent")}))}m=T.nextNode()}const f=document.createTreeWalker(i,NodeFilter.SHOW_ELEMENT,{acceptNode:()=>NodeFilter.FILTER_ACCEPT});for(m=f.nextNode();m;){for(const e of[...m.attributes])e.nodeValue.includes("{{")&&s(m,e.nodeValue.replace("{{","").replace("}}",""),e.name);m=f.nextNode()}let g=i.firstElementChild.outerHTML;return d.forEach((e=>{let t="{{"+e[0]+"}}";g=g.replace(new RegExp(t,"g"),"")})),i.outerHTML=g,{D:i.firstElementChild,H:l,C:d}},fetchTemplate=e=>new Promise(((t,o)=>{const a=new XMLHttpRequest;a.open("GET",e),a.onload=()=>t(a.responseText),a.onerror=()=>o(a.statusText),a.send()})),setReactiveDataNodes=e=>{const t=[],o=e=>{let t=0;for(;e.parentElement;)e=e.parentElement,t++;return t};e.innerHTML=e.innerHTML.replace(/\$\{(.+?)\}/gm,((t,o)=>isNaN(o)?e.getAttribute(o)||"":Config.u.BEG+e.R?.[o-1]+Config.u.END||""));const a=e.content.querySelectorAll(`[${Config.o}]`);a.forEach((t=>{t.hasAttribute("data-src")||t.setAttribute("data-src",e.hasAttribute("doo-dispatch")?"DooX":Config.o),t.removeAttribute("data-src")})),(e=>{[...e].map((e=>({I:e,level:o(e),F:e.getAttribute("data-src")?.startsWith("this.parent"),M:e.hasAttribute("data-norepeat")}))).sort(((e,t)=>t.level-e.level)).forEach((({I:e,level:o,F:a,M:l},n)=>{const d="|STYLE|LINK|".includes(`|${e.tagName}|`)?e:(e.parentElement&&"|DL|UL|TBODY|THEAD|TFOOT|TR|SELECT|SECTION|".includes(`|${e.parentElement.tagName}|`),e.parentElement),s=dooParse(e);Object.assign(d,{h:e.getAttribute(Config.o),D:s.D,H:s.H,C:s.C,name:n,level:o,F:a,M:l,O:isTable(d)}),"DATA"!==d.tagName&&"STYLE"!==d.tagName&&"LINK"!==d.tagName||e.parentElement?.replaceChild(d,e)||console.warn("Templates should only have one child node"),t.push(d)}))})(a),e.place=t},setNodeValues=(e,t)=>{for(let o=0;o<len;o++){const a=getNode(e,place.C[o][1],0);a?"textContent"===place.C[o][2]?a.textContent=data[t][place.C[o][0]]:a.setAttribute(place.C[o][2],data[t][place.C[o][0]]):console.info("Field:"+place.C[o][0]+" does not exist")}if(this.S){let e=place.querySelectorAll(place.D.tagName);for(let t=start;t<stop;t++){let o=e.item(t);const a=o||place.D;setNodeValues(a,t),o||(place.appendChild(a.cloneNode(!0))[Config.A]=getItemValue(data[t],this.h))}}else for(let e=start;e<stop;e++){const t=place.D;setNodeValues(t,e),place.appendChild(t.cloneNode(!0))[Config.A]=getItemValue(data[e],this.h)}},prefetchTemplate=async e=>{if(e&&(e.startsWith("./")||e.startsWith("../")||e.startsWith("http"))){return await fetchTemplate(e)}return null},createTemplate=async(e,t=[],o=null)=>{let a=o?await prefetchTemplate(o):"";a||(a=e.startsWith("<")?e:e.startsWith("#")?document.querySelector(e).outerHTML:document.querySelector("#"+e).outerHTML);const l=document.createElement("div");l.innerHTML=a,l.querySelector("template")&&(l.innerHTML=l.querySelector("template")?a:`<template><center><pre>The template you are trying to import does not have a &lt;template&gt; tag</pre><div style="color:red">${a}</div></center></template>`);const n=l.querySelector("template").cloneNode(!0),d=document.createElement("template");n.removeAttribute("id"),d.innerHTML=n.innerHTML,setReactiveDataNodes(d);const s=`[data-template="${e}"]`;return document.querySelector(s).parentElement.replaceChild(d.content,document.querySelector(s)),render(d.place[0],t,0),d};export{createTemplate,append,render,Config,version,prefetchTemplate};

frameworks/keyed/doohtml-lite/package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "js-framework-benchmark-doohtml",
3+
"version": "0.97.5",
4+
"description": "DooHTML-lite JS-Benchmark",
5+
"main": "main.js",
6+
"js-framework-benchmark": {
7+
"frameworkVersion": "",
8+
"frameworkHomeURL": "https://doohtml.com",
9+
"issues": [772]
10+
},
11+
"scripts": {
12+
"dev": "exit 0",
13+
"build-prod": "exit 0"
14+
},
15+
"keywords": [],
16+
"author": "Henrik Javen",
17+
"license": "Apache-2.0",
18+
"homepage": "https://doohtml.com",
19+
"repository": {
20+
"type": "git",
21+
"url": "https://github.com/hman61/js-framework-benchmark"
22+
}
23+
}
24+
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
'use strict'
2+
3+
import {render, createTemplate, append, version} from '../lib/doohtml.mjs';
4+
const _random = max => Math.random() * max | 0
5+
6+
const adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]
7+
const colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]
8+
const nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]
9+
10+
const lenA = adjectives.length, lenB = colours.length, lenC = nouns.length
11+
12+
const DEFAULT_SIZE = 1000
13+
const DEFAULT_SIZE_RUN_LOTS = 10000
14+
const SWAP_ROW = 998
15+
const BANG = ' !!!'
16+
const DANGER = 'danger'
17+
class Main {
18+
constructor() {
19+
this.rows = []
20+
this.ID = 1
21+
this.add = this.add.bind(this)
22+
this.run = this.run.bind(this)
23+
this.runLots = this.runLots.bind(this)
24+
this.update = this.update.bind(this)
25+
this.clear = this.clear.bind(this)
26+
this.swapRows = this.swapRows.bind(this)
27+
this.addEventListeners()
28+
this.selectedRow = undefined
29+
document.querySelector(".ver").innerHTML += `${version} (keyed)`
30+
document.title += ` (keyed)`
31+
}
32+
33+
async init() {
34+
this.tbody = await createTemplate('table', [])
35+
render(this.tbody, this.rows)
36+
this.firstDataBindNode = document.querySelector('#tbody')
37+
this.dooAfterRender()
38+
}
39+
40+
async dooAfterRender() {
41+
this.firstDataBindNode.addEventListener('click', e => {
42+
e.preventDefault()
43+
if (e.target.parentElement.matches('.remove')) {
44+
this.delete(e.target.parentElement)
45+
} else if (e.target.tagName === 'A') {
46+
this.select(e.target)
47+
}
48+
})
49+
}
50+
51+
getParentRow(elem) {
52+
while (elem) {
53+
if (elem.tagName === "TR") {return elem}
54+
elem = elem.parentNode
55+
}
56+
return undefined
57+
}
58+
59+
buildData(count = DEFAULT_SIZE) {
60+
const data = Array(count);
61+
for (let i = 0; i < count; i=i+1) {
62+
const label = `${adjectives[_random(lenA)]} ${colours[_random(lenB)]} ${nouns[_random(lenC)]}`
63+
const id = this.ID++
64+
data[i] = { id, label }
65+
}
66+
return data
67+
}
68+
69+
getIndex(row) {
70+
let idx = this.rows.findIndex((item, i) => {
71+
if (item.id === row.key) {
72+
return i
73+
}
74+
})
75+
return idx
76+
}
77+
78+
delete(elem) {
79+
let row = this.getParentRow(elem)
80+
if (row) {
81+
row.parentElement.removeChild(row)
82+
let idx = this.getIndex(row)
83+
if (idx !== undefined) {
84+
this.rows.splice(idx,1)
85+
}
86+
87+
}
88+
}
89+
90+
run() {
91+
this.select(undefined)
92+
if (this.rows.length) this.clear()
93+
this.rows = this.buildData()
94+
render(this.tbody, this.rows)
95+
}
96+
97+
add() {
98+
let start = this.rows.length
99+
this.rows = this.rows.concat(this.buildData())
100+
append(this.tbody, this.rows, start)
101+
}
102+
103+
runLots() {
104+
this.select(undefined)
105+
if (this.rows.length) this.clear()
106+
this.rows = this.buildData(DEFAULT_SIZE_RUN_LOTS)
107+
render(this.tbody, this.rows)
108+
}
109+
110+
update() {
111+
const len = this.rows.length
112+
for (let i = 0; i < len; i += 10) {
113+
this.firstDataBindNode.childNodes[i].querySelector('a').append(BANG)
114+
}
115+
}
116+
117+
select(elem) {
118+
if (this.selectedRow) {
119+
this.selectedRow.className = ''
120+
this.selectedRow = undefined
121+
}
122+
123+
if (elem) {
124+
const row = this.getParentRow(elem)
125+
if (row) {
126+
this.selectedRow = row
127+
row.className = DANGER
128+
}
129+
}
130+
}
131+
132+
133+
clear() {
134+
this.firstDataBindNode.textContent = null
135+
this.rows = []
136+
}
137+
138+
swapRows() {
139+
if (this.rows.length > SWAP_ROW) {
140+
let node1 = this.firstDataBindNode.firstChild.nextSibling,
141+
swapRow = this.firstDataBindNode.childNodes[SWAP_ROW],
142+
node999 = swapRow.nextSibling,
143+
row1 = this.rows[1]
144+
145+
this.rows[1] = this.rows[SWAP_ROW];
146+
this.rows[SWAP_ROW] = row1
147+
148+
this.firstDataBindNode.insertBefore(node1.parentNode.replaceChild(swapRow, node1), node999)
149+
}
150+
}
151+
152+
addEventListeners() {
153+
const actions = {
154+
'run': this.run,
155+
'runlots': this.runLots,
156+
'add': this.add,
157+
'update': this.update,
158+
'clear': this.clear,
159+
'swaprows': this.swapRows,
160+
runAction: (e) => {
161+
e.preventDefault()
162+
if (actions[e.target.id]) {
163+
actions[e.target.id]()
164+
}
165+
}
166+
}
167+
document.getElementById("main").addEventListener('click', e => actions.runAction(e))
168+
}
169+
}
170+
const main = new Main()
171+
main.init()

frameworks/keyed/nanoviews/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<title>Nanoviews-keyed</title>
6+
<link href="/css/currentStyle.css" rel="stylesheet"/>
7+
</head>
8+
<body>
9+
<div id='main'></div>
10+
<script src='dist/main.js'></script>
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)