///|
/// 从样式源生成类型化 wrapper(每个 class 一个 pub fn),供 rabbita 等前端做智能提示/校验
///
/// 流程:自动识别格式 → 编译成 css(展开 @each/插值成字面 .m-0 等)→ 提取全部 class
/// → 生成 `pub fn xxx() -> String { "xxx" }`。第三方在 build/SSG 里调用,写盘成 .mbt。
pub fn generate_types(source : String) -> String {
let css = compile(source) catch { _ => "" }
let classes = @scss.extract_classes_scss(css)
gen_type_wrapper(classes)
}
///|
fn gen_type_wrapper(classes : Array[String]) -> String {
let sb = StringBuilder()
sb.write_string("pub struct TW { classes : Array[String] }\n\n")
// 顶层工厂 @tw.tw();其余函数使用 MoonBit 的类型方法语法
sb.write_string("pub fn tw() -> TW { { classes: [] } }\n\n")
sb.write_string(
"pub fn TW::add(self : TW, c : String) -> TW {\n self.classes.push(c)\n self\n}\n\n",
)
sb.write_string(
"pub fn TW::class(self : TW) -> String { self.classes.join(\" \") }\n\n",
)
let seen : Array[String] = []
for c in classes {
let f = class_to_fn(c)
if contains_str(seen, f) == false {
seen.push(f)
sb.write_string("pub fn ")
sb.write_string("TW::")
sb.write_string(f)
sb.write_string("(self : TW) -> TW { self.add(\"")
sb.write_string(c)
sb.write_string("\") }\n")
}
}
sb.to_string()
}
///|
fn class_to_fn(s : String) -> String {
let sb = StringBuilder()
for ch in s {
let is_id = (ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '_'
if is_id {
sb.write_string(ch.to_string())
} else {
sb.write_string("_")
}
}
sb.to_string()
}
///|
fn contains_str(xs : Array[String], x : String) -> Bool {
for y in xs {
if y == x {
return true
}
}
false
}