Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Qiita / Qiita:Team における Markdown レンダリングの歴史

Qiita / Qiita:Team における Markdown レンダリングの歴史

Markdown Night 2017 Summer
https://connpass.com/event/63383/

Yuji Nakayama

August 29, 2017
Tweet

More Decks by Yuji Nakayama

Other Decks in Technology

Transcript

  1. 2JJUB2JJUB5FBNʹ͓͚Δ
    .BSLEPXOϨϯμϦϯάͷྺ࢙
    Yuji Nakayama
    @nkym37
    @yujinakayama

    View full-size slide

  2. ࠷ॳ͸Q&AαʔϏεͩͬͨ

    View full-size slide

  3. ࠷ॳ͸
    MarkdownະରԠͩͬͨ

    View full-size slide

  4. ࠓ೔࿩͢͜ͱ
    .BSLEPXOυΩϡϝϯτΛϗετ͢Δ8FCαʔϏεΛӡ
    Ӧ͢Δ্Ͱ௚໘͖ͯͨ͠ɺ.BSLEPXOϨϯμϥʔपΓͷ
    టष͍ࣄ৘

    View full-size slide

  5. 2JJUBͷॳظͷ.BSLEPXOαϙʔτ
    ೥݄
    2JJUBϦϦʔεͷϲ݄ޙ

    View full-size slide

  6. ॳظͷ2JJUBͷ.BSLEPXOϨϯμϥʔ
    w ࣮૷͸SFEDBSQFUΧελϜϨϯμϥʔ
    w SFEDBSQFU͸$Ͱॻ͔Εͨ.BSLEPXOύʔαʔͷSVCZHFN
    w ౰࣌ͷ(JU)VC'MBWPSFE.BSLEPXOͷ࣮૷͸SFEDBSQFUͷ
    ϕʔεͰ͋ΔTVOEPXOΛϕʔεʹ͍ͯͨ͠ʢͱࢥΘΕΔʣ
    w ·ͩ$PNNPO.BSL͸ͳ͔ͬͨ

    View full-size slide

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

    View full-size slide

  8. ॳظͷ࢓༷
    w ࢓༷తʹ͸(JU)VC'MBWPSFE.BSLEPXOʹد͍ͤͯͨ
    w BVUPMJOL63-ͬΆ͍จࣈྻΛࣗಈͰϦϯΫʹ
    w GFODFE@DPEF@CMPDLT```\nsome code\n```
    w [email protected]ͷվߦͰ
    ग़ྗ
    w ΧελϜϨϯμϥʔͰγϯλοΫεϋΠϥΠτ
    w ͷͪʹଧͪফ͠ઢ΍ςʔϒϧه๏ʹ΋ରԠ

    View full-size slide

  9. ϝϯγϣϯه๏ͷಋೖ
    ೥݄
    @username

    View full-size slide

  10. 2JJUB5FBNϦϦʔε
    ೥݄
    αχλΠζͷϧʔϧ͕2JJUBͱएׯҟͳΔ

    View full-size slide

  11. ֆจࣈͷαϙʔτ
    ೥݄

    :tada:

    View full-size slide

  12. qiita-markdown gem
    ೥݄

    View full-size slide

  13. qiita-markdown gem
    w IUNMQJQFMJOFSFEDBSQFUOPLPHJSJ
    w IUNMQJQFMJOF͸)5.-ॲཧͷ3VCZϑϨʔϜϫʔΫ
    w ίΞϨϯμϥʔͱͯ͠SFEDBSQFUΛ࢖͍ɺͦͷग़ྗʹର͠
    ͯෳ਺ͷϑΟϧλʔʹΑΔޙॲཧΛద༻
    w 044Խ

    View full-size slide

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

    View full-size slide

  15. IUNMQJQFMJOFͷԿ͕خ͍͔͠
    w ੹຿͝ͱʹϑΟϧλʔΛ෼͚ΒΕΔͷͰɺίʔυͷݟ௨͕͠ྑ͘ͳΔ
    w ϑΟϧλʔͷద༻ॱং͕໌֬
    w جຊσʔλߏ଄ͱͯ͠OPLPHJSJͷ)5.-USFFΛ࠾༻͍ͯ͠ΔͨΊ
    )5.-ͷૢ࡞͕ݎ࿚
    w ҎલͷϨϯμϥʔͰ͸Ұ෦ਖ਼نදݱΛ࢖͍ͬͯΔՕॴ͕͋ͬͨ

    View full-size slide

  16. ϢʔβʔͷաڈͷίϝϯτҰཡ
    ೥݄

    View full-size slide

  17. ίϝϯτҰཡΛදࣔ͢Δ
    w هࣄҰཡͳΒλΠτϧΛදࣔ͢Ε͹ྑ͍͕ɺίϝϯτʹ͸
    λΠτϧ͕ͳ͍ͷͰɺຊจͷཁ໿Λදࣔ͢Δඞཁ͕͋Δ
    w ௕͗͢ΔίϝϯτશจΛදࣔͨ͘͠͸ͳ͍
    w ཁ໿ͱͯ͠දࣔ͢Δͷ͕೉͍͠ɺෳࡶͳϚʔΫΞοϓΛऔ
    Γআ͖͍ͨ

    View full-size slide

  18. Qiita::Markdown::SummaryProcessor
    w ϒϩοΫཁૉͷத਎͸࢒ͭͭ͠λάΛ࡟আ͢Δ͜ͱͰɺΠϯϥΠϯԽ
    •foobarˠfoobar
    w ςʔϒϧͷΑ͏ͳɺΠϯϥΠϯԽͯ͠΋ෳࡶ͗ͯ͢ҙຯΛͳ͞ͳ͍ཁ
    ૉ͸த਎͝ͱ࡟আ
    w )5.-ͷυΩϡϝϯτߏ଄Λߟྀͭͭ͠USVODBUF

    View full-size slide

  19. ϝϯγϣϯͰ͖ͳ͍Ϣʔβʔ໰୊
    ೥݄

    View full-size slide

  20. ϝϯγϣϯͰ͖ͳ͍ਓ͕͍ΔΜͰ͕͢ʜ

    View full-size slide

  21. @qiitan
    Markdown HTML
    @qiitan
    @gfx
    @__gfx__

    Hi
    @foo

    _Hi @foo_

    View full-size slide


  22. w__foo__Λfooʹม׵͢Δॲཧ͸
    SFEDBSQFU͕΍͍ͬͯΔ
    w@fooΛ@fooʹม׵͢Δॲཧ͸ɺ
    SFEDBSQFUΑΓޙ޻ఔͷ.FOUJPOϑΟϧλʔ͕΍͍ͬͯΔ
    wͭ·Γ.FOUJPOϑΟϧλʔͷೖྗͷ࣌఺Ͱɺ@__gfx__͸
    @gfxʹͳͬͯ͠·͍ͬͯΔ

    View full-size slide

  23. Redcarpet filter
    Mention filter
    @__gfx__
    @gfx
    @gfx
    ͳΜ͔λά͍ͭͯΔ͠
    ͜Ε͸ϝϯγϣϯ͡Όͳ͍ͳ
    ͳΜ͔ઌ಄ʹ@͍ͭͯΔ͚Ͳ
    ڧௐه๏ʹϚον͢Δ͔Βڧௐ͠ͱ͜

    View full-size slide


  24. w ࠜຊతʹ͜ͷ໰୊ʹରॲ͢Δʹ͸ɺSFEDBSQFUʹखΛՃ͑ͯϝϯγϣϯه๏
    ͷ஌ࣝΛ༩͑ΔʢϝϯγϣϯͷҰ෦ͩͬͨΒڧௐ͠ͳ͍ʣඞཁ͕͋Δ
    w ͔͠͠SFEDBSQFUͷGPSL͸࠷ऴखஈͰ͋ΓɺͰ͖Ε͹΍Γͨ͘ͳ͍
    w ϫʔΫΞϥ΢ϯυͱͯ͠ɺ.FOUJPOϑΟϧλʔʹ@gfx
    strong>͕౉͞ΕͨΒɺ@__gfx__ʹ໭ͯ͠ϝϯγϣϯͱͯ͠ѻ͑͹ྑ͍ʁ
    w ڧௐه๏͸_͚ͩͰͳ͘*΋࢖͑ΔͷͰ@gfxͷݩ
    ͷ.BSLEPXOιʔε͕ɺ@**gfx**ͩͬͨՄೳੑ΋͋Δ

    View full-size slide

  25. (JU)VC͸͜ͷ໰୊ʹ
    Ͳ͏ରॲ͍ͯ͠Δͷ͔

    View full-size slide

  26. .BSLEPXOͰϝϯγϣϯͰ͖ΔαʔϏεΛ࡞ΔͳΒɺ
    Ϣʔβʔ໊ʹ͸_Λ࢖͑ͳ͍Α͏ʹͨ͠ํ͕ྑ͍
    গͳ͘ͱ΋ઌ಄ͱ຤ඌͷ_͸ආ͚͍ͨ

    View full-size slide

  27. ݹ͍Ωϟογϡ໰୊
    ೥݄

    View full-size slide

  28. .BSLEPXOϨϯμϦϯάͷύϑΥʔϚϯε
    w 8FCαʔϏεͱͯ͠ɺϢʔβʔʹͱͬͯշదͳϨεϙϯελΠ
    ϜΛୡ੒͢Δͱ͍͏จ຺Ͱ͸ɺ.BSLEPXO RJJUBNBSLEPXO
    ͷ
    ϨϯμϦϯά͸ॏ͍
    w ຊจͷ಺༰΍௕͞ʹΑͬͯॲཧ͕࣌ؒେ͖͘มΘΔ
    w ڊେͳςʔϒϧΛؚΜͩهࣄ͸ɺϨϯμϦϯάʹඵ͔͔ۙ͘
    Δ͜ͱ΋͋Δ

    View full-size slide

  29. ϨϯμϦϯά݁ՌΛΩϟογϡ͢Δ
    w ౤ߘ࣌ʹҰ౓͚ͩϨϯμϦϯάͯ͠ɺ݁ՌΛΩϟογϡ
    ͓ͯ͘͠
    w هࣄϖʔδӾཡϦΫΤετʹରͯ͠ຖճϨϯμϦϯά͸
    ͠ͳ͍

    View full-size slide

  30. ݹ͍Ωϟογϡ໰୊
    w RJJUBNBSLEPXO͸೔ʑਐԽ͍ͯ͠ΔͨΊɺ౤ߘ࣌ʹΩϟο
    γϡ͞ΕͨϨϯμϦϯά݁Ռͱɺ࠷৽ͷϨϯμϥʔͰϨϯ
    μϦϯάͨ͠৔߹ͷ݁Ռʹဃ཭͕ͰΔ
    w ࠣࡉͳมߋͰ͋Ε͹ݹ͍ΩϟογϡΛࢀর͠ଓ͚ͯ΋ྑ͍
    ͕ɺ944ͳͲͷ੬ऑੑରԠͷ৔߹͸৽͍͠ϨϯμϥʔͰ֬
    ࣮ʹϨϯμϦϯά͠௚͍ͨ͠

    View full-size slide

  31. ࠶ϨϯμϦϯάػߏ
    w *ODSFNFOUBMͳSFOEFSFSWFSTJPO *OUFHFS
    Λఆٛ͢Δ
    w ϨϯμϦϯά݁ՌͷΩϟογϡʹɺͦͷ࣌఺ͰͷSFOEFSFSWFSTJPOΛҰॹʹ֨ೲ͓ͯ͘͠
    w هࣄΫϥεͷϨϯμϦϯά݁ՌΛฦ͢ϝιου಺ͰɺΩϟογϡͷSFOEFSFSWFSTJPO͕ݱ
    ࡏͷWFSTJPOΑΓ΋ݹ͍৔߹͸ࣗಈతʹ࠶ϨϯμϦϯάΛ࣮ߦ͢Δ
    w ࣮ࡍʹ͸શϦΫΤετͰ࠶ϨϯμϦϯά͕૸Δͱෛՙͷ໰୊͕͋ΔͷͰɺ֬཰తʹ࣮
    ߦ͞ΕΔΑ͏ʹ͠ɺ࣌ؒͱڞʹ཰Λঃʑʹ্͍͛ͯ͘
    w RJJUBNBSLEPXOʹखΛՃ͑ͨ৔߹΍ɺԿΒ͔ͷཧ༝Ͱશهࣄͷ࠶ϨϯμϦϯάΛ࣮ߦ͠
    ͍ͨ৔߹͸SFOEFSFSWFSTJPOΛ͢Δ

    View full-size slide

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

    View full-size slide

  33. .BSLEPXO͸௚઀)5.-λάΛೖྗͰ͖Δ
    ໌Β͔ʹةݥͳλά΍ଐੑ͸αχλΠζ͍͕ͯͨ͠ɺ
    DMBTTଐੑ͸ڐՄ͍ͯͨ͠

    ·ΘΔίϝϯτ

    View full-size slide

  34. ΑΓݫ֨ͳαχλΠζ
    w 2JJUBͷ6*ʹ࢖ΘΕ͍ͯΔDMBTTΛࢦఆ͢Δ͜ͱͰɺ2JJUBΛ໛฿ͨ͠ϑΟογϯάϖʔδΛ࡞
    ੒Ͱ͖ͯ͠·͏
    w FH2JJUBͷϩάΠϯϖʔδΛ໛฿ͨ͠ϑΥʔϜΛ࡞Γɺ֎෦αΠτ΁ύεϫʔυΛૹ৴͢Δ
    w ͜Ε·Ͱ΋αχλΠζ͸͍͕ͯͨ͠ɺϗϫΠτϦετϧʔϧΛΑΓݫ֨ʹ͠ɺར༻Ͱ͖Δ
    )5.-ཁૉ΍ଐੑΛݶఆతʹͨ͠
    w HSFFONBU SFEDBSQFU
    ʹ͓͍ͯɺதؒϝλσʔλΛDMBTTଐੑͱͯ͠ग़ྗ͍ͯ͠ΔՕॴ͕͋ͬ
    ͨͷͰɺผͷEBUBଐੑʹग़ྗ͢ΔΑ͏ʹมߋ͠ɺϢʔβʔʹΑΔೖྗͱ۠ผͰ͖ΔΑ͏
    ʹͨ͠

    View full-size slide

  35. $PNNPO.BSL͸ʁ
    w ௕ظతʹ͸Ҡߦ͍ͨ͠ʢݸਓͷײ૝ʣ͕ɺطଘͷهࣄσʔ
    λͷҠߦ͕େมͦ͏
    w (JU)VC͸$PNNPO.BSL΁ͷҠߦ࣌ɺ৽چͷϨϯμϥʔͰ
    ղऍ͕ҟͳΔυΩϡϝϯτ͸ม׵ॲஔΛߦͳͬͨ
    w IUUQTHJUIVCFOHJOFFSJOHDPNBGPSNBMTQFDGPS
    HJUIVCNBSLEPXO

    View full-size slide