@bendyline/docblocks 2.6.1 → 2.7.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/THIRD_PARTY_NOTICES.txt +33 -33
- package/dist/capabilities-CdQAc745.d.ts +1233 -0
- package/dist/catalog-BQK05tne.d.ts +122 -0
- package/dist/chunk-245W57QP.js +31 -0
- package/dist/{chunk-2WDJ27EH.js → chunk-46AGYHDY.js} +8 -0
- package/dist/{chunk-4437YWLE.js → chunk-6UPO2GE6.js} +4 -2
- package/dist/{chunk-UMWCTEXW.js → chunk-7SN7YQL4.js} +211 -40
- package/dist/{chunk-OQCPBOQA.js → chunk-DAPFSEKY.js} +35 -0
- package/dist/{chunk-M62ZGJ5I.js → chunk-HABG2JM3.js} +0 -17
- package/dist/{chunk-YM7O3PWO.js → chunk-HKOOHM67.js} +20 -12
- package/dist/chunk-IDYE73TU.js +77 -0
- package/dist/{chunk-KLQKU74Q.js → chunk-IGB2VSRE.js} +124 -330
- package/dist/{chunk-BVY7GGNV.js → chunk-L6PRMR7T.js} +137 -95
- package/dist/chunk-LPIJ6HKL.js +19 -0
- package/dist/{chunk-SJBB5OD7.js → chunk-QS5WTLUZ.js} +10 -8
- package/dist/chunk-R2JX5N3F.js +382 -0
- package/dist/{chunk-ZO7G53QP.js → chunk-UDEWLHQI.js} +4 -2
- package/dist/chunk-UK7R3RC7.js +514 -0
- package/dist/chunk-XTNWCNSK.js +464 -0
- package/dist/chunk-YHSFRPBS.js +42 -0
- package/dist/chunk-YNUQG4GF.js +1173 -0
- package/dist/document/index.d.ts +31 -1
- package/dist/document/index.js +7 -6
- package/dist/filesystem/electron.d.ts +8 -34
- package/dist/filesystem/electron.js +7 -4
- package/dist/filesystem/host.d.ts +28 -0
- package/dist/filesystem/host.js +103 -0
- package/dist/filesystem/index.d.ts +52 -6
- package/dist/filesystem/index.js +36 -15
- package/dist/filesystem/indexeddb.d.ts +8 -1
- package/dist/filesystem/indexeddb.js +7 -6
- package/dist/filesystem/memory.d.ts +2 -1
- package/dist/filesystem/memory.js +3 -2
- package/dist/filesystem/native.d.ts +2 -1
- package/dist/filesystem/native.js +3 -2
- package/dist/filesystem-v2-C8AdSXUN.d.ts +74 -0
- package/dist/host/index.d.ts +127 -5
- package/dist/host/index.js +100 -4
- package/dist/host/mobile.d.ts +389 -0
- package/dist/host/mobile.js +315 -0
- package/dist/host-provider-v2-CyLTRKJF.d.ts +51 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +153 -34
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/zod.d.ts +23 -1
- package/dist/mcp/zod.js +1 -0
- package/dist/settings-HrrCikVX.d.ts +170 -0
- package/dist/types-BvDnr3YU.d.ts +88 -0
- package/dist/{types-Oy9U5FST.d.ts → types-d0yvHUJz.d.ts} +6 -0
- package/dist/{types-Bb3yccTH.d.ts → v2-BVnZZyd4.d.ts} +1 -86
- package/dist/vscode/index.d.ts +43 -1
- package/dist/vscode/index.js +67 -1
- package/dist/workspace/index.d.ts +10 -6
- package/dist/workspace/index.js +4 -2
- package/dist/workspace-index/index.d.ts +240 -0
- package/dist/workspace-index/index.js +1287 -0
- package/dist/workspace-settings/index.d.ts +301 -0
- package/dist/workspace-settings/index.js +820 -0
- package/package.json +22 -2
- package/dist/chunk-6XHOOBYF.js +0 -36
- package/dist/chunk-QI6YKTQV.js +0 -110
- package/dist/types-DBYraXxE.d.ts +0 -557
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CATALOG_FORMAT_VERSION,
|
|
3
|
+
CATALOG_GENERATOR,
|
|
4
|
+
CATALOG_LIMITS,
|
|
5
|
+
OUTSIDE_IN_FORMAT_IDS,
|
|
6
|
+
buildCatalogMarkdownDocument,
|
|
7
|
+
catalogEntryForUnreadable,
|
|
8
|
+
catalogEntryFromDocument,
|
|
9
|
+
catalogEntryFromMarkdown,
|
|
10
|
+
chooseOutsideInMarkdownPath,
|
|
11
|
+
createWorkspaceCatalog,
|
|
12
|
+
isGeneratedCatalogHtml,
|
|
13
|
+
isGeneratedCatalogJson,
|
|
14
|
+
readCatalogHtmlDigest,
|
|
15
|
+
relativeCatalogLink,
|
|
16
|
+
relocateOutsideInLayout,
|
|
17
|
+
resolveOutsideInLayout,
|
|
18
|
+
serializeCatalogJson,
|
|
19
|
+
sha256Hex,
|
|
20
|
+
sortCatalogEntries,
|
|
21
|
+
stampCatalogHtml
|
|
22
|
+
} from "../chunk-R2JX5N3F.js";
|
|
23
|
+
import {
|
|
24
|
+
CATALOG_JSON_CONTENT_MODES,
|
|
25
|
+
CATALOG_SORT_ORDERS,
|
|
26
|
+
DEFAULT_CATALOG_HTML_PATH,
|
|
27
|
+
DEFAULT_CATALOG_JSON_PATH,
|
|
28
|
+
DEFAULT_CATALOG_TITLE,
|
|
29
|
+
EMPTY_WORKSPACE_SETTINGS,
|
|
30
|
+
UnsupportedWorkspaceSettingsVersionError,
|
|
31
|
+
WORKSPACE_SETTINGS_DIRECTORY,
|
|
32
|
+
WORKSPACE_SETTINGS_LIMITS,
|
|
33
|
+
WORKSPACE_SETTINGS_PATH,
|
|
34
|
+
WORKSPACE_SETTINGS_VERSION,
|
|
35
|
+
WORKSPACE_THEME_ID_PATTERN,
|
|
36
|
+
applyWorkspaceSettingsPatch,
|
|
37
|
+
checkCatalogOutputPath,
|
|
38
|
+
diffWorkspaceSettings,
|
|
39
|
+
isDefaultWorkspaceSettings,
|
|
40
|
+
isEmptyWorkspaceSettingsPatch,
|
|
41
|
+
parseWorkspaceSettings,
|
|
42
|
+
parseWorkspaceSettingsPatch,
|
|
43
|
+
parseWorkspaceSettingsText,
|
|
44
|
+
resolveCatalogOutputs,
|
|
45
|
+
resolveFallbackThemeId,
|
|
46
|
+
resolveWorkspaceDefaultThemeId,
|
|
47
|
+
resolveWorkspaceVersioningEnabled,
|
|
48
|
+
serializeWorkspaceSettings,
|
|
49
|
+
tryApplyWorkspaceSettingsPatch,
|
|
50
|
+
validateCatalogOutputPath
|
|
51
|
+
} from "../chunk-UK7R3RC7.js";
|
|
52
|
+
import {
|
|
53
|
+
SQUISQ_RUNTIME_DIRECTORY_NAME,
|
|
54
|
+
isDiscoverableWorkspaceEntry,
|
|
55
|
+
isIgnoredWorkspaceEntryName,
|
|
56
|
+
isMarkdownFileName
|
|
57
|
+
} from "../chunk-YHSFRPBS.js";
|
|
58
|
+
import {
|
|
59
|
+
decodeUtf8Text
|
|
60
|
+
} from "../chunk-M5ZNQGR5.js";
|
|
61
|
+
import {
|
|
62
|
+
FsError,
|
|
63
|
+
WORKSPACE_ROOT,
|
|
64
|
+
parseWorkspacePath
|
|
65
|
+
} from "../chunk-AYWKIZLD.js";
|
|
66
|
+
|
|
67
|
+
// src/workspace-settings/schema.ts
|
|
68
|
+
var themeId = {
|
|
69
|
+
type: "string",
|
|
70
|
+
pattern: WORKSPACE_THEME_ID_PATTERN.source,
|
|
71
|
+
description: 'A DocBlocks document theme id, such as "warm-earth".'
|
|
72
|
+
};
|
|
73
|
+
var relativePath = {
|
|
74
|
+
type: "string",
|
|
75
|
+
minLength: 1,
|
|
76
|
+
maxLength: WORKSPACE_SETTINGS_LIMITS.maxPathCharacters
|
|
77
|
+
};
|
|
78
|
+
var WORKSPACE_SETTINGS_JSON_SCHEMA = {
|
|
79
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
80
|
+
title: "DocBlocks workspace settings",
|
|
81
|
+
description: "Settings shared by everyone who opens this folder in DocBlocks. Every section is optional.",
|
|
82
|
+
type: "object",
|
|
83
|
+
additionalProperties: false,
|
|
84
|
+
required: ["version"],
|
|
85
|
+
properties: {
|
|
86
|
+
$schema: { type: "string", maxLength: WORKSPACE_SETTINGS_LIMITS.maxSchemaCharacters },
|
|
87
|
+
version: { const: 1, description: "Settings format version." },
|
|
88
|
+
documents: {
|
|
89
|
+
type: "object",
|
|
90
|
+
additionalProperties: false,
|
|
91
|
+
properties: {
|
|
92
|
+
defaultTheme: {
|
|
93
|
+
...themeId,
|
|
94
|
+
description: "Theme for documents whose frontmatter does not name one. A document\u2019s own theme always wins."
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
versionHistory: {
|
|
99
|
+
type: "object",
|
|
100
|
+
additionalProperties: false,
|
|
101
|
+
properties: {
|
|
102
|
+
enabled: {
|
|
103
|
+
type: "boolean",
|
|
104
|
+
description: "Keep prior revisions for documents in this folder. Omit to use the app default."
|
|
105
|
+
},
|
|
106
|
+
keep: {
|
|
107
|
+
type: "integer",
|
|
108
|
+
minimum: WORKSPACE_SETTINGS_LIMITS.minKeep,
|
|
109
|
+
maximum: WORKSPACE_SETTINGS_LIMITS.maxKeep,
|
|
110
|
+
description: "Revisions kept per document."
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
catalog: {
|
|
115
|
+
type: "object",
|
|
116
|
+
additionalProperties: false,
|
|
117
|
+
properties: {
|
|
118
|
+
title: {
|
|
119
|
+
type: "string",
|
|
120
|
+
minLength: 1,
|
|
121
|
+
maxLength: WORKSPACE_SETTINGS_LIMITS.maxTitleCharacters,
|
|
122
|
+
description: `Catalog heading. Defaults to "${DEFAULT_CATALOG_TITLE}".`
|
|
123
|
+
},
|
|
124
|
+
sort: {
|
|
125
|
+
enum: [...CATALOG_SORT_ORDERS],
|
|
126
|
+
description: 'Catalog order. Defaults to "title".'
|
|
127
|
+
},
|
|
128
|
+
exclude: {
|
|
129
|
+
type: "array",
|
|
130
|
+
maxItems: WORKSPACE_SETTINGS_LIMITS.maxExcludes,
|
|
131
|
+
items: relativePath,
|
|
132
|
+
description: "Workspace-relative folders or files left out of the catalog."
|
|
133
|
+
},
|
|
134
|
+
html: {
|
|
135
|
+
type: "object",
|
|
136
|
+
additionalProperties: false,
|
|
137
|
+
properties: {
|
|
138
|
+
enabled: { type: "boolean", description: "Regenerate the catalog page on every save." },
|
|
139
|
+
path: {
|
|
140
|
+
...relativePath,
|
|
141
|
+
pattern: "\\.html?$",
|
|
142
|
+
description: `Catalog page path. Defaults to "${DEFAULT_CATALOG_HTML_PATH}".`
|
|
143
|
+
},
|
|
144
|
+
theme: { ...themeId, description: "Theme for the catalog page only." }
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
json: {
|
|
148
|
+
type: "object",
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
properties: {
|
|
151
|
+
enabled: { type: "boolean", description: "Regenerate the catalog data on every save." },
|
|
152
|
+
path: {
|
|
153
|
+
...relativePath,
|
|
154
|
+
pattern: "\\.json$",
|
|
155
|
+
description: `Catalog data path. Defaults to "${DEFAULT_CATALOG_JSON_PATH}".`
|
|
156
|
+
},
|
|
157
|
+
content: {
|
|
158
|
+
enum: [...CATALOG_JSON_CONTENT_MODES],
|
|
159
|
+
description: '"metadata" (default) or "markdown" to include each document\u2019s source.'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// src/workspace-settings/outputs.ts
|
|
169
|
+
var WORKSPACE_OUTPUT_LIMITS = {
|
|
170
|
+
maxDocuments: 5e3,
|
|
171
|
+
maxDirectories: 2e4,
|
|
172
|
+
maxDepth: 32,
|
|
173
|
+
maxDocumentBytes: 4 * 1024 * 1024,
|
|
174
|
+
maxTotalBytes: 256 * 1024 * 1024,
|
|
175
|
+
maxOutputBytes: 32 * 1024 * 1024
|
|
176
|
+
};
|
|
177
|
+
var WorkspaceOutputsLimitError = class extends Error {
|
|
178
|
+
constructor(message) {
|
|
179
|
+
super(message);
|
|
180
|
+
this.name = "WorkspaceOutputsLimitError";
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
function createWorkspaceCatalogCache() {
|
|
184
|
+
return /* @__PURE__ */ new Map();
|
|
185
|
+
}
|
|
186
|
+
function throwIfAborted(signal) {
|
|
187
|
+
if (signal?.aborted) {
|
|
188
|
+
throw new FsError("aborted", "Workspace catalog refresh was cancelled.", {
|
|
189
|
+
operation: "read",
|
|
190
|
+
retryable: false
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function isNotFound(error) {
|
|
195
|
+
return error instanceof FsError && (error.code === "not-found" || error.code === "type-mismatch");
|
|
196
|
+
}
|
|
197
|
+
function hasUndiscoverableSegment(path) {
|
|
198
|
+
return path.split("/").some(
|
|
199
|
+
(segment) => isIgnoredWorkspaceEntryName(segment) || segment === SQUISQ_RUNTIME_DIRECTORY_NAME
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
function isExcluded(path, exclude) {
|
|
203
|
+
return exclude.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
204
|
+
}
|
|
205
|
+
function isCatalogRelevantPath(path, settings) {
|
|
206
|
+
const normalized = path.replace(/^\/+/, "");
|
|
207
|
+
if (!normalized || hasUndiscoverableSegment(normalized)) return false;
|
|
208
|
+
let resolved;
|
|
209
|
+
try {
|
|
210
|
+
resolved = resolveCatalogOutputs(settings);
|
|
211
|
+
} catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
if (!resolved) return false;
|
|
215
|
+
const lower = normalized.toLowerCase();
|
|
216
|
+
return lower !== resolved.html?.path.toLowerCase() && lower !== resolved.json?.path.toLowerCase();
|
|
217
|
+
}
|
|
218
|
+
function isWorkspaceSettingsPath(path) {
|
|
219
|
+
const normalized = path.replace(/^\/+/, "");
|
|
220
|
+
return normalized === WORKSPACE_SETTINGS_DIRECTORY || normalized.startsWith(`${WORKSPACE_SETTINGS_DIRECTORY}/`);
|
|
221
|
+
}
|
|
222
|
+
async function collectCandidates(io, resolved, limits, signal) {
|
|
223
|
+
const outputPaths = new Set(
|
|
224
|
+
[resolved.html?.path, resolved.json?.path].filter(Boolean).map((path) => path.toLowerCase())
|
|
225
|
+
);
|
|
226
|
+
const exclude = resolved.exclude;
|
|
227
|
+
const candidates = [];
|
|
228
|
+
const queue = [{ path: WORKSPACE_ROOT, depth: 0 }];
|
|
229
|
+
let directories = 0;
|
|
230
|
+
while (queue.length > 0) {
|
|
231
|
+
throwIfAborted(signal);
|
|
232
|
+
const { path, depth } = queue.shift();
|
|
233
|
+
directories += 1;
|
|
234
|
+
if (directories > limits.maxDirectories) {
|
|
235
|
+
throw new WorkspaceOutputsLimitError(
|
|
236
|
+
`This workspace has more than ${limits.maxDirectories} folders; the catalog was not updated.`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
let entries;
|
|
240
|
+
try {
|
|
241
|
+
entries = await io.readDirectory(path);
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (path !== WORKSPACE_ROOT && isNotFound(error)) continue;
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
for (const entry of entries) {
|
|
247
|
+
if (!isDiscoverableWorkspaceEntry(entry.name, entry.kind)) continue;
|
|
248
|
+
if (isExcluded(entry.path, exclude)) continue;
|
|
249
|
+
if (entry.kind === "directory") {
|
|
250
|
+
if (depth + 1 > limits.maxDepth) {
|
|
251
|
+
throw new WorkspaceOutputsLimitError(
|
|
252
|
+
`Folders nest deeper than ${limits.maxDepth} levels; the catalog was not updated.`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
queue.push({ path: entry.path, depth: depth + 1 });
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (outputPaths.has(entry.path.toLowerCase())) continue;
|
|
259
|
+
if (isMarkdownFileName(entry.name)) {
|
|
260
|
+
candidates.push({ kind: "markdown", entry });
|
|
261
|
+
} else {
|
|
262
|
+
const layout = resolveOutsideInLayout(entry.path);
|
|
263
|
+
if (layout) candidates.push({ kind: "outside-in", entry, layout });
|
|
264
|
+
}
|
|
265
|
+
if (candidates.length > limits.maxDocuments) {
|
|
266
|
+
throw new WorkspaceOutputsLimitError(
|
|
267
|
+
`This workspace has more than ${limits.maxDocuments} documents; the catalog was not updated.`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return candidates;
|
|
273
|
+
}
|
|
274
|
+
var HTML_TITLE = /<title[^>]*>([\s\S]*?)<\/title>/i;
|
|
275
|
+
var HTML_DESCRIPTION = /<meta\b[^>]*\bname\s*=\s*["']description["'][^>]*\bcontent\s*=\s*["']([^"']*)["']/i;
|
|
276
|
+
function decodeEntities(text) {
|
|
277
|
+
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'|'/g, "'").replace(/&/g, "&");
|
|
278
|
+
}
|
|
279
|
+
async function resolveReadTarget(io, candidate) {
|
|
280
|
+
if (candidate.kind === "markdown") {
|
|
281
|
+
return {
|
|
282
|
+
source: { path: candidate.entry.path, format: "markdown" },
|
|
283
|
+
readPath: candidate.entry.path,
|
|
284
|
+
version: candidate.entry.version,
|
|
285
|
+
size: candidate.entry.size,
|
|
286
|
+
mode: "markdown"
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const { layout, entry } = candidate;
|
|
290
|
+
let companion = [];
|
|
291
|
+
try {
|
|
292
|
+
companion = await io.readDirectory(parseWorkspacePath(layout.companionDirectory));
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (!isNotFound(error)) throw error;
|
|
295
|
+
}
|
|
296
|
+
const markdownPath = chooseOutsideInMarkdownPath(
|
|
297
|
+
layout,
|
|
298
|
+
companion.filter((item) => item.kind === "file").map((item) => item.path)
|
|
299
|
+
);
|
|
300
|
+
const markdownEntry = markdownPath ? companion.find((item) => item.path === markdownPath) : void 0;
|
|
301
|
+
if (markdownEntry) {
|
|
302
|
+
return {
|
|
303
|
+
source: { path: entry.path, source: markdownEntry.path, format: layout.format },
|
|
304
|
+
readPath: markdownEntry.path,
|
|
305
|
+
version: markdownEntry.version,
|
|
306
|
+
size: markdownEntry.size,
|
|
307
|
+
mode: "markdown"
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
source: { path: entry.path, format: layout.format },
|
|
312
|
+
readPath: layout.format === "html" ? entry.path : null,
|
|
313
|
+
version: layout.format === "html" ? entry.version : null,
|
|
314
|
+
size: entry.size,
|
|
315
|
+
mode: layout.format === "html" ? "html" : "unreadable"
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
async function collectWorkspaceCatalog(io, resolved, renderer, options = {}) {
|
|
319
|
+
const limits = { ...WORKSPACE_OUTPUT_LIMITS, ...options.limits };
|
|
320
|
+
const cache = options.cache;
|
|
321
|
+
const includeMarkdown = resolved.json?.content === "markdown";
|
|
322
|
+
const candidates = await collectCandidates(io, resolved, limits, options.signal);
|
|
323
|
+
const entries = [];
|
|
324
|
+
const seen = /* @__PURE__ */ new Set();
|
|
325
|
+
let totalBytes = 0;
|
|
326
|
+
for (const candidate of candidates) {
|
|
327
|
+
throwIfAborted(options.signal);
|
|
328
|
+
const target = await resolveReadTarget(io, candidate);
|
|
329
|
+
seen.add(target.source.path);
|
|
330
|
+
if (target.mode === "unreadable" || !target.readPath || target.size !== null && target.size > limits.maxDocumentBytes) {
|
|
331
|
+
entries.push(catalogEntryForUnreadable(target.source));
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const cached = cache?.get(target.source.path);
|
|
335
|
+
if (cached && cached.readPath === target.readPath && cached.version === target.version && cached.includeMarkdown === includeMarkdown) {
|
|
336
|
+
if (cached.entry) entries.push(cached.entry);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const read = await io.readFile(parseWorkspacePath(target.readPath));
|
|
340
|
+
if (!read) continue;
|
|
341
|
+
let entry;
|
|
342
|
+
if (read.entry.size > limits.maxDocumentBytes) {
|
|
343
|
+
entry = catalogEntryForUnreadable(target.source);
|
|
344
|
+
} else {
|
|
345
|
+
totalBytes += read.entry.size;
|
|
346
|
+
if (totalBytes > limits.maxTotalBytes) {
|
|
347
|
+
throw new WorkspaceOutputsLimitError(
|
|
348
|
+
`Documents in this workspace exceed ${Math.round(limits.maxTotalBytes / 1024 / 1024)} MiB; the catalog was not updated.`
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
const text = new TextDecoder("utf-8").decode(read.data);
|
|
352
|
+
if (target.mode === "markdown") {
|
|
353
|
+
entry = await catalogEntryFromMarkdown(target.source, text, { includeMarkdown });
|
|
354
|
+
} else if (isGeneratedCatalogHtml(text)) {
|
|
355
|
+
entry = null;
|
|
356
|
+
} else if (renderer.importHtml) {
|
|
357
|
+
const head = text.slice(0, 64 * 1024);
|
|
358
|
+
entry = await catalogEntryFromDocument(target.source, await renderer.importHtml(text), {
|
|
359
|
+
fallbackTitle: decodeEntities(HTML_TITLE.exec(head)?.[1] ?? ""),
|
|
360
|
+
description: decodeEntities(HTML_DESCRIPTION.exec(head)?.[1] ?? "")
|
|
361
|
+
});
|
|
362
|
+
} else {
|
|
363
|
+
entry = catalogEntryForUnreadable(target.source);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
cache?.set(target.source.path, {
|
|
367
|
+
readPath: target.readPath,
|
|
368
|
+
version: read.entry.version,
|
|
369
|
+
includeMarkdown,
|
|
370
|
+
entry
|
|
371
|
+
});
|
|
372
|
+
if (entry) entries.push(entry);
|
|
373
|
+
}
|
|
374
|
+
if (cache) {
|
|
375
|
+
for (const key of [...cache.keys()]) if (!seen.has(key)) cache.delete(key);
|
|
376
|
+
}
|
|
377
|
+
return createWorkspaceCatalog(resolved.title, entries, resolved.sort);
|
|
378
|
+
}
|
|
379
|
+
function withoutMarkdown(catalog) {
|
|
380
|
+
if (!catalog.documents.some((entry) => entry.markdown !== void 0)) return catalog;
|
|
381
|
+
return {
|
|
382
|
+
...catalog,
|
|
383
|
+
documents: catalog.documents.map(({ markdown: _markdown, ...entry }) => entry)
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
function sameBytes(left, right) {
|
|
387
|
+
if (left.byteLength !== right.byteLength) return false;
|
|
388
|
+
const view = new Uint8Array(left);
|
|
389
|
+
for (let index = 0; index < view.length; index += 1) {
|
|
390
|
+
if (view[index] !== right[index]) return false;
|
|
391
|
+
}
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
async function writeOutput(io, request, limits, options) {
|
|
395
|
+
const { kind, path } = request;
|
|
396
|
+
const blocked = (message) => ({
|
|
397
|
+
kind,
|
|
398
|
+
path,
|
|
399
|
+
status: "blocked",
|
|
400
|
+
message
|
|
401
|
+
});
|
|
402
|
+
let existing;
|
|
403
|
+
try {
|
|
404
|
+
existing = await io.readFile(path);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
if (error instanceof FsError && error.code === "type-mismatch") {
|
|
407
|
+
return blocked(`${path} is a folder. Choose another catalog path.`);
|
|
408
|
+
}
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
if (existing) {
|
|
412
|
+
const head = new TextDecoder("utf-8").decode(existing.data.slice(0, 4096));
|
|
413
|
+
const generated = kind === "html" ? isGeneratedCatalogHtml(head) : isGeneratedCatalogJson(head);
|
|
414
|
+
if (!generated) {
|
|
415
|
+
return blocked(
|
|
416
|
+
`${path} already exists and was not created by DocBlocks. Choose another catalog path or remove that file.`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
if (kind === "html" && !options.force && readCatalogHtmlDigest(head) === request.digest) {
|
|
420
|
+
return { kind, path, status: "unchanged" };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (kind === "html") {
|
|
424
|
+
const layout = resolveOutsideInLayout(path);
|
|
425
|
+
if (layout && await io.stat(parseWorkspacePath(layout.companionDirectory))) {
|
|
426
|
+
return blocked(`${path} is an edited document. Choose another catalog path.`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const bytes = new TextEncoder().encode(await request.produce());
|
|
430
|
+
if (bytes.byteLength > limits.maxOutputBytes) {
|
|
431
|
+
return blocked(
|
|
432
|
+
`The catalog would exceed ${Math.round(limits.maxOutputBytes / 1024 / 1024)} MiB and was not written.`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
if (existing && sameBytes(existing.data, bytes)) return { kind, path, status: "unchanged" };
|
|
436
|
+
if (options.dryRun) return { kind, path, status: "would-write" };
|
|
437
|
+
await io.writeFile(path, bytes, {
|
|
438
|
+
mode: existing ? "replace" : "create",
|
|
439
|
+
createParents: true,
|
|
440
|
+
expectedVersion: existing ? existing.entry.version : null
|
|
441
|
+
});
|
|
442
|
+
return { kind, path, status: "written", ...existing ? {} : { created: true } };
|
|
443
|
+
}
|
|
444
|
+
async function refreshWorkspaceOutputs(io, settings, renderer, options = {}) {
|
|
445
|
+
const resolved = resolveCatalogOutputs(settings);
|
|
446
|
+
if (!resolved) return { documentCount: 0, outputs: [] };
|
|
447
|
+
const limits = { ...WORKSPACE_OUTPUT_LIMITS, ...options.limits };
|
|
448
|
+
const catalog = await collectWorkspaceCatalog(io, resolved, renderer, options);
|
|
449
|
+
const metadataCatalog = withoutMarkdown(catalog);
|
|
450
|
+
const outputs = [];
|
|
451
|
+
if (resolved.json) {
|
|
452
|
+
throwIfAborted(options.signal);
|
|
453
|
+
const content = resolved.json.content;
|
|
454
|
+
outputs.push(
|
|
455
|
+
await writeOutput(
|
|
456
|
+
io,
|
|
457
|
+
{
|
|
458
|
+
kind: "json",
|
|
459
|
+
path: resolved.json.path,
|
|
460
|
+
produce: async () => serializeCatalogJson(content === "markdown" ? catalog : metadataCatalog)
|
|
461
|
+
},
|
|
462
|
+
limits,
|
|
463
|
+
options
|
|
464
|
+
)
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
if (resolved.html) {
|
|
468
|
+
throwIfAborted(options.signal);
|
|
469
|
+
const html = resolved.html;
|
|
470
|
+
const digest = await sha256Hex(
|
|
471
|
+
JSON.stringify({
|
|
472
|
+
marker: 1,
|
|
473
|
+
path: html.path,
|
|
474
|
+
themeId: html.themeId ?? null,
|
|
475
|
+
catalog: serializeCatalogJson(metadataCatalog)
|
|
476
|
+
})
|
|
477
|
+
);
|
|
478
|
+
outputs.push(
|
|
479
|
+
await writeOutput(
|
|
480
|
+
io,
|
|
481
|
+
{
|
|
482
|
+
kind: "html",
|
|
483
|
+
path: html.path,
|
|
484
|
+
digest,
|
|
485
|
+
produce: async () => stampCatalogHtml(
|
|
486
|
+
await renderer.renderCatalogHtml(
|
|
487
|
+
buildCatalogMarkdownDocument(metadataCatalog, html.path),
|
|
488
|
+
{ title: catalog.title, themeId: html.themeId }
|
|
489
|
+
),
|
|
490
|
+
digest
|
|
491
|
+
)
|
|
492
|
+
},
|
|
493
|
+
limits,
|
|
494
|
+
options
|
|
495
|
+
)
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
return { documentCount: catalog.documents.length, outputs };
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/workspace-settings/store.ts
|
|
502
|
+
var UNAVAILABLE_WORKSPACE_SETTINGS = Object.freeze({
|
|
503
|
+
status: "unavailable",
|
|
504
|
+
settings: null,
|
|
505
|
+
version: null,
|
|
506
|
+
message: "Workspace settings need a folder workspace."
|
|
507
|
+
});
|
|
508
|
+
var LOADING_WORKSPACE_SETTINGS = Object.freeze({
|
|
509
|
+
status: "loading",
|
|
510
|
+
settings: null,
|
|
511
|
+
version: null,
|
|
512
|
+
message: null
|
|
513
|
+
});
|
|
514
|
+
var SETTINGS_PATH = parseWorkspacePath(WORKSPACE_SETTINGS_PATH);
|
|
515
|
+
function isWorkspaceSettingsWritable(state) {
|
|
516
|
+
return state.status === "missing" || state.status === "ready";
|
|
517
|
+
}
|
|
518
|
+
async function readWorkspaceSettings(provider) {
|
|
519
|
+
let file;
|
|
520
|
+
try {
|
|
521
|
+
file = await provider.readFile(SETTINGS_PATH);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
return {
|
|
524
|
+
status: "error",
|
|
525
|
+
settings: null,
|
|
526
|
+
version: null,
|
|
527
|
+
message: `Couldn't read ${WORKSPACE_SETTINGS_PATH}: ${errorMessage(error)}`
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
if (!file) return { status: "missing", settings: null, version: null, message: null };
|
|
531
|
+
let text;
|
|
532
|
+
try {
|
|
533
|
+
text = decodeUtf8Text(file.data, { label: WORKSPACE_SETTINGS_PATH, path: SETTINGS_PATH });
|
|
534
|
+
} catch (error) {
|
|
535
|
+
return {
|
|
536
|
+
status: "invalid",
|
|
537
|
+
settings: null,
|
|
538
|
+
version: file.entry.version,
|
|
539
|
+
message: errorMessage(error)
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
const parsed = parseWorkspaceSettingsText(text);
|
|
543
|
+
if (parsed.status === "ok") {
|
|
544
|
+
return {
|
|
545
|
+
status: "ready",
|
|
546
|
+
settings: parsed.settings,
|
|
547
|
+
version: file.entry.version,
|
|
548
|
+
message: null
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
status: parsed.status,
|
|
553
|
+
settings: null,
|
|
554
|
+
version: file.entry.version,
|
|
555
|
+
message: parsed.message
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function isConcurrentChange(error) {
|
|
559
|
+
return error instanceof FsError && (error.code === "conflict" || error.code === "already-exists" || error.code === "not-found");
|
|
560
|
+
}
|
|
561
|
+
async function writeSettings(provider, base, version, patch) {
|
|
562
|
+
const next = applyWorkspaceSettingsPatch(base, patch);
|
|
563
|
+
if (version === null && isDefaultWorkspaceSettings(next)) {
|
|
564
|
+
return { status: "missing", settings: null, version: null, message: null };
|
|
565
|
+
}
|
|
566
|
+
const snapshot = await provider.writeFile(
|
|
567
|
+
SETTINGS_PATH,
|
|
568
|
+
new TextEncoder().encode(serializeWorkspaceSettings(next)),
|
|
569
|
+
{ mode: version ? "replace" : "create", createParents: true, expectedVersion: version }
|
|
570
|
+
);
|
|
571
|
+
return { status: "ready", settings: next, version: snapshot.version, message: null };
|
|
572
|
+
}
|
|
573
|
+
async function saveWorkspaceSettingsPatch(provider, observed, patch) {
|
|
574
|
+
if (!isWorkspaceSettingsWritable(observed)) {
|
|
575
|
+
throw new Error(observed.message ?? "These workspace settings cannot be changed.");
|
|
576
|
+
}
|
|
577
|
+
try {
|
|
578
|
+
return await writeSettings(provider, observed.settings, observed.version, patch);
|
|
579
|
+
} catch (error) {
|
|
580
|
+
if (!isConcurrentChange(error)) throw error;
|
|
581
|
+
}
|
|
582
|
+
const fresh = await readWorkspaceSettings(provider);
|
|
583
|
+
if (!isWorkspaceSettingsWritable(fresh)) {
|
|
584
|
+
throw new Error(fresh.message ?? "The workspace settings file changed and cannot be updated.");
|
|
585
|
+
}
|
|
586
|
+
return writeSettings(provider, fresh.settings, fresh.version, patch);
|
|
587
|
+
}
|
|
588
|
+
function errorMessage(error) {
|
|
589
|
+
return error instanceof Error ? error.message : String(error);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// src/workspace-settings/scheduler.ts
|
|
593
|
+
var IDLE_WORKSPACE_OUTPUTS_STATUS = Object.freeze({
|
|
594
|
+
state: "idle",
|
|
595
|
+
result: null,
|
|
596
|
+
message: null
|
|
597
|
+
});
|
|
598
|
+
var WORKSPACE_OUTPUTS_DEBOUNCE_MS = 2500;
|
|
599
|
+
var WORKSPACE_OUTPUTS_MAX_WAIT_MS = 2e4;
|
|
600
|
+
function outputsSignature(settings) {
|
|
601
|
+
try {
|
|
602
|
+
return JSON.stringify(resolveCatalogOutputs(settings));
|
|
603
|
+
} catch {
|
|
604
|
+
return "invalid";
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
function describeFailure(error) {
|
|
608
|
+
if (error instanceof WorkspaceOutputsLimitError) return error.message;
|
|
609
|
+
if (error instanceof FsError) return `Couldn't update the catalog: ${error.message}`;
|
|
610
|
+
return `Couldn't update the catalog: ${error instanceof Error ? error.message : String(error)}`;
|
|
611
|
+
}
|
|
612
|
+
function firstBlocked(result) {
|
|
613
|
+
return result.outputs.find((output) => output.status === "blocked");
|
|
614
|
+
}
|
|
615
|
+
function createWorkspaceOutputsScheduler(options) {
|
|
616
|
+
const debounceMs = options.debounceMs ?? WORKSPACE_OUTPUTS_DEBOUNCE_MS;
|
|
617
|
+
const maxWaitMs = options.maxWaitMs ?? WORKSPACE_OUTPUTS_MAX_WAIT_MS;
|
|
618
|
+
const cache = createWorkspaceCatalogCache();
|
|
619
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
620
|
+
let settings = options.settings;
|
|
621
|
+
let signature = outputsSignature(settings);
|
|
622
|
+
let status = IDLE_WORKSPACE_OUTPUTS_STATUS;
|
|
623
|
+
let debounceTimer = null;
|
|
624
|
+
let maxWaitTimer = null;
|
|
625
|
+
let running = null;
|
|
626
|
+
let controller = null;
|
|
627
|
+
let dirty = false;
|
|
628
|
+
let forceNext = false;
|
|
629
|
+
let disposed = false;
|
|
630
|
+
const setStatus = (next) => {
|
|
631
|
+
status = next;
|
|
632
|
+
for (const listener of [...listeners]) listener();
|
|
633
|
+
};
|
|
634
|
+
const clearTimers = () => {
|
|
635
|
+
if (debounceTimer !== null) clearTimeout(debounceTimer);
|
|
636
|
+
if (maxWaitTimer !== null) clearTimeout(maxWaitTimer);
|
|
637
|
+
debounceTimer = null;
|
|
638
|
+
maxWaitTimer = null;
|
|
639
|
+
};
|
|
640
|
+
const enabled = () => resolveCatalogOutputsSafe(settings) !== null;
|
|
641
|
+
const run = () => {
|
|
642
|
+
clearTimers();
|
|
643
|
+
if (disposed || !enabled()) {
|
|
644
|
+
dirty = false;
|
|
645
|
+
return Promise.resolve(status);
|
|
646
|
+
}
|
|
647
|
+
if (running) {
|
|
648
|
+
dirty = true;
|
|
649
|
+
return running;
|
|
650
|
+
}
|
|
651
|
+
dirty = false;
|
|
652
|
+
const force = forceNext;
|
|
653
|
+
forceNext = false;
|
|
654
|
+
const runSettings = settings;
|
|
655
|
+
controller = new AbortController();
|
|
656
|
+
const signal = controller.signal;
|
|
657
|
+
setStatus({ ...status, state: "running" });
|
|
658
|
+
running = (async () => {
|
|
659
|
+
try {
|
|
660
|
+
const renderer = typeof options.renderer === "function" ? await options.renderer() : options.renderer;
|
|
661
|
+
let result;
|
|
662
|
+
try {
|
|
663
|
+
result = await refreshWorkspaceOutputs(options.provider, runSettings, renderer, {
|
|
664
|
+
cache,
|
|
665
|
+
signal,
|
|
666
|
+
force
|
|
667
|
+
});
|
|
668
|
+
} catch (error) {
|
|
669
|
+
if (!(error instanceof FsError && error.code === "conflict")) throw error;
|
|
670
|
+
result = await refreshWorkspaceOutputs(options.provider, runSettings, renderer, {
|
|
671
|
+
cache,
|
|
672
|
+
signal,
|
|
673
|
+
force
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
const blocked = firstBlocked(result);
|
|
677
|
+
return { state: "done", result, message: blocked?.message ?? null };
|
|
678
|
+
} catch (error) {
|
|
679
|
+
if (error instanceof FsError && error.code === "aborted") {
|
|
680
|
+
return status.state === "running" ? { ...status, state: "idle" } : status;
|
|
681
|
+
}
|
|
682
|
+
return { state: "error", result: null, message: describeFailure(error) };
|
|
683
|
+
}
|
|
684
|
+
})().then((next) => {
|
|
685
|
+
running = null;
|
|
686
|
+
controller = null;
|
|
687
|
+
if (!disposed) {
|
|
688
|
+
setStatus(next);
|
|
689
|
+
if (dirty) schedule();
|
|
690
|
+
}
|
|
691
|
+
return next;
|
|
692
|
+
});
|
|
693
|
+
return running;
|
|
694
|
+
};
|
|
695
|
+
const schedule = () => {
|
|
696
|
+
if (disposed || !enabled()) return;
|
|
697
|
+
if (status.state !== "running") setStatus({ ...status, state: "pending" });
|
|
698
|
+
if (debounceTimer !== null) clearTimeout(debounceTimer);
|
|
699
|
+
debounceTimer = setTimeout(() => void run(), debounceMs);
|
|
700
|
+
maxWaitTimer ?? (maxWaitTimer = setTimeout(() => void run(), maxWaitMs));
|
|
701
|
+
};
|
|
702
|
+
const scheduler = {
|
|
703
|
+
workspaceId: options.workspaceId,
|
|
704
|
+
notify(path) {
|
|
705
|
+
if (disposed) return;
|
|
706
|
+
if (path !== void 0 && !isCatalogRelevantPath(path, settings)) return;
|
|
707
|
+
if (running) {
|
|
708
|
+
dirty = true;
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
schedule();
|
|
712
|
+
},
|
|
713
|
+
flush() {
|
|
714
|
+
if (debounceTimer !== null || maxWaitTimer !== null) void run();
|
|
715
|
+
},
|
|
716
|
+
regenerate(regenerateOptions) {
|
|
717
|
+
if (regenerateOptions?.force) forceNext = true;
|
|
718
|
+
if (running) dirty = true;
|
|
719
|
+
return running ?? run();
|
|
720
|
+
},
|
|
721
|
+
updateSettings(next) {
|
|
722
|
+
settings = next;
|
|
723
|
+
const nextSignature = outputsSignature(next);
|
|
724
|
+
if (nextSignature === signature) return;
|
|
725
|
+
signature = nextSignature;
|
|
726
|
+
if (!enabled()) {
|
|
727
|
+
clearTimers();
|
|
728
|
+
controller?.abort();
|
|
729
|
+
setStatus(IDLE_WORKSPACE_OUTPUTS_STATUS);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
scheduler.notify();
|
|
733
|
+
},
|
|
734
|
+
getStatus: () => status,
|
|
735
|
+
subscribe(listener) {
|
|
736
|
+
listeners.add(listener);
|
|
737
|
+
return () => listeners.delete(listener);
|
|
738
|
+
},
|
|
739
|
+
dispose() {
|
|
740
|
+
disposed = true;
|
|
741
|
+
clearTimers();
|
|
742
|
+
controller?.abort();
|
|
743
|
+
listeners.clear();
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
if (enabled()) scheduler.notify();
|
|
747
|
+
return scheduler;
|
|
748
|
+
}
|
|
749
|
+
function resolveCatalogOutputsSafe(settings) {
|
|
750
|
+
try {
|
|
751
|
+
return resolveCatalogOutputs(settings);
|
|
752
|
+
} catch {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
export {
|
|
757
|
+
CATALOG_FORMAT_VERSION,
|
|
758
|
+
CATALOG_GENERATOR,
|
|
759
|
+
CATALOG_JSON_CONTENT_MODES,
|
|
760
|
+
CATALOG_LIMITS,
|
|
761
|
+
CATALOG_SORT_ORDERS,
|
|
762
|
+
DEFAULT_CATALOG_HTML_PATH,
|
|
763
|
+
DEFAULT_CATALOG_JSON_PATH,
|
|
764
|
+
DEFAULT_CATALOG_TITLE,
|
|
765
|
+
EMPTY_WORKSPACE_SETTINGS,
|
|
766
|
+
IDLE_WORKSPACE_OUTPUTS_STATUS,
|
|
767
|
+
LOADING_WORKSPACE_SETTINGS,
|
|
768
|
+
OUTSIDE_IN_FORMAT_IDS,
|
|
769
|
+
UNAVAILABLE_WORKSPACE_SETTINGS,
|
|
770
|
+
UnsupportedWorkspaceSettingsVersionError,
|
|
771
|
+
WORKSPACE_OUTPUTS_DEBOUNCE_MS,
|
|
772
|
+
WORKSPACE_OUTPUTS_MAX_WAIT_MS,
|
|
773
|
+
WORKSPACE_OUTPUT_LIMITS,
|
|
774
|
+
WORKSPACE_SETTINGS_DIRECTORY,
|
|
775
|
+
WORKSPACE_SETTINGS_JSON_SCHEMA,
|
|
776
|
+
WORKSPACE_SETTINGS_LIMITS,
|
|
777
|
+
WORKSPACE_SETTINGS_PATH,
|
|
778
|
+
WORKSPACE_SETTINGS_VERSION,
|
|
779
|
+
WORKSPACE_THEME_ID_PATTERN,
|
|
780
|
+
WorkspaceOutputsLimitError,
|
|
781
|
+
applyWorkspaceSettingsPatch,
|
|
782
|
+
buildCatalogMarkdownDocument,
|
|
783
|
+
catalogEntryForUnreadable,
|
|
784
|
+
catalogEntryFromDocument,
|
|
785
|
+
catalogEntryFromMarkdown,
|
|
786
|
+
checkCatalogOutputPath,
|
|
787
|
+
chooseOutsideInMarkdownPath,
|
|
788
|
+
collectWorkspaceCatalog,
|
|
789
|
+
createWorkspaceCatalog,
|
|
790
|
+
createWorkspaceCatalogCache,
|
|
791
|
+
createWorkspaceOutputsScheduler,
|
|
792
|
+
diffWorkspaceSettings,
|
|
793
|
+
isCatalogRelevantPath,
|
|
794
|
+
isDefaultWorkspaceSettings,
|
|
795
|
+
isEmptyWorkspaceSettingsPatch,
|
|
796
|
+
isGeneratedCatalogHtml,
|
|
797
|
+
isGeneratedCatalogJson,
|
|
798
|
+
isWorkspaceSettingsPath,
|
|
799
|
+
isWorkspaceSettingsWritable,
|
|
800
|
+
parseWorkspaceSettings,
|
|
801
|
+
parseWorkspaceSettingsPatch,
|
|
802
|
+
parseWorkspaceSettingsText,
|
|
803
|
+
readCatalogHtmlDigest,
|
|
804
|
+
readWorkspaceSettings,
|
|
805
|
+
refreshWorkspaceOutputs,
|
|
806
|
+
relativeCatalogLink,
|
|
807
|
+
relocateOutsideInLayout,
|
|
808
|
+
resolveCatalogOutputs,
|
|
809
|
+
resolveFallbackThemeId,
|
|
810
|
+
resolveOutsideInLayout,
|
|
811
|
+
resolveWorkspaceDefaultThemeId,
|
|
812
|
+
resolveWorkspaceVersioningEnabled,
|
|
813
|
+
saveWorkspaceSettingsPatch,
|
|
814
|
+
serializeCatalogJson,
|
|
815
|
+
serializeWorkspaceSettings,
|
|
816
|
+
sortCatalogEntries,
|
|
817
|
+
stampCatalogHtml,
|
|
818
|
+
tryApplyWorkspaceSettingsPatch,
|
|
819
|
+
validateCatalogOutputPath
|
|
820
|
+
};
|