@ape-egg/vibe-compiler 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,96 @@
1
+ use std::collections::HashMap;
2
+ use std::path::PathBuf;
3
+
4
+ /// Represents a parsed Vibe element/component
5
+ #[derive(Debug, Clone)]
6
+ pub struct Element {
7
+ /// Tag name (derived from filename, e.g., "counter" from counter.html)
8
+ pub _tag_name: String,
9
+ /// Original file path
10
+ pub _path: PathBuf,
11
+ /// Raw HTML content (the inner content of the element)
12
+ pub content: String,
13
+ /// Bindings found in this element (@[property])
14
+ pub _bindings: Vec<String>,
15
+ /// Nested element references (custom tags used within this element)
16
+ pub _nested_elements: Vec<String>,
17
+ }
18
+
19
+ impl Element {
20
+ pub fn new(tag_name: String, path: PathBuf, content: String) -> Self {
21
+ let bindings = extract_bindings(&content);
22
+ let nested_elements = extract_custom_tags(&content);
23
+
24
+ Self {
25
+ _tag_name: tag_name,
26
+ _path: path,
27
+ content,
28
+ _bindings: bindings,
29
+ _nested_elements: nested_elements,
30
+ }
31
+ }
32
+ }
33
+
34
+ /// Extract all @[property] bindings from content
35
+ fn extract_bindings(content: &str) -> Vec<String> {
36
+ let mut bindings = Vec::new();
37
+ let re = regex::Regex::new(r"@\[([^\]]+)\]").unwrap();
38
+
39
+ for cap in re.captures_iter(content) {
40
+ if let Some(m) = cap.get(1) {
41
+ let binding = m.as_str().to_string();
42
+ if !bindings.contains(&binding) {
43
+ bindings.push(binding);
44
+ }
45
+ }
46
+ }
47
+
48
+ bindings
49
+ }
50
+
51
+ /// Extract custom HTML tags (potential element references)
52
+ /// Custom tags are lowercase with hyphens, or single-word lowercase non-standard tags
53
+ fn extract_custom_tags(content: &str) -> Vec<String> {
54
+ let mut tags = Vec::new();
55
+ // Match opening tags: <tag-name> or <tagname (self-closing handled too)
56
+ let re = regex::Regex::new(r"<([a-z][a-z0-9-]*)[>\s/]").unwrap();
57
+
58
+ // Standard HTML5 elements to exclude
59
+ let standard_tags: std::collections::HashSet<&str> = [
60
+ "a", "abbr", "address", "area", "article", "aside", "audio",
61
+ "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button",
62
+ "canvas", "caption", "cite", "code", "col", "colgroup",
63
+ "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt",
64
+ "em", "embed",
65
+ "fieldset", "figcaption", "figure", "footer", "form",
66
+ "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html",
67
+ "i", "iframe", "img", "input", "ins",
68
+ "kbd",
69
+ "label", "legend", "li", "link",
70
+ "main", "map", "mark", "menu", "meta", "meter",
71
+ "nav", "noscript",
72
+ "object", "ol", "optgroup", "option", "output",
73
+ "p", "param", "picture", "pre", "progress",
74
+ "q",
75
+ "rp", "rt", "ruby",
76
+ "s", "samp", "script", "search", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg",
77
+ "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track",
78
+ "u", "ul",
79
+ "var", "video",
80
+ "wbr",
81
+ ].into_iter().collect();
82
+
83
+ for cap in re.captures_iter(content) {
84
+ if let Some(m) = cap.get(1) {
85
+ let tag = m.as_str().to_string();
86
+ if !standard_tags.contains(tag.as_str()) && !tags.contains(&tag) {
87
+ tags.push(tag);
88
+ }
89
+ }
90
+ }
91
+
92
+ tags
93
+ }
94
+
95
+ /// Cache of loaded elements by tag name
96
+ pub type ElementCache = HashMap<String, Element>;