@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,200 @@
|
|
|
1
|
+
import { ExtractionContext, } from '../types/index.js';
|
|
2
|
+
import { ViewportManager } from '../browser/viewport-manager.js';
|
|
3
|
+
import { StylesheetCollector } from './stylesheet-collector.js';
|
|
4
|
+
import { DomLabeler } from './dom-labeler.js';
|
|
5
|
+
import { StyleMatcher } from './style-matcher.js';
|
|
6
|
+
import { PseudoStateHandler } from './pseudo-state-handler.js';
|
|
7
|
+
import { KeyframeCollector } from './keyframe-collector.js';
|
|
8
|
+
import { FontCollector } from './font-collector.js';
|
|
9
|
+
import { CssVariableResolver } from './css-variable-resolver.js';
|
|
10
|
+
import { SelectorFixer } from './selector-fixer.js';
|
|
11
|
+
import { RuleDeduplicator } from './rule-deduplicator.js';
|
|
12
|
+
import { ResultBuilder } from './result-builder.js';
|
|
13
|
+
import { removeExtraAttributes } from './html-cleaner.js';
|
|
14
|
+
import { getTailwindHtml, getTailwindBodyClasses } from '../tailwind/tailwind-converter.js';
|
|
15
|
+
const BATCH_SIZE = 5; // Number of elements to process in parallel
|
|
16
|
+
/**
|
|
17
|
+
* Main extraction pipeline orchestrator.
|
|
18
|
+
* Replaces the doSnipper() function from snipbackground.js.
|
|
19
|
+
*/
|
|
20
|
+
export class ExtractionPipeline {
|
|
21
|
+
browserManager;
|
|
22
|
+
viewportManager = new ViewportManager();
|
|
23
|
+
stylesheetCollector = new StylesheetCollector();
|
|
24
|
+
domLabeler = new DomLabeler();
|
|
25
|
+
styleMatcher = new StyleMatcher();
|
|
26
|
+
pseudoStateHandler = new PseudoStateHandler();
|
|
27
|
+
keyframeCollector = new KeyframeCollector();
|
|
28
|
+
fontCollector = new FontCollector();
|
|
29
|
+
variableResolver = new CssVariableResolver();
|
|
30
|
+
selectorFixer = new SelectorFixer();
|
|
31
|
+
ruleDeduplicator = new RuleDeduplicator();
|
|
32
|
+
resultBuilder = new ResultBuilder();
|
|
33
|
+
constructor(browserManager) {
|
|
34
|
+
this.browserManager = browserManager;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extract CSS from a page element and optionally convert to Tailwind.
|
|
38
|
+
*/
|
|
39
|
+
async extract(url, selector, options = {}) {
|
|
40
|
+
const ctx = new ExtractionContext();
|
|
41
|
+
ctx.siteUrl = url;
|
|
42
|
+
const resolveVariables = options.resolveVariables !== false;
|
|
43
|
+
const includeHoverStates = options.includeHoverStates !== false;
|
|
44
|
+
const doRemoveClasses = options.removeUnusedClasses ?? true;
|
|
45
|
+
const doRemoveAttrs = options.removeUnusedAttributes ?? true;
|
|
46
|
+
const viewportOption = options.viewport || 'all';
|
|
47
|
+
let bp = null;
|
|
48
|
+
try {
|
|
49
|
+
// STEP 1: Create page and CDP session
|
|
50
|
+
bp = await this.browserManager.createPage(url);
|
|
51
|
+
const { page, cdp } = bp;
|
|
52
|
+
// STEP 2: Start collecting stylesheets
|
|
53
|
+
await this.stylesheetCollector.startCollecting(cdp);
|
|
54
|
+
// Wait a moment for stylesheets to be collected
|
|
55
|
+
await page.waitForLoadState('networkidle');
|
|
56
|
+
// STEP 3: Get DOM document
|
|
57
|
+
const doc = await cdp.send('DOM.getDocument');
|
|
58
|
+
const docRootNodeId = doc.root.nodeId;
|
|
59
|
+
// STEP 4: Stop collecting and get stylesheets
|
|
60
|
+
const stylesheets = this.stylesheetCollector.stopCollecting();
|
|
61
|
+
ctx.stylesheetArr = stylesheets;
|
|
62
|
+
// STEP 5: Label elements in the DOM
|
|
63
|
+
const labelResult = await this.domLabeler.labelElements(page, selector);
|
|
64
|
+
ctx.allClassnamesArr = labelResult.allClassnamesArr;
|
|
65
|
+
console.log(`Labeled ${labelResult.allClassnamesArr.length} elements`);
|
|
66
|
+
// STEP 6: Parse fonts and CSS variables from stylesheets
|
|
67
|
+
await this.fontCollector.collectAll(cdp, stylesheets, url, ctx);
|
|
68
|
+
// STEP 7: Determine viewports to process
|
|
69
|
+
const viewports = this.viewportManager.getViewportsForOption(viewportOption, options.customWidth);
|
|
70
|
+
// STEP 8: For each viewport, extract matched styles
|
|
71
|
+
for (const viewport of viewports) {
|
|
72
|
+
console.log(`Processing viewport: ${viewport.name} (${viewport.width}x${viewport.height})`);
|
|
73
|
+
// Set viewport (skip for default)
|
|
74
|
+
if (viewport.name !== 'default') {
|
|
75
|
+
await this.viewportManager.setViewport(cdp, viewport);
|
|
76
|
+
// Wait for layout to stabilize
|
|
77
|
+
await page.waitForTimeout(500);
|
|
78
|
+
}
|
|
79
|
+
// Refresh DOM document after viewport change
|
|
80
|
+
const vpDoc = await cdp.send('DOM.getDocument');
|
|
81
|
+
// Process elements in batches for parallelization
|
|
82
|
+
// NOTE: getMatchedStylesForNode is parallelizable, but
|
|
83
|
+
// forcePseudoState is NOT (it mutates global state)
|
|
84
|
+
for (let i = 0; i < ctx.allClassnamesArr.length; i += BATCH_SIZE) {
|
|
85
|
+
const batch = ctx.allClassnamesArr.slice(i, i + BATCH_SIZE);
|
|
86
|
+
// Parallel: Get matched styles for batch
|
|
87
|
+
const batchResults = await Promise.all(batch.map(async (classname) => {
|
|
88
|
+
try {
|
|
89
|
+
// Query DOM for the element
|
|
90
|
+
const node = await cdp.send('DOM.querySelector', {
|
|
91
|
+
nodeId: vpDoc.root.nodeId,
|
|
92
|
+
selector: '.' + classname,
|
|
93
|
+
});
|
|
94
|
+
if (!node.nodeId || node.nodeId === 0) {
|
|
95
|
+
console.log(`Element not found: .${classname}`);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// Get matched styles (THE core CDP call)
|
|
99
|
+
const allMatchedStyles = await this.styleMatcher.getMatchedStyles(cdp, node.nodeId);
|
|
100
|
+
return { classname, nodeId: node.nodeId, allMatchedStyles };
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.error(`Error matching styles for .${classname}:`, e);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}));
|
|
107
|
+
// Process results (sequential for state-dependent operations)
|
|
108
|
+
for (const result of batchResults) {
|
|
109
|
+
if (!result)
|
|
110
|
+
continue;
|
|
111
|
+
const { classname, nodeId, allMatchedStyles } = result;
|
|
112
|
+
// Process matched rules
|
|
113
|
+
const matchedRules = this.styleMatcher.processMatchedStyles(allMatchedStyles, classname, ctx, { resolveVariables, mediaQueriesOnly: viewport.name !== 'default' && viewport.name.startsWith('custom') });
|
|
114
|
+
// Extract CSS variables
|
|
115
|
+
this.styleMatcher.extractCssVariables(matchedRules, classname, ctx);
|
|
116
|
+
// Collect keyframes
|
|
117
|
+
this.keyframeCollector.collect(allMatchedStyles, ctx);
|
|
118
|
+
// Convert to SnippedRules and add (deduplicated)
|
|
119
|
+
for (const ruleMatch of matchedRules) {
|
|
120
|
+
const snippedRule = this.styleMatcher.toSnippedRule(ruleMatch, classname, viewport.name, ctx);
|
|
121
|
+
if (snippedRule) {
|
|
122
|
+
this.ruleDeduplicator.addRule(snippedRule, ctx);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Sequential: Extract hover/checked styles (mutates page state)
|
|
127
|
+
if (includeHoverStates) {
|
|
128
|
+
for (const result of batchResults) {
|
|
129
|
+
if (!result)
|
|
130
|
+
continue;
|
|
131
|
+
const { classname, nodeId } = result;
|
|
132
|
+
// Hover styles
|
|
133
|
+
const hoverRules = await this.pseudoStateHandler.extractHoverStyles(cdp, page, nodeId, classname, vpDoc.root.nodeId);
|
|
134
|
+
for (const ruleMatch of hoverRules) {
|
|
135
|
+
const snippedRule = this.styleMatcher.toSnippedRule(ruleMatch, classname, viewport.name, ctx);
|
|
136
|
+
if (snippedRule) {
|
|
137
|
+
snippedRule.is_hover = true;
|
|
138
|
+
this.ruleDeduplicator.addRule(snippedRule, ctx);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Checked styles (for checkboxes/radios)
|
|
142
|
+
const checkedRules = await this.pseudoStateHandler.extractCheckedStyles(cdp, page, nodeId, classname, vpDoc.root.nodeId);
|
|
143
|
+
for (const ruleMatch of checkedRules) {
|
|
144
|
+
const snippedRule = this.styleMatcher.toSnippedRule(ruleMatch, classname, viewport.name, ctx);
|
|
145
|
+
if (snippedRule) {
|
|
146
|
+
this.ruleDeduplicator.addRule(snippedRule, ctx);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Reset viewport
|
|
153
|
+
if (viewport.name !== 'default') {
|
|
154
|
+
await this.viewportManager.clearViewport(cdp);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
console.log(`Extracted ${ctx.snippedArr.length} CSS rules`);
|
|
158
|
+
// STEP 9: Build final result
|
|
159
|
+
const result = this.resultBuilder.buildResult(ctx, labelResult.allElementOuterHtml, {
|
|
160
|
+
resolveVariables,
|
|
161
|
+
});
|
|
162
|
+
// STEP 10: Tailwind conversion
|
|
163
|
+
try {
|
|
164
|
+
const labeledHtml = labelResult.allElementOuterHtml;
|
|
165
|
+
result.tailwindHtml = getTailwindHtml(labeledHtml, result.css, ctx.snippedArr, false, // forceBreakpoints
|
|
166
|
+
resolveVariables, ctx);
|
|
167
|
+
result.tailwindBodyClasses = getTailwindBodyClasses(ctx.snippedArr, false, resolveVariables, [], // tailwindUltimateArr - populated inside getTailwindBodyClasses
|
|
168
|
+
ctx);
|
|
169
|
+
}
|
|
170
|
+
catch (e) {
|
|
171
|
+
console.error('Tailwind conversion error:', e);
|
|
172
|
+
// Non-fatal: CSS output is still valid
|
|
173
|
+
}
|
|
174
|
+
// STEP 11: Get clean HTML (without marker classes)
|
|
175
|
+
result.html = await this.domLabeler.getCleanHtml(page, selector);
|
|
176
|
+
// STEP 12: Remove unused attributes and classes from HTML
|
|
177
|
+
if (doRemoveClasses || doRemoveAttrs) {
|
|
178
|
+
const cleanOpts = {
|
|
179
|
+
removeUnusedClasses: doRemoveClasses,
|
|
180
|
+
removeUnusedAttributes: doRemoveAttrs,
|
|
181
|
+
keepTailwindLabels: false,
|
|
182
|
+
};
|
|
183
|
+
result.html = removeExtraAttributes(result.html, ctx.snippedArr, cleanOpts);
|
|
184
|
+
if (result.tailwindHtml) {
|
|
185
|
+
result.tailwindHtml = removeExtraAttributes(result.tailwindHtml, ctx.snippedArr, { ...cleanOpts, keepTailwindLabels: true });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// STEP 13: Remove labels from DOM
|
|
189
|
+
await this.domLabeler.removeLabels(page);
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
// Cleanup
|
|
194
|
+
if (bp) {
|
|
195
|
+
await this.browserManager.closePage(bp);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=extraction-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-pipeline.js","sourceRoot":"","sources":["../../src/extraction/extraction-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CDPSession } from 'playwright';
|
|
2
|
+
import { FontData, StylesheetInfo, ExtractionContext } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses @font-face declarations and CSS variables from stylesheets.
|
|
5
|
+
* Port of snipbackground.js:1343-1627
|
|
6
|
+
*/
|
|
7
|
+
export declare class FontCollector {
|
|
8
|
+
/**
|
|
9
|
+
* Parse @font-face rules from stylesheet text.
|
|
10
|
+
*/
|
|
11
|
+
parseFontFaces(cssText: string, baseUrl: string): FontData[];
|
|
12
|
+
/**
|
|
13
|
+
* Extract Google Font imports from stylesheet text.
|
|
14
|
+
*/
|
|
15
|
+
parseGoogleFontImports(cssText: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Extract global CSS variables from stylesheet text.
|
|
18
|
+
* Looks for :root, :host, *, html, body selectors.
|
|
19
|
+
*/
|
|
20
|
+
parseGlobalCssVariables(cssText: string, ctx: ExtractionContext): void;
|
|
21
|
+
/**
|
|
22
|
+
* Collect all font data and CSS variables from all stylesheets.
|
|
23
|
+
*/
|
|
24
|
+
collectAll(cdp: CDPSession, stylesheets: StylesheetInfo[], siteUrl: string, ctx: ExtractionContext): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=font-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-collector.d.ts","sourceRoot":"","sources":["../../src/extraction/font-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAGlG;;;GAGG;AACH,qBAAa,aAAa;IACxB;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE;IA6D5D;;OAEG;IACH,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAcjD;;;OAGG;IACH,uBAAuB,CACrB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,iBAAiB,GACrB,IAAI;IA0CP;;OAEG;IACG,UAAU,CACd,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,IAAI,CAAC;CAqDjB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { resolveUrl } from '../utils/helpers.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses @font-face declarations and CSS variables from stylesheets.
|
|
4
|
+
* Port of snipbackground.js:1343-1627
|
|
5
|
+
*/
|
|
6
|
+
export class FontCollector {
|
|
7
|
+
/**
|
|
8
|
+
* Parse @font-face rules from stylesheet text.
|
|
9
|
+
*/
|
|
10
|
+
parseFontFaces(cssText, baseUrl) {
|
|
11
|
+
const fonts = [];
|
|
12
|
+
// Regex to find @font-face blocks
|
|
13
|
+
const fontFaceRegex = /@font-face\s*\{([^}]+)\}/gi;
|
|
14
|
+
let match;
|
|
15
|
+
while ((match = fontFaceRegex.exec(cssText)) !== null) {
|
|
16
|
+
const block = match[1];
|
|
17
|
+
const font = {
|
|
18
|
+
font_family: '',
|
|
19
|
+
font_url: '',
|
|
20
|
+
full_rule: '@font-face {' + block + '}',
|
|
21
|
+
};
|
|
22
|
+
// Extract font-family
|
|
23
|
+
const familyMatch = block.match(/font-family\s*:\s*(['"]?)([^;'"]+)\1/i);
|
|
24
|
+
if (familyMatch) {
|
|
25
|
+
font.font_family = familyMatch[2].trim();
|
|
26
|
+
}
|
|
27
|
+
// Extract src URLs
|
|
28
|
+
const srcMatch = block.match(/src\s*:\s*([^;]+)/i);
|
|
29
|
+
if (srcMatch) {
|
|
30
|
+
const urlMatch = srcMatch[1].match(/url\(['"]?([^'")\s]+)['"]?\)/);
|
|
31
|
+
if (urlMatch) {
|
|
32
|
+
font.font_url = resolveUrl(urlMatch[1], baseUrl);
|
|
33
|
+
}
|
|
34
|
+
// Extract format
|
|
35
|
+
const formatMatch = srcMatch[1].match(/format\(['"]?([^'")\s]+)['"]?\)/);
|
|
36
|
+
if (formatMatch) {
|
|
37
|
+
font.font_format = formatMatch[1];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Extract font-weight
|
|
41
|
+
const weightMatch = block.match(/font-weight\s*:\s*([^;]+)/i);
|
|
42
|
+
if (weightMatch) {
|
|
43
|
+
font.font_weight = weightMatch[1].trim();
|
|
44
|
+
}
|
|
45
|
+
// Extract font-style
|
|
46
|
+
const styleMatch = block.match(/font-style\s*:\s*([^;]+)/i);
|
|
47
|
+
if (styleMatch) {
|
|
48
|
+
font.font_style = styleMatch[1].trim();
|
|
49
|
+
}
|
|
50
|
+
// Extract font-display
|
|
51
|
+
const displayMatch = block.match(/font-display\s*:\s*([^;]+)/i);
|
|
52
|
+
if (displayMatch) {
|
|
53
|
+
font.font_display = displayMatch[1].trim();
|
|
54
|
+
}
|
|
55
|
+
if (font.font_family) {
|
|
56
|
+
fonts.push(font);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return fonts;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extract Google Font imports from stylesheet text.
|
|
63
|
+
*/
|
|
64
|
+
parseGoogleFontImports(cssText) {
|
|
65
|
+
const imports = [];
|
|
66
|
+
const importRegex = /@import\s+url\(['"]?(https?:\/\/fonts\.googleapis\.com[^'")\s]+)['"]?\)/gi;
|
|
67
|
+
let match;
|
|
68
|
+
while ((match = importRegex.exec(cssText)) !== null) {
|
|
69
|
+
if (!imports.includes(match[1])) {
|
|
70
|
+
imports.push(match[1]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return imports;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Extract global CSS variables from stylesheet text.
|
|
77
|
+
* Looks for :root, :host, *, html, body selectors.
|
|
78
|
+
*/
|
|
79
|
+
parseGlobalCssVariables(cssText, ctx) {
|
|
80
|
+
// Match :root, :host, *, html, body blocks
|
|
81
|
+
const globalBlockRegex = /(?::root|:host|\*|html|body)\s*\{([^}]+)\}/gi;
|
|
82
|
+
let match;
|
|
83
|
+
while ((match = globalBlockRegex.exec(cssText)) !== null) {
|
|
84
|
+
const block = match[1];
|
|
85
|
+
const selector = match[0].split('{')[0].trim();
|
|
86
|
+
// Find all --var declarations
|
|
87
|
+
const varRegex = /(--[a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;
|
|
88
|
+
let varMatch;
|
|
89
|
+
while ((varMatch = varRegex.exec(block)) !== null) {
|
|
90
|
+
const prop = varMatch[1];
|
|
91
|
+
const val = varMatch[2].trim();
|
|
92
|
+
ctx.cssvarAllArr[prop] = val + ';';
|
|
93
|
+
if (!ctx.cssvarDefinedArr[prop]) {
|
|
94
|
+
ctx.cssvarDefinedArr[prop] = [];
|
|
95
|
+
}
|
|
96
|
+
const globalKey = `__global__${selector}${prop}`;
|
|
97
|
+
const exists = ctx.cssvarDefinedArr[prop].some((item) => item.key === globalKey);
|
|
98
|
+
if (!exists) {
|
|
99
|
+
ctx.cssvarDefinedArr[prop].push({
|
|
100
|
+
key: globalKey,
|
|
101
|
+
label: '__global__',
|
|
102
|
+
value: val,
|
|
103
|
+
media: '',
|
|
104
|
+
selector,
|
|
105
|
+
source: 'stylesheet',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Collect all font data and CSS variables from all stylesheets.
|
|
113
|
+
*/
|
|
114
|
+
async collectAll(cdp, stylesheets, siteUrl, ctx) {
|
|
115
|
+
// Fetch all stylesheet texts in parallel
|
|
116
|
+
const results = await Promise.all(stylesheets
|
|
117
|
+
.filter(ss => ss.origin !== 'user-agent')
|
|
118
|
+
.map(async (ss) => {
|
|
119
|
+
try {
|
|
120
|
+
const result = await cdp.send('CSS.getStyleSheetText', {
|
|
121
|
+
styleSheetId: ss.stylesheet_id,
|
|
122
|
+
});
|
|
123
|
+
return { ss, text: result.text || '' };
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return { ss, text: '' };
|
|
127
|
+
}
|
|
128
|
+
}));
|
|
129
|
+
for (const { ss, text } of results) {
|
|
130
|
+
if (!text)
|
|
131
|
+
continue;
|
|
132
|
+
const baseUrl = ss.source_url || siteUrl;
|
|
133
|
+
// Parse @font-face rules
|
|
134
|
+
if (text.includes('@font-face')) {
|
|
135
|
+
const fonts = this.parseFontFaces(text, baseUrl);
|
|
136
|
+
for (const font of fonts) {
|
|
137
|
+
// Deduplicate by font_family + font_weight + font_style
|
|
138
|
+
const exists = ctx.customfontsArr.some((f) => f.font_family === font.font_family &&
|
|
139
|
+
f.font_weight === font.font_weight &&
|
|
140
|
+
f.font_style === font.font_style);
|
|
141
|
+
if (!exists) {
|
|
142
|
+
ctx.customfontsArr.push(font);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Parse Google Font imports
|
|
147
|
+
const imports = this.parseGoogleFontImports(text);
|
|
148
|
+
for (const imp of imports) {
|
|
149
|
+
if (!ctx.importfontsArr.includes(imp)) {
|
|
150
|
+
ctx.importfontsArr.push(imp);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Parse global CSS variables
|
|
154
|
+
if (text.includes('--')) {
|
|
155
|
+
this.parseGlobalCssVariables(text, ctx);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=font-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-collector.js","sourceRoot":"","sources":["../../src/extraction/font-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SnippedRule } from '../types/index.js';
|
|
2
|
+
export interface CleanupOptions {
|
|
3
|
+
removeUnusedClasses?: boolean;
|
|
4
|
+
removeUnusedAttributes?: boolean;
|
|
5
|
+
keepTailwindLabels?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Remove unused attributes and CSS classes from extracted HTML.
|
|
9
|
+
*
|
|
10
|
+
* @param html The extracted HTML string
|
|
11
|
+
* @param snippedArr The array of extracted CSS rules
|
|
12
|
+
* @param options What to clean up
|
|
13
|
+
* @returns Cleaned HTML string
|
|
14
|
+
*/
|
|
15
|
+
export declare function removeExtraAttributes(html: string, snippedArr: SnippedRule[], options?: CleanupOptions): string;
|
|
16
|
+
//# sourceMappingURL=html-cleaner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-cleaner.d.ts","sourceRoot":"","sources":["../../src/extraction/html-cleaner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA8CrD,MAAM,WAAW,cAAc;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,WAAW,EAAE,EACzB,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAoGR"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removes unused attributes and CSS classes from extracted HTML.
|
|
3
|
+
* Port of removeExtraAttributes() from snipbackground.js:5613-5800
|
|
4
|
+
*/
|
|
5
|
+
import * as cheerio from 'cheerio';
|
|
6
|
+
const KEEP_ATTRS = new Set([
|
|
7
|
+
'align', 'for', 'type', 'value', 'valign', 'bgcolor', 'background',
|
|
8
|
+
'width', 'height', 'style', 'src', 'href', 'source', 'dir', 'viewbox',
|
|
9
|
+
'xmlns', 'placeholder', 'd', 'colspan', 'rowspan', 'span', 'headers',
|
|
10
|
+
'scope', 'alt', 'title', 'role', 'aria-label', 'aria-hidden',
|
|
11
|
+
'loading', 'decoding', 'srcset', 'sizes', 'media', 'rel', 'target',
|
|
12
|
+
'action', 'method', 'enctype', 'name',
|
|
13
|
+
]);
|
|
14
|
+
const SVG_TAGS = new Set([
|
|
15
|
+
'path', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'svg',
|
|
16
|
+
'g', 'defs', 'use', 'symbol', 'clippath', 'mask', 'filter',
|
|
17
|
+
]);
|
|
18
|
+
const FORM_TAGS = new Set(['input', 'select', 'meter', 'progress', 'textarea', 'label']);
|
|
19
|
+
const ICON_PREFIXES = [
|
|
20
|
+
'fa-', 'fa ', 'fas ', 'far ', 'fab ', 'fal ', 'fad ',
|
|
21
|
+
'bi-', 'bi ',
|
|
22
|
+
'icon-', 'icon ',
|
|
23
|
+
'ti-', 'ti ',
|
|
24
|
+
'material-icons',
|
|
25
|
+
'glyphicon',
|
|
26
|
+
];
|
|
27
|
+
function isIconFontClass(cls) {
|
|
28
|
+
const lower = cls.toLowerCase();
|
|
29
|
+
return ICON_PREFIXES.some(p => lower.startsWith(p)) || lower === 'fa';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Extract the base class name for selector matching.
|
|
33
|
+
* Strips pseudo-selectors, escapes, brackets, dots.
|
|
34
|
+
*/
|
|
35
|
+
function baseClassName(cls) {
|
|
36
|
+
let base = cls;
|
|
37
|
+
if (base.includes(':'))
|
|
38
|
+
base = base.split(':')[0];
|
|
39
|
+
if (base.includes('\\'))
|
|
40
|
+
base = base.split('\\')[0];
|
|
41
|
+
if (base.includes('/'))
|
|
42
|
+
base = base.split('/')[0];
|
|
43
|
+
if (base.includes('['))
|
|
44
|
+
base = base.split('[')[0];
|
|
45
|
+
if (base.includes('.'))
|
|
46
|
+
base = base.split('.')[0];
|
|
47
|
+
return base.trim();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Remove unused attributes and CSS classes from extracted HTML.
|
|
51
|
+
*
|
|
52
|
+
* @param html The extracted HTML string
|
|
53
|
+
* @param snippedArr The array of extracted CSS rules
|
|
54
|
+
* @param options What to clean up
|
|
55
|
+
* @returns Cleaned HTML string
|
|
56
|
+
*/
|
|
57
|
+
export function removeExtraAttributes(html, snippedArr, options = {}) {
|
|
58
|
+
const { removeUnusedClasses = true, removeUnusedAttributes = true, keepTailwindLabels = false, } = options;
|
|
59
|
+
if (!removeUnusedClasses && !removeUnusedAttributes)
|
|
60
|
+
return html;
|
|
61
|
+
// Collect all selectors for matching
|
|
62
|
+
const allSelectors = snippedArr.map(r => r.selector);
|
|
63
|
+
const $ = cheerio.load(html, { xml: { xmlMode: false, decodeEntities: false } }, false);
|
|
64
|
+
// Remove HTML comments
|
|
65
|
+
$.root().find('*').contents().filter((_i, node) => node.type === 'comment').remove();
|
|
66
|
+
// Also remove top-level comments
|
|
67
|
+
$.root().contents().filter((_i, node) => node.type === 'comment').remove();
|
|
68
|
+
$.root().find('*').each((_i, elem) => {
|
|
69
|
+
if (elem.type !== 'tag')
|
|
70
|
+
return;
|
|
71
|
+
const el = elem;
|
|
72
|
+
const tagName = (el.tagName || el.name || '').toLowerCase();
|
|
73
|
+
if (!tagName)
|
|
74
|
+
return;
|
|
75
|
+
// Skip SVG elements
|
|
76
|
+
if (SVG_TAGS.has(tagName))
|
|
77
|
+
return;
|
|
78
|
+
const attribs = el.attribs || {};
|
|
79
|
+
for (const attrName of Object.keys(attribs)) {
|
|
80
|
+
const lowerAttr = attrName.toLowerCase();
|
|
81
|
+
// Always keep essential attributes
|
|
82
|
+
if (KEEP_ATTRS.has(lowerAttr))
|
|
83
|
+
continue;
|
|
84
|
+
// Handle data-* attributes
|
|
85
|
+
if (lowerAttr.startsWith('data')) {
|
|
86
|
+
if (!removeUnusedAttributes)
|
|
87
|
+
continue;
|
|
88
|
+
// Keep if any selector references this attribute
|
|
89
|
+
const inSelector = allSelectors.some(s => s.includes(attrName));
|
|
90
|
+
if (inSelector)
|
|
91
|
+
continue;
|
|
92
|
+
// Remove it
|
|
93
|
+
$(elem).removeAttr(attrName);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Handle class attribute
|
|
97
|
+
if (lowerAttr === 'class') {
|
|
98
|
+
if (!removeUnusedClasses)
|
|
99
|
+
continue;
|
|
100
|
+
// In Tailwind mode, don't touch classes - they're utility classes, not CSS selectors
|
|
101
|
+
if (keepTailwindLabels)
|
|
102
|
+
continue;
|
|
103
|
+
const classList = (attribs[attrName] || '').split(/\s+/).filter(Boolean);
|
|
104
|
+
const removeList = [];
|
|
105
|
+
for (const cls of classList) {
|
|
106
|
+
// Keep icon font classes
|
|
107
|
+
if (isIconFontClass(cls))
|
|
108
|
+
continue;
|
|
109
|
+
const base = baseClassName(cls);
|
|
110
|
+
if (base === '')
|
|
111
|
+
continue;
|
|
112
|
+
// Check if this class appears in any selector
|
|
113
|
+
const found = allSelectors.some(s => s.includes(base));
|
|
114
|
+
if (!found) {
|
|
115
|
+
removeList.push(cls);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const cls of removeList) {
|
|
119
|
+
$(elem).removeClass(cls);
|
|
120
|
+
}
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
// Handle id and name
|
|
124
|
+
if (lowerAttr === 'id' || lowerAttr === 'name') {
|
|
125
|
+
if (!removeUnusedAttributes)
|
|
126
|
+
continue;
|
|
127
|
+
// Keep on form elements
|
|
128
|
+
if (FORM_TAGS.has(tagName))
|
|
129
|
+
continue;
|
|
130
|
+
// Keep if any selector references this value
|
|
131
|
+
const attrVal = attribs[attrName];
|
|
132
|
+
const inSelector = allSelectors.some(s => s.includes(attrVal));
|
|
133
|
+
if (inSelector)
|
|
134
|
+
continue;
|
|
135
|
+
$(elem).removeAttr(attrName);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// All other non-essential attributes
|
|
139
|
+
if (removeUnusedAttributes) {
|
|
140
|
+
$(elem).removeAttr(attrName);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
let result = $.root().html() || '';
|
|
145
|
+
// Clean up empty class attributes
|
|
146
|
+
result = result.replace(/\s*class=""\s*/g, ' ').replace(/\s+>/g, '>');
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=html-cleaner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-cleaner.js","sourceRoot":"","sources":["../../src/extraction/html-cleaner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CDPMatchedStyles, ExtractionContext } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collects @keyframes animation rules from matched styles.
|
|
4
|
+
* Port of snipbackground.js:1997-2035
|
|
5
|
+
*/
|
|
6
|
+
export declare class KeyframeCollector {
|
|
7
|
+
/**
|
|
8
|
+
* Extract keyframe animations from matched styles.
|
|
9
|
+
*/
|
|
10
|
+
collect(allMatchedStyles: CDPMatchedStyles, ctx: ExtractionContext): void;
|
|
11
|
+
/**
|
|
12
|
+
* Generate CSS text for all collected keyframes.
|
|
13
|
+
*/
|
|
14
|
+
generateCss(ctx: ExtractionContext): string;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=keyframe-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyframe-collector.d.ts","sourceRoot":"","sources":["../../src/extraction/keyframe-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,OAAO,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,IAAI;IAuCzE;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM;CAgB5C"}
|