続・Scrapboxの日記にWebページをブックマークするためのブックマークレット

以下のアップデート版。

note103.hateblo.jp

コードはこんな感じで。

javascript:(function(){var input = window.prompt('Bookmark to Scrapbox','[' + document.title + ' ' + window.location.href + ']');
if (input==null) return;

var dt = new Date();
var dty = dt.getFullYear();
var dtm = dt.getMonth()+1;
var dtd = dt.getDate();
if (dtm < 10) { dtm = '0'+dtm };
if (dtd < 10) { dtd = '0'+dtd };
var today = dty+'-'+dtm+'-'+dtd;

var dh = dt.getHours();
var dm = dt.getMinutes();
var ds = dt.getSeconds();
if (dh < 10) {dh = '0' + dh};
if (dm < 10) {dm = '0' + dm};
if (ds < 10) {ds = '0' + ds};
var time = dh + ':' + dm + ':' + ds;

var data=window.prompt('Date',today);
if (data==null) return;
str = data;
elems = str.split('-');
dateYear = (elems[0]);
dateMonth = ((elems[1])-1);
dateDate = (elems[2]);
dt = new Date(dateYear, dateMonth, dateDate);
dy = dt.getFullYear();
dtm = dt.getMonth()+1;
dtd = dt.getDate();
if (dtm < 10) { dtm = '0'+dtm };
if (dtd < 10) { dtd = '0'+dtd };
var date = dy+'-'+dtm+'-'+dtd;

if (date == today) {time = ' ' + time} else {time = ' [' + today + '] ' + time};

var link = '[' + document.title + ' ' + window.location.href + ']';
var lines = [];
if (input == link) { lines.push(link + time) } else { lines.push(input + time + "\n" + '  ' + link) };
var quote = window.getSelection().toString();
if (quote.trim()) lines = lines.concat(quote.split(/\n/g).map(function(line){ if (line !== '') { return '  > ' + line } }));

var lines_and_quotes = [];
for (var i = 0; i < lines.length; ++i) { if (lines[i] !== undefined) { lines_and_quotes.push(lines[i])}};
var body = encodeURIComponent(lines_and_quotes.join('\n'));

window.open('https://scrapbox.io/***/' + date + '?body= ' + body)})()

最後の「***」にページのIDを入れる感じ。GIF動画は今回はパス。

もう1年ぐらいはずっとこれを使っていたんだけど、ブログで紹介していたのはその前のバージョンだったので、ひとまず現在のものをシェア、ということで。

前バージョンとの違いとしては、前の方だと当日のページに追記することしかできなかったけど、これだと日付を変えられる。その分、日付を確定するためのプロンプトが1つ増えてしまうんだけど、そんなに気にはならない。というかそれで慣れてしまった。

その他の機能については、冒頭リンクから前回の記事をご参照。

毎日使っているので、便利と言える。ブックマークがそのまま日記になるという感じ。プログラミング最高。

最近よく使っている自作ブックマークレット

ブックマークレットをよく作っては使っている。こんなのあったら便利では、と思ったらとりあえず作ってみて、使いながらだんだん出てくるさらなる希望に応じて機能を追加したり変更したり、それを延々とやっている。いつまででもできる。

このブログでは以前から時々そういうブックマークレットを紹介しているが、久しぶりに最近よく使っているものを紹介しておく。

選択した英語を日本語に翻訳

使用例はこんな感じ。

f:id:note103:20210411122513g:plain

コードは以下。

javascript:(function(){var quote = window.getSelection().toString();window.open('https://translate.google.co.jp/?hl=ja&sl=en&tl=ja&text=' + quote + '&op=translate')})()

Google翻訳を使ってるんだけど、翻訳元の文章に応じたURLにアクセスしているのだとふと気づいて、それを使ってみた感じ。

選択した韓国語を日本語に翻訳

使用例。

f:id:note103:20210411025355g:plain

コードは以下。

javascript:(function(){var quote = window.getSelection().toString();window.open('https://papago.naver.com/?sk=ko&tk=ja&hn=0&st=' + quote)})()

原理は同じだけど、Google翻訳の韓日版は今イチに思われることがあり、それでPapagoを使っている。仕組みが同様で助かった。

選択した部分をググる

使用例。

f:id:note103:20210411025506g:plain

コードは以下。

javascript:(function(){var quote = window.getSelection().toString();window.open('https://www.google.com/search?q=' + quote)})()

これも原理は同様。ここでは英単語をググっているけど、直訳ではなく用例を知りたいときとか、あるいは人名とか、もちろん日本語を含めてちょっと知りたいフレーズが出てきたら即ググるボタン、みたいな感じ。

いずれもコード自体は何のひねりもないシンプルなものだけど、ワンクリックで翻訳・検索されてくれるので毎日のように使っている。(とくに英語のやつ)

エンジニアでもなければ30代後半までプログラミングにかすりすらしてこなかった自分が何か思いつくたびにこのようなことをできるようになったのは、ひとえにPerl入学式で丁寧にプログラミングを教えてくれた皆さんのおかげなので、本当に感謝しています。

www.perl-entrance.org

ターミナルからScrapboxにメモを投稿するbashの関数

タイトルのとおりですが。

gist.github.com

`***` と書いてある部分にプロジェクト名を入れます。

使い方は、こんな感じ。↓

gyazo.com

パッと思いついたことをサッとどこかにメモしておきたい、というときに使っています。

ちなみに、if文の中の変数($msg)をダブルクオートで囲ってないと、上記サンプルのような2語以上に分かれるメッセージ(スペース区切りの内容)を入れられない。それで結構ハマった・・。

カレントディレクトリのファイルの中身をざらっとcatする

プログラミングの練習問題的に少し考えてみた。

catを使うのでシェルスクリプトでサラッと書ければよいのだろうけど、大変そうなのでいつものようにPerlのお力を借り・・

*実行の様子は最後に入れます。

Perlのコードのはこのような感じで。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

my $arg = $ARGV[0] // '';
my @files;

if ($arg =~ /-[al]/) {
    @files = glob "* .*"; # 不可視ファイルも対象
    if ($arg eq '-l') {
        for (@files) {
            say $_ if -f; # ファイル一覧だけ表示
        }
        exit;
    }
}
else {
    @files = glob "*"; # 不可視ファイル外す
}

my %cats;
for (@files) {
    $cats{$_} = `cat $_` if -f;
}

say for (sort keys %cats);
say "===\n";

for (sort keys %cats) {
    say $_;
    say '---';
    say $cats{$_};
}

しかしこれだけだと、ターミナルに出力するだけで、行数が多いときに不便なのでlessで出すようにしたい。ということでPerlだけでは済まず、.bashrcに以下みたいなのを書く。

# .bashrcに入れる。パスは環境に応じて。
# 当該ファイルは cats.pl とする。

function cats {
    local arg="$1"
    perl path/to/cats.pl $arg | less
}

で、結果はこんな感じ。

gyazo.com

コマンド名catsを入れると、カレントディレクトリ内のファイルを全部対象にしてcatしていく。

最初にファイル名が列記されて、それに各ファイ名+中身が続いていく感じ。

オプションで -a を入れると不可視ファイルも対象にする。

lessを使わなければ、bashrcでは関数にしなくてもエイリアスだけで行けるんだけど、自分的にはlessは必須なので・・という感じ。

この機能は以前からたびたび欲しいと思っていたので、今後少しでも快適になればよいのだけど。

*別環境でも使えるようにGitHubにも上げておきました。
GitHub - note103/cats

EpisoPassを使ってみた

GyazoやScrapboxでお馴染みの増井俊之さんによるEpisoPassの存在は以前から知っていたけど、

episopass.com

基本的な仕組み自体はわかるものの、どうしてこれが安全なのか、数点の疑問がどうしても解けなかった。

ご本人に聞いてしまえば早かったのだと思うけど、そこまで急いでいるわけでもなく、たぶん数年そのままだったのだけど、ようやく理解できた気がするのでメモをかねて書いておく。

EpisoPass全体については、以下のScrapboxをご参照。

scrapbox.io

簡単に言うと、質問&正答のいわば「なぞなぞ」を作っておいて、それに正解したらパスワードフレーズが出てくる、みたいな感じ。

特徴的なのは、そのパスワードと正答はどこにも保管されておらず、とくに「正答」は自分の頭の中にしかナイので(というかそういうなぞなぞを事前に作っておくので)、仮に運営者のサーバ等からすべてのデータが抜き取られても、パスワードが漏洩することはないということ。

もう少し具体的な仕組みとしては、一意のパスワードを作るには以下の要素が必要になる。

  1. ID(URLのこと)
  2. Seed(パスワードの長さ等を指定するキーワード)
  3. なぞなぞの質問
  4. なぞなぞの正答

2番めのSeedというのが少しわかりづらいが、これがたぶんこのシステムのキモで、おそらく質問・回答の選択肢・正答・URLの組み合わせだけでもそれなりに複雑な(他人には破られづらい)仕組みにはなるだろうが、そこにSeedが絡むことでより複雑性が高まるのだと思われる。

その上で、EpisoPassには「編集ページ」と「利用ページ」があり、前者ではなぞなぞやSeedなど各種の設定を行い、後者ではそれによって出来上がったなぞなぞを解く。

で、それらのページはどちらも全世界に公開されている。

たとえば、増井さんが使用例として公開している、ご自身のTwitterのEpisoPass利用ページを見てみると、こんな感じ。

https://episopass.com/Twitter_masui@pitecan.com.html

で、その編集ページを見るとこんな感じ。(最後の「.html」をトルだけ)

https://episopass.com/Twitter_masui@pitecan.com

あれ、Seedもパスワードも見れてしまってる・・というのが、じつはつい最近までまったく意味がわからなかったところ。
パスワード、見えちゃってるんじゃないの?という。

しかし実際には、第一にこの画面内のSeedは利用者が使っているものとは限らず、試しに他のSeedを入れてみると、それに応じてパスワードも変わる。
また、アクセスした時点ではすべての回答候補の最初(左端)の選択肢が選択されているので、どれが正答かは本人以外にはわからない。
つまり、これらの変数が存在することにより、この編集ページを見られても実質的な問題はない。

*増井さんはご自身の使用例では「Seedを公開している*1」と言っているけど、本当に上記アクセス先のSeedを使っているかはもちろん誰にもわからない。

ぼくは上記後者の、「編集ページにアクセスした時点ではすべて回答候補の左端が選択されている」という前提をわかっていなかったので、編集ページが知られたら自動的にパスワードもバレるのでは・・と思っていた。

もしそうなら、編集ページはなぞなぞページのURLから推測(というか)できるのだから、そもそもなぞなぞの意味ないのでは・・と思っていたのだけど、そうではないことがわかったので、その記念にこうしてブログにメモをしている。

その他、この仕組みに関するよくある質問は以下。想定可能な疑問点はだいたい網羅されているのでは。

scrapbox.io

ちなみに、今回久しぶりにEpisoPassについて調べてみようと思ったのは、増井さんの以下の直近ブログ記事を読んだから。

scrapbox.io

先日仕事でChromebookに触る機会があり、たしかにあのログインは大変!と思っていたので、用途として非常に興味を持ったという。
(まあ実際には、まだ仕事でこれを使うことはできないが・・)

ひとまずは、自分が趣味で使っている&他への影響が考えづらいサービスで小さく試し始めているところ。

なお、Chrome拡張機能を入れてみたけど、これはなぜか上手く動いてくれない。

scrapbox.io

もしかしたら、すでに別のパスワード管理サービスのアドオンを入れているせいかも。

ちなみに、増井さんはご自身でも解説されているように、

解説スライド - EpisoPass

以前にパスワードの使い回しでちょっとした話題になったことがあり、しかしこれは逆に言うと、どんなかたちであれパスワード自体を登録・保存せざるを得ない既存のパスワード管理サービスの欠点を明らかにしたものでもあったと思う。

EpisoPassにはそれはそれで、「なぞなぞを作るのが面倒」等の問題はありそうなものの(人によりそうだが)上記の根本的な問題は含んでいないから、その点からも期待できるところがあるなあ、と思っている。アルゴリズムなど、システムの仕組み部分もシンプルかつ公開されているようだし。(FAQをざっと見た感想)

*1:FAQにて。その上で、通常は公開する必要はないし、安全を期するためにはSeedも非公開にした方が良いだろうと言っている。

ランダムな文字列をパッと出すPerlスクリプトを書いた

ランダムな文字列を何文字分かサクッと出したい、ということが時々あります。
このようなときに使える小さいツールを作りました。

github.com

https://i.gyazo.com/bfd3df7a31cb38788c00ffb1cd63377b.gif

使い方

たとえば以下のようにターミナルに打ち込むと、

perl randstr.pl 5

5文字のランダムな文字列が出てきます。

+/2ox

文字数を指定しなければ、100文字出力されます。

この際には数字・アルファベット(大小)・記号がミックスされたものが出てきますが、オプションを指定することによって、数字だけ・大文字ないし小文字だけ・数字とアルファベットだけ、などの組み合わせも可能です。

perl randstr.pl -d 5 #=> 91486
perl randstr.pl -w 5 #=> vkDrV
perl randstr.pl -m 5 #=> 4Md8g
perl randstr.pl -l 5 #=> jajnu
perl randstr.pl -u 5 #=> OKKQX

詳しくは以下。

-d --digit           Set digit
-w --word            Set words
-m --mix             Set digit & words
-l --lower           Set lower case
-u --upper           Set upper case
-h --help            Show help

便利な使い方

どういう時にこれが必要になる、という具体的な事例は自分でもよくわからないんですが、案外必要になるケースが多く、その時にいちいちスクリプト名を打ち込むのも面倒なので、.bashrcに以下のようなエイリアスと関数を設定してシュッと出てくるようにしています。

alias pw="perl path/to/randstr.pl"
function pww {
    randstr=$(pw "$@")
    echo $randstr | tr -d "\n" | pbcopy
    echo $randstr
}

ただ表示したいだけなら pw で済みますが、実際の用途としてはそれをクリップボードにコピーするところまでセットなので、 pww の方がよく使います。(要Mac)

Getopt::Long

少し前にGetopt::Longを初めて使って、オプションの取り回しがだいぶラクになったな、と思っていましたが、しばらく使わないうちに忘れかけていたので、今回はそのリハビリもかねてそれ周りをGetopt::Longで書き直しました。

ただ、このツールでは引数の値は受け取らないので、あまり効果は大きくないですが・・。

後の自分の参考用に、Getopt::Longの復習にともない参考にしたブログ記事を掲示しておきます。

お蔵出し

このツールはじつは少し前に寄稿した、WEB+DB PRESSの記事で紹介する候補のひとつでした。

note103.hateblo.jp

その記事では自作の小ネタツールを紙芝居コントのように次々紹介していたので、内容的にも規模的にもちょうどいい感じでしたが、紙数が足りなかったのと、最終的な構成からは少し浮く感じもあったので、お蔵になっていました。

展望

これのRuby版も作ってみたいところです。Rubyの練習。

あとはブラウザで動くのも作ってみたいです。JavaScriptの練習・・かな。

WebサービスのヘルプをGitとかで編集する

こちらは『書き手と編み手の Advent Calendar 2019』の2日目の記事です。

adventar.org

昨日はid:mohriさんの以下でした。

mohritaroh.hateblo.jp

さて、続く私はWebサービスのヘルプを編集することについて書きます。

といっても、あんまり汎用的・抽象的な話ではなく(そうしたかったんですが、ならず)、やや特殊な事例かもしれません。あらかじめご承知おきのほど・・。

ぼくは昨年の11月にそれまでのフリーランス編集者(兼たまにライター)からIT企業の会社員に転職しまして、現在はその会社が開発・運営しているWebサービスのカスタマーサポート、兼編集者みたいなことをしています。

*転職時のブログ記事はこちら。

note103.hatenablog.com

ここで言うWebサービスとは以下で、

the-board.jp

こちらは見積書や請求書などの取引で使う書類をクラウドで作成・管理したり、そこで登録した金額を使って売上分析・経営管理できるよ、みたいなものですが、これのチャットサポートをしながら、そのサービスに関わるヘルプ記事の校正・テキスト表現の監修みたいなことをしています。*1

このヘルプ、現在400本ぐらいありますが、

boardヘルプセンター - board

そのすべてを同サービスのメイン開発者であり弊社代表でもある田向さん(id:fw_tx76129)が書いていまして、何しろこのサービスは元々田向さんが自分が欲しくて作った(理想に合致するものがあれば使ったけど、なかったので作った)もので、コードも最初のプロトタイプから今に至るまでずっと中心になって書いているので、その仕様については誰よりも彼がよく知っていて、だからそういうこともできるわけですが、とはいえ同サービスがスタートしてからぼくが入社するまでの4年ちょっとの間、ヘルプの文章は他の誰も触っていない状態だったので、いわば「外部の目」によるチェックというのはほとんどされていない状態だったのですよね。

で、そこにぼくが入ってきたということで、じゃあ編集、やりましょうかやりましょうよ、ということで、まずは校正的な視点で表記を揃えたり、ちょっと内容が伝わりづらそうなところを適当に書き換えたり、ということからスタートしてできたのが以下のようなシステムでした。

tamukai.blog.velc.jp

tamukai.blog.velc.jp

詳しくは上記の田向さんによる記事をご覧頂きたいですが、簡単に解説すると特徴は2点で、

  • Git/GitHubを使ってヘルプ記事をバージョン管理する
  • textlintを使って表記揺れを自動的にチェックする

という感じです。

とくに大きいのは前者のバージョン管理で、以前はその1本目の記事にも解説されているとおり、HTMLエディタ形式の管理画面で編集してそのまま保存するような仕組みだったので、もし修正してもその差分(どこをどう修正したのか)はわからず、とくに複数人で編集する場合には困難が生じそうな状況でしたが、ここにGitをかませることで、第一に複数人による作業が非常にしやすくなり、また普段づかいのエディタ(Vim)でローカルのテキストファイルを気軽に編集できるようになり、感覚的には「コードを書くようにヘルプを書く(編集する)」みたいな感じになりました。

さらには、これによって上記2点目の特徴であるリントツールも経由できるようになり、事前に登録しておいた「辞書」と異なる表記をしていたらエラーが出るようになっています。

textlint.github.io

その作業の流れについて、もう少し具体的に書いてみると、こんな感じ。

  1. まず修正前のブランチを元に修正用のブランチをチェックアウト。
  2. その中でどんどん修正&コミット。
  3. 時間がかかりそうだったら一旦途中でプッシュして、Draft Pull Request(WIPみたいなやつ)を作成。
  4. 1本の記事につき頭から終わりまでを2〜3周ぐらい読み直しながらつど修正。
  5. 終わったら、DPRからPRに切り替え。田向さんにアサインを移す。

ちなみに、Git操作はSourceTreeを使っています。

www.sourcetreeapp.com

ぼくは以前は、Git操作なんて黒い画面でやってナンボでしょ、GUIなんて邪道!と思っていましたが、入社してみるとエンジニアで黒い画面を使っている人はいなくて(笑)むしろSourceTreeの割合が多かったので、あっさり改宗。

普段それを本業で使ってるエンジニアさんにGitやSourceTreeの使い方を教われるなんてありがたすぎるので大人しく教わった次第でしたが、なんやこれ、めっちゃ便利やん!という感じで今では手放せないものになっています。*2

上記を踏まえて、あらためてそれらツールに着目しながら手順を追うと、こんな感じ。

  1. SourceTreeでブランチ作成・チェックアウト。
  2. エディタでひたすら編集。コミット。
  3. 途中でプッシュ。GitHub上でDraft Pull Request。
  4. エディタで編集の続き。コミット。プッシュ。その繰り返し。
  5. GitHub上でPull Requestに切り替え。

実際は上記に加えて、Ruby製のMiddlemanを使ってプレビューを確認したり、

Middleman: 作業を効率化するフロントエンド開発ツール

Perl製の自作ツールを使って対象ファイルをシュッと開いたりしていますが*3、そこまで説明していると細かすぎて伝わらないアドベントカレンダーになってしまいそうなので*4、ここまでにしたいと思います。

本当はこの後、Webサービスのヘルプを編集するとはどういうことか、その時にはどんなことに気をつけて、何を考えているのか、みたいなことも書きたかったのですが、ここまでの話でちょうどキリが良い感じがするので、その辺はまた日にちが空いていたら書くかも、という感じにしておきます。

本日の記事は以上です。ひき続き、『書き手と編み手の Advent Calendar 2019』をお楽しみください!

adventar.org

*1:チャットサポートをどんなふうにしているのか、という話はたまたま先月初頭に行われたテキストエディタVimの国際カンファレンス VimConf 2019 にて簡単なLT(登壇)をしましたので、ご興味おありの方はぜひどうぞ。 docs.google.com www.youtube.com

*2:まあ、黒い画面と格闘した日々があったからこその感動なのだとは思いたいですが。

*3:これについてはコレの最後の方で紹介しています。 note103.hateblo.jp

*4:もう遅いかも。