Spaces:
Sleeping
Sleeping
Commit ·
96c754a
1
Parent(s): 77accfa
feat: transform JSON terminal output into styled HTML list hierarchy in UI
Browse files- code.html +55 -17
- dashboard.html +71 -19
- glassui.html +58 -19
code.html
CHANGED
|
@@ -164,23 +164,7 @@ SKU: JK-2024-WTR"></textarea>
|
|
| 164 |
</div>
|
| 165 |
</div>
|
| 166 |
<div class="flex-1 p-4 overflow-auto custom-scrollbar font-mono text-sm leading-6">
|
| 167 |
-
<
|
| 168 |
-
<span class="text-slate-500">2</span> <span class="text-primary">"product_analysis"</span><span class="text-white">:</span> <span class="text-yellow-500">{</span>
|
| 169 |
-
<span class="text-slate-500">3</span> <span class="text-primary">"title"</span><span class="text-white">:</span> <span class="text-sky-300">"Apex Terrain All-Weather Performance Jacket"</span><span class="text-white">,</span>
|
| 170 |
-
<span class="text-slate-500">4</span> <span class="text-primary">"category"</span><span class="text-white">:</span> <span class="text-sky-300">"Outerwear / Men's / Technical Shells"</span><span class="text-white">,</span>
|
| 171 |
-
<span class="text-slate-500">5</span> <span class="text-primary">"features"</span><span class="text-white">:</span> <span class="text-yellow-500">[</span>
|
| 172 |
-
<span class="text-slate-500">6</span> <span class="text-sky-300">"Gore-Tex Pro Membrane"</span><span class="text-white">,</span>
|
| 173 |
-
<span class="text-slate-500">7</span> <span class="text-sky-300">"Articulated Sleeves"</span><span class="text-white">,</span>
|
| 174 |
-
<span class="text-slate-500">8</span> <span class="text-sky-300">"Helmet-Compatible Hood"</span>
|
| 175 |
-
<span class="text-slate-500">9</span> <span class="text-yellow-500">]</span><span class="text-white">,</span>
|
| 176 |
-
<span class="text-slate-500">10</span> <span class="text-primary">"seo_tags"</span><span class="text-white">:</span> <span class="text-yellow-500">[</span>
|
| 177 |
-
<span class="text-slate-500">11</span> <span class="text-sky-300">"#hikinggear"</span><span class="text-white">,</span> <span class="text-sky-300">"#waterproof"</span><span class="text-white">,</span> <span class="text-sky-300">"#adventure"</span>
|
| 178 |
-
<span class="text-slate-500">12</span> <span class="text-yellow-500">]</span><span class="text-white">,</span>
|
| 179 |
-
<span class="text-slate-500">13</span> <span class="text-primary">"sentiment_score"</span><span class="text-white">:</span> <span class="text-purple-400">0.98</span><span class="text-white">,</span>
|
| 180 |
-
<span class="text-slate-500">14</span> <span class="text-primary">"market_fit"</span><span class="text-white">:</span> <span class="text-sky-300">"High Demand"</span>
|
| 181 |
-
<span class="text-slate-500">15</span> <span class="text-yellow-500">}</span><span class="text-white">,</span>
|
| 182 |
-
<span class="text-slate-500">16</span> <span class="text-primary">"deployment_status"</span><span class="text-white">:</span> <span class="text-sky-300">"Ready"</span>
|
| 183 |
-
<span class="text-slate-500">17</span> <span class="text-yellow-500">}</span></code></pre>
|
| 184 |
</div>
|
| 185 |
</div>
|
| 186 |
</div>
|
|
@@ -195,6 +179,60 @@ SKU: JK-2024-WTR"></textarea>
|
|
| 195 |
'100%': { left: '125%' },
|
| 196 |
}
|
| 197 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
</script>
|
| 199 |
|
| 200 |
</body></html>
|
|
|
|
| 164 |
</div>
|
| 165 |
</div>
|
| 166 |
<div class="flex-1 p-4 overflow-auto custom-scrollbar font-mono text-sm leading-6">
|
| 167 |
+
<div id="jsonOutput" class="w-full"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
</div>
|
| 169 |
</div>
|
| 170 |
</div>
|
|
|
|
| 179 |
'100%': { left: '125%' },
|
| 180 |
}
|
| 181 |
}
|
| 182 |
+
|
| 183 |
+
const INITIAL_DATA = {
|
| 184 |
+
"product_analysis": {
|
| 185 |
+
"title": "Apex Terrain All-Weather Performance Jacket",
|
| 186 |
+
"category": "Outerwear / Men's / Technical Shells",
|
| 187 |
+
"features": ["Gore-Tex Pro Membrane", "Articulated Sleeves", "Helmet-Compatible Hood"],
|
| 188 |
+
"seo_tags": ["#hikinggear", "#waterproof", "#adventure"],
|
| 189 |
+
"sentiment_score": 0.98,
|
| 190 |
+
"market_fit": "High Demand"
|
| 191 |
+
},
|
| 192 |
+
"deployment_status": "Ready"
|
| 193 |
+
};
|
| 194 |
+
window.__currentJSONData = INITIAL_DATA;
|
| 195 |
+
|
| 196 |
+
function jsonToHTMLList(data, isRoot = true) {
|
| 197 |
+
if (typeof data !== 'object' || data === null) {
|
| 198 |
+
return `<span class="text-slate-300 break-words">${data}</span>`;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
const isArray = Array.isArray(data);
|
| 202 |
+
let html = `<ul class="space-y-2 ${isRoot ? '' : 'pl-4 lg:pl-6 border-l border-border-dark mt-2'}">`;
|
| 203 |
+
|
| 204 |
+
for (const key in data) {
|
| 205 |
+
if (data.hasOwnProperty(key)) {
|
| 206 |
+
const value = data[key];
|
| 207 |
+
const isValueObject = typeof value === 'object' && value !== null;
|
| 208 |
+
|
| 209 |
+
html += `<li class="relative">`;
|
| 210 |
+
|
| 211 |
+
if (!isRoot) {
|
| 212 |
+
html += `<span class="absolute -left-[20px] lg:-left-[28px] top-2.5 size-1.5 rounded-full bg-primary/50"></span>`;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
if (!isArray) {
|
| 216 |
+
html += `<strong class="text-primary font-semibold mr-2">${key}:</strong>`;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
if (isValueObject) {
|
| 220 |
+
html += `<div class="mt-1">${jsonToHTMLList(value, false)}</div>`;
|
| 221 |
+
} else {
|
| 222 |
+
if (isArray) {
|
| 223 |
+
html += `<span class="inline-block bg-primary/10 border border-primary/20 rounded-full px-2.5 py-0.5 text-xs text-sky-300 mt-1">${value}</span>`;
|
| 224 |
+
} else {
|
| 225 |
+
html += `<span class="text-slate-300 break-words">${value}</span>`;
|
| 226 |
+
}
|
| 227 |
+
}
|
| 228 |
+
html += `</li>`;
|
| 229 |
+
}
|
| 230 |
+
}
|
| 231 |
+
html += `</ul>`;
|
| 232 |
+
return html;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
document.getElementById('jsonOutput').innerHTML = jsonToHTMLList(window.__currentJSONData);
|
| 236 |
</script>
|
| 237 |
|
| 238 |
</body></html>
|
dashboard.html
CHANGED
|
@@ -258,23 +258,7 @@
|
|
| 258 |
</div>
|
| 259 |
</div>
|
| 260 |
<div class="flex-1 p-4 lg:p-5 overflow-auto custom-scrollbar font-mono text-xs lg:text-sm leading-6 lg:leading-7">
|
| 261 |
-
<
|
| 262 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">02</span> <span class="text-amber-600">"product_analysis"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">{</span>
|
| 263 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">03</span> <span class="text-amber-600">"title"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Noir Elite Series Artisan Timepiece"</span><span class="text-neutral-400">,</span>
|
| 264 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">04</span> <span class="text-amber-600">"category"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Luxury / Accessories"</span><span class="text-neutral-400">,</span>
|
| 265 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">05</span> <span class="text-amber-600">"features"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">[</span>
|
| 266 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">06</span> <span class="text-amber-200">"Obsidian Finish"</span><span class="text-neutral-400">,</span>
|
| 267 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">07</span> <span class="text-amber-200">"Golden Accents"</span><span class="text-neutral-400">,</span>
|
| 268 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">08</span> <span class="text-amber-200">"Smart Haptic Interface"</span>
|
| 269 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">09</span> <span class="text-amber-400">]</span><span class="text-neutral-400">,</span>
|
| 270 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">10</span> <span class="text-amber-600">"seo_tags"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">[</span>
|
| 271 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">11</span> <span class="text-amber-200">"#luxurywear"</span><span class="text-neutral-400">,</span> <span class="text-amber-200">"#amberstyle"</span><span class="text-neutral-400">,</span> <span class="text-amber-200">"#premiumtech"</span>
|
| 272 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">12</span> <span class="text-amber-400">]</span><span class="text-neutral-400">,</span>
|
| 273 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">13</span> <span class="text-amber-600">"sentiment_score"</span><span class="text-neutral-400">:</span> <span class="text-amber-500">0.99</span><span class="text-neutral-400">,</span>
|
| 274 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">14</span> <span class="text-amber-600">"market_fit"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Exceptional"</span>
|
| 275 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">15</span> <span class="text-amber-400">}</span><span class="text-neutral-400">,</span>
|
| 276 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">16</span> <span class="text-amber-600">"deployment_status"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Authorized"</span>
|
| 277 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">17</span><span class="text-amber-400">}</span></code></pre>
|
| 278 |
</div>
|
| 279 |
</div>
|
| 280 |
</div>
|
|
@@ -288,6 +272,57 @@
|
|
| 288 |
tailwind.config.theme.extend.keyframes = {
|
| 289 |
shine: { '0%': { left: '-100%' }, '100%': { left: '200%' } }
|
| 290 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
const dropZone = document.getElementById('dropZone');
|
| 292 |
const fileInput = document.getElementById('fileInput');
|
| 293 |
const startBtn = document.getElementById('startBtn');
|
|
@@ -373,7 +408,8 @@ startBtn.addEventListener('click', async (e) => {
|
|
| 373 |
const response = await fetch('/generate-catalog', { method: 'POST', body: formData });
|
| 374 |
if (!response.ok) throw new Error("Server Error " + response.status);
|
| 375 |
const data = await response.json();
|
| 376 |
-
|
|
|
|
| 377 |
isCatalogGenerated = true;
|
| 378 |
} catch (error) {
|
| 379 |
console.error("Agent Error:", error); alert("Pipeline failed: " + error.message);
|
|
@@ -382,11 +418,27 @@ startBtn.addEventListener('click', async (e) => {
|
|
| 382 |
}
|
| 383 |
});
|
| 384 |
copyBtn.addEventListener('click', () => {
|
| 385 |
-
navigator.clipboard.writeText(
|
| 386 |
const originalIcon = copyIcon.innerText; copyIcon.innerText = 'check'; copyIcon.classList.add('text-green-400');
|
| 387 |
setTimeout(() => { copyIcon.innerText = originalIcon; copyIcon.classList.remove('text-green-400'); }, 2000);
|
| 388 |
});
|
| 389 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 390 |
</script>
|
| 391 |
</body>
|
| 392 |
</html>
|
|
|
|
| 258 |
</div>
|
| 259 |
</div>
|
| 260 |
<div class="flex-1 p-4 lg:p-5 overflow-auto custom-scrollbar font-mono text-xs lg:text-sm leading-6 lg:leading-7">
|
| 261 |
+
<div id="jsonOutput" class="w-full"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
</div>
|
| 263 |
</div>
|
| 264 |
</div>
|
|
|
|
| 272 |
tailwind.config.theme.extend.keyframes = {
|
| 273 |
shine: { '0%': { left: '-100%' }, '100%': { left: '200%' } }
|
| 274 |
}
|
| 275 |
+
const INITIAL_DATA = {
|
| 276 |
+
"product_analysis": {
|
| 277 |
+
"title": "Noir Elite Series Artisan Timepiece",
|
| 278 |
+
"category": "Luxury / Accessories",
|
| 279 |
+
"features": ["Obsidian Finish", "Golden Accents", "Smart Haptic Interface"],
|
| 280 |
+
"seo_tags": ["#luxurywear", "#amberstyle", "#premiumtech"],
|
| 281 |
+
"sentiment_score": 0.99,
|
| 282 |
+
"market_fit": "Exceptional"
|
| 283 |
+
},
|
| 284 |
+
"deployment_status": "Authorized"
|
| 285 |
+
};
|
| 286 |
+
window.__currentJSONData = INITIAL_DATA;
|
| 287 |
+
|
| 288 |
+
function jsonToHTMLList(data, isRoot = true) {
|
| 289 |
+
if (typeof data !== 'object' || data === null) {
|
| 290 |
+
return `<span class="text-neutral-300 break-words">${data}</span>`;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
const isArray = Array.isArray(data);
|
| 294 |
+
let html = `<ul class="space-y-2 ${isRoot ? '' : 'pl-4 lg:pl-6 border-l border-white/10 mt-2'}">`;
|
| 295 |
+
|
| 296 |
+
for (const key in data) {
|
| 297 |
+
if (data.hasOwnProperty(key)) {
|
| 298 |
+
const value = data[key];
|
| 299 |
+
const isValueObject = typeof value === 'object' && value !== null;
|
| 300 |
+
|
| 301 |
+
html += `<li class="relative">`;
|
| 302 |
+
|
| 303 |
+
if (!isRoot) {
|
| 304 |
+
html += `<span class="absolute -left-[20px] lg:-left-[28px] top-2.5 size-1.5 rounded-full bg-amber-500/50"></span>`;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
if (!isArray) {
|
| 308 |
+
html += `<strong class="text-amber-400 font-semibold mr-2">${key}:</strong>`;
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
if (isValueObject) {
|
| 312 |
+
html += `<div class="mt-1">${jsonToHTMLList(value, false)}</div>`;
|
| 313 |
+
} else {
|
| 314 |
+
if (isArray) {
|
| 315 |
+
html += `<span class="inline-block bg-amber-500/10 border border-amber-500/20 rounded-full px-2.5 py-0.5 text-xs text-amber-200 mt-1">${value}</span>`;
|
| 316 |
+
} else {
|
| 317 |
+
html += `<span class="text-neutral-300 break-words">${value}</span>`;
|
| 318 |
+
}
|
| 319 |
+
}
|
| 320 |
+
html += `</li>`;
|
| 321 |
+
}
|
| 322 |
+
}
|
| 323 |
+
html += `</ul>`;
|
| 324 |
+
return html;
|
| 325 |
+
}
|
| 326 |
const dropZone = document.getElementById('dropZone');
|
| 327 |
const fileInput = document.getElementById('fileInput');
|
| 328 |
const startBtn = document.getElementById('startBtn');
|
|
|
|
| 408 |
const response = await fetch('/generate-catalog', { method: 'POST', body: formData });
|
| 409 |
if (!response.ok) throw new Error("Server Error " + response.status);
|
| 410 |
const data = await response.json();
|
| 411 |
+
window.__currentJSONData = data;
|
| 412 |
+
jsonOutput.innerHTML = jsonToHTMLList(data);
|
| 413 |
isCatalogGenerated = true;
|
| 414 |
} catch (error) {
|
| 415 |
console.error("Agent Error:", error); alert("Pipeline failed: " + error.message);
|
|
|
|
| 418 |
}
|
| 419 |
});
|
| 420 |
copyBtn.addEventListener('click', () => {
|
| 421 |
+
navigator.clipboard.writeText(JSON.stringify(window.__currentJSONData, null, 2)).then(() => {
|
| 422 |
const originalIcon = copyIcon.innerText; copyIcon.innerText = 'check'; copyIcon.classList.add('text-green-400');
|
| 423 |
setTimeout(() => { copyIcon.innerText = originalIcon; copyIcon.classList.remove('text-green-400'); }, 2000);
|
| 424 |
});
|
| 425 |
});
|
| 426 |
+
|
| 427 |
+
const downloadBtn = document.getElementById('downloadBtn');
|
| 428 |
+
if (downloadBtn) {
|
| 429 |
+
downloadBtn.addEventListener('click', () => {
|
| 430 |
+
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(window.__currentJSONData, null, 2));
|
| 431 |
+
const downloadAnchorNode = document.createElement('a');
|
| 432 |
+
downloadAnchorNode.setAttribute("href", dataStr);
|
| 433 |
+
downloadAnchorNode.setAttribute("download", "stylesync_output.json");
|
| 434 |
+
document.body.appendChild(downloadAnchorNode);
|
| 435 |
+
downloadAnchorNode.click();
|
| 436 |
+
downloadAnchorNode.remove();
|
| 437 |
+
});
|
| 438 |
+
}
|
| 439 |
+
|
| 440 |
+
// Initialize placeholder data
|
| 441 |
+
jsonOutput.innerHTML = jsonToHTMLList(window.__currentJSONData);
|
| 442 |
</script>
|
| 443 |
</body>
|
| 444 |
</html>
|
glassui.html
CHANGED
|
@@ -254,23 +254,7 @@
|
|
| 254 |
</div>
|
| 255 |
</div>
|
| 256 |
<div class="flex-1 p-4 lg:p-5 overflow-auto custom-scrollbar font-mono text-xs lg:text-sm leading-6 lg:leading-7">
|
| 257 |
-
<
|
| 258 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">02</span> <span class="text-amber-600">"product_analysis"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">{</span>
|
| 259 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">03</span> <span class="text-amber-600">"title"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Noir Elite Series Artisan Timepiece"</span><span class="text-neutral-400">,</span>
|
| 260 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">04</span> <span class="text-amber-600">"category"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Luxury / Accessories"</span><span class="text-neutral-400">,</span>
|
| 261 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">05</span> <span class="text-amber-600">"features"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">[</span>
|
| 262 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">06</span> <span class="text-amber-200">"Obsidian Finish"</span><span class="text-neutral-400">,</span>
|
| 263 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">07</span> <span class="text-amber-200">"Golden Accents"</span><span class="text-neutral-400">,</span>
|
| 264 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">08</span> <span class="text-amber-200">"Smart Haptic Interface"</span>
|
| 265 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">09</span> <span class="text-amber-400">]</span><span class="text-neutral-400">,</span>
|
| 266 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">10</span> <span class="text-amber-600">"seo_tags"</span><span class="text-neutral-400">:</span> <span class="text-amber-400">[</span>
|
| 267 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">11</span> <span class="text-amber-200">"#luxurywear"</span><span class="text-neutral-400">,</span> <span class="text-amber-200">"#amberstyle"</span><span class="text-neutral-400">,</span> <span class="text-amber-200">"#premiumtech"</span>
|
| 268 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">12</span> <span class="text-amber-400">]</span><span class="text-neutral-400">,</span>
|
| 269 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">13</span> <span class="text-amber-600">"sentiment_score"</span><span class="text-neutral-400">:</span> <span class="text-amber-500">0.99</span><span class="text-neutral-400">,</span>
|
| 270 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">14</span> <span class="text-amber-600">"market_fit"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Exceptional"</span>
|
| 271 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">15</span> <span class="text-amber-400">}</span><span class="text-neutral-400">,</span>
|
| 272 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">16</span> <span class="text-amber-600">"deployment_status"</span><span class="text-neutral-400">:</span> <span class="text-amber-200">"Authorized"</span>
|
| 273 |
-
<span class="text-neutral-700 select-none mr-3 lg:mr-4 border-r border-neutral-800 pr-2">17</span><span class="text-amber-400">}</span></code></pre>
|
| 274 |
</div>
|
| 275 |
</div>
|
| 276 |
</div>
|
|
@@ -289,6 +273,58 @@
|
|
| 289 |
'100%': { left: '200%' },
|
| 290 |
}
|
| 291 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
const dropZone = document.getElementById('dropZone');
|
| 293 |
const fileInput = document.getElementById('fileInput');
|
| 294 |
const startBtn = document.getElementById('startBtn');
|
|
@@ -376,7 +412,7 @@
|
|
| 376 |
}
|
| 377 |
|
| 378 |
copyBtn.addEventListener('click', () => {
|
| 379 |
-
const textToCopy =
|
| 380 |
navigator.clipboard.writeText(textToCopy).then(() => {
|
| 381 |
const originalIcon = copyIcon.innerText;
|
| 382 |
copyIcon.style.opacity = '0';
|
|
@@ -405,7 +441,7 @@
|
|
| 405 |
});
|
| 406 |
});
|
| 407 |
downloadBtn.addEventListener('click', () => {
|
| 408 |
-
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(
|
| 409 |
const downloadAnchorNode = document.createElement('a');
|
| 410 |
downloadAnchorNode.setAttribute("href", dataStr);
|
| 411 |
downloadAnchorNode.setAttribute("download", "stylesync_output.json");
|
|
@@ -428,6 +464,9 @@
|
|
| 428 |
startBtn.classList.add('animate-pulse-slow', 'animate-glow-pulse');
|
| 429 |
}, 1500);
|
| 430 |
});
|
|
|
|
|
|
|
|
|
|
| 431 |
</script>
|
| 432 |
|
| 433 |
</body></html>
|
|
|
|
| 254 |
</div>
|
| 255 |
</div>
|
| 256 |
<div class="flex-1 p-4 lg:p-5 overflow-auto custom-scrollbar font-mono text-xs lg:text-sm leading-6 lg:leading-7">
|
| 257 |
+
<div id="jsonOutput" class="w-full"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
</div>
|
| 259 |
</div>
|
| 260 |
</div>
|
|
|
|
| 273 |
'100%': { left: '200%' },
|
| 274 |
}
|
| 275 |
}
|
| 276 |
+
|
| 277 |
+
const INITIAL_DATA = {
|
| 278 |
+
"product_analysis": {
|
| 279 |
+
"title": "Noir Elite Series Artisan Timepiece",
|
| 280 |
+
"category": "Luxury / Accessories",
|
| 281 |
+
"features": ["Obsidian Finish", "Golden Accents", "Smart Haptic Interface"],
|
| 282 |
+
"seo_tags": ["#luxurywear", "#amberstyle", "#premiumtech"],
|
| 283 |
+
"sentiment_score": 0.99,
|
| 284 |
+
"market_fit": "Exceptional"
|
| 285 |
+
},
|
| 286 |
+
"deployment_status": "Authorized"
|
| 287 |
+
};
|
| 288 |
+
window.__currentJSONData = INITIAL_DATA;
|
| 289 |
+
|
| 290 |
+
function jsonToHTMLList(data, isRoot = true) {
|
| 291 |
+
if (typeof data !== 'object' || data === null) {
|
| 292 |
+
return `<span class="text-neutral-300 break-words">${data}</span>`;
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
const isArray = Array.isArray(data);
|
| 296 |
+
let html = `<ul class="space-y-2 ${isRoot ? '' : 'pl-4 lg:pl-6 border-l border-white/10 mt-2'}">`;
|
| 297 |
+
|
| 298 |
+
for (const key in data) {
|
| 299 |
+
if (data.hasOwnProperty(key)) {
|
| 300 |
+
const value = data[key];
|
| 301 |
+
const isValueObject = typeof value === 'object' && value !== null;
|
| 302 |
+
|
| 303 |
+
html += `<li class="relative">`;
|
| 304 |
+
|
| 305 |
+
if (!isRoot) {
|
| 306 |
+
html += `<span class="absolute -left-[20px] lg:-left-[28px] top-2.5 size-1.5 rounded-full bg-amber-500/50"></span>`;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
if (!isArray) {
|
| 310 |
+
html += `<strong class="text-amber-400 font-semibold mr-2">${key}:</strong>`;
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
if (isValueObject) {
|
| 314 |
+
html += `<div class="mt-1">${jsonToHTMLList(value, false)}</div>`;
|
| 315 |
+
} else {
|
| 316 |
+
if (isArray) {
|
| 317 |
+
html += `<span class="inline-block bg-amber-500/10 border border-amber-500/20 rounded-full px-2.5 py-0.5 text-xs text-amber-200 mt-1">${value}</span>`;
|
| 318 |
+
} else {
|
| 319 |
+
html += `<span class="text-neutral-300 break-words">${value}</span>`;
|
| 320 |
+
}
|
| 321 |
+
}
|
| 322 |
+
html += `</li>`;
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
html += `</ul>`;
|
| 326 |
+
return html;
|
| 327 |
+
}
|
| 328 |
const dropZone = document.getElementById('dropZone');
|
| 329 |
const fileInput = document.getElementById('fileInput');
|
| 330 |
const startBtn = document.getElementById('startBtn');
|
|
|
|
| 412 |
}
|
| 413 |
|
| 414 |
copyBtn.addEventListener('click', () => {
|
| 415 |
+
const textToCopy = JSON.stringify(window.__currentJSONData, null, 2);
|
| 416 |
navigator.clipboard.writeText(textToCopy).then(() => {
|
| 417 |
const originalIcon = copyIcon.innerText;
|
| 418 |
copyIcon.style.opacity = '0';
|
|
|
|
| 441 |
});
|
| 442 |
});
|
| 443 |
downloadBtn.addEventListener('click', () => {
|
| 444 |
+
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(window.__currentJSONData, null, 2));
|
| 445 |
const downloadAnchorNode = document.createElement('a');
|
| 446 |
downloadAnchorNode.setAttribute("href", dataStr);
|
| 447 |
downloadAnchorNode.setAttribute("download", "stylesync_output.json");
|
|
|
|
| 464 |
startBtn.classList.add('animate-pulse-slow', 'animate-glow-pulse');
|
| 465 |
}, 1500);
|
| 466 |
});
|
| 467 |
+
|
| 468 |
+
// Initialize placeholder data
|
| 469 |
+
jsonOutput.innerHTML = jsonToHTMLList(window.__currentJSONData);
|
| 470 |
</script>
|
| 471 |
|
| 472 |
</body></html>
|