@callstack/rspress-preset 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Callstack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # Callstack Rspress Preset
2
+
3
+ ## Installation
4
+
5
+ To install the `@callstack/rspress-preset` package, use your package manager of choice.
6
+
7
+ ```bash
8
+ npm install @callstack/rspress-preset
9
+ # or
10
+ yarn add @callstack/rspress-preset
11
+ # or
12
+ pnpm add @callstack/rspress-preset
13
+ # or
14
+ bun add @callstack/rspress-preset
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Use the preset helper `withCallstackPreset` to generate a complete Rspress config from a small set of options, and then merge it with your own overrides if needed.
20
+
21
+ > The preset wires up the Callstack theme, sensible defaults, sitemap and open-graph plugins, search, clean URLs, and common theme config.
22
+
23
+ Update your `rspress.config.ts`:
24
+
25
+ ```ts
26
+ import { defineConfig } from '@rspress/core';
27
+ import { withCallstackPreset } from '@callstack/rspress-preset';
28
+
29
+ export default withCallstackPreset(
30
+ {
31
+ context: __dirname,
32
+ docs: {
33
+ title: 'My Project',
34
+ description: 'Awesome docs powered by Rspress',
35
+ editUrl: 'https://github.com/org/repo/edit/main',
36
+ rootUrl: 'https://docs.example.com',
37
+ icon: 'icon.ico',
38
+ logoLight: 'logo-light.png',
39
+ logoDark: 'logo-dark.png',
40
+ ogImage: 'og-image.png',
41
+ // Optional: defaults to 'docs'
42
+ rootDir: 'docs',
43
+ // Optional: social links; keys follow Rspress theme icons
44
+ socials: {
45
+ github: 'https://github.com/org/repo',
46
+ x: 'https://x.com/my_profile',
47
+ },
48
+ },
49
+ // Optional: forwarded to @callstack/rspress-theme/plugin
50
+ theme: {
51
+ // theme settings
52
+ },
53
+ // Optional: boolean or config for rspress-plugin-vercel-analytics.
54
+ vercelAnalytics: true,
55
+ },
56
+ defineConfig({
57
+ // Your extra/override Rspress config if needed
58
+ })
59
+ );
60
+ ```
61
+
62
+ ### Required/expected public assets
63
+
64
+ All graphical assets are optional but recommended. Place files in `<docs.rootDir>/public/` (default `docs/public/`), and set their filenames via theme options (`docs.icon`, `docs.logoLight`, `docs.logoDark`, `docs.ogImage`). Defaults are used if omitted.
65
+
66
+ - **Favicon**: default `icon.png` (supports `png|svg|jpg|jpeg|webp|avif|ico`)
67
+ - **Logo (light)**: default `logo-light.png` (supports `png|svg|jpg|jpeg|webp|avif`)
68
+ - **Logo (dark)**: default `logo-dark.png` (supports `png|svg|jpg|jpeg|webp|avif`)
69
+ - **Open Graph image**: default `og.png` (supports `png|svg|jpg|jpeg|webp|avif`)
70
+
71
+ If only one of `logoLight` or `logoDark` is provided, it will be used for both modes.
72
+
73
+ ## Options Reference
74
+
75
+ ```ts
76
+ withCallstackPreset(options, userConfig)
77
+ ```
78
+
79
+ - **options** (object, required): Preset options.
80
+ - **options.context** (string, required): Absolute path to your project root (e.g. `__dirname`).
81
+ - **options.docs** (object, required):
82
+ - **title** (string, required): Docs site title.
83
+ - **description** (string, required): Site description.
84
+ - **editUrl** (url string, required): Base repo URL used to build “Edit this page” links.
85
+ - **icon** (string, optional): Filename from docs public directory for site icon.
86
+ - **logoLight** (string, optional): Filename from docs public for light logo.
87
+ - **logoDark** (string, optional): Filename from docs public for dark logo.
88
+ - **ogImage** (string, optional): Filename from docs public for Open Graph image.
89
+ - **rootDir** (string, optional): Directory containing markdown docs. Default: `docs`.
90
+ - **rootUrl** (url string, required): Absolute site origin, e.g. `https://docs.example.com`.
91
+ - **socials** (record, optional): Map of social icon name → URL. Keys must match Rspress theme `socialLinks` icons (e.g. `github`, `x`, `discord`, …).
92
+ - **options.theme** (object, optional): Passed through to `@callstack/rspress-theme/plugin`. See that package for available settings.
93
+ - **options.vercelAnalytics** (boolean | object, optional): Enable/disable Vercel Analytics or pass its config. If omitted, it auto-enables when a `vercel.json` exists at the project root.
94
+
95
+ - **userConfig** (Rspress `UserConfig`, optional): Your additional config merged after the preset config via `mergeDocConfig`.
package/dist/index.cjs ADDED
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ withCallstackPreset: ()=>withCallstackPreset
37
+ });
38
+ const external_node_fs_namespaceObject = require("node:fs");
39
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
40
+ const external_node_path_namespaceObject = require("node:path");
41
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
42
+ const plugin_namespaceObject = require("@callstack/rspress-theme/plugin");
43
+ const core_namespaceObject = require("@rspress/core");
44
+ const plugin_llms_namespaceObject = require("@rspress/plugin-llms");
45
+ const plugin_sitemap_namespaceObject = require("@rspress/plugin-sitemap");
46
+ const external_rsbuild_plugin_open_graph_namespaceObject = require("rsbuild-plugin-open-graph");
47
+ const external_rspress_plugin_vercel_analytics_namespaceObject = require("rspress-plugin-vercel-analytics");
48
+ var external_rspress_plugin_vercel_analytics_default = /*#__PURE__*/ __webpack_require__.n(external_rspress_plugin_vercel_analytics_namespaceObject);
49
+ const external_node_util_namespaceObject = require("node:util");
50
+ const external_zod_namespaceObject = require("zod");
51
+ const nonEmptyString = external_zod_namespaceObject.z.string().trim().min(1, {
52
+ message: 'must be a non-empty string'
53
+ });
54
+ const presetOptionsSchema = external_zod_namespaceObject.z.object({
55
+ context: nonEmptyString.refine((value)=>external_node_path_default().isAbsolute(value), {
56
+ message: 'must be an absolute path'
57
+ }).describe('Absolute path to the project root'),
58
+ docs: external_zod_namespaceObject.z.object({
59
+ title: nonEmptyString.describe('Title of the docs'),
60
+ description: nonEmptyString.describe("Description of the docs"),
61
+ editUrl: external_zod_namespaceObject.z.string().trim().url({
62
+ message: 'must be a valid URL'
63
+ }).describe('Base URL to repository for edit links'),
64
+ logoLight: nonEmptyString.optional().describe('Filename from docs public directory for light mode logo (default: logo-light.png)'),
65
+ logoDark: nonEmptyString.optional().describe('Filename from docs public directory for dark mode logo (default: logo-dark.png)'),
66
+ icon: nonEmptyString.optional().describe('Filename from docs public directory for site icon (default: icon.png)'),
67
+ ogImage: nonEmptyString.optional().describe('Filename from docs public directory for Open Graph image (default: og.png)'),
68
+ rootDir: nonEmptyString.optional().describe('Root directory containing markdown docs'),
69
+ rootUrl: external_zod_namespaceObject.z.string().trim().url({
70
+ message: 'must be a valid URL'
71
+ }).describe('Absolute public site origin (e.g. https://example.com)'),
72
+ socials: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.string().url()).optional().describe('Map of social icon name to profile URL')
73
+ }),
74
+ theme: external_zod_namespaceObject.z.unknown().optional(),
75
+ vercelAnalytics: external_zod_namespaceObject.z.union([
76
+ external_zod_namespaceObject.z.boolean(),
77
+ external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown())
78
+ ]).optional().describe('Enable/disable Vercel Analytics or pass its config (overrides auto-detect)')
79
+ });
80
+ function error(...message) {
81
+ for (const msg of message)console.error((0, external_node_util_namespaceObject.styleText)('red', msg));
82
+ }
83
+ function validatePresetOptions(options) {
84
+ const result = presetOptionsSchema.safeParse(options);
85
+ if (!result.success) {
86
+ const bullets = result.error.issues.map((issue)=>{
87
+ var _current__def;
88
+ const pathSegments = issue.path;
89
+ const pathLabel = pathSegments.length > 0 ? pathSegments.join('.') : 'root';
90
+ let current = presetOptionsSchema;
91
+ for (const segment of pathSegments)if (current instanceof external_zod_namespaceObject.z.ZodObject) {
92
+ const objectSchema = current;
93
+ const shape = objectSchema.shape;
94
+ current = shape[String(segment)];
95
+ } else if (current instanceof external_zod_namespaceObject.z.ZodRecord) current = current._def.valueType;
96
+ else break;
97
+ const description = null == current ? void 0 : null == (_current__def = current._def) ? void 0 : _current__def.description;
98
+ const received = issue.received;
99
+ const details = received ? `${issue.message} \u{2014} received ${received}` : issue.message;
100
+ const withDesc = description ? `${details} (${description})` : details;
101
+ return `- ${pathLabel}: ${withDesc}`;
102
+ }).join('\n');
103
+ error('Invalid @callstack/rspress-preset configuration:');
104
+ error(bullets);
105
+ process.exit(1);
106
+ }
107
+ return result.data;
108
+ }
109
+ function createSocialLinks(socials) {
110
+ return Object.entries(socials ?? {}).map(([key, value])=>({
111
+ icon: key,
112
+ mode: 'link',
113
+ content: value
114
+ }));
115
+ }
116
+ const createPreset = (config)=>{
117
+ var _docs_socials, _docs_socials1;
118
+ const { context, docs, theme, vercelAnalytics } = config;
119
+ const rootDir = external_node_path_default().join(context, docs.rootDir ?? 'docs');
120
+ const enableVercel = void 0 === vercelAnalytics ? external_node_fs_default().existsSync(external_node_path_default().join(context, 'vercel.json')) : Boolean(vercelAnalytics);
121
+ const vercelOptions = 'object' == typeof vercelAnalytics ? vercelAnalytics : {};
122
+ return (0, core_namespaceObject.defineConfig)({
123
+ root: rootDir,
124
+ title: docs.title,
125
+ description: docs.description,
126
+ icon: docs.icon,
127
+ globalStyles: external_node_path_default().join(context, 'theme/styles.css'),
128
+ logo: docs.logoLight || docs.logoDark ? {
129
+ light: docs.logoLight ?? docs.logoDark,
130
+ dark: docs.logoDark ?? docs.logoLight
131
+ } : void 0,
132
+ markdown: {
133
+ link: {
134
+ checkDeadLinks: true
135
+ }
136
+ },
137
+ route: {
138
+ cleanUrls: true
139
+ },
140
+ search: {
141
+ versioned: true,
142
+ codeBlocks: true
143
+ },
144
+ themeConfig: {
145
+ enableContentAnimation: true,
146
+ enableScrollToTop: false,
147
+ footer: {
148
+ message: `Copyright \xa9 ${new Date().getFullYear()} Callstack Open Source`
149
+ },
150
+ editLink: {
151
+ docRepoBaseUrl: docs.editUrl,
152
+ text: 'Edit this page on GitHub'
153
+ },
154
+ socialLinks: createSocialLinks(docs.socials)
155
+ },
156
+ builderConfig: {
157
+ plugins: [
158
+ (0, external_rsbuild_plugin_open_graph_namespaceObject.pluginOpenGraph)({
159
+ title: docs.title,
160
+ type: 'website',
161
+ url: docs.rootUrl,
162
+ image: `${docs.rootUrl}/${docs.ogImage}`,
163
+ description: docs.description,
164
+ twitter: (null == (_docs_socials = docs.socials) ? void 0 : _docs_socials.x) ? {
165
+ site: null == (_docs_socials1 = docs.socials) ? void 0 : _docs_socials1.x,
166
+ card: 'summary_large_image'
167
+ } : void 0
168
+ })
169
+ ]
170
+ },
171
+ plugins: [
172
+ (0, plugin_namespaceObject.pluginCallstackTheme)(theme),
173
+ (0, plugin_sitemap_namespaceObject.pluginSitemap)({
174
+ siteUrl: docs.rootUrl
175
+ }),
176
+ (0, plugin_llms_namespaceObject.pluginLlms)({
177
+ exclude: ({ page })=>page.routePath.includes('404')
178
+ }),
179
+ enableVercel && external_rspress_plugin_vercel_analytics_default()(vercelOptions)
180
+ ].filter(Boolean)
181
+ });
182
+ };
183
+ function withCallstackPreset(options, userConfig) {
184
+ const parsed = validatePresetOptions(options);
185
+ return (0, core_namespaceObject.mergeDocConfig)(createPreset(parsed), userConfig);
186
+ }
187
+ exports.withCallstackPreset = __webpack_exports__.withCallstackPreset;
188
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
189
+ "withCallstackPreset"
190
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
191
+ Object.defineProperty(exports, '__esModule', {
192
+ value: true
193
+ });
@@ -0,0 +1 @@
1
+ export { withCallstackPreset } from './preset';
package/dist/index.js ADDED
@@ -0,0 +1,147 @@
1
+ import node_fs from "node:fs";
2
+ import node_path from "node:path";
3
+ import { pluginCallstackTheme } from "@callstack/rspress-theme/plugin";
4
+ import { defineConfig, mergeDocConfig } from "@rspress/core";
5
+ import { pluginLlms } from "@rspress/plugin-llms";
6
+ import { pluginSitemap } from "@rspress/plugin-sitemap";
7
+ import { pluginOpenGraph } from "rsbuild-plugin-open-graph";
8
+ import rspress_plugin_vercel_analytics from "rspress-plugin-vercel-analytics";
9
+ import { styleText } from "node:util";
10
+ import { z } from "zod";
11
+ const nonEmptyString = z.string().trim().min(1, {
12
+ message: 'must be a non-empty string'
13
+ });
14
+ const presetOptionsSchema = z.object({
15
+ context: nonEmptyString.refine((value)=>node_path.isAbsolute(value), {
16
+ message: 'must be an absolute path'
17
+ }).describe('Absolute path to the project root'),
18
+ docs: z.object({
19
+ title: nonEmptyString.describe('Title of the docs'),
20
+ description: nonEmptyString.describe("Description of the docs"),
21
+ editUrl: z.string().trim().url({
22
+ message: 'must be a valid URL'
23
+ }).describe('Base URL to repository for edit links'),
24
+ logoLight: nonEmptyString.optional().describe('Filename from docs public directory for light mode logo (default: logo-light.png)'),
25
+ logoDark: nonEmptyString.optional().describe('Filename from docs public directory for dark mode logo (default: logo-dark.png)'),
26
+ icon: nonEmptyString.optional().describe('Filename from docs public directory for site icon (default: icon.png)'),
27
+ ogImage: nonEmptyString.optional().describe('Filename from docs public directory for Open Graph image (default: og.png)'),
28
+ rootDir: nonEmptyString.optional().describe('Root directory containing markdown docs'),
29
+ rootUrl: z.string().trim().url({
30
+ message: 'must be a valid URL'
31
+ }).describe('Absolute public site origin (e.g. https://example.com)'),
32
+ socials: z.record(z.string().url()).optional().describe('Map of social icon name to profile URL')
33
+ }),
34
+ theme: z.unknown().optional(),
35
+ vercelAnalytics: z.union([
36
+ z.boolean(),
37
+ z.record(z.unknown())
38
+ ]).optional().describe('Enable/disable Vercel Analytics or pass its config (overrides auto-detect)')
39
+ });
40
+ function error(...message) {
41
+ for (const msg of message)console.error(styleText('red', msg));
42
+ }
43
+ function validatePresetOptions(options) {
44
+ const result = presetOptionsSchema.safeParse(options);
45
+ if (!result.success) {
46
+ const bullets = result.error.issues.map((issue)=>{
47
+ var _current__def;
48
+ const pathSegments = issue.path;
49
+ const pathLabel = pathSegments.length > 0 ? pathSegments.join('.') : 'root';
50
+ let current = presetOptionsSchema;
51
+ for (const segment of pathSegments)if (current instanceof z.ZodObject) {
52
+ const objectSchema = current;
53
+ const shape = objectSchema.shape;
54
+ current = shape[String(segment)];
55
+ } else if (current instanceof z.ZodRecord) current = current._def.valueType;
56
+ else break;
57
+ const description = null == current ? void 0 : null == (_current__def = current._def) ? void 0 : _current__def.description;
58
+ const received = issue.received;
59
+ const details = received ? `${issue.message} \u{2014} received ${received}` : issue.message;
60
+ const withDesc = description ? `${details} (${description})` : details;
61
+ return `- ${pathLabel}: ${withDesc}`;
62
+ }).join('\n');
63
+ error('Invalid @callstack/rspress-preset configuration:');
64
+ error(bullets);
65
+ process.exit(1);
66
+ }
67
+ return result.data;
68
+ }
69
+ function createSocialLinks(socials) {
70
+ return Object.entries(socials ?? {}).map(([key, value])=>({
71
+ icon: key,
72
+ mode: 'link',
73
+ content: value
74
+ }));
75
+ }
76
+ const createPreset = (config)=>{
77
+ var _docs_socials, _docs_socials1;
78
+ const { context, docs, theme, vercelAnalytics } = config;
79
+ const rootDir = node_path.join(context, docs.rootDir ?? 'docs');
80
+ const enableVercel = void 0 === vercelAnalytics ? node_fs.existsSync(node_path.join(context, 'vercel.json')) : Boolean(vercelAnalytics);
81
+ const vercelOptions = 'object' == typeof vercelAnalytics ? vercelAnalytics : {};
82
+ return defineConfig({
83
+ root: rootDir,
84
+ title: docs.title,
85
+ description: docs.description,
86
+ icon: docs.icon,
87
+ globalStyles: node_path.join(context, 'theme/styles.css'),
88
+ logo: docs.logoLight || docs.logoDark ? {
89
+ light: docs.logoLight ?? docs.logoDark,
90
+ dark: docs.logoDark ?? docs.logoLight
91
+ } : void 0,
92
+ markdown: {
93
+ link: {
94
+ checkDeadLinks: true
95
+ }
96
+ },
97
+ route: {
98
+ cleanUrls: true
99
+ },
100
+ search: {
101
+ versioned: true,
102
+ codeBlocks: true
103
+ },
104
+ themeConfig: {
105
+ enableContentAnimation: true,
106
+ enableScrollToTop: false,
107
+ footer: {
108
+ message: `Copyright \xa9 ${new Date().getFullYear()} Callstack Open Source`
109
+ },
110
+ editLink: {
111
+ docRepoBaseUrl: docs.editUrl,
112
+ text: 'Edit this page on GitHub'
113
+ },
114
+ socialLinks: createSocialLinks(docs.socials)
115
+ },
116
+ builderConfig: {
117
+ plugins: [
118
+ pluginOpenGraph({
119
+ title: docs.title,
120
+ type: 'website',
121
+ url: docs.rootUrl,
122
+ image: `${docs.rootUrl}/${docs.ogImage}`,
123
+ description: docs.description,
124
+ twitter: (null == (_docs_socials = docs.socials) ? void 0 : _docs_socials.x) ? {
125
+ site: null == (_docs_socials1 = docs.socials) ? void 0 : _docs_socials1.x,
126
+ card: 'summary_large_image'
127
+ } : void 0
128
+ })
129
+ ]
130
+ },
131
+ plugins: [
132
+ pluginCallstackTheme(theme),
133
+ pluginSitemap({
134
+ siteUrl: docs.rootUrl
135
+ }),
136
+ pluginLlms({
137
+ exclude: ({ page })=>page.routePath.includes('404')
138
+ }),
139
+ enableVercel && rspress_plugin_vercel_analytics(vercelOptions)
140
+ ].filter(Boolean)
141
+ });
142
+ };
143
+ function withCallstackPreset(options, userConfig) {
144
+ const parsed = validatePresetOptions(options);
145
+ return mergeDocConfig(createPreset(parsed), userConfig);
146
+ }
147
+ export { withCallstackPreset };
@@ -0,0 +1,83 @@
1
+ import type { pluginCallstackTheme } from '@callstack/rspress-theme/plugin';
2
+ import type pluginVercelAnalytics from 'rspress-plugin-vercel-analytics';
3
+ import { z } from 'zod';
4
+ export declare const presetOptionsSchema: z.ZodObject<{
5
+ context: z.ZodEffects<z.ZodString, string, string>;
6
+ docs: z.ZodObject<{
7
+ title: z.ZodString;
8
+ description: z.ZodString;
9
+ editUrl: z.ZodString;
10
+ logoLight: z.ZodOptional<z.ZodString>;
11
+ logoDark: z.ZodOptional<z.ZodString>;
12
+ icon: z.ZodOptional<z.ZodString>;
13
+ ogImage: z.ZodOptional<z.ZodString>;
14
+ rootDir: z.ZodOptional<z.ZodString>;
15
+ rootUrl: z.ZodString;
16
+ socials: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ title: string;
19
+ description: string;
20
+ editUrl: string;
21
+ rootUrl: string;
22
+ logoLight?: string | undefined;
23
+ logoDark?: string | undefined;
24
+ icon?: string | undefined;
25
+ ogImage?: string | undefined;
26
+ rootDir?: string | undefined;
27
+ socials?: Record<string, string> | undefined;
28
+ }, {
29
+ title: string;
30
+ description: string;
31
+ editUrl: string;
32
+ rootUrl: string;
33
+ logoLight?: string | undefined;
34
+ logoDark?: string | undefined;
35
+ icon?: string | undefined;
36
+ ogImage?: string | undefined;
37
+ rootDir?: string | undefined;
38
+ socials?: Record<string, string> | undefined;
39
+ }>;
40
+ theme: z.ZodOptional<z.ZodUnknown>;
41
+ vercelAnalytics: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
42
+ }, "strip", z.ZodTypeAny, {
43
+ context: string;
44
+ docs: {
45
+ title: string;
46
+ description: string;
47
+ editUrl: string;
48
+ rootUrl: string;
49
+ logoLight?: string | undefined;
50
+ logoDark?: string | undefined;
51
+ icon?: string | undefined;
52
+ ogImage?: string | undefined;
53
+ rootDir?: string | undefined;
54
+ socials?: Record<string, string> | undefined;
55
+ };
56
+ theme?: unknown;
57
+ vercelAnalytics?: boolean | Record<string, unknown> | undefined;
58
+ }, {
59
+ context: string;
60
+ docs: {
61
+ title: string;
62
+ description: string;
63
+ editUrl: string;
64
+ rootUrl: string;
65
+ logoLight?: string | undefined;
66
+ logoDark?: string | undefined;
67
+ icon?: string | undefined;
68
+ ogImage?: string | undefined;
69
+ rootDir?: string | undefined;
70
+ socials?: Record<string, string> | undefined;
71
+ };
72
+ theme?: unknown;
73
+ vercelAnalytics?: boolean | Record<string, unknown> | undefined;
74
+ }>;
75
+ type ThemeConfig = Parameters<typeof pluginCallstackTheme>[0];
76
+ type VercelAnalyticsConfig = Parameters<typeof pluginVercelAnalytics>[0];
77
+ type PresetSchema = z.infer<typeof presetOptionsSchema>;
78
+ export type PresetConfig = Omit<PresetSchema, 'theme' | 'vercelAnalytics'> & {
79
+ theme?: ThemeConfig;
80
+ vercelAnalytics?: boolean | VercelAnalyticsConfig;
81
+ };
82
+ export declare function validatePresetOptions(options: unknown): PresetConfig;
83
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { UserConfig } from '@rspress/core';
2
+ import { type PresetConfig } from './options';
3
+ export declare function withCallstackPreset(options: PresetConfig, userConfig: UserConfig): Promise<UserConfig>;
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@callstack/rspress-preset",
3
+ "version": "0.4.0",
4
+ "description": "Callstack preset for Rspress docs",
5
+ "author": "Jakub Romańczyk <jakub.romanczyk@callstack.com>",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public",
23
+ "registry": "https://registry.npmjs.org/"
24
+ },
25
+ "homepage": "https://github.com/callstack/rspress-theme/tree/main/packages/preset#readme",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/callstack/rspress-theme.git",
29
+ "directory": "packages/preset"
30
+ },
31
+ "keywords": [
32
+ "rspress",
33
+ "theme",
34
+ "preset",
35
+ "callstack",
36
+ "documentation",
37
+ "react",
38
+ "typescript"
39
+ ],
40
+ "dependencies": {
41
+ "@rspress/plugin-llms": "2.0.0-beta.32",
42
+ "@rspress/plugin-sitemap": "2.0.0-beta.32",
43
+ "rsbuild-plugin-open-graph": "^1.0.2",
44
+ "rspress-plugin-vercel-analytics": "^0.3.0",
45
+ "zod": "^3.23.8",
46
+ "@callstack/rspress-theme": "0.4.0"
47
+ },
48
+ "peerDependencies": {
49
+ "@rspress/core": "2.0.0-beta.32"
50
+ },
51
+ "devDependencies": {
52
+ "@microsoft/api-extractor": "^7.52.8",
53
+ "@rslib/core": "^0.10.5",
54
+ "@rspress/core": "2.0.0-beta.32",
55
+ "@types/node": "^22",
56
+ "typescript": "^5.8.3"
57
+ },
58
+ "scripts": {
59
+ "build": "rslib build",
60
+ "dev": "rslib build --watch",
61
+ "typecheck": "tsc --noEmit"
62
+ }
63
+ }