| raw | true |
|---|---|
| title | Language Bindings |
| nav_group | Guides |
| nav_order | 2 |
Inky provides official bindings for Node.js, PHP, Python, and Ruby. All bindings expose the same core API surface.
For complete working examples with build scripts and email sending, see: Node.js | PHP | Python | Ruby | Go
Every binding provides these functions:
| Function | Description |
|---|---|
transform(html, columns?) |
Transform Inky HTML into email-safe table markup |
transformInline(html) |
Transform and inline CSS from <style> blocks |
transformWithData(html, dataJson) |
Transform with JSON data merge, then inline CSS |
transformHybrid(html) |
Transform using hybrid output (div + MSO ghost tables) |
toPlainText(html) |
Convert HTML to plain text for multipart email |
migrate(html) |
Migrate v1 syntax to v2 (returns HTML string) |
migrateWithDetails(html) |
Migrate v1 syntax, returns {html, changes[]} |
validate(html) |
Validate template, returns array of diagnostics |
version() |
Get the Inky engine version |
Diagnostics from validate() are objects/dicts with severity ("warning" or "error"), rule, and message fields.
Package: inky on npm
Engine: WASM (compiled from Rust via wasm-bindgen)
Requires: Node.js (any recent version)
npm install inkyconst inky = require("inky");
// Transform
const html = inky.transform('<button href="#">Click</button>');
const html16 = inky.transform('<row><column>Wide</column></row>', { columns: 16 });
// Transform + inline CSS
const inlined = inky.transformInline(`
<style>.button { background: blue; }</style>
<button href="#">Click</button>
`);
// Transform with data merge
const merged = inky.transformWithData(
'<button href="{{ url }}">{{ text }}</button>',
JSON.stringify({ url: "https://example.com", text: "Click" })
);
// Migrate v1 to v2
const migrated = inky.migrate('<columns large="6">Content</columns>');
// Migrate with change details
const result = inky.migrateWithDetails('<columns large="6">Content</columns>');
// result.html => '<column lg="6">Content</column>'
// result.changes => ['<columns> -> <column>', ...]
// Validate
const diagnostics = inky.validate('<button>No href</button>');
// [{ severity: "error", rule: "button-no-href", message: "..." }]
const diagnostics16 = inky.validate(html, { columns: 16 });
// Version
console.log(inky.version()); // "2.0.0"Type definitions are included. Key types:
interface TransformOptions { columns?: number; }
interface ValidateOptions { columns?: number; }
interface Diagnostic { severity: "warning" | "error"; rule: string; message: string; }
interface MigrateResult { html: string; changes: string[]; }Package: foundation/inky on Packagist
Engine: Native shared library via FFI (or PECL extension)
Requires: PHP >= 8.1
composer require foundation/inkyYou also need the libinky shared library available. Build it from source:
cargo build -p inky-ffi --release
# produces target/release/libinky.dylib (macOS) or libinky.so (Linux)The PHP package auto-detects the best available driver:
| Priority | Driver | Mechanism | Best For |
|---|---|---|---|
| 1 | PECL Extension | ext-inky |
Shared hosting, production |
| 2 | FFI | ext-ffi + libinky |
Local dev, self-managed servers |
FFI setup -- enable in php.ini:
# Option A: Enable globally (dev)
ffi.enable = true
# Option B: Preload mode (production, more secure)
ffi.enable = preload
opcache.preload = /path/to/vendor/inky/preload.phpNote: ffi.enable is a PHP_INI_SYSTEM directive and cannot be changed with ini_set().
use Inky\Inky;
// Transform
$html = Inky::transform('<button href="#">Click</button>');
$html = Inky::transform('<row><column>Content</column></row>', columns: 16);
// Transform + inline CSS
$html = Inky::transformInline('<style>...</style><button href="#">Click</button>');
// Transform with data merge
$html = Inky::transformWithData(
'<button href="{{ url }}">{{ text }}</button>',
json_encode(['url' => 'https://example.com', 'text' => 'Click'])
);
// Migrate
$html = Inky::migrate('<columns large="6">Content</columns>');
// Migrate with details
$result = Inky::migrateWithDetails('<columns large="6">Content</columns>');
// $result['html'] => '<column lg="6">Content</column>'
// $result['changes'] => ['<columns> -> <column>', ...]
// Validate
$diagnostics = Inky::validate('<button>No href</button>');
// [['severity' => 'error', 'rule' => 'button-no-href', 'message' => '...']]
// Version
echo Inky::version(); // "2.0.0"Package: inky-email on PyPI
Engine: Native shared library via ctypes
Requires: Python >= 3.8
pip install inky-emailYou also need the libinky shared library. Build from source:
cargo build -p inky-ffi --releaseThe library searches these paths automatically:
target/release/(development)- Bundled with the package
/usr/local/lib//usr/lib/
import inky
# Transform
html = inky.transform('<button href="#">Click</button>')
html = inky.transform('<row><column>Content</column></row>', columns=16)
# Transform + inline CSS
html = inky.transform_inline('<style>...</style><button href="#">Click</button>')
# Transform with data merge
html = inky.transform_with_data(
'<button href="{{ url }}">{{ text }}</button>',
'{"url": "https://example.com", "text": "Click"}'
)
# Migrate
html = inky.migrate('<columns large="6">Content</columns>')
# Migrate with details
result = inky.migrate_with_details('<columns large="6">Content</columns>')
# result['html'] => '<column lg="6">Content</column>'
# result['changes'] => ['<columns> -> <column>', ...]
# Validate
diagnostics = inky.validate('<button>No href</button>')
# [{'severity': 'error', 'rule': 'button-no-href', 'message': '...'}]
# Version
print(inky.version()) # "2.0.0"Note: Python uses snake_case -- transform_inline, migrate_with_details.
Package: inky-email on RubyGems
Engine: Native shared library via Fiddle
Requires: Ruby >= 2.7
gem install inky-emailOr in your Gemfile:
gem "inky-email"You also need the libinky shared library. Build from source:
cargo build -p inky-ffi --releaseThe library searches these paths automatically:
target/release/(development)- Bundled with the gem
/usr/local/lib//usr/lib/
require "inky"
# Transform
html = Inky.transform('<button href="#">Click</button>')
html = Inky.transform('<row><column>Content</column></row>', columns: 16)
# Transform + inline CSS
html = Inky.transform_inline('<style>...</style><button href="#">Click</button>')
# Transform with data merge
html = Inky.transform_with_data(
'<button href="{{ url }}">{{ text }}</button>',
'{"url": "https://example.com", "text": "Click"}'
)
# Migrate
html = Inky.migrate('<columns large="6">Content</columns>')
# Migrate with details
result = Inky.migrate_with_details('<columns large="6">Content</columns>')
# result[:html] => '<column lg="6">Content</column>'
# result[:changes] => ['<columns> -> <column>', ...]
# Validate
diagnostics = Inky.validate('<button>No href</button>')
# [{severity: "error", rule: "button-no-href", message: "..."}]
# Version
puts Inky.version # "2.0.0"PHP, Python, and Ruby bindings all depend on the libinky shared library from inky-ffi. To build it:
cd /path/to/inky
cargo build -p inky-ffi --releaseThis produces:
- macOS:
target/release/libinky.dylib - Linux:
target/release/libinky.so - Windows:
target/release/inky.dll
For production, copy the library to a system path (/usr/local/lib/) or bundle it with your package.
The Node.js binding uses the WASM module from inky-wasm:
cd crates/inky-wasm
wasm-pack build --target nodejsThis generates the .wasm file and JS/TS wrapper in pkg/.