@trops/dash-core 0.1.179 → 0.1.180

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.
@@ -39234,6 +39234,28 @@ function extractComputedColors(computedStyles) {
39234
39234
  return results;
39235
39235
  }
39236
39236
 
39237
+ /**
39238
+ * Extract colors from broad DOM color scan (frequency-based).
39239
+ * @param {Array<{color: string, count: number}>} domColors - Sorted by frequency
39240
+ * @returns {Array<{hex: string, source: string, confidence: number, count: number}>}
39241
+ */
39242
+ function extractDomColors(domColors) {
39243
+ if (!Array.isArray(domColors) || domColors.length === 0) return [];
39244
+ const results = [];
39245
+ for (const entry of domColors) {
39246
+ if (!entry.color || !entry.count) continue;
39247
+ const rgb = parseColor(entry.color);
39248
+ if (!rgb) continue;
39249
+ results.push({
39250
+ hex: rgbToHex(rgb),
39251
+ source: "dom",
39252
+ confidence: 0.7,
39253
+ count: entry.count,
39254
+ });
39255
+ }
39256
+ return results;
39257
+ }
39258
+
39237
39259
  // ─── Favicon extraction ──────────────────────────────────────────────────────
39238
39260
 
39239
39261
  /**
@@ -39462,7 +39484,7 @@ function mergeAndRank(allColors, maxColors = 6) {
39462
39484
  for (const cluster of clusters) {
39463
39485
  if (deltaE$1(cluster.lab, lab) < THRESHOLD) {
39464
39486
  // Merge into existing cluster — keep the highest-confidence color as representative
39465
- cluster.count++;
39487
+ cluster.count += color.count || 1;
39466
39488
  cluster.sources.add(color.source);
39467
39489
  if (color.confidence > cluster.confidence) {
39468
39490
  cluster.hex = color.hex;
@@ -39481,7 +39503,7 @@ function mergeAndRank(allColors, maxColors = 6) {
39481
39503
  rgb,
39482
39504
  lab,
39483
39505
  confidence: color.confidence,
39484
- count: 1,
39506
+ count: color.count || 1,
39485
39507
  sources: new Set([color.source]),
39486
39508
  });
39487
39509
  }
@@ -39563,6 +39585,7 @@ function mergeAndRank(allColors, maxColors = 6) {
39563
39585
  * @param {string} params.htmlContent - Raw HTML of the page
39564
39586
  * @param {string} params.cssContent - Concatenated CSS content
39565
39587
  * @param {Object} params.computedStyles - Map of selector → { color, backgroundColor, borderColor }
39588
+ * @param {Array<{color: string, count: number}>} [params.domColors] - Frequency-sorted DOM colors from broad scan
39566
39589
  * @param {string} [params.baseUrl] - Page URL for resolving favicon paths (enables image extraction)
39567
39590
  * @returns {Promise<{ palette: Array, rawCount: number }>}
39568
39591
  */
@@ -39570,6 +39593,7 @@ async function extractColorsFromUrl({
39570
39593
  htmlContent,
39571
39594
  cssContent,
39572
39595
  computedStyles,
39596
+ domColors,
39573
39597
  baseUrl,
39574
39598
  }) {
39575
39599
  console.log("[themeFromUrlController] Starting color extraction pipeline");
@@ -39594,6 +39618,11 @@ async function extractColorsFromUrl({
39594
39618
  `[themeFromUrlController] Computed styles: ${computedColors.length} colors`,
39595
39619
  );
39596
39620
 
39621
+ const domColorResults = extractDomColors(domColors);
39622
+ console.log(
39623
+ `[themeFromUrlController] DOM scan: ${domColorResults.length} colors`,
39624
+ );
39625
+
39597
39626
  // Favicon extraction (async, requires baseUrl)
39598
39627
  let faviconColors = [];
39599
39628
  if (baseUrl) {
@@ -39613,6 +39642,7 @@ async function extractColorsFromUrl({
39613
39642
  ...metaColors,
39614
39643
  ...cssVarColors,
39615
39644
  ...computedColors,
39645
+ ...domColorResults,
39616
39646
  ...faviconColors,
39617
39647
  ].filter((c) => {
39618
39648
  if (!c.hex) {
@@ -70426,30 +70456,54 @@ async function handleCreateThemeFromUrl$1({ url, name }) {
70426
70456
  const extracted = await scanWindow.webContents.executeJavaScript(`
70427
70457
  (function() {
70428
70458
  try {
70429
- const htmlContent = document.documentElement.outerHTML;
70430
- let cssContent = '';
70459
+ var htmlContent = document.documentElement.outerHTML;
70460
+ var cssContent = '';
70431
70461
  try {
70432
- for (const sheet of document.styleSheets) {
70462
+ for (var s = 0; s < document.styleSheets.length; s++) {
70433
70463
  try {
70434
- for (const rule of sheet.cssRules) {
70435
- cssContent += rule.cssText + '\\n';
70464
+ var rules = document.styleSheets[s].cssRules;
70465
+ for (var r = 0; r < rules.length; r++) {
70466
+ cssContent += rules[r].cssText + '\\n';
70436
70467
  }
70437
- } catch (e) { /* cross-origin stylesheet */ }
70468
+ } catch (e) {}
70438
70469
  }
70439
70470
  } catch (e) {}
70440
- const selectors = ['body', 'header', 'nav', 'main', 'footer', 'a', 'button', 'h1', 'h2'];
70441
- const computedStyles = {};
70442
- for (const sel of selectors) {
70443
- const el = document.querySelector(sel);
70444
- if (!el) continue;
70445
- const cs = window.getComputedStyle(el);
70446
- computedStyles[sel] = {
70447
- color: cs.color,
70448
- backgroundColor: cs.backgroundColor,
70449
- borderColor: cs.borderColor,
70450
- };
70471
+
70472
+ var DEFAULT_COLORS = {
70473
+ 'rgba(0, 0, 0, 0)': 1, 'transparent': 1,
70474
+ 'rgb(0, 0, 0)': 1, 'rgb(255, 255, 255)': 1
70475
+ };
70476
+ var colorFreq = {};
70477
+ var elements = document.body ? document.body.querySelectorAll('*') : [];
70478
+ var limit = Math.min(elements.length, 500);
70479
+ for (var i = 0; i < limit; i++) {
70480
+ var el = elements[i];
70481
+ if (el.offsetWidth === 0 && el.offsetHeight === 0) continue;
70482
+ var cs = window.getComputedStyle(el);
70483
+ var props = ['color', 'backgroundColor', 'borderColor'];
70484
+ for (var p = 0; p < props.length; p++) {
70485
+ var val = cs[props[p]];
70486
+ if (val && !DEFAULT_COLORS[val]) {
70487
+ colorFreq[val] = (colorFreq[val] || 0) + 1;
70488
+ }
70489
+ }
70490
+ if (el instanceof SVGElement) {
70491
+ var fill = cs.fill;
70492
+ var stroke = cs.stroke;
70493
+ if (fill && fill !== 'none' && !DEFAULT_COLORS[fill]) {
70494
+ colorFreq[fill] = (colorFreq[fill] || 0) + 1;
70495
+ }
70496
+ if (stroke && stroke !== 'none' && !DEFAULT_COLORS[stroke]) {
70497
+ colorFreq[stroke] = (colorFreq[stroke] || 0) + 1;
70498
+ }
70499
+ }
70451
70500
  }
70452
- return { success: true, htmlContent, cssContent, computedStyles };
70501
+ var domColors = Object.keys(colorFreq)
70502
+ .map(function(key) { return { color: key, count: colorFreq[key] }; })
70503
+ .sort(function(a, b) { return b.count - a.count; })
70504
+ .slice(0, 50);
70505
+
70506
+ return { success: true, htmlContent: htmlContent, cssContent: cssContent, domColors: domColors };
70453
70507
  } catch (e) {
70454
70508
  return { success: false, error: { type: 'EXTRACTION_FAILED', message: e.message } };
70455
70509
  }
@@ -70465,7 +70519,7 @@ async function handleCreateThemeFromUrl$1({ url, name }) {
70465
70519
  return themeFromUrlController$1.extractColorsFromUrl({
70466
70520
  htmlContent: extracted.htmlContent,
70467
70521
  cssContent: extracted.cssContent,
70468
- computedStyles: extracted.computedStyles,
70522
+ domColors: extracted.domColors,
70469
70523
  baseUrl: trimmedUrl,
70470
70524
  });
70471
70525
  } finally {