@j0hanz/fetch-url-mcp 1.10.19 → 1.10.21
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/transform/metadata.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAoCnE,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAkBR;
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/transform/metadata.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAoCnE,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAkBR;AAuJD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAYnB;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,GAAG,IAAI,CAY1B;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAC/B,IAAI,EAAE,iBAAiB,GACtB,iBAAiB,CAmBnB;AA2GD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAOpB;AACD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAuCxE;AAmBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAczD;AAaD,wBAAgB,mBAAmB,CACjC,QAAQ,CAAC,EAAE,aAAa,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAmBR"}
|
|
@@ -136,21 +136,36 @@ function resolveMetadataFromContext(ctx) {
|
|
|
136
136
|
// ---------------------------------------------------------------------------
|
|
137
137
|
// Favicon resolution
|
|
138
138
|
// ---------------------------------------------------------------------------
|
|
139
|
+
/** Ordered by preference: exact 32×32, SVG, any generic icon, legacy shortcut. */
|
|
140
|
+
const FAVICON_SELECTORS = [
|
|
141
|
+
'link[rel="icon"][sizes="32x32"]',
|
|
142
|
+
'link[rel="icon"][type="image/svg+xml"]',
|
|
143
|
+
'link[rel="icon"]',
|
|
144
|
+
'link[rel="shortcut icon"]',
|
|
145
|
+
];
|
|
139
146
|
function resolveFaviconUrl(href, baseUrl) {
|
|
140
147
|
const trimmed = href.trim();
|
|
141
|
-
if (!trimmed)
|
|
142
|
-
return undefined;
|
|
143
|
-
if (trimmed.toLowerCase().startsWith('data:'))
|
|
148
|
+
if (!trimmed || trimmed.toLowerCase().startsWith('data:'))
|
|
144
149
|
return undefined;
|
|
145
150
|
const resolved = parseUrlOrNull(trimmed, baseUrl);
|
|
146
|
-
if (
|
|
147
|
-
return undefined;
|
|
148
|
-
}
|
|
149
|
-
if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') {
|
|
151
|
+
if (resolved?.protocol !== 'http:' && resolved?.protocol !== 'https:') {
|
|
150
152
|
return undefined;
|
|
151
153
|
}
|
|
152
154
|
return resolved.toString();
|
|
153
155
|
}
|
|
156
|
+
function extractFavicon(document, baseUrl) {
|
|
157
|
+
for (const selector of FAVICON_SELECTORS) {
|
|
158
|
+
for (const el of document.querySelectorAll(selector)) {
|
|
159
|
+
const href = el.getAttribute('href');
|
|
160
|
+
if (href) {
|
|
161
|
+
const resolved = resolveFaviconUrl(href, baseUrl);
|
|
162
|
+
if (resolved)
|
|
163
|
+
return resolved;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
154
169
|
// ---------------------------------------------------------------------------
|
|
155
170
|
// Public interface
|
|
156
171
|
// ---------------------------------------------------------------------------
|
|
@@ -161,13 +176,9 @@ export function extractMetadata(document, baseUrl) {
|
|
|
161
176
|
metadata.title = normalizeDocumentTitle(metadata.title, baseUrl);
|
|
162
177
|
}
|
|
163
178
|
if (baseUrl) {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const resolved = resolveFaviconUrl(href, baseUrl);
|
|
168
|
-
if (resolved)
|
|
169
|
-
metadata.favicon = resolved;
|
|
170
|
-
}
|
|
179
|
+
const favicon = extractFavicon(document, baseUrl);
|
|
180
|
+
if (favicon)
|
|
181
|
+
metadata.favicon = favicon;
|
|
171
182
|
}
|
|
172
183
|
return metadata;
|
|
173
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title-policy.d.ts","sourceRoot":"","sources":["../../src/transform/title-policy.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CAC7C;AAMD,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,CAER;AAED,wBAAgB,+BAA+B,CAC7C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAWT;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAU9D;
|
|
1
|
+
{"version":3,"file":"title-policy.d.ts","sourceRoot":"","sources":["../../src/transform/title-policy.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CAC7C;AAMD,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,CAER;AAED,wBAAgB,+BAA+B,CAC7C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAWT;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAU9D;AAkCD,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,GAAG,EAAE,MAAM,GACV,MAAM,CAMR;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,qBAAqB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,CAYR"}
|
|
@@ -28,14 +28,11 @@ export function isGithubRepositoryRootUrl(url) {
|
|
|
28
28
|
}
|
|
29
29
|
return parsed.pathname.split('/').filter(Boolean).length === 2;
|
|
30
30
|
}
|
|
31
|
-
function normalizeHeadingText(value) {
|
|
32
|
-
return value.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
33
|
-
}
|
|
34
31
|
function stripLeadingHeading(markdown, headingText) {
|
|
35
32
|
if (!markdown)
|
|
36
33
|
return markdown;
|
|
37
34
|
const lines = markdown.split('\n');
|
|
38
|
-
const target =
|
|
35
|
+
const target = normalizeSyntheticTitleToken(headingText);
|
|
39
36
|
let nonEmptySeen = 0;
|
|
40
37
|
for (let index = 0; index < lines.length && nonEmptySeen < HEADING_SCAN_LIMIT; index += 1) {
|
|
41
38
|
const trimmed = lines[index]?.trim() ?? '';
|
|
@@ -45,7 +42,7 @@ function stripLeadingHeading(markdown, headingText) {
|
|
|
45
42
|
const match = LEADING_HEADING_PATTERN.exec(trimmed);
|
|
46
43
|
if (!match)
|
|
47
44
|
continue;
|
|
48
|
-
const current =
|
|
45
|
+
const current = normalizeSyntheticTitleToken(match[2] ?? '');
|
|
49
46
|
if (current !== target)
|
|
50
47
|
return markdown;
|
|
51
48
|
lines.splice(index, 1);
|
|
@@ -62,15 +59,14 @@ export function maybeStripGithubPrimaryHeading(markdown, primaryHeading, url) {
|
|
|
62
59
|
}
|
|
63
60
|
return stripLeadingHeading(markdown, primaryHeading);
|
|
64
61
|
}
|
|
65
|
-
function buildSyntheticTitlePrefix(url, favicon, suppressFavicon) {
|
|
66
|
-
if (!favicon || suppressFavicon)
|
|
67
|
-
return ' ';
|
|
68
|
-
const alt = parseUrlOrNull(url)?.hostname ?? '';
|
|
69
|
-
return `  `;
|
|
70
|
-
}
|
|
71
62
|
export function maybePrependSyntheticTitle(markdown, context, url) {
|
|
72
63
|
if (!context.title || /^(#{1,6})\s/.test(markdown.trimStart())) {
|
|
73
64
|
return markdown;
|
|
74
65
|
}
|
|
75
|
-
|
|
66
|
+
let prefix = ' ';
|
|
67
|
+
if (context.favicon && !context.suppressSyntheticFavicon) {
|
|
68
|
+
const alt = parseUrlOrNull(url)?.hostname ?? '';
|
|
69
|
+
prefix = `  `;
|
|
70
|
+
}
|
|
71
|
+
return `#${prefix}${context.title}\n\n${markdown}`;
|
|
76
72
|
}
|
package/package.json
CHANGED