Skip to main content

MARKUP_JS

Constant MARKUP_JS 

Source
pub const MARKUP_JS: &str = "// Rendered markup, for the one value that is parsed as HTML.\n//\n// **Its own module, and that is a size decision rather than a tidiness\n// one** \u{2014} the same decision `foreign.js` records. `Prose` is the only\n// element with a `Slot::Rendered`, and a program can go its whole life\n// without writing one; \u{a7}16.3.1 promises a bundle ships nothing it does\n// not use. Left in `dom.js` these bytes were downloaded by every page\n// ever served, including one with no markup in it at all, which is a\n// fixed cost paid for an optional feature. `Bundle::runtime` already\n// computes a transitive import closure, so this is that existing\n// mechanism applied once more and not a new exemption from the size\n// gate: a null program must not reach this file, and a program with a\n// `Prose` must.\n//\n// It needs the reactivity core and nothing else \u{2014} the node is handed in,\n// as it is for a foreign \u{2014} so linking it costs a program `signal.js` it\n// already had.\n\nimport { effect } from \'./signal.js\';\n\n/**\n * Replace an element\'s content with parsed HTML.\n *\n * **This is the only function in the runtime that parses HTML, and it is\n * the only assignment to `innerHTML` anywhere in it.** Everything else a\n * program renders reaches the DOM through `nodeValue`, `setAttribute`,\n * `.value` or `.checked`, none of which parses (spec \u{a7}16.3.5). Adding\n * this narrows that claim rather than dropping it, and the narrowing is\n * carried by the compiler, not by anything here:\n *\n * * The emitter calls this from one place \u{2014} `Slot::Rendered`, which only\n *   `Prose` has.\n * * `Prose`\'s argument must have type `Markup`, which `Text` is not and\n *   does not convert to.\n * * The one producer of a `Markup` is `build markdown`, which runs inside\n *   the compiler over a file in the project directory, and which escapes\n *   every raw HTML span and rewrites every non-http(s) URL before\n *   returning.\n *\n * So this function trusts its argument, and the reason that is sound is\n * that no user-supplied value can ever become one. It performs no\n * sanitising of its own: a sanitiser here would be a second, weaker copy\n * of a guarantee the type system already makes, and the failure mode of\n * two disagreeing checks is worse than one.\n */\nexport function markup(node, value) {\n  node.innerHTML = value === null || value === undefined ? \'\' : String(value);\n}\n\n/**\n * The same, re-parsed whenever the value changes.\n */\nexport function bindMarkup(node, getter) {\n  effect(() => {\n    const value = typeof getter === \'function\' ? getter() : getter;\n    const next = value === null || value === undefined ? \'\' : String(value);\n    if (node.innerHTML !== next) node.innerHTML = next;\n  });\n}\n";
Expand description

The Prose render path — the one function in the runtime that parses HTML. Its own module so a program with no Prose does not ship it.