Development Guide
Developer documentation for contributing to AozoraEpub3 or understanding its internal implementation.
Table of Contents
- Development Environment Setup
- Building and Testing
- Project Structure
- Code Architecture
- Template System (Velocity)
- EPUB 3.3 Compliance
- Aozora Notation Support
- External Character Handling
- GitHub Actions CI
- Contributing Guidelines
- Common Issues
Development Environment Setup
Requirements
- Java: JDK 25 LTS recommended (JDK 21 or later works for building and running)
- Gradle: 9.6.1 (use the bundled Gradle Wrapper)
- Git: Version control
- IDE: IntelliJ IDEA, Eclipse, VS Code, etc.
Clone Repository
git clone https://github.com/AozoraEpub3-JDK21/AozoraEpub3-JDK21.git
cd AozoraEpub3-JDK21
IDE Setup
VS Code
- Install Java Extension Pack
- Open folder
- Gradle tasks auto-detected
IntelliJ IDEA
- File โ Open โ Select
build.gradle - โImport Gradle Projectโ auto-configures
Eclipse
./gradlew eclipse
Then: Import โ Existing Projects
Building and Testing
Basic Build
## Clean build
./gradlew clean build
## Create FAT JAR (with all dependencies)
./gradlew jar
## Create distribution packages (ZIP + TAR.GZ)
./gradlew dist
Important: distZip task is disabled. Use dist task for distribution packages.
Running Tests
## Run all tests
./gradlew test
## Generate test report
./gradlew test --rerun-tasks
## โ build/reports/tests/test/index.html
Build Artifacts
- FAT JAR:
build/libs/AozoraEpub3.jar - Distribution packages:
build/distributions/AozoraEpub3-<version>.zipbuild/distributions/AozoraEpub3-<version>.tar.gz
- Test report:
build/reports/tests/test/index.html
Running the Application
## Launch GUI (no arguments)
java -jar build/libs/AozoraEpub3.jar
## CLI usage (convert UTF-8 text to EPUB)
java -jar build/libs/AozoraEpub3.jar -of -d out input.txt
## Vertical writing sample
java -jar build/libs/AozoraEpub3.jar -enc UTF-8 test_data/test_title.txt
## Horizontal writing sample
java -jar build/libs/AozoraEpub3.jar -enc UTF-8 -hor test_data/test_yoko.txt
Project Structure
AozoraEpub3/
โโโ src/ # Main source code
โ โโโ AozoraEpub3.java # CLI entry point
โ โโโ AozoraEpub3Applet.java # GUI entry point
โ โโโ com/github/hmdev/ # Package root
โ โโโ converter/ # TextโEPUB conversion
โ โโโ epub/ # EPUB specification
โ โโโ io/ # File/archive handling
โ โโโ image/ # Image processing
โ โโโ config/ # Configuration parsing
โ โโโ pipeline/ # Conversion pipeline
โ
โโโ test/ # Test code
โ โโโ AozoraEpub3SmokeTest.java
โ โโโ IniCssIntegrationTest.java
โ โโโ com/github/hmdev/ # Package tests
โ
โโโ template/ # Velocity templates
โ โโโ mimetype # EPUB mimetype file
โ โโโ META-INF/
โ โ โโโ container.xml # EPUB container definition
โ โโโ OPS/
โ โโโ package.vm # package.opf generation
โ โโโ toc.ncx.vm # NCX TOC generation
โ โโโ css/ # CSS templates
โ โโโ vertical_text.vm
โ โโโ horizontal_text.vm
โ
โโโ test_data/ # Test fixtures
โ โโโ test_title.txt # Title/author tests
โ โโโ test_ruby.txt # Ruby conversion tests
โ โโโ test_gaiji.txt # Gaiji conversion tests
โ โโโ img/ # Test images
โ
โโโ presets/ # Device presets
โ โโโ kobo__full.ini # Kobo maximum size
โ โโโ kindle_pw.ini # Kindle Paperwhite
โ โโโ reader.ini # Sony Reader
โ
โโโ chuki_*.txt # Notation definition files
โ โโโ chuki_tag.txt # Notation โ Tag conversion
โ โโโ chuki_alt.txt # Gaiji โ Alternative chars
โ โโโ chuki_utf.txt # Gaiji โ UTF-8
โ โโโ chuki_ivs.txt # Gaiji โ IVS
โ โโโ chuki_latin.txt # Latin character conversion
โ
โโโ build.gradle # Gradle build definition
โโโ gradlew, gradlew.bat # Gradle Wrapper
โโโ README.md # User documentation
โโโ DEVELOPMENT.md # Original dev documentation
Key Classes
Entry Points
AozoraEpub3.java: CLI processing, argument parsing, conversion executionAozoraEpub3Applet.java: Swing-based GUI
Conversion Pipeline
Epub3Writer: EPUB 3 file generation (uses Velocity)AozoraEpub3Converter: Aozora notation parsing, conversion, and ruby handlingBookInfo: Holds bibliographic data such as title and authorAozoraGaijiConverter/JisConverter/LatinConverter: Gaiji annotation conversionJisLevelUtil: JIS level detection (used by the gaiji annotation fallback)
I/O & Archives
ArchiveTextExtractor: Text extraction from zip/rar (with caching)ArchiveCache: Archive scan result cachingOutputNamer: Output filename generation
Image Processing
ImageInfoReader: Image metadata readingImageUtils: Image resizing and optimization
Configuration
SettingDefaults: Default values for ini keys, shared by the GUI and the CLI
Code Architecture
Improvements in v1.2.4 (historical record)
Modularization and Class Extraction
Separated responsibilities out of the large AozoraEpub3.java (645 lines at the time) to improve maintainability. All line counts below are the figures from that release:
Extracted Classes:
- OutputNamer (
com.github.hmdev.io): Filename generation logic (50 lines)- Creator/title-based auto-naming
- Filename sanitization (invalid character removal)
- Default extension handling
- WriterConfigurator (
com.github.hmdev.pipeline): Writer configuration aggregation (110 lines)- Image parameter configuration
- TOC nesting configuration
- Style settings (margins, line height, fonts)
- ArchiveTextExtractor (
com.github.hmdev.io): Unified archive handling (90 lines)- Text extraction from zip/rar/txt
- Text file counting
- Cache mechanism integration
Refactoring Results:
AozoraEpub3.java: 645 lines โ 450 lines (200 lines reduced)- New classes: 5 classes (350 lines total)
- Unit tests added: OutputNamerTest (4 tests)
Details: notes/refactor-plan.md
Performance Optimization ๐
Problem: 4 archive scans per file:
- Text file count
- Book information retrieval
- Image list loading
- Actual conversion
Solution: Archive caching mechanism
- ArchiveCache: Scan archive once and hold info in memory
- Text file content (byte array)
- Image file entry name list
- Text file count
- ArchiveScanner: Unified zip/rar scanner
- Collect text and image entries in one pass
- Optimized RAR temporary file extraction
Optimization Results:
- Archive scans: 4 โ 1 (75% reduction)
- Significant speed improvement for large zip/rar (100MB+)
- Memory usage: ~10-20MB cache even for 2GB archives
Memory Management:
- Auto-release via
ArchiveTextExtractor.clearCache()after conversion - Only text content cached (images loaded on demand)
Details: notes/archive-cache-optimization.md
Template System (Velocity)
Design Principles
Epub3Writer supports VelocityEngine injection to avoid global initialization dependencies.
Constructors
// Recommended: Inject VelocityEngine (testable, customizable)
new Epub3Writer(templatePath, velocityEngine)
// Or legacy style (backward compatible)
new Epub3Writer(templatePath) // Uses global initialization
Test Usage Example
Properties p = new Properties();
p.setProperty("resource.loaders", "file");
p.setProperty("resource.loader.file.class",
"org.apache.velocity.runtime.resource.loader.FileResourceLoader");
p.setProperty("resource.loader.file.path",
projectRoot.resolve("template").resolve("OPS").toString());
VelocityEngine ve = new VelocityEngine(p);
VelocityContext ctx = new VelocityContext();
ctx.put("title", "Sample Title");
ctx.put("bookInfo", bookInfoObject);
ctx.put("sections", sectionList);
// ... other context setup
Template t = ve.getTemplate("package.vm", "UTF-8");
StringWriter out = new StringWriter();
t.merge(ctx, out);
String opf = out.toString();
Template Files
| Template | Purpose | Output File |
|---|---|---|
package.vm |
EPUB metadata/manifest | package.opf |
toc.ncx.vm |
Table of contents (NCX) | toc.ncx |
css/vertical_text.vm |
Vertical text CSS | vertical_text.css |
css/horizontal_text.vm |
Horizontal text CSS | horizontal_text.css |
xhtml/*.vm |
Content XHTML | *.xhtml |
INI Values to CSS
INI settings (font_size, line_height, etc.) are placed in Velocity context and used as CSS variables in templates.
Example (vertical_text.vm):
:root {
--font-size: ${fontSize}%;
--line-height: ${lineHeight};
}
Related Tests:
- CssTemplateRenderTest.java: Vertical CSS
- HorizontalCssTemplateRenderTest.java: Horizontal CSS
EPUB 3.3 Compliance
Validation Items (Automated in CI)
mimetype File
- Must be first entry in ZIP and stored uncompressed (STORED)
package.opf (OPF File)
unique-identifierrequireddc:identifierinurn:uuid:format (RFC 4122)dcterms:modifiedin ISO8601 formatlanguage=ja(Japanese content)navitem exists in manifestspinepage-progression-directionattribute:- Vertical โ
rtl(right-to-left) - Horizontal โ
ltr(left-to-right)
- Vertical โ
- CSS
writing-modeconsistency:- Vertical โ
vertical-rl - Horizontal โ unspecified or
horizontal-tb
- Vertical โ
container.xml
- Well-formed XML (validated with xmllint)
Kindle (iPhone) Support
In package.vm L60 (for ImageOnly + Kindle):
<meta name="primary-writing-mode" content="horizontal-rl"/>
Preservation Test: PackageTemplateKindleMetaTest.java
epubcheck Validation
## Custom Gradle task
./gradlew epubcheck \
-PepubDir=build/epub_local \
-PepubcheckJar=build/tools/epubcheck-5.3.0/epubcheck.jar
Get epubcheck:
mkdir -p build/tools
cd build/tools
curl -L -o epubcheck-5.3.0.zip \
https://github.com/w3c/epubcheck/releases/download/v5.3.0/epubcheck-5.3.0.zip
unzip epubcheck-5.3.0.zip
Aozora Notation Support
Basic Notation (Configuration Files)
chuki_tag.txt: Notation โ ePub tag conversionchuki_tag_suf.txt: Forward-reference โ Start-end conversionchuki_alt.txt: Gaiji โ Alternative character mappingchuki_utf.txt: Gaiji โ UTF-8 mappingchuki_ivs.txt: Gaiji โ IVS UTF-8 mappingchuki_latin.txt: Latin character โ UTF-8 conversion
Programmatically Processed Notation
- Page left/right centering
- Auto ruby notation conversion ๏ผป๏ผใโใใซใโณใใฎใซใ๏ผฝ โ ๏ฝโใโณใ
- Auto emphasis conversion ๏ผป๏ผใโใใซรๅ็น๏ผฝ โ ร ruby
- Complex indentation (fold/indent calculation)
- Warichu line break addition
- Page break by ๅบๆฌ๏ผ
Unsupported Notation
- Corrections and "ใใ" (ignored)
- Left ruby
- Inline bottom alignment
- Two-column layout
External Character Handling
Extract and convert gaiji (external characters) from Aozora notation:
โป๏ผป๏ผใๅญๅใใU+6DB6๏ผฝ โ Direct Unicode
โป๏ผป๏ผใๅญๅใใ็ฌฌ3ๆฐดๆบ1-85-57๏ผฝ โ JIS code โ UTF-8
โป๏ผป๏ผใใใใใ๏ผๅใใUCS6DB6๏ผฝ โ UCS format
Gaiji without corresponding code are replaced with alternative characters via chuki_alt.txt.
GitHub Actions CI
Workflows
ci.yml (Build, Test, EPUB Generation, Validation)
Automated processes:
- Build (Gradle)
- Test execution (JUnit)
- Sample EPUB generation (vertical/horizontal, multiple presets)
epubcheckvalidation- OPF XPath validation (UUID format, writing direction consistency)
- Accessibility warning summary (missing img alt count)
- Upload generated EPUBs as artifacts
- Manual execution support (workflow_dispatch + inputs)
Manual Execution:
GitHub โ Actions โ CI โ Run workflow
Optional inputs:
ini_font_size: INI font_size (default: 115)ini_line_height: INI line_height (default: 1.7)
test.yml (Unit Tests Only)
- Test execution (JUnit)
- Manual execution support
Contributing Guidelines
Bug Reports & Feature Requests
Provide the following information in GitHub Issues:
For Bugs
- Environment (OS, Java version)
- Input text (or minimal reproduction)
- Error messages/logs
- Expected vs actual behavior
For Feature Requests
- Proposal details
- Use cases
- References (if any)
Pull Requests
- Fork repository and create feature branch
- Make changes and add tests
- Verify all tests pass:
./gradlew test - Create PR (with description and related issue links)
Coding Conventions
- Follow existing style (Java standard)
- Always add tests (JUnit 4)
- Update corresponding tests when modifying templates
- Write clear commit messages (English or Japanese)
Common Issues
Velocity Resource Resolution Failure
Symptom: template/*.vm not found during test execution
Cause: Gradle Worker runs in different working directory
Solution:
- Specify absolute path with FileResourceLoader
- Get projectRoot via
Paths.get(".").toAbsolutePath().normalize() - Use
VelocityTestUtilsutility
Windows Path Issues
Symptom: \ causes escaping failures
Solution:
- Use
PathsAPI (auto-converts to/) - Or explicitly use forward slashes
Test Instability
Symptom: Passes locally but fails in CI
Causes:
- File I/O timing
- Resource resolution path dependencies
Solutions:
- Avoid relative paths, use absolute or classpath
- Make template paths configurable
Performance Optimization Tips
Large Text Conversion
- Increase memory:
java -Xmx2g ... - Enable forced page breaks (file splitting)
Image Processing
- Resizing has high CPU load (Bicubic)
- Margin removal is slow for PNG
EPUB Generation Speed
- Optimize Velocity templates (avoid large loops)
- Image streaming (process large images incrementally)
Links
- ๐ Home
- ๐ Usage Guide
- ๐ EPUB 3.3 Support
- ๐ป GitHub Repository
- ๐ง Original Project
- ๐ Aozora Bunko
- ๐ EPUB 3.3 Specification
- โ epubcheck
License
GPL v3 - See README for details