開發佈景主題
建立並散佈自訂佈景主題的指南。
註事項
若您正在尋找現有的第三方佈景主題,它們會列在 社群 Wiki 頁面和 MkDocs 專案目錄 中。如果您想分享自己建立的佈景主題,應該將它列在其中。
在建立新的佈景主題時,您可以依照本指南中的步驟從頭開始建立一個,或下載 mkdocs-basic-theme
當成一個基礎且完整的佈景主題,它具備所有必要的樣板程式碼。您可以在 GitHub 上找到這個基本佈景主題。其程式碼中包含詳細註解,用於說明不同的功能和用法。
建立自訂佈景主題
自訂佈景主題所需要的最少檔案為 main.html
Jinja2 範本 檔案,它放置在不是 docs_dir
子目錄的目錄中。在 mkdocs.yml
中,將 theme.custom_dir
選項設定為包含 main.html
的目錄路徑。路徑應該是相對於設定檔而言。例如,看看這個專案範例佈局
mkdocs.yml
docs/
index.md
about.md
custom_theme/
main.html
...
... 您必須在 mkdocs.yml
中加入以下設定,才能使用自訂佈景主題目錄
theme:
name: null
custom_dir: 'custom_theme/'
註事項
通常,在建置自己的自訂佈景主題時,佈景主題.name
設定應該設定成 null
。然而,若佈景主題.custom_dir
設定值與現有佈景主題一起使用,則可以利用佈景主題.custom_dir
取代內建佈景主題的特定部分。例如,如果您採用上述佈局並設定 name: "mkdocs"
,則 main.html
檔案中的佈景主題.custom_dir
會取代 mkdocs
佈景主題中同名的檔案,但 mkdocs
佈景主題的其他部分則保持不變。如果您想對現有佈景主題進行微調,這項功能便會相當有用。
如需更詳細的資訊,請參閱 自訂佈景主題。
警告
在 mkdocs_theme.yml
檔案中設定的主題設定檔並不會由 theme.custom_dir
載入。當整體主題存在於 theme.custom_dir
中,且 theme.name
設定為 null
時,整體主題設定檔就必須在 mkdocs.yml
檔案中的主題設定選項中定義。
不過,如果將主題打包用於發行,且使用 theme.name
設定選項載入,那麼,主題會需要 mkdocs_theme.yml
檔案。
基本主題
最基本的 main.html
檔案如下所示
<!DOCTYPE html>
<html>
<head>
<title>{% if page.title %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
{%- for path in config.extra_css %}
<link href="{{ path | url }}" rel="stylesheet">
{%- endfor %}
</head>
<body>
{{ page.content }}
{%- for script in config.extra_javascript %}
{{ script | script_tag }}
{%- endfor %}
</body>
</html>
在 mkdocs.yml
中指定的每頁主體內容都會使用 {{ page.content }}
標籤插入。樣式表和腳本可透過與一般 HTML 檔案相同的方式帶入此主題。導覽列和目錄表也可透過 nav
和 toc
物件自動產生並包含。如果您想撰寫自己的主題,建議從其中一個內建主題開始,並根據需要修改。
註事項
由於 MkDocs 使用Jinja作為其範本引擎,因此,你可以運用 Jinja 的所有強大功能,包括範本繼承。你可能會注意到 MkDocs 附帶的主題大量使用範本繼承和區塊,這樣,使用者就可以輕鬆地覆寫主題custom_dir中範本的小部分內容。因此,內建主題是在 base.html
檔案中實作,main.html
會延伸這個檔案。雖然不需要這麼做,但建議第三方範本作者遵循類似的模式,並可能會想要定義與內建主題中所用的區塊區塊相同的內容,以維持一致性。
從設定檔中挑選 CSS 和 JavaScript
Mkdocs 定義了最上層的extra_css和extra_javascript設定檔。這些檔案都是清單。
主題必須包含連結這些設定檔項目的 HTML,否則這些設定檔將無法運作。你可以在以上基本範例中看到建議用來呈現兩者的方法。
在 1.5 版中變更
config.extra_javascript
清單中的項目以前是單純的字串,但現在已變成具有以下欄位的物件:path
、type
、async
、defer
。
在該版本中,MkDocs 也加入了script_tag
濾鏡。
過時的樣式
{%- for path in extra_javascript %}
<script src="{{ path }}"></script>
{%- endfor %}
這個舊式範例甚至使用了過時的 top-level extra_javascript
清單。請務必永遠使用 config.extra_javascript
來取代。
因此,稍微現代一點的方式如下所示,但它仍然過時,因為它忽略了腳本的額外屬性
{%- for path in config.extra_javascript %}
<script src="{{ path | url }}"></script>
{%- endfor %}
範例:**新樣式:**
{%- for script in config.extra_javascript %}
{{ script | script_tag }}
{%- endfor %}
如果你希望能夠使用新的自訂內容,同時讓你的主題與舊版 Mkdocs 相容,請使用這個片段
向下相容的樣式
{%- for script in config.extra_javascript %}
{%- if script.path %} {# Detected MkDocs 1.5+ which has `script.path` and `script_tag` #}
{{ script | script_tag }}
{%- else %} {# Fallback - examine the file name directly #}
<script src="{{ script | url }}"{% if script.endswith(".mjs") %} type="module"{% endif %}></script>
{%- endif %}
{%- endfor %}
主題檔案
主題會以某種特殊方式處理各種檔案。在建立網站時,其他任何檔案都會從主題目錄複製到 site_dir
中的相同路徑。例如,圖片和 CSS 檔案沒有特別意義,因此會原樣複製。不過,請注意,如果使用者在他們的 docs_dir
中提供具有相同路徑的檔案,那麼使用者的檔案將取代主題檔案。
範本檔案
任何副檔名為 .html
的檔案都被視為範本檔案,不會從主題目錄或任何子目錄複製。此外,在 static_templates 中列出的任何檔案都將視為範本,而不考慮其副檔名。
主題元資料檔
封裝主題所需的各種檔案也會被忽略。具體而言,就是 mkdocs_theme.yml
設定檔和任何 Python 檔案。
開頭為點的檔案
主題作者可以透過以點號開頭的檔案或目錄名稱,明確強制 MkDocs 忽略檔案。以下任何檔案都會被忽略
.ignored.txt
.ignored/file.txt
foo/.ignored.txt
foo/.ignored/file.txt
文件檔案
所有文件檔案都被忽略。具體而言,是指任何 Markdown 檔(使用 MkDocs 支援的任何副檔名)。此外,主題目錄中可能存在的任何 README 檔案也會被忽略。
範本變數
主題中的每個範本都是使用範本內容建立的。這些是可供主題使用的變數。內容會根據所建立的範本來而有所不同。目前,範本是使用全域內容或針對特定頁面的內容建立。全域內容用於不表示個別 Markdown 文件的 HTML 頁面,例如 404.html 頁面或 search.html。
全域內容
以下變數在任何範本上都可用於全域。
config
config
變數是從 mkdocs.yml
設定檔產生的 MkDocs 設定物件的實例。雖然你可以使用任何設定選項,但有些常用的選項包括
- config.site_name
- config.site_url
- config.site_author
- config.site_description
- config.theme.locale(另見下方的 主題設定)
- config.extra_javascript
- config.extra_css
- config.repo_url
- config.repo_name
- config.copyright
nav
nav
變數用於建立文件的導覽。nav
物件是由 導覽物件 所組成的可迭代,正如 nav 設定所定義的。
除了 導覽物件 的可迭代之外,nav
物件還包含以下屬性
由於此清單不包含未包含於導覽中的頁面,此清單並不一定是所有網站頁面的完整清單。此清單會符合用於所有「下一頁」和「上一頁」連結的頁面清單和順序。若要檢視所有頁面的清單,請使用 pages 範本變數。
導覽範例
下列是將第一和第二層導覽作為巢狀清單輸出的基本使用範例。
{% if nav|length > 1 %}
<ul>
{% for nav_item in nav %}
{% if nav_item.children %}
<li>{{ nav_item.title }}
<ul>
{% for nav_item in nav_item.children %}
<li class="{% if nav_item.active %}current{% endif %}">
<a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li class="{% if nav_item.active %}current{% endif %}">
<a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
base_url
base_url
提供 MkDocs 專案根目錄的相對路徑。雖然您可以直接透過在其前面加上本機相對 URL 來使用,但最好使用 url 範本過濾器,它會更明智地套用 base_url
。
mkdocs_version
包含目前 MkDocs 版本。
build_date_utc
Python datetime 物件,表示文件建立於 UTC 的日期和時間。這對於顯示文件最後更新時間很有用。
pages
專案中所有頁面的 File
物件扁平清單。此清單可能包含未包含於全球 導覽 中的頁面,且可能與該導覽中的頁面順序不符。可以從 file.page
存取每個 File
的 page 物件。
page
在非從 Markdown 原始檔呈現的範本中,page
變數為 None
。在從 Markdown 原始檔呈現的範本中,page
變數包含 page
物件。相同的 page
物件用於全球 導覽 中的 導覽物件 和 pages 範本變數。
所有 page
物件都包含下列屬性
title() -> str | None
傳回當前頁面的標題。
在呼叫 read_source()
之前,此值為空。也可以透過 render()
來更新。
依序檢查並使用最早傳回有效標題的標題
- 在 init 上提供的值(從設定檔傳入)
- metadata 的 'title' 值
- Markdown 內容中第一個 H1 的內容
- 將檔案名稱轉換為標題
content: str | None
instance-attribute
Markdown 呈現為 HTML 的內容,這是範文的內容。
在 .render()
後填入。
toc: TableOfContents
instance-attribute
表示頁面目錄的 iterable 物件。toc
中的每個項目都是 AnchorLink
。
下列範例會顯示頁面目錄的前兩層。
<ul>
{% for toc_item in page.toc %}
<li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% for toc_item in toc_item.children %}
<li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% endfor %}
{% endfor %}
</ul>
meta: MutableMapping[str, Any]
instance-attribute
封裝在 markdown 頁面開頭的元資料。
在此範例中,我們定義頁面標題上方有一個 source
屬性。
source: generics.py
mixins.py
# Page title
Content...
範本可以使用 meta.source
變數來存取頁面的這些元資料。接著,可以使用它來連結至與文件頁面相關的原始檔。
{% for filename in page.meta.source %}
<a class="github" href="https://github.com/.../{{ filename }}">
<span class="label label-info">{{ filename }}</span>
</a>
{% endfor %}
url: str
特性
相對於 MkDocs site_dir
網址的頁面網址。
預期要結合 url 篩選器來使用,以確保網址與目前的頁面相關。
<a href="{{ page.url|url }}">{{ page.title }}</a>
abs_url: str | None
實體屬性
例如,如果 site_url: https://example.com/
,則頁面 foo.md
的 page.abs_url
值為 /foo/
。然而,如果 site_url: https://example.com/bar/
,則頁面 foo.md
的 page.abs_url
值為 /bar/foo/
。
canonical_url: str | None
實體屬性
is_homepage: bool
特性
評估網站首頁為 True
,其他所有頁面為 False
。
它可以與 Page
物件的其他屬性一起使用來改變行為。例如,首頁顯示不同的標題
{% if not page.is_homepage %}{{ page.title }} - {% endif %}{{ site_name }}
parent: Section | None = None
類別屬性
實例屬性
此項目在導覽網站中的直接父物件。如果在最上層,則為 `None`。
children: None = None
類別屬性
實例屬性
頁面不包含子項目,且屬性總是為 `None`。
active: bool
屬性
可寫入
如果是 `True`,表示此頁面為目前檢視的頁面。預設為 `False`。
is_section: bool = False
類別屬性
實例屬性
表示此導覽物件為「區段」物件。對於頁面物件,總是為 `False`。
is_page: bool = True
類別屬性
實例屬性
表示此導覽物件為「頁面」物件。對於頁面物件,總是為 `True`。
is_link: bool = False
類別屬性
實例屬性
表示此導覽物件為「連結」物件。對於頁面物件,總是為 `False`。
AnchorLink
導覽物件
nav 範本變數中包含的導覽物件可能是其中一個 區段 物件、頁面 物件,以及 連結 物件。雖然區段物件可能包含嵌套的導覽物件,但頁面和連結不會。
頁面物件是完整的頁面物件,就像用於目前 頁面 的物件一樣,具有可用的相同所有屬性。區段和連結物件包含的屬性子集定義如下
區段
區段
導覽物件定義導覽中的命名區段,並包含子導覽物件的清單。請注意,區段不包含 URL,也不是任何類型的連結。但預設上,MkDocs 將索引頁面排序到最上方,如果某個佈景主題選擇這麼做,第一個子項可以做為區段的 URL。
區段
物件提供了以下屬性
標題:str
執行個體屬性
區段的標題。
parent: Section | None = None
類別屬性
實例屬性
此項目在導覽網站中的直接父物件。如果在最上層,則為 `None`。
子項:list[StructureItem]
執行個體屬性
所有子導覽物件的可迭代清單。子項可能包括嵌套的區段、頁面和連結。
已啟用:bool
屬性
可寫
為 True
時,表示這個區段的子頁面是目前頁面,可做為目前已檢視的區段來突顯這個區段。預設值為 False
。
is_section:bool = True
類別屬性
執行個體屬性
表示導覽物件是「區段」物件。對區段物件永遠為 True
。
is_page:bool = False
類別屬性
執行個體屬性
表示導覽物件是「頁面」物件。對區段物件永遠為 False
。
is_link:bool = False
類別屬性
執行個體屬性
表示導覽物件是「連結」物件。對區段物件永遠為 False
。
連結
連結
導覽物件包含一個連結,不會指向 MkDocs 內部頁面。
連結
物件提供了以下屬性
標題:str
執行個體屬性
連結的標題。這一般來說都會用作連結標籤。
url: str
實例屬性
連結指標的 URL。URL 永遠都應該是絕對路徑 URL,不應該需要在前面加上 base_url
。
parent: Section | None = None
類別屬性
實例屬性
此項目在導覽網站中的直接父物件。如果在最上層,則為 `None`。
children: None = None
類別屬性
實例屬性
連結不包含子物件,屬性總是為 None
。
active: bool = False
類別屬性
實例屬性
外部連結無法「啟用」,屬性永遠都是 False
。
is_section: bool = False
類別屬性
實例屬性
表示導覽物件是「區段」物件。針對連結物件,永遠都是 False
。
is_page: bool = False
類別屬性
實例屬性
表示導覽物件是「頁面」物件。針對連結物件,永遠都是 False
。
is_link: bool = True
類別屬性
實例屬性
表示導覽物件是「連結」物件。針對連結物件,永遠都是 True
。
額外內容
可以用 extra
組態選項將其他變數傳遞給範本。這是一組可以讓自訂範本有更佳彈性的關鍵值配對。
例如,這可以用來包含所有頁面的專案版本和與專案有關的一堆連結。這可以用以下的 extra
組態實作:
extra:
version: 0.13.0
links:
- https://github.com/mkdocs
- https://docs.readthedocs.org/en/latest/builds.html#mkdocs
- https://mkdocs.dev.org.tw/
然後顯示在自訂佈景主題的這段 HTML 中。
{{ config.extra.version }}
{% if config.extra.links %}
<ul>
{% for link in config.extra.links %}
<li>{{ link }}</li>
{% endfor %}
</ul>
{% endif %}
範本篩選器
除了 Jinja 的預設篩選器 外,也可以在 MkDocs 範本中使用下列自訂篩選器
url
正規化 URL。絕對路徑 URL 會直接通過。如果 URL 是相對路徑,而範本內容包括頁面物件,則會以該頁面物件為相對值傳回 URL。否則,會預先加上 base_url 傳回 URL。
<a href="{{ page.url|url }}">{{ page.title }}</a>
tojson
安全地將 Python 物件轉換為 JavaScript 程式碼中的值。
<script>
var mkdocs_page_name = {{ page.title|tojson|safe }};
</script>
script_tag
1.5 版的新功能
將 `extra_javascript` 中的項目轉換為 `