class Can::Codegen

Overview

Codegen: emits Crystal source that writes HTML to a local io.

Static text from the source template is emitted verbatim — author responsibility to write valid HTML (e.g. &lt; for literal <). Interpolated {expr} values in text and expression attributes are HTML-escaped at runtime via stdlib ::HTML.escape. Quoted attributes are literal text.

Tags render as literal HTML unless Can can resolve them to a component method. <.def tag="Card"> defines card(io, ...), and <Card> calls it. Manually written methods can also be used as components when their first argument is named io; otherwise unknown tags pass through as literal HTML. The tag is mapped to a method name via tag.gsub('-', '_').underscore.

<.def> at the top level becomes a method (with optional named-slot Proc params and a default-slot __slot proc). <.def> inside a body becomes a local Proc that closes over surrounding bindings; v1 restriction: inline defs can't host <.slot/> and can't be invoked with slot content.

Defined in:

can/codegen.cr

Constant Summary

HTML_ELEMENTS = Set {"a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "search", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr", "animate", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "feblend", "fecolormatrix", "fecomponenttransfer", "fecomposite", "feconvolvematrix", "fediffuselighting", "fedisplacementmap", "fedistantlight", "fedropshadow", "feflood", "fefunca", "fefuncb", "fefuncg", "fefuncr", "fegaussianblur", "feimage", "femerge", "femergenode", "femorphology", "feoffset", "fepointlight", "fespecularlighting", "fespotlight", "fetile", "feturbulence", "filter", "foreignobject", "g", "image", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "set", "stop", "symbol", "textpath", "tspan", "use", "view"}
RAW_TEXT_TAGS = {"style", "script"}

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(out __arg0 : IO, scope : Symbol = :class, source_name : String | Nil = nil, used_templates : Set(String) = Set(String).new, component_methods : Set(String) = Set(String).new) #

[View source]

Class Method Detail

def self.compile(template : AST::Template, scope : Symbol = :class, source_name : String | Nil = nil) : String #

Compiles a parsed template to Crystal source. When source_name is provided, generated code includes # can: source:line:column markers that make macro-expansion errors easier to map back to the template.


[View source]
def self.compile(source : String, scope : Symbol = :class, source_name : String | Nil = nil) : String #

Parses and compiles a template string to Crystal source.


[View source]

Instance Method Detail

def emit_template(t : AST::Template) : Nil #

[View source]