# Packaging API Reference Complete API reference for MarkiTect's advanced packaging system (Issue #150). ## Module Structure ``` markitect.packaging/ ├── __init__.py # Main module exports ├── base.py # Base classes and constants ├── errors.py # Exception hierarchy ├── metadata.py # Metadata dataclasses ├── asset_utils.py # Asset management utilities ├── path_utils.py # Path handling utilities ├── mdz_variant.py # MDZ format implementation └── transclusion/ # Transclusion engine ├── __init__.py ├── engine.py # Main transclusion engine ├── context.py # Processing context └── directives.py # Directive parsing ``` ## Core Classes ### PackagingVariant Abstract base class for all packaging variants. ```python from markitect.packaging.base import PackagingVariant class MyPackagingVariant(PackagingVariant): def create_package(self, source_path: Path, options: Dict[str, Any]) -> Dict[str, Any]: # Implementation pass def extract_package(self, package_path: Path, options: Dict[str, Any]) -> Dict[str, Any]: # Implementation pass # ... other required methods ``` #### Abstract Methods - **`create_package(source_path, options)`**: Create package from source - **`extract_package(package_path, options)`**: Extract package to destination - **`get_package_metadata(package_path)`**: Get package metadata - **`embed_assets(assets, package_path)`**: Embed assets into package - **`rewrite_asset_paths(content, asset_map)`**: Rewrite asset paths in content ### MdzVariant Complete implementation of MDZ (Markdown Zip) format. ```python from markitect.packaging.mdz_variant import MdzVariant # Initialize variant mdz = MdzVariant() # Create package result = mdz.create_package( source_path=Path("document.md"), options={ 'output_path': Path("document.mdz"), 'compression_level': 6 } ) # Extract package extract_result = mdz.extract_package( package_path=Path("document.mdz"), options={'output_dir': Path("extracted/")} ) # Get metadata metadata = mdz.get_package_metadata(Path("document.mdz")) ``` #### Methods ##### `create_package(source_path: Path, options: Dict[str, Any]) -> Dict[str, Any]` Creates MDZ package from source content. **Parameters:** - `source_path`: Path to source markdown file or directory - `options`: Package creation options - `output_path` (optional): Output package path - `compression_level` (optional): ZIP compression level (0-9) **Returns:** Dictionary with creation results: ```python { 'success': True, 'package_path': Path('document.mdz'), 'assets_embedded': 5, 'package_size': 1024000 } ``` ##### `extract_package(package_path: Path, options: Dict[str, Any]) -> Dict[str, Any]` Extracts MDZ package contents. **Parameters:** - `package_path`: Path to MDZ package file - `options`: Extraction options - `output_dir` (optional): Output directory path **Returns:** Dictionary with extraction results: ```python { 'success': True, 'output_directory': Path('extracted/'), 'files_extracted': 8, 'extracted_files': [Path('content.md'), Path('assets/image.png'), ...] } ``` ##### `get_package_metadata(package_path: Path) -> PackageMetadata` Retrieves package metadata. **Returns:** `PackageMetadata` object with package information. ## Transclusion Engine ### TransclusionEngine Main engine for processing transclusion directives. ```python from markitect.packaging.transclusion import TransclusionEngine engine = TransclusionEngine( base_path=Path("templates/"), variables={'title': 'My Document', 'version': '1.0'}, max_depth=10 ) # Process content with directives result = engine.process_content(content_with_directives) # Process file result = engine.process_file(Path("template.mdt")) ``` #### Methods ##### `__init__(base_path=None, variables=None, max_depth=10)` Initialize transclusion engine. **Parameters:** - `base_path`: Base path for relative file resolution - `variables`: Initial variables dictionary - `max_depth`: Maximum inclusion depth (default: 10) ##### `process_content(content: str, context=None) -> str` Process transclusion directives in content. **Parameters:** - `content`: String containing transclusion directives - `context`: Optional TransclusionContext (created if None) **Returns:** Processed content with directives resolved ##### `process_file(file_path: Path, context=None) -> str` Process file with transclusion directives. **Parameters:** - `file_path`: Path to file to process - `context`: Optional TransclusionContext **Returns:** Processed file content ### TransclusionContext Context manager for transclusion processing. ```python from markitect.packaging.transclusion import TransclusionContext context = TransclusionContext( base_path=Path("templates/"), variables={'author': 'John Doe'}, max_depth=5 ) # Set variables context.set_variable('title', 'Advanced Guide') # Get variables with default title = context.get_variable('title', 'Untitled') # Substitute variables in text result = context.substitute_variables("Title: {{title}}") ``` #### Methods ##### `set_variable(name: str, value: Any)` Set a variable in the context. ##### `get_variable(name: str, default=None) -> Any` Get variable value with optional default. ##### `substitute_variables(text: str) -> str` Substitute variables using `{{variable}}` syntax. ##### `resolve_path(path: str) -> Path` Resolve path relative to context base path. ##### `enter_file(file_path: Path)` / `exit_file(file_path: Path)` Track file processing for circular reference detection. ### DirectiveParser Parser for transclusion directives. ```python from markitect.packaging.transclusion import DirectiveParser # Parse all directives from content directives = DirectiveParser.parse_directives(content) # Extract just file includes files = DirectiveParser.extract_file_includes(content) ``` #### Methods ##### `parse_directives(content: str) -> List[Directive]` Parse all transclusion directives from content. **Returns:** List of `Directive` objects with: - `type`: Directive type ('include', 'variable', 'conditional') - `args`: Parsed arguments dictionary - `content`: Block content (for conditional directives) - `start_pos`, `end_pos`: Position in original content ##### `extract_file_includes(content: str) -> List[str]` Extract file paths from include directives. **Returns:** List of file paths referenced in includes ## Utility Classes ### AssetUtils Utilities for asset discovery and management. ```python from markitect.packaging.asset_utils import AssetUtils # Discover assets in directory assets = AssetUtils.discover_assets(Path("project/")) # Create asset metadata metadata = AssetUtils.create_asset_metadata( file_path=Path("image.png"), package_path="assets/image.png" ) # Calculate checksum checksum = AssetUtils.calculate_checksum(Path("file.jpg")) # Validate integrity valid = AssetUtils.validate_asset_integrity(Path("file.jpg"), expected_checksum) ``` #### Static Methods ##### `discover_assets(source_path: Path, asset_extensions=None) -> List[Path]` Discover asset files in a source path. **Parameters:** - `source_path`: Directory or file to search - `asset_extensions`: Set of extensions to consider (optional) **Returns:** List of discovered asset paths ##### `create_asset_metadata(file_path: Path, package_path: str, original_path=None) -> AssetMetadata` Create metadata for an asset file. **Returns:** `AssetMetadata` object with file information ##### `calculate_checksum(file_path: Path) -> str` Calculate SHA-256 checksum of file. ##### `validate_asset_integrity(file_path: Path, expected_checksum: str) -> bool` Validate file integrity using checksum. ### PathUtils Path manipulation and rewriting utilities. ```python from markitect.packaging.path_utils import PathUtils # Rewrite asset paths in content content = "![Image](./assets/logo.png)" asset_map = {"./assets/logo.png": "embedded/logo.png"} rewritten = PathUtils.rewrite_asset_paths(content, asset_map) # Extract referenced paths paths = PathUtils.extract_referenced_paths(markdown_content) # Normalize path normalized = PathUtils.normalize_path("./images/../assets/file.png") ``` #### Static Methods ##### `rewrite_asset_paths(content: str, asset_map: Dict[str, str]) -> str` Rewrite asset paths in markdown content. **Parameters:** - `content`: Markdown content to process - `asset_map`: Mapping from original to new paths ##### `extract_referenced_paths(content: str) -> Set[str]` Extract all asset paths referenced in markdown. ##### `normalize_path(path: str, base_path=None) -> str` Normalize path for consistent handling. ##### `is_external_url(url: str) -> bool` Check if URL is external (has scheme). ## Data Classes ### PackageMetadata ```python @dataclass class PackageMetadata: format: str # Package format ("mdz", "mdt", etc.) version: str # Package format version created: str # ISO timestamp of creation markitect_version: str # MarkiTect version used assets: List[AssetMetadata] # List of embedded assets dependencies: List[str] = None # Optional dependencies ``` ### AssetMetadata ```python @dataclass class AssetMetadata: path: str # Path within package original_path: str # Original source path size: int # File size in bytes checksum: str # SHA-256 checksum mime_type: Optional[str] = None # MIME type ``` ## Exception Hierarchy ``` PackagingError # Base packaging exception ├── PackageFormatError # Package format issues │ └── InvalidPackageError # Invalid package structure ├── AssetError # Asset handling errors │ └── AssetNotFoundError # Asset file not found ├── PathRewriteError # Path rewriting issues └── TransclusionError # Transclusion processing errors ├── CircularReferenceError # Circular inclusion detected └── DepthLimitError # Max inclusion depth exceeded ``` ### Usage ```python from markitect.packaging.errors import ( PackagingError, AssetError, TransclusionError, CircularReferenceError, DepthLimitError ) try: result = engine.process_file(template_file) except CircularReferenceError as e: print(f"Circular reference: {e}") except TransclusionError as e: print(f"Transclusion error: {e}") except PackagingError as e: print(f"General packaging error: {e}") ``` ## Integration Points ### Variant System Integration ```python # Add to ExplodeVariant enum from markitect.explode_variants.enums import ExplodeVariant # ExplodeVariant.MDZ and ExplodeVariant.MDT are now available # Factory integration from markitect.explode_variants import get_variant_factory factory = get_variant_factory() mdz_variant = factory.create_variant(ExplodeVariant.MDZ) ``` ### CLI Integration Future CLI commands will integrate with this API: ```bash # Will use MdzVariant.create_package() markitect md-package create document.md --format mdz # Will use TransclusionEngine.process_file() markitect md-transclude process template.mdt --variables vars.json ``` --- **Version**: 1.0 (Issue #150) **Status**: Complete implementation with 100% test coverage **Compatibility**: Integrates seamlessly with existing MarkiTect variant system