わたしの日記だよ

ー生きる厳しさと哀しさを鮮烈に謳うー

vue + ckeditor5 でエラーが出たときにしたこと

前回、vue + ckeditor5 の使い方についてまとめました。 その際、私の環境だと色々とエラーが出たので、対応方法を書いていきます。

前回の記事は、こちら↓↓↓ https://s31o3.hatenablog.com/entry/2019/10/20/231141

【その1】cssのビルドに失敗している風

【事象】webpack で、以下のようなエラーが出てしまう。

ERROR in ./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css (./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/src??ref--4-2!./node_modules/style-loader!./node_modules/css-loader/dist/cjs.js!./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css)
Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError

(2:1) Unknown word

  1 | 
> 2 | var content = require("!!../../../../../css-loader/dist/cjs.js!./button.css");
    | ^
  3 | 
  4 | if(typeof content === 'string') content = [[module.id, content, '']];

【原因】ckeditor5 の CSS を複数回 loader にかけようとしている

新しく追加したckeditorのCSS用の設定と、既存のCSS設定がかぶってしまっています。 webpack.config.js の既存のCSS設定部分に、ckeditorを除外する指定を追加します。

module: {
        rules: [
            ...
            {
                test: /\.css$/,
                exclude: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/, // 👈これを追加 
                loader: ...
            }
        ...
        ]
    }

【その2】ckeditor のビルドに失敗している

【事象】

build版と同じバージョンの関連パッケージをインストールし、config.plugins に設定したはずが
「ckeditor-duplicated-modules 」とエラーが出てしまう。

【原因】

エラーの通りなのですが、重複した module を実行しようとしています。 私の環境では、関連パッケージのバージョンを上げると解決しました。

【その3】ckeditor のクラスを extends したクラスを作ると、実行時にエラーが出る

【事象】

Uncaught TypeError: Class constructor [ClassName] cannot be invoked without 'new'

【原因】ES5にトランスパイルしようとしている

ckeditor5 は、ES6で書かれています。 ES6 で書かれたクラスを継承したものを、ES5 にトランスパイルするのは許してくれないらしい。

qiita.com

幸い今回は、IE捨てても問題なかったので、おとなしくトランスパイルのターゲットをES6にしました。

思い返すと、ほとんどフロント不勉強なだけのようなエラーですね、、

vue + ckeditor5 を使ってみる

vue で ckeditor 5 を使ってみたところ、4系とだいぶ使用方法が変わっていたのでメモ👀。

前提

  • vue 2.6.X
  • webpack 4.32.X
  • ckeditor 5系

build 版(@ckeditor/ckeditor5-editor-classic)を使う

カスタマイズせず、そのまま使うので良いなら、↓するだけ

yarn add @ckeditor/ckeditor5-build-classic @ckeditor/ckeditor5-vue

toolbar などカスタマイズしたい場合は、以下の手順が必要になります。

  1. ckeditor5-editor-classic のリポジトリを clone してくる
  2. 追加したいプラグインをインストール
  3. ClassicEditor.builtinPlugins に 2. のプラグインを追加
  4. build する

詳細は ↓↓↓

https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html#adding-a-plugin-to-a-build

当初、こっちを使用する予定でしたが clone するのはちょっとイヤだったので、もう一方を使うことにしました。

source 版(@ckeditor/ckeditor5-editor-classic)を使う

Rich text editor component for Vue.js ↓↓↓ https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/vuejs.html

公式の Vue.js 版のドキュメントは、vue-cli 前提なのですが 今回のプロジェクトでは vue-cli は使っていないため、Advanced setup のページを見ながら進めます。 https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/advanced-setup.html#scenario-2-building-from-source

1. build版の package.json の devDependencies から、ckeditor 関連の package 部分を、自分の package.json にコピーしてくる。 (2019/10/20時点の Tag: v12.3.1 だと↓こんなかんじ)

  "dependencies": {
    "@ckeditor/ckeditor5-adapter-ckfinder": "^11.0.4",
    "@ckeditor/ckeditor5-autoformat": "^11.0.4",
    "@ckeditor/ckeditor5-basic-styles": "^11.1.3",
    "@ckeditor/ckeditor5-block-quote": "^11.1.2",
    "@ckeditor/ckeditor5-ckfinder": "^11.0.4",
    "@ckeditor/ckeditor5-core": "^12.2.1",
    "@ckeditor/ckeditor5-dev-utils": "^12.0.0",
    "@ckeditor/ckeditor5-dev-webpack-plugin": "^8.0.0",
    "@ckeditor/ckeditor5-easy-image": "^11.0.4",
    "@ckeditor/ckeditor5-editor-classic": "^12.1.3",
    "@ckeditor/ckeditor5-essentials": "^11.0.4",
    "@ckeditor/ckeditor5-heading": "^11.0.4",
    "@ckeditor/ckeditor5-image": "^13.1.2",
    "@ckeditor/ckeditor5-link": "^11.1.1",
    "@ckeditor/ckeditor5-list": "^12.0.4",
    "@ckeditor/ckeditor5-media-embed": "^11.1.3",
    "@ckeditor/ckeditor5-paragraph": "^11.0.4",
    "@ckeditor/ckeditor5-paste-from-office": "^11.0.4",
    "@ckeditor/ckeditor5-table": "^13.0.2",
    "@ckeditor/ckeditor5-theme-lark": "^14.1.1",
    // ...
}

2. source 版本体と、build に必要な package をインストールする

yarn add @ckeditor/ckeditor5-editor-classic @ckeditor/ckeditor5-vue postcss-loader@3 raw-loader@3 style-loader@1 webpack@4 webpack-cli@3

3. webpack の設定追加

const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );

module.exports = {
    plugins: [
        // ...

        new CKEditorWebpackPlugin( {
            language: 'ja'
        } )
    ],

    module: {
        rules: [
            {
                test: /ckeditor5-[^/]+\/theme\/icons\/.+\.svg$/,
                use: [ 'raw-loader' ]
            },
            {

                test: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            injectType: 'singletonStyleTag'
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: styles.getPostCssConfig( {
                            themeImporter: {
                                themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
                            },
                            minify: true
                        } )
                    },
                ]
            }
        ]
    }
};

4. vue 作成 これも、build 版のコードを参考に。

ckeditor5-build-classic/ckeditor.js at v12.4.0 · ckeditor/ckeditor5-build-classic · GitHub

以上なのですが、私の環境だと色々エラーが出たので 別ページでまとめたいと思います👀

Julia + Genie 環境構築

記事を見ながらやっていたら、ちょこちょこエラーが出たのでメモ。 (結局、公式 Genie | Genie.jl の通りにやったら、何も問題なかった、、、)

Julia インストール

1. Mac なら、homebrew or 公式ページからダウンロードしてきます。 今回は homebrew で。

brew tap caskroom/cask
brew cask install julia

念のため、julia -v して確認

Genie セットアップ

1. ターミナルから、julia を対話モードで起動

julia

f:id:s31o3:20190909003115p:plain

2. Pkg の update

using Pkg
Pkg.update()

f:id:s31o3:20190909003303p:plain

3. Genie Install

Pkg.add("Genie")

f:id:s31o3:20190909001725p:plain

4. Genie プロジェクトを作成

using Genie

f:id:s31o3:20190909003154p:plain

※ ちょっと時間がかかります

Genie.newapp("MyAppName")

f:id:s31o3:20190909004645p:plain

ここまでで、juliaコマンドを実行したときにいたディレクトリに、MyAppNameのお名前でプロジェクトが作成されます

5. ブラウザから確認 f:id:s31o3:20190909003618p:plain

※ Julia の対話モードを終了したいときは、

exit()

まだ構文を遠目に見ただけなので、何か作りながら覚えたいな

【Elasticsearch】 index.max_result_window の値を変更する

Elasticsearch 2.1 から、Search API で from + size の値に制限がかかるようになりました。 デフォルトで、10000 を超えると「Result window is too large〜」というエラーが出ます。

この制限は、index.max_result_window を指定することで変更できます。

設定方法

[ Index をこれから作る or 作り直してもよい場合 ]

  • elasticsearch.yml の「index.max_result_window: 10000」の値を変更する
  • rails を一緒に使っていて、elasticsearch-ruby gem を入れているなら、普通に settings のところに書けます(他の gem でも同じかな?)
settings: {
        number_of_shards: 1,
        number_of_replicas: 0,
        max_result_window: 10000,
        analysis: {
          analyzer: {
          …

[ Index を作り直したくない場合 ]

Index API を使っても変更できます。Kibanaだったら、こんなかんじ↓

PUT index_name/_settings
{
    "index": {
        "max_result_window": "10000" 
    }
}

上限を十分に大きくすれば、エラーは出なくなります。 が、結局は一度指定された位置までの全ドキュメントを読み込んでから
不要な部分を削除して返すので、値が大きくなるとコストがすごくなってしまいます。

状況によっては scroll や search_after の利用を検討します。

【MySQL】Query メモだよ

どうやって書くか、すぐ忘れちゃう、、

特定の文字の数

cf.) ancestry カラム内の、「/」の数
「1/10」→「1」
「1/10/1000」→「2」

LENGTH(ancestry) - LENGTH(REPLACE(ancestry, '/', ''))

特定の文字列の数

cf.) school カラム内の、「コース」の数

(LENGTH(school) - LENGTH(REPLACE(school, 'コース', ''))) / LENGTH('コース')

「最初に出現した特定の文字」より前を切り出す

cf.) ancestry カラム内の、最初に出現した「/」より前
「1/10」→「1」
「1/10/1000」→「1」

SUBSTRING_INDEX(ancestry, '/', 1)

「最後に出現した特定の文字」より後を切り出す

cf.) ancestry カラム内の、最後に出現した「/」より後
「1/10」→「10」
「1/10/1000」→「1000」

SUBSTRING_INDEX(ancestry, '/', -1)

「最後に出現した特定の文字」より前を切り出す

cf.) ancestry カラム内の、最後に出現した「/」より前
「1/10」→「1」
「1/10/1000」→「1/10」

SUBSTRING_INDEX(ancestry, '/', LENGTH(ancestry) - LENGTH(REPLACE(ancestry, '/', '')))

【IE11】border-radiusを指定すると、うすく枠線が入る問題

久しぶりに、結構ハマったIE問題です。。

 

通知アイコン(画像の上にマルを重ねて、通知数を表示するようなあれです)を作っていたのですが、IEのときだけ、ほそーく外枠が表示されてしまうのです。

↓こんな感じに。
f:id:s31o3:20171114135849p:plain

コードはこんな感じ。ベースのdivの中で、重ねて表示しているだけ。

HTML

    <div class="base">
      <span class="rect"></span>
      <span class="circle"></span>
    </div>

CSS

.base {
  position: relative;
  width: 30px;
  height: 30px;
}
.base .rect {
  position: absolute;
  display: block;
  left: 0;
  bottom: 0;
  width: 30px;
  height: 30px;
  background-color: gray;
}
.base .circle {
  position: absolute;
  display: block;
  top: -10px;
  right: -10px;
  width: 20px;
  height: 20px;
  border: 2px solid #fff;
  border-radius: 20px;
  background-color: red;
  color:#fff;
}


隣接要素とくっついた要素に、border-ragiusを設定すると出てしまうらしい。
border-radius設定時、IE11だと隣接要素との間に薄く線が入る(隙間ができる) - Qiita

最初、HTMLから変えるつもりでごにょごにょしてみたけど、なかなかキレイに表示できず。
ダメ元で、spanの片方を擬似要素にしたりしても、やっぱりダメでした!


.circle が border: none; のときは
f:id:s31o3:20171114153746p:plain
こんなかんじで、隣接要素とくっついていても大丈夫だったので、
border を使わない方向で解決しました。

.base .circle {
  position: absolute;
  display: block;
  top: -10px;
  right: -10px;
  width: 18px;                           
  height: 18px;
  border: none;                                         // ここから
  -webkit-box-shadow: 0 0 0 2px #fff; 
  box-shadow: 0 0 0 2px #fff;                // ここまでを変更!
  border-radius: 18px;                             //   ※あとは、width,height,border-radiusを枠線分マイナス
  background-color: red;
  color:#fff;
}


見た目はこんなかんじ。
f:id:s31o3:20171114160706p:plain


でも、そのあとすぐ、このページを発見。
css - Strange border-color issue - Stack Overflow
↓これを追加するだけでOKだったのでした。。。><

  -webkit-background-clip: padding-box; 
  -moz-background-clip: padding; 
  background-clip: padding-box;

jQuery で Unicodeエスケープされた値を含む json を処理する

 

郵便番号を入力して、対応する住所を表示する〜という、よくあるやつを実装しています。

ajax で直に WebAPI を呼んでいるときは問題なかったのですが、該当ページが https なのに

WebAPI は https 非対応で Mixed Content の警告が出てしまうため、間にサーバーを挟んだところ

json の中身が Unicodeエスケープされるようになって、うまく認識できなくなってしまいました。

 

これが、ajax から直接 WebAPI を呼んでいたときの json

{"status":200,"rows":[{"col1":"値1", "col2":"値2"}]}

ajax の部分はこんな感じ。

$.ajax({
    type : 'get',
    url : 'XXXX?postalCode=' + postalCode
})
.then(
    function (data) {
        if (data.status == "200") {
            …略…
        } else {
            // 失敗
        }
    },
    function () {
        // 失敗
    }
);

 

そして、こっちが ajax →サーバー→ WebAPI と、サーバーを経由したときの json

"{\"status\":200,\"rows\":[{\"col1\":\"\\u5024\\uff11\",\"col2\":\"\\u5024\\uff12\"]}"

 色々と、エスケープされまくっている。。。

元のコードのようにただ data.status 〜としても何も取れません。

 

 【結論】オブジェクトに変換すれば大丈夫。

function (data) {
        try {
            data = $.parseJSON(data); // ←これだけ!
        catch (e) {
            // 失敗
        }
        if (data.status == "200") {
            …略…
        } else {
            // 失敗
        }

 Unicodeエスケープをマルチバイト文字に戻して、ダブルクォーテーションをエスケープしてる

バックスラッシュもreplaceで取って〜など、色々試しましたが、結局 parseJSON で

すべて解決しました。

結構ハマってしまった><