bindings

command
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

Documentation

Overview

Command bindings turns framework attribute syntax into plain HTML attributes where it can, and says why it cannot everywhere else.

$ bindings page.html
9 bindings: 4 rewritten, 5 left alone
  rewritten
    :title="'Home'"           -> title="Home"
    v-bind:id="'main'"        -> id="main"
    [attr.role]="'nav'"       -> role="nav"
    :hidden="true"            -> hidden="true"
  left alone
    :href="url"               the value is an expression, and nothing here evaluates one
    @click="go"               an event handler has no plain form
    *ngIf="ok"                a structural directive decides whether the element exists
    [(ngModel)]="v"           two-way binding has no plain form
    v-html="body"             writing markup from a binding is not a plain attribute

Only a literal can become a plain attribute: a quoted string, a number, true or false. An expression needs a runtime, and a program that guessed would produce a page that looks right and says something else.

A template is not HTML, and its compiler is case-sensitive

The tokenizer lower-cases attribute names, because HTML matches them case-insensitively. A framework template is HTML-shaped text read by something that does not:

source              Attribute.Name      Attribute.NamePreserveCase
*ngIf="ok"          *ngif               *ngIf
[ngClass]="c"       [ngclass]           [ngClass]
[(ngModel)]="v"     [(ngmodel)]         [(ngModel)]
v-bind:someProp     v-bind:someprop     v-bind:someProp
@myEvent            @myevent            @myEvent

`*ngIf` is a directive and `*ngif` is not, so a report built from Name names something the author cannot find, and an attribute *added* as `*ngIf` arrives as `*ngif` and stops working - lolhtml.Element.SetAttribute lower-cases a name it is adding and keeps the document's spelling for one already there. This program reads NamePreserveCase for everything it prints and never adds a name with a capital in it: the plain attributes it writes are lower-case by definition, which is the only reason it is safe to write them at all.

The same rule is documented for SVG, where viewbox is not viewBox. A template compiler is the second consumer of the same kind, and there will be others: the question is not whether the document is HTML but whether whoever reads it next cares about case.

Why the selectors are not used

Every one of these names needs escaping to appear in a selector, because the characters that make them recognisable are the characters CSS uses for something else:

[\:href]  [\@click]  [\*ngIf]  [\(click\)]  [\[ngClass\]]  [\[\(ngModel\)\]]

Those all work, and are tested. What this program does instead is match every element and read its attribute list, because a page can carry a dozen prefixes and one selector per prefix is a dozen registrations to keep in step with a list that is only going to grow. The escaping is worth knowing about anyway: an unescaped `[:href]` is a rejected selector rather than one that matches nothing, so it fails loudly - see the package documentation on escaping.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL