-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
111 lines (85 loc) · 2.76 KB
/
Copy pathindex.js
File metadata and controls
111 lines (85 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
const STYLE_TAG_ID = "ai-css-runtime-styles";
let styleTag = null;
let styleCache = {};
let classCache = new Set();
// Built-in API URL
const API_URL = "https://server-css.vercel.app/api/css/get-styles";
// Load mapping from API (cached)
async function loadCSSMapping() {
if (Object.keys(styleCache).length > 0) return styleCache;
try {
const res = await fetch(API_URL);
const data = await res.json();
if (data?.Status === "Success" && data?.Result) {
styleCache = data.Result;
}
return styleCache;
} catch (err) {
console.error("[AI-CSS] Failed to fetch CSS mapping:", err);
return {};
}
}
// ✅ SMART PHRASE MATCHING (FIXED)
function combineCSS(instructionStr, mapping) {
const input = instructionStr.toLowerCase();
let cssText = "";
// Sort keys: longest first (important for phrases)
const keys = Object.keys(mapping).sort((a, b) => b.length - a.length);
let remaining = input;
keys.forEach(key => {
if (remaining.includes(key)) {
cssText += mapping[key];
// Remove matched part to avoid smaller overlaps
remaining = remaining.replace(key, " ");
}
});
return cssText;
}
// Inject CSS into <style>
function injectStyle(className, css) {
if (!styleTag) {
styleTag = document.createElement("style");
styleTag.id = STYLE_TAG_ID;
document.head.appendChild(styleTag);
}
if (classCache.has(className)) return;
styleTag.innerHTML += `
.${className} { ${css} }
`;
classCache.add(className);
}
// Apply styles to elements
async function scanAIClasses() {
const mapping = await loadCSSMapping();
if (!mapping || Object.keys(mapping).length === 0) return;
const elements = document.querySelectorAll("[aiclass]");
elements.forEach(el => {
const instructionStr = el.getAttribute("aiclass");
if (!instructionStr) return;
const css = combineCSS(instructionStr, mapping);
if (!css) return;
const className =
"ai_" + instructionStr.toLowerCase().replace(/\s+/g, "_");
injectStyle(className, css);
el.classList.add(className);
});
}
//////////////////////////////////////////////////////////
// ✅ AUTO RUN (React + Dynamic DOM SUPPORT)
//////////////////////////////////////////////////////////
// Run initially
setTimeout(scanAIClasses, 0);
setTimeout(scanAIClasses, 500);
setTimeout(scanAIClasses, 1000);
// Watch for DOM changes (React, Vue, dynamic UI)
const observer = new MutationObserver(() => {
scanAIClasses();
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["aiclass"]
});
// Export for manual use
export default scanAIClasses;