Last active
May 13, 2020 00:10
-
-
Save nykula/0575494162a547100b5432938330ebe8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/qjs | |
// Initial hyperscript test cases, framework-independent. | |
// ./h.test.js|tee h.test~|diff -u h.test -&&echo ok h.test||echo fail h.test | |
// 0BSD / public domain. 2020 Denys Nykula <[email protected]> | |
// TODO h("p", h("hr")), h("p", h("hr"), "2020"), h("p", "2020", h("hr")) | |
// TODO h('a[href=#][title="hyper script"]') | |
function h(s, a, c) { | |
if (!c && a && ("" + a === a || 0 in a)) (c = a), (a = {}); | |
(a = a || {}), (c = c || []); | |
if ("" + s !== s) return s(a, c); | |
var k = ""; | |
var t = "div"; | |
var r = /^(\w+)|^\.(\w+)|^#(\w+)|^\[(\w+)=(\w+)\]|^(\s*>\s*|$)/; | |
var xs = []; | |
for (var m; (m = r.exec(s)); s = s.slice(m.index + m[0].length)) | |
if (m[1]) t = m[1]; | |
else if (m[2]) k = (k ? k + " " : "") + m[2]; | |
else if (m[3] && !a.id) a.id = m[3]; | |
else if (m[4]) a[m[4]] = m[5]; | |
else if (m[6] || m[6] == "") { | |
a.className = k + (a.className ? " " + a.className : ""); | |
xs.push([t, a, c]), (a = {}), (k = ""), (t = "div"); | |
if (m[6] == "") break; | |
} | |
for (var x; (x = xs.pop()) && xs.length; ) xs[xs.length - 1][2] = [x]; | |
return x; | |
} | |
var render = (x) => x; | |
var t = (...x) => console.log(JSON.stringify(x)); | |
t("creates div with text", render(h("div", "Hyperscript"))); | |
t("creates div with text[1]", render(h("div", ["Hyperscript"]))); | |
t("creates div with text[3]", render(h("div", ["Hyper", " ", "script"]))); | |
t( | |
"creates a with href and text", | |
render(h("a", { href: "about:blank" }, "Home")) | |
); | |
t( | |
"creates div explicitly with classes", | |
[1, 0].map((big) => render(h("div.hr" + (big ? ".big" : "")))) | |
); | |
t( | |
"creates div implicitly with classes", | |
[1, 0].map((big) => render(h(".hr" + (big ? ".big" : "")))) | |
); | |
t( | |
"creates nested tree", | |
render( | |
h("#wrap > header>.container", [ | |
h(".brand", null, [ | |
h("div.title", { className: "punch" }, [ | |
h("a", { href: "#" }, [ | |
h("h1", "Initial hyperscript test cases."), | |
h("p.sub", "Framework-independent!"), | |
]), | |
]), | |
]), | |
h("nav"), | |
]) | |
) | |
); | |
t( | |
"allows array child", | |
render( | |
h("article", [ | |
h("h1", "Jackdaws love my big sphinx of quartz?"), | |
[ | |
"Zing, vext cwm fly jabs Kurd qoph.", | |
"Foo bar baz qux!", | |
"Prating jokers quizzically vexed me with fibs.", | |
].map((p) => h("p", p)), | |
h("p.more", [h("a", { href: "#" }, "Read more")]), | |
]) | |
) | |
); | |
function TodoV(props) { | |
return h(".todo", [ | |
h("label.inner", [ | |
h("input.done", { | |
checked: props.done ? "checked" : "", | |
type: "checkbox", | |
}), | |
" ", | |
h("span.text", props.text), | |
]), | |
]); | |
} | |
function TodoAdd() { | |
return h("form#todoadd[method=POST]", [ | |
h("input.todoaddtext", { | |
placeholder: "Create a todo", | |
title: "Todo text", | |
type: "text", | |
}), | |
h("button", { type: "submit" }, "Submit"), | |
]); | |
} | |
class TodosV { | |
static fetch() { | |
return { | |
todos: [ | |
{ done: true, text: "Wake up" }, | |
{ done: false, text: "Drink coffee" }, | |
{ done: true, text: "Take shower" }, | |
], | |
}; | |
} | |
static render(props) { | |
return h(".todos", [h(TodoAdd), props.todos.map((x) => h(TodoV, x))]); | |
} | |
} | |
// How do you pass props from server to client in Crank instead? Tell me pls :D | |
t("renders todos", render(h(TodosV.render, TodosV.fetch()))); | |
// Also, how do you return them without render, when headers.accept says json? | |
t("doesn't render todos", TodosV.fetch()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment