# Design decisions


## Design decisions (intentional - do not flag)

The following behaviors are deliberate; do not re-report them as bugs.

- **The Chart.js loader may sit in `<head>`, before the JS END marker.** `Export to Plain HTML` removes only the four HTML-comment BEGIN/END regions (HANDLED IDS, EMBEDDED COMMENTS, COMMENT UI, JS), which all live in `<body>`, and keeps the CSS region; a loader in `<head>` is outside those regions and survives. So the validator intentionally does NOT flag "loader before the JS END marker" - it only flags chart init that runs before the marker or before the loader.
- **`new Chart(` / guard detection is lexical, after blanking comments and (for the init) string literals - not a full JavaScript parse.** A `new Chart(` or a `typeof Chart` guard hidden entirely inside a template/regex construct, or a complete guard embedded inside a string literal, is an accepted residual: real init and real guards are never written that way.
- **A `<!--` inside chart-data JSON is an error even when the JSON is otherwise valid.** Chart data must escape `<` as `\u003C`; a raw `<!--` risks the legacy script-comment parsing, so it is flagged regardless of JSON validity.
- **A self-closing `<script src=... />` is treated as "no loader".** `<script>` is not a void element, so `/>` is ignored and the tag swallows the following markup as (ignored) content - the page breaks. Failing closed (E3) is correct; the validator does not pretend a self-closed loader works.
- **Malformed markup that makes the HTML parser raise fails closed** with a single "could not be parsed" error, rather than running checks on partial parser state.
- **A `<canvas>` is treated as a Chart.js chart.** This skill's only sanctioned charting path is Chart.js (canvas based - see [Chart.js embedding and tooltips](charts-embedding.md)); it does not do raw/hand-rolled canvas drawing. So the presence of a `<canvas>` deliberately triggers the full Chart.js embedding checks (loader, chart-data JSON, init ordering, `cm-skip`, accessibility, network-failure guard). A canvas still needs a renderer: either the Chart.js loader OR an inline `getContext` draw satisfies that (E3), so a hand-drawn non-Chart.js canvas is accepted and only a canvas with neither a loader nor an inline draw is flagged. A document can also run `--layer-only` to skip the chart half entirely.
- **Layer region-marker checks stay line-oriented regex; element / id / attribute / script-body checks use the shared HTML parser (`_DocParser`).** Region markers are BEGIN/END comment lines, not elements, so a line regex is the right tool; everything that reads real DOM structure goes through the parser.
- **"four HTML-comment regions" in the Save-as-plain code is correct.** Of the five regions, four are HTML comments (HANDLED IDS, EMBEDDED COMMENTS, COMMENT UI, JS) and one (CSS) is a `/* */` CSS comment; Save-as-plain removes the four HTML-comment regions and keeps the CSS region intact so the plain copy stays styled.
- **A comment anchored on a link is opened via the hover bubble, not by clicking the link.** Clicking a highlighted link follows the link (by design); the `#hlBubble` affordance is the way to open its comment.
- **E5 compares document source order and does not model `type="module"` / `defer` execution timing.** A module or deferred chart-init placed in source before a classic loader technically runs after it, yet E5 flags "init before the loader". The recipe uses classic synchronous inline init after the loader, so this never occurs in skill-emitted docs; module/deferred chart init is discouraged, so flagging it is acceptable.
- **`new Chart(` / guard detection models regex literals but not template-literal substitutions.** The single-pass lexer treats a whole `` `...` `` template (including any executable `${ ... }` substitution) as a string and blanks it. It DOES model `/.../` regex literals (character classes included, and division is told apart from a literal by a prev-significant-token heuristic that resolves ambiguity to division), so a quote or backtick inside a regex cannot open a phantom string that blanks the rest of the script, and a `new Chart(` or a guard written inside a regex is correctly not counted. Two residuals remain and are accepted: a `new Chart(` written inside a `${}` substitution is not detected, and a regex literal placed directly after a `}` is read as division (a statement block and an object literal are indistinguishable there), so a backtick inside THAT regex can still blank what follows. Init is never written either way (plain strings, regex literals, both comment styles, and `<script src>` dead bodies ARE handled).


