かすみん日記

暇なときに何か喋ります

【vscode】マークダウンのコードブロックにファイル名を表示する

Visual Studio CodeMarkdownプレビュー機能にて、コードブロック(code block)にファイル名を表示するには、以下の拡張機能を導入します:

marketplace.visualstudio.com

使い方

マークアップの方法は、以下のように、言語名のあとにコロン:で区切ってファイル名を書きます:

~~~css:./hoge/style.css
body {
  color: #abc;
}
~~~

はてなブログだと、コードブロックの中でバッククォート`を3つ書くことができなかったので、代わりにチルダ~で書いています。 ちなみに、コードブロックにはバッククォートが一般的ですが、代わりにチルダも使えます。 これは余談ですが

上記の拡張機能の標準スタイルでは、以下のようにプレビューされます(右側)。

言語名指定なしだとうまくプレビューされないので、シンタックスハイライトが不要の場合は適当にtxtとかを指定しておきましょう。

余談

なお、上で少し書いた通り、コードブロックのマークアップにはバッククォート`の代わりにチルダ~を用いることもできます。

そのおかげで、上の画像の4つめのコードブロックの例のように、ファイル名(パス)に~を含めると、エディタ中のシンタックスハイライト(syntax highlighting)が乱れます。

該当行のトークンを表示していますが、期待通りになっていないのがわかります。

ちなみに、スコープインスペクタを表示するには、cmd + Pctrl + P on windows)で表示される検索窓にDeveloper: Inspect Editor Tokens and Scopesと入力すれば見つけられます。 標準ではキーバインドは用意されていません。 参考

実際、vscode標準搭載(built-in)のmarkdownのsyntax設定のソースを見てみると、コードブロック開始は以下のような正規表現でキャプチャされています:

"fenced_code_block_css": {
  "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(css|css.erb)((\\s+|:|,|\\{|\\?)[^`~]*)?$)",

ファイル名にマッチングする箇所は[^`~]*となっているので、`~は含められないことがわかります。

このソースは以下のリポジトリで見ることができます:

github.com

もう少し余談

はじめに紹介した拡張機能リポジトリは以下です:

github.com

vscode自体がJavaScriptで作られているので、vscodeで使われているmarkdownパーサももちろんJS製です。 つまり、markdown-itですね。

github.com

はじめに紹介した「Markdown Named CodeBlocks」はvscode拡張機能ですが、やっていることとしてはmarkdown-it用に作られた拡張機能vscodeでも使うように指定しているだけです。

vscode拡張機能Markdown Named CodeBlocks」のリポジトリ

github.com

上で使われている、markdown-it用の拡張機能

github.com

この箇所にマッチングパターンが書いてありますね。

以下、抜粋して少し修正したものです:

const match = arr[0].match(/^([^:\n]+)?(:([^:\n]*))?([^:\n]*)?$/);
data.langName = match[1] || "";
data.fileName = match[3] || "";

最後の余談

以下のドキュメントによれば、vscodemarkdown拡張機能を作るには、markdown-itの拡張機能を持ってくるだけでいいそうですね。

code.visualstudio.com

まあ、自分で何か作るとなったら、この記事で何度も紹介している「Markdown Named CodeBlocks」のソースを参考にするといいかもですね。

以上です。

【Chrome】リーダーモードを使う

Safariのように、Chromeでもリーダーモードを使えるようにします。

むしろChrome以外のブラウザ(SafariFirefox、Edge)では標準で使えます。

Chromeがだけそうでないのは、Googleが広告企業だからでしょうか?

環境

% date
2022年 8月26日 金曜日 22時52分12秒 JST

Chromeのバージョン:

104.0.5112.101(Official Build) (x86_64)

方法

アドレスバー(URLが表示されている場所)にchrome://flagsと入力し、エンターを押下します。

すると隠し設定?のページが表示されるので、Enable Reader Modeと検索します。

「Enable Reader Mode」の項目が表示されますので、右のボタンみたいなプルダウンから「Enabled」を選択します。

設定を変更すると、ウインドウ下部に「Relaunch」ボタンが表示されるので、クリックしてChromeを再起動します。

その後、何かしらの記事サイト(例えばこのブログ)をChromeで開くと、アドレスバーの右側にリーダーモードのアイコンが表示されるので、クリックすればリーダーモードで表示してくれます。

以上。

あとがき

chromeのリーダーモードだと、はてなブログですらまともに表示されないね(埋め込みリンクとか)。

safariの方がきれいにちゃんと表示される。

ウインドウズだとSafariが使えないので毎日が苦しい。

firefoxに乗り換えようかな

参考

news.yahoo.co.jp

support.mozilla.org

【SVN】無視リストとバージョン管理外

TortoiseSVNクライアントで「無視リスト」と「バージョン管理外」のフィルターがあるので、何が違うのかと思った。

無視リストは、svnの設定ファイルやフォルダのプロパティで無視するように指定されたファイルやフォルダのこと。

バージョン管理外は、まだ一度もコミットされていない、つまり新規作成したファイルやフォルダのこと。

無視リスト

ローカル設定(常に無視するパターンのリスト)

svnの設定は、%APPDATA%\Subversion\にあるconfigという名前のファイルに記載されている。

%APPDATA%C:\Users\%username%\AppData\Roamingの意味なので、そのままエクスプローラのパス窓に貼り付けてOK。

配置場所からもわかるように、この設定はローカルにしか適用されない。

また、逆に言えばローカル環境全体に適用されるので、チェックアウトしているプロジェクトごとに設定を変更したりすることはできない。

無視リストに追加したいファイルやフォルダは、configファイルの[miscellany]の下にあるglobal-ignoresに指定する:

[miscellany]
global-ignores = .DS_Store *.dll *.exe bin .git .vscode

名前の指定には、以下のワイルドカードが使える:

  • *:0文字以上の任意の文字列にマッチ
  • ?:任意の1文字にマッチ
  • [...]:鍵括弧で囲まれた文字のうちの1文字にマッチ。ハイフン-で範囲も表現できる([AGm-p]A, G, m, n, o, pにマッチ)。

複数項目は半角スペース or 改行で区切る。

なので、1行で書かなくてもいい:

global-ignores = .DS_Store
    *.dll *.exe
    bin .git .vscode

残念ながら、パスは含めることはできない:

global-ignores = log/*.txt src/bin  # NG

あと、#から行末まではコメントとして扱われる。

フォルダのプロパティ

svn管理下のフォルダのプロパティには「Subversion」タブが追加されているので、そこでsvn:ignoreプロパティに無視したいファイルを指定する。

例えばsrcフォルダのsvn:ignore*.exeが指定されていると、srcフォルダ以下のexeファイルだけが無視される。 このとき、他のディレクトリ、例えばbuildToolフォルダ以下のexeファイルは無視されない。

ただし、この設定はフォルダのプロパティを書き換えるので、その修正をコミットする必要があるため、 ローカル(自分)だけじゃなくプロジェクトをチェックアウトした人全員に影響が及ぶ。

プロパティの更新だけをコミットすることもできるらしい:

yanor.net

バージョン管理外

バージョン管理外のファイルやフォルダは、まだ一度もコミットされていないものというだけ。

つまり、新規作成したファイルは管理下に置かれていないので、コミットする際はバージョン管理外を非表示にするフィルターを外してチェックするのを忘れずに。

なお、すでにバージョン管理下に置かれているファイルは、後から追加した無視リストにマッチしても、途中からバージョン管理外になったりしないので注意。

後から管理対象から外したい場合は、下記記事を参照(TortoiseSVN):

tortoisesvn.net

後書き

Gitって便利ですよね(こなみ)

お仕事ではウインドウズだしSVNだしで毎日がつらたにえんです。

無視リストにパス指定できないのはgmすぎる...

TortoiseSVNもクソ使いにくいし(GitHub Desktopと比べて)

でもSVNはバイナリファイル(画像やエクセルとか)の管理に自信があるようなので、それはGitよりいいところですかね(そもそも論は置いといて)。

まあ、ローカルではGitも併用してるんですけどね。機能単位じゃなくて作業単位でコミットしたいよね。

参考

tortoisesvn.net

tortoisesvn.net

oki2a24.com

zenn.dev

node.jsでMySQLを使うときは、hostにはlocalhostじゃなくて127.0.0.1を指定する【MySQL 8】

環境

% sw_vers
ProductName:    macOS
ProductVersion: 12.4
BuildVersion:   21F79

% node -v
v18.4.0

% mysql --version
mysql  Ver 8.0.30 for macos12.4 on x86_64 (Homebrew)

% brew -v
Homebrew 3.5.9
Homebrew/homebrew-core (git revision 27007d7668a; last commit 2022-08-20)
Homebrew/homebrew-cask (git revision d2da3c1a45; last commit 2022-08-20)

概要

MySQLの設定ファイルmy.cnfに以下の記載

bind-address = 127.0.0.1

がある場合に、node(のmysql2パッケージ)でhostlocalhostを指定して接続しようとすると失敗します。

なので、localhostではなく、直接127.0.0.1を指定します。

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: '127.0.0.1', // localhostだとダメ
  user: 'root',
  database: 'hoge'
});

調べたこと

特にHomebrewでMySQLをインストールした人がこの問題に直面しているかと思います。

HomebrewでMySQLをインストールすると、自動で設定ファイルmy.cnfが作成されます:

% cat /usr/local/etc/my.cnf
# Default Homebrew MySQL server config
[mysqld]
# Only allow connections from localhost
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1

コメント文からもわかるように、bind-addressIPアドレスを指定すると、そのアドレス以外からのアクセスを禁止します。

基本的に、127.0.0.1にはlocalhostというホスト名が設定されています:

% cat /etc/hosts    
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost

なので、上記のようにbind-addressの設定がされていても、localhostからでもアクセスできるはずです。

実際、ターミナルからであれば、localhostでログインできます:

% mysql.server start
Starting MySQL
.. SUCCESS! 

% mysql -u root -h localhost
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.30 Homebrew

略

mysql> 

ところが、nodeの方では、ホスト名にlocalhostを指定してMySQLに接続しようとすると失敗します。

下記内容のファイルをtest.jsという名前で保存:

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: ''
});

connection.query(
  'SELECT 1 + 1',
  function(err, results) {
    console.log(results);
  }
);

connection.end();

実行してみると、エラーが出る:

% node test.js
undefined
node:events:515
      throw er; // Unhandled 'error' event
      ^

Error: connect ECONNREFUSED ::1:3306
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1237:16)
Emitted 'error' event on Connection instance at:
    at Connection._notifyError (/Users/hoge/test/node_modules/mysql2/lib/connection.js:236:12)
    at Connection._handleFatalError (/Users/hoge/test/node_modules/mysql2/lib/connection.js:167:10)
    at Connection._handleNetworkError (/Users/hoge/test/node_modules/mysql2/lib/connection.js:180:10)
    at Socket.emit (node:events:537:28)
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -61,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '::1',
  port: 3306,
  fatal: true
}

Node.js v18.4.0

上記コードのlocalhost部分を127.0.0.1に置き換えます:

  // host: 'localhost',
  host: '127.0.0.1',

再度実行してみると、ちゃんとクエリが実行されました:

% node test.js
[ { '1 + 1': 2 } ]

これは奇妙ですね。mysql2パッケージがブラックボックスなのでこれ以上何とも言えません。

node + MySQLの解説記事を見ていると、ほとんどの記事でhost: 'localhost'と書いています。

おそらく、それでクエリ実行できているのは、my.cnfbind-addressの記載がないからでしょう。

あるいはバージョンの違いでしょうか。そこまでは調べられていません。

とにかく、HomebrewでMySQLをインストールするとmy.cnfbind-addressの設定が自動で作成されてしまいますので、その設定をコメントアウトするか、hostに直接127.0.0.1を指定するかのいずれかの対応が必要になります。

以上。

補足

"mysql2"パッケージ

nodeでMySQL接続するためのパッケージですが、mysqlではなくmysql2を使っているのは、前者がMySQL 8系に非対応だからです。

私はそもそも初心者で何も知らないのですが、mysql2mysqlと同じように使えるらしいです(メソッド名とかが同じ?)。

my.cnfの場所

my.cnfが配置されうる場所は以下のようにして調べられるらしいです:

% mysql --help | grep "/my.cnf"
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf 

HomebrewでMySQLをインストールしたときに作成されるのは/usr/local/etc/my.cnfのみです。

他の3つもcatしてみましたが、いずれもファイルが存在していませんでした。

なお、既に/usr/local/etc/my.cnfが存在している状態で、brew install mysqlしたときは、/usr/local/etc/my.cnfに変更は加わりません。

なので昔にMySQLの環境を作っていた人は、Homebrewからインストールし直しても上記問題には気がつかなかったかも知れません。

ちなみに、brew uninstall mysqlしてもこの設定ファイルは消去されないので、いらなくなったら手動で削除して下さい:

rm /usr/local/etc/my.cnf

参考

MySQL 8系ではmysqlではなくmysql2を使わないとダメだと気付かせてくれたサイト

teratail.com

mysql2パッケージ

www.npmjs.com

同様のエラーに対し試行錯誤している記事。これ読んで下さい

full-push.com

インストールしたMySQLを完全に消したい記事。いつか必要になるかも

qiita.com

フロントエンドで完結するテンプレートエンジンを作った?【JavaScript】

テンプレート言語は便利だけど、いちいちサーバーでレンダリングしないと使えないのがアレ。

もちろん、サーバー側で動的にHTMLを作るからこそ意味があるのだが、APIでデータ(今日の天気とか?)を取ってきて表示をif文で分岐させる、みたいな使い方ならフロント側だけで十分だなと思った。

というわけで、フロントエンドで完結するテンプレートエンジンを作った。

と言っても、変数定義と変数展開の機能しか実装していないので、ただのおもちゃです。 if文も無いよ。

フロントではJavaScriptしか動かないので、それで作りました。

ソースコード

github.com

使い方

nyaa.jsを読み込む:

<script src="./nyaa.js"></script>

読み込んだHTML内で、変数の定義と展開ができる:

<!-- 変数定義 -->
{% assign nyaa = にゃあ! %}

<!-- 変数展開 -->
{{ nyaa }}

その他の機能は皆無です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="./nyaa.js"></script>
  <title>テストにゃ</title>
</head>
<body>
  {% assign hello = 'こんちわ!' %}
  {% assign good_night = "おやすみ" %}
  {% assign url = https://google.com %}
  {% assign nyaa = にゃあ %}
  <h1>テスト</h1>
  <p>ほげ</p>
  <p>にゃあ</p>
  <p>{{ hello }}</p>
  <p>{{ hello }}で始まり{{ good_night }}で終わる。</p>
  <p>{{ good }}</p>
  <p><a href="{{ url }}">Google</a>です。</p>
</body>
</html>

参考

developer.mozilla.org

developer.mozilla.org

koseki.hatenablog.com

qiita.com

フロントエンドで完結するテンプレートエンジンを作った?【JavaScript】

テンプレート言語は便利だけど、いちいちサーバーでレンダリングしないと使えないのがアレ。

もちろん、サーバー側で動的にHTMLを作るからこそ意味があるのだが、APIでデータ(今日の天気とか?)を取ってきて表示をif文で分岐させる、みたいな使い方ならフロント側だけで十分だなと思った。

というわけで、フロントエンドで完結するテンプレートエンジンを作った。

と言っても、変数定義と変数展開の機能しか実装していないので、ただのおもちゃです。 if文も無いよ。

フロントではJavaScriptしか動かないので、それで作りました。

ソースコード

github.com

使い方

nyaa.jsを読み込む:

<script src="./nyaa.js"></script>

読み込んだHTML内で、変数の定義と展開ができる:

<!-- 変数定義 -->
{% assign nyaa = にゃあ! %}

<!-- 変数展開 -->
{{ nyaa }}

その他の機能は皆無です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="./nyaa.js"></script>
  <title>テストにゃ</title>
</head>
<body>
  {% assign hello = 'こんちわ!' %}
  {% assign good_night = "おやすみ" %}
  {% assign url = https://google.com %}
  {% assign nyaa = にゃあ %}
  <h1>テスト</h1>
  <p>ほげ</p>
  <p>にゃあ</p>
  <p>{{ hello }}</p>
  <p>{{ hello }}で始まり{{ good_night }}で終わる。</p>
  <p>{{ good }}</p>
  <p><a href="{{ url }}">Google</a>です。</p>
</body>
</html>