Skip to content

fable-hub/Fable.Scriptorium

Repository files navigation

Fable.UI

A family of focused F# libraries for building and testing Fable applications. Each library has a single responsibility and a name drawn from the same metaphor: the act of writing.


Libraries

The writing-instrument family

Fable.Scriptorium

Once upon a time

Scriptorium: a room in a monastery where manuscripts were copied and illuminated by hand.

The scribe sits down and fills the pot of Ink — colour and style, ready to give life to every stroke. Bold or dim, red or green, the Ink asks no questions. It simply waits to be used.

The scribe reaches for a sheet of Parchment and begins to write. The words appear structured, purposeful — a log of what happened, what was warned, what went wrong. Parchment dips into the Ink pot to illuminate its headings: a cyan [INFO], a yellow [WARN], a red [ERROR]. The record is clear. The page holds everything.

Then the scribe takes the Quill — and it is the Nib at its tip that does the real work. That sharp, precise point is where expectation meets reality. The Nib touches the Parchment and either the mark is true, or it is not. Every flaw is recorded without interruption; the hand does not stop mid-stroke. Only when the page is full does the Quill lift — and every deviation is reported at once.

The Quill itself is the instrument that holds all of this together. It carries the Nib, dips into the Ink, and lays the results onto the Parchment — a complete manuscript of your test run, illuminated in green for what passed, red for what failed, and dim grey for what was left unwritten.

Fable.Ink          ──────────────────────────────────────────────── leaf
Fable.Parchment    → Fable.Ink ──────────────────────────────────── leaf
Fable.Nib          ──────────────────────────────────────────────── leaf
Fable.Quill        → Fable.Ink, Fable.Parchment, Fable.Nib ─────── leaf

Fable.Ink is the ink itself — pure colour and style for terminal output. It wraps ANSI escape codes into a small set of composable functions: red, green, bold, dim, underline, strip, and so on. No dependencies. Everything downstream reaches for Ink when it needs to colour output.

Fable.Parchment is the page that receives the ink — structured log output. It exposes a single [<RequireQualifiedAccess>] module, Log, with functions Log.log, Log.info, Log.warn, Log.error, Log.newLine, and Log.inline_. Each prefixed variant (info, warn, error) uses Ink to colour its label. Depends on: Fable.Ink.

Fable.Nib is the nib of the quill — the sharp, precise point that makes the mark. It is a standalone fluent assertion library: write expectations as composable functions, chain them with >>, and collect every failure before reporting. No runner dependency. Can be used with any test harness or inline in application code. Depends on: nothing.

Fable.Quill is the quill itself — the test runner that holds everything together. It provides a DSL (testCase, testList, ftestCase, ptestList, …), an executor that respects focused / pending state, and a pretty-printer that renders results with colour, indentation, and OSC 8 terminal hyperlinks pointing back to the exact source location of each failure. Depends on: Fable.Ink, Fable.Parchment, Fable.Nib.


Application libraries

Fable.Ripple is the reactive UI framework. A value changes; a ripple propagates outward through the adaptive graph; the DOM updates — no diff, no virtual tree. Built on FSharp.Data.Adaptive.

Value drops, UI wakes
No diff, no virtual tree
Just ripples outward

Fable.UrlParser is a composable URL parser. It supports path segments, query parameters (required, optional, flag, multi-value), fragments, and hash-based routing. No dependencies.


Dependency graph

Fable.Ink
│
├── Fable.Parchment
│       │
│       └── Fable.Quill ◄── Fable.Nib
│
Fable.Nib
│
└── (used by Fable.Quill, and directly by test suites)

Fable.UrlParser    (independent)
Fable.Ripple       (independent)

Test suites

Test project Tests Runner
tests/Fable.Quill.Test Runner behaviour (focus, pending, paths, exit codes) dotnet fable … --runScript
tests/Fable.Nib.Test All assertion combinators (primitives, collections, Option, Result, DU, tags, short-circuit) dotnet fable … --runScript
tests/Fable.UrlParser.Tests SimpleParser (segments, query, fragment, hash, error depth) dotnet fable … --runScript
tests/Fable.Ripple.Tests DOM rendering and routing Vitest (browser)

Run a suite:

dotnet fable tests/Fable.Quill.Test/ --runScript
dotnet fable tests/Fable.Nib.Test/ --runScript
dotnet fable tests/Fable.UrlParser/ --runScript

Usage at a glance

// Bring assertion functions into scope
open Fable.Nib

// Bring test DSL into scope
open Fable.Quill.Runner
open type Fable.Quill.Runner.Test

[<EntryPoint>]
let main _ =
    runTests [
        testList "My suite" [

            testCase("equality", fun () ->
                assertThat 42 (isEqualTo 42)
            )

            testCase("option chain", fun () ->
                assertThat (Some "hello") (Option.value >> isEqualTo "hello")
            )

            testCase("record fields with tags", fun () ->
                assertThat { Name = "alice"; Age = 25 } (
                    inside _.Age  (tag "age"  >> isGreaterOrEqual 18)
                    >> inside _.Name (tag "name" >> isNotEqualTo "")
                )
            )

        ]
    ]

Notes

Attribute order in Fable.Ripple

Attributes are applied to DOM elements sequentially, in the order they appear in source. This matches browser behaviour but can produce surprises:

// 'valueVal' is set before 'step', so the browser clamps it to 1.
input (
    type' = "range",
    min = "0",
    max = "1",
    valueVal = AVal.const "0.5",  // ← applied before step
    step = "0.1",
    onInput = ...
)

Similarly for lazy image loading:

// 'src' fires the request before 'loading = "lazy"' is set.
img (
    src = "https://example.com/image.png",
    loading = "lazy",
)

Attribute order is intentionally not reordered by the library. If order matters, place the controlling attribute before the dependent one.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages