Skip to content

yidafu/feishu2html

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

107 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Feishu2HTML

Kotlin License: MIT Maven Central Gradle GitHub Release API Docs Kotlin Multiplatform

A powerful Kotlin Multiplatform library and CLI tool to convert Feishu (Lark) documents to beautiful, standalone HTML files.

🌐 Now supports JVM, JS, and Native platforms!

📦 Download Latest Release - Pre-built binaries for macOS, Linux, Windows
📖 View API Documentation - Complete KDoc reference
🚀 Maven Central - Use as library dependency

✨ Features

  • 🌐 Kotlin Multiplatform - Runs on JVM, JS (Node.js/Browser), and Native platforms
  • 🎯 Comprehensive Block Support - All major Feishu document block types (headings, paragraphs, lists, tables, code blocks, etc.)
  • 📦 Resource Management - Automatic download and save of images and attachments
  • 🖼️ Base64 Image Embedding - Optional base64 encoding for standalone HTML files
  • 🎨 Rich Text Formatting - Full support for text styles (bold, italic, underline, strikethrough, links, etc.)
  • 📎 Enhanced File Attachments - Beautiful Feishu-style attachment cards with type icons
  • 🧮 Math Rendering - Mathematical formulas powered by MathJax
  • 💻 Syntax Highlighting - Code blocks with 70+ language support
  • 🎨 Customizable Templates - Default, Fragment, and Full HTML template modes
  • 🔧 Flexible Usage - Use as library or CLI tool with rich options
  • Async Downloads - Asynchronous resource downloading for better performance
  • 🛡️ Type Safety - Type-safe HTML generation using kotlinx.html DSL
  • 🎭 Clean Architecture - Elegant Renderer delegation pattern
  • 🚀 Cross-Platform - >95% code shared across all platforms
  • 🧹 Clean Output - Optional hiding of unsupported block warnings

🎨 Visual Comparison

Feishu2HTML faithfully recreates the original styling and layout. Side-by-side comparison:

Feishu Online Local HTML Output
Feishu Online Local HTML Output

The generated HTML preserves typography, colors, layout, and all media content with 100% authentic Feishu appearance.

📋 Table of Contents

🚀 Quick Start

Prerequisites

  • JVM: JDK 17+, Gradle 8.0+ (or use included wrapper)
  • JS: Node.js 16+ (browser not supported)
  • Native: Platform toolchain (XCode/GCC/MinGW)

1. Get Feishu App Credentials

  1. Visit Feishu Open Platform
  2. Create a self-built app
  3. Get your App ID and App Secret
  4. Add the following permissions to your app:
    • docx:document - View, comment, and export documents
    • drive:drive - View and download files in cloud storage

2. Grant Document Access

Important: You must grant your app access to the documents you want to export:

  1. Open the Feishu document you want to export
  2. Click the "Share" button in the top-right corner
  3. Add your app/bot to the document collaborators
  4. Grant at least "View" permission

⚠️ Limitation: If your document contains embedded/referenced external documents (e.g., via links or iframe blocks), you must also grant your app access to those external documents. Otherwise, the content may fail to load or appear as broken links.

3. Installation

Download pre-built binaries from GitHub Releases:

  • macOS Apple Silicon: feishu2html-{version}-macosArm64.tar.gz
  • macOS Intel: feishu2html-{version}-macosX64.tar.gz
  • Linux x64: feishu2html-{version}-linuxX64.tar.gz
  • Windows x64: feishu2html-{version}-mingwX64.zip
  • JVM JAR (cross-platform): feishu2html-{version}-jvm.jar

Or use Maven Central to add as a library dependency.

4. CLI Usage

Using JAR (Recommended):

Download the JVM JAR from GitHub Releases:

# Download
curl -L -O https://github.com/yidafu/feishu2html/releases/latest/download/feishu2html-1.0.2-jvm.jar

# Basic usage - Export a single document
java -jar feishu2html-1.0.2-jvm.jar <app_id> <app_secret> <document_id>

# Export multiple documents
java -jar feishu2html-1.0.2-jvm.jar <app_id> <app_secret> <doc_id_1> <doc_id_2> <doc_id_3>

# With options for standalone HTML (embedded images and CSS)
java -jar feishu2html-1.0.2-jvm.jar --inline-images --inline-css <app_id> <app_secret> <document_id>

# Clean output (hide unsupported block warnings)
java -jar feishu2html-1.0.2-jvm.jar --hide-unsupported <app_id> <app_secret> <document_id>

# All options combined
java -jar feishu2html-1.0.2-jvm.jar -t fragment --inline-images --inline-css --hide-unsupported <app_id> <app_secret> <document_id>

CLI Options:

Options:
  -t, --template <mode>   HTML template mode: default | fragment | full
  --inline-images         Embed images as base64 data URLs
  --inline-css            Embed CSS styles inline in <style> tag
  --hide-unsupported      Hide unsupported block type warnings
  -h, --help              Show help message

Using Gradle (from source):

# Clone the repository
git clone https://github.com/yidafu/feishu2html.git
cd feishu2html

# Build and run
./gradlew runJvm --args="<app_id> <app_secret> <document_id>"
./gradlew runJvm --args="--inline-images --inline-css <app_id> <app_secret> <document_id>"

Example:

java -jar feishu2html-1.0.2-jvm.jar cli_a1234567890abcde your_app_secret_here doxcnABC123XYZ456

Output files will be saved to ./output/ directory by default.

5. Library Usage

Add to Your Project

Kotlin Multiplatform Project:

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("dev.yidafu.feishu2html:feishu2html:1.0.2")
            }
        }
    }
}

JVM-only Project:

dependencies {
    implementation("dev.yidafu.feishu2html:feishu2html-jvm:1.0.2")
}

JS Project:

dependencies {
    implementation("dev.yidafu.feishu2html:feishu2html-js:1.0.2")
}

Basic Example

import dev.yidafu.feishu2html.Feishu2Html
import dev.yidafu.feishu2html.Feishu2HtmlOptions
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val options = Feishu2HtmlOptions(
        appId = "your_app_id",
        appSecret = "your_app_secret"
    )

    // Use .use {} for automatic resource management
    Feishu2Html(options).use { converter ->
        converter.export("doxcnABC123XYZ456")
        println("Export completed successfully!")
    }
}

Advanced Example with Custom Options

import dev.yidafu.feishu2html.Feishu2Html
import dev.yidafu.feishu2html.Feishu2HtmlOptions
import dev.yidafu.feishu2html.TemplateMode
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val options = Feishu2HtmlOptions(
        appId = "your_app_id",
        appSecret = "your_app_secret",
        outputDir = "./output",              // HTML output directory
        imageDir = "./output/images",        // Image save directory
        fileDir = "./output/files",          // Attachment save directory
        imagePath = "images",                // Relative path for images in HTML
        filePath = "files",                  // Relative path for files in HTML
        externalCss = false,                 // Inline CSS (true = external file)
        customCss = null,                    // Custom CSS (optional)
        templateMode = TemplateMode.DEFAULT, // HTML template mode
        inlineImages = true,                 // Embed images as base64
        showUnsupportedBlocks = false        // Hide unsupported block warnings
    )

    // Automatic resource cleanup with use {}
    Feishu2Html(options).use { converter ->
        // Batch export multiple documents
        val documentIds = listOf(
            "doxcnABC123XYZ456",
            "doxcnDEF789GHI012",
            "doxcnJKL345MNO678"
        )
        
        converter.exportBatch(documentIds)
        println("Batch export completed!")
    }
}

Available Options:

Option Type Default Description
appId String required Feishu application App ID
appSecret String required Feishu application App Secret
outputDir String "./output" HTML output directory
imageDir String "./output/images" Image save directory
fileDir String "./output/files" Attachment save directory
imagePath String "images" Relative path for images in HTML
filePath String "files" Relative path for files in HTML
customCss String? null Custom CSS styles
externalCss Boolean true Use external CSS file (false = inline)
cssFileName String "feishu-style-optimized.css" CSS filename
templateMode TemplateMode DEFAULT HTML template mode
inlineImages Boolean false Embed images as base64 data URLs
showUnsupportedBlocks Boolean true Show unsupported block warnings

6. CSS Styling Options

Using Official Feishu Styles (Default)

By default, exported HTML uses an optimized version extracted from official Feishu CSS:

val options = Feishu2HtmlOptions(
    appId = "your_app_id",
    appSecret = "your_app_secret",
    externalCss = true,                        // Use external CSS file (default)
    cssFileName = "feishu-style-optimized.css" // Optimized CSS (default, 16KB)
)

Feishu2Html(options).use { converter ->
    converter.export("document_id")
}
// Output: 
//   - document.html (with <link> to CSS)
//   - feishu-style-optimized.css (optimized styles, only 16KB!)

Why Optimized CSS? 98.4% smaller (16KB vs 1MB), faster load times, only needed selectors, 100% authentic appearance.

Inline CSS Mode

Use inline CSS for single-file portability (no separate CSS file):

val options = Feishu2HtmlOptions(
    appId = "your_app_id",
    appSecret = "your_app_secret",
    externalCss = false  // Embed CSS in <style> tag
)

Custom CSS Styling

Override with your own CSS (requires inline mode):

val customCss = """
    .protyle-wysiwyg { font-family: "Inter", sans-serif; }
    .heading-h1 { color: #2c3e50; border-bottom: 3px solid #3498db; }
    /* Add more custom styles... */
""".trimIndent()

val options = Feishu2HtmlOptions(
    appId = "your_app_id",
    appSecret = "your_app_secret",
    externalCss = false,  // Must use inline mode
    customCss = customCss
)

📚 Usage Guides

Detailed platform-specific usage guides:

🌐 Multiplatform Support

Feishu2HTML is built with Kotlin Multiplatform, enabling it to run on multiple platforms from a single codebase.

Supported Platforms

Platform Status Notes
JVM ✅ Production Ready Full features (Library + CLI)
JS (Node.js) ✅ Fully Supported Core library features
Native (macOS) ✅ Verified Core library features, tested on Intel & Apple Silicon
Native (Linux x64) 🔄 Experimental Core library features
Native (Windows x64) 🔄 Experimental Core library features
iOS 🔄 Experimental Core library features

Platform-Specific Notes

  • JVM: Full support including CLI tool, Logback logging, and complete file I/O
  • JS (Node.js): File system via Node.js fs module, Ktor client, browser not supported
  • Native: POSIX file I/O, platform-specific HTTP engines (Darwin/Curl)

Build Targets

Build for specific platforms:

# JVM
./gradlew compileKotlinJvm
./gradlew jvmJar

# JS
./gradlew compileKotlinJs
./gradlew jsJar

# Native (macOS ARM64)
./gradlew compileKotlinMacosArm64

# All platforms
./gradlew build

Platform-Specific Usage

All platforms use the same API (see Library Usage for examples):

  • JVM: Use runBlocking coroutine scope
  • JS (Node.js): Use GlobalScope.promise for async execution
  • Native: Use runBlocking coroutine scope

🔍 Getting Document ID

The document ID can be extracted from the Feishu document URL:

https://example.feishu.cn/docx/doxcnABC123XYZ456
                              └─────────────────┘
                                 Document ID

For example:

  • URL: https://company.feishu.cn/docx/TPDddjY5foJZ8axlf9fctf2Wnse
  • Document ID: TPDddjY5foJZ8axlf9fctf2Wnse

🔧 Troubleshooting

1. Token Acquisition Failure

Error: Failed to get token: app access token invalid

Solutions:

  • Verify app_id and app_secret are correct
  • Ensure the app is enabled and published
  • Check app permissions are configured

2. Document Access Failure

Error: Failed to get document content: no permission

Solutions:

  • Confirm app has required permissions
  • Ensure document is accessible to the app
  • Try adding the app to document collaborators

3. Image Download Failure

Solutions:

  • Check network connection
  • Confirm app has drive:drive permission
  • Some legacy documents may have API limitations

⚠️ Known Limitations

1. External Document References

When a Feishu document contains references to other documents (e.g., embedded documents, links to other docs), you must grant your app access to all referenced documents as well. The tool cannot automatically propagate permissions.

Workaround: Manually share each referenced document with your app before exporting.

2. Real-time Collaboration Content

Content from real-time collaboration features (e.g., comments, suggestions) is not included in the export.

3. Unsupported Block Types

Some advanced block types are not yet supported (ISV, Mindnote, Sheet, Task, OKR, Wiki Catalog, Agenda, Link Preview, etc.). By default, these will display a placeholder message for debugging purposes.

Solution: Use the --hide-unsupported CLI option or set showUnsupportedBlocks = false in library usage to hide these warnings for cleaner output.

# CLI: Hide unsupported block warnings
java -jar feishu2html.jar --hide-unsupported <app_id> <app_secret> <document_id>
// Library: Hide unsupported block warnings
val options = Feishu2HtmlOptions(
    appId = "your_app_id",
    appSecret = "your_app_secret",
    showUnsupportedBlocks = false  // Hide warnings
)

See the Supported Block Types table for a complete list.

4. API Rate Limiting

The Feishu API has rate limits. The tool includes built-in rate limiting (QPS=2) to avoid exceeding limits, but very large documents may take time to process.

📖 API Documentation & References

API Documentation

Complete API documentation is automatically generated and published to GitHub Pages:

🔗 View Online API Documentation

The documentation is automatically updated on every push to the main branch.

Platform-Specific Guides

Feishu API References

📊 Supported Block Types

Block Type Type Code Support Status Notes
Page 1 ✅ Full -
Text 2 ✅ Full -
Heading 1-9 3-11 ✅ Full All 9 levels supported
Bullet List 12 ✅ Full -
Ordered List 13 ✅ Full -
Code Block 14 ✅ Full 70+ languages
Quote 15 ✅ Full -
Equation 16 ✅ Full MathJax rendering
Todo 17 ✅ Full -
Bitable 18 ⚠️ Partial Placeholder only
Callout 19 ✅ Full -
Chat Card 20 ⚠️ Partial Placeholder only
Diagram 21 ✅ Full -
Divider 22 ✅ Full -
File 23 ✅ Full -
Grid 24 ✅ Full Column layout
Grid Column 25 ✅ Full -
Iframe 26 ✅ Full Multiple embed types
Image 27 ✅ Full -
ISV 28 ❌ Unsupported -
Mindnote 29 ❌ Unsupported -
Sheet 30 ❌ Unsupported -
Table 31 ✅ Full -
Table Cell 32 ✅ Full -
View 33 ❌ Unsupported -
Quote Container 34 ✅ Full -
Task 35 ❌ Unsupported -
OKR 36 ❌ Unsupported -
OKR Objective 37 ❌ Unsupported -
OKR Key Result 38 ❌ Unsupported -
OKR Progress 39 ❌ Unsupported -
Add-ons 40 ❌ Unsupported Plugin components
Jira Issue 41 ❌ Unsupported -
Wiki Catalog 42 ❌ Unsupported Legacy wiki subpage list
Board 43 ✅ Full Electronic whiteboard
Agenda 44 ❌ Unsupported -
Agenda Item 45 ❌ Unsupported -
Agenda Item Title 46 ❌ Unsupported -
Agenda Item Content 47 ❌ Unsupported -
Link Preview 48 ❌ Unsupported -
Source Synced 49 ❌ Unsupported -
Reference Synced 50 ❌ Unsupported -
Sub Page List 51 ❌ Unsupported Wiki subpage list (new)
AI Template 52 ❌ Unsupported -

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md for architecture, coding standards, and PR guidelines.

🙏 Acknowledgments

This project was inspired by feishu2md.


Made with ❤️ by the Feishu2HTML contributors

20:53:59.100 [main] INFO dev.yidafu.feishu2html.api.FeishuAuthService -- Requesting new tenant_access_token 20:53:59.100 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App ID: cli_a8790687b4bdd01c 20:53:59.101 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App Secret: 3sXNpzmX4ErVg07gNMOgdMkQn2usPg

20:54:47.596 [main] INFO dev.yidafu.feishu2html.api.FeishuAuthService -- Requesting new tenant_access_token 20:54:47.596 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App ID: cli_a8790687b4bdd01c 20:54:47.596 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App Secret: 3sxXNpzmX4ErVg07gNMOgdMkQn2usPgq

About

Convert Feishu(Lark) Document to HTML.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published