アクセシビリティチェックを自動化するためのmarkuplintのロードマップ

 アクセシビリティチェックを自動化するためのmarkuplintのロードマップ

Accessibility Step Vol.01

1adcc39bcb4268334437c9c12b84d7a4?s=128

Yusuke Hirao

August 10, 2018
Tweet

Transcript

  1. ΞΫηγϏϦςΟνΣοΫΛࣗಈԽ͢ΔͨΊͷ NBSLVQMJOUͷϩʔυϚοϓ "DDFTTJCJMJUZ4UFQ7PM

  2. ©2018 Yusuke Hirao ࣗݾ঺հ ฏඌ༏యʢͻΒ͓Ώ͏ͯΜʣ גࣜձࣾσΟʔθϩ ϑϩϯτΤϯυΤϯδχΞ #-0(IUUQTOPUFNVZVTVLFIJSBP Yusuke Hirao

    @cloud10designs
  3. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫΛࣗಈԽ͢ΔͨΊͷ NBSLVQMJOUͷϩʔυϚοϓ

  4. ©2018 Yusuke Hirao ࠓ೔͸ͪΐͬͱϑϩϯτدΓͷ ٕज़Ϊδϡπͨ͠࿩Ͱ͢

  5. ©2018 Yusuke Hirao NBSLVQMJOU͝ଘ஌ͷํ✋

  6. ©2018 Yusuke Hirao &4-JOUɾTUZMFMJOU͝ଘ஌ͷํ✋

  7. ©2018 Yusuke Hirao -JOUFSͱ͸ қ͘͠આ໌͢Δͱ ίʔυΛղੳͯ͠ɺ ϧʔϧʹଇͬͯͳ͍෦෼Λࢦఠ͢ΔπʔϧͰ͢ɻ

  8. ©2018 Yusuke Hirao )5.-ͷ-JOUFS Φʔϓϯιʔε/PEFKT੡)5.--JOUFS

  9. ©2018 Yusuke Hirao )5.-ͷ-JOUFS ͖͔͚ͬ IUUQTTQFBLFSEFDLDPNZVTVLFIJSBPLPEPSFCJZVOBOUFTJUFSBSFSVLBUV

  10. ©2018 Yusuke Hirao )5.-ͷ-JOUFS ͓͔͛͞·Ͱ4UBS௒͑·ͨ͠

  11. ©2018 Yusuke Hirao ։ൃ్্ ݱࡏW ʹ΋ؔΘΒͣ ஫໨͍͍ͨͩͯຊ౰ʹخ͍͠Ͱ͢

  12. ©2018 Yusuke Hirao ͱ͍͏Θ͚Ͱ ϩʔυϚοϓ ࠓޙͷ։ൃ༧ఆ ͷ͸ͳ͠

  13. ©2018 Yusuke Hirao ΞδΣϯμ ࠓ೔࿩͢͜ͱ  ࠓɺͲ͏͍͏ར༻Λ͍ͯ͠Δͷ͔ ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ΞΫηγϏϦςΟνΣοΫͷࣗಈԽʹ͍ͭͯ

  14. ©2018 Yusuke Hirao ίʔυ඼࣭νΣοΫ ࣾ಺πʔϧͱͯ͠ ίϚϯυʢλʔϛφϧʣ͔Β ΋͘͠͸ HVMQλεΫ͔Β ࠷ۙ—fixΦϓγϣϯ࣮૷͠·ͨ͠ ࠓɺͲΜͳར༻Λ͍ͯ͠Δͷ͔

  15. ©2018 Yusuke Hirao ΤσΟλʔͷػೳͱͯ͠ 7JTVBM4UVEJP$PEF "UPN 7JN ʹϓϥάΠϯ͕ఏڙ͞Ε͍ͯΔ ࠓɺͲΜͳར༻Λ͍ͯ͠Δͷ͔

  16. ©2018 Yusuke Hirao νΣοΫ͍ͯ͠Δ͜ͱ ϑΥʔϚοτɾίʔυελΠϧ Πϯσϯτ εϖʔεɾվߦҐஔ ໋໊نଇ όϦσʔγϣϯ γϯλοΫε

    ن֨ ඇਪ঑ɾΞϯνύλʔϯ ࠓɺͲΜͳར༻Λ͍ͯ͠Δͷ͔
  17. ©2018 Yusuke Hirao ΞδΣϯμ ࠓ೔࿩͢͜ͱ  ࠓɺͲ͏͍͏ར༻Λ͍ͯ͠Δͷ͔ ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ΞΫηγϏϦςΟνΣοΫͷࣗಈԽʹ͍ͭͯ

  18. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ NBSLVQMJOUͷϩʔυϚοϓ ೥݄WBMQIBΞϧϑΝ൛ύϒϦογϡ ೥݄Wਖ਼ࣜ൛ύϒϦογϡ ⾣೿ੜπʔϧల։ͷͨΊͷ"1*࣮૷ ⾣ϓϥάΠϯɾΧελϜϧʔϧͷ"1*࣮૷ ⾣ΠϯσϯτϑΥʔϚοτɾίʔυελΠϧΛ౷Ұ͢ΔϏϧτΠϯϧʔϧ࣮૷

    ⾣ཁૉɾଐੑνΣοΫ͕࠷௿ݶՄೳͳϏϧτΠϯϧʔϧ࣮૷ ⾣7JTVBM4UVEJP$PEF֦ுWਖ਼ࣜ൛ύϒϦογϡ ೥݄WϚΠφʔόʔδϣϯΞοϓ ⾣)5.--JWJOHTUBOEBSEͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣8$8"*"3*"ͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣ϒϥ΢β༻Ϟδϡʔϧ։ൃ ೥݄पลϓϥάΠϯ։ൃ ⾣)5.-JO+4ʢ5FNQMBUFMJUFSBMʣରԠϓϥάΠϯ ⾣QVHରԠϓϥάΠϯ ⾣QIQରԠϓϥάΠϯ
  19. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ NBSLVQMJOUͷϩʔυϚοϓ ೥݄WBMQIBΞϧϑΝ൛ύϒϦογϡ ೥݄Wਖ਼ࣜ൛ύϒϦογϡ ⾣೿ੜπʔϧల։ͷͨΊͷ"1*࣮૷ ⾣ϓϥάΠϯɾΧελϜϧʔϧͷ"1*࣮૷ ⾣ΠϯσϯτϑΥʔϚοτɾίʔυελΠϧΛ౷Ұ͢ΔϏϧτΠϯϧʔϧ࣮૷

    ⾣ཁૉɾଐੑνΣοΫ͕࠷௿ݶՄೳͳϏϧτΠϯϧʔϧ࣮૷ ⾣7JTVBM4UVEJP$PEF֦ுWਖ਼ࣜ൛ύϒϦογϡ ೥݄WϚΠφʔόʔδϣϯΞοϓ ⾣)5.--JWJOHTUBOEBSEͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣8$8"*"3*"ͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣ϒϥ΢β༻Ϟδϡʔϧ։ൃ ೥݄पลϓϥάΠϯ։ൃ ⾣)5.-JO+4ʢ5FNQMBUFMJUFSBMʣରԠϓϥάΠϯ ⾣QVHରԠϓϥάΠϯ ⾣QIQରԠϓϥάΠϯ
  20. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ೿ੜπʔϧల։ͷͨΊͷ"1*࣮૷ ೿ੜπʔϧ͕࡞ΕΔ࢓૊Έʹ͍ͭͯཁ๬͕͋ͬͨ

  21. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ೿ੜπʔϧల։ͷͨΊͷ"1*࣮૷ ೿ੜπʔϧ੍࡞ʹऔΓֻ͔ͬͯ͘Ε͍ͯΔํʑ͕͍Δ

  22. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ೿ੜπʔϧల։ͷͨΊͷ"1*࣮૷ ೿ੜπʔϧͷͨΊͷ"1*ఏڙ ࣮૷த  !// ॊೈͰඪ४ͳAPIΛఏڙ͢ΔຊՈ

    import * as markuplint from 'markuplint'; !// ࣮ߦ؀ڥΛ໰Θͳ͍Universal JavaScriptͰར༻Ͱ͖ΔAPI import { MLCore } from '@markuplint/ml-core'; ˞@textlint/kernelʹӨڹΛड͚͍ͯ·͢ɻ
  23. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ϑϩϯτΤϯυΤϯδχΞʹ ؾܰʹ ϛχϚϜʹ ΞυϗοΫʹ ར༻ͯ͠΄͍͠ ͳͷͰϥΠηϯε΋.*5Ͱ͢

  24. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ NBSLVQMJOUͷϩʔυϚοϓ ೥݄WBMQIBΞϧϑΝ൛ύϒϦογϡ ೥݄Wਖ਼ࣜ൛ύϒϦογϡ ⾣೿ੜπʔϧల։ͷͨΊͷ/PEFKT"1*࣮૷ ⾣ϓϥάΠϯɾΧελϜϧʔϧͷ"1*࣮૷ ⾣ΠϯσϯτϑΥʔϚοτɾίʔυελΠϧΛ౷Ұ͢ΔϏϧτΠϯϧʔϧ࣮૷

    ⾣ཁૉɾଐੑνΣοΫ͕࠷௿ݶՄೳͳϏϧτΠϯϧʔϧ࣮૷ ⾣7JTVBM4UVEJP$PEF֦ுWਖ਼ࣜ൛ύϒϦογϡ ೥݄WϚΠφʔόʔδϣϯΞοϓ ⾣)5.--JWJOHTUBOEBSEͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣8$8"*"3*"ͷόϦσʔγϣϯ͕Ͱ͖ΔϏϧτΠϯϧʔϧ௥Ճ ⾣ϒϥ΢β༻Ϟδϡʔϧ։ൃ ೥݄पลϓϥάΠϯ։ൃ ⾣)5.-JO+4ʢ5FNQMBUFMJUFSBMʣରԠϓϥάΠϯ ⾣QVHରԠϓϥάΠϯ ⾣QIQରԠϓϥάΠϯ
  25. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ 8$8"*"3*"ͷόϦσʔγϣϯ SPMFଐੑ BSJB ଐੑ ࢦఆཁૉͷଥ౰ੑ ଐੑ஋ͷنఆ஋ɾλΠϙνΣοΫ

    aria-***byଐੑͳͲͱ#idͷ੔߹ੑ aria-labelͷ্ॻ͖໰୊νΣοΫ ͳͲ
  26. ©2018 Yusuke Hirao ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ 8$8"*"3*"ͷόϦσʔγϣϯ SPMFଐੑ BSJB ଐੑ ࢦఆཁૉͷଥ౰ੑ ଐੑ஋ͷنఆ஋ɾλΠϙνΣοΫ

    aria-***byଐੑͳͲͱ#idͷ੔߹ੑ aria-labelͷ্ॻ͖໰୊νΣοΫ ͳͲ ਓ͕ؒνΣοΫ͢Δͷʹݶք͕͋Δ΍ͭ
  27. ©2018 Yusuke Hirao ΞδΣϯμ ࠓ೔࿩͢͜ͱ  ࠓɺͲ͏͍͏ར༻Λ͍ͯ͠Δͷ͔ ࠓޙɺͲ͏͍͏ར༻Λ͍͔ͨ͠ɾͯ͠΄͍͔͠ ΞΫηγϏϦςΟνΣοΫͷࣗಈԽʹ͍ͭͯ

  28. ©2018 Yusuke Hirao Έͳ͞ΜŊ΋ͪΖΜςετॻ͍ͯ·͢ΑͶʁ ʢ౜ಥͳἤΓʣ

  29. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ΋͏ͻͱͭར༻͍ͨ͠γʔϯ ίϯϙʔωϯτςετ ✕ ΞΫηγϏϦςΟ 8"*"3*" νΣοΫ

    ✕ ࣗಈςετπʔϧ
  30. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ίϯϙʔωϯτςετ 7VFKTͷྫ import { render }

    from '@vue/server-test-utils'; import Foo from './Foo.vue'; describe('Foo', () !=> { it('renders a div', () !=> { const wrapper = render(Foo); expect(wrapper.text()).toContain('<div>!</div>'); }); }); Ҿ༻IUUQTWVFUFTUVUJMTWVFKTPSHKBBQJSFOEFS
  31. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ίϯϙʔωϯτςετʹ8"*"3*"νΣοΫΛಋೖ NBSLVQMJOU͸)5.-ͷஅย %PDVNFOU'SBHNFOU Λѻ͑Δ import {

    render } from '@vue/server-test-utils'; import * as markuplint from 'markuplint'; import Foo from './Foo.vue'; describe('Foo', () !=> { it('renders a div', () !=> { const wrapper = render(Foo, { propsData: { pressed: true } }); expect( markuplint.verify({ sourceCodes: wrapper.html(), reportType: 'exception', }), ).toBe(true); }); }); ࢀߟIUUQTWVFUFTUVUJMTWVFKTPSHKBBQJSFOEFS
  32. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ίϯϙʔωϯτςετʹ8"*"3*"νΣοΫΛಋೖ NBSLVQMJOU͸)5.-ͷஅย %PDVNFOU'SBHNFOU Λѻ͑Δ ࢀߟIUUQTWVFUFTUVUJMTWVFKTPSHKBBQJSFOEFS import

    { render } from '@vue/server-test-utils'; import * as markuplint from 'markuplint'; import Foo from './Foo.vue'; describe('Foo', () !=> { it('renders a div', () !=> { const wrapper = render(Foo, { propsData: { pressed: true } }); expect( markuplint.verify({ sourceCodes: wrapper.html(), reportType: 'exception', }), ).toBe(true); }); }); ීวతͳଐੑ஋ςετ͸·ͱΊͯ୲͏
  33. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ίʔσΟϯά ίϯϙʔωϯτ ςετ ϦϯτνΣοΫ git push

    ϦϙδτϦ post-receive $*αʔόʔ ϔουϨε ϒϥ΢βʔ test —watch lint —watch ίϯϙʔωϯτ ςετ
  34. ©2018 Yusuke Hirao ͱ͜ΖͰ NBSLVQMJOU͸ΞΫηγϏϦςΟνΣοΧʔͳͷ͔

  35. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ NBSLVQMJOU͸ΞΫηγϏϦςΟνΣοΧʔͳͷ͔ νΣοΧʔͱ໊৐Δͱ͜Ζ·Ͱػೳ࣮૷͢Δͭ΋Γ͸ͳ͍Ͱ͢ɻ ͋͘·ͰNBSLVQMJOU͸ϚʔΫΞοϓϥϯήʔδ༻ͷϦϯλʔͰ͢ɻ ͳͷͰɺཁૉ΍ଐੑΛνΣοΫ͢Δ্Ͱid ΍for΍altɺ ͦͯ͠8"*"3*"΋ର৅ʹ͍ͯ͠Δ͚ͩͰ͢ɻ

    άϥϑΟΧϧͳ෦෼΍$44࣮૷ʹٴͿͱ͜Ζ·Ͱ͸αϙʔτ͠·ͤΜ͠ɺͰ͖·ͤΜɻ NBSLVQMJOUΛར༻ͯ͠ΞΫηγϏϦςΟνΣοΧʔΛ ։ൃ͍ͯͨͩ͘͠ͷ͸΍Ϳ͔͞Ͱ͸ͳ͍Ͱ͢
  36. ©2018 Yusuke Hirao ΞΫηγϏϦςΟνΣοΫͷࣗಈԽ ஫໨͍ͯ͠ΔΞΫηγϏϦςΟνΣοΧʔ "ZD 8FC্ͰΞΫηγϏϦςΟνΣοΫ͕ Ͱ͖ΔαʔϏεπʔϧɻ .*5ϥΠηϯεͷΦʔϓϯιʔεͰ 1)1Ͱॻ͔Ε͍ͯΔͷͰ

    $.4ͳͲʹ૊ΈࠐΈՄೳɻ 8PSE1SFTTϓϥάΠϯ͕഑෍͞Ε͍ͯ·͢ɻ CBTFS$.4ϓϥάΠϯ΋΄͍͠ʜ
  37. ©2018 Yusuke Hirao ·ͱΊ

  38. ©2018 Yusuke Hirao ·ͱΊ ؾܰʹɺϛχϚϜʹɺΞυϗοΫʹར༻ͯ͠΄͍͠ ίϯϙʔωϯτςετʹ΋࢖͑Δ ࣗಈςετπʔϧʹ૊ΈࠐΉͷ͕Φεεϝ ΞΫηγϏϦςΟνΣοΫ͸͋͘·Ͱཁૉɾଐੑ͕ର৅

  39. ΞΫηγϏϦςΟνΣοΫΛࣗಈԽ͢ΔͨΊͷ NBSLVQMJOUͷϩʔυϚοϓ "DDFTTJCJMJUZ4UFQ7PM