Skip to content

Markdownエディタ内で許可されているタグ、属性以外を使えないようにした#8450

Open
ghost wants to merge 52 commits intomainfrom
feature/prohibit-style-tag-and-onload-event-in-markdown
Open

Markdownエディタ内で許可されているタグ、属性以外を使えないようにした#8450
ghost wants to merge 52 commits intomainfrom
feature/prohibit-style-tag-and-onload-event-in-markdown

Conversation

@ghost
Copy link
Copy Markdown

@ghost ghost commented Mar 15, 2025

Issue

概要

Markdownエディタ内で、許可されているタグ、属性以外を使えないようにしました。

変更確認方法

  1. feature/prohibit-style-tag-and-onload-event-in-markdownをローカルに取り込む
    i. git fetch origin feature/prohibit-style-tag-and-onload-event-in-markdown
    ii. git checkout feature/prohibit-style-tag-and-onload-event-in-markdown
  2. foreman start -f Procfile.devで開発環境を立ち上げる.
  3. ユーザー名komagata、パスワードtesttestでログインする
  4. ドキュメント新規作成ページに移動する
  5. 本文に以下のように入力してDocを公開する(タイトルは適当でよい)
    • 許可されているタグ、属性以外は使えないが以下は代表的なタグ、属性として選出
<style>p { background: red; }</style>
<iframe onload=alert("XSS")></iframe>
  1. 公開後、許可していない上記のタグ、属性を含んだものはサニタイズされ表示されないことを確認する

Movie

変更前

development.Docs._.FBC.-.Google.Chrome.2025-04-22.18-28-42.mp4

変更後

development.Docs._.FBC.-.Google.Chrome.2025-06-01.20-44-41.mp4

Summary by CodeRabbit

  • 新機能

    • Markdownレンダリング時にHTMLサニタイズが追加され、危険なスクリプトやリンクが自動的に除去されます。
  • バグ修正 / 改善

    • 許可されたHTMLタグ(例:blockquote)やstyle属性は保持されます。
    • コメント保存後に生の表示が正しく更新されるようになりました。
    • トレーニングページのFAQ表示はカテゴリ未設定時に空配列でフォールバックします(表示ロジックが変更)。
  • スタイル

    • プレースホルダ表示と強調(em)の既定スタイルが調整されました。
  • テスト

    • HTMLサニタイズと許可タグ/属性の動作を確認するシステムテストが追加されました。

@ghost ghost marked this pull request as ready for review March 15, 2025 21:08
@ghost
Copy link
Copy Markdown
Author

ghost commented Mar 15, 2025

@SuzukiShuntarou
お疲れ様です!
こちらのPRについて、レビューをお願いさせていただきました
よろしくお願いいたします🙏

@SuzukiShuntarou
Copy link
Copy Markdown
Contributor

SuzukiShuntarou commented Mar 16, 2025

@harada-webdev
お疲れ様です!申し訳ございません。🙇‍♀️
ただいま別issueのレビュー中で対応が難しいです。もし可能であれば他の方に依頼いただけないでしょうか?🙏

@ghost
Copy link
Copy Markdown
Author

ghost commented Mar 16, 2025

@SuzukiShuntarou
承知しました!
では、また別の機会でよろしくお願いいたします🙏

@SuzukiShuntarou
Copy link
Copy Markdown
Contributor

@harada-webdev
断ってしまって申し訳ないです🙇‍♀️
もし他の方も難しい場合は再度ご連絡ください!

@sekito1107 sekito1107 force-pushed the feature/prohibit-style-tag-and-onload-event-in-markdown branch 5 times, most recently from 96418e0 to d1b6e63 Compare April 22, 2025 10:07
@sekito1107
Copy link
Copy Markdown
Contributor

@sugiwe

良ければこちらのレビューお願いできないでしょうかー😀
急いではいませんのでご検討いただけると嬉しいですー👍

@sekito1107 sekito1107 requested a review from sugiwe April 22, 2025 10:56
@sugiwe
Copy link
Copy Markdown
Contributor

sugiwe commented Apr 23, 2025

@sekito1107
お疲れ様です☕️ レビュー依頼ありがとうございます、承知しました!
1週間前後お時間いただいてもよろしいでしょうか。
どうぞよろしくお願いします!

@sekito1107
Copy link
Copy Markdown
Contributor

@sugiwe
是非よろしくお願いしますー🙏

Copy link
Copy Markdown
Contributor

@sugiwe sugiwe left a comment

Choose a reason for hiding this comment

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

@sekito1107
お待たせいたしました!レビューいたしました。

動作は無事確認できまして、内容についても全体的に問題ないように思います🙆
文章が長くなってしまい恐縮なのですが命名関連で2箇所と、テストについて1箇所コメントをさせていただきましたので、ご確認お願いいたします🙏

const escapeTags = ['style']
const escapeAttributes = ['onload']

md.core.ruler.push('sanitize', function (state) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sanitizeというルール名は、シンプルさはとても良いのですがhtmlタグも含めた全てを除去することを連想してしまうかもしれないと思いました👀
特に、issueの方も拝見しましたが今回は「あえてhtmlタグは除外しない」という点が特徴だと思いますので、issue・PRのタイトルになっているstyle・onloadを除外することを明示的に名前にするのが良いかなと思ったのですがいかがでしょうか?(例えば、ちゃんと説明するならescape_style_and_onload、少し省略するならescape_style_onloadなど)

またこれに関連して、ファイル名のmarkdown-it-sanitizer.jsについても検討の余地があるかもしれないと思いました。
全く同名の markdown-it-sanitizer というnpmがあるので、今回のissueからの文脈を把握していれば良いのですが、将来的にコードだけを見た時に「なぜnpmのmarkdown-it-sanitizerを使わずに自前のコードになっているのだろう」と疑問を持たれるかもしれません。
(何を隠そう、僕が「なんでnpmのmarkdown-it-sanitizerを剥がして自前にしたんだろう?」と疑問に思ってしまいました。今回でいうとissueをしっかり読まずにPRとコードの方を先に読んでしまった僕が悪いのですが😂)

なので、ルール名の方に合わせるなどして、例えばですがmarkdown-it-escape-style-and-onload.jsなどはいかがでしょうか?
(少し長いような気もしていますが現時点で他にmarkdown-it-task-lists-initializer.jsといったファイルもあるので、個人的には長めでも具体的な名前のほうが良いかなとは思いますが、長さの塩梅についてはお任せいたします🙏)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

両方の命名、結構僕もしっくりきてないところありました!

ファイル名の背景なのですが、同名のnpmがあることはこのIssueが元々そのnpmを利用する予定だったので存じていました。
しかし最終公開が9年前ということもあり問題ないかと思ったのですが、今確認してみると週当たりのダウンロード数は未だに多いようなので、おっしゃって頂いているように変更するのは妥当な選択かと思いました。

ご提案頂いたファイルの命名についてはIssueの内容を良く表していると思う一方で、現在はstyleタグとonload属性だけをエスケープしていますが、後々回避したいタグ、属性が増えることを予想して簡単にエスケープ対象を追加出来るように設計したので、ある程度汎用性を持たせた名前にしておかないと回避するタグ、属性が増えた際にまたファイル名を変更しなくてはいけないという問題があると思っています。

ルール名をescapeにしてファイル名をmarkdown-it-escapeくらいにしてまとめるのが落としどころとして良いのではないかと思うのですがいかがでしょうか?

こちらは今回の修正に含めず、合意を得られる形を見つけてから修正したいと思いますー。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@sekito1107
なるほどです、今後のカスタマイズを見越しての命名だったのですね。確かにmarkdown-it-escape-style-and-onloadにしてしまうとカスタマイズに伴ってまた名前を変更しなくてはいけないし、この命名ルールだと回避する要素がどんどん名前に連なっていくことになり、ちょっと厳しいですね💦

同名npmのmarkdown-it-sanitizerを避けてmarkdown-it-escapeにするアイデア、とても良いと思いました!

const parser = new DOMParser()
const doc = parser.parseFromString(`<body>${html}</body>`, 'text/html')

doc.querySelectorAll('*').forEach((el) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

elelementの略称かと思います、認知度も高く一般的な略称かとは思うのですが、bootcampアプリ内では今では数の減ったvue.js関連ファイル以外ではほぼelではなくelementを使っているようでしたので、コードが少し長くはなるもののelementに揃えるのが良いかなと思いましたがいかがでしょうか?
(nitsで個人的な感想な気もしているので、elでも全然大丈夫だとは思います!)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

他のjavascriptの実装まで確認して頂いたのですね!ありがとうございます!
プロジェクトとしては、たしかに揃ってるほうが可読性としては優れていると思いますので、修正させて頂きました!

Comment on lines +45 to +48
color = page.evaluate_script(<<~JS)
getComputedStyle(document.querySelector('p')).color
JS
assert_not_equal 'rgb(255, 0, 0)', color
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

こちらの部分ですが、実際に表示されているCSSのカラーをJSで取得して、「赤が表示されていない」ことを確認しているテストとお見受けしています。
色を実際に確認しているのは非常に丁寧で良いなと思ったのですが、assert_text '<style>p { color: red; }</style>'によって{ color: red; }がエスケープされ文字列のまま表示されていることは保証できているので、その上でJSを使って色を取得し確認する、ということまでしなくても良いかもしれないと思いましたがいかがでしょうか?

最近、システムテストをどこまで書くかというQAもあり、明確な定義は難しいという回答もありましたが、今回でいうとassert_textの方でエスケープされた表示を確認できれば良いかな?と感じました。

僕が掴めていない意図などもあるかもしれませんのでその場合は何なりとおっしゃってください、ご検討よろしくお願いいたします🙏

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

その通りですね、過剰な検証だったと思いますー。
こちらエスケープされてることだけを確認するように、修正させて頂きました👍

@sugiwe sugiwe self-requested a review May 1, 2025 09:06
Copy link
Copy Markdown
Contributor

@sekito1107 sekito1107 left a comment

Choose a reason for hiding this comment

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

@sugiwe
丁寧なレビューありがとうございます、大変参考になりました🙇‍♂️
修正と併せて、1点命名についてご相談させて頂いたので確認して頂ければと思います🙏

const escapeTags = ['style']
const escapeAttributes = ['onload']

md.core.ruler.push('sanitize', function (state) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

両方の命名、結構僕もしっくりきてないところありました!

ファイル名の背景なのですが、同名のnpmがあることはこのIssueが元々そのnpmを利用する予定だったので存じていました。
しかし最終公開が9年前ということもあり問題ないかと思ったのですが、今確認してみると週当たりのダウンロード数は未だに多いようなので、おっしゃって頂いているように変更するのは妥当な選択かと思いました。

ご提案頂いたファイルの命名についてはIssueの内容を良く表していると思う一方で、現在はstyleタグとonload属性だけをエスケープしていますが、後々回避したいタグ、属性が増えることを予想して簡単にエスケープ対象を追加出来るように設計したので、ある程度汎用性を持たせた名前にしておかないと回避するタグ、属性が増えた際にまたファイル名を変更しなくてはいけないという問題があると思っています。

ルール名をescapeにしてファイル名をmarkdown-it-escapeくらいにしてまとめるのが落としどころとして良いのではないかと思うのですがいかがでしょうか?

こちらは今回の修正に含めず、合意を得られる形を見つけてから修正したいと思いますー。

const parser = new DOMParser()
const doc = parser.parseFromString(`<body>${html}</body>`, 'text/html')

doc.querySelectorAll('*').forEach((el) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

他のjavascriptの実装まで確認して頂いたのですね!ありがとうございます!
プロジェクトとしては、たしかに揃ってるほうが可読性としては優れていると思いますので、修正させて頂きました!

Comment on lines +45 to +48
color = page.evaluate_script(<<~JS)
getComputedStyle(document.querySelector('p')).color
JS
assert_not_equal 'rgb(255, 0, 0)', color
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

その通りですね、過剰な検証だったと思いますー。
こちらエスケープされてることだけを確認するように、修正させて頂きました👍

@sugiwe
Copy link
Copy Markdown
Contributor

sugiwe commented May 2, 2025

@sekito1107
ご連絡ありがとうございます、修正箇所を確認しました!
命名の部分もお返事しましたので、ご確認お願いいたします✨

@sekito1107
Copy link
Copy Markdown
Contributor

@sugiwe
返信ありがとうございます!
前回修正に含めなかった命名の部分、修正させて頂きましたのでご確認お願いしますー🙏

Copy link
Copy Markdown
Contributor

@sugiwe sugiwe left a comment

Choose a reason for hiding this comment

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

@sekito1107
修正ありがとうございます、確認いたしました!
問題ないと思いますのでApproveとさせていただきます〜!

@sekito1107
Copy link
Copy Markdown
Contributor

@sugiwe
レビューありがとうございました!

@sekito1107 sekito1107 force-pushed the feature/prohibit-style-tag-and-onload-event-in-markdown branch from dc1cd90 to c99701c Compare May 19, 2025 03:58
@sekito1107
Copy link
Copy Markdown
Contributor

@kutimiti1234

こちらレビューお願いできないでしょうかー。
ご検討よろしくお願いします🙇

@sekito1107 sekito1107 requested a review from kutimiti1234 May 27, 2025 12:41
@kutimiti1234
Copy link
Copy Markdown
Contributor

kutimiti1234 commented May 27, 2025

@sekito1107 さん
先程はdiscord上でご連絡ありがとうございました。
こちら6月1日(日)までお待ちいただくかもしれませんが、そちらで良ければレビューさせていただきたいと思います。

@sekito1107
Copy link
Copy Markdown
Contributor

@kutimiti1234
期間については特に急いでませんので、お願いできればと思います

宜しくお願いしますー!

@sekito1107 sekito1107 force-pushed the feature/prohibit-style-tag-and-onload-event-in-markdown branch from dcfd371 to c58da0e Compare August 27, 2025 08:24
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dcfd371 and c58da0e.

📒 Files selected for processing (7)
  • app/controllers/welcome_controller.rb (1 hunks)
  • app/javascript/initializeComment.js (2 hunks)
  • app/javascript/markdown-initializer.js (2 hunks)
  • app/javascript/new-comment.js (1 hunks)
  • app/javascript/packs/application.js (1 hunks)
  • app/javascript/stylesheets/initializers/_reset.sass (0 hunks)
  • app/javascript/textarea-initializer.js (2 hunks)
💤 Files with no reviewable changes (1)
  • app/javascript/stylesheets/initializers/_reset.sass
✅ Files skipped from review due to trivial changes (1)
  • app/javascript/new-comment.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/javascript/markdown-initializer.js
  • app/javascript/textarea-initializer.js
🧰 Additional context used
📓 Path-based instructions (2)
**/*.js

⚙️ CodeRabbit configuration file

**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。

  • fetchメソッドの代わりにrequest.jsを使う。

Files:

  • app/javascript/packs/application.js
  • app/javascript/initializeComment.js
**/*.rb

⚙️ CodeRabbit configuration file

**/*.rb: # refactoring

  • まずFat Controllerを避け、次にFat Modelを避ける。
  • Serviceクラスの乱用を避ける。
  • controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。

Rails Patterns

  • ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
  • 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
  • Viewにpartialを作る場合はViewComponentを使うことを検討する。
  • 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
  • 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)

Files:

  • app/controllers/welcome_controller.rb
🧠 Learnings (1)
📓 Common learnings
Learnt from: tyrrell-IH
PR: fjordllc/bootcamp#8807
File: app/views/welcome/job_support.html.slim:391-392
Timestamp: 2025-06-21T22:30:20.116Z
Learning: このプロジェクトにはRailsの組み込みmarkdownヘルパが利用できないため、markdownのHTML変換には自前でヘルパを実装する必要がある。
🧬 Code graph analysis (1)
app/javascript/initializeComment.js (1)
app/javascript/new-comment.js (3)
  • markdownInitializer (38-38)
  • commentEditorPreview (41-43)
  • editorTextarea (44-46)
🪛 ESLint
app/javascript/packs/application.js

[error] 87-87: 'VueMounter' is defined but never used.

(no-unused-vars)


[error] 88-88: 'Questions' is defined but never used.

(no-unused-vars)


[error] 89-89: 'UserProducts' is defined but never used.

(no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test

Comment on lines +40 to 41
@faqs = FAQCategory.find_by(name: FAQ_CATEGORY_NAME)&.faqs || []
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

未定義定数 FAQ_CATEGORY_NAME を参照しています。元のヘルパを使って順序と戻り値型の整合も維持しましょう。

  • FAQ_CATEGORY_NAME は本クラスに未定義で NameError になります。
  • さらに faqs_for を介さないことで order(:position) が失われ、FAQ.none ではなく [] が返るため型(Relation→Array)が不一致になります。

修正案(定数・順序・型の整合を復元):

-    @faqs = FAQCategory.find_by(name: FAQ_CATEGORY_NAME)&.faqs || []
+    @faqs = faqs_for(FAQ_CATEGORY_NAME_FOR_TRAINING)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@faqs = FAQCategory.find_by(name: FAQ_CATEGORY_NAME)&.faqs || []
end
@faqs = faqs_for(FAQ_CATEGORY_NAME_FOR_TRAINING)
end
🤖 Prompt for AI Agents
In app/controllers/welcome_controller.rb around lines 40-41, the code directly
references an undefined constant FAQ_CATEGORY_NAME and bypasses the existing
faqs_for helper (losing order and returning an Array instead of an
ActiveRecord::Relation). Replace the direct find_by fallback with a call to the
existing faqs_for helper so the category lookup, order(:position) and relation
type are preserved; if FAQ_CATEGORY_NAME must be used, reference or define it
from the module where it lives (or pass the appropriate category name/symbol
into faqs_for) so no NameError occurs and the returned value remains an
ActiveRecord::Relation, not [].

const commentDisplay = comment.querySelector('.js-comment-display')
const commentDisplayContent =
commentDisplay?.querySelector('.js-comment-html')
const commentDisplayContent = commentDisplay?.querySelector('.js-comment-html')
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

commentRaw/commentDisplayContent が存在しない場合に保存時に例外が発生します。null安全な参照に修正を。

  • 行83: commentRaw が null の時に textContent 参照でクラッシュします。
  • 行25, 32-34: 取得時は optional chaining を統一し、後段の参照もnull安全に。

最小修正案:

-const commentRaw = commentDisplay.querySelector(
+const commentRaw = commentDisplay?.querySelector(
   '.js-comment-raw'
 )
-      commentRaw.textContent = editorTextarea.value
+      commentRaw?.textContent = editorTextarea.value

加えて(選択肢、推奨)保存後のHTML更新もnull安全にしてください(該当行は変更外ですが重要):

// 82行あたり
if (commentDisplayContent) {
  commentDisplayContent.innerHTML = markdownInitializer.render(savedComment)
}

(任意だが有益)nullを配列に含めていると toggleVisibility が落ちます。nullを除外する実装にすると堅牢です:

// 関数 toggleVisibility
function toggleVisibility(elements, className) {
  elements.filter(Boolean).forEach((el) => el.classList.toggle(className))
}

(任意の改善)fetchの代わりに @rails/request.js を使うガイドラインがあります。updateComment/deleteComment の置き換えを検討ください。

Also applies to: 32-34, 83-83

🤖 Prompt for AI Agents
In app/javascript/initializeComment.js around lines 25, 32-34 and 83, references
to commentRaw/commentDisplayContent can be null and currently cause exceptions;
make the DOM queries and subsequent accesses null-safe by using optional
chaining when selecting elements (e.g., commentDisplay?.querySelector(...)) and
guard all downstream property accesses (like textContent) with null checks or
optional chaining before using them; also update the post-save HTML update to
only set innerHTML when commentDisplayContent exists, and consider filtering out
null values passed to toggleVisibility so it ignores falsey entries (e.g.,
elements.filter(Boolean).forEach(...)).

Comment on lines +87 to +89
import VueMounter from '../VueMounter.js'
import Questions from '../components/questions.vue'
import UserProducts from '../components/user-products.vue'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

未使用のVue関連インポートでESLintエラー。用途がなければ削除、使うなら実際にマウントしてください。

ESLint: no-unused-vars が3件。このままではCIを落とします。現時点で参照されていないため削除が安全です。将来使用する場合は VueMounter でマウントする等、使用箇所を追加してください。

適用案(未使用のインポートを削除):

-import VueMounter from '../VueMounter.js'
-import Questions from '../components/questions.vue'
-import UserProducts from '../components/user-products.vue'

補足: 本PRの目的(Markdownサニタイズ)と無関係なVueコードの追加は、ガイドライン「どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない」にも抵触します。別PR分割を推奨します。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import VueMounter from '../VueMounter.js'
import Questions from '../components/questions.vue'
import UserProducts from '../components/user-products.vue'
🧰 Tools
🪛 ESLint

[error] 87-87: 'VueMounter' is defined but never used.

(no-unused-vars)


[error] 88-88: 'Questions' is defined but never used.

(no-unused-vars)


[error] 89-89: 'UserProducts' is defined but never used.

(no-unused-vars)

🤖 Prompt for AI Agents
In app/javascript/packs/application.js around lines 87 to 89, there are three
unused Vue-related imports (VueMounter, Questions, UserProducts) causing ESLint
no-unused-vars failures; remove these unused import lines to satisfy linting (or
if you intend to use them in this PR, instead call VueMounter to mount the
components where appropriate). Ensure the final change either deletes the three
import statements or replaces them with actual mounting code using VueMounter so
the imports are referenced; keep this PR focused on Markdown sanitization and
move any new Vue additions to a separate PR if not needed here.

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.

9 participants