pyssgA tiny-kernel, plugin-driven static site generator

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ồndiscover, 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 bodytransform (waterfall)
Tạo output từ một trangrender
Tạo các file dẫn xuất (rss, sitemap)generate
Hậu xử lý mọi outputoptimize
Ghi ra đĩaemit
Báo cáo sau khi ghiafter_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 đặt stage củ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"]["site"] (xem pyssg.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 trong collect, hãy đặt source.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