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.
Files changed (95) hide show
  1. package/README.md +136 -0
  2. package/dist/ai/GeminiAdapter.d.ts +7 -0
  3. package/dist/ai/GeminiAdapter.d.ts.map +1 -0
  4. package/dist/ai/GeminiAdapter.js +40 -0
  5. package/dist/ai/GeminiAdapter.js.map +1 -0
  6. package/dist/browser/BrowserManager.d.ts +17 -0
  7. package/dist/browser/BrowserManager.d.ts.map +1 -0
  8. package/dist/browser/BrowserManager.js +61 -0
  9. package/dist/browser/BrowserManager.js.map +1 -0
  10. package/dist/browser/PageLoader.d.ts +21 -0
  11. package/dist/browser/PageLoader.d.ts.map +1 -0
  12. package/dist/browser/PageLoader.js +116 -0
  13. package/dist/browser/PageLoader.js.map +1 -0
  14. package/dist/cli/index.d.ts +3 -0
  15. package/dist/cli/index.d.ts.map +1 -0
  16. package/dist/cli/index.js +98 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/extractors/AnimationExtractor.d.ts +12 -0
  19. package/dist/extractors/AnimationExtractor.d.ts.map +1 -0
  20. package/dist/extractors/AnimationExtractor.js +247 -0
  21. package/dist/extractors/AnimationExtractor.js.map +1 -0
  22. package/dist/extractors/AssetExtractor.d.ts +11 -0
  23. package/dist/extractors/AssetExtractor.d.ts.map +1 -0
  24. package/dist/extractors/AssetExtractor.js +124 -0
  25. package/dist/extractors/AssetExtractor.js.map +1 -0
  26. package/dist/extractors/ContentExtractor.d.ts +13 -0
  27. package/dist/extractors/ContentExtractor.d.ts.map +1 -0
  28. package/dist/extractors/ContentExtractor.js +60 -0
  29. package/dist/extractors/ContentExtractor.js.map +1 -0
  30. package/dist/extractors/DomExtractor.d.ts +11 -0
  31. package/dist/extractors/DomExtractor.d.ts.map +1 -0
  32. package/dist/extractors/DomExtractor.js +68 -0
  33. package/dist/extractors/DomExtractor.js.map +1 -0
  34. package/dist/extractors/InteractionExtractor.d.ts +10 -0
  35. package/dist/extractors/InteractionExtractor.d.ts.map +1 -0
  36. package/dist/extractors/InteractionExtractor.js +64 -0
  37. package/dist/extractors/InteractionExtractor.js.map +1 -0
  38. package/dist/extractors/MetaExtractor.d.ts +8 -0
  39. package/dist/extractors/MetaExtractor.d.ts.map +1 -0
  40. package/dist/extractors/MetaExtractor.js +33 -0
  41. package/dist/extractors/MetaExtractor.js.map +1 -0
  42. package/dist/extractors/StyleExtractor.d.ts +10 -0
  43. package/dist/extractors/StyleExtractor.d.ts.map +1 -0
  44. package/dist/extractors/StyleExtractor.js +87 -0
  45. package/dist/extractors/StyleExtractor.js.map +1 -0
  46. package/dist/index.d.ts +6 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +6 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/output/Writer.d.ts +5 -0
  51. package/dist/output/Writer.d.ts.map +1 -0
  52. package/dist/output/Writer.js +13 -0
  53. package/dist/output/Writer.js.map +1 -0
  54. package/dist/pipeline/Cleaner.d.ts +12 -0
  55. package/dist/pipeline/Cleaner.d.ts.map +1 -0
  56. package/dist/pipeline/Cleaner.js +41 -0
  57. package/dist/pipeline/Cleaner.js.map +1 -0
  58. package/dist/pipeline/ComponentDetector.d.ts +8 -0
  59. package/dist/pipeline/ComponentDetector.d.ts.map +1 -0
  60. package/dist/pipeline/ComponentDetector.js +43 -0
  61. package/dist/pipeline/ComponentDetector.js.map +1 -0
  62. package/dist/pipeline/runner.d.ts +3 -0
  63. package/dist/pipeline/runner.d.ts.map +1 -0
  64. package/dist/pipeline/runner.js +182 -0
  65. package/dist/pipeline/runner.js.map +1 -0
  66. package/dist/prompting/PromptGenerator.d.ts +5 -0
  67. package/dist/prompting/PromptGenerator.d.ts.map +1 -0
  68. package/dist/prompting/PromptGenerator.js +30 -0
  69. package/dist/prompting/PromptGenerator.js.map +1 -0
  70. package/dist/serializer/JsonSerializer.d.ts +6 -0
  71. package/dist/serializer/JsonSerializer.d.ts.map +1 -0
  72. package/dist/serializer/JsonSerializer.js +7 -0
  73. package/dist/serializer/JsonSerializer.js.map +1 -0
  74. package/dist/serializer/MarkdownSerializer.d.ts +7 -0
  75. package/dist/serializer/MarkdownSerializer.d.ts.map +1 -0
  76. package/dist/serializer/MarkdownSerializer.js +143 -0
  77. package/dist/serializer/MarkdownSerializer.js.map +1 -0
  78. package/dist/types/KhojContext.d.ts +141 -0
  79. package/dist/types/KhojContext.d.ts.map +1 -0
  80. package/dist/types/KhojContext.js +6 -0
  81. package/dist/types/KhojContext.js.map +1 -0
  82. package/dist/utils/logger.d.ts +15 -0
  83. package/dist/utils/logger.d.ts.map +1 -0
  84. package/dist/utils/logger.js +70 -0
  85. package/dist/utils/logger.js.map +1 -0
  86. package/dist/utils/text.d.ts +2 -0
  87. package/dist/utils/text.d.ts.map +1 -0
  88. package/dist/utils/text.js +6 -0
  89. package/dist/utils/text.js.map +1 -0
  90. package/dist/utils/tokenEstimator.d.ts +10 -0
  91. package/dist/utils/tokenEstimator.d.ts.map +1 -0
  92. package/dist/utils/tokenEstimator.js +17 -0
  93. package/dist/utils/tokenEstimator.js.map +1 -0
  94. package/khoj-context.schema.json +48 -0
  95. 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":"AAGA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAU;IAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAkB,EAAE;QACrC,MAAM,YAAY,GAAkB,EAAE,CAAC;QAEvC,SAAS,cAAc,CAAC,EAAW;YAC/B,IAAI,EAAE,CAAC,EAAE;gBAAE,OAAO,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACvC,CAAC;QAED,2EAA2E;QAC3E,QAAQ,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAC/C,MAAM,MAAM,GAAgB,EAAE,CAAC;YAC/B,IAAI,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC/D,MAAM,EAAE,GAAG,KAAmE,CAAC;gBAC/E,MAAM,CAAC,IAAI,CAAC;oBACR,SAAS,EAAE,EAAE,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAE,EAAuB,CAAC,IAAI,IAAI,MAAM;oBAChI,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;oBAC5B,WAAW,EAAG,EAAuB,CAAC,WAAW,IAAI,EAAE;oBACvD,QAAQ,EAAG,EAAuB,CAAC,QAAQ,IAAI,KAAK;iBACvD,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;YAEH,MAAM,KAAK,GACP,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC/B,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;gBACjE,IAAI,CAAC,EAAE;gBACP,MAAM,CAAC;YAEX,YAAY,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC;gBAC9B,KAAK;gBACL,MAAM;aACT,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,2EAA2E;QAC3E,QAAQ,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAClE,MAAM,KAAK,GACP,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC9B,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC;gBACtB,YAAY,CAAC;YAEjB,YAAY,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC;gBAC7B,KAAK;aACR,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,2EAA2E;QAC3E,MAAM,SAAS,GAAG,QAAQ,CAAC,gBAAgB,CACvC,qEAAqE,CACxE,CAAC;QACF,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YACrB,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;YAClF,YAAY,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,cAAc,CAAC,EAAE,CAAC;gBAC5B,KAAK;aACR,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,OAAO,YAAY,CAAC;IACxB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -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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"}
@@ -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,5 @@
1
+ /**
2
+ * Writes content to a file, creating directories as needed.
3
+ */
4
+ export declare function writeOutput(filePath: string, content: string): Promise<void>;
5
+ //# sourceMappingURL=Writer.d.ts.map
@@ -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,3 @@
1
+ import type { ExtractionOptions } from '../types/KhojContext.js';
2
+ export declare function runExtraction(opts: ExtractionOptions): Promise<void>;
3
+ //# sourceMappingURL=runner.d.ts.map
@@ -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":"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"}