Skip to content

Fix: Fix line break issue in ChatGPT.#329

Merged
ujiro99 merged 4 commits intomainfrom
feat/fix-chatgpt-newline
Mar 15, 2026
Merged

Fix: Fix line break issue in ChatGPT.#329
ujiro99 merged 4 commits intomainfrom
feat/fix-chatgpt-newline

Conversation

@ujiro99
Copy link
Owner

@ujiro99 ujiro99 commented Mar 15, 2026

close #322

@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 25.39%. Comparing base (e8db6f5) to head (84dfbab).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #329      +/-   ##
==========================================
+ Coverage   25.17%   25.39%   +0.22%     
==========================================
  Files         323      323              
  Lines       31727    31738      +11     
  Branches     1535     1551      +16     
==========================================
+ Hits         7986     8059      +73     
+ Misses      23741    23679      -62     

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

@claude
Copy link

claude bot commented Mar 15, 2026

PR レビュー: Fix line break issue in ChatGPT (#329)

変更内容を確認しました。以下にフィードバックをまとめます。


✅ 良い点

  • 変更スコープが適切: 最小限の変更でバグを修正しており、過剰な実装がない。
  • コメントが英語で記述されている: CLAUDE.md のガイドライン通り。
  • 不要なセレクターの削除 (packages/hub/public/data/ai-services.json): ChatGPT が <textarea> ではなく contenteditable div(Lexical エディタ)を使用するようになったため、旧セレクター #main form textarea の削除は適切。

⚠️ 懸念点・改善提案

1. テキスト挿入の中間通知が欠けている可能性

ファイル: packages/extension/src/services/dom/inputUtils.ts
: 29-78(ループ全体)

現在のフローは以下の通りです:

  1. テキストセグメント1を DOM に直接挿入(通知なし)
  2. InputEvent("insertLineBreak") を dispatch → Lexical が処理
  3. テキストセグメント2を DOM に直接挿入(通知なし)
  4. ...繰り返し...
  5. 最後に Event("input") を dispatch(行81)

問題: insertLineBreak イベントが発火する前に、直前のテキスト挿入が Lexical に通知されていないため、Lexical が状態を正確に把握できない可能性があります。もし Lexical が DOM の MutationObserver ではなく イベント駆動でステートを管理している場合、insertLineBreak 処理時に内部状態とDOMが乖離する恐れがあります。

各テキストセグメント挿入後にも InputEvent を dispatch することを検討してください:

// After range.insertNode(node) block (around line 69)
el.dispatchEvent(new InputEvent("input", {
  inputType: "insertText",
  bubbles: true,
  cancelable: false,
}))

実際に修正が機能しているのであれば問題ありませんが、Lexical が MutationObserver でDOMを監視していることを確認・コメントに記載するとより明確になります。


2. typeShiftEnter のパラメーター型の不一致

ファイル: packages/extension/src/services/dom/inputUtils.ts
: 89, 104-109

async function typeShiftEnter(node: Node): Promise<void> {
  // ...
  const inputEvent = new InputEvent("input", {
    inputType: "insertLineBreak",
    bubbles: true,
    cancelable: false,
  })
  node.dispatchEvent(inputEvent)  // ← node は HTMLElement として渡されている
}

typeShiftEnternode: Node 型を受け取りますが、呼び出し元(行75)では el: HTMLElement を渡しています。型としては問題なく動作しますが、InputEvent は通常 Element に対して dispatch されるものです。Node 型よりも HTMLElement に型を絞ることで意図が明確になります。

// 修正案
async function typeShiftEnter(node: HTMLElement): Promise<void> {

3. テストが追加されていない

参照: packages/extension/src/services/dom/ ディレクトリ
既存例: packages/extension/src/services/dom/index.test.ts

CLAUDE.md では Vitest + jsdom を使用したテストの記述が推奨されており、既存の index.test.ts も同パターンで書かれています。inputUtils.ts に対するテストファイル(inputUtils.test.ts)が存在せず、今回の変更にもテストが追加されていません。

追加すべきテストケースの例:

// IU-01: inputContentEditable がテキスト挿入後に "input" イベントを dispatch する
// IU-02: typeShiftEnter が keydown に続いて inputType "insertLineBreak" の InputEvent を dispatch する
// IU-03: 複数行テキストを正しく処理し、各行間で typeShiftEnter が呼ばれる

4. legacyMode 時の最終 input イベント通知

ファイル: packages/extension/src/services/dom/inputUtils.ts
: 30-34, 81

if (legacyMode) {
  document.execCommand("insertText", false, val)
}

legacyMode(Perplexity AI 向け)でも行81の Event("input") が dispatch されます。execCommand はすでに input イベントを発火する実装もあります。二重に input イベントが発火することで問題が起きないかの確認が望ましいです。ただし、モダンブラウザでは execCommand の動作が非標準のため、実害はない可能性が高いです。


📋 まとめ

観点 評価
コード品質 ✅ 良好
バグ修正の妥当性 ✅ アプローチは正しい
セキュリティ ✅ 問題なし
テストカバレッジ ❌ テスト未追加
型安全性 ⚠️ 軽微な改善余地あり

主要な懸念はテストの欠如です。他の点は軽微ですが、特にテキスト中間通知の件はマルチライン入力の信頼性に関わる可能性があるため、動作確認の結果をコメントに記載いただけると助かります。

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Issue #322(ChatGPT で aiPrompt 実行時に改行が入らない/入力が遅い)に対応するため、ChatGPT の入力要素選択と contenteditable への入力通知イベントを調整するPRです。

Changes:

  • ChatGPT の入力要素 selector 候補を整理(hub 配信データ側)
  • contenteditable への入力後に input イベントを送出
  • Shift+Enter 相当時に insertLineBreak の InputEvent を送出

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/hub/public/data/ai-services.json ChatGPT の inputSelectors を簡素化し、誤検出しやすい候補を削除
packages/extension/src/services/dom/inputUtils.ts contenteditable 入力後/改行時にフレームワークへ通知するイベント送出を追加

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 76 to +109
@@ -95,4 +99,12 @@ async function typeShiftEnter(node: Node): Promise<void> {
cancelable: true,
})
node.dispatchEvent(down)

// Dispatch InputEvent to notify frameworks (e.g., Lexical) of the line break
const inputEvent = new InputEvent("input", {
inputType: "insertLineBreak",
bubbles: true,
cancelable: false,
})
node.dispatchEvent(inputEvent)
ujiro99 and others added 2 commits March 16, 2026 05:32
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@claude
Copy link

claude bot commented Mar 15, 2026

PR #329 コードレビュー: Fix line break issue in ChatGPT

概要

このPRはissue #322「aiPrompt実行時、ChatGPTでは改行が入らない」を修正するもので、以下の2ファイルを変更しています。

  • packages/extension/src/services/dom/inputUtils.ts — InputEvent の dispatch を追加
  • packages/hub/public/data/ai-services.json — ChatGPT の古いセレクターを削除

修正のアプローチは適切で、変更スコープも最小限に抑えられています。ただし、いくつか指摘事項があります。


指摘事項

重要 1. フォールバック定義との不整合

ファイル: packages/extension/src/services/aiPrompt.ts(AI_SERVICES_FALLBACK 付近)

packages/hub/public/data/ai-services.json から "#main form textarea" セレクターを削除しているにもかかわらず、拡張機能側のハードコードされたフォールバックリスト AI_SERVICES_FALLBACK には同セレクターが残ったままと思われます。

外部JSONの取得失敗・当日キャッシュ未生成の両方のケースで AI_SERVICES_FALLBACK が使われます。具体的には以下のシナリオで旧セレクターが適用されてしまいます。

  • ユーザーがオフラインの場合
  • HUBサーバーが応答しない場合
  • 拡張機能インストール直後(キャッシュが存在しない)

#main form textarea が古い textarea 要素を指していて、Lexical ベースの contenteditable div よりも先にマッチしてしまうと、今回のイベント修正の効果がフォールバック時に全く発揮されないことになります。AI_SERVICES_FALLBACK からも同セレクターを削除することを推奨します。


重要 2. keydown のキャンセル状態を無視して InputEvent を dispatch している

ファイル: packages/extension/src/services/dom/inputUtils.ts、typeShiftEnter 関数内

dispatchEvent() は、イベントリスナーが preventDefault() を呼んだ場合に false を返します。keydown が cancelable: true で dispatch されているにもかかわらず、その戻り値を確認せずに無条件で insertLineBreak の InputEvent を送っています。

ページ側のスクリプトが keydown をキャンセルするケースでは、実際には改行が挿入されないにもかかわらず insertLineBreak イベントだけが発火し、フレームワークの内部状態とDOMの間に不整合が生じる可能性があります。

修正案として、node.dispatchEvent(down) の戻り値が true の場合のみ InputEvent を dispatch するよう修正することを推奨します。


推奨 3. inputContentEditable での InputEvent の data フィールド

ファイル: packages/extension/src/services/dom/inputUtils.ts、inputContentEditable 関数内

data フィールドに渡している value は改行文字を含む元の文字列全体です。もし Lexical がこの data を使って状態更新を行う場合、改行文字を含む文字列を受け取ることで予期しない動作になる可能性があります。

フレームワークが data を参照する際の挙動を確認した上で、コメントで意図を明示することを推奨します。


推奨 4. テストが追加されていない

ファイル: packages/extension/src/services/dom/ ディレクトリ

今回追加された InputEvent dispatch のロジックには対応するテストが存在しません。今回のような「イベントディスパッチ挙動の変更」はAIプロンプト入力の主要経路に関わるため、回帰リスクが高い変更です。

追加すべきテストケースの例:

  • inputContentEditable がテキスト挿入後に inputType "insertText" の InputEvent を dispatch することの検証
  • typeShiftEnter が keydown に続いて inputType "insertLineBreak" の InputEvent を dispatch することの検証
  • 複数行テキストを正しく処理することの検証

軽微 5. typeShiftEnter の引数型

ファイル: packages/extension/src/services/dom/inputUtils.ts、typeShiftEnter 関数定義

この関数は Node 型を受け取りますが、呼び出し元では HTMLElement を渡しており、InputEvent は通常 Element を対象とします。引数を HTMLElement に絞ることで意図が明確になります。


確認 6. legacyMode 時の input イベントの二重発火

ファイル: packages/extension/src/services/dom/inputUtils.ts、legacyMode 分岐

document.execCommand("insertText", ...) はブラウザによっては input イベントを自動発火します。追加された InputEvent dispatch と合わせて二重発火になる可能性があります。念のため確認・コメントを追加することを推奨します。


まとめ

観点 評価
バグ修正の方針 適切 (InputEvent dispatch によるLexicalへの通知)
コードスタイル 適切 (コメントが英語で記述、命名規則も問題なし)
フォールバック整合性 要確認 (AI_SERVICES_FALLBACK との不整合の可能性)
イベントキャンセル考慮 要改善 (keydown の戻り値未確認)
テストカバレッジ 未追加
型安全性 軽微な改善余地あり

最も重要な修正は 指摘事項1(フォールバック定義との不整合) です。AI_SERVICES_FALLBACK を更新しないと、キャッシュが存在しないユーザー環境では今回の修正が全く効かない状況が続く可能性があります。

Reviewed by Claude Sonnet 4.6

@claude
Copy link

claude bot commented Mar 15, 2026

PRレビュー

このPRはChatGPTの改行問題(#322)を修正するもので、全体的なアプローチは適切です。


重要な問題

1. InputEvent.data にマルチライン文字列を渡している
ファイル: packages/extension/src/services/dom/inputUtils.ts L81-87

InputEventdata フィールドは、その一回のイベントで実際に挿入されたテキストを表すものです。しかし現在の実装では元の value\n を含む)がそのまま渡されています。Lexical が e.data を使って内部ステートを更新する場合、改行を含む文字列が渡されることで二重入力や不正な状態になる可能性があります。改行は typeShiftEnter 内の insertLineBreak イベントで別途通知されているため、data フィールドは改行を含まない文字列(例: values[values.length - 1])または null にすることを検討してください。


中程度の問題

2. ai-services.jsonaiPrompt.ts の Perplexity セクションが非同期の可能性
ファイル: packages/extension/src/services/aiPrompt.ts L77-82 vs packages/hub/public/data/ai-services.json

aiPrompt.ts の Perplexity submitSelectors に2つの新しいセレクタが追加されましたが、ai-services.json のdiffにはこの変更が含まれていません。両ファイルが同期されているべきであれば、JSONファイルも更新が必要です。


軽微な指摘

3. typeShiftEnterkeyup イベントがない
ファイル: packages/extension/src/services/dom/inputUtils.ts L95-116

実際のキーボード操作では keydownkeyup の順でイベントが発火しますが、現状は keydown のみ発火しています。Lexical が keyup も必要とするケースでは問題が起きる可能性があります。意図的であれば、コメントで明示することを推奨します。

4. #main form textarea 削除の理由がコードに記載されていない
ファイル: packages/extension/src/services/aiPrompt.ts L30-35

将来の開発者が理由を把握できるよう、ChatGPT が contenteditable ベースの入力に移行したという簡単なコメントを追加することを推奨します。


良い点

  • InputEvent を使ってフレームワーク(Lexical)に変更を通知するアプローチは理にかなっています
  • テストケースが12件追加され、ICE-01ICE-12 の命名規則もCLAUDE.mdのガイドラインに準拠しています
  • beforeEach / afterEach でDOMのクリーンアップが適切に行われています
  • ICE-09でrangeCount=0のブランチが明示的にテストされており、カバレッジの意識が高い

テストの補足指摘

ファイル: packages/extension/src/services/dom/inputUtils.test.ts L73-87 (ICE-05)

ICE-05では value = "hello" (改行なし) のみテストしています。マルチライン値の場合に data フィールドがどう扱われるかのテストがあると、問題1をより明確に検証できます。

ファイル: packages/extension/src/services/dom/inputUtils.test.ts L165-172 (ICE-10)

ICE-10 (legacyMode + 改行) では execCommand の呼び出し検証はありますが、InputEvent のdispatch検証が抜けています。legacyModeでも InputEvent はdispatchされるため(inputUtils.ts:81-87)、テストに含めることを推奨します。

interval > 0 のテストがない: sleep を伴う非同期パスのテストが存在しません。タイミングに依存する動作を将来変更する際のリグレッション検出のため、追加を検討してください。

@ujiro99 ujiro99 merged commit 80e6f02 into main Mar 15, 2026
6 checks passed
@ujiro99 ujiro99 deleted the feat/fix-chatgpt-newline branch March 15, 2026 20:49
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.

aiPrompt実行時、ChatGPTでは改行が入らない。また、入力速度も遅い。

2 participants