-
Notifications
You must be signed in to change notification settings - Fork 1
resolves 14: add full Typst document compilation support #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resolves 14: add full Typst document compilation support #15
Conversation
prudhomm
commented
Jan 18, 2026
- closes Add full Typst document compilation support #14
…nstallation Add full Typst document compilation support Fixes #14
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds comprehensive Typst document compilation support to article-cli. However, there is a critical bug: the TypstCompiler class is imported and used throughout the codebase but the actual implementation file (typst_compiler.py) is missing from the pull request.
Changes:
- Adds Typst project types (
typst-presentation,typst-poster) with template generation - Extends theme installation to include Typst files alongside LaTeX files
- Updates CLI to support
.typfile detection and compilation with--engine typst - Adds Typst configuration section to config files
- Updates documentation and version to 1.4.0
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/article_cli/init.py | Imports missing TypstCompiler class and bumps version to 1.4.0 |
| src/article_cli/cli.py | Adds Typst engine option, .typ file auto-detection, and font path arguments |
| src/article_cli/config.py | Adds get_typst_config() method and typst_files to theme configuration |
| src/article_cli/themes.py | Extends theme installation to extract Typst files alongside LaTeX files |
| src/article_cli/repository_setup.py | Adds Typst template generation methods for presentations and posters |
| tests/test_themes.py | Adds tests for Typst file extraction from theme archives |
| README.md | Documents new Typst compilation features and usage examples |
| CHANGELOG.md | Documents v1.4.0 changes with future release date (2026-01-18) |
| pyproject.toml | Updates version and description to mention Typst support |
Comments suppressed due to low confidence (1)
src/article_cli/themes.py:138
- The theme installation check only verifies if LaTeX files (theme_files) exist, but doesn't check for Typst files (typst_files). If a theme has only Typst files or if the LaTeX files are deleted but Typst files remain, the check would incorrectly report the theme as not installed. Consider checking both theme_files and typst_files, or checking all_files instead.
if theme_files and not force:
main_file = self.themes_dir / theme_files[0]
if main_file.exists():
print_info(f"Theme '{name}' already installed at {self.themes_dir}")
return True
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if is_typst: | ||
| # Format authors for Typst | ||
| authors_typst = ", ".join([f'"{author}"' for author in authors]) | ||
|
|
||
| if project_type in ("typst-presentation", "presentation") and filename.endswith(".typ"): | ||
| doc_content = self._get_typst_presentation_template( | ||
| title, authors_typst, theme | ||
| ) | ||
| elif project_type in ("typst-poster", "poster") and filename.endswith(".typ"): | ||
| doc_content = self._get_typst_poster_template(title, authors_typst) | ||
| else: | ||
| doc_content = self._get_typst_presentation_template( | ||
| title, authors_typst, theme | ||
| ) | ||
| else: | ||
| tex_content = self._get_article_template(title, authors_latex) | ||
| # Format authors for LaTeX | ||
| authors_latex = " \\\\and ".join(authors) | ||
|
|
||
| if project_type == "presentation": | ||
| doc_content = self._get_presentation_template( | ||
| title, authors_latex, theme, aspect_ratio | ||
| ) | ||
| elif project_type == "poster": | ||
| doc_content = self._get_poster_template(title, authors_latex) | ||
| else: | ||
| doc_content = self._get_article_template(title, authors_latex) | ||
|
|
||
| tex_path.write_text(tex_content) | ||
| print_success(f"Created: {tex_path.relative_to(self.repo_path)}") | ||
| doc_path.write_text(doc_content) | ||
| print_success(f"Created: {doc_path.relative_to(self.repo_path)}") | ||
| return True |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new Typst functionality lacks test coverage. The repository has comprehensive tests for other features (test_repository_setup.py has tests for LaTeX templates, test_themes.py has theme tests), but there are no tests for:
- The _get_typst_presentation_template and _get_typst_poster_template methods
- The Typst file detection logic for typst-presentation and typst-poster project types
- The .typ file auto-detection in _detect_or_create_tex_file
Consider adding tests similar to the existing test_detect_or_create_tex_file_presentation_default but for typst-presentation and typst-poster types.
| # Determine engine from args or auto-detect from file extension | ||
| engine = args.engine | ||
| doc_file = args.tex_file | ||
|
|
||
| # Auto-detect file if not provided | ||
| if not doc_file: | ||
| # If engine is typst, look for .typ files first | ||
| if engine == "typst": | ||
| doc_file = _auto_detect_typ_file() | ||
| if not doc_file: | ||
| doc_file = _auto_detect_tex_file() | ||
| else: | ||
| doc_file = _auto_detect_tex_file() | ||
| if not doc_file: | ||
| doc_file = _auto_detect_typ_file() | ||
|
|
||
| # Auto-detect tex file if not provided | ||
| tex_file = args.tex_file | ||
| if not tex_file: | ||
| tex_file = _auto_detect_tex_file() | ||
| if not tex_file: | ||
| if not doc_file: | ||
| print_error( | ||
| "No .tex file specified and none found in current directory" | ||
| "No .tex or .typ file specified and none found in current directory" | ||
| ) | ||
| return 1 | ||
|
|
||
| # Validate tex file exists | ||
| tex_path = Path(tex_file) | ||
| if not tex_path.exists(): | ||
| print_error(f"LaTeX file not found: {tex_file}") | ||
| # Validate file exists | ||
| doc_path = Path(doc_file) | ||
| if not doc_path.exists(): | ||
| print_error(f"Document file not found: {doc_file}") | ||
| return 1 | ||
|
|
||
| compiler = LaTeXCompiler(config) | ||
| # Auto-detect engine from file extension if not explicitly set to typst | ||
| if doc_path.suffix == ".typ" and engine != "typst": | ||
| print_info(f"Detected Typst file, switching engine to typst") | ||
| engine = "typst" | ||
| elif doc_path.suffix == ".tex" and engine == "typst": | ||
| print_error(f"Cannot use Typst engine with .tex file: {doc_file}") | ||
| return 1 | ||
|
|
||
| # Clean before compilation if requested | ||
| if args.clean_first: | ||
| print_info("Cleaning build files before compilation...") | ||
| git_manager = GitManager() | ||
| latex_config = config.get_latex_config() | ||
| git_manager.clean_latex_files(latex_config["clean_extensions"]) | ||
|
|
||
| # Compile the document | ||
| success = compiler.compile( | ||
| tex_file=tex_file, | ||
| engine=args.engine, | ||
| shell_escape=args.shell_escape, | ||
| output_dir=args.output_dir, | ||
| watch=args.watch, | ||
| ) | ||
| # Use appropriate compiler | ||
| if engine == "typst": | ||
| from .typst_compiler import TypstCompiler | ||
|
|
||
| # Clean after compilation if requested | ||
| if args.clean_after and success: | ||
| print_info("Cleaning build files after compilation...") | ||
| git_manager = GitManager() | ||
| latex_config = config.get_latex_config() | ||
| git_manager.clean_latex_files(latex_config["clean_extensions"]) | ||
| compiler = TypstCompiler(config) | ||
|
|
||
| # Compile the document | ||
| success = compiler.compile( | ||
| typ_file=doc_file, | ||
| output_dir=args.output_dir, | ||
| font_paths=args.font_paths, | ||
| watch=args.watch, | ||
| ) |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new CLI functionality for Typst compilation lacks test coverage. The compile command handler now includes Typst-specific logic (lines 306-354) including auto-detection of .typ files and engine selection, but there are no tests for this functionality. The repository has tests for other modules (test_latex_compiler.py, test_repository_setup.py, test_themes.py), but no tests for the CLI compile command with Typst files.
| print_info( | ||
| f"Multiple .tex files found, using: {tex_files[0].name} " | ||
| f"Multiple {file_ext} files found, using: {doc_files[0].name} " | ||
| "(use --tex-file to specify different file)" |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user-facing message refers to '--tex-file' argument, but this should likely be '--doc-file' or similar since the method now handles both .tex and .typ files. However, the actual CLI argument name is still '--tex-file' (line 78 of cli.py), which may confuse users working with Typst files. Consider updating the argument name to be more generic or update this message to clarify it works for both file types.
| "(use --tex-file to specify different file)" | |
| "(use --tex-file to specify a different .tex/.typ file)" |
| from .typst_compiler import TypstCompiler | ||
|
|
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TypstCompiler class is imported but the module typst_compiler.py does not exist in the codebase. This will cause an ImportError when the package is imported or when the compile command is used with Typst files. The missing module needs to be created with a TypstCompiler class that implements the compile method with the signature used in cli.py (typ_file, output_dir, font_paths, watch parameters).
| from .typst_compiler import TypstCompiler | |
| try: | |
| from .typst_compiler import TypstCompiler | |
| except ImportError: | |
| class TypstCompiler: | |
| """ | |
| Fallback TypstCompiler used when the typst_compiler module is not available. | |
| This class exposes the expected interface but will raise a NotImplementedError | |
| if compile is called, indicating that Typst support is not installed. | |
| """ | |
| def compile(self, typ_file, output_dir, font_paths=None, watch=False): | |
| """ | |
| Compile a Typst file. | |
| Parameters | |
| ---------- | |
| typ_file : str or pathlib.Path | |
| Path to the Typst source file. | |
| output_dir : str or pathlib.Path | |
| Directory where compiled output should be written. | |
| font_paths : list[str] or list[pathlib.Path], optional | |
| Additional font search paths for the compiler. | |
| watch : bool, optional | |
| If True, recompile automatically when sources change. | |
| """ | |
| raise NotImplementedError( | |
| "TypstCompiler is not available because 'typst_compiler' module " | |
| "could not be imported. Ensure typst_compiler.py is present and " | |
| "provides a TypstCompiler implementation." | |
| ) |
| theme_import = f'#import "{theme}.typ": *' | ||
| theme_show = f"#show: {theme}-theme.with(" | ||
| else: | ||
| theme_import = "// No theme specified - using basic Typst presentation" |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable theme_import is not used.
| theme_import = "// No theme specified - using basic Typst presentation" | |
| # No theme specified - using basic Typst presentation |
| if theme: | ||
| return f"""{theme_import} |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable theme_show is not used.
| if theme: | |
| return f"""{theme_import} | |
| return f"""{theme_import} |
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>