Skip to main content

max / quasi

Give the form a canvas, and let a document take a region custom_page serves a creator's own markup with a platform strip around it, and neither half was sayable. Two productions: - `canvas <markup> { .. }`, the second node member whose body does not set on a Node. Node::Canvas holds a Canvas, and classed, identified and the nodes drawn in the scope are that type's builders, so the body accretes onto the canvas and the variant goes on afterwards, exactly as picture does with Image. One argument always: Canvas::new("") is the default, and an item page has no creator markup while its scope still carries the stylesheet. - A document takes an `include` of a region another shape built. A table already takes a row this way and a row a control. custom_page's three screens carry the same band top and bottom and every link in it is per request, so the strip is a shape rather than Chrome; without this a `-> Slot` shape is unreachable from a `-> Screen` one. `leaving` also said it addressed nothing and Action::leaving takes a url. Third word in a table that was wrong because no declared screen had used it, after filling and copying.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
Author: Max Johnson <me@maxj.phd> · 2026-09-04 01:12 UTC
Signed with PGP, not checked
Commit: ef568318d6d8f49b0054eb637ece6f3e7180ffb3
Parent: 092a3c9
2 files changed, +55 insertions, -2 deletions
@@ -48,6 +48,8 @@
48 48 Node,
49 49 /// One picture: its body sets on the `Image`, and it emits nothing.
50 50 Image,
51 + /// One canvas: its body sets on the `Canvas` and draws inside its scope.
52 + Canvas,
51 53 }
52 54
53 55 pub fn declaration(declaration: &Declaration) -> Result<TokenStream> {
@@ -525,9 +527,22 @@
525 527 (Container::Screen, Emission::Region { name, kind, body }) => {
526 528 Ok((slot(name, kind, body)?, quote!(.with(#held))))
527 529 }
530 + // A region another shape built. `custom_page`'s three screens carry the
531 + // same platform strip top and bottom, and every link in it is per
532 + // request, so the band is a shape rather than `Chrome`. A table already
533 + // takes a row this way and a row a control; this is a document taking a
534 + // region.
535 + (Container::Screen, Emission::Include(supplier)) => {
536 + let supplier = hole(supplier)?;
537 + Ok((
538 + quote!(::std::convert::Into::into(#supplier)),
539 + quote!(.with(#held)),
540 + ))
541 + }
528 542 (Container::Screen, other) => Err(syn::Error::new(
529 543 emission_span(other),
530 - "a document holds regions: write `region <name> as <kind> { .. }`",
544 + "a document holds regions: write `region <name> as <kind> { .. }` \
545 + or `include <shape>;`",
531 546 )),
532 547 (Container::Cells | Container::Cell | Container::Row, Emission::Activate(action)) => {
533 548 Ok((self::action(action)?, quote!(.activate(#held))))
@@ -562,6 +577,10 @@
562 577 emission_span(other),
563 578 "a picture holds nothing: its body says how it sits in its box",
564 579 )),
580 + // Inside the scope and after the markup, which is the only place a
581 + // canvas can hold anything: the markup is opaque, so nothing is
582 + // injected into the middle of it.
583 + (Container::Canvas, other) => Ok((node(other)?, quote!(.with(#held)))),
565 584 (Container::Run, Emission::Beside { priority, inner }) => Ok((
566 585 node(inner)?,
567 586 quote!(.beside(#held, ::quasi_router::layout::Priority::#priority)),
@@ -732,6 +751,24 @@
732 751 )?;
733 752 Ok(quote!(::quasi_router::Node::Image(#picture)))
734 753 }
754 + Emission::Simple { member, args, body } if member == "canvas" => {
755 + // The second member whose body does not set on a `Node`, and for
756 + // `picture`'s reason: `Node::Canvas` holds a `Canvas`, and
757 + // `classed`, `identified` and the nodes drawn in the scope are that
758 + // type's. `custom_page` is the site -- a creator's markup under the
759 + // scope `css_sanitizer` rewrote every one of their rules for.
760 + //
761 + // One argument always, because `Canvas::new("")` is
762 + // `Canvas::default()`: an item page has no creator markup and the
763 + // scope is still what carries the stylesheet.
764 + let args = args.iter().map(self::arg).collect::<Result<Vec<_>>>()?;
765 + let canvas = accrete(
766 + body,
767 + Container::Canvas,
768 + &quote!(::quasi_router::screen::Canvas::new(#(#args),*)),
769 + )?;
770 + Ok(quote!(::quasi_router::Node::Canvas(::std::boxed::Box::new(#canvas))))
771 + }
735 772 Emission::Simple { member, args, body } => {
736 773 let args = args.iter().map(self::arg).collect::<Result<Vec<_>>>()?;
737 774 accrete(
@@ -67,6 +67,13 @@
67 67 /// screen wanting a tag standing on its own reaches `Node::token` through a
68 68 /// supplier, which is the remedy the deferred table already names, and
69 69 /// `project_analytics`'s `chip` is that supplier.
70 + ///
71 + /// `canvas` is the second exception and is the last entry for that reason:
72 + /// `Canvas` is a builder type of its own, the way `Image` is, so the member's
73 + /// body accretes onto the canvas and the emitter wraps the variant afterwards.
74 + /// `custom_page` is the site -- a creator's opaque markup under the scope its
75 + /// stylesheet was rewritten for, with the platform's own blocks drawn inside
76 + /// it.
70 77 const NODE_MEMBERS: &[&str] = &[
71 78 "text",
72 79 "page",
@@ -80,6 +87,7 @@
80 87 "rich",
81 88 "literal",
82 89 "picture",
90 + "canvas",
83 91 ];
84 92
85 93 /// The arrangements a screen may be laid out in.
@@ -108,6 +116,14 @@
108 116 const FLAGS: &[&str] = &["must_use", "inline"];
109 117
110 118 /// The verbs, and whether each addresses something.
119 + ///
120 + /// **`leaving` said it addressed nothing and it addresses a url.** Same class
121 + /// of mistake as `filling` and `copying` above, and it survived for the same
122 + /// reason: no declared screen had used the word, so the table was wrong with
123 + /// nothing looking. `custom_page` is the site -- every link off a custom page
124 + /// replaces it rather than opening a tab, which is what `Action::leaving(url)`
125 + /// says. Read the signature, not the neighbours: `local` and `back` take
126 + /// nothing and `leaving` sits between them.
111 127 const VERBS: &[(&str, bool)] = &[
112 128 ("get", true),
113 129 ("post", true),
@@ -115,7 +131,7 @@
115 131 ("delete", true),
116 132 ("external", true),
117 133 ("local", false),
118 - ("leaving", false),
134 + ("leaving", true),
119 135 ("back", false),
120 136 ];
121 137