Skip to content

Add HtmlNode standard library type (#311)#363

Merged
aallan merged 6 commits into
mainfrom
feat/html-type
Mar 26, 2026
Merged

Add HtmlNode standard library type (#311)#363
aallan merged 6 commits into
mainfrom
feat/html-type

Conversation

@aallan

@aallan aallan commented Mar 26, 2026

Copy link
Copy Markdown
Owner

Summary

Parse HTML responses from Http.get, extract structured data, query by CSS selector.

HtmlNode ADT

data HtmlNode {
  HtmlElement(String, Map<String, String>, Array<HtmlNode>),
  HtmlText(String),
  HtmlComment(String)
}

5 built-in operations

Function Signature Implementation
`html_parse` `String -> Result<HtmlNode, String>` Host import (Python `html.parser`)
`html_to_string` `HtmlNode -> String` Host import
`html_query` `HtmlNode, String -> Array` Host import (CSS selector subset)
`html_text` `HtmlNode -> String` Host import (recursive text extraction)
`html_attr` `HtmlNode, String -> Option` Prelude (pure Vera via match + map_get)

CSS selector support

Tag name (`div`), class (`.foo`), ID (`#bar`), attribute (`[href]`), descendant (`div p`).

Architecture

  • Normal ADT with pattern matching (same as Json, not opaque handle)
  • Lenient parsing (like browsers) — malformed HTML produces best-effort tree
  • `Map<String, String>` for attributes — natural lookup via `map_get`
  • Conditional prelude injection — only when code references HtmlNode
  • Browser runtime — `DOMParser` for parsing, tree walker for queries

New files

File Purpose
`vera/wasm/html_serde.py` WASM memory marshalling for HtmlNode ADT
`tests/conformance/ch09_html.vera` 8-function conformance test
`examples/html.vera` Extract links and count headings from HTML

Documentation

  • Spec 9.7.4: full API docs
  • SKILL.md: HtmlNode section with examples
  • README.md: HTML code example
  • ROADMAP.md: HTML standard library type #311 marked complete
  • Version bumped to v0.0.100

Closes #311.

Test plan

  • All 3,045 tests pass (19 new: 10 checker + 9 codegen)
  • All 21 pre-commit hooks pass
  • 63 conformance programs pass
  • 29 examples pass check + verify
  • mypy clean
  • CI passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • HTML support: new HtmlNode type and built-ins for lenient parsing, serialization, CSS-selector queries, text extraction and attribute lookup.
  • Documentation

    • README, spec, roadmap and docs updated with HTML reference, examples and usage notes.
  • Tests

    • Added conformance, unit and integration tests for HTML; test and example counts updated.
  • Chores

    • Version bumped to 0.0.100, changelog updated and validation/allowlist entries adjusted.

HtmlNode ADT: HtmlElement(String, Map<String, String>, Array<HtmlNode>),
HtmlText(String), HtmlComment(String). Four host imports (html_parse,
html_to_string, html_query, html_text) plus one prelude function
(html_attr). Lenient parsing via Python html.parser, CSS selector
subset for queries. Browser runtime uses DOMParser.

New conformance test ch09_html (63 programs). New example html.vera.
19 new unit tests (10 checker + 9 codegen). Version bump to v0.0.100.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@coderabbitai

coderabbitai Bot commented Mar 26, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new HtmlNode ADT and five html_* built-ins (parse, to_string, query, text, attr); wires prelude injection, environment registration, type/wasm inference, codegen host imports, WASM marshalling, browser runtime host implementations, tests, manifests, docs and release metadata for v0.0.100.

Changes

Cohort / File(s) Summary
Release & metadata
CHANGELOG.md, pyproject.toml, vera/__init__.py
Bump to v0.0.100; add release entry and comparison links; update package and package version.
Specification & docs
spec/09-standard-library.md, SKILL.md, README.md, ROADMAP.md
Document HtmlNode ADT, five built-ins, behaviour and examples; update roadmap and skill docs to include HTML.
Language environment & prelude
vera/environment.py, vera/prelude.py
Register HtmlNode constructors and html_* signatures; conditional prelude injection for HtmlNode and html_attr.
Codegen & compilation pipeline
vera/codegen/api.py, vera/codegen/assembly.py, vera/codegen/core.py, vera/codegen/compilability.py, vera/codegen/functions.py, vera/codegen/modules.py, vera/codegen/monomorphize.py
Track HTML op usage, propagate into CompileResult, add assembly host-imports, detect HTML builtins in scans, add monomorphize/type mappings and whitelist host names.
WASM backend & serde
vera/wasm/calls.py, vera/wasm/context.py, vera/wasm/inference.py, vera/wasm/html_serde.py
Translate html_* calls to host imports, add wasm-type inference mappings and context tracking, and implement WASM marshalling/unmarshalling for HtmlNode.
Browser runtime
vera/browser/runtime.mjs
Add JS host-import implementations: DOM parsing, dom↔ADT conversion, marshalling helpers, selector matching, text extraction, serialization, and conditional import registration.
Tests & manifests
tests/conformance/manifest.json, tests/test_checker.py, tests/test_codegen.py, tests/test_readme.py, tests/test_verifier.py
Add conformance entry ch09_html; tests for type-checking, runtime behaviour and wasm imports; update README block counts and verification totals.
Scripts & validation allowlists
scripts/check_readme_examples.py, scripts/check_skill_examples.py, scripts/check_spec_examples.py
Adjust allowlist line numbers and add HTML-related FUTURE/FRAGMENT entries to skip parsing of doc snippets.
Docs & testing matrices
TESTING.md, CLAUDE.md
Update reported unit, conformance and example counts to reflect new tests/examples.
Runtime/WASM helpers
vera/wasm/html_serde.py, vera/browser/runtime.mjs, vera/codegen/api.py
New WASM marshalling layer for recursive HtmlNode; host-side JS/Python helpers and Map store integration for element attributes.

Sequence Diagram(s)

sequenceDiagram
    participant Code as Vera code
    participant Wasm as WASM module
    participant Host as Browser / JS host
    participant Heap as WASM heap / Map store

    Code->>Wasm: call html_parse(ptr,len)
    Wasm->>Host: import "vera.html_parse"(ptr,len)
    Host->>Host: DOMParser.parseFromString (lenient)
    Host->>Host: build JS HtmlNode ADT
    Host->>Heap: writeHtml(node) -> handle_ptr (alloc strings/attrs/children)
    Host-->>Wasm: return Ok(handle_ptr) / Err(err_ptr)

    Code->>Wasm: call html_query(handle, sel_ptr)
    Wasm->>Host: import "vera.html_query"(handle, sel_ptr)
    Host->>Host: perform selector match (limited CSS subset)
    Host->>Heap: writeHtml for each match -> array_ptr,len
    Host-->>Wasm: return (array_ptr, count)

    Code->>Wasm: call html_text(handle)
    Wasm->>Host: import "vera.html_text"(handle)
    Host->>Host: recursively extract text
    Host->>Heap: alloc string -> ptr,len
    Host-->>Wasm: return (ptr, len)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

compiler, tests, spec, ci, docs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add HtmlNode standard library type (#311)' clearly and concisely describes the main change: introducing a new HtmlNode ADT with associated built-in operations.
Linked Issues check ✅ Passed PR delivers all core coding objectives from #311: HtmlNode ADT with Element/Text/Comment variants, html_parse/html_to_string/html_query/html_text host imports, html_attr as prelude combinator, CSS selector support, and host bindings via Python html.parser and browser DOMParser.
Out of Scope Changes check ✅ Passed All changes are in scope for #311: HTML type implementation, test coverage, documentation updates for v0.0.100, and prelude injection logic. No unrelated refactoring or feature creep detected.
Docstring Coverage ✅ Passed Docstring coverage is 82.65% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/html-type

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Mar 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.90750% with 224 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.32%. Comparing base (22b6a71) to head (95f701f).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
vera/browser/runtime.mjs 15.15% 196 Missing ⚠️
vera/wasm/inference.py 50.00% 9 Missing ⚠️
vera/prelude.py 77.77% 6 Missing ⚠️
vera/codegen/api.py 96.15% 5 Missing ⚠️
vera/wasm/calls.py 92.00% 4 Missing ⚠️
vera/wasm/html_serde.py 95.34% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #363      +/-   ##
==========================================
- Coverage   91.22%   90.32%   -0.90%     
==========================================
  Files          48       49       +1     
  Lines       18429    18999     +570     
  Branches      215      219       +4     
==========================================
+ Hits        16811    17161     +350     
- Misses       1614     1834     +220     
  Partials        4        4              
Flag Coverage Δ
javascript 50.73% <15.15%> (-4.35%) ⬇️
python 95.30% <91.81%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_verifier.py (1)

1590-1603: 🧹 Nitpick | 🔵 Trivial

Update the stale docstring to reflect the new expected counts.

The docstring on Line 1591 states "145 T1 / 15 T3 without module resolution", but the assertions now expect 167 T1 / 20 T3 / 187 total. This discrepancy will mislead future reviewers.

📝 Suggested docstring update
     def test_overall_tier_counts(self) -> None:
-        """All examples together: 145 T1 / 15 T3 without module resolution."""
+        """All examples together: 167 T1 / 20 T3 without module resolution."""
         t1 = t3 = total = 0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_verifier.py` around lines 1590 - 1603, Update the docstring on
test_overall_tier_counts to match the current expected totals: change "145 T1 /
15 T3 without module resolution." to reflect "167 T1 / 20 T3 / 187 total" (or
equivalent wording); locate the test by the function name
test_overall_tier_counts and its usage of EXAMPLES_DIR, parse_to_ast, typecheck,
verify and ensure the new docstring matches the assertions for t1, t3, and
total.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_checker.py`:
- Around line 2155-2193: Add negative type tests for the HTML built-ins: update
the existing test methods (test_html_query, test_html_text_fn, test_html_attr)
to include _check_err cases that pass wrong argument types. For html_query add
one case where the first arg is not a HtmlNode (e.g. 42) and one where the
selector is not a String (e.g. 42) using _check_err(..., "type"); for html_text
add a case where the arg is not a HtmlNode (e.g. "not a node") using
_check_err(..., "type"); for html_attr add a case where the node arg is wrong
and a case where the attribute name arg is not a String (e.g. 42) using
_check_err(..., "type"). Ensure each new test mirrors the existing test
structure and uses the same return types (Array<HtmlNode>, String,
Option<String>) in the checked snippet.

In `@tests/test_codegen.py`:
- Around line 9171-9196: Expand WAT import-gating tests to cover each HTML
builtin individually: add per-operation assertions like in
test_html_parse_wat_import for html_to_string, html_query, and html_text (e.g.,
new tests similar to test_html_parse_wat_import that compile a tiny program
calling each builtin and assert the corresponding string appears in result.wat)
and extend test_html_no_imports_when_unused to verify each of '"html_parse"',
'"html_to_string"', '"html_query"', and '"html_text"' are absent when not used;
follow the existing JSON/Http per-op test patterns and reuse the _compile_ok
flow and assertion style from test_html_parse_wat_import to ensure sibling
absence checks are included.
- Around line 9105-9118: The current test_html_query_by_tag only exercises tag
selectors ("p"); extend this test (or add sibling tests) to cover class
selectors (e.g., elements with class="..."), ID selectors (e.g., "#id"),
attribute-presence selectors (e.g., "[attr]"), and descendant selectors (e.g.,
"div p") by parsing HTML with representative nodes via html_parse and asserting
html_query returns expected counts for each selector; update assertions to
include calls to html_query(`@HtmlNode.0`, "<selector>") for each selector type
and match the Ok/Err pattern used in the existing test so failures surface for
html_query, html_parse, and HtmlNode handling.

In `@vera/browser/runtime.mjs`:
- Around line 1775-1783: The htmlToString serializer builds attrStr from
node.attrs without escaping special characters, so attribute values containing &
or " (and other special chars) can break output; update htmlToString to escape
attribute values before concatenation (e.g., implement a small helper like
escapeAttr and call it when iterating node.attrs to replace & with &amp;, " with
&quot;, < with &lt; and > with &gt;), then use the escaped value when appending
to attrStr (refer to htmlToString, attrStr and node.attrs to locate the change).

In `@vera/codegen/api.py`:
- Around line 1676-1697: The serializer _html_to_string_py must HTML-escape node
text, attribute values and comment content before emitting strings: in the
"text" branch escape &, <, >; when building attr_str escape &, <, > and
double-quote characters in attribute values; in the "comment" branch ensure the
content does not contain the sequence "-->" (or replace/encode it) before
wrapping in <!-- -->; implement these escapes where _html_to_string_py reads
node.get("content", "") and where it iterates attrs.items() so round-trip
serialisation produces valid HTML.

---

Outside diff comments:
In `@tests/test_verifier.py`:
- Around line 1590-1603: Update the docstring on test_overall_tier_counts to
match the current expected totals: change "145 T1 / 15 T3 without module
resolution." to reflect "167 T1 / 20 T3 / 187 total" (or equivalent wording);
locate the test by the function name test_overall_tier_counts and its usage of
EXAMPLES_DIR, parse_to_ast, typecheck, verify and ensure the new docstring
matches the assertions for t1, t3, and total.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3eaa0faf-3cf1-4f5a-b4ea-798586043976

📥 Commits

Reviewing files that changed from the base of the PR and between 22b6a71 and bd18b77.

⛔ Files ignored due to path filters (7)
  • docs/index.html is excluded by !docs/**
  • docs/index.md is excluded by !docs/**
  • docs/llms-full.txt is excluded by !docs/**
  • docs/llms.txt is excluded by !docs/**
  • docs/sitemap.xml is excluded by !docs/**
  • examples/html.vera is excluded by !**/*.vera
  • tests/conformance/ch09_html.vera is excluded by !**/*.vera
📒 Files selected for processing (31)
  • CHANGELOG.md
  • CLAUDE.md
  • README.md
  • ROADMAP.md
  • SKILL.md
  • TESTING.md
  • pyproject.toml
  • scripts/check_readme_examples.py
  • scripts/check_skill_examples.py
  • scripts/check_spec_examples.py
  • spec/09-standard-library.md
  • tests/conformance/manifest.json
  • tests/test_checker.py
  • tests/test_codegen.py
  • tests/test_readme.py
  • tests/test_verifier.py
  • vera/__init__.py
  • vera/browser/runtime.mjs
  • vera/codegen/api.py
  • vera/codegen/assembly.py
  • vera/codegen/compilability.py
  • vera/codegen/core.py
  • vera/codegen/functions.py
  • vera/codegen/modules.py
  • vera/codegen/monomorphize.py
  • vera/environment.py
  • vera/prelude.py
  • vera/wasm/calls.py
  • vera/wasm/context.py
  • vera/wasm/html_serde.py
  • vera/wasm/inference.py

Comment thread tests/test_checker.py
Comment thread tests/test_codegen.py
Comment thread tests/test_codegen.py
Comment thread vera/browser/runtime.mjs
Comment thread vera/codegen/api.py
- Add 5 wrong-type checker tests (html_query, html_text, html_attr)
- Add per-operation WAT import tests (html_to_string, html_query, html_text)
- Add CSS selector tests (class, ID, descendant)
- Fix HTML escaping in api.py: escape text content, attribute values,
  and comment dashes in html_to_string serializer
- Fix browser runtime htmlToString: add escapeHtml/escapeAttr helpers
- Fix verifier docstring to match actual tier counts
- Fix doc counts (3,056 tests)

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
tests/test_codegen.py (2)

9222-9266: ⚠️ Potential issue | 🟠 Major

Attribute-presence selector coverage is still missing.

The feature contract includes attribute-presence selectors, but current selector tests cover tag/class/id/descendant only. Please add a [attr] case.

🧪 Proposed selector test addition
+    def test_html_query_attribute_presence(self) -> None:
+        """html_query with attribute-presence selector."""
+        source = '''
+public fn main(-> `@Int`)
+  requires(true) ensures(true) effects(pure)
+{
+  let `@Result`<HtmlNode, String> =
+    html_parse("<div><a href=\\"u\\">x</a><a>y</a></div>");
+  match `@Result`<HtmlNode, String>.0 {
+    Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "[href]")),
+    Err(`@String`) -> 0
+  }
+}
+'''
+        assert _run(source) == 1

As per coding guidelines: “DO flag … missing edge cases for new compiler features”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 9222 - 9266, Add a new test method
alongside
test_html_query_by_class/test_html_query_by_id/test_html_query_descendant that
exercises attribute-presence selectors (e.g., name it
test_html_query_attribute_presence); create a source string that calls
html_parse on HTML containing an element with an attribute (like <div
data-foo="x"> or <div data-foo></div>) plus another element without it, then
match the Result and call array_length(html_query(`@HtmlNode.0`, "[data-foo]"))
and assert _run(source) == 1 to verify the selector returns only the element
with the attribute.

9195-9220: ⚠️ Potential issue | 🟠 Major

html_query import-gating is not being proven in isolation.

test_html_query_wat_import currently calls html_parse, so it cannot verify that html_query alone gates imports correctly. Please mirror the JSON/Http per-op pattern by asserting sibling absence for query-only usage.

🧪 Proposed test tightening
     def test_html_query_wat_import(self) -> None:
         """html_query generates a WASM host import."""
         source = """
 public fn main(-> `@Int`)
   requires(true) ensures(true) effects(pure)
-{
-  let `@Result`<HtmlNode, String> = html_parse("<p>x</p>");
-  match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")),
-    Err(`@String`) -> 0
-  }
-}
+{ array_length(html_query(HtmlText("x"), "p")) }
 """
         result = _compile_ok(source)
         assert '"html_query"' in result.wat
+        assert '"html_parse"' not in result.wat
+        assert '"html_to_string"' not in result.wat
+        assert '"html_text"' not in result.wat

Based on learnings: per-operation import-gating tests in tests/test_codegen.py for JSON/Http require used import presence and sibling import absence.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 9195 - 9220, Update
test_html_query_wat_import so it does not call html_parse: change the source to
invoke html_query directly with an HtmlNode literal (analogous to test_html_text
using HtmlText("hello")), then assert '"html_query"' is in result.wat and assert
'"html_parse"' is not in result.wat; refer to the test function name
test_html_query_wat_import and the symbols html_query and html_parse to locate
and modify the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9222-9266: Add a new test method alongside
test_html_query_by_class/test_html_query_by_id/test_html_query_descendant that
exercises attribute-presence selectors (e.g., name it
test_html_query_attribute_presence); create a source string that calls
html_parse on HTML containing an element with an attribute (like <div
data-foo="x"> or <div data-foo></div>) plus another element without it, then
match the Result and call array_length(html_query(`@HtmlNode.0`, "[data-foo]"))
and assert _run(source) == 1 to verify the selector returns only the element
with the attribute.
- Around line 9195-9220: Update test_html_query_wat_import so it does not call
html_parse: change the source to invoke html_query directly with an HtmlNode
literal (analogous to test_html_text using HtmlText("hello")), then assert
'"html_query"' is in result.wat and assert '"html_parse"' is not in result.wat;
refer to the test function name test_html_query_wat_import and the symbols
html_query and html_parse to locate and modify the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9b725188-97c0-4d5d-ada6-8f0d7b25e715

📥 Commits

Reviewing files that changed from the base of the PR and between bd18b77 and f987c0e.

📒 Files selected for processing (6)
  • TESTING.md
  • tests/test_checker.py
  • tests/test_codegen.py
  • tests/test_verifier.py
  • vera/browser/runtime.mjs
  • vera/codegen/api.py

6 new codegen tests: comment roundtrip, text escaping, attribute
value escaping, attribute presence selector, parsed attributes,
void elements. Fix doc counts (3,062 tests).

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
TESTING.md (2)

82-82: ⚠️ Potential issue | 🟡 Minor

Update stale conformance program count.

Line 82 still references "62 small, focused programs", but the Overview table at Line 11 and the directory structure comment at Line 120 both correctly state 63 programs after this PR adds ch09_html.vera.

📝 Proposed fix
-The conformance suite is a collection of 62 small, focused programs in `tests/conformance/` that systematically validate every language feature against the spec. Each program is self-contained, imports nothing, and tests one feature or a small group of related features.
+The conformance suite is a collection of 63 small, focused programs in `tests/conformance/` that systematically validate every language feature against the spec. Each program is self-contained, imports nothing, and tests one feature or a small group of related features.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` at line 82, Update the stale count string "62 small, focused
programs" in TESTING.md to "63 small, focused programs" so it matches the
Overview table and directory structure note (this is the phrase to search for
and replace; no code changes required beyond updating that text).

154-154: ⚠️ Potential issue | 🟡 Minor

Update stale parametrised test count.

The comment claims 305 tests, but the "Test Files" table at Line 76 correctly shows test_conformance.py now has 315 tests (63 conformance programs × 5 test levels each). The comment predates even the previous count of 310.

📝 Proposed fix
-# Via pytest (parametrized — 305 tests)
+# Via pytest (parametrized — 315 tests)
 pytest tests/test_conformance.py -v
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` at line 154, Update the stale test count in the header "Via
pytest (parametrized — 305 tests)" to reflect the current total of 315 tests
(derived from test_conformance.py having 63 programs × 5 levels = 315); locate
the header string "Via pytest (parametrized — 305 tests)" and change the
displayed number to 315 so it matches the Test Files table and the actual
parametrized tests for test_conformance.py.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)

9171-9221: ⚠️ Potential issue | 🟡 Minor

Tighten HTML per-operation import-gating tests for full isolation parity.

Line [9195] still couples html_query with html_parse, and the import-gating tests do not consistently assert sibling absence for all html_* imports in each per-op test. This can miss gating regressions.

Suggested test tightening
@@
     def test_html_parse_wat_import(self) -> None:
@@
         result = _compile_ok(source)
         assert '"html_parse"' in result.wat
+        assert '"html_to_string"' not in result.wat
+        assert '"html_query"' not in result.wat
+        assert '"html_text"' not in result.wat
@@
     def test_html_to_string_wat_import(self) -> None:
@@
         result = _compile_ok(source)
         assert '"html_to_string"' in result.wat
         assert '"html_parse"' not in result.wat
+        assert '"html_query"' not in result.wat
+        assert '"html_text"' not in result.wat
@@
     def test_html_query_wat_import(self) -> None:
@@
-{
-  let `@Result`<HtmlNode, String> = html_parse("<p>x</p>");
-  match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")),
-    Err(`@String`) -> 0
-  }
-}
+{ array_length(html_query(HtmlText("x"), "p")) }
 """
         result = _compile_ok(source)
         assert '"html_query"' in result.wat
+        assert '"html_parse"' not in result.wat
+        assert '"html_to_string"' not in result.wat
+        assert '"html_text"' not in result.wat
@@
     def test_html_text_wat_import(self) -> None:
@@
         result = _compile_ok(source)
         assert '"html_text"' in result.wat
         assert '"html_parse"' not in result.wat
+        assert '"html_to_string"' not in result.wat
+        assert '"html_query"' not in result.wat

Based on learnings: In tests/test_codegen.py, JSON/Http import-gating tests use per-operation checks with sibling-absence assertions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 9171 - 9221, Tests for per-operation HTML
import gating are leaking: test_html_query embeds html_parse and most tests
don't assert that other html_* imports are absent. Update each test
(test_html_parse_wat_import, test_html_to_string_wat_import,
test_html_query_wat_import, test_html_text_wat_import) so they only exercise the
single operation under test (e.g., make test_html_query stop calling html_parse
and instead construct an HtmlNode/HtmlText directly or use an API that doesn't
import html_parse) and add explicit sibling-absence assertions in every test:
when asserting the expected import (e.g., '"html_query"'), also assert the other
three imports ('"html_parse"', '"html_to_string"', '"html_text"') are not in
result.wat, and do the analogous checks in the other tests to ensure full
isolation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@TESTING.md`:
- Line 316: Update the stale example count in TESTING.md: change the table entry
that reads "All 27 `.vera` examples pass `vera check` + `vera verify`" to
reflect 29 examples (i.e., "All 29 `.vera` examples pass `vera check` + `vera
verify`"). Locate the table row referencing `check_examples.py` and update the
numeric count only so it matches the new examples/html.vera addition.

In `@tests/test_codegen.py`:
- Around line 9328-9349: The test test_html_parse_with_attributes currently uses
a vacuous assertion (assert result >= 0); update the test so it actually
verifies the attribute value by querying the parsed HTML and asserting the
"class" attribute equals "main" (or that its length is 4). Concretely, in the
source snippet use html_query to select the div node returned by html_parse,
call html_attr on that node for "class", and replace the final assert with a
concrete check (e.g. assert attr == "main" or assert string_length(attr) == 4)
referencing the symbols html_parse, html_query, and html_attr.

---

Outside diff comments:
In `@TESTING.md`:
- Line 82: Update the stale count string "62 small, focused programs" in
TESTING.md to "63 small, focused programs" so it matches the Overview table and
directory structure note (this is the phrase to search for and replace; no code
changes required beyond updating that text).
- Line 154: Update the stale test count in the header "Via pytest (parametrized
— 305 tests)" to reflect the current total of 315 tests (derived from
test_conformance.py having 63 programs × 5 levels = 315); locate the header
string "Via pytest (parametrized — 305 tests)" and change the displayed number
to 315 so it matches the Test Files table and the actual parametrized tests for
test_conformance.py.

---

Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9171-9221: Tests for per-operation HTML import gating are leaking:
test_html_query embeds html_parse and most tests don't assert that other html_*
imports are absent. Update each test (test_html_parse_wat_import,
test_html_to_string_wat_import, test_html_query_wat_import,
test_html_text_wat_import) so they only exercise the single operation under test
(e.g., make test_html_query stop calling html_parse and instead construct an
HtmlNode/HtmlText directly or use an API that doesn't import html_parse) and add
explicit sibling-absence assertions in every test: when asserting the expected
import (e.g., '"html_query"'), also assert the other three imports
('"html_parse"', '"html_to_string"', '"html_text"') are not in result.wat, and
do the analogous checks in the other tests to ensure full isolation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ddb585e4-6fce-4bae-8d29-44b045d6f6d9

📥 Commits

Reviewing files that changed from the base of the PR and between f987c0e and acea392.

📒 Files selected for processing (2)
  • TESTING.md
  • tests/test_codegen.py

Comment thread TESTING.md Outdated
Comment thread tests/test_codegen.py
aallan and others added 2 commits March 26, 2026 12:59
- Fix examples count 27->29, conformance prose 62->63, pytest 305->315
- Add sibling-absence assertions to per-operation WAT import tests
- Fix test_html_parse_with_attributes: query by class then verify
  attribute value length (4 for 'main')
- Fix codegen line count

Co-Authored-By: Claude <noreply@anthropic.invalid>
- test_html_parse_comment_roundtrip: exercises write_html comment path
- test_html_query_empty_result: no-match selector returns empty array
- test_html_nested_elements: text extraction from nested tags

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
TESTING.md (3)

291-291: ⚠️ Potential issue | 🟡 Minor

Update stale example count in Round-Trip Testing section.

This line references "27 example programs", but the current total is 29 after this PR adds examples/html.vera.

📝 Proposed fix
-Every one of the 27 example programs in `examples/` is tested through **every pipeline stage**
+Every one of the 29 example programs in `examples/` is tested through **every pipeline stage**

As per coding guidelines: keep validation expectations and documented counts in sync with the PR's added conformance/program.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` at line 291, Update the stale example count in the Round-Trip
Testing section: change the sentence that currently says "27 example programs"
to "29 example programs" (this refers to the descriptive line about examples in
`examples/` being tested through every pipeline stage in TESTING.md) so the
documented count matches the newly added examples like `examples/html.vera`.

207-207: ⚠️ Potential issue | 🟡 Minor

Update stale example count in Contract Verification Coverage section.

This line references "all 27 example programs", but the PR adds examples/html.vera, bringing the total to 29 (as correctly reflected on lines 12, 40, and 316).

📝 Proposed fix
-Across all 27 example programs:
+Across all 29 example programs:

As per coding guidelines: keep validation expectations and documented counts in sync with the PR's added conformance/program.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` at line 207, Update the stale count in the "Contract Verification
Coverage" section that currently reads "all 27 example programs" to reflect the
new total "all 29 example programs" (the PR added examples/html.vera); locate
the phrase in TESTING.md within the Contract Verification Coverage paragraph and
change the numeric count to 29 so it matches the other references (lines that
already show 29).

233-267: ⚠️ Potential issue | 🟡 Minor

Add Html stdlib feature to Language Feature Coverage table.

The table systematically documents all Chapter 9 stdlib features (Markdown, Regex, Decimal, Json, Http), but the newly added Html feature is missing. This creates a factual gap in the documented language coverage.

📝 Proposed fix

Add after line 265 (the Json entry):

 | Ch 9: Stdlib | Json (json_parse, json_stringify, json_get, json_set) | test_codegen, test_checker | ch09_json | json |
+| Ch 9: Stdlib | Html (html_parse, html_to_string, html_query, html_text, html_attr) | test_codegen, test_checker | ch09_html | html |
 | Ch 9: Stdlib | Http effect (http_get, http_post) | test_codegen, test_checker | ch09_http | http_client |

As per coding guidelines: ensure HTML-related code samples/conformance entry are covered by the existing validation scripts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` around lines 233 - 267, Add a new row to the Language Feature
Coverage table for the Html stdlib feature immediately after the Json entry: add
"Ch 9: Stdlib | Html | test_codegen, test_checker, test_html | ch09_html |
html_examples" (or the actual test-suite and conformance id you use, e.g.,
test_html and ch09_html) so the table mirrors other Ch 9 entries; ensure the new
"ch09_html" conformance id and test file names match your existing validation
scripts so HTML-related examples are picked up by the validation pipeline.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)

9200-9215: ⚠️ Potential issue | 🟠 Major

Isolate html_query import-gating in this WAT test.

Line [9206] also calls html_parse, so this does not prove html_query is independently gated nor that sibling HTML imports remain absent for query-only usage.

🧪 Proposed tightening
     def test_html_query_wat_import(self) -> None:
         """html_query generates a WASM host import."""
         source = """
 public fn main(-> `@Int`)
   requires(true) ensures(true) effects(pure)
-{
-  let `@Result`<HtmlNode, String> = html_parse("<p>x</p>");
-  match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")),
-    Err(`@String`) -> 0
-  }
-}
+{ array_length(html_query(HtmlText("x"), "p")) }
 """
         result = _compile_ok(source)
         assert '"html_query"' in result.wat
+        assert '"html_parse"' not in result.wat
+        assert '"html_to_string"' not in result.wat
+        assert '"html_text"' not in result.wat

Based on learnings, tests/test_codegen.py already uses per-operation WAT import-gating patterns for JSON/Http and HTML should mirror that.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 9200 - 9215, The test
test_html_query_wat_import currently calls html_parse and html_query together,
so it does not prove html_query import is independently gated; change the test
to exercise only html_query (remove the html_parse call and any match branches
that rely on HtmlNode construction from html_parse) so the compiled result.wat
contains the "html_query" import without also requiring other HTML imports like
html_parse; update the source string in test_html_query_wat_import to produce or
reference an HtmlNode value usable by html_query (e.g., provide a dummy HtmlNode
literal or construct the call site to directly call html_query with a minimal
HtmlNode value) and keep the final assertion assert '"html_query"' in
result.wat.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@TESTING.md`:
- Line 358: Update the stale count text for the `check_examples.py` entry in the
validation scripts table: change the referenced "All 27 examples" to "All 29
examples" so it matches the other table entry (line referencing 29) and the
repository's current total; locate the table row containing the string
`check_examples.py` and update only the numeric count to 29 to keep validation
expectations consistent.

In `@tests/test_codegen.py`:
- Around line 9307-9319: The test test_html_attr_value_escaping currently only
asserts result > 0; change it to call html_to_string(HtmlElement(...)) to get
the serialized string and assert the escaping contract directly: that the
attribute value for "title" does not contain a raw double-quote and is escaped
(e.g. contains title="a&quot;b" or the equivalent HTML entity) — use
html_to_string, HtmlElement, and the map_insert/map_new construction already in
the test to build the element and assert the exact escaped substring instead of
a numeric check.

---

Outside diff comments:
In `@TESTING.md`:
- Line 291: Update the stale example count in the Round-Trip Testing section:
change the sentence that currently says "27 example programs" to "29 example
programs" (this refers to the descriptive line about examples in `examples/`
being tested through every pipeline stage in TESTING.md) so the documented count
matches the newly added examples like `examples/html.vera`.
- Line 207: Update the stale count in the "Contract Verification Coverage"
section that currently reads "all 27 example programs" to reflect the new total
"all 29 example programs" (the PR added examples/html.vera); locate the phrase
in TESTING.md within the Contract Verification Coverage paragraph and change the
numeric count to 29 so it matches the other references (lines that already show
29).
- Around line 233-267: Add a new row to the Language Feature Coverage table for
the Html stdlib feature immediately after the Json entry: add "Ch 9: Stdlib |
Html | test_codegen, test_checker, test_html | ch09_html | html_examples" (or
the actual test-suite and conformance id you use, e.g., test_html and ch09_html)
so the table mirrors other Ch 9 entries; ensure the new "ch09_html" conformance
id and test file names match your existing validation scripts so HTML-related
examples are picked up by the validation pipeline.

---

Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9200-9215: The test test_html_query_wat_import currently calls
html_parse and html_query together, so it does not prove html_query import is
independently gated; change the test to exercise only html_query (remove the
html_parse call and any match branches that rely on HtmlNode construction from
html_parse) so the compiled result.wat contains the "html_query" import without
also requiring other HTML imports like html_parse; update the source string in
test_html_query_wat_import to produce or reference an HtmlNode value usable by
html_query (e.g., provide a dummy HtmlNode literal or construct the call site to
directly call html_query with a minimal HtmlNode value) and keep the final
assertion assert '"html_query"' in result.wat.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 643c846c-3bb3-4662-9848-33d4d0612965

📥 Commits

Reviewing files that changed from the base of the PR and between acea392 and 749a260.

📒 Files selected for processing (2)
  • TESTING.md
  • tests/test_codegen.py

Comment thread TESTING.md Outdated
Comment thread tests/test_codegen.py
- Fix 27->29 example counts (4 occurrences) and 62->63 conformance
- Add Language Feature Coverage rows for Map/Set/Decimal, Json, Html, Http
- Fix test_html_attr_value_escaping: assert exact length (24)
- Fix test_html_query_wat_import: construct HtmlElement directly,
  no html_parse dependency, full sibling-absence assertions
- Fix conformance pytest snippet 305->315

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan

aallan commented Mar 26, 2026

Copy link
Copy Markdown
Owner Author

Merging with codecov/patch at ~89% (target 95.35%). The gap is the same structural issue as every PR touching the host runtime:

  • vera/browser/runtime.mjs — JS code invisible to pytest-cov (tracked by Improve browser runtime (runtime.mjs) test coverage to >80% #349)
  • vera/wasm/html_serde.py — HtmlComment write path (line 108-114) requires parsed HTML with comments, which the roundtrip test exercises but the serde path for writing comments back to WASM is only reached when the host returns comment nodes
  • vera/codegen/api.py — defensive exception handlers in html_parse/html_to_string host functions, CSS selector mismatch path
  • vera/prelude.py_has_standard_html guard (only fires if user shadows data HtmlNode)

Project coverage is 95.24% (-0.11% from baseline). All 3,065 tests pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
TESTING.md (1)

207-214: ⚠️ Potential issue | 🟡 Minor

Contract coverage figures are internally inconsistent.

This section says 162 Tier‑1 out of 177 total (91.0%), but that ratio is ~91.5%; it also conflicts with the overview metric (162 of 179). Please align total contracts and derived percentage across both sections.

As per coding guidelines: "**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@TESTING.md` around lines 207 - 214, The contract coverage numbers in the
"Across all 29 example programs" table are inconsistent: it lists "Tier 1
(static) 162", "Total 177", and "91.0%" (which is ~91.5%), and this conflicts
with the other overview metric "162 of 179"; confirm the actual contract counts
from the test output/codebase and then update the table and the overview metric
so both show the same total and a correctly computed percentage (e.g., 162/177 →
91.5% or 162/179 → 90.5%); ensure you update the numeric cells "Tier 1 (static)
162", "Tier 3 (runtime) 16", "Total X" and the percentage string wherever "162
of 177" or "162 of 179" appear so all instances match and the derived percent is
accurate.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)

9090-9104: ⚠️ Potential issue | 🟠 Major

Strengthen weak HTML test oracles to assert the actual contract.

These assertions are currently too permissive (> 0) and can pass even when the advertised behaviour is broken (roundtrip fidelity, comment preservation, nested text extraction).

Suggested tightening (concrete behavioural checks)
@@
     def test_html_to_string_roundtrip(self) -> None:
         """html_to_string serializes back to HTML."""
         source = """
 public fn main(-> `@Int`)
   requires(true) ensures(true) effects(pure)
 {
   let `@Result`<HtmlNode, String> = html_parse("<p>hi</p>");
   match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> string_length(html_to_string(`@HtmlNode.0`)),
+    Ok(`@HtmlNode`) ->
+      if string_contains(html_to_string(`@HtmlNode.0`), "<p>hi</p>") then { 1 } else { 0 },
     Err(`@String`) -> 0
   }
 }
 """
-        assert _run(source) > 0
+        assert _run(source) == 1
@@
     def test_html_parse_comment_roundtrip(self) -> None:
         """Parsed HTML comments survive roundtrip through html_to_string."""
         source = '''
 public fn main(-> `@Int`)
   requires(true) ensures(true) effects(pure)
 {
   let `@Result`<HtmlNode, String> = html_parse("<!-- hello --><p>text</p>");
   match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> string_length(html_to_string(`@HtmlNode.0`)),
+    Ok(`@HtmlNode`) ->
+      if string_contains(html_to_string(`@HtmlNode.0`), "<!-- hello -->") then { 1 } else { 0 },
     Err(`@String`) -> 0
   }
 }
 '''
-        result = _run(source)
-        assert result > 0  # roundtrip produces non-empty HTML
+        assert _run(source) == 1
@@
     def test_html_nested_elements(self) -> None:
         """html_text extracts text from nested elements."""
         source = '''
 public fn main(-> `@Int`)
   requires(true) ensures(true) effects(pure)
 {
   let `@Result`<HtmlNode, String> = html_parse("<div><span>hello</span> <em>world</em></div>");
   match `@Result`<HtmlNode, String>.0 {
-    Ok(`@HtmlNode`) -> string_length(html_text(`@HtmlNode.0`)),
+    Ok(`@HtmlNode`) ->
+      if string_contains(html_text(`@HtmlNode.0`), "hello") then {
+        if string_contains(html_text(`@HtmlNode.0`), "world") then { 1 } else { 0 }
+      } else { 0 },
     Err(`@String`) -> 0
   }
 }
 '''
-        result = _run(source)
-        assert result > 0  # extracts "hello world" text
+        assert _run(source) == 1

As per coding guidelines, “DO flag: Tests that don't assert anything meaningful.”

Also applies to: 9371-9386, 9402-9417

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 9090 - 9104, The test
test_html_to_string_roundtrip uses a weak oracle (assert _run(source) > 0);
update it to assert the actual contract by invoking _run(source) and comparing
the returned HTML/text to expected values (e.g., that html_to_string roundtrips
to "<p>hi</p>" or that string_length(html_to_string(...)) equals the expected
length and that comments/nested text are preserved). Locate the test function
test_html_to_string_roundtrip and the helper _run, replace the > 0 check with
precise assertions against the expected serialized HTML/text and length, and
apply the same tightening to the related tests referenced (the tests around the
other occurrences that call _run).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@TESTING.md`:
- Around line 207-214: The contract coverage numbers in the "Across all 29
example programs" table are inconsistent: it lists "Tier 1 (static) 162", "Total
177", and "91.0%" (which is ~91.5%), and this conflicts with the other overview
metric "162 of 179"; confirm the actual contract counts from the test
output/codebase and then update the table and the overview metric so both show
the same total and a correctly computed percentage (e.g., 162/177 → 91.5% or
162/179 → 90.5%); ensure you update the numeric cells "Tier 1 (static) 162",
"Tier 3 (runtime) 16", "Total X" and the percentage string wherever "162 of 177"
or "162 of 179" appear so all instances match and the derived percent is
accurate.

---

Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9090-9104: The test test_html_to_string_roundtrip uses a weak
oracle (assert _run(source) > 0); update it to assert the actual contract by
invoking _run(source) and comparing the returned HTML/text to expected values
(e.g., that html_to_string roundtrips to "<p>hi</p>" or that
string_length(html_to_string(...)) equals the expected length and that
comments/nested text are preserved). Locate the test function
test_html_to_string_roundtrip and the helper _run, replace the > 0 check with
precise assertions against the expected serialized HTML/text and length, and
apply the same tightening to the related tests referenced (the tests around the
other occurrences that call _run).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 00800ea7-27b7-4c85-bdb5-7514b260bf50

📥 Commits

Reviewing files that changed from the base of the PR and between 749a260 and 95f701f.

📒 Files selected for processing (2)
  • TESTING.md
  • tests/test_codegen.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTML standard library type

1 participant