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 Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

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

    View Slide

  8. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. 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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    :tada:

    View Slide

  18. qiita-markdown gem
    ೥݄

    View Slide

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

    View Slide

  20. 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 Slide

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

    View Slide

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

    View Slide

  23. View Slide

  24. View Slide

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

    View Slide

  26. View Slide

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

    View Slide

  28. View Slide

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

    View Slide

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

    View Slide

  31. @qiitan
    Markdown HTML
    @qiitan
    @gfx
    @__gfx__

    Hi
    @foo

    _Hi @foo_

    View Slide


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

    View Slide

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

    View Slide


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

    View Slide

  35. View Slide

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

    View Slide

  37. View Slide

  38. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  45. 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 Slide

  46. ೥݄

    View Slide

  47. View Slide

  48. View Slide

  49. View Slide

  50. View Slide

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

    ·ΘΔίϝϯτ

    View Slide

  52. View Slide

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

    View Slide

  54. ͜Ε͔Β

    View Slide

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

    View Slide

  56. Thank you

    View Slide