2025-09-24 01:14:27 +02:00
|
|
|
|
"""
|
|
|
|
|
|
Document manager for high-performance markdown file ingestion and AST caching.
|
|
|
|
|
|
|
|
|
|
|
|
This module implements the core functionality for Issue #2: Fast Document Loading & CLI Manipulation.
|
|
|
|
|
|
It provides performance-optimized document processing through AST caching and database integration.
|
|
|
|
|
|
|
|
|
|
|
|
Key Features:
|
|
|
|
|
|
- Parse once, access many times architecture
|
|
|
|
|
|
- AST cache loading < 50% of markdown parsing time
|
|
|
|
|
|
- Seamless integration with Issue #1 database foundation
|
|
|
|
|
|
- Comprehensive error handling and validation
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
|
import time
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
from typing import Dict, Any, Optional
|
|
|
|
|
|
|
|
|
|
|
|
from .parser import parse_markdown_to_ast
|
|
|
|
|
|
from .frontmatter import FrontMatterParser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DocumentManager:
|
|
|
|
|
|
"""
|
|
|
|
|
|
High-performance document manager for markdown file processing.
|
|
|
|
|
|
|
|
|
|
|
|
Implements the "parse once, manipulate many times" architecture by creating
|
|
|
|
|
|
fast-loading AST cache files alongside database metadata storage.
|
|
|
|
|
|
|
|
|
|
|
|
Architecture:
|
|
|
|
|
|
markdown file → AST parsing → cache file + database metadata
|
|
|
|
|
|
|
|
|
|
|
|
Performance Goal:
|
|
|
|
|
|
Cache loading must be < 50% of original parsing time
|
|
|
|
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
|
db_manager: Database manager for metadata storage
|
|
|
|
|
|
cache_dir: Directory for AST cache files
|
|
|
|
|
|
frontmatter_parser: YAML front matter processor
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, database_manager, cache_dir: Optional[Path] = None):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Initialize document manager with database and cache configuration.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
database_manager: DatabaseManager instance for metadata storage
|
|
|
|
|
|
cache_dir: Directory for AST cache files (default: .ast_cache)
|
|
|
|
|
|
"""
|
|
|
|
|
|
self.db_manager = database_manager
|
|
|
|
|
|
self.cache_dir = Path(cache_dir) if cache_dir else Path(".ast_cache")
|
|
|
|
|
|
self.cache_dir.mkdir(exist_ok=True)
|
|
|
|
|
|
self.frontmatter_parser = FrontMatterParser()
|
|
|
|
|
|
|
|
|
|
|
|
def ingest_file(self, file_path: Path) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Ingest a markdown file with performance-optimized AST caching.
|
|
|
|
|
|
|
|
|
|
|
|
Implements the core "parse once, manipulate many times" workflow:
|
|
|
|
|
|
1. Validates file existence
|
|
|
|
|
|
2. Parses markdown content to AST
|
|
|
|
|
|
3. Creates fast-loading AST cache file
|
|
|
|
|
|
4. Stores metadata in database
|
|
|
|
|
|
5. Returns processing results with performance metrics
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
file_path: Path to markdown file to ingest
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Dictionary containing:
|
|
|
|
|
|
- ast: Parsed AST representation
|
|
|
|
|
|
- metadata: File metadata (filename, title, etc.)
|
|
|
|
|
|
- ast_cache_path: Path to created cache file
|
|
|
|
|
|
- parse_time: Time spent parsing markdown (seconds)
|
|
|
|
|
|
- cache_time: Time spent creating cache (seconds)
|
|
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
|
FileNotFoundError: If the specified file doesn't exist
|
|
|
|
|
|
|
|
|
|
|
|
Performance:
|
|
|
|
|
|
Initial parse creates overhead, but subsequent cache loads
|
|
|
|
|
|
will be < 50% of this parse time.
|
|
|
|
|
|
"""
|
|
|
|
|
|
# Validate file exists
|
|
|
|
|
|
if not file_path.exists():
|
|
|
|
|
|
raise FileNotFoundError(f"File not found: {file_path}")
|
|
|
|
|
|
|
|
|
|
|
|
# Read file content
|
|
|
|
|
|
content = self._read_file_content(file_path)
|
|
|
|
|
|
|
|
|
|
|
|
# Parse front matter for metadata extraction
|
|
|
|
|
|
front_matter, markdown_content = self.frontmatter_parser.parse(content)
|
|
|
|
|
|
|
|
|
|
|
|
# Parse to AST with performance timing
|
|
|
|
|
|
ast, parse_time = self._parse_content_to_ast(content)
|
|
|
|
|
|
|
|
|
|
|
|
# Create cache file with performance timing
|
|
|
|
|
|
cache_file, cache_time = self._create_performance_cache(file_path.name, ast)
|
|
|
|
|
|
|
|
|
|
|
|
# Store in database (handles front matter parsing internally)
|
|
|
|
|
|
self._store_in_database(file_path.name, content)
|
|
|
|
|
|
|
|
|
|
|
|
# Return comprehensive result
|
|
|
|
|
|
return self._build_ingestion_result(
|
|
|
|
|
|
ast=ast,
|
|
|
|
|
|
filename=file_path.name,
|
|
|
|
|
|
front_matter=front_matter,
|
|
|
|
|
|
cache_file=cache_file,
|
|
|
|
|
|
parse_time=parse_time,
|
|
|
|
|
|
cache_time=cache_time
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def _read_file_content(self, file_path: Path) -> str:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Read file content with proper encoding.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
file_path: Path to file to read
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
File content as string
|
|
|
|
|
|
"""
|
|
|
|
|
|
return file_path.read_text(encoding='utf-8')
|
|
|
|
|
|
|
|
|
|
|
|
def _parse_content_to_ast(self, content: str) -> tuple[list, float]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Parse markdown content to AST with performance timing.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
content: Raw markdown content
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Tuple of (AST tokens, parse_time_seconds)
|
|
|
|
|
|
"""
|
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
ast = parse_markdown_to_ast(content)
|
|
|
|
|
|
parse_time = time.time() - start_time
|
|
|
|
|
|
return ast, parse_time
|
|
|
|
|
|
|
|
|
|
|
|
def _create_performance_cache(self, filename: str, ast: list) -> tuple[Path, float]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Create AST cache file with performance timing.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
filename: Source filename for cache naming
|
|
|
|
|
|
ast: AST tokens to cache
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Tuple of (cache_file_path, cache_time_seconds)
|
|
|
|
|
|
"""
|
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
cache_file = self._create_ast_cache(filename, ast)
|
|
|
|
|
|
cache_time = time.time() - start_time
|
|
|
|
|
|
return cache_file, cache_time
|
|
|
|
|
|
|
|
|
|
|
|
def _store_in_database(self, filename: str, content: str) -> None:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Store document in database using existing API.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
filename: Name of the file
|
|
|
|
|
|
content: Full markdown content (including front matter)
|
|
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
The database manager handles front matter parsing internally.
|
|
|
|
|
|
"""
|
|
|
|
|
|
self.db_manager.store_markdown_file(filename, content)
|
|
|
|
|
|
|
|
|
|
|
|
def _build_ingestion_result(self, ast: list, filename: str, front_matter: dict,
|
|
|
|
|
|
cache_file: Path, parse_time: float, cache_time: float) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Build comprehensive ingestion result dictionary.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
ast: Parsed AST tokens
|
|
|
|
|
|
filename: Source filename
|
|
|
|
|
|
front_matter: Parsed front matter metadata
|
|
|
|
|
|
cache_file: Path to created cache file
|
|
|
|
|
|
parse_time: Time spent parsing (seconds)
|
|
|
|
|
|
cache_time: Time spent caching (seconds)
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Structured result dictionary with all ingestion data
|
|
|
|
|
|
"""
|
|
|
|
|
|
return {
|
|
|
|
|
|
'ast': ast,
|
|
|
|
|
|
'metadata': {
|
|
|
|
|
|
'filename': filename,
|
|
|
|
|
|
'title': front_matter.get('title', ''),
|
|
|
|
|
|
},
|
|
|
|
|
|
'ast_cache_path': cache_file,
|
|
|
|
|
|
'parse_time': parse_time,
|
|
|
|
|
|
'cache_time': cache_time
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def _create_ast_cache(self, filename: str, ast: list) -> Path:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Create AST cache file in JSON format.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
filename: Source filename for cache naming
|
|
|
|
|
|
ast: AST tokens to serialize
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Path to created cache file
|
|
|
|
|
|
"""
|
|
|
|
|
|
cache_filename = f"{filename}.ast.json"
|
|
|
|
|
|
cache_path = self.cache_dir / cache_filename
|
|
|
|
|
|
|
|
|
|
|
|
with open(cache_path, 'w', encoding='utf-8') as f:
|
|
|
|
|
|
json.dump(ast, f, indent=2, ensure_ascii=False)
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
return cache_path
|
|
|
|
|
|
|
|
|
|
|
|
def list_files(self) -> list:
|
|
|
|
|
|
"""
|
|
|
|
|
|
List all markdown files in the system.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
List of dictionaries containing file metadata including filename,
|
|
|
|
|
|
size, and modification date information.
|
|
|
|
|
|
"""
|
|
|
|
|
|
# Get files from database
|
|
|
|
|
|
db_files = self.db_manager.list_markdown_files()
|
|
|
|
|
|
|
|
|
|
|
|
# Enhance with file system information
|
|
|
|
|
|
enhanced_files = []
|
|
|
|
|
|
for file_info in db_files:
|
|
|
|
|
|
enhanced_info = {
|
|
|
|
|
|
'filename': file_info['filename'],
|
|
|
|
|
|
'id': file_info['id'],
|
|
|
|
|
|
'created_at': file_info['created_at'],
|
|
|
|
|
|
'front_matter': file_info['front_matter']
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Try to get file system stats if file exists
|
|
|
|
|
|
try:
|
|
|
|
|
|
file_path = Path(file_info['filename'])
|
|
|
|
|
|
if file_path.exists():
|
|
|
|
|
|
stat = file_path.stat()
|
|
|
|
|
|
enhanced_info['size'] = f"{stat.st_size} bytes"
|
|
|
|
|
|
enhanced_info['modified'] = stat.st_mtime
|
|
|
|
|
|
else:
|
|
|
|
|
|
enhanced_info['size'] = 'unknown'
|
|
|
|
|
|
enhanced_info['modified'] = 'file not found'
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
enhanced_info['size'] = 'unknown'
|
|
|
|
|
|
enhanced_info['modified'] = 'unknown'
|
|
|
|
|
|
|
|
|
|
|
|
enhanced_files.append(enhanced_info)
|
|
|
|
|
|
|
|
|
|
|
|
return enhanced_files
|
|
|
|
|
|
|
2025-10-13 20:26:08 +02:00
|
|
|
|
def get_file(self, file_path: str) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Retrieve a markdown file from the database.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
file_path: Path to the markdown file to retrieve
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Dictionary containing file content and metadata
|
|
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
|
FileNotFoundError: If file is not found in database
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not self.db_manager:
|
|
|
|
|
|
raise ValueError("Database manager not initialized")
|
|
|
|
|
|
|
|
|
|
|
|
# Get file from database
|
|
|
|
|
|
file_data = self.db_manager.get_markdown_file(file_path)
|
|
|
|
|
|
|
|
|
|
|
|
if file_data is None:
|
|
|
|
|
|
raise FileNotFoundError(f"File '{file_path}' not found in database")
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
'content': file_data.get('content', ''),
|
|
|
|
|
|
'metadata': {
|
|
|
|
|
|
'filename': file_data.get('filename', file_path),
|
|
|
|
|
|
'front_matter': file_data.get('front_matter'),
|
|
|
|
|
|
'size': len(file_data.get('content', '')),
|
|
|
|
|
|
'modified': file_data.get('modified')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
def render_file(self, input_file: str, output_file: str, template: str = None, css: str = None,
|
|
|
|
|
|
edit_mode: bool = False, editor_theme: str = 'github', keyboard_shortcuts: bool = True) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Render a markdown file to HTML with client-side rendering capabilities.
|
|
|
|
|
|
|
|
|
|
|
|
Creates an HTML file with embedded markdown content that is rendered
|
|
|
|
|
|
client-side using JavaScript markdown parser.
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
input_file: Path to input markdown file
|
|
|
|
|
|
output_file: Path to output HTML file
|
|
|
|
|
|
template: Template to use (optional)
|
|
|
|
|
|
css: CSS file to include (optional)
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Dictionary with rendering results and metadata
|
|
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
|
FileNotFoundError: If input file doesn't exist
|
|
|
|
|
|
"""
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
input_path = Path(input_file)
|
|
|
|
|
|
output_path = Path(output_file)
|
|
|
|
|
|
|
|
|
|
|
|
# Validate input file exists
|
|
|
|
|
|
if not input_path.exists():
|
|
|
|
|
|
raise FileNotFoundError(f"Input file not found: {input_path}")
|
|
|
|
|
|
|
|
|
|
|
|
# Read markdown content
|
|
|
|
|
|
markdown_content = input_path.read_text(encoding='utf-8')
|
|
|
|
|
|
|
|
|
|
|
|
# Extract title from markdown (first h1 heading)
|
|
|
|
|
|
title = self._extract_title_from_markdown(markdown_content)
|
|
|
|
|
|
|
|
|
|
|
|
# Generate HTML content
|
|
|
|
|
|
html_content = self._generate_html_template(
|
|
|
|
|
|
markdown_content=markdown_content,
|
|
|
|
|
|
title=title,
|
|
|
|
|
|
css=css,
|
|
|
|
|
|
template=template,
|
|
|
|
|
|
edit_mode=edit_mode,
|
|
|
|
|
|
editor_theme=editor_theme,
|
|
|
|
|
|
keyboard_shortcuts=keyboard_shortcuts
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Write HTML file
|
|
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
output_path.write_text(html_content, encoding='utf-8')
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
'input_file': str(input_path),
|
|
|
|
|
|
'output_file': str(output_path),
|
|
|
|
|
|
'title': title,
|
|
|
|
|
|
'template': template,
|
|
|
|
|
|
'css': css
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def _extract_title_from_markdown(self, content: str) -> str:
|
|
|
|
|
|
"""Extract title from markdown content (first h1 heading)."""
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
|
|
# Look for first h1 heading
|
|
|
|
|
|
match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
|
|
|
|
|
|
if match:
|
|
|
|
|
|
return match.group(1).strip()
|
|
|
|
|
|
return "Markdown Document"
|
|
|
|
|
|
|
|
|
|
|
|
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) -> str:
|
|
|
|
|
|
"""Generate HTML template with embedded markdown and client-side rendering."""
|
|
|
|
|
|
import json
|
2025-10-25 20:37:32 +02:00
|
|
|
|
from pathlib import Path
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
|
|
|
|
|
|
# Escape the markdown content for JavaScript
|
|
|
|
|
|
js_markdown_content = json.dumps(markdown_content)
|
|
|
|
|
|
|
|
|
|
|
|
# Handle CSS styles
|
|
|
|
|
|
css_content = ""
|
|
|
|
|
|
if css:
|
|
|
|
|
|
# Try to read CSS file content and embed it
|
|
|
|
|
|
try:
|
|
|
|
|
|
css_path = Path(css)
|
|
|
|
|
|
if css_path.exists():
|
|
|
|
|
|
css_file_content = css_path.read_text(encoding='utf-8')
|
|
|
|
|
|
css_content = f"<style>\n{css_file_content}\n</style>"
|
|
|
|
|
|
else:
|
|
|
|
|
|
# Fallback to link if file doesn't exist
|
|
|
|
|
|
css_content = f'<link rel="stylesheet" href="{css}">'
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
# Fallback to link on any error
|
|
|
|
|
|
css_content = f'<link rel="stylesheet" href="{css}">'
|
|
|
|
|
|
|
|
|
|
|
|
# Get template-specific CSS
|
|
|
|
|
|
template_css = self._get_template_css(template)
|
|
|
|
|
|
|
|
|
|
|
|
# Default CSS for basic styling
|
|
|
|
|
|
default_css = f"""
|
|
|
|
|
|
<style>
|
|
|
|
|
|
{template_css}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# Add editor-specific content if in edit mode
|
|
|
|
|
|
editor_scripts = ""
|
|
|
|
|
|
editor_config = ""
|
|
|
|
|
|
editor_css = ""
|
|
|
|
|
|
body_classes = ""
|
|
|
|
|
|
|
|
|
|
|
|
if edit_mode:
|
|
|
|
|
|
body_classes = ' class="markitect-edit-mode"'
|
|
|
|
|
|
editor_css = """
|
|
|
|
|
|
<style>
|
2025-10-25 20:55:45 +02:00
|
|
|
|
/* Floating Control Panel - Slide-in from right */
|
|
|
|
|
|
.markitect-control-panel {
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
position: fixed;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
top: 20px;
|
|
|
|
|
|
right: -320px;
|
|
|
|
|
|
width: 320px;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.98);
|
|
|
|
|
|
border: 1px solid #e0e0e0;
|
|
|
|
|
|
border-radius: 12px 0 0 12px;
|
|
|
|
|
|
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
z-index: 1000;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
backdrop-filter: blur(10px);
|
|
|
|
|
|
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-panel.expanded {
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 21:08:39 +02:00
|
|
|
|
.markitect-control-panel.expanded .markitect-control-ribbon {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 20:55:45 +02:00
|
|
|
|
/* Control ribbon - always visible */
|
|
|
|
|
|
.markitect-control-ribbon {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: -40px;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: linear-gradient(135deg, #2196f3, #1976d2);
|
|
|
|
|
|
border-radius: 8px 0 0 8px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
font-size: 18px;
|
2025-10-25 21:08:39 +02:00
|
|
|
|
transition: all 0.3s ease, opacity 0.3s ease;
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
pointer-events: auto;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-ribbon:hover {
|
|
|
|
|
|
background: linear-gradient(135deg, #1976d2, #1565c0);
|
|
|
|
|
|
transform: translateX(-2px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Panel content */
|
|
|
|
|
|
.markitect-panel-header {
|
|
|
|
|
|
background: linear-gradient(135deg, #2196f3, #1976d2);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
border-radius: 12px 0 0 0;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-panel-title {
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
margin: 0 0 4px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-panel-version {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-panel-close {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 12px;
|
|
|
|
|
|
right: 16px;
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
padding: 4px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
transition: background 0.2s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-panel-close:hover {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-panel-body {
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-section {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-indicator {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
border-left: 4px solid #4caf50;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-indicator.loading {
|
|
|
|
|
|
border-left-color: #ff9800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-indicator.error {
|
|
|
|
|
|
border-left-color: #f44336;
|
|
|
|
|
|
background: #ffebee;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-icon {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-status-text {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-controls-section {
|
|
|
|
|
|
border-top: 1px solid #e0e0e0;
|
|
|
|
|
|
padding-top: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-controls-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-btn {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
background: #2196f3;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
transition: all 0.2s;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-btn:hover {
|
|
|
|
|
|
background: #1976d2;
|
|
|
|
|
|
transform: translateY(-1px);
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
2025-10-25 20:55:45 +02:00
|
|
|
|
|
|
|
|
|
|
.markitect-control-btn.secondary {
|
|
|
|
|
|
background: #757575;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-btn.secondary:hover {
|
|
|
|
|
|
background: #616161;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-control-btn .icon {
|
|
|
|
|
|
margin-right: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-save-info {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-error-details {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
background: #ffebee;
|
|
|
|
|
|
border: 1px solid #f44336;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-error-title {
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #c62828;
|
|
|
|
|
|
margin: 0 0 8px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-error-text {
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
margin: 0 0 8px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-error-help {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Content editing styles */
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
.markitect-section-editable {
|
|
|
|
|
|
border: 1px dashed transparent;
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
margin: 4px 0;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
cursor: pointer;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
transition: all 0.2s ease;
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
2025-10-25 20:55:45 +02:00
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
.markitect-section-editable:hover {
|
|
|
|
|
|
border-color: #007acc;
|
|
|
|
|
|
background: rgba(0, 122, 204, 0.05);
|
|
|
|
|
|
}
|
2025-10-25 20:55:45 +02:00
|
|
|
|
|
2025-10-25 21:35:53 +02:00
|
|
|
|
.markitect-section-editable[data-edited] {
|
|
|
|
|
|
border-color: rgba(76, 175, 80, 0.3);
|
|
|
|
|
|
background: rgba(76, 175, 80, 0.02);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.markitect-section-editable[data-edited]:hover {
|
|
|
|
|
|
border-color: #4caf50;
|
|
|
|
|
|
background: rgba(76, 175, 80, 0.08);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
.edit-mode textarea {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
min-height: 100px;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
border: 2px solid #007acc;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.edit-mode textarea:focus {
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
border-color: #1976d2;
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Responsive adjustments */
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.markitect-control-panel {
|
|
|
|
|
|
width: 280px;
|
|
|
|
|
|
right: -280px;
|
|
|
|
|
|
}
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
</style>"""
|
|
|
|
|
|
|
|
|
|
|
|
editor_config = f"""
|
|
|
|
|
|
const MARKITECT_EDIT_MODE = true;
|
|
|
|
|
|
const MARKITECT_EDITOR_CONFIG = {{
|
|
|
|
|
|
theme: '{editor_theme}',
|
|
|
|
|
|
keyboardShortcuts: {str(keyboard_shortcuts).lower()},
|
|
|
|
|
|
autosave: true,
|
|
|
|
|
|
sections: true
|
|
|
|
|
|
}};"""
|
|
|
|
|
|
|
|
|
|
|
|
editor_scripts = """
|
|
|
|
|
|
class MarkitectEditor {
|
|
|
|
|
|
constructor() {
|
2025-10-25 21:15:48 +02:00
|
|
|
|
this.hasEdits = false; // Track if any edits have been made
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
this.initializeEditor();
|
|
|
|
|
|
this.setupKeyboardShortcuts();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
initializeEditor() {
|
2025-10-25 20:55:45 +02:00
|
|
|
|
// Control panel is already in HTML, just make content editable
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
this.makeContentEditable();
|
2025-10-25 20:55:45 +02:00
|
|
|
|
|
|
|
|
|
|
// Auto-expand control panel briefly to show it's available
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
const panel = document.getElementById('markitect-control-panel');
|
|
|
|
|
|
if (panel) {
|
|
|
|
|
|
panel.classList.add('expanded');
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
panel.classList.remove('expanded');
|
|
|
|
|
|
}, 2000); // Show for 2 seconds then minimize
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 1000);
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
makeContentEditable() {
|
|
|
|
|
|
const content = document.getElementById('markdown-content');
|
|
|
|
|
|
if (content) {
|
|
|
|
|
|
content.addEventListener('click', this.handleSectionClick.bind(this));
|
|
|
|
|
|
this.markSections(content);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
markSections(element) {
|
2025-10-25 21:23:34 +02:00
|
|
|
|
// Clear existing section markers (except edited ones)
|
|
|
|
|
|
const existingSections = element.querySelectorAll('.markitect-section-editable:not([data-edited])');
|
|
|
|
|
|
existingSections.forEach(section => {
|
|
|
|
|
|
section.classList.remove('markitect-section-editable');
|
|
|
|
|
|
section.removeAttribute('data-section');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Mark new sections (skip elements inside edited wrappers)
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
const sections = element.querySelectorAll('h1, h2, h3, h4, h5, h6, p, blockquote, pre, ul, ol');
|
2025-10-25 21:23:34 +02:00
|
|
|
|
let sectionIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
sections.forEach((section) => {
|
|
|
|
|
|
// Skip if this element is inside an edited wrapper
|
|
|
|
|
|
if (section.closest('[data-edited]')) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Skip if already marked as edited wrapper
|
|
|
|
|
|
if (section.hasAttribute('data-edited')) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
section.classList.add('markitect-section-editable');
|
2025-10-25 21:23:34 +02:00
|
|
|
|
section.setAttribute('data-section', sectionIndex++);
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
handleSectionClick(event) {
|
|
|
|
|
|
const section = event.target.closest('.markitect-section-editable');
|
|
|
|
|
|
if (section && !section.querySelector('textarea')) {
|
|
|
|
|
|
this.editSection(section);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
editSection(section) {
|
|
|
|
|
|
const originalContent = section.innerHTML;
|
|
|
|
|
|
const textarea = document.createElement('textarea');
|
|
|
|
|
|
textarea.value = this.htmlToMarkdown(originalContent);
|
|
|
|
|
|
textarea.className = 'edit-mode';
|
|
|
|
|
|
|
|
|
|
|
|
textarea.addEventListener('blur', () => {
|
2025-10-25 21:15:48 +02:00
|
|
|
|
this.hasEdits = true; // Mark that edits have been made
|
2025-10-25 21:23:34 +02:00
|
|
|
|
|
2025-10-25 21:35:53 +02:00
|
|
|
|
// Check if the content contains paragraph breaks that should create separate sections
|
|
|
|
|
|
const content = textarea.value.trim();
|
|
|
|
|
|
const paragraphs = content.split(/\\n\\s*\\n/).filter(p => p.trim());
|
|
|
|
|
|
|
|
|
|
|
|
if (paragraphs.length > 1) {
|
|
|
|
|
|
// Multiple paragraphs - create separate sections
|
|
|
|
|
|
const parentNode = section.parentNode;
|
|
|
|
|
|
const sectionIndex = section.getAttribute('data-section');
|
2025-10-25 21:41:59 +02:00
|
|
|
|
const nextSibling = section.nextSibling; // Remember position
|
2025-10-25 21:35:53 +02:00
|
|
|
|
|
|
|
|
|
|
// Remove the original section
|
|
|
|
|
|
parentNode.removeChild(section);
|
|
|
|
|
|
|
2025-10-25 21:41:59 +02:00
|
|
|
|
// Create separate sections for each paragraph and insert at correct position
|
2025-10-25 21:35:53 +02:00
|
|
|
|
paragraphs.forEach((paragraph, index) => {
|
|
|
|
|
|
const wrapper = document.createElement('div');
|
|
|
|
|
|
wrapper.innerHTML = marked.parse(paragraph.trim());
|
|
|
|
|
|
wrapper.classList.add('markitect-section-editable');
|
|
|
|
|
|
wrapper.setAttribute('data-section', sectionIndex + '_' + index);
|
|
|
|
|
|
wrapper.setAttribute('data-edited', 'true');
|
|
|
|
|
|
|
2025-10-25 21:41:59 +02:00
|
|
|
|
// Insert at the correct position (before nextSibling)
|
|
|
|
|
|
parentNode.insertBefore(wrapper, nextSibling);
|
2025-10-25 21:35:53 +02:00
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Single content block - create one wrapper
|
|
|
|
|
|
const wrapper = document.createElement('div');
|
|
|
|
|
|
wrapper.innerHTML = marked.parse(content);
|
|
|
|
|
|
wrapper.classList.add('markitect-section-editable');
|
|
|
|
|
|
wrapper.setAttribute('data-section', section.getAttribute('data-section'));
|
|
|
|
|
|
wrapper.setAttribute('data-edited', 'true');
|
|
|
|
|
|
|
|
|
|
|
|
// Replace the section with the wrapper
|
|
|
|
|
|
section.parentNode.replaceChild(wrapper, section);
|
|
|
|
|
|
}
|
2025-10-25 21:23:34 +02:00
|
|
|
|
|
|
|
|
|
|
// Re-mark sections in the entire document, but skip edited wrappers
|
|
|
|
|
|
this.markSections(document.getElementById('markdown-content'));
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
section.innerHTML = '';
|
|
|
|
|
|
section.appendChild(textarea);
|
|
|
|
|
|
textarea.focus();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
htmlToMarkdown(html) {
|
2025-10-25 21:35:53 +02:00
|
|
|
|
// Create a temporary element to parse the HTML
|
|
|
|
|
|
const temp = document.createElement('div');
|
|
|
|
|
|
temp.innerHTML = html;
|
|
|
|
|
|
|
|
|
|
|
|
// Better HTML to Markdown conversion that preserves structure
|
|
|
|
|
|
let markdown = '';
|
|
|
|
|
|
|
|
|
|
|
|
const processNode = (node) => {
|
|
|
|
|
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
|
|
|
|
return node.textContent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
|
|
|
|
const tagName = node.tagName.toLowerCase();
|
|
|
|
|
|
const childText = Array.from(node.childNodes).map(processNode).join('');
|
|
|
|
|
|
|
|
|
|
|
|
switch (tagName) {
|
|
|
|
|
|
case 'h1': return '# ' + childText;
|
|
|
|
|
|
case 'h2': return '## ' + childText;
|
|
|
|
|
|
case 'h3': return '### ' + childText;
|
|
|
|
|
|
case 'h4': return '#### ' + childText;
|
|
|
|
|
|
case 'h5': return '##### ' + childText;
|
|
|
|
|
|
case 'h6': return '###### ' + childText;
|
|
|
|
|
|
case 'p': return childText;
|
|
|
|
|
|
case 'strong': case 'b': return '**' + childText + '**';
|
|
|
|
|
|
case 'em': case 'i': return '*' + childText + '*';
|
|
|
|
|
|
case 'code': return '`' + childText + '`';
|
|
|
|
|
|
case 'blockquote': return '> ' + childText;
|
|
|
|
|
|
case 'br': return '\\n';
|
|
|
|
|
|
default: return childText;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Process each child node and add appropriate spacing
|
|
|
|
|
|
Array.from(temp.childNodes).forEach((node, index) => {
|
|
|
|
|
|
const result = processNode(node);
|
|
|
|
|
|
if (result.trim()) {
|
|
|
|
|
|
if (index > 0) markdown += '\\n\\n';
|
|
|
|
|
|
markdown += result;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return markdown.trim();
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setupKeyboardShortcuts() {
|
|
|
|
|
|
if (MARKITECT_EDITOR_CONFIG.keyboardShortcuts) {
|
|
|
|
|
|
document.addEventListener('keydown', (event) => {
|
|
|
|
|
|
if (event.ctrlKey || event.metaKey) {
|
|
|
|
|
|
switch(event.key) {
|
|
|
|
|
|
case 's':
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
this.save();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'e':
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
this.togglePreview();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
save() {
|
2025-10-15 20:10:13 +02:00
|
|
|
|
try {
|
|
|
|
|
|
// Get the current markdown content from the editor
|
|
|
|
|
|
const markdownContent = this.getMarkdownContent();
|
|
|
|
|
|
|
|
|
|
|
|
// Create filename with timestamp suffix for backup convention
|
|
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const timestamp = now.toISOString().slice(0, 19).replace(/:/g, '-').replace('T', '-');
|
|
|
|
|
|
const originalFilename = window.location.pathname.split('/').pop().replace('.html', '.md');
|
|
|
|
|
|
const backupFilename = `${originalFilename.replace('.md', '')}-edited-${timestamp}.md`;
|
|
|
|
|
|
|
|
|
|
|
|
// Create and download the file
|
|
|
|
|
|
const blob = new Blob([markdownContent], { type: 'text/markdown' });
|
|
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
|
const a = document.createElement('a');
|
|
|
|
|
|
a.href = url;
|
|
|
|
|
|
a.download = backupFilename;
|
|
|
|
|
|
document.body.appendChild(a);
|
|
|
|
|
|
a.click();
|
|
|
|
|
|
document.body.removeChild(a);
|
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
|
|
|
|
|
|
|
// Update status with filename convention info
|
|
|
|
|
|
const statusEl = document.getElementById('save-status');
|
|
|
|
|
|
statusEl.textContent = `Downloaded: ${backupFilename}`;
|
|
|
|
|
|
statusEl.title = 'File saved with timestamp to avoid overwriting original';
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
statusEl.textContent = 'Ready';
|
|
|
|
|
|
statusEl.title = '';
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
document.getElementById('save-status').textContent = 'Save failed!';
|
|
|
|
|
|
console.error('Save error:', error);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
document.getElementById('save-status').textContent = 'Ready';
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
getMarkdownContent() {
|
2025-10-25 21:15:48 +02:00
|
|
|
|
// If no edits have been made, return the original markdown content
|
|
|
|
|
|
if (!this.hasEdits) {
|
|
|
|
|
|
return markdownContent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-15 20:10:13 +02:00
|
|
|
|
// Reconstruct markdown content from the current state of sections
|
|
|
|
|
|
const content = document.getElementById('markdown-content');
|
|
|
|
|
|
if (!content) {
|
|
|
|
|
|
return markdownContent; // fallback to original
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Simple approach: get the text content and convert back to markdown
|
|
|
|
|
|
// This is a basic implementation - could be enhanced for better preservation
|
|
|
|
|
|
const sections = content.querySelectorAll('.markitect-section-editable');
|
|
|
|
|
|
let reconstructed = '';
|
|
|
|
|
|
|
2025-10-25 16:46:47 +02:00
|
|
|
|
sections.forEach(section => {{
|
2025-10-25 21:23:34 +02:00
|
|
|
|
// Handle edited wrappers differently
|
|
|
|
|
|
if (section.hasAttribute('data-edited')) {{
|
|
|
|
|
|
// For edited sections, convert the child elements back to markdown
|
|
|
|
|
|
const childElements = section.children;
|
|
|
|
|
|
for (let i = 0; i < childElements.length; i++) {{
|
|
|
|
|
|
const child = childElements[i];
|
|
|
|
|
|
const tagName = child.tagName.toLowerCase();
|
|
|
|
|
|
const text = child.textContent.trim();
|
|
|
|
|
|
|
|
|
|
|
|
if (tagName.startsWith('h')) {{
|
|
|
|
|
|
const level = parseInt(tagName.charAt(1));
|
|
|
|
|
|
reconstructed += '#'.repeat(level) + ' ' + text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'p') {{
|
|
|
|
|
|
reconstructed += text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'blockquote') {{
|
|
|
|
|
|
reconstructed += '> ' + text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'pre') {{
|
|
|
|
|
|
reconstructed += '```\\n' + text + '\\n```\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'ul') {{
|
|
|
|
|
|
const items = child.querySelectorAll('li');
|
|
|
|
|
|
items.forEach(item => {{
|
|
|
|
|
|
reconstructed += '- ' + item.textContent.trim() + '\\n';
|
|
|
|
|
|
}});
|
|
|
|
|
|
reconstructed += '\\n';
|
|
|
|
|
|
}} else if (tagName === 'ol') {{
|
|
|
|
|
|
const items = child.querySelectorAll('li');
|
|
|
|
|
|
items.forEach((item, index) => {{
|
|
|
|
|
|
reconstructed += (index + 1) + '. ' + item.textContent.trim() + '\\n';
|
|
|
|
|
|
}});
|
|
|
|
|
|
reconstructed += '\\n';
|
|
|
|
|
|
}} else {{
|
|
|
|
|
|
reconstructed += text + '\\n\\n';
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
2025-10-25 16:46:47 +02:00
|
|
|
|
}} else {{
|
2025-10-25 21:23:34 +02:00
|
|
|
|
// Handle regular sections
|
|
|
|
|
|
const tagName = section.tagName.toLowerCase();
|
|
|
|
|
|
const text = section.textContent.trim();
|
|
|
|
|
|
|
|
|
|
|
|
if (tagName.startsWith('h')) {{
|
|
|
|
|
|
const level = parseInt(tagName.charAt(1));
|
|
|
|
|
|
reconstructed += '#'.repeat(level) + ' ' + text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'p') {{
|
|
|
|
|
|
reconstructed += text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'blockquote') {{
|
|
|
|
|
|
reconstructed += '> ' + text + '\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'pre') {{
|
|
|
|
|
|
reconstructed += '```\\n' + text + '\\n```\\n\\n';
|
|
|
|
|
|
}} else if (tagName === 'ul') {{
|
|
|
|
|
|
const items = section.querySelectorAll('li');
|
|
|
|
|
|
items.forEach(item => {{
|
|
|
|
|
|
reconstructed += '- ' + item.textContent.trim() + '\\n';
|
|
|
|
|
|
}});
|
|
|
|
|
|
reconstructed += '\\n';
|
|
|
|
|
|
}} else if (tagName === 'ol') {{
|
|
|
|
|
|
const items = section.querySelectorAll('li');
|
|
|
|
|
|
items.forEach((item, index) => {{
|
|
|
|
|
|
reconstructed += (index + 1) + '. ' + item.textContent.trim() + '\\n';
|
|
|
|
|
|
}});
|
|
|
|
|
|
reconstructed += '\\n';
|
|
|
|
|
|
}} else {{
|
|
|
|
|
|
reconstructed += text + '\\n\\n';
|
|
|
|
|
|
}}
|
2025-10-25 16:46:47 +02:00
|
|
|
|
}}
|
|
|
|
|
|
}});
|
2025-10-15 20:10:13 +02:00
|
|
|
|
|
|
|
|
|
|
return reconstructed.trim();
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
togglePreview() {
|
|
|
|
|
|
console.log('Toggle preview mode');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 20:55:45 +02:00
|
|
|
|
let markitectEditor;
|
|
|
|
|
|
|
|
|
|
|
|
// Control panel toggle functionality
|
|
|
|
|
|
function toggleControlPanel() {
|
|
|
|
|
|
const panel = document.getElementById('markitect-control-panel');
|
|
|
|
|
|
if (panel) {
|
|
|
|
|
|
panel.classList.toggle('expanded');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Auto-close panel when clicking outside
|
|
|
|
|
|
document.addEventListener('click', function(event) {
|
|
|
|
|
|
const panel = document.getElementById('markitect-control-panel');
|
|
|
|
|
|
if (panel && panel.classList.contains('expanded')) {
|
|
|
|
|
|
if (!panel.contains(event.target)) {
|
|
|
|
|
|
panel.classList.remove('expanded');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});"""
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
|
2025-10-15 00:55:46 +02:00
|
|
|
|
# Edit mode status and error reporting section
|
|
|
|
|
|
edit_mode_html = ""
|
|
|
|
|
|
if edit_mode:
|
2025-10-25 18:16:25 +02:00
|
|
|
|
# Get version info for header
|
|
|
|
|
|
try:
|
|
|
|
|
|
import markitect
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
|
|
# Get base version
|
|
|
|
|
|
version = "0.3.0" # fallback
|
|
|
|
|
|
try:
|
|
|
|
|
|
from importlib.metadata import version as get_version
|
|
|
|
|
|
version = get_version('markitect')
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
# Get git commit with timestamp and local changes info
|
|
|
|
|
|
git_info = ""
|
|
|
|
|
|
try:
|
|
|
|
|
|
repo_path = Path(__file__).parent.parent
|
|
|
|
|
|
|
|
|
|
|
|
# Get commit hash and timestamp
|
|
|
|
|
|
result = subprocess.run(['git', 'rev-parse', '--short', 'HEAD'],
|
|
|
|
|
|
capture_output=True, text=True, cwd=repo_path)
|
|
|
|
|
|
if result.returncode == 0:
|
|
|
|
|
|
commit_hash = result.stdout.strip()
|
|
|
|
|
|
|
|
|
|
|
|
# Get commit timestamp
|
|
|
|
|
|
timestamp_result = subprocess.run(['git', 'show', '-s', '--format=%ci', 'HEAD'],
|
|
|
|
|
|
capture_output=True, text=True, cwd=repo_path)
|
|
|
|
|
|
commit_time = ""
|
|
|
|
|
|
if timestamp_result.returncode == 0:
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
# Parse git timestamp and format it nicely
|
|
|
|
|
|
git_time = timestamp_result.stdout.strip()
|
|
|
|
|
|
try:
|
|
|
|
|
|
dt = datetime.fromisoformat(git_time.replace(' +', '+'))
|
|
|
|
|
|
commit_time = f" ({dt.strftime('%Y-%m-%d %H:%M')})"
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
git_info = f"+{commit_hash}{commit_time}"
|
|
|
|
|
|
|
|
|
|
|
|
# Check for uncommitted changes
|
|
|
|
|
|
status_result = subprocess.run(['git', 'status', '--porcelain'],
|
|
|
|
|
|
capture_output=True, text=True, cwd=repo_path)
|
|
|
|
|
|
if status_result.returncode == 0 and status_result.stdout.strip():
|
|
|
|
|
|
# Get timestamp of most recent uncommitted change
|
|
|
|
|
|
import os
|
|
|
|
|
|
import glob
|
|
|
|
|
|
|
|
|
|
|
|
latest_change = 0
|
|
|
|
|
|
for line in status_result.stdout.strip().split('\n'):
|
|
|
|
|
|
if line.strip():
|
|
|
|
|
|
# Extract filename (skip first 3 chars which are status indicators)
|
|
|
|
|
|
filename = line[3:].strip()
|
|
|
|
|
|
try:
|
|
|
|
|
|
file_path = repo_path / filename
|
|
|
|
|
|
if file_path.exists():
|
|
|
|
|
|
mtime = os.path.getmtime(file_path)
|
|
|
|
|
|
latest_change = max(latest_change, mtime)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
if latest_change > 0:
|
|
|
|
|
|
change_dt = datetime.fromtimestamp(latest_change)
|
|
|
|
|
|
git_info += f" including local changes until {change_dt.strftime('%Y-%m-%d %H:%M')}"
|
|
|
|
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
version_info = f"{version}{git_info}"
|
|
|
|
|
|
except:
|
|
|
|
|
|
version_info = "0.3.0"
|
|
|
|
|
|
|
2025-10-15 00:55:46 +02:00
|
|
|
|
edit_mode_html = f"""
|
2025-10-25 20:55:45 +02:00
|
|
|
|
<!-- Floating Control Panel -->
|
|
|
|
|
|
<div id="markitect-control-panel" class="markitect-control-panel">
|
|
|
|
|
|
<!-- Control Ribbon - Always Visible -->
|
|
|
|
|
|
<div class="markitect-control-ribbon" onclick="toggleControlPanel()" title="MarkiTect Editor Controls">
|
|
|
|
|
|
📝
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Panel Header -->
|
|
|
|
|
|
<div class="markitect-panel-header">
|
|
|
|
|
|
<h3 class="markitect-panel-title">📝 MarkiTect Editor</h3>
|
|
|
|
|
|
<p class="markitect-panel-version">v{version_info}</p>
|
|
|
|
|
|
<button class="markitect-panel-close" onclick="toggleControlPanel()" title="Close panel">×</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Panel Body -->
|
|
|
|
|
|
<div class="markitect-panel-body">
|
|
|
|
|
|
<!-- Status Section -->
|
|
|
|
|
|
<div class="markitect-status-section">
|
|
|
|
|
|
<div id="status-indicator" class="markitect-status-indicator loading">
|
|
|
|
|
|
<span class="markitect-status-icon">⏳</span>
|
|
|
|
|
|
<div class="markitect-status-text" id="status-message">Loading edit capabilities...</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Error Details (hidden by default) -->
|
|
|
|
|
|
<div id="error-details" class="markitect-error-details">
|
|
|
|
|
|
<div class="markitect-error-title">❌ Edit Mode Failed</div>
|
|
|
|
|
|
<div class="markitect-error-text" id="error-text"></div>
|
|
|
|
|
|
<div class="markitect-error-help">
|
|
|
|
|
|
📋 Browser: <span id="browser-info"></span><br>
|
|
|
|
|
|
🔗 <a href="https://github.com/anthropics/markitect/issues/new" target="_blank" style="color: #1976d2;">Report Issue</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Controls Section -->
|
|
|
|
|
|
<div class="markitect-controls-section">
|
|
|
|
|
|
<div class="markitect-controls-grid">
|
|
|
|
|
|
<button class="markitect-control-btn" onclick="markitectEditor.save()" title="Download edited content">
|
|
|
|
|
|
<span class="icon">💾</span>
|
|
|
|
|
|
Save & Download
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button class="markitect-control-btn secondary" onclick="markitectEditor.togglePreview()" title="Toggle preview mode">
|
|
|
|
|
|
<span class="icon">👁️</span>
|
|
|
|
|
|
Preview
|
|
|
|
|
|
</button>
|
2025-10-15 00:55:46 +02:00
|
|
|
|
</div>
|
2025-10-25 20:55:45 +02:00
|
|
|
|
|
|
|
|
|
|
<div class="markitect-save-info">
|
|
|
|
|
|
<div id="save-status">Ready to save</div>
|
|
|
|
|
|
<div style="margin-top: 4px; opacity: 0.8;">Saves as: filename-edited-YYYY-MM-DD-HH-MM-SS.md</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-15 00:55:46 +02:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>"""
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
html_template = f"""<!DOCTYPE html>
|
|
|
|
|
|
<html lang="en">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
|
<title>{title}</title>
|
|
|
|
|
|
{css_content}
|
|
|
|
|
|
{default_css}
|
|
|
|
|
|
{editor_css}
|
2025-10-15 00:55:46 +02:00
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"
|
|
|
|
|
|
onload="window.markitectMarkedLoaded = true"
|
|
|
|
|
|
onerror="window.markitectMarkedError = true"></script>
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
</head>
|
|
|
|
|
|
<body{body_classes}>
|
2025-10-15 00:55:46 +02:00
|
|
|
|
{edit_mode_html}
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
<div id="markdown-content"></div>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const markdownContent = {js_markdown_content};
|
|
|
|
|
|
{editor_config}
|
|
|
|
|
|
|
2025-10-15 01:06:03 +02:00
|
|
|
|
// Define editor class first (if in edit mode)
|
|
|
|
|
|
{editor_scripts if edit_mode else ''}
|
|
|
|
|
|
|
2025-10-25 16:53:09 +02:00
|
|
|
|
// Enhanced error reporting utility
|
|
|
|
|
|
function reportEditModeError(errorMsg, technicalDetails, errorType = 'error') {{
|
2025-10-15 00:55:46 +02:00
|
|
|
|
const statusDiv = document.getElementById('markitect-status');
|
|
|
|
|
|
const errorDiv = document.getElementById('error-details');
|
|
|
|
|
|
const errorText = document.getElementById('error-text');
|
|
|
|
|
|
const statusMsg = document.getElementById('status-message');
|
|
|
|
|
|
const browserInfo = document.getElementById('browser-info');
|
|
|
|
|
|
|
2025-10-25 16:53:09 +02:00
|
|
|
|
// Log to console for debugging
|
|
|
|
|
|
console.error('[MarkiTect Edit Mode Error]', errorMsg, technicalDetails);
|
|
|
|
|
|
|
|
|
|
|
|
// Create error report object
|
|
|
|
|
|
const errorReport = {{
|
|
|
|
|
|
timestamp: new Date().toISOString(),
|
|
|
|
|
|
error: errorMsg,
|
|
|
|
|
|
details: technicalDetails,
|
|
|
|
|
|
type: errorType,
|
|
|
|
|
|
userAgent: navigator.userAgent,
|
|
|
|
|
|
url: window.location.href,
|
|
|
|
|
|
markdownContent: typeof markdownContent !== 'undefined' ? markdownContent.length + ' chars' : 'unavailable'
|
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
|
|
// Store error for potential reporting
|
|
|
|
|
|
if (!window.markitectErrors) window.markitectErrors = [];
|
|
|
|
|
|
window.markitectErrors.push(errorReport);
|
|
|
|
|
|
|
|
|
|
|
|
// Update UI
|
|
|
|
|
|
if (statusMsg) {{
|
|
|
|
|
|
const statusText = errorType === 'warning'
|
|
|
|
|
|
? 'Edit mode partially available - some features may not work'
|
|
|
|
|
|
: 'Edit mode unavailable - content displayed in read-only mode';
|
|
|
|
|
|
statusMsg.textContent = statusText;
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
2025-10-15 00:55:46 +02:00
|
|
|
|
if (errorDiv) errorDiv.style.display = 'block';
|
2025-10-25 16:53:09 +02:00
|
|
|
|
if (errorText) {{
|
|
|
|
|
|
const fullError = errorMsg + (technicalDetails ? ' (' + technicalDetails + ')' : '');
|
|
|
|
|
|
errorText.textContent = fullError;
|
|
|
|
|
|
}}
|
2025-10-15 00:55:46 +02:00
|
|
|
|
if (browserInfo) browserInfo.textContent = navigator.userAgent.split(' ').slice(-2).join(' ');
|
2025-10-25 16:53:09 +02:00
|
|
|
|
|
|
|
|
|
|
// Auto-hide warnings after 10 seconds
|
|
|
|
|
|
if (errorType === 'warning' && errorDiv) {{
|
|
|
|
|
|
setTimeout(() => {{
|
|
|
|
|
|
errorDiv.style.display = 'none';
|
|
|
|
|
|
}}, 10000);
|
|
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
2025-10-15 00:55:46 +02:00
|
|
|
|
|
2025-10-15 01:06:03 +02:00
|
|
|
|
// Status update utility
|
|
|
|
|
|
function updateStatus(message, isError = false) {{
|
|
|
|
|
|
const statusMsg = document.getElementById('status-message');
|
2025-10-25 20:55:45 +02:00
|
|
|
|
const statusIndicator = document.getElementById('status-indicator');
|
|
|
|
|
|
const statusIcon = document.querySelector('.markitect-status-icon');
|
|
|
|
|
|
|
2025-10-15 01:06:03 +02:00
|
|
|
|
if (statusMsg) {{
|
|
|
|
|
|
statusMsg.textContent = message;
|
2025-10-25 20:55:45 +02:00
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
|
if (statusIndicator) {{
|
|
|
|
|
|
// Remove all status classes
|
|
|
|
|
|
statusIndicator.classList.remove('loading', 'error');
|
|
|
|
|
|
|
|
|
|
|
|
if (isError) {{
|
|
|
|
|
|
statusIndicator.classList.add('error');
|
|
|
|
|
|
if (statusIcon) statusIcon.textContent = '❌';
|
|
|
|
|
|
}} else if (message.includes('Loading') || message.includes('Initializing')) {{
|
|
|
|
|
|
statusIndicator.classList.add('loading');
|
|
|
|
|
|
if (statusIcon) statusIcon.textContent = '⏳';
|
|
|
|
|
|
}} else {{
|
|
|
|
|
|
// Success state
|
|
|
|
|
|
if (statusIcon) statusIcon.textContent = '✅';
|
|
|
|
|
|
}}
|
2025-10-15 01:06:03 +02:00
|
|
|
|
}}
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
2025-10-15 00:55:46 +02:00
|
|
|
|
// Always render content first (graceful degradation)
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {{
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus('Rendering content...');
|
|
|
|
|
|
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
const contentDiv = document.getElementById('markdown-content');
|
2025-10-15 00:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
// Step 1: Ensure content is always displayed
|
|
|
|
|
|
if (contentDiv) {{
|
|
|
|
|
|
if (typeof marked !== 'undefined') {{
|
|
|
|
|
|
try {{
|
|
|
|
|
|
contentDiv.innerHTML = marked.parse(markdownContent);
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus('Content rendered successfully ✓');
|
2025-10-15 00:55:46 +02:00
|
|
|
|
console.log('✓ Markdown rendered successfully');
|
|
|
|
|
|
}} catch (error) {{
|
|
|
|
|
|
contentDiv.innerHTML = '<p>Error rendering markdown: ' + error.message + '</p>';
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus('Content rendered with errors', true);
|
2025-10-15 00:55:46 +02:00
|
|
|
|
{'reportEditModeError("Markdown parsing failed", error.message);' if edit_mode else ''}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}} else {{
|
|
|
|
|
|
// Fallback: display raw markdown with basic formatting
|
|
|
|
|
|
const fallbackHtml = markdownContent
|
|
|
|
|
|
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
|
|
|
|
|
|
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
|
|
|
|
|
|
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
|
|
|
|
|
|
.replace(/\\*\\*(.*?)\\*\\*/g, '<strong>$1</strong>')
|
|
|
|
|
|
.replace(/\\*(.*?)\\*/g, '<em>$1</em>')
|
|
|
|
|
|
.replace(/^- (.*$)/gim, '<li>$1</li>')
|
|
|
|
|
|
.replace(/\\n\\n/g, '<br><br>')
|
|
|
|
|
|
.replace(/\\n/g, '<br>');
|
|
|
|
|
|
contentDiv.innerHTML = '<div style="white-space: pre-wrap;">' + fallbackHtml + '</div>';
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus('Content rendered with fallback parser', true);
|
2025-10-15 00:55:46 +02:00
|
|
|
|
{'reportEditModeError("CDN library failed to load", "Using basic fallback rendering");' if edit_mode else ''}
|
2025-10-15 00:45:55 +02:00
|
|
|
|
}}
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}}
|
2025-10-15 00:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
// Step 2: Try to enhance with edit capabilities (if in edit mode)
|
2025-10-25 18:16:25 +02:00
|
|
|
|
{'''if (typeof MARKITECT_EDIT_MODE !== 'undefined' && MARKITECT_EDIT_MODE) {
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus("Initializing edit capabilities...");
|
2025-10-25 18:16:25 +02:00
|
|
|
|
try {
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus("Creating editor instance...");
|
|
|
|
|
|
markitectEditor = new MarkitectEditor();
|
|
|
|
|
|
updateStatus("✓ Edit mode active - click any section to edit");
|
|
|
|
|
|
console.log("✓ Edit mode initialized successfully");
|
2025-10-25 18:16:25 +02:00
|
|
|
|
} catch (error) {
|
2025-10-15 01:06:03 +02:00
|
|
|
|
updateStatus("Edit mode failed to initialize", true);
|
2025-10-25 18:16:25 +02:00
|
|
|
|
reportEditModeError("Edit mode initialization failed", error.message);
|
2025-10-15 01:06:03 +02:00
|
|
|
|
console.error("Edit mode error:", error);
|
2025-10-25 18:16:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
}''' if edit_mode else ''}
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
}});
|
2025-10-15 00:55:46 +02:00
|
|
|
|
|
|
|
|
|
|
// Handle CDN loading errors
|
|
|
|
|
|
window.addEventListener('load', function() {{
|
|
|
|
|
|
if (window.markitectMarkedError) {{
|
|
|
|
|
|
{'reportEditModeError("CDN library failed to load", "Network or firewall blocking marked.js");' if edit_mode else ''}
|
|
|
|
|
|
}}
|
|
|
|
|
|
}});
|
2025-10-15 01:06:03 +02:00
|
|
|
|
|
|
|
|
|
|
// Safety timeout for edit mode initialization
|
|
|
|
|
|
{'''setTimeout(function() {
|
|
|
|
|
|
const statusMsg = document.getElementById("status-message");
|
|
|
|
|
|
if (statusMsg && (statusMsg.textContent.includes("Loading") || statusMsg.textContent.includes("Initializing"))) {
|
|
|
|
|
|
updateStatus("Edit mode initialization timeout", true);
|
|
|
|
|
|
reportEditModeError("Edit mode took too long to initialize", "Possible JavaScript performance issue");
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 5000);''' if edit_mode else ''} // 5 second timeout
|
feat: complete test fixing and decoupled functionality implementation
Major improvements to Issues #138, #139, and #140 with comprehensive
decoupled functionality approach:
## Issues Resolved
- Issue #138: Complete markdown parsing, directory creation, filename generation
- Issue #139: Full CLI integration, content aggregation, directory analysis,
end-to-end roundtrip testing, filename decoding system
- Issue #140: Fixed critical CLI parameter passing bug in roundtrip tests
## Key Features Added
- Comprehensive filename decoding system with special character restoration
- API version pattern handling (api_v2_1_reference.md → API v2.1: Reference)
- Smart title case with acronym recognition (API, SQL, HTTP, etc.)
- Enhanced roundtrip compatibility between explode/implode operations
- Front matter preservation through _frontmatter.yml files
- FilenameDecoder class for configurable batch processing
## Bug Fixes
- Fixed ImplodeOptions parameter passing in md_implode_command
- Corrected heading level preservation in roundtrip cycles
- Fixed README.md inclusion for roundtrip compatibility
- Enhanced pattern matching order to prevent conflicts
## Test Results
- All Issue #139 filename decoding tests: 18/18 passing ✅
- All Issue #140 roundtrip tests: 4/4 passing ✅
- Comprehensive test coverage for all new functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:05:48 +02:00
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>"""
|
|
|
|
|
|
|
|
|
|
|
|
return html_template
|
|
|
|
|
|
|
|
|
|
|
|
def _get_template_css(self, template: str = None) -> str:
|
|
|
|
|
|
"""Get CSS styles for the specified template theme."""
|
|
|
|
|
|
if template == 'github':
|
|
|
|
|
|
return """
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
|
|
|
|
|
|
max-width: 900px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
color: #24292f;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
#markdown-content {
|
|
|
|
|
|
min-height: 200px;
|
|
|
|
|
|
}
|
|
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
line-height: 1.25;
|
|
|
|
|
|
}
|
|
|
|
|
|
h1 { border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }
|
|
|
|
|
|
h2 { border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }
|
|
|
|
|
|
pre {
|
|
|
|
|
|
background: #f6f8fa;
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
border: 1px solid #d0d7de;
|
|
|
|
|
|
}
|
|
|
|
|
|
code {
|
|
|
|
|
|
background: rgba(175,184,193,0.2);
|
|
|
|
|
|
padding: 0.2em 0.4em;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
font-size: 0.85em;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre code {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
blockquote {
|
|
|
|
|
|
border-left: 4px solid #d0d7de;
|
|
|
|
|
|
margin: 0 0 16px 0;
|
|
|
|
|
|
padding: 0 1em;
|
|
|
|
|
|
color: #656d76;
|
|
|
|
|
|
}
|
|
|
|
|
|
"""
|
|
|
|
|
|
elif template == 'dark':
|
|
|
|
|
|
return """
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
|
|
|
|
|
max-width: 800px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
color: #e1e4e8;
|
|
|
|
|
|
background-color: #0d1117;
|
|
|
|
|
|
}
|
|
|
|
|
|
#markdown-content {
|
|
|
|
|
|
min-height: 200px;
|
|
|
|
|
|
}
|
|
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
|
|
|
|
color: #58a6ff;
|
|
|
|
|
|
border-color: #30363d;
|
|
|
|
|
|
}
|
|
|
|
|
|
h1 { border-bottom: 1px solid #30363d; padding-bottom: .3em; }
|
|
|
|
|
|
h2 { border-bottom: 1px solid #30363d; padding-bottom: .3em; }
|
|
|
|
|
|
pre {
|
|
|
|
|
|
background-color: #161b22;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
border: 1px solid #30363d;
|
|
|
|
|
|
}
|
|
|
|
|
|
code {
|
|
|
|
|
|
background: #6e768166;
|
|
|
|
|
|
padding: 0.2em 0.4em;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
font-size: 0.9em;
|
|
|
|
|
|
color: #e1e4e8;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre code {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
blockquote {
|
|
|
|
|
|
border-left: 4px solid #58a6ff;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding-left: 1rem;
|
|
|
|
|
|
color: #8b949e;
|
|
|
|
|
|
}
|
|
|
|
|
|
a { color: #58a6ff; }
|
|
|
|
|
|
a:hover { color: #79c0ff; }
|
|
|
|
|
|
"""
|
|
|
|
|
|
elif template == 'academic':
|
|
|
|
|
|
return """
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: Georgia, 'Times New Roman', serif;
|
|
|
|
|
|
max-width: 650px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
#markdown-content {
|
|
|
|
|
|
min-height: 200px;
|
|
|
|
|
|
}
|
|
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
|
|
|
|
|
margin-top: 2rem;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre {
|
|
|
|
|
|
background: #f8f8f8;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
border-left: 4px solid #ccc;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
font-family: 'Courier New', monospace;
|
|
|
|
|
|
}
|
|
|
|
|
|
code {
|
|
|
|
|
|
background: #f0f0f0;
|
|
|
|
|
|
padding: 0.1em 0.3em;
|
|
|
|
|
|
font-family: 'Courier New', monospace;
|
|
|
|
|
|
font-size: 0.9em;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre code {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
blockquote {
|
|
|
|
|
|
border-left: 4px solid #ddd;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding-left: 1rem;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
font-style: italic;
|
|
|
|
|
|
}
|
|
|
|
|
|
"""
|
|
|
|
|
|
else: # basic or default
|
|
|
|
|
|
return """
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
|
|
|
|
|
max-width: 800px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
#markdown-content {
|
|
|
|
|
|
min-height: 200px;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre {
|
|
|
|
|
|
background: #f6f8fa;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
code {
|
|
|
|
|
|
background: #f6f8fa;
|
|
|
|
|
|
padding: 0.2em 0.4em;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
font-size: 0.9em;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre code {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
blockquote {
|
|
|
|
|
|
border-left: 4px solid #dfe2e5;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding-left: 1rem;
|
|
|
|
|
|
color: #6a737d;
|
|
|
|
|
|
}
|
|
|
|
|
|
"""
|