@productivemark/snipcss 1.0.0
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/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +10 -0
- package/.mcp.json +8 -0
- package/dist/auth/config-manager.d.ts +13 -0
- package/dist/auth/config-manager.d.ts.map +1 -0
- package/dist/auth/config-manager.js +48 -0
- package/dist/auth/config-manager.js.map +1 -0
- package/dist/auth/usage-gate.d.ts +13 -0
- package/dist/auth/usage-gate.d.ts.map +1 -0
- package/dist/auth/usage-gate.js +69 -0
- package/dist/auth/usage-gate.js.map +1 -0
- package/dist/browser/browser-manager.d.ts +15 -0
- package/dist/browser/browser-manager.d.ts.map +1 -0
- package/dist/browser/browser-manager.js +61 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/viewport-manager.d.ts +8 -0
- package/dist/browser/viewport-manager.d.ts.map +1 -0
- package/dist/browser/viewport-manager.js +50 -0
- package/dist/browser/viewport-manager.js.map +1 -0
- package/dist/extraction/css-variable-resolver.d.ts +27 -0
- package/dist/extraction/css-variable-resolver.d.ts.map +1 -0
- package/dist/extraction/css-variable-resolver.js +105 -0
- package/dist/extraction/css-variable-resolver.js.map +1 -0
- package/dist/extraction/dom-labeler.d.ts +26 -0
- package/dist/extraction/dom-labeler.d.ts.map +1 -0
- package/dist/extraction/dom-labeler.js +124 -0
- package/dist/extraction/dom-labeler.js.map +1 -0
- package/dist/extraction/element-discovery.d.ts +59 -0
- package/dist/extraction/element-discovery.d.ts.map +1 -0
- package/dist/extraction/element-discovery.js +525 -0
- package/dist/extraction/element-discovery.js.map +1 -0
- package/dist/extraction/extraction-pipeline.d.ts +26 -0
- package/dist/extraction/extraction-pipeline.d.ts.map +1 -0
- package/dist/extraction/extraction-pipeline.js +200 -0
- package/dist/extraction/extraction-pipeline.js.map +1 -0
- package/dist/extraction/font-collector.d.ts +26 -0
- package/dist/extraction/font-collector.d.ts.map +1 -0
- package/dist/extraction/font-collector.js +160 -0
- package/dist/extraction/font-collector.js.map +1 -0
- package/dist/extraction/html-cleaner.d.ts +16 -0
- package/dist/extraction/html-cleaner.d.ts.map +1 -0
- package/dist/extraction/html-cleaner.js +149 -0
- package/dist/extraction/html-cleaner.js.map +1 -0
- package/dist/extraction/keyframe-collector.d.ts +16 -0
- package/dist/extraction/keyframe-collector.d.ts.map +1 -0
- package/dist/extraction/keyframe-collector.js +62 -0
- package/dist/extraction/keyframe-collector.js.map +1 -0
- package/dist/extraction/pseudo-state-handler.d.ts +36 -0
- package/dist/extraction/pseudo-state-handler.d.ts.map +1 -0
- package/dist/extraction/pseudo-state-handler.js +210 -0
- package/dist/extraction/pseudo-state-handler.js.map +1 -0
- package/dist/extraction/result-builder.d.ts +25 -0
- package/dist/extraction/result-builder.d.ts.map +1 -0
- package/dist/extraction/result-builder.js +136 -0
- package/dist/extraction/result-builder.js.map +1 -0
- package/dist/extraction/rule-deduplicator.d.ts +39 -0
- package/dist/extraction/rule-deduplicator.d.ts.map +1 -0
- package/dist/extraction/rule-deduplicator.js +107 -0
- package/dist/extraction/rule-deduplicator.js.map +1 -0
- package/dist/extraction/selector-fixer.d.ts +25 -0
- package/dist/extraction/selector-fixer.d.ts.map +1 -0
- package/dist/extraction/selector-fixer.js +111 -0
- package/dist/extraction/selector-fixer.js.map +1 -0
- package/dist/extraction/specificity.d.ts +17 -0
- package/dist/extraction/specificity.d.ts.map +1 -0
- package/dist/extraction/specificity.js +88 -0
- package/dist/extraction/specificity.js.map +1 -0
- package/dist/extraction/style-matcher.d.ts +33 -0
- package/dist/extraction/style-matcher.d.ts.map +1 -0
- package/dist/extraction/style-matcher.js +199 -0
- package/dist/extraction/style-matcher.js.map +1 -0
- package/dist/extraction/stylesheet-collector.d.ts +33 -0
- package/dist/extraction/stylesheet-collector.d.ts.map +1 -0
- package/dist/extraction/stylesheet-collector.js +71 -0
- package/dist/extraction/stylesheet-collector.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +235 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +349 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/tailwind/css-to-tailwind.d.ts +17 -0
- package/dist/tailwind/css-to-tailwind.d.ts.map +1 -0
- package/dist/tailwind/css-to-tailwind.js +1583 -0
- package/dist/tailwind/css-to-tailwind.js.map +1 -0
- package/dist/tailwind/shorthand-expander.d.ts +27 -0
- package/dist/tailwind/shorthand-expander.d.ts.map +1 -0
- package/dist/tailwind/shorthand-expander.js +812 -0
- package/dist/tailwind/shorthand-expander.js.map +1 -0
- package/dist/tailwind/tailwind-converter.d.ts +35 -0
- package/dist/tailwind/tailwind-converter.d.ts.map +1 -0
- package/dist/tailwind/tailwind-converter.js +1223 -0
- package/dist/tailwind/tailwind-converter.js.map +1 -0
- package/dist/tailwind/tailwind-helpers.d.ts +95 -0
- package/dist/tailwind/tailwind-helpers.d.ts.map +1 -0
- package/dist/tailwind/tailwind-helpers.js +593 -0
- package/dist/tailwind/tailwind-helpers.js.map +1 -0
- package/dist/tailwind/tailwind-reducer.d.ts +36 -0
- package/dist/tailwind/tailwind-reducer.d.ts.map +1 -0
- package/dist/tailwind/tailwind-reducer.js +189 -0
- package/dist/tailwind/tailwind-reducer.js.map +1 -0
- package/dist/types/index.d.ts +239 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +94 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/helpers.d.ts +34 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +120 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/parsel.d.ts +41 -0
- package/dist/utils/parsel.d.ts.map +1 -0
- package/dist/utils/parsel.js +314 -0
- package/dist/utils/parsel.js.map +1 -0
- package/package.json +41 -0
- package/skills/workflow/SKILL.md +95 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snipcss",
|
|
3
|
+
"owner": { "name": "SnipCSS" },
|
|
4
|
+
"metadata": {
|
|
5
|
+
"description": "CSS extraction and Tailwind conversion tools for Claude Code"
|
|
6
|
+
},
|
|
7
|
+
"plugins": [
|
|
8
|
+
{
|
|
9
|
+
"name": "snipcss",
|
|
10
|
+
"source": {
|
|
11
|
+
"source": "github",
|
|
12
|
+
"repo": "mrieck/snipcss-playwright-claudeplugin"
|
|
13
|
+
},
|
|
14
|
+
"description": "Convert repos to Tailwind or extract pixel-perfect designs from any website. Gives Claude design super-powers via Playwright and SnipCSS."
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snipcss",
|
|
3
|
+
"description": "Snipcss tools are the most accurate way to convert a repo to tailwind or extract designs from existing websites. The agent can use playwright with SnipCSS on any local or remote url. This plugin allows Claude to use SnipCSS however needed to achieve a goal - whether it's Tailwind conversion or importing pixel-perfect designs, this plugin will give Claude design super-powers.",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"author": { "name": "SnipCSS" },
|
|
6
|
+
"homepage": "https://www.snipcss.com",
|
|
7
|
+
"repository": "https://github.com/mrieck/snipcss-playwright-claudeplugin",
|
|
8
|
+
"license": "UNLICENSED",
|
|
9
|
+
"keywords": ["css", "tailwind", "extraction", "design"]
|
|
10
|
+
}
|
package/.mcp.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SnipcssConfig {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
usageCount: number;
|
|
4
|
+
lastVerified?: string;
|
|
5
|
+
verifiedPro?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadConfig(): SnipcssConfig;
|
|
8
|
+
export declare function saveConfig(config: SnipcssConfig): void;
|
|
9
|
+
export declare function getUsageCount(): number;
|
|
10
|
+
export declare function incrementUsage(): number;
|
|
11
|
+
export declare function setApiKey(key: string): void;
|
|
12
|
+
export declare function getApiKey(): string | undefined;
|
|
13
|
+
//# sourceMappingURL=config-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/auth/config-manager.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AASD,wBAAgB,UAAU,IAAI,aAAa,CAW1C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAKtD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAO3C;AAED,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.snipcss');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
usageCount: 0,
|
|
8
|
+
};
|
|
9
|
+
export function loadConfig() {
|
|
10
|
+
try {
|
|
11
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
12
|
+
return { ...DEFAULT_CONFIG };
|
|
13
|
+
}
|
|
14
|
+
const raw = readFileSync(CONFIG_FILE, 'utf-8');
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return { ...DEFAULT_CONFIG };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function saveConfig(config) {
|
|
23
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
24
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
27
|
+
}
|
|
28
|
+
export function getUsageCount() {
|
|
29
|
+
return loadConfig().usageCount;
|
|
30
|
+
}
|
|
31
|
+
export function incrementUsage() {
|
|
32
|
+
const config = loadConfig();
|
|
33
|
+
config.usageCount++;
|
|
34
|
+
saveConfig(config);
|
|
35
|
+
return config.usageCount;
|
|
36
|
+
}
|
|
37
|
+
export function setApiKey(key) {
|
|
38
|
+
const config = loadConfig();
|
|
39
|
+
config.apiKey = key;
|
|
40
|
+
// Clear cached verification when key changes
|
|
41
|
+
delete config.lastVerified;
|
|
42
|
+
delete config.verifiedPro;
|
|
43
|
+
saveConfig(config);
|
|
44
|
+
}
|
|
45
|
+
export function getApiKey() {
|
|
46
|
+
return loadConfig().apiKey;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=config-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/auth/config-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAS7B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,MAAM,cAAc,GAAkB;IACpC,UAAU,EAAE,CAAC;CACd,CAAC;AAEF,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAqB;IAC9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,EAAE,CAAC,UAAU,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC,UAAU,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;IACpB,6CAA6C;IAC7C,OAAO,MAAM,CAAC,YAAY,CAAC;IAC3B,OAAO,MAAM,CAAC,WAAW,CAAC;IAC1B,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,EAAE,CAAC,MAAM,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AccessResult {
|
|
2
|
+
allowed: boolean;
|
|
3
|
+
message?: string;
|
|
4
|
+
isPro?: boolean;
|
|
5
|
+
remaining?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function verifyApiKey(apiKey: string): Promise<{
|
|
8
|
+
isPro: boolean;
|
|
9
|
+
email?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function checkAccess(): Promise<AccessResult>;
|
|
13
|
+
//# sourceMappingURL=usage-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-gate.d.ts","sourceRoot":"","sources":["../../src/auth/usage-gate.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAe9G;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,CAoDzD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { loadConfig, saveConfig, incrementUsage } from './config-manager.js';
|
|
2
|
+
const VERIFY_URL = 'https://templates.snipcss.com/api/verify_claude_skill';
|
|
3
|
+
const FREE_LIMIT = 25;
|
|
4
|
+
const CACHE_HOURS = 24;
|
|
5
|
+
export async function verifyApiKey(apiKey) {
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetch(VERIFY_URL, {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: { 'Content-Type': 'application/json' },
|
|
10
|
+
body: JSON.stringify({ api_key: apiKey }),
|
|
11
|
+
});
|
|
12
|
+
const data = await res.json();
|
|
13
|
+
if (data.success && data.is_pro) {
|
|
14
|
+
return { isPro: true, email: data.email };
|
|
15
|
+
}
|
|
16
|
+
return { isPro: false, error: data.error || 'Not a Pro account' };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return { isPro: false, error: `Verification failed: ${err.message}` };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function checkAccess() {
|
|
23
|
+
const config = loadConfig();
|
|
24
|
+
// If user has an API key, try to verify Pro status
|
|
25
|
+
if (config.apiKey) {
|
|
26
|
+
// Check if we have a cached verification that's still fresh
|
|
27
|
+
if (config.lastVerified && config.verifiedPro) {
|
|
28
|
+
const verifiedAt = new Date(config.lastVerified).getTime();
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
const hoursSince = (now - verifiedAt) / (1000 * 60 * 60);
|
|
31
|
+
if (hoursSince < CACHE_HOURS) {
|
|
32
|
+
return { allowed: true, isPro: true };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Verify with the API
|
|
36
|
+
const result = await verifyApiKey(config.apiKey);
|
|
37
|
+
if (result.isPro) {
|
|
38
|
+
config.verifiedPro = true;
|
|
39
|
+
config.lastVerified = new Date().toISOString();
|
|
40
|
+
saveConfig(config);
|
|
41
|
+
return { allowed: true, isPro: true };
|
|
42
|
+
}
|
|
43
|
+
// Key exists but not Pro — clear cached status and fall through to free tier
|
|
44
|
+
config.verifiedPro = false;
|
|
45
|
+
delete config.lastVerified;
|
|
46
|
+
saveConfig(config);
|
|
47
|
+
}
|
|
48
|
+
// Free tier: check usage count
|
|
49
|
+
if (config.usageCount < FREE_LIMIT) {
|
|
50
|
+
const newCount = incrementUsage();
|
|
51
|
+
const remaining = FREE_LIMIT - newCount;
|
|
52
|
+
return {
|
|
53
|
+
allowed: true,
|
|
54
|
+
isPro: false,
|
|
55
|
+
remaining,
|
|
56
|
+
message: remaining <= 3
|
|
57
|
+
? `${remaining} free extraction${remaining === 1 ? '' : 's'} remaining. Get unlimited extractions with SnipCSS Pro: https://www.snipcss.com/pricing`
|
|
58
|
+
: undefined,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Over the free limit
|
|
62
|
+
return {
|
|
63
|
+
allowed: false,
|
|
64
|
+
isPro: false,
|
|
65
|
+
remaining: 0,
|
|
66
|
+
message: 'You have used all 25 free extractions. To continue, upgrade to SnipCSS Pro at https://www.snipcss.com/pricing and then set your API key using the set_api_key tool. Your API key can be found on your dashboard at https://www.snipcss.com/dashboard',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=usage-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-gate.js","sourceRoot":"","sources":["../../src/auth/usage-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Browser, Page, BrowserContext, CDPSession } from 'playwright';
|
|
2
|
+
export interface BrowserPage {
|
|
3
|
+
page: Page;
|
|
4
|
+
cdp: CDPSession;
|
|
5
|
+
context: BrowserContext;
|
|
6
|
+
}
|
|
7
|
+
export declare class BrowserManager {
|
|
8
|
+
private browser;
|
|
9
|
+
launch(): Promise<Browser>;
|
|
10
|
+
createPage(url: string, timeout?: number): Promise<BrowserPage>;
|
|
11
|
+
closePage(bp: BrowserPage): Promise<void>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
isRunning(): boolean;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=browser-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-manager.d.ts","sourceRoot":"","sources":["../../src/browser/browser-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,UAAU,CAAC;IAChB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAwB;IAEjC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB1B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;IA8B9D,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,SAAS,IAAI,OAAO;CAGrB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { chromium } from 'playwright';
|
|
2
|
+
export class BrowserManager {
|
|
3
|
+
browser = null;
|
|
4
|
+
async launch() {
|
|
5
|
+
if (this.browser)
|
|
6
|
+
return this.browser;
|
|
7
|
+
this.browser = await chromium.launch({
|
|
8
|
+
headless: true,
|
|
9
|
+
args: [
|
|
10
|
+
'--no-sandbox',
|
|
11
|
+
'--disable-setuid-sandbox',
|
|
12
|
+
'--disable-dev-shm-usage',
|
|
13
|
+
'--disable-gpu',
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
return this.browser;
|
|
17
|
+
}
|
|
18
|
+
async createPage(url, timeout = 30000) {
|
|
19
|
+
if (!this.browser) {
|
|
20
|
+
await this.launch();
|
|
21
|
+
}
|
|
22
|
+
const context = await this.browser.newContext({
|
|
23
|
+
viewport: { width: 1366, height: 768 },
|
|
24
|
+
ignoreHTTPSErrors: true,
|
|
25
|
+
});
|
|
26
|
+
const page = await context.newPage();
|
|
27
|
+
// Create CDP session - this replaces chrome.debugger.attach()
|
|
28
|
+
const cdp = await context.newCDPSession(page);
|
|
29
|
+
// Enable CDP domains - replaces onDebuggerAttach() from snipbackground.js:306-341
|
|
30
|
+
await cdp.send('DOM.enable');
|
|
31
|
+
await cdp.send('CSS.enable');
|
|
32
|
+
await cdp.send('Network.enable');
|
|
33
|
+
await cdp.send('Runtime.enable');
|
|
34
|
+
// Navigate to URL
|
|
35
|
+
await page.goto(url, {
|
|
36
|
+
waitUntil: 'networkidle',
|
|
37
|
+
timeout,
|
|
38
|
+
});
|
|
39
|
+
return { page, cdp, context };
|
|
40
|
+
}
|
|
41
|
+
async closePage(bp) {
|
|
42
|
+
try {
|
|
43
|
+
await bp.cdp.detach();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// CDP session may already be detached
|
|
47
|
+
}
|
|
48
|
+
await bp.page.close();
|
|
49
|
+
await bp.context.close();
|
|
50
|
+
}
|
|
51
|
+
async close() {
|
|
52
|
+
if (this.browser) {
|
|
53
|
+
await this.browser.close();
|
|
54
|
+
this.browser = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
isRunning() {
|
|
58
|
+
return this.browser !== null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=browser-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-manager.js","sourceRoot":"","sources":["../../src/browser/browser-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA6C,MAAM,YAAY,CAAC;AAQjF,MAAM,OAAO,cAAc;IACjB,OAAO,GAAmB,IAAI,CAAC;IAEvC,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC;QAEtC,IAAI,CAAC,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE;gBACJ,cAAc;gBACd,0BAA0B;gBAC1B,yBAAyB;gBACzB,eAAe;aAChB;SACF,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,OAAO,GAAG,KAAK;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,UAAU,CAAC;YAC7C,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;YACtC,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAErC,8DAA8D;QAC9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAE9C,kFAAkF;QAClF,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACjC,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAEjC,kBAAkB;QAClB,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACnB,SAAS,EAAE,aAAa;YACxB,OAAO;SACR,CAAC,CAAC;QAEH,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAe;QAC7B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CDPSession } from 'playwright';
|
|
2
|
+
import { ViewportConfig } from '../types/index.js';
|
|
3
|
+
export declare class ViewportManager {
|
|
4
|
+
setViewport(cdp: CDPSession, viewport: ViewportConfig): Promise<void>;
|
|
5
|
+
clearViewport(cdp: CDPSession): Promise<void>;
|
|
6
|
+
getViewportsForOption(option: string, customWidth?: number): ViewportConfig[];
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=viewport-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-manager.d.ts","sourceRoot":"","sources":["../../src/browser/viewport-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAqB,MAAM,mBAAmB,CAAC;AAEtE,qBAAa,eAAe;IACpB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrE,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE;CA0B9E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DEFAULT_VIEWPORTS } from '../types/index.js';
|
|
2
|
+
export class ViewportManager {
|
|
3
|
+
async setViewport(cdp, viewport) {
|
|
4
|
+
const params = {
|
|
5
|
+
width: viewport.width,
|
|
6
|
+
height: viewport.height,
|
|
7
|
+
deviceScaleFactor: viewport.deviceScaleFactor || 1,
|
|
8
|
+
mobile: viewport.mobile || false,
|
|
9
|
+
};
|
|
10
|
+
await cdp.send('Emulation.setDeviceMetricsOverride', params);
|
|
11
|
+
if (viewport.userAgent) {
|
|
12
|
+
await cdp.send('Emulation.setUserAgentOverride', {
|
|
13
|
+
userAgent: viewport.userAgent,
|
|
14
|
+
});
|
|
15
|
+
await cdp.send('Network.setUserAgentOverride', {
|
|
16
|
+
userAgent: viewport.userAgent,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async clearViewport(cdp) {
|
|
21
|
+
await cdp.send('Emulation.clearDeviceMetricsOverride');
|
|
22
|
+
}
|
|
23
|
+
getViewportsForOption(option, customWidth) {
|
|
24
|
+
switch (option) {
|
|
25
|
+
case 'desktop':
|
|
26
|
+
return [DEFAULT_VIEWPORTS.default];
|
|
27
|
+
case 'tablet':
|
|
28
|
+
return [DEFAULT_VIEWPORTS.ipad];
|
|
29
|
+
case 'mobile':
|
|
30
|
+
return [DEFAULT_VIEWPORTS.iphonexs];
|
|
31
|
+
case 'all':
|
|
32
|
+
return [
|
|
33
|
+
DEFAULT_VIEWPORTS.default,
|
|
34
|
+
DEFAULT_VIEWPORTS.iphonexs,
|
|
35
|
+
DEFAULT_VIEWPORTS.ipad,
|
|
36
|
+
DEFAULT_VIEWPORTS.ipadlandscape,
|
|
37
|
+
];
|
|
38
|
+
default:
|
|
39
|
+
if (customWidth) {
|
|
40
|
+
return [{
|
|
41
|
+
name: `custom-${customWidth}`,
|
|
42
|
+
width: customWidth,
|
|
43
|
+
height: 768,
|
|
44
|
+
}];
|
|
45
|
+
}
|
|
46
|
+
return [DEFAULT_VIEWPORTS.default];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=viewport-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-manager.js","sourceRoot":"","sources":["../../src/browser/viewport-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtE,MAAM,OAAO,eAAe;IAC1B,KAAK,CAAC,WAAW,CAAC,GAAe,EAAE,QAAwB;QACzD,MAAM,MAAM,GAAQ;YAClB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,IAAI,CAAC;YAClD,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,KAAK;SACjC,CAAC;QAEF,MAAM,GAAG,CAAC,IAAI,CAAC,oCAAoC,EAAE,MAAM,CAAC,CAAC;QAE7D,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACvB,MAAM,GAAG,CAAC,IAAI,CAAC,gCAAgC,EAAE;gBAC/C,SAAS,EAAE,QAAQ,CAAC,SAAS;aAC9B,CAAC,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE;gBAC7C,SAAS,EAAE,QAAQ,CAAC,SAAS;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAe;QACjC,MAAM,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACzD,CAAC;IAED,qBAAqB,CAAC,MAAc,EAAE,WAAoB;QACxD,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,SAAS;gBACZ,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,QAAQ;gBACX,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,QAAQ;gBACX,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YACtC,KAAK,KAAK;gBACR,OAAO;oBACL,iBAAiB,CAAC,OAAO;oBACzB,iBAAiB,CAAC,QAAQ;oBAC1B,iBAAiB,CAAC,IAAI;oBACtB,iBAAiB,CAAC,aAAa;iBAChC,CAAC;YACJ;gBACE,IAAI,WAAW,EAAE,CAAC;oBAChB,OAAO,CAAC;4BACN,IAAI,EAAE,UAAU,WAAW,EAAE;4BAC7B,KAAK,EAAE,WAAW;4BAClB,MAAM,EAAE,GAAG;yBACZ,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ExtractionContext } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves CSS custom properties (variables) to their computed values.
|
|
4
|
+
* Port of CSS variable resolution from snipbackground.js
|
|
5
|
+
*/
|
|
6
|
+
export declare class CssVariableResolver {
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a CSS variable reference like var(--my-color) to its value.
|
|
9
|
+
* Handles nested var() references recursively.
|
|
10
|
+
*/
|
|
11
|
+
resolveVar(varName: string, ctx: ExtractionContext, depth?: number): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Replace all var(--xxx) references in a value string with their resolved values.
|
|
14
|
+
* Handles fallback values like var(--primary, #000).
|
|
15
|
+
*/
|
|
16
|
+
resolveVarReferences(value: string, ctx: ExtractionContext, depth?: number): string;
|
|
17
|
+
/**
|
|
18
|
+
* Generate CSS text for all used CSS variables that need to be defined.
|
|
19
|
+
* Creates a :root block with the variable definitions that were used.
|
|
20
|
+
*/
|
|
21
|
+
generateVariablesCss(ctx: ExtractionContext): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get all resolved variables as a map.
|
|
24
|
+
*/
|
|
25
|
+
getResolvedVariables(ctx: ExtractionContext): Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=css-variable-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-variable-resolver.d.ts","sourceRoot":"","sources":["../../src/extraction/css-variable-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAExE;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,SAAI,GAAG,MAAM,GAAG,IAAI;IA8C7E;;;OAGG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,SAAI,GAAG,MAAM;IAmB9E;;;OAGG;IACH,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM;IAqBpD;;OAEG;IACH,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAYrE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves CSS custom properties (variables) to their computed values.
|
|
3
|
+
* Port of CSS variable resolution from snipbackground.js
|
|
4
|
+
*/
|
|
5
|
+
export class CssVariableResolver {
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a CSS variable reference like var(--my-color) to its value.
|
|
8
|
+
* Handles nested var() references recursively.
|
|
9
|
+
*/
|
|
10
|
+
resolveVar(varName, ctx, depth = 0) {
|
|
11
|
+
if (depth > 10)
|
|
12
|
+
return null; // Prevent infinite recursion
|
|
13
|
+
// Check resolved cache first
|
|
14
|
+
if (ctx.cssvarResolvedValues[varName]) {
|
|
15
|
+
return ctx.cssvarResolvedValues[varName];
|
|
16
|
+
}
|
|
17
|
+
// Check cssvarAllArr (global :root variables)
|
|
18
|
+
if (ctx.cssvarAllArr[varName]) {
|
|
19
|
+
let val = ctx.cssvarAllArr[varName].replace(/;$/, '').trim();
|
|
20
|
+
// If value contains another var() reference, resolve it
|
|
21
|
+
if (val.includes('var(')) {
|
|
22
|
+
val = this.resolveVarReferences(val, ctx, depth + 1);
|
|
23
|
+
}
|
|
24
|
+
ctx.cssvarResolvedValues[varName] = val;
|
|
25
|
+
return val;
|
|
26
|
+
}
|
|
27
|
+
// Check cssvarDefinedArr (contextual variables)
|
|
28
|
+
if (ctx.cssvarDefinedArr[varName] && ctx.cssvarDefinedArr[varName].length > 0) {
|
|
29
|
+
// Get the most specific definition (prefer global scope)
|
|
30
|
+
const definitions = ctx.cssvarDefinedArr[varName];
|
|
31
|
+
let bestDef = null;
|
|
32
|
+
for (const def of definitions) {
|
|
33
|
+
if (!bestDef || def.source === 'stylesheet') {
|
|
34
|
+
bestDef = def;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (bestDef) {
|
|
38
|
+
let val = bestDef.value.replace(/;$/, '').trim();
|
|
39
|
+
if (val.includes('var(')) {
|
|
40
|
+
val = this.resolveVarReferences(val, ctx, depth + 1);
|
|
41
|
+
}
|
|
42
|
+
ctx.cssvarResolvedValues[varName] = val;
|
|
43
|
+
return val;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Replace all var(--xxx) references in a value string with their resolved values.
|
|
50
|
+
* Handles fallback values like var(--primary, #000).
|
|
51
|
+
*/
|
|
52
|
+
resolveVarReferences(value, ctx, depth = 0) {
|
|
53
|
+
if (depth > 10)
|
|
54
|
+
return value;
|
|
55
|
+
return value.replace(/var\(\s*(--[a-zA-Z0-9_-]+)(?:\s*,\s*([^)]+))?\s*\)/g, (_match, varName, fallback) => {
|
|
56
|
+
const resolved = this.resolveVar(varName, ctx, depth);
|
|
57
|
+
if (resolved !== null)
|
|
58
|
+
return resolved;
|
|
59
|
+
if (fallback) {
|
|
60
|
+
// Fallback may also contain var() references
|
|
61
|
+
if (fallback.includes('var(')) {
|
|
62
|
+
return this.resolveVarReferences(fallback.trim(), ctx, depth + 1);
|
|
63
|
+
}
|
|
64
|
+
return fallback.trim();
|
|
65
|
+
}
|
|
66
|
+
return _match; // Return original if unresolvable
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Generate CSS text for all used CSS variables that need to be defined.
|
|
71
|
+
* Creates a :root block with the variable definitions that were used.
|
|
72
|
+
*/
|
|
73
|
+
generateVariablesCss(ctx) {
|
|
74
|
+
if (ctx.cssvarUsedArr.length === 0)
|
|
75
|
+
return '';
|
|
76
|
+
const lines = [];
|
|
77
|
+
const addedVars = new Set();
|
|
78
|
+
for (const varName of ctx.cssvarUsedArr) {
|
|
79
|
+
if (addedVars.has(varName))
|
|
80
|
+
continue;
|
|
81
|
+
const resolved = this.resolveVar(varName, ctx);
|
|
82
|
+
if (resolved !== null) {
|
|
83
|
+
lines.push(` ${varName}: ${resolved};`);
|
|
84
|
+
addedVars.add(varName);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (lines.length === 0)
|
|
88
|
+
return '';
|
|
89
|
+
return `:root {\n${lines.join('\n')}\n}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get all resolved variables as a map.
|
|
93
|
+
*/
|
|
94
|
+
getResolvedVariables(ctx) {
|
|
95
|
+
const resolved = {};
|
|
96
|
+
for (const varName of ctx.cssvarUsedArr) {
|
|
97
|
+
const val = this.resolveVar(varName, ctx);
|
|
98
|
+
if (val !== null) {
|
|
99
|
+
resolved[varName] = val;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return resolved;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=css-variable-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-variable-resolver.js","sourceRoot":"","sources":["../../src/extraction/css-variable-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { LabelResult } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Labels DOM elements with unique snipcss marker classes.
|
|
5
|
+
* Replaces the content script's snipcssLabelSubelements function.
|
|
6
|
+
* Runs entirely via page.evaluate() - no content script needed.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DomLabeler {
|
|
9
|
+
/**
|
|
10
|
+
* Label the target element and all its descendants with unique snipcss classes.
|
|
11
|
+
* Returns the list of classnames and the HTML.
|
|
12
|
+
*
|
|
13
|
+
* Port of snipcssLabelSubelements from sniptools.js
|
|
14
|
+
*/
|
|
15
|
+
labelElements(page: Page, selector: string): Promise<LabelResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Remove all snipcss marker classes from the page DOM.
|
|
18
|
+
* Called after extraction is complete.
|
|
19
|
+
*/
|
|
20
|
+
removeLabels(page: Page): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the outerHTML of an element after labels have been removed.
|
|
23
|
+
*/
|
|
24
|
+
getCleanHtml(page: Page, selector: string): Promise<string>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dom-labeler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-labeler.d.ts","sourceRoot":"","sources":["../../src/extraction/dom-labeler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD;;;;GAIG;AACH,qBAAa,UAAU;IACrB;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqEvE;;;OAGG;IACG,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7C;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkClE"}
|