lark-doc-exporter 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lark_doc_exporter-0.1.0/PKG-INFO +134 -0
- lark_doc_exporter-0.1.0/README.md +125 -0
- lark_doc_exporter-0.1.0/pyproject.toml +41 -0
- lark_doc_exporter-0.1.0/setup.cfg +4 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/PKG-INFO +134 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/SOURCES.txt +27 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/dependency_links.txt +1 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/entry_points.txt +2 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/requires.txt +2 -0
- lark_doc_exporter-0.1.0/src/lark_doc_exporter.egg-info/top_level.txt +1 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/__init__.py +5 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/__main__.py +5 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/cli.py +146 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/doctor.py +56 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/exporter.py +550 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/markdown_runtime.py +42 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/pdf_runtime.py +76 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/release_version.py +97 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/skill_assets/lark-doc-exporter/SKILL.md +61 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/skill_install.py +288 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/themes/company.css +31 -0
- lark_doc_exporter-0.1.0/src/lark_synced_export/themes/default.css +16 -0
- lark_doc_exporter-0.1.0/tests/test_doctor.py +54 -0
- lark_doc_exporter-0.1.0/tests/test_exporter.py +111 -0
- lark_doc_exporter-0.1.0/tests/test_markdown_runtime.py +61 -0
- lark_doc_exporter-0.1.0/tests/test_pdf_runtime.py +112 -0
- lark_doc_exporter-0.1.0/tests/test_release_version.py +65 -0
- lark_doc_exporter-0.1.0/tests/test_skill_install.py +314 -0
- lark_doc_exporter-0.1.0/tests/test_theme_resolution.py +7 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lark-doc-exporter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Export Feishu/Lark docs with synced blocks to Markdown and themeable PDF
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: markdown<4,>=3.7
|
|
8
|
+
Requires-Dist: playwright<2,>=1.54
|
|
9
|
+
|
|
10
|
+
# lark-doc-exporter
|
|
11
|
+
|
|
12
|
+
Export Feishu/Lark docs with synced blocks expanded into:
|
|
13
|
+
|
|
14
|
+
- Markdown with localized images
|
|
15
|
+
- Themeable locally rendered PDF
|
|
16
|
+
|
|
17
|
+
The PDF path deliberately avoids the Feishu `docs_ai -> export pdf` route so the
|
|
18
|
+
final file does not include the AI disclaimer injected by that server-side path.
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- `lark-cli` configured with a user session
|
|
23
|
+
- Python 3.14
|
|
24
|
+
- A working Chrome/Chromium runtime, or the ability to install one with `uvx --from playwright playwright install chromium`
|
|
25
|
+
|
|
26
|
+
If you use `uvx` / `uv tool install`, `uv` can provision the required Python for
|
|
27
|
+
the tool environment automatically.
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv tool install lark-doc-exporter
|
|
33
|
+
lark-doc-exporter doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If Chromium is missing, prepare it once:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
uvx --from playwright playwright install chromium
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then run an export:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
lark-doc-exporter \
|
|
46
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
47
|
+
--output-dir exports/demo \
|
|
48
|
+
--formats markdown,pdf \
|
|
49
|
+
--theme default
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## One-off Run
|
|
53
|
+
|
|
54
|
+
If you do not want a persistent tool install:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uvx lark-doc-exporter \
|
|
58
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
59
|
+
--output-dir exports/demo \
|
|
60
|
+
--formats markdown,pdf \
|
|
61
|
+
--theme default
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Install As A Tool
|
|
65
|
+
|
|
66
|
+
After installing the released package, companion-skill operations stay the same:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
lark-doc-exporter skill install --dry-run
|
|
70
|
+
lark-doc-exporter skill install
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Auto mode installs the companion skill into every detected supported host:
|
|
74
|
+
|
|
75
|
+
- Codex: `~/.agents/skills/lark-doc-exporter`
|
|
76
|
+
- Claude Code: `~/.claude/skills/lark-doc-exporter`
|
|
77
|
+
|
|
78
|
+
Use `--host codex`, `--host claude`, or `--host all` to target specific hosts. `--dry-run` previews the install plan and target directories without writing files. Use `--force` only when you intentionally want to replace an existing unmanaged target directory.
|
|
79
|
+
|
|
80
|
+
## Chromium Setup
|
|
81
|
+
|
|
82
|
+
- `doctor` reports whether both `lark-cli` and Chromium are ready.
|
|
83
|
+
- If you already have a browser binary, you can point the exporter at it with `LARK_DOC_EXPORTER_CHROMIUM=/path/to/chromium`.
|
|
84
|
+
- If `LARK_DOC_EXPORTER_CHROMIUM` is set to a missing path, the command fails explicitly instead of silently falling back.
|
|
85
|
+
|
|
86
|
+
## Output
|
|
87
|
+
|
|
88
|
+
- `markdown` keeps the localized Markdown file in the output directory.
|
|
89
|
+
- `pdf` is rendered locally from the localized Markdown via HTML/CSS + Chromium.
|
|
90
|
+
- `images/` contains same-run localized image assets used by the Markdown/PDF.
|
|
91
|
+
|
|
92
|
+
## Themes
|
|
93
|
+
|
|
94
|
+
Built-in themes:
|
|
95
|
+
|
|
96
|
+
- `default`
|
|
97
|
+
- `company`
|
|
98
|
+
|
|
99
|
+
You can also layer custom CSS on top:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
lark-doc-exporter \
|
|
103
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
104
|
+
--output-dir exports/company \
|
|
105
|
+
--formats pdf \
|
|
106
|
+
--theme company \
|
|
107
|
+
--css /path/to/your-company-print.css
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Development / Unreleased
|
|
111
|
+
|
|
112
|
+
Use the Git URL or a local checkout only when you intentionally need unreleased code:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
uvx --from git+https://github.com/spencercjh/lark-doc-exporter lark-doc-exporter doctor
|
|
116
|
+
|
|
117
|
+
git clone https://github.com/spencercjh/lark-doc-exporter
|
|
118
|
+
cd lark-doc-exporter
|
|
119
|
+
uv sync --python 3.14 --group dev
|
|
120
|
+
make fmt
|
|
121
|
+
make ci
|
|
122
|
+
|
|
123
|
+
# Optional runtime/environment check (not part of required CI)
|
|
124
|
+
uv run lark-doc-exporter doctor
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Notes
|
|
128
|
+
|
|
129
|
+
- The current implementation still uses a temporary Feishu doc to translate the
|
|
130
|
+
expanded XML into fresh Markdown.
|
|
131
|
+
- The temporary doc is deleted by default after the Markdown export step. Use
|
|
132
|
+
`--keep-temp-doc` only when you need to inspect that intermediate document.
|
|
133
|
+
- Feishu image `authcode` URLs expire quickly, so image localization happens in
|
|
134
|
+
the same run as the Markdown export.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# lark-doc-exporter
|
|
2
|
+
|
|
3
|
+
Export Feishu/Lark docs with synced blocks expanded into:
|
|
4
|
+
|
|
5
|
+
- Markdown with localized images
|
|
6
|
+
- Themeable locally rendered PDF
|
|
7
|
+
|
|
8
|
+
The PDF path deliberately avoids the Feishu `docs_ai -> export pdf` route so the
|
|
9
|
+
final file does not include the AI disclaimer injected by that server-side path.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- `lark-cli` configured with a user session
|
|
14
|
+
- Python 3.14
|
|
15
|
+
- A working Chrome/Chromium runtime, or the ability to install one with `uvx --from playwright playwright install chromium`
|
|
16
|
+
|
|
17
|
+
If you use `uvx` / `uv tool install`, `uv` can provision the required Python for
|
|
18
|
+
the tool environment automatically.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv tool install lark-doc-exporter
|
|
24
|
+
lark-doc-exporter doctor
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If Chromium is missing, prepare it once:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uvx --from playwright playwright install chromium
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then run an export:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
lark-doc-exporter \
|
|
37
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
38
|
+
--output-dir exports/demo \
|
|
39
|
+
--formats markdown,pdf \
|
|
40
|
+
--theme default
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## One-off Run
|
|
44
|
+
|
|
45
|
+
If you do not want a persistent tool install:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uvx lark-doc-exporter \
|
|
49
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
50
|
+
--output-dir exports/demo \
|
|
51
|
+
--formats markdown,pdf \
|
|
52
|
+
--theme default
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Install As A Tool
|
|
56
|
+
|
|
57
|
+
After installing the released package, companion-skill operations stay the same:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
lark-doc-exporter skill install --dry-run
|
|
61
|
+
lark-doc-exporter skill install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Auto mode installs the companion skill into every detected supported host:
|
|
65
|
+
|
|
66
|
+
- Codex: `~/.agents/skills/lark-doc-exporter`
|
|
67
|
+
- Claude Code: `~/.claude/skills/lark-doc-exporter`
|
|
68
|
+
|
|
69
|
+
Use `--host codex`, `--host claude`, or `--host all` to target specific hosts. `--dry-run` previews the install plan and target directories without writing files. Use `--force` only when you intentionally want to replace an existing unmanaged target directory.
|
|
70
|
+
|
|
71
|
+
## Chromium Setup
|
|
72
|
+
|
|
73
|
+
- `doctor` reports whether both `lark-cli` and Chromium are ready.
|
|
74
|
+
- If you already have a browser binary, you can point the exporter at it with `LARK_DOC_EXPORTER_CHROMIUM=/path/to/chromium`.
|
|
75
|
+
- If `LARK_DOC_EXPORTER_CHROMIUM` is set to a missing path, the command fails explicitly instead of silently falling back.
|
|
76
|
+
|
|
77
|
+
## Output
|
|
78
|
+
|
|
79
|
+
- `markdown` keeps the localized Markdown file in the output directory.
|
|
80
|
+
- `pdf` is rendered locally from the localized Markdown via HTML/CSS + Chromium.
|
|
81
|
+
- `images/` contains same-run localized image assets used by the Markdown/PDF.
|
|
82
|
+
|
|
83
|
+
## Themes
|
|
84
|
+
|
|
85
|
+
Built-in themes:
|
|
86
|
+
|
|
87
|
+
- `default`
|
|
88
|
+
- `company`
|
|
89
|
+
|
|
90
|
+
You can also layer custom CSS on top:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
lark-doc-exporter \
|
|
94
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
95
|
+
--output-dir exports/company \
|
|
96
|
+
--formats pdf \
|
|
97
|
+
--theme company \
|
|
98
|
+
--css /path/to/your-company-print.css
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Development / Unreleased
|
|
102
|
+
|
|
103
|
+
Use the Git URL or a local checkout only when you intentionally need unreleased code:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uvx --from git+https://github.com/spencercjh/lark-doc-exporter lark-doc-exporter doctor
|
|
107
|
+
|
|
108
|
+
git clone https://github.com/spencercjh/lark-doc-exporter
|
|
109
|
+
cd lark-doc-exporter
|
|
110
|
+
uv sync --python 3.14 --group dev
|
|
111
|
+
make fmt
|
|
112
|
+
make ci
|
|
113
|
+
|
|
114
|
+
# Optional runtime/environment check (not part of required CI)
|
|
115
|
+
uv run lark-doc-exporter doctor
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Notes
|
|
119
|
+
|
|
120
|
+
- The current implementation still uses a temporary Feishu doc to translate the
|
|
121
|
+
expanded XML into fresh Markdown.
|
|
122
|
+
- The temporary doc is deleted by default after the Markdown export step. Use
|
|
123
|
+
`--keep-temp-doc` only when you need to inspect that intermediate document.
|
|
124
|
+
- Feishu image `authcode` URLs expire quickly, so image localization happens in
|
|
125
|
+
the same run as the Markdown export.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lark-doc-exporter"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Export Feishu/Lark docs with synced blocks to Markdown and themeable PDF"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"markdown>=3.7,<4",
|
|
13
|
+
"playwright>=1.54,<2",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.scripts]
|
|
17
|
+
lark-doc-exporter = "lark_synced_export.cli:main"
|
|
18
|
+
|
|
19
|
+
[dependency-groups]
|
|
20
|
+
dev = [
|
|
21
|
+
"pytest>=9,<10",
|
|
22
|
+
"ruff>=0.12,<1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[tool.ruff]
|
|
26
|
+
target-version = "py314"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools]
|
|
29
|
+
package-dir = {"" = "src"}
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
where = ["src"]
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.package-data]
|
|
35
|
+
lark_synced_export = [
|
|
36
|
+
"themes/*.css",
|
|
37
|
+
"skill_assets/lark-doc-exporter/SKILL.md",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.pytest.ini_options]
|
|
41
|
+
pythonpath = ["src"]
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lark-doc-exporter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Export Feishu/Lark docs with synced blocks to Markdown and themeable PDF
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: markdown<4,>=3.7
|
|
8
|
+
Requires-Dist: playwright<2,>=1.54
|
|
9
|
+
|
|
10
|
+
# lark-doc-exporter
|
|
11
|
+
|
|
12
|
+
Export Feishu/Lark docs with synced blocks expanded into:
|
|
13
|
+
|
|
14
|
+
- Markdown with localized images
|
|
15
|
+
- Themeable locally rendered PDF
|
|
16
|
+
|
|
17
|
+
The PDF path deliberately avoids the Feishu `docs_ai -> export pdf` route so the
|
|
18
|
+
final file does not include the AI disclaimer injected by that server-side path.
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- `lark-cli` configured with a user session
|
|
23
|
+
- Python 3.14
|
|
24
|
+
- A working Chrome/Chromium runtime, or the ability to install one with `uvx --from playwright playwright install chromium`
|
|
25
|
+
|
|
26
|
+
If you use `uvx` / `uv tool install`, `uv` can provision the required Python for
|
|
27
|
+
the tool environment automatically.
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv tool install lark-doc-exporter
|
|
33
|
+
lark-doc-exporter doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If Chromium is missing, prepare it once:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
uvx --from playwright playwright install chromium
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then run an export:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
lark-doc-exporter \
|
|
46
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
47
|
+
--output-dir exports/demo \
|
|
48
|
+
--formats markdown,pdf \
|
|
49
|
+
--theme default
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## One-off Run
|
|
53
|
+
|
|
54
|
+
If you do not want a persistent tool install:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uvx lark-doc-exporter \
|
|
58
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
59
|
+
--output-dir exports/demo \
|
|
60
|
+
--formats markdown,pdf \
|
|
61
|
+
--theme default
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Install As A Tool
|
|
65
|
+
|
|
66
|
+
After installing the released package, companion-skill operations stay the same:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
lark-doc-exporter skill install --dry-run
|
|
70
|
+
lark-doc-exporter skill install
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Auto mode installs the companion skill into every detected supported host:
|
|
74
|
+
|
|
75
|
+
- Codex: `~/.agents/skills/lark-doc-exporter`
|
|
76
|
+
- Claude Code: `~/.claude/skills/lark-doc-exporter`
|
|
77
|
+
|
|
78
|
+
Use `--host codex`, `--host claude`, or `--host all` to target specific hosts. `--dry-run` previews the install plan and target directories without writing files. Use `--force` only when you intentionally want to replace an existing unmanaged target directory.
|
|
79
|
+
|
|
80
|
+
## Chromium Setup
|
|
81
|
+
|
|
82
|
+
- `doctor` reports whether both `lark-cli` and Chromium are ready.
|
|
83
|
+
- If you already have a browser binary, you can point the exporter at it with `LARK_DOC_EXPORTER_CHROMIUM=/path/to/chromium`.
|
|
84
|
+
- If `LARK_DOC_EXPORTER_CHROMIUM` is set to a missing path, the command fails explicitly instead of silently falling back.
|
|
85
|
+
|
|
86
|
+
## Output
|
|
87
|
+
|
|
88
|
+
- `markdown` keeps the localized Markdown file in the output directory.
|
|
89
|
+
- `pdf` is rendered locally from the localized Markdown via HTML/CSS + Chromium.
|
|
90
|
+
- `images/` contains same-run localized image assets used by the Markdown/PDF.
|
|
91
|
+
|
|
92
|
+
## Themes
|
|
93
|
+
|
|
94
|
+
Built-in themes:
|
|
95
|
+
|
|
96
|
+
- `default`
|
|
97
|
+
- `company`
|
|
98
|
+
|
|
99
|
+
You can also layer custom CSS on top:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
lark-doc-exporter \
|
|
103
|
+
--doc "https://dynamia-ai.feishu.cn/wiki/WEgBwqGYOiBoQikRzjncvJDonAg" \
|
|
104
|
+
--output-dir exports/company \
|
|
105
|
+
--formats pdf \
|
|
106
|
+
--theme company \
|
|
107
|
+
--css /path/to/your-company-print.css
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Development / Unreleased
|
|
111
|
+
|
|
112
|
+
Use the Git URL or a local checkout only when you intentionally need unreleased code:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
uvx --from git+https://github.com/spencercjh/lark-doc-exporter lark-doc-exporter doctor
|
|
116
|
+
|
|
117
|
+
git clone https://github.com/spencercjh/lark-doc-exporter
|
|
118
|
+
cd lark-doc-exporter
|
|
119
|
+
uv sync --python 3.14 --group dev
|
|
120
|
+
make fmt
|
|
121
|
+
make ci
|
|
122
|
+
|
|
123
|
+
# Optional runtime/environment check (not part of required CI)
|
|
124
|
+
uv run lark-doc-exporter doctor
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Notes
|
|
128
|
+
|
|
129
|
+
- The current implementation still uses a temporary Feishu doc to translate the
|
|
130
|
+
expanded XML into fresh Markdown.
|
|
131
|
+
- The temporary doc is deleted by default after the Markdown export step. Use
|
|
132
|
+
`--keep-temp-doc` only when you need to inspect that intermediate document.
|
|
133
|
+
- Feishu image `authcode` URLs expire quickly, so image localization happens in
|
|
134
|
+
the same run as the Markdown export.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/lark_doc_exporter.egg-info/PKG-INFO
|
|
4
|
+
src/lark_doc_exporter.egg-info/SOURCES.txt
|
|
5
|
+
src/lark_doc_exporter.egg-info/dependency_links.txt
|
|
6
|
+
src/lark_doc_exporter.egg-info/entry_points.txt
|
|
7
|
+
src/lark_doc_exporter.egg-info/requires.txt
|
|
8
|
+
src/lark_doc_exporter.egg-info/top_level.txt
|
|
9
|
+
src/lark_synced_export/__init__.py
|
|
10
|
+
src/lark_synced_export/__main__.py
|
|
11
|
+
src/lark_synced_export/cli.py
|
|
12
|
+
src/lark_synced_export/doctor.py
|
|
13
|
+
src/lark_synced_export/exporter.py
|
|
14
|
+
src/lark_synced_export/markdown_runtime.py
|
|
15
|
+
src/lark_synced_export/pdf_runtime.py
|
|
16
|
+
src/lark_synced_export/release_version.py
|
|
17
|
+
src/lark_synced_export/skill_install.py
|
|
18
|
+
src/lark_synced_export/skill_assets/lark-doc-exporter/SKILL.md
|
|
19
|
+
src/lark_synced_export/themes/company.css
|
|
20
|
+
src/lark_synced_export/themes/default.css
|
|
21
|
+
tests/test_doctor.py
|
|
22
|
+
tests/test_exporter.py
|
|
23
|
+
tests/test_markdown_runtime.py
|
|
24
|
+
tests/test_pdf_runtime.py
|
|
25
|
+
tests/test_release_version.py
|
|
26
|
+
tests/test_skill_install.py
|
|
27
|
+
tests/test_theme_resolution.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lark_synced_export
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .doctor import run_doctor
|
|
9
|
+
from .exporter import export_document
|
|
10
|
+
from .skill_install import run_skill_install
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def parse_export_args(argv: list[str]) -> argparse.Namespace:
|
|
14
|
+
parser = argparse.ArgumentParser(
|
|
15
|
+
description="Expand Feishu/Lark synced blocks, export Markdown, and render local PDF.",
|
|
16
|
+
epilog=(
|
|
17
|
+
"Other commands:\n"
|
|
18
|
+
" doctor\n"
|
|
19
|
+
" skill install [--host {auto,codex,claude,all}] [--force] [--dry-run]"
|
|
20
|
+
),
|
|
21
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
22
|
+
)
|
|
23
|
+
parser.add_argument(
|
|
24
|
+
"--doc",
|
|
25
|
+
required=True,
|
|
26
|
+
help="Original docx/wiki URL or token accepted by `lark-cli docs +fetch`.",
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"--output-dir", required=True, help="Directory for output artifacts."
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--formats",
|
|
33
|
+
default="markdown,pdf",
|
|
34
|
+
help="Comma-separated export formats. Supported: markdown,pdf",
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--title-suffix",
|
|
38
|
+
default="(同步块展开导出)",
|
|
39
|
+
help="Suffix appended to the temporary expanded doc title.",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--file-stem",
|
|
43
|
+
default="",
|
|
44
|
+
help="Optional output filename stem. Defaults to the expanded doc title slug.",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--keep-temp-doc",
|
|
48
|
+
action="store_true",
|
|
49
|
+
help="Keep the temporary expanded doc instead of deleting it after the Markdown export step.",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--theme",
|
|
53
|
+
default="default",
|
|
54
|
+
help="Built-in PDF theme name. Supported: default, company.",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--css",
|
|
58
|
+
default="",
|
|
59
|
+
help="Optional extra CSS file layered on top of the selected theme for PDF output.",
|
|
60
|
+
)
|
|
61
|
+
return parser.parse_args(argv)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def parse_skill_install_args(argv: list[str]) -> argparse.Namespace:
|
|
65
|
+
parser = argparse.ArgumentParser(
|
|
66
|
+
prog="lark-doc-exporter skill install",
|
|
67
|
+
description="Install the bundled companion skill into Codex and/or Claude Code.",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--host",
|
|
71
|
+
choices=["auto", "codex", "claude", "all"],
|
|
72
|
+
default="auto",
|
|
73
|
+
help="Install target selection. Auto mode uses only already-detected hosts.",
|
|
74
|
+
)
|
|
75
|
+
parser.add_argument(
|
|
76
|
+
"--force",
|
|
77
|
+
action="store_true",
|
|
78
|
+
help="Overwrite an existing unmanaged target directory.",
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"--dry-run",
|
|
82
|
+
action="store_true",
|
|
83
|
+
help="Show planned target paths without writing files.",
|
|
84
|
+
)
|
|
85
|
+
return parser.parse_args(argv)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def run_main(argv: list[str] | None = None) -> int:
|
|
89
|
+
argv = list(argv if argv is not None else sys.argv[1:])
|
|
90
|
+
if argv and argv[0] == "doctor":
|
|
91
|
+
print(json.dumps(run_doctor(), ensure_ascii=False, indent=2))
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
if argv[:2] == ["skill", "install"]:
|
|
95
|
+
args = parse_skill_install_args(argv[2:])
|
|
96
|
+
print(
|
|
97
|
+
json.dumps(
|
|
98
|
+
run_skill_install(
|
|
99
|
+
host=args.host,
|
|
100
|
+
force=args.force,
|
|
101
|
+
dry_run=args.dry_run,
|
|
102
|
+
),
|
|
103
|
+
ensure_ascii=False,
|
|
104
|
+
indent=2,
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
return 0
|
|
108
|
+
|
|
109
|
+
if argv and argv[0] == "skill":
|
|
110
|
+
raise SystemExit(
|
|
111
|
+
"unsupported skill command; expected `lark-doc-exporter skill install`"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
args = parse_export_args(argv)
|
|
115
|
+
formats = [item.strip() for item in args.formats.split(",") if item.strip()]
|
|
116
|
+
allowed = {"markdown", "pdf"}
|
|
117
|
+
invalid = [fmt for fmt in formats if fmt not in allowed]
|
|
118
|
+
if invalid:
|
|
119
|
+
raise SystemExit(f"unsupported formats: {', '.join(invalid)}")
|
|
120
|
+
|
|
121
|
+
result = export_document(
|
|
122
|
+
doc_ref=args.doc,
|
|
123
|
+
output_dir=Path(args.output_dir).expanduser().resolve(),
|
|
124
|
+
formats=formats,
|
|
125
|
+
title_suffix=args.title_suffix,
|
|
126
|
+
file_stem=args.file_stem,
|
|
127
|
+
keep_temp_doc=args.keep_temp_doc,
|
|
128
|
+
theme_name=args.theme,
|
|
129
|
+
override_css=Path(args.css).expanduser().resolve() if args.css else None,
|
|
130
|
+
)
|
|
131
|
+
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
132
|
+
return 0
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def main() -> None:
|
|
136
|
+
try:
|
|
137
|
+
raise SystemExit(run_main())
|
|
138
|
+
except KeyboardInterrupt:
|
|
139
|
+
raise SystemExit(130) from None
|
|
140
|
+
except Exception as exc: # pragma: no cover - CLI boundary
|
|
141
|
+
sys.stderr.write(f"{exc}\n")
|
|
142
|
+
raise SystemExit(1) from exc
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
main()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
from .pdf_runtime import check_chromium_ready
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class DoctorCheck:
|
|
12
|
+
name: str
|
|
13
|
+
ok: bool
|
|
14
|
+
detail: str
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def check_lark_cli() -> DoctorCheck:
|
|
18
|
+
binary = shutil.which("lark-cli")
|
|
19
|
+
if not binary:
|
|
20
|
+
return DoctorCheck(
|
|
21
|
+
name="lark-cli",
|
|
22
|
+
ok=False,
|
|
23
|
+
detail="`lark-cli` is not on PATH. Install/configure it before running exports.",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
subprocess.run(
|
|
28
|
+
[binary, "--help"],
|
|
29
|
+
capture_output=True,
|
|
30
|
+
text=True,
|
|
31
|
+
check=True,
|
|
32
|
+
timeout=10,
|
|
33
|
+
)
|
|
34
|
+
except (OSError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:
|
|
35
|
+
return DoctorCheck(
|
|
36
|
+
name="lark-cli",
|
|
37
|
+
ok=False,
|
|
38
|
+
detail=f"`lark-cli` was found but is not runnable: {exc}",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return DoctorCheck(
|
|
42
|
+
name="lark-cli", ok=True, detail=f"`lark-cli` is available at {binary}."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def check_pdf_runtime() -> DoctorCheck:
|
|
47
|
+
ok, detail = check_chromium_ready()
|
|
48
|
+
return DoctorCheck(name="chromium", ok=ok, detail=detail)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def run_doctor() -> dict:
|
|
52
|
+
checks = [check_lark_cli(), check_pdf_runtime()]
|
|
53
|
+
return {
|
|
54
|
+
"ok": all(check.ok for check in checks),
|
|
55
|
+
"checks": [asdict(check) for check in checks],
|
|
56
|
+
}
|