codeannex 0.2.0__tar.gz → 0.3.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.
- codeannex-0.3.0/PKG-INFO +112 -0
- codeannex-0.3.0/README.md +81 -0
- codeannex-0.3.0/codeannex/__main__.py +136 -0
- codeannex-0.3.0/codeannex/core/__init__.py +0 -0
- {codeannex-0.2.0/codeannex → codeannex-0.3.0/codeannex/core}/config.py +20 -32
- codeannex-0.3.0/codeannex/core/pdf_builder.py +333 -0
- codeannex-0.3.0/codeannex/interface/__init__.py +0 -0
- codeannex-0.3.0/codeannex/interface/cli.py +142 -0
- codeannex-0.3.0/codeannex/io/__init__.py +0 -0
- codeannex-0.3.0/codeannex/io/file_utils.py +108 -0
- codeannex-0.3.0/codeannex/io/git_utils.py +45 -0
- codeannex-0.3.0/codeannex/renderer/__init__.py +0 -0
- codeannex-0.3.0/codeannex/renderer/fonts.py +195 -0
- codeannex-0.3.0/codeannex/renderer/highlight.py +22 -0
- codeannex-0.3.0/codeannex/renderer/text_utils.py +59 -0
- codeannex-0.3.0/codeannex.egg-info/PKG-INFO +112 -0
- codeannex-0.3.0/codeannex.egg-info/SOURCES.txt +23 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/pyproject.toml +1 -1
- codeannex-0.2.0/PKG-INFO +0 -116
- codeannex-0.2.0/README.md +0 -85
- codeannex-0.2.0/codeannex/__main__.py +0 -249
- codeannex-0.2.0/codeannex/file_utils.py +0 -116
- codeannex-0.2.0/codeannex/fonts.py +0 -275
- codeannex-0.2.0/codeannex/highlight.py +0 -21
- codeannex-0.2.0/codeannex/pdf_builder.py +0 -492
- codeannex-0.2.0/codeannex/text_utils.py +0 -131
- codeannex-0.2.0/codeannex.egg-info/PKG-INFO +0 -116
- codeannex-0.2.0/codeannex.egg-info/SOURCES.txt +0 -24
- codeannex-0.2.0/tests/test_emoji.py +0 -119
- codeannex-0.2.0/tests/test_file_management.py +0 -48
- codeannex-0.2.0/tests/test_fonts_dynamic.py +0 -47
- codeannex-0.2.0/tests/test_interactive.py +0 -65
- codeannex-0.2.0/tests/test_pdf_layout.py +0 -94
- codeannex-0.2.0/tests/test_summary_hierarchy.py +0 -56
- codeannex-0.2.0/tests/test_text_utils.py +0 -25
- {codeannex-0.2.0 → codeannex-0.3.0}/LICENSE +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/codeannex/__init__.py +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/codeannex.egg-info/dependency_links.txt +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/codeannex.egg-info/entry_points.txt +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/codeannex.egg-info/requires.txt +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/codeannex.egg-info/top_level.txt +0 -0
- {codeannex-0.2.0 → codeannex-0.3.0}/setup.cfg +0 -0
codeannex-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codeannex
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Generates a professional PDF source code annex with Smart Index, Images and Emoji support.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Repository, https://github.com/tanhleno/codeannex
|
|
7
|
+
Keywords: pdf,source-code,documentation,annex,reportlab,emoji
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Documentation
|
|
17
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: reportlab>=4.0
|
|
22
|
+
Requires-Dist: Pillow>=10.0
|
|
23
|
+
Requires-Dist: Pygments>=2.16
|
|
24
|
+
Requires-Dist: pdfminer.six>=20231228
|
|
25
|
+
Provides-Extra: svg
|
|
26
|
+
Requires-Dist: cairosvg>=2.7; extra == "svg"
|
|
27
|
+
Requires-Dist: svglib>=1.5; extra == "svg"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# 📂 codeannex
|
|
33
|
+
|
|
34
|
+
Generates a professional PDF annex from a project's source code — with syntax highlighting, a hierarchical table of contents, image rendering, and intelligent font discovery.
|
|
35
|
+
|
|
36
|
+
## 🚀 Key Features
|
|
37
|
+
|
|
38
|
+
- **Interactive Wizard 2.0** — Organized by sections (Project, Style, Typography, Layout, Filters) with smart defaults and explicit (Y/n) prompts.
|
|
39
|
+
- **Git Integration & Version Tracking** — Automatically detects Repository URL, Branch, and **Commit SHA**. Supports subdirectories by intelligently ignoring Git metadata if not at the root.
|
|
40
|
+
- **Subdirectories First** — Improved document organization by listing subdirectories and their contents before root files.
|
|
41
|
+
- **Flexible File Filtering** — Multi-pattern include and exclude glob filters (e.g., `--include "src/*" --exclude "tests/*"`).
|
|
42
|
+
- **Intelligent Font Discovery** — Automatically finds fonts from your system (Windows, Linux, macOS) or custom paths via `--font-path`.
|
|
43
|
+
- **Fully Customizable UI** — Control everything: paper size (mm), margins (cm), colors (HEX), and font sizes.
|
|
44
|
+
- **Hierarchical Summary** — Real tree-structured Table of Contents with increasing page numbers and terminal-like connection lines.
|
|
45
|
+
- **Professional Design** — High-contrast line numbers, clean cover page, and smart contrast (auto-switching text between black/white based on accent brightness).
|
|
46
|
+
|
|
47
|
+
## 🛠 Installation
|
|
48
|
+
|
|
49
|
+
The recommended way to install **codeannex** is via [pipx](https://github.com/pypa/pipx), which installs the tool in an isolated environment:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pipx install codeannex
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For full SVG support (required for crisp line numbers and SVG image rendering):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pipx install "codeannex[svg]"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
*Alternatively, you can use standard pip:* `pip install codeannex`
|
|
62
|
+
|
|
63
|
+
## 📖 Usage
|
|
64
|
+
|
|
65
|
+
### Interactive Mode (Wizard)
|
|
66
|
+
Simply run without arguments to start the step-by-step configuration:
|
|
67
|
+
```bash
|
|
68
|
+
python3 -m codeannex
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Automation / CI
|
|
72
|
+
```bash
|
|
73
|
+
python3 -m codeannex . \
|
|
74
|
+
--cover-title "Technical Annex" \
|
|
75
|
+
--primary-color "#0f4761" \
|
|
76
|
+
--code-size 9 \
|
|
77
|
+
--include "src/*" \
|
|
78
|
+
--exclude "*.log" \
|
|
79
|
+
--no-input
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## ⚙️ Configuration Options
|
|
83
|
+
|
|
84
|
+
### Git & Metadata
|
|
85
|
+
- `--repo-url URL` — Manual repository URL.
|
|
86
|
+
- `--branch NAME` — Manual branch name.
|
|
87
|
+
- `--no-git` — Force disable Git integration.
|
|
88
|
+
- `--repo-label LABEL` — Label for repo (default: "Repository Name: ").
|
|
89
|
+
|
|
90
|
+
### File Selection
|
|
91
|
+
- `--include PATTERN` — Include glob pattern (can be used multiple times).
|
|
92
|
+
- `--exclude PATTERN` — Exclude glob pattern (can be used multiple times).
|
|
93
|
+
|
|
94
|
+
### Design & Layout
|
|
95
|
+
- `--page-width MM` / `--page-height MM` — Custom paper size in mm (default: A4).
|
|
96
|
+
- `--margin CM` — General margin (top, bottom, left, right).
|
|
97
|
+
- `--primary-color HEX` — Accent color for headers and summary icons.
|
|
98
|
+
- `--code-size N` — Font size for code and line numbers.
|
|
99
|
+
|
|
100
|
+
### Fonts
|
|
101
|
+
- `--font-path PATH` — Additional directory to search for `.ttf`/`.otf` files.
|
|
102
|
+
- `--title-font` / `--normal-font` / `--mono-font` — System font names.
|
|
103
|
+
|
|
104
|
+
## 🧪 Testing
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
PYTHONPATH=. pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 📄 License
|
|
111
|
+
|
|
112
|
+
MIT
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# 📂 codeannex
|
|
2
|
+
|
|
3
|
+
Generates a professional PDF annex from a project's source code — with syntax highlighting, a hierarchical table of contents, image rendering, and intelligent font discovery.
|
|
4
|
+
|
|
5
|
+
## 🚀 Key Features
|
|
6
|
+
|
|
7
|
+
- **Interactive Wizard 2.0** — Organized by sections (Project, Style, Typography, Layout, Filters) with smart defaults and explicit (Y/n) prompts.
|
|
8
|
+
- **Git Integration & Version Tracking** — Automatically detects Repository URL, Branch, and **Commit SHA**. Supports subdirectories by intelligently ignoring Git metadata if not at the root.
|
|
9
|
+
- **Subdirectories First** — Improved document organization by listing subdirectories and their contents before root files.
|
|
10
|
+
- **Flexible File Filtering** — Multi-pattern include and exclude glob filters (e.g., `--include "src/*" --exclude "tests/*"`).
|
|
11
|
+
- **Intelligent Font Discovery** — Automatically finds fonts from your system (Windows, Linux, macOS) or custom paths via `--font-path`.
|
|
12
|
+
- **Fully Customizable UI** — Control everything: paper size (mm), margins (cm), colors (HEX), and font sizes.
|
|
13
|
+
- **Hierarchical Summary** — Real tree-structured Table of Contents with increasing page numbers and terminal-like connection lines.
|
|
14
|
+
- **Professional Design** — High-contrast line numbers, clean cover page, and smart contrast (auto-switching text between black/white based on accent brightness).
|
|
15
|
+
|
|
16
|
+
## 🛠 Installation
|
|
17
|
+
|
|
18
|
+
The recommended way to install **codeannex** is via [pipx](https://github.com/pypa/pipx), which installs the tool in an isolated environment:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pipx install codeannex
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For full SVG support (required for crisp line numbers and SVG image rendering):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pipx install "codeannex[svg]"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
*Alternatively, you can use standard pip:* `pip install codeannex`
|
|
31
|
+
|
|
32
|
+
## 📖 Usage
|
|
33
|
+
|
|
34
|
+
### Interactive Mode (Wizard)
|
|
35
|
+
Simply run without arguments to start the step-by-step configuration:
|
|
36
|
+
```bash
|
|
37
|
+
python3 -m codeannex
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Automation / CI
|
|
41
|
+
```bash
|
|
42
|
+
python3 -m codeannex . \
|
|
43
|
+
--cover-title "Technical Annex" \
|
|
44
|
+
--primary-color "#0f4761" \
|
|
45
|
+
--code-size 9 \
|
|
46
|
+
--include "src/*" \
|
|
47
|
+
--exclude "*.log" \
|
|
48
|
+
--no-input
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## ⚙️ Configuration Options
|
|
52
|
+
|
|
53
|
+
### Git & Metadata
|
|
54
|
+
- `--repo-url URL` — Manual repository URL.
|
|
55
|
+
- `--branch NAME` — Manual branch name.
|
|
56
|
+
- `--no-git` — Force disable Git integration.
|
|
57
|
+
- `--repo-label LABEL` — Label for repo (default: "Repository Name: ").
|
|
58
|
+
|
|
59
|
+
### File Selection
|
|
60
|
+
- `--include PATTERN` — Include glob pattern (can be used multiple times).
|
|
61
|
+
- `--exclude PATTERN` — Exclude glob pattern (can be used multiple times).
|
|
62
|
+
|
|
63
|
+
### Design & Layout
|
|
64
|
+
- `--page-width MM` / `--page-height MM` — Custom paper size in mm (default: A4).
|
|
65
|
+
- `--margin CM` — General margin (top, bottom, left, right).
|
|
66
|
+
- `--primary-color HEX` — Accent color for headers and summary icons.
|
|
67
|
+
- `--code-size N` — Font size for code and line numbers.
|
|
68
|
+
|
|
69
|
+
### Fonts
|
|
70
|
+
- `--font-path PATH` — Additional directory to search for `.ttf`/`.otf` files.
|
|
71
|
+
- `--title-font` / `--normal-font` / `--mono-font` — System font names.
|
|
72
|
+
|
|
73
|
+
## 🧪 Testing
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
PYTHONPATH=. pytest
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 📄 License
|
|
80
|
+
|
|
81
|
+
MIT
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .core.config import PDFConfig
|
|
7
|
+
from .core.pdf_builder import ModernAnnexPDF
|
|
8
|
+
from .io.file_utils import get_project_files, classify_file, sort_files
|
|
9
|
+
from .io.git_utils import get_git_info
|
|
10
|
+
from .renderer.fonts import init_sprites, register_best_font, register_emoji_font, auto_register_font, ADDITIONAL_SEARCH_PATHS
|
|
11
|
+
from .interface.cli import parse_args, run_interactive_wizard
|
|
12
|
+
from reportlab.lib.units import cm
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def check_emoji_font_style():
|
|
16
|
+
emoji_font = register_emoji_font()
|
|
17
|
+
if emoji_font:
|
|
18
|
+
print(f"✅ Emoji font registered: {emoji_font}")
|
|
19
|
+
print("💡 Tip: Install Google Noto fonts for authentic Google emoji style")
|
|
20
|
+
else:
|
|
21
|
+
print("⚠️ No emoji font found - emojis may not render correctly")
|
|
22
|
+
return emoji_font
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
args, unknown = parse_args()
|
|
27
|
+
is_interactive = len(sys.argv) <= 2 and not args.no_input
|
|
28
|
+
if is_interactive: run_interactive_wizard(args)
|
|
29
|
+
|
|
30
|
+
# Register additional search paths first
|
|
31
|
+
if args.font_path:
|
|
32
|
+
ADDITIONAL_SEARCH_PATHS.extend(args.font_path)
|
|
33
|
+
|
|
34
|
+
if args.normal_font: args.normal_font = auto_register_font(args.normal_font, required=True)
|
|
35
|
+
if args.bold_font: args.bold_font = auto_register_font(args.bold_font, required=True)
|
|
36
|
+
if args.title_font: args.title_font = auto_register_font(args.title_font, required=True)
|
|
37
|
+
if args.subtitle_font: args.subtitle_font = auto_register_font(args.subtitle_font, required=True)
|
|
38
|
+
if args.mono_font: args.mono_font = auto_register_font(args.mono_font, required=True)
|
|
39
|
+
if args.emoji_font: args.emoji_font = auto_register_font(args.emoji_font, required=True)
|
|
40
|
+
|
|
41
|
+
if unknown:
|
|
42
|
+
for u in unknown:
|
|
43
|
+
if u.startswith("-"): print(f"⚠️ Warning: Unrecognized argument ignored: {u}")
|
|
44
|
+
|
|
45
|
+
if args.check_emoji_font:
|
|
46
|
+
check_emoji_font_style()
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
root, output = Path(args.dir).resolve(), args.output or f"{Path(args.dir).resolve().name}_anexo_codigo.pdf"
|
|
50
|
+
use_git = not args.no_git
|
|
51
|
+
git_url, git_branch, git_sha = get_git_info(root, use_git=use_git)
|
|
52
|
+
repo_url, branch_name = args.repo_url or git_url, args.branch or git_branch
|
|
53
|
+
|
|
54
|
+
mono_font, is_ttf, ttf_path = register_best_font()
|
|
55
|
+
emoji_font = register_emoji_font(error_on_missing=not args.emoji_description)
|
|
56
|
+
init_sprites(is_ttf, ttf_path)
|
|
57
|
+
|
|
58
|
+
def get_margin(spec, general, default):
|
|
59
|
+
if spec is not None: return spec * cm
|
|
60
|
+
if general is not None: return general * cm
|
|
61
|
+
return default
|
|
62
|
+
|
|
63
|
+
from reportlab.lib.units import mm
|
|
64
|
+
config = PDFConfig(
|
|
65
|
+
project_name=args.name or root.name,
|
|
66
|
+
margin_left=get_margin(args.margin_left, args.margin, PDFConfig().margin_left),
|
|
67
|
+
margin_right=get_margin(args.margin_right, args.margin, PDFConfig().margin_right),
|
|
68
|
+
margin_top=get_margin(args.margin_top, args.margin, PDFConfig().margin_top),
|
|
69
|
+
margin_bottom=get_margin(args.margin_bottom, args.margin, PDFConfig().margin_bottom),
|
|
70
|
+
page_width=args.page_width * mm if args.page_width else PDFConfig().page_width,
|
|
71
|
+
page_height=args.page_height * mm if args.page_height else PDFConfig().page_height,
|
|
72
|
+
start_page_num=args.start_page,
|
|
73
|
+
show_project_name=args.show_project,
|
|
74
|
+
normal_font=args.normal_font or PDFConfig().normal_font,
|
|
75
|
+
bold_font=args.bold_font or PDFConfig().bold_font,
|
|
76
|
+
mono_font=args.mono_font or mono_font,
|
|
77
|
+
emoji_font=args.emoji_font or emoji_font,
|
|
78
|
+
emoji_description=args.emoji_description,
|
|
79
|
+
repo_url=repo_url,
|
|
80
|
+
branch_name=branch_name,
|
|
81
|
+
commit_sha=git_sha,
|
|
82
|
+
page_number_size=args.page_number_size,
|
|
83
|
+
title_font=args.title_font,
|
|
84
|
+
title_size=args.title_size,
|
|
85
|
+
title_color=args.title_color,
|
|
86
|
+
subtitle_font=args.subtitle_font,
|
|
87
|
+
subtitle_size=args.subtitle_size,
|
|
88
|
+
subtitle_color=args.subtitle_color,
|
|
89
|
+
normal_text_size=args.normal_size,
|
|
90
|
+
normal_text_color=args.normal_color,
|
|
91
|
+
page_number_format=args.page_number_format,
|
|
92
|
+
show_page_numbers=not args.no_page_numbers,
|
|
93
|
+
cover_title=args.cover_title,
|
|
94
|
+
primary_color=args.primary_color,
|
|
95
|
+
cover_subtitle=args.cover_subtitle,
|
|
96
|
+
summary_title=args.summary_title,
|
|
97
|
+
repo_label=args.repo_label,
|
|
98
|
+
project_label=args.project_label,
|
|
99
|
+
file_part_format=args.file_part_format,
|
|
100
|
+
code_font_size=args.code_size,
|
|
101
|
+
code_bg_color=args.code_bg,
|
|
102
|
+
page_bg_color=args.page_bg_color,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
all_files = sort_files(get_project_files(root, includes=args.include, excludes=args.exclude, use_git=use_git), root)
|
|
106
|
+
included = []
|
|
107
|
+
from .core.config import IMAGE_EXTENSIONS, BINARY_EXTENSIONS
|
|
108
|
+
script_path, output_path = Path(__file__).resolve(), Path(output).resolve()
|
|
109
|
+
|
|
110
|
+
for fp in all_files:
|
|
111
|
+
try:
|
|
112
|
+
if fp.resolve() in (script_path, output_path): continue
|
|
113
|
+
except: pass
|
|
114
|
+
if not fp.is_file(): continue
|
|
115
|
+
ext = fp.suffix.lower()
|
|
116
|
+
if ext == ".svg": included += [(fp, "image"), (fp, "text")]
|
|
117
|
+
elif ext in IMAGE_EXTENSIONS: included.append((fp, "image"))
|
|
118
|
+
elif ext in BINARY_EXTENSIONS: continue
|
|
119
|
+
elif classify_file(fp) == "text": included.append((fp, "text"))
|
|
120
|
+
|
|
121
|
+
if not included:
|
|
122
|
+
print("❌ No compatible files found."); return
|
|
123
|
+
|
|
124
|
+
print(f"🧮 Step 1/2: Simulating layout of {len(included)} files...")
|
|
125
|
+
pdf_sim = ModernAnnexPDF(io.BytesIO(), root, mono_font, emoji_font, config)
|
|
126
|
+
pdf_sim.is_simulation = True
|
|
127
|
+
pdf_sim.build(included)
|
|
128
|
+
|
|
129
|
+
print("🚀 Step 2/2: Generating the final document...")
|
|
130
|
+
pdf_final = ModernAnnexPDF(output, root, mono_font, emoji_font, config)
|
|
131
|
+
pdf_final.summary_data = pdf_sim.summary_data
|
|
132
|
+
pdf_final.build(included)
|
|
133
|
+
print(f"✅ Success! Saved to: {output}")
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
main()
|
|
File without changes
|
|
@@ -29,64 +29,52 @@ COLOR_ACCENT = colors.HexColor("#89b4fa")
|
|
|
29
29
|
NORMAL_FONT = "Helvetica"
|
|
30
30
|
BOLD_FONT = "Helvetica-Bold"
|
|
31
31
|
|
|
32
|
-
# ── Supported image extensions ───────────────
|
|
33
32
|
IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".ico", ".gif", ".webp", ".bmp", ".svg"}
|
|
34
|
-
|
|
35
|
-
# ── Binary extensions to ignore quickly ──────
|
|
36
|
-
BINARY_EXTENSIONS = {".pdf", ".pyc", ".pyo", ".exe", ".dll", ".so", ".dylib",
|
|
37
|
-
".zip", ".tar", ".gz", ".rar", ".7z", ".jar", ".whl",
|
|
38
|
-
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx"}
|
|
39
|
-
|
|
33
|
+
BINARY_EXTENSIONS = {".pdf", ".pyc", ".pyo", ".exe", ".dll", ".so", ".dylib", ".zip", ".tar", ".gz", ".rar", ".7z", ".jar", ".whl"}
|
|
40
34
|
|
|
41
35
|
@dataclass
|
|
42
36
|
class PDFConfig:
|
|
43
|
-
"""PDF configuration for code annex."""
|
|
44
37
|
project_name: str | None = None
|
|
45
38
|
margin_left: float = _DEFAULT_MARGIN_LEFT
|
|
46
39
|
margin_right: float = _DEFAULT_MARGIN_RIGHT
|
|
47
40
|
margin_top: float = _DEFAULT_MARGIN_TOP
|
|
48
41
|
margin_bottom: float = _DEFAULT_MARGIN_BOTTOM
|
|
42
|
+
page_width: float = PAGE_W
|
|
43
|
+
page_height: float = PAGE_H
|
|
49
44
|
start_page_num: int = 1
|
|
50
45
|
show_project_name: bool = False
|
|
51
46
|
normal_font: str = NORMAL_FONT
|
|
52
47
|
bold_font: str = BOLD_FONT
|
|
53
|
-
mono_font: str | None = None
|
|
54
|
-
emoji_font: str | None = None
|
|
55
|
-
emoji_description: bool = False
|
|
56
|
-
repo_url: str | None = None
|
|
57
|
-
|
|
48
|
+
mono_font: str | None = None
|
|
49
|
+
emoji_font: str | None = None
|
|
50
|
+
emoji_description: bool = False
|
|
51
|
+
repo_url: str | None = None
|
|
52
|
+
branch_name: str | None = None
|
|
53
|
+
commit_sha: str | None = None
|
|
54
|
+
page_number_size: int = 8
|
|
58
55
|
|
|
59
|
-
# Customization fields
|
|
60
56
|
title_font: str | None = None
|
|
61
57
|
title_size: int = 28
|
|
62
58
|
title_color: str = "#1e1e2e"
|
|
63
59
|
subtitle_font: str | None = None
|
|
64
60
|
subtitle_size: int = 18
|
|
65
|
-
subtitle_color: str | None = None
|
|
61
|
+
subtitle_color: str | None = None
|
|
66
62
|
normal_text_size: int = 10
|
|
67
|
-
normal_text_color: str = "#4c4f69"
|
|
68
|
-
page_number_format: str = "{n}"
|
|
63
|
+
normal_text_color: str = "#4c4f69"
|
|
64
|
+
page_number_format: str = "{n}"
|
|
69
65
|
show_page_numbers: bool = True
|
|
70
66
|
cover_title: str = "TECHNICAL ANNEX"
|
|
71
67
|
cover_subtitle: str = "Source Code Documentation"
|
|
72
|
-
primary_color: str = "#1e66f5"
|
|
68
|
+
primary_color: str = "#1e66f5"
|
|
73
69
|
|
|
74
|
-
# Code style
|
|
75
70
|
code_font_size: int = CODE_FONT_SIZE
|
|
76
|
-
code_bg_color: str = "#1e1e2e"
|
|
77
|
-
page_bg_color: str = "#ffffff"
|
|
71
|
+
code_bg_color: str = "#1e1e2e"
|
|
72
|
+
page_bg_color: str = "#ffffff"
|
|
78
73
|
|
|
79
|
-
# Labels (Internationalization)
|
|
80
74
|
summary_title: str = "Summary / File Index"
|
|
81
|
-
repo_label: str = "Repository: "
|
|
75
|
+
repo_label: str = "Repository Name: "
|
|
82
76
|
project_label: str = "Project: "
|
|
83
|
-
file_part_format: str = "({current}/{total})"
|
|
84
|
-
cover_subtitle: str = "Source Code Documentation"
|
|
85
|
-
|
|
86
|
-
def get_code_x(self) -> float:
|
|
87
|
-
"""Calculates the initial X position of the code."""
|
|
88
|
-
return self.margin_left + GUTTER_W
|
|
77
|
+
file_part_format: str = "(part {current}/{total})"
|
|
89
78
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
return PAGE_W - self.get_code_x() - self.margin_right
|
|
79
|
+
def get_code_x(self) -> float: return self.margin_left + GUTTER_W
|
|
80
|
+
def get_code_w(self) -> float: return self.page_width - self.get_code_x() - self.margin_right
|