Skip to content

Add HTMLExporter to export PAGX file as standalone HTML matching pagx native rendering.#3424

Closed
shlzxjp wants to merge 609 commits into
mainfrom
feature/henryjpxie_pagx_html
Closed

Add HTMLExporter to export PAGX file as standalone HTML matching pagx native rendering.#3424
shlzxjp wants to merge 609 commits into
mainfrom
feature/henryjpxie_pagx_html

Conversation

@shlzxjp
Copy link
Copy Markdown
Collaborator

@shlzxjp shlzxjp commented May 12, 2026

Adds a new HTMLExporter under include/pagx/HTMLExporter.h that converts PAGX documents into standalone HTML fragments. The exporter mirrors PAGX rendering semantics against tgfx native: Layer geometry, Group transforms, SolidColor / Linear / Radial / Conic / Diamond gradients, ImagePattern, DropShadow / BackgroundBlur / InnerShadow / ColorMatrix styles, standalone Text and TextBox (including textAnchor, paragraphAlign, writingMode, fontSynthesis, TextPath, TextModifier RangeSelector), BlendMode mapping including a PlusDarker SVG fallback, Mask and ScrollRect clipping, Repeater expansion, Composition references, and font embedding through @font-face with multi-source URL / local fallbacks. Auxiliary assets (rasterized gradient fills, tiled patterns, and copies of external Image files) land in a caller-supplied staticImgDir so the HTML stays small. pagx export grows an html format (--format html, --html-font, --html-no-font-synthesis-*) so the CLI matches the new API.

The branch also merges origin/main and includes a one-line HTML-local wrapper (BuildGroupMatrixForHTML) that negates group skew to align with tgfx VectorGroup::ApplySkew; the shared pagx::BuildGroupMatrix is kept as-is so main's PAGXSVGTest.SVGExport_GroupSkew and the SVG / PPT exporters are unaffected. Merge conflicts across CliUtils, TextLayout, StringParser, and version.json were resolved by mirroring main's module splits (pagx::VerifyUtils, pagx::ExporterUtils) and deleting SVGTextLayout, whose logic the new SVG exporter subsumes.

Verified with PAGFullTest (1158/1158) on macOS, and against the PAGX-native comparison page generated by test/gen_html_comparison.sh across 275 samples (pagx_to_html / cli / layout / text / spec).

shlzxjp added 30 commits April 18, 2026 03:39
…L rows match tgfx regardless of whether the row is stretched or shrink-to-fit.
…nd labels are balanced around the doc center.
shlzxjp added 12 commits May 12, 2026 12:04
…wser-rendered pixels shifted after the HTML exporter stopped registering a real Noto Sans SC Bold typeface during applyLayout so tgfx faux bold metrics now drive the emitted HTML structure while Chromium still paints with the real Bold font.
…tchConvertAll write into a single top-level fonts directory and rewrite every emitted url('fonts/...') reference into url('../fonts/...') so the generated comparison bundle drops from ~131 MB to ~44 MB while staying deploy ready without any manual post-processing.
…gle float and per-corner values are silently truncated.
…apper to keep group skew aligned with tgfx native rendering.
…sks on document-origin layers still clip correctly.
@shlzxjp shlzxjp changed the title Add HTMLExporter to export PAGX as standalone HTML matching tgfx native rendering. Add HTMLExporter to export PAGX as standalone HTML matching pagx native rendering. May 12, 2026
@shlzxjp shlzxjp changed the title Add HTMLExporter to export PAGX as standalone HTML matching pagx native rendering. Add HTMLExporter to export PAGX file as standalone HTML matching pagx native rendering. May 12, 2026
@shlzxjp shlzxjp marked this pull request as ready for review May 12, 2026 15:47
shlzxjp added 3 commits May 13, 2026 10:27
…st workflow so HtmlScreenshotCompare can run on CI.
…match the repository, and drop empty npm-init placeholder fields.
…c_text_box to skip the mac autotest md5 mismatch.
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 62.35136% with 1678 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.85%. Comparing base (557c21a) to head (72334cd).

Files with missing lines Patch % Lines
src/pagx/html/HTMLWriterShape.cpp 68.43% 394 Missing and 134 partials ⚠️
src/pagx/html/HTMLWriterColor.cpp 39.69% 203 Missing and 34 partials ⚠️
src/cli/CommandExport.cpp 11.06% 220 Missing and 5 partials ⚠️
src/pagx/html/HTMLWriterFilter.cpp 69.67% 112 Missing and 46 partials ⚠️
src/pagx/html/HTMLStyleExtractor.cpp 76.80% 66 Missing and 88 partials ⚠️
src/pagx/html/HTMLExporter.cpp 45.92% 136 Missing and 10 partials ⚠️
src/pagx/html/HTMLStaticImageRenderer.cpp 64.02% 45 Missing and 14 partials ⚠️
src/pagx/html/HTMLPlusDarkerRenderer.cpp 59.55% 30 Missing and 25 partials ⚠️
src/pagx/html/HTMLBuilder.h 65.30% 35 Missing and 16 partials ⚠️
src/cli/CliUtils.cpp 0.00% 30 Missing ⚠️
... and 6 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3424      +/-   ##
==========================================
- Coverage   81.54%   78.85%   -2.70%     
==========================================
  Files         558      578      +20     
  Lines       51408    60569    +9161     
  Branches    13987    18763    +4776     
==========================================
+ Hits        41922    47763    +5841     
- Misses       6602     9160    +2558     
- Partials     2884     3646     +762     

☔ 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.

### HTML output

When the output is HTML, `pagx export` writes a complete `<!DOCTYPE html>` document that can
be opened directly in a browser. DiamondGradient and tiled/mirror ImagePattern fills that CSS
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

我们skills里不解释太多原理性的内容,只说明参数和用法,减少上下文篇幅。

commands (render, verify, format, layout, bounds, font info/embed, import/export), or
look up PAGX element attributes and syntax.
commands (render, verify, format, layout, bounds, font info/embed, import/export,
export to HTML for browser preview), or look up PAGX element attributes and syntax.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这部分不用单独为HTML修改描述吧

| `references/patterns.md` | Structural patterns for UI components, layouts, tables, charts, decorative effects | Read before generating |
| `references/attributes.md` | Attribute defaults, enumerations, required attributes | As needed |
| `references/cli.md` | CLI commands — `render`, `verify`, `format`, `layout`, `bounds`, `font info`, `font embed`, `import`, `export` | As needed |
| `references/cli.md` | CLI commands — `render`, `verify`, `format`, `layout`, `bounds`, `font info`, `font embed`, `import`, `export` (SVG, HTML) | As needed |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这里也不用特别强调SVG和HTML,总体说有export命令就行

Comment thread include/pagx/nodes/Text.h
Comment on lines +105 to +132
* Returns the font metrics line height (|ascent| + descent + leading) computed during layout.
* Returns 0 if layout has not been performed.
*/
float fontLineHeight() const;

/**
* Returns the maximum font ascent (distance from baseline to the top of the tallest glyph)
* computed during layout. Used by HTML export for alphabetic-baseline text positioning where
* CSS `top = position.y - fontAscent()` places the baseline at the authored position.y.
* Returns 0 if layout has not been performed.
*/
float fontAscent() const;

/**
* Returns the height of the text bounds computed during layout. For TextBox text, this reflects
* the number of lines tgfx actually retained after applying overflow:hidden clipping — lines
* whose bottom would exceed the box height are dropped and do not contribute to this value.
* Returns 0 if layout has not been performed.
*/
float layoutBoundsHeight() const;

/**
* Returns the width of the text bounds computed during layout — the actual inked width of the
* shaped glyph run(s), not the containing Layer's width. Useful for HTML export to scope a
* `background-clip:text` gradient to the same width tgfx uses when `fitsToGeometry=true`
* evaluates against the glyph bounding box. Returns 0 if layout has not been performed.
*/
float layoutBoundsWidth() const;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这些公开的读取接口不应该加,我们的行高就是css的line-box模型,直接用那个规范实现就行。

Comment on lines +99 to +109
bool isWidthAutoSized() const {
return widthAutoSized;
}

/**
* Returns true when neither the PAGX author nor the layout engine supplied an explicit height for
* this TextBox: the height was inferred entirely from tgfx's own text measurement.
*/
bool isHeightAutoSized() const {
return heightAutoSized;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这两个公开接口也不必要加。用isNaN(TextBox.width)这种就能判断

/**
* Output formatting style for the generated HTML document.
*/
enum class HTMLFormat {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个选项是不是没有必要?如果需要minify,业务自己有很多第三方工具吧。

Comment thread src/pagx/html/FontHoist.h
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个文件名是不是拼写错了?

@shlzxjp shlzxjp closed this May 13, 2026
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.

3 participants