feat: port el-ui vessels — rename crates→vessels, add El source + manifests
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
// el-html — Atomic HTML element primitives.
|
||||
//
|
||||
// Usage:
|
||||
// el_div("class=\"card\"", inner_html)
|
||||
// el_h1("", "Hello world")
|
||||
// el_img("/logo.png", "Logo", "width=\"120\"")
|
||||
//
|
||||
// Children args are raw HTML — pre-escaped by caller.
|
||||
// Use el_text(s) to safely insert plain text.
|
||||
|
||||
// ── Text escaping ─────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_escape(s: String) -> String {
|
||||
let s = str_replace(s, "&", "&")
|
||||
let s = str_replace(s, "<", "<")
|
||||
let s = str_replace(s, ">", ">")
|
||||
let s = str_replace(s, "\"", """)
|
||||
str_replace(s, "'", "'")
|
||||
}
|
||||
|
||||
fn el_text(s: String) -> String {
|
||||
el_escape(s)
|
||||
}
|
||||
|
||||
fn el_attr(name: String, value: String) -> String {
|
||||
" " + name + "=\"" + el_escape(value) + "\""
|
||||
}
|
||||
|
||||
// ── Block elements ────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_div(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<div>" + children + "</div>" }
|
||||
"<div " + attrs + ">" + children + "</div>"
|
||||
}
|
||||
|
||||
fn el_section(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<section>" + children + "</section>" }
|
||||
"<section " + attrs + ">" + children + "</section>"
|
||||
}
|
||||
|
||||
fn el_article(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<article>" + children + "</article>" }
|
||||
"<article " + attrs + ">" + children + "</article>"
|
||||
}
|
||||
|
||||
fn el_header(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<header>" + children + "</header>" }
|
||||
"<header " + attrs + ">" + children + "</header>"
|
||||
}
|
||||
|
||||
fn el_footer(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<footer>" + children + "</footer>" }
|
||||
"<footer " + attrs + ">" + children + "</footer>"
|
||||
}
|
||||
|
||||
fn el_main(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<main>" + children + "</main>" }
|
||||
"<main " + attrs + ">" + children + "</main>"
|
||||
}
|
||||
|
||||
fn el_nav(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<nav>" + children + "</nav>" }
|
||||
"<nav " + attrs + ">" + children + "</nav>"
|
||||
}
|
||||
|
||||
fn el_aside(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<aside>" + children + "</aside>" }
|
||||
"<aside " + attrs + ">" + children + "</aside>"
|
||||
}
|
||||
|
||||
fn el_ul(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<ul>" + children + "</ul>" }
|
||||
"<ul " + attrs + ">" + children + "</ul>"
|
||||
}
|
||||
|
||||
fn el_ol(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<ol>" + children + "</ol>" }
|
||||
"<ol " + attrs + ">" + children + "</ol>"
|
||||
}
|
||||
|
||||
fn el_li(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<li>" + children + "</li>" }
|
||||
"<li " + attrs + ">" + children + "</li>"
|
||||
}
|
||||
|
||||
fn el_p(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<p>" + children + "</p>" }
|
||||
"<p " + attrs + ">" + children + "</p>"
|
||||
}
|
||||
|
||||
fn el_span(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<span>" + children + "</span>" }
|
||||
"<span " + attrs + ">" + children + "</span>"
|
||||
}
|
||||
|
||||
fn el_form(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<form>" + children + "</form>" }
|
||||
"<form " + attrs + ">" + children + "</form>"
|
||||
}
|
||||
|
||||
// ── Headings ──────────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_h1(attrs: String, text: String) -> String {
|
||||
if str_eq(attrs, "") { return "<h1>" + el_escape(text) + "</h1>" }
|
||||
"<h1 " + attrs + ">" + el_escape(text) + "</h1>"
|
||||
}
|
||||
|
||||
fn el_h2(attrs: String, text: String) -> String {
|
||||
if str_eq(attrs, "") { return "<h2>" + el_escape(text) + "</h2>" }
|
||||
"<h2 " + attrs + ">" + el_escape(text) + "</h2>"
|
||||
}
|
||||
|
||||
fn el_h3(attrs: String, text: String) -> String {
|
||||
if str_eq(attrs, "") { return "<h3>" + el_escape(text) + "</h3>" }
|
||||
"<h3 " + attrs + ">" + el_escape(text) + "</h3>"
|
||||
}
|
||||
|
||||
fn el_h4(attrs: String, text: String) -> String {
|
||||
if str_eq(attrs, "") { return "<h4>" + el_escape(text) + "</h4>" }
|
||||
"<h4 " + attrs + ">" + el_escape(text) + "</h4>"
|
||||
}
|
||||
|
||||
// ── Interactive ───────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_button(attrs: String, label: String) -> String {
|
||||
if str_eq(attrs, "") { return "<button type=\"button\">" + el_escape(label) + "</button>" }
|
||||
"<button type=\"button\" " + attrs + ">" + el_escape(label) + "</button>"
|
||||
}
|
||||
|
||||
fn el_a(href: String, attrs: String, children: String) -> String {
|
||||
let h: String = "href=\"" + el_escape(href) + "\""
|
||||
if str_eq(attrs, "") { return "<a " + h + ">" + children + "</a>" }
|
||||
"<a " + h + " " + attrs + ">" + children + "</a>"
|
||||
}
|
||||
|
||||
fn el_input(type_attr: String, attrs: String) -> String {
|
||||
if str_eq(attrs, "") { return "<input type=\"" + type_attr + "\" />" }
|
||||
"<input type=\"" + type_attr + "\" " + attrs + " />"
|
||||
}
|
||||
|
||||
fn el_textarea(attrs: String, value: String) -> String {
|
||||
if str_eq(attrs, "") { return "<textarea>" + el_escape(value) + "</textarea>" }
|
||||
"<textarea " + attrs + ">" + el_escape(value) + "</textarea>"
|
||||
}
|
||||
|
||||
fn el_label(for_id: String, attrs: String, children: String) -> String {
|
||||
let f: String = "for=\"" + el_escape(for_id) + "\""
|
||||
if str_eq(attrs, "") { return "<label " + f + ">" + children + "</label>" }
|
||||
"<label " + f + " " + attrs + ">" + children + "</label>"
|
||||
}
|
||||
|
||||
// ── Media ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_img(src: String, alt: String, attrs: String) -> String {
|
||||
let base: String = "src=\"" + el_escape(src) + "\" alt=\"" + el_escape(alt) + "\""
|
||||
if str_eq(attrs, "") { return "<img " + base + " />" }
|
||||
"<img " + base + " " + attrs + " />"
|
||||
}
|
||||
|
||||
fn el_video(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<video>" + children + "</video>" }
|
||||
"<video " + attrs + ">" + children + "</video>"
|
||||
}
|
||||
|
||||
// ── Inline semantic ───────────────────────────────────────────────────────────
|
||||
|
||||
fn el_strong(children: String) -> String {
|
||||
"<strong>" + children + "</strong>"
|
||||
}
|
||||
|
||||
fn el_em(children: String) -> String {
|
||||
"<em>" + children + "</em>"
|
||||
}
|
||||
|
||||
fn el_code(children: String) -> String {
|
||||
"<code>" + children + "</code>"
|
||||
}
|
||||
|
||||
fn el_pre(attrs: String, children: String) -> String {
|
||||
if str_eq(attrs, "") { return "<pre>" + children + "</pre>" }
|
||||
"<pre " + attrs + ">" + children + "</pre>"
|
||||
}
|
||||
|
||||
fn el_hr() -> String { "<hr />" }
|
||||
fn el_br() -> String { "<br />" }
|
||||
|
||||
// ── Document shell ────────────────────────────────────────────────────────────
|
||||
|
||||
fn el_html_doc(lang: String, head_html: String, body_html: String) -> String {
|
||||
"<!doctype html><html lang=\"" + el_escape(lang) + "\"><head>"
|
||||
+ head_html + "</head><body>" + body_html + "</body></html>"
|
||||
}
|
||||
|
||||
fn el_meta(name: String, content: String) -> String {
|
||||
"<meta name=\"" + el_escape(name) + "\" content=\"" + el_escape(content) + "\" />"
|
||||
}
|
||||
|
||||
fn el_meta_charset(charset: String) -> String {
|
||||
"<meta charset=\"" + el_escape(charset) + "\" />"
|
||||
}
|
||||
|
||||
fn el_link_stylesheet(href: String) -> String {
|
||||
"<link rel=\"stylesheet\" href=\"" + el_escape(href) + "\" />"
|
||||
}
|
||||
|
||||
fn el_script_src(src: String, defer_load: Bool) -> String {
|
||||
if defer_load { return "<script src=\"" + el_escape(src) + "\" defer></script>" }
|
||||
"<script src=\"" + el_escape(src) + "\"></script>"
|
||||
}
|
||||
|
||||
fn el_script_inline(js: String) -> String {
|
||||
"<script>" + js + "</script>"
|
||||
}
|
||||
|
||||
fn el_title(text: String) -> String {
|
||||
"<title>" + el_escape(text) + "</title>"
|
||||
}
|
||||
|
||||
// ── Entry — smoke test ────────────────────────────────────────────────────────
|
||||
|
||||
let sample: String = el_div("class=\"card\"", el_h2("", "Hello") + el_p("", "World"))
|
||||
println("[el-html] sample = " + sample)
|
||||
Reference in New Issue
Block a user