design-clone 2.1.0 → 2.3.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/README.md +13 -34
- package/SKILL.md +69 -45
- package/bin/cli.js +22 -4
- package/bin/commands/clone-site.js +31 -171
- package/bin/commands/help.js +19 -6
- package/bin/commands/init.js +9 -86
- package/bin/commands/uninstall.js +105 -0
- package/bin/commands/update.js +70 -0
- package/bin/commands/verify.js +7 -14
- package/bin/utils/paths.js +28 -0
- package/bin/utils/validate.js +2 -22
- package/bin/utils/version.js +23 -0
- package/docs/code-standards.md +789 -0
- package/docs/codebase-summary.md +533 -286
- package/docs/index.md +74 -0
- package/docs/project-overview-pdr.md +797 -0
- package/docs/system-architecture.md +718 -0
- package/package.json +14 -17
- package/src/ai/prompts/design-tokens/basic.md +80 -0
- package/src/ai/prompts/design-tokens/section-with-css.md +41 -0
- package/src/ai/prompts/design-tokens/section.md +48 -0
- package/src/ai/prompts/design-tokens/with-css.md +87 -0
- package/src/ai/prompts/structure-analysis/basic.md +55 -0
- package/src/ai/prompts/structure-analysis/with-context.md +59 -0
- package/src/ai/prompts/structure-analysis/with-dimensions.md +63 -0
- package/src/ai/prompts/structure-analysis/with-hierarchy.md +73 -0
- package/src/ai/prompts/ux-audit/aggregation.md +42 -0
- package/src/ai/prompts/ux-audit/desktop.md +92 -0
- package/src/ai/prompts/ux-audit/mobile.md +93 -0
- package/src/ai/prompts/ux-audit/tablet.md +92 -0
- package/src/core/animation/animation-extractor-ast.js +183 -0
- package/src/core/animation/animation-extractor-output.js +152 -0
- package/src/core/animation/animation-extractor.js +178 -0
- package/src/core/animation/state-capture-detection.js +200 -0
- package/src/core/animation/state-capture.js +193 -0
- package/src/core/capture/browser-context-pool.js +96 -0
- package/src/core/capture/multi-page-screenshot-page.js +110 -0
- package/src/core/capture/multi-page-screenshot.js +208 -0
- package/src/core/capture/screenshot-extraction.js +186 -0
- package/src/core/capture/screenshot-helpers.js +175 -0
- package/src/core/capture/screenshot-orchestrator.js +174 -0
- package/src/core/capture/screenshot-viewport.js +93 -0
- package/src/core/capture/screenshot.js +192 -0
- package/src/core/content/content-counter-dom.js +191 -0
- package/src/core/content/content-counter.js +76 -0
- package/src/core/css/breakpoint-detector.js +66 -0
- package/src/core/css/chromium-defaults.json +23 -0
- package/src/core/css/computed-style-extractor.js +102 -0
- package/src/core/css/css-chunker.js +103 -0
- package/src/core/css/filter-css-dead-code.js +120 -0
- package/src/core/css/filter-css-html-analyzer.js +110 -0
- package/src/core/css/filter-css-selector-matcher.js +172 -0
- package/src/core/css/filter-css.js +206 -0
- package/src/core/css/merge-css-atrule-processor.js +158 -0
- package/src/core/css/merge-css-file-io.js +68 -0
- package/src/core/css/merge-css.js +148 -0
- package/src/core/detection/framework-detector-routing.js +68 -0
- package/src/core/detection/framework-detector-signals.js +65 -0
- package/src/core/detection/framework-detector.js +198 -0
- package/src/core/dimension/dimension-extractor-card-detector.js +82 -0
- package/src/core/dimension/dimension-extractor.js +317 -0
- package/src/core/dimension/dimension-output-ai-summary.js +111 -0
- package/src/core/dimension/dimension-output.js +173 -0
- package/src/core/dimension/dom-tree-analyzer-tree-builders.js +95 -0
- package/src/core/dimension/dom-tree-analyzer.js +191 -0
- package/src/core/discovery/app-state-snapshot-capture.js +195 -0
- package/src/core/discovery/app-state-snapshot-utils.js +178 -0
- package/src/core/discovery/app-state-snapshot.js +131 -0
- package/src/core/discovery/discover-pages-routes.js +84 -0
- package/src/core/discovery/discover-pages-utils.js +177 -0
- package/src/core/discovery/discover-pages.js +191 -0
- package/src/core/html/html-extractor-inline-styler.js +70 -0
- package/src/core/html/html-extractor.js +147 -0
- package/src/core/html/semantic-enhancer-mappings.js +200 -0
- package/src/core/html/semantic-enhancer-page.js +148 -0
- package/src/core/html/semantic-enhancer.js +135 -0
- package/src/core/links/rewrite-links-css-rewriter.js +53 -0
- package/src/core/links/rewrite-links.js +173 -0
- package/src/core/media/asset-validator.js +118 -0
- package/src/core/media/extract-assets-downloader.js +187 -0
- package/src/core/media/extract-assets-page-scraper.js +115 -0
- package/src/core/media/extract-assets.js +159 -0
- package/src/core/media/video-capture-convert.js +200 -0
- package/src/core/media/video-capture.js +201 -0
- package/src/core/{lazy-loader.js → page-prep/lazy-loader.js} +37 -39
- package/src/core/section/section-cropper-helpers.js +43 -0
- package/src/core/{section-cropper.js → section/section-cropper.js} +11 -88
- package/src/core/section/section-detector-strategies.js +139 -0
- package/src/core/section/section-detector-utils.js +100 -0
- package/src/core/section/section-detector.js +88 -0
- package/src/core/tests/test-section-cropper.js +2 -2
- package/src/core/tests/test-section-detector.js +2 -2
- package/src/post-process/enhance-assets.js +29 -4
- package/src/post-process/fetch-images-unsplash-client.js +123 -0
- package/src/post-process/fetch-images.js +60 -263
- package/src/post-process/inject-gosnap.js +88 -0
- package/src/post-process/inject-icons-svg-replacer.js +76 -0
- package/src/post-process/inject-icons.js +47 -200
- package/src/route-discoverers/base-discoverer-utils.js +137 -0
- package/src/route-discoverers/base-discoverer.js +29 -118
- package/src/route-discoverers/index.js +1 -1
- package/src/shared/config.js +38 -0
- package/src/shared/error-codes.js +31 -0
- package/src/shared/viewports.js +46 -0
- package/src/utils/browser.js +0 -7
- package/src/utils/helpers.js +4 -0
- package/src/utils/log.js +12 -0
- package/src/utils/playwright-loader.js +76 -0
- package/src/utils/playwright.js +3 -69
- package/src/utils/progress.js +32 -0
- package/src/verification/generate-audit-report-css-fixes.js +52 -0
- package/src/verification/generate-audit-report-sections.js +158 -0
- package/src/verification/generate-audit-report.js +5 -281
- package/src/verification/quality-scorer.js +92 -0
- package/src/verification/verify-footer-checks.js +103 -0
- package/src/verification/verify-footer-helpers.js +178 -0
- package/src/verification/verify-footer.js +23 -381
- package/src/verification/verify-header-checks.js +104 -0
- package/src/verification/verify-header-helpers.js +156 -0
- package/src/verification/verify-header.js +23 -365
- package/src/verification/verify-layout-report.js +101 -0
- package/src/verification/verify-layout.js +13 -259
- package/src/verification/verify-menu-checks.js +104 -0
- package/src/verification/verify-menu-helpers.js +112 -0
- package/src/verification/verify-menu.js +17 -285
- package/src/verification/verify-slider-checks.js +115 -0
- package/src/verification/verify-slider-constants.js +65 -0
- package/src/verification/verify-slider-helpers.js +164 -0
- package/src/verification/verify-slider.js +23 -414
- package/.env.example +0 -14
- package/docs/basic-clone.md +0 -63
- package/docs/cli-reference.md +0 -316
- package/docs/design-clone-architecture.md +0 -492
- package/docs/pixel-perfect.md +0 -117
- package/docs/project-roadmap.md +0 -382
- package/docs/troubleshooting.md +0 -170
- package/requirements.txt +0 -5
- package/src/ai/__pycache__/analyze-structure.cpython-313.pyc +0 -0
- package/src/ai/__pycache__/extract-design-tokens.cpython-313.pyc +0 -0
- package/src/ai/analyze-structure.py +0 -375
- package/src/ai/extract-design-tokens.py +0 -782
- package/src/ai/prompts/__init__.py +0 -2
- package/src/ai/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/ai/prompts/__pycache__/design_tokens.cpython-313.pyc +0 -0
- package/src/ai/prompts/__pycache__/structure_analysis.cpython-313.pyc +0 -0
- package/src/ai/prompts/__pycache__/ux_audit.cpython-313.pyc +0 -0
- package/src/ai/prompts/design_tokens.py +0 -316
- package/src/ai/prompts/structure_analysis.py +0 -592
- package/src/ai/prompts/ux_audit.py +0 -198
- package/src/ai/ux-audit.js +0 -596
- package/src/core/animation-extractor.js +0 -526
- package/src/core/app-state-snapshot.js +0 -511
- package/src/core/content-counter.js +0 -342
- package/src/core/design-tokens.js +0 -103
- package/src/core/dimension-extractor.js +0 -438
- package/src/core/dimension-output.js +0 -305
- package/src/core/discover-pages.js +0 -542
- package/src/core/dom-tree-analyzer.js +0 -298
- package/src/core/extract-assets.js +0 -468
- package/src/core/filter-css.js +0 -499
- package/src/core/framework-detector.js +0 -538
- package/src/core/html-extractor.js +0 -212
- package/src/core/merge-css.js +0 -407
- package/src/core/multi-page-screenshot.js +0 -380
- package/src/core/rewrite-links.js +0 -226
- package/src/core/screenshot.js +0 -701
- package/src/core/section-detector.js +0 -386
- package/src/core/semantic-enhancer.js +0 -492
- package/src/core/state-capture.js +0 -598
- package/src/core/video-capture.js +0 -546
- package/src/utils/__init__.py +0 -16
- package/src/utils/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/utils/__pycache__/env.cpython-313.pyc +0 -0
- package/src/utils/env.py +0 -134
- /package/src/core/{css-extractor.js → css/css-extractor.js} +0 -0
- /package/src/core/{cookie-handler.js → page-prep/cookie-handler.js} +0 -0
- /package/src/core/{page-readiness.js → page-prep/page-readiness.js} +0 -0
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dimension Output Builder
|
|
3
|
-
*
|
|
4
|
-
* Build and format component dimension output for JSON files.
|
|
5
|
-
* Includes sanitization, cross-viewport summary, and AI-friendly format.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Default viewport configurations
|
|
9
|
-
const VIEWPORTS = {
|
|
10
|
-
desktop: { width: 1440, height: 900, deviceScaleFactor: 1 },
|
|
11
|
-
tablet: { width: 768, height: 1024, deviceScaleFactor: 1 },
|
|
12
|
-
mobile: { width: 375, height: 812, deviceScaleFactor: 2 }
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Build final component-dimensions.json output with proper schema
|
|
17
|
-
* @param {Object} allViewportDimensions - Dimensions from all viewports
|
|
18
|
-
* @param {string} url - Source URL
|
|
19
|
-
* @returns {Object} Final JSON structure
|
|
20
|
-
*/
|
|
21
|
-
export function buildDimensionsOutput(allViewportDimensions, url) {
|
|
22
|
-
const output = {
|
|
23
|
-
meta: {
|
|
24
|
-
version: "1.0",
|
|
25
|
-
extractedAt: new Date().toISOString(),
|
|
26
|
-
url: url,
|
|
27
|
-
tool: "design-clone/screenshot.js"
|
|
28
|
-
},
|
|
29
|
-
viewports: {},
|
|
30
|
-
summary: {}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
for (const [vpName, vpData] of Object.entries(allViewportDimensions)) {
|
|
34
|
-
output.viewports[vpName] = sanitizeViewportData(vpData, vpName);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
output.summary = buildCrossViewportSummary(output.viewports);
|
|
38
|
-
return output;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Sanitize viewport data for JSON output
|
|
43
|
-
*/
|
|
44
|
-
export function sanitizeViewportData(data, vpName) {
|
|
45
|
-
if (!data) return {};
|
|
46
|
-
|
|
47
|
-
const clean = JSON.parse(JSON.stringify(data));
|
|
48
|
-
clean.width = VIEWPORTS[vpName]?.width || 0;
|
|
49
|
-
clean.height = VIEWPORTS[vpName]?.height || 0;
|
|
50
|
-
|
|
51
|
-
function roundNumbers(obj) {
|
|
52
|
-
for (const key in obj) {
|
|
53
|
-
if (typeof obj[key] === 'number') {
|
|
54
|
-
obj[key] = Math.round(obj[key]);
|
|
55
|
-
} else if (Array.isArray(obj[key])) {
|
|
56
|
-
obj[key].forEach(item => roundNumbers(item));
|
|
57
|
-
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
58
|
-
roundNumbers(obj[key]);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return obj;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function truncateStrings(obj, maxLen = 80) {
|
|
65
|
-
for (const key in obj) {
|
|
66
|
-
if (typeof obj[key] === 'string' && obj[key].length > maxLen) {
|
|
67
|
-
obj[key] = obj[key].slice(0, maxLen) + '...';
|
|
68
|
-
} else if (Array.isArray(obj[key])) {
|
|
69
|
-
obj[key].forEach(item => truncateStrings(item, maxLen));
|
|
70
|
-
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
71
|
-
truncateStrings(obj[key], maxLen);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return obj;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Limit array sizes for token efficiency
|
|
78
|
-
if (clean.containers && clean.containers.length > 15) {
|
|
79
|
-
clean.containers = clean.containers.slice(0, 15);
|
|
80
|
-
}
|
|
81
|
-
if (clean.images && clean.images.length > 10) {
|
|
82
|
-
clean.images = clean.images.slice(0, 10);
|
|
83
|
-
}
|
|
84
|
-
if (clean.buttons && clean.buttons.length > 10) {
|
|
85
|
-
clean.buttons = clean.buttons.slice(0, 10);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return truncateStrings(roundNumbers(clean));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Build cross-viewport summary for AI consumption.
|
|
93
|
-
* Includes section-aware typography and container data.
|
|
94
|
-
*
|
|
95
|
-
* @param {Object} viewports - Viewport data keyed by name (desktop, tablet, mobile)
|
|
96
|
-
* @returns {Object} Summary with:
|
|
97
|
-
* - maxContainerWidth: Largest container width across all viewports
|
|
98
|
-
* - commonGap: Average gap from card patterns
|
|
99
|
-
* - breakpoints: Viewport width breakpoints
|
|
100
|
-
* - typography: Flat h1/h2/h3/body sizes by viewport (backward compat)
|
|
101
|
-
* - typographyBySection: Typography grouped by section context (hero h1 != content h1)
|
|
102
|
-
* - cardPatterns: Card group statistics
|
|
103
|
-
* - sections: Section detection summary (found flag + width/containerWidth)
|
|
104
|
-
*/
|
|
105
|
-
export function buildCrossViewportSummary(viewports) {
|
|
106
|
-
const summary = {
|
|
107
|
-
maxContainerWidth: 0,
|
|
108
|
-
commonGap: 0,
|
|
109
|
-
breakpoints: {
|
|
110
|
-
desktop: VIEWPORTS.desktop.width,
|
|
111
|
-
tablet: VIEWPORTS.tablet.width,
|
|
112
|
-
mobile: VIEWPORTS.mobile.width
|
|
113
|
-
},
|
|
114
|
-
// Flat typography for backward compatibility
|
|
115
|
-
typography: { h1: {}, h2: {}, h3: {}, body: {} },
|
|
116
|
-
// NEW: Typography by section context
|
|
117
|
-
typographyBySection: {
|
|
118
|
-
hero: {},
|
|
119
|
-
content: {},
|
|
120
|
-
header: {},
|
|
121
|
-
footer: {},
|
|
122
|
-
sidebar: {}
|
|
123
|
-
},
|
|
124
|
-
cardPatterns: { totalGroups: 0, avgCardSize: null },
|
|
125
|
-
// NEW: Section summary
|
|
126
|
-
sections: {
|
|
127
|
-
hero: { found: false, containerWidth: null },
|
|
128
|
-
content: { found: false, containerWidth: null },
|
|
129
|
-
header: { found: false, containerWidth: null },
|
|
130
|
-
footer: { found: false, containerWidth: null },
|
|
131
|
-
sidebar: { found: false, width: null }
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
for (const [vpName, vpData] of Object.entries(viewports)) {
|
|
136
|
-
if (!vpData) continue;
|
|
137
|
-
|
|
138
|
-
// Container section mapping
|
|
139
|
-
if (vpData.containers) {
|
|
140
|
-
for (const container of vpData.containers) {
|
|
141
|
-
if (container.width > summary.maxContainerWidth) {
|
|
142
|
-
summary.maxContainerWidth = container.width;
|
|
143
|
-
}
|
|
144
|
-
// Track section widths
|
|
145
|
-
const section = container.section || 'content';
|
|
146
|
-
if (summary.sections[section]) {
|
|
147
|
-
summary.sections[section].found = true;
|
|
148
|
-
// Sidebar uses 'width' field, others use 'containerWidth'
|
|
149
|
-
if (section === 'sidebar') {
|
|
150
|
-
if (!summary.sections[section].width ||
|
|
151
|
-
container.width > summary.sections[section].width) {
|
|
152
|
-
summary.sections[section].width = container.width;
|
|
153
|
-
}
|
|
154
|
-
} else {
|
|
155
|
-
if (!summary.sections[section].containerWidth ||
|
|
156
|
-
container.width > summary.sections[section].containerWidth) {
|
|
157
|
-
summary.sections[section].containerWidth = container.width;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Typography by section
|
|
165
|
-
if (vpData.typography) {
|
|
166
|
-
for (const typo of vpData.typography) {
|
|
167
|
-
const tag = typo.selector?.toLowerCase();
|
|
168
|
-
const section = typo.section || 'content';
|
|
169
|
-
|
|
170
|
-
// Flat typography (backward compat) - take first found
|
|
171
|
-
if (tag === 'h1' && !summary.typography.h1[vpName]) summary.typography.h1[vpName] = typo.fontSize;
|
|
172
|
-
if (tag === 'h2' && !summary.typography.h2[vpName]) summary.typography.h2[vpName] = typo.fontSize;
|
|
173
|
-
if (tag === 'h3' && !summary.typography.h3[vpName]) summary.typography.h3[vpName] = typo.fontSize;
|
|
174
|
-
if (tag === 'p' && !summary.typography.body[vpName]) summary.typography.body[vpName] = typo.fontSize;
|
|
175
|
-
|
|
176
|
-
// Typography by section
|
|
177
|
-
if (!summary.typographyBySection[section]) {
|
|
178
|
-
summary.typographyBySection[section] = {};
|
|
179
|
-
}
|
|
180
|
-
if (!summary.typographyBySection[section][tag]) {
|
|
181
|
-
summary.typographyBySection[section][tag] = {};
|
|
182
|
-
}
|
|
183
|
-
// Take first found per section/tag/viewport
|
|
184
|
-
if (!summary.typographyBySection[section][tag][vpName]) {
|
|
185
|
-
summary.typographyBySection[section][tag][vpName] = typo.fontSize;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Card patterns (unchanged)
|
|
191
|
-
if (vpData.cards && vpData.cards.length > 0) {
|
|
192
|
-
summary.cardPatterns.totalGroups += vpData.cards.length;
|
|
193
|
-
if (vpName === 'desktop' && vpData.cards[0]?.avgDimensions) {
|
|
194
|
-
summary.cardPatterns.avgCardSize = vpData.cards[0].avgDimensions;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const gaps = vpData.cards.map(g => g.gap).filter(g => g > 0);
|
|
198
|
-
if (gaps.length > 0) {
|
|
199
|
-
summary.commonGap = Math.round(gaps.reduce((a, b) => a + b, 0) / gaps.length);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return summary;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Generate AI-friendly summary (compact, <5KB)
|
|
209
|
-
* Includes section-aware typography for accurate reconstruction
|
|
210
|
-
* @param {Object} fullOutput - Full component-dimensions.json
|
|
211
|
-
* @returns {Object} Compact summary for AI prompts
|
|
212
|
-
*/
|
|
213
|
-
export function generateAISummary(fullOutput) {
|
|
214
|
-
const { viewports, summary } = fullOutput;
|
|
215
|
-
const desktop = viewports.desktop || {};
|
|
216
|
-
|
|
217
|
-
function inferSectionPadding(containers) {
|
|
218
|
-
if (!containers || containers.length === 0) return "64px 0";
|
|
219
|
-
const paddings = containers.slice(0, 5).map(c => ({
|
|
220
|
-
v: c.paddingTop || c.paddingBottom || 64,
|
|
221
|
-
h: c.paddingLeft || c.paddingRight || 0
|
|
222
|
-
}));
|
|
223
|
-
const avgV = Math.round(paddings.reduce((s, p) => s + p.v, 0) / paddings.length);
|
|
224
|
-
const avgH = Math.round(paddings.reduce((s, p) => s + p.h, 0) / paddings.length);
|
|
225
|
-
return `${avgV}px ${avgH}px`;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function inferCardDimensions(cards) {
|
|
229
|
-
if (!cards || cards.length === 0) {
|
|
230
|
-
return { width: "auto", height: "auto", padding: "24px" };
|
|
231
|
-
}
|
|
232
|
-
const first = cards[0].avgDimensions || cards[0];
|
|
233
|
-
return {
|
|
234
|
-
width: first.width ? first.width + "px" : "auto",
|
|
235
|
-
height: first.height > 0 ? first.height + "px" : "auto",
|
|
236
|
-
padding: (first.paddingTop || first.padding || 24) + "px"
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Convert typographyBySection to AI-friendly format with px units
|
|
242
|
-
*/
|
|
243
|
-
function inferTypographyBySection(typographyBySection) {
|
|
244
|
-
const result = {};
|
|
245
|
-
for (const [section, tags] of Object.entries(typographyBySection || {})) {
|
|
246
|
-
if (!tags || Object.keys(tags).length === 0) continue;
|
|
247
|
-
result[section] = {};
|
|
248
|
-
for (const [tag, sizes] of Object.entries(tags)) {
|
|
249
|
-
// Use desktop first, then tablet, then mobile
|
|
250
|
-
const size = sizes.desktop || sizes.tablet || sizes.mobile || 0;
|
|
251
|
-
if (size > 0) {
|
|
252
|
-
result[section][tag] = size + "px";
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// Remove empty sections
|
|
256
|
-
if (Object.keys(result[section]).length === 0) {
|
|
257
|
-
delete result[section];
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
_comment: "USE THESE EXACT VALUES - DO NOT ESTIMATE",
|
|
265
|
-
EXACT_DIMENSIONS: {
|
|
266
|
-
container_max_width: summary.maxContainerWidth + "px",
|
|
267
|
-
section_padding: inferSectionPadding(desktop.containers),
|
|
268
|
-
card_dimensions: inferCardDimensions(desktop.cards),
|
|
269
|
-
gap: summary.commonGap + "px"
|
|
270
|
-
},
|
|
271
|
-
EXACT_TYPOGRAPHY: {
|
|
272
|
-
h1: (summary.typography.h1.desktop || 48) + "px",
|
|
273
|
-
h2: (summary.typography.h2.desktop || 36) + "px",
|
|
274
|
-
h3: (summary.typography.h3.desktop || 24) + "px",
|
|
275
|
-
body: (summary.typography.body.desktop || 16) + "px"
|
|
276
|
-
},
|
|
277
|
-
// NEW: Section-aware typography (hero h1 != content h1)
|
|
278
|
-
TYPOGRAPHY_BY_SECTION: inferTypographyBySection(summary.typographyBySection),
|
|
279
|
-
// NEW: Section info
|
|
280
|
-
SECTIONS: {
|
|
281
|
-
hero: summary.sections?.hero || { found: false },
|
|
282
|
-
content: summary.sections?.content || { found: false },
|
|
283
|
-
header: summary.sections?.header || { found: false },
|
|
284
|
-
footer: summary.sections?.footer || { found: false },
|
|
285
|
-
sidebar: summary.sections?.sidebar || { found: false }
|
|
286
|
-
},
|
|
287
|
-
RESPONSIVE: {
|
|
288
|
-
desktop_breakpoint: summary.breakpoints.desktop + "px",
|
|
289
|
-
tablet_breakpoint: summary.breakpoints.tablet + "px",
|
|
290
|
-
mobile_breakpoint: summary.breakpoints.mobile + "px",
|
|
291
|
-
typography_scaling: {
|
|
292
|
-
h1: {
|
|
293
|
-
desktop: (summary.typography.h1.desktop || 48) + "px",
|
|
294
|
-
tablet: (summary.typography.h1.tablet || 36) + "px",
|
|
295
|
-
mobile: (summary.typography.h1.mobile || 28) + "px"
|
|
296
|
-
},
|
|
297
|
-
h2: {
|
|
298
|
-
desktop: (summary.typography.h2.desktop || 36) + "px",
|
|
299
|
-
tablet: (summary.typography.h2.tablet || 28) + "px",
|
|
300
|
-
mobile: (summary.typography.h2.mobile || 24) + "px"
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
}
|