はなゐろぐ

2022.02.15

Tailwind CSSのフォントサイズクラスにはデフォルトでline-heightプロパティもついています(参考: Font Size - Tailwind CSS)。デザインがかっちり決まっている時には若干不便なので、設定ファイルで削除します。

tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme');
const defaultFontSize = defaultTheme.fontSize;
const fontSize = {};
Object.keys(defaultFontSize).forEach((key) => {
  fontSize[key] = [defaultFontSize[key][0]];
});

module.exports = {
  theme: {
    fontSize,
  }
};

fontSizeは配列でフォントサイズとその他のパラメータが格納されています(参考: Font Size - Tailwind CSS)。なので、配列0番目の値だけ抽出して指定しなおしてあげればOKです。

やってみれば案外簡単なことなんですが、ググっても出てこなかったので記事にしました。同じように悩んでいる方はお試しあれ。

まず、Markdownパーサをインストールします。今回はParsedownを使います。

$ composer require erusev/parsedown

次に、カスタムフィルタを追加します。

functions.php
require_once 'vendor/autoload.php';

add_filter(
    'timber/twig',
    function( $twig ) {
        $twig->addFilter(
            new \Twig\TwigFilter(
                'markdown',
                function( $value ) {
                    return Parsedown::instance()
                        ->setMarkupEscaped( true )
                        ->setBreaksEnabled( true )
                        ->text( $value );
                }
            )
        );

        return $twig;
    }
);

setBreaksEnabled()をtrueにすることで、単一の改行をbr要素に変換してくれます。

参考: Tutorial: Get Started · erusev/parsedown Wiki · GitHub

markdownという名前のカスタムフィールドをパースするなら、こんな感じ。

{{ post.meta('markdown')|markdown }}

余談: なぜMarkdownを使うのか

カスタムフィールドのコンテンツにリンクや簡単な装飾を含めたい、というご要望がありました。Wysiwygで対応しようと思っていましたが、機能が多く冗長感がありました。Wordのように自由度が高い一方、デザインを逸脱してしまわないかという懸念がありました(原色や極端に大きいフォントサイズなど)。Markdownは自由度が低く、今回のようなちょっとした装飾程度なら必要十分だと考えました。

導入

インストール

$ npx degit "sveltejs/sapper-template#rollup" sapper
$ cd sapper
$ npm install
$ npm i -D tailwindcss svelte-preprocess sass postcss autoprefixer
$ npx tailwind init

IE11をサポートするなら、tailwindcss@1.9.6を入れます。

Tailwind CSS の設定

tailwind.config.js
module.exports = {
  purge: {
    content: ['./src/**/*.svelte', './src/**/*.html'],
  },
};

未使用クラスを削除するPurgeCSSの設定を記入します。デフォルトではproductionの時のみ走る処理です。強制的にproductionにするなら、コマンドの頭にNODE_ENV=productionをつけます。

バンドラ(Rollup)の設定

rollup.config.js
import sveltePreprocess from 'svelte-preprocess';

const preprocess = {
  ...sveltePreprocess({
    sourceMap: dev,
    scss: true,
    postcss: {
      plugins: [
        require('tailwindcss'),
        require('autoprefixer')({ grid: 'no-autoplace' }),
      ],
    },
  }),
};

export default {
  client: {
    plugins: [
      svelte({
        dev,
        hydratable: true,,
        preprocess, // <- 追加 clientとserver両方
        emitCss: true
      }),
    ],
  },
};

CSSの処理設定を追記。途中ちょこちょこ端折ってますが…。

Svelte で Tailwind CSS を読み込む

_layout.svelte
<style global>
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
</style>

Lint 系設定

Stylelint

Svelte、Tailwind CSSの独自記法を許容させる。Prettierも入れます。

.stylelintrc.js
module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-prettier',
  ],
  rules: {
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          // Tailwind CSS
          'tailwind',
          'apply',
          'variants',
          'responsive',
          'screen',
        ],
      },
    ],
  },
};

ESLint

Svelteプラグインを入れます。Prettierも入れます。ESLintには<style>を無視してほしいので、その設定も追記。

.eslintrc.js
module.exports = {
  parserOptions: {
    ecmaVersion: 2019,
    sourceType: 'module',
  },
  env: {
    es6: true,
    browser: true,
  },
  extends: ['eslint-config-standard', 'prettier'],
  plugins: ['svelte3'],
  overrides: [
    {
      files: ['*.svelte'],
      processor: 'svelte3/svelte3',
    },
  ],
  settings: {
    'svelte3/ignore-styles': () => true,
  },
};

Prettier

Tailwind CSSを使うとどうしてもclass属性が長くなりがちなので、*.svelteの折返し幅を少しゆるめます。この値は各自お好みで。

.prettierrc.js
module.exports = {
  overrides: [
    {
      files: '*.svelte',
      options: {
        printWidth: 120,
      },
    },
  ],
};

prettier-plugin-tailwindも使いたいのですが、これを書いてる時点でSvelteをサポートしていないのでとりあえず見送り。Issueには要望が上がっているので期待したいですが、コミット履歴を見るに以前サポートしていたのをとりやめたようなので、難しいのかも…。

2020.11.17

microCMSでアップロードされた画像は、基本的に原寸で表示されます。

ユーザーによってはデジカメで撮った無加工の5000px超えJPG画像をアップロードされることもあります。Wordpressだとプラグインなどでアップロード時にリサイズできますが、microCMSにその機能はありません。その代わりに、画像URLにパラメータを付与することでリサイズされた画像を呼び出すことができます。ドキュメントはこちら

サムネイル画像など画像URLを直接呼び出すコンテンツならよいですが、リッチエディタ内の画像URLではできません。なので、データ取得後に置換してしまいます。

axios
  .get(`${$config.microCMSApiUrl}/blog/${params.id}`, {
    headers: {
      'X-API-KEY': $config.microCMSApiKey,
    },
  })
  .then((res) => {
    // 画像をリサイズするためパラメータを付与
    res.data.body = res.data.body.replace(
      /"(https?:\/\/images\.microcms-assets\.io\/.+?\.(jpe?g|gif|png))"/g,
      '"$1?fit=max&w=800&h=800"'
    );

    return res.data;
  });

記事詳細ページのコードを掲載します。リッチエディタのフィールドIDが「body」なので、res.data.bodyにリッチエディタ入力内容が格納されています。その中の画像URLを抽出し、末尾に?fit=max&w=800&h=800を付けてやります。このパラメータは、「800×800pxの中で縦横比を保ったままリサイズ」という意味です。800px四方より小さい場合はリサイズされません。

このほか、画像の品質を下げたりwebp形式に変換したりと、かなり柔軟に画像を呼び出せます。srcset属性付与やLightbox追加など、いろいろなことができそうですね。

普段ESLintやstylelintでソースコードをLintすることはありますが、文章のLintはしたことがなかったので、試してみました。

textlintを導入する

まず、textlint本体とルールプリセットをインストールし、設定ファイルを作成します。JS形式なのは私の好みです。

$ npm i -D textlint textlint-rule-preset-ja-spacing textlint-rule-preset-ja-technical-writing textlint-rule-spellcheck-tech-word
$ touch .textlintrc.js

設定ファイルはこんな感じ。preset-ja-technical-writingに関してはデフォルトよりゆるめにしています。

.textlintrc.js
module.exports = {
  rules: {
    // Youtube→YouTubeなど、技術系用語のスペルチェック
    "spellcheck-tech-word": true,
    // 技術系記事を書くためのルール
    "preset-ja-technical-writing": {
      // 一文あたりの最大文字数
      "sentence-length": {
        max: 120,
      },
      // 漢字が連続してよい最大文字数
      "max-kanji-continuous-len": {
        max: 8,
      },
      // 全角の「!?」を許容する
      "no-exclamation-question-mark": {
        // allow to use !
        allowHalfWidthExclamation: false,
        // allow to use !
        allowFullWidthExclamation: true,
        // allow to use ?
        allowHalfWidthQuestion: false,
        // allow to use ?
        allowFullWidthQuestion: true,
      },
    },
    // スペース関連のルール
    "preset-ja-spacing": true,
  },
};

コマンドを叩いてみます。私はHexoを使っているので、パスは下記のようになります。

$ npx textlint source/**/*.md

   11:17  ✓ error  Youtube => YouTube                     spellcheck-tech-word
   16:92  error    一つの文で"、"を3つ以上使用しています  ja-technical-writing/max-ten
   30:2   ✓ error  %o => %o                              spellcheck-tech-word
   30:65  ✓ error  %} => %}                              spellcheck-tech-word
   32:5   ✓ error  Youtube => YouTube                     spellcheck-tech-word
   37:2   ✓ error  %o => %o                              spellcheck-tech-word
   37:54  ✓ error  %} => %}                              spellcheck-tech-word
   44:2   ✓ error  %o => %o                              spellcheck-tech-word
   44:37  ✓ error  %} => %}                              spellcheck-tech-word
   51:2   ✓ error  %o => %o                              spellcheck-tech-word
   51:66  ✓ error  %} => %}                              spellcheck-tech-word
   58:2   ✓ error  %o => %o                              spellcheck-tech-word
   58:50  ✓ error  %} => %}                              spellcheck-tech-word
   65:2   ✓ error  %o => %o                              spellcheck-tech-word
   65:60  ✓ error  %} => %}                              spellcheck-tech-word
   72:2   ✓ error  %o => %o                              spellcheck-tech-word
   72:45  ✓ error  %} => %}                              spellcheck-tech-word
   79:2   ✓ error  %a => %a                              spellcheck-tech-word
  100:27  error    "ほど" が連続して2回使われています。   ja-technical-writing/ja-no-successive-word
  (...後略)

大量にエラーが出ました。「✓」がついたものは--fixオプションで自動的に修正できます。右側に表示されているのが引っかかったルールです。これは許容したい、というものがあれば設定ファイルに追記します。私の場合はHEXOの独自記法が引っかかったので、これを許容するようにルールを変えてみます。

$ npm i -D textlint-filter-rule-allowlist

プラグインをインストールできたら、設定ファイルに下記のように追記します。

.textlintrc.js
module.exports = {
  // 前略
  filters: {
    allowlist: {
      allow: [
        // HEXOの独自記法
        "/\\{%\\w+\\s.+\\s%\\}/",
      ],
    },
  },
};

正規表現で該当箇所を指定すると、エラーが出なくなります。

VSCodeと連携する

vscode-textlintをインストールします。私はtextlint.autoFixOnSaveをオンにして、保存時にfixも走るようにしました。

私はVSCodeにPrettierを入れて保存時に自動修正が走るようにしているのですが、これがpreset-ja-spacingの「英数字と日本語の間にスペースを開けない」とバッティングしてしまいました。PrettierリポジトリのIssueにもちょくちょく上がっているようなのですが、なかなか対応されていないようです。幸いMarkdownにおいてはPrettierがないと困るほどではないので、settings.jsonに下記を追記して無効化しました。

settings.json
"prettier.disableLanguages": ["markdown"]

とりあえずこれでしばらく運用してみます。まずは更新ペースを上げなくては…。