added pandoc as renderer
This commit is contained in:
@@ -141,6 +141,7 @@ Each managed directory must contain a `.wp-materialize.json` manifest. See `conf
|
|||||||
|
|
||||||
1. `wp` CLI must be installed and available in PATH for `apply`.
|
1. `wp` CLI must be installed and available in PATH for `apply`.
|
||||||
2. `local` does not require `wp`.
|
2. `local` does not require `wp`.
|
||||||
|
3. `pandoc` must be installed and available in PATH when using `renderer: "pandoc"`.
|
||||||
|
|
||||||
Install dependencies:
|
Install dependencies:
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Top-level fields:
|
|||||||
2. `repo_storage_dir` (string, required)
|
2. `repo_storage_dir` (string, required)
|
||||||
Directory where git repositories are cloned or updated.
|
Directory where git repositories are cloned or updated.
|
||||||
3. `renderer` (string, optional)
|
3. `renderer` (string, optional)
|
||||||
Markdown renderer to use. Allowed values: `default`, `py-gfm`.
|
Markdown renderer to use. Allowed values: `default`, `py-gfm`, `pandoc`.
|
||||||
4. `git_repositories` (array, optional)
|
4. `git_repositories` (array, optional)
|
||||||
List of git repositories to manage. Default is an empty list.
|
List of git repositories to manage. Default is an empty list.
|
||||||
5. `directories` (array, optional)
|
5. `directories` (array, optional)
|
||||||
@@ -53,7 +53,7 @@ Top-level fields:
|
|||||||
3. `author` (object, optional)
|
3. `author` (object, optional)
|
||||||
Inherited author for this directory and its children. Must resolve to a single author.
|
Inherited author for this directory and its children. Must resolve to a single author.
|
||||||
4. `renderer` (string, optional)
|
4. `renderer` (string, optional)
|
||||||
Markdown renderer to use for this directory. Allowed values: `default`, `py-gfm`.
|
Markdown renderer to use for this directory. Allowed values: `default`, `py-gfm`, `pandoc`.
|
||||||
If omitted, it inherits from the parent scope.
|
If omitted, it inherits from the parent scope.
|
||||||
5. `subdirectories` (object, optional)
|
5. `subdirectories` (object, optional)
|
||||||
Explicit list of subdirectories to traverse.
|
Explicit list of subdirectories to traverse.
|
||||||
@@ -80,6 +80,11 @@ The `renderer` field inherits implicitly: if omitted, the renderer is inherited
|
|||||||
from the parent scope; if specified, it overrides the parent without an explicit
|
from the parent scope; if specified, it overrides the parent without an explicit
|
||||||
`inherit` flag.
|
`inherit` flag.
|
||||||
|
|
||||||
|
Renderer dependencies:
|
||||||
|
1. `default` uses the Python `Markdown` library.
|
||||||
|
2. `py-gfm` requires the `py_gfm` package (imported as `mdx_gfm`).
|
||||||
|
3. `pandoc` requires the `pandoc` binary to be available on PATH.
|
||||||
|
|
||||||
`files` entries:
|
`files` entries:
|
||||||
|
|
||||||
Each key is a Markdown file name (relative to the manifest directory).
|
Each key is a Markdown file name (relative to the manifest directory).
|
||||||
@@ -95,7 +100,7 @@ Each value is an object with the following fields:
|
|||||||
4. `last_modified` (string, optional)
|
4. `last_modified` (string, optional)
|
||||||
Manual override for the post modified time in `YYYY-MM-DD hh:mm` format.
|
Manual override for the post modified time in `YYYY-MM-DD hh:mm` format.
|
||||||
5. `renderer` (string, optional)
|
5. `renderer` (string, optional)
|
||||||
Markdown renderer to use for this file. Allowed values: `default`, `py-gfm`.
|
Markdown renderer to use for this file. Allowed values: `default`, `py-gfm`, `pandoc`.
|
||||||
If omitted, it inherits from the parent scope.
|
If omitted, it inherits from the parent scope.
|
||||||
6. `categories` (object, optional)
|
6. `categories` (object, optional)
|
||||||
Overrides categories for this file. Uses the same `content` and `inherit` fields
|
Overrides categories for this file. Uses the same `content` and `inherit` fields
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Root directory manifest (`.wp-materialize.json`):
|
|||||||
"categories": { "content": ["Systems", "Infrastructure"], "inherit": true },
|
"categories": { "content": ["Systems", "Infrastructure"], "inherit": true },
|
||||||
"tags": { "content": ["automation", "wordpress"], "inherit": true },
|
"tags": { "content": ["automation", "wordpress"], "inherit": true },
|
||||||
"author": { "content": ["editorial"], "inherit": true },
|
"author": { "content": ["editorial"], "inherit": true },
|
||||||
"renderer": "py-gfm",
|
"renderer": "pandoc",
|
||||||
"subdirectories": { "content": ["design", "notes"], "inherit": true },
|
"subdirectories": { "content": ["design", "notes"], "inherit": true },
|
||||||
"files": {
|
"files": {
|
||||||
"post.md": {
|
"post.md": {
|
||||||
@@ -21,7 +21,7 @@ Root directory manifest (`.wp-materialize.json`):
|
|||||||
},
|
},
|
||||||
"essay.md": {
|
"essay.md": {
|
||||||
"use_heading_as_title": { "level": 1, "strict": true },
|
"use_heading_as_title": { "level": 1, "strict": true },
|
||||||
"renderer": "default",
|
"renderer": "py-gfm",
|
||||||
"created_on": "2025-01-10 09:30",
|
"created_on": "2025-01-10 09:30",
|
||||||
"last_modified": "2025-02-14 16:45"
|
"last_modified": "2025-02-14 16:45"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,6 @@ def _require_renderer(value: object, context: str) -> Optional[str]:
|
|||||||
if not isinstance(value, str) or not value.strip():
|
if not isinstance(value, str) or not value.strip():
|
||||||
raise ConfigurationError(f"{context} must be a non-empty string")
|
raise ConfigurationError(f"{context} must be a non-empty string")
|
||||||
renderer = value.strip()
|
renderer = value.strip()
|
||||||
if renderer not in {"default", "py-gfm"}:
|
if renderer not in {"default", "py-gfm", "pandoc"}:
|
||||||
raise ConfigurationError(f"{context} must be one of: default, py-gfm")
|
raise ConfigurationError(f"{context} must be one of: default, py-gfm, pandoc")
|
||||||
return renderer
|
return renderer
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ def _parse_renderer_field(value: object, issues: list[ValidationIssue], context:
|
|||||||
issues.append(ValidationIssue("Must be a non-empty string", context=context))
|
issues.append(ValidationIssue("Must be a non-empty string", context=context))
|
||||||
return None
|
return None
|
||||||
renderer = value.strip()
|
renderer = value.strip()
|
||||||
if renderer not in {"default", "py-gfm"}:
|
if renderer not in {"default", "py-gfm", "pandoc"}:
|
||||||
issues.append(ValidationIssue("Must be one of: default, py-gfm", context=context))
|
issues.append(ValidationIssue("Must be one of: default, py-gfm, pandoc", context=context))
|
||||||
return None
|
return None
|
||||||
return renderer
|
return renderer
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import markdown as md_lib
|
import markdown as md_lib
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from .errors import ValidationIssue
|
from .errors import ValidationIssue
|
||||||
|
|
||||||
@@ -81,5 +82,22 @@ def convert_markdown(
|
|||||||
except Exception as exc: # pragma: no cover - depends on markdown internals
|
except Exception as exc: # pragma: no cover - depends on markdown internals
|
||||||
issues.append(ValidationIssue(f"Markdown conversion failed: {exc}", context=context))
|
issues.append(ValidationIssue(f"Markdown conversion failed: {exc}", context=context))
|
||||||
return None
|
return None
|
||||||
|
if renderer == "pandoc":
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["pandoc", "--from=markdown", "--to=html5"],
|
||||||
|
input=markdown_text,
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return result.stdout
|
||||||
|
except FileNotFoundError as exc:
|
||||||
|
issues.append(ValidationIssue(f"pandoc is not available: {exc}", context=context))
|
||||||
|
return None
|
||||||
|
except subprocess.CalledProcessError as exc:
|
||||||
|
stderr = exc.stderr.strip() if exc.stderr else ""
|
||||||
|
issues.append(ValidationIssue(f"Pandoc conversion failed: {stderr}", context=context))
|
||||||
|
return None
|
||||||
issues.append(ValidationIssue(f"Unknown renderer: {renderer}", context=context))
|
issues.append(ValidationIssue(f"Unknown renderer: {renderer}", context=context))
|
||||||
return None
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user