vyrn

std/icons

5 exports, from std/icons.vyrn.

Inline SVG icons generated from a pinned Iconify collection, one function per named glyph. Resolution happens at generation time from hash-locked bytes, and a misspelled glyph fails the build with the nearest name.

import { icons } from "std/icons"
import * as ic from icons("icons", "github rss circle-check")
import { toHtmlString } from "std/html"

fn main() -> Int64 {
    print(toHtmlString(ic.github()))
    return 0
}

"icons" is a relative .json path or a vyrn.json dependency alias (vyrn add github:iconify/icon-sets@<sha>/json/lucide.json --name icons). Each glyph circle-check becomes fn circleCheck() -> Html: an inline <svg> sized 1em, in currentColor, and aria-hidden. Two names that camel-case to one identifier are refused.

A template's <Icon name="ui:github"/> needs a project provider module:

// `vyrn.json` binds `ui` and `codex`; those names are the prefixes.
import { iconProvider } from "std/icons"

export gen fn Icon(attrs: String, file: String, line: Int64, col: Int64) -> String {
    return iconProvider(attrs, file, line, col, "ui codex")
}

The tag takes name, and optionally size (a CSS length), label (the accessible name) and class; any other attribute is refused.

Dependencies

The import graph shows the whole library.

Imported by
gen fn icons(collection: String, names: String) -> String

One function per glyph in names (space-separated Iconify names), read from collection: a relative .json path or a vyrn.json dependency alias.

gen fn iconsAt(
    collection: String,
    names: String,
    anchorFile: String,
    line: Int64,
    col: Int64,
) -> String

icons with reports anchored at anchorFile/line/col, the template tag that asked. A provider emits an import of this, so the collection alias is this generation's own constant argument and resolves through vyrn.json.

gen fn iconsModule(
    collectionText: String,
    collectionPath: String,
    names: String,
    anchorFile: String,
    line: Int64,
    col: Int64,
) -> String

icons over collection text already read. collectionPath is only named in diagnostics and the header. An empty anchorFile anchors reports in the collection file.

gen fn iconProvider(
    attrs: String,
    file: String,
    line: Int64,
    col: Int64,
    collections: String,
) -> String

A project's <Icon> provider. collections is a space-separated list of vyrn.json aliases, and those names are the tag's prefixes. With one collection bound a bare name means that one; with more it is refused. Reads nothing: it emits an iconsAt import, where the alias resolves.

fn iconAttrs(g: consume Html, size: String, label: String, class: String) -> Html

Applies the use site's attributes to a generated glyph at run time. A size replaces 1em; a label adds role="img" and aria-label and removes aria-hidden; a class is appended.

Tests

26 test blocks in std/icons.vyrn. CI runs all of them.

Test names
  • a named glyph becomes one function over the shared helper
  • the collection's licence is the generated header's own line
  • a collection that declares no terms says so rather than saying nothing
  • a hyphenated name becomes one lowerCamelCase function
  • an alias resolves to its parent's markup
  • a glyph that overrides its width gets its own viewBox
  • an unknown glyph is a report with the nearest name, and no declaration
  • a report lands on the anchor the caller gave
  • an alias asking for a transform is refused, not rendered unturned
  • two names that camel-case to one identifier are refused
  • a prefixed name is refused, naming the bare glyph to write
  • an empty name list is refused
  • a collection that is not JSON is refused, naming the path
  • a JSON document that is not a collection is refused, naming the path
  • a glyph named like the module's own helper is refused, not emitted broken
  • an entry origin reaches the viewBox
  • the collection's own origin is inherited when the entry has none
  • an alias may re-origin as well as resize
  • a tag becomes an anchored iconsAt import and the conventional entry point
  • one bound collection takes a bare name
  • with two bound collections a bare name is refused, naming the vocabulary
  • a prefix the provider does not bind is refused at the tag
  • an attribute the provider does not know is refused by name
  • a tag with no name says what one looks like in this project's vocabulary
  • size, label and class reach the use site
  • a decorative glyph stays hidden and a labelled one is named

Examples

    No example program imports this module.