| name | pastebin-tile-system |
| description | Auto-detect, compose, render, and test interactive tiles in the Kant Pastebin. Covers tile detection from pasted content, plugin-based rendering, standalone testing, and perf measurement across 8 plugin types. |
| license | MIT |
| compatibility | cross-agent |
| metadata | {"imported":true,"source":"/home/mdupont/.agents/skills/pastebin-tile-system/SKILL.md"} |
Pastebin Tile System
Purpose: When content is pasted into the Kant Pastebin, auto-detect what type it is (PlantUML, Graphviz DOT, MiniZinc model, Lean 4 proof, Tulip graph, MIDI file, etc.) and render it as an interactive tile with Run/Solve/Verify/Render/Analyze buttons.
Architecture
User pastes content
โ
โผ
โโโโโโโโโโโโโโโโโโโโ
โ detect_tile_type()โ โ checks by: MIME type, file extension, content patterns
โโโโโโโโฌโโโโโโโโโโโโ
โ matches?
โผ
โโโโโโโโโโโโโโโโโโโโ
โ render_tile_html()โ โ generates interactive tile HTML
โโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ Tile displayed โโโโโโถโ Plugin executes โ
โ with Run button โ โ (subprocess) โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ โ
โผ โผ
โโโโโโโโโโโโ โโโโโโโโโโโโ
โ 18 unit โ โ 8 plugin โ
โ tests โ
โ โ types โ
โโโโโโโโโโโโ โโโโโโโโโโโโ
Tile Detection
The detect_tile_type(title, mime, content) function checks in order:
1. MIME type
| MIME Type | Tile |
|---|
text/vnd.plantuml | plantuml |
text/vnd.graphviz | graphviz |
text/x-minizinc | minizinc |
text/x-lean | lean |
text/x-tulip | tulip |
2. File extension (from title)
| Extension | Tile |
|---|
.puml, .plantuml | plantuml |
.dot, .gv | graphviz |
.mzn | minizinc |
.lean | lean |
.tlp | tulip |
3. Content patterns
| Content starts with | Tile |
|---|
@startuml, @startdot | plantuml |
digraph, graph | graphviz |
theorem, lemma, def | lean |
(nodes , (TLP | tulip |
| Content contains | Tile |
|---|
constraint , solve satisfy | minizinc |
Tile Rendering
Each tile type generates an interactive HTML component:
<div class="tile" data-tile="plantuml">
<h3>๐ PlantUML: filename.puml</h3>
<pre style="max-height:200px;overflow:auto">@startuml
A -> B
@enduml</pre>
<button onclick="renderPlantUML(this)">โถ Render Diagram</button>
<div class="tile-output"></div>
</div>
Tile JavaScript Functions
| Tile | JS Function | HTTP Endpoint |
|---|
| ๐ PlantUML | renderPlantUML(btn) | POST /plugin/plantuml?action=render&format=svg |
| ๐ Graphviz | renderGraphViz(btn) | POST /plugin/graphviz?action=render&format=svg |
| ๐งฎ MiniZinc | solveMiniZinc(btn) | POST /plugin/minizinc?action=solve |
| ๐๏ธ Lean 4 | verifyLean(btn) | POST /plugin/lean?action=verify |
| ๐ Tulip | analyzeTulip(btn) | POST /plugin/tulip?action=analyze |
Each function:
- Disables the button, shows โณ
- Sends content to the plugin endpoint
- Displays result in the output div
- Shows โ
or โ on completion
Plugin System
Each tile type is backed by a Rust plugin implementing the Plugin trait:
pub trait Plugin: Send + Sync {
fn name(&self) -> &str;
fn version(&self) -> &str;
fn description(&self) -> &str;
fn execute(&self, input: &PluginInput) -> PluginResult;
}
Registered in main.rs:
registry.register(Box::new(plugins::plantuml::PlantUmlPlugin::new(car_index)));
registry.register(Box::new(plugins::graphviz::GraphvizPlugin::new()));
registry.register(Box::new(plugins::minizinc::MiniZincPlugin::new()));
registry.register(Box::new(plugins::lean::LeanPlugin::new()));
registry.register(Box::new(plugins::tulip::TulipPlugin::new()));
registry.register(Box::new(plugins::midi::MidiPlugin::new(car_index)));
registry.register(Box::new(plugins::tiles::TilesPlugin::new()));
Routes via /plugin/{name} handler:
.route("/plugin/{name}", web::get().to(handlers::plugin_route))
Testing
Quick test (18 tests, instant)
cd /home/mdupont/pastebin
bash tests/run_tile_tests.sh
Tests tile detection by extension, MIME, content, and rendering correctness. Written in Bash + Python โ no Rust compilation needed.
Rust integration tests
cd /home/mdupont/pastebin
cargo test --test tile_tests
cargo test -p kant-pastebin --lib tile_test
Test coverage
| Category | Tests | What's verified |
|---|
| Detection by extension | 5 | .puml, .dot, .mzn, .lean, .tlp |
| Detection by content | 5 | @startuml, digraph, solve satisfy, theorem, (nodes |
| Detection by MIME | 5 | plantuml, graphviz, minizinc, lean, tulip MIMEs |
| No match | 1 | Plain text returns empty |
| Render buttons | 5 | Each tile has correct JS function name |
| Unknown type | 1 | Returns empty string |
| HTML escaping | 1 | < โ <, prevents XSS |
Files
Pastebin source
src/
โโโ handlers.rs # detect_tile_type(), render_tile_html(), plugin_route()
โโโ plugin.rs # Plugin trait, PluginRegistry
โโโ plugins/
โ โโโ plantuml.rs # PlantUML renderer via subprocess
โ โโโ graphviz.rs # Graphviz DOT renderer + METIS partitioning
โ โโโ minizinc.rs # MiniZinc constraint solving
โ โโโ lean.rs # Lean 4 theorem proving
โ โโโ tulip.rs # Tulip graph analysis
โ โโโ midi.rs # MIDI file browser via locate
โ โโโ tiles.rs # DAG-CBOR spec tiles viewer
โโโ tile_test.rs # Library test module with perf measurement
โโโ car_index.rs # Locate-based file index
โโโ main.rs # Route registration + plugin init
tests/
โโโ tile_tests.rs # Standalone Rust integration tests
โโโ run_tile_tests.sh # Shell/Python test runner (18 tests)
Adding a New Tile Type
- Create plugin in
src/plugins/{name}.rs implementing Plugin trait
- Register in
src/main.rs: registry.register(Box::new(plugins::{name}::{Name}Plugin::new()));
- Add detection in
detect_tile_type(): check MIME, extension, or content pattern
- Add renderer in
render_tile_html(): generate the interactive tile HTML
- Add JS function in
handlers.rs: button handler that calls /plugin/{name} endpoint
- Add route:
.route("/{name}", ...) or use the generic /plugin/{name} route
- Add tests in
tests/run_tile_tests.sh and tests/tile_tests.rs
Commands Quick Reference
bash tests/run_tile_tests.sh
cargo test --test tile_tests
nix develop -c cargo run
curl http://localhost:8090/plugin/tiles
curl http://localhost:8090/car/midi
curl http://localhost:8090/car/plantuml
curl "http://localhost:8090/plugin/plantuml?action=render" -d "@startuml\nA->B\n@enduml"