kubosho / blog.kubosho.com

https://blog.kubosho.com
MIT License
9 stars 0 forks source link

markuplintを導入する #888

Closed kubosho closed 2 years ago

kubosho commented 2 years ago

https://github.com/markuplint/markuplint

kubosho commented 2 years ago
kubosho commented 2 years ago

Getting started: https://markuplint.dev/getting-started

まずは npx markuplint --init を実行する。いくつか選択肢が出てくるのでそれに答えていく。 テンプレートエンジンの選択はスペースキーを押してチェックを付けないと何も選ばれていないことになるので注意が必要。

React向けに設定した結果、markuplintの設定は次のようになった。

{
  "parser": {
    "\\.[jt]sx?$": "@markuplint/jsx-parser"
  },
  "specs": {
    "\\.[jt]sx?$": "@markuplint/react-spec"
  },
  "extends": [
    "markuplint:recommended"
  ]
}
kubosho commented 2 years ago

markuplintを実行した結果。

$ markuplint **/*.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/EntryList.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/ErrorBoundary.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/FacebookLink.tsx
<markuplint> warning: 属性「xmlns」は効果がありません。属性は不要です (ineffective-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/icon/facebook.tsx:7:5
  6: ••<svg
  7: ••••xmlns="http://www.w3.org/2000/svg"
  8: ••••viewBox="0•0•320•512"
<markuplint> error: 属性「focusable」は許可されていません (invalid-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/icon/facebook.tsx:11:5
  10: ••••role="img"
  11: ••••focusable="false"
  12: ••>
<markuplint> warning: 属性「xmlns」は効果がありません。属性は不要です (ineffective-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/icon/twitter.tsx:6:5
  5: ••<svg
  6: ••••xmlns="http://www.w3.org/2000/svg"
  7: ••••viewBox="0•0•512•512"
<markuplint> error: 属性「focusable」は許可されていません (invalid-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/icon/twitter.tsx:10:5
  9: ••••role="img"
  10: ••••focusable="false"
  11: ••>
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/PublishedDate.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/SiteContents.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/SnsShare.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/components/TwitterLink.tsx
<markuplint> error: 属性「property」は次のパターンにマッチしませんでした /^og:[a-z_]+/ (invalid-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/_app.tsx:50:25
  49: ••••••••<meta•property="og:image:height"•content="630"•/>
  50: ••••••••<meta•property="fb:app_id"•content={FACEBOOK_APP_ID}•/>
  51: ••••••••<meta•name="twitter:card"•content="summary_large_image"•/>
<markuplint> error: 属性「property」は次のパターンにマッチしませんでした /^og:[a-z_]+/ (invalid-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/_app.tsx:52:25
  51: ••••••••<meta•name="twitter:card"•content="summary_large_image"•/>
  52: ••••••••<meta•property="twitter:image"•content={OG_IMAGE_URL}•/>
  53: ••••••••<meta•name="twitter:site"•content={`@${TWITTER_ACCOUNT_ID}`}•/>
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/_document.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/categories/[category].tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/draft/[id].tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/entry/[id].tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/feed.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/index.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/policy.tsx
<markuplint> passed /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/pages/tags/[tag].tsx
<markuplint> error: 要素「script」には属性「defer」が必要です (required-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/tracking/gtm.tsx:16:10
  15: ••});
  16: ••return•<script src={`https://www.googletagmanager.com/gtm.js?id=${id}`} async />;
  17: }
<markuplint> error: 要素「iframe」には属性「title」が必要です (required-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/tracking/gtm.tsx:22:7
  21: ••••<noscript>
  22: ••••••<iframe
        src={`https://www.googletagmanager.com/ns.html?id=${id}`}
        height="0"
        width="0"
        style={{ display: 'none', visibility: 'hidden' }}
      />
  23: ••••••••src={`https://www.googletagmanager.com/ns.html?id=${id}`}
<markuplint> error: 要素「iframe」には属性「loading」が必要です (required-attr) /Users/kubosho/src/github.com/kubosho/blog.kubosho.com/src/tracking/gtm.tsx:22:7
  21: ••••<noscript>
  22: ••••••<iframe
        src={`https://www.googletagmanager.com/ns.html?id=${id}`}
        height="0"
        width="0"
        style={{ display: 'none', visibility: 'hidden' }}
      />
  23: ••••••••src={`https://www.googletagmanager.com/ns.html?id=${id}`}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
kubosho commented 2 years ago

warning: 属性「xmlns」は効果がありません。属性は不要です (ineffective-attr)

根拠としては https://html.spec.whatwg.org/multipage/syntax.html#elements-2 のノートっぽい。

The HTML syntax does not support namespace declarations, even in foreign elements. https://html.spec.whatwg.org/multipage/syntax.html#elements-2 より

https://www.w3.org/TR/SVG2/struct.html#Namespace にも書いてあった。

As the example shows there's no need to have an ‘xmlns’ attribute declaring that the element is in the SVG namespace when using the HTML parser. The HTML parser will automatically create the SVG elements in the proper namespace.

kubosho commented 2 years ago

error: 属性「focusable」は許可されていません (invalid-attr)

https://momdo.hatenablog.jp/entry/20200906/1599378603 が詳しい。

kubosho commented 2 years ago

error: 属性「property」は次のパターンにマッチしませんでした /^og:[a-z_]+/ (invalid-attr) <meta•property="fb:app_id"•content={FACEBOOK_APP_ID}•/>

fb:app_id Facebookインサイトを使用するには、アプリIDをページに追加する必要があります。インサイトにより、Facebookからサイトへのトラフィックに関する分析を確認できます。アプリIDはアプリダッシュボードで確認できます。 https://developers.facebook.com/docs/sharing/webmasters/?locale=ja_JP

Facebookインサイトを使う場合は必須っぽい。

kubosho commented 2 years ago

error: 属性「property」は次のパターンにマッチしませんでした /^og:[a-z_]+/ (invalid-attr) <meta•property="twitter:image"•content={OG_IMAGE_URL}•/>

https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary-card-with-large-image を見る限りだと、<meta name=""> の形式で定義して良さそう。

<meta name="twitter:image" content="http://graphics8.nytimes.com/images/2012/02/19/us/19whitney-span/19whitney-span-articleLarge.jpg">
kubosho commented 2 years ago

error: 要素「script」には属性「defer」が必要です (required-attr) <script src={https://www.googletagmanager.com/gtm.js?id=${id}} async />

The defer attribute may be specified even if the async attribute is specified, to cause legacy web browsers that only support defer (and not async) to fall back to the defer behavior instead of the blocking behavior that is the default. https://html.spec.whatwg.org/multipage/scripting.html#the-script-element

という記述があるようにレガシーブラウザーのフォールバック用として、async属性を定義したときにdefer属性も一緒に定義して良いという記述はあるが、必須ではない認識。

そして asyncdefer 両方定義したら defer は必要ないというwarningが出力されて、defer のみ定義したら何のエラーも出なくなった。ルールの調整が必要そう。

kubosho commented 2 years ago

error: 要素「iframe」には属性「title」が必要です (required-attr)

  21: ••••<noscript>
  22: ••••••<iframe
        src={`https://www.googletagmanager.com/ns.html?id=${id}`}
        height="0"
        width="0"
        style={{ display: 'none', visibility: 'hidden' }}
      />
  23: ••••••••src={`https://www.googletagmanager.com/ns.html?id=${id}`}

などで書かれているように、iframe要素の説明のためにtitle属性が必要となる。 ただGoogle Tag Managerのiframeかつ、スタイル的にも不可視となっているため、title属性を定義したとしても値は空で良さそう。

kubosho commented 2 years ago

error: 要素「iframe」には属性「loading」が必要です (required-attr)

仕様では値が lazy または eager の2つしか定義されていないが、Chromeは独自に非標準の値である auto を既定値としているので明示的に定義しておいたほうがいい?

ref: https://web.dev/i18n/ja/iframe-lazy-loading/#iframe-2


既定だと loading="eager" にすると loading="lazy" にしろと怒られる。ルールの調整が必要そう。