「フィルターされたNotionページによるMediaWiki」の版間の差分
Notion-MW |
Notion-MW |
||
(同じ利用者による、間の6版が非表示) | |||
21行目: | 21行目: | ||
== データベース部分の設計 == | == データベース部分の設計 == | ||
<div class="res-img"> | <div class="res-img">https://turgenev.cloudfree.jp/mw1/imgs/notion-mw-db.jpg</div> | ||
このような感じで、「使うNotionページへのリンク」「スクリプトによる変換&更新の対象にするかどうか」(←これは今はもう使われていない)「MediaWikiでのID」「MediaWikiでのタイトル」「MediaWikiでのカテゴリー」「サイトの更新日時(=スクリプトによってMediaWiki側での編集が完了したタイミング)」をデータベースとして保持している。 | このような感じで、「使うNotionページへのリンク」「スクリプトによる変換&更新の対象にするかどうか」(←これは今はもう使われていない)「MediaWikiでのID」「MediaWikiでのタイトル」「MediaWikiでのカテゴリー」「サイトの更新日時(=スクリプトによってMediaWiki側での編集が完了したタイミング)」をデータベースとして保持している。 | ||
37行目: | 37行目: | ||
大まかな流れは以下の通り。 | 大まかな流れは以下の通り。 | ||
# 上記データベースの内容をNotion APIから取得する。以下、各行ごとに処理。 | |||
# ページの内容を取得し、黄色い見出しだけ残す変換を行う。Notionのブロックのリストができる | |||
# notion-to-mdのblocksToMarkdownでマークダウン形式に変換する。 | |||
# いくつか前処理を行う。 | |||
# pandocを用いてMediaWikiに変換する。 | |||
# いくつか後処理(整形)を行う | |||
# 完成した記事データをMediaWiki APIで投稿する。 | |||
その他、ページのリネーム、新規作成時のIDの反映(<code>-</code>を数字に変える)、既存の記事を新規作成しようとした場合のエラーなど、前後に多少の処理がある。 | その他、ページのリネーム、新規作成時のIDの反映(<code>-</code>を数字に変える)、既存の記事を新規作成しようとした場合のエラーなど、前後に多少の処理がある。 | ||
64行目: | 64行目: | ||
=== pandocの実行 === | === pandocの実行 === | ||
< | <syntaxhighlight lang="python">cp.spawn("pandoc", ["-f","gfm","-t", "mediawiki", "--shift-heading-level-by=1"]);</syntaxhighlight> | ||
<code>gfm</code>(Github Flavored Markdown)から<code>mediawiki</code>に変換する。<code>--shift-heading-level-by=1</code>は、[https://www.mediawiki.org/wiki/Help:Formatting/ja Help:書式整形 - MediaWiki]にもある通り、MediaWikiの記事内ではレベル1の見出しは非推奨だからである。 | <code>gfm</code>(Github Flavored Markdown)から<code>mediawiki</code>に変換する。<code>--shift-heading-level-by=1</code>は、[https://www.mediawiki.org/wiki/Help:Formatting/ja Help:書式整形 - MediaWiki]にもある通り、MediaWikiの記事内ではレベル1の見出しは非推奨だからである。 | ||
96行目: | 96行目: | ||
上記のような良い感じのMediaWikiに変換する目的と、単純にできたばかりでバグが多いため、色々変えている。 | 上記のような良い感じのMediaWikiに変換する目的と、単純にできたばかりでバグが多いため、色々変えている。 | ||
=== リポジトリ === | |||
[https://github.com/ge9/notion-to-md-mediawiki Githubリポジトリ]を作成したので、最新情報はそちらから。 | |||
=== 数式関連 === | === 数式関連 === | ||
117行目: | 121行目: | ||
コードにおいて、言語がpythonなどの良く知られたものに設定されていると、pandocによって<strong>syntaxhighlight</strong>タグに変えられてしまう。今回はSyntaxHightlight拡張機能が無効のMediaWikiを使っているので、言語にダミー文字列を付加する(付加ではなくダミー文字列だけにしても変わらないが、情報を落とすのは勿体ない気がしたので)。またpandoc側の問題で<code>visual basic</code>のように言語名にスペースが入っていると<code>visual</code>だけになってしまうようなので、スペースをアンダースコアに置換。 | コードにおいて、言語がpythonなどの良く知られたものに設定されていると、pandocによって<strong>syntaxhighlight</strong>タグに変えられてしまう。今回はSyntaxHightlight拡張機能が無効のMediaWikiを使っているので、言語にダミー文字列を付加する(付加ではなくダミー文字列だけにしても変わらないが、情報を落とすのは勿体ない気がしたので)。またpandoc側の問題で<code>visual basic</code>のように言語名にスペースが入っていると<code>visual</code>だけになってしまうようなので、スペースをアンダースコアに置換。 | ||
< | <syntaxhighlight lang="python">language = "dummy_str_"+language?.replace(" ", "_");//for MediaWiki without SyntaxHightlight extension</syntaxhighlight> | ||
<span id="notion-to-mdts内"></span> | <span id="notion-to-mdts内"></span> | ||
=== <code>notion-to-md.ts</code>内 === | === <code>notion-to-md.ts</code>内 === | ||
127行目: | 131行目: | ||
解説が面倒なのでコードだけとりあえず。 | 解説が面倒なのでコードだけとりあえず。 | ||
< | <syntaxhighlight lang="javascript">//`のみcodeに変え、```は```のままという仕様の場合 | ||
if (content.type === | if (content.type === "text"){ | ||
if (type == | if (type == "code"){ | ||
//```の内部では | //```の内部では<>は無効なので本来は不要だが、detailsまわりが修正されるまで、<>を最強エスケープの対象としておく。 | ||
//無事修正されたので、対象外に | //無事修正されたので、対象外に | ||
//plain_text = plain_text.replace(/[ | //plain_text = plain_text.replace(/[<>]/g, (c) =>"m_esc_" + c.charCodeAt(0)+"_m") | ||
//バッククォートはmarkdownの```の中でも有害になる珍しい文字であるが、外側と対処法が異なる。 | //バッククォートはmarkdownの```の中でも有害になる珍しい文字であるが、外側と対処法が異なる。 | ||
//markdownでコード内に`を書くには、両側をそれより多い`で囲うしかなく(\`や& | //markdownでコード内に`を書くには、両側をそれより多い`で囲うしかなく(\`や`ではそれがそのまま表示されてしまう)、その実装が面倒である。 | ||
//そこで、最強エスケープをかけて、MediaWikiに変換してから元に戻す。ちなみにMediaWikiでは`は特殊文字ではないのでエスケープ文字ではなくベタ書きに戻す。 | //そこで、最強エスケープをかけて、MediaWikiに変換してから元に戻す。ちなみにMediaWikiでは`は特殊文字ではないのでエスケープ文字ではなくベタ書きに戻す。 | ||
plain_text = plain_text.replace(/`/g, (c) = | plain_text = plain_text.replace(/`/g, (c) => "m_esc_" + c.charCodeAt(0)+"_m") | ||
}else{//テキストエリア | }else{//テキストエリア | ||
//以下は、MediaWikiの特殊文字であるにもかかわらずpandocがそのままべた書きしてしまう文字。最強エスケープが必要。 | //以下は、MediaWikiの特殊文字であるにもかかわらずpandocがそのままべた書きしてしまう文字。最強エスケープが必要。 | ||
//これらはMarkdownの```およびMediaWikiのpreの内側では無害である。(外側では特殊文字であるものとそうでないものがある。) | //これらはMarkdownの```およびMediaWikiのpreの内側では無害である。(外側では特殊文字であるものとそうでないものがある。) | ||
plain_text = plain_text.replace(/[=;:#*'{}~\-\[\]]/g, (c) = | plain_text = plain_text.replace(/[=;:#*'{}~\-\[\]]/g, (c) => "m_esc_" + c.charCodeAt(0)+"_m") | ||
//これらは、Markdownのテキストエリアでは特殊文字だが、MediaWikiの特殊文字ではないあるいはpandocがちゃんと扱えるもの。 | //これらは、Markdownのテキストエリアでは特殊文字だが、MediaWikiの特殊文字ではないあるいはpandocがちゃんと扱えるもの。 | ||
//(ただし、 | //(ただし、"."(ピリオド)のみ、「リンクテキストもURLになっているリンク及びcode内に書かれた(リンクでない)URLがpandocの変換でおかしくなるのを防ぐ」という目的で入れている。) | ||
//この変換は先ほどの最強エスケープより後でなければいけない。(#が最強エスケープされるのを防ぐため)(もちろん同時でもいい) | //この変換は先ほどの最強エスケープより後でなければいけない。(#が最強エスケープされるのを防ぐため)(もちろん同時でもいい) | ||
//スラッシュでのエスケープだと` | //スラッシュでのエスケープだと`<`でバグったことがあった(おそらくpandocのせい)ので、&#xx;を使用 | ||
plain_text = plain_text.replace(/[`$+& | plain_text = plain_text.replace(/[`$+&<>\\.]/g, (c) => "&#" + c.charCodeAt(0)+";") | ||
//2つ以上の連続する空白文字は(そのように表示したい特別な理由があると考えて)& | //2つ以上の連続する空白文字は(そのように表示したい特別な理由があると考えて) に変換。これは&のエスケープより後である必要がある。 | ||
plain_text = plain_text.replace(/ {2,}/g, (c) = | plain_text = plain_text.replace(/ {2,}/g, (c) => c.split('').map(function() { return ' '; }).join('')) | ||
//notion-to-mdがブロック内改行に対応していないので対応。nbspへの変換より後に行う。 | //notion-to-mdがブロック内改行に対応していないので対応。nbspへの変換より後に行う。 | ||
plain_text = plain_text.replace(/\n/g, | plain_text = plain_text.replace(/\n/g, " \n") | ||
} | } | ||
//また、 | //また、"も、mediawikiでの特殊文字ではないが、pandocでは"に変換される。 | ||
//ベタ書きでも表示には影響ないが、span id= | //ベタ書きでも表示には影響ないが、span id=""の中身に生のダブルクォーテーションが入ってしまう副作用があるし、その他問題が起きる可能性がある。 | ||
//下記のように最強エスケープすればそのまま書けるが、& | //下記のように最強エスケープすればそのまま書けるが、"を"にしてデータ量を削減するより安全を取ったほうが良さそうである。 | ||
//ちなみに1文字減らすために最強エスケープから& | //ちなみに1文字減らすために最強エスケープから"に戻す方法もあるが、"のほうが自動でspan id=""の中身から除去されるようなのでそのほうが良さそう。 | ||
//plain_text = plain_text.replace(/[ | //plain_text = plain_text.replace(/["]/g, (c) => "m_esc_" + c.charCodeAt(0)+"_m") | ||
}</ | }</syntaxhighlight> | ||
==== ブロック内改行 ==== | ==== ブロック内改行 ==== | ||