render: unstableToPlainText ignores mixed-case HTML attributes

オープン 初心者向け
#3,876 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
node.js, react, typescript
領域
backend

調査の方向性

まず、共有の変換境界と href、start、data-skip-in-text の検索箇所を読みます。issue にはファイルパスやテストは記載されていません。属性値を保持したまま属性名を正規化し、リンク、順序付きリスト、スキップ注釈で、大文字と小文字が混在する属性が小文字の属性と同じ動作になることを確認します。これらのケースで、URL、番号付け、スキップされたテキストが期待どおりに保持されれば完了です。

索引モデルが issue の本文から書いたものです。

説明

What versions are you using? (if relevant)

Latest stable @react-email/render 2.2.0 and current canary branch 674d8ec2804b86be5d99156383fb1810179847bf both reproduce, with html5parser 3.0.0 and Node 24.13.0 (also reproduced on 22.16.0).

I also checked the published canary dist-tag, which currently resolves to 2.0.7-canary.0. That version predates unstableToPlainText and has no such export, so this feature-specific test is not applicable there. Its default converter handles the sample inputs correctly.

Describe the Bug

unstableToPlainText recognizes attribute names only when they are lowercase. Valid mixed-case HTML attributes lose their behavior: link URLs disappear from plain text, ordered-list start offsets become 1, and data-skip-in-text is not recognized. The default toPlainText handles these inputs correctly.

What is affected (leave empty if unsure)

Render Utility.

Link to the code that reproduces this issue

Self-contained reproduction below uses the public @react-email/render API; no provider credentials or email delivery are needed.

To Reproduce

Save this as repro.mjs:

import * as renderApi from '@react-email/render';

if (typeof renderApi.unstableToPlainText !== 'function') {
  console.log('unstableToPlainText is not available in this version');
}

const cases = [
  '<a HrEf="https://example.com/pay">Pay invoice</a>',
  '<ol StArT="5"><li>Five</li><li>Six</li></ol>',
  '<span DATA-SKIP-IN-TEXT="true">Preview</span>Body',
];

for (const html of cases) {
  console.log(JSON.stringify(renderApi.toPlainText(html)));
  if (typeof renderApi.unstableToPlainText === 'function') {
    console.log(JSON.stringify(renderApi.unstableToPlainText(html)));
  }
}

Run in a disposable directory:

npm init -y
npm install --save-exact @react-email/[email protected] [email protected] [email protected]
node repro.mjs
npm install --save-exact @react-email/[email protected]
node repro.mjs

Actual pairs on 2.2.0 (the older published canary prints the availability notice and stable results only):

"Pay invoice https://example.com/pay"
"Pay invoice"
" 5. Five\n 6. Six"
" 1. Five\n 2. Six"
"Body"
"PreviewBody"

Lowercasing only the attribute names makes the two converters agree in all three examples. The missing URL also occurs through render() with plainText: true, unstableTextConversion: true when a component includes the same HTML through dangerouslySetInnerHTML. Existing React-comment text in that rendering path is the separate issue #3864, not part of this report.

Expected Behavior

Attribute names are case-insensitive in HTML. These inputs should behave like their lowercase equivalents, preserving the URL, list numbering and skip annotation. Attribute values should keep their existing decoding/case behavior.

The parser preserves attribute names in its attributeMap, while the converter looks up only href, start and data-skip-in-text. Normalizing attribute names at the shared conversion boundary appears sufficient; no table-separator or default-converter change is needed. Attribute values should not be lowercased.

What's your node version? (if relevant)

24.13.0; also reproduced on 22.16.0.

Prepared with Codex using GPT-6.1 Sol at high reasoning.

主要言語
TypeScript
スター
19.9k
フォーク
1.1k
平均マージ
1日 15時間
マージ済み PR(30日)
49

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

resend/react-email のほかの issue

resend/react-email の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。