@nbtca/docs 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -33
- package/dist/cache.d.ts +0 -1
- package/dist/cache.js +0 -1
- package/dist/client.d.ts +0 -1
- package/dist/client.js +239 -67
- package/dist/content.d.ts +3 -0
- package/dist/content.js +515 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/types.d.ts +36 -1
- package/dist/types.js +0 -1
- package/package.json +19 -7
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# @nbtca/docs
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
stale
|
|
6
|
-
|
|
7
|
-
Rendering is the consumer's job (e.g. `@nbtca/prompt`).
|
|
3
|
+
Typed GitHub client for the [NBTCA documents repository](https://github.com/nbtca/documents).
|
|
4
|
+
It lists Markdown documents, reads raw content, caches successful responses, and falls back to
|
|
5
|
+
stale data after transient failures. Rendering remains the consumer's responsibility.
|
|
8
6
|
|
|
9
7
|
## Install
|
|
10
8
|
|
|
@@ -17,53 +15,63 @@ npm install @nbtca/docs
|
|
|
17
15
|
```ts
|
|
18
16
|
import { createDocsClient } from '@nbtca/docs';
|
|
19
17
|
|
|
20
|
-
const docs = createDocsClient();
|
|
18
|
+
const docs = createDocsClient();
|
|
21
19
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Custom target:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
const docs = createDocsClient({
|
|
31
|
-
owner: 'my-org',
|
|
32
|
-
repo: 'my-docs',
|
|
33
|
-
branch: 'main',
|
|
34
|
-
token: process.env.GITHUB_TOKEN,
|
|
35
|
-
});
|
|
20
|
+
const sections = await docs.listDir();
|
|
21
|
+
const documents = await docs.listAll();
|
|
22
|
+
const markdown = await docs.getFile('repair/guide.md');
|
|
23
|
+
const page = await docs.getDocument('repair/index.md');
|
|
24
|
+
const matches = await docs.search('repair', { pathPrefix: 'repair' });
|
|
36
25
|
```
|
|
37
26
|
|
|
38
27
|
## API
|
|
39
28
|
|
|
40
29
|
### `createDocsClient(options?)`
|
|
41
30
|
|
|
42
|
-
| Option
|
|
43
|
-
|
|
44
|
-
| `owner`
|
|
45
|
-
| `repo`
|
|
46
|
-
| `branch`
|
|
47
|
-
| `token`
|
|
48
|
-
| `cacheTtlMs.dir`
|
|
49
|
-
| `cacheTtlMs.file` | `600000`
|
|
31
|
+
| Option | Default | Description |
|
|
32
|
+
| ----------------- | ---------------------------- | ---------------------------- |
|
|
33
|
+
| `owner` | `'nbtca'` | GitHub owner |
|
|
34
|
+
| `repo` | `'documents'` | Repository name |
|
|
35
|
+
| `branch` | `'main'` | Branch name or ref |
|
|
36
|
+
| `token` | `GITHUB_TOKEN` or `GH_TOKEN` | GitHub token |
|
|
37
|
+
| `cacheTtlMs.dir` | `300000` | Directory and tree cache TTL |
|
|
38
|
+
| `cacheTtlMs.file` | `600000` | File cache TTL |
|
|
50
39
|
|
|
51
40
|
### `docs.listDir(path?)`
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
Lists directories and Markdown files at a repository-relative path. The root path is used when
|
|
43
|
+
`path` is omitted.
|
|
55
44
|
|
|
56
45
|
### `docs.getFile(path)`
|
|
57
46
|
|
|
58
|
-
Returns raw
|
|
47
|
+
Returns raw file content.
|
|
59
48
|
|
|
60
49
|
### `docs.listAll()`
|
|
61
50
|
|
|
62
|
-
|
|
51
|
+
Lists every Markdown file through GitHub's recursive tree API.
|
|
52
|
+
|
|
53
|
+
### `docs.listSections()`
|
|
54
|
+
|
|
55
|
+
Returns top-level content sections with document counts and optional index paths.
|
|
56
|
+
|
|
57
|
+
### `docs.getDocument(path)`
|
|
58
|
+
|
|
59
|
+
Returns content with its route, section, title, summary, and semantic component attributes. Component
|
|
60
|
+
metadata covers `PageHero`, `FactStrip`, `LinkCard`, `Split`, `TimelineEntry`, and `Figure` without
|
|
61
|
+
imposing a renderer.
|
|
62
|
+
|
|
63
|
+
### `docs.search(query, options?)`
|
|
64
|
+
|
|
65
|
+
Searches paths, titles, summaries, Markdown text, and semantic component attributes. Results are
|
|
66
|
+
ranked and include excerpts. Use `pathPrefix` to scope a search and `limit` to cap results.
|
|
67
|
+
|
|
68
|
+
### `docs.clear()`
|
|
69
|
+
|
|
70
|
+
Clears all cached values and in-flight request bookkeeping.
|
|
63
71
|
|
|
64
72
|
### `DocsFetchError`
|
|
65
73
|
|
|
66
|
-
Thrown when a
|
|
74
|
+
Thrown when a request fails without usable stale data. Exposes `path` and HTTP `status`.
|
|
67
75
|
|
|
68
76
|
## License
|
|
69
77
|
|
package/dist/cache.d.ts
CHANGED
package/dist/cache.js
CHANGED
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TtlCache } from './cache.js';
|
|
2
|
+
import { parseDoc, searchDoc } from './content.js';
|
|
2
3
|
import { DocsFetchError } from './types.js';
|
|
3
4
|
const DEFAULTS = {
|
|
4
5
|
owner: 'nbtca',
|
|
@@ -7,15 +8,40 @@ const DEFAULTS = {
|
|
|
7
8
|
dirTtlMs: 5 * 60 * 1000,
|
|
8
9
|
fileTtlMs: 10 * 60 * 1000,
|
|
9
10
|
};
|
|
10
|
-
const SKIP = new Set([
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'.
|
|
11
|
+
const SKIP = new Set([
|
|
12
|
+
'.github',
|
|
13
|
+
'.husky',
|
|
14
|
+
'.vitepress',
|
|
15
|
+
'.vscode',
|
|
16
|
+
'node_modules',
|
|
17
|
+
'assets',
|
|
18
|
+
'public',
|
|
19
|
+
'scripts',
|
|
20
|
+
'utils',
|
|
21
|
+
'package.json',
|
|
22
|
+
'pnpm-lock.yaml',
|
|
23
|
+
'tsconfig.json',
|
|
24
|
+
'eslint.config.mjs',
|
|
25
|
+
'.nvmrc',
|
|
26
|
+
'.gitignore',
|
|
27
|
+
'.markdownlint-cli2.jsonc',
|
|
28
|
+
'CONTRIBUTING.md',
|
|
29
|
+
'CONTEXT.md',
|
|
30
|
+
'README.md',
|
|
31
|
+
'docs',
|
|
32
|
+
]);
|
|
33
|
+
const SEARCH_CONCURRENCY = 6;
|
|
34
|
+
const SEARCH_RESULT_LIMIT = 20;
|
|
14
35
|
function filterAndSort(raw) {
|
|
15
36
|
return raw
|
|
16
|
-
.filter(
|
|
17
|
-
|
|
18
|
-
|
|
37
|
+
.filter((item) => !item.name.startsWith('.') &&
|
|
38
|
+
!SKIP.has(item.name) &&
|
|
39
|
+
(item.type === 'dir' || (item.type === 'file' && item.name.endsWith('.md'))))
|
|
40
|
+
.map((item) => ({
|
|
41
|
+
name: item.name,
|
|
42
|
+
path: item.path,
|
|
43
|
+
type: item.type === 'dir' ? 'dir' : 'file',
|
|
44
|
+
}))
|
|
19
45
|
.sort((a, b) => {
|
|
20
46
|
if (a.type !== b.type)
|
|
21
47
|
return a.type === 'dir' ? -1 : 1;
|
|
@@ -24,54 +50,108 @@ function filterAndSort(raw) {
|
|
|
24
50
|
}
|
|
25
51
|
function filterTree(items) {
|
|
26
52
|
return items
|
|
27
|
-
.filter(
|
|
28
|
-
const parts =
|
|
29
|
-
if (parts.some(
|
|
53
|
+
.filter((item) => {
|
|
54
|
+
const parts = item.path.split('/');
|
|
55
|
+
if (parts.some((part) => part.startsWith('.') || SKIP.has(part)))
|
|
30
56
|
return false;
|
|
31
|
-
|
|
32
|
-
return i.type === 'blob' && i.path.endsWith('.md');
|
|
57
|
+
return item.type === 'blob' && item.path.endsWith('.md');
|
|
33
58
|
})
|
|
34
|
-
.map(
|
|
35
|
-
name:
|
|
36
|
-
path:
|
|
59
|
+
.map((item) => ({
|
|
60
|
+
name: item.path.slice(item.path.lastIndexOf('/') + 1),
|
|
61
|
+
path: item.path,
|
|
37
62
|
type: 'file',
|
|
38
63
|
}))
|
|
39
64
|
.sort((a, b) => a.path.localeCompare(b.path));
|
|
40
65
|
}
|
|
41
66
|
function copyItems(items) {
|
|
42
|
-
return items.map(item => ({ ...item }));
|
|
67
|
+
return items.map((item) => ({ ...item }));
|
|
68
|
+
}
|
|
69
|
+
function sectionsFromItems(items) {
|
|
70
|
+
const sections = new Map();
|
|
71
|
+
for (const item of items) {
|
|
72
|
+
const separator = item.path.indexOf('/');
|
|
73
|
+
if (separator < 1)
|
|
74
|
+
continue;
|
|
75
|
+
const path = item.path.slice(0, separator);
|
|
76
|
+
const current = sections.get(path) ?? { count: 0, path };
|
|
77
|
+
current.count += 1;
|
|
78
|
+
if (item.path === `${path}/index.md`)
|
|
79
|
+
current.indexPath = item.path;
|
|
80
|
+
sections.set(path, current);
|
|
81
|
+
}
|
|
82
|
+
return [...sections.values()]
|
|
83
|
+
.map((section) => ({ ...section }))
|
|
84
|
+
.sort((left, right) => left.path.localeCompare(right.path));
|
|
85
|
+
}
|
|
86
|
+
function searchLimit(value) {
|
|
87
|
+
const limit = value ?? SEARCH_RESULT_LIMIT;
|
|
88
|
+
if (!Number.isSafeInteger(limit) || limit < 0) {
|
|
89
|
+
throw new RangeError('limit must be a non-negative safe integer');
|
|
90
|
+
}
|
|
91
|
+
return limit;
|
|
92
|
+
}
|
|
93
|
+
async function mapConcurrent(values, concurrency, map) {
|
|
94
|
+
const results = new Array(values.length);
|
|
95
|
+
let nextIndex = 0;
|
|
96
|
+
async function worker() {
|
|
97
|
+
for (;;) {
|
|
98
|
+
const index = nextIndex;
|
|
99
|
+
nextIndex += 1;
|
|
100
|
+
if (index >= values.length)
|
|
101
|
+
return;
|
|
102
|
+
const value = values[index];
|
|
103
|
+
if (value !== undefined)
|
|
104
|
+
results[index] = await map(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const workers = Math.min(concurrency, values.length);
|
|
108
|
+
await Promise.all(Array.from({ length: workers }, worker));
|
|
109
|
+
return results;
|
|
43
110
|
}
|
|
44
111
|
function encodePath(path) {
|
|
45
|
-
return path
|
|
112
|
+
return path
|
|
113
|
+
.split('/')
|
|
114
|
+
.map((segment) => encodeURIComponent(segment))
|
|
115
|
+
.join('/');
|
|
46
116
|
}
|
|
47
117
|
function assertRepositoryPath(path, allowEmpty) {
|
|
48
118
|
if (allowEmpty && path === '')
|
|
49
119
|
return;
|
|
50
120
|
const parts = path.split('/');
|
|
51
|
-
if (path === ''
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
121
|
+
if (path === '' ||
|
|
122
|
+
path.startsWith('/') ||
|
|
123
|
+
path.endsWith('/') ||
|
|
124
|
+
path.includes('\\') ||
|
|
125
|
+
parts.some((part) => part === '' || part === '.' || part === '..')) {
|
|
56
126
|
throw new TypeError('path must be a normalized repository-relative path');
|
|
57
127
|
}
|
|
58
128
|
}
|
|
129
|
+
function hasControlCharacter(value) {
|
|
130
|
+
for (const character of value) {
|
|
131
|
+
const code = character.charCodeAt(0);
|
|
132
|
+
if (code <= 0x1f || code === 0x7f)
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
59
137
|
function assertRepositoryCoordinate(value, name) {
|
|
60
|
-
if (value === ''
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
138
|
+
if (value === '' ||
|
|
139
|
+
value !== value.trim() ||
|
|
140
|
+
value === '.' ||
|
|
141
|
+
value === '..' ||
|
|
142
|
+
value.includes('/') ||
|
|
143
|
+
value.includes('\\') ||
|
|
144
|
+
hasControlCharacter(value)) {
|
|
65
145
|
throw new TypeError(`${name} must be a valid GitHub repository coordinate`);
|
|
66
146
|
}
|
|
67
147
|
}
|
|
68
148
|
function assertBranchRef(value) {
|
|
69
149
|
const parts = value.split('/');
|
|
70
|
-
if (value === ''
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
150
|
+
if (value === '' ||
|
|
151
|
+
value !== value.trim() ||
|
|
152
|
+
value.includes('\\') ||
|
|
153
|
+
hasControlCharacter(value) ||
|
|
154
|
+
parts.some((part) => part === '' || part === '.' || part === '..')) {
|
|
75
155
|
throw new TypeError('branch must be a valid Git ref');
|
|
76
156
|
}
|
|
77
157
|
}
|
|
@@ -85,16 +165,56 @@ function cacheTtl(value, fallback, name) {
|
|
|
85
165
|
function isTransientStatus(status) {
|
|
86
166
|
return status === 408 || status === 429 || status >= 500;
|
|
87
167
|
}
|
|
168
|
+
function isSecondaryRateLimitMessage(value) {
|
|
169
|
+
if (!isRecord(value) || typeof value.message !== 'string')
|
|
170
|
+
return false;
|
|
171
|
+
const message = value.message.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
172
|
+
return (/\b(?:exceeded|hit|triggered) (?:a |the )?secondary rate limit\b/.test(message) ||
|
|
173
|
+
/\bsecondary rate limit (?:was |has been )?(?:exceeded|hit|triggered)\b/.test(message));
|
|
174
|
+
}
|
|
175
|
+
async function isTransientResponse(response) {
|
|
176
|
+
if (isTransientStatus(response.status))
|
|
177
|
+
return true;
|
|
178
|
+
if (response.status !== 403)
|
|
179
|
+
return false;
|
|
180
|
+
if (response.headers.get('x-ratelimit-remaining') === '0' ||
|
|
181
|
+
response.headers.get('retry-after') !== null) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
return isSecondaryRateLimitMessage(await response.clone().json());
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function reject(error) {
|
|
192
|
+
return Promise.reject(error instanceof Error ? error : new Error('Operation failed with a non-error value'));
|
|
193
|
+
}
|
|
194
|
+
function cancelUnusedResponseBody(response) {
|
|
195
|
+
try {
|
|
196
|
+
if (!response || response.bodyUsed)
|
|
197
|
+
return;
|
|
198
|
+
const body = response.body;
|
|
199
|
+
if (!body)
|
|
200
|
+
return;
|
|
201
|
+
void body.cancel().catch(() => undefined);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Cleanup must not override the request result.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
88
207
|
function isRecord(value) {
|
|
89
208
|
return typeof value === 'object' && value !== null;
|
|
90
209
|
}
|
|
91
210
|
function isGitHubItem(value) {
|
|
92
|
-
return isRecord(value) &&
|
|
93
|
-
typeof value.
|
|
211
|
+
return (isRecord(value) &&
|
|
212
|
+
typeof value.name === 'string' &&
|
|
213
|
+
typeof value.path === 'string' &&
|
|
214
|
+
typeof value.type === 'string');
|
|
94
215
|
}
|
|
95
216
|
function isGitHubTreeItem(value) {
|
|
96
|
-
return isRecord(value) && typeof value.path === 'string' &&
|
|
97
|
-
typeof value.type === 'string';
|
|
217
|
+
return isRecord(value) && typeof value.path === 'string' && typeof value.type === 'string';
|
|
98
218
|
}
|
|
99
219
|
function parseContentsResponse(value) {
|
|
100
220
|
if (!Array.isArray(value) || !value.every(isGitHubItem)) {
|
|
@@ -103,8 +223,10 @@ function parseContentsResponse(value) {
|
|
|
103
223
|
return value;
|
|
104
224
|
}
|
|
105
225
|
function parseTreeResponse(value) {
|
|
106
|
-
if (!isRecord(value) ||
|
|
107
|
-
|
|
226
|
+
if (!isRecord(value) ||
|
|
227
|
+
typeof value.truncated !== 'boolean' ||
|
|
228
|
+
!Array.isArray(value.tree) ||
|
|
229
|
+
!value.tree.every(isGitHubTreeItem)) {
|
|
108
230
|
throw new TypeError('Invalid GitHub tree response');
|
|
109
231
|
}
|
|
110
232
|
return { tree: value.tree, truncated: value.truncated };
|
|
@@ -116,45 +238,51 @@ export function createDocsClient(options = {}) {
|
|
|
116
238
|
assertRepositoryCoordinate(owner, 'owner');
|
|
117
239
|
assertRepositoryCoordinate(repo, 'repo');
|
|
118
240
|
assertBranchRef(branch);
|
|
119
|
-
const token = options.token ??
|
|
120
|
-
|
|
121
|
-
|
|
241
|
+
const token = options.token ??
|
|
242
|
+
(typeof process !== 'undefined'
|
|
243
|
+
? (process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN)
|
|
244
|
+
: undefined);
|
|
122
245
|
const apiRepoUrl = `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`;
|
|
123
246
|
const rawRepoUrl = `https://raw.githubusercontent.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`;
|
|
124
247
|
const encodedBranch = encodeURIComponent(branch);
|
|
125
248
|
const dirTtlMs = cacheTtl(options.cacheTtlMs?.dir, DEFAULTS.dirTtlMs, 'cacheTtlMs.dir');
|
|
126
249
|
const fileTtlMs = cacheTtl(options.cacheTtlMs?.file, DEFAULTS.fileTtlMs, 'cacheTtlMs.file');
|
|
127
250
|
const dirCache = new TtlCache(dirTtlMs, 30);
|
|
128
|
-
const fileCache = new TtlCache(fileTtlMs,
|
|
251
|
+
const fileCache = new TtlCache(fileTtlMs, 200);
|
|
129
252
|
const treeCache = new TtlCache(dirTtlMs, 1);
|
|
130
253
|
const dirRequests = new Map();
|
|
131
254
|
const fileRequests = new Map();
|
|
132
255
|
const treeRequests = new Map();
|
|
133
256
|
let cacheGeneration = 0;
|
|
134
257
|
function headers() {
|
|
135
|
-
const
|
|
258
|
+
const requestHeaders = {
|
|
259
|
+
Accept: 'application/vnd.github.v3+json',
|
|
260
|
+
};
|
|
136
261
|
if (token)
|
|
137
|
-
|
|
138
|
-
return
|
|
262
|
+
requestHeaders.Authorization = `Bearer ${token}`;
|
|
263
|
+
return requestHeaders;
|
|
139
264
|
}
|
|
140
265
|
async function withResponse(url, timeoutMs, consume) {
|
|
141
266
|
const ctrl = new AbortController();
|
|
142
|
-
const timer = setTimeout(() =>
|
|
267
|
+
const timer = setTimeout(() => {
|
|
268
|
+
ctrl.abort();
|
|
269
|
+
}, timeoutMs);
|
|
270
|
+
let response;
|
|
143
271
|
try {
|
|
144
|
-
|
|
272
|
+
response = await fetch(url, { signal: ctrl.signal, headers: headers() });
|
|
145
273
|
return await consume(response);
|
|
146
274
|
}
|
|
147
275
|
finally {
|
|
148
276
|
clearTimeout(timer);
|
|
277
|
+
// Not awaited: a custom transport's cancel may never settle.
|
|
278
|
+
cancelUnusedResponseBody(response);
|
|
149
279
|
}
|
|
150
280
|
}
|
|
151
|
-
function recoverFailure(cache, key, path, error, copy = value => value) {
|
|
281
|
+
function recoverFailure(cache, key, path, error, copy = (value) => value) {
|
|
152
282
|
const stale = cache.getStale(key);
|
|
153
283
|
if (stale !== undefined)
|
|
154
284
|
return copy(stale);
|
|
155
|
-
const message = error instanceof Error && error.name === 'AbortError'
|
|
156
|
-
? 'Request timed out'
|
|
157
|
-
: String(error);
|
|
285
|
+
const message = error instanceof Error && error.name === 'AbortError' ? 'Request timed out' : String(error);
|
|
158
286
|
throw new DocsFetchError(path, null, message);
|
|
159
287
|
}
|
|
160
288
|
function shareRequest(requests, key, load) {
|
|
@@ -170,27 +298,27 @@ export function createDocsClient(options = {}) {
|
|
|
170
298
|
requests.set(key, request);
|
|
171
299
|
return request;
|
|
172
300
|
}
|
|
173
|
-
async function loadDir(path,
|
|
301
|
+
async function loadDir(path, generation) {
|
|
174
302
|
const url = `${apiRepoUrl}/contents/${encodePath(path)}?ref=${encodedBranch}`;
|
|
175
303
|
try {
|
|
176
304
|
return await withResponse(url, 10000, async (response) => {
|
|
177
305
|
if (!response.ok) {
|
|
178
|
-
const stale = dirCache.getStale(
|
|
179
|
-
if (
|
|
306
|
+
const stale = dirCache.getStale(path);
|
|
307
|
+
if (stale !== undefined && (await isTransientResponse(response)))
|
|
180
308
|
return copyItems(stale);
|
|
181
|
-
throw new DocsFetchError(path, response.status, `HTTP ${response.status}`);
|
|
309
|
+
throw new DocsFetchError(path, response.status, `HTTP ${String(response.status)}`);
|
|
182
310
|
}
|
|
183
311
|
const data = parseContentsResponse(await response.json());
|
|
184
312
|
const items = filterAndSort(data);
|
|
185
313
|
if (generation === cacheGeneration)
|
|
186
|
-
dirCache.set(
|
|
314
|
+
dirCache.set(path, copyItems(items));
|
|
187
315
|
return items;
|
|
188
316
|
});
|
|
189
317
|
}
|
|
190
318
|
catch (error) {
|
|
191
319
|
if (error instanceof DocsFetchError)
|
|
192
320
|
throw error;
|
|
193
|
-
return recoverFailure(dirCache,
|
|
321
|
+
return recoverFailure(dirCache, path, path, error, copyItems);
|
|
194
322
|
}
|
|
195
323
|
}
|
|
196
324
|
function listDir(path = '') {
|
|
@@ -198,12 +326,12 @@ export function createDocsClient(options = {}) {
|
|
|
198
326
|
assertRepositoryPath(path, true);
|
|
199
327
|
}
|
|
200
328
|
catch (error) {
|
|
201
|
-
return
|
|
329
|
+
return reject(error);
|
|
202
330
|
}
|
|
203
331
|
const hit = dirCache.get(path);
|
|
204
332
|
if (hit)
|
|
205
333
|
return Promise.resolve(copyItems(hit));
|
|
206
|
-
return shareRequest(dirRequests, path, () => loadDir(path,
|
|
334
|
+
return shareRequest(dirRequests, path, () => loadDir(path, cacheGeneration)).then(copyItems);
|
|
207
335
|
}
|
|
208
336
|
async function loadAll(generation) {
|
|
209
337
|
const key = '__tree__';
|
|
@@ -212,9 +340,9 @@ export function createDocsClient(options = {}) {
|
|
|
212
340
|
return await withResponse(url, 20000, async (response) => {
|
|
213
341
|
if (!response.ok) {
|
|
214
342
|
const stale = treeCache.getStale(key);
|
|
215
|
-
if (
|
|
343
|
+
if (stale !== undefined && (await isTransientResponse(response)))
|
|
216
344
|
return copyItems(stale);
|
|
217
|
-
throw new DocsFetchError('', response.status, `HTTP ${response.status}`);
|
|
345
|
+
throw new DocsFetchError('', response.status, `HTTP ${String(response.status)}`);
|
|
218
346
|
}
|
|
219
347
|
const data = parseTreeResponse(await response.json());
|
|
220
348
|
if (data.truncated) {
|
|
@@ -240,7 +368,10 @@ export function createDocsClient(options = {}) {
|
|
|
240
368
|
const hit = treeCache.get(key);
|
|
241
369
|
if (hit)
|
|
242
370
|
return Promise.resolve(copyItems(hit));
|
|
243
|
-
return shareRequest(treeRequests, key, () => loadAll(cacheGeneration));
|
|
371
|
+
return shareRequest(treeRequests, key, () => loadAll(cacheGeneration)).then(copyItems);
|
|
372
|
+
}
|
|
373
|
+
async function listSections() {
|
|
374
|
+
return sectionsFromItems(await listAll());
|
|
244
375
|
}
|
|
245
376
|
async function loadFile(path, generation) {
|
|
246
377
|
const url = `${rawRepoUrl}/${encodedBranch}/${encodePath(path)}`;
|
|
@@ -248,9 +379,9 @@ export function createDocsClient(options = {}) {
|
|
|
248
379
|
return await withResponse(url, 15000, async (response) => {
|
|
249
380
|
if (!response.ok) {
|
|
250
381
|
const stale = fileCache.getStale(path);
|
|
251
|
-
if (
|
|
382
|
+
if (stale !== undefined && (await isTransientResponse(response)))
|
|
252
383
|
return stale;
|
|
253
|
-
throw new DocsFetchError(path, response.status, `HTTP ${response.status}`);
|
|
384
|
+
throw new DocsFetchError(path, response.status, `HTTP ${String(response.status)}`);
|
|
254
385
|
}
|
|
255
386
|
const content = await response.text();
|
|
256
387
|
if (generation === cacheGeneration)
|
|
@@ -269,13 +400,55 @@ export function createDocsClient(options = {}) {
|
|
|
269
400
|
assertRepositoryPath(path, false);
|
|
270
401
|
}
|
|
271
402
|
catch (error) {
|
|
272
|
-
return
|
|
403
|
+
return reject(error);
|
|
273
404
|
}
|
|
274
405
|
const hit = fileCache.get(path);
|
|
275
406
|
if (hit !== undefined)
|
|
276
407
|
return Promise.resolve(hit);
|
|
277
408
|
return shareRequest(fileRequests, path, () => loadFile(path, cacheGeneration));
|
|
278
409
|
}
|
|
410
|
+
async function getDocument(path) {
|
|
411
|
+
if (!path.toLowerCase().endsWith('.md')) {
|
|
412
|
+
throw new TypeError('path must point to a Markdown document');
|
|
413
|
+
}
|
|
414
|
+
return parseDoc(path, await getFile(path));
|
|
415
|
+
}
|
|
416
|
+
async function search(query, options = {}) {
|
|
417
|
+
const normalizedQuery = query.trim();
|
|
418
|
+
if (!normalizedQuery)
|
|
419
|
+
throw new TypeError('query must not be empty');
|
|
420
|
+
const limit = searchLimit(options.limit);
|
|
421
|
+
const pathPrefix = options.pathPrefix ?? '';
|
|
422
|
+
assertRepositoryPath(pathPrefix, true);
|
|
423
|
+
if (limit === 0)
|
|
424
|
+
return [];
|
|
425
|
+
const all = await listAll();
|
|
426
|
+
const candidates = pathPrefix
|
|
427
|
+
? all.filter((item) => item.path.startsWith(`${pathPrefix}/`))
|
|
428
|
+
: all;
|
|
429
|
+
let loaded = 0;
|
|
430
|
+
let firstFailure;
|
|
431
|
+
const matches = await mapConcurrent(candidates, SEARCH_CONCURRENCY, async (item) => {
|
|
432
|
+
try {
|
|
433
|
+
const document = await getDocument(item.path);
|
|
434
|
+
loaded += 1;
|
|
435
|
+
return searchDoc(document, normalizedQuery);
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
if (error instanceof DocsFetchError) {
|
|
439
|
+
firstFailure ?? (firstFailure = error);
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
if (loaded === 0 && firstFailure)
|
|
446
|
+
throw firstFailure;
|
|
447
|
+
return matches
|
|
448
|
+
.filter((result) => result !== null)
|
|
449
|
+
.sort((left, right) => right.score - left.score || left.path.localeCompare(right.path))
|
|
450
|
+
.slice(0, limit);
|
|
451
|
+
}
|
|
279
452
|
function clear() {
|
|
280
453
|
cacheGeneration += 1;
|
|
281
454
|
dirCache.clear();
|
|
@@ -285,6 +458,5 @@ export function createDocsClient(options = {}) {
|
|
|
285
458
|
fileRequests.clear();
|
|
286
459
|
treeRequests.clear();
|
|
287
460
|
}
|
|
288
|
-
return { listDir, listAll, getFile, clear };
|
|
461
|
+
return { listDir, listAll, listSections, getFile, getDocument, search, clear };
|
|
289
462
|
}
|
|
290
|
-
//# sourceMappingURL=client.js.map
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
const SUMMARY_LENGTH = 160;
|
|
2
|
+
const EXCERPT_LENGTH = 180;
|
|
3
|
+
const GRAPHEME_SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
4
|
+
const LIST_ITEM = /^( {0,3}(?:[-+*]|\d{1,9}[.)]))([ \t]+)/;
|
|
5
|
+
const NORMALIZATION_CHUNK = 512;
|
|
6
|
+
// NFKC never joins these characters to what precedes them, so chunks split before them.
|
|
7
|
+
const NORMALIZATION_BOUNDARY = /[ -~\u4e00-\u9fff]/g;
|
|
8
|
+
const COMPONENT_ATTRIBUTES = {
|
|
9
|
+
Band: ['alt', 'source'],
|
|
10
|
+
Figure: ['alt', 'caption', 'date', 'source'],
|
|
11
|
+
LinkCard: ['title', 'desc', 'alt'],
|
|
12
|
+
PageHero: ['title', 'lede', 'alt', 'source'],
|
|
13
|
+
Split: ['heading', 'alt'],
|
|
14
|
+
TimelineEntry: ['year', 'title'],
|
|
15
|
+
};
|
|
16
|
+
function splitFrontmatter(content) {
|
|
17
|
+
const source = content.startsWith('\uFEFF') ? content.slice(1) : content;
|
|
18
|
+
const match = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/.exec(source);
|
|
19
|
+
if (!match)
|
|
20
|
+
return { body: source, frontmatter: '' };
|
|
21
|
+
return {
|
|
22
|
+
body: source.slice(match[0].length),
|
|
23
|
+
frontmatter: match[1] ?? '',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function decodeScalar(value) {
|
|
27
|
+
const trimmed = value.trim();
|
|
28
|
+
if (!trimmed || trimmed === '|' || trimmed === '>' || trimmed === '~' || trimmed === 'null') {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(trimmed);
|
|
34
|
+
return typeof parsed === 'string' ? parsed : undefined;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return trimmed.slice(1, -1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
41
|
+
return trimmed.slice(1, -1).replace(/''/g, "'");
|
|
42
|
+
}
|
|
43
|
+
return trimmed;
|
|
44
|
+
}
|
|
45
|
+
function frontmatterValue(frontmatter, key) {
|
|
46
|
+
for (const line of frontmatter.split(/\r?\n/)) {
|
|
47
|
+
if (/^[ \t]/.test(line))
|
|
48
|
+
continue;
|
|
49
|
+
const separator = line.indexOf(':');
|
|
50
|
+
if (separator < 0 || line.slice(0, separator).trim() !== key)
|
|
51
|
+
continue;
|
|
52
|
+
return decodeScalar(line.slice(separator + 1));
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function cleanInline(value) {
|
|
57
|
+
return value
|
|
58
|
+
.replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
|
|
59
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
|
|
60
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
61
|
+
.replace(/<[^>]+>/g, '')
|
|
62
|
+
.replace(/[*_~]+/g, '')
|
|
63
|
+
.replace(/\s+/g, ' ')
|
|
64
|
+
.trim();
|
|
65
|
+
}
|
|
66
|
+
function quoteContainer(line) {
|
|
67
|
+
let depth = 0;
|
|
68
|
+
let rest = line;
|
|
69
|
+
for (;;) {
|
|
70
|
+
const prefix = /^ {0,3}>[ \t]?/.exec(rest)?.[0];
|
|
71
|
+
if (!prefix)
|
|
72
|
+
return { depth, rest };
|
|
73
|
+
depth += 1;
|
|
74
|
+
rest = rest.slice(prefix.length);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function transitionFence(line, current) {
|
|
78
|
+
const quote = quoteContainer(line);
|
|
79
|
+
let candidate = quote.rest;
|
|
80
|
+
let listIndent = 0;
|
|
81
|
+
if (current) {
|
|
82
|
+
if (quote.depth < current.quoteDepth)
|
|
83
|
+
return transitionFence(line, undefined);
|
|
84
|
+
if (quote.depth !== current.quoteDepth)
|
|
85
|
+
return { delimiter: false, fence: current };
|
|
86
|
+
if (current.listIndent > 0) {
|
|
87
|
+
const indentation = /^ */.exec(candidate)?.[0].length ?? 0;
|
|
88
|
+
if (candidate.trim() !== '' && indentation < current.listIndent) {
|
|
89
|
+
return transitionFence(line, undefined);
|
|
90
|
+
}
|
|
91
|
+
candidate = candidate.slice(Math.min(indentation, current.listIndent));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
listIndent = LIST_ITEM.exec(candidate)?.[0].length ?? 0;
|
|
96
|
+
candidate = candidate.slice(listIndent);
|
|
97
|
+
}
|
|
98
|
+
const match = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(candidate);
|
|
99
|
+
const sequence = match?.[1];
|
|
100
|
+
if (!sequence)
|
|
101
|
+
return { delimiter: false, fence: current };
|
|
102
|
+
const marker = sequence.startsWith('`') ? '`' : '~';
|
|
103
|
+
const suffix = match[2] ?? '';
|
|
104
|
+
if (!current) {
|
|
105
|
+
if (marker === '`' && suffix.includes('`')) {
|
|
106
|
+
return { delimiter: false, fence: undefined };
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
delimiter: true,
|
|
110
|
+
fence: { length: sequence.length, listIndent, marker, quoteDepth: quote.depth },
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (marker === current.marker && sequence.length >= current.length && /^[ \t]*$/.test(suffix)) {
|
|
114
|
+
return { delimiter: true, fence: undefined };
|
|
115
|
+
}
|
|
116
|
+
return { delimiter: false, fence: current };
|
|
117
|
+
}
|
|
118
|
+
function indentWidth(line) {
|
|
119
|
+
let width = 0;
|
|
120
|
+
for (const character of line) {
|
|
121
|
+
if (character === ' ')
|
|
122
|
+
width += 1;
|
|
123
|
+
else if (character === '\t')
|
|
124
|
+
width += 4 - (width % 4);
|
|
125
|
+
else
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
return width;
|
|
129
|
+
}
|
|
130
|
+
function proseLines(body) {
|
|
131
|
+
let fence;
|
|
132
|
+
let afterBreak = true;
|
|
133
|
+
let inCode = false;
|
|
134
|
+
let listIndent = 0;
|
|
135
|
+
return body.split(/\r?\n/).map((line) => {
|
|
136
|
+
const transition = transitionFence(line, fence);
|
|
137
|
+
fence = transition.fence;
|
|
138
|
+
if (transition.delimiter || fence) {
|
|
139
|
+
afterBreak = true;
|
|
140
|
+
inCode = false;
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
const candidate = quoteContainer(line).rest;
|
|
144
|
+
if (candidate.trim() === '') {
|
|
145
|
+
afterBreak = true;
|
|
146
|
+
return line;
|
|
147
|
+
}
|
|
148
|
+
const width = indentWidth(candidate);
|
|
149
|
+
if (afterBreak && width < listIndent)
|
|
150
|
+
listIndent = 0;
|
|
151
|
+
inCode = width - listIndent >= 4 && (afterBreak || inCode);
|
|
152
|
+
afterBreak = false;
|
|
153
|
+
if (inCode)
|
|
154
|
+
return undefined;
|
|
155
|
+
const item = LIST_ITEM.exec(candidate);
|
|
156
|
+
if (!item)
|
|
157
|
+
return line;
|
|
158
|
+
const marker = item[1]?.length ?? 0;
|
|
159
|
+
const padding = item[2] ?? '';
|
|
160
|
+
const rest = candidate.slice(item[0].length);
|
|
161
|
+
if (padding.includes('\t') || padding.length >= 5 || /^(?: {4}|\t)/.test(rest)) {
|
|
162
|
+
listIndent = marker + 1;
|
|
163
|
+
inCode = true;
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
listIndent = marker + padding.length;
|
|
167
|
+
return line;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function extractTitle(body) {
|
|
171
|
+
for (const line of proseLines(body)) {
|
|
172
|
+
if (line === undefined)
|
|
173
|
+
continue;
|
|
174
|
+
const match = /^#\s+(.+?)\s*$/.exec(line);
|
|
175
|
+
if (match?.[1])
|
|
176
|
+
return cleanInline(match[1].replace(/\s+#+\s*$/, ''));
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
function truncate(value, length) {
|
|
181
|
+
let end = 0;
|
|
182
|
+
let codePoints = 0;
|
|
183
|
+
for (const { index, segment } of GRAPHEME_SEGMENTER.segment(value)) {
|
|
184
|
+
codePoints += Array.from(segment).length;
|
|
185
|
+
if (codePoints > length)
|
|
186
|
+
return `${value.slice(0, end).trimEnd()}…`;
|
|
187
|
+
end = index + segment.length;
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
function extractSummary(body) {
|
|
192
|
+
const paragraphs = [];
|
|
193
|
+
let current = [];
|
|
194
|
+
let inContainer = false;
|
|
195
|
+
let inTag = false;
|
|
196
|
+
let hiddenTag;
|
|
197
|
+
const finishParagraph = () => {
|
|
198
|
+
if (current.length > 0)
|
|
199
|
+
paragraphs.push(current.join(' '));
|
|
200
|
+
current = [];
|
|
201
|
+
};
|
|
202
|
+
for (const rawLine of proseLines(body)) {
|
|
203
|
+
if (rawLine === undefined) {
|
|
204
|
+
finishParagraph();
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const line = rawLine.trim();
|
|
208
|
+
if (hiddenTag) {
|
|
209
|
+
if (line.toLowerCase().includes(`</${hiddenTag}>`))
|
|
210
|
+
hiddenTag = undefined;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const hiddenStart = /^<(script|style)(?:\s|>)/i.exec(line)?.[1]?.toLowerCase();
|
|
214
|
+
if (hiddenStart === 'script' || hiddenStart === 'style') {
|
|
215
|
+
hiddenTag = line.toLowerCase().includes(`</${hiddenStart}>`) ? undefined : hiddenStart;
|
|
216
|
+
finishParagraph();
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (line.startsWith(':::')) {
|
|
220
|
+
inContainer = !inContainer;
|
|
221
|
+
finishParagraph();
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (inContainer)
|
|
225
|
+
continue;
|
|
226
|
+
if (inTag) {
|
|
227
|
+
if (line.endsWith('>'))
|
|
228
|
+
inTag = false;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (line.startsWith('<')) {
|
|
232
|
+
if (!line.endsWith('>'))
|
|
233
|
+
inTag = true;
|
|
234
|
+
finishParagraph();
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (line === '') {
|
|
238
|
+
finishParagraph();
|
|
239
|
+
if (paragraphs.length > 0)
|
|
240
|
+
break;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (/^(?:#{1,6}\s|>|\||[-*+]\s|\d+[.)]\s|(?:-{3,}|\*{3,}|_{3,})$)/.test(line)) {
|
|
244
|
+
finishParagraph();
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
current.push(line);
|
|
248
|
+
}
|
|
249
|
+
finishParagraph();
|
|
250
|
+
return truncate(cleanInline(paragraphs[0] ?? ''), SUMMARY_LENGTH);
|
|
251
|
+
}
|
|
252
|
+
function markdownText(body) {
|
|
253
|
+
return cleanInline(body
|
|
254
|
+
.replace(/<!--[\s\S]*?-->/g, ' ')
|
|
255
|
+
.replace(/<(?:script|style)(?:\s[^>]*)?>[\s\S]*?<\/(?:script|style)>/gi, ' ')
|
|
256
|
+
.replace(/<[A-Z][A-Za-z\d]*(?:\s[^>]*)?\s*\/\s*>/g, ' ')
|
|
257
|
+
.replace(/<\/?[A-Z][A-Za-z\d]*(?:\s[^>]*)?>/g, ' ')
|
|
258
|
+
.replace(/^---\s*$/gm, ' ')
|
|
259
|
+
.replace(/^:::[^\n]*$/gm, ' ')
|
|
260
|
+
.replace(/^\s*(?:#{1,6}|>|[-*+]|\d+[.)])\s+/gm, ''));
|
|
261
|
+
}
|
|
262
|
+
function parseAttributes(source) {
|
|
263
|
+
const attributes = {};
|
|
264
|
+
const pattern = /([:@A-Za-z_][:@\w.-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
|
|
265
|
+
for (const match of source.matchAll(pattern)) {
|
|
266
|
+
const name = match[1];
|
|
267
|
+
if (!name)
|
|
268
|
+
continue;
|
|
269
|
+
attributes[name] = match[2] ?? match[3] ?? match[4] ?? true;
|
|
270
|
+
}
|
|
271
|
+
return attributes;
|
|
272
|
+
}
|
|
273
|
+
function componentSource(body) {
|
|
274
|
+
return proseLines(body)
|
|
275
|
+
.filter((line) => line !== undefined)
|
|
276
|
+
.join('\n')
|
|
277
|
+
.replace(/<!--[\s\S]*?-->/g, ' ');
|
|
278
|
+
}
|
|
279
|
+
function extractComponents(body) {
|
|
280
|
+
const components = [];
|
|
281
|
+
const pattern = /<([A-Z][A-Za-z\d]*)\b((?:[^>"']|"[^"]*"|'[^']*')*)\/?\s*>/g;
|
|
282
|
+
for (const match of componentSource(body).matchAll(pattern)) {
|
|
283
|
+
const name = match[1];
|
|
284
|
+
if (!name)
|
|
285
|
+
continue;
|
|
286
|
+
components.push({ attributes: parseAttributes(match[2] ?? ''), name });
|
|
287
|
+
}
|
|
288
|
+
return components;
|
|
289
|
+
}
|
|
290
|
+
function componentText(components) {
|
|
291
|
+
const values = [];
|
|
292
|
+
for (const component of components) {
|
|
293
|
+
if (component.name === 'FactStrip') {
|
|
294
|
+
const facts = component.attributes[':facts'];
|
|
295
|
+
if (typeof facts === 'string') {
|
|
296
|
+
for (const match of facts.matchAll(/\b(?:label|value)\s*:\s*(['"])(.*?)\1/gs)) {
|
|
297
|
+
if (match[2])
|
|
298
|
+
values.push(match[2].replace(/\\(['"\\])/g, '$1'));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
for (const name of COMPONENT_ATTRIBUTES[component.name] ?? []) {
|
|
303
|
+
const value = component.attributes[name];
|
|
304
|
+
if (typeof value === 'string')
|
|
305
|
+
values.push(value);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return values.join(' ');
|
|
309
|
+
}
|
|
310
|
+
function routeFromPath(path) {
|
|
311
|
+
const withoutExtension = path.replace(/\.md$/i, '');
|
|
312
|
+
if (withoutExtension === 'index')
|
|
313
|
+
return '/';
|
|
314
|
+
if (withoutExtension.endsWith('/index'))
|
|
315
|
+
return `/${withoutExtension.slice(0, -5)}`;
|
|
316
|
+
return `/${withoutExtension}`;
|
|
317
|
+
}
|
|
318
|
+
function fallbackTitle(path) {
|
|
319
|
+
const name = path.slice(path.lastIndexOf('/') + 1);
|
|
320
|
+
return name.replace(/\.md$/i, '');
|
|
321
|
+
}
|
|
322
|
+
export function parseDoc(path, content) {
|
|
323
|
+
const { body, frontmatter } = splitFrontmatter(content);
|
|
324
|
+
const components = extractComponents(body);
|
|
325
|
+
const hero = components.find((component) => component.name === 'PageHero');
|
|
326
|
+
const heroTitle = hero?.attributes.title;
|
|
327
|
+
const heroSummary = hero?.attributes.lede;
|
|
328
|
+
const name = path.slice(path.lastIndexOf('/') + 1);
|
|
329
|
+
const title = cleanInline(extractTitle(body) ??
|
|
330
|
+
frontmatterValue(frontmatter, 'title') ??
|
|
331
|
+
(typeof heroTitle === 'string' ? heroTitle : ''));
|
|
332
|
+
const summary = cleanInline(frontmatterValue(frontmatter, 'summary') ??
|
|
333
|
+
(typeof heroSummary === 'string' ? heroSummary : extractSummary(body)));
|
|
334
|
+
return {
|
|
335
|
+
components,
|
|
336
|
+
content,
|
|
337
|
+
name,
|
|
338
|
+
path,
|
|
339
|
+
route: routeFromPath(path),
|
|
340
|
+
section: path.includes('/') ? (path.split('/')[0] ?? null) : null,
|
|
341
|
+
summary: truncate(summary, SUMMARY_LENGTH),
|
|
342
|
+
title: title || fallbackTitle(path),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function normalize(value) {
|
|
346
|
+
// Lowercasing keeps final sigma (ς) where a search for Σ yields σ.
|
|
347
|
+
return value
|
|
348
|
+
.normalize('NFKC')
|
|
349
|
+
.toLowerCase()
|
|
350
|
+
.replace(/\u03c2/g, '\u03c3');
|
|
351
|
+
}
|
|
352
|
+
function normalizeChunks(text) {
|
|
353
|
+
const offsets = [];
|
|
354
|
+
const sources = [];
|
|
355
|
+
const parts = [];
|
|
356
|
+
let length = 0;
|
|
357
|
+
for (let start = 0; start < text.length;) {
|
|
358
|
+
NORMALIZATION_BOUNDARY.lastIndex = start + NORMALIZATION_CHUNK;
|
|
359
|
+
const end = NORMALIZATION_BOUNDARY.exec(text)?.index ?? text.length;
|
|
360
|
+
const part = normalize(text.slice(start, end));
|
|
361
|
+
offsets.push(length);
|
|
362
|
+
sources.push(start);
|
|
363
|
+
parts.push(part);
|
|
364
|
+
length += part.length;
|
|
365
|
+
start = end;
|
|
366
|
+
}
|
|
367
|
+
return { offsets, sources, value: parts.join('') };
|
|
368
|
+
}
|
|
369
|
+
function lastIndexAtMost(count, target, valueAt) {
|
|
370
|
+
let low = 0;
|
|
371
|
+
let high = count - 1;
|
|
372
|
+
while (low < high) {
|
|
373
|
+
const middle = Math.ceil((low + high) / 2);
|
|
374
|
+
if (valueAt(middle) <= target)
|
|
375
|
+
low = middle;
|
|
376
|
+
else
|
|
377
|
+
high = middle - 1;
|
|
378
|
+
}
|
|
379
|
+
return low;
|
|
380
|
+
}
|
|
381
|
+
function graphemeAt(graphemes, position) {
|
|
382
|
+
const part = graphemes.containing(position);
|
|
383
|
+
if (!part)
|
|
384
|
+
return { codePoints: 0, end: position, start: position };
|
|
385
|
+
return {
|
|
386
|
+
codePoints: Array.from(part.segment).length,
|
|
387
|
+
end: part.index + part.segment.length,
|
|
388
|
+
start: part.index,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function normalizedLength(text, normalized, position) {
|
|
392
|
+
const { offsets, sources } = normalized;
|
|
393
|
+
const chunk = lastIndexAtMost(sources.length, position, (index) => sources[index] ?? 0);
|
|
394
|
+
const start = sources[chunk] ?? 0;
|
|
395
|
+
return (offsets[chunk] ?? 0) + normalize(text.slice(start, position)).length;
|
|
396
|
+
}
|
|
397
|
+
function sourceBoundary(text, normalized, graphemes, offset) {
|
|
398
|
+
const { offsets, sources } = normalized;
|
|
399
|
+
const chunk = lastIndexAtMost(offsets.length, offset, (index) => offsets[index] ?? 0);
|
|
400
|
+
const chunkEnd = sources[chunk + 1] ?? text.length;
|
|
401
|
+
const boundaries = [graphemeAt(graphemes, sources[chunk] ?? 0).start];
|
|
402
|
+
for (let position = boundaries[0] ?? 0; position < chunkEnd;) {
|
|
403
|
+
position = graphemeAt(graphemes, position).end;
|
|
404
|
+
boundaries.push(position);
|
|
405
|
+
}
|
|
406
|
+
const lengths = new Map();
|
|
407
|
+
const lengthAt = (index) => {
|
|
408
|
+
const position = boundaries[index] ?? 0;
|
|
409
|
+
const length = lengths.get(position) ?? normalizedLength(text, normalized, position);
|
|
410
|
+
lengths.set(position, length);
|
|
411
|
+
return length;
|
|
412
|
+
};
|
|
413
|
+
const index = lastIndexAtMost(boundaries.length, offset, lengthAt);
|
|
414
|
+
return { length: lengthAt(index), position: boundaries[index] ?? 0 };
|
|
415
|
+
}
|
|
416
|
+
function countMatches(value, term) {
|
|
417
|
+
let count = 0;
|
|
418
|
+
let offset = 0;
|
|
419
|
+
while (offset < value.length) {
|
|
420
|
+
const index = value.indexOf(term, offset);
|
|
421
|
+
if (index < 0)
|
|
422
|
+
break;
|
|
423
|
+
count += 1;
|
|
424
|
+
offset = index + Math.max(term.length, 1);
|
|
425
|
+
}
|
|
426
|
+
return count;
|
|
427
|
+
}
|
|
428
|
+
function excerpt(text, query, terms) {
|
|
429
|
+
if (!text)
|
|
430
|
+
return '';
|
|
431
|
+
const normalized = normalizeChunks(text);
|
|
432
|
+
const exactIndex = normalized.value.indexOf(query);
|
|
433
|
+
let matchIndex = exactIndex;
|
|
434
|
+
let matchLength = query.length;
|
|
435
|
+
if (matchIndex < 0) {
|
|
436
|
+
matchIndex = Number.POSITIVE_INFINITY;
|
|
437
|
+
for (const term of terms) {
|
|
438
|
+
const index = normalized.value.indexOf(term);
|
|
439
|
+
if (index >= 0 && index < matchIndex) {
|
|
440
|
+
matchIndex = index;
|
|
441
|
+
matchLength = term.length;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (!Number.isFinite(matchIndex))
|
|
446
|
+
return truncate(text, EXCERPT_LENGTH);
|
|
447
|
+
const graphemes = GRAPHEME_SEGMENTER.segment(text);
|
|
448
|
+
const matchStart = sourceBoundary(text, normalized, graphemes, matchIndex).position;
|
|
449
|
+
const endOffset = Math.min(normalized.value.length, matchIndex + matchLength);
|
|
450
|
+
const floor = sourceBoundary(text, normalized, graphemes, endOffset);
|
|
451
|
+
const matchEnd = floor.length < endOffset ? graphemeAt(graphemes, floor.position).end : floor.position;
|
|
452
|
+
const matchCodePoints = Array.from(text.slice(matchStart, matchEnd)).length;
|
|
453
|
+
const contextLimit = Math.min(Math.floor(EXCERPT_LENGTH / 3), Math.max(0, EXCERPT_LENGTH - matchCodePoints));
|
|
454
|
+
let start = matchStart;
|
|
455
|
+
let contextCodePoints = 0;
|
|
456
|
+
while (start > 0) {
|
|
457
|
+
const previous = graphemeAt(graphemes, start - 1);
|
|
458
|
+
if (contextCodePoints + previous.codePoints > contextLimit)
|
|
459
|
+
break;
|
|
460
|
+
contextCodePoints += previous.codePoints;
|
|
461
|
+
start = previous.start;
|
|
462
|
+
}
|
|
463
|
+
let end = start;
|
|
464
|
+
let selectedCodePoints = 0;
|
|
465
|
+
while (end < text.length) {
|
|
466
|
+
const next = graphemeAt(graphemes, end);
|
|
467
|
+
if (end > start && selectedCodePoints + next.codePoints > EXCERPT_LENGTH)
|
|
468
|
+
break;
|
|
469
|
+
selectedCodePoints += next.codePoints;
|
|
470
|
+
end = next.end;
|
|
471
|
+
}
|
|
472
|
+
const prefix = start > 0 ? '…' : '';
|
|
473
|
+
const suffix = end < text.length ? '…' : '';
|
|
474
|
+
return `${prefix}${text.slice(start, end).trim()}${suffix}`;
|
|
475
|
+
}
|
|
476
|
+
export function searchDoc(page, query) {
|
|
477
|
+
const normalizedQuery = normalize(query.trim());
|
|
478
|
+
if (!normalizedQuery)
|
|
479
|
+
throw new TypeError('query must not be empty');
|
|
480
|
+
const terms = normalizedQuery.split(/\s+/).filter(Boolean);
|
|
481
|
+
const componentValue = componentText(page.components);
|
|
482
|
+
const bodyValue = markdownText(splitFrontmatter(page.content).body);
|
|
483
|
+
const textValue = `${componentValue} ${bodyValue}`.trim();
|
|
484
|
+
const title = normalize(page.title);
|
|
485
|
+
const summary = normalize(page.summary);
|
|
486
|
+
const path = normalize(page.path.replace(/[-_/]+/g, ' '));
|
|
487
|
+
const components = normalize(componentValue);
|
|
488
|
+
const text = normalize(bodyValue);
|
|
489
|
+
const combined = `${title}\n${summary}\n${path}\n${components}\n${text}`;
|
|
490
|
+
if (!terms.every((term) => combined.includes(term)))
|
|
491
|
+
return null;
|
|
492
|
+
let score = title === normalizedQuery ? 240 : 0;
|
|
493
|
+
score += countMatches(title, normalizedQuery) * 80;
|
|
494
|
+
score += countMatches(summary, normalizedQuery) * 40;
|
|
495
|
+
score += countMatches(components, normalizedQuery) * 60;
|
|
496
|
+
score += countMatches(path, normalizedQuery) * 24;
|
|
497
|
+
score += Math.min(countMatches(text, normalizedQuery), 5) * 10;
|
|
498
|
+
for (const term of terms) {
|
|
499
|
+
score += countMatches(title, term) * 24;
|
|
500
|
+
score += countMatches(summary, term) * 12;
|
|
501
|
+
score += countMatches(components, term) * 18;
|
|
502
|
+
score += countMatches(path, term) * 8;
|
|
503
|
+
score += Math.min(countMatches(text, term), 5) * 3;
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
excerpt: excerpt(textValue, normalizedQuery, terms),
|
|
507
|
+
name: page.name,
|
|
508
|
+
path: page.path,
|
|
509
|
+
route: page.route,
|
|
510
|
+
score,
|
|
511
|
+
section: page.section,
|
|
512
|
+
summary: page.summary,
|
|
513
|
+
title: page.title,
|
|
514
|
+
};
|
|
515
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { createDocsClient } from './client.js';
|
|
2
|
-
export
|
|
2
|
+
export { parseDoc } from './content.js';
|
|
3
|
+
export type { DocComponent, DocItem, DocPage, DocSection, DocsClient, DocsClientOptions, DocsSearchOptions, DocsSearchResult, } from './types.js';
|
|
3
4
|
export { DocsFetchError } from './types.js';
|
|
4
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,39 @@ export interface DocItem {
|
|
|
3
3
|
path: string;
|
|
4
4
|
type: 'file' | 'dir';
|
|
5
5
|
}
|
|
6
|
+
export interface DocComponent {
|
|
7
|
+
attributes: Readonly<Record<string, string | true>>;
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DocPage {
|
|
11
|
+
components: DocComponent[];
|
|
12
|
+
content: string;
|
|
13
|
+
name: string;
|
|
14
|
+
path: string;
|
|
15
|
+
route: string;
|
|
16
|
+
section: string | null;
|
|
17
|
+
summary: string;
|
|
18
|
+
title: string;
|
|
19
|
+
}
|
|
20
|
+
export interface DocSection {
|
|
21
|
+
count: number;
|
|
22
|
+
indexPath?: string;
|
|
23
|
+
path: string;
|
|
24
|
+
}
|
|
25
|
+
export interface DocsSearchOptions {
|
|
26
|
+
limit?: number;
|
|
27
|
+
pathPrefix?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface DocsSearchResult {
|
|
30
|
+
excerpt: string;
|
|
31
|
+
name: string;
|
|
32
|
+
path: string;
|
|
33
|
+
route: string;
|
|
34
|
+
score: number;
|
|
35
|
+
section: string | null;
|
|
36
|
+
summary: string;
|
|
37
|
+
title: string;
|
|
38
|
+
}
|
|
6
39
|
export interface DocsClientOptions {
|
|
7
40
|
owner?: string;
|
|
8
41
|
repo?: string;
|
|
@@ -16,7 +49,10 @@ export interface DocsClientOptions {
|
|
|
16
49
|
export interface DocsClient {
|
|
17
50
|
listDir(path?: string): Promise<DocItem[]>;
|
|
18
51
|
listAll(): Promise<DocItem[]>;
|
|
52
|
+
listSections(): Promise<DocSection[]>;
|
|
19
53
|
getFile(path: string): Promise<string>;
|
|
54
|
+
getDocument(path: string): Promise<DocPage>;
|
|
55
|
+
search(query: string, options?: DocsSearchOptions): Promise<DocsSearchResult[]>;
|
|
20
56
|
clear(): void;
|
|
21
57
|
}
|
|
22
58
|
export declare class DocsFetchError extends Error {
|
|
@@ -24,4 +60,3 @@ export declare class DocsFetchError extends Error {
|
|
|
24
60
|
readonly status: number | null;
|
|
25
61
|
constructor(path: string, status: number | null, message: string);
|
|
26
62
|
}
|
|
27
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nbtca/docs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "GitHub-backed document client for NBTCA",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -18,11 +18,16 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"clean": "node --input-type=module --eval \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",
|
|
20
20
|
"prebuild": "npm run clean",
|
|
21
|
-
"build": "tsc",
|
|
21
|
+
"build": "tsc -p tsconfig.build.json",
|
|
22
|
+
"format": "prettier --write .",
|
|
23
|
+
"format:check": "prettier --check .",
|
|
24
|
+
"lint": "eslint . --max-warnings 0",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
22
26
|
"test": "vitest run",
|
|
23
27
|
"precheck:package": "npm run build",
|
|
24
28
|
"check:package": "node scripts/check-package.mjs",
|
|
25
|
-
"
|
|
29
|
+
"audit": "npm audit --audit-level=moderate",
|
|
30
|
+
"check": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run check:package && npm run audit",
|
|
26
31
|
"prepublishOnly": "npm run check"
|
|
27
32
|
},
|
|
28
33
|
"keywords": [
|
|
@@ -46,8 +51,15 @@
|
|
|
46
51
|
"node": ">=20.12.0"
|
|
47
52
|
},
|
|
48
53
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
54
|
+
"@eslint/js": "^9.39.5",
|
|
55
|
+
"@types/node": "20.12.12",
|
|
56
|
+
"eslint": "^9.39.5",
|
|
57
|
+
"eslint-config-prettier": "^10.1.8",
|
|
58
|
+
"globals": "^17.9.0",
|
|
59
|
+
"prettier": "^3.9.6",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"typescript-eslint": "^8.67.0",
|
|
62
|
+
"vite": "6.4.3",
|
|
63
|
+
"vitest": "^4.1.11"
|
|
52
64
|
}
|
|
53
65
|
}
|
package/dist/cache.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAKA,qBAAa,QAAQ,CAAC,CAAC;IAInB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+B;gBAGhC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAAW;IAGvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAO/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAIpC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAKhC,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,WAAW;CAMpB"}
|
package/dist/cache.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,QAAQ;IAGnB,YACmB,KAAa,EACb,UAAkB,EAAE;QADpB,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAa;QAJtB,QAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;IAKhD,CAAC;IAEJ,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC;QACrD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAQ;QACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACjE,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACvD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAEO,WAAW;QACjB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;aACnC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;aAC/C,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM;YAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;CACF"}
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAsIzE,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAqL5E"}
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,qBAAa,cAAe,SAAQ,KAAK;aAErB,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM,GAAG,IAAI;gBADrB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrC,OAAO,EAAE,MAAM;CAKlB"}
|
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwBA,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YACkB,IAAY,EACZ,MAAqB,EACrC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAe;QAIrC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
|