通過 Markdown 和 Pandoc,可以做到編寫一次,發布兩次。
Pandoc 是一個命令列工具,用於將檔案從一種標示語言轉換為另一種標示語言。在我 一文中,我演示了如何把 Markdown 編寫的文字轉換為網頁、幻燈片和 PDF。
在這篇後續文章中,我將深入探討 Pandoc,展示如何從同一個 Markdown 原始檔生成網頁和 ePub 格式的電子書。我將使用我即將發布的電子書《物件導向思想的 GRASP 原則》為例進行講解,這本電子書正是通過以下過程建立的。
首先,我將解釋這本書使用的檔案結構,然後介紹如何使用 Pandoc 生成網頁並將其部署在 GitHub 上;最後,我演示了如何生成對應的 ePub 格式電子書。
你可以在我的 GitHub 倉庫 Programming Fight Club 中找到相應程式碼。
我用 Markdown 語法完成了所有的寫作,你也可以使用 HTML 標記,但是當 Pandoc 將 Markdown 轉換為 ePub 文件時,引入的 HTML 標記越多,出現問題的風險就越高。我的書按照每章一個檔案的形式進行組織,用 Markdown 的 H1
標記(#
)宣告每章的標題。你也可以在每個檔案中放置多個章節,但將它們放在單獨的檔案中可以更輕鬆地查詢內容並在以後進行更新。
元資訊遵循類似的模式,每種輸出格式都有自己的元資訊檔案。元資訊檔案定義有關文件的資訊,例如要新增到 HTML 中的文字或 ePub 的許可證。我將所有 Markdown 文件儲存在名為 parts
的資料夾中(這對於用來生成網頁和 ePub 的 Makefile 非常重要)。下面以一個例子進行說明,讓我們看一下目錄,前言和關於本書(分為 toc.md
、preface.md
和 about.md
三個檔案)這三部分,為清楚起見,我們將省略其餘的章節。
關於本書這部分內容的開頭部分類似:
# About this book {-}## Who should read this book {-}Before creating a complex software system one needs to create a solid foundation.General Responsibility Assignment Software Principles (GRASP) are guidelines to assignresponsibilities to software classes in object-oriented programming.
每一章完成後,下一步就是新增元資訊來設定網頁和 ePub 的格式。
我建立的網頁的元資訊檔案(web-metadata.yaml
)是一個簡單的 YAML 檔案,其中包含 <head>
標籤中的作者、標題、和版權等資訊,以及 HTML 檔案中開頭和結尾的內容。
我建議(至少)包括 web-metadata.yaml
檔案中的以下欄位:
---title: <a href="/grasp-principles/toc/">GRASP principles for the Object-oriented mind</a>author: Kiko Fernandez-Reyesrights: 2017 Kiko Fernandez-Reyes, CC-BY-NC-SA 4.0 Internationalheader-includes:- | ```{=html} <link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Gentium+Basic|Inconsolata" rel="stylesheet"> ```include-before:- | ```{=html} <p>If you like this book, please consider spreading the word or <a href="https://www.buymeacoffee.com/programming"> buying me a coffee </a> </p> ```include-after:- | ```{=html} <div class="footnotes"> <hr> <div class="container"> <nav class="pagination" role="pagination"> <ul> <p> <span class="page-number">Designed with</span> ?? <span class="page-number"> from Uppsala, Sweden</span> </p> <p> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="/a/img/202006/88x31ayuwnnbjxpe.png" /></a> </p> </ul> </nav> </div> </div> ```---
下面幾個變數需要注意一下:
header-includes
變數包含將要嵌入 <head>
標籤的 HTML 文字。- |
。再往下一行必須以與 |
對齊的三個反引號開始,否則 Pandoc 將無法識別。{= html}
告訴 Pandoc 其中的內容是原始文字,不應該作為 Markdown 處理。(為此,需要檢查 Pandoc 中的 raw_attribute
擴充套件是否已啟用。要進行此檢查,鍵入 pandoc --list-extensions | grep raw
並確保返回的列表包含名為 + raw_html
的專案,加號表示已啟用。)include-before
在網頁開頭新增一些 HTML 文字,此處我請求讀者幫忙宣傳我的書或給我打賞。include-after
變數在網頁末尾新增原始 HTML 文字,同時顯示我的圖書許可證。這些只是其中一部分可用的變數,檢視 HTML 中的模板變數(我的文章 中介紹了如何檢視 LaTeX 的模版變數,檢視 HTML 模版變數的過程是相同的)對其餘變數進行了解。
網頁可以作為一個整體生成,這會產生一個包含所有內容的長頁面;也可以分成多章,我認為這樣會更容易閱讀。我將解釋如何將網頁劃分為多章,以便讀者不會被長網頁嚇到。
為了使網頁易於在 GitHub Pages 上部署,需要建立一個名為 docs
的根資料夾(這是 GitHub Pages 預設用於渲染網頁的根資料夾)。然後我們需要為 docs
下的每一章建立資料夾,將 HTML 內容放在各自的資料夾中,將檔案內容放在名為 index.html
的檔案中。
例如,about.md
檔案將轉換成名為 index.html
的檔案,該檔案位於名為 about
(about/index.html
)的資料夾中。這樣,當使用者鍵入 http://<your-website.com>/about/
時,資料夾中的 index.html
檔案將顯示在其瀏覽器中。
下面的 Makefile
將執行上述所有操作:
# Your book filesDEPENDENCIES= toc preface about# Placement of your HTML filesDOCS=docsall: webweb: setup $(DEPENDENCIES) @cp $(DOCS)/toc/index.html $(DOCS)# Creation and copy of stylesheet and images into# the assets folder. This is important to deploy the# website to Github Pages.setup: @mkdir -p $(DOCS) @cp -r assets $(DOCS)# Creation of folder and index.html file on a# per-chapter basis$(DEPENDENCIES): @mkdir -p $(DOCS)/$@ @pandoc -s --toc web-metadata.yaml parts/[email protected] \ -c /assets/pandoc.css -o $(DOCS)/$@/index.htmlclean: @rm -rf $(DOCS).PHONY: all clean web setup
選項 - c /assets/pandoc.css
宣告要使用的 CSS 樣式表,它將從 /assets/pandoc.cs
中獲取。也就是說,在 <head>
標籤內,Pandoc 會新增這樣一行:
<link rel="stylesheet" href="/assets/pandoc.css">
使用下面的命令生成網頁:
make
根資料夾現在應該包含如下所示的檔案結構:
.---parts| |--- toc.md| |--- preface.md| |--- about.md||---docs |--- assets/ |--- index.html |--- toc | |--- index.html | |--- preface | |--- index.html | |--- about |--- index.html
通過以下步驟將網頁部署到 GitHub 上:
Source
選項讓 GitHub 使用主分支的內容你可以在 GitHub Pages 的網站上獲得更多詳細資訊。
我的書的網頁 便是通過上述過程生成的,可以在網頁上檢視結果。
ePub 格式的元資訊檔案 epub-meta.yaml
和 HTML 元資訊檔案是類似的。主要區別在於 ePub 提供了其他模板變數,例如 publisher
和 cover-image
。ePub 格式圖書的樣式表可能與網頁所用的不同,在這裡我使用一個名為 epub.css
的樣式表。
---title: 'GRASP principles for the Object-oriented Mind'publisher: 'Programming Language Fight Club'author: Kiko Fernandez-Reyesrights: 2017 Kiko Fernandez-Reyes, CC-BY-NC-SA 4.0 Internationalcover-image: assets/cover.pngstylesheet: assets/epub.css...
將以下內容新增到之前的 Makefile
中:
epub: @pandoc -s --toc epub-meta.yaml \ $(addprefix parts/, $(DEPENDENCIES:=.md)) -o $(DOCS)/assets/book.epub
用於產生 ePub 格式圖書的命令從 HTML 版本獲取所有依賴項(每章的名稱),向它們新增 Markdown 擴充套件,並在它們前面加上每一章的資料夾路徑,以便讓 Pandoc 知道如何進行處理。例如,如果 $(DEPENDENCIES
變數只包含 “前言” 和 “關於本書” 兩章,那麼 Makefile
將會這樣呼叫:
@pandoc -s --toc epub-meta.yaml \parts/preface.md parts/about.md -o $(DOCS)/assets/book.epub
Pandoc 將提取這兩章的內容,然後進行組合,最後生成 ePub 格式的電子書,並放在 Assets
資料夾中。
這是使用此過程建立 ePub 格式電子書的一個 範例。
從 Markdown 檔案建立網頁和 ePub 格式電子書的過程並不困難,但有很多細節需要注意。遵循以下大綱可能使你更容易使用 Pandoc。
Makefile
將各個部分組合在一起Makefile
以將各個部分組合在一起