Repository navigation
Description
Problem
In the id web editor, the image node's parseDOM converts the width/height attributes with a bare Number() and the attrs declare no validation, so non-integer dimensions are stored verbatim and then silently dropped (or reinterpreted) downstream:
pkgs/id/web/src/editor.ts:145-146—width: el.getAttribute("width") ? Number(el.getAttribute("width")) : null(same forheight). The image attrs ateditor.ts:125-126are{ default: null }with novalidate, unlikeordered_list'sorderwhich at least declaresvalidate: "number"(and still lets NaN through — id(web/editor): ordered_list parseDOM bare Number() lets NaN/fractional start through — pasted lists silently renumber from 1 on save #2005).pkgs/id/web/src/editor.ts:157-158—toDOMemits the attr onlyif (node.attrs.width):NaNand0are falsy, so they vanish; a fraction (2.5) or negative (-5) is emitted as the invalid attributewidth="2.5"/width="-5".pkgs/id/src/web/markdown.rs:1953-1954— on save,json["attrs"]["width"].as_u64()isNonefor a fraction, a negative, and forNaN(which serialises to JSONnull), so the dimension is dropped from the saved markdown with no error. The Rust-side HTML parse (markdown.rs:1208-1215) accepts only a pureu64, so the editor is the permissive side of an asymmetric pair.pkgs/id/web/src/image-node-view.ts:58-62— the node view setsimg.style.width =${width}px``;NaNpx/ `-5px` are invalid and silently ignored by the browser.
Verified this run (2026-10-28, main 38f1f00f)
Probe on the laptop (~/git/fleet/probe-2026-10-28-laneB-imgdim/, the shipped getAttrs conversion copied verbatim; editor.ts sha256 4340aef4… identical on laptop and sandbox main), with the toDOM truthiness check and the save-side as_u64() semantics modelled from the shipped code:
- Control
width="200"→ parseDOM200, toDOM"200", saved200✓ width="200px"→NaN→ toDOM omits the attribute, savednull— dimension silently lostwidth="50%"→NaN→ same silent losswidth="2.5"→2.5→ toDOM emitswidth="2.5", savednull— lost on savewidth="-5"→-5→ toDOM emitswidth="-5", savednull— lost on savewidth="abc"→NaN→ silently lostwidth="0x10"→16andwidth="1e3"→1000— silently reinterpreted as values the author never wrote (an HTML dimension attribute is a leading-digits value, not a JS numeric literal)
Pasted web content is the realistic source: images in copied HTML routinely carry width="200px", percentage widths, or fractional/negative junk from CMS markup, and every one of those pastes loses its sizing on the next save without any signal.
Why it matters
This is the same silent-coercion class as #2005 (ordered-list start) in the adjacent node of the same file, but with a different failure shape: the list renumbers, the image loses its dimensions (or gains ones nobody typed, 0x10 → 16). The repo's own strict parsers show the intended pattern — parseWorldSeed (web/src/world-seed.ts, #707/#832) accepts only decimal digits, and parseProxyPortValue does the same for the bin proxies (#483). The image attrs are an unhardened spot the earlier passes missed.
Acceptance criteria
- Image
width/heightfromparseDOMare either a non-negative integer ornull: a value that is not a plain run of decimal digits (e.g.200px,50%,2.5,-5,abc,0x10,1e3) never reaches the node attrs asNaN, a fraction, a negative, or a reinterpreted number — it is dropped tonullat parse time (the triage-pinned contract may instead take the HTML leading-digits value, but it must be one documented behaviour, applied identically towidthandheight). - The editor-side result agrees with the save side: any dimension the editor keeps survives
markdown.rs'sas_u64()round-trip, and any it drops is dropped at parse time, not discovered missing after save. - Regression tests (web/src/editor.test.ts or a sibling) cover at least:
"200"(kept),"200px","50%","2.5","-5","0x10"— asserting the resulting attrs; existing editor tests still pass. - The fix is scoped to the image node (the ordered-list site is id(web/editor): ordered_list parseDOM bare Number() lets NaN/fractional start through — pasted lists silently renumber from 1 on save #2005's, already filed).
Filed by new-issue-creator-code-b. Related: #2005 (same file, same bare-Number() class, ordered_list node), #893 (image parseDOM link handling).
Activity
developing-today commentedon Oct 29, 2026
CODE-931
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
125 remaining items
dezren39 commentedon Nov 2, 2026
agent-note:v1
state: parked
task: 5066
lane: a (repo-queue-worker-shift)
note: PR #4201 verified this shift: targeted editor tests 117/117 pass on the laptop @ 66aea20; full pkgs/id/web suite 589 passed with only the 4 pre-existing main failures (proven identical on clean base 77970eb; tracked by #4103 and #3243). Codex review on 66aea20: no findings. Parked 20m because basic+native CI checks remain QUEUED (runner delay, run 41394912384) after a 5-minute poll. Resume: merge PR #4201 when checks green, close #2010, complete task 5066 as fixed_merged.
dezren39 commentedon Nov 2, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
fix(id): validate pasted image width/height in parseDOM (#2010) (#4201)
dezren39 commentedon Nov 2, 2026
🤖 Agent note · done