diff --git a/markitect/clean_document_manager.py b/markitect/clean_document_manager.py
index 9cb98529..cc493c01 100644
--- a/markitect/clean_document_manager.py
+++ b/markitect/clean_document_manager.py
@@ -118,6 +118,202 @@ class CleanDocumentManager:
return version_info
+ def _get_template_css(self, template: str = None) -> str:
+ """Generate layered theme CSS styles."""
+ # Import layered theme functions
+ from markitect.plugins.builtin.markdown_commands import (
+ parse_theme_string, combine_theme_properties, TEMPLATE_STYLES
+ )
+
+ # Handle layered themes or fall back to legacy
+ if template and ',' in template:
+ # New layered theme system
+ theme_list = parse_theme_string(template)
+ combined_props = combine_theme_properties(theme_list)
+ return self._generate_layered_css(combined_props)
+ else:
+ # Legacy single theme or fallback
+ if not template or template not in TEMPLATE_STYLES:
+ # Use default layered themes
+ theme_list = parse_theme_string('basic')
+ combined_props = combine_theme_properties(theme_list)
+ return self._generate_layered_css(combined_props)
+ else:
+ # Legacy theme - convert to layered
+ theme_list = parse_theme_string(template)
+ combined_props = combine_theme_properties(theme_list)
+ return self._generate_layered_css(combined_props)
+
+ def _generate_layered_css(self, properties: dict) -> str:
+ """Generate CSS from combined theme properties."""
+
+ # Set defaults for missing properties (properties override defaults)
+ defaults = {
+ 'body_background': '#ffffff',
+ 'body_color': '#333333',
+ 'font_family': '-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif',
+ 'max_width': '800px',
+ 'heading_color': '#333333', # Use same as body color by default
+ 'heading_style': 'simple',
+ 'text_align': 'left',
+ 'code_background': '#f6f8fa',
+ 'code_color': '#333333',
+ 'border_color': '#d0d7de',
+ 'blockquote_border': '#dfe2e5',
+ 'blockquote_color': '#6a737d',
+ 'table_border': '#d0d7de',
+ 'table_header_bg': '#f6f8fa',
+ 'accent_color': None,
+ 'secondary_color': None
+ }
+
+ # Merge defaults first, then override with theme properties
+ props = {**defaults, **properties}
+
+ # Base CSS
+ base_css = f"""
+ body {{
+ font-family: {props['font_family']};
+ max-width: {props['max_width']};
+ margin: 0 auto;
+ padding: 2rem;
+ line-height: 1.6;
+ color: {props['body_color']};
+ background-color: {props['body_background']};
+ }}
+ #markdown-content {{
+ min-height: 200px;
+ }}"""
+
+ # Heading styles
+ heading_css = ""
+ if props['heading_style'] == 'underlined':
+ heading_css = f"""
+ h1, h2, h3, h4, h5, h6 {{
+ color: {props['heading_color']};
+ border-bottom: 1px solid {props['border_color']};
+ padding-bottom: 0.3em;
+ }}"""
+ elif props['heading_style'] == 'centered':
+ heading_css = f"""
+ h1, h2, h3, h4, h5, h6 {{
+ color: {props['heading_color']};
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+ }}
+ h1 {{
+ text-align: center;
+ font-size: 2.2em;
+ border-bottom: 2px solid {props['heading_color']};
+ padding-bottom: 0.5rem;
+ }}"""
+ else: # simple
+ heading_css = f"""
+ h1, h2, h3, h4, h5, h6 {{
+ color: {props['heading_color']};
+ }}"""
+
+ # Text alignment
+ text_css = ""
+ if props['text_align'] == 'justify':
+ text_css = """
+ p {
+ text-align: justify;
+ margin-bottom: 1.2rem;
+ }"""
+
+ # Element styling
+ element_css = f"""
+ pre {{
+ background-color: {props['code_background']};
+ color: {props['code_color']};
+ padding: 1rem;
+ border-radius: 6px;
+ overflow-x: auto;
+ border: 1px solid {props['border_color']};
+ }}
+ code {{
+ background-color: {props['code_background']};
+ color: {props['code_color']};
+ padding: 0.2em 0.4em;
+ border-radius: 3px;
+ font-size: 0.9em;
+ }}
+ pre code {{
+ background: none;
+ padding: 0;
+ }}
+ blockquote {{
+ border-left: 4px solid {props['blockquote_border']};
+ margin: 0;
+ padding-left: 1rem;
+ color: {props['blockquote_color']};
+ }}
+ table {{
+ font-size: 0.85em;
+ border-collapse: collapse;
+ margin: 1rem 0;
+ width: 100%;
+ border: 1px solid {props['table_border']};
+ }}
+ th, td {{
+ font-size: inherit;
+ border: 1px solid {props['table_border']};
+ padding: 0.5rem;
+ text-align: left;
+ }}
+ th {{
+ background-color: {props['table_header_bg']};
+ font-weight: 600;
+ }}"""
+
+ # Branding accents (if specified)
+ accent_css = ""
+ if props.get('accent_color'):
+ accent_css = f"""
+ a {{
+ color: {props['accent_color']};
+ }}
+ a:hover {{
+ opacity: 0.8;
+ }}"""
+
+ return f""
+
+ def _get_legacy_template_css(self, template: str) -> str:
+ """Legacy CSS generation - kept for backward compatibility."""
+ # Import template styles
+ from markitect.plugins.builtin.markdown_commands import TEMPLATE_STYLES
+
+ # Use basic as default if no template specified
+ if not template or template not in TEMPLATE_STYLES:
+ template = 'basic'
+
+ style_config = TEMPLATE_STYLES[template]
+
+ # Base CSS that's common to all templates
+ base_css = f"""
+ body {{
+ font-family: {style_config['font_family']};
+ max-width: {style_config['max_width']};
+ margin: 0 auto;
+ padding: 2rem;
+ line-height: 1.6;
+ color: {style_config['body_color']};
+ }}
+ #markdown-content {{
+ min-height: 200px;
+ }}"""
+
+ # Convert legacy template config to layered format
+ legacy_config = TEMPLATE_STYLES[template]
+ layered_props = {
+ 'font_family': legacy_config['font_family'],
+ 'max_width': legacy_config['max_width'],
+ 'body_color': legacy_config['body_color'],
+ }
+ return self._generate_layered_css(layered_props)
+
def _generate_html_template(self, markdown_content: str, title: str, css: str = None, template: str = None,
edit_mode: bool = False, editor_theme: str = 'github', keyboard_shortcuts: bool = True, original_filename: str = 'document', version_info: dict = None) -> str:
"""Generate clean HTML template."""
@@ -138,60 +334,8 @@ class CleanDocumentManager:
except Exception:
css_content = f''
- # Default CSS for basic styling
- default_css = """
-
- """
+ # Generate template-specific CSS
+ default_css = self._get_template_css(template)
# Load clean editor JavaScript files
editor_scripts = ""
diff --git a/markitect/plugins/builtin/markdown_commands.py b/markitect/plugins/builtin/markdown_commands.py
index 502e3fcd..98fac116 100644
--- a/markitect/plugins/builtin/markdown_commands.py
+++ b/markitect/plugins/builtin/markdown_commands.py
@@ -26,7 +26,97 @@ def get_default_format(available_formats=['table', 'json', 'yaml', 'simple'], fa
return fallback
-# Template styles configuration for tests
+# Layered theme system - themes can be combined across different scopes
+LAYERED_THEMES = {
+ # UI Themes - Interface colors and backgrounds
+ 'light': {
+ 'scope': 'ui',
+ 'properties': {
+ 'body_background': '#ffffff',
+ 'body_color': '#333333',
+ 'heading_color': '#24292f',
+ 'code_background': '#f6f8fa',
+ 'code_color': '#24292e',
+ 'border_color': '#d0d7de',
+ 'blockquote_border': '#dfe2e5',
+ 'blockquote_color': '#6a737d',
+ 'table_border': '#d0d7de',
+ 'table_header_bg': '#f6f8fa'
+ }
+ },
+ 'dark': {
+ 'scope': 'ui',
+ 'properties': {
+ 'body_background': '#0d1117',
+ 'body_color': '#e1e4e8',
+ 'heading_color': '#58a6ff',
+ 'code_background': '#161b22',
+ 'code_color': '#e1e4e8',
+ 'border_color': '#30363d',
+ 'blockquote_border': '#58a6ff',
+ 'blockquote_color': '#8b949e',
+ 'table_border': '#30363d',
+ 'table_header_bg': '#161b22'
+ }
+ },
+
+ # Document Themes - Typography and layout
+ 'basic': {
+ 'scope': 'document',
+ 'properties': {
+ 'font_family': '-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif',
+ 'max_width': '800px',
+ 'heading_style': 'simple',
+ 'text_align': 'left'
+ }
+ },
+ 'github': {
+ 'scope': 'document',
+ 'properties': {
+ 'font_family': '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif',
+ 'max_width': '900px',
+ 'heading_style': 'underlined',
+ 'text_align': 'left'
+ }
+ },
+ 'academic': {
+ 'scope': 'document',
+ 'properties': {
+ 'font_family': 'Georgia, Times New Roman, serif',
+ 'max_width': '650px',
+ 'heading_style': 'centered',
+ 'text_align': 'justify'
+ }
+ },
+
+ # Branding Themes - Company/personal styling
+ 'corporate': {
+ 'scope': 'branding',
+ 'properties': {
+ 'accent_color': '#0066cc',
+ 'secondary_color': '#f8f9fa',
+ 'brand_font': 'inherit'
+ }
+ },
+ 'startup': {
+ 'scope': 'branding',
+ 'properties': {
+ 'accent_color': '#ff6b35',
+ 'secondary_color': '#f4f4f4',
+ 'brand_font': 'inherit'
+ }
+ }
+}
+
+# Legacy compatibility - map old theme names to new layered equivalents
+LEGACY_THEME_MAPPING = {
+ 'basic': ['light', 'basic'],
+ 'github': ['light', 'github'],
+ 'dark': ['dark', 'basic'],
+ 'academic': ['light', 'academic']
+}
+
+# Keep TEMPLATE_STYLES for backward compatibility in tests
TEMPLATE_STYLES = {
'basic': {
'body_color': '#333',
@@ -51,21 +141,133 @@ TEMPLATE_STYLES = {
}
-def generate_html_with_embedded_markdown(markdown_content, title, template, css_content, template_vars):
+def parse_theme_string(theme_string: str) -> list:
+ """
+ Parse theme string into list of individual themes.
+
+ Supports:
+ - Single theme: "dark"
+ - Multiple themes: "dark,academic" or "dark, academic"
+ - Legacy theme mapping: "basic" -> ["light", "basic"]
+
+ Args:
+ theme_string: Comma-separated theme names
+
+ Returns:
+ List of theme names in order
+ """
+ if not theme_string:
+ return ['light', 'basic'] # Default themes
+
+ # Split by comma and clean up whitespace
+ themes = [theme.strip() for theme in theme_string.split(',')]
+
+ # Expand legacy themes only if they don't exist in the new layered system
+ expanded_themes = []
+ for theme in themes:
+ if theme in LAYERED_THEMES:
+ # Theme exists in new system, use as-is
+ expanded_themes.append(theme)
+ elif theme in LEGACY_THEME_MAPPING:
+ # Legacy theme, expand it
+ expanded_themes.extend(LEGACY_THEME_MAPPING[theme])
+ else:
+ # Unknown theme, add as-is (will be warned about later)
+ expanded_themes.append(theme)
+
+ return expanded_themes
+
+
+class ThemeType(click.ParamType):
+ """Custom click type for theme validation."""
+
+ name = "theme"
+
+ def convert(self, value, param, ctx):
+ if value is None:
+ return value
+
+ try:
+ validate_theme_string(value)
+ return value
+ except click.BadParameter as e:
+ self.fail(str(e), param, ctx)
+
+
+def validate_theme_string(theme_string: str) -> None:
+ """
+ Validate that all themes in a theme string are known themes.
+
+ Args:
+ theme_string: Comma-separated theme names
+
+ Raises:
+ click.BadParameter: If any theme is unknown
+ """
+ if not theme_string:
+ return # Allow empty/None themes
+
+ themes = parse_theme_string(theme_string)
+ unknown_themes = []
+
+ for theme_name in themes:
+ if theme_name not in LAYERED_THEMES and theme_name not in LEGACY_THEME_MAPPING:
+ unknown_themes.append(theme_name)
+
+ if unknown_themes:
+ available_themes = list(LAYERED_THEMES.keys()) + list(LEGACY_THEME_MAPPING.keys())
+ raise click.BadParameter(
+ f"Unknown theme(s): {', '.join(unknown_themes)}. "
+ f"Available themes: {', '.join(sorted(set(available_themes)))}"
+ )
+
+
+def combine_theme_properties(theme_list: list) -> dict:
+ """
+ Combine properties from multiple themes, with later themes overriding earlier ones.
+
+ Args:
+ theme_list: List of theme names in order of application
+
+ Returns:
+ Combined properties dictionary
+ """
+ combined_properties = {}
+
+ for theme_name in theme_list:
+ if theme_name in LAYERED_THEMES:
+ theme_data = LAYERED_THEMES[theme_name]
+ # Later themes override earlier ones
+ combined_properties.update(theme_data['properties'])
+ elif theme_name in LEGACY_THEME_MAPPING:
+ # Handle legacy themes by expanding them
+ expanded_themes = LEGACY_THEME_MAPPING[theme_name]
+ for expanded_theme in expanded_themes:
+ if expanded_theme in LAYERED_THEMES:
+ theme_data = LAYERED_THEMES[expanded_theme]
+ combined_properties.update(theme_data['properties'])
+ else:
+ # This should not happen if validation is working
+ print(f"Warning: Unknown theme '{theme_name}' - skipping")
+ return combined_properties
+
+
+def generate_html_with_embedded_markdown(markdown_content, title, theme, css_content, template_vars):
"""
Generate HTML with embedded markdown content for testing.
This function is used by tests to validate template functionality.
"""
# Create a temporary document manager for rendering
- doc_manager = DocumentManager(None)
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(None)
# Generate HTML template
html_content = doc_manager._generate_html_template(
markdown_content=markdown_content,
title=title,
css=css_content,
- template=template
+ template=theme
)
return html_content
@@ -191,7 +393,8 @@ def process_single_file(input_file: Path, use_publication_dir: bool, publication
output_file = input_file.with_suffix('.html')
# Create document manager and render
- doc_manager = DocumentManager(None)
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(None)
doc_manager.render_file(str(input_file), str(output_file))
return output_file
@@ -212,7 +415,8 @@ def process_directory(input_dir: Path, use_publication_dir: bool, publication_di
markdown_files = find_markdown_files(input_dir)
output_files = []
- doc_manager = DocumentManager(None)
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(None)
for md_file in markdown_files:
if use_publication_dir:
@@ -304,21 +508,22 @@ def extract_html_title(html_file: Path) -> str:
return html_file.stem
-def generate_index_html(html_files: list, title: str, template: str = None) -> str:
+def generate_index_html(html_files: list, title: str, theme: str = None) -> str:
"""
Generate HTML content for an index page.
Args:
html_files: List of dictionaries with 'path', 'title', and 'relative_path' keys
title: Title for the index page
- template: Template theme to use
+ theme: Theme to use
Returns:
HTML content string
"""
# Get template CSS
- doc_manager = DocumentManager(None)
- template_css = doc_manager._get_template_css(template)
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(None)
+ template_css = doc_manager._get_template_css(theme)
# Generate file list HTML
if not html_files:
@@ -1530,7 +1735,8 @@ def md_ingest_command(ctx, file_path):
click.echo(f"Processing file: {file_path}")
# Initialize document manager with database manager
- doc_manager = DocumentManager(config.get('db_manager'))
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(config.get('db_manager'))
# Process the file
result = doc_manager.ingest_file(Path(file_path))
@@ -1571,7 +1777,8 @@ def md_get_command(ctx, file_path, output):
config = ctx.obj or {}
try:
# Initialize document manager
- doc_manager = DocumentManager(config.get('db_manager'))
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(config.get('db_manager'))
# Get file information
result = doc_manager.get_file(file_path)
@@ -1620,7 +1827,8 @@ def md_list_command(ctx, output_format, names_only):
config = ctx.obj or {}
try:
# Initialize document manager
- doc_manager = DocumentManager(config.get('db_manager'))
+ from markitect.clean_document_manager import CleanDocumentManager
+ doc_manager = CleanDocumentManager(config.get('db_manager'))
# Get file listing
files = doc_manager.list_files()
@@ -1654,8 +1862,8 @@ def md_list_command(ctx, output_format, names_only):
@click.argument('input_file', type=click.Path(exists=True))
@click.option('--output', '-o', type=click.Path(),
help='Output HTML file (default: .html)')
-@click.option('--template', type=click.Choice(['basic', 'github', 'dark', 'academic']),
- help='Built-in template theme (basic, github, dark, academic)')
+@click.option('--theme', type=ThemeType(),
+ help='Theme(s) to apply. Single: dark or layered: dark,academic or light,github,corporate. Available: basic, github, dark, academic, light, corporate, startup')
@click.option('--css', type=click.Path(),
help='Custom CSS file to include')
@click.option('--edit', is_flag=True,
@@ -1670,22 +1878,28 @@ def md_list_command(ctx, output_format, names_only):
@click.option('--dont-use-publication-dir', is_flag=True,
help='Don\'t use publication directory for output')
@click.pass_context
-def md_render_command(ctx, input_file, output, template, css, edit, editor_theme,
+def md_render_command(ctx, input_file, output, theme, css, edit, editor_theme,
keyboard_shortcuts, use_publication_dir, dont_use_publication_dir):
"""
Render a markdown file to HTML with basic templates and live preview capabilities.
- Converts a markdown file to HTML using customizable templates and styles.
+ Converts a markdown file to HTML using customizable layered themes and styles.
Supports live editing mode with real-time preview and syntax highlighting.
- Choose from basic, github, dark, or academic themes for professional output.
+
+ Theme Layering:
+ - Single themes: basic, github, dark, academic, light, corporate, startup
+ - Layered themes: dark,academic combines dark UI with academic typography
+ - Later themes override settings from earlier themes
INPUT_FILE: Path to the markdown file to render
Examples:
markitect md-render README.md
- markitect md-render docs/guide.md --output guide.html --template github
+ markitect md-render docs/guide.md --output guide.html --theme github
markitect md-render draft.md --edit --editor-theme monokai
- markitect md-render doc.md --template dark --css custom.css
+ markitect md-render doc.md --theme dark --css custom.css
+ markitect md-render doc.md --theme dark,academic
+ markitect md-render doc.md --theme light,github,corporate
"""
config = ctx.obj or {}
@@ -1712,7 +1926,7 @@ def md_render_command(ctx, input_file, output, template, css, edit, editor_theme
if edit:
# Edit mode - generate HTML with editing capabilities
result = doc_manager.render_file(input_file, str(output_path),
- template=template, css=css,
+ template=theme, css=css,
edit_mode=True,
editor_theme=editor_theme,
keyboard_shortcuts=keyboard_shortcuts)
@@ -1722,16 +1936,16 @@ def md_render_command(ctx, input_file, output, template, css, edit, editor_theme
if config.get('verbose', False):
click.echo(f"Editor theme: {editor_theme}")
click.echo(f"Keyboard shortcuts: {'enabled' if keyboard_shortcuts else 'disabled'}")
- click.echo(f"Template: {template or 'default'}")
+ click.echo(f"Theme: {theme or 'default'}")
click.echo(f"CSS: {css or 'default'}")
else:
# Static render
result = doc_manager.render_file(input_file, str(output_path),
- template=template, css=css)
+ template=theme, css=css)
click.echo(f"✓ Rendered to: {output_path}")
if config.get('verbose', False):
- click.echo(f"Template: {template or 'default'}")
+ click.echo(f"Theme: {theme or 'default'}")
click.echo(f"CSS: {css or 'default'}")
except Exception as e:
@@ -1743,12 +1957,12 @@ def md_render_command(ctx, input_file, output, template, css, edit, editor_theme
@click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option('--output', '-o', type=click.Path(),
help='Output index file (default: /index.html)')
-@click.option('--template', type=click.Choice(['basic', 'github', 'dark', 'academic']),
- help='Built-in template theme for index')
+@click.option('--theme', type=ThemeType(),
+ help='Theme(s) to apply to index. Single: dark or layered: dark,github. Available: basic, github, dark, academic, light, corporate, startup')
@click.option('--recursive', '-r', is_flag=True,
help='Include subdirectories recursively')
@click.pass_context
-def md_index_command(ctx, directory, output, template, recursive):
+def md_index_command(ctx, directory, output, theme, recursive):
"""
Generate an index page for HTML files in a directory.
@@ -1800,7 +2014,7 @@ def md_index_command(ctx, directory, output, template, recursive):
index_title = f"Index - {dir_path.name}"
# Generate HTML content
- html_content = generate_index_html(file_info_list, index_title, template)
+ html_content = generate_index_html(file_info_list, index_title, theme)
# Write index file
output_path.parent.mkdir(parents=True, exist_ok=True)
diff --git a/tests/test_issue_132_cli_integration.py b/tests/test_issue_132_cli_integration.py
index 93f0d010..07b1b38b 100644
--- a/tests/test_issue_132_cli_integration.py
+++ b/tests/test_issue_132_cli_integration.py
@@ -93,7 +93,7 @@ markitect md-render input.md --output result.html
'md-render',
str(input_file),
'--output', str(output_file),
- '--template', 'github'
+ '--theme', 'github'
])
assert result.exit_code == 0
@@ -139,7 +139,7 @@ markitect md-render input.md --output result.html
assert 'markdown' in result.output.lower()
assert 'html' in result.output.lower()
assert '--output' in result.output
- assert '--template' in result.output
+ assert '--theme' in result.output
assert 'basic' in result.output
assert 'github' in result.output
assert 'dark' in result.output
@@ -176,12 +176,14 @@ markitect md-render input.md --output result.html
'md-render',
str(input_file),
'--output', str(output_file),
- '--template', 'invalid_template_name'
+ '--theme', 'invalid_template_name'
])
# Should exit with error code (Click choice validation)
assert result.exit_code != 0
- assert 'invalid choice' in result.output.lower() or 'not one of' in result.output.lower()
+ assert ('invalid choice' in result.output.lower() or
+ 'not one of' in result.output.lower() or
+ 'unknown theme' in result.output.lower())
def test_output_directory_creation(self):
"""Test that output directory is created if it doesn't exist - Issue #132."""
diff --git a/tests/test_issue_132_template_system.py b/tests/test_issue_132_template_system.py
index f155800d..a2a43da9 100644
--- a/tests/test_issue_132_template_system.py
+++ b/tests/test_issue_132_template_system.py
@@ -85,7 +85,7 @@ This is a test document for template system validation.
'md-render',
str(input_file),
'--output', str(output_file),
- '--template', 'github'
+ '--theme', 'github'
])
assert result.exit_code == 0
@@ -262,7 +262,7 @@ This is a test document for template system validation.
def test_multiple_templates_available(self):
"""Test that multiple template options are available - Issue #132."""
# Test template availability
- template_options = ['basic', 'github', 'academic', 'dark']
+ theme_options = ['basic', 'github', 'academic', 'dark']
from markitect.plugins.builtin.markdown_commands import md_render_command
from click.testing import CliRunner
@@ -273,13 +273,13 @@ This is a test document for template system validation.
runner = CliRunner()
- for template in template_options:
- output_file = Path(self.temp_dir) / f"{template}_output.html"
+ for theme in theme_options:
+ output_file = Path(self.temp_dir) / f"{theme}_output.html"
result = runner.invoke(md_render_command, [
str(input_file),
'--output', str(output_file),
- '--template', template
+ '--theme', theme
])
# Should be able to specify different templates
@@ -304,7 +304,7 @@ This is a test document for template system validation.
result = runner.invoke(md_render_command, [
str(input_file),
'--output', str(output_file),
- '--template', 'dark'
+ '--theme', 'dark'
])
assert result.exit_code == 0
@@ -332,12 +332,14 @@ This is a test document for template system validation.
result = runner.invoke(cli, [
'md-render',
str(input_file),
- '--template', 'nonexistent_template'
+ '--theme', 'nonexistent_template'
])
# Should exit with error code for invalid template choice
assert result.exit_code != 0
- assert 'invalid choice' in result.output.lower() or 'not one of' in result.output.lower()
+ assert ('invalid choice' in result.output.lower() or
+ 'not one of' in result.output.lower() or
+ 'unknown theme' in result.output.lower())
def test_template_title_extraction_from_markdown(self):
"""Test title extraction from markdown for template variables - Issue #132."""
diff --git a/tests/test_issue_133_cli_integration.py b/tests/test_issue_133_cli_integration.py
index 3460a03b..dde09ca1 100644
--- a/tests/test_issue_133_cli_integration.py
+++ b/tests/test_issue_133_cli_integration.py
@@ -94,7 +94,7 @@ Content paragraph that should be editable.
'md-render',
str(input_file),
'--output', str(output_file),
- '--template', template,
+ '--theme', template,
'--edit'
])
@@ -145,7 +145,7 @@ Content paragraph that should be editable.
'md-render',
str(input_file),
'--output', str(output_file),
- '--template', 'github'
+ '--theme', 'github'
])
assert result.exit_code == 0
diff --git a/tests/test_issue_136_index_generation.py b/tests/test_issue_136_index_generation.py
index 0739b1ed..2f325cf1 100644
--- a/tests/test_issue_136_index_generation.py
+++ b/tests/test_issue_136_index_generation.py
@@ -410,10 +410,10 @@ class TestCLIIntegration:
assert result.returncode == 0
assert custom_output.exists()
- def test_md_index_command_with_template_option(self):
- """Test md-index command with template option."""
+ def test_md_index_command_with_theme_option(self):
+ """Test md-index command with theme option."""
result = subprocess.run(
- ["markitect", "md-index", str(self.test_dir), "--template", "github"],
+ ["markitect", "md-index", str(self.test_dir), "--theme", "github"],
capture_output=True,
text=True,
timeout=30