@lupinum/ginko-content 0.1.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/LICENSE +21 -0
- package/README.md +90 -0
- package/compatibility.json +27 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +690 -0
- package/dist/cms-contract/build +1 -0
- package/dist/cms-contract/build.d.ts +44 -0
- package/dist/cms-contract/build.js +513 -0
- package/dist/cms-contract/index +1 -0
- package/dist/cms-contract/index.d.ts +25 -0
- package/dist/cms-contract/index.js +37 -0
- package/dist/cms-contract/mdc +1 -0
- package/dist/cms-contract/mdc.d.ts +32 -0
- package/dist/cms-contract/mdc.js +52 -0
- package/dist/cms-contract/path +1 -0
- package/dist/cms-contract/path.d.ts +12 -0
- package/dist/cms-contract/path.js +18 -0
- package/dist/cms-contract/schema +1 -0
- package/dist/cms-contract/schema.d.ts +18 -0
- package/dist/cms-contract/schema.js +13 -0
- package/dist/cms-contract/types +1 -0
- package/dist/cms-contract/types.d.ts +177 -0
- package/dist/cms-contract/types.js +0 -0
- package/dist/cms-import/index +1 -0
- package/dist/cms-import/index.d.ts +21 -0
- package/dist/cms-import/index.js +57 -0
- package/dist/config.d.mts +3 -0
- package/dist/config.mjs +3 -0
- package/dist/core/cache +1 -0
- package/dist/core/cache-hints +1 -0
- package/dist/core/cache-hints.d.ts +3 -0
- package/dist/core/cache-hints.js +55 -0
- package/dist/core/cache.d.ts +29 -0
- package/dist/core/cache.js +0 -0
- package/dist/core/content/collection +1 -0
- package/dist/core/content/collection.d.ts +3 -0
- package/dist/core/content/collection.js +52 -0
- package/dist/core/content/graph +1 -0
- package/dist/core/content/graph.d.ts +147 -0
- package/dist/core/content/graph.js +189 -0
- package/dist/core/content/ignore +1 -0
- package/dist/core/content/ignore.d.ts +5 -0
- package/dist/core/content/ignore.js +10 -0
- package/dist/core/content/locale +1 -0
- package/dist/core/content/locale.d.ts +61 -0
- package/dist/core/content/locale.js +77 -0
- package/dist/core/content/path +1 -0
- package/dist/core/content/path.d.ts +36 -0
- package/dist/core/content/path.js +143 -0
- package/dist/core/content/slug +1 -0
- package/dist/core/content/slug.d.ts +4 -0
- package/dist/core/content/slug.js +41 -0
- package/dist/core/content/sources +1 -0
- package/dist/core/content/sources.d.ts +2 -0
- package/dist/core/content/sources.js +6 -0
- package/dist/core/errors +1 -0
- package/dist/core/errors.d.ts +15 -0
- package/dist/core/errors.js +10 -0
- package/dist/core/markdown/tree +1 -0
- package/dist/core/markdown/tree.d.ts +9 -0
- package/dist/core/markdown/tree.js +47 -0
- package/dist/core/query/builder +1 -0
- package/dist/core/query/builder.d.ts +18 -0
- package/dist/core/query/builder.js +186 -0
- package/dist/core/query/execute +1 -0
- package/dist/core/query/execute.d.ts +52 -0
- package/dist/core/query/execute.js +304 -0
- package/dist/core/query/filter +1 -0
- package/dist/core/query/filter.d.ts +42 -0
- package/dist/core/query/filter.js +118 -0
- package/dist/core/query/json +1 -0
- package/dist/core/query/json.d.ts +2 -0
- package/dist/core/query/json.js +20 -0
- package/dist/core/query/lower +1 -0
- package/dist/core/query/lower.d.ts +14 -0
- package/dist/core/query/lower.js +121 -0
- package/dist/core/query/operators +1 -0
- package/dist/core/query/operators.d.ts +23 -0
- package/dist/core/query/operators.js +126 -0
- package/dist/core/query/params +1 -0
- package/dist/core/query/params.d.ts +15 -0
- package/dist/core/query/params.js +83 -0
- package/dist/core/query/plan +1 -0
- package/dist/core/query/plan.d.ts +110 -0
- package/dist/core/query/plan.js +0 -0
- package/dist/core/references/resolve +1 -0
- package/dist/core/references/resolve.d.ts +31 -0
- package/dist/core/references/resolve.js +121 -0
- package/dist/core/references/schema +1 -0
- package/dist/core/references/schema.d.ts +8 -0
- package/dist/core/references/schema.js +70 -0
- package/dist/core/result +1 -0
- package/dist/core/result.d.ts +27 -0
- package/dist/core/result.js +2 -0
- package/dist/features/collections/resolve +1 -0
- package/dist/features/collections/resolve.d.ts +63 -0
- package/dist/features/collections/resolve.js +76 -0
- package/dist/features/localization/config +1 -0
- package/dist/features/localization/config.d.ts +18 -0
- package/dist/features/localization/config.js +25 -0
- package/dist/features/localization/links +1 -0
- package/dist/features/localization/links.d.ts +1 -0
- package/dist/features/localization/links.js +69 -0
- package/dist/features/localization/path +1 -0
- package/dist/features/localization/path.d.ts +32 -0
- package/dist/features/localization/path.js +80 -0
- package/dist/features/localization/results +1 -0
- package/dist/features/localization/results.d.ts +42 -0
- package/dist/features/localization/results.js +149 -0
- package/dist/features/localization/translated-slugs +1 -0
- package/dist/features/localization/translated-slugs.d.ts +11 -0
- package/dist/features/localization/translated-slugs.js +80 -0
- package/dist/features/navigation/build +1 -0
- package/dist/features/navigation/build.d.ts +28 -0
- package/dist/features/navigation/build.js +104 -0
- package/dist/features/navigation/canonical +1 -0
- package/dist/features/navigation/canonical.d.ts +33 -0
- package/dist/features/navigation/canonical.js +149 -0
- package/dist/features/navigation/query +1 -0
- package/dist/features/navigation/query.d.ts +19 -0
- package/dist/features/navigation/query.js +51 -0
- package/dist/features/navigation/resolve +1 -0
- package/dist/features/navigation/resolve.d.ts +20 -0
- package/dist/features/navigation/resolve.js +79 -0
- package/dist/features/navigation/tree +1 -0
- package/dist/features/navigation/tree.d.ts +6 -0
- package/dist/features/navigation/tree.js +32 -0
- package/dist/features/search/navigation +1 -0
- package/dist/features/search/navigation.d.ts +6 -0
- package/dist/features/search/navigation.js +21 -0
- package/dist/features/search/sections +1 -0
- package/dist/features/search/sections.d.ts +21 -0
- package/dist/features/search/sections.js +98 -0
- package/dist/features/sitemap/query +1 -0
- package/dist/features/sitemap/query.d.ts +68 -0
- package/dist/features/sitemap/query.js +171 -0
- package/dist/integrations/nitro/context +1 -0
- package/dist/integrations/nitro/context.d.ts +63 -0
- package/dist/integrations/nitro/context.js +28 -0
- package/dist/integrations/nitro/ingest +1 -0
- package/dist/integrations/nitro/ingest.d.ts +18 -0
- package/dist/integrations/nitro/ingest.js +120 -0
- package/dist/integrations/nitro/preview +1 -0
- package/dist/integrations/nitro/preview.d.ts +5 -0
- package/dist/integrations/nitro/preview.js +21 -0
- package/dist/integrations/nitro/runtime-config +1 -0
- package/dist/integrations/nitro/runtime-config.d.ts +1 -0
- package/dist/integrations/nitro/runtime-config.js +4 -0
- package/dist/integrations/nitro/storage +1 -0
- package/dist/integrations/nitro/storage.d.ts +9 -0
- package/dist/integrations/nitro/storage.js +113 -0
- package/dist/integrations/vue/content-components +1 -0
- package/dist/integrations/vue/content-components.d.ts +24 -0
- package/dist/integrations/vue/content-components.js +67 -0
- package/dist/integrations/vue/html-tags +1 -0
- package/dist/integrations/vue/html-tags.d.ts +2 -0
- package/dist/integrations/vue/html-tags.js +119 -0
- package/dist/integrations/vue/markdown-refs +1 -0
- package/dist/integrations/vue/markdown-refs.d.ts +1 -0
- package/dist/integrations/vue/markdown-refs.js +1 -0
- package/dist/module.d.mts +2044 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +1381 -0
- package/dist/parsers/csv +1 -0
- package/dist/parsers/csv.d.ts +2 -0
- package/dist/parsers/csv.js +38 -0
- package/dist/parsers/from-csv +1 -0
- package/dist/parsers/from-csv.d.ts +20 -0
- package/dist/parsers/from-csv.js +85 -0
- package/dist/parsers/index +1 -0
- package/dist/parsers/index.d.ts +10 -0
- package/dist/parsers/index.js +50 -0
- package/dist/parsers/json +1 -0
- package/dist/parsers/json.d.ts +2 -0
- package/dist/parsers/json.js +29 -0
- package/dist/parsers/markdown +1 -0
- package/dist/parsers/markdown-plugins +1 -0
- package/dist/parsers/markdown-plugins.d.ts +3 -0
- package/dist/parsers/markdown-plugins.js +58 -0
- package/dist/parsers/markdown.d.ts +2 -0
- package/dist/parsers/markdown.js +64 -0
- package/dist/parsers/path-meta +1 -0
- package/dist/parsers/path-meta.d.ts +4 -0
- package/dist/parsers/path-meta.js +37 -0
- package/dist/parsers/utils +1 -0
- package/dist/parsers/utils.d.ts +2 -0
- package/dist/parsers/utils.js +3 -0
- package/dist/parsers/yaml +1 -0
- package/dist/parsers/yaml.d.ts +2 -0
- package/dist/parsers/yaml.js +19 -0
- package/dist/public/client +1 -0
- package/dist/public/client.d.ts +19 -0
- package/dist/public/client.js +26 -0
- package/dist/public/provider +1 -0
- package/dist/public/provider-errors +1 -0
- package/dist/public/provider-errors.d.ts +4 -0
- package/dist/public/provider-errors.js +28 -0
- package/dist/public/provider.d.ts +74 -0
- package/dist/public/provider.js +6 -0
- package/dist/public/server +1 -0
- package/dist/public/server.d.ts +19 -0
- package/dist/public/server.js +28 -0
- package/dist/runtime/app/components/ContentRenderer.d.vue.ts +62 -0
- package/dist/runtime/app/components/ContentRenderer.vue +84 -0
- package/dist/runtime/app/components/ContentRenderer.vue.d.ts +62 -0
- package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +50 -0
- package/dist/runtime/app/components/ContentRendererInline.vue +97 -0
- package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +50 -0
- package/dist/runtime/app/components/Prose/ProseCode.d.vue.ts +61 -0
- package/dist/runtime/app/components/Prose/ProseCode.vue +32 -0
- package/dist/runtime/app/components/Prose/ProseCode.vue.d.ts +61 -0
- package/dist/runtime/app/components/Prose/ProseCodeInline.d.vue.ts +13 -0
- package/dist/runtime/app/components/Prose/ProseCodeInline.vue +3 -0
- package/dist/runtime/app/components/Prose/ProseCodeInline.vue.d.ts +13 -0
- package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +59 -0
- package/dist/runtime/app/components/Prose/ProseImg.vue +59 -0
- package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +59 -0
- package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +79 -0
- package/dist/runtime/app/components/Prose/ProsePre.vue +42 -0
- package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +79 -0
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +68 -0
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +99 -0
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +68 -0
- package/dist/runtime/app/components/internal/MarkdownRenderer +1 -0
- package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +90 -0
- package/dist/runtime/app/components/internal/MarkdownRenderer.js +191 -0
- package/dist/runtime/app/composables/async-data +1 -0
- package/dist/runtime/app/composables/async-data.d.ts +2 -0
- package/dist/runtime/app/composables/async-data.js +4 -0
- package/dist/runtime/app/composables/content-i18n +1 -0
- package/dist/runtime/app/composables/content-i18n.d.ts +5 -0
- package/dist/runtime/app/composables/content-i18n.js +1 -0
- package/dist/runtime/app/composables/head +1 -0
- package/dist/runtime/app/composables/head.d.ts +11 -0
- package/dist/runtime/app/composables/head.js +98 -0
- package/dist/runtime/app/composables/locale +1 -0
- package/dist/runtime/app/composables/locale-context +1 -0
- package/dist/runtime/app/composables/locale-context.d.ts +5 -0
- package/dist/runtime/app/composables/locale-context.js +8 -0
- package/dist/runtime/app/composables/locale.d.ts +8 -0
- package/dist/runtime/app/composables/locale.js +15 -0
- package/dist/runtime/app/composables/navigation +1 -0
- package/dist/runtime/app/composables/navigation.d.ts +3 -0
- package/dist/runtime/app/composables/navigation.js +7 -0
- package/dist/runtime/app/composables/preview +1 -0
- package/dist/runtime/app/composables/preview.d.ts +5 -0
- package/dist/runtime/app/composables/preview.js +52 -0
- package/dist/runtime/app/composables/query-api +1 -0
- package/dist/runtime/app/composables/query-api.d.ts +27 -0
- package/dist/runtime/app/composables/query-api.js +46 -0
- package/dist/runtime/app/composables/route +1 -0
- package/dist/runtime/app/composables/route.d.ts +11 -0
- package/dist/runtime/app/composables/route.js +150 -0
- package/dist/runtime/app/composables/runtime +1 -0
- package/dist/runtime/app/composables/runtime.d.ts +2 -0
- package/dist/runtime/app/composables/runtime.js +7 -0
- package/dist/runtime/app/composables/search +1 -0
- package/dist/runtime/app/composables/search.d.ts +58 -0
- package/dist/runtime/app/composables/search.js +321 -0
- package/dist/runtime/app/composables/site-data +1 -0
- package/dist/runtime/app/composables/site-data.d.ts +12 -0
- package/dist/runtime/app/composables/site-data.js +12 -0
- package/dist/runtime/app/composables/toc +1 -0
- package/dist/runtime/app/composables/toc.d.ts +10 -0
- package/dist/runtime/app/composables/toc.js +31 -0
- package/dist/runtime/app/composables/use-content +1 -0
- package/dist/runtime/app/composables/use-content.d.ts +188 -0
- package/dist/runtime/app/composables/use-content.js +307 -0
- package/dist/runtime/app/composables/useUnwrap +1 -0
- package/dist/runtime/app/composables/useUnwrap.d.ts +8 -0
- package/dist/runtime/app/composables/useUnwrap.js +35 -0
- package/dist/runtime/app/composables/utils +1 -0
- package/dist/runtime/app/composables/utils.d.ts +22 -0
- package/dist/runtime/app/composables/utils.js +76 -0
- package/dist/runtime/app/composables/web-socket +1 -0
- package/dist/runtime/app/composables/web-socket.d.ts +3 -0
- package/dist/runtime/app/composables/web-socket.js +65 -0
- package/dist/runtime/app/pages/content.d.vue.ts +3 -0
- package/dist/runtime/app/pages/content.vue +14 -0
- package/dist/runtime/app/pages/content.vue.d.ts +3 -0
- package/dist/runtime/app/plugins/markdown-components +1 -0
- package/dist/runtime/app/plugins/markdown-components.d.ts +2 -0
- package/dist/runtime/app/plugins/markdown-components.js +19 -0
- package/dist/runtime/app/plugins/ws +1 -0
- package/dist/runtime/app/plugins/ws.d.ts +2 -0
- package/dist/runtime/app/plugins/ws.js +7 -0
- package/dist/runtime/app.d.vue.ts +3 -0
- package/dist/runtime/app.vue +3 -0
- package/dist/runtime/app.vue.d.ts +3 -0
- package/dist/runtime/markdown/plugins +1 -0
- package/dist/runtime/markdown/plugins.d.ts +3 -0
- package/dist/runtime/markdown/plugins.js +39 -0
- package/dist/runtime/query/public-limits +1 -0
- package/dist/runtime/query/public-limits.d.ts +2 -0
- package/dist/runtime/query/public-limits.js +2 -0
- package/dist/runtime/query/resolve +1 -0
- package/dist/runtime/query/resolve.d.ts +5 -0
- package/dist/runtime/query/resolve.js +9 -0
- package/dist/runtime/query/routes +1 -0
- package/dist/runtime/query/routes.d.ts +33 -0
- package/dist/runtime/query/routes.js +21 -0
- package/dist/runtime/query/unified +1 -0
- package/dist/runtime/query/unified.d.ts +94 -0
- package/dist/runtime/query/unified.js +473 -0
- package/dist/runtime/server/api/cache +1 -0
- package/dist/runtime/server/api/cache.d.ts +8 -0
- package/dist/runtime/server/api/cache.js +26 -0
- package/dist/runtime/server/api/locales +1 -0
- package/dist/runtime/server/api/locales.d.ts +6 -0
- package/dist/runtime/server/api/locales.js +28 -0
- package/dist/runtime/server/api/navigation +1 -0
- package/dist/runtime/server/api/navigation.d.ts +2 -0
- package/dist/runtime/server/api/navigation.js +21 -0
- package/dist/runtime/server/api/query +1 -0
- package/dist/runtime/server/api/query.d.ts +2 -0
- package/dist/runtime/server/api/query.js +6 -0
- package/dist/runtime/server/api/revalidate +1 -0
- package/dist/runtime/server/api/revalidate.d.ts +6 -0
- package/dist/runtime/server/api/revalidate.js +156 -0
- package/dist/runtime/server/api/search +1 -0
- package/dist/runtime/server/api/search-index +1 -0
- package/dist/runtime/server/api/search-index.d.ts +2 -0
- package/dist/runtime/server/api/search-index.js +20 -0
- package/dist/runtime/server/api/search.d.ts +2 -0
- package/dist/runtime/server/api/search.js +40 -0
- package/dist/runtime/server/api/site-data +1 -0
- package/dist/runtime/server/api/site-data.d.ts +2 -0
- package/dist/runtime/server/api/site-data.js +22 -0
- package/dist/runtime/server/api/sitemap +1 -0
- package/dist/runtime/server/api/sitemap.d.ts +2 -0
- package/dist/runtime/server/api/sitemap.js +11 -0
- package/dist/runtime/server/cache-adapter +1 -0
- package/dist/runtime/server/cache-adapter.d.ts +2 -0
- package/dist/runtime/server/cache-adapter.js +11 -0
- package/dist/runtime/server/cache-adapters +1 -0
- package/dist/runtime/server/cache-adapters.d.ts +9 -0
- package/dist/runtime/server/cache-adapters.js +50 -0
- package/dist/runtime/server/cache-hints +1 -0
- package/dist/runtime/server/cache-hints.d.ts +5 -0
- package/dist/runtime/server/cache-hints.js +17 -0
- package/dist/runtime/server/collection-helpers +1 -0
- package/dist/runtime/server/collection-helpers.d.ts +13 -0
- package/dist/runtime/server/collection-helpers.js +99 -0
- package/dist/runtime/server/index +1 -0
- package/dist/runtime/server/index.d.ts +9 -0
- package/dist/runtime/server/index.js +15 -0
- package/dist/runtime/server/manifest +1 -0
- package/dist/runtime/server/manifest.d.ts +1 -0
- package/dist/runtime/server/manifest.js +1 -0
- package/dist/runtime/server/navigation +1 -0
- package/dist/runtime/server/navigation-query +1 -0
- package/dist/runtime/server/navigation-query.d.ts +4 -0
- package/dist/runtime/server/navigation-query.js +80 -0
- package/dist/runtime/server/navigation.d.ts +2 -0
- package/dist/runtime/server/navigation.js +9 -0
- package/dist/runtime/server/pagefind +1 -0
- package/dist/runtime/server/pagefind.d.ts +2 -0
- package/dist/runtime/server/pagefind.js +30 -0
- package/dist/runtime/server/plugins/cache +1 -0
- package/dist/runtime/server/plugins/cache.d.ts +2 -0
- package/dist/runtime/server/plugins/cache.js +17 -0
- package/dist/runtime/server/plugins/sitemap +1 -0
- package/dist/runtime/server/plugins/sitemap.d.ts +2 -0
- package/dist/runtime/server/plugins/sitemap.js +25 -0
- package/dist/runtime/server/preview +1 -0
- package/dist/runtime/server/preview.d.ts +1 -0
- package/dist/runtime/server/preview.js +1 -0
- package/dist/runtime/server/provider-query +1 -0
- package/dist/runtime/server/provider-query.d.ts +27 -0
- package/dist/runtime/server/provider-query.js +131 -0
- package/dist/runtime/server/provider-result +1 -0
- package/dist/runtime/server/provider-result.d.ts +10 -0
- package/dist/runtime/server/provider-result.js +30 -0
- package/dist/runtime/server/providers/filesystem +1 -0
- package/dist/runtime/server/providers/filesystem.d.ts +2 -0
- package/dist/runtime/server/providers/filesystem.js +47 -0
- package/dist/runtime/server/providers/index +1 -0
- package/dist/runtime/server/providers/index.d.ts +3 -0
- package/dist/runtime/server/providers/index.js +190 -0
- package/dist/runtime/server/query-api +1 -0
- package/dist/runtime/server/query-api.d.ts +28 -0
- package/dist/runtime/server/query-api.js +54 -0
- package/dist/runtime/server/query-executor +1 -0
- package/dist/runtime/server/query-executor.d.ts +4 -0
- package/dist/runtime/server/query-executor.js +121 -0
- package/dist/runtime/server/runtime-config +1 -0
- package/dist/runtime/server/runtime-config.d.ts +1 -0
- package/dist/runtime/server/runtime-config.js +1 -0
- package/dist/runtime/server/search +1 -0
- package/dist/runtime/server/search.d.ts +18 -0
- package/dist/runtime/server/search.js +134 -0
- package/dist/runtime/server/sitemap +1 -0
- package/dist/runtime/server/sitemap-provider +1 -0
- package/dist/runtime/server/sitemap-provider.d.ts +10 -0
- package/dist/runtime/server/sitemap-provider.js +11 -0
- package/dist/runtime/server/sitemap.d.ts +6 -0
- package/dist/runtime/server/sitemap.js +45 -0
- package/dist/runtime/server/storage +1 -0
- package/dist/runtime/server/storage-access +1 -0
- package/dist/runtime/server/storage-access.d.ts +1 -0
- package/dist/runtime/server/storage-access.js +9 -0
- package/dist/runtime/server/storage.d.ts +2 -0
- package/dist/runtime/server/storage.js +2 -0
- package/dist/runtime/server/validation +1 -0
- package/dist/runtime/server/validation.d.ts +1 -0
- package/dist/runtime/server/validation.js +6 -0
- package/dist/runtime/shared/search +1 -0
- package/dist/runtime/shared/search.d.ts +2 -0
- package/dist/runtime/shared/search.js +89 -0
- package/dist/runtime/transformers/component-resolver +1 -0
- package/dist/runtime/transformers/component-resolver.d.ts +10 -0
- package/dist/runtime/transformers/component-resolver.js +30 -0
- package/dist/runtime/transformers/csv/from-csv +1 -0
- package/dist/runtime/transformers/csv/from-csv.d.ts +1 -0
- package/dist/runtime/transformers/csv/from-csv.js +1 -0
- package/dist/runtime/transformers/csv/index +1 -0
- package/dist/runtime/transformers/csv/index.d.ts +1 -0
- package/dist/runtime/transformers/csv/index.js +1 -0
- package/dist/runtime/transformers/define +1 -0
- package/dist/runtime/transformers/define.d.ts +1 -0
- package/dist/runtime/transformers/define.js +1 -0
- package/dist/runtime/transformers/index +1 -0
- package/dist/runtime/transformers/index.d.ts +1 -0
- package/dist/runtime/transformers/index.js +1 -0
- package/dist/runtime/transformers/json +1 -0
- package/dist/runtime/transformers/json.d.ts +1 -0
- package/dist/runtime/transformers/json.js +1 -0
- package/dist/runtime/transformers/markdown +1 -0
- package/dist/runtime/transformers/markdown.d.ts +1 -0
- package/dist/runtime/transformers/markdown.js +1 -0
- package/dist/runtime/transformers/path-meta +1 -0
- package/dist/runtime/transformers/path-meta.d.ts +2 -0
- package/dist/runtime/transformers/path-meta.js +2 -0
- package/dist/runtime/transformers/utils +1 -0
- package/dist/runtime/transformers/utils.d.ts +1 -0
- package/dist/runtime/transformers/utils.js +1 -0
- package/dist/runtime/transformers/yaml +1 -0
- package/dist/runtime/transformers/yaml.d.ts +1 -0
- package/dist/runtime/transformers/yaml.js +1 -0
- package/dist/runtime/utils/content-components +1 -0
- package/dist/runtime/utils/content-components.d.ts +9 -0
- package/dist/runtime/utils/content-components.js +16 -0
- package/dist/runtime/utils/query +1 -0
- package/dist/runtime/utils/query.d.ts +5 -0
- package/dist/runtime/utils/query.js +18 -0
- package/dist/runtime/virtual/transformers.d.ts +4 -0
- package/dist/runtime/virtual.d.ts +7 -0
- package/dist/storage/cache +1 -0
- package/dist/storage/cache.d.ts +32 -0
- package/dist/storage/cache.js +42 -0
- package/dist/storage/content +1 -0
- package/dist/storage/content.d.ts +41 -0
- package/dist/storage/content.js +86 -0
- package/dist/storage/contents +1 -0
- package/dist/storage/contents.d.ts +5 -0
- package/dist/storage/contents.js +116 -0
- package/dist/storage/driver +1 -0
- package/dist/storage/driver.d.ts +28 -0
- package/dist/storage/driver.js +22 -0
- package/dist/storage/graph +1 -0
- package/dist/storage/graph.d.ts +3 -0
- package/dist/storage/graph.js +14 -0
- package/dist/storage/manifest +1 -0
- package/dist/storage/manifest.d.ts +18 -0
- package/dist/storage/manifest.js +68 -0
- package/dist/storage/references +1 -0
- package/dist/storage/references.d.ts +13 -0
- package/dist/storage/references.js +78 -0
- package/dist/storage/validation +1 -0
- package/dist/storage/validation.d.ts +46 -0
- package/dist/storage/validation.js +341 -0
- package/dist/testing/provider-contract +1 -0
- package/dist/testing/provider-contract.d.ts +31 -0
- package/dist/testing/provider-contract.js +237 -0
- package/dist/testing/provider-fixture +1 -0
- package/dist/testing/provider-fixture.d.ts +65 -0
- package/dist/testing/provider-fixture.js +606 -0
- package/dist/types/api +1 -0
- package/dist/types/api.d.ts +47 -0
- package/dist/types/api.js +1 -0
- package/dist/types/config +1 -0
- package/dist/types/config.d.ts +281 -0
- package/dist/types/config.js +28 -0
- package/dist/types/content +1 -0
- package/dist/types/content.d.ts +311 -0
- package/dist/types/content.js +1 -0
- package/dist/types/fields +1 -0
- package/dist/types/fields.d.ts +81 -0
- package/dist/types/fields.js +146 -0
- package/dist/types/index +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +6 -0
- package/dist/types/module +1 -0
- package/dist/types/module.d.ts +428 -0
- package/dist/types/module.js +0 -0
- package/dist/types/picomatch.d.ts +8 -0
- package/dist/types/query +1 -0
- package/dist/types/query.d.ts +862 -0
- package/dist/types/query.js +1 -0
- package/dist/types/reference +1 -0
- package/dist/types/reference.d.ts +1 -0
- package/dist/types/reference.js +1 -0
- package/dist/types/runtime +1 -0
- package/dist/types/runtime.d.ts +45 -0
- package/dist/types/runtime.js +1 -0
- package/dist/types/search +1 -0
- package/dist/types/search.d.ts +64 -0
- package/dist/types/search.js +0 -0
- package/dist/types/virtual.d.ts +19 -0
- package/dist/types.d.mts +11 -0
- package/dist/web-types.json +466 -0
- package/package.json +135 -0
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,1381 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join as join$1, basename, resolve as resolve$1, relative as relative$1, dirname } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { addTypeTemplate, addImports, addServerImports, addComponentsDir, addPlugin, addServerHandler, defineNuxtModule, createResolver, useLogger, addTemplate } from '@nuxt/kit';
|
|
5
|
+
import { defu } from 'defu';
|
|
6
|
+
import { hash } from 'ohash';
|
|
7
|
+
import { resolve, join, relative, isAbsolute } from 'pathe';
|
|
8
|
+
import { withTrailingSlash } from 'ufo';
|
|
9
|
+
import 'unstorage/drivers/fs';
|
|
10
|
+
import 'unstorage/drivers/http';
|
|
11
|
+
import 'unstorage/drivers/github';
|
|
12
|
+
import { WebSocketServer } from 'ws';
|
|
13
|
+
import { consola } from 'consola';
|
|
14
|
+
import fs, { existsSync } from 'fs';
|
|
15
|
+
import jiti from 'jiti';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
import { genSafeVariableName, genImport } from 'knitwork';
|
|
18
|
+
import { listen } from 'listhen';
|
|
19
|
+
import { makeIgnored } from '../dist/core/content/ignore';
|
|
20
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
21
|
+
import { resolveCollectionI18nConfig } from '../dist/features/localization/config';
|
|
22
|
+
import { globby } from 'globby';
|
|
23
|
+
import { transformContent } from '../dist/parsers/index';
|
|
24
|
+
import { expandDataLocaleVariants } from '../dist/core/content/locale';
|
|
25
|
+
import { buildContentGraph } from '../dist/core/content/graph';
|
|
26
|
+
import { normalizeCollectionSources, normalizeCollectionExcludes } from '../dist/core/content/sources';
|
|
27
|
+
import { resolveCollectionI18n, prefixPathWithLocale } from '../dist/features/localization/path';
|
|
28
|
+
import { resolveCollection } from '../dist/core/content/collection';
|
|
29
|
+
export { defineCollection, defineContentConfig, reference } from '../dist/types/config';
|
|
30
|
+
|
|
31
|
+
const name = "@lupinum/ginko-content";
|
|
32
|
+
const version = "0.1.0";
|
|
33
|
+
|
|
34
|
+
const logger = consola.withTag("@lupinum/ginko-content");
|
|
35
|
+
const CACHE_VERSION = 3;
|
|
36
|
+
const MOUNT_PREFIX = "content:source:";
|
|
37
|
+
function useContentMounts(nuxt, storages) {
|
|
38
|
+
const key = (path, prefix = "") => `${MOUNT_PREFIX}${path.replace(/[/:]/g, "_")}${prefix.replace(/\//g, ":")}`;
|
|
39
|
+
const baseDir = nuxt.options.future?.compatibilityVersion === 4 ? nuxt.options.rootDir : nuxt.options.srcDir;
|
|
40
|
+
storages = Object.entries(storages).reduce((mounts, [name, storage]) => {
|
|
41
|
+
mounts[key(storage.name || name, storage.prefix)] = storage;
|
|
42
|
+
return mounts;
|
|
43
|
+
}, {});
|
|
44
|
+
const defaultStorage = key("content");
|
|
45
|
+
if (!storages[defaultStorage]) {
|
|
46
|
+
storages[defaultStorage] = {
|
|
47
|
+
name: defaultStorage,
|
|
48
|
+
driver: "fs",
|
|
49
|
+
base: resolve(baseDir, "content")
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return storages;
|
|
53
|
+
}
|
|
54
|
+
function createWebSocket() {
|
|
55
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
56
|
+
const serve = (req, socket = req.socket, head = "") => wss.handleUpgrade(req, socket, head, (client) => wss.emit("connection", client, req));
|
|
57
|
+
const broadcast = (data) => {
|
|
58
|
+
data = JSON.stringify(data);
|
|
59
|
+
for (const client of wss.clients) {
|
|
60
|
+
try {
|
|
61
|
+
client.send(data);
|
|
62
|
+
} catch {
|
|
63
|
+
logger.debug("Skipping websocket client that is not ready to receive content refresh events.");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
serve,
|
|
69
|
+
broadcast,
|
|
70
|
+
close: () => {
|
|
71
|
+
wss.clients.forEach((client) => client.close());
|
|
72
|
+
return new Promise((resolve2) => wss.close(resolve2));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function processMarkdownOptions(options) {
|
|
77
|
+
const anchorLinks = typeof options.anchorLinks === "boolean" ? { depth: options.anchorLinks ? 6 : 0, exclude: [] } : { depth: 4, exclude: [1], ...options.anchorLinks };
|
|
78
|
+
const plugins = options.plugins?.length ? options.plugins : [
|
|
79
|
+
["toc", { depth: 2, searchDepth: 2 }],
|
|
80
|
+
"summary"
|
|
81
|
+
];
|
|
82
|
+
return {
|
|
83
|
+
...options,
|
|
84
|
+
anchorLinks,
|
|
85
|
+
plugins: resolveMarkdownPlugins(plugins)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function resolveMarkdownPlugins(plugins) {
|
|
89
|
+
return (plugins || []).map((plugin) => {
|
|
90
|
+
const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];
|
|
91
|
+
return {
|
|
92
|
+
name,
|
|
93
|
+
options
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const CONFIG_FILES = [
|
|
99
|
+
"content.config.ts",
|
|
100
|
+
"content.config.mts",
|
|
101
|
+
"content.config.js",
|
|
102
|
+
"content.config.mjs",
|
|
103
|
+
"content.config.cjs"
|
|
104
|
+
];
|
|
105
|
+
function resolveContentConfigPath(nuxt) {
|
|
106
|
+
return CONFIG_FILES.map((name) => join(nuxt.options.rootDir, name)).find((path) => existsSync(path));
|
|
107
|
+
}
|
|
108
|
+
async function loadContentConfig(nuxt) {
|
|
109
|
+
const configPath = resolveContentConfigPath(nuxt);
|
|
110
|
+
if (!configPath) {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
const importer = jiti(nuxt.options.rootDir, { interopDefault: true });
|
|
114
|
+
const loaded = await importer.import(configPath);
|
|
115
|
+
return loaded?.default || loaded || {};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const require$1 = createRequire(import.meta.url);
|
|
119
|
+
const jitiImportSpecifier = pathToFileURL(require$1.resolve("jiti")).href;
|
|
120
|
+
const createVirtualContentTemplates = (contentContext, nuxt, contentConfigPath, addTemplateImpl) => {
|
|
121
|
+
const transformersTemplate = addTemplateImpl({
|
|
122
|
+
filename: "content/virtual-transformers.mjs",
|
|
123
|
+
write: true,
|
|
124
|
+
getContents: () => {
|
|
125
|
+
const transformers = contentContext.transformers.map((transformer) => {
|
|
126
|
+
const name = genSafeVariableName(relative(nuxt.options.rootDir, transformer)).replace(/_(45|46|47)/g, "_") + "_" + hash(transformer);
|
|
127
|
+
return { name, import: genImport(transformer, name) };
|
|
128
|
+
});
|
|
129
|
+
return [
|
|
130
|
+
...transformers.map((transformer) => transformer.import),
|
|
131
|
+
`export const transformers = [${transformers.map((transformer) => transformer.name).join(", ")}]`,
|
|
132
|
+
'export const getParser = (ext) => transformers.find(p => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.parse)',
|
|
133
|
+
'export const getTransformers = (ext) => transformers.filter(p => ext.match(new RegExp(p.extensions.join("|"), "i")) && p.transform)',
|
|
134
|
+
"export default () => {}"
|
|
135
|
+
].join("\n");
|
|
136
|
+
}
|
|
137
|
+
}).dst;
|
|
138
|
+
const virtualConfigTemplate = addTemplateImpl({
|
|
139
|
+
filename: "content/virtual-config.mjs",
|
|
140
|
+
write: true,
|
|
141
|
+
getContents: () => contentConfigPath ? [
|
|
142
|
+
`import jiti from ${JSON.stringify(jitiImportSpecifier)}`,
|
|
143
|
+
`const importer = jiti(import.meta.url, { interopDefault: true })`,
|
|
144
|
+
`const config = await importer.import(${JSON.stringify(contentConfigPath)})`,
|
|
145
|
+
"export default config?.default || config || {}"
|
|
146
|
+
].join("\n") : "export default {}"
|
|
147
|
+
}).dst;
|
|
148
|
+
const virtualProvidersTemplate = addTemplateImpl({
|
|
149
|
+
filename: "content/virtual-providers.mjs",
|
|
150
|
+
write: true,
|
|
151
|
+
getContents: () => {
|
|
152
|
+
const providers = Object.entries(contentContext.providers || {});
|
|
153
|
+
const cases = providers.map(([name, specifier]) => {
|
|
154
|
+
return `case ${JSON.stringify(name)}: return import(${JSON.stringify(specifier)}).then(resolveProviderModule)`;
|
|
155
|
+
});
|
|
156
|
+
return [
|
|
157
|
+
"const resolveProviderModule = (mod) => mod.default || mod.contentProvider || mod.provider",
|
|
158
|
+
"export const externalContentProviderNames = " + JSON.stringify(providers.map(([name]) => name)),
|
|
159
|
+
"export const loadExternalContentProvider = (name) => {",
|
|
160
|
+
" switch (name) {",
|
|
161
|
+
...cases.map((item) => ` ${item}`),
|
|
162
|
+
" default: return undefined",
|
|
163
|
+
" }",
|
|
164
|
+
"}",
|
|
165
|
+
"export default {}"
|
|
166
|
+
].join("\n");
|
|
167
|
+
}
|
|
168
|
+
}).dst;
|
|
169
|
+
const virtualCacheAdapterTemplate = addTemplateImpl({
|
|
170
|
+
filename: "content/virtual-cache-adapter.mjs",
|
|
171
|
+
write: true,
|
|
172
|
+
getContents: () => {
|
|
173
|
+
const cache = contentContext.cache;
|
|
174
|
+
if (!cache || cache === false) {
|
|
175
|
+
return [
|
|
176
|
+
"export const loadContentCacheAdapter = () => undefined",
|
|
177
|
+
"export default {}"
|
|
178
|
+
].join("\n");
|
|
179
|
+
}
|
|
180
|
+
return [
|
|
181
|
+
"const resolveCacheAdapterModule = (mod) => mod.default || mod.contentCacheAdapter || mod.cacheAdapter",
|
|
182
|
+
`export const loadContentCacheAdapter = () => import(${JSON.stringify(cache)}).then(resolveCacheAdapterModule)`,
|
|
183
|
+
"export default {}"
|
|
184
|
+
].join("\n");
|
|
185
|
+
}
|
|
186
|
+
}).dst;
|
|
187
|
+
return {
|
|
188
|
+
transformersTemplate,
|
|
189
|
+
virtualConfigTemplate,
|
|
190
|
+
virtualProvidersTemplate,
|
|
191
|
+
virtualCacheAdapterTemplate
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const registerVirtualContentAliases = (nuxt, transformersTemplate, virtualConfigTemplate, virtualProvidersTemplate, virtualCacheAdapterTemplate, resolveRuntimeModule) => {
|
|
195
|
+
nuxt.options.alias = nuxt.options.alias || {};
|
|
196
|
+
nuxt.options.alias["#content/virtual/transformers"] = transformersTemplate;
|
|
197
|
+
nuxt.options.alias["#content/virtual/config"] = virtualConfigTemplate;
|
|
198
|
+
nuxt.options.alias["#content/virtual/providers"] = virtualProvidersTemplate;
|
|
199
|
+
nuxt.options.alias["#content/virtual/cache-adapter"] = virtualCacheAdapterTemplate;
|
|
200
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
201
|
+
nitroConfig.alias = nitroConfig.alias || {};
|
|
202
|
+
nitroConfig.alias["#content/server"] = resolveRuntimeModule("./server/index.js");
|
|
203
|
+
nitroConfig.alias["#content/virtual/transformers"] = transformersTemplate;
|
|
204
|
+
nitroConfig.alias["#content/virtual/config"] = virtualConfigTemplate;
|
|
205
|
+
nitroConfig.alias["#content/virtual/providers"] = virtualProvidersTemplate;
|
|
206
|
+
nitroConfig.alias["#content/virtual/cache-adapter"] = virtualCacheAdapterTemplate;
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const registerContentDevRuntime = (nuxt, options, contentContext) => {
|
|
211
|
+
const isIgnored = makeIgnored(contentContext.ignores);
|
|
212
|
+
nuxt.hook("nitro:init", async (nitro) => {
|
|
213
|
+
if (!options.watch || !options.watch.ws) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const ws = createWebSocket();
|
|
217
|
+
const { server, url } = await listen(() => "Ginko", options.watch.ws);
|
|
218
|
+
const unwatch = await nitro.storage.watch(async (event, key) => {
|
|
219
|
+
if (!key.startsWith(MOUNT_PREFIX) || isIgnored(key)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
key = key.substring(MOUNT_PREFIX.length);
|
|
223
|
+
await nitro.storage.removeItem("cache:content:_manifest.json");
|
|
224
|
+
await nitro.storage.removeItem("cache:content:_nav.json");
|
|
225
|
+
await nitro.storage.removeItem("cache:content:_meta.json");
|
|
226
|
+
ws.broadcast({ event, key });
|
|
227
|
+
});
|
|
228
|
+
nitro.hooks.hook("close", async () => {
|
|
229
|
+
await unwatch();
|
|
230
|
+
await ws.close();
|
|
231
|
+
await server.close();
|
|
232
|
+
});
|
|
233
|
+
server.on("upgrade", ws.serve);
|
|
234
|
+
nitro.options.runtimeConfig.public.content.wsUrl = url.replace("http", "ws");
|
|
235
|
+
await nitro.storage.removeItem("cache:content:_manifest.json");
|
|
236
|
+
await nitro.storage.removeItem("cache:content:_nav.json");
|
|
237
|
+
await nitro.storage.removeItem("cache:content:_meta.json");
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const registerRuntimeImports = (resolveRuntimeModule) => {
|
|
242
|
+
addImports([
|
|
243
|
+
// Unified query API (ADR-0016) — app wrappers bind the Nuxt content context explicitly.
|
|
244
|
+
{ name: "one", as: "one", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
245
|
+
{ name: "many", as: "many", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
246
|
+
{ name: "paginate", as: "paginate", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
247
|
+
{ name: "backlinks", as: "backlinks", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
248
|
+
{ name: "resolveOne", as: "resolveOne", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
249
|
+
{ name: "variants", as: "variants", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
250
|
+
{ name: "tree", as: "tree", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
251
|
+
{ name: "neighbors", as: "neighbors", from: resolveRuntimeModule("./app/composables/query-api.js") },
|
|
252
|
+
{ name: "getCollectionPath", as: "getCollectionPath", from: resolveRuntimeModule("./query/routes.js") },
|
|
253
|
+
// Vue composables — reactive wrappers over the same options shape.
|
|
254
|
+
{ name: "useContentPage", as: "useContentPage", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
255
|
+
{ name: "useContentOne", as: "useContentOne", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
256
|
+
{ name: "useContentMany", as: "useContentMany", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
257
|
+
{ name: "useContentPagination", as: "useContentPagination", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
258
|
+
{ name: "useContentBacklinks", as: "useContentBacklinks", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
259
|
+
{ name: "useContentResolveOne", as: "useContentResolveOne", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
260
|
+
{ name: "useContentVariants", as: "useContentVariants", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
261
|
+
{ name: "useContentTree", as: "useContentTree", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
262
|
+
{ name: "useContentNeighbors", as: "useContentNeighbors", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
263
|
+
{ name: "useContentLocaleSwitch", as: "useContentLocaleSwitch", from: resolveRuntimeModule("./app/composables/use-content.js") },
|
|
264
|
+
// Search & site data — kept (out of scope for ADR-0016).
|
|
265
|
+
{ name: "useContentSearchData", as: "useContentSearchData", from: resolveRuntimeModule("./app/composables/search.js") },
|
|
266
|
+
{ name: "useContentSearchResults", as: "useContentSearchResults", from: resolveRuntimeModule("./app/composables/search.js") },
|
|
267
|
+
{ name: "querySiteData", as: "querySiteData", from: resolveRuntimeModule("./app/composables/site-data.js") }
|
|
268
|
+
]);
|
|
269
|
+
addServerImports([
|
|
270
|
+
{ name: "one", as: "one", from: resolveRuntimeModule("./server/index.js") },
|
|
271
|
+
{ name: "many", as: "many", from: resolveRuntimeModule("./server/index.js") },
|
|
272
|
+
{ name: "paginate", as: "paginate", from: resolveRuntimeModule("./server/index.js") },
|
|
273
|
+
{ name: "backlinks", as: "backlinks", from: resolveRuntimeModule("./server/index.js") },
|
|
274
|
+
{ name: "resolveOne", as: "resolveOne", from: resolveRuntimeModule("./server/index.js") },
|
|
275
|
+
{ name: "variants", as: "variants", from: resolveRuntimeModule("./server/index.js") },
|
|
276
|
+
{ name: "tree", as: "tree", from: resolveRuntimeModule("./server/index.js") },
|
|
277
|
+
{ name: "neighbors", as: "neighbors", from: resolveRuntimeModule("./server/index.js") },
|
|
278
|
+
{ name: "getCollectionPath", as: "getCollectionPath", from: resolveRuntimeModule("./server/index.js") },
|
|
279
|
+
{ name: "queryCollectionsSitemapEntries", as: "queryCollectionsSitemapEntries", from: resolveRuntimeModule("./server/index.js") }
|
|
280
|
+
]);
|
|
281
|
+
};
|
|
282
|
+
const registerRuntimeComponents = (resolve) => {
|
|
283
|
+
addComponentsDir({
|
|
284
|
+
path: resolve("./runtime/app/components"),
|
|
285
|
+
pathPrefix: false,
|
|
286
|
+
prefix: "",
|
|
287
|
+
global: true,
|
|
288
|
+
ignore: ["Prose/**", "internal/**"]
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
const registerContentI18nTemplate = (addTemplateImpl, hasNuxtI18nModule) => {
|
|
292
|
+
addTemplateImpl({
|
|
293
|
+
filename: "content-i18n.mjs",
|
|
294
|
+
write: true,
|
|
295
|
+
getContents: () => hasNuxtI18nModule ? [
|
|
296
|
+
"export { useRouteBaseName, useSetI18nParams, useSwitchLocalePath } from '#i18n'"
|
|
297
|
+
].join("\n") : [
|
|
298
|
+
"const routeNameLocaleRE = /___([^_]+)$/",
|
|
299
|
+
"const resolveName = (value) => {",
|
|
300
|
+
" if (typeof value === 'string') {",
|
|
301
|
+
" return value",
|
|
302
|
+
" }",
|
|
303
|
+
" if (value && typeof value === 'object' && 'name' in value) {",
|
|
304
|
+
" return value.name",
|
|
305
|
+
" }",
|
|
306
|
+
" return undefined",
|
|
307
|
+
"}",
|
|
308
|
+
"export const useRouteBaseName = () => (value) => {",
|
|
309
|
+
" const name = resolveName(value)",
|
|
310
|
+
" return typeof name === 'string' ? name.replace(routeNameLocaleRE, '') : undefined",
|
|
311
|
+
"}",
|
|
312
|
+
"export const useSetI18nParams = () => () => {}",
|
|
313
|
+
"export const useSwitchLocalePath = () => () => ''"
|
|
314
|
+
].join("\n")
|
|
315
|
+
});
|
|
316
|
+
addTemplateImpl({
|
|
317
|
+
filename: "content-i18n.d.mts",
|
|
318
|
+
write: true,
|
|
319
|
+
getContents: () => [
|
|
320
|
+
"export function useRouteBaseName(): (route: { name?: unknown } | unknown) => string | undefined",
|
|
321
|
+
"export function useSetI18nParams(): (params: Record<string, unknown>) => void",
|
|
322
|
+
"export function useSwitchLocalePath(): (locale: string) => string"
|
|
323
|
+
].join("\n")
|
|
324
|
+
});
|
|
325
|
+
addTypeTemplate({
|
|
326
|
+
filename: "types/content-i18n.d.ts",
|
|
327
|
+
getContents: () => [
|
|
328
|
+
"declare module '#build/content-i18n.mjs' {",
|
|
329
|
+
" export function useRouteBaseName(): (route: { name?: unknown } | unknown) => string | undefined",
|
|
330
|
+
" export function useSetI18nParams(): (params: Record<string, unknown>) => void",
|
|
331
|
+
" export function useSwitchLocalePath(): (locale: string) => string",
|
|
332
|
+
"}"
|
|
333
|
+
].join("\n")
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
const registerUserContentComponents = async (nuxt, resolve) => {
|
|
337
|
+
const layers = [...nuxt.options._layers];
|
|
338
|
+
for (const layer of layers) {
|
|
339
|
+
const srcDir = layer.config.srcDir;
|
|
340
|
+
const globalComponents = resolve(srcDir, "components/content");
|
|
341
|
+
const dirStat = await fs.promises.stat(globalComponents).catch((error) => {
|
|
342
|
+
if (error.code === "ENOENT") {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
throw error;
|
|
346
|
+
});
|
|
347
|
+
if (dirStat && dirStat.isDirectory()) {
|
|
348
|
+
nuxt.hook("components:dirs", (dirs) => {
|
|
349
|
+
dirs.unshift({
|
|
350
|
+
path: globalComponents,
|
|
351
|
+
global: false,
|
|
352
|
+
pathPrefix: false,
|
|
353
|
+
prefix: ""
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const registerGeneratedTypes = (contentConfigPath, resolveRuntimeModuleRoot) => {
|
|
360
|
+
return addTypeTemplate({
|
|
361
|
+
filename: "types/content.d.ts",
|
|
362
|
+
getContents: () => [
|
|
363
|
+
contentConfigPath ? `import type contentConfig from ${JSON.stringify(contentConfigPath)}` : "type __ContentConfig = { collections?: {} }",
|
|
364
|
+
"import type { StrictParsedContent } from '@lupinum/ginko-content'",
|
|
365
|
+
"import type { CollectionSchema } from '@lupinum/ginko-content/config'",
|
|
366
|
+
contentConfigPath ? "type __ContentConfig = typeof contentConfig" : "",
|
|
367
|
+
"type __ContentCollections = NonNullable<__ContentConfig['collections']>",
|
|
368
|
+
"type __GeneratedContentCollectionMap = {",
|
|
369
|
+
" [K in keyof __ContentCollections & string]: StrictParsedContent & CollectionSchema<__ContentCollections[K]>",
|
|
370
|
+
"}",
|
|
371
|
+
"type __GeneratedI18nCollectionNames = {",
|
|
372
|
+
" [K in keyof __ContentCollections & string]: NonNullable<__ContentCollections[K]['i18n']> extends never ? never : K",
|
|
373
|
+
"}[keyof __ContentCollections & string]",
|
|
374
|
+
"declare module '@lupinum/ginko-content' {",
|
|
375
|
+
" interface ContentCollectionMap extends __GeneratedContentCollectionMap {}",
|
|
376
|
+
" interface ContentCollectionI18nMap extends Pick<__GeneratedContentCollectionMap, __GeneratedI18nCollectionNames> {}",
|
|
377
|
+
"}",
|
|
378
|
+
"declare module '#content/server' {",
|
|
379
|
+
` const one: typeof import('${resolveRuntimeModuleRoot("./server")}').one`,
|
|
380
|
+
` const many: typeof import('${resolveRuntimeModuleRoot("./server")}').many`,
|
|
381
|
+
` const paginate: typeof import('${resolveRuntimeModuleRoot("./server")}').paginate`,
|
|
382
|
+
` const backlinks: typeof import('${resolveRuntimeModuleRoot("./server")}').backlinks`,
|
|
383
|
+
` const resolveOne: typeof import('${resolveRuntimeModuleRoot("./server")}').resolveOne`,
|
|
384
|
+
` const variants: typeof import('${resolveRuntimeModuleRoot("./server")}').variants`,
|
|
385
|
+
` const tree: typeof import('${resolveRuntimeModuleRoot("./server")}').tree`,
|
|
386
|
+
` const neighbors: typeof import('${resolveRuntimeModuleRoot("./server")}').neighbors`,
|
|
387
|
+
` const queryCollectionsSitemapEntries: typeof import('${resolveRuntimeModuleRoot("./server")}').queryCollectionsSitemapEntries`,
|
|
388
|
+
` const contentCacheHeaders: typeof import('${resolveRuntimeModuleRoot("./server")}').contentCacheHeaders`,
|
|
389
|
+
` const noopContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').noopContentCache`,
|
|
390
|
+
` const vercelContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').vercelContentCache`,
|
|
391
|
+
` const clearContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').clearContentCacheHint`,
|
|
392
|
+
` const collectContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').collectContentCacheHint`,
|
|
393
|
+
` const getContentCacheHint: typeof import('${resolveRuntimeModuleRoot("./server")}').getContentCacheHint`,
|
|
394
|
+
` const withContentCache: typeof import('${resolveRuntimeModuleRoot("./server")}').withContentCache`,
|
|
395
|
+
` const createContentProviderError: typeof import('${resolveRuntimeModuleRoot("./server")}').createContentProviderError`,
|
|
396
|
+
` type ContentCacheAdapter = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheAdapter`,
|
|
397
|
+
` type ContentCacheHint = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheHint`,
|
|
398
|
+
` type ContentCacheHintInput = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheHintInput`,
|
|
399
|
+
` type ContentCacheInvalidateInput = import('${resolveRuntimeModuleRoot("./server")}').ContentCacheInvalidateInput`,
|
|
400
|
+
` type ContentProvider = import('${resolveRuntimeModuleRoot("./server")}').ContentProvider`,
|
|
401
|
+
` type ContentProviderCapabilities = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderCapabilities`,
|
|
402
|
+
` type ContentProviderResult<T> = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderResult<T>`,
|
|
403
|
+
` type MaybeContentProviderResult<T> = import('${resolveRuntimeModuleRoot("./server")}').MaybeContentProviderResult<T>`,
|
|
404
|
+
` type ContentProviderErrorCode = import('${resolveRuntimeModuleRoot("./server")}').ContentProviderErrorCode`,
|
|
405
|
+
` type VercelContentCacheOptions = import('${resolveRuntimeModuleRoot("./server")}').VercelContentCacheOptions`,
|
|
406
|
+
"}"
|
|
407
|
+
].filter(Boolean).join("\n")
|
|
408
|
+
});
|
|
409
|
+
};
|
|
410
|
+
const registerDevRuntimePlugin = (resolveRuntimeModule) => {
|
|
411
|
+
addPlugin(resolveRuntimeModule("./app/plugins/ws.js"));
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const registerContentServerHandlers = (nuxt, options, resolveRuntimeModule, buildIntegrity) => {
|
|
415
|
+
addServerHandler({
|
|
416
|
+
method: "get",
|
|
417
|
+
route: `${options.api.baseURL}/query/**:params`,
|
|
418
|
+
handler: resolveRuntimeModule("./server/api/query.js")
|
|
419
|
+
});
|
|
420
|
+
addServerHandler({
|
|
421
|
+
method: "get",
|
|
422
|
+
route: `${options.api.baseURL}/query`,
|
|
423
|
+
handler: resolveRuntimeModule("./server/api/query.js")
|
|
424
|
+
});
|
|
425
|
+
addServerHandler({
|
|
426
|
+
method: "get",
|
|
427
|
+
route: `${options.api.baseURL}/locales/:collection`,
|
|
428
|
+
handler: resolveRuntimeModule("./server/api/locales.js")
|
|
429
|
+
});
|
|
430
|
+
addServerHandler({
|
|
431
|
+
method: "get",
|
|
432
|
+
route: `${options.api.baseURL}/site-data`,
|
|
433
|
+
handler: resolveRuntimeModule("./server/api/site-data.js")
|
|
434
|
+
});
|
|
435
|
+
if (options.revalidate && options.revalidate !== false && options.revalidate.token) {
|
|
436
|
+
addServerHandler({
|
|
437
|
+
method: "post",
|
|
438
|
+
route: `${options.api.baseURL}/revalidate`,
|
|
439
|
+
handler: resolveRuntimeModule("./server/api/revalidate.js")
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
addServerHandler({
|
|
443
|
+
method: "get",
|
|
444
|
+
route: nuxt.options.dev ? `${options.api.baseURL}/cache.json` : `${options.api.baseURL}/cache.${buildIntegrity}.json`,
|
|
445
|
+
handler: resolveRuntimeModule("./server/api/cache.js")
|
|
446
|
+
});
|
|
447
|
+
if (options.sitemap !== false) {
|
|
448
|
+
addServerHandler({
|
|
449
|
+
method: "get",
|
|
450
|
+
route: `${options.api.baseURL}${options.sitemap.path || "/sitemap"}`,
|
|
451
|
+
handler: resolveRuntimeModule("./server/api/sitemap.js")
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
if (options.navigation) {
|
|
455
|
+
addServerHandler({
|
|
456
|
+
method: "get",
|
|
457
|
+
route: `${options.api.baseURL}/navigation/**:params`,
|
|
458
|
+
handler: resolveRuntimeModule("./server/api/navigation.js")
|
|
459
|
+
});
|
|
460
|
+
addServerHandler({
|
|
461
|
+
method: "get",
|
|
462
|
+
route: `${options.api.baseURL}/navigation`,
|
|
463
|
+
handler: resolveRuntimeModule("./server/api/navigation.js")
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
const registerContentSearchServerHandlers = (apiBaseURL, search, resolveRuntimeModule) => {
|
|
468
|
+
const searchBaseURL = search.apiBaseURL || `${apiBaseURL.replace(/\/$/, "")}/search`;
|
|
469
|
+
const indexURL = `${searchBaseURL.replace(/\/$/, "")}/index.json`;
|
|
470
|
+
addServerHandler({
|
|
471
|
+
method: "get",
|
|
472
|
+
route: searchBaseURL,
|
|
473
|
+
handler: resolveRuntimeModule("./server/api/search.js")
|
|
474
|
+
});
|
|
475
|
+
if (search.engine !== "cms") {
|
|
476
|
+
addServerHandler({
|
|
477
|
+
method: "get",
|
|
478
|
+
route: indexURL,
|
|
479
|
+
handler: resolveRuntimeModule("./server/api/search-index.js")
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const SITEMAP_INDEX = "sitemap_index.xml";
|
|
485
|
+
const assert = (condition, message) => {
|
|
486
|
+
if (!condition) {
|
|
487
|
+
throw new Error(message);
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
const countTag = (xml, tag) => (xml.match(new RegExp(`<${tag}>`, "g")) || []).length;
|
|
491
|
+
const extractLocValues = (xml) => {
|
|
492
|
+
return Array.from(xml.matchAll(/<loc>([^<]+)<\/loc>/g), (match) => match[1]);
|
|
493
|
+
};
|
|
494
|
+
const toLocalPath = (value) => {
|
|
495
|
+
try {
|
|
496
|
+
return new URL(value).pathname;
|
|
497
|
+
} catch {
|
|
498
|
+
return value;
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
const discoverSitemapsFromDisk = async (outputPublicDir) => {
|
|
502
|
+
const indexPath = join$1(outputPublicDir, SITEMAP_INDEX);
|
|
503
|
+
try {
|
|
504
|
+
const sitemapIndex = await readFile(indexPath, "utf8");
|
|
505
|
+
const locValues = extractLocValues(sitemapIndex);
|
|
506
|
+
const discovered = locValues.map(toLocalPath).filter((path) => path.endsWith(".xml") && path !== "/sitemap.xml" && path !== "/sitemap_index.xml").map((path) => {
|
|
507
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
508
|
+
return {
|
|
509
|
+
name: basename(normalizedPath, ".xml"),
|
|
510
|
+
path: join$1(outputPublicDir, normalizedPath)
|
|
511
|
+
};
|
|
512
|
+
});
|
|
513
|
+
if (discovered.length > 0) {
|
|
514
|
+
return Promise.all(discovered.map(async (target) => ({
|
|
515
|
+
...target,
|
|
516
|
+
xml: await readFile(target.path, "utf8")
|
|
517
|
+
})));
|
|
518
|
+
}
|
|
519
|
+
} catch {
|
|
520
|
+
}
|
|
521
|
+
const children = [];
|
|
522
|
+
const sitemapDir = join$1(outputPublicDir, "__sitemap__");
|
|
523
|
+
try {
|
|
524
|
+
const sitemapFiles = (await readdir(sitemapDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".xml")).map((entry) => ({
|
|
525
|
+
name: basename(entry.name, ".xml"),
|
|
526
|
+
path: join$1(sitemapDir, entry.name)
|
|
527
|
+
}));
|
|
528
|
+
children.push(...await Promise.all(sitemapFiles.map(async (target) => ({
|
|
529
|
+
...target,
|
|
530
|
+
xml: await readFile(target.path, "utf8")
|
|
531
|
+
}))));
|
|
532
|
+
} catch {
|
|
533
|
+
}
|
|
534
|
+
if (children.length > 0) {
|
|
535
|
+
return children;
|
|
536
|
+
}
|
|
537
|
+
const rootSitemapPath = join$1(outputPublicDir, "sitemap.xml");
|
|
538
|
+
const rootSitemapXml = await readFile(rootSitemapPath, "utf8");
|
|
539
|
+
assert(
|
|
540
|
+
countTag(rootSitemapXml, "url") > 0 || rootSitemapXml.includes("<urlset"),
|
|
541
|
+
`Content sitemap assertion failed: no child sitemap files were discovered in ${indexPath} or ${sitemapDir}, and ${rootSitemapPath} is not a urlset sitemap.`
|
|
542
|
+
);
|
|
543
|
+
return [{
|
|
544
|
+
name: "sitemap",
|
|
545
|
+
path: rootSitemapPath,
|
|
546
|
+
xml: rootSitemapXml
|
|
547
|
+
}];
|
|
548
|
+
};
|
|
549
|
+
const normalizeContentSitemapAssertOptions = (options) => ({
|
|
550
|
+
enabled: options?.enabled ?? false,
|
|
551
|
+
mode: options?.mode ?? "generate",
|
|
552
|
+
allowEmpty: options?.allowEmpty ?? false,
|
|
553
|
+
minUrlsPerSitemap: options?.minUrlsPerSitemap ?? 1,
|
|
554
|
+
requireImages: options?.requireImages ?? false,
|
|
555
|
+
requiredCollections: options?.requiredCollections ?? [],
|
|
556
|
+
sitemaps: options?.sitemaps ?? {}
|
|
557
|
+
});
|
|
558
|
+
const shouldRunSitemapAssertionOnCompiled = (options, nitro) => {
|
|
559
|
+
const isStaticLikeBuild = nitro.options.static || nitro.options.preset === "static";
|
|
560
|
+
if (!options.enabled || isStaticLikeBuild) {
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
return options.mode === "build" || options.mode === "both";
|
|
564
|
+
};
|
|
565
|
+
const shouldRunSitemapAssertionOnPrerenderedSitemaps = (options) => options.enabled && options.mode !== "build";
|
|
566
|
+
async function assertGeneratedSitemaps({
|
|
567
|
+
options,
|
|
568
|
+
collectionRouteCounts,
|
|
569
|
+
outputPublicDir,
|
|
570
|
+
targets,
|
|
571
|
+
logger
|
|
572
|
+
}) {
|
|
573
|
+
const discoveredSitemaps = targets || (outputPublicDir ? await discoverSitemapsFromDisk(outputPublicDir) : []);
|
|
574
|
+
assert(discoveredSitemaps.length > 0, "Content sitemap assertion failed: no sitemap targets were available for validation.");
|
|
575
|
+
const targetMap = new Map(discoveredSitemaps.map((target) => [target.name, target]));
|
|
576
|
+
const failures = [];
|
|
577
|
+
for (const sitemapName of Object.keys(options.sitemaps)) {
|
|
578
|
+
if (!targetMap.has(sitemapName)) {
|
|
579
|
+
const sourceDescription = outputPublicDir ? join$1(outputPublicDir, SITEMAP_INDEX) : "prerendered sitemap_index.xml";
|
|
580
|
+
failures.push(`- Missing sitemap "${sitemapName}" in ${sourceDescription}`);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
for (const target of targetMap.values()) {
|
|
584
|
+
const overrides = options.sitemaps[target.name] || {};
|
|
585
|
+
const allowEmpty = overrides.allowEmpty ?? options.allowEmpty;
|
|
586
|
+
const minUrls = overrides.minUrls ?? options.minUrlsPerSitemap;
|
|
587
|
+
const requireImages = overrides.requireImages ?? options.requireImages;
|
|
588
|
+
const urlCount = countTag(target.xml, "url");
|
|
589
|
+
const imageCount = countTag(target.xml, "image:image");
|
|
590
|
+
if (!allowEmpty && urlCount < minUrls) {
|
|
591
|
+
failures.push(`- ${target.name}: ${urlCount} URLs, expected at least ${minUrls}`);
|
|
592
|
+
}
|
|
593
|
+
if (requireImages && imageCount === 0) {
|
|
594
|
+
failures.push(`- ${target.name}: expected image entries but found none`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
const missingCollections = options.requiredCollections.filter((collection) => (collectionRouteCounts[collection] || 0) === 0);
|
|
598
|
+
if (missingCollections.length) {
|
|
599
|
+
failures.push(`- Missing content sitemap routes for collections: ${missingCollections.join(", ")}`);
|
|
600
|
+
}
|
|
601
|
+
if (failures.length) {
|
|
602
|
+
throw new Error(`Content sitemap assertion failed:
|
|
603
|
+
${failures.join("\n")}`);
|
|
604
|
+
}
|
|
605
|
+
logger?.info(`Content sitemap assertion passed for ${targetMap.size} sitemap${targetMap.size === 1 ? "" : "s"}.`);
|
|
606
|
+
}
|
|
607
|
+
const createSitemapAssertionTargetsFromPrerenderedSitemaps = (sitemaps) => {
|
|
608
|
+
const targets = sitemaps.map((sitemap) => {
|
|
609
|
+
const path = toLocalPath(sitemap.name);
|
|
610
|
+
const name = basename(path, ".xml");
|
|
611
|
+
return {
|
|
612
|
+
name,
|
|
613
|
+
path,
|
|
614
|
+
xml: sitemap.content
|
|
615
|
+
};
|
|
616
|
+
}).filter((target) => {
|
|
617
|
+
if (target.name === "sitemap_index") {
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
if (target.name === "sitemap") {
|
|
621
|
+
return target.xml.includes("<urlset");
|
|
622
|
+
}
|
|
623
|
+
return true;
|
|
624
|
+
});
|
|
625
|
+
assert(targets.length > 0, "Content sitemap assertion failed: no sitemap urlsets were available from sitemap:prerender:done.");
|
|
626
|
+
return targets;
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
function hasNuxtModule(modules = [], name) {
|
|
630
|
+
return modules.some((entry) => {
|
|
631
|
+
if (typeof entry === "string") {
|
|
632
|
+
return entry === name;
|
|
633
|
+
}
|
|
634
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
635
|
+
return entry[0] === name;
|
|
636
|
+
}
|
|
637
|
+
return false;
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
function hasNuxtI18nModule(modules = []) {
|
|
641
|
+
return hasNuxtModule(modules, "@nuxtjs/i18n");
|
|
642
|
+
}
|
|
643
|
+
function hasNuxtSitemapModule(modules = []) {
|
|
644
|
+
return hasNuxtModule(modules, "@nuxtjs/sitemap");
|
|
645
|
+
}
|
|
646
|
+
function resolveNuxtSitemapPrerenderRoutes(nuxt) {
|
|
647
|
+
if (!hasNuxtSitemapModule(nuxt.options.modules)) {
|
|
648
|
+
return [];
|
|
649
|
+
}
|
|
650
|
+
const nuxtI18n = nuxt.options.i18n || {};
|
|
651
|
+
if (!hasNuxtI18nModule(nuxt.options.modules) || !Array.isArray(nuxtI18n.locales) || nuxtI18n.locales.length === 0) {
|
|
652
|
+
return [];
|
|
653
|
+
}
|
|
654
|
+
const childRoutes = nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.language || locale.code).filter(Boolean).map((locale) => `/__sitemap__/${locale}.xml`);
|
|
655
|
+
return Array.from(/* @__PURE__ */ new Set(["/sitemap_index.xml", ...childRoutes]));
|
|
656
|
+
}
|
|
657
|
+
function resolveModuleI18nOptions(options, nuxt) {
|
|
658
|
+
if (options.i18n === false) {
|
|
659
|
+
return {
|
|
660
|
+
locales: [],
|
|
661
|
+
defaultLocale: void 0,
|
|
662
|
+
fallback: {},
|
|
663
|
+
translatedSlugs: false,
|
|
664
|
+
strictTranslatedSlugs: false
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
const moduleI18n = options.i18n === true ? {} : options.i18n || {};
|
|
668
|
+
const nuxtI18n = nuxt.options.i18n || {};
|
|
669
|
+
const nuxtLocales = Array.isArray(nuxtI18n.locales) ? nuxtI18n.locales.map((locale) => typeof locale === "string" ? locale : locale.code).filter(Boolean) : [];
|
|
670
|
+
const locales = Array.from(new Set([
|
|
671
|
+
moduleI18n.defaultLocale,
|
|
672
|
+
nuxtI18n.defaultLocale,
|
|
673
|
+
...moduleI18n.locales || [],
|
|
674
|
+
...nuxtLocales
|
|
675
|
+
].filter(Boolean)));
|
|
676
|
+
const defaultLocale = moduleI18n.defaultLocale || nuxtI18n.defaultLocale || locales[0];
|
|
677
|
+
return {
|
|
678
|
+
locales,
|
|
679
|
+
defaultLocale,
|
|
680
|
+
fallback: defu({}, moduleI18n.fallback),
|
|
681
|
+
translatedSlugs: moduleI18n.translatedSlugs ?? false,
|
|
682
|
+
strictTranslatedSlugs: moduleI18n.strictTranslatedSlugs ?? false
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function normalizeSitemapOptions(options) {
|
|
686
|
+
if (options.sitemap === false) {
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
const sitemap = options.sitemap === true ? {} : options.sitemap;
|
|
690
|
+
return {
|
|
691
|
+
path: sitemap.path || "/sitemap",
|
|
692
|
+
include: sitemap.include,
|
|
693
|
+
exclude: sitemap.exclude || [],
|
|
694
|
+
includeDrafts: sitemap.includeDrafts,
|
|
695
|
+
assert: normalizeContentSitemapAssertOptions(sitemap.assert)
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
function normalizeSearchOptions(options) {
|
|
699
|
+
if (options.search === false) {
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
engine: options.search?.engine || "minisearch",
|
|
704
|
+
ignoredTags: options.search?.ignoredTags || ["script", "style", "pre"],
|
|
705
|
+
filterQuery: options.search?.filterQuery || { _draft: false, _partial: false },
|
|
706
|
+
collections: options.search?.collections,
|
|
707
|
+
extraFields: options.search?.extraFields || [],
|
|
708
|
+
apiBaseURL: options.search?.apiBaseURL,
|
|
709
|
+
minisearch: normalizeMiniSearchOptions(options.search?.minisearch)
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
const defaultMiniSearchOptions = {
|
|
713
|
+
fields: ["title", "content", "headings"],
|
|
714
|
+
storeFields: ["path", "title", "excerpt", "anchor", "locale"],
|
|
715
|
+
boost: {
|
|
716
|
+
title: 4,
|
|
717
|
+
headings: 2,
|
|
718
|
+
content: 1
|
|
719
|
+
},
|
|
720
|
+
fuzzy: 0.2,
|
|
721
|
+
prefix: true
|
|
722
|
+
};
|
|
723
|
+
const requiredMiniSearchStoreFields = ["path", "title", "excerpt"];
|
|
724
|
+
function normalizeMiniSearchOptions(options = {}) {
|
|
725
|
+
const fields = options?.fields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
726
|
+
const storeFields = options?.storeFields?.filter((field) => typeof field === "string" && field.length > 0);
|
|
727
|
+
const boost = Object.fromEntries(
|
|
728
|
+
Object.entries(options?.boost || {}).filter((entry) => typeof entry[0] === "string" && entry[0].length > 0 && typeof entry[1] === "number" && Number.isFinite(entry[1]))
|
|
729
|
+
);
|
|
730
|
+
const resolvedFields = fields?.length ? fields : [...defaultMiniSearchOptions.fields];
|
|
731
|
+
const resolvedStoreFields = storeFields?.length ? storeFields : defaultMiniSearchOptions.storeFields;
|
|
732
|
+
return {
|
|
733
|
+
fields: resolvedFields,
|
|
734
|
+
storeFields: Array.from(/* @__PURE__ */ new Set([...requiredMiniSearchStoreFields, ...resolvedStoreFields])),
|
|
735
|
+
boost: Object.keys(boost).length ? boost : { ...defaultMiniSearchOptions.boost },
|
|
736
|
+
fuzzy: typeof options?.fuzzy === "boolean" || typeof options?.fuzzy === "number" ? options.fuzzy : defaultMiniSearchOptions.fuzzy,
|
|
737
|
+
prefix: typeof options?.prefix === "boolean" ? options.prefix : defaultMiniSearchOptions.prefix
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function createSearchRuntimeConfig(search, apiBaseURL) {
|
|
741
|
+
const resolvedApiBaseURL = search.apiBaseURL || `${apiBaseURL.replace(/\/$/, "")}/search`;
|
|
742
|
+
return {
|
|
743
|
+
apiBaseURL: resolvedApiBaseURL,
|
|
744
|
+
indexURL: `${resolvedApiBaseURL.replace(/\/$/, "")}/index.json`,
|
|
745
|
+
engine: search.engine || "minisearch",
|
|
746
|
+
minisearch: normalizeMiniSearchOptions(search.minisearch)
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
const resolveNuxtSiteUrl = (nuxt) => {
|
|
751
|
+
const publicRuntime = nuxt.options.runtimeConfig.public;
|
|
752
|
+
const configuredSiteUrl = publicRuntime.siteUrl;
|
|
753
|
+
if (typeof configuredSiteUrl === "string" && configuredSiteUrl.length > 0) {
|
|
754
|
+
return configuredSiteUrl;
|
|
755
|
+
}
|
|
756
|
+
const nuxtSite = nuxt.options.site;
|
|
757
|
+
return typeof nuxtSite?.url === "string" && nuxtSite.url.length > 0 ? nuxtSite.url : void 0;
|
|
758
|
+
};
|
|
759
|
+
const applyContentRuntimeConfig = (nuxt, options, contentContext, runtimeCollections, buildIntegrity, cacheIntegrity) => {
|
|
760
|
+
const searchRuntime = contentContext.search === false ? false : {
|
|
761
|
+
apiBaseURL: contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`,
|
|
762
|
+
indexURL: `${(contentContext.search.apiBaseURL || `${options.api.baseURL.replace(/\/$/, "")}/search`).replace(/\/$/, "")}/index.json`,
|
|
763
|
+
engine: contentContext.search.engine || "minisearch",
|
|
764
|
+
minisearch: normalizeMiniSearchOptions(contentContext.search.minisearch)
|
|
765
|
+
};
|
|
766
|
+
const contentRuntime = defu(nuxt.options.runtimeConfig.public.content, {
|
|
767
|
+
locales: contentContext.locales,
|
|
768
|
+
provider: contentContext.provider || "filesystem",
|
|
769
|
+
providers: contentContext.providers || {},
|
|
770
|
+
defaultLocale: contentContext.defaultLocale || void 0,
|
|
771
|
+
localeFallback: contentContext.localeFallback || {},
|
|
772
|
+
translatedSlugs: contentContext.translatedSlugs ?? false,
|
|
773
|
+
strictTranslatedSlugs: contentContext.strictTranslatedSlugs ?? false,
|
|
774
|
+
collections: runtimeCollections,
|
|
775
|
+
integrity: buildIntegrity,
|
|
776
|
+
experimental: {
|
|
777
|
+
stripQueryParameters: options.experimental.stripQueryParameters
|
|
778
|
+
},
|
|
779
|
+
respectPathCase: options.respectPathCase ?? false,
|
|
780
|
+
api: {
|
|
781
|
+
baseURL: options.api.baseURL
|
|
782
|
+
},
|
|
783
|
+
markdown: {
|
|
784
|
+
plugins: contentContext.markdown.plugins,
|
|
785
|
+
tags: contentContext.markdown.tags,
|
|
786
|
+
anchorLinks: contentContext.markdown.anchorLinks,
|
|
787
|
+
image: contentContext.markdown.image || "auto"
|
|
788
|
+
},
|
|
789
|
+
sitemap: contentContext.sitemap ? {
|
|
790
|
+
path: contentContext.sitemap.path || "/sitemap",
|
|
791
|
+
...contentContext.sitemap.include?.length ? { include: contentContext.sitemap.include } : {},
|
|
792
|
+
...contentContext.sitemap.exclude?.length ? { exclude: contentContext.sitemap.exclude } : {},
|
|
793
|
+
...typeof contentContext.sitemap.includeDrafts === "boolean" ? { includeDrafts: contentContext.sitemap.includeDrafts } : {}
|
|
794
|
+
} : false,
|
|
795
|
+
search: searchRuntime,
|
|
796
|
+
navigation: contentContext.navigation,
|
|
797
|
+
wsUrl: "",
|
|
798
|
+
contentHead: options.contentHead ?? true
|
|
799
|
+
});
|
|
800
|
+
const siteUrl = resolveNuxtSiteUrl(nuxt);
|
|
801
|
+
if (siteUrl) {
|
|
802
|
+
nuxt.options.runtimeConfig.public.siteUrl = siteUrl;
|
|
803
|
+
}
|
|
804
|
+
nuxt.options.runtimeConfig.public.content = contentRuntime;
|
|
805
|
+
nuxt.options.runtimeConfig.content = defu(nuxt.options.runtimeConfig.content, {
|
|
806
|
+
cacheVersion: CACHE_VERSION,
|
|
807
|
+
cacheIntegrity,
|
|
808
|
+
revalidate: options.revalidate && options.revalidate !== false && options.revalidate.token ? {
|
|
809
|
+
token: options.revalidate.token,
|
|
810
|
+
allowUnsigned: options.revalidate.allowUnsigned === true
|
|
811
|
+
} : false,
|
|
812
|
+
...contentContext,
|
|
813
|
+
collections: runtimeCollections
|
|
814
|
+
});
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
const registerContentComponentsTemplate = (addTemplateImpl) => {
|
|
818
|
+
addTemplateImpl({
|
|
819
|
+
filename: "content-components.mjs",
|
|
820
|
+
getContents({ app, nuxt }) {
|
|
821
|
+
const componentsMap = app.components.filter((component) => {
|
|
822
|
+
if (component.island) {
|
|
823
|
+
return false;
|
|
824
|
+
}
|
|
825
|
+
if (component.filePath.endsWith(".css")) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
if (component.pascalName === "ClientOnly" || component.filePath.includes("nuxt/dist/") || component.filePath.includes("NuxtWelcome")) {
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
return true;
|
|
832
|
+
}).reduce((map, component) => {
|
|
833
|
+
const importPath = isAbsolute(component.filePath) ? "./" + relative(nuxt.options.buildDir, component.filePath).replace(/\b\.(?!vue)\w+$/g, "") : component.filePath.replace(/\b\.(?!vue)\w+$/g, "");
|
|
834
|
+
map[component.pascalName] = map[component.pascalName] || [
|
|
835
|
+
component.pascalName,
|
|
836
|
+
importPath,
|
|
837
|
+
component.global,
|
|
838
|
+
component.export || "default"
|
|
839
|
+
];
|
|
840
|
+
return map;
|
|
841
|
+
}, {});
|
|
842
|
+
const componentsList = Object.values(componentsMap);
|
|
843
|
+
const globalComponents = componentsList.filter((component) => component[2]).map((component) => component[0]);
|
|
844
|
+
const localComponents = componentsList.filter((component) => !component[2]);
|
|
845
|
+
return [
|
|
846
|
+
"const pickExport = (mod, exportName, componentName, path) => {",
|
|
847
|
+
" const resolved = exportName === 'default' ? mod?.default || mod : mod?.[exportName]",
|
|
848
|
+
" if (!resolved) {",
|
|
849
|
+
' throw new Error(`[nuxt-content] Missing export "${exportName}" for component "${componentName}" in "${path}".`)',
|
|
850
|
+
" }",
|
|
851
|
+
" return resolved",
|
|
852
|
+
"}",
|
|
853
|
+
"export const localComponentLoaders = {",
|
|
854
|
+
...localComponents.map(([pascalName, path, , exp]) => {
|
|
855
|
+
const pathLiteral = JSON.stringify(path);
|
|
856
|
+
const exportLiteral = JSON.stringify(exp);
|
|
857
|
+
const nameLiteral = JSON.stringify(pascalName);
|
|
858
|
+
return ` ${pascalName}: () => import(${pathLiteral}).then(mod => pickExport(mod, ${exportLiteral}, ${nameLiteral}, ${pathLiteral})),`;
|
|
859
|
+
}),
|
|
860
|
+
"}",
|
|
861
|
+
`export const globalComponents = ${JSON.stringify(globalComponents)}`,
|
|
862
|
+
`export const localComponents = ${JSON.stringify(localComponents.map((component) => component[0]))}`
|
|
863
|
+
].join("\n");
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
const appendHook = (hooks, name, handler) => {
|
|
869
|
+
const existing = hooks[name];
|
|
870
|
+
if (!existing) {
|
|
871
|
+
hooks[name] = handler;
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
hooks[name] = Array.isArray(existing) ? [...existing, handler] : [existing, handler];
|
|
875
|
+
};
|
|
876
|
+
const resolveSitemapCollections = (collections, sitemap) => {
|
|
877
|
+
if (!sitemap || sitemap === false) {
|
|
878
|
+
return [];
|
|
879
|
+
}
|
|
880
|
+
const include = sitemap.include?.length ? sitemap.include : Object.keys(collections);
|
|
881
|
+
const excluded = new Set(sitemap.exclude || []);
|
|
882
|
+
return include.filter((collection) => !excluded.has(collection) && collections[collection]?.sitemap !== false);
|
|
883
|
+
};
|
|
884
|
+
const numericSlugSegmentPattern = /^(\d+)\.[^*?[\]{}()]+(.*)$/;
|
|
885
|
+
const toTranslatedSlugSourcePattern = (source) => {
|
|
886
|
+
return source.split("/").map((segment) => {
|
|
887
|
+
const match = segment.match(numericSlugSegmentPattern);
|
|
888
|
+
return match ? `${match[1]}.*${match[2] || ""}` : segment;
|
|
889
|
+
}).join("/");
|
|
890
|
+
};
|
|
891
|
+
const parseCollectionFiles = async (rootDir, collections, collectionNames, contentContext) => {
|
|
892
|
+
const contentDir = resolve$1(rootDir, "content");
|
|
893
|
+
const patterns = Array.from(new Set(
|
|
894
|
+
collectionNames.flatMap((name) => {
|
|
895
|
+
const source = collections[name]?.source;
|
|
896
|
+
if (!source) {
|
|
897
|
+
return [];
|
|
898
|
+
}
|
|
899
|
+
const sources = normalizeCollectionSources(source);
|
|
900
|
+
const excludes = normalizeCollectionExcludes(collections[name]?.exclude);
|
|
901
|
+
const localeSources = contentContext.translatedSlugs ? Array.from(new Set(sources.flatMap((pattern) => [
|
|
902
|
+
pattern,
|
|
903
|
+
toTranslatedSlugSourcePattern(pattern)
|
|
904
|
+
]))) : sources;
|
|
905
|
+
const localePatterns = (contentContext.locales || []).flatMap((locale) => localeSources.map((pattern) => `${locale}/${pattern}`));
|
|
906
|
+
const excludePatterns = excludes.flatMap((pattern) => [
|
|
907
|
+
`!${pattern}`,
|
|
908
|
+
...(contentContext.locales || []).map((locale) => `!${locale}/${pattern}`)
|
|
909
|
+
]);
|
|
910
|
+
return [...sources, ...localePatterns, ...excludePatterns];
|
|
911
|
+
}).filter(Boolean)
|
|
912
|
+
));
|
|
913
|
+
const ids = await globby(patterns, {
|
|
914
|
+
cwd: contentDir,
|
|
915
|
+
onlyFiles: true,
|
|
916
|
+
dot: false
|
|
917
|
+
});
|
|
918
|
+
const documents = [];
|
|
919
|
+
for (const id of ids) {
|
|
920
|
+
const file = resolve$1(contentDir, id);
|
|
921
|
+
const content = await readFile(file, "utf8");
|
|
922
|
+
const normalizedId = `content:${relative$1(contentDir, file).replaceAll("\\", "/")}`;
|
|
923
|
+
const parsed = await transformContent(normalizedId, content, {
|
|
924
|
+
markdown: contentContext.markdown,
|
|
925
|
+
yaml: contentContext.yaml,
|
|
926
|
+
csv: contentContext.csv,
|
|
927
|
+
pathMeta: {
|
|
928
|
+
locales: contentContext.locales,
|
|
929
|
+
defaultLocale: contentContext.defaultLocale,
|
|
930
|
+
translatedSlugs: contentContext.translatedSlugs,
|
|
931
|
+
respectPathCase: contentContext.respectPathCase,
|
|
932
|
+
collections,
|
|
933
|
+
collectionResolver: (filePath) => resolveCollection(filePath, collections, contentContext.locales || [])
|
|
934
|
+
}
|
|
935
|
+
});
|
|
936
|
+
const collection = parsed._collection ? collections[parsed._collection] : void 0;
|
|
937
|
+
documents.push(...expandDataLocaleVariants(parsed, collection?.i18n));
|
|
938
|
+
}
|
|
939
|
+
return documents;
|
|
940
|
+
};
|
|
941
|
+
const collectPrerenderRoutes = async (rootDir, contentContext) => {
|
|
942
|
+
const collections = contentContext.collections || {};
|
|
943
|
+
if (!contentContext.sitemap || contentContext.sitemap === false) {
|
|
944
|
+
return [];
|
|
945
|
+
}
|
|
946
|
+
const includeCollections = resolveSitemapCollections(collections, contentContext.sitemap);
|
|
947
|
+
if (!includeCollections.length) {
|
|
948
|
+
return [];
|
|
949
|
+
}
|
|
950
|
+
const documents = await parseCollectionFiles(rootDir, collections, includeCollections, contentContext);
|
|
951
|
+
const graph = buildContentGraph(documents, {
|
|
952
|
+
locales: contentContext.locales,
|
|
953
|
+
defaultLocale: contentContext.defaultLocale
|
|
954
|
+
});
|
|
955
|
+
const routes = /* @__PURE__ */ new Set();
|
|
956
|
+
for (const collection of includeCollections) {
|
|
957
|
+
const { defaultLocale } = resolveCollectionI18n(collection, contentContext);
|
|
958
|
+
const includeDrafts = contentContext.sitemap && contentContext.sitemap !== false ? Boolean(contentContext.sitemap.includeDrafts) : false;
|
|
959
|
+
const seenCanonicalKeys = /* @__PURE__ */ new Set();
|
|
960
|
+
for (const contentId of graph.byCollection[collection] || []) {
|
|
961
|
+
const document = graph.byId[contentId];
|
|
962
|
+
if (!document || !document._canonicalKey || document._partial || document._navigation) {
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
if (document._draft && !includeDrafts) {
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
if (seenCanonicalKeys.has(document._canonicalKey)) {
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
seenCanonicalKeys.add(document._canonicalKey);
|
|
972
|
+
const variants = graph.byCanonical[document._canonicalKey] || {};
|
|
973
|
+
for (const [locale, variant] of Object.entries(variants)) {
|
|
974
|
+
if (!variant.path) {
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
const routeLocale = (contentContext.locales || []).includes(locale) ? locale : void 0;
|
|
978
|
+
routes.add(prefixPathWithLocale(variant.path, routeLocale, defaultLocale));
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return Array.from(routes).sort();
|
|
983
|
+
};
|
|
984
|
+
const collectSitemapCollectionRouteCounts = async (rootDir, contentContext) => {
|
|
985
|
+
const collections = contentContext.collections || {};
|
|
986
|
+
const includedCollections = resolveSitemapCollections(collections, contentContext.sitemap);
|
|
987
|
+
if (!includedCollections.length) {
|
|
988
|
+
return {};
|
|
989
|
+
}
|
|
990
|
+
const documents = await parseCollectionFiles(rootDir, collections, includedCollections, contentContext);
|
|
991
|
+
const graph = buildContentGraph(documents, {
|
|
992
|
+
locales: contentContext.locales,
|
|
993
|
+
defaultLocale: contentContext.defaultLocale
|
|
994
|
+
});
|
|
995
|
+
const counts = Object.fromEntries(includedCollections.map((collection) => [collection, 0]));
|
|
996
|
+
const includeDrafts = contentContext.sitemap && contentContext.sitemap !== false ? Boolean(contentContext.sitemap.includeDrafts) : false;
|
|
997
|
+
for (const collection of includedCollections) {
|
|
998
|
+
const seenCanonicalKeys = /* @__PURE__ */ new Set();
|
|
999
|
+
for (const contentId of graph.byCollection[collection] || []) {
|
|
1000
|
+
const document = graph.byId[contentId];
|
|
1001
|
+
if (!document || !document._canonicalKey || document._partial || document._navigation) {
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
if (document._draft && !includeDrafts) {
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
if (seenCanonicalKeys.has(document._canonicalKey)) {
|
|
1008
|
+
continue;
|
|
1009
|
+
}
|
|
1010
|
+
const variants = Object.values(graph.byCanonical[document._canonicalKey] || {});
|
|
1011
|
+
if (!variants.some((variant) => variant.path)) {
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
seenCanonicalKeys.add(document._canonicalKey);
|
|
1015
|
+
counts[collection] += 1;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
return counts;
|
|
1019
|
+
};
|
|
1020
|
+
const registerContentNitroIntegrationHooks = (nitroConfig, options, contentContext) => {
|
|
1021
|
+
if (contentContext.provider && contentContext.provider !== "filesystem") {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
nitroConfig.hooks ||= {};
|
|
1025
|
+
if (contentContext.sitemap?.assert?.enabled) {
|
|
1026
|
+
appendHook(nitroConfig.hooks, "compiled", async (nitro) => {
|
|
1027
|
+
const assertOptions = contentContext.sitemap?.assert;
|
|
1028
|
+
if (!assertOptions || !shouldRunSitemapAssertionOnCompiled(assertOptions, nitro)) {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
try {
|
|
1032
|
+
await assertGeneratedSitemaps({
|
|
1033
|
+
outputPublicDir: nitro.options.output.publicDir,
|
|
1034
|
+
options: assertOptions,
|
|
1035
|
+
collectionRouteCounts: await collectSitemapCollectionRouteCounts(options.rootDir, contentContext),
|
|
1036
|
+
logger: nitro.logger
|
|
1037
|
+
});
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
if (error?.code === "ENOENT") {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
throw error;
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
appendHook(nitroConfig.hooks, "prerender:routes", async (routes) => {
|
|
1047
|
+
for (const route of await collectPrerenderRoutes(options.rootDir, contentContext)) {
|
|
1048
|
+
routes.add(route);
|
|
1049
|
+
}
|
|
1050
|
+
for (const route of options.sitemapPrerenderRoutes || []) {
|
|
1051
|
+
routes.add(route);
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
const module$1 = defineNuxtModule({
|
|
1057
|
+
meta: {
|
|
1058
|
+
name,
|
|
1059
|
+
version,
|
|
1060
|
+
configKey: "content",
|
|
1061
|
+
compatibility: {
|
|
1062
|
+
nuxt: ">=4.0.0"
|
|
1063
|
+
}
|
|
1064
|
+
},
|
|
1065
|
+
moduleDependencies: {
|
|
1066
|
+
"@nuxt/ui": {
|
|
1067
|
+
optional: true,
|
|
1068
|
+
defaults: {
|
|
1069
|
+
content: true,
|
|
1070
|
+
prose: true
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
defaults: {
|
|
1075
|
+
api: {
|
|
1076
|
+
baseURL: "/api/_content"
|
|
1077
|
+
},
|
|
1078
|
+
i18n: true,
|
|
1079
|
+
sitemap: true,
|
|
1080
|
+
search: {
|
|
1081
|
+
engine: "minisearch",
|
|
1082
|
+
ignoredTags: ["script", "style", "pre"],
|
|
1083
|
+
filterQuery: { _draft: false, _partial: false },
|
|
1084
|
+
extraFields: [],
|
|
1085
|
+
minisearch: {
|
|
1086
|
+
fields: ["title", "content", "headings"],
|
|
1087
|
+
storeFields: ["path", "title", "excerpt", "anchor", "locale"],
|
|
1088
|
+
boost: {
|
|
1089
|
+
title: 4,
|
|
1090
|
+
headings: 2,
|
|
1091
|
+
content: 1
|
|
1092
|
+
},
|
|
1093
|
+
fuzzy: 0.2,
|
|
1094
|
+
prefix: true
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
watch: {
|
|
1098
|
+
ws: {
|
|
1099
|
+
port: {
|
|
1100
|
+
port: 4e3,
|
|
1101
|
+
portRange: [4e3, 4040]
|
|
1102
|
+
},
|
|
1103
|
+
hostname: "localhost",
|
|
1104
|
+
showURL: false
|
|
1105
|
+
}
|
|
1106
|
+
},
|
|
1107
|
+
sources: {},
|
|
1108
|
+
ignores: [],
|
|
1109
|
+
collections: {},
|
|
1110
|
+
markdown: {
|
|
1111
|
+
plugins: [],
|
|
1112
|
+
tags: {
|
|
1113
|
+
code: "ProseCode",
|
|
1114
|
+
img: "ProseImg",
|
|
1115
|
+
pre: "ProsePre"
|
|
1116
|
+
},
|
|
1117
|
+
anchorLinks: {
|
|
1118
|
+
depth: 4,
|
|
1119
|
+
exclude: [1]
|
|
1120
|
+
},
|
|
1121
|
+
image: "auto"
|
|
1122
|
+
},
|
|
1123
|
+
yaml: {},
|
|
1124
|
+
csv: {
|
|
1125
|
+
delimiter: ",",
|
|
1126
|
+
json: true
|
|
1127
|
+
},
|
|
1128
|
+
navigation: {
|
|
1129
|
+
fields: []
|
|
1130
|
+
},
|
|
1131
|
+
contentHead: true,
|
|
1132
|
+
respectPathCase: false,
|
|
1133
|
+
experimental: {
|
|
1134
|
+
stripQueryParameters: false
|
|
1135
|
+
}
|
|
1136
|
+
},
|
|
1137
|
+
async setup(options, nuxt) {
|
|
1138
|
+
const { resolve, resolvePath } = createResolver(import.meta.url);
|
|
1139
|
+
const logger = useLogger(name);
|
|
1140
|
+
const resolveRuntimeModule = (path) => resolve("./runtime", path);
|
|
1141
|
+
const runtimeInlineDependencies = ["comark", "@comark/vue"];
|
|
1142
|
+
validateRemovedMarkdownOptions(options);
|
|
1143
|
+
nuxt.options.build.transpile ||= [];
|
|
1144
|
+
for (const dependency of runtimeInlineDependencies) {
|
|
1145
|
+
if (!nuxt.options.build.transpile.includes(dependency)) {
|
|
1146
|
+
nuxt.options.build.transpile.push(dependency);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
nuxt.options.vite = nuxt.options.vite || {};
|
|
1150
|
+
nuxt.options.vite.ssr = defu(nuxt.options.vite.ssr || {}, {
|
|
1151
|
+
noExternal: runtimeInlineDependencies
|
|
1152
|
+
});
|
|
1153
|
+
const contentConfigPath = resolveContentConfigPath(nuxt);
|
|
1154
|
+
const appContentConfig = await loadContentConfig(nuxt);
|
|
1155
|
+
if (!contentConfigPath || !appContentConfig.collections || !Object.keys(appContentConfig.collections).length) {
|
|
1156
|
+
throw new Error("@lupinum/ginko-content requires a content.config.ts with at least one collection. Define collections with defineContentConfig({ collections: { ... } }).");
|
|
1157
|
+
}
|
|
1158
|
+
const resolvedI18n = resolveModuleI18nOptions(options, nuxt);
|
|
1159
|
+
const resolvedSitemap = normalizeSitemapOptions(options);
|
|
1160
|
+
const resolvedSearch = normalizeSearchOptions(options);
|
|
1161
|
+
options.collections = Object.fromEntries(Object.entries(appContentConfig.collections).map(([name2, collection]) => [
|
|
1162
|
+
name2,
|
|
1163
|
+
{
|
|
1164
|
+
...collection,
|
|
1165
|
+
i18n: resolveCollectionI18nConfig(
|
|
1166
|
+
collection,
|
|
1167
|
+
resolvedI18n.defaultLocale && resolvedI18n.locales.length ? { defaultLocale: resolvedI18n.defaultLocale, locales: resolvedI18n.locales } : void 0,
|
|
1168
|
+
{ warnMissingGlobal: true }
|
|
1169
|
+
)
|
|
1170
|
+
}
|
|
1171
|
+
]));
|
|
1172
|
+
options.provider = appContentConfig.provider || options.provider || "filesystem";
|
|
1173
|
+
options.providers = {
|
|
1174
|
+
...options.providers || {},
|
|
1175
|
+
...appContentConfig.providers || {}
|
|
1176
|
+
};
|
|
1177
|
+
const buildIntegrity = nuxt.options.dev ? void 0 : Date.now();
|
|
1178
|
+
const contentContext = {
|
|
1179
|
+
...options,
|
|
1180
|
+
transformers: [],
|
|
1181
|
+
locales: resolvedI18n.locales,
|
|
1182
|
+
defaultLocale: resolvedI18n.defaultLocale,
|
|
1183
|
+
localeFallback: resolvedI18n.fallback,
|
|
1184
|
+
translatedSlugs: resolvedI18n.translatedSlugs,
|
|
1185
|
+
strictTranslatedSlugs: resolvedI18n.strictTranslatedSlugs,
|
|
1186
|
+
sitemap: resolvedSitemap,
|
|
1187
|
+
search: resolvedSearch
|
|
1188
|
+
};
|
|
1189
|
+
if (resolvedSitemap && resolvedSitemap.assert.enabled) {
|
|
1190
|
+
nuxt.hook("sitemap:prerender:done", async ({ sitemaps }) => {
|
|
1191
|
+
const assertOptions = contentContext.sitemap?.assert;
|
|
1192
|
+
if (!assertOptions || !shouldRunSitemapAssertionOnPrerenderedSitemaps(assertOptions)) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
await assertGeneratedSitemaps({
|
|
1196
|
+
options: assertOptions,
|
|
1197
|
+
targets: createSitemapAssertionTargetsFromPrerenderedSitemaps(sitemaps),
|
|
1198
|
+
collectionRouteCounts: await collectSitemapCollectionRouteCounts(nuxt.options.rootDir, contentContext),
|
|
1199
|
+
logger
|
|
1200
|
+
});
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
const { transformersTemplate, virtualConfigTemplate, virtualProvidersTemplate, virtualCacheAdapterTemplate } = createVirtualContentTemplates(contentContext, nuxt, contentConfigPath, addTemplate);
|
|
1204
|
+
registerVirtualContentAliases(nuxt, transformersTemplate, virtualConfigTemplate, virtualProvidersTemplate, virtualCacheAdapterTemplate, resolveRuntimeModule);
|
|
1205
|
+
registerContentServerHandlers(nuxt, options, resolveRuntimeModule, buildIntegrity);
|
|
1206
|
+
registerContentI18nTemplate(addTemplate, hasNuxtI18nModule(nuxt.options.modules));
|
|
1207
|
+
registerRuntimeImports(resolveRuntimeModule);
|
|
1208
|
+
registerRuntimeComponents(resolve);
|
|
1209
|
+
registerContentComponentsTemplate(addTemplate);
|
|
1210
|
+
registerGeneratedTypes(contentConfigPath, resolveRuntimeModule);
|
|
1211
|
+
await registerUserContentComponents(nuxt, resolve);
|
|
1212
|
+
const getSearchRuntime = () => contentContext.search === false ? false : createSearchRuntimeConfig(contentContext.search, options.api.baseURL);
|
|
1213
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
1214
|
+
const searchRuntime = getSearchRuntime();
|
|
1215
|
+
nitroConfig.prerender = nitroConfig.prerender || {};
|
|
1216
|
+
nitroConfig.prerender.routes = nitroConfig.prerender.routes || [];
|
|
1217
|
+
const usesFilesystemProvider = !contentContext.provider || contentContext.provider === "filesystem";
|
|
1218
|
+
if (!nuxt.options.dev && usesFilesystemProvider) {
|
|
1219
|
+
nitroConfig.prerender.routes.unshift(`${options.api.baseURL}/cache.${buildIntegrity}.json`);
|
|
1220
|
+
}
|
|
1221
|
+
const sources = useContentMounts(nuxt, contentContext.sources);
|
|
1222
|
+
nitroConfig.devStorage = Object.assign(nitroConfig.devStorage || {}, sources);
|
|
1223
|
+
nitroConfig.devStorage["cache:content"] = {
|
|
1224
|
+
driver: "fs",
|
|
1225
|
+
base: resolve(nuxt.options.buildDir, "content-cache")
|
|
1226
|
+
};
|
|
1227
|
+
for (const source of Object.values(sources)) {
|
|
1228
|
+
if (source.driver === "fs" && source.base.includes(nuxt.options.srcDir)) {
|
|
1229
|
+
const wildcard = join(source.base, "**/*").replace(withTrailingSlash(nuxt.options.srcDir), "");
|
|
1230
|
+
nuxt.options.ignore.push(
|
|
1231
|
+
// Remove `srcDir` from the path
|
|
1232
|
+
wildcard,
|
|
1233
|
+
`!${wildcard}.vue`
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
nitroConfig.bundledStorage = nitroConfig.bundledStorage || [];
|
|
1238
|
+
nitroConfig.bundledStorage.push("cache:content");
|
|
1239
|
+
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
|
|
1240
|
+
inline: [
|
|
1241
|
+
resolve("./runtime"),
|
|
1242
|
+
...runtimeInlineDependencies
|
|
1243
|
+
]
|
|
1244
|
+
});
|
|
1245
|
+
if (searchRuntime !== false && searchRuntime.engine !== "cms" && usesFilesystemProvider) {
|
|
1246
|
+
nitroConfig.routeRules = nitroConfig.routeRules || {};
|
|
1247
|
+
nitroConfig.routeRules[searchRuntime.indexURL] = {
|
|
1248
|
+
prerender: true,
|
|
1249
|
+
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
if (contentContext.sitemap !== false) {
|
|
1253
|
+
nitroConfig.plugins ||= [];
|
|
1254
|
+
const sitemapPlugin = resolveRuntimeModule("server/plugins/sitemap.js");
|
|
1255
|
+
if (!nitroConfig.plugins.includes(sitemapPlugin)) {
|
|
1256
|
+
nitroConfig.plugins.push(sitemapPlugin);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (contentContext.cache && contentContext.cache !== false) {
|
|
1260
|
+
nitroConfig.plugins ||= [];
|
|
1261
|
+
const cachePlugin = resolveRuntimeModule("server/plugins/cache.js");
|
|
1262
|
+
if (!nitroConfig.plugins.includes(cachePlugin)) {
|
|
1263
|
+
nitroConfig.plugins.push(cachePlugin);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
registerContentNitroIntegrationHooks(nitroConfig, {
|
|
1267
|
+
rootDir: nuxt.options.rootDir,
|
|
1268
|
+
sitemapPrerenderRoutes: contentContext.sitemap === false ? [] : resolveNuxtSitemapPrerenderRoutes(nuxt)
|
|
1269
|
+
}, {
|
|
1270
|
+
collections: contentContext.collections,
|
|
1271
|
+
locales: contentContext.locales,
|
|
1272
|
+
defaultLocale: contentContext.defaultLocale,
|
|
1273
|
+
translatedSlugs: contentContext.translatedSlugs,
|
|
1274
|
+
strictTranslatedSlugs: contentContext.strictTranslatedSlugs,
|
|
1275
|
+
respectPathCase: contentContext.respectPathCase,
|
|
1276
|
+
markdown: contentContext.markdown,
|
|
1277
|
+
yaml: contentContext.yaml,
|
|
1278
|
+
csv: contentContext.csv,
|
|
1279
|
+
sitemap: contentContext.sitemap,
|
|
1280
|
+
provider: contentContext.provider
|
|
1281
|
+
});
|
|
1282
|
+
});
|
|
1283
|
+
if (!nuxt.options.dev) {
|
|
1284
|
+
nuxt.hook("nitro:build:before", (nitro) => {
|
|
1285
|
+
nitro.hooks.hook("prerender:init", (prerenderer) => {
|
|
1286
|
+
prerenderer.hooks.hook("compiled", async () => {
|
|
1287
|
+
const searchRuntime = getSearchRuntime();
|
|
1288
|
+
if (searchRuntime === false || searchRuntime.engine === "cms" || contentContext.provider && contentContext.provider !== "filesystem") {
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
const publicDir = nitro.options.output.publicDir || nuxt.options.nitro.output?.publicDir || resolve$1(nuxt.options.rootDir, ".output/public");
|
|
1292
|
+
const serverFilename = typeof prerenderer.options.rollupConfig?.output?.entryFileNames === "string" ? prerenderer.options.rollupConfig.output.entryFileNames : "index.mjs";
|
|
1293
|
+
const serverEntrypoint = resolve$1(prerenderer.options.output.serverDir, serverFilename);
|
|
1294
|
+
const { localFetch } = await import(pathToFileURL(serverEntrypoint).href);
|
|
1295
|
+
const response = await localFetch(searchRuntime.indexURL);
|
|
1296
|
+
if (!response.ok) {
|
|
1297
|
+
throw new Error(`Failed to generate search index: [${response.status}] ${response.statusText}`);
|
|
1298
|
+
}
|
|
1299
|
+
const json = await response.text();
|
|
1300
|
+
const indexPath = join(publicDir, searchRuntime.indexURL.replace(/^\//, ""));
|
|
1301
|
+
mkdirSync(dirname(indexPath), { recursive: true });
|
|
1302
|
+
writeFileSync(indexPath, json, "utf8");
|
|
1303
|
+
if (searchRuntime.engine === "pagefind") {
|
|
1304
|
+
const records = JSON.parse(json);
|
|
1305
|
+
const { writePagefindIndex } = await import(resolveRuntimeModule("./server/pagefind.js"));
|
|
1306
|
+
await writePagefindIndex(records, resolve$1(publicDir, "pagefind"));
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1309
|
+
});
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
nuxt.hook("modules:done", async () => {
|
|
1313
|
+
await nuxt.callHook("content:context", contentContext);
|
|
1314
|
+
if (contentContext.search !== false) {
|
|
1315
|
+
registerContentSearchServerHandlers(options.api.baseURL, contentContext.search, resolveRuntimeModule);
|
|
1316
|
+
}
|
|
1317
|
+
contentContext.defaultLocale = contentContext.defaultLocale || contentContext.locales[0];
|
|
1318
|
+
contentContext.markdown = processMarkdownOptions(contentContext.markdown);
|
|
1319
|
+
await validateBuiltinMarkdownPlugins(contentContext.markdown.plugins, resolvePath);
|
|
1320
|
+
const runtimeCollections = Object.fromEntries(Object.entries(options.collections || {}).map(([name2, collection]) => [
|
|
1321
|
+
name2,
|
|
1322
|
+
{
|
|
1323
|
+
...collection.source ? { source: collection.source } : {},
|
|
1324
|
+
...collection.exclude ? { exclude: collection.exclude } : {},
|
|
1325
|
+
strict: collection.strict ?? true,
|
|
1326
|
+
...collection.route ? { route: collection.route } : {},
|
|
1327
|
+
...typeof collection.sitemap === "boolean" ? { sitemap: collection.sitemap } : {},
|
|
1328
|
+
...collection.i18n && collection.i18n !== true ? { i18n: collection.i18n } : {}
|
|
1329
|
+
}
|
|
1330
|
+
]));
|
|
1331
|
+
const cacheIntegrity = hash({
|
|
1332
|
+
locales: contentContext.locales,
|
|
1333
|
+
defaultLocale: contentContext.defaultLocale,
|
|
1334
|
+
localeFallback: contentContext.localeFallback,
|
|
1335
|
+
translatedSlugs: contentContext.translatedSlugs,
|
|
1336
|
+
strictTranslatedSlugs: contentContext.strictTranslatedSlugs,
|
|
1337
|
+
respectPathCase: contentContext.respectPathCase,
|
|
1338
|
+
collections: runtimeCollections,
|
|
1339
|
+
markdown: contentContext.markdown,
|
|
1340
|
+
yaml: contentContext.yaml,
|
|
1341
|
+
csv: contentContext.csv
|
|
1342
|
+
});
|
|
1343
|
+
applyContentRuntimeConfig(nuxt, options, contentContext, runtimeCollections, buildIntegrity, cacheIntegrity);
|
|
1344
|
+
});
|
|
1345
|
+
if (nuxt.options.dev) {
|
|
1346
|
+
registerDevRuntimePlugin(resolveRuntimeModule);
|
|
1347
|
+
registerContentDevRuntime(nuxt, options, contentContext);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
function validateRemovedMarkdownOptions(options) {
|
|
1352
|
+
if (options.highlight !== void 0) {
|
|
1353
|
+
throw new Error("`content.highlight` was removed. Enable syntax highlighting with `content.markdown.plugins`, for example `[['highlight', { ...options }]]`.");
|
|
1354
|
+
}
|
|
1355
|
+
const markdown = options.markdown || {};
|
|
1356
|
+
const removedOptions = ["mdc", "remarkPlugins", "rehypePlugins", "toc"];
|
|
1357
|
+
const removed = removedOptions.filter((key) => typeof markdown[key] !== "undefined");
|
|
1358
|
+
if (removed.length) {
|
|
1359
|
+
throw new Error(`Removed markdown options: ${removed.map((option) => `content.markdown.${String(option)}`).join(", ")}. Use ordered \`content.markdown.plugins\` entries instead.`);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
async function validateBuiltinMarkdownPlugins(plugins, resolvePath) {
|
|
1363
|
+
for (const plugin of plugins) {
|
|
1364
|
+
const peerDependency = BUILTIN_PLUGIN_PEER_DEPS[plugin.name];
|
|
1365
|
+
if (!peerDependency) {
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
try {
|
|
1369
|
+
await resolvePath(peerDependency);
|
|
1370
|
+
} catch (error) {
|
|
1371
|
+
throw new Error(`Markdown plugin "${plugin.name}" requires "${peerDependency}" to be installed.`, { cause: error });
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
const BUILTIN_PLUGIN_PEER_DEPS = {
|
|
1376
|
+
highlight: "shiki",
|
|
1377
|
+
math: "katex",
|
|
1378
|
+
mermaid: "beautiful-mermaid"
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1381
|
+
export { module$1 as default };
|