Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A modern, type-safe Kotlin library for building and manipulating structured document trees. Create rich documents programmatically with a fluent DSL, comprehensive styling, visitor patterns, and undo/redo support.

License

Notifications You must be signed in to change notification settings

codirex/doc-tree

Repository files navigation

DocTree

A modern, type-safe Kotlin library for building and manipulating structured document trees.

DocTree provides a clean, fluent API for creating rich document structures programmatically. Whether you're generating reports, building documentation tools, or creating content management systems, DocTree gives you the power to represent complex documents as typed object trees.


✨ Features

  • 🎯 Type-Safe DSL - Build documents using an intuitive Kotlin DSL
  • πŸ—οΈ Clean Architecture - Separation of concerns between API, core, and implementation
  • πŸ”„ Visitor Pattern - Traverse and transform document trees efficiently
  • 🎨 Rich Styling - Comprehensive styling system for text and blocks
  • πŸ“Š Complex Structures - Support for tables, lists, code blocks, quotes, and more
  • πŸ” Text Extraction - Extract plain text from any document structure
  • πŸ“ˆ Statistics - Analyze document structure with built-in visitors
  • 🧡 Thread-Safe - ID generation and core operations are thread-safe
  • πŸ”Œ Extensible - Easy to extend with custom node types and visitors

πŸš€ Quick Start

Installation

Add to your build.gradle.kts:

dependencies {
 implementation("org.codirex.doctree:doc-tree:1.0.0")
}

Basic Usage

import org.codirex.doctree.api.document
import org.codirex.doctree.api.visitor.toPlainText
import org.codirex.doctree.style.*
// Create a document using the fluent DSL
val doc = document {
 metadata {
 title = "Getting Started with DocTree"
 author = "John Doe"
 keywords = listOf("documentation", "kotlin", "tutorial")
 }
 heading(1) {
 text("Welcome to DocTree")
 }
 paragraph {
 text("DocTree is a ")
 bold("powerful")
 text(" and ")
 italic("flexible")
 text(" library for building structured documents.")
 }
 list(ordered = true) {
 item {
 paragraph { text("Easy to use") }
 }
 item {
 paragraph { text("Type-safe") }
 }
 item {
 paragraph { text("Extensible") }
 }
 }
 codeBlock(
 language = "kotlin",
 code = """
 val doc = document {
 paragraph { text("Hello, World!") }
 }
 """.trimIndent()
 )
}
// Extract plain text
val plainText = doc.toPlainText()
println(plainText)

πŸ“š Core Concepts

Document Tree Structure

DocTree represents documents as hierarchical trees of nodes:

Document (root)
β”œβ”€ Paragraph
β”‚ β”œβ”€ TextRun (plain)
β”‚ └─ TextRun (bold)
β”œβ”€ Heading
β”‚ └─ TextRun
β”œβ”€ List
β”‚ β”œβ”€ ListItem
β”‚ β”‚ └─ Paragraph
β”‚ └─ ListItem
β”‚ └─ Paragraph
└─ Table
 β”œβ”€ TableRow
 β”‚ β”œβ”€ TableCell
 β”‚ └─ TableCell
 └─ TableRow
 β”œβ”€ TableCell
 └─ TableCell

Node Types

Block Elements

  • Document - Root container for all content
  • Paragraph - Basic text block with styled runs
  • Heading - Section headings (levels 1-6)
  • ListBlock - Ordered or unordered lists
  • ListItem - Individual list items
  • CodeBlock - Syntax-highlighted code blocks
  • BlockQuote - Quoted content
  • Table - Tabular data with rows and cells
  • Image - Embedded images
  • HorizontalRule - Thematic breaks

Text Elements

  • TextRun - Styled text content with formatting

🎨 Styling System

DocTree provides comprehensive styling capabilities:

Text Styling

paragraph {
 // Basic styling
 text("Normal text")
 bold("Bold text")
 italic("Italic text")
 underline("Underlined")
 strikethrough("Strikethrough")
 // Custom styling
 text("Custom", TextStyle(
 font = Font.ROBOTO,
 size = 14f,
 weight = 600,
 color = Color.BLUE,
 backgroundColor = Color.YELLOW,
 decoration = setOf(TextDecoration.BOLD, TextDecoration.UNDERLINE)
 ))
 // Code styling
 code("inline code")
}

Block Styling

val paragraph = Paragraph(
 id = "para-1",
 style = BlockStyle(
 margin = Spacing.all(16),
 padding = Spacing.symmetric(vertical = 8, horizontal = 12),
 border = Border.all(width = 1, color = Color.BLACK),
 background = Background(color = Color(240, 240, 240)),
 width = Dimension.percent(100f),
 textStyle = TextStyle(size = 14f)
 )
)

Colors

// Predefined colors
val red = Color.RED
val blue = Color.BLUE
// Custom RGB colors
val purple = Color(128, 0, 128)
// Colors with transparency
val semiTransparent = Color(255, 0, 0, 0.5f)
// Hex colors
val orange = Color.fromHex("#FF6600")

πŸ”„ Visitor Pattern

DocTree uses the Visitor pattern for tree traversal and transformation:

Built-in Visitors

Text Extraction

val plainText = document.toPlainText()

Statistics

val stats = document.getStatistics()
println("Paragraphs: ${stats.paragraphCount}")
println("Headings: ${stats.headingCount}")
println("Total words: ${stats.totalWords}")
println("Total characters: ${stats.totalCharacters}")

Custom Visitors

Create custom visitors by extending AbstractNodeVisitor:

class MarkdownExportVisitor : AbstractNodeVisitor<String>() {
 override fun defaultResult() = ""
 override fun visitHeading(heading: Heading): String {
 val hashes = "#".repeat(heading.level)
 return "$hashes ${heading.getPlainText()}\n\n"
 }
 override fun visitParagraph(paragraph: Paragraph): String {
 return "${paragraph.getPlainText()}\n\n"
 }
 override fun visitCodeBlock(codeBlock: CodeBlock): String {
 val lang = codeBlock.language ?: ""
 return "```$lang\n${codeBlock.code}\n```\n\n"
 }
 // Implement other visit methods...
}
// Use the visitor
val markdown = document.accept(MarkdownExportVisitor())

πŸ“Š Advanced Examples

Creating a Complex Table

document {
 table(columnCount = 3, hasHeaderRow = true) {
 // Header row
 row {
 cell { paragraph { bold("Name") } }
 cell { paragraph { bold("Age") } }
 cell { paragraph { bold("Role") } }
 }
 // Data rows
 row {
 cell { paragraph { text("Alice") } }
 cell { paragraph { text("30") } }
 cell { paragraph { text("Developer") } }
 }
 row {
 cell { paragraph { text("Bob") } }
 cell { paragraph { text("25") } }
 cell { paragraph { text("Designer") } }
 }
 }
}

Nested Lists

document {
 list(ordered = true) {
 item {
 paragraph { text("First level item 1") }
 }
 item {
 paragraph { text("First level item 2") }
 // Nested list would be added as a separate ListBlock within the item
 }
 }
}

Rich Text with Multiple Styles

paragraph {
 text("This paragraph contains ")
 bold("bold")
 text(", ")
 italic("italic")
 text(", ")
 underline("underlined")
 text(", and ")
 colored("colored", Color.RED)
 text(" text, as well as ")
 highlighted("highlighted", Color.YELLOW)
 text(" content.")
}

πŸ›οΈ Architecture

DocTree follows clean architecture principles:

org.codirex.doctree
β”œβ”€β”€ api/ # Public API layer
β”‚ β”œβ”€β”€ DocumentBuilder # Fluent DSL builder
β”‚ └── visitor/ # Visitor implementations
β”‚ β”œβ”€β”€ AbstractNodeVisitor
β”‚ β”œβ”€β”€ TextExtractorVisitor
β”‚ └── NodeCounterVisitor
β”‚
β”œβ”€β”€ core/ # Core domain model
β”‚ β”œβ”€β”€ Node # Base node interface
β”‚ β”œβ”€β”€ NodeVisitor # Visitor interface
β”‚ β”œβ”€β”€ block/ # Block-level elements
β”‚ β”‚ β”œβ”€β”€ BlockElement # Base block class
β”‚ β”‚ β”œβ”€β”€ Document
β”‚ β”‚ β”œβ”€β”€ Paragraph
β”‚ β”‚ β”œβ”€β”€ Heading
β”‚ β”‚ β”œβ”€β”€ ListBlock
β”‚ β”‚ β”œβ”€β”€ CodeBlock
β”‚ β”‚ β”œβ”€β”€ Table
β”‚ β”‚ └── ...
β”‚ └── text/ # Text-level elements
β”‚ └── TextRun
β”‚
β”œβ”€β”€ style/ # Styling system
β”‚ β”œβ”€β”€ BlockStyle
β”‚ β”œβ”€β”€ TextStyle
β”‚ β”œβ”€β”€ Color
β”‚ β”œβ”€β”€ Font
β”‚ β”œβ”€β”€ Border
β”‚ β”œβ”€β”€ Spacing
β”‚ └── ...
β”‚
└── utils/ # Utilities
 └── IdGenerator # Unique ID generation

Design Principles

  1. Separation of Concerns - Clear boundaries between API, domain, and utilities
  2. Immutability - Style objects are immutable; use copy() for modifications
  3. Type Safety - Strong typing throughout the API
  4. Extensibility - Easy to add new node types and visitors
  5. Testability - Pure functions and dependency injection where needed

πŸ”Œ Extensibility

Adding Custom Node Types

  1. Extend BlockElement or implement Node
  2. Add visit method to NodeVisitor interface
  3. Implement in all visitor implementations
  4. Add builder methods if needed

Adding Custom Visitors

Extend AbstractNodeVisitor<R> and override methods for nodes you care about:

class MyCustomVisitor : AbstractNodeVisitor<MyResult>() {
 override fun defaultResult() = MyResult()
 override fun visitParagraph(paragraph: Paragraph): MyResult {
 // Your custom logic
 }
}

⚑ Performance Considerations

  • Memory Efficiency - Nodes are lightweight; styling is done via immutable data classes
  • Thread Safety - ID generation is thread-safe; document trees themselves are not inherently thread-safe (use external synchronization if needed)
  • Lazy Evaluation - Use visitors for on-demand processing
  • Immutable Styles - Enables safe sharing and caching

πŸ§ͺ Testing

DocTree is designed for testability:

@Test
fun `should create document with proper structure`() {
 val doc = document {
 heading(1) { text("Title") }
 paragraph { text("Content") }
 }
 val stats = doc.getStatistics()
 assertEquals(1, stats.headingCount)
 assertEquals(1, stats.paragraphCount)
}

πŸ“¦ Version History

Version 1.0.0

  • Initial release
  • Complete document tree model
  • Fluent DSL API
  • Visitor pattern support
  • Comprehensive styling system
  • Built-in text extraction and statistics visitors

🀝 Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues.

Development Setup

  1. Clone the repository
  2. Open in IntelliJ IDEA
  3. Build: ./gradlew build
  4. Test: ./gradlew test

πŸ“„ License

This project is licensed under the Apache License 2.0. See the LICENSE file for the full text. Third-party attributions (if any) are listed in NOTICE.


πŸ™ Acknowledgments

Built with ❀️ using Kotlin and modern software engineering principles.


πŸ“ž Support


Made with πŸš€ by Codirex

About

A modern, type-safe Kotlin library for building and manipulating structured document trees. Create rich documents programmatically with a fluent DSL, comprehensive styling, visitor patterns, and undo/redo support.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /