kk-codeimg 0.0.1__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.
- kk_codeimg-0.0.1/LICENSE +21 -0
- kk_codeimg-0.0.1/PKG-INFO +282 -0
- kk_codeimg-0.0.1/README.md +291 -0
- kk_codeimg-0.0.1/README_PYPI.md +246 -0
- kk_codeimg-0.0.1/kk_codeimg/__init__.py +126 -0
- kk_codeimg-0.0.1/kk_codeimg/contrast.py +115 -0
- kk_codeimg-0.0.1/kk_codeimg/palette.py +347 -0
- kk_codeimg-0.0.1/kk_codeimg/py.typed +0 -0
- kk_codeimg-0.0.1/kk_codeimg/renderer.py +641 -0
- kk_codeimg-0.0.1/kk_codeimg/styles.py +233 -0
- kk_codeimg-0.0.1/kk_codeimg.egg-info/PKG-INFO +282 -0
- kk_codeimg-0.0.1/kk_codeimg.egg-info/SOURCES.txt +15 -0
- kk_codeimg-0.0.1/kk_codeimg.egg-info/dependency_links.txt +1 -0
- kk_codeimg-0.0.1/kk_codeimg.egg-info/requires.txt +7 -0
- kk_codeimg-0.0.1/kk_codeimg.egg-info/top_level.txt +1 -0
- kk_codeimg-0.0.1/pyproject.toml +64 -0
- kk_codeimg-0.0.1/setup.cfg +4 -0
kk_codeimg-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Python卡皮巴拉
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kk_codeimg
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: 把代码渲染成精美的代码图片:12 套主题、16 种预设风格,支持窗口标题与中英文混排,纯 Pillow + Pygments 离线渲染
|
|
5
|
+
Author: Python卡皮巴拉
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kapikkkk/kk_codeimg
|
|
8
|
+
Project-URL: Repository, https://github.com/kapikkkk/kk_codeimg
|
|
9
|
+
Project-URL: Issues, https://github.com/kapikkkk/kk_codeimg/issues
|
|
10
|
+
Keywords: code-image,codeimg,code-screenshot,carbon,syntax-highlight,png,thumbnail,social-media,代码截图,代码图片,分享图
|
|
11
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
23
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
24
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: pillow>=9.0
|
|
30
|
+
Requires-Dist: pygments>=2.10
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# kk_codeimg
|
|
38
|
+
|
|
39
|
+
**🌟【Python卡皮巴拉】—— 你的Python修炼秘籍,代码界的"神兽"驾到!🌟**
|
|
40
|
+
|
|
41
|
+
**🌟 [Python Capybara] — Your Python cultivation manual; the coding realm's "mythical beast" has arrived! 🌟**
|
|
42
|
+
|
|
43
|
+
[PyPI](https://pypi.org/project/kk_codeimg/) · [MIT License](LICENSE) · [Python 3.8+](https://pypi.org/project/kk_codeimg/)
|
|
44
|
+
|
|
45
|
+
### 安装
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install kk_codeimg
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 快速开始
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from kk_codeimg import code_generator
|
|
55
|
+
|
|
56
|
+
code_generator(code, 'python', output='out.png')
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
不传 `output` 时返回 `PIL.Image.Image`,可自行 `.save()` 或做后处理。
|
|
60
|
+
|
|
61
|
+
### 特点
|
|
62
|
+
|
|
63
|
+
- **12 套主题** —— 全部通过 WCAG AA 对比度校验,不是"看着差不多"
|
|
64
|
+
- **16 种预设风格** —— 一行代码切换整套视觉配置
|
|
65
|
+
- **窗口标题** —— 显示文件名,支持中文,字体与代码自动统一
|
|
66
|
+
- **中英文混排** —— 等宽字体没有中文字形?自动回退到系统 CJK 字体
|
|
67
|
+
- **对比度达标** —— 按 WCAG 标准实算,注释不再"灰到看不见"
|
|
68
|
+
- **纯离线** —— 不联网、不开浏览器,CI 里也能跑
|
|
69
|
+
- **零重型依赖** —— 只用 `Pillow` + `Pygments`
|
|
70
|
+
- **主题可扩展** —— 加一套主题只需往 `palette.py` 里加一组色值
|
|
71
|
+
|
|
72
|
+
### 效果预览
|
|
73
|
+
|
|
74
|
+
生成全套样图:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python scripts/make_samples.py # 在仓库根目录执行
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
输出到 `out/`。
|
|
81
|
+
|
|
82
|
+
### 预设风格
|
|
83
|
+
|
|
84
|
+
不想逐个记参数就用 `style`,一次套用一整套视觉配置:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
code_generator(code, 'python', style='tokyo', output='out.png')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| 风格 | 说明 |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `default` | 深色经典:One Dark 主题 + 柔和渐变 |
|
|
93
|
+
| `carbon` | 极简纯色底、无窗口控制点、方正小圆角 |
|
|
94
|
+
| `dracula` | Dracula 紫调 + 极光渐变 |
|
|
95
|
+
| `tokyo` | Tokyo Night 夜色 + 深海渐变 |
|
|
96
|
+
| `github` | GitHub 浅色 + 淡雅渐变(不透明底,可读性最佳) |
|
|
97
|
+
| `light-frosted` | 浅色磨砂:保留渐变氛围但垫白底,深字清晰 |
|
|
98
|
+
| `frosted` | 深色磨砂玻璃:大圆角,背景隐约透出 |
|
|
99
|
+
| `minimal` | 极简:无行号、无控制点、大留白 |
|
|
100
|
+
| `neon` | 霓虹酷炫:Cool Glow + 大圆角 |
|
|
101
|
+
| `share` | 社交分享:大字号、大圆角、宽留白 |
|
|
102
|
+
| `print` | 打印友好:白底黑字、无干扰 |
|
|
103
|
+
| `ocean` | 深海蓝:冷色调、克制圆角 |
|
|
104
|
+
| `sunset` | 日落暖橙:亮色系、适合长代码 |
|
|
105
|
+
| `forest` | 森林绿:护眼低饱和 |
|
|
106
|
+
| `grid` | 网格纸:零圆角、细边框控制点、代码排版感 |
|
|
107
|
+
| `sticker` | 贴纸风:浅色、夸张圆角、紧凑 |
|
|
108
|
+
|
|
109
|
+
还有一批顺手加的**别名**,记不住名字也能用:
|
|
110
|
+
`dark` / `light` / `plain` / `classic` / `night` / `big` / `rounded` / `sharp` / `matrix` / `frost`
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
code_generator(code, 'python', style='dark') # 等同 default
|
|
114
|
+
code_generator(code, 'python', style='plain') # 等同 minimal
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
显式传入的参数**优先级高于** `style`:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# style 提供预设,再用 theme 覆盖其中一项
|
|
121
|
+
code_generator(code, 'python', style='minimal', theme='dracula')
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 常用参数
|
|
125
|
+
|
|
126
|
+
| 参数 | 默认 | 说明 |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| `code` | 必填 | 代码文本 |
|
|
129
|
+
| `language` | `'python'` | Pygments 语言名:`python` / `javascript` / `sql` / `java` / `go`… |
|
|
130
|
+
| `output` | `None` | PNG 路径;`None` 则只返回 Image |
|
|
131
|
+
| `style` | `None` | 预设风格名,见上表 |
|
|
132
|
+
| `theme` | 随 style | 12 套主题,见下表 |
|
|
133
|
+
| `background` | 随 style | 渐变名 / `single` / `transparent` / 任意 `#hex` |
|
|
134
|
+
| `font` | `None` | 字体名或 `.ttf` 路径;`None` 自动探测 |
|
|
135
|
+
| `font_size` | `15` | 字号(逻辑像素) |
|
|
136
|
+
| `border_radius` | `9` | 编辑器圆角 |
|
|
137
|
+
| `window_controls` | `'color'` | `color` / `gray` / `gray-light` / `outline` / `none` |
|
|
138
|
+
| `line_height` | `1.45` | 行高倍数 |
|
|
139
|
+
| `padding` | `64` | 图片四周留白 |
|
|
140
|
+
| `line_numbers` | `True` | 是否显示行号 |
|
|
141
|
+
| `transparent_editor` | `False` | 编辑器区域透明 |
|
|
142
|
+
| `scrim_alpha` | `None` | 透明模式下的底色不透明度 `0~1`;`None` 时按主题明暗自动决定 |
|
|
143
|
+
| `title` | `None` | 窗口标题,显示在窗口栏居中,支持中文 |
|
|
144
|
+
| `title_alpha` | `0.72` | 标题不透明度,调低可让标题退居次要 |
|
|
145
|
+
| `title_size` | `None` | 标题字号。`None`/`'same'` = 与代码同字号;传数字则单独指定 |
|
|
146
|
+
| `scale` | `2` | 渲染倍率,`2` 适合高清分享 |
|
|
147
|
+
|
|
148
|
+
传了 `output` 时返回 `RenderResult`,带 `.image`、`.path`、`.editor_box`、`.code_box`。
|
|
149
|
+
|
|
150
|
+
### 窗口标题
|
|
151
|
+
|
|
152
|
+
`title` 显示在窗口栏居中位置:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
code_generator(code, 'python', title='point.py', output='out.png')
|
|
156
|
+
code_generator(code, 'python', title='几何工具 · 坐标计算', output='out.png') # 支持中文
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**字体始终与代码一致**,只有字号可以不同:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
# 标题与代码同字号同字体(默认)
|
|
163
|
+
code_generator(code, 'python', title='main.py')
|
|
164
|
+
|
|
165
|
+
# 标题小一号
|
|
166
|
+
code_generator(code, 'python', title='main.py', font_size=20, title_size=13)
|
|
167
|
+
|
|
168
|
+
# 换个字体,标题自动跟随
|
|
169
|
+
code_generator(code, 'python', title='main.py', font='consolas')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
细节:
|
|
173
|
+
|
|
174
|
+
- 字体统一是硬约束——代码用什么字体,标题就用同一个字体文件
|
|
175
|
+
(同字号时直接复用同一个字体对象);中文回退字体同样统一
|
|
176
|
+
- `title_size` 超过窗口栏容量(40px 栏高,约 48.6px 上限)会**自动钳制**,
|
|
177
|
+
不会出现标题盖住代码的情况;`0` / 负数 / 非数字会抛 `ValueError`
|
|
178
|
+
- 超长标题自动截断加省略号,不溢出窗口
|
|
179
|
+
- `window_controls='none'` 时标题仍然显示(标题独立于控制点)
|
|
180
|
+
- 配色用主题**前景色**而非行号色——实测行号色在部分主题上对比度仅 2.76:1,
|
|
181
|
+
前景色全部 ≥ 6.10:1
|
|
182
|
+
- 标题在**整个编辑器宽度上居中**
|
|
183
|
+
|
|
184
|
+
### 主题(12 套)
|
|
185
|
+
|
|
186
|
+
`one-dark`(默认)、`dracula`、`vscode`、`ayu-light`、`github-light`、
|
|
187
|
+
`github-dark`、`tokyo-night`、`xcode-dark`、`xcode-light`、`amy`、`aura`、`cool-glow`
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
code_generator(code, 'python', output='a.png', theme='dracula', background='aurora')
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 背景
|
|
194
|
+
|
|
195
|
+
10 套渐变:`mystic`(默认)、`aruba`、`jungle`、`tropical`、`aurora`、`candy`、
|
|
196
|
+
`peach`、`bananas`、`leaf`、`ocean`
|
|
197
|
+
|
|
198
|
+
外加 `single`(单色)、`transparent`(透明)、以及任意 `#hex` 值:
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
code_generator(code, 'python', output='a.png', background='#1d976c')
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 完整示例
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from kk_codeimg import code_generator
|
|
208
|
+
|
|
209
|
+
code = '''def greet(name: str) -> str:
|
|
210
|
+
# 生成问候语
|
|
211
|
+
return f"Hello, {name}!"
|
|
212
|
+
'''
|
|
213
|
+
|
|
214
|
+
# 默认风格
|
|
215
|
+
code_generator(code, 'python', output='out.png')
|
|
216
|
+
|
|
217
|
+
# 换主题与背景
|
|
218
|
+
code_generator(code, 'python', output='dracula.png',
|
|
219
|
+
theme='dracula', background='ocean')
|
|
220
|
+
|
|
221
|
+
# 带窗口标题
|
|
222
|
+
code_generator(code, 'python', output='titled.png', title='greet.py')
|
|
223
|
+
|
|
224
|
+
# 浅色主题 + 无行号
|
|
225
|
+
code_generator(code, 'python', output='light.png',
|
|
226
|
+
theme='github-light', background='leaf', line_numbers=False)
|
|
227
|
+
|
|
228
|
+
# 不落盘,直接拿 Image 做后处理
|
|
229
|
+
img = code_generator(code, 'python', font_size=18)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 设计说明
|
|
233
|
+
|
|
234
|
+
**对比度是算出来的,不是看出来的。** 早期直接采用现成配色,实测发现一批槽位
|
|
235
|
+
达不到 WCAG AA 标准(4.5:1),实际观感问题例如:
|
|
236
|
+
|
|
237
|
+
- 某浅色主题的 `number` 仅 **1.85:1** —— 白底上几乎看不见
|
|
238
|
+
- 某深色主题的 `comment` 仅 **2.25:1** —— 注释难以辨认
|
|
239
|
+
|
|
240
|
+
修正方式是**保持色相与饱和度、只调整明度**,直到达到 4.5:1,观感不跑偏。
|
|
241
|
+
现 12 套主题全部达标(最差 4.50:1,最好 6.74:1)。`kk_codeimg/contrast.py`
|
|
242
|
+
提供 WCAG 计算与评估工具,`test_all_themes_meet_wcag_aa_on_own_bg` 做回归守卫。
|
|
243
|
+
|
|
244
|
+
原主题未定义的槽位(如 Xcode 系列的数字/运算符)按其编辑器默认配色补齐,
|
|
245
|
+
并配 `_FALLBACK` 语义回退链,避免整片 token 退化成前景色。
|
|
246
|
+
|
|
247
|
+
**透明模式下的可读性**:浅色主题(深色文字)若抽掉底色直接压到饱和背景上,
|
|
248
|
+
文字会糊掉——实测某组合仅 **1.24:1**。因此透明模式下浅色主题会自动垫一层
|
|
249
|
+
不透明底色(磨砂效果,背景氛围仍在)。深色主题文字本身够亮,保持全透明。
|
|
250
|
+
手动控制用 `scrim_alpha`(0~1)。
|
|
251
|
+
|
|
252
|
+
**中英文混排**:等宽字体普遍无中文字形,`_TextPen` 会按字符切分,
|
|
253
|
+
CJK 交给系统 CJK 字体(微软雅黑 / Noto Sans SC 等)绘制并按全角宽度计算 advance。
|
|
254
|
+
|
|
255
|
+
**字体**:默认按 `Cascadia Mono`(SIL OFL 1.1)→ `JetBrains Mono`(OFL 1.1)→
|
|
256
|
+
`DejaVu Sans Mono`(Bitstream Vera)顺序探测,**均为免费商用字体**。
|
|
257
|
+
|
|
258
|
+
**圆角**:编辑器圆角通过 alpha 遮罩真实生效(不是只改描边),可用
|
|
259
|
+
`border_radius` 自由调整,`0` 即直角。
|
|
260
|
+
|
|
261
|
+
### 测试
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m pytest scripts/test_kk_codeimg.py -q
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
47 项测试,覆盖缩进保留、中文出字、12 主题 / 12 背景 / 16 风格 / 10 别名渲染、
|
|
268
|
+
**WCAG 对比度守卫**、透明模式垫底、圆角生效、槽位退化防护、参数覆盖优先级、
|
|
269
|
+
窗口标题(中文/截断/无控制点/透明度/字号独立/字体统一/居中)、多语言、异常输入等。
|
|
270
|
+
|
|
271
|
+
### 已知限制
|
|
272
|
+
|
|
273
|
+
- 超长单行不自动换行(长代码建议调大 `font_size` 或分屏)
|
|
274
|
+
- 粗体/斜体未实现,部分主题原设计里关键字是加粗的
|
|
275
|
+
- 透明模式 + 浅色主题时,背景渐变基本透不出来(实测需 100% 不透明才达 AA),
|
|
276
|
+
想要通透感建议用深色主题配 `style='frosted'`
|
|
277
|
+
|
|
278
|
+
### 许可证
|
|
279
|
+
|
|
280
|
+
[MIT](LICENSE) © 2026 Python卡皮巴拉
|
|
281
|
+
|
|
282
|
+
---
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
English | [简体中文](docs/README.zh-CN.md)
|
|
2
|
+
|
|
3
|
+
# kk_codeimg
|
|
4
|
+
|
|
5
|
+
**🌟【Python卡皮巴拉】—— 你的Python修炼秘籍,代码界的"神兽"驾到!🌟**
|
|
6
|
+
|
|
7
|
+
**🌟 [Python Capybara] — Your Python cultivation manual; the coding realm's "mythical beast" has arrived! 🌟**
|
|
8
|
+
|
|
9
|
+
[PyPI](https://pypi.org/project/kk_codeimg/) · [MIT License](LICENSE) · [Python 3.8+](https://pypi.org/project/kk_codeimg/)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Turn your code into beautiful, share-ready code images.
|
|
15
|
+
Pure Python (`Pillow` + `Pygments`) — **fully offline**: no browser, no headless
|
|
16
|
+
Chrome, no network calls.
|
|
17
|
+
|
|
18
|
+
## English
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
- 🎨 **12 themes** — every one verified against WCAG AA contrast, not "close enough"
|
|
23
|
+
- 🖼️ **16 preset styles** — switch an entire look with a single argument
|
|
24
|
+
- 🏷️ **Window title** — file name in the title bar, CJK-ready, font always
|
|
25
|
+
matches the code
|
|
26
|
+
- 🇨🇳 **Mixed CJK + Latin** — monospace fonts lack Chinese glyphs? We fall back
|
|
27
|
+
to a system CJK font automatically
|
|
28
|
+
- 🔒 **Accessible by default** — contrast ratios are *computed*, so comments
|
|
29
|
+
are never too faint to read
|
|
30
|
+
- 🐍 **100% offline** — no network requests, so it works in CI
|
|
31
|
+
- 🪶 **Light dependencies** — just `Pillow` + `Pygments`
|
|
32
|
+
- 🧩 **Extensible** — adding a theme means adding one dict of colours
|
|
33
|
+
|
|
34
|
+
### Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install kk_codeimg
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Quick start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from kk_codeimg import code_generator
|
|
44
|
+
|
|
45
|
+
code_generator(code, 'python', output='out.png')
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Without `output`, a `PIL.Image.Image` is returned so you can post-process it yourself.
|
|
49
|
+
|
|
50
|
+
### Preview
|
|
51
|
+
|
|
52
|
+
**One Dark theme + gradient (default `default`)**
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
**GitHub Light theme (`github`)**
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
**`neon`: large radius + Cool Glow**
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
**`ocean`: cool and restrained**
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
**`sticker`: exaggerated radius**
|
|
69
|
+
|
|
70
|
+

|
|
71
|
+
|
|
72
|
+
**`grid`: square grid paper**
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
Generate the full sample set:/n/n```bash
|
|
77
|
+
python scripts/make_samples.py
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Writes to `out/`.
|
|
81
|
+
|
|
82
|
+
### Preset styles
|
|
83
|
+
|
|
84
|
+
Don't want to memorise parameters? Use `style` to apply a whole look at once:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
code_generator(code, 'python', style='tokyo', output='out.png')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Style | Description |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `default` | Dark classic: One Dark theme with a soft gradient |
|
|
93
|
+
| `carbon` | Minimal solid background, no window controls, small radius |
|
|
94
|
+
| `dracula` | Dracula purple tones with an aurora gradient |
|
|
95
|
+
| `tokyo` | Tokyo Night on a deep-ocean gradient |
|
|
96
|
+
| `github` | GitHub Light on a soft gradient (opaque, most readable) |
|
|
97
|
+
| `light-frosted` | Light frosted glass: keeps the ambience, adds a white base for legibility |
|
|
98
|
+
| `frosted` | Dark frosted glass: large radius, background softly shows through |
|
|
99
|
+
| `minimal` | Minimal: no line numbers, no window controls, generous padding |
|
|
100
|
+
| `neon` | Neon: Cool Glow theme with a large corner radius |
|
|
101
|
+
| `share` | Social sharing: large font, large radius, wide padding |
|
|
102
|
+
| `print` | Print-friendly: black on white, no distractions |
|
|
103
|
+
| `ocean` | Deep ocean: cool tones, restrained radius |
|
|
104
|
+
| `sunset` | Sunset: warm and bright, good for long snippets |
|
|
105
|
+
| `forest` | Forest: low-saturation greens, easy on the eyes |
|
|
106
|
+
| `grid` | Grid paper: square corners, outlined controls, typographic feel |
|
|
107
|
+
| `sticker` | Sticker: light background, exaggerated radius, compact |
|
|
108
|
+
|
|
109
|
+
Handy **aliases** so you don't have to memorise exact names:
|
|
110
|
+
`dark` / `light` / `plain` / `classic` / `night` / `big` / `rounded` / `sharp` / `matrix` / `frost`
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
code_generator(code, 'python', style='dark') # same as default
|
|
114
|
+
code_generator(code, 'python', style='plain') # same as minimal
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Explicit arguments always **override** `style`:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
code_generator(code, 'python', style='minimal', theme='dracula')
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Parameters
|
|
124
|
+
|
|
125
|
+
| Parameter | Default | Description |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `code` | required | Source code text |
|
|
128
|
+
| `language` | `'python'` | Pygments lexer name: `python` / `javascript` / `sql` / `java` / `go`… |
|
|
129
|
+
| `output` | `None` | Path to save the PNG; `None` returns the Image instead |
|
|
130
|
+
| `style` | `None` | Preset style name (see table above) |
|
|
131
|
+
| `theme` | follows `style` | One of 12 themes (see below) |
|
|
132
|
+
| `background` | follows `style` | Gradient name / `single` / `transparent` / any `#hex` |
|
|
133
|
+
| `font` | `None` | Font name or `.ttf` path; auto-detected when `None` |
|
|
134
|
+
| `font_size` | `15` | Font size (logical pixels) |
|
|
135
|
+
| `border_radius` | `9` | Editor corner radius |
|
|
136
|
+
| `window_controls` | `'color'` | `color` / `gray` / `gray-light` / `outline` / `none` |
|
|
137
|
+
| `line_height` | `1.45` | Line height multiplier |
|
|
138
|
+
| `padding` | `64` | Outer margin |
|
|
139
|
+
| `line_numbers` | `True` | Show line numbers |
|
|
140
|
+
| `transparent_editor` | `False` | Make the editor area transparent |
|
|
141
|
+
| `scrim_alpha` | `None` | Base opacity (`0`–`1`) in transparent mode; auto-decided from theme brightness when `None` |
|
|
142
|
+
| `title` | `None` | Window title, centred in the title bar; CJK supported |
|
|
143
|
+
| `title_alpha` | `0.72` | Title opacity — lower it to make the title recede |
|
|
144
|
+
| `title_size` | `None` | Title font size. `None`/`'same'` = same as code; pass a number to set it independently |
|
|
145
|
+
| `scale` | `2` | Render scale; `2` is good for sharing |
|
|
146
|
+
|
|
147
|
+
When `output` is given, a `RenderResult` is returned with `.image`, `.path`,
|
|
148
|
+
`.editor_box` and `.code_box`.
|
|
149
|
+
|
|
150
|
+
### Window title
|
|
151
|
+
|
|
152
|
+
`title` renders in the centre of the title bar:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
code_generator(code, 'python', title='point.py', output='out.png')
|
|
156
|
+
code_generator(code, 'python', title='几何工具 · 坐标计算', output='out.png') # CJK OK
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**The font always matches the code** — only the size may differ:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
# Same font, same size (default)
|
|
163
|
+
code_generator(code, 'python', title='main.py')
|
|
164
|
+
|
|
165
|
+
# Smaller title
|
|
166
|
+
code_generator(code, 'python', title='main.py', font_size=20, title_size=13)
|
|
167
|
+
|
|
168
|
+
# Change the font — the title follows automatically
|
|
169
|
+
code_generator(code, 'python', title='main.py', font='consolas')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Details:
|
|
173
|
+
|
|
174
|
+
- Font unification is a hard constraint — whatever the code uses, the title uses
|
|
175
|
+
the exact same font file (the very same font object when sizes match); the CJK
|
|
176
|
+
fallback is unified too
|
|
177
|
+
- A `title_size` larger than the title bar can hold (40 px bar, ~48.6 px limit)
|
|
178
|
+
is **clamped automatically**, so the title never covers the code;
|
|
179
|
+
`0` / negative / non-numeric values raise `ValueError`
|
|
180
|
+
- Overlong titles are truncated with an ellipsis and never overflow
|
|
181
|
+
- The title still shows when `window_controls='none'`
|
|
182
|
+
- Colours come from the theme's **foreground**, not the gutter colour — the
|
|
183
|
+
gutter measures only 2.76:1 on some themes, while every foreground is ≥ 6.10:1
|
|
184
|
+
- The title is centred across the **entire editor width**
|
|
185
|
+
|
|
186
|
+
### Themes (12)
|
|
187
|
+
|
|
188
|
+
`one-dark` (default), `dracula`, `vscode`, `ayu-light`, `github-light`,
|
|
189
|
+
`github-dark`, `tokyo-night`, `xcode-dark`, `xcode-light`, `amy`, `aura`,
|
|
190
|
+
`cool-glow`
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
code_generator(code, 'python', output='a.png', theme='dracula', background='aurora')
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Backgrounds
|
|
197
|
+
|
|
198
|
+
10 gradients: `mystic` (default), `aruba`, `jungle`, `tropical`, `aurora`,
|
|
199
|
+
`candy`, `peach`, `bananas`, `leaf`, `ocean`
|
|
200
|
+
|
|
201
|
+
Plus `single` (solid), `transparent`, and any `#hex` value:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
code_generator(code, 'python', output='a.png', background='#1d976c')
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Full example
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from kk_codeimg import code_generator
|
|
211
|
+
|
|
212
|
+
code = '''def greet(name: str) -> str:
|
|
213
|
+
# say hello
|
|
214
|
+
return f"Hello, {name}!"
|
|
215
|
+
'''
|
|
216
|
+
|
|
217
|
+
# Default look
|
|
218
|
+
code_generator(code, 'python', output='out.png')
|
|
219
|
+
|
|
220
|
+
# Different theme and background
|
|
221
|
+
code_generator(code, 'python', output='dracula.png',
|
|
222
|
+
theme='dracula', background='ocean')
|
|
223
|
+
|
|
224
|
+
# With a window title
|
|
225
|
+
code_generator(code, 'python', output='titled.png', title='greet.py')
|
|
226
|
+
|
|
227
|
+
# Light theme without line numbers
|
|
228
|
+
code_generator(code, 'python', output='light.png',
|
|
229
|
+
theme='github-light', background='leaf', line_numbers=False)
|
|
230
|
+
|
|
231
|
+
# No file written — grab the Image and post-process it
|
|
232
|
+
img = code_generator(code, 'python', font_size=18)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Design notes
|
|
236
|
+
|
|
237
|
+
**Contrast is computed, not eyeballed.** Early on we shipped off-the-shelf
|
|
238
|
+
palettes, then measured them and found a number of slots below WCAG AA (4.5:1):
|
|
239
|
+
|
|
240
|
+
- one light theme's `number` measured only **1.85:1** — effectively invisible
|
|
241
|
+
- one dark theme's `comment` measured only **2.25:1** — hard to read
|
|
242
|
+
|
|
243
|
+
The fix keeps **hue and saturation, adjusting only lightness** until 4.5:1 is
|
|
244
|
+
reached, so each palette still looks like itself. All 12 themes now pass (worst
|
|
245
|
+
4.50:1, best 6.74:1). `kk_codeimg/contrast.py` provides the WCAG maths and
|
|
246
|
+
`test_all_themes_meet_wcag_aa_on_own_bg` guards against regressions.
|
|
247
|
+
|
|
248
|
+
Slots the original themes never defined (e.g. numbers and operators in the Xcode
|
|
249
|
+
family) are filled in from those editors' own defaults, plus a `_FALLBACK`
|
|
250
|
+
semantic chain so whole regions never collapse to the foreground colour.
|
|
251
|
+
|
|
252
|
+
**Readability in transparent mode**: a light theme (dark text) loses its
|
|
253
|
+
background and lands directly on a saturated gradient — one combination measured
|
|
254
|
+
only **1.24:1**. So in transparent mode light themes automatically get an opaque
|
|
255
|
+
base (a frosted effect that keeps the ambience). Dark themes stay fully
|
|
256
|
+
transparent. Override with `scrim_alpha` (0–1).
|
|
257
|
+
|
|
258
|
+
**Mixed CJK + Latin**: monospace fonts rarely carry Chinese glyphs, so
|
|
259
|
+
`_TextPen` splits runs per character and hands CJK to a system CJK font
|
|
260
|
+
(Microsoft YaHei / Noto Sans SC, …), advancing by full-width metrics.
|
|
261
|
+
|
|
262
|
+
**Fonts**: probed in the order `Cascadia Mono` (SIL OFL 1.1) → `JetBrains Mono`
|
|
263
|
+
(OFL 1.1) → `DejaVu Sans Mono` (Bitstream Vera) — **all free for commercial use**.
|
|
264
|
+
|
|
265
|
+
**Corner radius** is applied through a real alpha mask (not just the outline),
|
|
266
|
+
so `border_radius=0` gives you genuinely square corners.
|
|
267
|
+
|
|
268
|
+
### Tests
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
python -m pytest scripts/test_kk_codeimg.py -q
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
47 tests covering indentation preservation, CJK rendering, all 12 themes /
|
|
275
|
+
12 backgrounds / 16 styles, **WCAG contrast guards**, transparent-mode base
|
|
276
|
+
fill, corner radius, slot-collapse prevention, parameter override precedence,
|
|
277
|
+
window titles (CJK / truncation / no controls / opacity / independent size /
|
|
278
|
+
unified font / centring), multiple languages and invalid input.
|
|
279
|
+
|
|
280
|
+
### Known limitations
|
|
281
|
+
|
|
282
|
+
- Very long single lines are not wrapped (try a larger `font_size` or split the
|
|
283
|
+
snippet)
|
|
284
|
+
- Bold/italic are not implemented; some original themes bold their keywords
|
|
285
|
+
- In transparent mode a light theme hides the gradient almost completely
|
|
286
|
+
(measured: 100% opacity is required to reach AA). For a translucent look,
|
|
287
|
+
use a dark theme with `style='frosted'`
|
|
288
|
+
|
|
289
|
+
### License
|
|
290
|
+
|
|
291
|
+
[MIT](LICENSE) © 2026 Python Capybara
|