khoji 2.1.4
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/README.md +136 -0
- package/dist/ai/GeminiAdapter.d.ts +7 -0
- package/dist/ai/GeminiAdapter.d.ts.map +1 -0
- package/dist/ai/GeminiAdapter.js +40 -0
- package/dist/ai/GeminiAdapter.js.map +1 -0
- package/dist/browser/BrowserManager.d.ts +17 -0
- package/dist/browser/BrowserManager.d.ts.map +1 -0
- package/dist/browser/BrowserManager.js +61 -0
- package/dist/browser/BrowserManager.js.map +1 -0
- package/dist/browser/PageLoader.d.ts +21 -0
- package/dist/browser/PageLoader.d.ts.map +1 -0
- package/dist/browser/PageLoader.js +116 -0
- package/dist/browser/PageLoader.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +98 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extractors/AnimationExtractor.d.ts +12 -0
- package/dist/extractors/AnimationExtractor.d.ts.map +1 -0
- package/dist/extractors/AnimationExtractor.js +247 -0
- package/dist/extractors/AnimationExtractor.js.map +1 -0
- package/dist/extractors/AssetExtractor.d.ts +11 -0
- package/dist/extractors/AssetExtractor.d.ts.map +1 -0
- package/dist/extractors/AssetExtractor.js +124 -0
- package/dist/extractors/AssetExtractor.js.map +1 -0
- package/dist/extractors/ContentExtractor.d.ts +13 -0
- package/dist/extractors/ContentExtractor.d.ts.map +1 -0
- package/dist/extractors/ContentExtractor.js +60 -0
- package/dist/extractors/ContentExtractor.js.map +1 -0
- package/dist/extractors/DomExtractor.d.ts +11 -0
- package/dist/extractors/DomExtractor.d.ts.map +1 -0
- package/dist/extractors/DomExtractor.js +68 -0
- package/dist/extractors/DomExtractor.js.map +1 -0
- package/dist/extractors/InteractionExtractor.d.ts +10 -0
- package/dist/extractors/InteractionExtractor.d.ts.map +1 -0
- package/dist/extractors/InteractionExtractor.js +64 -0
- package/dist/extractors/InteractionExtractor.js.map +1 -0
- package/dist/extractors/MetaExtractor.d.ts +8 -0
- package/dist/extractors/MetaExtractor.d.ts.map +1 -0
- package/dist/extractors/MetaExtractor.js +33 -0
- package/dist/extractors/MetaExtractor.js.map +1 -0
- package/dist/extractors/StyleExtractor.d.ts +10 -0
- package/dist/extractors/StyleExtractor.d.ts.map +1 -0
- package/dist/extractors/StyleExtractor.js +87 -0
- package/dist/extractors/StyleExtractor.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/output/Writer.d.ts +5 -0
- package/dist/output/Writer.d.ts.map +1 -0
- package/dist/output/Writer.js +13 -0
- package/dist/output/Writer.js.map +1 -0
- package/dist/pipeline/Cleaner.d.ts +12 -0
- package/dist/pipeline/Cleaner.d.ts.map +1 -0
- package/dist/pipeline/Cleaner.js +41 -0
- package/dist/pipeline/Cleaner.js.map +1 -0
- package/dist/pipeline/ComponentDetector.d.ts +8 -0
- package/dist/pipeline/ComponentDetector.d.ts.map +1 -0
- package/dist/pipeline/ComponentDetector.js +43 -0
- package/dist/pipeline/ComponentDetector.js.map +1 -0
- package/dist/pipeline/runner.d.ts +3 -0
- package/dist/pipeline/runner.d.ts.map +1 -0
- package/dist/pipeline/runner.js +182 -0
- package/dist/pipeline/runner.js.map +1 -0
- package/dist/prompting/PromptGenerator.d.ts +5 -0
- package/dist/prompting/PromptGenerator.d.ts.map +1 -0
- package/dist/prompting/PromptGenerator.js +30 -0
- package/dist/prompting/PromptGenerator.js.map +1 -0
- package/dist/serializer/JsonSerializer.d.ts +6 -0
- package/dist/serializer/JsonSerializer.d.ts.map +1 -0
- package/dist/serializer/JsonSerializer.js +7 -0
- package/dist/serializer/JsonSerializer.js.map +1 -0
- package/dist/serializer/MarkdownSerializer.d.ts +7 -0
- package/dist/serializer/MarkdownSerializer.d.ts.map +1 -0
- package/dist/serializer/MarkdownSerializer.js +143 -0
- package/dist/serializer/MarkdownSerializer.js.map +1 -0
- package/dist/types/KhojContext.d.ts +141 -0
- package/dist/types/KhojContext.d.ts.map +1 -0
- package/dist/types/KhojContext.js +6 -0
- package/dist/types/KhojContext.js.map +1 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +70 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/text.d.ts +2 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +6 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/tokenEstimator.d.ts +10 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +17 -0
- package/dist/utils/tokenEstimator.js.map +1 -0
- package/khoj-context.schema.json +48 -0
- package/package.json +75 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps interactive regions of the page:
|
|
3
|
+
* - Forms with all their input fields
|
|
4
|
+
* - Navigation elements
|
|
5
|
+
* - Interactive button-like elements
|
|
6
|
+
*/
|
|
7
|
+
export async function extractInteractions(page) {
|
|
8
|
+
return page.evaluate(() => {
|
|
9
|
+
const interactions = [];
|
|
10
|
+
function getCssSelector(el) {
|
|
11
|
+
if (el.id)
|
|
12
|
+
return `#${el.id}`;
|
|
13
|
+
const tag = el.tagName.toLowerCase();
|
|
14
|
+
const cls = el.className?.toString().trim().split(/\s+/)[0];
|
|
15
|
+
return cls ? `${tag}.${cls}` : tag;
|
|
16
|
+
}
|
|
17
|
+
// ── Forms ───────────────────────────────────────────────────────────────
|
|
18
|
+
document.querySelectorAll('form').forEach((form) => {
|
|
19
|
+
const fields = [];
|
|
20
|
+
form.querySelectorAll('input, select, textarea').forEach((field) => {
|
|
21
|
+
const el = field;
|
|
22
|
+
fields.push({
|
|
23
|
+
inputType: el.tagName === 'SELECT' ? 'select' : el.tagName === 'TEXTAREA' ? 'textarea' : el.type || 'text',
|
|
24
|
+
name: el.name || el.id || '',
|
|
25
|
+
placeholder: el.placeholder || '',
|
|
26
|
+
required: el.required ?? false,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
const label = form.getAttribute('aria-label') ??
|
|
30
|
+
form.querySelector('legend, h1, h2, h3, h4')?.textContent?.trim() ??
|
|
31
|
+
form.id ??
|
|
32
|
+
'Form';
|
|
33
|
+
interactions.push({
|
|
34
|
+
type: 'form',
|
|
35
|
+
selector: getCssSelector(form),
|
|
36
|
+
label,
|
|
37
|
+
fields,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
// ── Navigation ──────────────────────────────────────────────────────────
|
|
41
|
+
document.querySelectorAll('nav, [role="navigation"]').forEach((nav) => {
|
|
42
|
+
const label = nav.getAttribute('aria-label') ??
|
|
43
|
+
nav.getAttribute('id') ??
|
|
44
|
+
'Navigation';
|
|
45
|
+
interactions.push({
|
|
46
|
+
type: 'nav',
|
|
47
|
+
selector: getCssSelector(nav),
|
|
48
|
+
label,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
// ── Interactive Buttons ─────────────────────────────────────────────────
|
|
52
|
+
const buttonEls = document.querySelectorAll('[role="button"]:not(button), [data-action], [data-click], [onclick]');
|
|
53
|
+
buttonEls.forEach((el) => {
|
|
54
|
+
const label = el.getAttribute('aria-label') ?? el.textContent?.trim() ?? 'Button';
|
|
55
|
+
interactions.push({
|
|
56
|
+
type: 'button',
|
|
57
|
+
selector: getCssSelector(el),
|
|
58
|
+
label,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
return interactions;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=InteractionExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionExtractor.js","sourceRoot":"","sources":["../../src/extractors/InteractionExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { PageMeta } from '../types/KhojContext.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts page metadata: title, description, Open Graph tags, canonical URL,
|
|
5
|
+
* theme-color, and embedded JSON-LD structured data.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractMeta(page: Page): Promise<PageMeta>;
|
|
8
|
+
//# sourceMappingURL=MetaExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetaExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/MetaExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CA+B/D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts page metadata: title, description, Open Graph tags, canonical URL,
|
|
3
|
+
* theme-color, and embedded JSON-LD structured data.
|
|
4
|
+
*/
|
|
5
|
+
export async function extractMeta(page) {
|
|
6
|
+
return page.evaluate(() => {
|
|
7
|
+
function getMeta(name) {
|
|
8
|
+
const el = document.querySelector(`meta[name="${name}"]`) ??
|
|
9
|
+
document.querySelector(`meta[property="${name}"]`);
|
|
10
|
+
return el?.content ?? '';
|
|
11
|
+
}
|
|
12
|
+
// Collect JSON-LD scripts
|
|
13
|
+
const jsonLd = [];
|
|
14
|
+
document.querySelectorAll('script[type="application/ld+json"]').forEach((el) => {
|
|
15
|
+
try {
|
|
16
|
+
jsonLd.push(JSON.parse(el.textContent ?? ''));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Malformed JSON-LD — skip silently
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const canonical = document.querySelector('link[rel="canonical"]')?.href ?? null;
|
|
23
|
+
return {
|
|
24
|
+
title: document.title?.trim() ?? '',
|
|
25
|
+
description: getMeta('description') || getMeta('og:description') || '',
|
|
26
|
+
ogImage: getMeta('og:image') || null,
|
|
27
|
+
canonical: canonical || null,
|
|
28
|
+
themeColor: getMeta('theme-color') || null,
|
|
29
|
+
jsonLd,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=MetaExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetaExtractor.js","sourceRoot":"","sources":["../../src/extractors/MetaExtractor.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAU;IACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAa,EAAE;QAChC,SAAS,OAAO,CAAC,IAAY;YACzB,MAAM,EAAE,GACJ,QAAQ,CAAC,aAAa,CAAC,cAAc,IAAI,IAAI,CAAC;gBAC9C,QAAQ,CAAC,aAAa,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC;YACvD,OAAQ,EAA6B,EAAE,OAAO,IAAI,EAAE,CAAC;QACzD,CAAC;QAED,0BAA0B;QAC1B,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,QAAQ,CAAC,gBAAgB,CAAC,oCAAoC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YAC3E,IAAI,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACL,oCAAoC;YACxC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GACV,QAAQ,CAAC,aAAa,CAAC,uBAAuB,CAA4B,EAAE,IAAI,IAAI,IAAI,CAAC;QAE9F,OAAO;YACH,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE;YACnC,WAAW,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE;YACtE,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI;YACpC,SAAS,EAAE,SAAS,IAAI,IAAI;YAC5B,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,IAAI;YAC1C,MAAM;SACT,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { DesignTokens } from '../types/KhojContext.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts design tokens from the page's stylesheets:
|
|
5
|
+
* - CSS custom properties (--color-*, --space-*, etc.)
|
|
6
|
+
* - Font families in use
|
|
7
|
+
* - Media query breakpoints
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractStyles(page: Page): Promise<DesignTokens>;
|
|
10
|
+
//# sourceMappingURL=StyleExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StyleExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/StyleExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAiFrE"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts design tokens from the page's stylesheets:
|
|
3
|
+
* - CSS custom properties (--color-*, --space-*, etc.)
|
|
4
|
+
* - Font families in use
|
|
5
|
+
* - Media query breakpoints
|
|
6
|
+
*/
|
|
7
|
+
export async function extractStyles(page) {
|
|
8
|
+
return page.evaluate(() => {
|
|
9
|
+
const colors = {};
|
|
10
|
+
const spacing = {};
|
|
11
|
+
const typography = {};
|
|
12
|
+
const fontSet = new Set();
|
|
13
|
+
const breakpointSet = new Set();
|
|
14
|
+
const COLOR_KEYWORDS = ['color', 'bg', 'background', 'fill', 'stroke', 'text', 'border', 'shadow', 'accent', 'primary', 'secondary'];
|
|
15
|
+
const SPACING_KEYWORDS = ['space', 'gap', 'margin', 'padding', 'indent', 'inset', 'offset', 'size', 'width', 'height'];
|
|
16
|
+
const TYPO_KEYWORDS = ['font', 'text', 'line-height', 'letter', 'weight', 'size'];
|
|
17
|
+
function categorise(name, value) {
|
|
18
|
+
const lower = name.toLowerCase();
|
|
19
|
+
if (COLOR_KEYWORDS.some((k) => lower.includes(k))) {
|
|
20
|
+
colors[name] = value;
|
|
21
|
+
}
|
|
22
|
+
else if (SPACING_KEYWORDS.some((k) => lower.includes(k))) {
|
|
23
|
+
spacing[name] = value;
|
|
24
|
+
}
|
|
25
|
+
else if (TYPO_KEYWORDS.some((k) => lower.includes(k))) {
|
|
26
|
+
typography[name] = value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Walk all CSSStyleSheets
|
|
30
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
31
|
+
let rules;
|
|
32
|
+
try {
|
|
33
|
+
rules = sheet.cssRules;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Cross-origin stylesheet — skip
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
for (const rule of Array.from(rules)) {
|
|
40
|
+
// CSS custom properties on :root or html
|
|
41
|
+
if (rule instanceof CSSStyleRule) {
|
|
42
|
+
const sel = rule.selectorText ?? '';
|
|
43
|
+
if (sel === ':root' || sel === 'html') {
|
|
44
|
+
for (const prop of Array.from(rule.style)) {
|
|
45
|
+
if (prop.startsWith('--')) {
|
|
46
|
+
const val = rule.style.getPropertyValue(prop).trim();
|
|
47
|
+
categorise(prop, val);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// @media breakpoints
|
|
53
|
+
if (rule instanceof CSSMediaRule) {
|
|
54
|
+
const condition = rule.conditionText ?? rule.media.mediaText;
|
|
55
|
+
const match = condition.match(/\d+px/);
|
|
56
|
+
if (match)
|
|
57
|
+
breakpointSet.add(match[0]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Font families from computed styles
|
|
62
|
+
const targets = ['body', 'h1', 'h2', 'p', 'button', 'a'];
|
|
63
|
+
for (const selector of targets) {
|
|
64
|
+
const el = document.querySelector(selector);
|
|
65
|
+
if (!el)
|
|
66
|
+
continue;
|
|
67
|
+
const computed = window.getComputedStyle(el);
|
|
68
|
+
const family = computed.fontFamily;
|
|
69
|
+
if (family) {
|
|
70
|
+
family.split(',').forEach((f) => {
|
|
71
|
+
const clean = f.trim().replace(/['"]/g, '');
|
|
72
|
+
if (clean && clean !== 'inherit' && clean !== 'initial') {
|
|
73
|
+
fontSet.add(clean);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
colors,
|
|
80
|
+
spacing,
|
|
81
|
+
typography,
|
|
82
|
+
fonts: Array.from(fontSet).slice(0, 12),
|
|
83
|
+
breakpoints: Array.from(breakpointSet).sort((a, b) => parseInt(a) - parseInt(b)),
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=StyleExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StyleExtractor.js","sourceRoot":"","sources":["../../src/extractors/StyleExtractor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { runExtraction } from './pipeline/runner.js';
|
|
2
|
+
export type { KhojContext, PageMeta, DomNode, DesignTokens, DetectedComponent, AssetMap, ImageAsset, ContentBlock, ContentType, Interaction, FormField, InteractionType, AnimationMap, CSSAnimation, CSSTransition, JSAnimation, JSAnimationLibrary, ScrollAnimation, ScrollAnimationLibrary, GifAnimation, GifAnimationPurpose, ExtractionOptions, } from './types/KhojContext.js';
|
|
3
|
+
export { estimateTokens } from './utils/tokenEstimator.js';
|
|
4
|
+
export { serializeJson } from './serializer/JsonSerializer.js';
|
|
5
|
+
export { serializeMarkdown } from './serializer/MarkdownSerializer.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Public API — import khoj as a library in your own Node.js/TypeScript project
|
|
2
|
+
export { runExtraction } from './pipeline/runner.js';
|
|
3
|
+
export { estimateTokens } from './utils/tokenEstimator.js';
|
|
4
|
+
export { serializeJson } from './serializer/JsonSerializer.js';
|
|
5
|
+
export { serializeMarkdown } from './serializer/MarkdownSerializer.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAyBrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Writer.d.ts","sourceRoot":"","sources":["../../src/output/Writer.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Writes content to a file, creating directories as needed.
|
|
6
|
+
*/
|
|
7
|
+
export async function writeOutput(filePath, content) {
|
|
8
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
9
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
10
|
+
const sizeKb = (Buffer.byteLength(content, 'utf-8') / 1024).toFixed(1);
|
|
11
|
+
logger.success(`Written: ${filePath} (${sizeKb} KB)`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=Writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Writer.js","sourceRoot":"","sources":["../../src/output/Writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IAC/D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,OAAO,CAAC,YAAY,QAAQ,KAAK,MAAM,MAAM,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ContentBlock, DomNode, ImageAsset } from '../types/KhojContext.js';
|
|
2
|
+
/**
|
|
3
|
+
* Post-processing pipeline:
|
|
4
|
+
* - Removes duplicate content blocks
|
|
5
|
+
* - Deduplicates asset URLs
|
|
6
|
+
* - Prunes empty DOM nodes
|
|
7
|
+
*/
|
|
8
|
+
export declare function cleanContent(blocks: ContentBlock[]): ContentBlock[];
|
|
9
|
+
export declare function cleanImages(images: ImageAsset[]): ImageAsset[];
|
|
10
|
+
export declare function cleanStringList(list: string[]): string[];
|
|
11
|
+
export declare function pruneEmptyDomNodes(nodes: DomNode[]): DomNode[];
|
|
12
|
+
//# sourceMappingURL=Cleaner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cleaner.d.ts","sourceRoot":"","sources":["../../src/pipeline/Cleaner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEjF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAQnE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAO9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAExD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAc9D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processing pipeline:
|
|
3
|
+
* - Removes duplicate content blocks
|
|
4
|
+
* - Deduplicates asset URLs
|
|
5
|
+
* - Prunes empty DOM nodes
|
|
6
|
+
*/
|
|
7
|
+
export function cleanContent(blocks) {
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
return blocks.filter((b) => {
|
|
10
|
+
const key = `${b.type}:${b.text.toLowerCase()}`;
|
|
11
|
+
if (seen.has(key))
|
|
12
|
+
return false;
|
|
13
|
+
seen.add(key);
|
|
14
|
+
return true;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function cleanImages(images) {
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
return images.filter((img) => {
|
|
20
|
+
if (seen.has(img.url))
|
|
21
|
+
return false;
|
|
22
|
+
seen.add(img.url);
|
|
23
|
+
return true;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function cleanStringList(list) {
|
|
27
|
+
return [...new Set(list.filter((s) => s.trim().length > 0))];
|
|
28
|
+
}
|
|
29
|
+
export function pruneEmptyDomNodes(nodes) {
|
|
30
|
+
return nodes
|
|
31
|
+
.map((node) => {
|
|
32
|
+
const children = node.children ? pruneEmptyDomNodes(node.children) : undefined;
|
|
33
|
+
return { ...node, children: children?.length ? children : undefined };
|
|
34
|
+
})
|
|
35
|
+
.filter((node) => node.text ||
|
|
36
|
+
node.id ||
|
|
37
|
+
node.classes.length > 0 ||
|
|
38
|
+
node.role ||
|
|
39
|
+
(node.children && node.children.length > 0));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=Cleaner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cleaner.js","sourceRoot":"","sources":["../../src/pipeline/Cleaner.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAc;IAC1C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IAC/C,OAAO,KAAK;SACP,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1E,CAAC,CAAC;SACD,MAAM,CACH,CAAC,IAAI,EAAE,EAAE,CACL,IAAI,CAAC,IAAI;QACT,IAAI,CAAC,EAAE;QACP,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QACvB,IAAI,CAAC,IAAI;QACT,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAClD,CAAC;AACV,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { DetectedComponent } from '../types/KhojContext.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detects repeated DOM structural patterns that likely represent UI components.
|
|
5
|
+
* Examples: card grids, list items, nav links, table rows.
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectComponents(page: Page): Promise<DetectedComponent[]>;
|
|
8
|
+
//# sourceMappingURL=ComponentDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentDetector.d.ts","sourceRoot":"","sources":["../../src/pipeline/ComponentDetector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAwC/E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects repeated DOM structural patterns that likely represent UI components.
|
|
3
|
+
* Examples: card grids, list items, nav links, table rows.
|
|
4
|
+
*/
|
|
5
|
+
export async function detectComponents(page) {
|
|
6
|
+
return page.evaluate(() => {
|
|
7
|
+
const MIN_REPETITIONS = 3;
|
|
8
|
+
const components = [];
|
|
9
|
+
// Candidate selectors — common repeating component patterns
|
|
10
|
+
const candidates = [
|
|
11
|
+
{ name: 'Card', pattern: '.card, [class*="card"]' },
|
|
12
|
+
{ name: 'ListItem', pattern: 'ul > li, ol > li' },
|
|
13
|
+
{ name: 'GridItem', pattern: '[class*="grid"] > *, [class*="col-"]' },
|
|
14
|
+
{ name: 'NavLink', pattern: 'nav a, header a' },
|
|
15
|
+
{ name: 'TableRow', pattern: 'tbody tr' },
|
|
16
|
+
{ name: 'Article', pattern: 'article, [class*="post"], [class*="article"]' },
|
|
17
|
+
{ name: 'Testimonial', pattern: '[class*="testimonial"], [class*="review"]' },
|
|
18
|
+
{ name: 'Feature', pattern: '[class*="feature"], [class*="benefit"]' },
|
|
19
|
+
{ name: 'Pricing', pattern: '[class*="pricing"], [class*="plan"], [class*="tier"]' },
|
|
20
|
+
{ name: 'MenuItem', pattern: '[role="menuitem"], [class*="menu-item"]' },
|
|
21
|
+
{ name: 'Tag', pattern: '[class*="tag"], [class*="badge"], [class*="chip"]' },
|
|
22
|
+
];
|
|
23
|
+
for (const { name, pattern } of candidates) {
|
|
24
|
+
let els;
|
|
25
|
+
try {
|
|
26
|
+
els = document.querySelectorAll(pattern);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (els.length < MIN_REPETITIONS)
|
|
32
|
+
continue;
|
|
33
|
+
components.push({
|
|
34
|
+
name,
|
|
35
|
+
pattern,
|
|
36
|
+
count: els.length,
|
|
37
|
+
sampleHTML: els[0].outerHTML.slice(0, 400),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return components;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ComponentDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentDetector.js","sourceRoot":"","sources":["../../src/pipeline/ComponentDetector.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAU;IAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAwB,EAAE;QAC3C,MAAM,eAAe,GAAG,CAAC,CAAC;QAC1B,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,4DAA4D;QAC5D,MAAM,UAAU,GAAG;YACf,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,EAAE;YACnD,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,EAAE;YACjD,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,sCAAsC,EAAE;YACrE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE;YAC/C,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE;YACzC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,8CAA8C,EAAE;YAC5E,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,2CAA2C,EAAE;YAC7E,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,wCAAwC,EAAE;YACtE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,sDAAsD,EAAE;YACpF,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,yCAAyC,EAAE;YACxE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,mDAAmD,EAAE;SAChF,CAAC;QAEF,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,UAAU,EAAE,CAAC;YACzC,IAAI,GAAwB,CAAC;YAC7B,IAAI,CAAC;gBACD,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACL,SAAS;YACb,CAAC;YAED,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe;gBAAE,SAAS;YAE3C,UAAU,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,OAAO;gBACP,KAAK,EAAE,GAAG,CAAC,MAAM;gBACjB,UAAU,EAAG,GAAG,CAAC,CAAC,CAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;aAC9D,CAAC,CAAC;QACP,CAAC;QAED,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,yBAAyB,CAAC;AAE9E,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4L1E"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { PromptGenerator } from '../prompting/PromptGenerator.js';
|
|
4
|
+
import { BrowserManager } from '../browser/BrowserManager.js';
|
|
5
|
+
import { PageLoader } from '../browser/PageLoader.js';
|
|
6
|
+
import { extractMeta } from '../extractors/MetaExtractor.js';
|
|
7
|
+
import { extractDom } from '../extractors/DomExtractor.js';
|
|
8
|
+
import { extractStyles } from '../extractors/StyleExtractor.js';
|
|
9
|
+
import { extractAssets } from '../extractors/AssetExtractor.js';
|
|
10
|
+
import { extractContent } from '../extractors/ContentExtractor.js';
|
|
11
|
+
import { extractInteractions } from '../extractors/InteractionExtractor.js';
|
|
12
|
+
import { extractAnimations } from '../extractors/AnimationExtractor.js';
|
|
13
|
+
import { detectComponents } from './ComponentDetector.js';
|
|
14
|
+
import { cleanContent, cleanImages, cleanStringList, pruneEmptyDomNodes } from './Cleaner.js';
|
|
15
|
+
import { serializeJson } from '../serializer/JsonSerializer.js';
|
|
16
|
+
import { serializeMarkdown } from '../serializer/MarkdownSerializer.js';
|
|
17
|
+
import { writeOutput } from '../output/Writer.js';
|
|
18
|
+
import { estimateTokens } from '../utils/tokenEstimator.js';
|
|
19
|
+
import { logger } from '../utils/logger.js';
|
|
20
|
+
export async function runExtraction(opts) {
|
|
21
|
+
const browserManager = new BrowserManager();
|
|
22
|
+
const mode = opts.fast ? 'fast' : 'full';
|
|
23
|
+
try {
|
|
24
|
+
const context = await browserManager.launch(mode);
|
|
25
|
+
const loader = new PageLoader(context, opts.timeout);
|
|
26
|
+
logger.step('🚀', `Loading page (${mode} mode)...`);
|
|
27
|
+
const { page, finalUrl, loadTime } = await loader.load(opts.url, opts.clickSelector);
|
|
28
|
+
logger.step('⚙️', 'Running extraction pipeline (parallel)...');
|
|
29
|
+
logger.divider();
|
|
30
|
+
// Run all extractors in parallel for performance
|
|
31
|
+
const [meta, structure, designTokens, assets, content, interactions, components] = await Promise.all([
|
|
32
|
+
extractMeta(page).catch(() => ({ title: '', description: '', ogImage: null, canonical: null, themeColor: null, jsonLd: [] })),
|
|
33
|
+
extractDom(page).catch(() => []),
|
|
34
|
+
extractStyles(page).catch(() => ({ colors: {}, spacing: {}, typography: {}, fonts: [], breakpoints: [] })),
|
|
35
|
+
extractAssets(page, finalUrl).catch(() => ({ images: [], gifs: [], fonts: [], icons: [], scripts: [] })),
|
|
36
|
+
extractContent(page).catch(() => []),
|
|
37
|
+
extractInteractions(page).catch(() => []),
|
|
38
|
+
detectComponents(page).catch(() => []),
|
|
39
|
+
]);
|
|
40
|
+
logger.step('🎬', 'Analysing animations...');
|
|
41
|
+
const animations = await extractAnimations(page, assets.gifs).catch(() => ({
|
|
42
|
+
cssAnimations: [],
|
|
43
|
+
cssTransitions: [],
|
|
44
|
+
jsAnimations: [],
|
|
45
|
+
scrollAnimations: [],
|
|
46
|
+
gifAnimations: [],
|
|
47
|
+
summary: 'Animation extraction failed',
|
|
48
|
+
}));
|
|
49
|
+
// Post-processing
|
|
50
|
+
const cleanedContent = cleanContent(content);
|
|
51
|
+
const cleanedImages = cleanImages(assets.images);
|
|
52
|
+
const cleanedGifs = cleanImages(assets.gifs);
|
|
53
|
+
const cleanedStructure = pruneEmptyDomNodes(structure);
|
|
54
|
+
const ctx = {
|
|
55
|
+
schemaVersion: '1.0',
|
|
56
|
+
url: opts.url,
|
|
57
|
+
finalUrl,
|
|
58
|
+
extractedAt: new Date().toISOString(),
|
|
59
|
+
loadTimeMs: loadTime,
|
|
60
|
+
tokenEstimate: 0, // calculated below
|
|
61
|
+
meta,
|
|
62
|
+
structure: cleanedStructure,
|
|
63
|
+
designTokens,
|
|
64
|
+
components,
|
|
65
|
+
assets: {
|
|
66
|
+
images: cleanedImages,
|
|
67
|
+
gifs: cleanedGifs,
|
|
68
|
+
fonts: cleanStringList(assets.fonts),
|
|
69
|
+
icons: cleanStringList(assets.icons),
|
|
70
|
+
scripts: cleanStringList(assets.scripts),
|
|
71
|
+
},
|
|
72
|
+
content: cleanedContent,
|
|
73
|
+
interactions,
|
|
74
|
+
animations,
|
|
75
|
+
};
|
|
76
|
+
// Calculate token estimate on the final object
|
|
77
|
+
const jsonString = JSON.stringify(ctx, null, 2);
|
|
78
|
+
ctx.tokenEstimate = estimateTokens(jsonString);
|
|
79
|
+
// Serialize
|
|
80
|
+
logger.step('📦', 'Serializing output...');
|
|
81
|
+
logger.divider();
|
|
82
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
83
|
+
// Create a domain-specific subdirectory
|
|
84
|
+
const hostname = new URL(opts.url).hostname.replace(/^www\./, '');
|
|
85
|
+
const outputDir = path.resolve(opts.outputDir, hostname);
|
|
86
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
87
|
+
if (opts.format === 'json' || opts.format === 'both') {
|
|
88
|
+
const json = serializeJson(ctx);
|
|
89
|
+
await writeOutput(path.join(outputDir, `khoj-context-${timestamp}.json`), json);
|
|
90
|
+
}
|
|
91
|
+
if (opts.format === 'markdown' || opts.format === 'both') {
|
|
92
|
+
const md = serializeMarkdown(ctx);
|
|
93
|
+
await writeOutput(path.join(outputDir, `khoj-context-${timestamp}.md`), md);
|
|
94
|
+
}
|
|
95
|
+
// Clone Mode Extraction
|
|
96
|
+
if (opts.clone) {
|
|
97
|
+
logger.step('📸', 'Extracting clone assets (Screenshot, HTML, CSS)...');
|
|
98
|
+
logger.divider();
|
|
99
|
+
// 1. Full Page Screenshot
|
|
100
|
+
const screenshotPath = path.join(outputDir, `khoj-clone-${timestamp}.png`);
|
|
101
|
+
await page.screenshot({ path: screenshotPath, fullPage: true });
|
|
102
|
+
// 2. Raw HTML
|
|
103
|
+
const rawHtml = await page.content();
|
|
104
|
+
const htmlPath = path.join(outputDir, `khoj-clone-${timestamp}.html`);
|
|
105
|
+
await writeOutput(htmlPath, rawHtml);
|
|
106
|
+
// 3. Raw CSS (Inline + External)
|
|
107
|
+
const cssPath = path.join(outputDir, `khoj-clone-${timestamp}.css`);
|
|
108
|
+
// First get all inline styles and external URLs from the browser context
|
|
109
|
+
const { inlineStyles, externalUrls } = await page.evaluate(() => {
|
|
110
|
+
const styles = Array.from(document.querySelectorAll('style')).map(s => s.textContent || '');
|
|
111
|
+
const links = Array.from(document.querySelectorAll('link[rel="stylesheet"]'))
|
|
112
|
+
.map(l => l.getAttribute('href'))
|
|
113
|
+
.filter((href) => href !== null)
|
|
114
|
+
.map(href => new URL(href, document.baseURI).href);
|
|
115
|
+
return { inlineStyles: styles, externalUrls: links };
|
|
116
|
+
});
|
|
117
|
+
let rawCss = '';
|
|
118
|
+
// Render inline styles
|
|
119
|
+
for (const style of inlineStyles) {
|
|
120
|
+
if (style.trim()) {
|
|
121
|
+
rawCss += `/* Inline Style */\n${style}\n\n`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Fetch external styles from Node context to bypass browser CORS policies
|
|
125
|
+
for (const url of externalUrls) {
|
|
126
|
+
try {
|
|
127
|
+
const response = await fetch(url);
|
|
128
|
+
if (response.ok) {
|
|
129
|
+
const cssText = await response.text();
|
|
130
|
+
rawCss += `/* External Style: ${url} */\n${cssText}\n\n`;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
rawCss += `/* Failed to fetch external style (HTTP ${response.status}): ${url} */\n\n`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
rawCss += `/* Failed to fetch external style (Network Error): ${url} */\n\n`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
await writeOutput(cssPath, rawCss);
|
|
141
|
+
// 4. Generate AI Prompt (if requested)
|
|
142
|
+
if (opts.cloneSkills !== undefined) {
|
|
143
|
+
// We assert the type here because PromptGenerator expects CloneSkill[]
|
|
144
|
+
// and the CLI ensures only valid values are passed.
|
|
145
|
+
const promptContent = PromptGenerator.generate(opts.cloneSkills);
|
|
146
|
+
const promptPath = path.join(outputDir, `prompt.md`);
|
|
147
|
+
await writeOutput(promptPath, promptContent);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Final report
|
|
151
|
+
logger.divider();
|
|
152
|
+
logger.step('📊', 'Extraction complete');
|
|
153
|
+
logger.stat('URL', ctx.url);
|
|
154
|
+
logger.stat('Images', `${cleanedImages.length} images, ${cleanedGifs.length} GIFs`);
|
|
155
|
+
logger.stat('Animations', `${ctx.animations.cssAnimations.length} CSS, ${ctx.animations.jsAnimations.length} JS`);
|
|
156
|
+
logger.stat('Token estimate', `~${ctx.tokenEstimate.toLocaleString()} tokens`);
|
|
157
|
+
logger.stat('Load time', `${(loadTime / 1000).toFixed(2)}s`);
|
|
158
|
+
logger.divider();
|
|
159
|
+
if (opts.clone) {
|
|
160
|
+
logger.step('📸', 'Clone artifacts saved:');
|
|
161
|
+
logger.stat('Screenshot', `khoj-clone-${timestamp}.png`);
|
|
162
|
+
logger.stat('HTML Source', `khoj-clone-${timestamp}.html`);
|
|
163
|
+
logger.stat('CSS Source', `khoj-clone-${timestamp}.css`);
|
|
164
|
+
if (opts.cloneSkills !== undefined) {
|
|
165
|
+
logger.stat('System Prompt', `prompt.md`);
|
|
166
|
+
}
|
|
167
|
+
logger.divider();
|
|
168
|
+
}
|
|
169
|
+
if (ctx.animations.summary) {
|
|
170
|
+
logger.step('🎬', `Animations: ${ctx.animations.summary}`);
|
|
171
|
+
}
|
|
172
|
+
// Optional Gemini integration
|
|
173
|
+
if (opts.sendToGemini) {
|
|
174
|
+
const { sendToGemini } = await import('../ai/GeminiAdapter.js');
|
|
175
|
+
await sendToGemini(ctx, opts.prompt);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
await browserManager.close();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAuB;IACvD,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAEzC,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAErD,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,IAAI,WAAW,CAAC,CAAC;QACpD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAErF,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,EAAE,CAAC;QAEjB,iDAAiD;QACjD,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,GAC5E,MAAM,OAAO,CAAC,GAAG,CAAC;YACd,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YAC7H,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YAChC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1G,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YACxG,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YACpC,mBAAmB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YACzC,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;SACzC,CAAC,CAAC;QAEP,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YACvE,aAAa,EAAE,EAAE;YACjB,cAAc,EAAE,EAAE;YAClB,YAAY,EAAE,EAAE;YAChB,gBAAgB,EAAE,EAAE;YACpB,aAAa,EAAE,EAAE;YACjB,OAAO,EAAE,6BAA6B;SACzC,CAAC,CAAC,CAAC;QAEJ,kBAAkB;QAClB,MAAM,cAAc,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAEvD,MAAM,GAAG,GAAgB;YACrB,aAAa,EAAE,KAAK;YACpB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ;YACR,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACrC,UAAU,EAAE,QAAQ;YACpB,aAAa,EAAE,CAAC,EAAE,mBAAmB;YACrC,IAAI;YACJ,SAAS,EAAE,gBAAgB;YAC3B,YAAY;YACZ,UAAU;YACV,MAAM,EAAE;gBACJ,MAAM,EAAE,aAAa;gBACrB,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC;aAC3C;YACD,OAAO,EAAE,cAAc;YACvB,YAAY;YACZ,UAAU;SACb,CAAC;QAEF,+CAA+C;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAChD,GAAG,CAAC,aAAa,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QAE/C,YAAY;QACZ,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,EAAE,CAAC;QAEjB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAE9E,wCAAwC;QACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACvD,MAAM,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,SAAS,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,wBAAwB;QACxB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,oDAAoD,CAAC,CAAC;YACxE,MAAM,CAAC,OAAO,EAAE,CAAC;YAEjB,0BAA0B;YAC1B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,SAAS,MAAM,CAAC,CAAC;YAC3E,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAEhE,cAAc;YACd,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,SAAS,OAAO,CAAC,CAAC;YACtE,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAErC,iCAAiC;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,SAAS,MAAM,CAAC,CAAC;YAEpE,yEAAyE;YACzE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;gBAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;gBAC5F,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;qBACxE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;qBAChC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;qBAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;gBAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;YACzD,CAAC,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAEhB,uBAAuB;YACvB,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;gBAC/B,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBACf,MAAM,IAAI,uBAAuB,KAAK,MAAM,CAAC;gBACjD,CAAC;YACL,CAAC;YAED,0EAA0E;YAC1E,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;oBAClC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;wBACd,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;wBACtC,MAAM,IAAI,sBAAsB,GAAG,QAAQ,OAAO,MAAM,CAAC;oBAC7D,CAAC;yBAAM,CAAC;wBACJ,MAAM,IAAI,2CAA2C,QAAQ,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC;oBAC3F,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACT,MAAM,IAAI,sDAAsD,GAAG,SAAS,CAAC;gBACjF,CAAC;YACL,CAAC;YAED,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAEnC,uCAAuC;YACvC,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACjC,wEAAwE;gBACxE,oDAAoD;gBACpD,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAkB,CAAC,CAAC;gBACxE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;gBACrD,MAAM,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YACjD,CAAC;QACL,CAAC;QAED,eAAe;QACf,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC,MAAM,YAAY,WAAW,CAAC,MAAM,OAAO,CAAC,CAAC;QACpF,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM,SAAS,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC;QAClH,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,CAAC,aAAa,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,OAAO,EAAE,CAAC;QAEjB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,SAAS,MAAM,CAAC,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,SAAS,OAAO,CAAC,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,SAAS,MAAM,CAAC,CAAC;YACzD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;YAC9C,CAAC;YACD,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,8BAA8B;QAC9B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;YAChE,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;IAEL,CAAC;YAAS,CAAC;QACP,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;AACL,CAAC"}
|