fumadocs-core 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/breadcrumb.d.ts +11 -0
- package/dist/breadcrumb.js +47 -0
- package/dist/chunk-2ZGUSAWB.js +12 -0
- package/dist/chunk-AFKH746E.js +40 -0
- package/dist/chunk-GT3Y35O6.js +46 -0
- package/dist/chunk-WEAGW6MQ.js +63 -0
- package/dist/dynamic-link.d.ts +14 -0
- package/dist/dynamic-link.js +33 -0
- package/dist/get-toc-YF_TdazL.d.ts +14 -0
- package/dist/link.d.ts +24 -0
- package/dist/link.js +7 -0
- package/dist/mdx-plugins/index.d.ts +89 -0
- package/dist/mdx-plugins/index.js +353 -0
- package/dist/middleware.d.ts +10 -0
- package/dist/middleware.js +43 -0
- package/dist/page-tree-izSPERQk.d.ts +37 -0
- package/dist/remark-structure-RwYPDA6M.d.ts +34 -0
- package/dist/search/client.d.ts +13 -0
- package/dist/search/client.js +52 -0
- package/dist/search/server.d.ts +51 -0
- package/dist/search/server.js +209 -0
- package/dist/search/shared.d.ts +8 -0
- package/dist/search/shared.js +0 -0
- package/dist/search-algolia/client.d.ts +28 -0
- package/dist/search-algolia/client.js +68 -0
- package/dist/search-algolia/server.d.ts +45 -0
- package/dist/search-algolia/server.js +68 -0
- package/dist/server/index.d.ts +57 -0
- package/dist/server/index.js +148 -0
- package/dist/sidebar.d.ts +19 -0
- package/dist/sidebar.js +88 -0
- package/dist/source/index.d.ts +171 -0
- package/dist/source/index.js +389 -0
- package/dist/toc.d.ts +20 -0
- package/dist/toc.js +113 -0
- package/package.json +158 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__spreadProps,
|
|
3
|
+
__spreadValues
|
|
4
|
+
} from "../chunk-WEAGW6MQ.js";
|
|
5
|
+
|
|
6
|
+
// src/search/server.ts
|
|
7
|
+
import { Document } from "flexsearch";
|
|
8
|
+
import nextLib from "next/server";
|
|
9
|
+
function createSearchAPI(type, options) {
|
|
10
|
+
if (type === "simple") {
|
|
11
|
+
return initSearchAPI(options);
|
|
12
|
+
}
|
|
13
|
+
return initSearchAPIAdvanced(options);
|
|
14
|
+
}
|
|
15
|
+
function createI18nSearchAPI(type, options) {
|
|
16
|
+
const map = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const [k, v] of options.indexes) {
|
|
18
|
+
map.set(
|
|
19
|
+
k,
|
|
20
|
+
createSearchAPI(type, __spreadProps(__spreadValues({}, options), {
|
|
21
|
+
language: k,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment -- Avoid complicated types
|
|
23
|
+
indexes: v
|
|
24
|
+
}))
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
GET(request) {
|
|
29
|
+
const locale = request.nextUrl.searchParams.get("locale");
|
|
30
|
+
if (locale) {
|
|
31
|
+
const handler = map.get(locale);
|
|
32
|
+
if (handler)
|
|
33
|
+
return handler.GET(request);
|
|
34
|
+
}
|
|
35
|
+
return nextLib.NextResponse.json([]);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function initSearchAPI({ indexes, language }) {
|
|
40
|
+
const store = ["title", "url"];
|
|
41
|
+
const index = new Document({
|
|
42
|
+
language,
|
|
43
|
+
optimize: true,
|
|
44
|
+
cache: 100,
|
|
45
|
+
document: {
|
|
46
|
+
id: "url",
|
|
47
|
+
store,
|
|
48
|
+
index: [
|
|
49
|
+
{
|
|
50
|
+
field: "title",
|
|
51
|
+
tokenize: "forward",
|
|
52
|
+
resolution: 9
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
field: "content",
|
|
56
|
+
tokenize: "strict",
|
|
57
|
+
context: {
|
|
58
|
+
depth: 1,
|
|
59
|
+
resolution: 9
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
field: "keywords",
|
|
64
|
+
tokenize: "strict",
|
|
65
|
+
resolution: 9
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
for (const page of indexes) {
|
|
71
|
+
index.add({
|
|
72
|
+
title: page.title,
|
|
73
|
+
url: page.url,
|
|
74
|
+
content: page.content,
|
|
75
|
+
keywords: page.keywords
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
GET(request) {
|
|
80
|
+
const { searchParams } = request.nextUrl;
|
|
81
|
+
const query = searchParams.get("query");
|
|
82
|
+
if (!query)
|
|
83
|
+
return nextLib.NextResponse.json([]);
|
|
84
|
+
const results = index.search(query, 5, {
|
|
85
|
+
enrich: true,
|
|
86
|
+
suggest: true
|
|
87
|
+
});
|
|
88
|
+
if (results.length === 0)
|
|
89
|
+
return nextLib.NextResponse.json([]);
|
|
90
|
+
const pages = results[0].result.map((page) => ({
|
|
91
|
+
type: "page",
|
|
92
|
+
content: page.doc.title,
|
|
93
|
+
id: page.doc.url,
|
|
94
|
+
url: page.doc.url
|
|
95
|
+
}));
|
|
96
|
+
return nextLib.NextResponse.json(pages);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function initSearchAPIAdvanced({
|
|
101
|
+
indexes,
|
|
102
|
+
language,
|
|
103
|
+
tag = false
|
|
104
|
+
}) {
|
|
105
|
+
const store = ["id", "url", "content", "page_id", "type"];
|
|
106
|
+
const index = new Document({
|
|
107
|
+
language,
|
|
108
|
+
cache: 100,
|
|
109
|
+
tokenize: "forward",
|
|
110
|
+
optimize: true,
|
|
111
|
+
context: {
|
|
112
|
+
depth: 2,
|
|
113
|
+
bidirectional: true,
|
|
114
|
+
resolution: 9
|
|
115
|
+
},
|
|
116
|
+
document: {
|
|
117
|
+
id: "id",
|
|
118
|
+
tag: tag ? "tag" : void 0,
|
|
119
|
+
store,
|
|
120
|
+
index: ["content"]
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
for (const page of indexes) {
|
|
124
|
+
const data = page.structuredData;
|
|
125
|
+
let id = 0;
|
|
126
|
+
index.add({
|
|
127
|
+
id: page.id,
|
|
128
|
+
page_id: page.id,
|
|
129
|
+
type: "page",
|
|
130
|
+
content: page.title,
|
|
131
|
+
tag: page.tag,
|
|
132
|
+
url: page.url
|
|
133
|
+
});
|
|
134
|
+
for (const heading of data.headings) {
|
|
135
|
+
index.add({
|
|
136
|
+
id: page.id + id++,
|
|
137
|
+
page_id: page.id,
|
|
138
|
+
type: "heading",
|
|
139
|
+
tag: page.tag,
|
|
140
|
+
url: `${page.url}#${heading.id}`,
|
|
141
|
+
content: heading.content
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
for (const content of data.contents) {
|
|
145
|
+
index.add({
|
|
146
|
+
id: page.id + id++,
|
|
147
|
+
page_id: page.id,
|
|
148
|
+
tag: page.tag,
|
|
149
|
+
type: "text",
|
|
150
|
+
url: content.heading ? `${page.url}#${content.heading}` : page.url,
|
|
151
|
+
content: content.content
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
GET(request) {
|
|
157
|
+
var _a, _b, _c;
|
|
158
|
+
const query = request.nextUrl.searchParams.get("query");
|
|
159
|
+
const paramTag = request.nextUrl.searchParams.get("tag");
|
|
160
|
+
if (!query)
|
|
161
|
+
return nextLib.NextResponse.json([]);
|
|
162
|
+
const results = index.search(query, 5, {
|
|
163
|
+
enrich: true,
|
|
164
|
+
tag: paramTag != null ? paramTag : void 0,
|
|
165
|
+
limit: 6
|
|
166
|
+
});
|
|
167
|
+
const map = /* @__PURE__ */ new Map();
|
|
168
|
+
const sortedResult = [];
|
|
169
|
+
for (const item of (_b = (_a = results[0]) == null ? void 0 : _a.result) != null ? _b : []) {
|
|
170
|
+
if (item.doc.type === "page") {
|
|
171
|
+
if (!map.has(item.doc.page_id)) {
|
|
172
|
+
map.set(item.doc.page_id, []);
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const i = {
|
|
177
|
+
id: item.doc.id,
|
|
178
|
+
content: item.doc.content,
|
|
179
|
+
type: item.doc.type,
|
|
180
|
+
url: item.doc.url
|
|
181
|
+
};
|
|
182
|
+
if (map.has(item.doc.page_id)) {
|
|
183
|
+
(_c = map.get(item.doc.page_id)) == null ? void 0 : _c.push(i);
|
|
184
|
+
} else {
|
|
185
|
+
map.set(item.doc.page_id, [i]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
for (const [id, items] of map.entries()) {
|
|
189
|
+
const page = index.get(id);
|
|
190
|
+
if (!page)
|
|
191
|
+
continue;
|
|
192
|
+
sortedResult.push({
|
|
193
|
+
id: page.id,
|
|
194
|
+
content: page.content,
|
|
195
|
+
type: "page",
|
|
196
|
+
url: page.url
|
|
197
|
+
});
|
|
198
|
+
sortedResult.push(...items);
|
|
199
|
+
}
|
|
200
|
+
return nextLib.NextResponse.json(sortedResult);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
export {
|
|
205
|
+
createI18nSearchAPI,
|
|
206
|
+
createSearchAPI,
|
|
207
|
+
initSearchAPI,
|
|
208
|
+
initSearchAPIAdvanced
|
|
209
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SearchOptions, Hit } from '@algolia/client-search';
|
|
2
|
+
import { SearchIndex } from 'algoliasearch/lite';
|
|
3
|
+
import { SWRResponse } from 'swr';
|
|
4
|
+
import { SortedResult } from '../search/shared.js';
|
|
5
|
+
import { BaseIndex } from './server.js';
|
|
6
|
+
import 'algoliasearch';
|
|
7
|
+
import '../remark-structure-RwYPDA6M.js';
|
|
8
|
+
import 'mdast';
|
|
9
|
+
import 'unified';
|
|
10
|
+
|
|
11
|
+
interface Options extends SearchOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Use `empty` as result if query is empty
|
|
14
|
+
*/
|
|
15
|
+
allowEmpty?: boolean;
|
|
16
|
+
}
|
|
17
|
+
declare function groupResults(hits: Hit<BaseIndex>[]): SortedResult[];
|
|
18
|
+
declare function searchDocs(index: SearchIndex, query: string, options?: SearchOptions): Promise<SortedResult[]>;
|
|
19
|
+
interface UseAlgoliaSearch {
|
|
20
|
+
search: string;
|
|
21
|
+
setSearch: (v: string) => void;
|
|
22
|
+
query: SWRResponse<SortedResult[] | 'empty', Error, {
|
|
23
|
+
keepPreviousData: true;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
declare function useAlgoliaSearch(index: SearchIndex, { allowEmpty, ...options }?: Options): UseAlgoliaSearch;
|
|
27
|
+
|
|
28
|
+
export { type Options, groupResults, searchDocs, useAlgoliaSearch };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__async,
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-WEAGW6MQ.js";
|
|
6
|
+
|
|
7
|
+
// src/search-algolia/client.ts
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import useSWR from "swr";
|
|
10
|
+
function groupResults(hits) {
|
|
11
|
+
const grouped = [];
|
|
12
|
+
const scannedUrls = /* @__PURE__ */ new Set();
|
|
13
|
+
for (const hit of hits) {
|
|
14
|
+
if (!scannedUrls.has(hit.url)) {
|
|
15
|
+
scannedUrls.add(hit.url);
|
|
16
|
+
grouped.push({
|
|
17
|
+
id: hit.url,
|
|
18
|
+
type: "page",
|
|
19
|
+
url: hit.url,
|
|
20
|
+
content: hit.title
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
grouped.push({
|
|
24
|
+
id: hit.objectID,
|
|
25
|
+
type: hit.content === hit.section ? "heading" : "text",
|
|
26
|
+
url: hit.section_id ? `${hit.url}#${hit.section_id}` : hit.url,
|
|
27
|
+
content: hit.content
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return grouped;
|
|
31
|
+
}
|
|
32
|
+
function searchDocs(index, query, options) {
|
|
33
|
+
return __async(this, null, function* () {
|
|
34
|
+
if (query.length === 0) {
|
|
35
|
+
const result2 = yield index.search(query, __spreadValues({
|
|
36
|
+
distinct: 1,
|
|
37
|
+
hitsPerPage: 8
|
|
38
|
+
}, options));
|
|
39
|
+
return groupResults(result2.hits).filter((hit) => hit.type === "page");
|
|
40
|
+
}
|
|
41
|
+
const result = yield index.search(query, __spreadValues({
|
|
42
|
+
distinct: 5,
|
|
43
|
+
hitsPerPage: 10
|
|
44
|
+
}, options));
|
|
45
|
+
return groupResults(result.hits);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function useAlgoliaSearch(index, _a = {}) {
|
|
49
|
+
var _b = _a, { allowEmpty = true } = _b, options = __objRest(_b, ["allowEmpty"]);
|
|
50
|
+
const [search, setSearch] = useState("");
|
|
51
|
+
const query = useSWR(
|
|
52
|
+
["/api/search", search, allowEmpty, options],
|
|
53
|
+
() => __async(this, null, function* () {
|
|
54
|
+
if (allowEmpty && search.length === 0)
|
|
55
|
+
return "empty";
|
|
56
|
+
return searchDocs(index, search, options);
|
|
57
|
+
}),
|
|
58
|
+
{
|
|
59
|
+
keepPreviousData: true
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
return { search, setSearch, query };
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
groupResults,
|
|
66
|
+
searchDocs,
|
|
67
|
+
useAlgoliaSearch
|
|
68
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SearchClient, SearchIndex } from 'algoliasearch';
|
|
2
|
+
import { S as StructuredData } from '../remark-structure-RwYPDA6M.js';
|
|
3
|
+
import 'mdast';
|
|
4
|
+
import 'unified';
|
|
5
|
+
|
|
6
|
+
interface DocumentRecord {
|
|
7
|
+
/**
|
|
8
|
+
* The ID of document, must be unique
|
|
9
|
+
*/
|
|
10
|
+
_id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* URL to the page
|
|
14
|
+
*/
|
|
15
|
+
url: string;
|
|
16
|
+
structured: StructuredData;
|
|
17
|
+
/**
|
|
18
|
+
* Data to be added to each section index
|
|
19
|
+
*/
|
|
20
|
+
extra_data?: object;
|
|
21
|
+
}
|
|
22
|
+
interface SyncOptions {
|
|
23
|
+
document?: string;
|
|
24
|
+
documents: DocumentRecord[];
|
|
25
|
+
}
|
|
26
|
+
declare function sync(client: SearchClient, { document, documents }: SyncOptions): Promise<void>;
|
|
27
|
+
declare function setIndexSettings(index: SearchIndex): Promise<void>;
|
|
28
|
+
declare function updateDocuments(index: SearchIndex, documents: DocumentRecord[]): Promise<void>;
|
|
29
|
+
interface BaseIndex {
|
|
30
|
+
objectID: string;
|
|
31
|
+
title: string;
|
|
32
|
+
url: string;
|
|
33
|
+
section?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The anchor id
|
|
36
|
+
*/
|
|
37
|
+
section_id?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The id of page, used for distinct
|
|
40
|
+
*/
|
|
41
|
+
page_id: string;
|
|
42
|
+
content: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { type BaseIndex, setIndexSettings, sync, updateDocuments };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__async,
|
|
3
|
+
__spreadValues
|
|
4
|
+
} from "../chunk-WEAGW6MQ.js";
|
|
5
|
+
|
|
6
|
+
// src/search-algolia/server.ts
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
function sync(_0, _1) {
|
|
9
|
+
return __async(this, arguments, function* (client, { document = "document", documents }) {
|
|
10
|
+
const index = client.initIndex(document);
|
|
11
|
+
yield setIndexSettings(index);
|
|
12
|
+
yield updateDocuments(index, documents);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function setIndexSettings(index) {
|
|
16
|
+
return __async(this, null, function* () {
|
|
17
|
+
yield index.setSettings({
|
|
18
|
+
attributeForDistinct: "page_id",
|
|
19
|
+
attributesToRetrieve: ["title", "section", "content", "url", "section_id"],
|
|
20
|
+
searchableAttributes: ["title", "section", "content"],
|
|
21
|
+
attributesToSnippet: [],
|
|
22
|
+
attributesForFaceting: ["tag"]
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function getSections(page) {
|
|
27
|
+
const scannedHeadings = /* @__PURE__ */ new Set();
|
|
28
|
+
return page.structured.contents.flatMap((p) => {
|
|
29
|
+
const heading = p.heading ? page.structured.headings.find((h) => p.heading === h.id) : null;
|
|
30
|
+
const section = {
|
|
31
|
+
section: heading == null ? void 0 : heading.content,
|
|
32
|
+
section_id: heading == null ? void 0 : heading.id,
|
|
33
|
+
content: p.content
|
|
34
|
+
};
|
|
35
|
+
if (heading && !scannedHeadings.has(heading.id)) {
|
|
36
|
+
scannedHeadings.add(heading.id);
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
section: heading.content,
|
|
40
|
+
section_id: heading.id,
|
|
41
|
+
content: heading.content
|
|
42
|
+
},
|
|
43
|
+
section
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
return section;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function updateDocuments(index, documents) {
|
|
50
|
+
return __async(this, null, function* () {
|
|
51
|
+
const objects = documents.flatMap((page) => {
|
|
52
|
+
return getSections(page).map(
|
|
53
|
+
(section) => __spreadValues(__spreadValues({
|
|
54
|
+
objectID: `${page._id}-${randomUUID()}`,
|
|
55
|
+
title: page.title,
|
|
56
|
+
url: page.url,
|
|
57
|
+
page_id: page._id
|
|
58
|
+
}, section), page.extra_data)
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
yield index.replaceAllObjects(objects);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
setIndexSettings,
|
|
66
|
+
sync,
|
|
67
|
+
updateDocuments
|
|
68
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { T as TableOfContents } from '../get-toc-YF_TdazL.js';
|
|
2
|
+
export { a as TOCItemType, g as getTableOfContents } from '../get-toc-YF_TdazL.js';
|
|
3
|
+
import { N as Node, I as Item, R as Root } from '../page-tree-izSPERQk.js';
|
|
4
|
+
export { p as PageTree } from '../page-tree-izSPERQk.js';
|
|
5
|
+
import 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parse TOC from portable text (Sanity)
|
|
9
|
+
*
|
|
10
|
+
* @param value - Blocks
|
|
11
|
+
* @param slugFn - A function that generates slug from title
|
|
12
|
+
*/
|
|
13
|
+
declare function getTableOfContentsFromPortableText(value: any): TableOfContents;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Flatten tree to an array of page nodes
|
|
17
|
+
*/
|
|
18
|
+
declare function flattenTree(tree: Node[]): Item[];
|
|
19
|
+
/**
|
|
20
|
+
* Get neighbours of a page, useful for implementing "previous & next" buttons
|
|
21
|
+
*/
|
|
22
|
+
declare function findNeighbour(tree: Root, url: string): {
|
|
23
|
+
previous?: Item;
|
|
24
|
+
next?: Item;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Separate the folder nodes of a root into multiple roots
|
|
28
|
+
*/
|
|
29
|
+
declare function separatePageTree(pageTree: Root): Root[];
|
|
30
|
+
|
|
31
|
+
interface GetGithubLastCommitOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Repository name, like "next-docs"
|
|
34
|
+
*/
|
|
35
|
+
repo: string;
|
|
36
|
+
/** Owner of repository */
|
|
37
|
+
owner: string;
|
|
38
|
+
/**
|
|
39
|
+
* Path to file
|
|
40
|
+
*/
|
|
41
|
+
path: string;
|
|
42
|
+
/**
|
|
43
|
+
* Github access token
|
|
44
|
+
*/
|
|
45
|
+
token?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Custom query parameters
|
|
48
|
+
*/
|
|
49
|
+
params?: Record<string, string>;
|
|
50
|
+
options?: RequestInit;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the last edit time of a file
|
|
54
|
+
*/
|
|
55
|
+
declare function getGithubLastEdit({ repo, token, owner, path, options, params: customParams, }: GetGithubLastCommitOptions): Promise<Date | null>;
|
|
56
|
+
|
|
57
|
+
export { type GetGithubLastCommitOptions, TableOfContents, findNeighbour, flattenTree, getGithubLastEdit, getTableOfContentsFromPortableText, separatePageTree };
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
remarkHeading
|
|
3
|
+
} from "../chunk-GT3Y35O6.js";
|
|
4
|
+
import {
|
|
5
|
+
__async
|
|
6
|
+
} from "../chunk-WEAGW6MQ.js";
|
|
7
|
+
|
|
8
|
+
// src/server/get-toc.ts
|
|
9
|
+
import { remark } from "remark";
|
|
10
|
+
function getTableOfContents(content) {
|
|
11
|
+
return __async(this, null, function* () {
|
|
12
|
+
const result = yield remark().use(remarkHeading).process(content);
|
|
13
|
+
if ("toc" in result.data)
|
|
14
|
+
return result.data.toc;
|
|
15
|
+
return [];
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/server/get-toc-sanity.ts
|
|
20
|
+
import Slugger from "github-slugger";
|
|
21
|
+
var slugger = new Slugger();
|
|
22
|
+
function getTableOfContentsFromPortableText(value) {
|
|
23
|
+
if (!Array.isArray(value)) {
|
|
24
|
+
throw new Error("Invalid body type");
|
|
25
|
+
}
|
|
26
|
+
slugger.reset();
|
|
27
|
+
const result = [];
|
|
28
|
+
for (const block of value) {
|
|
29
|
+
dfs(block, result);
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function dfs(block, list) {
|
|
34
|
+
var _a;
|
|
35
|
+
if (block.style && block.style.length === 2 && block.style.startsWith("h")) {
|
|
36
|
+
const depth = Number(block.style[1]);
|
|
37
|
+
if (Number.isNaN(depth))
|
|
38
|
+
return;
|
|
39
|
+
const text = flattenNode(block);
|
|
40
|
+
list.push({
|
|
41
|
+
title: text,
|
|
42
|
+
url: slugger.slug(text),
|
|
43
|
+
depth
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
(_a = block.children) == null ? void 0 : _a.forEach((child) => {
|
|
48
|
+
dfs(child, list);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function flattenNode(block) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
let text = "";
|
|
54
|
+
if (block._type === "span") {
|
|
55
|
+
return (_a = block.text) != null ? _a : "";
|
|
56
|
+
}
|
|
57
|
+
(_b = block.children) == null ? void 0 : _b.forEach((child) => {
|
|
58
|
+
text += flattenNode(child);
|
|
59
|
+
});
|
|
60
|
+
return text;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/server/page-tree-utils.ts
|
|
64
|
+
function flattenTree(tree) {
|
|
65
|
+
return tree.flatMap((node) => {
|
|
66
|
+
if (node.type === "separator")
|
|
67
|
+
return [];
|
|
68
|
+
if (node.type === "folder") {
|
|
69
|
+
const child = flattenTree(node.children);
|
|
70
|
+
if (node.index)
|
|
71
|
+
return [node.index, ...child];
|
|
72
|
+
return child;
|
|
73
|
+
}
|
|
74
|
+
return [node];
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function findNeighbour(tree, url) {
|
|
78
|
+
const list = flattenTree(tree.children);
|
|
79
|
+
for (let i = 0; i < list.length; i++) {
|
|
80
|
+
if (list[i].url === url) {
|
|
81
|
+
return {
|
|
82
|
+
next: list[i + 1],
|
|
83
|
+
previous: list[i - 1]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
function separatePageTree(pageTree) {
|
|
90
|
+
return pageTree.children.flatMap((child) => {
|
|
91
|
+
var _a;
|
|
92
|
+
if (child.type !== "folder")
|
|
93
|
+
return [];
|
|
94
|
+
return {
|
|
95
|
+
name: child.name,
|
|
96
|
+
url: (_a = child.index) == null ? void 0 : _a.url,
|
|
97
|
+
children: child.children
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/server/page-tree.ts
|
|
103
|
+
var page_tree_exports = {};
|
|
104
|
+
|
|
105
|
+
// src/server/git-api.ts
|
|
106
|
+
function getGithubLastEdit(_0) {
|
|
107
|
+
return __async(this, arguments, function* ({
|
|
108
|
+
repo,
|
|
109
|
+
token,
|
|
110
|
+
owner,
|
|
111
|
+
path,
|
|
112
|
+
options = {},
|
|
113
|
+
params: customParams = {}
|
|
114
|
+
}) {
|
|
115
|
+
const params = new URLSearchParams();
|
|
116
|
+
params.set("path", path);
|
|
117
|
+
params.set("page", "1");
|
|
118
|
+
params.set("per_page", "1");
|
|
119
|
+
for (const [key, value] of Object.entries(customParams)) {
|
|
120
|
+
params.set(key, value);
|
|
121
|
+
}
|
|
122
|
+
if (token) {
|
|
123
|
+
options.headers = new Headers(options.headers);
|
|
124
|
+
options.headers.append("authorization", token);
|
|
125
|
+
}
|
|
126
|
+
const res = yield fetch(
|
|
127
|
+
`https://api.github.com/repos/${owner}/${repo}/commits?${params.toString()}`,
|
|
128
|
+
options
|
|
129
|
+
);
|
|
130
|
+
if (!res.ok)
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Failed to fetch last edit time from Git ${yield res.text()}`
|
|
133
|
+
);
|
|
134
|
+
const data = yield res.json();
|
|
135
|
+
if (data.length === 0)
|
|
136
|
+
return null;
|
|
137
|
+
return new Date(data[0].commit.committer.date);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
page_tree_exports as PageTree,
|
|
142
|
+
findNeighbour,
|
|
143
|
+
flattenTree,
|
|
144
|
+
getGithubLastEdit,
|
|
145
|
+
getTableOfContents,
|
|
146
|
+
getTableOfContentsFromPortableText,
|
|
147
|
+
separatePageTree
|
|
148
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
|
|
3
|
+
interface SidebarProviderProps {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
onOpenChange?: (v: boolean) => void;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
declare function SidebarProvider(props: SidebarProviderProps): JSX.Element;
|
|
9
|
+
type WithAs<T extends ElementType, Extend = object> = Omit<ComponentPropsWithoutRef<T>, 'as' | keyof Extend> & Extend & {
|
|
10
|
+
as?: T;
|
|
11
|
+
};
|
|
12
|
+
type SidebarTriggerProps<T extends ElementType> = WithAs<T>;
|
|
13
|
+
declare function SidebarTrigger<T extends ElementType = 'button'>({ as, ...props }: SidebarTriggerProps<T>): JSX.Element;
|
|
14
|
+
type SidebarContentProps<T extends ElementType> = WithAs<T, {
|
|
15
|
+
minWidth?: number;
|
|
16
|
+
}>;
|
|
17
|
+
declare function SidebarList<T extends ElementType = 'aside'>({ as, minWidth, ...props }: SidebarContentProps<T>): JSX.Element;
|
|
18
|
+
|
|
19
|
+
export { type SidebarContentProps, SidebarList, SidebarProvider, type SidebarProviderProps, SidebarTrigger, type SidebarTriggerProps };
|