Viết plugin
Một plugin là bất kỳ đối tượng nào có phương thức apply(builder). Bên trong nó,
hãy tap vào những hook bạn quan tâm.
Một plugin tối giản
Plugin này thêm ước lượng thời gian đọc vào metadata của mỗi trang:
from pyssg.builder import Builder
from pyssg.build import Build
from pyssg.models import Source
class ReadingTime:
def __init__(self, wpm: int = 200) -> None:
self._wpm = wpm
def apply(self, builder: Builder) -> None:
builder.hooks.parse.tap("ReadingTime", self._estimate)
def _estimate(self, source: Source, build: Build) -> None:
words = len(source.body.split())
source.meta["reading_time"] = max(1, round(words / self._wpm))
Dùng nó như bất kỳ plugin có sẵn nào:
plugins = [..., ReadingTime(wpm=180), ...]
Và đọc nó trong một template:
<span>{{ page.reading_time }} min read</span>
Chọn một hook
| Bạn muốn... | Tap |
|---|---|
| Phát hiện hoặc đọc file nguồn | discover, load |
| Phân tích hoặc chú thích một trang đơn lẻ | parse |
| Dựng dữ liệu toàn-trang (nav, group) | collect |
| Biến đổi nội dung body | transform (waterfall) |
| Tạo output từ một trang | render |
| Tạo các file dẫn xuất (rss, sitemap) | generate |
| Hậu xử lý mọi output | optimize |
| Ghi ra đĩa | emit |
| Báo cáo sau khi ghi | after_emit |
Quy ước
- Sắp thứ tự với
stage. Nếu plugin của bạn phải chạy trước hoặc sau một plugin khác trên cùng một hook, hãy đặtstagecủa nó. Số nhỏ hơn chạy trước. - Import lười các phụ thuộc nặng. Import thư viện bên thứ ba bên trong phương thức dùng đến nó, không phải ở đầu module, để plugin có thể được cài đặt và soi xét mà không cần phụ thuộc đó hiện diện.
- Tái dùng mô hình nội dung. Đọc và ghi
build.meta["collections"],["menus"]và["site"](xempyssg.content) thay vì tự nghĩ ra khóa riêng, để plugin của bạn ghép được với các plugin có sẵn. - Đánh dấu trang nhân tạo. Nếu bạn nối thêm một
Sourceđược sinh ra trongcollect, hãy đặtsource.meta["generated"] = Trueđể các plugin khác phân biệt được nó với file thật.
Plugin waterfall
Với transform, hãy trả về giá trị (có thể đã sửa đổi) để tap kế tiếp tiếp tục
đường ống:
def apply(self, builder: Builder) -> None:
builder.hooks.transform.tap("Anchors", self._add_anchors, stage=10)
def _add_anchors(self, source: Source, build: Build) -> Source:
source.content = inject_heading_anchors(source.content)
return source