file loading
This commit is contained in:
@@ -1,10 +1,33 @@
|
||||
from collections.abc import Generator
|
||||
from dataclasses import dataclass
|
||||
from importlib.abc import Traversable
|
||||
from itertools import starmap
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Self
|
||||
|
||||
import yaml
|
||||
|
||||
from .models.skill import SkillFrontmatter
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class LoadedMarkdownDocument:
|
||||
"""Represents a loaded markdown document with its content and frontmatter."""
|
||||
|
||||
relpath: PurePosixPath
|
||||
"""The relative path of the document within the package resources."""
|
||||
content: str
|
||||
"""The raw markdown content of the document."""
|
||||
frontmatter: str
|
||||
"""The raw YAML frontmatter of the document, if present."""
|
||||
|
||||
@classmethod
|
||||
def from_root(cls, root: Traversable) -> set[Self]:
|
||||
"""Recursively load all markdown documents from the root resource."""
|
||||
return set(starmap(cls.from_resource, walk_resources(root)))
|
||||
|
||||
@classmethod
|
||||
def from_resource(cls, relpath: PurePosixPath, resource: Traversable) -> Self:
|
||||
"""Load a markdown document from a package resource."""
|
||||
raw = resource.read_text(encoding="utf-8")
|
||||
frontmatter = get_raw_frontmatter(raw)
|
||||
return cls(relpath=relpath, content=raw, frontmatter=frontmatter)
|
||||
|
||||
|
||||
def walk_resources(
|
||||
@@ -25,27 +48,14 @@ def walk_resources(
|
||||
yield relpath.as_posix(), child
|
||||
|
||||
|
||||
def get_markdown_content(resource: Traversable) -> dict[str, str]:
|
||||
"""Read the content of a markdown resource as text."""
|
||||
return {relpath: doc_file.read_text(encoding="utf-8") for relpath, doc_file in walk_resources(resource)}
|
||||
|
||||
|
||||
def get_idx(raw):
|
||||
for i, line in enumerate(raw.splitlines()):
|
||||
if line.strip().startswith("---"):
|
||||
yield i
|
||||
|
||||
|
||||
def get_raw_frontmatter(raw: str) -> str:
|
||||
delimiter = iter(get_idx(raw))
|
||||
delimiter = iter(get_frontmatter_delim_idx(raw, delimiter="---"))
|
||||
start = next(delimiter) + 1
|
||||
end = next(delimiter)
|
||||
return "\n".join(raw.splitlines()[start:end])
|
||||
|
||||
|
||||
def gen_valid_frontmatter(content: dict[str, str]) -> Generator[SkillFrontmatter]:
|
||||
for relpath, raw in content.items():
|
||||
if relpath.endswith("SKILL.md"):
|
||||
fm = get_raw_frontmatter(raw)
|
||||
validated = SkillFrontmatter.model_validate(yaml.safe_load(fm))
|
||||
yield validated
|
||||
def get_frontmatter_delim_idx(raw: str, *, delimiter: str = "---") -> Generator[int]:
|
||||
for i, line in enumerate(raw.splitlines()):
|
||||
if line.strip().startswith(delimiter):
|
||||
yield i
|
||||
|
||||
Reference in New Issue
Block a user