From 53cfb90237285172eed817ec69956fc77ac6e264 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 27 Oct 2025 22:11:51 +0100 Subject: [PATCH] feat: add themes list command to CLI for theme discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added `markitect themes` command to list all available themes - Supports multiple output formats: table (default), list, and json - Allows filtering by theme scope: ui, document, branding, or all - Shows key properties for each theme (colors, fonts, etc.) - Includes legacy theme mappings and usage examples - Enhances discoverability of the layered theme system Usage examples: - markitect themes - markitect themes --format json - markitect themes --scope ui - markitect themes --scope document --format list 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../plugins/builtin/markdown_commands.py | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/markitect/plugins/builtin/markdown_commands.py b/markitect/plugins/builtin/markdown_commands.py index 286cccdb..7a79c566 100644 --- a/markitect/plugins/builtin/markdown_commands.py +++ b/markitect/plugins/builtin/markdown_commands.py @@ -1708,6 +1708,7 @@ class MarkdownCommandsPlugin(CommandPlugin): 'md-get': md_get_command, 'md-list': md_list_command, 'md-render': md_render_command, + 'themes': themes_list_command, 'md-index': md_index_command, 'md-explode': md_explode_command, 'md-implode': md_implode_command, @@ -1959,6 +1960,104 @@ def md_render_command(ctx, input_file, output, theme, css, edit, editor_theme, raise click.Abort() +@click.command() +@click.option('--format', type=click.Choice(['table', 'list', 'json']), default='table', + help='Output format: table (default), list, or json') +@click.option('--scope', type=click.Choice(['ui', 'document', 'branding', 'all']), default='all', + help='Filter themes by scope: ui, document, branding, or all (default)') +def themes_list_command(format, scope): + """ + List all available themes and their properties. + + Shows the available themes that can be used with md-render and other commands. + Themes can be used individually or combined in layers. + + Examples: + markitect themes list + markitect themes list --format json + markitect themes list --scope ui + markitect themes list --scope document --format list + """ + from tabulate import tabulate + import json + + # Get theme data + layered_themes = [] + legacy_mappings = [] + + # Process layered themes + for theme_name, theme_data in LAYERED_THEMES.items(): + theme_scope = theme_data['scope'] + if scope == 'all' or scope == theme_scope: + properties = theme_data['properties'] + # Get key properties for display + key_props = [] + if 'body_background' in properties: + key_props.append(f"bg:{properties['body_background']}") + if 'font_family' in properties: + family = properties['font_family'].split(',')[0].strip().strip('"\'') + key_props.append(f"font:{family}") + if 'link_color' in properties: + key_props.append(f"links:{properties['link_color']}") + if 'accent_color' in properties: + key_props.append(f"accent:{properties['accent_color']}") + + layered_themes.append({ + 'name': theme_name, + 'scope': theme_scope, + 'properties': ', '.join(key_props) if key_props else 'default styling' + }) + + # Process legacy mappings + for legacy_name, expanded_themes in LEGACY_THEME_MAPPING.items(): + legacy_mappings.append({ + 'name': legacy_name, + 'expands_to': ' + '.join(expanded_themes) + }) + + if format == 'json': + # JSON output + output_data = { + 'layered_themes': layered_themes, + 'legacy_mappings': legacy_mappings, + 'usage': { + 'single': 'markitect md-render file.md --theme dark', + 'layered': 'markitect md-render file.md --theme dark,academic', + 'legacy': 'markitect md-render file.md --theme github' + } + } + click.echo(json.dumps(output_data, indent=2)) + + elif format == 'list': + # Simple list output + click.echo("Available themes:") + for theme in layered_themes: + click.echo(f" {theme['name']} ({theme['scope']})") + if legacy_mappings: + click.echo("\nLegacy mappings:") + for mapping in legacy_mappings: + click.echo(f" {mapping['name']} -> {mapping['expands_to']}") + + else: # table format (default) + # Table output + if layered_themes: + click.echo("Layered themes (can be combined):") + headers = ['Theme', 'Scope', 'Key Properties'] + table_data = [[t['name'], t['scope'], t['properties']] for t in layered_themes] + click.echo(tabulate(table_data, headers=headers, tablefmt='grid')) + + if legacy_mappings: + click.echo("\nLegacy theme mappings:") + headers = ['Legacy Name', 'Expands To'] + table_data = [[m['name'], m['expands_to']] for m in legacy_mappings] + click.echo(tabulate(table_data, headers=headers, tablefmt='grid')) + + click.echo("\nUsage examples:") + click.echo(" Single theme: markitect md-render file.md --theme dark") + click.echo(" Layered themes: markitect md-render file.md --theme dark,academic") + click.echo(" Legacy mapping: markitect md-render file.md --theme github") + + @click.command() @click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True)) @click.option('--output', '-o', type=click.Path(),