@prenta/admin 0.92.0 → 0.93.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/CHANGELOG.md +552 -0
- package/design-system/tokens.css +173 -71
- package/design-system/tokens.json +244 -63
- package/design-system/tokens.scss +203 -98
- package/design-system/tokens.tailwind.cjs +93 -38
- package/dist/AdminRoot.d.ts +27 -6
- package/dist/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/components/breakpoint-controls.render.test.d.ts +2 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.js +51 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.js.map +1 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.d.ts +2 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.js +37 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.js.map +1 -0
- package/dist/__tests__/components/editor-rail.render.test.d.ts +2 -0
- package/dist/__tests__/components/editor-rail.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/editor-rail.render.test.js +138 -0
- package/dist/__tests__/components/editor-rail.render.test.js.map +1 -0
- package/dist/__tests__/components/media-block.render.test.d.ts +2 -0
- package/dist/__tests__/components/media-block.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/media-block.render.test.js +108 -0
- package/dist/__tests__/components/media-block.render.test.js.map +1 -0
- package/dist/__tests__/components/page-audit-panel.render.test.d.ts +2 -0
- package/dist/__tests__/components/page-audit-panel.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/page-audit-panel.render.test.js +59 -0
- package/dist/__tests__/components/page-audit-panel.render.test.js.map +1 -0
- package/dist/__tests__/components/reflow-meter.render.test.d.ts +2 -0
- package/dist/__tests__/components/reflow-meter.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/reflow-meter.render.test.js +94 -0
- package/dist/__tests__/components/reflow-meter.render.test.js.map +1 -0
- package/dist/__tests__/components/seo-char-count.test.js +24 -6
- package/dist/__tests__/components/seo-char-count.test.js.map +1 -1
- package/dist/__tests__/components/serp-preview.render.test.d.ts +2 -0
- package/dist/__tests__/components/serp-preview.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/serp-preview.render.test.js +25 -0
- package/dist/__tests__/components/serp-preview.render.test.js.map +1 -0
- package/dist/__tests__/lib/breakpoints.test.d.ts +2 -0
- package/dist/__tests__/lib/breakpoints.test.d.ts.map +1 -0
- package/dist/__tests__/lib/breakpoints.test.js +67 -0
- package/dist/__tests__/lib/breakpoints.test.js.map +1 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.d.ts +2 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.d.ts.map +1 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.js +44 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.js.map +1 -0
- package/dist/__tests__/lib/media-format.test.d.ts +2 -0
- package/dist/__tests__/lib/media-format.test.d.ts.map +1 -0
- package/dist/__tests__/lib/media-format.test.js +70 -0
- package/dist/__tests__/lib/media-format.test.js.map +1 -0
- package/dist/__tests__/lib/page-audit-input.test.d.ts +2 -0
- package/dist/__tests__/lib/page-audit-input.test.d.ts.map +1 -0
- package/dist/__tests__/lib/page-audit-input.test.js +122 -0
- package/dist/__tests__/lib/page-audit-input.test.js.map +1 -0
- package/dist/__tests__/lib/page-editor-service.test.js +2 -0
- package/dist/__tests__/lib/page-editor-service.test.js.map +1 -1
- package/dist/__tests__/lib/page-redirect.test.d.ts +2 -0
- package/dist/__tests__/lib/page-redirect.test.d.ts.map +1 -0
- package/dist/__tests__/lib/page-redirect.test.js +26 -0
- package/dist/__tests__/lib/page-redirect.test.js.map +1 -0
- package/dist/__tests__/lib/rail-width.test.d.ts +2 -0
- package/dist/__tests__/lib/rail-width.test.d.ts.map +1 -0
- package/dist/__tests__/lib/rail-width.test.js +69 -0
- package/dist/__tests__/lib/rail-width.test.js.map +1 -0
- package/dist/__tests__/lib/reflow-baseline.test.d.ts +2 -0
- package/dist/__tests__/lib/reflow-baseline.test.d.ts.map +1 -0
- package/dist/__tests__/lib/reflow-baseline.test.js +56 -0
- package/dist/__tests__/lib/reflow-baseline.test.js.map +1 -0
- package/dist/__tests__/lib/reflow-probe.test.d.ts +2 -0
- package/dist/__tests__/lib/reflow-probe.test.d.ts.map +1 -0
- package/dist/__tests__/lib/reflow-probe.test.js +73 -0
- package/dist/__tests__/lib/reflow-probe.test.js.map +1 -0
- package/dist/__tests__/styles/canvas-container-queries.test.d.ts +2 -0
- package/dist/__tests__/styles/canvas-container-queries.test.d.ts.map +1 -0
- package/dist/__tests__/styles/canvas-container-queries.test.js +87 -0
- package/dist/__tests__/styles/canvas-container-queries.test.js.map +1 -0
- package/dist/__tests__/styles/packaging.test.d.ts +2 -0
- package/dist/__tests__/styles/packaging.test.d.ts.map +1 -0
- package/dist/__tests__/styles/packaging.test.js +31 -0
- package/dist/__tests__/styles/packaging.test.js.map +1 -0
- package/dist/__tests__/styles/tokens-drift.test.d.ts +2 -0
- package/dist/__tests__/styles/tokens-drift.test.d.ts.map +1 -0
- package/dist/__tests__/styles/tokens-drift.test.js +92 -0
- package/dist/__tests__/styles/tokens-drift.test.js.map +1 -0
- package/dist/__tests__/views/admin-renderer-compat.test.d.ts +2 -0
- package/dist/__tests__/views/admin-renderer-compat.test.d.ts.map +1 -0
- package/dist/__tests__/views/admin-renderer-compat.test.js +43 -0
- package/dist/__tests__/views/admin-renderer-compat.test.js.map +1 -0
- package/dist/__tests__/views/admin-section-renderers.test.js +52 -4
- package/dist/__tests__/views/admin-section-renderers.test.js.map +1 -1
- package/dist/__tests__/views/editor-top-bar.render.test.js +1 -1
- package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
- package/dist/__tests__/views/page-tab.render.test.d.ts +2 -0
- package/dist/__tests__/views/page-tab.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/page-tab.render.test.js +151 -0
- package/dist/__tests__/views/page-tab.render.test.js.map +1 -0
- package/dist/__tests__/views/section-class-parity.test.d.ts +2 -0
- package/dist/__tests__/views/section-class-parity.test.d.ts.map +1 -0
- package/dist/__tests__/views/section-class-parity.test.js +81 -0
- package/dist/__tests__/views/section-class-parity.test.js.map +1 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.d.ts +2 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.js +86 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.js.map +1 -0
- package/dist/components/BreakpointPicker.d.ts +18 -0
- package/dist/components/BreakpointPicker.d.ts.map +1 -0
- package/dist/components/BreakpointPicker.js +31 -0
- package/dist/components/BreakpointPicker.js.map +1 -0
- package/dist/components/CanvasEditTip.d.ts +6 -0
- package/dist/components/CanvasEditTip.d.ts.map +1 -0
- package/dist/components/CanvasEditTip.js +22 -0
- package/dist/components/CanvasEditTip.js.map +1 -0
- package/dist/components/EditorRail.d.ts +36 -0
- package/dist/components/EditorRail.d.ts.map +1 -0
- package/dist/components/EditorRail.js +104 -0
- package/dist/components/EditorRail.js.map +1 -0
- package/dist/components/EditorRailTabs.d.ts +32 -0
- package/dist/components/EditorRailTabs.d.ts.map +1 -0
- package/dist/components/EditorRailTabs.js +45 -0
- package/dist/components/EditorRailTabs.js.map +1 -0
- package/dist/components/MediaBlock.d.ts +49 -0
- package/dist/components/MediaBlock.d.ts.map +1 -0
- package/dist/components/MediaBlock.js +50 -0
- package/dist/components/MediaBlock.js.map +1 -0
- package/dist/components/ReflowMeter.d.ts +28 -0
- package/dist/components/ReflowMeter.d.ts.map +1 -0
- package/dist/components/ReflowMeter.js +42 -0
- package/dist/components/ReflowMeter.js.map +1 -0
- package/dist/components/ZoomChip.d.ts +17 -0
- package/dist/components/ZoomChip.d.ts.map +1 -0
- package/dist/components/ZoomChip.js +17 -0
- package/dist/components/ZoomChip.js.map +1 -0
- package/dist/components/breakpoint-icons.d.ts +3 -0
- package/dist/components/breakpoint-icons.d.ts.map +1 -0
- package/dist/components/breakpoint-icons.js +16 -0
- package/dist/components/breakpoint-icons.js.map +1 -0
- package/dist/components/page-tab/AuthorPicker.d.ts +31 -0
- package/dist/components/page-tab/AuthorPicker.d.ts.map +1 -0
- package/dist/components/page-tab/AuthorPicker.js +95 -0
- package/dist/components/page-tab/AuthorPicker.js.map +1 -0
- package/dist/components/page-tab/DirectiveSwitch.d.ts +38 -0
- package/dist/components/page-tab/DirectiveSwitch.d.ts.map +1 -0
- package/dist/components/page-tab/DirectiveSwitch.js +29 -0
- package/dist/components/page-tab/DirectiveSwitch.js.map +1 -0
- package/dist/components/seo/EditorSeoScoreBadge.d.ts +8 -1
- package/dist/components/seo/EditorSeoScoreBadge.d.ts.map +1 -1
- package/dist/components/seo/EditorSeoScoreBadge.js +2 -2
- package/dist/components/seo/EditorSeoScoreBadge.js.map +1 -1
- package/dist/components/seo/PageAuditPanel.d.ts +14 -0
- package/dist/components/seo/PageAuditPanel.d.ts.map +1 -0
- package/dist/components/seo/PageAuditPanel.js +59 -0
- package/dist/components/seo/PageAuditPanel.js.map +1 -0
- package/dist/components/seo/SeoCharCount.d.ts +19 -7
- package/dist/components/seo/SeoCharCount.d.ts.map +1 -1
- package/dist/components/seo/SeoCharCount.js +30 -16
- package/dist/components/seo/SeoCharCount.js.map +1 -1
- package/dist/components/seo/SeoEditorPane.d.ts +15 -1
- package/dist/components/seo/SeoEditorPane.d.ts.map +1 -1
- package/dist/components/seo/SeoEditorPane.js +118 -21
- package/dist/components/seo/SeoEditorPane.js.map +1 -1
- package/dist/components/seo/SerpPreview.d.ts +20 -0
- package/dist/components/seo/SerpPreview.d.ts.map +1 -0
- package/dist/components/seo/SerpPreview.js +6 -0
- package/dist/components/seo/SerpPreview.js.map +1 -0
- package/dist/hooks/usePageAudit.d.ts +41 -0
- package/dist/hooks/usePageAudit.d.ts.map +1 -0
- package/dist/hooks/usePageAudit.js +68 -0
- package/dist/hooks/usePageAudit.js.map +1 -0
- package/dist/hooks/useReflowGuard.d.ts +47 -0
- package/dist/hooks/useReflowGuard.d.ts.map +1 -0
- package/dist/hooks/useReflowGuard.js +52 -0
- package/dist/hooks/useReflowGuard.js.map +1 -0
- package/dist/lib/breakpoints.d.ts +51 -0
- package/dist/lib/breakpoints.d.ts.map +1 -0
- package/dist/lib/breakpoints.js +84 -0
- package/dist/lib/breakpoints.js.map +1 -0
- package/dist/lib/canvas-edit-chrome.d.ts +22 -0
- package/dist/lib/canvas-edit-chrome.d.ts.map +1 -0
- package/dist/lib/canvas-edit-chrome.js +81 -0
- package/dist/lib/canvas-edit-chrome.js.map +1 -0
- package/dist/lib/media-format.d.ts +55 -0
- package/dist/lib/media-format.d.ts.map +1 -0
- package/dist/lib/media-format.js +93 -0
- package/dist/lib/media-format.js.map +1 -0
- package/dist/lib/page-audit-input.d.ts +45 -0
- package/dist/lib/page-audit-input.d.ts.map +1 -0
- package/dist/lib/page-audit-input.js +53 -0
- package/dist/lib/page-audit-input.js.map +1 -0
- package/dist/lib/page-editor-service.d.ts +12 -0
- package/dist/lib/page-editor-service.d.ts.map +1 -1
- package/dist/lib/page-editor-service.js +6 -0
- package/dist/lib/page-editor-service.js.map +1 -1
- package/dist/lib/page-redirect.d.ts +39 -0
- package/dist/lib/page-redirect.d.ts.map +1 -0
- package/dist/lib/page-redirect.js +38 -0
- package/dist/lib/page-redirect.js.map +1 -0
- package/dist/lib/rail-width.d.ts +23 -0
- package/dist/lib/rail-width.d.ts.map +1 -0
- package/dist/lib/rail-width.js +59 -0
- package/dist/lib/rail-width.js.map +1 -0
- package/dist/lib/reflow-baseline.d.ts +45 -0
- package/dist/lib/reflow-baseline.d.ts.map +1 -0
- package/dist/lib/reflow-baseline.js +38 -0
- package/dist/lib/reflow-baseline.js.map +1 -0
- package/dist/lib/reflow-probe.d.ts +159 -0
- package/dist/lib/reflow-probe.d.ts.map +1 -0
- package/dist/lib/reflow-probe.js +228 -0
- package/dist/lib/reflow-probe.js.map +1 -0
- package/dist/lib/seo-service.d.ts +10 -0
- package/dist/lib/seo-service.d.ts.map +1 -1
- package/dist/lib/seo-service.js.map +1 -1
- package/dist/prenta-admin.css +1 -1
- package/dist/views/page-editor/CanvasMetaLine.d.ts +19 -0
- package/dist/views/page-editor/CanvasMetaLine.d.ts.map +1 -0
- package/dist/views/page-editor/CanvasMetaLine.js +23 -0
- package/dist/views/page-editor/CanvasMetaLine.js.map +1 -0
- package/dist/views/page-editor/EditorCanvas.d.ts +34 -8
- package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
- package/dist/views/page-editor/EditorCanvas.js +68 -34
- package/dist/views/page-editor/EditorCanvas.js.map +1 -1
- package/dist/views/page-editor/EditorTopBar.d.ts +14 -1
- package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
- package/dist/views/page-editor/EditorTopBar.js +8 -17
- package/dist/views/page-editor/EditorTopBar.js.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.js +275 -53
- package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
- package/dist/views/page-editor/PageTab.d.ts +36 -0
- package/dist/views/page-editor/PageTab.d.ts.map +1 -0
- package/dist/views/page-editor/PageTab.js +65 -0
- package/dist/views/page-editor/PageTab.js.map +1 -0
- package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
- package/dist/views/page-editor/SectionInspector.js +63 -19
- package/dist/views/page-editor/SectionInspector.js.map +1 -1
- package/dist/views/page-editor/SectionsPanel.d.ts +30 -5
- package/dist/views/page-editor/SectionsPanel.d.ts.map +1 -1
- package/dist/views/page-editor/SectionsPanel.js +38 -7
- package/dist/views/page-editor/SectionsPanel.js.map +1 -1
- package/dist/views/page-editor/SitePreviewFrame.d.ts.map +1 -1
- package/dist/views/page-editor/SitePreviewFrame.js +3 -0
- package/dist/views/page-editor/SitePreviewFrame.js.map +1 -1
- package/dist/views/page-editor/reflow-context.d.ts +28 -0
- package/dist/views/page-editor/reflow-context.d.ts.map +1 -0
- package/dist/views/page-editor/reflow-context.js +14 -0
- package/dist/views/page-editor/reflow-context.js.map +1 -0
- package/dist/views/page-editor/sections/ByTheNumbersSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js.map +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.js +2 -2
- package/dist/views/page-editor/sections/FeatureHighlightSection.js.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.js +7 -3
- package/dist/views/page-editor/sections/GallerySection.js.map +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.js +1 -1
- package/dist/views/page-editor/sections/MissionSection.js.map +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js.map +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js +49 -24
- package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
- package/dist/views/page-editor/sections/admin-renderers.d.ts +47 -15
- package/dist/views/page-editor/sections/admin-renderers.d.ts.map +1 -1
- package/dist/views/page-editor/sections/admin-renderers.js +27 -15
- package/dist/views/page-editor/sections/admin-renderers.js.map +1 -1
- package/dist/views/page-editor/sections/parts.d.ts +0 -1
- package/dist/views/page-editor/sections/parts.d.ts.map +1 -1
- package/dist/views/page-editor/sections/parts.js +41 -16
- package/dist/views/page-editor/sections/parts.js.map +1 -1
- package/dist/views/page-editor/viewports.d.ts +7 -14
- package/dist/views/page-editor/viewports.d.ts.map +1 -1
- package/dist/views/page-editor/viewports.js +7 -12
- package/dist/views/page-editor/viewports.js.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.d.ts +2 -1
- package/dist/views/post-editor/PostEditorCanvas.d.ts.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.js +5 -2
- package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.js +2 -20
- package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.js +4 -1
- package/dist/views/post-editor/PostTemplateEditor.js.map +1 -1
- package/package.json +5 -3
- package/src/AdminRoot.tsx +27 -6
- package/src/__tests__/components/breakpoint-controls.render.test.tsx +57 -0
- package/src/__tests__/components/canvas-edit-tip.render.test.tsx +41 -0
- package/src/__tests__/components/editor-rail.render.test.tsx +192 -0
- package/src/__tests__/components/media-block.render.test.tsx +126 -0
- package/src/__tests__/components/page-audit-panel.render.test.tsx +64 -0
- package/src/__tests__/components/reflow-meter.render.test.tsx +144 -0
- package/src/__tests__/components/seo-char-count.test.tsx +26 -6
- package/src/__tests__/components/serp-preview.render.test.tsx +32 -0
- package/src/__tests__/lib/breakpoints.test.ts +84 -0
- package/src/__tests__/lib/canvas-edit-chrome.test.ts +56 -0
- package/src/__tests__/lib/media-format.test.ts +89 -0
- package/src/__tests__/lib/page-audit-input.test.ts +144 -0
- package/src/__tests__/lib/page-editor-service.test.ts +2 -0
- package/src/__tests__/lib/page-redirect.test.ts +29 -0
- package/src/__tests__/lib/rail-width.test.ts +86 -0
- package/src/__tests__/lib/reflow-baseline.test.ts +64 -0
- package/src/__tests__/lib/reflow-probe.test.ts +95 -0
- package/src/__tests__/styles/canvas-container-queries.test.ts +103 -0
- package/src/__tests__/styles/packaging.test.ts +38 -0
- package/src/__tests__/styles/tokens-drift.test.ts +110 -0
- package/src/__tests__/views/admin-renderer-compat.test.ts +48 -0
- package/src/__tests__/views/admin-section-renderers.test.tsx +70 -4
- package/src/__tests__/views/editor-top-bar.render.test.tsx +1 -1
- package/src/__tests__/views/page-tab.render.test.tsx +226 -0
- package/src/__tests__/views/section-class-parity.test.ts +98 -0
- package/src/__tests__/views/sections-panel-design-owned.render.test.tsx +104 -0
- package/src/components/BreakpointPicker.tsx +114 -0
- package/src/components/CanvasEditTip.tsx +46 -0
- package/src/components/EditorRail.tsx +219 -0
- package/src/components/EditorRailTabs.tsx +117 -0
- package/src/components/MediaBlock.tsx +223 -0
- package/src/components/ReflowMeter.tsx +125 -0
- package/src/components/ZoomChip.tsx +39 -0
- package/src/components/breakpoint-icons.ts +17 -0
- package/src/components/page-tab/AuthorPicker.tsx +240 -0
- package/src/components/page-tab/DirectiveSwitch.tsx +86 -0
- package/src/components/seo/EditorSeoScoreBadge.tsx +9 -1
- package/src/components/seo/PageAuditPanel.tsx +192 -0
- package/src/components/seo/SeoCharCount.tsx +55 -24
- package/src/components/seo/SeoEditorPane.tsx +213 -31
- package/src/components/seo/SerpPreview.tsx +41 -0
- package/src/hooks/usePageAudit.ts +98 -0
- package/src/hooks/useReflowGuard.ts +96 -0
- package/src/lib/breakpoints.ts +107 -0
- package/src/lib/canvas-edit-chrome.ts +82 -0
- package/src/lib/media-format.ts +99 -0
- package/src/lib/page-audit-input.ts +104 -0
- package/src/lib/page-editor-service.ts +18 -0
- package/src/lib/page-redirect.ts +60 -0
- package/src/lib/rail-width.ts +58 -0
- package/src/lib/reflow-baseline.ts +70 -0
- package/src/lib/reflow-probe.ts +299 -0
- package/src/lib/seo-service.ts +10 -0
- package/src/styles/prenta-tokens.css +120 -42
- package/src/styles/theme.css +130 -0
- package/src/views/page-editor/CanvasMetaLine.tsx +50 -0
- package/src/views/page-editor/EditorCanvas.tsx +109 -50
- package/src/views/page-editor/EditorTopBar.tsx +35 -43
- package/src/views/page-editor/PageSectionEditor.tsx +419 -148
- package/src/views/page-editor/PageTab.tsx +433 -0
- package/src/views/page-editor/SectionInspector.tsx +82 -41
- package/src/views/page-editor/SectionsPanel.tsx +281 -140
- package/src/views/page-editor/SitePreviewFrame.tsx +3 -0
- package/src/views/page-editor/reflow-context.ts +43 -0
- package/src/views/page-editor/sections/ByTheNumbersSection.tsx +3 -2
- package/src/views/page-editor/sections/CtaBannerSection.tsx +3 -1
- package/src/views/page-editor/sections/FeatureHighlightSection.tsx +3 -2
- package/src/views/page-editor/sections/GallerySection.tsx +7 -3
- package/src/views/page-editor/sections/HeroBannerSection.tsx +2 -2
- package/src/views/page-editor/sections/MissionSection.tsx +4 -2
- package/src/views/page-editor/sections/PullQuoteSection.tsx +3 -1
- package/src/views/page-editor/sections/RelatedPostsSection.tsx +2 -1
- package/src/views/page-editor/sections/SectionRenderer.tsx +69 -29
- package/src/views/page-editor/sections/admin-renderers.tsx +54 -15
- package/src/views/page-editor/sections/parts.tsx +46 -18
- package/src/views/page-editor/viewports.ts +13 -26
- package/src/views/post-editor/PostEditorCanvas.tsx +18 -11
- package/src/views/post-editor/PostSectionEditor.tsx +1 -56
- package/src/views/post-editor/PostTemplateEditor.tsx +3 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { probeFieldReflow, reflowSeverity, worstBreakpoint, } from '../lib/reflow-probe.js';
|
|
4
|
+
const EMPTY = { rows: [], grown: [], worst: null, delta: 0 };
|
|
5
|
+
/**
|
|
6
|
+
* Measures how one field wraps at every breakpoint, and how that compares to
|
|
7
|
+
* what is published.
|
|
8
|
+
*
|
|
9
|
+
* ── Why it runs on a delay ────────────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* A pass clones the canvas and lays it out twelve times (six widths, current
|
|
12
|
+
* and published). That is far too much to do per keystroke, and it is also
|
|
13
|
+
* pointless — mid-word text tells an editor nothing. So it settles first.
|
|
14
|
+
*
|
|
15
|
+
* `null` from the probe means the field is not measurable: the section may be
|
|
16
|
+
* rendered by a consumer's own component that carries no `data-cms-field`
|
|
17
|
+
* markers. The guard then reports nothing rather than a number read off the
|
|
18
|
+
* wrong element — an editor treats a line count as a fact, and a confident
|
|
19
|
+
* wrong one is worse than a blank.
|
|
20
|
+
*/
|
|
21
|
+
export function useReflowGuard(options) {
|
|
22
|
+
const { canvas, sectionId, fieldPath, value, baseline, enabled = true, delayMs = 200 } = options;
|
|
23
|
+
const [result, setResult] = useState(EMPTY);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!enabled || !canvas) {
|
|
26
|
+
setResult(EMPTY);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const timer = setTimeout(() => {
|
|
30
|
+
const probed = probeFieldReflow({ canvas, sectionId, fieldPath, baselineText: baseline });
|
|
31
|
+
if (!probed) {
|
|
32
|
+
setResult(EMPTY);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const rows = probed.current.map((row) => {
|
|
36
|
+
const was = probed.baseline.find((b) => b.id === row.id)?.lines ?? row.lines;
|
|
37
|
+
return { ...row, was, diff: row.lines - was, state: reflowSeverity(row.lines, was) };
|
|
38
|
+
});
|
|
39
|
+
setResult({
|
|
40
|
+
rows,
|
|
41
|
+
grown: rows.filter((r) => r.diff > 0),
|
|
42
|
+
worst: worstBreakpoint(probed.current, probed.baseline),
|
|
43
|
+
delta: baseline === undefined ? 0 : value.length - baseline.length,
|
|
44
|
+
});
|
|
45
|
+
}, delayMs);
|
|
46
|
+
return () => clearTimeout(timer);
|
|
47
|
+
// `value` is a dependency because the canvas re-renders as it changes —
|
|
48
|
+
// the probe reads the resulting DOM rather than the string itself.
|
|
49
|
+
}, [canvas, sectionId, fieldPath, value, baseline, enabled, delayMs]);
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=useReflowGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReflowGuard.js","sourceRoot":"","sources":["../../src/hooks/useReflowGuard.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,eAAe,GAGhB,MAAM,wBAAwB,CAAA;AAoB/B,MAAM,KAAK,GAAsB,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,OAW9B;IACC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,GAAG,EAAE,GAAG,OAAO,CAAA;IAChG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB,KAAK,CAAC,CAAA;IAE9D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,SAAS,CAAC,KAAK,CAAC,CAAA;YAChB,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAA;YACzF,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,SAAS,CAAC,KAAK,CAAC,CAAA;gBAChB,OAAM;YACR,CAAC;YAED,MAAM,IAAI,GAAgB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBACnD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC,KAAK,CAAA;gBAC5E,OAAO,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAA;YACtF,CAAC,CAAC,CAAA;YAEF,SAAS,CAAC;gBACR,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;gBACrC,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC;gBACvD,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM;aACnE,CAAC,CAAA;QACJ,CAAC,EAAE,OAAO,CAAC,CAAA;QAEX,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAChC,wEAAwE;QACxE,mEAAmE;IACrE,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAErE,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breakpoint presets for the editor canvas — shared by the page editor, the
|
|
3
|
+
* post editor, and the site-preview frame.
|
|
4
|
+
*
|
|
5
|
+
* Each entry's `width` is the **real CSS width** the canvas renders at. The
|
|
6
|
+
* canvas is then scaled down with a transform to fit the available column, so
|
|
7
|
+
* the page reflows against its own width via container queries rather than
|
|
8
|
+
* being squeezed by a max-width clamp. A clamp does not reflow: it produces a
|
|
9
|
+
* narrow desktop layout, not the mobile layout.
|
|
10
|
+
*
|
|
11
|
+
* `4k` is 2560, not 3840. 2560 is the CSS width a 4K/Retina display reports
|
|
12
|
+
* once device-pixel-ratio is applied; 3840 is the physical pixel count and no
|
|
13
|
+
* stylesheet ever sees it. It is also the only preset above the canvas's
|
|
14
|
+
* `min-width: 2000px` container step, so it is the only one that exercises
|
|
15
|
+
* that branch.
|
|
16
|
+
*/
|
|
17
|
+
export type BreakpointId = '4k' | 'wide' | 'laptop' | 'tabletL' | 'tabletP' | 'mobile';
|
|
18
|
+
export type BreakpointGroup = 'DESKTOP' | 'TABLET' | 'MOBILE';
|
|
19
|
+
export interface Breakpoint {
|
|
20
|
+
id: BreakpointId;
|
|
21
|
+
/** Full name, shown in the picker menu. */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Two-letter form for the collapsed trigger. */
|
|
24
|
+
abbr: string;
|
|
25
|
+
/** lucide-react icon name */
|
|
26
|
+
icon: string;
|
|
27
|
+
/** Real CSS width of the preview surface, in px. */
|
|
28
|
+
width: number;
|
|
29
|
+
group: BreakpointGroup;
|
|
30
|
+
}
|
|
31
|
+
export declare const BREAKPOINTS: readonly Breakpoint[];
|
|
32
|
+
/** Menu order. Groups render as labelled sections in the breakpoint picker. */
|
|
33
|
+
export declare const BREAKPOINT_GROUPS: readonly BreakpointGroup[];
|
|
34
|
+
export declare const DEFAULT_BREAKPOINT: BreakpointId;
|
|
35
|
+
export declare function getBreakpoint(id: BreakpointId): Breakpoint;
|
|
36
|
+
export declare function breakpointsInGroup(group: BreakpointGroup): Breakpoint[];
|
|
37
|
+
export declare function coerceBreakpointId(value: unknown): BreakpointId;
|
|
38
|
+
export type Zoom = 'fit' | 1;
|
|
39
|
+
/**
|
|
40
|
+
* Scale factor for the canvas transform.
|
|
41
|
+
*
|
|
42
|
+
* `available` must come from a zero-height sentinel measured inside the canvas
|
|
43
|
+
* panel — NOT from `panel.clientWidth - padding`. The two disagree whenever the
|
|
44
|
+
* host scales the preview or a scrollbar appears, and the padding arithmetic is
|
|
45
|
+
* the kind that silently rots when the gutter changes.
|
|
46
|
+
*
|
|
47
|
+
* Never scales above 1: a 390px mobile canvas blown up to fill a 1200px column
|
|
48
|
+
* would show text at 3× the size the visitor sees.
|
|
49
|
+
*/
|
|
50
|
+
export declare function fitScale(available: number, width: number, zoom?: Zoom): number;
|
|
51
|
+
//# sourceMappingURL=breakpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breakpoints.d.ts","sourceRoot":"","sources":["../../src/lib/breakpoints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEtF,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE7D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,YAAY,CAAA;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,eAAe,CAAA;CACvB;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,UAAU,EAqB5C,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAAoC,CAAA;AAE5F,eAAO,MAAM,kBAAkB,EAAE,YAAqB,CAAA;AAItD,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,UAAU,CAE1D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,UAAU,EAAE,CAEvE;AAaD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAI/D;AAED,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAA;AAE5B;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAY,GAAG,MAAM,CAIrF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breakpoint presets for the editor canvas — shared by the page editor, the
|
|
3
|
+
* post editor, and the site-preview frame.
|
|
4
|
+
*
|
|
5
|
+
* Each entry's `width` is the **real CSS width** the canvas renders at. The
|
|
6
|
+
* canvas is then scaled down with a transform to fit the available column, so
|
|
7
|
+
* the page reflows against its own width via container queries rather than
|
|
8
|
+
* being squeezed by a max-width clamp. A clamp does not reflow: it produces a
|
|
9
|
+
* narrow desktop layout, not the mobile layout.
|
|
10
|
+
*
|
|
11
|
+
* `4k` is 2560, not 3840. 2560 is the CSS width a 4K/Retina display reports
|
|
12
|
+
* once device-pixel-ratio is applied; 3840 is the physical pixel count and no
|
|
13
|
+
* stylesheet ever sees it. It is also the only preset above the canvas's
|
|
14
|
+
* `min-width: 2000px` container step, so it is the only one that exercises
|
|
15
|
+
* that branch.
|
|
16
|
+
*/
|
|
17
|
+
export const BREAKPOINTS = [
|
|
18
|
+
{ id: '4k', name: '4K / Retina', abbr: '4K', icon: 'monitor', width: 2560, group: 'DESKTOP' },
|
|
19
|
+
{ id: 'wide', name: 'Wide Screen', abbr: 'WS', icon: 'monitor', width: 1920, group: 'DESKTOP' },
|
|
20
|
+
{ id: 'laptop', name: 'Laptop', abbr: 'LT', icon: 'laptop', width: 1440, group: 'DESKTOP' },
|
|
21
|
+
{
|
|
22
|
+
id: 'tabletL',
|
|
23
|
+
name: 'Tablet Landscape',
|
|
24
|
+
abbr: 'TL',
|
|
25
|
+
icon: 'tablet',
|
|
26
|
+
width: 1024,
|
|
27
|
+
group: 'TABLET',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'tabletP',
|
|
31
|
+
name: 'Tablet Portrait',
|
|
32
|
+
abbr: 'TP',
|
|
33
|
+
icon: 'tablet',
|
|
34
|
+
width: 768,
|
|
35
|
+
group: 'TABLET',
|
|
36
|
+
},
|
|
37
|
+
{ id: 'mobile', name: 'Mobile', abbr: 'M', icon: 'smartphone', width: 390, group: 'MOBILE' },
|
|
38
|
+
];
|
|
39
|
+
/** Menu order. Groups render as labelled sections in the breakpoint picker. */
|
|
40
|
+
export const BREAKPOINT_GROUPS = ['DESKTOP', 'TABLET', 'MOBILE'];
|
|
41
|
+
export const DEFAULT_BREAKPOINT = 'wide';
|
|
42
|
+
const BY_ID = new Map(BREAKPOINTS.map((b) => [b.id, b]));
|
|
43
|
+
export function getBreakpoint(id) {
|
|
44
|
+
return BY_ID.get(id) ?? BY_ID.get(DEFAULT_BREAKPOINT);
|
|
45
|
+
}
|
|
46
|
+
export function breakpointsInGroup(group) {
|
|
47
|
+
return BREAKPOINTS.filter((b) => b.group === group);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Narrows arbitrary input (persisted state, a URL param, a stale prop) to a
|
|
51
|
+
* known id. The v0.92 preset ids — `1080p` and `tablet` — map onto their
|
|
52
|
+
* closest current equivalents so an editor open across the upgrade doesn't
|
|
53
|
+
* land on the default.
|
|
54
|
+
*/
|
|
55
|
+
const LEGACY_IDS = {
|
|
56
|
+
'1080p': 'laptop', // was 1440 — same width, renamed
|
|
57
|
+
tablet: 'tabletP', // was 768 — same width, split into landscape/portrait
|
|
58
|
+
};
|
|
59
|
+
export function coerceBreakpointId(value) {
|
|
60
|
+
if (typeof value !== 'string')
|
|
61
|
+
return DEFAULT_BREAKPOINT;
|
|
62
|
+
if (BY_ID.has(value))
|
|
63
|
+
return value;
|
|
64
|
+
return LEGACY_IDS[value] ?? DEFAULT_BREAKPOINT;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Scale factor for the canvas transform.
|
|
68
|
+
*
|
|
69
|
+
* `available` must come from a zero-height sentinel measured inside the canvas
|
|
70
|
+
* panel — NOT from `panel.clientWidth - padding`. The two disagree whenever the
|
|
71
|
+
* host scales the preview or a scrollbar appears, and the padding arithmetic is
|
|
72
|
+
* the kind that silently rots when the gutter changes.
|
|
73
|
+
*
|
|
74
|
+
* Never scales above 1: a 390px mobile canvas blown up to fill a 1200px column
|
|
75
|
+
* would show text at 3× the size the visitor sees.
|
|
76
|
+
*/
|
|
77
|
+
export function fitScale(available, width, zoom = 'fit') {
|
|
78
|
+
if (zoom !== 'fit')
|
|
79
|
+
return 1;
|
|
80
|
+
if (!Number.isFinite(available) || available <= 0 || width <= 0)
|
|
81
|
+
return 1;
|
|
82
|
+
return Math.min(1, available / width);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=breakpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breakpoints.js","sourceRoot":"","sources":["../../src/lib/breakpoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared edit affordances for the page/post canvas and Site preview iframe.
|
|
3
|
+
*
|
|
4
|
+
* Structure canvas: section hover is styled in `theme.css` under `.prenta-canvas`.
|
|
5
|
+
* Site preview: the same field chrome is injected into the iframe document when
|
|
6
|
+
* same-origin (CMS-host preview) so consumers get hover borders without shipping CSS.
|
|
7
|
+
*/
|
|
8
|
+
/** localStorage key for the dismissible canvas tip. */
|
|
9
|
+
export declare const CANVAS_EDIT_TIP_STORAGE_KEY = "prenta.canvasEditTip.dismissed";
|
|
10
|
+
/**
|
|
11
|
+
* CSS injected into the Site preview iframe while editing is enabled.
|
|
12
|
+
* Uses system colors so it works without admin theme tokens in the iframe.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PREVIEW_EDITABLE_FIELD_CHROME_CSS: string;
|
|
15
|
+
/**
|
|
16
|
+
* Inject (or refresh) editable-field hover chrome into a same-origin preview
|
|
17
|
+
* iframe. No-ops on cross-origin frames (browser blocks contentDocument).
|
|
18
|
+
*/
|
|
19
|
+
export declare function injectPreviewEditChrome(iframe: HTMLIFrameElement | null): boolean;
|
|
20
|
+
export declare function isCanvasEditTipDismissed(): boolean;
|
|
21
|
+
export declare function dismissCanvasEditTip(): void;
|
|
22
|
+
//# sourceMappingURL=canvas-edit-chrome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-edit-chrome.d.ts","sourceRoot":"","sources":["../../src/lib/canvas-edit-chrome.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,uDAAuD;AACvD,eAAO,MAAM,2BAA2B,mCAAmC,CAAA;AAE3E;;;GAGG;AACH,eAAO,MAAM,iCAAiC,QA0BtC,CAAA;AAIR;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAgBjF;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAMlD;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAM3C"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared edit affordances for the page/post canvas and Site preview iframe.
|
|
3
|
+
*
|
|
4
|
+
* Structure canvas: section hover is styled in `theme.css` under `.prenta-canvas`.
|
|
5
|
+
* Site preview: the same field chrome is injected into the iframe document when
|
|
6
|
+
* same-origin (CMS-host preview) so consumers get hover borders without shipping CSS.
|
|
7
|
+
*/
|
|
8
|
+
/** localStorage key for the dismissible canvas tip. */
|
|
9
|
+
export const CANVAS_EDIT_TIP_STORAGE_KEY = 'prenta.canvasEditTip.dismissed';
|
|
10
|
+
/**
|
|
11
|
+
* CSS injected into the Site preview iframe while editing is enabled.
|
|
12
|
+
* Uses system colors so it works without admin theme tokens in the iframe.
|
|
13
|
+
*/
|
|
14
|
+
export const PREVIEW_EDITABLE_FIELD_CHROME_CSS = `
|
|
15
|
+
/* Prenta Site preview — editable field hover chrome (injected by @prenta/admin) */
|
|
16
|
+
[data-cms-field] {
|
|
17
|
+
outline: 1px solid transparent;
|
|
18
|
+
outline-offset: 2px;
|
|
19
|
+
border-radius: 2px;
|
|
20
|
+
transition: outline-color 120ms ease;
|
|
21
|
+
cursor: text;
|
|
22
|
+
}
|
|
23
|
+
[data-cms-field]:hover,
|
|
24
|
+
[data-cms-field]:focus,
|
|
25
|
+
[data-cms-field]:focus-within {
|
|
26
|
+
outline-color: color-mix(in oklab, CanvasText 24%, transparent);
|
|
27
|
+
}
|
|
28
|
+
[data-cms-field][data-cms-field-kind="media"] {
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
31
|
+
[data-cms-field][data-cms-field-kind="media"]:hover,
|
|
32
|
+
[data-cms-field][data-cms-field-kind="media"]:focus {
|
|
33
|
+
outline-color: color-mix(in oklab, CanvasText 32%, transparent);
|
|
34
|
+
}
|
|
35
|
+
@media (prefers-reduced-motion: reduce) {
|
|
36
|
+
[data-cms-field] {
|
|
37
|
+
transition: none;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`.trim();
|
|
41
|
+
const STYLE_ATTR = 'data-prenta-edit-chrome';
|
|
42
|
+
/**
|
|
43
|
+
* Inject (or refresh) editable-field hover chrome into a same-origin preview
|
|
44
|
+
* iframe. No-ops on cross-origin frames (browser blocks contentDocument).
|
|
45
|
+
*/
|
|
46
|
+
export function injectPreviewEditChrome(iframe) {
|
|
47
|
+
try {
|
|
48
|
+
const doc = iframe?.contentDocument;
|
|
49
|
+
if (!doc?.head)
|
|
50
|
+
return false;
|
|
51
|
+
let style = doc.head.querySelector(`style[${STYLE_ATTR}]`);
|
|
52
|
+
if (!style) {
|
|
53
|
+
style = doc.createElement('style');
|
|
54
|
+
style.setAttribute(STYLE_ATTR, '1');
|
|
55
|
+
doc.head.appendChild(style);
|
|
56
|
+
}
|
|
57
|
+
style.textContent = PREVIEW_EDITABLE_FIELD_CHROME_CSS;
|
|
58
|
+
doc.documentElement.setAttribute('data-prenta-preview-editing', 'true');
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function isCanvasEditTipDismissed() {
|
|
66
|
+
try {
|
|
67
|
+
return localStorage.getItem(CANVAS_EDIT_TIP_STORAGE_KEY) === '1';
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export function dismissCanvasEditTip() {
|
|
74
|
+
try {
|
|
75
|
+
localStorage.setItem(CANVAS_EDIT_TIP_STORAGE_KEY, '1');
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
/* private mode — tip will reappear next session */
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=canvas-edit-chrome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-edit-chrome.js","sourceRoot":"","sources":["../../src/lib/canvas-edit-chrome.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,gCAAgC,CAAA;AAE3E;;;GAGG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BhD,CAAC,IAAI,EAAE,CAAA;AAER,MAAM,UAAU,GAAG,yBAAyB,CAAA;AAE5C;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAgC;IACtE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,eAAe,CAAA;QACnC,IAAI,CAAC,GAAG,EAAE,IAAI;YAAE,OAAO,KAAK,CAAA;QAC5B,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,aAAa,CAAmB,SAAS,UAAU,GAAG,CAAC,CAAA;QAC5E,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;YAClC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;YACnC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC;QACD,KAAK,CAAC,WAAW,GAAG,iCAAiC,CAAA;QACrD,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAA;QACvE,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,OAAO,CAAC,2BAA2B,CAAC,KAAK,GAAG,CAAA;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAA;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation helpers for the media block.
|
|
3
|
+
*
|
|
4
|
+
* Pure, because these are the parts with real logic — the rest of the block is
|
|
5
|
+
* layout. Ported from the design prototype so the labels an editor reads match
|
|
6
|
+
* the ones the design specifies.
|
|
7
|
+
*/
|
|
8
|
+
/** The crop the template renders an image at. Drives the frame's aspect ratio. */
|
|
9
|
+
export type MediaCrop = 'section' | 'social';
|
|
10
|
+
/**
|
|
11
|
+
* Aspect ratio per crop, as a CSS `aspect-ratio` value.
|
|
12
|
+
*
|
|
13
|
+
* The frame shows the crop the TEMPLATE renders, not the asset's own ratio.
|
|
14
|
+
* Showing the asset's ratio would tell an editor their portrait photo is fine
|
|
15
|
+
* and then crop its subject out on the page.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CROP_RATIO: Record<MediaCrop, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Human ratio for an asset's intrinsic dimensions.
|
|
20
|
+
*
|
|
21
|
+
* Snaps to a named ratio when within 0.05, else reports the number. The
|
|
22
|
+
* tolerance matters: a 2400×1600 photo is 1.5 exactly, but a 2401×1600 scan is
|
|
23
|
+
* 1.5006 and an editor should still read "3:2" rather than "1.50:1".
|
|
24
|
+
*
|
|
25
|
+
* Returns null when dimensions are unknown — the library does not always have
|
|
26
|
+
* them, and inventing "1.00:1" would be worse than saying nothing.
|
|
27
|
+
*/
|
|
28
|
+
export declare function ratioLabel(width?: number, height?: number): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Short format badge — the file extension, uppercased.
|
|
31
|
+
*
|
|
32
|
+
* Falls back to the MIME subtype so a URL with no extension (a signed CDN link,
|
|
33
|
+
* an upload route) still shows something meaningful rather than a blank chip.
|
|
34
|
+
*/
|
|
35
|
+
export declare function formatBadge(filenameOrUrl: string, mimeType?: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Filename for display, from a filename or a URL.
|
|
38
|
+
*
|
|
39
|
+
* Query strings are dropped — a signed URL's token is noise in a 200px-wide
|
|
40
|
+
* toolbar, and it is never what an editor is trying to read.
|
|
41
|
+
*/
|
|
42
|
+
export declare function displayName(filenameOrUrl: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* A stable background tint for an asset.
|
|
45
|
+
*
|
|
46
|
+
* The design fills the frame with a wash derived from the asset's dominant
|
|
47
|
+
* colour. The media library stores no such value, so it is derived from the
|
|
48
|
+
* name instead: the same asset is always the same colour, which is the property
|
|
49
|
+
* that actually matters for recognising a thumbnail, and it costs no storage
|
|
50
|
+
* and no extra request.
|
|
51
|
+
*
|
|
52
|
+
* Returned as a 135° gradient to the design's `color-mix(tint 45%, #fff)`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function assetWash(seed: string): string;
|
|
55
|
+
//# sourceMappingURL=media-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-format.d.ts","sourceRoot":"","sources":["../../src/lib/media-format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAGhD,CAAA;AAaD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKzE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK9C"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation helpers for the media block.
|
|
3
|
+
*
|
|
4
|
+
* Pure, because these are the parts with real logic — the rest of the block is
|
|
5
|
+
* layout. Ported from the design prototype so the labels an editor reads match
|
|
6
|
+
* the ones the design specifies.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Aspect ratio per crop, as a CSS `aspect-ratio` value.
|
|
10
|
+
*
|
|
11
|
+
* The frame shows the crop the TEMPLATE renders, not the asset's own ratio.
|
|
12
|
+
* Showing the asset's ratio would tell an editor their portrait photo is fine
|
|
13
|
+
* and then crop its subject out on the page.
|
|
14
|
+
*/
|
|
15
|
+
export const CROP_RATIO = {
|
|
16
|
+
section: '16 / 10',
|
|
17
|
+
social: '1.91 / 1',
|
|
18
|
+
};
|
|
19
|
+
/** Named ratios an editor recognises, nearest-match within a tolerance. */
|
|
20
|
+
const KNOWN_RATIOS = [
|
|
21
|
+
[1.91, '1.91:1'],
|
|
22
|
+
[16 / 9, '16:9'],
|
|
23
|
+
[1.5, '3:2'],
|
|
24
|
+
[4 / 3, '4:3'],
|
|
25
|
+
[1, '1:1'],
|
|
26
|
+
[0.8, '4:5'],
|
|
27
|
+
[9 / 16, '9:16'],
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Human ratio for an asset's intrinsic dimensions.
|
|
31
|
+
*
|
|
32
|
+
* Snaps to a named ratio when within 0.05, else reports the number. The
|
|
33
|
+
* tolerance matters: a 2400×1600 photo is 1.5 exactly, but a 2401×1600 scan is
|
|
34
|
+
* 1.5006 and an editor should still read "3:2" rather than "1.50:1".
|
|
35
|
+
*
|
|
36
|
+
* Returns null when dimensions are unknown — the library does not always have
|
|
37
|
+
* them, and inventing "1.00:1" would be worse than saying nothing.
|
|
38
|
+
*/
|
|
39
|
+
export function ratioLabel(width, height) {
|
|
40
|
+
if (!width || !height || width <= 0 || height <= 0)
|
|
41
|
+
return null;
|
|
42
|
+
const r = width / height;
|
|
43
|
+
const best = KNOWN_RATIOS.reduce((a, b) => (Math.abs(b[0] - r) < Math.abs(a[0] - r) ? b : a));
|
|
44
|
+
return Math.abs(best[0] - r) < 0.05 ? best[1] : `${r.toFixed(2)}:1`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Short format badge — the file extension, uppercased.
|
|
48
|
+
*
|
|
49
|
+
* Falls back to the MIME subtype so a URL with no extension (a signed CDN link,
|
|
50
|
+
* an upload route) still shows something meaningful rather than a blank chip.
|
|
51
|
+
*/
|
|
52
|
+
export function formatBadge(filenameOrUrl, mimeType) {
|
|
53
|
+
const path = filenameOrUrl.split(/[?#]/)[0] ?? '';
|
|
54
|
+
const segment = path.split('/').pop() ?? '';
|
|
55
|
+
// Only a segment that actually contains a dot has an extension. Comparing
|
|
56
|
+
// against the whole path instead of the segment let a dotless filename —
|
|
57
|
+
// which is what signed CDN links look like — read as its own extension.
|
|
58
|
+
const ext = segment.includes('.') ? (segment.split('.').pop() ?? '') : '';
|
|
59
|
+
if (ext && ext.length <= 5 && /^[a-z0-9]+$/i.test(ext)) {
|
|
60
|
+
return ext.toUpperCase();
|
|
61
|
+
}
|
|
62
|
+
const sub = mimeType?.split('/')[1];
|
|
63
|
+
return sub ? sub.split('+')[0].toUpperCase() : 'FILE';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Filename for display, from a filename or a URL.
|
|
67
|
+
*
|
|
68
|
+
* Query strings are dropped — a signed URL's token is noise in a 200px-wide
|
|
69
|
+
* toolbar, and it is never what an editor is trying to read.
|
|
70
|
+
*/
|
|
71
|
+
export function displayName(filenameOrUrl) {
|
|
72
|
+
const path = filenameOrUrl.split(/[?#]/)[0] ?? '';
|
|
73
|
+
return decodeURIComponent(path.split('/').pop() ?? '') || filenameOrUrl;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A stable background tint for an asset.
|
|
77
|
+
*
|
|
78
|
+
* The design fills the frame with a wash derived from the asset's dominant
|
|
79
|
+
* colour. The media library stores no such value, so it is derived from the
|
|
80
|
+
* name instead: the same asset is always the same colour, which is the property
|
|
81
|
+
* that actually matters for recognising a thumbnail, and it costs no storage
|
|
82
|
+
* and no extra request.
|
|
83
|
+
*
|
|
84
|
+
* Returned as a 135° gradient to the design's `color-mix(tint 45%, #fff)`.
|
|
85
|
+
*/
|
|
86
|
+
export function assetWash(seed) {
|
|
87
|
+
let hash = 0;
|
|
88
|
+
for (let i = 0; i < seed.length; i++)
|
|
89
|
+
hash = (hash * 31 + seed.charCodeAt(i)) % 360;
|
|
90
|
+
const tint = `oklch(0.88 0.06 ${hash})`;
|
|
91
|
+
return `linear-gradient(135deg, ${tint}, color-mix(in srgb, ${tint} 45%, #fff))`;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=media-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-format.js","sourceRoot":"","sources":["../../src/lib/media-format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAA8B;IACnD,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,UAAU;CACnB,CAAA;AAED,2EAA2E;AAC3E,MAAM,YAAY,GAA4B;IAC5C,CAAC,IAAI,EAAE,QAAQ,CAAC;IAChB,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;IACd,CAAC,CAAC,EAAE,KAAK,CAAC;IACV,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC;CACjB,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,MAAe;IACxD,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/D,MAAM,CAAC,GAAG,KAAK,GAAG,MAAM,CAAA;IACxB,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7F,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;AACrE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,aAAqB,EAAE,QAAiB;IAClE,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAA;IAC3C,0EAA0E;IAC1E,yEAAyE;IACzE,wEAAwE;IACxE,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACzE,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;IAC1B,CAAC;IACD,MAAM,GAAG,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACnC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,aAAqB;IAC/C,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACjD,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,aAAa,CAAA;AACzE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;IACnF,MAAM,IAAI,GAAG,mBAAmB,IAAI,GAAG,CAAA;IACvC,OAAO,2BAA2B,IAAI,wBAAwB,IAAI,cAAc,CAAA;AAClF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PageSection } from '@prenta/core/page-sections';
|
|
2
|
+
import type { PageAuditInput } from '@prenta/core/seo/page-audit';
|
|
3
|
+
import type { SeoContentRecord } from './seo-service.js';
|
|
4
|
+
/**
|
|
5
|
+
* One place that turns editor state into `PageAuditInput`.
|
|
6
|
+
*
|
|
7
|
+
* Two callers build the audit and their numbers must agree:
|
|
8
|
+
*
|
|
9
|
+
* - the page editor, from the SAVED record, so the header chip and rail dot
|
|
10
|
+
* have a score from first paint rather than after someone opens a tab;
|
|
11
|
+
* - the SEO pane, from LIVE form state, so the score moves as you type.
|
|
12
|
+
*
|
|
13
|
+
* They differ only in where the metadata comes from — saved versus unsaved —
|
|
14
|
+
* which is exactly the difference an editor expects to see. Everything else
|
|
15
|
+
* (which fields feed which check, how the title is rendered, what counts as
|
|
16
|
+
* unknown) is decided here once. Two hand-written copies of this mapping is how
|
|
17
|
+
* the editor ended up showing three different scores in the first place.
|
|
18
|
+
*/
|
|
19
|
+
export interface AuditMetaSource {
|
|
20
|
+
/** Page-level meta title, before the site title template is applied. */
|
|
21
|
+
metaTitle: string;
|
|
22
|
+
metaDescription: string;
|
|
23
|
+
focusKeyword: string;
|
|
24
|
+
structuredDataType: string;
|
|
25
|
+
noindex: boolean;
|
|
26
|
+
/** `nosnippet` — blocks AI Overview and chat citations outright. */
|
|
27
|
+
nosnippet: boolean;
|
|
28
|
+
/** `NEVER` excludes the page from llms.txt. */
|
|
29
|
+
llmsInclude: string;
|
|
30
|
+
/** True when an OG image is set — dimensions are not stored, see below. */
|
|
31
|
+
hasOgImage: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface BuildAuditInputArgs {
|
|
34
|
+
sections: PageSection[];
|
|
35
|
+
meta: AuditMetaSource;
|
|
36
|
+
slug: string;
|
|
37
|
+
/** Document title and site template, for the rendered `<title>`. */
|
|
38
|
+
record: Pick<SeoContentRecord, 'title' | 'siteName' | 'titleTemplate' | 'url'> | null;
|
|
39
|
+
/** Fallback title when there is no saved record yet. */
|
|
40
|
+
fallbackTitle?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function buildPageAuditInput({ sections, meta, slug, record, fallbackTitle, }: BuildAuditInputArgs): PageAuditInput;
|
|
43
|
+
/** Meta source from a saved SEO record. */
|
|
44
|
+
export declare function metaFromRecord(record: SeoContentRecord): AuditMetaSource;
|
|
45
|
+
//# sourceMappingURL=page-audit-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-audit-input.d.ts","sourceRoot":"","sources":["../../src/lib/page-audit-input.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,IAAI,EAAE,eAAe,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,oEAAoE;IACpE,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,UAAU,GAAG,eAAe,GAAG,KAAK,CAAC,GAAG,IAAI,CAAA;IACrF,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,aAAa,GACd,EAAE,mBAAmB,GAAG,cAAc,CAsCtC;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAWxE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolveRenderedMetaTitle } from '@prenta/core/client';
|
|
2
|
+
export function buildPageAuditInput({ sections, meta, slug, record, fallbackTitle, }) {
|
|
3
|
+
// Measure the title a searcher actually sees — the page meta title with the
|
|
4
|
+
// site's template applied — not the raw field. Checking the raw field would
|
|
5
|
+
// give length advice that contradicts the rendered result.
|
|
6
|
+
const renderedTitle = record
|
|
7
|
+
? resolveRenderedMetaTitle({
|
|
8
|
+
metaTitlePage: meta.metaTitle,
|
|
9
|
+
documentTitle: record.title,
|
|
10
|
+
site: {
|
|
11
|
+
siteName: record.siteName ?? undefined,
|
|
12
|
+
titleTemplate: record.titleTemplate ?? undefined,
|
|
13
|
+
},
|
|
14
|
+
})
|
|
15
|
+
: meta.metaTitle.trim() || fallbackTitle || '';
|
|
16
|
+
return {
|
|
17
|
+
sections,
|
|
18
|
+
seo: {
|
|
19
|
+
title: renderedTitle,
|
|
20
|
+
description: meta.metaDescription,
|
|
21
|
+
slug: slug || record?.url?.split('/').filter(Boolean).pop() || '',
|
|
22
|
+
keyword: meta.focusKeyword,
|
|
23
|
+
schema: meta.structuredDataType,
|
|
24
|
+
// `undefined` (unknown) when an image is set: the record stores a URL
|
|
25
|
+
// with no dimensions, and the check needs width and ratio. `null` when
|
|
26
|
+
// none is set, which is a genuine absence and correctly fails.
|
|
27
|
+
ogImage: meta.hasOgImage ? undefined : null,
|
|
28
|
+
robots: {
|
|
29
|
+
index: !meta.noindex,
|
|
30
|
+
snippet: !meta.nosnippet,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
llmsTxt: meta.llmsInclude !== 'NEVER',
|
|
34
|
+
// Not resolved in the editor yet; both report not-applicable rather than
|
|
35
|
+
// failing an editor for a gap in the plumbing.
|
|
36
|
+
brand: '',
|
|
37
|
+
author: undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Meta source from a saved SEO record. */
|
|
41
|
+
export function metaFromRecord(record) {
|
|
42
|
+
return {
|
|
43
|
+
metaTitle: record.metaTitlePage ?? '',
|
|
44
|
+
metaDescription: record.metaDescription ?? '',
|
|
45
|
+
focusKeyword: record.focusKeyword ?? '',
|
|
46
|
+
structuredDataType: record.structuredDataType ?? 'WebPage',
|
|
47
|
+
noindex: record.noindex,
|
|
48
|
+
nosnippet: record.nosnippet ?? false,
|
|
49
|
+
llmsInclude: record.llmsInclude ?? 'AUTO',
|
|
50
|
+
hasOgImage: Boolean(record.ogImage),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=page-audit-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-audit-input.js","sourceRoot":"","sources":["../../src/lib/page-audit-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AA6C9D,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,aAAa,GACO;IACpB,4EAA4E;IAC5E,4EAA4E;IAC5E,2DAA2D;IAC3D,MAAM,aAAa,GAAG,MAAM;QAC1B,CAAC,CAAC,wBAAwB,CAAC;YACvB,aAAa,EAAE,IAAI,CAAC,SAAS;YAC7B,aAAa,EAAE,MAAM,CAAC,KAAK;YAC3B,IAAI,EAAE;gBACJ,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,SAAS;gBACtC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,SAAS;aACjD;SACF,CAAC;QACJ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,aAAa,IAAI,EAAE,CAAA;IAEhD,OAAO;QACL,QAAQ;QACR,GAAG,EAAE;YACH,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,IAAI,CAAC,eAAe;YACjC,IAAI,EAAE,IAAI,IAAI,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE;YACjE,OAAO,EAAE,IAAI,CAAC,YAAY;YAC1B,MAAM,EAAE,IAAI,CAAC,kBAAkB;YAC/B,sEAAsE;YACtE,uEAAuE;YACvE,+DAA+D;YAC/D,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YAC3C,MAAM,EAAE;gBACN,KAAK,EAAE,CAAC,IAAI,CAAC,OAAO;gBACpB,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS;aACzB;SACF;QACD,OAAO,EAAE,IAAI,CAAC,WAAW,KAAK,OAAO;QACrC,yEAAyE;QACzE,+CAA+C;QAC/C,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,SAAS;KAClB,CAAA;AACH,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QACrC,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,EAAE;QAC7C,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;QACvC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,SAAS;QAC1D,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QACpC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM;QACzC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;KACpC,CAAA;AACH,CAAC"}
|
|
@@ -22,6 +22,18 @@ export interface EditorPage {
|
|
|
22
22
|
updatedAt: string | null;
|
|
23
23
|
scheduledAt: string | null;
|
|
24
24
|
scheduledUnpublishAt: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Displayed byline. Read by `composePageMeta` into the page's structured
|
|
27
|
+
* data, so this is a real output and not decoration.
|
|
28
|
+
*
|
|
29
|
+
* Deliberately separate from the document's `createdById`, which the API
|
|
30
|
+
* never reassigns. That field records who created the record — provenance —
|
|
31
|
+
* and overwriting it to change a displayed name would trade an audit trail
|
|
32
|
+
* for a label.
|
|
33
|
+
*/
|
|
34
|
+
authorName: string;
|
|
35
|
+
/** CMS user behind the byline, when it is one. Empty for generic/guest. */
|
|
36
|
+
authorId: string;
|
|
25
37
|
/**
|
|
26
38
|
* True when the document was authored in the visual Page Builder (it carries
|
|
27
39
|
* a `_layout` tree). Such a page's `sections` are *compiled* from the layout
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-editor-service.d.ts","sourceRoot":"","sources":["../../src/lib/page-editor-service.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEL,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EAGjB,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAA;AAKnC,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAI7D,OAAO,EACL,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,GAClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAA;AAEzE,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB;;;;OAIG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,UAAQ,GAAG,gBAAgB,CAoCnF;AAoBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAE3D;
|
|
1
|
+
{"version":3,"file":"page-editor-service.d.ts","sourceRoot":"","sources":["../../src/lib/page-editor-service.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEL,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EAGjB,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAA;AAKnC,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAI7D,OAAO,EACL,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,GAClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAA;AAEzE,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB;;;;OAIG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,UAAQ,GAAG,gBAAgB,CAoCnF;AAoBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAE3D;AAqDD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAI5E;AAoCD,wDAAwD;AACxD,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtE;AAED,iDAAiD;AACjD,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAQzE;AAED,wEAAwE;AACxE,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAUvE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,YAAY,GAAE,MAAM,GAAG,IAAW,GAAG,UAAU,CAmBxE"}
|
|
@@ -118,6 +118,8 @@ function rowToEditorPage(doc) {
|
|
|
118
118
|
updatedAt: doc.updatedAt ?? null,
|
|
119
119
|
scheduledAt: doc.scheduledAt ?? null,
|
|
120
120
|
scheduledUnpublishAt: doc.scheduledUnpublishAt ?? null,
|
|
121
|
+
authorName: typeof data.authorName === 'string' ? data.authorName : '',
|
|
122
|
+
authorId: typeof data.authorId === 'string' ? data.authorId : '',
|
|
121
123
|
builderOwned,
|
|
122
124
|
};
|
|
123
125
|
}
|
|
@@ -145,6 +147,8 @@ function toWriteBody(page, extra) {
|
|
|
145
147
|
sections: page.sections.map(({ unmanaged: _unmanaged, ...rest }) => rest),
|
|
146
148
|
metaTitle: page.seoTitle,
|
|
147
149
|
metaDescription: page.seoDescription,
|
|
150
|
+
authorName: page.authorName,
|
|
151
|
+
authorId: page.authorId,
|
|
148
152
|
...extra,
|
|
149
153
|
};
|
|
150
154
|
return JSON.stringify(payload);
|
|
@@ -203,6 +207,8 @@ export function emptyPage(parentPageId = null) {
|
|
|
203
207
|
updatedAt: null,
|
|
204
208
|
scheduledAt: null,
|
|
205
209
|
scheduledUnpublishAt: null,
|
|
210
|
+
authorName: '',
|
|
211
|
+
authorId: '',
|
|
206
212
|
builderOwned: false,
|
|
207
213
|
};
|
|
208
214
|
}
|