Skip to content

html: deep pages, text in other scripts, every element of the standard, and a byte order mark - #177

Merged
donislawdev merged 2 commits into
mainfrom
format/html-settings
Oct 14, 2026
Merged

donislawdev merged 2 commits into
mainfrom
format/html-settings

Conversation

@donislawdev

@donislawdev donislawdev commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

What

Four new settings for the html format. Each is off by default, so files made with the earlier settings keep their bytes (the golden values are unchanged).

  • nesting - the content of a page inside up to 100 000 div elements, each inside the last, with the label outside them. Readers part ways early: lxml drops everything but the label from a page about 250 deep, Chromium keeps 511 levels and moves the deeper ones out, and jsdom, parse5 and DOMPurify can run out of stack writing out a page from about 2 000 deep. The Nu HTML Checker calls a page past 513 elements deep an error.
  • characters=international - paragraphs in Polish, Russian, Japanese and Arabic (right to left), emoji with a ZWJ sequence, a letter written as two code points, and named and numbered entities.
  • elements=every - a block that uses every element of the HTML standard but script at least once (114 of the 115 names in its index), all 22 kinds of input, and pictures and a sound written into the page as data:, so opening it fetches nothing. The Nu HTML Checker finds nothing wrong with it. A fragment has no head, so it leaves out the eight elements only a whole page holds, and the manifest carries a note saying so.
  • bom - a UTF-8 byte order mark in front, from the shared text encoding axis. Chromium and file still see HTML. Content sniffing as the WHATWG describes it, which Go's net/http follows, reads it as plain text.

Around it

  • htmlfile split into settings.go, page.go, blocks.go (bytes unchanged), catalogue.go and characters.go. The bytes that close the levels, the body and the document stay in the last record. The minimum is summed from lengths, so a deep page keeps 600 KB out of every plan.
  • strict.py check_html is told all five settings and checks each from the bytes. It no longer takes <header> for <head>.
  • Engine and registry sentences in English and Polish, the format table in README, the changelog, and the site in 22 languages.

Checked by

  • Eight readers measured on generated files: Chromium 152, Nu HTML Checker 26.10.12, lxml with libxml2 2.11.9 and 2.14.6, html5lib, BeautifulSoup, parse5, jsdom, DOMPurify, plus pandoc and two content sniffers for the mark.
  • New guards (htmlsettings_test.go, htmlcatalogue_test.go), four new golden values.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added configurable HTML output for document or fragment structure, nesting depth, ASCII or international text, basic or comprehensive elements, and an optional UTF-8 BOM.
    • Comprehensive output includes embedded media and standard HTML elements, excluding scripts. Fragments omit page-only elements.
    • Added English and Polish translations for the new HTML settings.
  • Documentation
    • Updated the README to list the available HTML format settings.

…d, and a byte order mark

Four new settings for the html format, each off by default, so files made
with the earlier settings keep their bytes.

- nesting puts the content inside up to 100 000 div elements, the label
  outside them. lxml drops the content of a page about 250 deep, Chromium
  flattens past 511, and jsdom, parse5 and DOMPurify can run out of stack
  writing out a page from about 2 000 deep.
- characters=international adds paragraphs in Polish, Russian, Japanese
  and Arabic (right to left), emoji, a letter in two code points and
  entities.
- elements=every adds a block using every element of the HTML standard
  but script, all 22 kinds of input, and pictures and a sound written into
  the page as data. The Nu HTML Checker finds nothing wrong with it.
- bom puts a UTF-8 byte order mark in front, from the shared text
  encoding axis. Content sniffing as the WHATWG describes it then reads the
  page as plain text.

The structural check is told every setting and checks each one from the
bytes. Four golden cases pin the new paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository UI (base), Organization UI (inherited)
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 1203f0d5-3411-4733-9ae5-e17313ab8adc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI (base), Organization UI (inherited)
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 5f16e8c0-cee0-4391-a055-9f859516a620
📥 Commits

Reviewing files that changed from the base of the PR and between 557d2f1 and 202d504.

⛔ Files ignored due to path filters: 22
  • web/public/ar/formats/index.html is excluded by !**/web/public/**
  • web/public/cs/formaty/index.html is excluded by !**/web/public/**
  • web/public/de/formate/index.html is excluded by !**/web/public/**
  • web/public/es/formatos/index.html is excluded by !**/web/public/**
  • web/public/formats/index.html is excluded by !**/web/public/**
  • web/public/fr/formats/index.html is excluded by !**/web/public/**
  • web/public/hi/formats/index.html is excluded by !**/web/public/**
  • web/public/id/format/index.html is excluded by !**/web/public/**
  • web/public/it/formati/index.html is excluded by !**/web/public/**
  • web/public/ja/formats/index.html is excluded by !**/web/public/**
  • web/public/ko/formats/index.html is excluded by !**/web/public/**
  • web/public/nl/formaten/index.html is excluded by !**/web/public/**
  • web/public/pl/formaty/index.html is excluded by !**/web/public/**
  • web/public/pt-br/formatos/index.html is excluded by !**/web/public/**
  • web/public/ro/formate/index.html is excluded by !**/web/public/**
  • web/public/ru/formats/index.html is excluded by !**/web/public/**
  • web/public/th/formats/index.html is excluded by !**/web/public/**
  • web/public/tr/bicimler/index.html is excluded by !**/web/public/**
  • web/public/uk/formats/index.html is excluded by !**/web/public/**
  • web/public/vi/dinh-dang/index.html is excluded by !**/web/public/**
  • web/public/zh-hans/formats/index.html is excluded by !**/web/public/**
  • web/public/zh-hant/formats/index.html is excluded by !**/web/public/**
📒 Files selected for processing: 18
  • CHANGELOG.md
  • README.md
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/html.go
  • internal/format/htmlfile/page.go
  • internal/format/htmlfile/settings.go
  • internal/guard/generatorbytes_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/layers_test.go
  • internal/guard/testdata/generator-golden.json
  • internal/gui/text/locale/registry/en.json
  • internal/gui/text/locale/registry/pl.json
  • internal/gui/text/locale/said/en.json
  • internal/gui/text/locale/said/pl.json
  • internal/oracle/strict.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout: 17
  • GitHub Check: review new dependencies
  • GitHub Check: reference tools actually installed
  • GitHub Check: linters
  • GitHub Check: semgrep
  • GitHub Check: test on windows-latest
  • GitHub Check: known vulnerabilities
  • GitHub Check: the installer installs and leaves
  • GitHub Check: coverage gate
  • GitHub Check: import table of the window binary
  • GitHub Check: staticcheck
  • GitHub Check: bill of materials
  • GitHub Check: the Chocolatey packages install and leave
  • GitHub Check: test on ubuntu-latest
  • GitHub Check: test on macos-latest
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (go)
🧰 Additional context used
📚 Code guidelines: 1
CONTRIBUTING.md — configured
📓 Path-based instructions: 14
Applies to text shown to the user (labels, buttons, tooltips, placeholders, dialogs, errors, status messages, empty states, translations).

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/gui/text/locale/said/pl.json
  • internal/gui/text/locale/registry/pl.json
  • internal/guard/generatorbytes_test.go
  • internal/gui/text/locale/registry/en.json
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/gui/text/locale/said/en.json
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Verify tests check real behavior and would fail if the implementation were broken.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
These are end-user desktop applications.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Performance is a known weak spot of these projects.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Applies only to code that builds or styles a GUI.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
User-facing changelog.

⚙️ CodeRabbit configuration file

Files:

  • CHANGELOG.md
Domain: test file generator (Go; `tfg` CLI and `tfg-gui` Fyne window over one engine).

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/gui/text/locale/said/pl.json
  • internal/gui/text/locale/registry/pl.json
  • internal/guard/testdata/generator-golden.json
  • internal/guard/generatorbytes_test.go
  • internal/gui/text/locale/registry/en.json
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/gui/text/locale/said/en.json
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
SECURITY, HIGH PRIORITY.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
These apps are QA/developer tools.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Go code.

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • internal/guard/generatorbytes_test.go
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/format/htmlfile/catalogue.go
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Check that documentation matches the actual code in this PR: commands, flags, config keys, file paths, build steps and examples must exist.

⚙️ CodeRabbit configuration file

Files:

  • README.md
  • CHANGELOG.md
Python code.

⚙️ CodeRabbit configuration file

Files:

  • internal/oracle/strict.py
All code in this repository is written by an AI coding agent (Claude Code).

⚙️ CodeRabbit configuration file

Files:

  • internal/guard/layers_test.go
  • README.md
  • internal/gui/text/locale/said/pl.json
  • CHANGELOG.md
  • internal/gui/text/locale/registry/pl.json
  • internal/guard/testdata/generator-golden.json
  • internal/guard/generatorbytes_test.go
  • internal/gui/text/locale/registry/en.json
  • internal/format/htmlfile/characters.go
  • internal/format/htmlfile/page.go
  • internal/oracle/strict.py
  • internal/format/htmlfile/catalogue.go
  • internal/gui/text/locale/said/en.json
  • internal/format/htmlfile/settings.go
  • internal/guard/htmlsettings_test.go
  • internal/guard/htmlcatalogue_test.go
  • internal/format/htmlfile/blocks.go
  • internal/format/htmlfile/html.go
Source excerpt: **Words a user reads are English, with a flat hyphen and no semicolons.**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Files:

  • README.md
  • CHANGELOG.md
🪛 ast-grep (0.45.3)
internal/oracle/strict.py

[warning] 819-819: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.search(r"<" + name + r"[\s>]", text, re.IGNORECASE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🔇 Additional comments: 18
internal/format/htmlfile/settings.go: 1

1-174: LGTM!

internal/format/htmlfile/page.go: 1

1-98: LGTM!

internal/format/htmlfile/characters.go: 1

1-38: LGTM!

internal/format/htmlfile/catalogue.go: 1

1-154: LGTM!

internal/guard/htmlcatalogue_test.go: 1

1-144: LGTM!

internal/guard/htmlsettings_test.go: 1

1-209: LGTM!

internal/guard/layers_test.go: 1

174-174: LGTM!

README.md: 1

624-624: LGTM!

CHANGELOG.md: 1

142-159: LGTM!

internal/gui/text/locale/registry/en.json: 1

182-191: LGTM!

internal/gui/text/locale/registry/pl.json: 1

38-39: LGTM!

internal/gui/text/locale/said/en.json: 1

1758-1777: LGTM!

internal/gui/text/locale/said/pl.json: 1

352-355: LGTM!

internal/format/htmlfile/html.go: 1

194-200: LGTM!

internal/format/htmlfile/blocks.go: 1

1-117: LGTM!

internal/guard/generatorbytes_test.go: 1

443-462: LGTM!

internal/guard/testdata/generator-golden.json: 1

60-67: LGTM!

internal/oracle/strict.py: 1

816-820: LGTM!

📝 Walkthrough

HTML generation now supports settings for document structure, nesting, character content, element coverage, and BOM output. The generator records settings in manifests, and the strict checker validates generated HTML against them.

Changes: HTML format settings and generation

Layer / File(s) Summary
HTML settings and page content
internal/format/htmlfile/settings.go, internal/format/htmlfile/page.go, internal/format/htmlfile/characters.go, internal/format/htmlfile/catalogue.go, internal/guard/htmlcatalogue_test.go, internal/guard/htmlsettings_test.go, internal/guard/layers_test.go, README.md, CHANGELOG.md, internal/gui/text/locale/...
HTML settings now cover structure, nesting, character content, element coverage, and BOM output. Page helpers compose the configured content, and tests cover output, settings, and minimum sizes. The README, changelog, and English and Polish locale files describe the settings and related messages.
Settings-aware generation
internal/format/htmlfile/html.go, internal/format/htmlfile/blocks.go, internal/guard/generatorbytes_test.go, internal/guard/testdata/generator-golden.json, internal/gui/text/locale/said/...
Planning, manifests, labels, and writing use resolved HTML settings. Block generation supports exact-size output. Golden cases cover nested, international, all-elements, and BOM configurations.
Strict HTML validation
internal/oracle/strict.py, internal/guard/htmlsettings_test.go
The strict checker validates configured nesting, character and element modes, BOM presence, and fragment structure. Tests check acceptance of matching settings and rejection of mismatches.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Plan
  participant settingsOf
  participant Write
  Caller->>Plan: HTML properties and requested size
  Plan->>settingsOf: Parse and validate properties
  settingsOf-->>Plan: Resolved settings
  Plan-->>Caller: Generation plan
  Caller->>Write: Plan and output destination
  Write-->>Caller: Generated HTML
Loading

Suggested labels: enhancement, bug, performance

Merge Risk: ⚪ Minimal · up to 202d5

No identified issue prevents merging after normal checks.

Pre-merge checks: Passed 13 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Safe File Parsing Warning The new HTML checker can crash or hang on malformed settings or input. In internal/oracle/strict.py:700-703, settings.get("nesting") is accepted after .isdigit() and passed to int() without a … Bound and validate nesting before conversion. Require a string matching a bounded decimal form (for example [0-9]{1,6}), enforce 0 <= value <= 100000, and convert inside guarded handling; report invalid values with fail() instead of…
Passed Passed checks: 13 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main user-facing HTML changes: deep nesting, international text, broad element coverage, and UTF-8 BOM support. It is specific and suitable for release notes.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Tests For Changed Behavior Passed The PR adds non-UI HTML runtime behavior and adds direct coverage for it. internal/guard/htmlcatalogue_test.go checks elements, input types, international text, ASCII output, and BOM placement. `int…
No Secrets Or Debug Leftovers Passed The pull-request diff adds no CLAUDE.md, CLAUDE.local.md, AGENTS.md, .claude/, or .env files. Added-line scans found no credentials, API keys, private URLs, email addresses, IPs, local absolute paths,…
No Hardcoded Ui Styling Passed The pull request does not change GUI implementation code. Its only internal/gui changes are English and Polish locale JSON entries for labels and messages. No XAML, Slint, Fyne, Tkinter, or WPF code…
No Obvious Performance Problems Passed No clear performance problem was introduced. The HTML generator performs linear-size string construction and record filling, including bounded 100,000-level nesting. The strict checker uses linear sca…
Desktop Robustness Passed No desktop robustness failure is introduced. The changed HTML generator writes only to its supplied io.Writer and passes context cancellation to core.FillRecords. The embedded media uses data: URIs, w…
System Changes Are Reversible Passed PASS. The pull request changes HTML generation, validation, tests, documentation, translations, and static pages. The implementation uses local byte construction and embedded data: resources; it doe…
Clear User-Facing Text Passed PASS. The PR adds user-facing HTML setting descriptions, localized labels, format-table entries, notes, and validation messages. The GUI composes non-choice controls with generated allowed values and …
No Resource Leaks Passed No resource leak is introduced. The changed Go code generates bounded HTML buffers and passes the existing context-aware core.FillRecords; it adds no handlers, timers, goroutines, external handles, …
Scope, Duplication And Docs Passed No scope, duplication, documentation, or breaking-change violation found. The PR is cohesive: HTML settings, validation, tests, localization, and generated site pages. README and CHANGELOG document th…
Full details: Safe File Parsing

Explanation

The new HTML checker can crash or hang on malformed settings or input. In internal/oracle/strict.py:700-703, settings.get("nesting") is accepted after .isdigit() and passed to int() without a bound or exception handling. A 5000-digit value raises ValueError in Python 3.11. In html_settings line 744, re.findall(r'&lt;input[^&gt;]*\btype="([a-z-]+)"', text) scans to the next &gt; for every &lt;input; malformed input with repeated &lt;input and no &gt; shows quadratic behavior (about 4.2 seconds for 8,000 markers in an isolated reproduction). The new elements=every path activates this code before the existing tag scan.

Resolution

Bound and validate nesting before conversion. Require a string matching a bounded decimal form (for example [0-9]{1,6}), enforce 0 &lt;= value &lt;= 100000, and convert inside guarded handling; report invalid values with fail() instead of allowing int() to raise. Replace the unbounded re.findall input-type expression with a single-pass tag/attribute scanner or html.parser.HTMLParser callback that cannot rescan an unterminated tag. Add checker tests for a 5000-digit nesting setting and repeated unterminated &lt;input markers, and require a normal FAIL result.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot added bug Something isn't working enhancement New feature or request performance labels Oct 14, 2026
…eads nesting safely

The parity guard classifies html.bom, characters, elements and nesting as reachable from the window. The structural check accepts only ASCII digits up to 100000 for nesting before converting it, and asks for the page skeleton with one literal pattern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@donislawdev
donislawdev merged commit 25d9d8a into main Oct 14, 2026
22 checks passed
@donislawdev
donislawdev deleted the format/html-settings branch October 14, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant