@pixelated-tech/components 3.5.12 → 3.5.13

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 (23) hide show
  1. package/dist/components/admin/site-health/seo-metrics.config.json +38 -18
  2. package/dist/components/admin/site-health/site-health-accessibility.js +1 -1
  3. package/dist/components/admin/site-health/site-health-axe-core.js +2 -2
  4. package/dist/components/admin/site-health/site-health-cloudwatch.js +2 -2
  5. package/dist/components/admin/site-health/site-health-dependency-vulnerabilities.js +1 -1
  6. package/dist/components/admin/site-health/site-health-github.js +3 -3
  7. package/dist/components/admin/site-health/site-health-google-analytics.js +1 -1
  8. package/dist/components/admin/site-health/site-health-google-search-console.js +1 -1
  9. package/dist/components/admin/site-health/site-health-on-site-seo.integration.js +275 -3
  10. package/dist/components/admin/site-health/site-health-on-site-seo.js +6 -6
  11. package/dist/components/admin/site-health/site-health-performance.js +1 -1
  12. package/dist/components/admin/site-health/site-health-security.js +1 -1
  13. package/dist/components/admin/site-health/site-health-seo.js +1 -1
  14. package/dist/components/admin/site-health/site-health.css +41 -3
  15. package/dist/components/cms/smartimage.js +28 -8
  16. package/dist/components/general/table.js +2 -2
  17. package/dist/components/sitebuilder/config/ConfigBuilder.js +12 -3
  18. package/dist/types/components/admin/site-health/site-health-on-site-seo.integration.d.ts.map +1 -1
  19. package/dist/types/components/cms/smartimage.d.ts.map +1 -1
  20. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -1
  21. package/dist/types/tests/test-seo-logic.d.ts +2 -0
  22. package/dist/types/tests/test-seo-logic.d.ts.map +1 -0
  23. package/package.json +4 -4
@@ -148,16 +148,6 @@
148
148
  "scoreLogic": "present",
149
149
  "displayTemplate": "{{count}} manifest link(s) found"
150
150
  },
151
- "schema-markup": {
152
- "id": "schema-markup",
153
- "title": "Schema Markup",
154
- "description": "Checks for structured data markup",
155
- "scoreDisplayMode": "binary",
156
- "pattern": "(<script[^>]*type=[\"']application/ld\\+json[\"'][^>]*>[^<]*</script>)|(<[^>]*itemtype=[\"'][^\"']*[\"'][^>]*>)",
157
- "countLogic": "count",
158
- "scoreLogic": "present",
159
- "displayTemplate": "{{count}} schema markup element(s) found"
160
- },
161
151
  "twitter-cards": {
162
152
  "id": "twitter-cards",
163
153
  "title": "Twitter Cards",
@@ -239,15 +229,45 @@
239
229
  "scoreLogic": "present",
240
230
  "displayTemplate": "{{count}} pagination link(s) found"
241
231
  },
242
- "local-seo-elements": {
243
- "id": "local-seo-elements",
244
- "title": "Local SEO Elements",
245
- "description": "Checks for local business schema markup",
232
+ "schema-blogposting": {
233
+ "id": "schema-blogposting",
234
+ "title": "BlogPosting Schema",
235
+ "description": "Checks for BlogPosting structured data markup",
246
236
  "scoreDisplayMode": "binary",
247
- "pattern": "(<script[^>]*type=[\"']application/ld\\+json[\"'][^>]*>[^<]*\"@type\"[^<]*\"LocalBusiness\"[^<]*</script>)|(<[^>]*itemtype=[\"'][^\"']*LocalBusiness[^\"']*[\"'][^>]*>)",
248
- "countLogic": "count",
249
- "scoreLogic": "present",
250
- "displayTemplate": "{{count}} local business schema element(s) found"
237
+ "dataCollector": "collectSchemaBlogPostingData",
238
+ "scorer": "calculateSchemaBlogPostingScore"
239
+ },
240
+ "schema-faq": {
241
+ "id": "schema-faq",
242
+ "title": "FAQ Schema",
243
+ "description": "Checks for FAQPage structured data markup",
244
+ "scoreDisplayMode": "binary",
245
+ "dataCollector": "collectSchemaFAQData",
246
+ "scorer": "calculateSchemaFAQScore"
247
+ },
248
+ "schema-localbusiness": {
249
+ "id": "schema-localbusiness",
250
+ "title": "LocalBusiness Schema",
251
+ "description": "Checks for LocalBusiness structured data markup",
252
+ "scoreDisplayMode": "binary",
253
+ "dataCollector": "collectSchemaLocalBusinessData",
254
+ "scorer": "calculateSchemaLocalBusinessScore"
255
+ },
256
+ "schema-services": {
257
+ "id": "schema-services",
258
+ "title": "Service Schema",
259
+ "description": "Checks for Service structured data markup",
260
+ "scoreDisplayMode": "binary",
261
+ "dataCollector": "collectSchemaServicesData",
262
+ "scorer": "calculateSchemaServicesScore"
263
+ },
264
+ "schema-website": {
265
+ "id": "schema-website",
266
+ "title": "WebSite Schema",
267
+ "description": "Checks for WebSite structured data markup",
268
+ "scoreDisplayMode": "binary",
269
+ "dataCollector": "collectSchemaWebsiteData",
270
+ "scorer": "calculateSchemaWebsiteScore"
251
271
  },
252
272
  "amp-validation": {
253
273
  "id": "amp-validation",
@@ -119,7 +119,7 @@ export function SiteHealthAccessibility({ siteName }) {
119
119
  return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), siteData.scores.accessibility !== null && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Accessibility Score" }), _jsxs("div", { className: "health-score-value", style: { color: getScoreColor(siteData.scores.accessibility) }, children: [Math.round((siteData.scores.accessibility || 0) * 100), "%"] }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
120
120
  width: `${(siteData.scores.accessibility || 0) * 100}%`,
121
121
  backgroundColor: getScoreColor(siteData.scores.accessibility)
122
- } }) })] }) })), siteData.categories.accessibility && siteData.categories.accessibility.audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Accessibility Issues & Recommendations" }), _jsx("div", { className: "space-y-2", children: siteData.categories.accessibility.audits
122
+ } }) })] }) })), siteData.categories.accessibility && siteData.categories.accessibility.audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Accessibility Issues & Recommendations" }), _jsx("div", { className: "health-audit-list", children: siteData.categories.accessibility.audits
123
123
  .filter((audit) => audit.scoreDisplayMode !== 'notApplicable')
124
124
  .sort((a, b) => {
125
125
  // Prioritize specific important accessibility audits
@@ -43,13 +43,13 @@ export function SiteHealthAxeCore({ siteName }) {
43
43
  return (_jsxs("p", { style: { color: '#ef4444', fontSize: '0.875rem' }, children: ["Error: ", siteData.error] }));
44
44
  }
45
45
  const { result, summary } = siteData;
46
- return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), _jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Accessibility Summary" }), _jsxs("div", { className: "health-score-grid", children: [_jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Violations : " }), _jsx("span", { className: "health-stat-value", style: { color: summary.violations > 0 ? '#ef4444' : '#10b981' }, children: summary.violations })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Passes : " }), _jsx("span", { className: "health-stat-value", style: { color: '#10b981' }, children: summary.passes })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Incomplete : " }), _jsx("span", { className: "health-stat-value", style: { color: '#f59e0b' }, children: summary.incomplete })] })] })] }) }), summary.violations > 0 && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Violation Impact Levels" }), _jsxs("div", { className: "health-score-grid", children: [_jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Critical : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('critical') }, children: summary.critical })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Serious : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('serious') }, children: summary.serious })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Moderate : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('moderate') }, children: summary.moderate })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Minor : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('minor') }, children: summary.minor })] })] })] }) })), result.violations.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Accessibility Violations" }), _jsx("div", { className: "space-y-2", children: result.violations
46
+ return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), _jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Accessibility Summary" }), _jsxs("div", { className: "health-score-grid", children: [_jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Violations : " }), _jsx("span", { className: "health-stat-value", style: { color: summary.violations > 0 ? '#ef4444' : '#10b981' }, children: summary.violations })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Passes : " }), _jsx("span", { className: "health-stat-value", style: { color: '#10b981' }, children: summary.passes })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Incomplete : " }), _jsx("span", { className: "health-stat-value", style: { color: '#f59e0b' }, children: summary.incomplete })] })] })] }) }), summary.violations > 0 && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Violation Impact Levels" }), _jsxs("div", { className: "health-score-grid", children: [_jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Critical : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('critical') }, children: summary.critical })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Serious : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('serious') }, children: summary.serious })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Moderate : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('moderate') }, children: summary.moderate })] }), _jsxs("div", { className: "health-stat-item", children: [_jsx("span", { className: "health-stat-label", children: "Minor : " }), _jsx("span", { className: "health-stat-value", style: { color: getImpactColor('minor') }, children: summary.minor })] })] })] }) })), result.violations.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Accessibility Violations" }), _jsx("div", { className: "health-audit-list", children: result.violations
47
47
  .sort((a, b) => {
48
48
  const impactOrder = { critical: 4, serious: 3, moderate: 2, minor: 1 };
49
49
  return impactOrder[b.impact] - impactOrder[a.impact];
50
50
  })
51
51
  .slice(0, 20)
52
- .map((violation) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getImpactIcon(violation.impact) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: [violation.help, " (", violation.impact, ")"] }), _jsx("p", { className: "health-audit-description", children: violation.description }), violation.nodes && violation.nodes.length > 0 && (_jsx("div", { className: "health-audit-details", children: _jsxs("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: ["Affected elements (", violation.nodes.length, "):", violation.nodes.map((node, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatNodeInfo(node) }, idx)))] }) })), _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: _jsx("a", { href: violation.helpUrl, target: "_blank", rel: "noopener noreferrer", style: { color: '#3b82f6', textDecoration: 'underline' }, children: "Learn more about this rule" }) })] })] }, violation.id))) })] })), result.passes.length > 0 && result.violations.length === 0 && (_jsxs("div", { children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem', color: '#10b981' }, children: [getPassingIndicator().icon, " All Accessibility Checks Passed"] }), _jsxs("p", { style: { color: '#6b7280', fontSize: '0.875rem' }, children: [result.passes.length, " accessibility rules were successfully validated."] })] })), result.incomplete.length > 0 && (_jsxs("div", { style: { marginTop: '15px' }, children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem', color: '#f59e0b' }, children: ["Incomplete Tests (", result.incomplete.length, ")"] }), _jsx("div", { className: "space-y-2", children: result.incomplete
52
+ .map((violation) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getImpactIcon(violation.impact) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: [violation.help, " (", violation.impact, ")"] }), _jsx("p", { className: "health-audit-description", children: violation.description }), violation.nodes && violation.nodes.length > 0 && (_jsx("div", { className: "health-audit-details", children: _jsxs("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: ["Affected elements (", violation.nodes.length, "):", violation.nodes.map((node, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatNodeInfo(node) }, idx)))] }) })), _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: _jsx("a", { href: violation.helpUrl, target: "_blank", rel: "noopener noreferrer", style: { color: '#3b82f6', textDecoration: 'underline' }, children: "Learn more about this rule" }) })] })] }, violation.id))) })] })), result.passes.length > 0 && result.violations.length === 0 && (_jsxs("div", { children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem', color: '#10b981' }, children: [getPassingIndicator().icon, " All Accessibility Checks Passed"] }), _jsxs("p", { style: { color: '#6b7280', fontSize: '0.875rem' }, children: [result.passes.length, " accessibility rules were successfully validated."] })] })), result.incomplete.length > 0 && (_jsxs("div", { style: { marginTop: '15px' }, children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem', color: '#f59e0b' }, children: ["Incomplete Tests (", result.incomplete.length, ")"] }), _jsx("div", { className: "health-audit-list", children: result.incomplete
53
53
  .sort((a, b) => a.id.localeCompare(b.id))
54
54
  .slice(0, 10)
55
55
  .map((incomplete) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getIncompleteIndicator().icon }), _jsxs("div", { className: "health-audit-content", children: [_jsx("span", { className: "health-audit-title", children: incomplete.help }), _jsx("p", { className: "health-audit-description", children: incomplete.description }), incomplete.nodes && incomplete.nodes.length > 0 && (_jsx("div", { className: "health-audit-details", children: _jsxs("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: ["Elements tested (", incomplete.nodes.length, "):", incomplete.nodes.slice(0, 3).map((node, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatNodeInfo(node) }, idx))), incomplete.nodes.length > 3 && (_jsxs("div", { style: { marginTop: '0.25rem', fontStyle: 'italic' }, children: ["... and ", incomplete.nodes.length - 3, " more elements"] }))] }) })), _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: _jsx("a", { href: incomplete.helpUrl, target: "_blank", rel: "noopener noreferrer", style: { color: '#3b82f6', textDecoration: 'underline' }, children: "Learn more about this rule" }) })] })] }, incomplete.id))) })] })), _jsxs("div", { className: "health-timestamp", children: [_jsxs("div", { children: ["Tested with axe-core ", result.testEngine?.version || 'unknown'] }), _jsxs("div", { children: ["Last checked: ", new Date(siteData.timestamp).toLocaleString()] })] })] }));
@@ -32,12 +32,12 @@ export function SiteHealthCloudwatch({ siteName, startDate, endDate }) {
32
32
  };
33
33
  return (_jsx(SiteHealthTemplate, { siteName: siteName, title: "CloudWatch Uptime", columnSpan: 2, fetchData: fetchCloudwatchData, children: (data) => {
34
34
  if (!data || data.length === 0) {
35
- return (_jsx("div", { className: "flex items-center justify-center h-64", children: _jsx("div", { className: "text-gray-500", children: "No uptime data available. Route53 health checks may not be configured to send metrics to CloudWatch." }) }));
35
+ return (_jsx("div", { className: "health-visualization-placeholder", children: _jsx("div", { className: "health-text-secondary", children: "No uptime data available. Route53 health checks may not be configured to send metrics to CloudWatch." }) }));
36
36
  }
37
37
  // Check if all data points have zero checks (no actual data)
38
38
  const hasActualData = data.some((point) => point.totalChecks > 0);
39
39
  if (!hasActualData) {
40
- return (_jsx("div", { className: "flex items-center justify-center h-64", children: _jsxs("div", { className: "text-gray-500", children: ["Health check exists but has no metric data in CloudWatch for the selected period.", _jsx("br", {}), "Route53 health checks must be configured to send metrics to CloudWatch for historical data."] }) }));
40
+ return (_jsx("div", { className: "health-visualization-placeholder", children: _jsxs("div", { className: "health-text-secondary", children: ["Health check exists but has no metric data in CloudWatch for the selected period.", _jsx("br", {}), "Route53 health checks must be configured to send metrics to CloudWatch for historical data."] }) }));
41
41
  }
42
42
  return (_jsx("div", { children: _jsx("div", { style: { width: '100%', height: '400px', border: '1px solid #ddd' }, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", children: _jsxs(ComposedChart, { data: data, margin: { top: 40, right: 30, left: 20, bottom: 5 }, children: [_jsx("text", { x: "50%", y: 20, textAnchor: "middle", fontSize: "16", fontWeight: "bold", fill: "#374151", children: "CloudWatch Health Check Availability Over Time" }), _jsx(CartesianGrid, { strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: "date", tick: { fontSize: 12 }, angle: -45, textAnchor: "end", height: 60 }), _jsx(YAxis, { tick: { fontSize: 12 }, label: { value: 'Check Count', angle: -90, position: 'insideLeft' } }), _jsx(Tooltip, { formatter: (value, name) => [
43
43
  value?.toLocaleString() || '0',
@@ -37,6 +37,6 @@ export function SiteHealthDependencyVulnerabilities({ siteName }) {
37
37
  data.status === 'Moderate Risk' ? '#f59e0b' :
38
38
  data.status === 'High Risk' ? '#ef4444' :
39
39
  data.status === 'Critical' ? '#ef4444' : '#6b7280'
40
- } }) })] }) }), _jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", style: { color: '#10b981' }, children: "\u2713" }), _jsx("div", { className: "health-audit-content", children: _jsxs("span", { className: "health-audit-title", children: ["Dependencies: ", data.totalDependencies || data.dependencies || 0] }) })] }), data.vulnerabilities && data.vulnerabilities.length > 0 && (_jsxs("div", { children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: ["Vulnerabilities (", data.summary.total, ")"] }), _jsx("div", { className: "space-y-2", children: data.vulnerabilities.map((vuln, index) => (_jsx("div", { className: `health-vulnerability-item health-vulnerability-${vuln.severity}`, children: _jsxs("div", { className: "health-vulnerability-header", children: [_jsx("span", { className: "health-vulnerability-severity", children: vuln.severity }), _jsxs("div", { children: [_jsx("span", { className: "health-vulnerability-name", children: vuln.name }), vuln.title && (_jsx("p", { className: "health-vulnerability-details", children: vuln.title })), _jsxs("div", { className: "health-vulnerability-meta", children: [_jsxs("span", { className: "health-vulnerability-range", children: ["Range: ", vuln.range] }), vuln.fixAvailable && (_jsx("span", { className: "health-vulnerability-fix", children: "\u2713 Fix available" }))] }), vuln.url && (_jsx("a", { href: vuln.url, target: "_blank", rel: "noopener noreferrer", className: "health-vulnerability-link", children: "View details \u2192" }))] })] }) }, index))) })] })), (!data.vulnerabilities || data.vulnerabilities.length === 0) && data.status === 'Secure' && (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", style: { color: '#10b981' }, children: "\u2713" }), _jsx("div", { className: "health-audit-content", children: _jsx("span", { className: "health-audit-title", children: "No vulnerabilities found" }) })] })), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(data.timestamp).toLocaleString()] })] }));
40
+ } }) })] }) }), _jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", style: { color: '#10b981' }, children: "\u2713" }), _jsx("div", { className: "health-audit-content", children: _jsxs("span", { className: "health-audit-title", children: ["Dependencies: ", data.totalDependencies || data.dependencies || 0] }) })] }), data.vulnerabilities && data.vulnerabilities.length > 0 && (_jsxs("div", { children: [_jsxs("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: ["Vulnerabilities (", data.summary.total, ")"] }), _jsx("div", { className: "health-audit-list", children: data.vulnerabilities.map((vuln, index) => (_jsx("div", { className: `health-vulnerability-item health-vulnerability-${vuln.severity}`, children: _jsxs("div", { className: "health-vulnerability-header", children: [_jsx("span", { className: "health-vulnerability-severity", children: vuln.severity }), _jsxs("div", { children: [_jsx("span", { className: "health-vulnerability-name", children: vuln.name }), vuln.title && (_jsx("p", { className: "health-vulnerability-details", children: vuln.title })), _jsxs("div", { className: "health-vulnerability-meta", children: [_jsxs("span", { className: "health-vulnerability-range", children: ["Range: ", vuln.range] }), vuln.fixAvailable && (_jsx("span", { className: "health-vulnerability-fix", children: "\u2713 Fix available" }))] }), vuln.url && (_jsx("a", { href: vuln.url, target: "_blank", rel: "noopener noreferrer", className: "health-vulnerability-link", children: "View details \u2192" }))] })] }) }, index))) })] })), (!data.vulnerabilities || data.vulnerabilities.length === 0) && data.status === 'Secure' && (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", style: { color: '#10b981' }, children: "\u2713" }), _jsx("div", { className: "health-audit-content", children: _jsx("span", { className: "health-audit-title", children: "No vulnerabilities found" }) })] })), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(data.timestamp).toLocaleString()] })] }));
41
41
  } }));
42
42
  }
@@ -32,9 +32,9 @@ export function SiteHealthGit({ siteName, startDate, endDate }) {
32
32
  // Prepare table data
33
33
  const tableData = (data.commits || []).map((commit) => ({
34
34
  Date: new Date(commit.date).toLocaleDateString(),
35
- Message: _jsx("span", { className: "max-w-xs truncate inline-block", title: commit.message, children: commit.message }),
36
- Version: commit.version ? (_jsx("span", { className: "px-2 py-1 text-xs bg-green-100 text-green-800 rounded", children: commit.version.split('~')[0] })) : (_jsx("span", { className: "text-gray-400", children: "-" }))
35
+ Message: _jsx("span", { className: "health-truncate-text", title: commit.message, children: commit.message }),
36
+ Version: commit.version ? (_jsx("span", { className: "health-version-tag", children: commit.version.split('~')[0] })) : (_jsx("span", { className: "health-text-muted", children: "-" }))
37
37
  }));
38
- return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteName.replace('-', ' ') }), _jsx("div", { className: "space-y-4", children: tableData.length === 0 ? (_jsx("p", { className: "text-gray-500 text-center py-4", children: "No recent commits found" })) : (_jsx(Table, { id: "git-table", data: tableData, altRowColor: "#DDD" })) }), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(data.timestamp).toLocaleString()] })] }));
38
+ return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteName.replace('-', ' ') }), _jsx("div", { className: "health-section-list", children: tableData.length === 0 ? (_jsx("p", { className: "health-empty-state", children: "No recent commits found" })) : (_jsx(Table, { id: "git-table", data: tableData, altRowColor: "#DDD" })) }), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(data.timestamp).toLocaleString()] })] }));
39
39
  } }));
40
40
  }
@@ -36,7 +36,7 @@ export function SiteHealthGoogleAnalytics({ siteName, startDate, endDate }) {
36
36
  };
37
37
  return (_jsx(SiteHealthTemplate, { siteName: siteName, title: "Google Analytics", columnSpan: 2, fetchData: fetchAnalyticsData, children: (data) => {
38
38
  if (!data || data.length === 0) {
39
- return (_jsx("div", { className: "flex items-center justify-center h-64", children: _jsx("div", { className: "text-gray-500", children: "No data available for the selected date range" }) }));
39
+ return (_jsx("div", { className: "health-visualization-placeholder", children: _jsx("div", { className: "health-text-secondary", children: "No data available for the selected date range" }) }));
40
40
  }
41
41
  return (_jsx("div", { children: _jsx("div", { style: { width: '100%', height: '400px', border: '1px solid #ddd' }, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", children: _jsxs(ComposedChart, { data: data, margin: { top: 40, right: 30, left: 20, bottom: 5 }, children: [_jsx("text", { x: "50%", y: 20, textAnchor: "middle", fontSize: "16", fontWeight: "bold", fill: "#374151", children: "Page Views (Current vs Previous Period)" }), _jsx(CartesianGrid, { strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: "date", tick: { fontSize: 12 }, angle: -45, textAnchor: "end", height: 60 }), _jsx(YAxis, { tick: { fontSize: 12 } }), _jsx(Tooltip, { formatter: (value, name) => [
42
42
  value?.toLocaleString() || '0',
@@ -36,7 +36,7 @@ export function SiteHealthGoogleSearchConsole({ siteName, startDate, endDate })
36
36
  };
37
37
  return (_jsx(SiteHealthTemplate, { siteName: siteName, title: "Google Search Console", columnSpan: 2, fetchData: fetchSearchConsoleData, children: (data) => {
38
38
  if (!data || data.length === 0) {
39
- return (_jsx("div", { className: "flex items-center justify-center h-64", children: _jsx("div", { className: "text-gray-500", children: "No indexing data available for the selected date range" }) }));
39
+ return (_jsx("div", { className: "health-visualization-placeholder", children: _jsx("div", { className: "health-text-secondary", children: "No indexing data available for the selected date range" }) }));
40
40
  }
41
41
  return (_jsx("div", { children: _jsx("div", { style: { width: '100%', height: '400px', border: '1px solid #ddd' }, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", children: _jsxs(ComposedChart, { data: data, margin: { top: 40, right: 30, left: 20, bottom: 5 }, children: [_jsx("text", { x: "50%", y: 20, textAnchor: "middle", fontSize: "16", fontWeight: "bold", fill: "#374151", children: "Impressions vs Clicks (Current vs Previous Period)" }), _jsx(CartesianGrid, { strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: "date", tick: { fontSize: 12 }, angle: -45, textAnchor: "end", height: 60 }), _jsx(YAxis, { tick: { fontSize: 12 } }), _jsx(Tooltip, { formatter: (value, name) => [
42
42
  value?.toLocaleString() || '0',
@@ -24,7 +24,12 @@ const dataCollectors = {
24
24
  collectInternationalSEOData,
25
25
  collectFacetedNavigationData,
26
26
  collectBrowserCachingData,
27
- collectGzipCompressionData
27
+ collectGzipCompressionData,
28
+ collectSchemaBlogPostingData,
29
+ collectSchemaFAQData,
30
+ collectSchemaLocalBusinessData,
31
+ collectSchemaServicesData,
32
+ collectSchemaWebsiteData
28
33
  };
29
34
  /**
30
35
  * Registry of scoring functions
@@ -38,7 +43,12 @@ const scorers = {
38
43
  calculateInternationalSEOData,
39
44
  calculateFacetedNavigationScore,
40
45
  calculateBrowserCachingScore,
41
- calculateGzipCompressionScore
46
+ calculateGzipCompressionScore,
47
+ calculateSchemaBlogPostingScore,
48
+ calculateSchemaFAQScore,
49
+ calculateSchemaLocalBusinessScore,
50
+ calculateSchemaServicesScore,
51
+ calculateSchemaWebsiteScore
42
52
  };
43
53
  /**
44
54
  * Data collection functions
@@ -512,6 +522,124 @@ async function collectGzipCompressionData(url) {
512
522
  };
513
523
  }
514
524
  }
525
+ /**
526
+ * Schema Detection Data Collectors
527
+ */
528
+ function collectSchemaBlogPostingData(html) {
529
+ const hasBlogPostingSchema = /"@type"\s*:\s*"BlogPosting"/i.test(html) ||
530
+ /"@type":\s*"BlogPosting"/i.test(html) ||
531
+ /itemtype="https?:\/\/schema\.org\/BlogPosting"/i.test(html);
532
+ return {
533
+ present: hasBlogPostingSchema
534
+ };
535
+ }
536
+ function collectSchemaFAQData(html) {
537
+ const hasFAQSchema = /"@type"\s*:\s*"FAQPage"/i.test(html) ||
538
+ /"@type":\s*"FAQPage"/i.test(html) ||
539
+ /itemtype="https?:\/\/schema\.org\/FAQPage"/i.test(html);
540
+ return {
541
+ present: hasFAQSchema
542
+ };
543
+ }
544
+ function collectSchemaLocalBusinessData(html) {
545
+ const hasLocalBusinessSchema = /"@type"\s*:\s*"LocalBusiness"/i.test(html) ||
546
+ /"@type":\s*"LocalBusiness"/i.test(html) ||
547
+ /itemtype="https?:\/\/schema\.org\/LocalBusiness"/i.test(html);
548
+ return {
549
+ present: hasLocalBusinessSchema
550
+ };
551
+ }
552
+ function collectSchemaServicesData(html) {
553
+ const hasServicesSchema = /"@type"\s*:\s*"Service"/i.test(html) ||
554
+ /"@type":\s*"Service"/i.test(html) ||
555
+ /itemtype="https?:\/\/schema\.org\/Service"/i.test(html);
556
+ return {
557
+ present: hasServicesSchema
558
+ };
559
+ }
560
+ function collectSchemaWebsiteData(html) {
561
+ const hasWebsiteSchema = /"@type"\s*:\s*"WebSite"/i.test(html) ||
562
+ /"@type":\s*"WebSite"/i.test(html) ||
563
+ /itemtype="https?:\/\/schema\.org\/WebSite"/i.test(html);
564
+ return {
565
+ present: hasWebsiteSchema
566
+ };
567
+ }
568
+ /**
569
+ * Detect if a specific page is a blog page
570
+ */
571
+ function detectBlogPage(html, url) {
572
+ // Check URL patterns for blog pages (most reliable)
573
+ const blogUrlPatterns = /\/(blog|news|articles|posts|journal)(\/|$)/i;
574
+ const hasBlogUrl = blogUrlPatterns.test(url);
575
+ // Check for blog schema on this page (very reliable)
576
+ const hasBlogPostingSchema = /"@type"\s*:\s*"BlogPosting"/i.test(html) ||
577
+ /"@type":\s*"BlogPosting"/i.test(html) ||
578
+ /itemtype="https?:\/\/schema\.org\/BlogPosting"/i.test(html);
579
+ // Check for blog-specific headings (h1 or h2)
580
+ const hasBlogHeading = /<(h1|h2)[^>]*>.*?\b(blog|news|articles|journal|posts)\b.*?<\/\1>/i.test(html);
581
+ // Check for article structure with a date that isn't just a copyright year
582
+ const hasArticle = /<article[^>]*>/i.test(html);
583
+ const hasSpecificDate = /<time[^>]*datetime=["']\d{4}-\d{2}-\d{2}/i.test(html) ||
584
+ /\b(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{1,2},?\s+\d{4}\b/i.test(html);
585
+ return hasBlogUrl || hasBlogPostingSchema || (hasArticle && hasSpecificDate) || (hasBlogHeading && hasArticle);
586
+ }
587
+ /**
588
+ * Detect if a specific page is an FAQ page
589
+ */
590
+ function detectFAQPage(html, url) {
591
+ // Check URL patterns for FAQ pages
592
+ const faqUrlPatterns = /\/(faq|faqs|frequently-asked-questions)(\/|$)/i;
593
+ const hasFAQUrl = faqUrlPatterns.test(url);
594
+ // Check for FAQ schema on this page
595
+ const hasFAQSchema = /"@type"\s*:\s*"FAQPage"/i.test(html) ||
596
+ /"@type":\s*"FAQPage"/i.test(html) ||
597
+ /itemtype="https?:\/\/schema\.org\/FAQPage"/i.test(html);
598
+ // Check for FAQ-specific headings
599
+ const hasFAQHeading = /<(h1|h2)[^>]*>.*?\b(faq|faqs|frequently asked questions)\b.*?<\/\1>/i.test(html);
600
+ // Check for multiple question/answer structures (dt/dd or details/summary)
601
+ const dtCount = (html.match(/<dt[^>]*>/gi) || []).length;
602
+ const ddCount = (html.match(/<dd[^>]*>/gi) || []).length;
603
+ const detailsCount = (html.match(/<details[^>]*>/gi) || []).length;
604
+ const hasFAQStructure = (dtCount >= 3 && ddCount >= 3) || detailsCount >= 3;
605
+ return hasFAQUrl || hasFAQSchema || (hasFAQHeading && hasFAQStructure);
606
+ }
607
+ /**
608
+ * Detect if a specific page is a LocalBusiness page (usually homepage)
609
+ */
610
+ function detectLocalBusinessPage(html, url) {
611
+ const urlObj = new URL(url);
612
+ const isHomepage = urlObj.pathname === '/' || urlObj.pathname === '';
613
+ // Check for LocalBusiness schema
614
+ const hasLocalBusinessSchema = /"@type"\s*:\s*"LocalBusiness"/i.test(html) ||
615
+ /"@type":\s*"LocalBusiness"/i.test(html) ||
616
+ /itemtype="https?:\/\/schema\.org\/LocalBusiness"/i.test(html);
617
+ return isHomepage || hasLocalBusinessSchema;
618
+ }
619
+ /**
620
+ * Detect if a specific page is a Service page
621
+ */
622
+ function detectServicePage(html, url) {
623
+ const serviceUrlPatterns = /\/services\/|\/service\/|\/capabilities\/|\/what-we-do\//i;
624
+ const hasServiceUrl = serviceUrlPatterns.test(url);
625
+ // Check for Service schema
626
+ const hasServiceSchema = /"@type"\s*:\s*"Service"/i.test(html) ||
627
+ /"@type":\s*"Service"/i.test(html) ||
628
+ /itemtype="https?:\/\/schema\.org\/Service"/i.test(html);
629
+ return hasServiceUrl || hasServiceSchema;
630
+ }
631
+ /**
632
+ * Detect if a specific page is a WebSite page (usually homepage)
633
+ */
634
+ function detectWebsitePage(html, url) {
635
+ const urlObj = new URL(url);
636
+ const isHomepage = urlObj.pathname === '/' || urlObj.pathname === '';
637
+ // Check for WebSite schema
638
+ const hasWebsiteSchema = /"@type"\s*:\s*"WebSite"/i.test(html) ||
639
+ /"@type":\s*"WebSite"/i.test(html) ||
640
+ /itemtype="https?:\/\/schema\.org\/WebSite"/i.test(html);
641
+ return isHomepage || hasWebsiteSchema;
642
+ }
515
643
  /**
516
644
  * Gzip Compression Scorer
517
645
  */
@@ -544,6 +672,49 @@ function calculateGzipCompressionScore(data) {
544
672
  }
545
673
  };
546
674
  }
675
+ /**
676
+ * Schema Detection Scorers
677
+ */
678
+ function calculateSchemaBlogPostingScore(data) {
679
+ const score = data.present ? 1 : 0;
680
+ const displayValue = data.present ? 'BlogPosting schema found' : 'BlogPosting schema not found';
681
+ return {
682
+ score,
683
+ displayValue
684
+ };
685
+ }
686
+ function calculateSchemaFAQScore(data) {
687
+ const score = data.present ? 1 : 0;
688
+ const displayValue = data.present ? 'FAQ schema found' : 'FAQ schema not found';
689
+ return {
690
+ score,
691
+ displayValue
692
+ };
693
+ }
694
+ function calculateSchemaLocalBusinessScore(data) {
695
+ const score = data.present ? 1 : 0;
696
+ const displayValue = data.present ? 'LocalBusiness schema found' : 'LocalBusiness schema not found';
697
+ return {
698
+ score,
699
+ displayValue
700
+ };
701
+ }
702
+ function calculateSchemaServicesScore(data) {
703
+ const score = data.present ? 1 : 0;
704
+ const displayValue = data.present ? 'Service schema found' : 'Service schema not found';
705
+ return {
706
+ score,
707
+ displayValue
708
+ };
709
+ }
710
+ function calculateSchemaWebsiteScore(data) {
711
+ const score = data.present ? 1 : 0;
712
+ const displayValue = data.present ? 'WebSite schema found' : 'WebSite schema not found';
713
+ return {
714
+ score,
715
+ displayValue
716
+ };
717
+ }
547
718
  /**
548
719
  * Crawl the site to discover internal pages
549
720
  */
@@ -695,6 +866,12 @@ async function analyzeSinglePage(url) {
695
866
  const html = await page.content();
696
867
  // Don't close the page here - let it be reused or closed by caller
697
868
  // await page.close();
869
+ // Detect page types
870
+ const isBlogPage = detectBlogPage(html, url);
871
+ const isFAQPage = detectFAQPage(html, url);
872
+ const isLocalBusinessPage = detectLocalBusinessPage(html, url);
873
+ const isServicePage = detectServicePage(html, url);
874
+ const isWebsitePage = detectWebsitePage(html, url);
698
875
  const audits = [];
699
876
  // Process on-page metrics from configuration
700
877
  const config = seoMetricsConfig;
@@ -703,7 +880,27 @@ async function analyzeSinglePage(url) {
703
880
  let score = 0;
704
881
  let displayValue = '';
705
882
  let details = undefined;
706
- // Use data collector and scorer if available
883
+ // Special handling for schema metrics - only check on relevant page types
884
+ if (metric.id === 'schema-blogposting') {
885
+ if (!isBlogPage)
886
+ continue;
887
+ }
888
+ else if (metric.id === 'schema-faq') {
889
+ if (!isFAQPage)
890
+ continue;
891
+ }
892
+ else if (metric.id === 'schema-localbusiness') {
893
+ if (!isLocalBusinessPage)
894
+ continue;
895
+ }
896
+ else if (metric.id === 'schema-services') {
897
+ if (!isServicePage)
898
+ continue;
899
+ }
900
+ else if (metric.id === 'schema-website') {
901
+ if (!isWebsitePage)
902
+ continue;
903
+ }
707
904
  if (metric.dataCollector && metric.scorer) {
708
905
  const collector = dataCollectors[metric.dataCollector];
709
906
  const scorer = scorers[metric.scorer];
@@ -979,9 +1176,29 @@ export async function performOnSiteSEOAnalysis(baseUrl) {
979
1176
  }
980
1177
  // Analyze each page
981
1178
  const pagesAnalyzed = [];
1179
+ const schemaResults = {
1180
+ 'schema-blogposting': [],
1181
+ 'schema-faq': [],
1182
+ 'schema-localbusiness': [],
1183
+ 'schema-services': [],
1184
+ 'schema-website': []
1185
+ };
982
1186
  for (const pageUrl of pagesToAnalyze) {
983
1187
  try {
984
1188
  const pageAnalysis = await analyzeSinglePage(pageUrl);
1189
+ // Extract and remove schema audits from page-level audits to avoid duplication
1190
+ const schemaIds = Object.keys(schemaResults);
1191
+ pageAnalysis.audits = pageAnalysis.audits.filter(audit => {
1192
+ if (schemaIds.includes(audit.id)) {
1193
+ schemaResults[audit.id].push({
1194
+ url: pageAnalysis.url,
1195
+ title: pageAnalysis.title || '',
1196
+ score: audit.score || 0
1197
+ });
1198
+ return false; // Remove from page-level audits
1199
+ }
1200
+ return true;
1201
+ });
985
1202
  pagesAnalyzed.push(pageAnalysis);
986
1203
  }
987
1204
  catch (error) {
@@ -990,6 +1207,61 @@ export async function performOnSiteSEOAnalysis(baseUrl) {
990
1207
  }
991
1208
  // Perform site-wide audits
992
1209
  const onSiteAudits = await performSiteWideAudits(baseUrl);
1210
+ // Handle Schema Metrics with specific aggregation logic
1211
+ const schemaConfigs = [
1212
+ { id: 'schema-blogposting', title: 'BlogPosting Schema', optional: true, failMsg: 'BlogPosting schema not found' },
1213
+ { id: 'schema-faq', title: 'FAQ Schema', optional: false, failMsg: 'FAQ schema not found', emptyMsg: 'No FAQ pages detected - sites should have FAQ content' },
1214
+ { id: 'schema-localbusiness', title: 'LocalBusiness Schema', optional: false, failMsg: 'LocalBusiness schema not found' },
1215
+ { id: 'schema-services', title: 'Service Schema', optional: false, failMsg: 'Service schema not found' },
1216
+ { id: 'schema-website', title: 'WebSite Schema', optional: false, failMsg: 'WebSite schema not found' }
1217
+ ];
1218
+ for (const config of schemaConfigs) {
1219
+ const results = schemaResults[config.id];
1220
+ if (results.length === 0) {
1221
+ if (config.optional) {
1222
+ // Optional and none found -> N/A (white dot)
1223
+ onSiteAudits.push({
1224
+ id: config.id,
1225
+ title: config.title,
1226
+ score: null,
1227
+ scoreDisplayMode: 'binary',
1228
+ displayValue: `No ${config.title.split(' ')[0]} pages detected`,
1229
+ category: 'on-site'
1230
+ });
1231
+ }
1232
+ else {
1233
+ // Required but none found -> 0% (red dot)
1234
+ onSiteAudits.push({
1235
+ id: config.id,
1236
+ title: config.title,
1237
+ score: 0,
1238
+ scoreDisplayMode: 'binary',
1239
+ displayValue: config.emptyMsg || `No ${config.title.split(' ')[0]} pages detected`,
1240
+ category: 'on-site'
1241
+ });
1242
+ }
1243
+ }
1244
+ else {
1245
+ const passCount = results.filter(r => r.score === 1).length;
1246
+ const totalCount = results.length;
1247
+ const score = passCount / totalCount;
1248
+ const failedPages = results.filter(r => r.score === 0).map(r => ({
1249
+ page: r.title || r.url,
1250
+ url: r.url,
1251
+ score: 0,
1252
+ displayValue: config.failMsg
1253
+ }));
1254
+ onSiteAudits.push({
1255
+ id: config.id,
1256
+ title: config.title,
1257
+ score: score,
1258
+ scoreDisplayMode: 'binary',
1259
+ displayValue: `${passCount}/${totalCount} pages pass`,
1260
+ category: 'on-site',
1261
+ details: score < 1 ? { items: failedPages } : undefined
1262
+ });
1263
+ }
1264
+ }
993
1265
  // Calculate overall score (simplified - average of all page scores)
994
1266
  let totalScore = 0;
995
1267
  let totalAudits = 0;
@@ -53,8 +53,8 @@ function restructureAuditsByType(pagesAnalyzed) {
53
53
  scoreDisplayMode: audit.scoreDisplayMode,
54
54
  displayValue: `${passCount}/${totalCount} pages pass`,
55
55
  category: audit.category,
56
- details: allPageResults.length > 0 ? {
57
- items: allPageResults
56
+ details: (overallScore !== null && overallScore < 1 && allPageResults.length > 0) ? {
57
+ items: allPageResults.filter(r => r.score !== 1) // Only show failed pages in details
58
58
  } : undefined
59
59
  };
60
60
  restructuredAudits.push(restructuredAudit);
@@ -194,14 +194,14 @@ export function SiteHealthOnSiteSEO({ siteName }) {
194
194
  return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: data.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", data.url] }), data.overallScore !== null && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "On-Site SEO Score" }), _jsxs("div", { className: "health-score-value", style: { color: getScoreColor(data.overallScore) }, children: [Math.round((data.overallScore || 0) * 100), "%"] }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
195
195
  width: `${(data.overallScore || 0) * 100}%`,
196
196
  backgroundColor: getScoreColor(data.overallScore)
197
- } }) })] }) })), aggregatedOnPageAudits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "On-Page SEO Audits" }), _jsx("div", { className: "space-y-2", children: aggregatedOnPageAudits
197
+ } }) })] }) })), aggregatedOnPageAudits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "On-Page SEO Audits" }), _jsx("div", { className: "health-audit-list", children: aggregatedOnPageAudits
198
198
  .filter(audit => audit.scoreDisplayMode !== 'notApplicable')
199
- .map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: ["(", Math.round((audit.score || 0) * 100), "%) ", audit.title] }), audit.displayValue && audit.score !== 1 && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details && audit.details.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && audit.score !== 1 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items
199
+ .map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: [audit.score === null ? '(N/A)' : `(${Math.round((audit.score || 0) * 100)}%)`, " ", audit.title] }), audit.displayValue && audit.score !== 1 && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details && audit.details.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && audit.score !== 1 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items
200
200
  .filter((item) => item.score !== 1)
201
- .map((item, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatPageIssue(item) }, idx))) }) }))] })] }, audit.id))) })] })), data.onSiteAudits.length > 0 && (_jsxs("div", { style: { marginTop: data.pagesAnalyzed.length > 0 ? '2rem' : '0' }, children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "On-Site SEO Audits" }), _jsx("div", { className: "space-y-2", children: data.onSiteAudits
201
+ .map((item, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatPageIssue(item) }, idx))) }) }))] })] }, audit.id))) })] })), data.onSiteAudits.length > 0 && (_jsxs("div", { style: { marginTop: data.pagesAnalyzed.length > 0 ? '2rem' : '0' }, children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "On-Site SEO Audits" }), _jsx("div", { className: "health-audit-list", children: data.onSiteAudits
202
202
  .filter(audit => audit.scoreDisplayMode !== 'notApplicable')
203
203
  .sort((a, b) => (b.score || 0) - (a.score || 0))
204
- .map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: ["(", Math.round((audit.score || 0) * 100), "%) ", audit.title] }), audit.displayValue && audit.score !== 1 && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details && audit.details.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && audit.score !== 1 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items
204
+ .map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: [audit.score === null ? '(N/A)' : `(${Math.round((audit.score || 0) * 100)}%)`, " ", audit.title] }), audit.displayValue && audit.score !== 1 && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details && audit.details.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && audit.score !== 1 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items
205
205
  .filter((item) => item.score !== 1)
206
206
  .map((item, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatAuditItem(item) }, idx))) }) }))] })] }, audit.id))) })] })), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(data.timestamp).toLocaleString()] })] }));
207
207
  } }));
@@ -183,7 +183,7 @@ export function SiteHealthPerformance({ siteName }) {
183
183
  return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), _jsx("div", { style: { marginBottom: '1.5rem' }, children: _jsxs("div", { className: "health-score-item", style: { width: '100%' }, children: [_jsx("div", { className: "health-score-label", children: "Performance Score" }), _jsx("div", { className: "health-score-value", style: { color: getScoreColor(siteData.scores.performance) }, children: formatScore(siteData.scores.performance) }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
184
184
  width: siteData.scores.performance !== null ? `${siteData.scores.performance * 100}%` : '0%',
185
185
  backgroundColor: siteData.scores.performance !== null ? getScoreColor(siteData.scores.performance) : '#6b7280'
186
- } }) })] }) }), ((siteData.categories.performance?.audits?.length > 0) || (siteData.categories.pwa?.audits?.length > 0)) && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Performance Opportunities" }), _jsx("div", { className: "space-y-2", children: [
186
+ } }) })] }) }), ((siteData.categories.performance?.audits?.length > 0) || (siteData.categories.pwa?.audits?.length > 0)) && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Performance Opportunities" }), _jsx("div", { className: "health-audit-list", children: [
187
187
  ...(siteData.categories.performance?.audits || []),
188
188
  ...(siteData.categories.pwa?.audits || [])
189
189
  ]
@@ -164,7 +164,7 @@ export function SiteHealthSecurity({ siteName }) {
164
164
  return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteName.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", psiData.url] }), psiData.scores['best-practices'] !== null && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "Best Practices Score" }), _jsxs("div", { className: "health-score-value", style: { color: getScoreColor(psiData.scores['best-practices']) }, children: [Math.round((psiData.scores['best-practices'] || 0) * 100), "%"] }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
165
165
  width: `${(psiData.scores['best-practices'] || 0) * 100}%`,
166
166
  backgroundColor: getScoreColor(psiData.scores['best-practices'])
167
- } }) })] }) })), psiData.categories['best-practices'] && psiData.categories['best-practices'].audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Security Best Practices" }), _jsx("div", { className: "space-y-2", children: psiData.categories['best-practices'].audits
167
+ } }) })] }) })), psiData.categories['best-practices'] && psiData.categories['best-practices'].audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Security Best Practices" }), _jsx("div", { className: "health-audit-list", children: psiData.categories['best-practices'].audits
168
168
  .filter((audit) => audit.scoreDisplayMode !== 'notApplicable')
169
169
  .sort((a, b) => (b.score || 0) - (a.score || 0))
170
170
  .slice(0, 20)
@@ -119,7 +119,7 @@ export function SiteHealthSEO({ siteName }) {
119
119
  return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), siteData.scores.seo !== null && (_jsx("div", { className: "health-score-container", children: _jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: "SEO Score" }), _jsxs("div", { className: "health-score-value", style: { color: getScoreColor(siteData.scores.seo) }, children: [Math.round((siteData.scores.seo || 0) * 100), "%"] }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
120
120
  width: `${(siteData.scores.seo || 0) * 100}%`,
121
121
  backgroundColor: getScoreColor(siteData.scores.seo)
122
- } }) })] }) })), siteData.categories.seo && siteData.categories.seo.audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "SEO Issues & Recommendations" }), _jsx("div", { className: "space-y-2", children: siteData.categories.seo.audits
122
+ } }) })] }) })), siteData.categories.seo && siteData.categories.seo.audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "SEO Issues & Recommendations" }), _jsx("div", { className: "health-audit-list", children: siteData.categories.seo.audits
123
123
  .filter((audit) => audit.scoreDisplayMode !== 'notApplicable')
124
124
  .sort((a, b) => (b.score || 0) - (a.score || 0))
125
125
  .slice(0, 20)
@@ -67,8 +67,7 @@
67
67
 
68
68
  .site-health-select select:focus {
69
69
  outline: none;
70
- ring: 2px;
71
- ring-color: var(--color-primary);
70
+ box-shadow: 0 0 0 2px var(--color-primary);
72
71
  border-color: var(--color-primary);
73
72
  }
74
73
 
@@ -418,10 +417,49 @@ td {
418
417
 
419
418
  table {
420
419
  width: 100%;
421
- table-layout: fixed;
422
420
  }
423
421
 
424
422
  th, td {
425
423
  word-wrap: break-word;
426
424
  overflow-wrap: break-word;
427
425
  }
426
+
427
+ /* Helper & Semantic classes */
428
+ .health-audit-list > * + * { margin-top: 0.5rem; }
429
+ .health-section-list > * + * { margin-top: 1rem; }
430
+
431
+ .health-text-muted { color: #9ca3af; }
432
+ .health-text-secondary { color: var(--color-text-secondary); }
433
+ .health-text-error { color: var(--color-error); }
434
+
435
+ .health-visualization-placeholder {
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ height: 16rem;
440
+ }
441
+
442
+ .health-version-tag {
443
+ display: inline-block;
444
+ padding: 0.25rem 0.5rem;
445
+ font-size: 0.75rem;
446
+ line-height: 1;
447
+ background-color: #dcfce7;
448
+ color: #166534;
449
+ border-radius: 0.25rem;
450
+ font-weight: 500;
451
+ }
452
+
453
+ .health-truncate-text {
454
+ max-width: 20rem;
455
+ white-space: nowrap;
456
+ overflow: hidden;
457
+ text-overflow: ellipsis;
458
+ display: inline-block;
459
+ }
460
+
461
+ .health-empty-state {
462
+ text-align: center;
463
+ padding: 1rem 0;
464
+ color: var(--color-text-secondary);
465
+ }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
3
+ import React, { useState } from 'react';
4
4
  import PropTypes from 'prop-types';
5
5
  import Image from 'next/image';
6
6
  import { buildCloudinaryUrl } from './cloudinary';
@@ -67,8 +67,27 @@ SmartImage.propTypes = {
67
67
  export function SmartImage(props) {
68
68
  const config = usePixelatedConfig();
69
69
  const cloudCfg = config?.cloudinary;
70
- const variant = props.variant || 'cloudinary';
70
+ // State to track current variant - only changes on actual errors (rare)
71
+ const [currentVariant, setCurrentVariant] = useState(props.variant || 'cloudinary');
72
+ const handleError = (error) => {
73
+ if (currentVariant === 'cloudinary') {
74
+ console.warn(`SmartImage: Cloudinary variant failed for "${props.src}", falling back to Next.js Image`, error);
75
+ setCurrentVariant('nextjs');
76
+ }
77
+ else if (currentVariant === 'nextjs') {
78
+ console.warn(`SmartImage: Next.js Image variant failed for "${props.src}", falling back to HTML img`, error);
79
+ setCurrentVariant('img');
80
+ }
81
+ // No more fallbacks after 'img'
82
+ };
83
+ // Reset variant if props change (different image)
84
+ React.useEffect(() => {
85
+ setCurrentVariant(props.variant || 'cloudinary');
86
+ }, [props.src, props.variant]);
87
+ const variant = currentVariant;
71
88
  const newProps = { ...props };
89
+ // Always create ref to maintain consistent hook count across re-renders
90
+ const imgRef = React.useRef(null);
72
91
  newProps.cloudinaryEnv = safeString(props.cloudinaryEnv ?? cloudCfg?.product_env);
73
92
  newProps.cloudinaryDomain = safeString(cloudCfg?.baseUrl ?? CLOUDINARY_DOMAIN);
74
93
  newProps.cloudinaryTransforms = safeString(CLOUDINARY_TRANSFORMS ?? cloudCfg?.transforms);
@@ -102,7 +121,7 @@ export function SmartImage(props) {
102
121
  });
103
122
  if (newProps.width) {
104
123
  const widths = [Math.ceil(newProps.width * 0.5), newProps.width, Math.ceil(newProps.width * 1.5), Math.ceil(newProps.width * 2)];
105
- newProps.srcSet = generateSrcSet(String(newProps.src), newProps.cloudinaryEnv, widths, {
124
+ newProps.srcSet = generateSrcSet(newProps.src, newProps.cloudinaryEnv, widths, {
106
125
  quality: newProps.quality,
107
126
  transforms: newProps.cloudinaryTransforms ?? undefined,
108
127
  cloudinaryDomain: newProps.cloudinaryDomain
@@ -111,7 +130,7 @@ export function SmartImage(props) {
111
130
  }
112
131
  else {
113
132
  const breakpoints = [320, 640, 768, 1024, 1280, 1536];
114
- newProps.srcSet = generateSrcSet(String(newProps.src), newProps.cloudinaryEnv, breakpoints, {
133
+ newProps.srcSet = generateSrcSet(newProps.src, newProps.cloudinaryEnv, breakpoints, {
115
134
  quality: newProps.quality,
116
135
  transforms: newProps.cloudinaryTransforms ?? undefined,
117
136
  cloudinaryDomain: newProps.cloudinaryDomain
@@ -135,13 +154,14 @@ export function SmartImage(props) {
135
154
  delete newProps.cloudinaryTransforms;
136
155
  if (variant !== 'img') {
137
156
  try {
138
- return (_jsx(Image, { ...newProps, src: newProps.src, alt: newProps.alt }));
157
+ return (_jsx(Image, { ...newProps, src: newProps.src, alt: newProps.alt, onError: handleError }));
139
158
  }
140
159
  catch (e) {
141
- if (typeof console !== 'undefined')
142
- console.warn('next/image unavailable, falling back to <img>', e);
160
+ console.warn(`SmartImage: Next.js Image threw exception for "${props.src}", falling back to plain img`, e);
161
+ // Force fallback to img variant
162
+ setCurrentVariant('img');
143
163
  }
144
164
  }
145
165
  /* ===== IMG VARIANT ===== */
146
- return (_jsx("img", { ...newProps, ref: React.useRef(null), alt: newProps.alt }));
166
+ return (_jsx("img", { ...newProps, ref: imgRef, alt: newProps.alt }));
147
167
  }
@@ -25,8 +25,8 @@ export function Table(props) {
25
25
  function getHeadings(data) {
26
26
  const headings = Object.keys(data[0]).map((key, i) => {
27
27
  return (props.sortable && props.sortable == true)
28
- ? _jsxs("th", { onClick: () => { sortTable(key); }, children: [key, " ", _jsx("span", { className: "sortArrow" })] }, i)
29
- : _jsx("th", { children: key }, i);
28
+ ? _jsxs("th", { onClick: () => { sortTable(key); }, children: [_jsx("span", { children: key }), " ", _jsx("span", { className: "sortArrow" })] }, i)
29
+ : _jsx("th", { children: _jsx("span", { children: key }) }, i);
30
30
  });
31
31
  return _jsx("tr", { children: headings });
32
32
  }
@@ -229,13 +229,22 @@ export function ConfigBuilder(props) {
229
229
  ...field.props,
230
230
  value: (config.visualdesign && config.visualdesign[field.props.name]) ? (config.visualdesign[field.props.name].value ?? config.visualdesign[field.props.name]) : '',
231
231
  defaultValue: (config.visualdesign && config.visualdesign[field.props.name]) ? (config.visualdesign[field.props.name].value ?? config.visualdesign[field.props.name]) : field.props.defaultValue || '',
232
- onChange: (event) => {
233
- const value = event.target.value;
232
+ onChange: (value) => {
233
+ // Handle both direct values and event objects
234
+ let actualValue = value;
235
+ if (value && typeof value === 'object' && value.target) {
236
+ actualValue = value.target.value;
237
+ }
234
238
  setConfig((prev) => ({
235
239
  ...prev,
236
240
  visualdesign: {
237
241
  ...(prev.visualdesign || {}),
238
- [field.props.name]: { value }
242
+ [field.props.name]: {
243
+ ...(prev.visualdesign && prev.visualdesign[field.props.name]
244
+ ? prev.visualdesign[field.props.name]
245
+ : {}),
246
+ value: actualValue
247
+ }
239
248
  }
240
249
  }));
241
250
  }
@@ -1 +1 @@
1
- {"version":3,"file":"site-health-on-site-seo.integration.d.ts","sourceRoot":"","sources":["../../../../../src/components/admin/site-health/site-health-on-site-seo.integration.ts"],"names":[],"mappings":"AAknBA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,QAAQ,GAAG,eAAe,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACxC,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8bD;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAwFtF"}
1
+ {"version":3,"file":"site-health-on-site-seo.integration.d.ts","sourceRoot":"","sources":["../../../../../src/components/admin/site-health/site-health-on-site-seo.integration.ts"],"names":[],"mappings":"AAq0BA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,QAAQ,GAAG,eAAe,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACxC,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAidD;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAwKtF"}
@@ -1 +1 @@
1
- {"version":3,"file":"smartimage.d.ts","sourceRoot":"","sources":["../../../../src/components/cms/smartimage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA0EnD,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;AACjH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,2CAwG/C;yBAxGe,UAAU"}
1
+ {"version":3,"file":"smartimage.d.ts","sourceRoot":"","sources":["../../../../src/components/cms/smartimage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA4EnD,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;AACjH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,2CAoI/C;yBApIe,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/components/sitebuilder/config/ConfigBuilder.tsx"],"names":[],"mappings":"AAGA,OAAO,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAYnD,OAAO,qBAAqB,CAAC;AAE7B,QAAA,MAAM,cAAc;;;;;;;CAOnB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BtB,CAAC;AACF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AA+ChE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,2CAgnBrD;yBAhnBe,aAAa"}
1
+ {"version":3,"file":"ConfigBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/components/sitebuilder/config/ConfigBuilder.tsx"],"names":[],"mappings":"AAGA,OAAO,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAYnD,OAAO,qBAAqB,CAAC;AAE7B,QAAA,MAAM,cAAc;;;;;;;CAOnB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BtB,CAAC;AACF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AA+ChE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,2CA0nBrD;yBA1nBe,aAAa"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-seo-logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-seo-logic.d.ts","sourceRoot":"","sources":["../../../src/tests/test-seo-logic.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixelated-tech/components",
3
- "version": "3.5.12",
3
+ "version": "3.5.13",
4
4
  "private": false,
5
5
  "author": {
6
6
  "name": "Pixelated Technologies",
@@ -116,8 +116,8 @@
116
116
  "@types/prop-types": "^15.7.15",
117
117
  "@types/react": "^19.2.7",
118
118
  "@types/react-dom": "^19.2.3",
119
- "@typescript-eslint/eslint-plugin": "^8.51.0",
120
- "@typescript-eslint/parser": "^8.51.0",
119
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
120
+ "@typescript-eslint/parser": "^8.52.0",
121
121
  "@vitejs/plugin-react": "^5.1.2",
122
122
  "@vitest/coverage-v8": "^4.0.16",
123
123
  "@vitest/ui": "^4.0.16",
@@ -146,7 +146,7 @@
146
146
  "react": "^19.2.3",
147
147
  "react-dom": "^19.2.3",
148
148
  "react-test-renderer": "^19.2.3",
149
- "sass": "^1.97.1",
149
+ "sass": "^1.97.2",
150
150
  "sass-loader": "^16.0.6",
151
151
  "storybook": "^10.1.11",
152
152
  "style-loader": "^4.0.0",