Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
> [!NOTE]
> This was quickly hacked to support globs in the `source_file` input.

# Typst GitHub action

Build Typst documents using GitHub workflows.
Expand Down Expand Up @@ -39,7 +42,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Typst
uses: lvignoli/typst-action@main
with:
Expand Down
49 changes: 37 additions & 12 deletions entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import logging
import subprocess
import sys
from pathlib import Path


def compile(filename: str, options: list[str]) -> bool:
def compile(filename: Path, options: list[str]) -> bool:
"""Compiles a Typst file with the specified global options.

Returns True if the typst command exited with status 0, False otherwise.
"""
command = ["typst"] + options + ["compile", filename]
command = ["typst"] + options + ["compile", str(filename)]
logging.debug("Running: " + " ".join(command))

result = subprocess.run(command, capture_output=True, text=True)
Expand All @@ -22,15 +23,41 @@ def compile(filename: str, options: list[str]) -> bool:
return True


def main():
def parse_source_files(source_files_input: list[str]) -> list[Path]:
"""
Handles globs and directories in the source files argument.
"""
source_files_paths = []
for source_file in source_files_input:
source_file = source_file.strip()
if source_file == "":
continue
source_file_path = Path(source_file)
if source_file_path.is_dir():
source_files_paths.extend(source_file_path.glob("**/*.typ"))
elif source_file_path.is_file():
source_files_paths.append(source_file_path)
elif "*" in source_file:
source_files = list(Path.cwd().glob(source_file))
if not source_files:
logging.error(f"No matching files found for {source_file}.")
logging.debug(f"Current directory: {Path.cwd()}")
logging.debug(f"First 10 files: {list(Path.cwd().iterdir())[:10]}")
else:
source_files_paths.extend(source_files)
else:
logging.error(f"Source file {source_file} does not exist.")
return source_files_paths


def main():
logging.basicConfig(level=logging.INFO)

# Parse the positional arguments, expected in the following form
# 1. The Typst files to compile in a line separated string
# 2. The global Typst CLI options, in a line separated string. It means each
# whitespace separated field should be on its own line.
source_files = sys.argv[1].splitlines()
source_files = parse_source_files(sys.argv[1].splitlines())
options = sys.argv[2].splitlines()

version = subprocess.run(
Expand All @@ -40,16 +67,14 @@ def main():

success: dict[str, bool] = {}

for filename in source_files:
filename = filename.strip()
if filename == "":
continue
logging.info(f"Compiling {filename}…")
success[filename] = compile(filename, options)
logging.info(f"Got {len(source_files)} files to compile…")
for file in source_files:
logging.info(f"Compiling {file}…")
success[str(file)] = compile(file, options)

# Log status of each input files.
for filename, status in success.items():
logging.info(f"{filename}: {'✔' if status else '❌'}")
for file, status in success.items():
logging.info(f"{file}: {'✔' if status else '❌'}")

if not all(success.values()):
sys.exit(1)
Expand Down