Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions app/javascript/markdown-it-container-speak.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.

if の条件分岐が少し多めに見えました👀
ネストも少し深くなっているので、どのパターンでどういう処理が走るのかを把握するのに少し時間がかかるかも?と感じました。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ご指摘ありがとうございます!
確かに条件分岐が多く、ネストも深くて理解しにくい状態でした。
早期リターンパターンでリファクタリングし、処理パターンが分かりやすいように修正いたしました。

Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,63 @@ import escapeHTML from './escapeHtml.js'

export default (md) => {
md.use(MarkdownItContainer, 'speak', {
render: (tokens, idx) => {
const speakerName = escapeHTML(tokens[idx].info)
.replace('speak @', '')
marker: ':',
validate: function (params) {
return params
.trim()
.match(/^speak(?:\s(?![(])|$|\s*\([^,]+,\s*[^)]+\)\s*$)/)
},
render: (tokens, idx) => {
const info = tokens[idx].info.trim()

if (tokens[idx].nesting !== 1) {
return '</div></div>\n'
}

const parenMatch = info.match(/^speak\s*\(\s*([^,]+)\s*,\s*([^)]+)\s*\)$/)
if (parenMatch) {
const speakerName = escapeHTML(parenMatch[1].trim())
const avatarUrl = escapeHTML(parenMatch[2].trim())

return `<div class="speak">
<div class="speak__speaker">
<span class="a-user-emoji-link">
<img src="${avatarUrl}" alt="${speakerName}" title="@${speakerName}" class="a-user-emoji speak__speaker-avatar">
<span class="speak__speaker-name">${speakerName}</span>
</span>
</div>
<div class="speak__body">`
}

const speakerName = escapeHTML(
info
.replace(/^speak[\s\n]*@?/, '')
.replace(/^\*\*/, '')
.replace(/\*\*$/, '')
.trim()
)

if (tokens[idx].nesting === 1) {
if (info.includes('@')) {
return `<div class="speak">
<div class="speak__speaker">
<a href="/users/${speakerName}" class="a-user-emoji-link">
<a href="/users/${encodeURIComponent(
speakerName
)}" class="a-user-emoji-link">
<img title="@${speakerName}" class="js-user-icon a-user-emoji" data-user="${speakerName}">
<span class="speak__speaker-name">${speakerName}</span>
</a>
</div>
<div class="speak__body">`
} else {
return '</div></div>\n'
}

return `<div class="speak">
<div class="speak__speaker">
<span class="a-user-emoji-link">
<img src="/images/users/avatars/default.png" alt="${speakerName}" title="${speakerName}" class="a-user-emoji speak__speaker-avatar">
<span class="speak__speaker-name">${speakerName}</span>
</span>
</div>
<div class="speak__body">`
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
font-weight: 700
.speak__speaker
margin-bottom: .75em
>a
& > a,
& > span
display: flex
align-items: center
gap: .5rem
Expand All @@ -78,6 +79,8 @@
>a:hover
.speak__speaker-name
text-decoration: underline
img
margin-bottom: 0
.speak__speaker-name
flex: 1
+text-block(1em 1.6, 700)
Expand Down
1 change: 1 addition & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@
t.integer "os"
t.boolean "trainee", default: false, null: false
t.text "retire_reason"
t.boolean "job_seeking", default: false, null: false
t.string "customer_id"
t.string "subscription_id"
t.boolean "mail_notification", default: true, null: false
Expand Down
35 changes: 35 additions & 0 deletions test/system/markdown_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,39 @@ def undo(selector)
assert_selector '.twitter-tweet'
assert_no_selector 'a.before-replacement-link-card[href="https://x.com/fjordbootcamp/status/1866097842483503117"]', visible: true
end

test 'speak block with arguments test' do
visit_with_auth new_page_path, 'machida'
fill_in 'page[title]', with: 'インタビュー'
fill_in 'page[body]', with: ":::speak(machida, https://avatars.githubusercontent.com/u/168265?v=4)\n## (名前, 画像URL)ver\n:::"

click_button 'Docを公開'

assert_css '.a-long-text.is-md.js-markdown-view'
assert_css '.speak'
assert_no_css "a[href='/users/machida']"

img = find('.speak__speaker img')
assert_includes img['src'], 'https://avatars.githubusercontent.com/u/168265?v=4'
assert_includes img['title'], 'machida'

name_span = find('.speak__speaker-name')
assert_includes name_span.text, 'machida'
end

test 'speak block without @ test' do
visit_with_auth new_page_path, 'machida'
fill_in 'page[title]', with: 'インタビュー'
fill_in 'page[body]', with: ":::speak username\n## 名前のみver\n:::"

click_button 'Docを公開'

assert_css '.a-long-text.is-md.js-markdown-view'
assert_css '.speak'
assert_no_css "a[href='/users/username']"

img = find('.speak__speaker img')
assert_includes img['src'], '/images/users/avatars/default.png'
assert_includes img['title'], 'username'
end
end