rspress-plugin-api-extractor 0.9.2 → 0.11.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/BuildEnv.js +58 -0
- package/README.md +2 -1
- package/build-program.js +33 -30
- package/build-stages.js +47 -39
- package/errors.js +0 -1
- package/index.d.ts +22 -14
- package/layers/ConfigServiceLive.js +349 -400
- package/layers/HighlighterServiceLive.js +52 -0
- package/layers/ObservabilityLive.js +26 -7
- package/layers/OgServiceLive.js +134 -0
- package/layers/TwoslashCacheServiceLive.js +108 -0
- package/layers/TwoslashEnvironmentsLive.js +33 -0
- package/layers/TypeRegistryServiceLive.js +54 -47
- package/layers/build-metrics.js +32 -5
- package/layers/xdg.js +44 -0
- package/markdown/helpers.js +9 -55
- package/markdown/page-generators/class-page.js +8 -31
- package/markdown/page-generators/index-pages.js +6 -8
- package/markdown/page-generators/interface-page.js +7 -7
- package/markdown/shiki-utils.js +65 -10
- package/observability/EventBus.js +29 -9
- package/observability/heartbeat.js +1 -1
- package/observability/metric-report.js +124 -0
- package/observability/sinks/console-sink.js +6 -0
- package/observability/sinks/metrics-sink.js +64 -21
- package/observability/sinks/render-sink.js +86 -0
- package/observability/sinks/trace-sink.js +10 -17
- package/observability/spans.js +4 -2
- package/observability/sync-emitter.js +78 -0
- package/og-resolver.js +46 -287
- package/package.json +4 -5
- package/path-derivation.js +19 -1
- package/plugin.js +64 -52
- package/prettier-formatter.js +4 -10
- package/remark-api-codeblocks.js +33 -15
- package/remark-with-api.js +24 -27
- package/schemas/config.js +11 -7
- package/services/HighlighterService.js +30 -0
- package/services/OgService.js +23 -0
- package/services/PluginConfig.js +26 -0
- package/services/TwoslashCacheService.js +15 -0
- package/services/TwoslashEnvironments.js +7 -0
- package/shiki-transformer.js +55 -256
- package/twoslash-access.js +48 -0
- package/twoslash-cache.js +174 -0
- package/twoslash-patterns.js +1 -1
- package/twoslash-timing-wrapper.js +23 -0
- package/twoslash-transformer.js +153 -89
- package/vfs-registry.js +1 -31
- package/layers/PathDerivationServiceLive.js +0 -16
- package/runtime/components/MarkdownText/index.js +0 -34
- package/services/PathDerivationService.js +0 -7
package/twoslash-transformer.js
CHANGED
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
import { PluginEvent } from "./observability/events.js";
|
|
2
|
+
import { emitSync, syncBuildId } from "./observability/sync-emitter.js";
|
|
2
3
|
import { DEFAULT_COMPILER_OPTIONS } from "./typescript-config.js";
|
|
4
|
+
import { Result } from "effect";
|
|
5
|
+
import { Markdown, Mdast } from "@effected/markdown";
|
|
6
|
+
import { TsEnumCodec } from "@effected/tsconfig-json";
|
|
3
7
|
import { rendererRich, transformerTwoslash } from "@shikijs/twoslash";
|
|
4
|
-
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
5
8
|
import { toHast } from "mdast-util-to-hast";
|
|
6
9
|
|
|
7
10
|
//#region src/twoslash-transformer.ts
|
|
8
11
|
/* v8 ignore start -- Shiki/Twoslash integration, requires full highlighter setup for testing */
|
|
9
12
|
/**
|
|
10
|
-
* Module-level emitter seam. Default is a no-op; wire in `setEventEmitter(emitSync)`
|
|
11
|
-
* from plugin.ts right after the runtime emitter is created so that Twoslash error
|
|
12
|
-
* events flow through the EventBus even though they fire in a sync Shiki callback
|
|
13
|
-
* outside any Effect fiber.
|
|
14
|
-
*/
|
|
15
|
-
let emitEvent = () => {};
|
|
16
|
-
let currentBuildId = "";
|
|
17
|
-
/**
|
|
18
|
-
* Inject the runtime-bound emitter into the Twoslash module.
|
|
19
|
-
* Call this right after `makeRuntimeEmitter` in plugin.ts.
|
|
20
|
-
*/
|
|
21
|
-
function setEventEmitter(fn, buildId = "") {
|
|
22
|
-
emitEvent = fn;
|
|
23
|
-
currentBuildId = buildId;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
13
|
* Module-level type routes map for resolving link references.
|
|
27
14
|
* This is set by TwoslashManager.setTypeRoutes() before initialization.
|
|
28
15
|
*/
|
|
@@ -116,8 +103,10 @@ function addLinkClasses(node) {
|
|
|
116
103
|
* Render markdown content to HAST (Hypertext Abstract Syntax Tree) elements.
|
|
117
104
|
*
|
|
118
105
|
* This function converts markdown strings (from TSDoc comments) into HAST nodes
|
|
119
|
-
* that can be rendered in Twoslash hover popups. It
|
|
120
|
-
*
|
|
106
|
+
* that can be rendered in Twoslash hover popups. It parses with
|
|
107
|
+
* `@effected/markdown` (CommonMark dialect) and converts to HAST with
|
|
108
|
+
* `mdast-util-to-hast`, which stays because markdown-to-HTML is permanently
|
|
109
|
+
* out of scope for the kit.
|
|
121
110
|
*
|
|
122
111
|
* TSDoc link references are transformed to markdown links before parsing.
|
|
123
112
|
* Whitespace is normalized for proper inline display.
|
|
@@ -131,8 +120,12 @@ function renderMarkdown(markdown) {
|
|
|
131
120
|
try {
|
|
132
121
|
let transformed = transformTsDocLinks(markdown);
|
|
133
122
|
transformed = transformed.split(/\n\n+/).map((para) => para.replace(/\s+/g, " ").trim()).filter((para) => para.length > 0).join("\n\n");
|
|
134
|
-
const
|
|
135
|
-
|
|
123
|
+
const parsed = Markdown.parseResult(transformed, { dialect: "commonmark" });
|
|
124
|
+
if (Result.isFailure(parsed)) return [{
|
|
125
|
+
type: "text",
|
|
126
|
+
value: markdown
|
|
127
|
+
}];
|
|
128
|
+
const hast = toHast(Mdast.toMdast(parsed.success));
|
|
136
129
|
if (hast && "children" in hast) {
|
|
137
130
|
const children = hast.children;
|
|
138
131
|
for (const child of children) addLinkClasses(child);
|
|
@@ -228,12 +221,86 @@ function renderMarkdownInline(markdown, context) {
|
|
|
228
221
|
*
|
|
229
222
|
* @see {@link TypeRegistryService} for VFS generation
|
|
230
223
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Fingerprint a compiler configuration so environments can be deduped and code
|
|
226
|
+
* blocks routed to the right one. Keys are sorted, so two configurations that
|
|
227
|
+
* differ only in property order share an environment.
|
|
228
|
+
*/
|
|
229
|
+
/**
|
|
230
|
+
* Convert resolved compiler options from the tsconfig JSON spelling to the
|
|
231
|
+
* programmatic one a real compiler expects.
|
|
232
|
+
*
|
|
233
|
+
* @remarks
|
|
234
|
+
* Two spellings meet here, and only here. `tsconfig.json` writes
|
|
235
|
+
* `lib: ["ESNext", "DOM"]` and `target: "esnext"`; `ts.CompilerOptions` wants
|
|
236
|
+
* lib FILE NAMES (`lib.esnext.d.ts`) and numeric enums. `DEFAULT_COMPILER_OPTIONS`
|
|
237
|
+
* is authored in the tsconfig spelling, and a tsconfig discovered from disk
|
|
238
|
+
* arrives already converted by `ts.parseJsonConfigFileContent`, so both forms
|
|
239
|
+
* reach this function — which is why the conversion must be idempotent rather
|
|
240
|
+
* than one-directional.
|
|
241
|
+
*
|
|
242
|
+
* Exported for the four-path regression test: no runtime path in this repo
|
|
243
|
+
* reaches the broken spelling (an unscoped block inherits the first registered
|
|
244
|
+
* environment, not the raw default), so a synthetic test compiling each
|
|
245
|
+
* resolution path through the real compiler is the only verification there is.
|
|
246
|
+
*/
|
|
247
|
+
function toProgrammaticCompilerOptions(options) {
|
|
248
|
+
return TsEnumCodec.encodeCompilerOptions(options);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Fingerprint a compiler configuration, for keying the environment map.
|
|
252
|
+
*
|
|
253
|
+
* @remarks
|
|
254
|
+
* INVARIANT: every call site must pass options that have already been through
|
|
255
|
+
* {@link toProgrammaticCompilerOptions}. There are two — `initialize`, which
|
|
256
|
+
* stores an environment under this key, and `registerScope`, which looks one
|
|
257
|
+
* up by it. Both must encode, and encode the same way.
|
|
258
|
+
*
|
|
259
|
+
* The failure mode is SILENT. Encode at one site and not the other and the
|
|
260
|
+
* keys stop matching, so `getTransformer(scope)` finds nothing and falls back
|
|
261
|
+
* to the default environment: per-scope type-checking quietly degrades to
|
|
262
|
+
* build-wide, no error is raised, and nothing in the output looks wrong.
|
|
263
|
+
*
|
|
264
|
+
* This is not hypothetical. Task 1.2 moved the `initialize` fingerprint behind
|
|
265
|
+
* the encoder as a step specified — and reviewed — as a no-op, left
|
|
266
|
+
* `registerScope` on the raw options, and the full 994-test suite stayed green
|
|
267
|
+
* over the defect. The mutation that should have caught it (fingerprinting the
|
|
268
|
+
* pre-encoded value) also survived that suite. What caught it was a test
|
|
269
|
+
* written specifically for the hazard, which then failed for this second,
|
|
270
|
+
* unanticipated reason. `__test__/twoslash-transformer.test.ts` now pins both
|
|
271
|
+
* halves; keep that test whenever this code moves.
|
|
272
|
+
*/
|
|
273
|
+
function twoslashConfigKey(options) {
|
|
274
|
+
const entries = Object.entries(options).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
275
|
+
return JSON.stringify(entries);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* The mutable registry behind {@link TwoslashEnvironments}.
|
|
279
|
+
*
|
|
280
|
+
* @remarks
|
|
281
|
+
* A plain class the Layer constructs, not a singleton. `getInstance()` and the
|
|
282
|
+
* static `reset()` that stood in for layer substitution are gone: a test that
|
|
283
|
+
* wants a different environment set provides a different layer.
|
|
284
|
+
*/
|
|
285
|
+
var TwoslashEnvironmentRegistry = class {
|
|
233
286
|
/**
|
|
234
|
-
*
|
|
287
|
+
* Transformers keyed by compiler-config fingerprint.
|
|
288
|
+
*
|
|
289
|
+
* One environment per DISTINCT configuration, not per API: two packages
|
|
290
|
+
* documented under the same compiler options share an environment, and with
|
|
291
|
+
* it the TypeScript language services Twoslash builds per block. A build
|
|
292
|
+
* where every API agrees on its config therefore costs exactly what the
|
|
293
|
+
* single shared environment used to.
|
|
235
294
|
*/
|
|
236
|
-
|
|
295
|
+
environments = /* @__PURE__ */ new Map();
|
|
296
|
+
/** API scope to config fingerprint, for `getTransformer(scope)`. */
|
|
297
|
+
scopeConfigs = /* @__PURE__ */ new Map();
|
|
298
|
+
/**
|
|
299
|
+
* Fingerprint of the first environment initialized, used for code blocks
|
|
300
|
+
* that carry no scope — a `with-api` fence in a page outside any documented
|
|
301
|
+
* package's route.
|
|
302
|
+
*/
|
|
303
|
+
defaultConfigKey = null;
|
|
237
304
|
/**
|
|
238
305
|
* VFS keys snapshot captured at initialize() time.
|
|
239
306
|
* Returned by vfsKeysSnapshot() for TwoslashCheckFailed events.
|
|
@@ -243,7 +310,7 @@ var TwoslashManager = class TwoslashManager {
|
|
|
243
310
|
* Resolved compiler options captured at initialize() time.
|
|
244
311
|
* Returned by compilerOptionsSnapshot() for TwoslashCheckFailed events.
|
|
245
312
|
*/
|
|
246
|
-
_resolvedCompilerOptions = DEFAULT_COMPILER_OPTIONS;
|
|
313
|
+
_resolvedCompilerOptions = toProgrammaticCompilerOptions(DEFAULT_COMPILER_OPTIONS);
|
|
247
314
|
/**
|
|
248
315
|
* Path of the file whose code block is currently being processed.
|
|
249
316
|
* Used to attribute Twoslash error events to a source file. Defaults to
|
|
@@ -252,33 +319,25 @@ var TwoslashManager = class TwoslashManager {
|
|
|
252
319
|
*/
|
|
253
320
|
currentFilePath = "unknown";
|
|
254
321
|
/**
|
|
255
|
-
*
|
|
256
|
-
*/
|
|
257
|
-
constructor() {}
|
|
258
|
-
/**
|
|
259
|
-
* Get the singleton instance of TwoslashManager
|
|
260
|
-
*/
|
|
261
|
-
static getInstance() {
|
|
262
|
-
if (!TwoslashManager.instance) TwoslashManager.instance = new TwoslashManager();
|
|
263
|
-
return TwoslashManager.instance;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Initialize the Twoslash transformer with a TypeScript environment cache.
|
|
267
|
-
* This enables type-aware documentation with hover information and IntelliSense.
|
|
322
|
+
* Build an environment for a configuration, or return if one exists.
|
|
268
323
|
*
|
|
269
|
-
* @
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
324
|
+
* @remarks
|
|
325
|
+
* The signature this replaces took six positional parameters, two named
|
|
326
|
+
* `_reserved`/`_reserved2` and one (`tsEnvCache`) that every call site
|
|
327
|
+
* passed as `undefined`. Dropping `tsEnvCache` changes nothing at runtime
|
|
328
|
+
* for exactly that reason — Twoslash was never handed a shared environment
|
|
329
|
+
* cache.
|
|
274
330
|
*/
|
|
275
|
-
|
|
331
|
+
registerEnvironment({ vfs, compilerOptions, typesCache }) {
|
|
276
332
|
const extraFiles = {};
|
|
277
333
|
for (const [path, content] of vfs.entries()) extraFiles[path] = content;
|
|
278
334
|
this._vfsKeys = Array.from(vfs.keys());
|
|
279
|
-
const resolvedOptions = compilerOptions ?? DEFAULT_COMPILER_OPTIONS;
|
|
335
|
+
const resolvedOptions = toProgrammaticCompilerOptions(compilerOptions ?? DEFAULT_COMPILER_OPTIONS);
|
|
280
336
|
this._resolvedCompilerOptions = resolvedOptions;
|
|
281
|
-
|
|
337
|
+
const configKey = twoslashConfigKey(resolvedOptions);
|
|
338
|
+
if (this.defaultConfigKey === null) this.defaultConfigKey = configKey;
|
|
339
|
+
if (this.environments.has(configKey)) return;
|
|
340
|
+
const transformer = transformerTwoslash({
|
|
282
341
|
renderer: rendererRich({
|
|
283
342
|
processHoverInfo: (info) => {
|
|
284
343
|
return info.replace(/^\(([\w-]+)\)\s+/gm, "").replace(/\nimport .*$/gm, "").trim();
|
|
@@ -287,7 +346,7 @@ var TwoslashManager = class TwoslashManager {
|
|
|
287
346
|
renderMarkdown,
|
|
288
347
|
renderMarkdownInline
|
|
289
348
|
}),
|
|
290
|
-
...
|
|
349
|
+
...typesCache != null ? { typesCache } : {},
|
|
291
350
|
twoslashOptions: {
|
|
292
351
|
extraFiles,
|
|
293
352
|
compilerOptions: resolvedOptions,
|
|
@@ -299,13 +358,26 @@ var TwoslashManager = class TwoslashManager {
|
|
|
299
358
|
this.handleTwoslashError(error, code, this.currentFilePath);
|
|
300
359
|
}
|
|
301
360
|
});
|
|
361
|
+
this.environments.set(configKey, transformer);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Associate an API scope with the compiler configuration it is documented
|
|
365
|
+
* under, so its code blocks are type-checked with that configuration.
|
|
366
|
+
*/
|
|
367
|
+
registerScope(apiScope, compilerOptions) {
|
|
368
|
+
this.scopeConfigs.set(apiScope, twoslashConfigKey(toProgrammaticCompilerOptions(compilerOptions)));
|
|
302
369
|
}
|
|
303
370
|
/**
|
|
304
|
-
* Get the
|
|
305
|
-
*
|
|
371
|
+
* Get the Twoslash transformer for an API scope.
|
|
372
|
+
*
|
|
373
|
+
* An unknown or absent scope falls back to the first environment built: a
|
|
374
|
+
* `with-api` fence can appear on a page outside any documented package's
|
|
375
|
+
* route, and type-checking it under some configuration beats not checking it.
|
|
376
|
+
* Returns null before any environment is initialized.
|
|
306
377
|
*/
|
|
307
|
-
|
|
308
|
-
|
|
378
|
+
transformerFor(apiScope) {
|
|
379
|
+
const key = (apiScope != null ? this.scopeConfigs.get(apiScope) : void 0) ?? this.defaultConfigKey;
|
|
380
|
+
return key != null ? this.environments.get(key) ?? null : null;
|
|
309
381
|
}
|
|
310
382
|
/**
|
|
311
383
|
* Set the source file path used to attribute subsequent Twoslash error events.
|
|
@@ -320,13 +392,9 @@ var TwoslashManager = class TwoslashManager {
|
|
|
320
392
|
* Clear the Twoslash transformer (useful for testing or reinitializing)
|
|
321
393
|
*/
|
|
322
394
|
clear() {
|
|
323
|
-
this.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
* Reset the singleton instance (useful for testing)
|
|
327
|
-
*/
|
|
328
|
-
static reset() {
|
|
329
|
-
TwoslashManager.instance = null;
|
|
395
|
+
this.environments.clear();
|
|
396
|
+
this.scopeConfigs.clear();
|
|
397
|
+
this.defaultConfigKey = null;
|
|
330
398
|
}
|
|
331
399
|
/** Returns VFS keys snapshotted at initialize() time. Empty array before initialize(). */
|
|
332
400
|
vfsKeysSnapshot() {
|
|
@@ -340,9 +408,9 @@ var TwoslashManager = class TwoslashManager {
|
|
|
340
408
|
const message = error instanceof Error ? error.message : String(error);
|
|
341
409
|
const match = /TS(\d+)/.exec(message);
|
|
342
410
|
const tsCode = match ? Number(match[1]) : 0;
|
|
343
|
-
|
|
411
|
+
emitSync(PluginEvent.TwoslashDiagnostic({
|
|
344
412
|
ctx: {
|
|
345
|
-
buildId:
|
|
413
|
+
buildId: syncBuildId(),
|
|
346
414
|
file
|
|
347
415
|
},
|
|
348
416
|
level: "warn",
|
|
@@ -353,9 +421,9 @@ var TwoslashManager = class TwoslashManager {
|
|
|
353
421
|
message,
|
|
354
422
|
snippet: ""
|
|
355
423
|
}));
|
|
356
|
-
|
|
424
|
+
emitSync(PluginEvent.TwoslashCheckFailed({
|
|
357
425
|
ctx: {
|
|
358
|
-
buildId:
|
|
426
|
+
buildId: syncBuildId(),
|
|
359
427
|
file
|
|
360
428
|
},
|
|
361
429
|
level: "trace",
|
|
@@ -369,34 +437,30 @@ var TwoslashManager = class TwoslashManager {
|
|
|
369
437
|
* Test seam: drive `handleTwoslashError` directly without going through the Shiki transformer.
|
|
370
438
|
* @internal
|
|
371
439
|
*/
|
|
372
|
-
|
|
440
|
+
reportErrorForTest(error, code, file) {
|
|
373
441
|
this.handleTwoslashError(error, code, file);
|
|
374
442
|
}
|
|
375
|
-
/**
|
|
376
|
-
* Set the type routes map for resolving link references in hover docs.
|
|
377
|
-
* This should be called before initialize() to enable type linking.
|
|
378
|
-
*
|
|
379
|
-
* @param routes - Map of type names to their documentation URLs
|
|
380
|
-
*/
|
|
381
|
-
static setTypeRoutes(routes) {
|
|
382
|
-
typeRoutes = routes;
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Add routes to the existing type routes map.
|
|
386
|
-
* Useful for adding routes from multiple packages.
|
|
387
|
-
*
|
|
388
|
-
* @param routes - Map of type names to their documentation URLs
|
|
389
|
-
*/
|
|
390
|
-
static addTypeRoutes(routes) {
|
|
391
|
-
for (const [name, route] of routes) typeRoutes.set(name, route);
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Clear the type routes map (useful for testing)
|
|
395
|
-
*/
|
|
396
|
-
static clearTypeRoutes() {
|
|
397
|
-
typeRoutes.clear();
|
|
398
|
-
}
|
|
399
443
|
};
|
|
444
|
+
/** Merge routes in, so a multi-API build accumulates every scope's names. */
|
|
445
|
+
function addTypeRoutes(routes) {
|
|
446
|
+
for (const [name, route] of routes) typeRoutes.set(name, route);
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Clear the accumulated type routes.
|
|
450
|
+
*
|
|
451
|
+
* @remarks
|
|
452
|
+
* Called from `config()` at the start of every build. `addTypeRoutes` only
|
|
453
|
+
* ever adds, so without this a dev session keeps routes for items that have
|
|
454
|
+
* since been renamed or removed, and a multi-API build leaks every scope's
|
|
455
|
+
* names into one map.
|
|
456
|
+
*
|
|
457
|
+
* Clears ONLY the routes. The environments are per-build too, but they are
|
|
458
|
+
* owned by the layer now, so nothing here can discard the per-scope
|
|
459
|
+
* transformers `ConfigServiceLive` just built.
|
|
460
|
+
*/
|
|
461
|
+
function clearTypeRoutes() {
|
|
462
|
+
typeRoutes.clear();
|
|
463
|
+
}
|
|
400
464
|
|
|
401
465
|
//#endregion
|
|
402
|
-
export {
|
|
466
|
+
export { TwoslashEnvironmentRegistry, addTypeRoutes, clearTypeRoutes, toProgrammaticCompilerOptions };
|
package/vfs-registry.js
CHANGED
|
@@ -34,35 +34,6 @@ var VfsRegistryImpl = class {
|
|
|
34
34
|
return this.configs.get(apiScope);
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Get the VFS configuration by matching a file path to an API scope.
|
|
38
|
-
*
|
|
39
|
-
* This method extracts the API scope from a file path and returns
|
|
40
|
-
* the corresponding VFS configuration.
|
|
41
|
-
*
|
|
42
|
-
* @param filePath - The absolute file path being processed
|
|
43
|
-
* @returns The VFS configuration, or undefined if not found
|
|
44
|
-
*/
|
|
45
|
-
getByFilePath(filePath) {
|
|
46
|
-
const apiScope = this.extractApiScope(filePath);
|
|
47
|
-
if (!apiScope) return;
|
|
48
|
-
return this.get(apiScope);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Extract the API scope from a file path.
|
|
52
|
-
*
|
|
53
|
-
* Path patterns:
|
|
54
|
-
* - `docs/en/api-scope/rest.mdx`
|
|
55
|
-
* - `website/docs/en/api-scope/rest.mdx`
|
|
56
|
-
*
|
|
57
|
-
* @param filePath - The file path to extract from
|
|
58
|
-
* @returns The API scope, or undefined if not matched
|
|
59
|
-
*/
|
|
60
|
-
extractApiScope(filePath) {
|
|
61
|
-
const match = filePath.replace(/\\/g, "/").match(/(?:^|\/)(docs\/en|website\/docs\/en)\/([^/]+)(?:\/|$)/);
|
|
62
|
-
if (!match) return;
|
|
63
|
-
return match[2];
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
37
|
* Check if any VFS configurations are registered.
|
|
67
38
|
*
|
|
68
39
|
* @returns True if at least one configuration is registered
|
|
@@ -96,7 +67,6 @@ var VfsRegistryImpl = class {
|
|
|
96
67
|
* ```ts
|
|
97
68
|
* // In beforeBuild hook:
|
|
98
69
|
* VfsRegistry.register("claude-binary-plugin", {
|
|
99
|
-
* vfs: combinedVfs,
|
|
100
70
|
* highlighter,
|
|
101
71
|
* twoslashTransformer,
|
|
102
72
|
* crossLinker: shikiCrossLinker,
|
|
@@ -105,7 +75,7 @@ var VfsRegistryImpl = class {
|
|
|
105
75
|
* });
|
|
106
76
|
*
|
|
107
77
|
* // In remark plugin:
|
|
108
|
-
* const config = VfsRegistry.
|
|
78
|
+
* const config = VfsRegistry.get(apiScope);
|
|
109
79
|
* if (config) {
|
|
110
80
|
* // Generate HAST with Shiki, then post-process with cross-linker
|
|
111
81
|
* let hast = await generateShikiHast(code, config.highlighter, transformers);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { deriveOutputPaths, normalizeBaseRoute } from "../path-derivation.js";
|
|
2
|
-
import { PathDerivationService } from "../services/PathDerivationService.js";
|
|
3
|
-
import { Effect, Layer } from "effect";
|
|
4
|
-
|
|
5
|
-
//#region src/layers/PathDerivationServiceLive.ts
|
|
6
|
-
const PathDerivationServiceLive = Layer.succeed(PathDerivationService, {
|
|
7
|
-
derivePaths: (input) => Effect.succeed(deriveOutputPaths({
|
|
8
|
-
...input,
|
|
9
|
-
locales: [...input.locales],
|
|
10
|
-
versions: [...input.versions]
|
|
11
|
-
})),
|
|
12
|
-
normalizeBaseRoute: (route) => Effect.succeed(normalizeBaseRoute(route))
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
//#endregion
|
|
16
|
-
export { PathDerivationServiceLive };
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
//#region src/runtime/components/MarkdownText/index.tsx
|
|
4
|
-
/**
|
|
5
|
-
* Renders plain text with markdown links as React elements.
|
|
6
|
-
* Only supports basic markdown links: [text](url)
|
|
7
|
-
*/
|
|
8
|
-
function MarkdownText({ children }) {
|
|
9
|
-
const parts = parseMarkdownLinks(children);
|
|
10
|
-
return /* @__PURE__ */ jsx(Fragment, { children: parts });
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Parse markdown links and return array of React nodes
|
|
14
|
-
*/
|
|
15
|
-
function parseMarkdownLinks(text) {
|
|
16
|
-
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
17
|
-
const parts = [];
|
|
18
|
-
let lastIndex = 0;
|
|
19
|
-
let key = 0;
|
|
20
|
-
for (const match of text.matchAll(linkRegex)) {
|
|
21
|
-
if (match.index !== void 0 && match.index > lastIndex) parts.push(text.slice(lastIndex, match.index));
|
|
22
|
-
const [fullMatch, linkText, url] = match;
|
|
23
|
-
parts.push(/* @__PURE__ */ jsx("a", {
|
|
24
|
-
href: url,
|
|
25
|
-
children: linkText
|
|
26
|
-
}, key++));
|
|
27
|
-
lastIndex = (match.index ?? 0) + fullMatch.length;
|
|
28
|
-
}
|
|
29
|
-
if (lastIndex < text.length) parts.push(text.slice(lastIndex));
|
|
30
|
-
return parts;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
//#endregion
|
|
34
|
-
export { MarkdownText, MarkdownText as default };
|