vitepress-plugin-api-extractor 0.1.2 → 0.2.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/ApiExtractor.js CHANGED
@@ -5,20 +5,6 @@ import { TwoslashCacheStore } from "./TwoslashCache.js";
5
5
  import { Effect, Layer, ManagedRuntime } from "effect";
6
6
 
7
7
  //#region src/ApiExtractor.ts
8
- /**
9
- * The public helper a site's `.vitepress/config.mts` awaits at config-load
10
- * time: generates the pages, opens the Twoslash result cache and returns the
11
- * sidebar, the code transformer and the `buildEnd` hook that persists the
12
- * cache.
13
- *
14
- * @remarks
15
- * Generation happens HERE, at config load, because VitePress has no
16
- * pre-scan hook comparable to RSPress's `config()`: its config file is ESM
17
- * and may top-level await, and `buildEnd` / `postRender` run after the fact.
18
- * The result is merged into `defineConfig` by the site.
19
- *
20
- * @packageDocumentation
21
- */
22
8
  const AppLive = Layer.mergeAll(PlatformLive, RegistryLive, TwoslashCacheStore.layer);
23
9
  /**
24
10
  * Generate the API pages and return what the site's config needs.
@@ -55,7 +41,8 @@ async function apiExtractor(options) {
55
41
  categories: options.categories,
56
42
  externalPackages: options.externalPackages,
57
43
  suppressExampleErrors: options.suppressExampleErrors,
58
- source: options.source
44
+ source: options.source,
45
+ ogImage: options.ogImage
59
46
  }));
60
47
  const envHash = environmentHash(generated.vfs);
61
48
  const typesCache = await runtime.runPromise(Effect.gen(function* () {
package/Generate.js CHANGED
@@ -5,9 +5,9 @@ import { sidebarFor } from "./emit/sidebar.js";
5
5
  import { externalPackagesOf, loadExternalTypes } from "./Registry.js";
6
6
  import { Effect, FileSystem, Option, Path } from "effect";
7
7
  import { PackageManifest } from "@effected/package-json";
8
- import { discoverBundle } from "@tsdoctor/bundle";
8
+ import { loadBundle, publishBundleAssets, resolveBundleFrom } from "@tsdoctor/bundle";
9
9
  import { ApiExtractedPackage, CrossLinker, Model, TypeReferenceExtractor } from "@tsdoctor/model";
10
- import { buildIndexPage, buildNav, buildPage, prepareWorkItems } from "@tsdoctor/pages";
10
+ import { buildIndexPage, buildNav, buildPage, prepareWorkItems, unscopedName } from "@tsdoctor/pages";
11
11
  import { attributionFacts, deriveScriptBody, deriveSiteUrl, headTags, packageContext } from "@tsdoctor/seo";
12
12
  import { resolveTypeScriptConfig } from "@tsdoctor/vfs";
13
13
 
@@ -74,7 +74,8 @@ const fileFor = (docsDir, route) => `${docsDir}${route}.md`;
74
74
  const generate = Effect.fn("Generate.generate")(function* (input) {
75
75
  const fs = yield* FileSystem.FileSystem;
76
76
  const path = yield* Path.Path;
77
- const descriptor = yield* discoverBundle(input.dir, { cwd: input.cwd });
77
+ const bundle = yield* loadBundle(input.dir, { cwd: input.cwd });
78
+ const descriptor = bundle.descriptor;
78
79
  const apiPackage = yield* Model.load(descriptor.modelPath);
79
80
  const packageName = descriptor.name;
80
81
  const packageJson = descriptor.packageJsonPath === void 0 ? void 0 : yield* fs.readFileString(descriptor.packageJsonPath).pipe(Effect.map((text) => JSON.parse(text)), Effect.orElseSucceed(() => void 0));
@@ -92,6 +93,17 @@ const generate = Effect.fn("Generate.generate")(function* (input) {
92
93
  if (prepared.collisions.length > 0) return yield* Effect.die(/* @__PURE__ */ new Error(`route collisions under ${input.baseRoute}: ${prepared.collisions.map((c) => `${c.route} <- ${c.items.map((i) => i.displayName).join(", ")}`).join("; ")}`));
93
94
  const linker = CrossLinker.fromRoutes(prepared.crossLinkData.routes);
94
95
  const siteUrl = deriveSiteUrl(input.siteOrigin, input.base);
96
+ const docsDir = path.resolve(input.cwd, input.docsDir);
97
+ const platform = input.ogImage === void 0 ? {} : { openGraph: { images: [typeof input.ogImage === "string" ? /^https?:\/\//.test(input.ogImage) ? { url: input.ogImage } : { path: input.ogImage } : input.ogImage] } };
98
+ const resolvedBundle = resolveBundleFrom(bundle, platform);
99
+ const siteName = resolvedBundle.project?.value.name ?? resolvedBundle.name.value;
100
+ const ogImage = (resolvedBundle.openGraph === void 0 ? [] : yield* publishBundleAssets({
101
+ bundleDir: descriptor.dir,
102
+ images: resolvedBundle.openGraph.value.images,
103
+ publicDir: path.join(docsDir, "public"),
104
+ siteUrl,
105
+ unscopedName: unscopedName(packageName)
106
+ }).pipe(Effect.orElseSucceed(() => [])))[0];
95
107
  const structuredDataPkg = manifest === void 0 ? void 0 : packageContext({
96
108
  siteUrl,
97
109
  baseRoute: input.baseRoute,
@@ -101,7 +113,6 @@ const generate = Effect.fn("Generate.generate")(function* (input) {
101
113
  attribution: attributionFacts(manifest)
102
114
  });
103
115
  const buildTime = (/* @__PURE__ */ new Date()).toISOString();
104
- const docsDir = path.resolve(input.cwd, input.docsDir);
105
116
  const entries = [];
106
117
  const routes = [];
107
118
  const formatFailures = [];
@@ -111,6 +122,8 @@ const generate = Effect.fn("Generate.generate")(function* (input) {
111
122
  packageName,
112
123
  linker,
113
124
  siteUrl,
125
+ siteName,
126
+ ogImage,
114
127
  structuredDataPkg,
115
128
  buildTime,
116
129
  docsDir,
@@ -190,11 +203,14 @@ const writePage = Effect.fn("Generate.writePage")(function* (workItem, ctx) {
190
203
  const tags = headTags({
191
204
  siteUrl: ctx.siteUrl,
192
205
  pageRoute: page.route,
206
+ title: item.displayName,
207
+ siteName: ctx.siteName,
193
208
  description: page.description,
194
209
  publishedTime: ctx.buildTime,
195
210
  modifiedTime: ctx.buildTime,
196
211
  section: categoryConfig.displayName,
197
212
  packageName: ctx.packageName,
213
+ ...ctx.ogImage !== void 0 ? { ogImage: ctx.ogImage } : {},
198
214
  ...structuredData !== void 0 && structuredData._tag === "Success" ? { structuredData: structuredData.success } : {}
199
215
  });
200
216
  const body = yield* Effect.fromResult(emitMarkdownBody(page)).pipe(Effect.orDie);
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { OpenGraphImage } from "@tsdoctor/bundle";
1
2
  import { ShikiTransformer } from "shiki";
2
3
  import { Block, CrossLinkData, NavTree, Page, WorkItemCategory } from "@tsdoctor/pages";
3
4
  import { Model } from "@tsdoctor/model";
@@ -164,6 +165,13 @@ interface GenerateInput {
164
165
  readonly url: string;
165
166
  readonly ref?: string | undefined;
166
167
  } | undefined;
168
+ /**
169
+ * The `manifest.platform` Open Graph image override, ranked above the
170
+ * bundle's own `tsdoctor.json`. A string is an absolute `http(s)://` URL or
171
+ * a path relative to the bundle directory; an object is the manifest image
172
+ * shape (`path` XOR `url`, plus `type`/`width`/`height`/`alt`).
173
+ */
174
+ readonly ogImage?: string | OpenGraphImage | undefined;
167
175
  }
168
176
  /**
169
177
  * What generation produced, for the site's config and for the report.
@@ -235,7 +243,7 @@ declare const generate: (input: GenerateInput) => Effect.Effect<{
235
243
  };
236
244
  uncategorized: string[];
237
245
  formatFailures: string[];
238
- }, import("@tsdoctor/bundle").BundleDiscoveryError | import("@tsdoctor/bundle").BundleLayerError | Model.ModelNotFoundError | Model.ModelParseError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path | TypeRegistry>;
246
+ }, import("@tsdoctor/bundle").BundleDiscoveryError | import("@tsdoctor/bundle").BundleLayerError | import("@tsdoctor/bundle").BundleManifestError | Model.ModelNotFoundError | Model.ModelParseError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path | TypeRegistry>;
239
247
  /**
240
248
  * The services {@link generate} runs over: the platform plus the registry.
241
249
  *
@@ -326,6 +334,13 @@ interface ApiExtractorOptions {
326
334
  readonly url: string;
327
335
  readonly ref?: string | undefined;
328
336
  } | undefined;
337
+ /**
338
+ * The `manifest.platform` Open Graph image override, ranked above the
339
+ * bundle's own `tsdoctor.json`. A string is an absolute `http(s)://` URL or
340
+ * a path relative to the bundle directory; an object is the manifest image
341
+ * shape (`path` XOR `url`, plus `type`/`width`/`height`/`alt`).
342
+ */
343
+ readonly ogImage?: string | OpenGraphImage | undefined;
329
344
  /** Whether to print a one-line summary. Defaults to `true`. */
330
345
  readonly log?: boolean | undefined;
331
346
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitepress-plugin-api-extractor",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "VitePress adapter for generating API documentation from TypeScript API Extractor models: markdown pages over the @tsdoctor/pages IR, a sidebar from its navigation tree, and Twoslash type-checking over the same virtual file system the RSPress plugin resolves.",
6
6
  "keywords": [
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@effect/platform-node": "4.0.0-rc.109",
41
- "@effected/markdown": "^0.8.0",
41
+ "@effected/markdown": "^0.8.1",
42
42
  "@effected/package-json": "^0.13.0",
43
43
  "@effected/store": "^0.6.0",
44
44
  "@effected/tsconfig-json": "^0.7.0",
@@ -46,13 +46,15 @@
46
46
  "@microsoft/api-extractor-model": "^7.33.11",
47
47
  "@shikijs/twoslash": "^4.4.3",
48
48
  "@shikijs/vitepress-twoslash": "^4.4.3",
49
- "@tsdoctor/bundle": "0.2.4",
50
- "@tsdoctor/model": "0.6.1",
51
- "@tsdoctor/pages": "0.1.1",
52
- "@tsdoctor/registry": "0.3.2",
53
- "@tsdoctor/seo": "0.1.2",
49
+ "@tsdoctor/bundle": "0.3.0",
50
+ "@tsdoctor/manifest": "0.1.0",
51
+ "@tsdoctor/model": "0.6.2",
52
+ "@tsdoctor/pages": "0.1.3",
53
+ "@tsdoctor/registry": "0.3.3",
54
+ "@tsdoctor/seo": "0.2.0",
54
55
  "@tsdoctor/vfs": "0.2.1",
55
56
  "effect": "4.0.0-rc.109",
57
+ "image-size": "^2.0.2",
56
58
  "shiki": "^4.4.3",
57
59
  "typescript": "^6.0.3"
58
60
  },