Skip to content

fix(export): fix broken template placeholders in session export HTML#41861

Merged
vincentkoc merged 4 commits into
openclaw:mainfrom
briannewman:fix/export-session-template-placeholders
Apr 28, 2026
Merged

fix(export): fix broken template placeholders in session export HTML#41861
vincentkoc merged 4 commits into
openclaw:mainfrom
briannewman:fix/export-session-template-placeholders

Conversation

@briannewman

Copy link
Copy Markdown
Contributor

Problem

The /export-session command produces an HTML file that opens but renders completely blank — no messages, no sidebar, nothing. The file is ~2MB (session data is present) but the viewer JS never loads.

Root Cause

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in template.html were reformatted by Prettier into multi-line JS block statements:

<script>
  {
    {
      MARKED_JS;
    }
  }
</script>

The generateHtml() function in commands-export-session.ts uses .replace('{{MARKED_JS}}', markedJs) which requires contiguous {{MARKED_JS}} strings. The prettified version doesn't match, so the vendor libraries (marked.js, highlight.js) and the main app JS are never injected.

Introduced in 9d403fd.

Fix

Collapse placeholders back to single-line {{TOKEN}} format and add <!-- prettier-ignore --> comments to prevent re-formatting.

Testing

Before: /export-session → 2MB HTML file, opens with dark theme background but blank content
After: template placeholders match the .replace() calls, JS gets injected, session renders

@greptile-apps

greptile-apps Bot commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a critical regression introduced in 9d403fd where Prettier reformatted the {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in template.html into syntactically valid (but incorrect) multi-line JS block expressions, breaking the exact-string .replace() calls in generateHtml() so that vendor libraries and the application JS were never injected into the exported HTML.

The fix is minimal, targeted, and correct:

  • Collapses each placeholder back to a single-line <script>{{TOKEN}}</script> form that matches the existing .replace() calls in commands-export-session.ts
  • Adds <!-- prettier-ignore --> comments immediately before each <script> tag to prevent Prettier from re-introducing the same breakage

No logic changes are made to commands-export-session.ts; the template is the only file touched.

Confidence Score: 5/5

  • This PR is safe to merge — it is a targeted, one-file fix that restores the intended behavior of the export feature.
  • The root cause is clearly identified and the fix is precise. The <!-- prettier-ignore --> guards prevent the same regression from recurring. No logic is changed; no other code paths are affected. The remaining placeholders ({{CSS}} in a <style> tag and {{SESSION_DATA}} in a type="application/json" script block) were never vulnerable to this Prettier issue, so they correctly remain untouched.
  • No files require special attention.

Last reviewed commit: 3f73181

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f7318177d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/auto-reply/reply/export-html/template.html Outdated
@briannewman briannewman force-pushed the fix/export-session-template-placeholders branch from 8377d86 to c25e66e Compare March 10, 2026 22:38
@briannewman

Copy link
Copy Markdown
Contributor Author

CI Status: The TypeScript failures in this run (missing DEFAULT_ACCOUNT_ID, type mismatches in extensions/nextcloud-talk, googlechat, zalouser) are pre-existing issues in the repository, not caused by these template changes. The PR itself only modifies template.html and commands-export-session.ts to fix the export HTML rendering.

Latest main (run #11081) shows a successful build, confirming these are unrelated. The export fix is ready to merge. 🐻

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Codex automated review: keeping this open.

Keep this PR open. Current main still has the session export template/replacement mismatch, the latest release tree has the same mismatch, and the PR is paired with an open same-author bug report (#41862). The PR is a focused implementation candidate rather than obsolete cleanup.

Best possible solution:

Keep this PR open as a valid focused fix candidate. The best maintainer path is to land one canonical implementation that restores compact protected script placeholders, uses function replacers for injected JS content, adds a regression test against the real template/generation path, and then closes the paired bug report #41862 plus duplicate reports such as #49957 after merge.

What I checked:

Remaining risk / open question:

  • Current main and v2026.4.24 still leave unresolved script placeholder identifiers in exported HTML, so users can still get a blank session export viewer.
  • The existing tests do not assert the real generated HTML injection path; landing should add focused regression coverage that the real template no longer contains unresolved JS placeholders after generation.
  • There are multiple open or closed duplicate attempts around the same bug, so maintainers should choose one canonical fix path rather than closing all candidates before a fix lands.

Codex Review notes: model gpt-5.5, reasoning high; reviewed against 9bc703213bb3.

briannewman and others added 4 commits April 28, 2026 04:18
The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 9d403fd.
String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).
@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish pushed a narrow repair to this branch so the original contributor path can stay canonical.

Source PR: #41861
Validation: pnpm -s vitest run src/auto-reply/reply/commands-export-session.test.ts src/auto-reply/reply/export-html/template.security.test.ts; pnpm check:changed
Contributor credit is preserved in the branch history and PR context.

@vincentkoc vincentkoc force-pushed the fix/export-session-template-placeholders branch from 485acbd to 2256419 Compare April 28, 2026 04:25
@openclaw-barnacle openclaw-barnacle Bot added size: S and removed size: XS stale Marked as stale due to inactivity labels Apr 28, 2026
@vincentkoc vincentkoc merged commit 0551274 into openclaw:main Apr 28, 2026
51 of 66 checks passed
@vincentkoc vincentkoc added the clawsweeper Tracked by ClawSweeper automation label Apr 28, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in b8e9d67.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 44b1f63.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 6bf62fb.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 3582d5b.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 90dc2e5.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…penclaw#41861)

* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in c9bcee7.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper Tracked by ClawSweeper automation size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants