Vexy Markliff
A Python package and CLI tool for bidirectional conversion between Markdown/HTML and XLIFF 2.1 format, enabling high-fidelity localization workflows.
Documentation: https://vexy.dev/vexy-markliff/
Features
- Bidirectional Conversion: Seamless Markdown ↔ XLIFF and HTML ↔ XLIFF conversion
- XLIFF 2.1 Compliant: Full compliance with OASIS XLIFF 2.1 standard
- Format Style Module: Preserves HTML attributes and structure using fs:fs and fs:subFs
- ITS 2.0 Support: Native integration with W3C Internationalization Tag Set
- Flexible Modes: One-document and two-document translation workflows
- Round-trip Fidelity: Lossless Markdown → XLIFF → Markdown conversion
- Intelligent Segmentation: Smart sentence splitting for translation units
- Skeleton Management: External skeleton files for document structure preservation
- Rich CLI: Comprehensive command-line interface built with Fire
- Modern Python: Type hints, Pydantic models, and async support
Installation
uv pip install --system vexy-markliff
or
uv add vexy-markliff
Quick Start
CLI Usage
# Convert Markdown to XLIFF
vexy-markliff md2xliff document.md document.xlf
# Convert HTML to XLIFF
vexy-markliff html2xliff page.html page.xlf
# Convert XLIFF back to Markdown
vexy-markliff xliff2md translated.xlf result.md
# Two-document mode (parallel source and target)
vexy-markliff md2xliff --mode=two-doc source.md target.md aligned.xlf
Python API
from vexy_markliff import Config, process_data
summary = process_data(
["alpha", "beta", "alpha"],
config=Config(name="demo", value="count", options={"mode": "summary"}),
)
print(summary["unique"]) # -> 2
Advanced Usage
Configuration
Create a vexy-markliff.yaml configuration file:
source_language: en
target_language: es
markdown:
extensions:
- tables
- footnotes
- task_lists
html_passthrough: true
xliff:
version: "2.1"
format_style: true
its_support: true
segmentation:
split_sentences: true
sentence_splitter: nltk
Use the configuration:
vexy-markliff md2xliff --config=vexy-markliff.yaml input.md output.xlf
Two-Document Mode
Process parallel source and target documents for alignment:
from vexy_markliff import VexyMarkliff, TwoDocumentMode
converter = VexyMarkliff()
# Load source and target content
with open("source.md", "r") as f:
source = f.read()
with open("target.md", "r") as f:
target = f.read()
# Process parallel documents
result = converter.process_parallel(
source_content=source,
target_content=target,
mode=TwoDocumentMode.ALIGNED
)
# Generate XLIFF with aligned segments
xliff_content = result.to_xliff()
Custom Processing Pipeline
from vexy_markliff import Pipeline, MarkdownParser, XLIFFGenerator
# Build custom pipeline
pipeline = Pipeline()
pipeline.add_stage(MarkdownParser())
pipeline.add_stage(CustomProcessor()) # Your custom processor
pipeline.add_stage(XLIFFGenerator())
# Process content
result = pipeline.process(markdown_content)
Supported Formats
Markdown Elements
- CommonMark compliant base
- Tables (GitHub Flavored Markdown)
- Task lists
- Strikethrough
- Footnotes
- Front matter (YAML/TOML)
- Raw HTML passthrough
HTML Elements
- All HTML5 structural elements
- Text content elements (p, h1-h6, etc.)
- Inline formatting (strong, em, a, etc.)
- Tables with complex structures
- Forms and inputs
- Media elements (img, video, audio)
- Web Components and custom elements
XLIFF Features
- XLIFF 2.1 Core compliance
- Format Style (fs) module for attribute preservation
- ITS 2.0 metadata support
- Translation unit notes
- Preserve space handling
- External skeleton files
- Inline element protection
How It Works
- Parsing: Markdown is parsed using markdown-it-py, HTML using lxml
- HTML Conversion: Markdown is converted to HTML as intermediate format
- Content Extraction: Translatable content is identified and extracted
- Structure Preservation: Document structure is stored in skeleton files
- XLIFF Generation: Content is formatted as XLIFF 2.1 with Format Style attributes
- Round-trip: Translated XLIFF is merged with skeleton to reconstruct the original format
Development
This project uses Hatch for development workflow management.
Setup Development Environment
# Install hatch if you haven't already
pip install hatch
# Create and activate development environment
hatch shell
# Run tests
hatch run test
# Run tests with coverage
hatch run test-cov
# Run linting
hatch run lint
# Format code
hatch run format
Testing
# Run all tests (preferred)
uvx hatch run test
# Run with coverage
uvx hatch run test-cov
# Underlying command if hatch env already active
python -m pytest
# Run specific test file
python -m pytest tests/test_markdown_parser.py
# Run with verbose output
python -m pytest -xvs
Documentation
Full documentation: https://vexy.dev/vexy-markliff/
The sources are in src_docs/md/ (build with src_docs/build.sh). The design notes that used to live in docs/ (HTML and Markdown mapping rules, the XLIFF primer, segmentation research) are now in the Design notes section.
Contributing
Contributions are welcome! Please ensure:
- All tests pass
- Code follows PEP 8 style guidelines
- Type hints are provided
- Documentation is updated
License
MIT License
Acknowledgments
Built on the XLIFF 2.1 OASIS standard and leverages:
- markdown-it-py for Markdown parsing
- lxml for XML/HTML processing
- Fire for CLI interface
- Pydantic for data validation
Metadata
Release files for vexy-markliff 1.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| vexy_markliff-1.3.2.tar.gz | 43.8 kB | Without provenance | Details for vexy_markliff-1.3.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| vexy_markliff-1.3.2-py3-none-any.whl | Python 3 | none | any | Details for vexy_markliff-1.3.2-py3-none-any.whl |
Total release size: 61.1 kB
Release files / vexy_markliff-1.3.2.tar.gz
| Download URL | vexy_markliff-1.3.2.tar.gz |
|---|---|
| Size | 43.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
084bbf194b61455786d26adde439e8e5500ac38c1bf5edd6466bbb0b788066c3
|
|
BLAKE2b-256 checksum How to use checksums |
237cff142f6ab19f659f05f53e499114d47f16ca3591f6e35edc407d9281bafc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / vexy_markliff-1.3.2-py3-none-any.whl
| Download URL | vexy_markliff-1.3.2-py3-none-any.whl |
|---|---|
| Size | 17.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af41909058388334c85b26953e567625791d05bd75ec28eb4480bac2bcc7bba8
|
|
BLAKE2b-256 checksum How to use checksums |
3448bb6855791365613979219dfdfcc7fdfea16250461203861feb9adac3f064
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for vexy-markliff 1.3.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.