@ztl-uwu/nuxt-content 2.13.5
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 +64 -0
- package/dist/module.d.mts +1176 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +696 -0
- package/dist/runtime/app.vue +3 -0
- package/dist/runtime/app.vue.d.ts +2 -0
- package/dist/runtime/components/ContentDoc.vue +108 -0
- package/dist/runtime/components/ContentDoc.vue.d.ts +118 -0
- package/dist/runtime/components/ContentList.vue +59 -0
- package/dist/runtime/components/ContentList.vue.d.ts +59 -0
- package/dist/runtime/components/ContentNavigation.vue +61 -0
- package/dist/runtime/components/ContentNavigation.vue.d.ts +35 -0
- package/dist/runtime/components/ContentQuery.vue +212 -0
- package/dist/runtime/components/ContentQuery.vue.d.ts +0 -0
- package/dist/runtime/components/ContentRenderer.vue +78 -0
- package/dist/runtime/components/ContentRenderer.vue.d.ts +56 -0
- package/dist/runtime/components/ContentRendererMarkdown.vue +69 -0
- package/dist/runtime/components/ContentRendererMarkdown.vue.d.ts +73 -0
- package/dist/runtime/components/ContentSlot.vue +25 -0
- package/dist/runtime/components/ContentSlot.vue.d.ts +37 -0
- package/dist/runtime/components/DocumentDrivenEmpty.vue +18 -0
- package/dist/runtime/components/DocumentDrivenEmpty.vue.d.ts +17 -0
- package/dist/runtime/components/DocumentDrivenNotFound.vue +9 -0
- package/dist/runtime/components/DocumentDrivenNotFound.vue.d.ts +5 -0
- package/dist/runtime/components/Markdown.vue +29 -0
- package/dist/runtime/components/Markdown.vue.d.ts +31 -0
- package/dist/runtime/components/Prose/ProseCode.vue +32 -0
- package/dist/runtime/components/Prose/ProseCode.vue.d.ts +110 -0
- package/dist/runtime/components/Prose/ProseCodeInline.vue +3 -0
- package/dist/runtime/components/Prose/ProseCodeInline.vue.d.ts +14 -0
- package/dist/runtime/components/Prose/ProsePre.vue +42 -0
- package/dist/runtime/components/Prose/ProsePre.vue.d.ts +146 -0
- package/dist/runtime/composables/client-db.d.ts +14 -0
- package/dist/runtime/composables/client-db.js +105 -0
- package/dist/runtime/composables/content.d.ts +19 -0
- package/dist/runtime/composables/content.js +41 -0
- package/dist/runtime/composables/head.d.ts +4 -0
- package/dist/runtime/composables/head.js +94 -0
- package/dist/runtime/composables/helpers.d.ts +7 -0
- package/dist/runtime/composables/helpers.js +66 -0
- package/dist/runtime/composables/navigation.d.ts +2 -0
- package/dist/runtime/composables/navigation.js +34 -0
- package/dist/runtime/composables/preview.d.ts +5 -0
- package/dist/runtime/composables/preview.js +41 -0
- package/dist/runtime/composables/query.d.ts +10 -0
- package/dist/runtime/composables/query.js +64 -0
- package/dist/runtime/composables/search.d.ts +130 -0
- package/dist/runtime/composables/search.js +59 -0
- package/dist/runtime/composables/useUnwrap.d.ts +5 -0
- package/dist/runtime/composables/useUnwrap.js +5 -0
- package/dist/runtime/composables/utils.d.ts +6 -0
- package/dist/runtime/composables/utils.js +36 -0
- package/dist/runtime/composables/web-socket.d.ts +3 -0
- package/dist/runtime/composables/web-socket.js +65 -0
- package/dist/runtime/legacy/composables/client-db.d.ts +12 -0
- package/dist/runtime/legacy/composables/client-db.js +105 -0
- package/dist/runtime/legacy/composables/navigation.d.ts +2 -0
- package/dist/runtime/legacy/composables/navigation.js +34 -0
- package/dist/runtime/legacy/composables/query.d.ts +10 -0
- package/dist/runtime/legacy/composables/query.js +61 -0
- package/dist/runtime/legacy/plugins/documentDriven.d.ts +2 -0
- package/dist/runtime/legacy/plugins/documentDriven.js +231 -0
- package/dist/runtime/legacy/server.d.ts +3 -0
- package/dist/runtime/legacy/server.js +3 -0
- package/dist/runtime/legacy/types.d.ts +5 -0
- package/dist/runtime/pages/document-driven.vue +27 -0
- package/dist/runtime/pages/document-driven.vue.d.ts +2 -0
- package/dist/runtime/plugins/documentDriven.d.ts +2 -0
- package/dist/runtime/plugins/documentDriven.js +222 -0
- package/dist/runtime/plugins/ws.d.ts +2 -0
- package/dist/runtime/plugins/ws.js +7 -0
- package/dist/runtime/query/match/index.d.ts +6 -0
- package/dist/runtime/query/match/index.js +123 -0
- package/dist/runtime/query/match/pipeline-legacy.d.ts +2 -0
- package/dist/runtime/query/match/pipeline-legacy.js +22 -0
- package/dist/runtime/query/match/pipeline.d.ts +2 -0
- package/dist/runtime/query/match/pipeline.js +104 -0
- package/dist/runtime/query/match/utils.d.ts +35 -0
- package/dist/runtime/query/match/utils.js +65 -0
- package/dist/runtime/query/query.d.ts +12 -0
- package/dist/runtime/query/query.js +61 -0
- package/dist/runtime/server/api/cache.d.ts +7 -0
- package/dist/runtime/server/api/cache.js +18 -0
- package/dist/runtime/server/api/navigation-qid-params.d.ts +1 -0
- package/dist/runtime/server/api/navigation-qid-params.js +1 -0
- package/dist/runtime/server/api/navigation-qid.d.ts +1 -0
- package/dist/runtime/server/api/navigation-qid.js +1 -0
- package/dist/runtime/server/api/navigation.d.ts +2 -0
- package/dist/runtime/server/api/navigation.js +42 -0
- package/dist/runtime/server/api/query-qid-params.d.ts +1 -0
- package/dist/runtime/server/api/query-qid-params.js +1 -0
- package/dist/runtime/server/api/query-qid.d.ts +1 -0
- package/dist/runtime/server/api/query-qid.js +1 -0
- package/dist/runtime/server/api/query.d.ts +2 -0
- package/dist/runtime/server/api/query.js +32 -0
- package/dist/runtime/server/api/search.d.ts +8 -0
- package/dist/runtime/server/api/search.js +16 -0
- package/dist/runtime/server/content-index.d.ts +4 -0
- package/dist/runtime/server/content-index.js +37 -0
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +1 -0
- package/dist/runtime/server/navigation.d.ts +5 -0
- package/dist/runtime/server/navigation.js +96 -0
- package/dist/runtime/server/plugins/refresh-cache.d.ts +2 -0
- package/dist/runtime/server/plugins/refresh-cache.js +15 -0
- package/dist/runtime/server/preview.d.ts +5 -0
- package/dist/runtime/server/preview.js +9 -0
- package/dist/runtime/server/search.d.ts +14 -0
- package/dist/runtime/server/search.js +70 -0
- package/dist/runtime/server/storage.d.ts +35 -0
- package/dist/runtime/server/storage.js +238 -0
- package/dist/runtime/transformers/component-resolver.d.ts +2 -0
- package/dist/runtime/transformers/component-resolver.js +44 -0
- package/dist/runtime/transformers/csv/create-tokenizer.d.ts +39 -0
- package/dist/runtime/transformers/csv/create-tokenizer.js +307 -0
- package/dist/runtime/transformers/csv/from-csv.d.ts +13 -0
- package/dist/runtime/transformers/csv/from-csv.js +203 -0
- package/dist/runtime/transformers/csv/index.d.ts +2 -0
- package/dist/runtime/transformers/csv/index.js +50 -0
- package/dist/runtime/transformers/csv/parser.d.ts +24 -0
- package/dist/runtime/transformers/csv/parser.js +154 -0
- package/dist/runtime/transformers/index.d.ts +7 -0
- package/dist/runtime/transformers/index.js +50 -0
- package/dist/runtime/transformers/json.d.ts +2 -0
- package/dist/runtime/transformers/json.js +29 -0
- package/dist/runtime/transformers/markdown.d.ts +2 -0
- package/dist/runtime/transformers/markdown.js +88 -0
- package/dist/runtime/transformers/path-meta.d.ts +27 -0
- package/dist/runtime/transformers/path-meta.js +59 -0
- package/dist/runtime/transformers/utils.d.ts +3 -0
- package/dist/runtime/transformers/utils.js +12 -0
- package/dist/runtime/transformers/yaml.d.ts +2 -0
- package/dist/runtime/transformers/yaml.js +21 -0
- package/dist/runtime/utils/config.d.ts +4 -0
- package/dist/runtime/utils/config.js +7 -0
- package/dist/runtime/utils/html-tags.d.ts +2 -0
- package/dist/runtime/utils/html-tags.js +119 -0
- package/dist/runtime/utils/json.d.ts +10 -0
- package/dist/runtime/utils/json.js +20 -0
- package/dist/runtime/utils/query.d.ts +5 -0
- package/dist/runtime/utils/query.js +77 -0
- package/dist/runtime/virtual/transformers.d.ts +2 -0
- package/dist/types.d.mts +9 -0
- package/dist/web-types.json +572 -0
- package/package.json +111 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
declare const __VLS_ctx: InstanceType<__VLS_PickNotAny<typeof __VLS_self, new () => {}>>;
|
|
2
|
+
declare var __VLS_6: {};
|
|
3
|
+
type __VLS_Slots = __VLS_PrettifyGlobal<__VLS_OmitStringIndex<typeof __VLS_ctx.$slots> & {
|
|
4
|
+
default?: (props: typeof __VLS_6) => any;
|
|
5
|
+
}>;
|
|
6
|
+
declare const __VLS_self: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
7
|
+
code: {
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
default: string;
|
|
10
|
+
};
|
|
11
|
+
language: {
|
|
12
|
+
type: StringConstructor;
|
|
13
|
+
default: null;
|
|
14
|
+
};
|
|
15
|
+
filename: {
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
default: null;
|
|
18
|
+
};
|
|
19
|
+
highlights: {
|
|
20
|
+
type: () => number[];
|
|
21
|
+
default: () => never[];
|
|
22
|
+
};
|
|
23
|
+
meta: {
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
default: null;
|
|
26
|
+
};
|
|
27
|
+
class: {
|
|
28
|
+
type: StringConstructor;
|
|
29
|
+
default: null;
|
|
30
|
+
};
|
|
31
|
+
style: {
|
|
32
|
+
type: (ObjectConstructor | StringConstructor)[];
|
|
33
|
+
default: null;
|
|
34
|
+
};
|
|
35
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
36
|
+
code: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: string;
|
|
39
|
+
};
|
|
40
|
+
language: {
|
|
41
|
+
type: StringConstructor;
|
|
42
|
+
default: null;
|
|
43
|
+
};
|
|
44
|
+
filename: {
|
|
45
|
+
type: StringConstructor;
|
|
46
|
+
default: null;
|
|
47
|
+
};
|
|
48
|
+
highlights: {
|
|
49
|
+
type: () => number[];
|
|
50
|
+
default: () => never[];
|
|
51
|
+
};
|
|
52
|
+
meta: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: null;
|
|
55
|
+
};
|
|
56
|
+
class: {
|
|
57
|
+
type: StringConstructor;
|
|
58
|
+
default: null;
|
|
59
|
+
};
|
|
60
|
+
style: {
|
|
61
|
+
type: (ObjectConstructor | StringConstructor)[];
|
|
62
|
+
default: null;
|
|
63
|
+
};
|
|
64
|
+
}>> & Readonly<{}>, {
|
|
65
|
+
meta: string;
|
|
66
|
+
style: string | Record<string, any>;
|
|
67
|
+
class: string;
|
|
68
|
+
code: string;
|
|
69
|
+
language: string;
|
|
70
|
+
filename: string;
|
|
71
|
+
highlights: number[];
|
|
72
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
73
|
+
declare const __VLS_component: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
74
|
+
code: {
|
|
75
|
+
type: StringConstructor;
|
|
76
|
+
default: string;
|
|
77
|
+
};
|
|
78
|
+
language: {
|
|
79
|
+
type: StringConstructor;
|
|
80
|
+
default: null;
|
|
81
|
+
};
|
|
82
|
+
filename: {
|
|
83
|
+
type: StringConstructor;
|
|
84
|
+
default: null;
|
|
85
|
+
};
|
|
86
|
+
highlights: {
|
|
87
|
+
type: () => number[];
|
|
88
|
+
default: () => never[];
|
|
89
|
+
};
|
|
90
|
+
meta: {
|
|
91
|
+
type: StringConstructor;
|
|
92
|
+
default: null;
|
|
93
|
+
};
|
|
94
|
+
class: {
|
|
95
|
+
type: StringConstructor;
|
|
96
|
+
default: null;
|
|
97
|
+
};
|
|
98
|
+
style: {
|
|
99
|
+
type: (ObjectConstructor | StringConstructor)[];
|
|
100
|
+
default: null;
|
|
101
|
+
};
|
|
102
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
103
|
+
code: {
|
|
104
|
+
type: StringConstructor;
|
|
105
|
+
default: string;
|
|
106
|
+
};
|
|
107
|
+
language: {
|
|
108
|
+
type: StringConstructor;
|
|
109
|
+
default: null;
|
|
110
|
+
};
|
|
111
|
+
filename: {
|
|
112
|
+
type: StringConstructor;
|
|
113
|
+
default: null;
|
|
114
|
+
};
|
|
115
|
+
highlights: {
|
|
116
|
+
type: () => number[];
|
|
117
|
+
default: () => never[];
|
|
118
|
+
};
|
|
119
|
+
meta: {
|
|
120
|
+
type: StringConstructor;
|
|
121
|
+
default: null;
|
|
122
|
+
};
|
|
123
|
+
class: {
|
|
124
|
+
type: StringConstructor;
|
|
125
|
+
default: null;
|
|
126
|
+
};
|
|
127
|
+
style: {
|
|
128
|
+
type: (ObjectConstructor | StringConstructor)[];
|
|
129
|
+
default: null;
|
|
130
|
+
};
|
|
131
|
+
}>> & Readonly<{}>, {
|
|
132
|
+
meta: string;
|
|
133
|
+
style: string | Record<string, any>;
|
|
134
|
+
class: string;
|
|
135
|
+
code: string;
|
|
136
|
+
language: string;
|
|
137
|
+
filename: string;
|
|
138
|
+
highlights: number[];
|
|
139
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
140
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
141
|
+
export default _default;
|
|
142
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
143
|
+
new (): {
|
|
144
|
+
$slots: S;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Storage, type StorageValue } from 'unstorage';
|
|
2
|
+
import type { NavItem, ContentQueryBuilderParams } from '@nuxt/content';
|
|
3
|
+
export declare const contentStorage: Storage<StorageValue>;
|
|
4
|
+
export declare function createDB(storage: Storage): {
|
|
5
|
+
storage: Storage<StorageValue>;
|
|
6
|
+
fetch: (query: NavItem<unknown>) => Promise<NavItem<unknown>>;
|
|
7
|
+
query: (initialParams?: ContentQueryBuilderParams) => ContentQueryBuilder<T>;
|
|
8
|
+
};
|
|
9
|
+
export declare function useContentDatabase(): Promise<{
|
|
10
|
+
storage: Storage<StorageValue>;
|
|
11
|
+
fetch: (query: NavItem<unknown>) => Promise<NavItem<unknown>>;
|
|
12
|
+
query: (initialParams?: ContentQueryBuilderParams) => ContentQueryBuilder<T>;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function generateNavigation(query?: ContentQueryBuilderParams): Promise<Array<NavItem>>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import memoryDriver from "unstorage/drivers/memory";
|
|
2
|
+
import { createStorage, prefixStorage } from "unstorage";
|
|
3
|
+
import { withBase } from "ufo";
|
|
4
|
+
import { createQuery } from "../query/query.js";
|
|
5
|
+
import { createNav } from "../server/navigation.js";
|
|
6
|
+
import { createPipelineFetcher } from "../query/match/pipeline.js";
|
|
7
|
+
import { useContentPreview } from "./preview.js";
|
|
8
|
+
import { useRuntimeConfig, useNuxtApp } from "#imports";
|
|
9
|
+
const withContentBase = (url) => withBase(url, useRuntimeConfig().public.content.api.baseURL);
|
|
10
|
+
export const contentStorage = prefixStorage(createStorage({ driver: memoryDriver() }), "@content");
|
|
11
|
+
export function createDB(storage) {
|
|
12
|
+
async function getItems() {
|
|
13
|
+
const keys = new Set(await storage.getKeys("cache:"));
|
|
14
|
+
const previewToken = useContentPreview().getPreviewToken();
|
|
15
|
+
if (previewToken) {
|
|
16
|
+
const previewMeta = await storage.getItem(`${previewToken}$`).then((data) => data || {});
|
|
17
|
+
if (Array.isArray(previewMeta.ignoreSources)) {
|
|
18
|
+
const sources = previewMeta.ignoreSources.map((s) => `cache:${s.trim()}:`);
|
|
19
|
+
for (const key of keys) {
|
|
20
|
+
if (sources.some((s) => key.startsWith(s))) {
|
|
21
|
+
keys.delete(key);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const previewKeys = await storage.getKeys(`${previewToken}:`);
|
|
26
|
+
const previewContents = await Promise.all(previewKeys.map((key) => storage.getItem(key)));
|
|
27
|
+
for (const pItem of previewContents) {
|
|
28
|
+
keys.delete(`cache:${pItem._id}`);
|
|
29
|
+
if (!pItem.__deleted) {
|
|
30
|
+
keys.add(`${previewToken}:${pItem._id}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const items = await Promise.all(Array.from(keys).map((key) => storage.getItem(key)));
|
|
35
|
+
return items;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
storage,
|
|
39
|
+
fetch: createPipelineFetcher(getItems),
|
|
40
|
+
query: (initialParams) => createQuery(
|
|
41
|
+
createPipelineFetcher(getItems),
|
|
42
|
+
{ initialParams, legacy: false }
|
|
43
|
+
)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
let contentDatabase = null;
|
|
47
|
+
let contentDatabaseInitPromise = null;
|
|
48
|
+
export async function useContentDatabase() {
|
|
49
|
+
if (contentDatabaseInitPromise) {
|
|
50
|
+
await contentDatabaseInitPromise;
|
|
51
|
+
} else if (!contentDatabase) {
|
|
52
|
+
contentDatabaseInitPromise = initContentDatabase();
|
|
53
|
+
contentDatabase = await contentDatabaseInitPromise;
|
|
54
|
+
}
|
|
55
|
+
return contentDatabase;
|
|
56
|
+
}
|
|
57
|
+
async function initContentDatabase() {
|
|
58
|
+
const nuxtApp = useNuxtApp();
|
|
59
|
+
const { content } = useRuntimeConfig().public;
|
|
60
|
+
const _contentDatabase = createDB(contentStorage);
|
|
61
|
+
const integrity = await _contentDatabase.storage.getItem("integrity");
|
|
62
|
+
if (content.integrity !== +(integrity || 0)) {
|
|
63
|
+
const { contents, navigation } = await $fetch(withContentBase(content.integrity ? `cache.${content.integrity}.json` : "cache.json"));
|
|
64
|
+
await Promise.all(
|
|
65
|
+
contents.map((content2) => _contentDatabase.storage.setItem(`cache:${content2._id}`, content2))
|
|
66
|
+
);
|
|
67
|
+
await _contentDatabase.storage.setItem("navigation", navigation);
|
|
68
|
+
await _contentDatabase.storage.setItem("integrity", content.integrity);
|
|
69
|
+
}
|
|
70
|
+
await nuxtApp.callHook("content:storage", _contentDatabase.storage);
|
|
71
|
+
return _contentDatabase;
|
|
72
|
+
}
|
|
73
|
+
export async function generateNavigation(query) {
|
|
74
|
+
const db = await useContentDatabase();
|
|
75
|
+
if (!useContentPreview().getPreviewToken() && Object.keys(query || {}).length === 0) {
|
|
76
|
+
return db.storage.getItem("navigation");
|
|
77
|
+
}
|
|
78
|
+
const contents = await db.query(query).where({
|
|
79
|
+
/**
|
|
80
|
+
* Partial contents are not included in the navigation
|
|
81
|
+
* A partial content is a content that has `_` prefix in its path
|
|
82
|
+
*/
|
|
83
|
+
_partial: false,
|
|
84
|
+
/**
|
|
85
|
+
* Exclude any pages which have opted out of navigation via frontmatter.
|
|
86
|
+
*/
|
|
87
|
+
navigation: {
|
|
88
|
+
$ne: false
|
|
89
|
+
}
|
|
90
|
+
}).find();
|
|
91
|
+
const dirConfigs = await db.query().where({ _path: /\/_dir$/i, _partial: true }).find();
|
|
92
|
+
const configs = dirConfigs.result.reduce((configs2, conf) => {
|
|
93
|
+
if (conf.title?.toLowerCase() === "dir") {
|
|
94
|
+
conf.title = void 0;
|
|
95
|
+
}
|
|
96
|
+
const key = conf._path.split("/").slice(0, -1).join("/") || "/";
|
|
97
|
+
configs2[key] = {
|
|
98
|
+
...conf,
|
|
99
|
+
// Extract meta from body. (non MD files)
|
|
100
|
+
...conf.body
|
|
101
|
+
};
|
|
102
|
+
return configs2;
|
|
103
|
+
}, {});
|
|
104
|
+
return createNav(contents?.result || contents, configs);
|
|
105
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ParsedContent } from '@nuxt/content';
|
|
2
|
+
export declare const useContentState: <G extends object = Record<string, unknown>>() => {
|
|
3
|
+
pages: import("vue").Ref<Record<string, ParsedContent>, Record<string, ParsedContent>>;
|
|
4
|
+
surrounds: import("vue").Ref<Record<string, [Omit<ParsedContent, "body"> | null, Omit<ParsedContent, "body"> | null]>, Record<string, [Omit<ParsedContent, "body"> | null, Omit<ParsedContent, "body"> | null]>>;
|
|
5
|
+
navigation: import("vue").Ref<NavItem[], NavItem[]>;
|
|
6
|
+
globals: import("vue").Ref<Record<string, G>, Record<string, G>>;
|
|
7
|
+
};
|
|
8
|
+
export declare const useContent: <T extends ParsedContent, G extends object = Record<string, unknown>>() => {
|
|
9
|
+
globals: import("vue").Ref<Record<string, G>, Record<string, G>>;
|
|
10
|
+
navigation: import("vue").Ref<NavItem[], NavItem[]>;
|
|
11
|
+
surround: import("vue").ComputedRef<[Omit<ParsedContent, "body"> | null, Omit<ParsedContent, "body"> | null] | undefined>;
|
|
12
|
+
page: import("vue").ComputedRef<T>;
|
|
13
|
+
excerpt: import("vue").ComputedRef<any>;
|
|
14
|
+
toc: import("vue").ComputedRef<any>;
|
|
15
|
+
type: import("vue").ComputedRef<any>;
|
|
16
|
+
layout: import("vue").ComputedRef<any>;
|
|
17
|
+
next: import("vue").ComputedRef<Omit<ParsedContent, "body"> | null | undefined>;
|
|
18
|
+
prev: import("vue").ComputedRef<Omit<ParsedContent, "body"> | null | undefined>;
|
|
19
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { withoutTrailingSlash } from "ufo";
|
|
2
|
+
import { computed, shallowReactive, shallowRef, useState, useRoute } from "#imports";
|
|
3
|
+
export const useContentState = () => {
|
|
4
|
+
const pages = useState("dd-pages", () => shallowRef(shallowReactive({})));
|
|
5
|
+
const surrounds = useState("dd-surrounds", () => shallowRef(shallowReactive({})));
|
|
6
|
+
const navigation = useState("dd-navigation");
|
|
7
|
+
const globals = useState("dd-globals", () => shallowRef(shallowReactive({})));
|
|
8
|
+
return {
|
|
9
|
+
pages,
|
|
10
|
+
surrounds,
|
|
11
|
+
navigation,
|
|
12
|
+
globals
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export const useContent = () => {
|
|
16
|
+
const { navigation, pages, surrounds, globals } = useContentState();
|
|
17
|
+
const _path = computed(() => withoutTrailingSlash(useRoute().path));
|
|
18
|
+
const page = computed(() => pages.value[_path.value]);
|
|
19
|
+
const surround = computed(() => surrounds.value[_path.value]);
|
|
20
|
+
const toc = computed(() => page?.value?.body?.toc);
|
|
21
|
+
const type = computed(() => page.value?._type);
|
|
22
|
+
const excerpt = computed(() => page.value?.excerpt);
|
|
23
|
+
const layout = computed(() => page.value?.layout);
|
|
24
|
+
const next = computed(() => surround.value?.[1]);
|
|
25
|
+
const prev = computed(() => surround.value?.[0]);
|
|
26
|
+
return {
|
|
27
|
+
// Refs
|
|
28
|
+
globals,
|
|
29
|
+
navigation,
|
|
30
|
+
surround,
|
|
31
|
+
page,
|
|
32
|
+
// From page
|
|
33
|
+
excerpt,
|
|
34
|
+
toc,
|
|
35
|
+
type,
|
|
36
|
+
layout,
|
|
37
|
+
// From surround
|
|
38
|
+
next,
|
|
39
|
+
prev
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded } from 'vue-router';
|
|
2
|
+
import type { Ref } from 'vue';
|
|
3
|
+
import type { ParsedContent } from '@nuxt/content';
|
|
4
|
+
export declare const useContentHead: (_content: ParsedContent | Ref<ParsedContent>, to?: RouteLocationNormalized | RouteLocationNormalizedLoaded) => void;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { hasProtocol, joinURL, withTrailingSlash, withoutTrailingSlash } from "ufo";
|
|
2
|
+
import { useRoute, nextTick, useHead, unref, watch, useRuntimeConfig } from "#imports";
|
|
3
|
+
export const useContentHead = (_content, to = useRoute()) => {
|
|
4
|
+
const content = unref(_content);
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const refreshHead = (data = content) => {
|
|
7
|
+
if (!to.path || !data) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const head = Object.assign({}, data?.head || {});
|
|
11
|
+
head.meta = [...head.meta || []];
|
|
12
|
+
head.link = [...head.link || []];
|
|
13
|
+
const title = head.title || data?.title;
|
|
14
|
+
if (title) {
|
|
15
|
+
head.title = title;
|
|
16
|
+
if (import.meta.server && !head.meta.some((m) => m.property === "og:title")) {
|
|
17
|
+
head.meta.push({
|
|
18
|
+
property: "og:title",
|
|
19
|
+
content: title
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const host = config.public.content.host;
|
|
24
|
+
if (import.meta.server && host) {
|
|
25
|
+
const _url = joinURL(host ?? "/", config.app.baseURL, to.fullPath);
|
|
26
|
+
const url = config.public.content.trailingSlash ? withTrailingSlash(_url) : withoutTrailingSlash(_url);
|
|
27
|
+
if (!head.meta.some((m) => m.property === "og:url")) {
|
|
28
|
+
head.meta.push({
|
|
29
|
+
property: "og:url",
|
|
30
|
+
content: url
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (!head.link.some((m) => m.rel === "canonical")) {
|
|
34
|
+
head.link.push({
|
|
35
|
+
rel: "canonical",
|
|
36
|
+
href: url
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const description = head?.description || data?.description;
|
|
41
|
+
if (description && head.meta.filter((m) => m.name === "description").length === 0) {
|
|
42
|
+
head.meta.push({
|
|
43
|
+
name: "description",
|
|
44
|
+
content: description
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (import.meta.server && description && !head.meta.some((m) => m.property === "og:description")) {
|
|
48
|
+
head.meta.push({
|
|
49
|
+
property: "og:description",
|
|
50
|
+
content: description
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const image = head?.image || data?.image;
|
|
54
|
+
if (import.meta.server && image && head.meta.filter((m) => m.property === "og:image").length === 0) {
|
|
55
|
+
if (typeof image === "string") {
|
|
56
|
+
head.meta.push({
|
|
57
|
+
property: "og:image",
|
|
58
|
+
content: host && !hasProtocol(image) ? new URL(joinURL(config.app.baseURL, image), host).href : image
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (typeof image === "object") {
|
|
62
|
+
const imageKeys = [
|
|
63
|
+
"src",
|
|
64
|
+
"secure_url",
|
|
65
|
+
"type",
|
|
66
|
+
"width",
|
|
67
|
+
"height",
|
|
68
|
+
"alt"
|
|
69
|
+
];
|
|
70
|
+
for (const key of imageKeys) {
|
|
71
|
+
if (key === "src" && image.src) {
|
|
72
|
+
const isAbsoluteURL = hasProtocol(image.src);
|
|
73
|
+
const imageURL = isAbsoluteURL ? image.src : joinURL(config.app.baseURL, image.src ?? "/");
|
|
74
|
+
head.meta.push({
|
|
75
|
+
property: "og:image",
|
|
76
|
+
content: host && !isAbsoluteURL ? new URL(imageURL, host).href : imageURL
|
|
77
|
+
});
|
|
78
|
+
} else if (image[key]) {
|
|
79
|
+
head.meta.push({
|
|
80
|
+
property: `og:image:${key}`,
|
|
81
|
+
content: image[key]
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (import.meta.client) {
|
|
88
|
+
nextTick(() => useHead(head));
|
|
89
|
+
} else {
|
|
90
|
+
useHead(head);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
watch(() => unref(_content), refreshHead, { immediate: true });
|
|
94
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NavItem } from '@nuxt/content';
|
|
2
|
+
export declare const useContentHelpers: () => {
|
|
3
|
+
navBottomLink: (link: NavItem) => string | undefined;
|
|
4
|
+
navDirFromPath: (path: string, tree: NavItem[]) => NavItem[] | undefined;
|
|
5
|
+
navPageFromPath: (path: string, tree: NavItem[]) => NavItem | undefined;
|
|
6
|
+
navKeyFromPath: (path: string, key: string, tree: NavItem[]) => any;
|
|
7
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const navBottomLink = (link) => {
|
|
2
|
+
if (!link.children) {
|
|
3
|
+
return link._path;
|
|
4
|
+
}
|
|
5
|
+
for (const child of link?.children || []) {
|
|
6
|
+
const result = navBottomLink(child);
|
|
7
|
+
if (result) {
|
|
8
|
+
return result;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
const navDirFromPath = (path, tree) => {
|
|
13
|
+
for (const file of tree) {
|
|
14
|
+
if (file._path === path && !file._id) {
|
|
15
|
+
return file.children;
|
|
16
|
+
}
|
|
17
|
+
if (file.children) {
|
|
18
|
+
const result = navDirFromPath(path, file.children);
|
|
19
|
+
if (result) {
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const navPageFromPath = (path, tree) => {
|
|
26
|
+
for (const file of tree) {
|
|
27
|
+
if (file._path === path) {
|
|
28
|
+
return file;
|
|
29
|
+
}
|
|
30
|
+
if (file.children) {
|
|
31
|
+
const result = navPageFromPath(path, file.children);
|
|
32
|
+
if (result) {
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const navKeyFromPath = (path, key, tree) => {
|
|
39
|
+
let value;
|
|
40
|
+
const goDeep = (path2, tree2) => {
|
|
41
|
+
for (const file of tree2) {
|
|
42
|
+
if (path2 !== "/" && file._path === "/") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (path2?.startsWith(file._path) && file[key]) {
|
|
46
|
+
value = file[key];
|
|
47
|
+
}
|
|
48
|
+
if (file._path === path2) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (file.children) {
|
|
52
|
+
goDeep(path2, file.children);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
goDeep(path, tree);
|
|
57
|
+
return value;
|
|
58
|
+
};
|
|
59
|
+
export const useContentHelpers = () => {
|
|
60
|
+
return {
|
|
61
|
+
navBottomLink,
|
|
62
|
+
navDirFromPath,
|
|
63
|
+
navPageFromPath,
|
|
64
|
+
navKeyFromPath
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { hash } from "ohash";
|
|
2
|
+
import { encodeQueryParams } from "../utils/query.js";
|
|
3
|
+
import { jsonStringify } from "../utils/json.js";
|
|
4
|
+
import { addPrerenderPath, shouldUseClientDB, withContentBase } from "./utils.js";
|
|
5
|
+
import { queryContent } from "./query.js";
|
|
6
|
+
import { useContentPreview } from "./preview.js";
|
|
7
|
+
import { useRuntimeConfig } from "#imports";
|
|
8
|
+
export const fetchContentNavigation = async (queryBuilder) => {
|
|
9
|
+
const { content } = useRuntimeConfig().public;
|
|
10
|
+
if (typeof queryBuilder?.params !== "function") {
|
|
11
|
+
queryBuilder = queryContent(queryBuilder);
|
|
12
|
+
}
|
|
13
|
+
const params = queryBuilder.params();
|
|
14
|
+
const apiPath = content.experimental.stripQueryParameters ? withContentBase(`/navigation/${import.meta.dev ? "_" : `${hash(params)}.${content.integrity}`}/${encodeQueryParams(params)}.json`) : withContentBase(import.meta.dev ? `/navigation/${hash(params)}` : `/navigation/${hash(params)}.${content.integrity}.json`);
|
|
15
|
+
if (!import.meta.dev && import.meta.server) {
|
|
16
|
+
addPrerenderPath(apiPath);
|
|
17
|
+
}
|
|
18
|
+
if (shouldUseClientDB()) {
|
|
19
|
+
const generateNavigation = await import("./client-db.js").then((m) => m.generateNavigation);
|
|
20
|
+
return generateNavigation(params);
|
|
21
|
+
}
|
|
22
|
+
const data = await $fetch(apiPath, {
|
|
23
|
+
method: "GET",
|
|
24
|
+
responseType: "json",
|
|
25
|
+
params: content.experimental.stripQueryParameters ? void 0 : {
|
|
26
|
+
_params: jsonStringify(params),
|
|
27
|
+
previewToken: useContentPreview().getPreviewToken()
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
if (typeof data === "string" && data.startsWith("<!DOCTYPE html>")) {
|
|
31
|
+
throw new Error("Not found");
|
|
32
|
+
}
|
|
33
|
+
return data;
|
|
34
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useCookie, useRoute } from "#imports";
|
|
2
|
+
let showWarning = true;
|
|
3
|
+
export const useContentPreview = () => {
|
|
4
|
+
const getPreviewToken = () => {
|
|
5
|
+
return useCookie("previewToken").value || import.meta.client && sessionStorage.getItem("previewToken") || void 0;
|
|
6
|
+
};
|
|
7
|
+
const setPreviewToken = (token) => {
|
|
8
|
+
useCookie("previewToken").value = token;
|
|
9
|
+
useRoute().query.preview = token || "";
|
|
10
|
+
if (import.meta.client) {
|
|
11
|
+
if (token) {
|
|
12
|
+
sessionStorage.setItem("previewToken", token);
|
|
13
|
+
} else {
|
|
14
|
+
sessionStorage.removeItem("previewToken");
|
|
15
|
+
}
|
|
16
|
+
window.location.reload();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const isEnabled = () => {
|
|
20
|
+
const query = useRoute().query;
|
|
21
|
+
if (Object.prototype.hasOwnProperty.call(query, "preview") && !query.preview) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (query.preview || useCookie("previewToken").value) {
|
|
25
|
+
if (import.meta.dev && showWarning) {
|
|
26
|
+
console.warn("[content] Client DB enabled since a preview token is set (either in query or cookie).");
|
|
27
|
+
showWarning = false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (import.meta.client && sessionStorage.getItem("previewToken")) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
isEnabled,
|
|
38
|
+
getPreviewToken,
|
|
39
|
+
setPreviewToken
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedContent, ContentQueryBuilder, ContentQueryBuilderParams } from '@nuxt/content';
|
|
2
|
+
/**
|
|
3
|
+
* Query fetcher
|
|
4
|
+
*/
|
|
5
|
+
export declare const createQueryFetch: <T = ParsedContent>() => (query: ContentQueryBuilder<T>) => Promise<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Query contents from path
|
|
8
|
+
*/
|
|
9
|
+
export declare function queryContent<T = ParsedContent>(query?: ContentQueryBuilderParams): ContentQueryBuilder<T>;
|
|
10
|
+
export declare function queryContent<T = ParsedContent>(query: string, ...pathParts: string[]): ContentQueryBuilder<T>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { joinURL, withLeadingSlash, withoutTrailingSlash } from "ufo";
|
|
2
|
+
import { hash } from "ohash";
|
|
3
|
+
import { createQuery } from "../query/query.js";
|
|
4
|
+
import { encodeQueryParams } from "../utils/query.js";
|
|
5
|
+
import { jsonStringify } from "../utils/json.js";
|
|
6
|
+
import { addPrerenderPath, shouldUseClientDB, withContentBase } from "./utils.js";
|
|
7
|
+
import { useContentPreview } from "./preview.js";
|
|
8
|
+
import { useRuntimeConfig } from "#imports";
|
|
9
|
+
export const createQueryFetch = () => async (query) => {
|
|
10
|
+
const { content } = useRuntimeConfig().public;
|
|
11
|
+
const params = query.params();
|
|
12
|
+
const apiPath = content.experimental.stripQueryParameters ? withContentBase(`/query/${import.meta.dev ? "_" : `${hash(params)}.${content.integrity}`}/${encodeQueryParams(params)}.json`) : withContentBase(import.meta.dev ? "/query" : `/query/${hash(params)}.${content.integrity}.json`);
|
|
13
|
+
if (!import.meta.dev && import.meta.server) {
|
|
14
|
+
addPrerenderPath(apiPath);
|
|
15
|
+
}
|
|
16
|
+
if (shouldUseClientDB()) {
|
|
17
|
+
const db = await import("./client-db.js").then((m) => m.useContentDatabase());
|
|
18
|
+
return db.fetch(query);
|
|
19
|
+
}
|
|
20
|
+
const _query = content.experimental.stripQueryParameters ? void 0 : `_params=${encodeURIComponent(jsonStringify(params))}&previewToken=${useContentPreview().getPreviewToken()}`;
|
|
21
|
+
const data = await $fetch(apiPath + "?" + _query, { method: "GET", responseType: "json" });
|
|
22
|
+
if (typeof data === "string" && data.startsWith("<!DOCTYPE html>")) {
|
|
23
|
+
throw new Error("Not found");
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
};
|
|
27
|
+
export function queryContent(query, ...pathParts) {
|
|
28
|
+
const { content } = useRuntimeConfig().public;
|
|
29
|
+
const queryBuilder = content.experimental.advanceQuery ? createQuery(createQueryFetch(), { initialParams: typeof query !== "string" ? query : {}, legacy: false }) : createQuery(createQueryFetch(), { initialParams: typeof query !== "string" ? query : {}, legacy: true });
|
|
30
|
+
let path;
|
|
31
|
+
if (typeof query === "string") {
|
|
32
|
+
path = withLeadingSlash(joinURL(query, ...pathParts));
|
|
33
|
+
}
|
|
34
|
+
const originalParamsFn = queryBuilder.params;
|
|
35
|
+
queryBuilder.params = () => {
|
|
36
|
+
const params = originalParamsFn();
|
|
37
|
+
if (path) {
|
|
38
|
+
params.where = params.where || [];
|
|
39
|
+
if (params.first && (params.where || []).length === 0) {
|
|
40
|
+
params.where.push({ _path: withoutTrailingSlash(path) });
|
|
41
|
+
} else {
|
|
42
|
+
params.where.push({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, "\\$&")}`) });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!params.sort?.length) {
|
|
46
|
+
params.sort = [{ _stem: 1, $numeric: true }];
|
|
47
|
+
}
|
|
48
|
+
if (!import.meta.dev) {
|
|
49
|
+
params.where = params.where || [];
|
|
50
|
+
if (!params.where.find((item) => typeof item._draft !== "undefined")) {
|
|
51
|
+
params.where.push({ _draft: { $ne: true } });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (content.locales.length) {
|
|
55
|
+
const queryLocale = params.where?.find((w) => w._locale)?._locale;
|
|
56
|
+
if (!queryLocale) {
|
|
57
|
+
params.where = params.where || [];
|
|
58
|
+
params.where.push({ _locale: content.defaultLocale });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return params;
|
|
62
|
+
};
|
|
63
|
+
return queryBuilder;
|
|
64
|
+
}
|