dembrandt 0.12.2 → 0.12.3

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.
@@ -146,6 +146,12 @@ export async function extractLogo(page, url) {
146
146
  if (imgSrc.toLowerCase().includes(siteDomain) || altText.includes(siteDomain) || className.includes(siteDomain)) score += 40;
147
147
  if (className.includes('logo') || el.id?.toLowerCase().includes('logo')) score += 30;
148
148
 
149
+ // SVG with aria-label="Homepage" directly in a home anchor — strong signal
150
+ if (el.tagName === 'svg' || el.tagName === 'SVG') {
151
+ const ariaLabel = (el.getAttribute('aria-label') || '').toLowerCase();
152
+ if (ariaLabel.includes('home') || ariaLabel.includes('logo')) score += 40;
153
+ }
154
+
149
155
  if (parentLink) {
150
156
  const href = linkHref.toLowerCase();
151
157
  if (href === '/' || href === baseUrl || href.endsWith('://' + new URL(baseUrl).hostname + '/') || href.endsWith('://' + new URL(baseUrl).hostname)) {
@@ -156,8 +162,19 @@ export async function extractLogo(page, url) {
156
162
  if (rect.top < 200) score += 10;
157
163
  if (rect.left < 400) score += 10;
158
164
 
159
- const width = el.naturalWidth || el.width?.baseVal?.value || rect.width;
160
- const height = el.naturalHeight || el.height?.baseVal?.value || rect.height;
165
+ // Penalize images hosted on a different domain (CDN paths on same domain are fine)
166
+ if (el.tagName === 'IMG') {
167
+ try {
168
+ const srcHost = new URL(el.src).hostname.replace('www.', '')
169
+ const pageHost = new URL(baseUrl).hostname.replace('www.', '')
170
+ // If neither is a subdomain/CDN of the other, it's third-party
171
+ if (!srcHost.endsWith(pageHost) && !pageHost.endsWith(srcHost)) score -= 60
172
+ } catch {}
173
+ }
174
+
175
+ // For SVGs use rendered rect — baseVal reflects viewBox coordinates, not display size
176
+ const width = el.tagName === 'IMG' ? (el.naturalWidth || rect.width) : rect.width;
177
+ const height = el.tagName === 'IMG' ? (el.naturalHeight || rect.height) : rect.height;
161
178
  if (width < 20 || height < 20) score -= 30;
162
179
  if (width > 600 || height > 400) score -= 40;
163
180
  if (altText.length > 50) score -= 30;
@@ -247,7 +264,18 @@ export async function extractLogo(page, url) {
247
264
  if (rect.width === 0 || rect.height === 0) return;
248
265
 
249
266
  const className = (typeof el.className === 'string' ? el.className : el.className.baseVal || '').toLowerCase();
250
- const attrs = (className + ' ' + (el.id || '') + ' ' + (el.getAttribute('alt') || '')).toLowerCase();
267
+ const altText = (el.getAttribute('alt') || '').toLowerCase();
268
+ const attrs = (className + ' ' + (el.id || '') + ' ' + altText).toLowerCase();
269
+
270
+ // Disqualify third-party brand logos: alt like "Notion logo" / "Perplexity logo" / "Figma" where the brand isn't our site
271
+ // These appear in customer/integration/testimonial sections on marketing pages.
272
+ const altBrandMatch = altText.match(/^([a-z][a-z0-9\-\.]{1,30}?)(?:\s+(?:logo|icon|brand|wordmark))?$/i);
273
+ if (altBrandMatch) {
274
+ const altBrand = altBrandMatch[1].replace(/[\s\-\.]/g, '').toLowerCase();
275
+ if (altBrand && altBrand !== 'logo' && altBrand !== 'brand' && altBrand !== 'icon' && altBrand !== siteDomain && !altBrand.includes(siteDomain) && !siteDomain.includes(altBrand)) {
276
+ return; // third-party brand, skip entirely
277
+ }
278
+ }
251
279
 
252
280
  let qualifies = attrs.includes('logo') || attrs.includes('brand');
253
281
 
@@ -257,6 +285,9 @@ export async function extractLogo(page, url) {
257
285
  const href = use.getAttribute('href') || use.getAttribute('xlink:href') || '';
258
286
  if (href.toLowerCase().includes('logo') || href.toLowerCase().includes('brand')) { qualifies = true; break; }
259
287
  }
288
+ // aria-label="Homepage" or similar on the SVG itself
289
+ const ariaLabel = (el.getAttribute('aria-label') || '').toLowerCase();
290
+ if (ariaLabel.includes('home') || ariaLabel.includes('logo')) qualifies = true;
260
291
  }
261
292
 
262
293
  if (!qualifies) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dembrandt",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "Extract design tokens and publicly visible CSS information from any website",
5
5
  "mcpName": "io.github.dembrandt/dembrandt",
6
6
  "main": "index.js",