[技巧] 用 VSCode 把 OneNote 快速轉換到 Markdown + 包含程式碼
工作上的筆記總是寫在 OneNote,但如果想要貼部分資訊到 GitHub/GitLab 中,單純用複製貼上整個格式就會跑掉,還要手動一個一個調整滿麻煩的。有沒有什麼快速的方法來把 OneNote 轉換到 Marrkdown 格式呢?
範例 OneNote 文件
由於 OneNote 中我常常用 tables 來把 code 片段包起來,所以很常筆記會變成下面這樣:
Pandoc 工具
網路上常見的解法背後其實常常用了 Pandoc 這個工具,如果我們按照這個教學方法把上面的 OneNote 文件轉換成 Word 再轉成 Markdown 會變成這樣:
我們會發現 tables 與程式碼的 indents 整個都跑掉了,就不是我預期的。
而且還要先匯出成 Word,再開 PowerShell 輸入指令,如果頻繁的做這件事就會覺得很累,尤其是還在修改部分細節的時候。
VSCode + Replace Rules 插件
如果我們直接複製 OneNote 的文字,在 VSCode 貼上,會發現他會貼上這樣的格式:
除了文字前面的小圖示,我們會發現他的 indents 終於有保留下來。所以我一開始都是手動用 Ctrl+D 或 Ctrl+Shift+L 把 tabs + 小圖示選起來再改成 Markdown 的格式。Tables 比較麻煩要手動在前後加上 ```
這個動作做久了之後我就想到,這個動作其實和 find regex & replace 在做的事其實差不多,為何我不用 regex 來自動做到呢?
如果我們去裝 Replace Rules 這個插件,並且在 settings.json 中加上一些設定 (在文章的最後)。
之後,先在最下方空兩行 (為了讓 table bottom regex 可以正常運作),我們就可以在 VSCode 中按 Ctrl+Shift+P 然後輸入 Run Ruleset -> Ruleset: OneNote plaintext to markdown,剛剛貼過來的 OneNote 文件就會變成下方這樣:
我們再手動把 Title/Subtitle 加上 # 與 ##,把結果貼到 GitHub 的 editor 上,預覽就會正確地把 code block 顯示出來:
筆記格式的限制
- 最後一行
- 不支援有 indent 的 numbered list:因為 indent 第一層的文字會是 a. b. c. ...,第二層是 i. ii. iii. ...,這個用 regex 來取代就會讓 replace rules 多非常多設定,而且不知道到底要支援到第幾個項目。當然如果你要自己加這方面的 replace rules 當然可以,就依樣畫葫蘆就可以了。如果一開始知道要轉換到 markdown,通常我在撰寫就會盡量用 bulleted list,然後在 bulleted list 最上面先用文字敘述說底下這些項目要按照順序
- 不支援 heading:因為從 OneNote 貼過來 VSCode 後,標題和一般文字都長得一樣,無法用 regex 去判別,不過標題通常不多,所以手動加一下 # 通常不會多花時間
- 不支援文字以外的東西:畢竟貼到 VSCode 的時候只會有文字留下來
- Table 只支援 1x1:其他形狀的表格用 regex 做大概很難吧
- Indent 只支援到 level 5:OneNote 如果 indent 層級太多恐怕會有點難閱讀,Markdown 也是
Replace Rules 設定
在 VSCode 中按 Ctrl+Shift+P 輸入 Open User Settings (JSON) 後在適當的地方貼上以下的設定:
{
//-------------------------------------------------------------------------
// Extension: Replace Rules
//-------------------------------------------------------------------------
"replacerules.rules": {
"OneNote plaintext to markdown: Bulleted list level 1": {
"find": "^(\\t){1}• ",
"replace": "- ",
},
"OneNote plaintext to markdown: Bulleted list level 2": {
"find": "^(\\t){2}○ ",
"replace": " * ",
},
"OneNote plaintext to markdown: Bulleted list level 3": {
"find": "^(\\t){3}§ ",
"replace": " + ",
},
"OneNote plaintext to markdown: Bulleted list level 4": {
"find": "^(\\t){4}□ ",
"replace": " - ",
},
"OneNote plaintext to markdown: Bulleted list level 5": {
"find": "^(\\t){5}® ",
"replace": " * ",
},
"OneNote plaintext to markdown: Numbered list level 1": {
"find": "^(\\t){1}(\\w+)\\. ",
"replace": "$2. ",
},
"OneNote plaintext to markdown: Table level 1 top": {
// 1st group: Any line that doesn't start with tab
// 2nd group: A line that starts with 1 tab
"find": "^([^\\t\\n]+\\n)(\\t{1}[^\\t\\n]+\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 1 bottom": {
// 1st group: A line that starts with 1 tab
// 2nd group: Any line that doesn't start with tab
"find": "^(\\t{1}[^\\t\\n]+\\n)([^\\t\\n]*\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 2 top": {
// 1st group: Any line that doesn't start with tab
// 2nd group: A line that starts with 2 tabs
"find": "^([^\\t\\n]+\\n)(\\t{2}[^\\t\\n]+\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 2 bottom": {
// 1st group: A line that starts with 2 tabs
// 2nd group: Any line that doesn't start with tab
"find": "^(\\t{2}[^\\t\\n]+\\n)([^\\t\\n]*\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 3 top": {
// 1st group: Any line that doesn't start with tab
// 2nd group: A line that starts with 3 tabs
"find": "^([^\\t\\n]+\\n)(\\t{3}[^\\t\\n]+\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 3 bottom": {
// 1st group: A line that starts with 3 tabs
// 2nd group: Any line that doesn't start with tab
"find": "^(\\t{3}[^\\t\\n]+\\n)([^\\t\\n]*\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 4 top": {
// 1st group: Any line that doesn't start with tab
// 2nd group: A line that starts with 4 tabs
"find": "^([^\\t\\n]+\\n)(\\t{4}[^\\t\\n]+\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 4 bottom": {
// 1st group: A line that starts with 4 tabs
// 2nd group: Any line that doesn't start with tab
"find": "^(\\t{4}[^\\t\\n]+\\n)([^\\t\\n]*\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 5 top": {
// 1st group: Any line that doesn't start with tab
// 2nd group: A line that starts with 5 tabs
"find": "^([^\\t\\n]+\\n)(\\t{5}[^\\t\\n]+\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Table level 5 bottom": {
// 1st group: A line that starts with 5 tabs
// 2nd group: Any line that doesn't start with tab
"find": "^(\\t{5}[^\\t\\n]+\\n)([^\\t\\n]*\\n)",
"replace": "$1 ```\n$2",
},
"OneNote plaintext to markdown: Tab to spaces": {
"find": "\\t",
"replace": " ",
},
},
"replacerules.rulesets": {
"OneNote plaintext to markdown": {
"rules": [
"OneNote plaintext to markdown: Bulleted list level 1",
"OneNote plaintext to markdown: Bulleted list level 2",
"OneNote plaintext to markdown: Bulleted list level 3",
"OneNote plaintext to markdown: Bulleted list level 4",
"OneNote plaintext to markdown: Bulleted list level 5",
"OneNote plaintext to markdown: Numbered list level 1",
"OneNote plaintext to markdown: Table level 1 top",
"OneNote plaintext to markdown: Table level 1 bottom",
"OneNote plaintext to markdown: Table level 2 top",
"OneNote plaintext to markdown: Table level 2 bottom",
"OneNote plaintext to markdown: Table level 3 top",
"OneNote plaintext to markdown: Table level 3 bottom",
"OneNote plaintext to markdown: Table level 4 top",
"OneNote plaintext to markdown: Table level 4 bottom",
"OneNote plaintext to markdown: Table level 5 top",
"OneNote plaintext to markdown: Table level 5 bottom",
"OneNote plaintext to markdown: Tab to spaces",
]
}
},
}
結語
通常我會在 OneNote 先寫好 spec,再貼到 GitLab 上給團隊的其他人 review,但是 spec 塗塗改改的過程中要一直轉成 Markdown 如果還要叫我用什麼工具去執行我就會覺得很麻煩。用 VSCode 轉換雖然對於筆記的撰寫格式限制滿多的,但轉換的過程非常快速,而且對於寫程式的來說 VSCode 幾乎是經常開著的狀態,何不就地取材一下,加速我們的軟體開發呢?
留言
發佈留言