小技チョコレート

ちょっとした小技を紹介するだけのブログです。

Dynalistからプレーンテキスト形式でエクスポートした内容をScrapbox記法に置換するPythonスクリプト

Dynalistからプレーンテキスト形式でエクスポートした内容を、Scrapbox記法に置換するPythonスクリプトを作ったので、コードと使い方を書いておきます。

スクリプトのコードは更新されることがあります(更新履歴)。
この記事は長くて細かいので、大要を知りたい場合は機能の節のみお読み下さい。

Python不要でブラウザのみで動作するUserScript版もあります。UserScript版のほうが、置換機能が充実しています。


〈目次〉


機能

概要

  • Dynalistからプレーンテキスト形式でエクスポートしたテキストを、PCの標準入力(コマンドプロンプト)にペーストすると、その内容をScrapbox記法に置換します。
  • 置換後のテキストの出力方法は下記の3種類のうちから選べます。
    • クリップボードに自動でコピーする。
    • コマンドプロンプト(端末, Terminal)に表示する。
    • 自動でブラウザを開き、Scrapboxに記入する。
      • Dynalistからエクスポートした内容の1行目がScrapboxのページタイトルとなり、2行目以降がページの本文となって記入されます。
  • Dynalistにおける階層が再現されます。
    • Dynalistからエクスポートした内容の1行目(最上位の行)が、Scrapboxにおいても最上位の階層(インデントなし)となり、2行目以降は、箇条書きの形で階層を再現します。

置換できるもの/できないもののリスト

Dynalistにおける全てのMarkdownや、Dynalistの独自記法を完全にScrapbox記法へ置換できるわけではなく、置換できないものも存在します。置換できるもの/できないものの詳しいリストは下記のとおりです。

置換できるもの
  • リンク
    • [リンクテキスト](URL)[リンクテキスト URL]
    • [](URL)[URL]
  • 画像
    • ![リンクテキスト](URL)[リンクテキスト URL]
    • ![](URL)[URL]
  • 強調を太字へ置換(**hoge**[* hoge]
  • イタリック(__hoge__[/ hoge]
  • 取り消し線(~~hoge~~[- hoge]
  • 日時記法
    • !(2019-09-08)2019-09-08
    • !(2019-09-08 10:00)2019-09-08 10:00
  • ハッシュタグ用の@#へ置換(@hoge#hoge
  • 数式($$E=mc^2$$[$ E=mc^2]
  • 余分なインデント(Dynalistでは階層が1段下がるごとにインデントが4個ずつ付くので、これをインデント1個ずつに置換)*1
置換できないもの
  • Dynalistにおいて見出し(H1, H2, H3)の状態にある項目(Ctrl+Shift+Hを押した行)は、Dynalistではフォントサイズが大きくなっていますが、そのサイズ変更は再現されません。
  • カラーラベル(Dynalistで特定の行にのみ使用している背景色)は再現されません。
  • Dynalistでチェック(Check off)した項目(hogeのように表示されているもの=Ctrl+Enterを押した行)そのものは消さずに引き継ぐことができますが、この項目のフォントカラーの変更(色が薄くなっていること)と、同項目に付けられている取り消し線は再現されません。
    • Dynalistのcheckbox(行頭に付けることができるチェック機能)にチェックを入れた項目も、これに該当します。
  • Dynalistのcheckbox(行頭に付けることができるチェック機能)は再現されません。
  • Dynalistの1項目(1行)の内部で改行してある場合(Ctrl+Shift+Enterを押してある場合)は、その項目における改行以降の部分には、階層の深さが引き継がれません。他の項目の階層は正しく再現されます。
  • Dynalistのnoteに記入したものは、Dynalistにおけるスタイル(小さいフォントで各項目の下側に付いている状態)がScrapboxに引き継がれず、独立の1項目(1行)に置き換えられます。

その他の、仕様上実現できない事柄などを「既知の問題点」の節にまとめています。細かいことなので、詳しく知りたい場合はお読み下さい。

「他のツールとの機能比較」も参考にしてください。

scrapbox.io

実行例

Dynalistにこのような内容があるとき、これをScrapbox記法に置換してScrapboxに記入する、という例を示します。

f:id:ichbin:20191117120621p:plain
(この例では1行の中にMarkdownやDynalistの独自記法が1つずつあるだけですが、複数個ある場合も正しく置換できます)

置換後のコンテンツは、Scrapboxでこのように表示されます。

f:id:ichbin:20191113170228p:plain
(数式記法のところで行頭のマーカー(・)が見えなくなっているのはScrapboxの仕様です)

必要なもの

  • Pythonスクリプトを実行できること。
    • 出力方法として「クリップボードに自動でコピーする」を選ぶ場合は、Pythonpyperclipというモジュールが必要です(Pythonをインストールしただけでは含まれていないかもしれません)。*2
  • 出力方法として「自動でブラウザを開き、Scrapboxに記入する」を選ぶ場合は、Scrapboxにログインした状態でウェブブラウザが使える必要があります。

設定の仕方

スクリプトの作成

テキストエディタこちらのdy2sc.pyのコードを貼り付け、ファイル名をdy2sc.pyのように拡張子を.pyとして保存します。

機能の選択

出力の仕方の選択

置換後のテキストを出力する方法を、下記の3つのうちから1つ選び、コードの13行目付近のoutput=○のところに数字で記入します。

ページタイトルの取扱い方の選択

Scrapboxのページタイトルの部分では、Scrapbox記法が機能しません。ですので、Scrapboxのページタイトルになる可能性が高い箇所(Dynalistからエクスポートした内容の1行目がそれに相当します)においては、そこにMarkdownによる修飾(強調/イタリック/取り消し線)や数式記法($$〜$$)が含まれていても、それをScrapbox記法に置換する必要はさほどなく、それら(修飾や数式)を単に取り除いたほうが、Scrapbox運用の観点からも好都合と思われます。

ですので、Dynalistからエクスポートした内容の1行目にそれらが含まれている場合には、Scrapbox記法への置換をせず、単に修飾を取り除く(数式の場合は両端の$$を取り除く)機能を設けています。

この機能はデフォルトではオンになっています。オフにすると、1行目に含まれる修飾と数式記法はScrapbox記法に置換されます。オフにしたい場合は、コードの18行目付近のfirstline=0のところをfirstline=1に書き換えます。

なお、1行目にリンクや、画像、日時記法、Dynalistでのハッシュタグ用の@が含まれている場合は、それらは上掲のとおりに置換されます。

ブラウザで新規ページを開くか選択

置換後のテキストを出力する方法として「クリップボードに自動でコピーする」または「コマンドプロンプトに表示する」を選んでいる場合は、そのテキストをScrapboxに貼り付けるために、Scrapboxの新規ページ(白紙のページ)をブラウザで自動で開かせると便利だと思いますので、それができるようにしています。

この機能はデフォルトでオンにしています。オフにしたい場合は、コードの22行目付近のbrowseropen=1のところをbrowseropen=0に書き換えます。

プロジェクトURLの指定

下記の2つのうち、少なくとも1つにあてはまる場合は、Scrapboxの「プロジェクトURL」の指定が必須です。どちらにもあてはまらない場合は、無視してかまいません。

  • 置換後のテキストの出力方法として「自動でブラウザを開き、Scrapboxに記入する」を選んでいる(output=2としている)。
  • Scrapboxの新規ページ(白紙のページ)をブラウザで自動で開かせる機能をオンにしている(browseropen=1としている)。

プロジェクトURLを指定する方法は次のとおりです。コードの26行目付近のYOUR_PROJECT_URLという文字列を、自分が書き込みたい対象のScrapboxプロジェクトの「プロジェクトURL」に書き換えます。
プロジェクトURLとは、各プロジェクトのトップページのURL(https://scrapbox.io/○○○/)の○○○の部分のことです。

使い方

1. Dynalistからエクスポートする

Dynalistからエクスポートしたい内容の、最上位の行の行頭にマウスポインタを合わせると、「≡」の形のアイコンが表示されるので、それをクリックしてメニューを開き、“Export...”をクリック。

f:id:ichbin:20190910181020p:plain

f:id:ichbin:20190910181109p:plain

このような画面が開きます。

f:id:ichbin:20190910181622p:plain

中央上部の“Plain text”をマウスで選択し、下の方にある“Indentation style”のところで“Spaces”を選択しておきます(通常は何もしなくても“Spaces”が選択されていると思います)。

そして“Copy to clipboard”のボタンを押すか、もしくは、中央の入力欄の内容を選択した状態でCtrl+cなどと操作して、この入力欄の内容をクリップボードにコピーします。

2. 標準入力にペーストする

PCのコマンドプロンプト(端末, Terminal)を起動し、上掲のdy2sc.pyを保存してあるディレクトリにてpython dy2sc.pyと入力してEnter。すると行末で改行されて、カーソルが次の行頭へ移ります。

f:id:ichbin:20190910184028p:plain
(カーソルが次の行頭へ移っている状態)

この状態で、上述のDynalistからエクスポートした内容をここにペーストします。Ctrl+Vという通常のショートカットキーではペーストができない場合があるので、それぞれのソフトの仕様に従ってペーストの操作をします。右クリックメニューからペーストできる場合もあります。

f:id:ichbin:20190910184101p:plain
(ペーストした状態)

ペーストし終わったら、末尾でEnterキーを1回以上押してからCtrl+dとキーを叩きます(Ctrl+dは入力の終わりを示します。ソフトによっては別のキーかもしれません)。

f:id:ichbin:20190910184120p:plain
(この例であれば11:00)の末尾でEnterキーを押してからCtrl+dを押すということです)

すると、置換後のテキストが出力されます。

3. 出力される

上掲の3種類の出力方法のうち、選択されている方法で出力されます。

(A) クリップボードに自動でコピーされる

置換後のテキストはクリップボードに自動でコピーされ、コマンドプロンプトには【置換してクリップボードへコピーしました】というメッセージが表示されます。

f:id:ichbin:20190910184206p:plain

Scrapboxの新規ページや既存のページに、クリップボードの中身を貼り付ければ完了です。

(B) コマンドプロンプトに表示される

置換後のテキストがコマンドプロンプトに表示されます。
===== 置換済みテキスト START =====
から
===== END =====
までの間に表示されています。

f:id:ichbin:20190910184229p:plain

これをコマンドプロンプトの画面上からクリップボードにコピーし、Scrapboxの新規ページや既存のページに貼り付ければ完了です。

(C) 自動でブラウザを開き、Scrapboxに記入する

上掲の手順でCtrl+dのキーを叩くと、ウェブブラウザが起動し、置換後のテキストが記入された状態のScrapboxページが開きます。*3

f:id:ichbin:20190910180824p:plain

Dynalistからエクスポートした内容の1行目がScrapboxのページタイトルとなり、2行目以降がページの本文となります。2行目以降は箇条書きとなります。

〈Dynalistに存在しているが画面上で見えていないもの〉をエクスポート対象から除外する方法

Dynalistにおいて「存在はしているけれども画面上で見えていないもの」を、エクスポート対象に含めないようにすることができます。具体的には次の2つです。

(1) エクスポート対象の中で、ある階層よりも下位にあって、折り畳まれているから見えなくなっているもの。

f:id:ichbin:20190910181738p:plain
(赤枠で囲ってある項目は「食材」の下位)

f:id:ichbin:20190910181924p:plain
(「食材」のところで折り畳むと、見えなくなっている)

(2) DynalistのView optionsでCHECKED ITEMSをHideに設定している場合の、チェック済みの項目(Ctrl+Enterを押されている行)。checkbox機能でチェックを入れたものも含む。

f:id:ichbin:20190910182110p:plain

左上のhogeはチェック済みのもの。その下のfugaはckeckbox機能でチェックを入れられているものです。

右上の目の形のアイコンをクリックするとView optionsが開きます。上段のCHECKED ITEMSのところで、赤線をひいてあるGlobal(hide)またはHideを選択してある場合は、これらのhogefugaはDynalistの画面上で見えません。

この(1)や(2)に当てはまっているものは、デフォルトでは、エクスポート対象に含まれます。これらをエクスポート対象に含めないようにするためには、エクスポートの画面で右上にある“Export visible items only”にチェックを入れます。

f:id:ichbin:20190910182231p:plain

既知の問題点

  • 出力方法として「自動でブラウザを開き、Scrapboxに記入する」を選んでいて、かつページタイトルにアンダーバー(_)が含まれている場合は、そのページタイトルになるべき部分を1行後ろ(=本文の最上部)へ移し、ページタイトルを空白とします。すなわち、ページの全体が1行分だけ下へ下げられた状態になります。
    • Scrapboxの仕様として、ページタイトルに含まれているアンダーバーは半角スペースに置き換えられてしまうので、その影響を回避するためです。
  • 次のような場合は、その箇所では正しい置換結果になりません。
    • Markdown入れ子になっている場合(**__hoge__**~~**hoge **~~など)
    • Dynalistの数式記法($$〜$$)で式に]を含む場合(例:$$[a + b]$$*4
    • 数式記法($$〜$$)で半角の$が3個以上連続している場合
      • 数式の左端や右端に$がある場合($aとかa+$のような数式)がこれに該当します。
      • 1行の中で数式記法が連続しているだけの場合は、問題ありません。
        • $$a+b$$$$x-y$$[$ a+b][$ x-y]と正しく置換される。
    • Dynalistからエクスポートした内容に、半角のバーティカルバーの3連続(|||)がある場合
      • この3文字は、Dynalistからエクスポートした各行同士を区切るためのものとしてスクリプトの中で使っているためです。*5
  • Dynalistで行頭に半角スペースがあると、Scrapboxにおいて階層が正しく再現されません。行頭の半角スペースがインデントとして解釈されてしまうためです。

f:id:ichbin:20190910182404p:plain
(1行目は行頭に半角スペースがある)

Scrapboxに自動で記入させる場合のセキュリティについて

出力方法として「自動でブラウザを開き、Scrapboxに記入する」を選んでいる場合は、その記入しようとするページタイトルと本文はhttps://scrapbox.io/(プロジェクトURL)/(タイトル)?body=(本文)という形でURLに含まれており、このURLをブラウザで開くと、Scrapboxに記入されます(Scrapboxのヘルプを参照)。

このとき、?body=以降(すなわちページの本文となる内容)はHTTPSで暗号化されるようですが、アクセス先のWebサーバー(Scrapboxのサーバーでしょう)のログには平文で残る可能性があるかもしれません。そのログが外部に漏洩する、というような事態がありうると想定するならば、このPythonスクリプトでページの本文に記入したい内容の中に「他人に見られると困る情報」を記入しないほうがよいのかもしれません。

いずれにしましても、この問題については筆者の専門知識が乏しいので、確定的なことは言えません。上述のようなリスクがあるかもしれないということをご了承のうえでスクリプトをお使い下さい。

おわりに

不具合のご報告やご要望、改良のアイデアなどがありましたら、本記事のコメント欄か筆者のTwitterメールGithubなどへお知らせ下さい。

免責事項

本記事で紹介したPythonスクリプトの使用やその不具合等により生じたいかなる損害に関しましても、筆者は一切の責任を負いません。予めご了承ください。


*1:インデントを4個のままにすると、Scrapboxにおいては箇条書きの階層が深くなりすぎます。

*2:インストールするには、コマンドプロンプトで pip install pyperclip と実行。Linuxの場合は sudo pip install pyperclip とする必要があるかもしれない。

*3:これはScrapboxの「ページを作る機能」を利用したものです。

*4:これはScrapboxの仕様によるものです。

*5:これを回避する方法はあるのだと思いますが、現状、どのようにすれば回避できるか分かりませんので、このままにしています。