codeannex 0.3.2__tar.gz → 0.3.4__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.2 → codeannex-0.3.4}/PKG-INFO +1 -1
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/core/pdf_builder.py +28 -24
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/PKG-INFO +1 -1
- {codeannex-0.3.2 → codeannex-0.3.4}/pyproject.toml +1 -1
- {codeannex-0.3.2 → codeannex-0.3.4}/LICENSE +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/README.md +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/__init__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/__main__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/core/__init__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/core/config.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/interface/__init__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/interface/cli.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/io/__init__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/io/file_utils.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/io/git_utils.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/renderer/__init__.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/renderer/fonts.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/renderer/highlight.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex/renderer/text_utils.py +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/SOURCES.txt +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/dependency_links.txt +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/entry_points.txt +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/requires.txt +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/codeannex.egg-info/top_level.txt +0 -0
- {codeannex-0.3.2 → codeannex-0.3.4}/setup.cfg +0 -0
|
@@ -133,7 +133,17 @@ class ModernAnnexPDF:
|
|
|
133
133
|
curr_y = self.config.page_height * 0.45
|
|
134
134
|
|
|
135
135
|
if project_name:
|
|
136
|
-
|
|
136
|
+
display_repo = f"{self.config.repo_label}{project_name}"
|
|
137
|
+
name_w = self._gsw(display_repo, self.config.normal_font, 14)
|
|
138
|
+
start_x = mid_x - name_w / 2
|
|
139
|
+
|
|
140
|
+
# Draw the name (blue if it has a link)
|
|
141
|
+
final_color = colors.HexColor(self.config.primary_color) if self.config.repo_url else text_color
|
|
142
|
+
self._dtf(start_x, curr_y, display_repo, self.config.normal_font, 14, final_color)
|
|
143
|
+
|
|
144
|
+
if self.config.repo_url:
|
|
145
|
+
self.c.linkURL(self.config.repo_url, (start_x, curr_y - 2, start_x + name_w, curr_y + 12), relative=0, thickness=0, border=None)
|
|
146
|
+
|
|
137
147
|
curr_y -= 8*mm
|
|
138
148
|
|
|
139
149
|
# 4. Technical Metadata (Branch | Commit)
|
|
@@ -147,13 +157,6 @@ class ModernAnnexPDF:
|
|
|
147
157
|
tech_str = " | ".join(tech_items)
|
|
148
158
|
self._dctf(mid_x, curr_y, tech_str, self.config.normal_font, 10, colors.HexColor("#6c7086"))
|
|
149
159
|
curr_y -= 12*mm
|
|
150
|
-
|
|
151
|
-
if self.config.repo_url:
|
|
152
|
-
url = self.config.repo_url
|
|
153
|
-
url_w = self._gsw(url, self.config.normal_font, 11)
|
|
154
|
-
start_x = mid_x - url_w / 2
|
|
155
|
-
self._dtf(start_x, curr_y, url, self.config.normal_font, 11, colors.HexColor(self.config.primary_color))
|
|
156
|
-
self.c.linkURL(url, (start_x, curr_y - 2, start_x + url_w, curr_y + 10), relative=0, thickness=0, border=None)
|
|
157
160
|
|
|
158
161
|
def draw_summary_page(self, files: list):
|
|
159
162
|
self.start_new_page()
|
|
@@ -163,7 +166,16 @@ class ModernAnnexPDF:
|
|
|
163
166
|
title_font, 16, colors.HexColor(self.config.title_color))
|
|
164
167
|
self.y -= 12*mm
|
|
165
168
|
nested_tree: dict = {"_files": []}
|
|
169
|
+
|
|
170
|
+
# To avoid double entries for SVG (Image + Code)
|
|
171
|
+
processed_paths = set()
|
|
172
|
+
unique_files = []
|
|
166
173
|
for fpath, ftype in files:
|
|
174
|
+
if fpath not in processed_paths:
|
|
175
|
+
unique_files.append((fpath, ftype))
|
|
176
|
+
processed_paths.add(fpath)
|
|
177
|
+
|
|
178
|
+
for fpath, ftype in unique_files:
|
|
167
179
|
rel = fpath.relative_to(self.project_root)
|
|
168
180
|
curr = nested_tree
|
|
169
181
|
for part in rel.parts[:-1]: curr = curr.setdefault(part, {"_files": []})
|
|
@@ -174,10 +186,7 @@ class ModernAnnexPDF:
|
|
|
174
186
|
def _draw_recursive_summary(self, node: dict, depth: int, path_parts: list, is_last_list: list):
|
|
175
187
|
subdirs = sorted([k for k in node.keys() if k != "_files"], key=str.lower)
|
|
176
188
|
files_in_node = node.get("_files", [])
|
|
177
|
-
|
|
178
|
-
# Subdirectories first, then files (matches the new sort_files logic)
|
|
179
189
|
all_entries = [(d, "dir") for d in subdirs] + [(f, "file") for f in files_in_node]
|
|
180
|
-
|
|
181
190
|
indent_step, text_color = 5*mm, colors.HexColor(self.config.normal_text_color)
|
|
182
191
|
for i, (item, type) in enumerate(all_entries):
|
|
183
192
|
is_last = (i == len(all_entries) - 1)
|
|
@@ -204,9 +213,9 @@ class ModernAnnexPDF:
|
|
|
204
213
|
self.y -= 6*mm
|
|
205
214
|
if type == "dir": self._draw_recursive_summary(node[item], depth + 1, path_parts + [item], is_last_list + [is_last])
|
|
206
215
|
|
|
207
|
-
def render_text_file(self, fpath: Path
|
|
216
|
+
def render_text_file(self, fpath: Path):
|
|
208
217
|
rel = fpath.relative_to(self.project_root).as_posix()
|
|
209
|
-
display_name, bookmark_key = rel
|
|
218
|
+
display_name, bookmark_key = rel, _make_bookmark_key(rel)
|
|
210
219
|
try: content = fpath.read_text(encoding="utf-8", errors="replace")
|
|
211
220
|
except: return
|
|
212
221
|
self._check_space(25*mm)
|
|
@@ -224,10 +233,8 @@ class ModernAnnexPDF:
|
|
|
224
233
|
else:
|
|
225
234
|
lexer = get_lexer_for_filename(str(fpath), stripnl=False)
|
|
226
235
|
except ClassNotFound:
|
|
227
|
-
if not self.is_simulation:
|
|
228
|
-
print(f"ℹ️ Highlighting fallback: No lexer for '{fpath.name}'. Using plain text.")
|
|
236
|
+
if not self.is_simulation: print(f"ℹ️ Highlighting fallback: No lexer for '{fpath.name}'. Using plain text.")
|
|
229
237
|
lexer = TextLexer(stripnl=False)
|
|
230
|
-
|
|
231
238
|
self._render_tokens_to_lines(lexer.get_tokens(content or " "), display_name, bookmark_parts, total_parts)
|
|
232
239
|
self.y -= 4*mm
|
|
233
240
|
|
|
@@ -289,20 +296,18 @@ class ModernAnnexPDF:
|
|
|
289
296
|
if line_num is not None:
|
|
290
297
|
num_str = str(line_num)
|
|
291
298
|
num_char_w = pdfmetrics.stringWidth("0", self.mono_font, self.config.code_font_size)
|
|
292
|
-
# Increase box size from 0.8 to 0.9 for better legibility
|
|
293
299
|
box_hw = self.config.code_font_size * 0.9
|
|
294
300
|
start_x = self.config.margin_left + GUTTER_W - 2.5*mm - len(num_str) * num_char_w
|
|
295
301
|
for char in num_str:
|
|
296
|
-
# Improved vertical centering
|
|
297
302
|
self.c.drawImage(get_digit_sprites()[char], start_x + (num_char_w - box_hw) / 2.0, (self.y - self.config.code_font_size - 1.5) - box_hw * 0.1, width=box_hw, height=box_hw, mask="auto")
|
|
298
303
|
start_x += num_char_w
|
|
299
304
|
code_x = self.config.get_code_x() + 2*mm
|
|
300
305
|
for chunk, color in v_line:
|
|
301
306
|
code_x = draw_text_with_fallback(self.c, code_x, self.y - self.config.code_font_size - 1, chunk, self.mono_font, self.config.code_font_size, self.emoji_font, color, emoji_description=self.config.emoji_description)
|
|
302
307
|
|
|
303
|
-
def render_image_file(self, fpath: Path
|
|
308
|
+
def render_image_file(self, fpath: Path):
|
|
304
309
|
rel = fpath.relative_to(self.project_root).as_posix()
|
|
305
|
-
self._check_space(40*mm); self._register_bookmark(rel
|
|
310
|
+
self._check_space(40*mm); self._register_bookmark(rel, _make_bookmark_key(rel)); self._draw_file_header(rel)
|
|
306
311
|
self._draw_image(fpath)
|
|
307
312
|
|
|
308
313
|
def _draw_image(self, fpath):
|
|
@@ -322,7 +327,7 @@ class ModernAnnexPDF:
|
|
|
322
327
|
draw_y, block_bottom, block_w = self.y - draw_h - padding, self.y - draw_h - 2*padding, self.config.page_width - self.config.margin_left - self.config.margin_right
|
|
323
328
|
if not self.is_simulation:
|
|
324
329
|
self.c.setFillColor(colors.HexColor("#ffffff")); self.c.rect(self.config.margin_left, block_bottom, block_w, self.y - block_bottom, fill=1, stroke=0)
|
|
325
|
-
self.c.setStrokeColor(colors.HexColor("#e6e9ef")); self.c.setLineWidth(0
|
|
330
|
+
self.c.setStrokeColor(colors.HexColor("#e6e9ef")); self.c.setLineWidth(1.0); self.c.rect(self.config.margin_left, block_bottom, block_w, self.y - block_bottom, fill=0, stroke=1)
|
|
326
331
|
draw_x = self.config.margin_left + (block_w - draw_w) / 2
|
|
327
332
|
if img is None and png_data: img = PilImage.open(io.BytesIO(png_data))
|
|
328
333
|
if img: self.c.drawImage(ImageReader(img), draw_x, draw_y, draw_w, draw_h, preserveAspectRatio=True, mask="auto")
|
|
@@ -337,7 +342,6 @@ class ModernAnnexPDF:
|
|
|
337
342
|
self.draw_cover(); self.draw_summary_page(files)
|
|
338
343
|
for i, (fpath, ftype) in enumerate(files):
|
|
339
344
|
if not self.is_simulation: print(f"\r\033[K[{i+1}/{len(files)}] Processing: {fpath.name}", end="")
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
elif ftype == "image": self.render_image_file(fpath, label_suffix=suffix)
|
|
345
|
+
if ftype == "text": self.render_text_file(fpath)
|
|
346
|
+
elif ftype == "image": self.render_image_file(fpath)
|
|
343
347
|
if not self.is_simulation: print(); self.c.save()
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codeannex"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.4"
|
|
8
8
|
description = "Generates a professional PDF source code annex with Smart Index, Images and Emoji support."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|