diff --git a/README.md b/README.md
index a06ea30..8f80156 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,10 @@
**Python bindings for [Silicon](https://github.com/Aloxaf/silicon)'s renderer — create beautiful images of your source code, powered by Rust.**
+
+
+
+
Unlike wrapper approaches that shell out to a CLI, Silicate uses [PyO3](https://pyo3.rs) to call Silicon's Rust library directly, giving you native performance with a clean Python API.
## Installation
@@ -44,6 +48,25 @@ print(silicate.list_themes())
print(silicate.list_languages())
```
+## Theme gallery
+
+Silicate ships with 24+ built-in themes. Here are a few:
+
+
+
+ Dracula
 |
+ Nord
 |
+
+
+ Monokai Extended
 |
+ GitHub
 |
+
+
+ Solarized Dark
 |
+ Your code here
 |
+
+
+
### Options
All parameters after `code` (and `output` for `to_file`) are keyword-only:
@@ -62,6 +85,9 @@ All parameters after `code` (and `output` for `to_file`) are keyword-only:
| `shadow_blur_radius` | `50.0` | Shadow blur radius |
| `pad_horiz` | `80` | Horizontal padding (px) |
| `pad_vert` | `100` | Vertical padding (px) |
+| `shadow_offset_x` | `0` | Shadow offset in X axis |
+| `shadow_offset_y` | `0` | Shadow offset in Y axis |
+| `code_pad_right` | `25` | Right padding inside code window (px) |
| `highlight_lines` | `None` | 1-based line numbers to highlight |
| `tab_width` | `4` | Spaces per tab |
| `line_offset` | `1` | Starting line number |
@@ -85,3 +111,7 @@ uv run python -c "import silicate; print(silicate.list_themes())"
## License
MIT
+
+---
+
+Built by [All Tuner Labs](https://alltuner.com)
diff --git a/docs/api.md b/docs/api.md
index 4b8b5d2..df67413 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -18,6 +18,9 @@ def generate(
shadow_blur_radius: float = 50.0,
pad_horiz: int = 80,
pad_vert: int = 100,
+ shadow_offset_x: int = 0,
+ shadow_offset_y: int = 0,
+ code_pad_right: int = 25,
highlight_lines: list[int] | None = None,
tab_width: int = 4,
line_offset: int = 1,
@@ -44,6 +47,9 @@ Generate a code image and return raw PNG bytes.
| `shadow_blur_radius` | `float` | `50.0` | Gaussian blur radius for shadow |
| `pad_horiz` | `int` | `80` | Horizontal padding in pixels |
| `pad_vert` | `int` | `100` | Vertical padding in pixels |
+| `shadow_offset_x` | `int` | `0` | Shadow offset in X axis |
+| `shadow_offset_y` | `int` | `0` | Shadow offset in Y axis |
+| `code_pad_right` | `int` | `25` | Padding to the right of the code in pixels |
| `highlight_lines` | `list[int] \| None` | `None` | 1-based line numbers to highlight |
| `tab_width` | `int` | `4` | Spaces per tab character |
| `line_offset` | `int` | `1` | Starting line number |
diff --git a/docs/assets/example-github.png b/docs/assets/example-github.png
new file mode 100644
index 0000000..ff28ecc
Binary files /dev/null and b/docs/assets/example-github.png differ
diff --git a/docs/assets/example-monokai.png b/docs/assets/example-monokai.png
new file mode 100644
index 0000000..3e72908
Binary files /dev/null and b/docs/assets/example-monokai.png differ
diff --git a/docs/assets/example-nord.png b/docs/assets/example-nord.png
new file mode 100644
index 0000000..bddb5c8
Binary files /dev/null and b/docs/assets/example-nord.png differ
diff --git a/docs/assets/example-solarized.png b/docs/assets/example-solarized.png
new file mode 100644
index 0000000..01437f5
Binary files /dev/null and b/docs/assets/example-solarized.png differ
diff --git a/docs/assets/example-usage.png b/docs/assets/example-usage.png
new file mode 100644
index 0000000..3a44c02
Binary files /dev/null and b/docs/assets/example-usage.png differ
diff --git a/docs/assets/hero-example.png b/docs/assets/hero-example.png
new file mode 100644
index 0000000..550cd63
Binary files /dev/null and b/docs/assets/hero-example.png differ
diff --git a/docs/assets/logo.png b/docs/assets/logo.png
new file mode 100644
index 0000000..599cfa3
Binary files /dev/null and b/docs/assets/logo.png differ
diff --git a/docs/index.md b/docs/index.md
index 23c59cb..70394a6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -2,6 +2,10 @@
**Python bindings for [Silicon](https://github.com/Aloxaf/silicon)'s renderer — create beautiful images of your source code, powered by Rust.**
+
+
+
+
Unlike wrapper approaches that shell out to a CLI, Silicate uses [PyO3](https://pyo3.rs) to call Silicon's Rust library directly, giving you native performance with a clean Python API.
## Features
@@ -35,6 +39,32 @@ silicate.to_file(
)
```
+## Theme gallery
+
+Silicate ships with 24+ built-in themes. Here are a few examples across different languages:
+
+
+
+### Dracula — Python
+
+
+### Nord — Rust
+
+
+### Monokai Extended — TypeScript
+
+
+### GitHub — SQL
+
+
+### Solarized Dark — Go
+
+
+### Silicate itself — Python
+
+
+
+
## How it works
```mermaid
@@ -47,3 +77,7 @@ graph LR
```
Silicate embeds the Silicon Rust library via [PyO3](https://pyo3.rs), compiled with [maturin](https://github.com/PyO3/maturin). The syntax highlighting engine, font rendering, and image composition all run in native Rust — Python only handles the API surface.
+
+---
+
+Built by [All Tuner Labs](https://alltuner.com)
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css
index 187a2ce..8130df3 100644
--- a/docs/stylesheets/extra.css
+++ b/docs/stylesheets/extra.css
@@ -1,33 +1,85 @@
-/* Silicate brand colors — indigo/violet code-editor theme */
+/* All Tuner Labs brand colors and MkDocs Material theme overrides. */
+/* Provides wine/burgundy color scheme with light/dark mode support. */
+/* All Tuner Labs Brand Colors */
:root {
- /* Primary palette */
- --silicon-indigo: #6366f1;
- --silicon-violet: #8b5cf6;
- --silicon-slate: #1e293b;
- --silicon-light: #f1f5f9;
+ --wine: #5B2333;
+ --white-smoke: #F7F4F3;
+ --taupe-gray: #928E8D;
+ --raisin-black: #2C2826;
+}
+
+/* Light mode custom colors */
+[data-md-color-scheme="default"] {
+ --md-primary-fg-color: var(--wine);
+ --md-primary-fg-color--light: #7a2f45;
+ --md-primary-fg-color--dark: #4a1b28;
+ --md-primary-bg-color: var(--white-smoke);
+
+ --md-accent-fg-color: var(--wine);
+ --md-accent-fg-color--transparent: rgba(91, 35, 51, 0.1);
- /* Material overrides — light mode */
- --md-primary-fg-color: var(--silicon-indigo);
- --md-primary-fg-color--light: #818cf8;
- --md-primary-fg-color--dark: #4f46e5;
- --md-accent-fg-color: var(--silicon-violet);
+ --md-default-bg-color: var(--white-smoke);
+ --md-default-fg-color: var(--raisin-black);
+ --md-default-fg-color--light: var(--taupe-gray);
+ --md-default-fg-color--lighter: #b5b2b1;
+ --md-default-fg-color--lightest: #d4d3d2;
+
+ --md-code-bg-color: #ffffff;
+ --md-code-fg-color: var(--raisin-black);
}
+/* Dark mode custom colors */
[data-md-color-scheme="slate"] {
- /* Material overrides — dark mode */
- --md-primary-fg-color: #818cf8;
- --md-primary-fg-color--light: #a5b4fc;
- --md-primary-fg-color--dark: #6366f1;
- --md-accent-fg-color: #a78bfa;
+ --md-primary-fg-color: var(--wine);
+ --md-primary-fg-color--light: #7a2f45;
+ --md-primary-fg-color--dark: #4a1b28;
+
+ --md-accent-fg-color: #8a3d51;
+ --md-accent-fg-color--transparent: rgba(138, 61, 81, 0.1);
+
+ --md-default-bg-color: var(--raisin-black);
+ --md-default-fg-color: var(--white-smoke);
+ --md-default-fg-color--light: var(--taupe-gray);
+
+ --md-code-bg-color: #1a1816;
+ --md-code-fg-color: var(--white-smoke);
+}
+
+/* Custom link colors for light mode */
+[data-md-color-scheme="default"] .md-content a {
+ color: var(--wine);
+}
+
+[data-md-color-scheme="default"] .md-content a:hover {
+ color: #7a2f45;
+}
+
+/* Custom link colors for dark mode - use white-smoke for readability */
+[data-md-color-scheme="slate"] .md-content a {
+ color: var(--white-smoke);
+}
+
+[data-md-color-scheme="slate"] .md-content a:hover {
+ color: var(--taupe-gray);
+}
+
+/* Sidebar navigation links in dark mode */
+[data-md-color-scheme="slate"] .md-nav__link {
+ color: var(--white-smoke);
+}
+
+[data-md-color-scheme="slate"] .md-nav__link:hover {
+ color: var(--taupe-gray);
}
-/* Code block styling */
-.md-typeset code {
- border-radius: 4px;
+[data-md-color-scheme="slate"] .md-nav__link--active {
+ color: var(--white-smoke);
}
-/* Navigation tab highlight */
-.md-tabs__link--active {
- border-bottom: 2px solid var(--md-accent-fg-color);
+/* Custom header logo sizing */
+.md-header__button.md-logo img,
+.md-header__button.md-logo svg {
+ height: 2rem;
+ width: auto;
}
diff --git a/docs/usage.md b/docs/usage.md
index be8ef30..2376626 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -48,6 +48,19 @@ for theme in silicate.list_themes():
Available themes include: `1337`, `Coldark-Cold`, `Coldark-Dark`, `DarkNeon`, `Dracula`, `GitHub`, `Monokai Extended`, `Nord`, `OneHalfDark`, `OneHalfLight`, `Solarized (dark)`, `Solarized (light)`, `Sublime Snazzy`, `TwoDark`, `Visual Studio Dark+`, `gruvbox-dark`, `gruvbox-light`, `zenburn`, and more.
+Here's the same code rendered with different themes:
+
+
+
+ Dracula
 |
+ Nord
 |
+
+
+ Monokai Extended
 |
+ GitHub
 |
+
+
+
### Languages
```python
@@ -162,3 +175,7 @@ silicate.to_file(
pad_vert=80,
)
```
+
+The code above produces:
+
+
diff --git a/mkdocs.yml b/mkdocs.yml
index 0277b85..b20bfc4 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,7 +1,7 @@
site_name: Silicate
-site_description: Python bindings for Silicon's renderer
-site_url: https://silicate.alltuner.com
-site_author: David Poblador i Garcia
+site_url: https://silicate.alltuner.com/
+site_description: Python bindings for Silicon's renderer — create beautiful images of your source code, powered by Rust
+site_author: All Tuner Labs, S.L.
repo_url: https://github.com/alltuner/silicate
repo_name: alltuner/silicate
@@ -9,6 +9,8 @@ edit_uri: edit/main/docs/
theme:
name: material
+ logo: assets/logo.png
+ favicon: assets/logo.png
palette:
# Light mode
- media: "(prefers-color-scheme: light)"
@@ -29,8 +31,10 @@ theme:
features:
- navigation.instant
- navigation.tracking
+ - navigation.tabs
+ - navigation.sections
+ - navigation.expand
- navigation.top
- - toc.integrate
- search.suggest
- search.highlight
- content.code.copy
diff --git a/pyproject.toml b/pyproject.toml
index be4c422..97f58a8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -12,16 +12,42 @@ authors = [
{ name = "David Poblador i Garcia", email = "david@poblador.com" }
]
requires-python = ">=3.9"
-keywords = ["code", "image", "screenshot", "syntax-highlighting", "silicon", "rust"]
+keywords = [
+ "code",
+ "image",
+ "screenshot",
+ "syntax-highlighting",
+ "silicon",
+ "rust",
+ "code-to-image",
+ "carbon",
+ "code-screenshot",
+ "png",
+ "developer-tools",
+ "pyo3",
+ "rendering",
+]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
+ "Intended Audience :: Information Technology",
"License :: OSI Approved :: MIT License",
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
"Topic :: Multimedia :: Graphics",
+ "Topic :: Multimedia :: Graphics :: Graphics Conversion",
"Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Software Development :: Documentation",
+ "Topic :: Text Processing :: Markup",
+ "Topic :: Utilities",
+ "Typing :: Typed",
]
[project.urls]
diff --git a/python/silicate/__init__.pyi b/python/silicate/__init__.pyi
index baf83ef..5d95afe 100644
--- a/python/silicate/__init__.pyi
+++ b/python/silicate/__init__.pyi
@@ -13,6 +13,9 @@ def generate(
shadow_blur_radius: float = 50.0,
pad_horiz: int = 80,
pad_vert: int = 100,
+ shadow_offset_x: int = 0,
+ shadow_offset_y: int = 0,
+ code_pad_right: int = 25,
highlight_lines: list[int] | None = None,
tab_width: int = 4,
line_offset: int = 1,
@@ -34,6 +37,9 @@ def generate(
shadow_blur_radius: Gaussian blur radius for the shadow.
pad_horiz: Horizontal padding in pixels.
pad_vert: Vertical padding in pixels.
+ shadow_offset_x: Shadow offset in X axis.
+ shadow_offset_y: Shadow offset in Y axis.
+ code_pad_right: Padding to the right of the code in pixels.
highlight_lines: List of 1-based line numbers to highlight.
tab_width: Number of spaces per tab character.
line_offset: Starting line number.
@@ -57,6 +63,9 @@ def to_file(
shadow_blur_radius: float = 50.0,
pad_horiz: int = 80,
pad_vert: int = 100,
+ shadow_offset_x: int = 0,
+ shadow_offset_y: int = 0,
+ code_pad_right: int = 25,
highlight_lines: list[int] | None = None,
tab_width: int = 4,
line_offset: int = 1,
@@ -81,6 +90,9 @@ def to_file(
shadow_blur_radius: Gaussian blur radius for the shadow.
pad_horiz: Horizontal padding in pixels.
pad_vert: Vertical padding in pixels.
+ shadow_offset_x: Shadow offset in X axis.
+ shadow_offset_y: Shadow offset in Y axis.
+ code_pad_right: Padding to the right of the code in pixels.
highlight_lines: List of 1-based line numbers to highlight.
tab_width: Number of spaces per tab character.
line_offset: Starting line number.
diff --git a/src/lib.rs b/src/lib.rs
index 9f9d64b..a3d3685 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,6 +32,9 @@ fn render(
shadow_blur_radius: f32,
pad_horiz: u32,
pad_vert: u32,
+ shadow_offset_x: i32,
+ shadow_offset_y: i32,
+ code_pad_right: u32,
highlight_lines: Option>,
tab_width: u8,
line_offset: u32,
@@ -72,7 +75,9 @@ fn render(
.shadow_color(shadow)
.blur_radius(shadow_blur_radius)
.pad_horiz(pad_horiz)
- .pad_vert(pad_vert);
+ .pad_vert(pad_vert)
+ .offset_x(shadow_offset_x)
+ .offset_y(shadow_offset_y);
let font_spec = font.unwrap_or_else(|| vec![("Hack".to_string(), 26.0)]);
let font_refs: Vec<(&str, f32)> = font_spec.iter().map(|(n, s)| (n.as_str(), *s)).collect();
@@ -88,6 +93,7 @@ fn render(
.shadow_adder(shadow_adder)
.highlight_lines(highlight_lines.unwrap_or_default())
.tab_width(tab_width)
+ .code_pad_right(code_pad_right)
.build()
.map_err(|e| PyValueError::new_err(format!("Font error: {}", e)))?;
@@ -126,6 +132,9 @@ fn encode_png(image: &image::RgbaImage) -> PyResult> {
shadow_blur_radius = 50.0,
pad_horiz = 80,
pad_vert = 100,
+ shadow_offset_x = 0,
+ shadow_offset_y = 0,
+ code_pad_right = 25,
highlight_lines = None,
tab_width = 4,
line_offset = 1,
@@ -146,6 +155,9 @@ fn generate<'py>(
shadow_blur_radius: f32,
pad_horiz: u32,
pad_vert: u32,
+ shadow_offset_x: i32,
+ shadow_offset_y: i32,
+ code_pad_right: u32,
highlight_lines: Option>,
tab_width: u8,
line_offset: u32,
@@ -165,6 +177,9 @@ fn generate<'py>(
shadow_blur_radius,
pad_horiz,
pad_vert,
+ shadow_offset_x,
+ shadow_offset_y,
+ code_pad_right,
highlight_lines,
tab_width,
line_offset,
@@ -194,6 +209,9 @@ fn generate<'py>(
shadow_blur_radius = 50.0,
pad_horiz = 80,
pad_vert = 100,
+ shadow_offset_x = 0,
+ shadow_offset_y = 0,
+ code_pad_right = 25,
highlight_lines = None,
tab_width = 4,
line_offset = 1,
@@ -214,6 +232,9 @@ fn to_file(
shadow_blur_radius: f32,
pad_horiz: u32,
pad_vert: u32,
+ shadow_offset_x: i32,
+ shadow_offset_y: i32,
+ code_pad_right: u32,
highlight_lines: Option>,
tab_width: u8,
line_offset: u32,
@@ -233,6 +254,9 @@ fn to_file(
shadow_blur_radius,
pad_horiz,
pad_vert,
+ shadow_offset_x,
+ shadow_offset_y,
+ code_pad_right,
highlight_lines,
tab_width,
line_offset,
diff --git a/uv.lock b/uv.lock
index 8974082..a41b119 100644
--- a/uv.lock
+++ b/uv.lock
@@ -671,7 +671,7 @@ wheels = [
[[package]]
name = "silicate"
-version = "0.1.0"
+version = "0.1.2"
source = { editable = "." }
[package.dev-dependencies]