@canvas-digital/blog-sdk 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -0
- package/dist/BlogPlatform.d.ts +40 -0
- package/dist/BlogPlatform.d.ts.map +1 -0
- package/dist/BlogPlatform.js +38 -0
- package/dist/admin/components/BlogAdmin.d.ts +10 -0
- package/dist/admin/components/BlogAdmin.d.ts.map +1 -0
- package/dist/admin/components/BlogAdmin.js +36 -0
- package/dist/admin/components/CategoryManager.d.ts +5 -0
- package/dist/admin/components/CategoryManager.d.ts.map +1 -0
- package/dist/admin/components/CategoryManager.js +43 -0
- package/dist/admin/components/MediaManager.d.ts +7 -0
- package/dist/admin/components/MediaManager.d.ts.map +1 -0
- package/dist/admin/components/MediaManager.js +37 -0
- package/dist/admin/components/PostEditor.d.ts +7 -0
- package/dist/admin/components/PostEditor.d.ts.map +1 -0
- package/dist/admin/components/PostEditor.js +160 -0
- package/dist/admin/components/PostList.d.ts +8 -0
- package/dist/admin/components/PostList.d.ts.map +1 -0
- package/dist/admin/components/PostList.js +32 -0
- package/dist/admin/components/TagManager.d.ts +5 -0
- package/dist/admin/components/TagManager.d.ts.map +1 -0
- package/dist/admin/components/TagManager.js +41 -0
- package/dist/admin/components/editor/RichTextEditor.d.ts +8 -0
- package/dist/admin/components/editor/RichTextEditor.d.ts.map +1 -0
- package/dist/admin/components/editor/RichTextEditor.js +47 -0
- package/dist/admin/components/internal/States.d.ts +16 -0
- package/dist/admin/components/internal/States.d.ts.map +1 -0
- package/dist/admin/components/internal/States.js +15 -0
- package/dist/admin/hooks/useAsync.d.ts +23 -0
- package/dist/admin/hooks/useAsync.d.ts.map +1 -0
- package/dist/admin/hooks/useAsync.js +40 -0
- package/dist/admin/index.d.ts +10 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +9 -0
- package/dist/admin/theme.d.ts +6 -0
- package/dist/admin/theme.d.ts.map +1 -0
- package/dist/admin/theme.js +52 -0
- package/dist/admin/types.d.ts +27 -0
- package/dist/admin/types.d.ts.map +1 -0
- package/dist/admin/types.js +1 -0
- package/dist/blog-client.iife.js +1 -0
- package/dist/client/admin-client.d.ts +33 -0
- package/dist/client/admin-client.d.ts.map +1 -0
- package/dist/client/admin-client.js +153 -0
- package/dist/client/errors.d.ts +14 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +26 -0
- package/dist/client/http.d.ts +12 -0
- package/dist/client/http.d.ts.map +1 -0
- package/dist/client/http.js +135 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/pagination.d.ts +4 -0
- package/dist/client/pagination.d.ts.map +1 -0
- package/dist/client/pagination.js +32 -0
- package/dist/client/public-client.d.ts +23 -0
- package/dist/client/public-client.d.ts.map +1 -0
- package/dist/client/public-client.js +94 -0
- package/dist/client/types.d.ts +115 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +1 -0
- package/dist/components/BlogUploader/BackButton.d.ts +5 -0
- package/dist/components/BlogUploader/BackButton.d.ts.map +1 -0
- package/dist/components/BlogUploader/BackButton.js +27 -0
- package/dist/components/BlogUploader/CommentSection.d.ts +12 -0
- package/dist/components/BlogUploader/CommentSection.d.ts.map +1 -0
- package/dist/components/BlogUploader/CommentSection.js +65 -0
- package/dist/components/BlogUploader/PostCard.d.ts +17 -0
- package/dist/components/BlogUploader/PostCard.d.ts.map +1 -0
- package/dist/components/BlogUploader/PostCard.js +42 -0
- package/dist/components/BlogUploader/PostFormatHero.d.ts +7 -0
- package/dist/components/BlogUploader/PostFormatHero.d.ts.map +1 -0
- package/dist/components/BlogUploader/PostFormatHero.js +47 -0
- package/dist/components/BlogUploader/ReadingProgress.d.ts +9 -0
- package/dist/components/BlogUploader/ReadingProgress.d.ts.map +1 -0
- package/dist/components/BlogUploader/ReadingProgress.js +28 -0
- package/dist/components/BlogUploader/RichText.d.ts +5 -0
- package/dist/components/BlogUploader/RichText.d.ts.map +1 -0
- package/dist/components/BlogUploader/RichText.js +59 -0
- package/dist/components/BlogUploader/ShareRow.d.ts +12 -0
- package/dist/components/BlogUploader/ShareRow.d.ts.map +1 -0
- package/dist/components/BlogUploader/ShareRow.js +13 -0
- package/dist/components/BlogUploader/ViewBeacon.d.ts +12 -0
- package/dist/components/BlogUploader/ViewBeacon.d.ts.map +1 -0
- package/dist/components/BlogUploader/ViewBeacon.js +37 -0
- package/dist/components/BlogUploader/dashboard/BrandSettings.d.ts +28 -0
- package/dist/components/BlogUploader/dashboard/BrandSettings.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/BrandSettings.js +60 -0
- package/dist/components/BlogUploader/dashboard/BrandSwitcher.d.ts +14 -0
- package/dist/components/BlogUploader/dashboard/BrandSwitcher.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/BrandSwitcher.js +25 -0
- package/dist/components/BlogUploader/dashboard/Chips.d.ts +15 -0
- package/dist/components/BlogUploader/dashboard/Chips.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/Chips.js +15 -0
- package/dist/components/BlogUploader/dashboard/CommentsManager.d.ts +19 -0
- package/dist/components/BlogUploader/dashboard/CommentsManager.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/CommentsManager.js +32 -0
- package/dist/components/BlogUploader/dashboard/LogOutButton.d.ts +4 -0
- package/dist/components/BlogUploader/dashboard/LogOutButton.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/LogOutButton.js +22 -0
- package/dist/components/BlogUploader/dashboard/MediaLibrary.d.ts +16 -0
- package/dist/components/BlogUploader/dashboard/MediaLibrary.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/MediaLibrary.js +124 -0
- package/dist/components/BlogUploader/dashboard/MediaPicker.d.ts +19 -0
- package/dist/components/BlogUploader/dashboard/MediaPicker.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/MediaPicker.js +99 -0
- package/dist/components/BlogUploader/dashboard/PostsTable.d.ts +46 -0
- package/dist/components/BlogUploader/dashboard/PostsTable.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/PostsTable.js +109 -0
- package/dist/components/BlogUploader/dashboard/Shell.d.ts +25 -0
- package/dist/components/BlogUploader/dashboard/Shell.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/Shell.js +128 -0
- package/dist/components/BlogUploader/dashboard/TermManager.d.ts +29 -0
- package/dist/components/BlogUploader/dashboard/TermManager.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/TermManager.js +96 -0
- package/dist/components/BlogUploader/dashboard/ToastProvider.d.ts +6 -0
- package/dist/components/BlogUploader/dashboard/ToastProvider.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/ToastProvider.js +5 -0
- package/dist/components/BlogUploader/dashboard/UsersManager.d.ts +32 -0
- package/dist/components/BlogUploader/dashboard/UsersManager.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/UsersManager.js +98 -0
- package/dist/components/BlogUploader/dashboard/charts.d.ts +22 -0
- package/dist/components/BlogUploader/dashboard/charts.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/charts.js +79 -0
- package/dist/components/BlogUploader/dashboard/editor/FormatContentPanel.d.ts +25 -0
- package/dist/components/BlogUploader/dashboard/editor/FormatContentPanel.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/FormatContentPanel.js +62 -0
- package/dist/components/BlogUploader/dashboard/editor/PostEditor.d.ts +95 -0
- package/dist/components/BlogUploader/dashboard/editor/PostEditor.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/PostEditor.js +649 -0
- package/dist/components/BlogUploader/dashboard/editor/RichTextEditor.d.ts +37 -0
- package/dist/components/BlogUploader/dashboard/editor/RichTextEditor.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/RichTextEditor.js +475 -0
- package/dist/components/BlogUploader/dashboard/editor/SeoAnalysisPanel.d.ts +11 -0
- package/dist/components/BlogUploader/dashboard/editor/SeoAnalysisPanel.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/SeoAnalysisPanel.js +31 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastCollapsible.d.ts +12 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastCollapsible.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastCollapsible.js +5 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInsightsPanel.d.ts +4 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInsightsPanel.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInsightsPanel.js +31 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInternalLinksPanel.d.ts +4 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInternalLinksPanel.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastInternalLinksPanel.js +35 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoAnalysisPanel.d.ts +11 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoAnalysisPanel.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoAnalysisPanel.js +23 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoMetabox.d.ts +50 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoMetabox.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSeoMetabox.js +101 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSnippetField.d.ts +22 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSnippetField.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/YoastSnippetField.js +51 -0
- package/dist/components/BlogUploader/dashboard/editor/load.d.ts +10 -0
- package/dist/components/BlogUploader/dashboard/editor/load.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/editor/load.js +141 -0
- package/dist/components/BlogUploader/dashboard/loadTerms.d.ts +13 -0
- package/dist/components/BlogUploader/dashboard/loadTerms.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/loadTerms.js +41 -0
- package/dist/components/BlogUploader/dashboard/seo/BrandSeoActions.d.ts +8 -0
- package/dist/components/BlogUploader/dashboard/seo/BrandSeoActions.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/BrandSeoActions.js +35 -0
- package/dist/components/BlogUploader/dashboard/seo/Ga4Settings.d.ts +9 -0
- package/dist/components/BlogUploader/dashboard/seo/Ga4Settings.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/Ga4Settings.js +40 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectAnalyticsDashboard.d.ts +5 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectAnalyticsDashboard.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectAnalyticsDashboard.js +29 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectDetail.d.ts +10 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectDetail.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectDetail.js +31 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectForm.d.ts +27 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectForm.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectForm.js +79 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectList.d.ts +20 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectList.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/RedirectList.js +33 -0
- package/dist/components/BlogUploader/dashboard/seo/RobotsEditor.d.ts +11 -0
- package/dist/components/BlogUploader/dashboard/seo/RobotsEditor.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/RobotsEditor.js +54 -0
- package/dist/components/BlogUploader/dashboard/seo/SearchConsoleSettings.d.ts +9 -0
- package/dist/components/BlogUploader/dashboard/seo/SearchConsoleSettings.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/SearchConsoleSettings.js +38 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandList.d.ts +28 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandList.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandList.js +29 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandLists.d.ts +17 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandLists.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/SeoBrandLists.js +8 -0
- package/dist/components/BlogUploader/dashboard/seo/shared.d.ts +18 -0
- package/dist/components/BlogUploader/dashboard/seo/shared.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/seo/shared.js +6 -0
- package/dist/components/BlogUploader/dashboard/tools/ExportTool.d.ts +8 -0
- package/dist/components/BlogUploader/dashboard/tools/ExportTool.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/tools/ExportTool.js +78 -0
- package/dist/components/BlogUploader/dashboard/tools/ImportTool.d.ts +7 -0
- package/dist/components/BlogUploader/dashboard/tools/ImportTool.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/tools/ImportTool.js +70 -0
- package/dist/components/BlogUploader/dashboard/upload.d.ts +47 -0
- package/dist/components/BlogUploader/dashboard/upload.d.ts.map +1 -0
- package/dist/components/BlogUploader/dashboard/upload.js +68 -0
- package/dist/components/BlogUploader/site/ArticleDetailHero.d.ts +27 -0
- package/dist/components/BlogUploader/site/ArticleDetailHero.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/ArticleDetailHero.js +13 -0
- package/dist/components/BlogUploader/site/ArticleRailDetails.d.ts +27 -0
- package/dist/components/BlogUploader/site/ArticleRailDetails.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/ArticleRailDetails.js +17 -0
- package/dist/components/BlogUploader/site/BlogIndexView.d.ts +28 -0
- package/dist/components/BlogUploader/site/BlogIndexView.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/BlogIndexView.js +34 -0
- package/dist/components/BlogUploader/site/BrandTableOfContents.d.ts +18 -0
- package/dist/components/BlogUploader/site/BrandTableOfContents.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/BrandTableOfContents.js +15 -0
- package/dist/components/BlogUploader/site/HeroFadeSlide.d.ts +11 -0
- package/dist/components/BlogUploader/site/HeroFadeSlide.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/HeroFadeSlide.js +3 -0
- package/dist/components/BlogUploader/site/HeroMediaVisual.d.ts +23 -0
- package/dist/components/BlogUploader/site/HeroMediaVisual.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/HeroMediaVisual.js +50 -0
- package/dist/components/BlogUploader/site/IndexFeedSection.d.ts +14 -0
- package/dist/components/BlogUploader/site/IndexFeedSection.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/IndexFeedSection.js +12 -0
- package/dist/components/BlogUploader/site/InfinitePostFeed.d.ts +23 -0
- package/dist/components/BlogUploader/site/InfinitePostFeed.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/InfinitePostFeed.js +152 -0
- package/dist/components/BlogUploader/site/SiteMediaHero.d.ts +12 -0
- package/dist/components/BlogUploader/site/SiteMediaHero.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/SiteMediaHero.js +80 -0
- package/dist/components/BlogUploader/site/SiteMotion.d.ts +12 -0
- package/dist/components/BlogUploader/site/SiteMotion.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/SiteMotion.js +27 -0
- package/dist/components/BlogUploader/site/SiteNavAuth.d.ts +8 -0
- package/dist/components/BlogUploader/site/SiteNavAuth.d.ts.map +1 -0
- package/dist/components/BlogUploader/site/SiteNavAuth.js +36 -0
- package/dist/components/admin/AdminPostDetail.d.ts +7 -0
- package/dist/components/admin/AdminPostDetail.d.ts.map +1 -0
- package/dist/components/admin/AdminPostDetail.js +105 -0
- package/dist/components/admin/BrandSettings.d.ts +11 -0
- package/dist/components/admin/BrandSettings.d.ts.map +1 -0
- package/dist/components/admin/BrandSettings.js +71 -0
- package/dist/components/admin/BrandSwitcher.d.ts +3 -0
- package/dist/components/admin/BrandSwitcher.d.ts.map +1 -0
- package/dist/components/admin/BrandSwitcher.js +12 -0
- package/dist/components/admin/CategoryManager.d.ts +2 -0
- package/dist/components/admin/CategoryManager.d.ts.map +1 -0
- package/dist/components/admin/CategoryManager.js +1 -0
- package/dist/components/admin/Chips.d.ts +15 -0
- package/dist/components/admin/Chips.d.ts.map +1 -0
- package/dist/components/admin/Chips.js +15 -0
- package/dist/components/admin/CommentsManager.d.ts +6 -0
- package/dist/components/admin/CommentsManager.d.ts.map +1 -0
- package/dist/components/admin/CommentsManager.js +30 -0
- package/dist/components/admin/Dashboard.d.ts +3 -0
- package/dist/components/admin/Dashboard.d.ts.map +1 -0
- package/dist/components/admin/Dashboard.js +34 -0
- package/dist/components/admin/MediaLibrary.d.ts +4 -0
- package/dist/components/admin/MediaLibrary.d.ts.map +1 -0
- package/dist/components/admin/MediaLibrary.js +119 -0
- package/dist/components/admin/MediaManager.d.ts +2 -0
- package/dist/components/admin/MediaManager.d.ts.map +1 -0
- package/dist/components/admin/MediaManager.js +1 -0
- package/dist/components/admin/MediaPicker.d.ts +10 -0
- package/dist/components/admin/MediaPicker.d.ts.map +1 -0
- package/dist/components/admin/MediaPicker.js +86 -0
- package/dist/components/admin/PostEditor.d.ts +2 -0
- package/dist/components/admin/PostEditor.d.ts.map +1 -0
- package/dist/components/admin/PostEditor.js +1 -0
- package/dist/components/admin/PostList.d.ts +13 -0
- package/dist/components/admin/PostList.d.ts.map +1 -0
- package/dist/components/admin/PostList.js +93 -0
- package/dist/components/admin/PostsTable.d.ts +15 -0
- package/dist/components/admin/PostsTable.d.ts.map +1 -0
- package/dist/components/admin/PostsTable.js +106 -0
- package/dist/components/admin/Shell.d.ts +18 -0
- package/dist/components/admin/Shell.d.ts.map +1 -0
- package/dist/components/admin/Shell.js +99 -0
- package/dist/components/admin/TagManager.d.ts +2 -0
- package/dist/components/admin/TagManager.d.ts.map +1 -0
- package/dist/components/admin/TagManager.js +1 -0
- package/dist/components/admin/TermManager.d.ts +9 -0
- package/dist/components/admin/TermManager.d.ts.map +1 -0
- package/dist/components/admin/TermManager.js +105 -0
- package/dist/components/admin/UsersManager.d.ts +5 -0
- package/dist/components/admin/UsersManager.d.ts.map +1 -0
- package/dist/components/admin/UsersManager.js +96 -0
- package/dist/components/admin/api/mappers.d.ts +37 -0
- package/dist/components/admin/api/mappers.d.ts.map +1 -0
- package/dist/components/admin/api/mappers.js +174 -0
- package/dist/components/admin/charts.d.ts +30 -0
- package/dist/components/admin/charts.d.ts.map +1 -0
- package/dist/components/admin/charts.js +79 -0
- package/dist/components/admin/editor/FormatContentPanel.d.ts +25 -0
- package/dist/components/admin/editor/FormatContentPanel.d.ts.map +1 -0
- package/dist/components/admin/editor/FormatContentPanel.js +62 -0
- package/dist/components/admin/editor/PostEditor.d.ts +5 -0
- package/dist/components/admin/editor/PostEditor.d.ts.map +1 -0
- package/dist/components/admin/editor/PostEditor.js +404 -0
- package/dist/components/admin/editor/RichTextEditor.d.ts +42 -0
- package/dist/components/admin/editor/RichTextEditor.d.ts.map +1 -0
- package/dist/components/admin/editor/RichTextEditor.js +475 -0
- package/dist/components/admin/editor/SeoAnalysisPanel.d.ts +11 -0
- package/dist/components/admin/editor/SeoAnalysisPanel.d.ts.map +1 -0
- package/dist/components/admin/editor/SeoAnalysisPanel.js +31 -0
- package/dist/components/admin/editor/YoastCollapsible.d.ts +12 -0
- package/dist/components/admin/editor/YoastCollapsible.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastCollapsible.js +5 -0
- package/dist/components/admin/editor/YoastInsightsPanel.d.ts +4 -0
- package/dist/components/admin/editor/YoastInsightsPanel.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastInsightsPanel.js +31 -0
- package/dist/components/admin/editor/YoastInternalLinksPanel.d.ts +4 -0
- package/dist/components/admin/editor/YoastInternalLinksPanel.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastInternalLinksPanel.js +35 -0
- package/dist/components/admin/editor/YoastSeoAnalysisPanel.d.ts +11 -0
- package/dist/components/admin/editor/YoastSeoAnalysisPanel.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastSeoAnalysisPanel.js +23 -0
- package/dist/components/admin/editor/YoastSeoMetabox.d.ts +54 -0
- package/dist/components/admin/editor/YoastSeoMetabox.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastSeoMetabox.js +101 -0
- package/dist/components/admin/editor/YoastSnippetField.d.ts +22 -0
- package/dist/components/admin/editor/YoastSnippetField.d.ts.map +1 -0
- package/dist/components/admin/editor/YoastSnippetField.js +51 -0
- package/dist/components/admin/editor/load.d.ts +10 -0
- package/dist/components/admin/editor/load.d.ts.map +1 -0
- package/dist/components/admin/editor/load.js +141 -0
- package/dist/components/admin/index.d.ts +28 -0
- package/dist/components/admin/index.d.ts.map +1 -0
- package/dist/components/admin/index.js +27 -0
- package/dist/components/admin/internal/States.d.ts +16 -0
- package/dist/components/admin/internal/States.d.ts.map +1 -0
- package/dist/components/admin/internal/States.js +15 -0
- package/dist/components/admin/lib/format.d.ts +7 -0
- package/dist/components/admin/lib/format.d.ts.map +1 -0
- package/dist/components/admin/lib/format.js +43 -0
- package/dist/components/admin/lib/publishing.d.ts +8 -0
- package/dist/components/admin/lib/publishing.d.ts.map +1 -0
- package/dist/components/admin/lib/publishing.js +10 -0
- package/dist/components/admin/lib/robots.d.ts +13 -0
- package/dist/components/admin/lib/robots.d.ts.map +1 -0
- package/dist/components/admin/lib/robots.js +22 -0
- package/dist/components/admin/mock/fixtures.d.ts +240 -0
- package/dist/components/admin/mock/fixtures.d.ts.map +1 -0
- package/dist/components/admin/mock/fixtures.js +546 -0
- package/dist/components/admin/mock/store.d.ts +139 -0
- package/dist/components/admin/mock/store.d.ts.map +1 -0
- package/dist/components/admin/mock/store.js +1067 -0
- package/dist/components/admin/seo/Ga4Settings.d.ts +34 -0
- package/dist/components/admin/seo/Ga4Settings.d.ts.map +1 -0
- package/dist/components/admin/seo/Ga4Settings.js +80 -0
- package/dist/components/admin/seo/RedirectAnalyticsDashboard.d.ts +5 -0
- package/dist/components/admin/seo/RedirectAnalyticsDashboard.d.ts.map +1 -0
- package/dist/components/admin/seo/RedirectAnalyticsDashboard.js +24 -0
- package/dist/components/admin/seo/RedirectDetail.d.ts +11 -0
- package/dist/components/admin/seo/RedirectDetail.d.ts.map +1 -0
- package/dist/components/admin/seo/RedirectDetail.js +30 -0
- package/dist/components/admin/seo/RedirectForm.d.ts +29 -0
- package/dist/components/admin/seo/RedirectForm.d.ts.map +1 -0
- package/dist/components/admin/seo/RedirectForm.js +89 -0
- package/dist/components/admin/seo/RedirectList.d.ts +10 -0
- package/dist/components/admin/seo/RedirectList.d.ts.map +1 -0
- package/dist/components/admin/seo/RedirectList.js +28 -0
- package/dist/components/admin/seo/RobotsEditor.d.ts +5 -0
- package/dist/components/admin/seo/RobotsEditor.d.ts.map +1 -0
- package/dist/components/admin/seo/RobotsEditor.js +50 -0
- package/dist/components/admin/seo/SearchConsoleSettings.d.ts +3 -0
- package/dist/components/admin/seo/SearchConsoleSettings.d.ts.map +1 -0
- package/dist/components/admin/seo/SearchConsoleSettings.js +1 -0
- package/dist/components/admin/seo/SeoBrandList.d.ts +3 -0
- package/dist/components/admin/seo/SeoBrandList.d.ts.map +1 -0
- package/dist/components/admin/seo/SeoBrandList.js +1 -0
- package/dist/components/admin/seo/shared.d.ts +17 -0
- package/dist/components/admin/seo/shared.d.ts.map +1 -0
- package/dist/components/admin/seo/shared.js +7 -0
- package/dist/components/admin/tools/ExportTool.d.ts +3 -0
- package/dist/components/admin/tools/ExportTool.d.ts.map +1 -0
- package/dist/components/admin/tools/ExportTool.js +1 -0
- package/dist/components/admin/tools/ImportTool.d.ts +3 -0
- package/dist/components/admin/tools/ImportTool.d.ts.map +1 -0
- package/dist/components/admin/tools/ImportTool.js +1 -0
- package/dist/components/admin/tools/ToolsHub.d.ts +10 -0
- package/dist/components/admin/tools/ToolsHub.d.ts.map +1 -0
- package/dist/components/admin/tools/ToolsHub.js +106 -0
- package/dist/components/admin/tools/index.d.ts +3 -0
- package/dist/components/admin/tools/index.d.ts.map +1 -0
- package/dist/components/admin/tools/index.js +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +2 -0
- package/dist/components/user/BlogCard.d.ts +20 -0
- package/dist/components/user/BlogCard.d.ts.map +1 -0
- package/dist/components/user/BlogCard.js +22 -0
- package/dist/components/user/BlogCategories.d.ts +6 -0
- package/dist/components/user/BlogCategories.d.ts.map +1 -0
- package/dist/components/user/BlogCategories.js +11 -0
- package/dist/components/user/BlogDetail.d.ts +25 -0
- package/dist/components/user/BlogDetail.d.ts.map +1 -0
- package/dist/components/user/BlogDetail.js +90 -0
- package/dist/components/user/BlogList.d.ts +20 -0
- package/dist/components/user/BlogList.d.ts.map +1 -0
- package/dist/components/user/BlogList.js +56 -0
- package/dist/components/user/BlogSearch.d.ts +8 -0
- package/dist/components/user/BlogSearch.d.ts.map +1 -0
- package/dist/components/user/BlogSearch.js +19 -0
- package/dist/components/user/BlogTags.d.ts +6 -0
- package/dist/components/user/BlogTags.d.ts.map +1 -0
- package/dist/components/user/BlogTags.js +11 -0
- package/dist/components/user/FeaturedBlogs.d.ts +8 -0
- package/dist/components/user/FeaturedBlogs.d.ts.map +1 -0
- package/dist/components/user/FeaturedBlogs.js +12 -0
- package/dist/components/user/RelatedBlogs.d.ts +9 -0
- package/dist/components/user/RelatedBlogs.d.ts.map +1 -0
- package/dist/components/user/RelatedBlogs.js +12 -0
- package/dist/components/user/SiteMediaHero.d.ts +14 -0
- package/dist/components/user/SiteMediaHero.d.ts.map +1 -0
- package/dist/components/user/SiteMediaHero.js +43 -0
- package/dist/components/user/detail/ArticleDetailHero.d.ts +30 -0
- package/dist/components/user/detail/ArticleDetailHero.d.ts.map +1 -0
- package/dist/components/user/detail/ArticleDetailHero.js +29 -0
- package/dist/components/user/detail/ArticleRailDetails.d.ts +24 -0
- package/dist/components/user/detail/ArticleRailDetails.d.ts.map +1 -0
- package/dist/components/user/detail/ArticleRailDetails.js +12 -0
- package/dist/components/user/detail/BackButton.d.ts +7 -0
- package/dist/components/user/detail/BackButton.d.ts.map +1 -0
- package/dist/components/user/detail/BackButton.js +18 -0
- package/dist/components/user/detail/CommentSection.d.ts +28 -0
- package/dist/components/user/detail/CommentSection.d.ts.map +1 -0
- package/dist/components/user/detail/CommentSection.js +68 -0
- package/dist/components/user/detail/HeroFadeSlide.d.ts +12 -0
- package/dist/components/user/detail/HeroFadeSlide.d.ts.map +1 -0
- package/dist/components/user/detail/HeroFadeSlide.js +5 -0
- package/dist/components/user/detail/ReadingProgress.d.ts +2 -0
- package/dist/components/user/detail/ReadingProgress.d.ts.map +1 -0
- package/dist/components/user/detail/ReadingProgress.js +20 -0
- package/dist/components/user/detail/ShareRow.d.ts +7 -0
- package/dist/components/user/detail/ShareRow.d.ts.map +1 -0
- package/dist/components/user/detail/ShareRow.js +7 -0
- package/dist/components/user/detail/toc.d.ts +14 -0
- package/dist/components/user/detail/toc.d.ts.map +1 -0
- package/dist/components/user/detail/toc.js +106 -0
- package/dist/components/user/index.d.ts +14 -0
- package/dist/components/user/index.d.ts.map +1 -0
- package/dist/components/user/index.js +13 -0
- package/dist/components/user/internal/States.d.ts +18 -0
- package/dist/components/user/internal/States.d.ts.map +1 -0
- package/dist/components/user/internal/States.js +21 -0
- package/dist/constants/index.d.ts +4 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +3 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useAsync.d.ts +23 -0
- package/dist/hooks/useAsync.d.ts.map +1 -0
- package/dist/hooks/useAsync.js +40 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/lib/access.d.ts +64 -0
- package/dist/lib/access.d.ts.map +1 -0
- package/dist/lib/access.js +127 -0
- package/dist/lib/canonical.d.ts +15 -0
- package/dist/lib/canonical.d.ts.map +1 -0
- package/dist/lib/canonical.js +34 -0
- package/dist/lib/comments.d.ts +9 -0
- package/dist/lib/comments.d.ts.map +1 -0
- package/dist/lib/comments.js +23 -0
- package/dist/lib/dashboard.d.ts +39 -0
- package/dist/lib/dashboard.d.ts.map +1 -0
- package/dist/lib/dashboard.js +157 -0
- package/dist/lib/data-transfer.d.ts +23 -0
- package/dist/lib/data-transfer.d.ts.map +1 -0
- package/dist/lib/data-transfer.js +436 -0
- package/dist/lib/default-author.d.ts +12 -0
- package/dist/lib/default-author.d.ts.map +1 -0
- package/dist/lib/default-author.js +57 -0
- package/dist/lib/format-media.d.ts +6 -0
- package/dist/lib/format-media.d.ts.map +1 -0
- package/dist/lib/format-media.js +18 -0
- package/dist/lib/format.d.ts +7 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +43 -0
- package/dist/lib/hero-post.d.ts +24 -0
- package/dist/lib/hero-post.d.ts.map +1 -0
- package/dist/lib/hero-post.js +95 -0
- package/dist/lib/lexical-build.d.ts +30 -0
- package/dist/lib/lexical-build.d.ts.map +1 -0
- package/dist/lib/lexical-build.js +57 -0
- package/dist/lib/lexical-doc.d.ts +88 -0
- package/dist/lib/lexical-doc.d.ts.map +1 -0
- package/dist/lib/lexical-doc.js +385 -0
- package/dist/lib/lexical-dom.d.ts +19 -0
- package/dist/lib/lexical-dom.d.ts.map +1 -0
- package/dist/lib/lexical-dom.js +181 -0
- package/dist/lib/lexical.d.ts +31 -0
- package/dist/lib/lexical.d.ts.map +1 -0
- package/dist/lib/lexical.js +59 -0
- package/dist/lib/post-categories.d.ts +11 -0
- package/dist/lib/post-categories.d.ts.map +1 -0
- package/dist/lib/post-categories.js +27 -0
- package/dist/lib/post-format.d.ts +39 -0
- package/dist/lib/post-format.d.ts.map +1 -0
- package/dist/lib/post-format.js +82 -0
- package/dist/lib/publishing.d.ts +3 -0
- package/dist/lib/publishing.d.ts.map +1 -0
- package/dist/lib/publishing.js +1 -0
- package/dist/lib/queries.d.ts +49 -0
- package/dist/lib/queries.d.ts.map +1 -0
- package/dist/lib/queries.js +340 -0
- package/dist/lib/redirect-analytics.d.ts +27 -0
- package/dist/lib/redirect-analytics.d.ts.map +1 -0
- package/dist/lib/redirect-analytics.js +147 -0
- package/dist/lib/redirects.d.ts +39 -0
- package/dist/lib/redirects.d.ts.map +1 -0
- package/dist/lib/redirects.js +96 -0
- package/dist/lib/revalidate.d.ts +30 -0
- package/dist/lib/revalidate.d.ts.map +1 -0
- package/dist/lib/revalidate.js +91 -0
- package/dist/lib/robots.d.ts +19 -0
- package/dist/lib/robots.d.ts.map +1 -0
- package/dist/lib/robots.js +38 -0
- package/dist/lib/seo-analysis.d.ts +28 -0
- package/dist/lib/seo-analysis.d.ts.map +1 -0
- package/dist/lib/seo-analysis.js +153 -0
- package/dist/lib/seo-limits.d.ts +19 -0
- package/dist/lib/seo-limits.d.ts.map +1 -0
- package/dist/lib/seo-limits.js +39 -0
- package/dist/lib/seo.d.ts +50 -0
- package/dist/lib/seo.d.ts.map +1 -0
- package/dist/lib/seo.js +238 -0
- package/dist/lib/slug.d.ts +3 -0
- package/dist/lib/slug.d.ts.map +1 -0
- package/dist/lib/slug.js +9 -0
- package/dist/lib/stats.d.ts +71 -0
- package/dist/lib/stats.d.ts.map +1 -0
- package/dist/lib/stats.js +207 -0
- package/dist/lib/tenant-host.d.ts +9 -0
- package/dist/lib/tenant-host.d.ts.map +1 -0
- package/dist/lib/tenant-host.js +15 -0
- package/dist/lib/tenant.d.ts +41 -0
- package/dist/lib/tenant.d.ts.map +1 -0
- package/dist/lib/tenant.js +140 -0
- package/dist/lib/toc.d.ts +16 -0
- package/dist/lib/toc.d.ts.map +1 -0
- package/dist/lib/toc.js +28 -0
- package/dist/lib/yoast-snippet.d.ts +25 -0
- package/dist/lib/yoast-snippet.d.ts.map +1 -0
- package/dist/lib/yoast-snippet.js +79 -0
- package/dist/pages/admin/BlogAdmin.d.ts +9 -0
- package/dist/pages/admin/BlogAdmin.d.ts.map +1 -0
- package/dist/pages/admin/BlogAdmin.js +234 -0
- package/dist/pages/admin/index.d.ts +2 -0
- package/dist/pages/admin/index.d.ts.map +1 -0
- package/dist/pages/admin/index.js +1 -0
- package/dist/pages/index.d.ts +3 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +2 -0
- package/dist/pages/user/UserBlogPage.d.ts +10 -0
- package/dist/pages/user/UserBlogPage.d.ts.map +1 -0
- package/dist/pages/user/UserBlogPage.js +15 -0
- package/dist/pages/user/index.d.ts +2 -0
- package/dist/pages/user/index.d.ts.map +1 -0
- package/dist/pages/user/index.js +1 -0
- package/dist/services/admin-client.d.ts +33 -0
- package/dist/services/admin-client.d.ts.map +1 -0
- package/dist/services/admin-client.js +154 -0
- package/dist/services/admin-sdk-client.d.ts +285 -0
- package/dist/services/admin-sdk-client.d.ts.map +1 -0
- package/dist/services/admin-sdk-client.js +242 -0
- package/dist/services/errors.d.ts +14 -0
- package/dist/services/errors.d.ts.map +1 -0
- package/dist/services/errors.js +26 -0
- package/dist/services/http.d.ts +24 -0
- package/dist/services/http.d.ts.map +1 -0
- package/dist/services/http.js +159 -0
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +7 -0
- package/dist/services/pagination.d.ts +4 -0
- package/dist/services/pagination.d.ts.map +1 -0
- package/dist/services/pagination.js +32 -0
- package/dist/services/public-client.d.ts +23 -0
- package/dist/services/public-client.d.ts.map +1 -0
- package/dist/services/public-client.js +94 -0
- package/dist/services/types.d.ts +124 -0
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/types.js +1 -0
- package/dist/style.css +3105 -0
- package/dist/styles/adminTheme.d.ts +6 -0
- package/dist/styles/adminTheme.d.ts.map +1 -0
- package/dist/styles/adminTheme.js +52 -0
- package/dist/styles/index.d.ts +3 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles/index.js +2 -0
- package/dist/styles/userTheme.d.ts +8 -0
- package/dist/styles/userTheme.d.ts.map +1 -0
- package/dist/styles/userTheme.js +60 -0
- package/dist/types/admin.d.ts +28 -0
- package/dist/types/admin.d.ts.map +1 -0
- package/dist/types/admin.js +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/user.d.ts +41 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +1 -0
- package/dist/user/components/BlogCard.d.ts +15 -0
- package/dist/user/components/BlogCard.d.ts.map +1 -0
- package/dist/user/components/BlogCard.js +31 -0
- package/dist/user/components/BlogCategories.d.ts +6 -0
- package/dist/user/components/BlogCategories.d.ts.map +1 -0
- package/dist/user/components/BlogCategories.js +11 -0
- package/dist/user/components/BlogDetail.d.ts +7 -0
- package/dist/user/components/BlogDetail.d.ts.map +1 -0
- package/dist/user/components/BlogDetail.js +19 -0
- package/dist/user/components/BlogList.d.ts +8 -0
- package/dist/user/components/BlogList.d.ts.map +1 -0
- package/dist/user/components/BlogList.js +18 -0
- package/dist/user/components/BlogSearch.d.ts +8 -0
- package/dist/user/components/BlogSearch.d.ts.map +1 -0
- package/dist/user/components/BlogSearch.js +19 -0
- package/dist/user/components/BlogTags.d.ts +6 -0
- package/dist/user/components/BlogTags.d.ts.map +1 -0
- package/dist/user/components/BlogTags.js +11 -0
- package/dist/user/components/FeaturedBlogs.d.ts +8 -0
- package/dist/user/components/FeaturedBlogs.d.ts.map +1 -0
- package/dist/user/components/FeaturedBlogs.js +12 -0
- package/dist/user/components/RelatedBlogs.d.ts +9 -0
- package/dist/user/components/RelatedBlogs.d.ts.map +1 -0
- package/dist/user/components/RelatedBlogs.js +12 -0
- package/dist/user/components/internal/States.d.ts +18 -0
- package/dist/user/components/internal/States.d.ts.map +1 -0
- package/dist/user/components/internal/States.js +16 -0
- package/dist/user/hooks/useAsync.d.ts +21 -0
- package/dist/user/hooks/useAsync.d.ts.map +1 -0
- package/dist/user/hooks/useAsync.js +40 -0
- package/dist/user/index.d.ts +11 -0
- package/dist/user/index.d.ts.map +1 -0
- package/dist/user/index.js +10 -0
- package/dist/user/sanitize.d.ts +2 -0
- package/dist/user/sanitize.d.ts.map +1 -0
- package/dist/user/sanitize.js +120 -0
- package/dist/user/theme.d.ts +8 -0
- package/dist/user/theme.d.ts.map +1 -0
- package/dist/user/theme.js +60 -0
- package/dist/user/types.d.ts +41 -0
- package/dist/user/types.d.ts.map +1 -0
- package/dist/user/types.js +1 -0
- package/dist/utils/env.d.ts +16 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +57 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/sanitize.d.ts +2 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +120 -0
- package/package.json +63 -0
package/dist/lib/seo.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { extractPlainText, wordCount } from './lexical';
|
|
2
|
+
import { categoryPath, postPath } from './slug';
|
|
3
|
+
import { resolveMetaDescription, resolveSeoTitle } from './yoast-snippet';
|
|
4
|
+
import { primaryCategory } from './post-categories';
|
|
5
|
+
const isObj = (v) => typeof v === 'object' && v !== null;
|
|
6
|
+
export const mediaUrl = (m, size) => {
|
|
7
|
+
if (!isObj(m))
|
|
8
|
+
return null;
|
|
9
|
+
if (size && m.sizes) {
|
|
10
|
+
const s = m.sizes[size];
|
|
11
|
+
if (s?.url)
|
|
12
|
+
return s.url;
|
|
13
|
+
}
|
|
14
|
+
return m.url ?? null;
|
|
15
|
+
};
|
|
16
|
+
export const mediaDimensions = (m, size) => {
|
|
17
|
+
if (!isObj(m))
|
|
18
|
+
return null;
|
|
19
|
+
if (size && m.sizes) {
|
|
20
|
+
const s = m.sizes[size];
|
|
21
|
+
if (s?.width && s?.height)
|
|
22
|
+
return { width: s.width, height: s.height };
|
|
23
|
+
}
|
|
24
|
+
if (m.width && m.height)
|
|
25
|
+
return { width: m.width, height: m.height };
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const absolute = (origin, pathOrUrl) => {
|
|
29
|
+
if (!pathOrUrl)
|
|
30
|
+
return null;
|
|
31
|
+
if (/^https?:\/\//i.test(pathOrUrl))
|
|
32
|
+
return pathOrUrl;
|
|
33
|
+
return `${origin}${pathOrUrl.startsWith('/') ? '' : '/'}${pathOrUrl}`;
|
|
34
|
+
};
|
|
35
|
+
const applyTitleTemplate = (tenant, title) => {
|
|
36
|
+
const template = tenant.seoDefaults?.titleTemplate || '%s';
|
|
37
|
+
const siteName = tenant.seoDefaults?.siteName || tenant.name;
|
|
38
|
+
return template.replace('%s', title).replace('%site%', siteName);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Indexing controls. Anything that is not the production environment is forced
|
|
42
|
+
* to noindex here *and* at the header level in middleware — a staging site
|
|
43
|
+
* cannot be indexed even if someone links to it.
|
|
44
|
+
*/
|
|
45
|
+
const robotsFor = (args) => {
|
|
46
|
+
const isProd = process.env.NEXT_PUBLIC_APP_ENV === 'production';
|
|
47
|
+
const index = isProd && !args.noindex;
|
|
48
|
+
const follow = !args.nofollow;
|
|
49
|
+
return {
|
|
50
|
+
index,
|
|
51
|
+
follow,
|
|
52
|
+
googleBot: { index, follow, 'max-image-preview': 'large', 'max-snippet': -1 },
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Metadata
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
export const postMetadata = (args) => {
|
|
59
|
+
const { tenant, post, origin } = args;
|
|
60
|
+
const path = args.path ?? postPath(post.slug);
|
|
61
|
+
const canonical = post.seo?.canonicalOverride || `${origin}${path}`;
|
|
62
|
+
const category = primaryCategory(post);
|
|
63
|
+
const snippetCtx = {
|
|
64
|
+
title: post.title,
|
|
65
|
+
slug: post.slug,
|
|
66
|
+
excerpt: post.excerpt ?? '',
|
|
67
|
+
siteName: tenant.seoDefaults?.siteName || tenant.name,
|
|
68
|
+
categoryName: category?.name,
|
|
69
|
+
focusKeyphrase: post.seo?.focusKeyphrase ?? '',
|
|
70
|
+
contentText: extractPlainText(post.content),
|
|
71
|
+
date: post.publishedAt ?? post.createdAt,
|
|
72
|
+
};
|
|
73
|
+
const title = resolveSeoTitle(post.seo?.metaTitle, snippetCtx);
|
|
74
|
+
const description = resolveMetaDescription(post.seo?.metaDescription, snippetCtx);
|
|
75
|
+
const ogTitle = post.seo?.ogTitle || title;
|
|
76
|
+
const ogDescription = post.seo?.ogDescription || description;
|
|
77
|
+
const ogSource = post.seo?.ogImage ?? post.featuredImage ?? tenant.seoDefaults?.defaultOgImage;
|
|
78
|
+
const ogUrl = absolute(origin, mediaUrl(ogSource, 'og'));
|
|
79
|
+
const ogDims = mediaDimensions(ogSource, 'og');
|
|
80
|
+
return {
|
|
81
|
+
title: applyTitleTemplate(tenant, title),
|
|
82
|
+
description,
|
|
83
|
+
alternates: { canonical },
|
|
84
|
+
robots: robotsFor({ noindex: post.seo?.noindex, nofollow: post.seo?.nofollow }),
|
|
85
|
+
openGraph: {
|
|
86
|
+
type: 'article',
|
|
87
|
+
title: ogTitle,
|
|
88
|
+
description: ogDescription,
|
|
89
|
+
url: canonical,
|
|
90
|
+
siteName: tenant.seoDefaults?.siteName || tenant.name,
|
|
91
|
+
publishedTime: post.publishedAt ?? undefined,
|
|
92
|
+
modifiedTime: post.updatedAt,
|
|
93
|
+
images: ogUrl
|
|
94
|
+
? [{ url: ogUrl, width: ogDims?.width ?? 1200, height: ogDims?.height ?? 630 }]
|
|
95
|
+
: undefined,
|
|
96
|
+
},
|
|
97
|
+
twitter: {
|
|
98
|
+
card: 'summary_large_image',
|
|
99
|
+
title: ogTitle,
|
|
100
|
+
description: ogDescription,
|
|
101
|
+
images: ogUrl ? [ogUrl] : undefined,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export const listingMetadata = (args) => {
|
|
106
|
+
const { tenant, origin, title, description, path, noindex, page } = args;
|
|
107
|
+
// Paginated pages are their own canonical — pointing page 2 at page 1 hides
|
|
108
|
+
// the deeper articles from crawlers entirely.
|
|
109
|
+
const canonical = `${origin}${path}${page && page > 1 ? `?page=${page}` : ''}`;
|
|
110
|
+
return {
|
|
111
|
+
title: applyTitleTemplate(tenant, page && page > 1 ? `${title} — page ${page}` : title),
|
|
112
|
+
description: description || undefined,
|
|
113
|
+
alternates: { canonical },
|
|
114
|
+
robots: robotsFor({ noindex }),
|
|
115
|
+
openGraph: {
|
|
116
|
+
type: 'website',
|
|
117
|
+
title,
|
|
118
|
+
description: description || undefined,
|
|
119
|
+
url: canonical,
|
|
120
|
+
siteName: tenant.seoDefaults?.siteName || tenant.name,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Structured data
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
const organizationNode = (tenant, origin) => ({
|
|
128
|
+
'@type': 'Organization',
|
|
129
|
+
'@id': `${origin}#organization`,
|
|
130
|
+
name: tenant.seoDefaults?.siteName || tenant.name,
|
|
131
|
+
url: origin,
|
|
132
|
+
...(mediaUrl(tenant.seoDefaults?.organizationLogo)
|
|
133
|
+
? {
|
|
134
|
+
logo: {
|
|
135
|
+
'@type': 'ImageObject',
|
|
136
|
+
url: absolute(origin, mediaUrl(tenant.seoDefaults?.organizationLogo)),
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
: {}),
|
|
140
|
+
});
|
|
141
|
+
const personNodes = (authors, origin) => authors.filter((isObj)).map((a) => ({
|
|
142
|
+
'@type': 'Person',
|
|
143
|
+
'@id': `${origin}/blog/author/${a.slug}#person`,
|
|
144
|
+
name: a.name,
|
|
145
|
+
...(a.jobTitle ? { jobTitle: a.jobTitle } : {}),
|
|
146
|
+
...(a.bio ? { description: a.bio } : {}),
|
|
147
|
+
...(a.links?.length
|
|
148
|
+
? { sameAs: a.links.map((l) => l.url).filter(Boolean) }
|
|
149
|
+
: {}),
|
|
150
|
+
}));
|
|
151
|
+
/**
|
|
152
|
+
* A single @graph containing Article, BreadcrumbList, Person and Organization.
|
|
153
|
+
* One script tag, cross-referenced by @id, is what Google prefers over several
|
|
154
|
+
* disconnected blocks.
|
|
155
|
+
*/
|
|
156
|
+
export const articleJsonLd = (args) => {
|
|
157
|
+
const { tenant, post, origin } = args;
|
|
158
|
+
const url = `${origin}${postPath(post.slug)}`;
|
|
159
|
+
const category = primaryCategory(post);
|
|
160
|
+
const authors = Array.isArray(post.authors) ? post.authors : [];
|
|
161
|
+
const image = absolute(origin, mediaUrl(post.featuredImage, 'og') || mediaUrl(post.featuredImage, 'hero'));
|
|
162
|
+
const breadcrumbItems = [
|
|
163
|
+
{ name: 'Home', item: origin },
|
|
164
|
+
{ name: tenant.seoDefaults?.blogTitle || 'Blog', item: `${origin}/blog` },
|
|
165
|
+
...(category
|
|
166
|
+
? [{ name: category.name, item: `${origin}${categoryPath(category.slug)}` }]
|
|
167
|
+
: []),
|
|
168
|
+
{ name: post.seo?.breadcrumbTitle || post.title, item: url },
|
|
169
|
+
];
|
|
170
|
+
const schemaType = post.seo?.schemaType || 'Article';
|
|
171
|
+
return {
|
|
172
|
+
'@context': 'https://schema.org',
|
|
173
|
+
'@graph': [
|
|
174
|
+
{
|
|
175
|
+
'@type': schemaType,
|
|
176
|
+
'@id': `${url}#article`,
|
|
177
|
+
headline: post.title.slice(0, 110),
|
|
178
|
+
description: post.seo?.metaDescription || post.excerpt || undefined,
|
|
179
|
+
url,
|
|
180
|
+
mainEntityOfPage: { '@id': url },
|
|
181
|
+
datePublished: post.publishedAt ?? post.createdAt,
|
|
182
|
+
dateModified: post.updatedAt,
|
|
183
|
+
wordCount: wordCount(post.content) || undefined,
|
|
184
|
+
...(image
|
|
185
|
+
? { image: { '@type': 'ImageObject', url: image } }
|
|
186
|
+
: {}),
|
|
187
|
+
...(category ? { articleSection: category.name } : {}),
|
|
188
|
+
author: personNodes(authors, origin).map((p) => ({ '@id': p['@id'] })),
|
|
189
|
+
publisher: { '@id': `${origin}#organization` },
|
|
190
|
+
isPartOf: { '@id': `${origin}#website` },
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
'@type': 'BreadcrumbList',
|
|
194
|
+
'@id': `${url}#breadcrumbs`,
|
|
195
|
+
itemListElement: breadcrumbItems.map((b, i) => ({
|
|
196
|
+
'@type': 'ListItem',
|
|
197
|
+
position: i + 1,
|
|
198
|
+
name: b.name,
|
|
199
|
+
item: b.item,
|
|
200
|
+
})),
|
|
201
|
+
},
|
|
202
|
+
...personNodes(authors, origin),
|
|
203
|
+
organizationNode(tenant, origin),
|
|
204
|
+
{
|
|
205
|
+
'@type': 'WebSite',
|
|
206
|
+
'@id': `${origin}#website`,
|
|
207
|
+
url: origin,
|
|
208
|
+
name: tenant.seoDefaults?.siteName || tenant.name,
|
|
209
|
+
publisher: { '@id': `${origin}#organization` },
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
export const blogJsonLd = (args) => {
|
|
215
|
+
const { tenant, origin, posts } = args;
|
|
216
|
+
return {
|
|
217
|
+
'@context': 'https://schema.org',
|
|
218
|
+
'@graph': [
|
|
219
|
+
{
|
|
220
|
+
'@type': 'Blog',
|
|
221
|
+
'@id': `${origin}/blog#blog`,
|
|
222
|
+
url: `${origin}/blog`,
|
|
223
|
+
name: tenant.seoDefaults?.blogTitle || `${tenant.name} Blog`,
|
|
224
|
+
description: tenant.seoDefaults?.blogDescription || undefined,
|
|
225
|
+
publisher: { '@id': `${origin}#organization` },
|
|
226
|
+
blogPost: posts.slice(0, 10).map((p) => ({
|
|
227
|
+
'@type': 'BlogPosting',
|
|
228
|
+
headline: p.title.slice(0, 110),
|
|
229
|
+
url: `${origin}${postPath(p.slug)}`,
|
|
230
|
+
datePublished: p.publishedAt ?? p.createdAt,
|
|
231
|
+
})),
|
|
232
|
+
},
|
|
233
|
+
organizationNode(tenant, origin),
|
|
234
|
+
],
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
/** JSON-LD is serialised with `<` escaped so it can never break out of the script tag. */
|
|
238
|
+
export const jsonLdScript = (data) => JSON.stringify(data).replace(/</g, '\\u003c');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../../app/lib/slug.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,KAAG,MAQvB,CAAC"}
|
package/dist/lib/slug.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard aggregations.
|
|
3
|
+
*
|
|
4
|
+
* These run through Mongo's aggregation pipeline rather than by loading
|
|
5
|
+
* documents into Node and reducing there. At 90 days × 500 posts that is the
|
|
6
|
+
* difference between one indexed group-by and 45,000 documents crossing the
|
|
7
|
+
* process boundary on every dashboard load.
|
|
8
|
+
*
|
|
9
|
+
* Tenant scoping is passed in explicitly by the caller, which has already
|
|
10
|
+
* resolved it from access control — this module never decides who sees what.
|
|
11
|
+
*/
|
|
12
|
+
export type DayPoint = {
|
|
13
|
+
date: string;
|
|
14
|
+
views: number;
|
|
15
|
+
uniques: number;
|
|
16
|
+
};
|
|
17
|
+
export type TopPost = {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
views: number;
|
|
22
|
+
brand: string;
|
|
23
|
+
};
|
|
24
|
+
export type Bucket = {
|
|
25
|
+
label: string;
|
|
26
|
+
value: number;
|
|
27
|
+
};
|
|
28
|
+
export declare const daysBack: (n: number) => string[];
|
|
29
|
+
/** Views per day over the window, zero-filled so the chart has no gaps. */
|
|
30
|
+
export declare const viewsByDay: (args: {
|
|
31
|
+
tenantIds: string[];
|
|
32
|
+
days: number;
|
|
33
|
+
}) => Promise<DayPoint[]>;
|
|
34
|
+
/** Total views in a window, plus the previous equal window for the trend. */
|
|
35
|
+
export declare const viewsTotals: (args: {
|
|
36
|
+
tenantIds: string[];
|
|
37
|
+
days: number;
|
|
38
|
+
}) => Promise<{
|
|
39
|
+
current: number;
|
|
40
|
+
previous: number;
|
|
41
|
+
changePct: number | null;
|
|
42
|
+
}>;
|
|
43
|
+
/** Most-viewed posts in the window. */
|
|
44
|
+
export declare const topPosts: (args: {
|
|
45
|
+
tenantIds: string[];
|
|
46
|
+
days: number;
|
|
47
|
+
limit?: number;
|
|
48
|
+
}) => Promise<TopPost[]>;
|
|
49
|
+
/** Published post counts per category, largest first. */
|
|
50
|
+
export declare const postsByCategory: (args: {
|
|
51
|
+
tenantIds: string[];
|
|
52
|
+
max?: number;
|
|
53
|
+
}) => Promise<Bucket[]>;
|
|
54
|
+
/** Pipeline counts: the funnel from writing to live. */
|
|
55
|
+
export declare const pipelineCounts: (args: {
|
|
56
|
+
tenantIds: string[];
|
|
57
|
+
}) => Promise<{
|
|
58
|
+
writing: number;
|
|
59
|
+
inReview: number;
|
|
60
|
+
approved: number;
|
|
61
|
+
live: number;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Views per post for a specific set of posts — one aggregate for the whole page
|
|
65
|
+
* of the list, rather than a query per row.
|
|
66
|
+
*/
|
|
67
|
+
export declare const viewsForPosts: (args: {
|
|
68
|
+
postIds: string[];
|
|
69
|
+
days: number;
|
|
70
|
+
}) => Promise<Map<string, number>>;
|
|
71
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../app/lib/stats.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AACvE,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAC/F,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAIrD,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,KAAG,MAAM,EAO1C,CAAA;AAeD,2EAA2E;AAC3E,eAAO,MAAM,UAAU,GAAU,MAAM;IACrC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,KAAG,OAAO,CAAC,QAAQ,EAAE,CAgCrB,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,WAAW,GAAU,MAAM;IACtC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CA2B1E,CAAA;AAED,uCAAuC;AACvC,eAAO,MAAM,QAAQ,GAAU,MAAM;IACnC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,KAAG,OAAO,CAAC,OAAO,EAAE,CA+CpB,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,eAAe,GAAU,MAAM;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,KAAG,OAAO,CAAC,MAAM,EAAE,CAyCnB,CAAA;AAED,wDAAwD;AACxD,eAAO,MAAM,cAAc,GAAU,MAAM;IACzC,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA0BhF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,MAAM;IACxC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,KAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAmB9B,CAAA"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { getPayloadClient } from './tenant';
|
|
2
|
+
import { asCategories } from './post-categories';
|
|
3
|
+
const utcDay = (d) => d.toISOString().slice(0, 10);
|
|
4
|
+
export const daysBack = (n) => {
|
|
5
|
+
const out = [];
|
|
6
|
+
const today = new Date();
|
|
7
|
+
for (let i = n - 1; i >= 0; i -= 1) {
|
|
8
|
+
out.push(utcDay(new Date(today.getTime() - i * 86400000)));
|
|
9
|
+
}
|
|
10
|
+
return out;
|
|
11
|
+
};
|
|
12
|
+
const rawDb = async () => {
|
|
13
|
+
const payload = await getPayloadClient();
|
|
14
|
+
return (payload.db.connection?.db ?? null);
|
|
15
|
+
};
|
|
16
|
+
/** Views per day over the window, zero-filled so the chart has no gaps. */
|
|
17
|
+
export const viewsByDay = async (args) => {
|
|
18
|
+
const { tenantIds, days } = args;
|
|
19
|
+
const window = daysBack(days);
|
|
20
|
+
const db = await rawDb();
|
|
21
|
+
const empty = window.map((date) => ({ date, views: 0, uniques: 0 }));
|
|
22
|
+
if (!db || tenantIds.length === 0)
|
|
23
|
+
return empty;
|
|
24
|
+
const rows = await db
|
|
25
|
+
.collection('analytics')
|
|
26
|
+
.aggregate([
|
|
27
|
+
{ $match: { tenant: { $in: tenantIds }, date: { $gte: window[0] } } },
|
|
28
|
+
{
|
|
29
|
+
$group: {
|
|
30
|
+
_id: '$date',
|
|
31
|
+
views: { $sum: '$views' },
|
|
32
|
+
uniques: { $sum: '$uniques' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
])
|
|
36
|
+
.toArray();
|
|
37
|
+
const byDate = new Map(rows.map((r) => [String(r._id), r]));
|
|
38
|
+
// Zero-fill: a day with no traffic is a real zero, not a missing point. Letting
|
|
39
|
+
// the line skip it would silently redraw the shape of the trend.
|
|
40
|
+
return window.map((date) => {
|
|
41
|
+
const hit = byDate.get(date);
|
|
42
|
+
return {
|
|
43
|
+
date,
|
|
44
|
+
views: Number(hit?.views ?? 0),
|
|
45
|
+
uniques: Number(hit?.uniques ?? 0),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
/** Total views in a window, plus the previous equal window for the trend. */
|
|
50
|
+
export const viewsTotals = async (args) => {
|
|
51
|
+
const { tenantIds, days } = args;
|
|
52
|
+
const db = await rawDb();
|
|
53
|
+
if (!db || tenantIds.length === 0)
|
|
54
|
+
return { current: 0, previous: 0, changePct: null };
|
|
55
|
+
const now = new Date();
|
|
56
|
+
const startCurrent = utcDay(new Date(now.getTime() - (days - 1) * 86400000));
|
|
57
|
+
const startPrev = utcDay(new Date(now.getTime() - (days * 2 - 1) * 86400000));
|
|
58
|
+
const rows = await db
|
|
59
|
+
.collection('analytics')
|
|
60
|
+
.aggregate([
|
|
61
|
+
{ $match: { tenant: { $in: tenantIds }, date: { $gte: startPrev } } },
|
|
62
|
+
{
|
|
63
|
+
$group: {
|
|
64
|
+
_id: { $cond: [{ $gte: ['$date', startCurrent] }, 'current', 'previous'] },
|
|
65
|
+
views: { $sum: '$views' },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
])
|
|
69
|
+
.toArray();
|
|
70
|
+
const current = Number(rows.find((r) => r._id === 'current')?.views ?? 0);
|
|
71
|
+
const previous = Number(rows.find((r) => r._id === 'previous')?.views ?? 0);
|
|
72
|
+
const changePct = previous > 0 ? ((current - previous) / previous) * 100 : null;
|
|
73
|
+
return { current, previous, changePct };
|
|
74
|
+
};
|
|
75
|
+
/** Most-viewed posts in the window. */
|
|
76
|
+
export const topPosts = async (args) => {
|
|
77
|
+
const { tenantIds, days, limit = 6 } = args;
|
|
78
|
+
const db = await rawDb();
|
|
79
|
+
if (!db || tenantIds.length === 0)
|
|
80
|
+
return [];
|
|
81
|
+
const window = daysBack(days);
|
|
82
|
+
const rows = await db
|
|
83
|
+
.collection('analytics')
|
|
84
|
+
.aggregate([
|
|
85
|
+
{ $match: { tenant: { $in: tenantIds }, date: { $gte: window[0] } } },
|
|
86
|
+
{ $group: { _id: '$post', views: { $sum: '$views' } } },
|
|
87
|
+
{ $sort: { views: -1 } },
|
|
88
|
+
{ $limit: limit },
|
|
89
|
+
])
|
|
90
|
+
.toArray();
|
|
91
|
+
if (rows.length === 0)
|
|
92
|
+
return [];
|
|
93
|
+
const payload = await getPayloadClient();
|
|
94
|
+
const posts = await payload.find({
|
|
95
|
+
collection: 'posts',
|
|
96
|
+
where: { id: { in: rows.map((r) => String(r._id)) } },
|
|
97
|
+
depth: 1,
|
|
98
|
+
limit,
|
|
99
|
+
pagination: false,
|
|
100
|
+
overrideAccess: true,
|
|
101
|
+
});
|
|
102
|
+
const byId = new Map(posts.docs.map((p) => [String(p.id), p]));
|
|
103
|
+
return rows
|
|
104
|
+
.map((r) => {
|
|
105
|
+
const post = byId.get(String(r._id));
|
|
106
|
+
if (!post)
|
|
107
|
+
return null;
|
|
108
|
+
const brand = post.tenant && typeof post.tenant === 'object'
|
|
109
|
+
? post.tenant.name
|
|
110
|
+
: '';
|
|
111
|
+
return {
|
|
112
|
+
id: String(post.id),
|
|
113
|
+
title: post.title,
|
|
114
|
+
slug: post.slug,
|
|
115
|
+
views: Number(r.views),
|
|
116
|
+
brand,
|
|
117
|
+
};
|
|
118
|
+
})
|
|
119
|
+
.filter((x) => x !== null);
|
|
120
|
+
};
|
|
121
|
+
/** Published post counts per category, largest first. */
|
|
122
|
+
export const postsByCategory = async (args) => {
|
|
123
|
+
const { tenantIds, max = 4 } = args;
|
|
124
|
+
const payload = await getPayloadClient();
|
|
125
|
+
if (tenantIds.length === 0)
|
|
126
|
+
return [];
|
|
127
|
+
const res = await payload.find({
|
|
128
|
+
collection: 'posts',
|
|
129
|
+
where: {
|
|
130
|
+
and: [
|
|
131
|
+
{ tenant: { in: tenantIds } },
|
|
132
|
+
{ _status: { equals: 'published' } },
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
depth: 1,
|
|
136
|
+
limit: 2000,
|
|
137
|
+
pagination: false,
|
|
138
|
+
overrideAccess: true,
|
|
139
|
+
});
|
|
140
|
+
const counts = new Map();
|
|
141
|
+
for (const post of res.docs) {
|
|
142
|
+
const names = asCategories(post.category).map((c) => c.name);
|
|
143
|
+
if (!names.length) {
|
|
144
|
+
counts.set('Uncategorised', (counts.get('Uncategorised') ?? 0) + 1);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
for (const name of names) {
|
|
148
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const sorted = [...counts.entries()]
|
|
152
|
+
.map(([label, value]) => ({ label, value }))
|
|
153
|
+
.sort((a, b) => b.value - a.value);
|
|
154
|
+
// The palette validates three categorical slots for all-pairs use; anything
|
|
155
|
+
// past that folds into "Other" rather than inventing a fourth hue.
|
|
156
|
+
if (sorted.length <= max)
|
|
157
|
+
return sorted;
|
|
158
|
+
const head = sorted.slice(0, max - 1);
|
|
159
|
+
const tail = sorted.slice(max - 1).reduce((sum, b) => sum + b.value, 0);
|
|
160
|
+
return [...head, { label: 'Other', value: tail }];
|
|
161
|
+
};
|
|
162
|
+
/** Pipeline counts: the funnel from writing to live. */
|
|
163
|
+
export const pipelineCounts = async (args) => {
|
|
164
|
+
const payload = await getPayloadClient();
|
|
165
|
+
if (args.tenantIds.length === 0) {
|
|
166
|
+
return { writing: 0, inReview: 0, approved: 0, live: 0 };
|
|
167
|
+
}
|
|
168
|
+
const scope = { tenant: { in: args.tenantIds } };
|
|
169
|
+
const count = async (extra) => (await payload.find({
|
|
170
|
+
collection: 'posts',
|
|
171
|
+
where: { and: [scope, ...extra] },
|
|
172
|
+
limit: 0,
|
|
173
|
+
depth: 0,
|
|
174
|
+
overrideAccess: true,
|
|
175
|
+
})).totalDocs;
|
|
176
|
+
const [writing, inReview, approved, live] = await Promise.all([
|
|
177
|
+
count([{ _status: { equals: 'draft' } }, { reviewState: { equals: 'writing' } }]),
|
|
178
|
+
count([{ _status: { equals: 'draft' } }, { reviewState: { equals: 'in-review' } }]),
|
|
179
|
+
count([{ _status: { equals: 'draft' } }, { reviewState: { equals: 'approved' } }]),
|
|
180
|
+
count([{ _status: { equals: 'published' } }]),
|
|
181
|
+
]);
|
|
182
|
+
return { writing, inReview, approved, live };
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Views per post for a specific set of posts — one aggregate for the whole page
|
|
186
|
+
* of the list, rather than a query per row.
|
|
187
|
+
*/
|
|
188
|
+
export const viewsForPosts = async (args) => {
|
|
189
|
+
const { postIds, days } = args;
|
|
190
|
+
const out = new Map();
|
|
191
|
+
if (postIds.length === 0)
|
|
192
|
+
return out;
|
|
193
|
+
const db = await rawDb();
|
|
194
|
+
if (!db)
|
|
195
|
+
return out;
|
|
196
|
+
const window = daysBack(days);
|
|
197
|
+
const rows = await db
|
|
198
|
+
.collection('analytics')
|
|
199
|
+
.aggregate([
|
|
200
|
+
{ $match: { post: { $in: postIds }, date: { $gte: window[0] } } },
|
|
201
|
+
{ $group: { _id: '$post', views: { $sum: '$views' } } },
|
|
202
|
+
])
|
|
203
|
+
.toArray();
|
|
204
|
+
for (const row of rows)
|
|
205
|
+
out.set(String(row._id), Number(row.views ?? 0));
|
|
206
|
+
return out;
|
|
207
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Cookie + query keys for picking a brand on a shared host (localhost, *.vercel.app). */
|
|
2
|
+
export declare const DEV_TENANT_PARAM = "_tenant";
|
|
3
|
+
export declare const DEV_TENANT_COOKIE = "dev-tenant";
|
|
4
|
+
export declare const DEV_TENANT_HEADER = "x-dev-tenant";
|
|
5
|
+
export declare const ADMIN_BRAND_PARAM = "brand";
|
|
6
|
+
/** Hostnames where several brands share one origin and a slug override is allowed. */
|
|
7
|
+
export declare const isSharedPreviewHost: (host: string | null | undefined) => boolean;
|
|
8
|
+
export declare const allowTenantSlugOverride: (host: string | null | undefined) => boolean;
|
|
9
|
+
//# sourceMappingURL=tenant-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-host.d.ts","sourceRoot":"","sources":["../../app/lib/tenant-host.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,eAAO,MAAM,gBAAgB,YAAY,CAAA;AACzC,eAAO,MAAM,iBAAiB,eAAe,CAAA;AAC7C,eAAO,MAAM,iBAAiB,iBAAiB,CAAA;AAC/C,eAAO,MAAM,iBAAiB,UAAU,CAAA;AAIxC,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,OAQrE,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,OACK,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Cookie + query keys for picking a brand on a shared host (localhost, *.vercel.app). */
|
|
2
|
+
export const DEV_TENANT_PARAM = '_tenant';
|
|
3
|
+
export const DEV_TENANT_COOKIE = 'dev-tenant';
|
|
4
|
+
export const DEV_TENANT_HEADER = 'x-dev-tenant';
|
|
5
|
+
export const ADMIN_BRAND_PARAM = 'brand';
|
|
6
|
+
const normaliseHost = (host) => host.trim().toLowerCase().replace(/\.$/, '');
|
|
7
|
+
/** Hostnames where several brands share one origin and a slug override is allowed. */
|
|
8
|
+
export const isSharedPreviewHost = (host) => {
|
|
9
|
+
const h = normaliseHost(host ?? '');
|
|
10
|
+
return (h.startsWith('localhost') ||
|
|
11
|
+
h.startsWith('127.0.0.1') ||
|
|
12
|
+
h.endsWith('.vercel.app') ||
|
|
13
|
+
h === 'vercel.app');
|
|
14
|
+
};
|
|
15
|
+
export const allowTenantSlugOverride = (host) => process.env.NEXT_PUBLIC_APP_ENV !== 'production' || isSharedPreviewHost(host);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Tenant } from '../payload-types';
|
|
2
|
+
/**
|
|
3
|
+
* Tenant resolution.
|
|
4
|
+
*
|
|
5
|
+
* The renderer is a single deployment serving every brand, so which brand a
|
|
6
|
+
* request belongs to is derived from the Host header — never from a path prefix
|
|
7
|
+
* and never from an environment variable. That is what lets one origin sit
|
|
8
|
+
* behind fifteen `/blog` rewrites without any per-brand configuration.
|
|
9
|
+
*
|
|
10
|
+
* In local development several brands share localhost, so `?_tenant=slug` (and
|
|
11
|
+
* a short-lived cookie set from it) selects the brand when the Host alone is
|
|
12
|
+
* ambiguous.
|
|
13
|
+
*/
|
|
14
|
+
export { ADMIN_BRAND_PARAM, DEV_TENANT_COOKIE, DEV_TENANT_HEADER, DEV_TENANT_PARAM } from './tenant-host';
|
|
15
|
+
/** One Payload instance per request — pages + layout used to open it twice. */
|
|
16
|
+
export declare const getPayloadClient: any;
|
|
17
|
+
export declare const resolveTenantByHost: (host: string | null) => Promise<Tenant | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Brand slug from the current request override header (set by middleware from
|
|
20
|
+
* `?_tenant=` on public pages, or `?brand=` / cookie on admin).
|
|
21
|
+
*/
|
|
22
|
+
export declare const getExplicitTenantSlug: () => Promise<string | null>;
|
|
23
|
+
/**
|
|
24
|
+
* On localhost / *.vercel.app, public listings match admin "All brands" by default.
|
|
25
|
+
* Pass `tenantFromQuery` from `?_tenant=` to scope to one brand.
|
|
26
|
+
*/
|
|
27
|
+
export declare const shouldListAllBrands: (tenantFromQuery?: string | null) => Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the tenant for the current request.
|
|
30
|
+
*
|
|
31
|
+
* On a real brand domain, the Host header wins. On shared preview hosts
|
|
32
|
+
* (localhost, *.vercel.app), `?_tenant=` (public) or `?brand=` (admin) selects
|
|
33
|
+
* a brand. Public default with no picker is all-brands listings.
|
|
34
|
+
*
|
|
35
|
+
* Wrapped in React cache so layout + page share one lookup per request.
|
|
36
|
+
*/
|
|
37
|
+
export declare const getCurrentTenant: any;
|
|
38
|
+
/** Absolute origin for canonical URLs and the sitemap. */
|
|
39
|
+
export declare const tenantOrigin: (tenant: Pick<Tenant, "primaryDomain">, requestHost?: string) => string;
|
|
40
|
+
export declare const currentOrigin: (tenant: Pick<Tenant, "primaryDomain">) => Promise<string>;
|
|
41
|
+
//# sourceMappingURL=tenant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../app/lib/tenant.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAQ9C;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEzG,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,KAA4C,CAAA;AAyBzE,eAAO,MAAM,mBAAmB,GAAU,MAAM,MAAM,GAAG,IAAI,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAsCpF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,MAAM,GAAG,IAAI,CAKnE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,kBAAkB,MAAM,GAAG,IAAI,KAC9B,OAAO,CAAC,OAAO,CAQjB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,KAgB3B,CAAA;AAEF,0DAA0D;AAC1D,eAAO,MAAM,YAAY,GAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,cAAc,MAAM,KAAG,MAO1F,CAAA;AAED,eAAO,MAAM,aAAa,GAAU,QAAQ,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,KAAG,OAAO,CAAC,MAAM,CAGzF,CAAA"}
|