@j0hanz/fetch-url-mcp 1.1.0 → 1.1.2
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.
- package/dist/cache.d.ts +5 -5
- package/dist/cache.js +5 -2
- package/dist/cli.js +12 -5
- package/dist/config.d.ts +1 -1
- package/dist/config.js +19 -18
- package/dist/crypto.js +7 -4
- package/dist/dom-noise-removal.js +14 -11
- package/dist/errors.js +5 -2
- package/dist/fetch.d.ts +4 -3
- package/dist/fetch.js +5 -2
- package/dist/host-normalization.js +7 -6
- package/dist/http-native.js +6 -4
- package/dist/index.js +7 -4
- package/dist/ip-blocklist.js +3 -3
- package/dist/json.js +3 -2
- package/dist/language-detection.js +1 -5
- package/dist/markdown-cleanup.d.ts +6 -1
- package/dist/markdown-cleanup.js +92 -30
- package/dist/mcp-validator.d.ts +3 -2
- package/dist/mcp-validator.js +7 -8
- package/dist/mcp.js +32 -17
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +9 -8
- package/dist/prompts.js +2 -10
- package/dist/resources.js +6 -4
- package/dist/server-tuning.d.ts +2 -1
- package/dist/server-tuning.js +20 -15
- package/dist/server.js +4 -8
- package/dist/session.d.ts +3 -2
- package/dist/session.js +7 -4
- package/dist/tasks.d.ts +1 -1
- package/dist/tasks.js +4 -4
- package/dist/timer-utils.js +4 -1
- package/dist/tools.d.ts +9 -14
- package/dist/tools.js +8 -8
- package/dist/transform-types.d.ts +5 -1
- package/dist/transform.d.ts +2 -2
- package/dist/transform.js +52 -6
- package/dist/type-guards.d.ts +2 -1
- package/dist/type-guards.js +3 -3
- package/dist/workers/transform-child.js +8 -4
- package/dist/workers/transform-worker.js +5 -3
- package/package.json +1 -1
package/dist/cache.d.ts
CHANGED
|
@@ -5,22 +5,22 @@ declare const CachedPayloadSchema: z.ZodObject<{
|
|
|
5
5
|
markdown: z.ZodOptional<z.ZodString>;
|
|
6
6
|
title: z.ZodOptional<z.ZodString>;
|
|
7
7
|
}, z.core.$strict>;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
type CachedPayload = z.infer<typeof CachedPayloadSchema>;
|
|
9
|
+
interface CacheEntry {
|
|
10
10
|
url: string;
|
|
11
11
|
title?: string;
|
|
12
12
|
content: string;
|
|
13
13
|
fetchedAt: string;
|
|
14
14
|
expiresAt: string;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
interface CacheKeyParts {
|
|
17
17
|
namespace: string;
|
|
18
18
|
urlHash: string;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
interface CacheSetOptions {
|
|
21
21
|
force?: boolean;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
interface CacheGetOptions {
|
|
24
24
|
force?: boolean;
|
|
25
25
|
}
|
|
26
26
|
interface CacheEntryMetadata {
|
package/dist/cache.js
CHANGED
|
@@ -93,13 +93,16 @@ class InMemoryCacheStore {
|
|
|
93
93
|
isEnabled() {
|
|
94
94
|
return config.cache.enabled;
|
|
95
95
|
}
|
|
96
|
+
isExpired(entry, now = Date.now()) {
|
|
97
|
+
return entry.expiresAtMs <= now;
|
|
98
|
+
}
|
|
96
99
|
keys() {
|
|
97
100
|
if (!this.isEnabled())
|
|
98
101
|
return [];
|
|
99
102
|
const now = Date.now();
|
|
100
103
|
const result = [];
|
|
101
104
|
for (const [key, entry] of this.entries) {
|
|
102
|
-
if (entry
|
|
105
|
+
if (!this.isExpired(entry, now))
|
|
103
106
|
result.push(key);
|
|
104
107
|
}
|
|
105
108
|
return result;
|
|
@@ -130,7 +133,7 @@ class InMemoryCacheStore {
|
|
|
130
133
|
if (!entry)
|
|
131
134
|
return undefined;
|
|
132
135
|
const now = Date.now();
|
|
133
|
-
if (entry
|
|
136
|
+
if (this.isExpired(entry, now)) {
|
|
134
137
|
this.delete(cacheKey);
|
|
135
138
|
this.notify(cacheKey, true);
|
|
136
139
|
return undefined;
|
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,17 @@ const optionSchema = {
|
|
|
19
19
|
function toErrorMessage(error) {
|
|
20
20
|
return error instanceof Error ? error.message : String(error);
|
|
21
21
|
}
|
|
22
|
+
function toBoolean(value) {
|
|
23
|
+
return value === true;
|
|
24
|
+
}
|
|
25
|
+
function buildCliValues(values) {
|
|
26
|
+
const { stdio, help, version } = values;
|
|
27
|
+
return {
|
|
28
|
+
stdio: toBoolean(stdio),
|
|
29
|
+
help: toBoolean(help),
|
|
30
|
+
version: toBoolean(version),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
22
33
|
export function renderCliUsage() {
|
|
23
34
|
return `${usageLines.join('\n')}\n`;
|
|
24
35
|
}
|
|
@@ -32,11 +43,7 @@ export function parseCliArgs(args) {
|
|
|
32
43
|
});
|
|
33
44
|
return {
|
|
34
45
|
ok: true,
|
|
35
|
-
values:
|
|
36
|
-
stdio: values.stdio,
|
|
37
|
-
help: values.help,
|
|
38
|
-
version: values.version,
|
|
39
|
-
},
|
|
46
|
+
values: buildCliValues(values),
|
|
40
47
|
};
|
|
41
48
|
}
|
|
42
49
|
catch (error) {
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const serverVersion: string;
|
|
2
2
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
3
|
-
|
|
3
|
+
type TransformWorkerMode = 'threads' | 'process';
|
|
4
4
|
type AuthMode = 'oauth' | 'static';
|
|
5
5
|
interface WorkerResourceLimits {
|
|
6
6
|
maxOldGenerationSizeMb?: number;
|
package/dist/config.js
CHANGED
|
@@ -233,24 +233,25 @@ const RESOLVED_TASKS_MAX_PER_OWNER = Math.min(DEFAULT_TASKS_MAX_PER_OWNER, DEFAU
|
|
|
233
233
|
function resolveWorkerResourceLimits() {
|
|
234
234
|
const limits = {};
|
|
235
235
|
let hasAny = false;
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
236
|
+
const entries = [
|
|
237
|
+
[
|
|
238
|
+
'maxOldGenerationSizeMb',
|
|
239
|
+
parseOptionalInteger(env['TRANSFORM_WORKER_MAX_OLD_GENERATION_MB'], 1),
|
|
240
|
+
],
|
|
241
|
+
[
|
|
242
|
+
'maxYoungGenerationSizeMb',
|
|
243
|
+
parseOptionalInteger(env['TRANSFORM_WORKER_MAX_YOUNG_GENERATION_MB'], 1),
|
|
244
|
+
],
|
|
245
|
+
[
|
|
246
|
+
'codeRangeSizeMb',
|
|
247
|
+
parseOptionalInteger(env['TRANSFORM_WORKER_CODE_RANGE_MB'], 1),
|
|
248
|
+
],
|
|
249
|
+
['stackSizeMb', parseOptionalInteger(env['TRANSFORM_WORKER_STACK_MB'], 1)],
|
|
250
|
+
];
|
|
251
|
+
for (const [key, value] of entries) {
|
|
252
|
+
if (value === undefined)
|
|
253
|
+
continue;
|
|
254
|
+
limits[key] = value;
|
|
254
255
|
hasAny = true;
|
|
255
256
|
}
|
|
256
257
|
return hasAny ? limits : undefined;
|
package/dist/crypto.js
CHANGED
|
@@ -18,6 +18,11 @@ function assertAllowedAlgorithm(algorithm) {
|
|
|
18
18
|
throw new Error(`Hash algorithm not allowed: ${algorithm}`);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
function padBuffer(buffer, length) {
|
|
22
|
+
const padded = Buffer.alloc(length);
|
|
23
|
+
buffer.copy(padded);
|
|
24
|
+
return padded;
|
|
25
|
+
}
|
|
21
26
|
export function timingSafeEqualUtf8(a, b) {
|
|
22
27
|
const aBuffer = Buffer.from(a, 'utf8');
|
|
23
28
|
const bBuffer = Buffer.from(b, 'utf8');
|
|
@@ -26,10 +31,8 @@ export function timingSafeEqualUtf8(a, b) {
|
|
|
26
31
|
}
|
|
27
32
|
// Avoid early return timing differences on length mismatch.
|
|
28
33
|
const maxLength = Math.max(aBuffer.length, bBuffer.length);
|
|
29
|
-
const paddedA =
|
|
30
|
-
const paddedB =
|
|
31
|
-
aBuffer.copy(paddedA);
|
|
32
|
-
bBuffer.copy(paddedB);
|
|
34
|
+
const paddedA = padBuffer(aBuffer, maxLength);
|
|
35
|
+
const paddedB = padBuffer(bBuffer, maxLength);
|
|
33
36
|
return timingSafeEqual(paddedA, paddedB) && aBuffer.length === bBuffer.length;
|
|
34
37
|
}
|
|
35
38
|
function hashHex(algorithm, input) {
|
|
@@ -103,22 +103,25 @@ function buildTokenRegex(tokens) {
|
|
|
103
103
|
return NO_MATCH_REGEX;
|
|
104
104
|
return new RegExp(`(?:^|[^a-z0-9])(?:${[...tokens].map(escapeRegexLiteral).join('|')})(?:$|[^a-z0-9])`, 'i');
|
|
105
105
|
}
|
|
106
|
+
function addTokens(target, tokens) {
|
|
107
|
+
for (const token of tokens)
|
|
108
|
+
target.add(token);
|
|
109
|
+
}
|
|
106
110
|
function getPromoMatchers(currentConfig, flags) {
|
|
107
111
|
const baseTokens = new Set(PROMO_TOKENS_ALWAYS);
|
|
108
112
|
const aggressiveTokens = new Set();
|
|
109
113
|
if (currentConfig.aggressiveMode) {
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
addTokens(aggressiveTokens, PROMO_TOKENS_AGGRESSIVE);
|
|
115
|
+
}
|
|
116
|
+
if (flags.cookieBanners) {
|
|
117
|
+
addTokens(baseTokens, PROMO_TOKENS_BY_CATEGORY['cookie-banners']);
|
|
118
|
+
}
|
|
119
|
+
if (flags.newsletters) {
|
|
120
|
+
addTokens(baseTokens, PROMO_TOKENS_BY_CATEGORY['newsletters']);
|
|
121
|
+
}
|
|
122
|
+
if (flags.socialShare) {
|
|
123
|
+
addTokens(baseTokens, PROMO_TOKENS_BY_CATEGORY['social-share']);
|
|
112
124
|
}
|
|
113
|
-
if (flags.cookieBanners)
|
|
114
|
-
for (const t of PROMO_TOKENS_BY_CATEGORY['cookie-banners'])
|
|
115
|
-
baseTokens.add(t);
|
|
116
|
-
if (flags.newsletters)
|
|
117
|
-
for (const t of PROMO_TOKENS_BY_CATEGORY['newsletters'])
|
|
118
|
-
baseTokens.add(t);
|
|
119
|
-
if (flags.socialShare)
|
|
120
|
-
for (const t of PROMO_TOKENS_BY_CATEGORY['social-share'])
|
|
121
|
-
baseTokens.add(t);
|
|
122
125
|
for (const t of currentConfig.extraTokens) {
|
|
123
126
|
const n = t.toLowerCase().trim();
|
|
124
127
|
if (n)
|
package/dist/errors.js
CHANGED
|
@@ -19,17 +19,20 @@ export class FetchError extends Error {
|
|
|
19
19
|
export function getErrorMessage(error) {
|
|
20
20
|
if (isError(error))
|
|
21
21
|
return error.message;
|
|
22
|
-
if (
|
|
22
|
+
if (isNonEmptyString(error))
|
|
23
23
|
return error;
|
|
24
24
|
if (isErrorWithMessage(error))
|
|
25
25
|
return error.message;
|
|
26
26
|
return formatUnknownError(error);
|
|
27
27
|
}
|
|
28
|
+
function isNonEmptyString(value) {
|
|
29
|
+
return typeof value === 'string' && value.length > 0;
|
|
30
|
+
}
|
|
28
31
|
function isErrorWithMessage(error) {
|
|
29
32
|
if (!isObject(error))
|
|
30
33
|
return false;
|
|
31
34
|
const { message } = error;
|
|
32
|
-
return
|
|
35
|
+
return isNonEmptyString(message);
|
|
33
36
|
}
|
|
34
37
|
function formatUnknownError(error) {
|
|
35
38
|
if (error === null || error === undefined)
|
package/dist/fetch.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
interface FetchOptions {
|
|
2
2
|
signal?: AbortSignal;
|
|
3
3
|
}
|
|
4
|
-
|
|
4
|
+
interface TransformResult {
|
|
5
5
|
readonly url: string;
|
|
6
6
|
readonly transformed: boolean;
|
|
7
7
|
readonly platform?: string;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
interface FetchTelemetryContext {
|
|
10
10
|
requestId: string;
|
|
11
11
|
startTime: number;
|
|
12
12
|
url: string;
|
|
@@ -40,3 +40,4 @@ export declare function fetchNormalizedUrlBuffer(normalizedUrl: string, options?
|
|
|
40
40
|
truncated: boolean;
|
|
41
41
|
finalUrl: string;
|
|
42
42
|
}>;
|
|
43
|
+
export {};
|
package/dist/fetch.js
CHANGED
|
@@ -569,8 +569,11 @@ function createTooManyRedirectsFetchError(url) {
|
|
|
569
569
|
function createMissingRedirectLocationFetchError(url) {
|
|
570
570
|
return new FetchError('Redirect response missing Location header', url);
|
|
571
571
|
}
|
|
572
|
+
function buildNetworkErrorMessage(url) {
|
|
573
|
+
return `Network error: Could not reach ${url}`;
|
|
574
|
+
}
|
|
572
575
|
function createNetworkFetchError(url, message) {
|
|
573
|
-
return new FetchError(
|
|
576
|
+
return new FetchError(buildNetworkErrorMessage(url), url, undefined, message ? { message } : {});
|
|
574
577
|
}
|
|
575
578
|
function createUnknownFetchError(url, message) {
|
|
576
579
|
return new FetchError(message, url);
|
|
@@ -619,7 +622,7 @@ function mapFetchError(error, fallbackUrl, timeoutMs) {
|
|
|
619
622
|
code === 'EINVAL') {
|
|
620
623
|
return new FetchError(error.message, url, 400, { code });
|
|
621
624
|
}
|
|
622
|
-
return new FetchError(
|
|
625
|
+
return new FetchError(buildNetworkErrorMessage(url), url, undefined, {
|
|
623
626
|
code,
|
|
624
627
|
message: error.message,
|
|
625
628
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isIP, SocketAddress } from 'node:net';
|
|
2
2
|
import { domainToASCII } from 'node:url';
|
|
3
3
|
export function normalizeHost(value) {
|
|
4
|
-
const trimmedLower = value
|
|
4
|
+
const trimmedLower = trimToNull(value)?.toLowerCase();
|
|
5
5
|
if (!trimmedLower)
|
|
6
6
|
return null;
|
|
7
7
|
const first = takeFirstHostValue(trimmedLower);
|
|
@@ -25,10 +25,7 @@ function takeFirstHostValue(value) {
|
|
|
25
25
|
// Faster than split(',') for large forwarded headers; preserves behavior.
|
|
26
26
|
const commaIndex = value.indexOf(',');
|
|
27
27
|
const first = commaIndex === -1 ? value : value.slice(0, commaIndex);
|
|
28
|
-
|
|
29
|
-
return null;
|
|
30
|
-
const trimmed = first.trim();
|
|
31
|
-
return trimmed ? trimmed : null;
|
|
28
|
+
return first ? trimToNull(first) : null;
|
|
32
29
|
}
|
|
33
30
|
function stripIpv6Brackets(value) {
|
|
34
31
|
if (!value.startsWith('['))
|
|
@@ -48,7 +45,7 @@ function isIpV6Literal(value) {
|
|
|
48
45
|
return isIP(value) === 6;
|
|
49
46
|
}
|
|
50
47
|
function normalizeHostname(value) {
|
|
51
|
-
const trimmed = value
|
|
48
|
+
const trimmed = trimToNull(value)?.toLowerCase();
|
|
52
49
|
if (!trimmed)
|
|
53
50
|
return null;
|
|
54
51
|
if (isIP(trimmed))
|
|
@@ -68,6 +65,10 @@ function parseHostWithUrl(value) {
|
|
|
68
65
|
return null;
|
|
69
66
|
}
|
|
70
67
|
}
|
|
68
|
+
function trimToNull(value) {
|
|
69
|
+
const trimmed = value.trim();
|
|
70
|
+
return trimmed ? trimmed : null;
|
|
71
|
+
}
|
|
71
72
|
function stripTrailingDots(value) {
|
|
72
73
|
// Keep loop (rather than regex) to preserve exact behavior and avoid hidden allocations.
|
|
73
74
|
let result = value;
|
package/dist/http-native.js
CHANGED
|
@@ -63,15 +63,13 @@ function createTransportAdapter(transportImpl) {
|
|
|
63
63
|
function sendJson(res, status, body) {
|
|
64
64
|
res.statusCode = status;
|
|
65
65
|
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
66
|
-
res
|
|
67
|
-
res.setHeader('Cache-Control', 'no-store');
|
|
66
|
+
setNoStoreHeaders(res);
|
|
68
67
|
res.end(JSON.stringify(body));
|
|
69
68
|
}
|
|
70
69
|
function sendText(res, status, body) {
|
|
71
70
|
res.statusCode = status;
|
|
72
71
|
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
73
|
-
res
|
|
74
|
-
res.setHeader('Cache-Control', 'no-store');
|
|
72
|
+
setNoStoreHeaders(res);
|
|
75
73
|
res.end(body);
|
|
76
74
|
}
|
|
77
75
|
function sendEmpty(res, status) {
|
|
@@ -79,6 +77,10 @@ function sendEmpty(res, status) {
|
|
|
79
77
|
res.setHeader('Content-Length', '0');
|
|
80
78
|
res.end();
|
|
81
79
|
}
|
|
80
|
+
function setNoStoreHeaders(res) {
|
|
81
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
82
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
83
|
+
}
|
|
82
84
|
function drainRequest(req) {
|
|
83
85
|
if (req.readableEnded)
|
|
84
86
|
return;
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,9 @@ import { logError } from './observability.js';
|
|
|
7
7
|
import { startStdioServer } from './server.js';
|
|
8
8
|
const FORCE_EXIT_TIMEOUT_MS = 10_000;
|
|
9
9
|
let forcedExitTimer;
|
|
10
|
+
function toError(value) {
|
|
11
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
12
|
+
}
|
|
10
13
|
function scheduleForcedExit(reason) {
|
|
11
14
|
if (forcedExitTimer)
|
|
12
15
|
return;
|
|
@@ -69,8 +72,7 @@ process.on('uncaughtException', (error) => {
|
|
|
69
72
|
handleFatalError('Uncaught exception', error, 'UNCAUGHT_EXCEPTION');
|
|
70
73
|
});
|
|
71
74
|
process.on('unhandledRejection', (reason) => {
|
|
72
|
-
|
|
73
|
-
handleFatalError('Unhandled rejection', error, 'UNHANDLED_REJECTION');
|
|
75
|
+
handleFatalError('Unhandled rejection', toError(reason), 'UNHANDLED_REJECTION');
|
|
74
76
|
});
|
|
75
77
|
try {
|
|
76
78
|
if (isStdioMode) {
|
|
@@ -83,8 +85,9 @@ try {
|
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
catch (error) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
const resolvedError = toError(error);
|
|
89
|
+
logError('Failed to start server', resolvedError);
|
|
90
|
+
const { message } = resolvedError;
|
|
88
91
|
process.stderr.write(`Failed to start server: ${message}\n`);
|
|
89
92
|
process.exitCode = 1;
|
|
90
93
|
scheduleForcedExit('Startup failure');
|
package/dist/ip-blocklist.js
CHANGED
|
@@ -14,6 +14,7 @@ const IPV6_2002 = buildIpv6(['2002', 0, 0, 0, 0, 0, 0, 0]);
|
|
|
14
14
|
const IPV6_FC00 = buildIpv6(['fc00', 0, 0, 0, 0, 0, 0, 0]);
|
|
15
15
|
const IPV6_FE80 = buildIpv6(['fe80', 0, 0, 0, 0, 0, 0, 0]);
|
|
16
16
|
const IPV6_FF00 = buildIpv6(['ff00', 0, 0, 0, 0, 0, 0, 0]);
|
|
17
|
+
const IPV6_MAPPED_PREFIX = '::ffff:';
|
|
17
18
|
const BLOCKED_SUBNETS = [
|
|
18
19
|
{ subnet: buildIpv4([0, 0, 0, 0]), prefix: 8, family: 'ipv4' },
|
|
19
20
|
{ subnet: buildIpv4([10, 0, 0, 0]), prefix: 8, family: 'ipv4' },
|
|
@@ -42,10 +43,9 @@ export function createDefaultBlockList() {
|
|
|
42
43
|
return list;
|
|
43
44
|
}
|
|
44
45
|
function extractMappedIpv4(ip) {
|
|
45
|
-
|
|
46
|
-
if (!ip.startsWith(prefix))
|
|
46
|
+
if (!ip.startsWith(IPV6_MAPPED_PREFIX))
|
|
47
47
|
return null;
|
|
48
|
-
const mapped = ip.slice(
|
|
48
|
+
const mapped = ip.slice(IPV6_MAPPED_PREFIX.length);
|
|
49
49
|
return isIP(mapped) === 4 ? mapped : null;
|
|
50
50
|
}
|
|
51
51
|
function stripIpv6ZoneId(ip) {
|
package/dist/json.js
CHANGED
|
@@ -13,14 +13,15 @@ function processValue(obj, depth, seen) {
|
|
|
13
13
|
}
|
|
14
14
|
seen.add(obj);
|
|
15
15
|
try {
|
|
16
|
+
const processChild = (value) => processValue(value, depth + 1, seen);
|
|
16
17
|
if (Array.isArray(obj)) {
|
|
17
|
-
return obj.map((item) =>
|
|
18
|
+
return obj.map((item) => processChild(item));
|
|
18
19
|
}
|
|
19
20
|
const keys = Object.keys(obj).sort((a, b) => a.localeCompare(b));
|
|
20
21
|
const record = obj;
|
|
21
22
|
const sortedObj = {};
|
|
22
23
|
for (const key of keys) {
|
|
23
|
-
sortedObj[key] =
|
|
24
|
+
sortedObj[key] = processChild(record[key]);
|
|
24
25
|
}
|
|
25
26
|
return sortedObj;
|
|
26
27
|
}
|
|
@@ -118,11 +118,7 @@ function isBashLine(line) {
|
|
|
118
118
|
return false;
|
|
119
119
|
}
|
|
120
120
|
function detectBashIndicators(lines) {
|
|
121
|
-
|
|
122
|
-
if (isBashLine(line))
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
return false;
|
|
121
|
+
return lines.some((line) => isBashLine(line));
|
|
126
122
|
}
|
|
127
123
|
function detectCssStructure(lines) {
|
|
128
124
|
for (const line of lines) {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { MetadataBlock } from './transform-types.js';
|
|
2
|
-
|
|
2
|
+
interface CleanupOptions {
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
url?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function cleanupMarkdownArtifacts(content: string, options?: CleanupOptions): string;
|
|
3
7
|
export declare function extractTitleFromRawMarkdown(content: string): string | undefined;
|
|
4
8
|
export declare function addSourceToMarkdown(content: string, url: string): string;
|
|
5
9
|
export declare function isRawTextContent(content: string): boolean;
|
|
6
10
|
export declare function buildMetadataFooter(metadata?: MetadataBlock, fallbackUrl?: string): string;
|
|
11
|
+
export {};
|