Include content from other files and automatically merge YAML frontmatter for modular document composition.
- Basic Imports
- Frontmatter Merging
- Merge Strategies
- Security Features
- Configuration Options
- Use Cases
- Best Practices
Include content from other files using the @import directive:
@import boilerplate/header.md
l. Terms and Conditions
@import clauses/confidentiality.md
@import clauses/payment.md
@import boilerplate/footer.mdUse double quotes when the file path contains spaces:
@import "clauses/non compete agreement.md"
@import "legal docs/standard terms.md"Both quoted and unquoted paths are supported:
@import clauses/confidentiality.md # unquoted (no spaces) @import "clauses/non
compete agreement.md" # quoted (has spaces)Quoted paths are recommended on systems where folder names commonly contain spaces (e.g., macOS, Google Drive synced folders).
project/
├── main-contract.md
├── boilerplate/
│ ├── header.md
│ └── footer.md
└── clauses/
├── confidentiality.md
├── payment.md
└── termination.md
When Legal Markdown processes imports:
- File Resolution: Locates imported files relative to the main document
- Content Inclusion: Inserts the imported content at the import location
- Frontmatter Merging: Automatically merges YAML metadata (see below)
- Recursive Processing: Imported files can contain their own imports
Legal Markdown JS automatically merges YAML frontmatter from imported files into the main document's metadata using a "source always wins" strategy.
Main Document (contract.md):
---
title: "Professional Services Agreement"
client:
name: "Default Client" # Will be overridden by import
liability_cap: 500000 # Main document wins over imports
payment_terms: "Net 45" # Main document preference
---
# {{title}}
@import components/client-info.md
@import components/standard-terms.mdComponent (components/client-info.md):
---
client:
name: "Acme Corporation" # Overrides main document
industry: "Manufacturing" # New field, added to metadata
contact: "legal@acme.com" # New nested field
liability_cap: 2000000 # Loses to main document
payment_terms: "Net 15" # Loses to main document
---
**Client:** {{client.name}} ({{client.industry}})
**Contact:** {{client.contact}}Result: The main document's values for liability_cap and payment_terms
are preserved, while client.name, client.industry, and client.contact are
merged from the imported file.
Frontmatter merging works at the property level for nested objects:
# Main document
config:
debug: true
server: "production"
database:
host: "main-db"
# Import
config:
debug: false # Conflict - main wins
timeout: 30 # New field - added
database:
host: "import-db" # Conflict - main wins
port: 5432 # New field - added
# Merged result
config:
debug: true # From main (wins conflict)
server: "production" # From main (preserved)
timeout: 30 # From import (added)
database:
host: "main-db" # From main (wins conflict)
port: 5432 # From import (added)Legal Markdown uses a "source always wins" strategy where:
- Main document values always take precedence
- First import wins over subsequent imports for the same field
- New fields from imports are added to the metadata
When multiple imports have conflicting metadata, the first import wins over subsequent imports (but main document always wins over all imports):
# main.md
shared_field: "main_value"
# First import
shared_field: "first_value" # Loses to main
unique_field: "from_first"
# Second import
shared_field: "second_value" # Loses to main
unique_field: "from_second" # Loses to first import
# Final result
shared_field: "main_value" # Main document wins
unique_field: "from_first" # First import winsFor security, certain fields are automatically filtered and cannot be overridden by imports:
# Malicious import attempt (automatically filtered)
level-one: 'HACKED %n' # Header configuration (filtered)
force_commands: 'rm -rf /' # Command injection (filtered)
meta-yaml-output: '/etc/passwd' # Path traversal (filtered)
pipeline-config: { ... } # System configuration (filtered)
# Only safe fields are merged
legitimate_field: 'safe value' # Allowed throughReserved fields include:
level-one,level-two, etc. (header configuration)force_commands,commands(command injection prevention)meta-yaml-output,meta-json-output(path traversal prevention)pipeline-config(system configuration protection)_cross_references(protected metadata fields)
The frontmatter merging system includes timeout protection to prevent infinite loops from circular references.
# Default behavior: frontmatter merging enabled
legal-md contract-template.md output.md
# Disable frontmatter merging
legal-md contract-template.md --disable-frontmatter-merge output.md
# Enable import tracing for debugging
legal-md contract-template.md --import-tracing output.md
# Validate type compatibility during merging
legal-md contract-template.md --validate-import-types output.md
# Log detailed merge operations
legal-md contract-template.md --log-import-operations output.md
# Combine multiple import options
legal-md template.md --import-tracing --validate-import-types --log-import-operations output.mdType Validation: Enable strict type checking during merge operations:
# Validate types during frontmatter merging
legal-md contract.md --validate-import-typesIf enabled, type conflicts are detected and logged:
# Main document
count: 42
# Import with type conflict
count: "not a number" # Type conflict - main value preserved
# Result with type validation
count: 42 # Preserved with warning loggedImport Operation Logging: Track detailed merge operations:
# Log detailed frontmatter merge operations
legal-md contract.md --log-import-operations- Standard Terms: Common clauses with default values
- Client Terms: Client-specific overrides and additions
- Project Terms: Project-specific parameters
- Regulatory Terms: Jurisdiction-specific requirements
- Base Templates: Core document structure with defaults
- Component Library: Reusable sections with metadata
- Customization Layers: Client/project specific modifications
- Compliance Overlays: Industry-specific requirements
# Main enterprise contract
---
title: "Enterprise Master Agreement"
liability_cap: 10000000 # Enterprise-level protection
payment_terms: "Net 15" # Fast payment for enterprise
---
@import components/client-specific-terms.md # Override defaults
@import components/standard-legal-terms.md # Base legal framework
@import components/enterprise-sla.md # Performance requirementsEach imported component contributes its metadata while the main document's preferences take precedence for any conflicts.
Main Contract (enterprise-agreement.md):
---
title: "Enterprise Service Agreement"
client_type: "enterprise"
liability_limit: 5000000
---
@import sections/definitions.md
@import sections/service-terms.md
@import sections/payment-terms.md
@import sections/termination.mdService Terms (sections/service-terms.md):
---
service_level: 'premium'
support_hours: '24x7'
response_time: '1 hour'
liability_limit: 1000000 # Lower than main - main wins
---
l. **Service Terms**
Client will receive {{service_level}} service with {{support_hours}} support and
{{response_time}} response time.Final Result: Main document's higher liability limit (5M) is preserved, while service-specific metadata is added.
templates/
├── contracts/
│ ├── base-contract.md
│ ├── enterprise-contract.md
│ └── standard-contract.md
├── clauses/
│ ├── confidentiality.md
│ ├── payment-terms.md
│ ├── termination.md
│ └── warranty.md
└── metadata/
├── client-defaults.md
├── enterprise-defaults.md
└── compliance-eu.md
Usage:
---
title: 'Custom Enterprise Agreement'
---
@import metadata/enterprise-defaults.md @import metadata/client-defaults.md
@import contracts/base-contract.md @import clauses/confidentiality.md @import
clauses/warranty.md @import metadata/compliance-eu.mdPut most general settings in main document:
# Main document - general settings
---
title: "Service Agreement"
version: "2.0"
effective_date: "@today"
currency: "USD"
---
# Imports provide specific details
@import client-specific.md # Client overrides
@import service-details.md # Service-specific termsName import files by their purpose:
@import metadata/client-acme-corp.md @import clauses/enterprise-warranty.md
@import terms/california-compliance.mdComment which fields should win conflicts:
---
# Main document values (highest priority)
liability_cap: 10000000 # Enterprise minimum - do not override
payment_terms: "Net 15" # Fast payment required
# Import will add client details but won't override above
---
@import client-metadata.mdUse --validate-import-types in CI/CD:
# In your build pipeline
legal-md contract-template.md --validate-import-types --log-import-operationsNever import untrusted content without validation:
# ✅ Good - trusted internal components
@import internal/standard-terms.md
@import internal/client-metadata.md
# ❌ Dangerous - external or user-provided content
# @import user-uploads/custom-terms.md
# @import external/untrusted-content.mdVerify merged metadata matches expectations:
# Export metadata to verify merge results
legal-md contract.md --export-yaml --output-path ./debug/Organize imports logically:
---
title: 'Main Contract'
---
# Metadata imports first
@import metadata/client-defaults.md @import metadata/project-settings.md
# Content imports
@import content/definitions.md @import content/main-terms.md
# Compliance last (highest specificity)
@import compliance/gdpr-terms.md# tenant-specific.md
---
tenant:
name: 'Acme Corp'
tier: 'enterprise'
region: 'US'
branding:
logo: 'acme-logo.png'
colors: '#ff0000'
---# service-level.md
---
sla:
uptime: '99.9%'
support: '24x7'
response: '1 hour'
tenant:
tier: 'standard' # Will be overridden by tenant-specific
---# main-contract.md
---
title: "Service Agreement" effective_date: "@today"
---
@import metadata/tenant-specific.md # Specific tenant config @import
metadata/service-level.md # Service defaults @import content/standard-terms.md #
Standard legal terms# base-contract.md
---
compliance: gdpr: false hipaa: false sox: false
---
@import base-terms.md
# GDPR-specific additions
{{#if compliance.gdpr}} @import compliance/gdpr-clauses.md {{/if}}
# HIPAA-specific additions
{{#if compliance.hipaa}} @import compliance/hipaa-clauses.md {{/if}}- YAML Frontmatter - Understanding metadata structure
- Optional Clauses - Using imported metadata in conditions
- Variables & Mixins - Using merged variables in content
- CLI Reference - Import-related command options