Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Qiita / Qiita:Team における Markdown レンダリングの歴史
Search
Yuji Nakayama
August 29, 2017
Technology
9
11k
Qiita / Qiita:Team における Markdown レンダリングの歴史
Markdown Night 2017 Summer
https://connpass.com/event/63383/
Yuji Nakayama
August 29, 2017
Tweet
Share
More Decks by Yuji Nakayama
See All by Yuji Nakayama
How the RSpec team and I built the smooth upgrade process for RSpec 3
yujinakayama
0
220
Other Decks in Technology
See All in Technology
監視のこれまでとこれから/sakura monitoring seminar 2025
fujiwara3
11
3.9k
Tech-Verse 2025 Keynote
lycorptech_jp
PRO
0
110
Кто отправит outbox? Валентин Удальцов, автор канала Пых
lamodatech
0
340
Amazon Bedrockで実現する 新たな学習体験
kzkmaeda
2
550
rubygem開発で鍛える設計力
joker1007
2
200
PostgreSQL 18 cancel request key長の変更とRailsへの関連
yahonda
0
120
なぜ私はいま、ここにいるのか? #もがく中堅デザイナー #プロダクトデザイナー
bengo4com
0
440
GitHub Copilot の概要
tomokusaba
1
130
Lambda Web Adapterについて自分なりに理解してみた
smt7174
3
110
セキュリティの民主化は何故必要なのか_AWS WAF 運用の 10 の苦悩から学ぶ
yoh
1
150
本が全く読めなかった過去の自分へ
genshun9
0
420
mrubyと micro-ROSが繋ぐロボットの世界
kishima
2
290
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
93
6.1k
Side Projects
sachag
455
42k
Bash Introduction
62gerente
614
210k
Raft: Consensus for Rubyists
vanstee
140
7k
Thoughts on Productivity
jonyablonski
69
4.7k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
17
940
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
Why Our Code Smells
bkeepers
PRO
337
57k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Transcript
2JJUB2JJUB5FBNʹ͓͚Δ .BSLEPXOϨϯμϦϯάͷྺ࢙ Yuji Nakayama @nkym37 @yujinakayama
None
None
None
None
None
࠷ॳQ&AαʔϏεͩͬͨ
None
࠷ॳ MarkdownະରԠͩͬͨ
ࠓ͢͜ͱ .BSLEPXOυΩϡϝϯτΛϗετ͢Δ8FCαʔϏεΛӡ Ӧ͢Δ্Ͱ໘͖ͯͨ͠ɺ.BSLEPXOϨϯμϥʔपΓͷ టष͍ࣄ
2JJUBͷॳظͷ.BSLEPXOαϙʔτ ݄ 2JJUBϦϦʔεͷϲ݄ޙ
ॳظͷ2JJUBͷ.BSLEPXOϨϯμϥʔ w ࣮SFEDBSQFU ΧελϜϨϯμϥʔ w SFEDBSQFU$Ͱॻ͔Εͨ.BSLEPXOύʔαʔͷSVCZHFN w ࣌ͷ(JU)VC'MBWPSFE.BSLEPXOͷ࣮SFEDBSQFUͷ ϕʔεͰ͋ΔTVOEPXOΛϕʔεʹ͍ͯͨ͠ʢͱࢥΘΕΔʣ w
·ͩ$PNNPO.BSLͳ͔ͬͨ
class Qiita::Markdown::Renderer < Redcarpet::Render::HTML # ... end renderer = Qiita::Markdown::Renderer(
filter_html: true, hard_wrap: true ) parser = Redcarpet::Markdown.new( renderer, autolink: true, fenced_code_blocks: true ) html = parser.render(markdown)
ॳظͷ༷ w ༷తʹ(JU)VC'MBWPSFE.BSLEPXOʹد͍ͤͯͨ w BVUPMJOL63-ͬΆ͍จࣈྻΛࣗಈͰϦϯΫʹ w GFODFE@DPEF@CMPDLT```\nsome code\n``` w IBSE@XSBQ.BSLEPXOͷվߦͰ<br>ग़ྗ
w ΧελϜϨϯμϥʔͰγϯλοΫεϋΠϥΠτ w ͷͪʹଧͪফ͠ઢςʔϒϧه๏ʹରԠ
ϝϯγϣϯه๏ͷಋೖ ݄ @username
2JJUB5FBNϦϦʔε ݄ αχλΠζͷϧʔϧ͕2JJUBͱएׯҟͳΔ
ֆจࣈͷαϙʔτ ݄ :tada:
qiita-markdown gem ݄
qiita-markdown gem w IUNMQJQFMJOF SFEDBSQFU OPLPHJSJ w IUNMQJQFMJOF)5.-ॲཧͷ3VCZϑϨʔϜϫʔΫ w ίΞϨϯμϥʔͱͯ͠SFEDBSQFUΛ͍ɺͦͷग़ྗʹର͠
ͯෳͷϑΟϧλʔʹΑΔޙॲཧΛద༻ w 044Խ
Redcarpet filter Emoji filter Syntax highlight filter Mention filter Markdown
string HTML tree HTML tree HTML tree HTML tree HTML tree HTML tree HTML tree
IUNMQJQFMJOFͷԿ͕خ͍͔͠ w ͝ͱʹϑΟϧλʔΛ͚ΒΕΔͷͰɺίʔυͷݟ௨͕͠ྑ͘ͳΔ w ϑΟϧλʔͷద༻ॱং͕໌֬ w جຊσʔλߏͱͯ͠OPLPHJSJͷ)5.-USFFΛ࠾༻͍ͯ͠ΔͨΊ )5.-ͷૢ࡞͕ݎ࿚ w ҎલͷϨϯμϥʔͰҰ෦ਖ਼نදݱΛ͍ͬͯΔՕॴ͕͋ͬͨ
ϢʔβʔͷաڈͷίϝϯτҰཡ ݄
None
None
ίϝϯτҰཡΛදࣔ͢Δ w هࣄҰཡͳΒλΠτϧΛදࣔ͢Εྑ͍͕ɺίϝϯτʹ λΠτϧ͕ͳ͍ͷͰɺຊจͷཁΛදࣔ͢Δඞཁ͕͋Δ w ͗͢ΔίϝϯτશจΛදࣔͨ͘͠ͳ͍ w ཁͱͯ͠දࣔ͢Δͷ͕͍͠ɺෳࡶͳϚʔΫΞοϓΛऔ Γআ͖͍ͨ
None
Qiita::Markdown::SummaryProcessor w ϒϩοΫཁૉͷதͭͭ͠λάΛআ͢Δ͜ͱͰɺΠϯϥΠϯԽ •<p>foo<em>bar</em></p>ˠfoo<em>bar</em> w ςʔϒϧͷΑ͏ͳɺΠϯϥΠϯԽͯ͠ෳࡶ͗ͯ͢ҙຯΛͳ͞ͳ͍ཁ ૉத͝ͱআ w )5.-ͷυΩϡϝϯτߏΛߟྀͭͭ͠USVODBUF
None
ϝϯγϣϯͰ͖ͳ͍Ϣʔβʔ ݄
ϝϯγϣϯͰ͖ͳ͍ਓ͕͍ΔΜͰ͕͢ʜ
@qiitan Markdown HTML <a href="/qiitan">@qiitan</a> @<strong>gfx</strong> @__gfx__ <em> Hi <a
href="/foo">@foo</a> </em> _Hi @foo_
w__foo__Λ<strong>foo</strong>ʹม͢Δॲཧ SFEDBSQFU͕͍ͬͯΔ w@fooΛ<a href="/foo">@foo</a>ʹม͢Δॲཧɺ SFEDBSQFUΑΓޙఔͷ.FOUJPOϑΟϧλʔ͕͍ͬͯΔ wͭ·Γ.FOUJPOϑΟϧλʔͷೖྗͷ࣌Ͱɺ@__gfx__ @<strong>gfx</strong>ʹͳͬͯ͠·͍ͬͯΔ
Redcarpet filter Mention filter @__gfx__ @<strong>gfx</strong> @<strong>gfx</strong> ͳΜ͔<strong>λά͍ͭͯΔ͠ ͜Εϝϯγϣϯ͡Όͳ͍ͳ ͳΜ͔ઌ಄ʹ@͍ͭͯΔ͚Ͳ
ڧௐه๏ʹϚον͢Δ͔Βڧௐ͠ͱ͜
w ࠜຊతʹ͜ͷʹରॲ͢ΔʹɺSFEDBSQFUʹखΛՃ͑ͯϝϯγϣϯه๏ ͷࣝΛ༩͑ΔʢϝϯγϣϯͷҰ෦ͩͬͨΒڧௐ͠ͳ͍ʣඞཁ͕͋Δ w ͔͠͠SFEDBSQFUͷGPSL࠷ऴखஈͰ͋ΓɺͰ͖ΕΓͨ͘ͳ͍ w ϫʔΫΞϥϯυͱͯ͠ɺ.FOUJPOϑΟϧλʔʹ@<strong>gfx</ strong>͕͞ΕͨΒɺ@__gfx__ʹͯ͠ϝϯγϣϯͱͯ͠ѻ͑ྑ͍ʁ w ڧௐه๏_͚ͩͰͳ͘*͑ΔͷͰ@<strong>gfx</strong>ͷݩ
ͷ.BSLEPXOιʔε͕ɺ@**gfx**ͩͬͨՄೳੑ͋Δ
None
(JU)VC͜ͷʹ Ͳ͏ରॲ͍ͯ͠Δͷ͔
None
None
.BSLEPXOͰϝϯγϣϯͰ͖ΔαʔϏεΛ࡞ΔͳΒɺ Ϣʔβʔ໊ʹ_Λ͑ͳ͍Α͏ʹͨ͠ํ͕ྑ͍ গͳ͘ͱઌ಄ͱඌͷ_ආ͚͍ͨ
ݹ͍Ωϟογϡ ݄
.BSLEPXOϨϯμϦϯάͷύϑΥʔϚϯε w 8FCαʔϏεͱͯ͠ɺϢʔβʔʹͱͬͯշదͳϨεϙϯελΠ ϜΛୡ͢Δͱ͍͏จ຺Ͱɺ.BSLEPXO RJJUBNBSLEPXO ͷ ϨϯμϦϯάॏ͍ w ຊจͷ༰͞ʹΑͬͯॲཧ͕࣌ؒେ͖͘มΘΔ w
ڊେͳςʔϒϧΛؚΜͩهࣄɺϨϯμϦϯάʹඵ͔͔ۙ͘ Δ͜ͱ͋Δ
ϨϯμϦϯά݁ՌΛΩϟογϡ͢Δ w ߘ࣌ʹҰ͚ͩϨϯμϦϯάͯ͠ɺ݁ՌΛΩϟογϡ ͓ͯ͘͠ w هࣄϖʔδӾཡϦΫΤετʹରͯ͠ຖճϨϯμϦϯά ͠ͳ͍
ݹ͍Ωϟογϡ w RJJUBNBSLEPXOʑਐԽ͍ͯ͠ΔͨΊɺߘ࣌ʹΩϟο γϡ͞ΕͨϨϯμϦϯά݁Ռͱɺ࠷৽ͷϨϯμϥʔͰϨϯ μϦϯάͨ͠߹ͷ݁Ռʹဃ͕ͰΔ w ࠣࡉͳมߋͰ͋Εݹ͍ΩϟογϡΛࢀর͠ଓ͚ͯྑ͍ ͕ɺ944ͳͲͷ੬ऑੑରԠͷ߹৽͍͠ϨϯμϥʔͰ֬ ࣮ʹϨϯμϦϯά͍ͨ͠͠
࠶ϨϯμϦϯάػߏ w *ODSFNFOUBMͳSFOEFSFSWFSTJPO *OUFHFS Λఆٛ͢Δ w ϨϯμϦϯά݁ՌͷΩϟογϡʹɺͦͷ࣌ͰͷSFOEFSFSWFSTJPOΛҰॹʹ֨ೲ͓ͯ͘͠ w هࣄΫϥεͷϨϯμϦϯά݁ՌΛฦ͢ϝιουͰɺΩϟογϡͷSFOEFSFSWFSTJPO͕ݱ ࡏͷWFSTJPOΑΓݹ͍߹ࣗಈతʹ࠶ϨϯμϦϯάΛ࣮ߦ͢Δ
w ࣮ࡍʹશϦΫΤετͰ࠶ϨϯμϦϯά͕Δͱෛՙͷ͕͋ΔͷͰɺ֬తʹ࣮ ߦ͞ΕΔΑ͏ʹ͠ɺ࣌ؒͱڞʹΛঃʑʹ্͍͛ͯ͘ w RJJUBNBSLEPXOʹखΛՃ͑ͨ߹ɺԿΒ͔ͷཧ༝Ͱશهࣄͷ࠶ϨϯμϦϯάΛ࣮ߦ͠ ͍ͨ߹SFOEFSFSWFSTJPOΛ ͢Δ
class Article < ActiveRecord::Base CURRENT_RENDERER_VERSION = 3 def rendered_body if
cached_body_renderer_version < CURRENT_RENDERER_VERSION self.cached_body = render(markdown_body) self.cached_body_renderer_version = CURRENT_RENDERER_VERSION end cached_body end end
݄
None
None
None
None
.BSLEPXO)5.-λάΛೖྗͰ͖Δ ໌Β͔ʹةݥͳλάଐੑαχλΠζ͍͕ͯͨ͠ɺ DMBTTଐੑڐՄ͍ͯͨ͠ <span class="fa fa-spin"> ·ΘΔίϝϯτ </span>
None
ΑΓݫ֨ͳαχλΠζ w 2JJUBͷ6*ʹΘΕ͍ͯΔDMBTTΛࢦఆ͢Δ͜ͱͰɺ2JJUBΛ฿ͨ͠ϑΟογϯάϖʔδΛ࡞ Ͱ͖ͯ͠·͏ w FH2JJUBͷϩάΠϯϖʔδΛ฿ͨ͠ϑΥʔϜΛ࡞Γɺ֎෦αΠτύεϫʔυΛૹ৴͢Δ w ͜Ε·ͰαχλΠζ͍͕ͯͨ͠ɺϗϫΠτϦετϧʔϧΛΑΓݫ֨ʹ͠ɺར༻Ͱ͖Δ )5.-ཁૉଐੑΛݶఆతʹͨ͠ w
HSFFONBU SFEDBSQFU ʹ͓͍ͯɺதؒϝλσʔλΛDMBTTଐੑͱͯ͠ग़ྗ͍ͯ͠ΔՕॴ͕͋ͬ ͨͷͰɺผͷEBUB ଐੑʹग़ྗ͢ΔΑ͏ʹมߋ͠ɺϢʔβʔʹΑΔೖྗͱ۠ผͰ͖ΔΑ͏ ʹͨ͠
͜Ε͔Β
$PNNPO.BSLʁ w ظతʹҠߦ͍ͨ͠ʢݸਓͷײʣ͕ɺطଘͷهࣄσʔ λͷҠߦ͕େมͦ͏ w (JU)VC$PNNPO.BSLͷҠߦ࣌ɺ৽چͷϨϯμϥʔͰ ղऍ͕ҟͳΔυΩϡϝϯτมॲஔΛߦͳͬͨ w IUUQTHJUIVCFOHJOFFSJOHDPNBGPSNBMTQFDGPS HJUIVCNBSLEPXO
Thank you