Edit9Docs
The language

Conventions

The rules that are true of e9-HTML and are in no schema — published verbatim from the engine, because three blind runs found them by getting them wrong.

Everything below is served by the engine itself, as the notes beside the Block vocabulary. They are not a restatement of the schemas: the schemas document themselves, and the Block reference prints them. These are the things that are true and that no schema can say — the ones three blind evaluation runs discovered by getting them wrong.

They are printed here verbatim rather than rewritten. A second wording of a rule is a second rule, and the two drift.

  • Every parameter is written as an HTML attribute, so every value is a string.
  • There are no comments. <!-- … --> is refused, and so are doctype, CDATA and processing instructions — a document is Blocks and nothing else. Say why you did something in <e9-brief>, which travels with the design, or name a node with e9-name.
  • A Block flows inside its parent by default and becomes absolutely positioned as soon as x or y is set.
  • Paint order is document order: later siblings draw on top. There is no z-index.
  • Colours are #rgb or #rrggbb only — no rgb(), no colour names. The one place a colour carries opacity is a gradient stop, where "#[email protected]" is allowed and "@0" is fully transparent; that is how a scrim over a photograph fades out instead of ending on a visible edge.
  • Layout comes from <e9-stack>, whose parameter names are shortened from CSS: direction, align, justify, and values like "between" rather than "space-between".
  • Use <e9-group> to assemble several Blocks into one thing that moves, rotates and clips as a unit; use <e9-stack> to distribute things along an axis. block.group builds one out of Blocks that already exist and rebases their coordinates for you, so grouping never moves the picture.
  • Lock, visibility and name are reserved attributes — e9-locked, e9-hidden and e9-name — and they are deliberately not Block parameters, so no Block declares them and block.setParam will refuse them. Use node.setLocked, node.setHidden and node.setName instead.
  • A locked node refuses every command except node.setLocked, and so does everything inside it — including deleting the group it sits in. The lock is somebody's decision, not a bug: you may unlock it, but do it in its own command and say so in the note. e9_get_doc marks every locked and hidden node, so you can see it before you try.
  • A hidden node still exists, keeps its parameters and its place in paint order, and simply is not drawn. Hide a variation rather than deleting it when you might want it back.
  • For a glow, set fade on a shape rather than lowering opacity — a translucent disc still has a visible edge.
  • Shapes the vocabulary cannot draw — arrows, curves, icons, logos — come in as SVG: write the markup with e9_add_asset, then place it with <e9-image>. Call e9_list_assets to see what is already available.
  • Photography, textures and brush lettering are source material and are never drawn by the engine. Make or fetch the picture outside it, then hand e9_add_asset the bytes as `base64` and place the result with <e9-image>; `from` only reaches files already inside the workspace.
  • Text is set in one or more of the bundled faces — font="Montserrat" for a single-script run, font="Montserrat, 马善政毛笔楷书" where a run mixes them — and the list is closed: Liberation Sans, Liberation Serif, Liberation Mono, Playfair Display, Inter, Bebas Neue, JetBrains Mono, Montserrat, Nunito, Roboto Slab, Libre Baskerville, Cormorant Garamond, Barlow Condensed, Oswald, Poppins, DM Sans, Work Sans, Space Grotesk, Quicksand, Comfortaa, Chakra Petch, Lora, Merriweather, EB Garamond, Bodoni Moda, Space Mono, IBM Plex Mono, 站酷小薇, Anton, Dancing Script, Caveat, 马善政毛笔楷书, Permanent Marker, Orbitron, Fredoka, Press Start 2P, Archivo Black, Staatliches, Bungee, Alfa Slab One, Abril Fatface, DM Serif Display, Lobster, Pacifico, Great Vibes, Amatic SC, VT323, UnifrakturMaguntia, Roboto, Open Sans, Raleway, Rubik, Lato, Black Ops One, Saira Stencil One, Big Shoulders Stencil Display, Bungee Outline, Bungee Shade, 思源黑体, 본고딕, 源ノ角ゴシック, 思源宋体, 본명조, 源ノ明朝, 思源等宽, 본고딕 등폭, 源ノ角ゴシック等幅, M PLUS Rounded 1c, 站酷庆科黄油体, 검은고딕, Dela Gothic One, 志莽行书, 나눔손글씨 펜, Yomogi, 나눔손글씨 붓, 佑字肅, 站酷快乐体, 주아, 霞鹜文楷, 도현, 고운바탕, しっぽり明朝, ドットゴシック16, 得意黑, 朱雀仿宋, Pretendard, 나눔고딕, Zen Kaku Gothic New, Zen Maru Gothic, Zen Old Mincho, Klee One, Rampart One. A face this engine does not ship would resolve against whatever fonts the rendering machine has, so it is refused rather than approximated. Any script no named face serves is completed with the shared 黑体 or 宋体, so a Latin-only list still renders Chinese; glyph-coverage refuses a character none of them can draw rather than letting it fall back, naming the faces that can. Read a face's own note before choosing it: the name is a face you may have opinions about, and the note is what it is for here.
  • Not every face has two weights or an italic. The display faces were mostly drawn once — weight="700" or italic="true" on one of them is refused by name, and the refusal points at a face that has it. A face is drawn for the scripts it is drawn for: the Latin ones set Latin, the Chinese display faces set hanzi and several of them carry no kana at all, and a list that names one face per script you are setting is how a headline stays one typeface across them. Each face's own note says which script it is for.
  • For a column of Chinese reading top to bottom, set vertical="true" on <e9-text> — never rotate. A rotation turns the glyphs on their side, and it cannot make successive columns run right to left, which is half of what vertical setting is.
  • Artwork that arrived baked onto its own ground — brushed lettering, a paper grain, an illustration on white — goes down with blend="multiply" so it composites onto the page instead of covering what is beneath it as a rectangle. multiply keeps the darker of the two, so it only erases a ground that is white: commission the asset on white, or leave blend alone.
  • italic="true" sets Latin in a bundled italic face. There is no italic Chinese face to bundle, so a Chinese run asked to slant would be slanted by the browser rather than drawn — the synthesized-style check warns about that by name. Emphasise Chinese with a different weight or face instead.
  • blur on <e9-image>, <e9-shape> or <e9-group> is depth of field — it softens the Block itself, and its edges with it, so oversize a blurred full-bleed image past the canvas and set bleed. backdrop-blur on a shape or group softens what is behind instead and leaves the Block sharp: that is the frosted panel, and it needs a translucent fill in front of it or the panel just covers what it blurred.
  • Line breaks are controllable and do not need a binary search on max-width: &#10; forces a break, &nbsp; keeps two words together, &shy; permits one inside a long word, and wrap="balance" evens out the lines of a heading.
  • To lift a panel or card off the surface behind it, set shadow on <e9-shape> or <e9-group> — fade only makes a radial glow, which cannot do it for a rectangle.

The same list is what e9_list_blocks returns to an agent, and what the editor's inspector renders its rows from. If you are reading this to write a document by hand, read it once end to end: most of it is a sentence that saves a rejection.