@gramlot/gramlot-examples 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/package.json +1 -1
- package/src/gramlot_examples/catalog.json +3 -10
- package/src/gramlot_examples/gallery/dist/gallery.js +68 -57
- package/src/gramlot_examples/pages/README.md +2 -2
- package/src/gramlot_examples/pages/controllers/{09_end_to_end.js → 08_end_to_end.js} +3 -18
- package/src/gramlot_examples/pages/controllers/{09_end_to_end.md → 08_end_to_end.md} +5 -6
- package/src/gramlot_examples/pages/controllers/README.md +1 -1
- package/src/gramlot_examples/pages/controllers/08_remote_source.js +0 -43
- package/src/gramlot_examples/pages/controllers/08_remote_source.md +0 -10
- /package/src/gramlot_examples/pages/controllers/{09_end_to_end.css → 08_end_to_end.css} +0 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm install @gramlot/gramlot-examples
|
|
|
12
12
|
[](https://pypi.org/project/gramlot-examples/)
|
|
13
13
|
[](https://www.npmjs.com/package/@gramlot/gramlot-examples)
|
|
14
14
|
|
|
15
|
-
Current release: 0.2.
|
|
15
|
+
Current release: 0.2.7.
|
|
16
16
|
|
|
17
17
|
The repositories of the family are described in
|
|
18
18
|
[The Gramlot family](https://github.com/gramlot-org/gramlot/blob/main/docs/public/055-family.md)
|
|
@@ -26,8 +26,8 @@ same-name README:
|
|
|
26
26
|
|
|
27
27
|
- `html_svg/`: thirteen HTML and SVG pages, without binding (`e01`–`e13`);
|
|
28
28
|
- `binding/`: eleven pages whose DOM follows the Data (`b01`–`b11`);
|
|
29
|
-
- `controllers/`:
|
|
30
|
-
|
|
29
|
+
- `controllers/`: eight pages with formulas, controllers, named logic, events and
|
|
30
|
+
the end-to-end story (`c01`–`c08`).
|
|
31
31
|
|
|
32
32
|
Each `NN_name.js` exports `Page` and `Logic`; the Python page `NN_name.py` takes its
|
|
33
33
|
`Logic` from the module beside it.
|
package/package.json
CHANGED
|
@@ -235,17 +235,10 @@
|
|
|
235
235
|
},
|
|
236
236
|
{
|
|
237
237
|
"key": "c08",
|
|
238
|
-
"title": "Remote Source",
|
|
239
|
-
"folder": "08_remote_source",
|
|
240
|
-
"description": "remoteSource replaces a branch with Source built on the server.",
|
|
241
|
-
"explanation": "The Page declares a Source method. A named controller asks for it; the new branch brings its own dataSetter values, visible at its first render."
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
"key": "c09",
|
|
245
238
|
"title": "End-to-end story",
|
|
246
|
-
"folder": "
|
|
247
|
-
"description": "Title, input, radios, checkbox, formula, SVG, button and
|
|
248
|
-
"explanation": "
|
|
239
|
+
"folder": "08_end_to_end",
|
|
240
|
+
"description": "Title, input, radios, checkbox, formula, SVG, button and freeze together.",
|
|
241
|
+
"explanation": "Setters after the controls, live editing, a radio pair, a formula and controller driving text and SVG, a counting button and freeze."
|
|
249
242
|
}
|
|
250
243
|
]
|
|
251
244
|
}
|
|
@@ -17767,9 +17767,9 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17767
17767
|
function I() {
|
|
17768
17768
|
return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
|
|
17769
17769
|
}
|
|
17770
|
-
var
|
|
17770
|
+
var P3 = I();
|
|
17771
17771
|
function W(l3) {
|
|
17772
|
-
|
|
17772
|
+
P3 = l3;
|
|
17773
17773
|
}
|
|
17774
17774
|
var A = { exec: () => null };
|
|
17775
17775
|
function C(l3) {
|
|
@@ -17800,9 +17800,9 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17800
17800
|
var G = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
|
|
17801
17801
|
var Ae = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
|
|
17802
17802
|
var J = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
|
|
17803
|
-
var
|
|
17804
|
-
var
|
|
17805
|
-
var Ee = h(
|
|
17803
|
+
var he = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |fences|blockquote|heading|hr|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
|
|
17804
|
+
var de = h(he).replace(/bull/g, J).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/hr/g, / {0,3}(?:(?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
|
|
17805
|
+
var Ee = h(he).replace(/bull/g, J).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/hr/g, / {0,3}(?:(?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
|
|
17806
17806
|
var V = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/;
|
|
17807
17807
|
var Me = /^[^\n]+/;
|
|
17808
17808
|
var Y = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
|
|
@@ -17811,36 +17811,36 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17811
17811
|
var N = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
|
|
17812
17812
|
var ee = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
|
|
17813
17813
|
var Be = h("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][a-z0-9-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][a-z0-9-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", ee).replace("tag", N).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
|
|
17814
|
-
var
|
|
17815
|
-
var De =
|
|
17816
|
-
var qe =
|
|
17814
|
+
var ke = (l3) => h(V).replace("hr", G).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", l3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", N).getRegex();
|
|
17815
|
+
var De = ke(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/);
|
|
17816
|
+
var qe = ke(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/);
|
|
17817
17817
|
var ve = h(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", qe).getRegex();
|
|
17818
|
-
var te = { blockquote: ve, code: Le, def: Ie, fences: ze, heading: Ae, hr: G, html: Be, lheading:
|
|
17819
|
-
var
|
|
17820
|
-
var Ze = { ...te, lheading: Ee, table:
|
|
17818
|
+
var te = { blockquote: ve, code: Le, def: Ie, fences: ze, heading: Ae, hr: G, html: Be, lheading: de, list: Ce, newline: $e, paragraph: De, table: A, text: Me };
|
|
17819
|
+
var ue = h("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", G).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", N).getRegex();
|
|
17820
|
+
var Ze = { ...te, lheading: Ee, table: ue, paragraph: h(V).replace("hr", G).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", ue).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", N).getRegex() };
|
|
17821
17821
|
var He = { ...te, html: h(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", ee).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: A, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: h(V).replace("hr", G).replace("heading", ` *#{1,6} *[^
|
|
17822
|
-
]`).replace("lheading",
|
|
17822
|
+
]`).replace("lheading", de).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
|
|
17823
17823
|
var Ge = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
|
|
17824
17824
|
var Ne = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
|
|
17825
|
-
var
|
|
17825
|
+
var ge = /^( {2,}|\\)\n(?!\s*$)[ \t]*/;
|
|
17826
17826
|
var Qe = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
|
|
17827
17827
|
var $ = /[\p{P}\p{S}]/u;
|
|
17828
17828
|
var B = /[\s\p{P}\p{S}]/u;
|
|
17829
17829
|
var Q = /[^\s\p{P}\p{S}]/u;
|
|
17830
17830
|
var je = h(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, B).getRegex();
|
|
17831
17831
|
var Fe = /[\p{Pi}\p{Ps}"']/u;
|
|
17832
|
-
var
|
|
17832
|
+
var fe = /(?!~)[\p{P}\p{S}]/u;
|
|
17833
17833
|
var Ue = /(?!~)[\s\p{P}\p{S}]/u;
|
|
17834
17834
|
var Ke = /(?:[^\s\p{P}\p{S}]|~)/u;
|
|
17835
17835
|
var We = h(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", _e ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
|
|
17836
|
-
var
|
|
17837
|
-
var Xe = h(
|
|
17838
|
-
var Je = h(
|
|
17836
|
+
var me = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
|
|
17837
|
+
var Xe = h(me, "u").replace(/punct/g, $).getRegex();
|
|
17838
|
+
var Je = h(me, "u").replace(/punct/g, fe).getRegex();
|
|
17839
17839
|
var Ve = /^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/;
|
|
17840
17840
|
var Ye = h(Ve, "u").replace(/openQuote/g, Fe).replace(/punct/g, $).getRegex();
|
|
17841
|
-
var
|
|
17842
|
-
var et = h(
|
|
17843
|
-
var tt = h(
|
|
17841
|
+
var xe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
|
|
17842
|
+
var et = h(xe, "gu").replace(/notPunctSpace/g, Q).replace(/punctSpace/g, B).replace(/punct/g, $).getRegex();
|
|
17843
|
+
var tt = h(xe, "gu").replace(/notPunctSpace/g, Ke).replace(/punctSpace/g, Ue).replace(/punct/g, fe).getRegex();
|
|
17844
17844
|
var nt = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)";
|
|
17845
17845
|
var rt = h(nt, "gu").replace(/notPunctSpace/g, Q).replace(/punctSpace/g, B).replace(/punct/g, $).getRegex();
|
|
17846
17846
|
var st = h("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, Q).replace(/punctSpace/g, B).replace(/punct/g, $).getRegex();
|
|
@@ -17853,32 +17853,32 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17853
17853
|
var ct = h(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
|
|
17854
17854
|
var ht = h(ee).replace("(?:-->|$)", "-->").getRegex();
|
|
17855
17855
|
var dt = h("^comment|^</[a-zA-Z][a-zA-Z0-9-]*\\s*>|^<[a-zA-Z][a-zA-Z0-9-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", ht).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
|
|
17856
|
-
var
|
|
17857
|
-
var U = h(/(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/).replace("brackets",
|
|
17858
|
-
var kt = h(/^!?\[(label)\]\(\
|
|
17856
|
+
var be = /\[(?:\\[\s\S]|[^\[\]\\])*\]/;
|
|
17857
|
+
var U = h(/(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/).replace("brackets", be).getRegex();
|
|
17858
|
+
var kt = h(/^!?\[(label)\]\([ \t\n]*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?[ \t\n]*\)/).replace("label", U).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
|
|
17859
17859
|
var gt = h(/^!?\[(label)\]\[(ref)\]/).replace("label", U).replace("ref", Y).getRegex();
|
|
17860
17860
|
var ft = h(/^!?\[(ref)\](?:\[\])?/).replace("ref", Y).getRegex();
|
|
17861
|
-
var
|
|
17862
|
-
var mt = h(/(?:[^\[\]\\`]*(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\]))){0,999}?[^\[\]\\`]*?/).replace("brackets",
|
|
17863
|
-
var xt = h("reflink|nolink(?!\\()", "g").replace("reflink", h(/^!?\[(label)\]\[(ref)\]/).replace("label", mt).replace("ref",
|
|
17864
|
-
var
|
|
17861
|
+
var pe = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\]){1,999}/;
|
|
17862
|
+
var mt = h(/(?:[^\[\]\\`]*(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\]))){0,999}?[^\[\]\\`]*?/).replace("brackets", be).getRegex();
|
|
17863
|
+
var xt = h("reflink|nolink(?!\\()", "g").replace("reflink", h(/^!?\[(label)\]\[(ref)\]/).replace("label", mt).replace("ref", pe).getRegex()).replace("nolink", h(/^!?\[(ref)\](?:\[\])?/).replace("ref", pe).getRegex()).getRegex();
|
|
17864
|
+
var ce = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
|
|
17865
17865
|
var bt = /[A-Za-z0-9._+-]+@[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![\w-])/;
|
|
17866
17866
|
var Rt = h(/(?:mailto:email|xmpp:email(?:\/[A-Za-z0-9@.]+)?)/).replace(/email/g, bt).getRegex();
|
|
17867
|
-
var ne = { _backpedal: A, anyPunctuation: pt, autolink: ct, blockSkip: We, br:
|
|
17867
|
+
var ne = { _backpedal: A, anyPunctuation: pt, autolink: ct, blockSkip: We, br: ge, code: Ne, del: A, delLDelim: A, delRDelim: A, emStrongLDelim: Xe, emStrongRDelimAst: et, emStrongRDelimUnd: st, escape: Ge, link: kt, nolink: ft, punctuation: je, reflink: gt, reflinkSearch: xt, tag: dt, text: Qe, url: A };
|
|
17868
17868
|
var Tt = { ...ne, emStrongLDelim: Ye, emStrongRDelimAst: rt, emStrongRDelimUnd: ot, link: h(/^!?\[(label)\]\((.*?)\)/).replace("label", U).getRegex(), reflink: h(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", U).getRegex() };
|
|
17869
|
-
var X = { ...ne, emStrongRDelimAst: tt, emStrongLDelim: Je, delLDelim: at, delRDelim: ut, url: h(/^emailProtocol|^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("emailProtocol", Rt).replace("protocol",
|
|
17870
|
-
var Ot = { ...X, br: h(
|
|
17869
|
+
var X = { ...ne, emStrongRDelimAst: tt, emStrongLDelim: Je, delLDelim: at, delRDelim: ut, url: h(/^emailProtocol|^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("emailProtocol", Rt).replace("protocol", ce).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![\w-])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: h(/^(?:[^a-zA-Z0-9](?=emailProtocol)|(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9](?=emailProtocol)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))))/).replace("protocol", ce).replace(/emailProtocol/g, /(?:mailto|xmpp):/).getRegex() };
|
|
17870
|
+
var Ot = { ...X, br: h(ge).replace("{2,}", "*").getRegex(), text: h(X.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
|
|
17871
17871
|
var j = { normal: te, gfm: Ze, pedantic: He };
|
|
17872
17872
|
var D = { normal: ne, gfm: X, breaks: Ot, pedantic: Tt };
|
|
17873
17873
|
var wt = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
17874
|
-
var
|
|
17874
|
+
var Re = (l3) => wt[l3];
|
|
17875
17875
|
function O(l3, e) {
|
|
17876
17876
|
if (e) {
|
|
17877
|
-
if (x.escapeTest.test(l3)) return l3.replace(x.escapeReplace,
|
|
17878
|
-
} else if (x.escapeTestNoEncode.test(l3)) return l3.replace(x.escapeReplaceNoEncode,
|
|
17877
|
+
if (x.escapeTest.test(l3)) return l3.replace(x.escapeReplace, Re);
|
|
17878
|
+
} else if (x.escapeTestNoEncode.test(l3)) return l3.replace(x.escapeReplaceNoEncode, Re);
|
|
17879
17879
|
return l3;
|
|
17880
17880
|
}
|
|
17881
|
-
function
|
|
17881
|
+
function Te(l3) {
|
|
17882
17882
|
return l3.replace(x.numericCharacterReference, (e, t, n) => {
|
|
17883
17883
|
let s = t === void 0 ? Number.parseInt(n, 16) : Number.parseInt(t, 10);
|
|
17884
17884
|
return s === 0 || s > 1114111 || s >= 55296 && s <= 57343 ? "\uFFFD" : String.fromCodePoint(s);
|
|
@@ -17925,15 +17925,15 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17925
17925
|
function q(l3) {
|
|
17926
17926
|
return l3.trim().toLowerCase().toUpperCase().toLowerCase();
|
|
17927
17927
|
}
|
|
17928
|
-
function
|
|
17929
|
-
if (l3.indexOf(e[1]) === -1) return -1;
|
|
17928
|
+
function oe(l3, e) {
|
|
17929
|
+
if (l3.indexOf(e[0]) === -1 && l3.indexOf(e[1]) === -1) return -1;
|
|
17930
17930
|
let t = 0;
|
|
17931
17931
|
for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
|
|
17932
17932
|
else if (l3[n] === e[0]) t++;
|
|
17933
17933
|
else if (l3[n] === e[1] && (t--, t < 0)) return n;
|
|
17934
17934
|
return t > 0 ? -2 : -1;
|
|
17935
17935
|
}
|
|
17936
|
-
function
|
|
17936
|
+
function ae(l3, e = 0) {
|
|
17937
17937
|
let t = e, n = "";
|
|
17938
17938
|
for (let s of l3) if (s === " ") {
|
|
17939
17939
|
let r = 4 - t % 4;
|
|
@@ -17956,7 +17956,7 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17956
17956
|
}
|
|
17957
17957
|
return { type: u ? "image" : "link", raw: t, href: r, title: o, text: i, tokens: c };
|
|
17958
17958
|
}
|
|
17959
|
-
function
|
|
17959
|
+
function Pt(l3, e, t) {
|
|
17960
17960
|
let n = l3.match(t.other.indentCodeCompensation);
|
|
17961
17961
|
if (n === null) return e;
|
|
17962
17962
|
let s = n[1];
|
|
@@ -17992,12 +17992,12 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
17992
17992
|
}
|
|
17993
17993
|
return false;
|
|
17994
17994
|
}
|
|
17995
|
-
var
|
|
17995
|
+
var y = class {
|
|
17996
17996
|
options;
|
|
17997
17997
|
rules;
|
|
17998
17998
|
lexer;
|
|
17999
17999
|
constructor(e) {
|
|
18000
|
-
this.options = e ||
|
|
18000
|
+
this.options = e || P3;
|
|
18001
18001
|
}
|
|
18002
18002
|
space(e) {
|
|
18003
18003
|
let t = this.rules.block.newline.exec(e);
|
|
@@ -18013,7 +18013,7 @@ ${" ".repeat(depth)}</${tag2}>`;
|
|
|
18013
18013
|
fences(e) {
|
|
18014
18014
|
let t = this.rules.block.fences.exec(e);
|
|
18015
18015
|
if (t) {
|
|
18016
|
-
let n = t[0], s =
|
|
18016
|
+
let n = t[0], s = Pt(n, t[3] || "", this.rules);
|
|
18017
18017
|
return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
|
|
18018
18018
|
}
|
|
18019
18019
|
}
|
|
@@ -18090,19 +18090,19 @@ ${Z.join(`
|
|
|
18090
18090
|
if (!(t = o.exec(e)) || this.rules.block.hr.test(e)) break;
|
|
18091
18091
|
p = t[0], e = e.substring(p.length);
|
|
18092
18092
|
let d = t[2].split(`
|
|
18093
|
-
`, 1)[0], m = t[1].length, b = this.options.pedantic ?
|
|
18093
|
+
`, 1)[0], m = t[1].length, b = this.options.pedantic ? ae(d, m) : d.replace(this.rules.other.leadingSpaceTab, (M) => ae(M, m)), g = e.split(`
|
|
18094
18094
|
`, 1)[0], w = !b.trim(), f = 0;
|
|
18095
18095
|
if (this.options.pedantic ? (f = 2, c = b.trimStart()) : w ? f = m + 1 : (f = b.search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, c = b.slice(f), f += m), w && this.rules.other.blankLine.test(g) && (p += g + `
|
|
18096
18096
|
`, e = e.substring(g.length + 1), a = true), !a) {
|
|
18097
|
-
let M = this.rules.other.nextBulletRegex(f), v = this.rules.other.hrRegex(f), Z = this.rules.other.fencesBeginRegex(f),
|
|
18097
|
+
let M = this.rules.other.nextBulletRegex(f), v = this.rules.other.hrRegex(f), Z = this.rules.other.fencesBeginRegex(f), le = this.rules.other.headingBeginRegex(f), Pe = this.rules.other.htmlBeginRegex(f), ye = this.rules.other.blockquoteBeginRegex(f);
|
|
18098
18098
|
for (; e; ) {
|
|
18099
18099
|
let K = e.split(`
|
|
18100
18100
|
`, 1)[0], H;
|
|
18101
|
-
if (g = K, this.options.pedantic ? (g = g.replace(this.rules.other.listReplaceNesting, " "), H = g) : H = g.replace(this.rules.other.leadingSpaceTab, (Se) => Se.replace(this.rules.other.tabCharGlobal, " ")), Z.test(g) ||
|
|
18101
|
+
if (g = K, this.options.pedantic ? (g = g.replace(this.rules.other.listReplaceNesting, " "), H = g) : H = g.replace(this.rules.other.leadingSpaceTab, (Se) => Se.replace(this.rules.other.tabCharGlobal, " ")), Z.test(g) || le.test(g) || Pe.test(g) || ye.test(g) || M.test(g) || v.test(g)) break;
|
|
18102
18102
|
if (H.search(this.rules.other.nonSpaceChar) >= f || !g.trim()) c += `
|
|
18103
18103
|
` + H.slice(f);
|
|
18104
18104
|
else {
|
|
18105
|
-
if (w || b.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || Z.test(b) ||
|
|
18105
|
+
if (w || b.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || Z.test(b) || le.test(b) || v.test(b)) break;
|
|
18106
18106
|
c += `
|
|
18107
18107
|
` + g;
|
|
18108
18108
|
}
|
|
@@ -18152,6 +18152,7 @@ ${Z.join(`
|
|
|
18152
18152
|
def(e) {
|
|
18153
18153
|
let t = this.rules.block.def.exec(e);
|
|
18154
18154
|
if (t) {
|
|
18155
|
+
if (!this.rules.other.startAngleBracket.test(t[2]) && oe(t[2], "()") !== -1) return;
|
|
18155
18156
|
let n = q(t[1]).replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
|
|
18156
18157
|
return { type: "def", tag: n, raw: L(t[0], `
|
|
18157
18158
|
`), href: s, title: r };
|
|
@@ -18199,6 +18200,7 @@ ${Z.join(`
|
|
|
18199
18200
|
if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
|
|
18200
18201
|
}
|
|
18201
18202
|
link(e) {
|
|
18203
|
+
if (this.lexer.state.linkParenPossible === false) return;
|
|
18202
18204
|
let t = this.rules.inline.link.exec(e);
|
|
18203
18205
|
if (t) {
|
|
18204
18206
|
let n = t[0].charAt(0) === "!" ? 2 : 1;
|
|
@@ -18209,7 +18211,7 @@ ${Z.join(`
|
|
|
18209
18211
|
let i = L(s.slice(0, -1), "\\");
|
|
18210
18212
|
if ((s.length - i.length) % 2 === 0) return;
|
|
18211
18213
|
} else {
|
|
18212
|
-
let i =
|
|
18214
|
+
let i = oe(t[2], "()");
|
|
18213
18215
|
if (i === -2) return;
|
|
18214
18216
|
if (i > -1) {
|
|
18215
18217
|
let a = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + i;
|
|
@@ -18321,7 +18323,7 @@ ${Z.join(`
|
|
|
18321
18323
|
let t = this.rules.inline.text.exec(e);
|
|
18322
18324
|
if (t) {
|
|
18323
18325
|
let n = this.lexer.state.inRawBlock;
|
|
18324
|
-
return { type: "text", raw: t[0], text: n ? t[0] :
|
|
18326
|
+
return { type: "text", raw: t[0], text: n ? t[0] : Te(t[0]), escaped: n };
|
|
18325
18327
|
}
|
|
18326
18328
|
}
|
|
18327
18329
|
};
|
|
@@ -18332,7 +18334,7 @@ ${Z.join(`
|
|
|
18332
18334
|
inlineQueue;
|
|
18333
18335
|
tokenizer;
|
|
18334
18336
|
constructor(e) {
|
|
18335
|
-
this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e ||
|
|
18337
|
+
this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || P3, this.options.tokenizer = this.options.tokenizer || new y(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, linkEmitted: false, linkParenPossible: true, top: true };
|
|
18336
18338
|
let t = { other: x, block: j.normal, inline: D.normal };
|
|
18337
18339
|
this.options.pedantic ? (t.block = j.pedantic, t.inline = D.pedantic) : this.options.gfm && (t.block = j.gfm, this.options.breaks ? t.inline = D.breaks : t.inline = D.gfm), this.tokenizer.rules = t;
|
|
18338
18340
|
}
|
|
@@ -18468,6 +18470,15 @@ ${Z.join(`
|
|
|
18468
18470
|
}
|
|
18469
18471
|
inlineTokens(e, t = []) {
|
|
18470
18472
|
this.tokenizer.lexer = this;
|
|
18473
|
+
let n = this.state.linkParenPossible;
|
|
18474
|
+
this.state.linkParenPossible = n && e.includes(")");
|
|
18475
|
+
try {
|
|
18476
|
+
return this.#e(e, t);
|
|
18477
|
+
} finally {
|
|
18478
|
+
this.state.linkParenPossible = n;
|
|
18479
|
+
}
|
|
18480
|
+
}
|
|
18481
|
+
#e(e, t) {
|
|
18471
18482
|
let n = e;
|
|
18472
18483
|
if (this.tokens.links && e.includes("[")) {
|
|
18473
18484
|
let i = this.tokenizer.rules.inline.reflinkSearch, u = (a) => {
|
|
@@ -18567,7 +18578,7 @@ ${Z.join(`
|
|
|
18567
18578
|
options;
|
|
18568
18579
|
parser;
|
|
18569
18580
|
constructor(e) {
|
|
18570
|
-
this.options = e ||
|
|
18581
|
+
this.options = e || P3;
|
|
18571
18582
|
}
|
|
18572
18583
|
space(e) {
|
|
18573
18584
|
return "";
|
|
@@ -18718,7 +18729,7 @@ ${e}</tr>
|
|
|
18718
18729
|
renderer;
|
|
18719
18730
|
textRenderer;
|
|
18720
18731
|
constructor(e) {
|
|
18721
|
-
this.options = e ||
|
|
18732
|
+
this.options = e || P3, this.options.renderer = this.options.renderer || new S(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new z();
|
|
18722
18733
|
}
|
|
18723
18734
|
static parse(e, t) {
|
|
18724
18735
|
return new l2(t).parse(e);
|
|
@@ -18869,7 +18880,7 @@ ${e}</tr>
|
|
|
18869
18880
|
options;
|
|
18870
18881
|
block;
|
|
18871
18882
|
constructor(e) {
|
|
18872
|
-
this.options = e ||
|
|
18883
|
+
this.options = e || P3;
|
|
18873
18884
|
}
|
|
18874
18885
|
static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
|
|
18875
18886
|
static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
|
|
@@ -18901,7 +18912,7 @@ ${e}</tr>
|
|
|
18901
18912
|
Renderer = S;
|
|
18902
18913
|
TextRenderer = z;
|
|
18903
18914
|
Lexer = R;
|
|
18904
|
-
Tokenizer =
|
|
18915
|
+
Tokenizer = y;
|
|
18905
18916
|
Hooks = _;
|
|
18906
18917
|
constructor(...e) {
|
|
18907
18918
|
this.use(...e);
|
|
@@ -18963,7 +18974,7 @@ ${e}</tr>
|
|
|
18963
18974
|
s.renderer = r;
|
|
18964
18975
|
}
|
|
18965
18976
|
if (n.tokenizer) {
|
|
18966
|
-
let r = this.defaults.tokenizer || new
|
|
18977
|
+
let r = this.defaults.tokenizer || new y(this.defaults);
|
|
18967
18978
|
for (let o in n.tokenizer) {
|
|
18968
18979
|
if (!(o in r)) throw new Error(`tokenizer '${o}' does not exist`);
|
|
18969
18980
|
if (["options", "rules", "lexer"].includes(o)) continue;
|
|
@@ -19061,11 +19072,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
19061
19072
|
return E.setOptions(l3), k.defaults = E.defaults, W(k.defaults), k;
|
|
19062
19073
|
};
|
|
19063
19074
|
k.getDefaults = I;
|
|
19064
|
-
k.defaults =
|
|
19065
|
-
function
|
|
19075
|
+
k.defaults = P3;
|
|
19076
|
+
function yt(...l3) {
|
|
19066
19077
|
return E.use(...l3), k.defaults = E.defaults, W(k.defaults), k;
|
|
19067
19078
|
}
|
|
19068
|
-
k.use =
|
|
19079
|
+
k.use = yt;
|
|
19069
19080
|
k.walkTokens = function(l3, e) {
|
|
19070
19081
|
return E.walkTokens(l3, e);
|
|
19071
19082
|
};
|
|
@@ -19076,7 +19087,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
19076
19087
|
k.TextRenderer = z;
|
|
19077
19088
|
k.Lexer = R;
|
|
19078
19089
|
k.lexer = R.lex;
|
|
19079
|
-
k.Tokenizer =
|
|
19090
|
+
k.Tokenizer = y;
|
|
19080
19091
|
k.Hooks = _;
|
|
19081
19092
|
k.parse = k;
|
|
19082
19093
|
var gn = k.options;
|
|
@@ -7,9 +7,9 @@ JavaScript, in three families:
|
|
|
7
7
|
- [`binding/`](binding/): eleven pages whose DOM follows the Data through pointers,
|
|
8
8
|
editing, booleans, style, SVG and freeze. The last three take the content of
|
|
9
9
|
`html_svg` examples 06, 08 and 12 and add the binding.
|
|
10
|
-
- [`controllers/`](controllers/):
|
|
10
|
+
- [`controllers/`](controllers/): eight pages with formulas, controllers, named
|
|
11
11
|
logic in the `Logic` class of the page module, inline expressions, node methods, buttons,
|
|
12
|
-
events
|
|
12
|
+
events and the end-to-end story.
|
|
13
13
|
|
|
14
14
|
Each example is a file page: `NN_name.py`, its JavaScript equivalent `NN_name.js`,
|
|
15
15
|
its README `NN_name.md`, and where needed a same-name stylesheet `NN_name.css`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Page as BasePage
|
|
1
|
+
import {Page as BasePage} from '@gramlot/gramlot/page';
|
|
2
2
|
|
|
3
3
|
export class Page extends BasePage {
|
|
4
4
|
static title = 'End-to-end story';
|
|
@@ -45,28 +45,17 @@ export class Page extends BasePage {
|
|
|
45
45
|
const notes = later.ul({node_id: 'notes', id: 'notes'});
|
|
46
46
|
for (const text of ['Setters live here too', 'This note can be removed under freeze']) notes.li(text);
|
|
47
47
|
const actions = later.div({class: 'actions'});
|
|
48
|
-
for (const [label, method] of [['
|
|
49
|
-
['Remove a note', 'removeNote'], ['Thaw', 'thaw']]) {
|
|
48
|
+
for (const [label, method] of [['Freeze', 'freeze'], ['Remove a note', 'removeNote'], ['Thaw', 'thaw']]) {
|
|
50
49
|
actions.button(label, {id: method}).dataController({func: method});
|
|
51
50
|
}
|
|
52
|
-
later.section({node_id: 'extras', id: 'extras'}).p('No extras yet.', {class: 'muted'});
|
|
53
51
|
later.dataSetter({destination_path: '.settings.caption', value: 'The story of a page'});
|
|
54
52
|
later.dataSetter({destination_path: '.size', value: {small: true, large: false}});
|
|
55
53
|
later.dataSetter({destination_path: '.gift', value: false});
|
|
56
54
|
later.dataSetter({destination_path: '.live', value: false});
|
|
57
55
|
}
|
|
58
|
-
|
|
59
|
-
extras(root) {
|
|
60
|
-
const branch = root.div({datapath: 'extras', class: 'stack'});
|
|
61
|
-
branch.h3('^.title', {id: 'extras-title'});
|
|
62
|
-
branch.p('^.items', {id: 'extras-items'});
|
|
63
|
-
branch.dataSetter({destination_path: '.title', value: 'Extras from the server'});
|
|
64
|
-
branch.dataSetter({destination_path: '.items', value: 'Ribbon, card, envelope'});
|
|
65
|
-
}
|
|
66
56
|
}
|
|
67
|
-
source(Page.prototype.extras);
|
|
68
57
|
|
|
69
|
-
/** Logic of
|
|
58
|
+
/** Logic of 08_end_to_end.py and 08_end_to_end.js: the named logic of the story. */
|
|
70
59
|
export class Logic {
|
|
71
60
|
sourceNode(nodeId) {
|
|
72
61
|
return this.page.source.getNodeByAttr('node_id', nodeId);
|
|
@@ -83,10 +72,6 @@ export class Logic {
|
|
|
83
72
|
node.SET('.modifiers', kwargs.button_shift ? 'with Shift' : 'without modifiers');
|
|
84
73
|
}
|
|
85
74
|
|
|
86
|
-
loadExtras() {
|
|
87
|
-
return this.page.remoteSource(this.sourceNode('extras'), 'extras');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
75
|
freeze() {
|
|
91
76
|
this.page.renderer.freeze(this.sourceNode('later'));
|
|
92
77
|
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 08 · End-to-end story
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Every piece of the controllers family on one page, in Python and JavaScript with one `Logic` class in `08_end_to_end.js`.
|
|
4
4
|
|
|
5
5
|
1. **First render.** The `dataSetter` nodes sit after some controls and in the later branch; `.settings.caption` is written twice and the later setter wins. The quantity has no setter and starts from its `default`. The first DOM already shows every final value.
|
|
6
6
|
2. **Editing.** The caption field writes at `change`; after checking `live` it writes at every keystroke.
|
|
7
7
|
3. **Formula and controller.** The formulas compute the total and the circle's radius; the named controller `paint` colors the circle.
|
|
8
8
|
4. **Radio.** Choosing Large writes `size.large` true and `size.small` false.
|
|
9
9
|
5. **Button.** The nested named controller `press` runs once per click, with `button_counter` and `button_shift`.
|
|
10
|
-
6. **
|
|
11
|
-
7. **
|
|
12
|
-
8. **Close.** Closing the page disposes the Gramlot instance: providers, timers, listeners and pending requests stop.
|
|
10
|
+
6. **Freeze.** Freeze the later branch, change the quantity and remove a note, then thaw once: the removal appears at the thaw.
|
|
11
|
+
7. **Close.** Closing the page disposes the Gramlot instance: providers, timers, listeners and pending requests stop.
|
|
13
12
|
|
|
14
|
-
**Try it:** Walk the
|
|
13
|
+
**Try it:** Walk the seven steps in order, then reload and walk them in another order.
|
|
@@ -6,6 +6,6 @@ The pages of this family run code when the Data changes.
|
|
|
6
6
|
|
|
7
7
|
Inline code needs a Content Security Policy that allows it. Named logic in the `Logic` class also runs under a strict policy.
|
|
8
8
|
|
|
9
|
-
Start with **Formula** and **Controller**, then move the code to the `Logic` class with **Named logic**. The last page is the end-to-end story
|
|
9
|
+
Start with **Formula** and **Controller**, then move the code to the `Logic` class with **Named logic**. The last page is the end-to-end story: every piece of the two families on one page.
|
|
10
10
|
|
|
11
11
|
Each example has a Python page and its JavaScript equivalent. Both use the `Logic` class of the JavaScript module.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {Page as BasePage, source} from '@gramlot/gramlot/page';
|
|
2
|
-
|
|
3
|
-
const TOPICS = {
|
|
4
|
-
binding: ['Binding', 'Pointers connect the DOM to the Data in both directions.'],
|
|
5
|
-
controllers: ['Controllers', 'Formulas and controllers run code when the Data changes.'],
|
|
6
|
-
svg: ['SVG', 'SVG attributes follow the Data like HTML attributes.'],
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export class Page extends BasePage {
|
|
10
|
-
static title = 'Remote Source';
|
|
11
|
-
static css = ['/themes/gramlot-base/theme.css'];
|
|
12
|
-
|
|
13
|
-
main(root) {
|
|
14
|
-
const pane = root.div({class: 'example-page stack', datapath: 'remote'});
|
|
15
|
-
pane.h1('Remote Source');
|
|
16
|
-
pane.html_label('Topic', {for: 'topic'});
|
|
17
|
-
const topic = pane.select({value: '^.topic', id: 'topic'});
|
|
18
|
-
for (const [key, [title]] of Object.entries(TOPICS)) topic.option(title, {value: key});
|
|
19
|
-
pane.button('Load from the server', {id: 'load'}).dataController({func: 'load', topic: '=.topic'});
|
|
20
|
-
const target = pane.section({node_id: 'details', class: 'card stack', id: 'details'});
|
|
21
|
-
target.p('Nothing loaded yet.', {class: 'muted'});
|
|
22
|
-
pane.dataSetter({destination_path: '.topic', value: 'binding'});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
details(root, {topic = 'binding'} = {}) {
|
|
26
|
-
const [title, summary] = TOPICS[topic];
|
|
27
|
-
const branch = root.div({datapath: `topics.${topic}`, class: 'stack'});
|
|
28
|
-
branch.h2('^.title', {id: 'remote-title'});
|
|
29
|
-
branch.p('^.summary', {id: 'remote-summary'});
|
|
30
|
-
branch.dataSetter({destination_path: '.title', value: title});
|
|
31
|
-
branch.dataSetter({destination_path: '.summary', value: summary});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
source(Page.prototype.details);
|
|
35
|
-
|
|
36
|
-
/** Logic of 08_remote_source.py and 08_remote_source.js. */
|
|
37
|
-
export class Logic {
|
|
38
|
-
/** The button's controller: ask the server for the Source method `details` of this Page. */
|
|
39
|
-
load(node, kwargs) {
|
|
40
|
-
const target = this.page.source.getNodeByAttr('node_id', 'details');
|
|
41
|
-
return this.page.remoteSource(target, 'details', {topic: kwargs.topic});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# 08 · Remote Source
|
|
2
|
-
|
|
3
|
-
`gramlot.remoteSource(target, method, params)` asks the host to run a Source method of the Page and replaces the children of `target` with the returned branch.
|
|
4
|
-
|
|
5
|
-
- The Page declares the method with `@source` in Python and `source(Page.prototype.details)` in JavaScript. It builds into its own `root` and runs on the server.
|
|
6
|
-
- The button's nested controller names `load` in the `Logic` class of `08_remote_source.js`. It finds the target by its `node_id` and passes the chosen topic.
|
|
7
|
-
- The new branch carries its own `dataSetter` nodes. They run before the branch is built, so its heading and summary show their values at the first render.
|
|
8
|
-
- The request lives as long as the target: if the target is removed first, the late answer is ignored. When two requests overlap, the latest wins.
|
|
9
|
-
|
|
10
|
-
**Try it:** Choose SVG and load it, then add a third `dataSetter` to the remote branch.
|
|
File without changes
|