This Site
My portfolio site is written in my own reactive declarative markup language, serving as a testbed for new source generation features.
Some demos:
Count: 0
state { int count } interface { Increment(), Decrement() } div(| class = {"d-flex flex-row gap-2"} | div(| class = {"my-auto"} | {"Count: " + count} ) button(| class = {"btn btn-danger"}, onclick = {"dispatch(this, 'Decrement');"} | <">-</"> ) button(| class = {"btn btn-success"}, onclick = {"dispatch(this, 'Increment');"} | <">+</"> ) )
using Generated; namespace TestApp.Views; public class UpDownDemo( IServiceProvider sp ) : UpDownDemoBase(sp) { public override void Decrement() { count--; } public override void Increment() { count++; } }
Serverside code is generated to render HTML for the component. Controller endpoints are also generated corresponding to any actions within the component interface.
Some minimal JS swaps out DOM elements to reactively update the page to reflect its latest state.
Value | Actions |
---|---|
Row 1 | |
Row 2 |
state { List<string> rows = {new() { "Row 1", "Row 2" }} } interface { Add(string row), Remove(int index), MoveUp(int index), MoveDown(int index) } table(| class = {"table table-striped table-bordered"}, style = {"user-select: none;"} | colgroup( col(| style = {"width: 70%;"} |) col(| style = {"width: 30%;"} |) ) thead( tr( th(<">Value</">) th(<">Actions</">) ) ) tbody( tr( td( input(| type = {"text"}, id = {"table-add"}, class = {"form-control"}, value = {rows.Count >= 5 ? "Max 5 rows" : ""}, disabled = {rows.Count >= 5}, autocomplete = {"off"} |) ) td( button(| type = {"button"}, class = {"btn btn-outline-primary"}, onclick = {"dispatch(this, 'Add', { row: $('#table-add').val() });"}, disabled = {rows.Count >= 5} | <">Add</"> ) ) ) foreach({var (row, i) in rows.Select((it, i) => (it, i))} tr( td({string.IsNullOrEmpty(row) ? "Blank!" : row}) td( i(| class = {"fa fa-arrow-up me-2"}, style = {"cursor: pointer;"}, onclick = {"dispatch(this, 'MoveUp', { index: " + i + " });"} |) i(| class = {"fa fa-arrow-down me-2"}, style = {"cursor: pointer;"}, onclick = {"dispatch(this, 'MoveDown', { index: " + i + " });"} |) i(| class = {"fa fa-trash me-2"}, style = {"cursor: pointer;"}, onclick = {"dispatch(this, 'Remove', { index: " + i + " });"} |) ) ) ) ) )
using Generated; namespace TestApp.Views; public class TableRowDemo( IServiceProvider sp ) : TableRowDemoBase(sp) { public override void Add(string row) { if (rows.Count < 5) { rows.Add(row); } } public override void MoveDown(int index) { if (index >= rows.Count - 1) { return; } (rows[index + 1], rows[index]) = (rows[index], rows[index + 1]); } public override void MoveUp(int index) { if (index <= 0) { return; } (rows[index - 1], rows[index]) = (rows[index], rows[index - 1]); } public override void Remove(int index) { rows.RemoveAt(index); } }
Recent Gists
Parser for Base64 and plaintext data URIsAn implementation of parsing the data URI scheme as specified by MDN
Quad-tree spatial index of regionsQuad-tree index for spatial queries and closest-neighbor searches (C++/C#)
RAID 5 and 6 calculations in C#Demonstrates the algorithms used to calculate the parities P and Q in RAID
Simple implementation of regexSingle-file FSA builder, token search, NFA to DFA algorithm, and state minimizer
String buffer writer in CAllows efficient concatenation of numerous strings (e.g., to build a source file)
JS drag-and-drop polyfillEnables dragging and dropping relying on fewer browser events
Least bottlenecked route finderBrute-force search for the least bottlenecked path through a graph
Centrifugal Sort joke algorithm"Sorts" items based on "weights" and loosely simulated inertia