joule-ui takes in OpenUI Lang 1.0 the way it takes in A2UI: a model writes a surface as a program, one widget a line, and joule-ui-lang builds a widget tree against the host's registry as the program streams. After every chunk a snapshot holds the tree as far as it can be built, each widget checked by joule-ui's own validate, and every error with its source line and reason code. State, queries, operators, conditionals, built-in functions and sequences of actions are parsed and refused not-declarative. A canonical writer turns a tree back into the language; it parses back to the same tree. - joule-ui-core: WidgetSchema::positional, the order a positional call passes props in (SPEC §3); absent from the wire form when undeclared. - joule-ui-interaction: begin_interaction and Pending::finish, the lifecycle's three phases in two steps for a host whose handler is asynchronous (SPEC §6); run_interaction is built on them and seals what it sealed before. - conformance/lang/v1: L1 statements, L2 ingest, L3 streaming, L4 the canonical form, L5 refusals, with an independent Python verifier written from §11. - docs/create.md: the design of Create. Co-Authored-By: Claude Opus 5.5 <[email protected]>
364 lines
9 KiB
JSON
364 lines
9 KiB
JSON
{
|
|
"cases": [
|
|
{
|
|
"name": "page-of-cards",
|
|
"text": "root = Page([card1, card2], \"Home\")\ncard1 = Card(\"One\", [text1])\ntext1 = Text(\"a\")\ncard2 = Card(\"Two\", null, \"sub\")\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"children": [
|
|
{
|
|
"name": "Text",
|
|
"props": {
|
|
"text": {
|
|
"type": "text",
|
|
"value": "a"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Card",
|
|
"props": {
|
|
"title": {
|
|
"type": "text",
|
|
"value": "One"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Card",
|
|
"props": {
|
|
"subtitle": {
|
|
"type": "text",
|
|
"value": "sub"
|
|
},
|
|
"title": {
|
|
"type": "text",
|
|
"value": "Two"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {
|
|
"title": {
|
|
"type": "text",
|
|
"value": "Home"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "middle-absent-is-null",
|
|
"text": "root = Page([card1])\ncard1 = Card(\"t\", null, \"s\")\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"name": "Card",
|
|
"props": {
|
|
"subtitle": {
|
|
"type": "text",
|
|
"value": "s"
|
|
},
|
|
"title": {
|
|
"type": "text",
|
|
"value": "t"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
},
|
|
{
|
|
"name": "numbers-and-strings",
|
|
"text": "root = Page([text1, text2, text3])\ntext1 = Text(\"quote \\\" back \\\\ line\\nfeed é \\u0001\", 0.1)\ntext2 = Text(\"neg\", -0)\ntext3 = Text(\"small\", 0.0000001)\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"name": "Text",
|
|
"props": {
|
|
"size": {
|
|
"type": "number",
|
|
"value": 0.1
|
|
},
|
|
"text": {
|
|
"type": "text",
|
|
"value": "quote \" back \\ line\nfeed é \u0001"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Text",
|
|
"props": {
|
|
"size": {
|
|
"type": "number",
|
|
"value": -0.0
|
|
},
|
|
"text": {
|
|
"type": "text",
|
|
"value": "neg"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Text",
|
|
"props": {
|
|
"size": {
|
|
"type": "number",
|
|
"value": 1e-7
|
|
},
|
|
"text": {
|
|
"type": "text",
|
|
"value": "small"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
},
|
|
{
|
|
"name": "data",
|
|
"text": "root = Page([chart1])\nchart1 = Chart([\"a\", null], [1, []], {\"max value\": 1000000000000000000000, \"null\": null, stacked: true})\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"name": "Chart",
|
|
"props": {
|
|
"labels": {
|
|
"type": "list",
|
|
"value": [
|
|
{
|
|
"type": "text",
|
|
"value": "a"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"options": {
|
|
"type": "object",
|
|
"value": {
|
|
"max value": {
|
|
"type": "number",
|
|
"value": 1e+21
|
|
},
|
|
"null": {
|
|
"type": "null"
|
|
},
|
|
"stacked": {
|
|
"type": "bool",
|
|
"value": true
|
|
}
|
|
}
|
|
},
|
|
"values": {
|
|
"type": "list",
|
|
"value": [
|
|
{
|
|
"type": "number",
|
|
"value": 1.0
|
|
},
|
|
{
|
|
"type": "list",
|
|
"value": []
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
},
|
|
{
|
|
"name": "actions",
|
|
"text": "root = Page([button1, button2, button3, button4, button5])\nbutton1 = Button(\"none\", @Go())\nbutton2 = Button(\"one\", @Open(\"x\"))\nbutton3 = Button(\"two\", @Send(\"a\", 2))\nbutton4 = Button(\"list of one\", @Pick([1]))\nbutton5 = Button(\"null\", @Clear(null), true)\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"name": "Button",
|
|
"props": {
|
|
"action": {
|
|
"type": "action",
|
|
"value": {
|
|
"id": "Go",
|
|
"payload": null
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "text",
|
|
"value": "none"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Button",
|
|
"props": {
|
|
"action": {
|
|
"type": "action",
|
|
"value": {
|
|
"id": "Open",
|
|
"payload": {
|
|
"type": "text",
|
|
"value": "x"
|
|
}
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "text",
|
|
"value": "one"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Button",
|
|
"props": {
|
|
"action": {
|
|
"type": "action",
|
|
"value": {
|
|
"id": "Send",
|
|
"payload": {
|
|
"type": "list",
|
|
"value": [
|
|
{
|
|
"type": "text",
|
|
"value": "a"
|
|
},
|
|
{
|
|
"type": "number",
|
|
"value": 2.0
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "text",
|
|
"value": "two"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Button",
|
|
"props": {
|
|
"action": {
|
|
"type": "action",
|
|
"value": {
|
|
"id": "Pick",
|
|
"payload": {
|
|
"type": "list",
|
|
"value": [
|
|
{
|
|
"type": "number",
|
|
"value": 1.0
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "text",
|
|
"value": "list of one"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Button",
|
|
"props": {
|
|
"action": {
|
|
"type": "action",
|
|
"value": {
|
|
"id": "Clear",
|
|
"payload": {
|
|
"type": "null"
|
|
}
|
|
}
|
|
},
|
|
"label": {
|
|
"type": "text",
|
|
"value": "null"
|
|
},
|
|
"primary": {
|
|
"type": "bool",
|
|
"value": true
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
},
|
|
{
|
|
"name": "derived-order",
|
|
"text": "root = Page([note1])\nnote1 = Note(null, \"b\", [text1])\ntext1 = Text(\"in\")\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"children": [
|
|
{
|
|
"name": "Text",
|
|
"props": {
|
|
"text": {
|
|
"type": "text",
|
|
"value": "in"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Note",
|
|
"props": {
|
|
"body": {
|
|
"type": "text",
|
|
"value": "b"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
},
|
|
{
|
|
"name": "tabs",
|
|
"text": "root = Page([tabs1])\ntabs1 = Tabs([tab1, tab2])\ntab1 = Tab(\"x\")\ntab2 = Tab(\"y\")\n",
|
|
"tree": {
|
|
"children": [
|
|
{
|
|
"children": [
|
|
{
|
|
"name": "Tab",
|
|
"props": {
|
|
"title": {
|
|
"type": "text",
|
|
"value": "x"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"name": "Tab",
|
|
"props": {
|
|
"title": {
|
|
"type": "text",
|
|
"value": "y"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"name": "Tabs",
|
|
"props": {}
|
|
}
|
|
],
|
|
"name": "Page",
|
|
"props": {}
|
|
}
|
|
}
|
|
],
|
|
"class": "L4"
|
|
}
|