アイデア
チャットアプリケーションなどで、ユーザー入力中のtextarea
などに対して、textlintを実行させたい。
アイデア自体は@textlint/browser でも議論されている。
Chrome拡張として、textlint-proofreaderが存在するが、今回はSPAを利用するすべてのユーザーに機能としての提供を行いたい。
できたもの
実装
texlint
コマンド自体は .textlintrc
に記載されたルールモジュールの解決や、対象ファイルの読み込みなどを行っており、lintの実行処理自体は、@textlint/kernel が担っている。
そこにTextlintKernelOptionsを正しく渡してあげれば実行できる。
export interface TextlintKernelOptions {
// file type
// For example) .md
ext: string;
// file path
filePath?: string;
// plugins
plugins?: TextlintKernelPlugin[];
// rules
rules?: TextlintKernelRule[];
// filterRules
filterRules?: TextlintKernelFilterRule[];
// config base directory
// It is a value of context.getConfigBaseDir.
configBaseDir?: string;
}
ビルド設定
TextlintKernelOptions
の plugins
やrules
はそれぞれnode_modules
として実装されているので、
それらも含めてトランスパイル済みの各ルールをバンドルしたJavaScriptとして出力してあげればIE11を含めてブラウザで動くはず。
core-js/babel/webpack の最適解がわからなさすぎだが、
browserで読み込むファイルのエントリーポイントの先頭で
import 'core-js/stable';
import 'regenerator-runtime/runtime';
して、webpack.config
は以下の設定にすることでIE11でも動くものがビルドできた。
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'production',
entry: {
'textlint': './browser.js',
},
output: {
filename: '[name].bundle.min.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /@babel(?:\/|\\{1,2})runtime|core-js/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3,
targets: {
ie: '11',
},
}]
]
}
}
}
]
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 5,
compress: true,
output: {
comments: false,
beautify: false
}
}
})]
},
plugins: [
new MomentLocalesPlugin({
localesToKeep: ['en', 'ja', 'es', 'fr', 'zh-cn', 'zh-hk', 'zh-tw',], // https://github.com/azu/textlint-rule-date-weekday-mismatch/blob/master/src/textlint-rule-date-weekday-mismatch.js#L10
}),
]
};
問題点
- bundleサイズが大きい
-
fs
アクセスするルールがbundleに失敗する。babel-plugin-static-fsをビルド時に利用すれば解決するかもしれない。