Web サイトの診断ツール Sonar を使ってみる | Monotalk続いて、sonar, a linting tool for the web Cli ツールを使ってみます。


目次

[TOC]


CLI ツールを実行する

User guide | sonar documentation参考にインストール、ツールを実行します。

インストール、作業ディレクトリの作成

  • インストール
    % npm install -g --engine-strict @sonarwhal/sonar
    
  • OUTPUT

    /usr/local/bin/sonar -> /usr/local/lib/node_modules/@sonarwhal/sonar/dist/src/bin/sonar.js
    
    > canvas-prebuilt@1.6.0 install /usr/local/lib/node_modules/@sonarwhal/sonar/node_modules/canvas-prebuilt
    > node-pre-gyp install
    
    [canvas-prebuilt] Success: "/usr/local/lib/node_modules/@sonarwhal/sonar/node_modules/canvas-prebuilt/canvas/build/Release/canvas-prebuilt.node" is installed via remote
    
    > amphtml-validator@1.0.20 postinstall /usr/local/lib/node_modules/@sonarwhal/sonar/node_modules/amphtml-validator
    > /bin/sh -c "exit 0" 2> postinstall.DELETEME && rm postinstall.DELETEME || node postinstall-windows.js
    
    
    > axe-core@2.4.2 postinstall /usr/local/lib/node_modules/@sonarwhal/sonar/node_modules/axe-core
    > node build/utils/postinstall.js
    
    + @sonarwhal/sonar@0.13.0
    added 438 packages in 81.745s
    

  • 作業ディレクトリを作成
    init コマンドを打つため、作業ディレクトリを作成します。

    mkdir sonar
    

init コマンド実行

  • ディレクトリ移動、initコマンドを実行
    cd sonar
    sonar --init
    

以下、console 上で幾つか質問を聞かれるので、答えていきます。

  • ブラウザを選択
    chrome選択しました。

    Welcome to sonar configuration generator
    ? What connector do you want to use? (Use arrow keys)
    ❯ chrome 
      jsdom 
    

  • formatter を選択
    json選択しました。

    ? What formatter do you want to use? 
    ❯ codeframe 
      json 
      stylish 
      summary 
    

  • 推奨ルールを使うか否かを選択
    Y選択しました。

    ? Do you want to use the recommended rules configuration? 
    

  • 対象ブラウザを選択
    Default選択しました。

    ? What browsers are you targeting? (Use arrow keys)
    ❯ Default (last 2 versions of each browser, and browsers with globaly usage over 1%, plus Firefox ESR) 
      Custom (use browserslist format:  https://github.com/ai/browserslist#queries) 
    

  • .sonarrc の内容を確認
    選択した設定に従い、.sonarrc作成されます。
    上記の選択だと、以下の内容で作成されました。

    % cat .sonarrc 
    {
        "browserslist": [],
        "connector": {
            "name": "chrome",
            "options": {
                "waitFor": 1000
            }
        },
        "formatters": [
            "json"
        ],
        "ignoredUrls": [],
        "rules": {
            "amp-validator": "off",
            "apple-touch-icons": "error",
            "axe": "error",
            "content-type": "error",
            "disown-opener": "error",
            "highest-available-document-mode": "error",
            "html-checker": "error",
            "image-optimization-cloudinary": "off",
            "manifest-app-name": "error",
            "manifest-exists": "error",
            "manifest-file-extension": "error",
            "manifest-is-valid": "error",
            "meta-charset-utf-8": "error",
            "meta-viewport": "error",
            "no-disallowed-headers": "error",
            "no-friendly-error-pages": "error",
            "no-html-only-headers": "error",
            "no-protocol-relative-urls": "error",
            "no-vulnerable-javascript-libraries": "error",
            "ssllabs": "off",
            "strict-transport-security": "error",
            "validate-set-cookie-header": "error",
            "x-content-type-options": "error"
        },
        "rulesTimeout": 120000
    }
    

チェック実行

このサイトに対して、チェックを実行します。

  • チェック実行

    sonar https://www.monotalk.xyz
    

  • 警告の抜粋
    json フォーマットを選択したので、json形式で出力されます。

    https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4: 5 issues
    [
      {
        "location": {
          "column": -1,
          "line": -1
        },
        "message": "'content-type' header should have media type 'application/font-woff2' (not 'application/x-font-woff')",
        "resource": "https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4",
        "ruleId": "content-type",
        "severity": 2,
        "sourceCode": null
      },
      {
        "location": {
          "column": -1,
          "line": -1
        },
        "message": "'server' header is disallowed",
        "resource": "https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4",
        "ruleId": "no-disallowed-headers",
        "severity": 2,
        "sourceCode": null
      },
      {
        "location": {
          "column": -1,
          "line": -1
        },
        "message": "'x-ua-compatible' header is not needed",
        "resource": "https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4",
        "ruleId": "no-html-only-headers",
        "severity": 2,
        "sourceCode": null
      },
      {
        "location": {
          "column": -1,
          "line": -1
        },
        "message": "'strict-transport-security' header was not specified",
        "resource": "https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4",
        "ruleId": "strict-transport-security",
        "severity": 2,
        "sourceCode": null
      },
      {
        "location": {
          "column": -1,
          "line": -1
        },
        "message": "'x-content-type-options' header was not specified",
        "resource": "https://www.monotalk.xyz/static/fonts/Open-Sans-800italic/Open-Sans-800italic.woff2?5ddec16961e4",
        "ruleId": "x-content-type-options",
        "severity": 2,
        "sourceCode": null
      }
    ]
    

設定変更して、再度チェックを実行

コンソールで内容を確認するには、json 形式だと見づらいので別の形式に変更、3rd party の リソースで出力される警告を OFF にします。
また、Web UI から チェック実施した際に無視したルールを除外します。

出力フォーマットを変更

  • .sonarrc編集
    .sonarrc編集して formatter を "stylish"変更します。
        "formatters": [
            "stylish"
        ],
    
  • チェックを再実行

    sonar https://www.monotalk.xyz
    

  • チェック結果の抜粋
    コンソール出力に見やすい形式で出力されます。

    ✖ Finishing...
    https://www.monotalk.xyz/
                        Error  Invalid date format in 'expires' value of the 'set-cookie' header to set 'csrftoken'. The recommended format is: Mon, 29 Oct 2018 11:58:05 GMT                                                                             validate-set-cookie-header
                        Error  Manifest not specified                                                                                                                                                                                                     manifest-exists
                        Error  jQuery@2.2.4 has 2 known vulnerabilities (1 medium, 1 low). See https://snyk.io/vuln/npm:jquery for more information.                                                                                                      no-vulnerable-javascript-libraries
    line 4   col 21516  Error  Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-323&1=BlogPost-324&1=BlogPost-325&1=BlogPost-326&1=BlogPost-327&1=BlogPost-328&1=BlogPost-329&1=BlogPost-330&1=BlogPost-331&1=BlogPost-332  no-protocol-relative-urls
    line 4   col 21764  Error  Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-333&1=BlogPost-334&1=BlogPost-335&1=BlogPost-337&1=BlogPost-338&1=BlogPost-339&1=BlogPost-340&1=BlogPost-341&1=BlogPost-342&1=BlogPost-343  no-protocol-relative-urls
    line 4   col 22012  Error  Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-344&1=BlogPost-345&1=BlogPost-346&1=BlogPost-347&1=BlogPost-348                                                                             no-protocol-relative-urls
    line 5   col 20046  Error  Protocol relative URL found: //uh.nakanohito.jp/uhj2/uh.js                                                                                                                                                                 no-protocol-relative-urls
    line 5   col 21384  Error  Protocol relative URL found: //monotalkxyz.disqus.com/count.js                                                                                                                                                             no-protocol-relative-urls
    line 5   col 22996  Error  <ul> and <ol> must only directly contain <li>, <script> or <template> elements                                                                                                                                             axe
    line 16  col 205    Error  Form elements must have labels                                                                                                                                                                                             axe
    line 16  col 310    Error  Form elements must have labels                                                                                                                                                                                             axe
    line 16  col 1002   Error  Protocol relative URL found: //pagead2.googlesyndication.com/pagead/js/adsbygoogle.js                                                                                                                                      no-protocol-relative-urls
    line 16  col 1598   Error  Frames must have title attribute                                                                                                                                                                                           axe
    line 20  col 7460   Error  Elements must have sufficient color contrast                                                                                                                                                                               axe
    line 31  col 88     Error  Protocol relative URL found: //pagead2.googlesyndication.com/pagead/js/adsbygoogle.js                                                                                                                                      no-protocol-relative-urls
    line 31  col 684    Error  Frames must have title attribute                                                                                                                                                                                           axe
    line 33  col 10696  Error  Links must have discernible text                                                                                                                                                                                           axe
    line 33  col 10909  Error  Links must have discernible text                                                                                                                                                                                           axe
    line 33  col 11119  Error  Elements must have sufficient color contrast                                                                                                                                                                               axe
    ✖ Found 19 errors and 0 warnings
    
    中略.....................
    
    https://fcmatch.youtube.com/pixel?goog … cql_Xe3xhq4cSK1pDUlBdIUqmjVJtWBTQ51wpzw
    Error  'x-frame-options', 'x-xss-protection' headers are not needed  no-html-only-headers
    Error  'strict-transport-security' header was not specified          strict-transport-security
    Error  'x-content-type-options' header was not specified             x-content-type-options
    ✖ Found 3 errors and 0 warnings
    
    https://pagead2.googlesyndication.com/ … UiZYl3_X2rV4FTV0sl2De43qVlh58jk7tgEaozB
    Error  'strict-transport-security' header was not specified  strict-transport-security
    ✖ Found 1 error and 0 warnings
    
    ✖ Found a total of 181 errors and 0 warnings
    

ignore URL を追加

3rd party のリソースで警告が出力されますが、対処ができないため一律 OFF にします。

  • ignore URL に、エラーを無視したいドメインを追加
    ignoredUrls に、エラーを無視したいドメインを追加します。
    全てのルールを無視したいので、rules には ["*"]設定しています。

  "ignoredUrls": [
        {
  "domain": "pagead2.googlesyndication.com",
  "rules": ["*"]
  },
  {
  "domain": "www.gstatic.com",
  "rules": ["*"]  
  },
  {
  "domain": "tpc.googlesyndication.com",
  "rules": ["*"]  
  },
  {
  "domain": "fonts.gstatic.com",
  "rules": ["*"]  
  },
        {
  "domain": "googleads.g.doubleclick.net",
  "rules": ["*"]  
  },
  {
  "domain": "monotalkxyz.disqus.com",
  "rules": ["*"]  
  },
  {
  "domain": "fonts.googleapis.com",
  "rules": ["*"]  
  },
  {
  "domain": "www.google-analytics.com",
  "rules": ["*"]  
  },
  {
  "domain": "securepubads.g.doubleclick.net",
  "rules": ["*"]  
  },
  {
  "domain": "uh.nakanohito.jp",
  "rules": ["*"]  
  },
  {
  "domain": "adservice.google.com",
  "rules": ["*"]  
  },
  {
  "domain": "adservice.google.co.jp",
  "rules": ["*"]  
  },
  {
  "domain": "www.googletagmanager.com",
  "rules": ["*"]  
  }
    ],

  • チェックを再実行

    sonar https://www.monotalk.xyz
    

  • チェック結果
    3rd party のドメインのエラーは出力されなくなりました。

    ✖ Finishing...
    https://www.monotalk.xyz/
                        Error    Invalid date format in 'expires' value of the 'set-cookie' header to set 'csrftoken'. The recommended format is: Mon, 29 Oct 2018 12:05:14 GMT                                                                             validate-set-cookie-header
                        Error    Manifest not specified                                                                                                                                                                                                     manifest-exists
                        Error    jQuery@2.2.4 has 2 known vulnerabilities (1 medium, 1 low). See https://snyk.io/vuln/npm:jquery for more information.                                                                                                      no-vulnerable-javascript-libraries
    line 4   col 21516  Error    Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-323&1=BlogPost-324&1=BlogPost-325&1=BlogPost-326&1=BlogPost-327&1=BlogPost-328&1=BlogPost-329&1=BlogPost-330&1=BlogPost-331&1=BlogPost-332  no-protocol-relative-urls
    line 4   col 21764  Error    Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-333&1=BlogPost-334&1=BlogPost-335&1=BlogPost-337&1=BlogPost-338&1=BlogPost-339&1=BlogPost-340&1=BlogPost-341&1=BlogPost-342&1=BlogPost-343  no-protocol-relative-urls
    line 4   col 22012  Error    Protocol relative URL found: //monotalkxyz.disqus.com/count-data.js?1=BlogPost-344&1=BlogPost-345&1=BlogPost-346&1=BlogPost-347&1=BlogPost-348                                                                             no-protocol-relative-urls
    line 5   col 20046  Error    Protocol relative URL found: //uh.nakanohito.jp/uhj2/uh.js                                                                                                                                                                 no-protocol-relative-urls
    line 5   col 21331  Error    Element “ul” not allowed as child of element “ul” in this context. (Suppressing further errors from this subtree.)                                                                                                         html-checker
    line 5   col 21384  Error    Protocol relative URL found: //monotalkxyz.disqus.com/count.js                                                                                                                                                             no-protocol-relative-urls
    line 5   col 22996  Error    <ul> and <ol> must only directly contain <li>, <script> or <template> elements                                                                                                                                             axe
    line 16  col 97     Error    Element “form” not allowed as child of element “ul” in this context. (Suppressing further errors from this subtree.)                                                                                                       html-checker
    line 16  col 205    Error    Form elements must have labels                                                                                                                                                                                             axe
    line 16  col 310    Error    Form elements must have labels                                                                                                                                                                                             axe
    line 16  col 743    Error    Element “p” not allowed as child of element “h1” in this context. (Suppressing further errors from this subtree.)                                                                                                          html-checker
    line 16  col 1002   Error    Protocol relative URL found: //pagead2.googlesyndication.com/pagead/js/adsbygoogle.js                                                                                                                                      no-protocol-relative-urls
    line 16  col 1598   Error    Frames must have title attribute                                                                                                                                                                                           axe
    line 19  col 2149   Warning  Text run is not in Unicode Normalization Form C.                                                                                                                                                                           html-checker
    line 20  col 7460   Error    Elements must have sufficient color contrast                                                                                                                                                                               axe
    line 31  col 88     Error    Protocol relative URL found: //pagead2.googlesyndication.com/pagead/js/adsbygoogle.js                                                                                                                                      no-protocol-relative-urls
    line 31  col 684    Error    Frames must have title attribute                                                                                                                                                                                           axe
    line 33  col 10696  Error    Links must have discernible text                                                                                                                                                                                           axe
    line 33  col 10909  Error    Links must have discernible text                                                                                                                                                                                           axe
    line 33  col 11119  Error    Elements must have sufficient color contrast                                                                                                                                                                               axe
    ✖ Found 22 errors and 1 warning
    
    ✖ Found a total of 22 errors and 1 warning
    

除外ルールを追加

validate-set-cookie-headerno-protocol-relative-urlsno-vulnerable-javascript-libraries Web UI でのチェック実施時に無視していたので、除外します。
また、manifest-existsついては、PWA 関連の manifest ファイル が存在しないことについての警告ですので、こちらも一旦除外します。

    "rules": {
        "amp-validator": "off",
        "apple-touch-icons": "error",
        "axe": "error",
        "content-type": "error",
        "disown-opener": "error",
        "highest-available-document-mode": "error",
        "html-checker": "error",
        "image-optimization-cloudinary": "off",
        "manifest-app-name": "error",
        "manifest-exists": "off", // off に設定
        "manifest-file-extension": "error",
        "manifest-is-valid": "error",
        "meta-charset-utf-8": "error",
        "meta-viewport": "error",
        "no-disallowed-headers": ["error",{ "ignore":["Server"] }],
        "no-friendly-error-pages": "error",
        "no-html-only-headers": "error",
        "no-protocol-relative-urls": "off", // off に設定
        "no-vulnerable-javascript-libraries": "off", // off に設定
        "ssllabs": "off",
        "strict-transport-security": "error",
        "validate-set-cookie-header": "off", // off に設定
        "x-content-type-options": "error"
    },


Web UI で実行する場合との違いについて

推奨ルールを使った場合の Web UI との適用ルールの差分について説明します。
aXeチェック、 html-checkerチェックがかかるため、Web UI とは警告の内容が異なります。

  • aXe のチェックが効いている
    2017/10/30 時点では Web UI での aXe のチェックは実施できないようですが、CLI からは実行されており、ログに警告が出力されています。

  • “html-checker” が効いている
    Web UI だと、html の妥当性検証はかかっていなかったのですが、CLI ツールで実行すると、チェックがかかるようです。

  • “ssllabs” が “off” になっている
    Web UI だと、Qualys SSL Labsチェックが行われますが、CLI では推奨ルールで OFF になっています。
    これは、イントラネット環境で Glogbal な Domain が割り当てられていない場合、チェックが失敗するからかと思います。

  • “image-optimization-cloudinary” が “off”
    cloudinary の api による 画像のサイズチェックも OFF になっています。
    これも、イントラネット環境で Glogbal な Domain が割り当てられていない場合、チェックが失敗するからかと思います。
    Cloudinary offers support for sonar | Cloudinary Blog

  • “amp-validator” が “off”
    これは、Web UI でも OFF になっていました。AMP ページの場合は有効にするのかと思います。


警告に対処する

出力された Found a total of 22 errors and 1 warning対して対処していきます。
Web UI で無視していた警告は、特に触らず修正は行なっていません。

html checker の警告

以下、出力されていた html checker警告になります。それぞれ対処していきます。

  • Error Element “ul” not allowed as child of element “ul” in this context. (Suppressing further errors from this subtree.)
    ul の 子要素として ul が使用されているという警告です。
    確かに不要な ul がありましたので削除しました。

  • Error Element “p” not allowed as child of element “h1” in this context. (Suppressing further errors from this subtree.)
    h1 の 子要素として、p タグが使われているという警告です。
    h タグの中に入れていいのはインライン要素のみなので、ブロックタグ である p タグは削除する必要があります。
    対象箇所の p タグを削除しました。1

  • Warning Text run is not in Unicode Normalization Form C.
    「Text run is not in Unicode Normalization Form C.」というHTML Validation Serviceの警告について: 小粋空間見る限り Unicode正規化形式C ではない文字列が混じっているとこの警告がでるようです。対象箇所をValidator.nu (X)HTML5 Validator確認したところ、濁点まじりの文字で警告が出ているようでした。
    Pythonのunicodedata.normalize(‘NFKC’, x)で正規化される文字一覧 - めもちょう見ると、unicodedata.normalize正規化はできそうなので、後日やってみようかと思います。

axe の警告

続いて、axe警告に対処します。
sonar ではエラーとしては認識できますが、実際の修正には、axe chrome plugin や、 firefox の plugin を使ったほうが修正作業はしやすいかと思います。
私は以下の chrome plugin を使って修正作業を行いました。
aXe - Chrome ウェブストア

  • Error Form elements must have labels
    Form の input タグに label が付与されていないという警告です。
    これは Form の デザイン的に入れるのが難しいため、無視しました。

  • **Error `

      and
        must only directly contain
      1. ,