@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.
Files changed (117) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/.claude-plugin/plugin.json +10 -0
  3. package/.mcp.json +8 -0
  4. package/dist/auth/config-manager.d.ts +13 -0
  5. package/dist/auth/config-manager.d.ts.map +1 -0
  6. package/dist/auth/config-manager.js +48 -0
  7. package/dist/auth/config-manager.js.map +1 -0
  8. package/dist/auth/usage-gate.d.ts +13 -0
  9. package/dist/auth/usage-gate.d.ts.map +1 -0
  10. package/dist/auth/usage-gate.js +69 -0
  11. package/dist/auth/usage-gate.js.map +1 -0
  12. package/dist/browser/browser-manager.d.ts +15 -0
  13. package/dist/browser/browser-manager.d.ts.map +1 -0
  14. package/dist/browser/browser-manager.js +61 -0
  15. package/dist/browser/browser-manager.js.map +1 -0
  16. package/dist/browser/viewport-manager.d.ts +8 -0
  17. package/dist/browser/viewport-manager.d.ts.map +1 -0
  18. package/dist/browser/viewport-manager.js +50 -0
  19. package/dist/browser/viewport-manager.js.map +1 -0
  20. package/dist/extraction/css-variable-resolver.d.ts +27 -0
  21. package/dist/extraction/css-variable-resolver.d.ts.map +1 -0
  22. package/dist/extraction/css-variable-resolver.js +105 -0
  23. package/dist/extraction/css-variable-resolver.js.map +1 -0
  24. package/dist/extraction/dom-labeler.d.ts +26 -0
  25. package/dist/extraction/dom-labeler.d.ts.map +1 -0
  26. package/dist/extraction/dom-labeler.js +124 -0
  27. package/dist/extraction/dom-labeler.js.map +1 -0
  28. package/dist/extraction/element-discovery.d.ts +59 -0
  29. package/dist/extraction/element-discovery.d.ts.map +1 -0
  30. package/dist/extraction/element-discovery.js +525 -0
  31. package/dist/extraction/element-discovery.js.map +1 -0
  32. package/dist/extraction/extraction-pipeline.d.ts +26 -0
  33. package/dist/extraction/extraction-pipeline.d.ts.map +1 -0
  34. package/dist/extraction/extraction-pipeline.js +200 -0
  35. package/dist/extraction/extraction-pipeline.js.map +1 -0
  36. package/dist/extraction/font-collector.d.ts +26 -0
  37. package/dist/extraction/font-collector.d.ts.map +1 -0
  38. package/dist/extraction/font-collector.js +160 -0
  39. package/dist/extraction/font-collector.js.map +1 -0
  40. package/dist/extraction/html-cleaner.d.ts +16 -0
  41. package/dist/extraction/html-cleaner.d.ts.map +1 -0
  42. package/dist/extraction/html-cleaner.js +149 -0
  43. package/dist/extraction/html-cleaner.js.map +1 -0
  44. package/dist/extraction/keyframe-collector.d.ts +16 -0
  45. package/dist/extraction/keyframe-collector.d.ts.map +1 -0
  46. package/dist/extraction/keyframe-collector.js +62 -0
  47. package/dist/extraction/keyframe-collector.js.map +1 -0
  48. package/dist/extraction/pseudo-state-handler.d.ts +36 -0
  49. package/dist/extraction/pseudo-state-handler.d.ts.map +1 -0
  50. package/dist/extraction/pseudo-state-handler.js +210 -0
  51. package/dist/extraction/pseudo-state-handler.js.map +1 -0
  52. package/dist/extraction/result-builder.d.ts +25 -0
  53. package/dist/extraction/result-builder.d.ts.map +1 -0
  54. package/dist/extraction/result-builder.js +136 -0
  55. package/dist/extraction/result-builder.js.map +1 -0
  56. package/dist/extraction/rule-deduplicator.d.ts +39 -0
  57. package/dist/extraction/rule-deduplicator.d.ts.map +1 -0
  58. package/dist/extraction/rule-deduplicator.js +107 -0
  59. package/dist/extraction/rule-deduplicator.js.map +1 -0
  60. package/dist/extraction/selector-fixer.d.ts +25 -0
  61. package/dist/extraction/selector-fixer.d.ts.map +1 -0
  62. package/dist/extraction/selector-fixer.js +111 -0
  63. package/dist/extraction/selector-fixer.js.map +1 -0
  64. package/dist/extraction/specificity.d.ts +17 -0
  65. package/dist/extraction/specificity.d.ts.map +1 -0
  66. package/dist/extraction/specificity.js +88 -0
  67. package/dist/extraction/specificity.js.map +1 -0
  68. package/dist/extraction/style-matcher.d.ts +33 -0
  69. package/dist/extraction/style-matcher.d.ts.map +1 -0
  70. package/dist/extraction/style-matcher.js +199 -0
  71. package/dist/extraction/style-matcher.js.map +1 -0
  72. package/dist/extraction/stylesheet-collector.d.ts +33 -0
  73. package/dist/extraction/stylesheet-collector.d.ts.map +1 -0
  74. package/dist/extraction/stylesheet-collector.js +71 -0
  75. package/dist/extraction/stylesheet-collector.js.map +1 -0
  76. package/dist/index.d.ts +3 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +235 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/mcp-server.d.ts +3 -0
  81. package/dist/mcp-server.d.ts.map +1 -0
  82. package/dist/mcp-server.js +349 -0
  83. package/dist/mcp-server.js.map +1 -0
  84. package/dist/tailwind/css-to-tailwind.d.ts +17 -0
  85. package/dist/tailwind/css-to-tailwind.d.ts.map +1 -0
  86. package/dist/tailwind/css-to-tailwind.js +1583 -0
  87. package/dist/tailwind/css-to-tailwind.js.map +1 -0
  88. package/dist/tailwind/shorthand-expander.d.ts +27 -0
  89. package/dist/tailwind/shorthand-expander.d.ts.map +1 -0
  90. package/dist/tailwind/shorthand-expander.js +812 -0
  91. package/dist/tailwind/shorthand-expander.js.map +1 -0
  92. package/dist/tailwind/tailwind-converter.d.ts +35 -0
  93. package/dist/tailwind/tailwind-converter.d.ts.map +1 -0
  94. package/dist/tailwind/tailwind-converter.js +1223 -0
  95. package/dist/tailwind/tailwind-converter.js.map +1 -0
  96. package/dist/tailwind/tailwind-helpers.d.ts +95 -0
  97. package/dist/tailwind/tailwind-helpers.d.ts.map +1 -0
  98. package/dist/tailwind/tailwind-helpers.js +593 -0
  99. package/dist/tailwind/tailwind-helpers.js.map +1 -0
  100. package/dist/tailwind/tailwind-reducer.d.ts +36 -0
  101. package/dist/tailwind/tailwind-reducer.d.ts.map +1 -0
  102. package/dist/tailwind/tailwind-reducer.js +189 -0
  103. package/dist/tailwind/tailwind-reducer.js.map +1 -0
  104. package/dist/types/index.d.ts +239 -0
  105. package/dist/types/index.d.ts.map +1 -0
  106. package/dist/types/index.js +94 -0
  107. package/dist/types/index.js.map +1 -0
  108. package/dist/utils/helpers.d.ts +34 -0
  109. package/dist/utils/helpers.d.ts.map +1 -0
  110. package/dist/utils/helpers.js +120 -0
  111. package/dist/utils/helpers.js.map +1 -0
  112. package/dist/utils/parsel.d.ts +41 -0
  113. package/dist/utils/parsel.d.ts.map +1 -0
  114. package/dist/utils/parsel.js +314 -0
  115. package/dist/utils/parsel.js.map +1 -0
  116. package/package.json +41 -0
  117. package/skills/workflow/SKILL.md +95 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-deduplicator.js","sourceRoot":"","sources":["../../src/extraction/rule-deduplicator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { Page } from 'playwright';
2
+ /**
3
+ * Validates and fixes CSS selectors to be scoped to the extracted element.
4
+ * Runs in page context via page.evaluate() since it needs live DOM access.
5
+ *
6
+ * Port of snipcssFixSelector from sniptools.js
7
+ */
8
+ export declare class SelectorFixer {
9
+ /**
10
+ * Fix a batch of selectors at once (reduces round-trips to the browser).
11
+ * Each selector is tested against the DOM to verify it matches within
12
+ * the extraction root.
13
+ */
14
+ fixSelectors(page: Page, selectors: string[], rootClassname: string, allClassnames: string[]): Promise<Record<string, string>>;
15
+ /**
16
+ * Check if a selector matches any element within the extraction root.
17
+ */
18
+ selectorMatchesInRoot(page: Page, selector: string, rootClassname: string): Promise<boolean>;
19
+ /**
20
+ * Get the element distance (depth) for inherited rule processing.
21
+ * Returns negative if the selector targets elements outside the root.
22
+ */
23
+ getElementDistance(page: Page, selectorClass: string, rootClassname: string): Promise<number>;
24
+ }
25
+ //# sourceMappingURL=selector-fixer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-fixer.d.ts","sourceRoot":"","sources":["../../src/extraction/selector-fixer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGlC;;;;;GAKG;AACH,qBAAa,aAAa;IACxB;;;;OAIG;IACG,YAAY,CAChB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAuDlC;;OAEG;IACG,qBAAqB,CACzB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC;IAsBnB;;;OAGG;IACG,kBAAkB,CACtB,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;CAqBnB"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Validates and fixes CSS selectors to be scoped to the extracted element.
3
+ * Runs in page context via page.evaluate() since it needs live DOM access.
4
+ *
5
+ * Port of snipcssFixSelector from sniptools.js
6
+ */
7
+ export class SelectorFixer {
8
+ /**
9
+ * Fix a batch of selectors at once (reduces round-trips to the browser).
10
+ * Each selector is tested against the DOM to verify it matches within
11
+ * the extraction root.
12
+ */
13
+ async fixSelectors(page, selectors, rootClassname, allClassnames) {
14
+ return await page.evaluate(({ selectors, rootClassname, allClassnames }) => {
15
+ const results = {};
16
+ const rootElem = document.querySelector('.' + rootClassname);
17
+ if (!rootElem)
18
+ return results;
19
+ for (const selector of selectors) {
20
+ try {
21
+ // Check if selector targets elements inside the root
22
+ const matchingElements = document.querySelectorAll(selector);
23
+ let insideRoot = false;
24
+ for (const elem of matchingElements) {
25
+ if (rootElem.contains(elem) || rootElem === elem) {
26
+ insideRoot = true;
27
+ break;
28
+ }
29
+ }
30
+ if (insideRoot) {
31
+ results[selector] = selector;
32
+ }
33
+ else {
34
+ // The selector doesn't match anything in our root -
35
+ // try to see if it matches something via descendant relation
36
+ const parts = selector.split(/\s+/);
37
+ if (parts.length > 1) {
38
+ // Take the last part as a local selector
39
+ const localPart = parts[parts.length - 1];
40
+ try {
41
+ const localMatches = rootElem.querySelectorAll(localPart);
42
+ if (localMatches.length > 0) {
43
+ results[selector] = localPart;
44
+ }
45
+ else {
46
+ results[selector] = selector;
47
+ }
48
+ }
49
+ catch {
50
+ results[selector] = selector;
51
+ }
52
+ }
53
+ else {
54
+ results[selector] = selector;
55
+ }
56
+ }
57
+ }
58
+ catch {
59
+ // Invalid selector - keep as-is
60
+ results[selector] = selector;
61
+ }
62
+ }
63
+ return results;
64
+ }, { selectors, rootClassname, allClassnames });
65
+ }
66
+ /**
67
+ * Check if a selector matches any element within the extraction root.
68
+ */
69
+ async selectorMatchesInRoot(page, selector, rootClassname) {
70
+ return await page.evaluate(({ selector, rootClassname }) => {
71
+ try {
72
+ const rootElem = document.querySelector('.' + rootClassname);
73
+ if (!rootElem)
74
+ return false;
75
+ const matchingElements = document.querySelectorAll(selector);
76
+ for (const elem of matchingElements) {
77
+ if (rootElem.contains(elem) || rootElem === elem) {
78
+ return true;
79
+ }
80
+ }
81
+ return false;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }, { selector, rootClassname });
87
+ }
88
+ /**
89
+ * Get the element distance (depth) for inherited rule processing.
90
+ * Returns negative if the selector targets elements outside the root.
91
+ */
92
+ async getElementDistance(page, selectorClass, rootClassname) {
93
+ return await page.evaluate(({ selectorClass, rootClassname }) => {
94
+ const targetElem = document.querySelector('.' + selectorClass);
95
+ const rootElem = document.querySelector('.' + rootClassname);
96
+ if (!targetElem || !rootElem)
97
+ return -1;
98
+ // Count depth from root to target
99
+ let depth = 0;
100
+ let current = targetElem;
101
+ while (current && current !== rootElem) {
102
+ depth++;
103
+ current = current.parentElement;
104
+ }
105
+ if (current === rootElem)
106
+ return depth;
107
+ return -1; // Not a descendant
108
+ }, { selectorClass, rootClassname });
109
+ }
110
+ }
111
+ //# sourceMappingURL=selector-fixer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-fixer.js","sourceRoot":"","sources":["../../src/extraction/selector-fixer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface SpecificityResult {
2
+ selector: string;
3
+ specificity: string;
4
+ specificityArray: [number, number, number, number];
5
+ parts: {
6
+ selector: string;
7
+ type: string;
8
+ index: number;
9
+ length: number;
10
+ }[];
11
+ }
12
+ export declare function calculateSingle(input: string): SpecificityResult;
13
+ /**
14
+ * Calculate a numeric specificity score from a specificity string like "0,1,2,3"
15
+ */
16
+ export declare function specificityScore(specificityStr: string): number;
17
+ //# sourceMappingURL=specificity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specificity.d.ts","sourceRoot":"","sources":["../../src/extraction/specificity.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAuFhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAG/D"}
@@ -0,0 +1,88 @@
1
+ // Port of calculateSingle from snipbackground.js:996-1124
2
+ // CSS specificity calculator
3
+ export function calculateSingle(input) {
4
+ let selector = input;
5
+ const typeCount = { a: 0, b: 0, c: 0 };
6
+ const parts = [];
7
+ const attributeRegex = /(\[[^\]]+\])/g;
8
+ const idRegex = /(#[^\#\s\+>~\.\[:\)]+)/g;
9
+ const classRegex = /(\.[^\s\+>~\.\[:\)]+)/g;
10
+ const pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
11
+ const pseudoClassWithBracketsRegex = /(:(?!not|global|local)[\w-]+\([^\)]*\))/gi;
12
+ const pseudoClassRegex = /(:(?!not|global|local)[^\s\+>~\.\[:]+)/g;
13
+ const elementRegex = /([^\s\+>~\.\[:]+)/g;
14
+ const findMatch = (regex, type) => {
15
+ if (regex.test(selector)) {
16
+ regex.lastIndex = 0;
17
+ const matches = selector.match(regex);
18
+ if (matches) {
19
+ for (const match of matches) {
20
+ typeCount[type] += 1;
21
+ const index = selector.indexOf(match);
22
+ const length = match.length;
23
+ parts.push({
24
+ selector: input.substr(index, length),
25
+ type,
26
+ index,
27
+ length,
28
+ });
29
+ selector = selector.replace(match, Array(length + 1).join(' '));
30
+ }
31
+ }
32
+ }
33
+ };
34
+ // Replace escaped characters
35
+ const replaceWithPlainText = (regex) => {
36
+ if (regex.test(selector)) {
37
+ regex.lastIndex = 0;
38
+ const matches = selector.match(regex);
39
+ if (matches) {
40
+ for (const match of matches) {
41
+ selector = selector.replace(match, Array(match.length + 1).join('A'));
42
+ }
43
+ }
44
+ }
45
+ };
46
+ replaceWithPlainText(/\\[0-9A-Fa-f]{6}\s?/g);
47
+ replaceWithPlainText(/\\[0-9A-Fa-f]{1,5}\s/g);
48
+ replaceWithPlainText(/\\./g);
49
+ // Remove anything after a left brace
50
+ const braceRegex = /{[^]*/gm;
51
+ if (braceRegex.test(selector)) {
52
+ braceRegex.lastIndex = 0;
53
+ const matches = selector.match(braceRegex);
54
+ if (matches) {
55
+ for (const match of matches) {
56
+ selector = selector.replace(match, Array(match.length + 1).join(' '));
57
+ }
58
+ }
59
+ }
60
+ findMatch(attributeRegex, 'b');
61
+ findMatch(idRegex, 'a');
62
+ findMatch(classRegex, 'b');
63
+ findMatch(pseudoElementRegex, 'c');
64
+ findMatch(pseudoClassWithBracketsRegex, 'b');
65
+ findMatch(pseudoClassRegex, 'b');
66
+ selector = selector.replace(/[\*\s\+>~]/g, ' ');
67
+ selector = selector.replace(/[#\.]/g, ' ');
68
+ selector = selector.replace(/:not/g, ' ');
69
+ selector = selector.replace(/:local/g, ' ');
70
+ selector = selector.replace(/:global/g, ' ');
71
+ selector = selector.replace(/[\(\)]/g, ' ');
72
+ findMatch(elementRegex, 'c');
73
+ parts.sort((a, b) => a.index - b.index);
74
+ return {
75
+ selector: input,
76
+ specificity: `0,${typeCount.a},${typeCount.b},${typeCount.c}`,
77
+ specificityArray: [0, typeCount.a, typeCount.b, typeCount.c],
78
+ parts,
79
+ };
80
+ }
81
+ /**
82
+ * Calculate a numeric specificity score from a specificity string like "0,1,2,3"
83
+ */
84
+ export function specificityScore(specificityStr) {
85
+ const parts = specificityStr.split(',').map(Number);
86
+ return parts[0] * 1000000 + parts[1] * 10000 + parts[2] * 100 + parts[3];
87
+ }
88
+ //# sourceMappingURL=specificity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specificity.js","sourceRoot":"","sources":["../../src/extraction/specificity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { CDPSession } from 'playwright';
2
+ import { CDPMatchedStyles, CDPRuleMatch, SnippedRule, ExtractionContext } from '../types/index.js';
3
+ /**
4
+ * Processes CSS.getMatchedStylesForNode results into SnippedRule objects.
5
+ * Port of the core matching logic from snipbackground.js:1700-2035
6
+ */
7
+ export declare class StyleMatcher {
8
+ /**
9
+ * Get matched styles for a DOM node via CDP.
10
+ */
11
+ getMatchedStyles(cdp: CDPSession, nodeId: number): Promise<CDPMatchedStyles>;
12
+ /**
13
+ * Process matched styles into a unified list of rule matches.
14
+ * This combines matched rules, inherited rules, and pseudo-element rules
15
+ * into a single ordered list for downstream processing.
16
+ *
17
+ * Port of snipbackground.js lines 1702-1820
18
+ */
19
+ processMatchedStyles(allMatchedStyles: CDPMatchedStyles, classname: string, ctx: ExtractionContext, options: {
20
+ resolveVariables: boolean;
21
+ mediaQueriesOnly: boolean;
22
+ }): CDPRuleMatch[];
23
+ /**
24
+ * Extract CSS variables from matched rules.
25
+ * Port of CSS variable extraction logic from snipbackground.js
26
+ */
27
+ extractCssVariables(matchedRules: CDPRuleMatch[], classname: string, ctx: ExtractionContext): void;
28
+ /**
29
+ * Convert a CDPRuleMatch to a SnippedRule for the final output.
30
+ */
31
+ toSnippedRule(ruleMatch: CDPRuleMatch, classname: string, viewport: string, ctx: ExtractionContext): SnippedRule | null;
32
+ }
33
+ //# sourceMappingURL=style-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-matcher.d.ts","sourceRoot":"","sources":["../../src/extraction/style-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EACL,gBAAgB,EAAE,YAAY,EAC9B,WAAW,EAAE,iBAAiB,EAC/B,MAAM,mBAAmB,CAAC;AAG3B;;;GAGG;AACH,qBAAa,YAAY;IAEvB;;OAEG;IACG,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKlF;;;;;;OAMG;IACH,oBAAoB,CAClB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE;QAAE,gBAAgB,EAAE,OAAO,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAA;KAAE,GAChE,YAAY,EAAE;IAuEjB;;;OAGG;IACH,mBAAmB,CACjB,YAAY,EAAE,YAAY,EAAE,EAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,iBAAiB,GACrB,IAAI;IA+CP;;OAEG;IACH,aAAa,CACX,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,iBAAiB,GACrB,WAAW,GAAG,IAAI;CAkEtB"}
@@ -0,0 +1,199 @@
1
+ import { calculateSingle, specificityScore } from './specificity.js';
2
+ /**
3
+ * Processes CSS.getMatchedStylesForNode results into SnippedRule objects.
4
+ * Port of the core matching logic from snipbackground.js:1700-2035
5
+ */
6
+ export class StyleMatcher {
7
+ /**
8
+ * Get matched styles for a DOM node via CDP.
9
+ */
10
+ async getMatchedStyles(cdp, nodeId) {
11
+ const result = await cdp.send('CSS.getMatchedStylesForNode', { nodeId });
12
+ return result;
13
+ }
14
+ /**
15
+ * Process matched styles into a unified list of rule matches.
16
+ * This combines matched rules, inherited rules, and pseudo-element rules
17
+ * into a single ordered list for downstream processing.
18
+ *
19
+ * Port of snipbackground.js lines 1702-1820
20
+ */
21
+ processMatchedStyles(allMatchedStyles, classname, ctx, options) {
22
+ const matchedCSSRules = [...(allMatchedStyles.matchedCSSRules || [])];
23
+ const inheritedCSSRules = allMatchedStyles.inherited || [];
24
+ // Process inline style CSS variables (lines 1711-1745)
25
+ if (options.resolveVariables && allMatchedStyles.inlineStyle) {
26
+ const cssProperties = allMatchedStyles.inlineStyle.cssProperties || [];
27
+ for (const prop of cssProperties) {
28
+ if (prop.name && prop.name.startsWith('--')) {
29
+ if (!ctx.cssvarDefinedArr[prop.name]) {
30
+ ctx.cssvarDefinedArr[prop.name] = [];
31
+ }
32
+ const inlineKey = `inline-${classname}-${prop.name}`;
33
+ const exists = ctx.cssvarDefinedArr[prop.name].some((item) => item.key === inlineKey);
34
+ if (!exists) {
35
+ ctx.cssvarDefinedArr[prop.name].push({
36
+ key: inlineKey,
37
+ label: classname,
38
+ value: prop.value,
39
+ media: '',
40
+ selector: '.' + classname,
41
+ source: 'inline-style',
42
+ });
43
+ }
44
+ }
45
+ }
46
+ }
47
+ // Process inherited rules - prepend in reverse order (lines 1748-1798)
48
+ if (inheritedCSSRules.length > 0) {
49
+ for (let m = inheritedCSSRules.length - 1; m >= 0; m--) {
50
+ const cRule = inheritedCSSRules[m];
51
+ const inheritedRules = cRule.matchedCSSRules || [];
52
+ for (let n = inheritedRules.length - 1; n >= 0; n--) {
53
+ const iRule = inheritedRules[n];
54
+ iRule.other_inherited = true;
55
+ // Filter to only implicit properties (ones actually defined in CSS)
56
+ const cssProps = iRule.rule.style.cssProperties || [];
57
+ const editedCssProperties = [];
58
+ for (const cProp of cssProps) {
59
+ if ('implicit' in cProp) {
60
+ editedCssProperties.push(cProp);
61
+ }
62
+ }
63
+ matchedCSSRules.unshift(iRule);
64
+ }
65
+ }
66
+ }
67
+ // Process pseudo-element rules (lines 1800-1820)
68
+ if (!options.mediaQueriesOnly && allMatchedStyles.pseudoElements) {
69
+ for (const pseudoMatch of allMatchedStyles.pseudoElements) {
70
+ for (const pMatch of pseudoMatch.matches) {
71
+ // Skip box-sizing inherit pseudo rules
72
+ const cssText = pMatch.rule.style.cssText || '';
73
+ if (cssText.includes('box-sizing: inherit')) {
74
+ continue;
75
+ }
76
+ pMatch.rule.rule_type = 'psuedo';
77
+ matchedCSSRules.push({ rule: pMatch.rule, matchingSelectors: pMatch.matchingSelectors });
78
+ }
79
+ }
80
+ }
81
+ return matchedCSSRules;
82
+ }
83
+ /**
84
+ * Extract CSS variables from matched rules.
85
+ * Port of CSS variable extraction logic from snipbackground.js
86
+ */
87
+ extractCssVariables(matchedRules, classname, ctx) {
88
+ for (const ruleMatch of matchedRules) {
89
+ const rule = ruleMatch.rule;
90
+ if (!rule || !rule.style)
91
+ continue;
92
+ const cssProperties = rule.style.cssProperties || [];
93
+ const selectorText = rule.selectorList?.text || '';
94
+ const media = (rule.media && rule.media.length > 0) ? rule.media[0].text : '';
95
+ for (const prop of cssProperties) {
96
+ // Capture variable definitions
97
+ if (prop.name && prop.name.startsWith('--') && prop.value) {
98
+ if (!ctx.cssvarDefinedArr[prop.name]) {
99
+ ctx.cssvarDefinedArr[prop.name] = [];
100
+ }
101
+ const key = `${selectorText}-${prop.name}-${media}`;
102
+ const exists = ctx.cssvarDefinedArr[prop.name].some((item) => item.key === key);
103
+ if (!exists) {
104
+ ctx.cssvarDefinedArr[prop.name].push({
105
+ key,
106
+ label: classname,
107
+ value: prop.value,
108
+ media,
109
+ selector: selectorText,
110
+ source: 'stylesheet',
111
+ });
112
+ }
113
+ }
114
+ // Track variable usage
115
+ if (prop.value && prop.value.includes('var(--')) {
116
+ const varMatches = prop.value.match(/var\(\s*(--[^,\)]+)/g);
117
+ if (varMatches) {
118
+ for (const varMatch of varMatches) {
119
+ const varName = varMatch.replace(/var\(\s*/, '');
120
+ if (!ctx.cssvarUsedArr.includes(varName)) {
121
+ ctx.cssvarUsedArr.push(varName);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ /**
130
+ * Convert a CDPRuleMatch to a SnippedRule for the final output.
131
+ */
132
+ toSnippedRule(ruleMatch, classname, viewport, ctx) {
133
+ const rule = ruleMatch.rule;
134
+ if (!rule || !rule.style)
135
+ return null;
136
+ // Skip user-agent rules
137
+ if (rule.origin === 'user-agent')
138
+ return null;
139
+ const selectorText = rule.selectorList?.text || '';
140
+ const cssProperties = rule.style.cssProperties || [];
141
+ // Build CSS body from properties
142
+ // CDP returns both shorthand and longhand versions. We want only the
143
+ // explicitly-written properties (those that have 'text' set or aren't implicit).
144
+ const bodyParts = [];
145
+ const seenProps = new Set();
146
+ for (const prop of cssProperties) {
147
+ if (!prop.name || !prop.value)
148
+ continue;
149
+ if (prop.disabled)
150
+ continue;
151
+ if (prop.parsedOk === false)
152
+ continue;
153
+ // Skip implicit longhand expansions - only keep explicitly defined properties.
154
+ // Implicit means CDP auto-expanded a shorthand; we want the shorthand only.
155
+ if (!('implicit' in prop) && !prop.text && prop.range === undefined)
156
+ continue;
157
+ // Deduplicate properties
158
+ if (seenProps.has(prop.name))
159
+ continue;
160
+ seenProps.add(prop.name);
161
+ const important = prop.important ? ' !important' : '';
162
+ const cleanValue = prop.value.replace(/\s*!important\s*/g, '').trim();
163
+ bodyParts.push(`${prop.name}: ${cleanValue}${important}`);
164
+ }
165
+ if (bodyParts.length === 0)
166
+ return null;
167
+ const body = bodyParts.join(';\n');
168
+ const media = (rule.media && rule.media.length > 0)
169
+ ? rule.media.map(m => m.text).join(' and ')
170
+ : '';
171
+ // Calculate specificity
172
+ let specScore = 0;
173
+ try {
174
+ const specResult = calculateSingle(selectorText);
175
+ specScore = specificityScore(specResult.specificity);
176
+ }
177
+ catch {
178
+ specScore = 0;
179
+ }
180
+ const isInherited = !!ruleMatch.other_inherited;
181
+ const isPseudo = rule.rule_type === 'psuedo';
182
+ const isHover = selectorText.includes(':hover') || rule.origin === 'pseudo';
183
+ return {
184
+ selector: selectorText,
185
+ body,
186
+ media,
187
+ classname,
188
+ stylesheet_id: rule.styleSheetId || '',
189
+ origin: rule.origin,
190
+ is_inherited: isInherited,
191
+ other_inherited: isInherited,
192
+ is_pseudo_element: isPseudo,
193
+ is_hover: isHover,
194
+ specificity_score: specScore,
195
+ viewport,
196
+ };
197
+ }
198
+ }
199
+ //# sourceMappingURL=style-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-matcher.js","sourceRoot":"","sources":["../../src/extraction/style-matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { CDPSession } from 'playwright';
2
+ import { StylesheetInfo } from '../types/index.js';
3
+ /**
4
+ * Collects stylesheets from the page using CDP CSS domain events.
5
+ * Replaces the onDebuggerEvent handler for CSS.styleSheetAdded in snipbackground.js:573-696
6
+ */
7
+ export declare class StylesheetCollector {
8
+ private stylesheets;
9
+ private collecting;
10
+ /**
11
+ * Start collecting stylesheet events. Call this BEFORE navigation or
12
+ * immediately after CSS.enable so we catch all CSS.styleSheetAdded events.
13
+ */
14
+ startCollecting(cdp: CDPSession): Promise<void>;
15
+ /**
16
+ * Stop collecting and return all captured stylesheets.
17
+ */
18
+ stopCollecting(): StylesheetInfo[];
19
+ /**
20
+ * Fetch the text content of all collected stylesheets.
21
+ * Parallelizes the CSS.getStyleSheetText calls.
22
+ */
23
+ fetchAllStylesheetTexts(cdp: CDPSession): Promise<StylesheetInfo[]>;
24
+ /**
25
+ * Get collected stylesheets (without text content).
26
+ */
27
+ getStylesheets(): StylesheetInfo[];
28
+ /**
29
+ * Get a specific stylesheet by ID.
30
+ */
31
+ getStylesheetById(id: string): StylesheetInfo | undefined;
32
+ }
33
+ //# sourceMappingURL=stylesheet-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stylesheet-collector.d.ts","sourceRoot":"","sources":["../../src/extraction/stylesheet-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAiB,MAAM,mBAAmB,CAAC;AAElE;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,UAAU,CAAS;IAE3B;;;OAGG;IACG,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrD;;OAEG;IACH,cAAc,IAAI,cAAc,EAAE;IAKlC;;;OAGG;IACG,uBAAuB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAsBzE;;OAEG;IACH,cAAc,IAAI,cAAc,EAAE;IAIlC;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;CAG1D"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Collects stylesheets from the page using CDP CSS domain events.
3
+ * Replaces the onDebuggerEvent handler for CSS.styleSheetAdded in snipbackground.js:573-696
4
+ */
5
+ export class StylesheetCollector {
6
+ stylesheets = [];
7
+ collecting = false;
8
+ /**
9
+ * Start collecting stylesheet events. Call this BEFORE navigation or
10
+ * immediately after CSS.enable so we catch all CSS.styleSheetAdded events.
11
+ */
12
+ async startCollecting(cdp) {
13
+ this.stylesheets = [];
14
+ this.collecting = true;
15
+ cdp.on('CSS.styleSheetAdded', (params) => {
16
+ if (!this.collecting)
17
+ return;
18
+ const header = params.header;
19
+ this.stylesheets.push({
20
+ stylesheet_id: header.styleSheetId,
21
+ source_url: header.sourceURL || '',
22
+ frame_id: header.frameId,
23
+ origin: header.origin,
24
+ is_inline: header.isInline || false,
25
+ });
26
+ });
27
+ }
28
+ /**
29
+ * Stop collecting and return all captured stylesheets.
30
+ */
31
+ stopCollecting() {
32
+ this.collecting = false;
33
+ return [...this.stylesheets];
34
+ }
35
+ /**
36
+ * Fetch the text content of all collected stylesheets.
37
+ * Parallelizes the CSS.getStyleSheetText calls.
38
+ */
39
+ async fetchAllStylesheetTexts(cdp) {
40
+ const results = await Promise.all(this.stylesheets.map(async (ss) => {
41
+ // Skip user-agent stylesheets - they don't have text
42
+ if (ss.origin === 'user-agent')
43
+ return ss;
44
+ try {
45
+ const result = await cdp.send('CSS.getStyleSheetText', {
46
+ styleSheetId: ss.stylesheet_id,
47
+ });
48
+ ss.text = result.text;
49
+ }
50
+ catch (e) {
51
+ // Some stylesheets may not be accessible (cross-origin)
52
+ ss.text = '';
53
+ }
54
+ return ss;
55
+ }));
56
+ return results;
57
+ }
58
+ /**
59
+ * Get collected stylesheets (without text content).
60
+ */
61
+ getStylesheets() {
62
+ return [...this.stylesheets];
63
+ }
64
+ /**
65
+ * Get a specific stylesheet by ID.
66
+ */
67
+ getStylesheetById(id) {
68
+ return this.stylesheets.find(s => s.stylesheet_id === id);
69
+ }
70
+ }
71
+ //# sourceMappingURL=stylesheet-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stylesheet-collector.js","sourceRoot":"","sources":["../../src/extraction/stylesheet-collector.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACtB,WAAW,GAAqB,EAAE,CAAC;IACnC,UAAU,GAAG,KAAK,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,GAAe;QACnC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,GAAG,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,MAAiC,EAAE,EAAE;YAClE,IAAI,CAAC,IAAI,CAAC,UAAU;gBAAE,OAAO;YAE7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC7B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACpB,aAAa,EAAE,MAAM,CAAC,YAAY;gBAClC,UAAU,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;gBAClC,QAAQ,EAAE,MAAM,CAAC,OAAO;gBACxB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,SAAS,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;aACpC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,uBAAuB,CAAC,GAAe;QAC3C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAChC,qDAAqD;YACrD,IAAI,EAAE,CAAC,MAAM,KAAK,YAAY;gBAAE,OAAO,EAAE,CAAC;YAE1C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE;oBACrD,YAAY,EAAE,EAAE,CAAC,aAAa;iBAC/B,CAAC,CAAC;gBACH,EAAE,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACxB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,wDAAwD;gBACxD,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC;YACf,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CACH,CAAC;QAEF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAU;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}