@xyd-js/plugin-docs 0.1.0-xyd.2 → 0.1.0-xyd.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # @xyd-js/plugin-docs
2
+
3
+ ## 0.1.0-xyd.3
4
+
5
+ ### Patch Changes
6
+
7
+ - documan + plugin-docs
8
+
9
+ ## 0.1.0-xyd.2
10
+
11
+ ### Patch Changes
12
+
13
+ - test
14
+ - Updated dependencies
15
+ - @xyd-js/components@0.1.0-xyd.13
16
+ - @xyd-js/composer@0.1.0-xyd.2
17
+ - @xyd-js/content@0.1.0-xyd.16
18
+ - @xyd-js/core@0.1.0-xyd.15
19
+ - @xyd-js/framework@0.1.0-xyd.34
20
+ - @xyd-js/gql@0.1.0-xyd.15
21
+ - @xyd-js/openapi@0.1.0-xyd.13
22
+ - @xyd-js/sources@0.1.1-xyd.5
23
+ - @xyd-js/themes@0.1.1-xyd.5
24
+ - @xyd-js/uniform@0.1.0-xyd.17
25
+
26
+ ## 0.1.0-xyd.1
27
+
28
+ ### Patch Changes
29
+
30
+ - update packages
31
+ - Updated dependencies
32
+ - @xyd-js/components@0.1.0-xyd.12
33
+ - @xyd-js/composer@0.1.0-xyd.1
34
+ - @xyd-js/content@0.1.0-xyd.15
35
+ - @xyd-js/core@0.1.0-xyd.14
36
+ - @xyd-js/framework@0.1.0-xyd.33
37
+ - @xyd-js/gql@0.1.0-xyd.14
38
+ - @xyd-js/openapi@0.1.0-xyd.12
39
+ - @xyd-js/sources@0.1.1-xyd.4
40
+ - @xyd-js/themes@0.1.1-xyd.4
41
+ - @xyd-js/uniform@0.1.0-xyd.16
package/TODO.md ADDED
@@ -0,0 +1 @@
1
+ 1. better API
package/package.json CHANGED
@@ -1,25 +1,15 @@
1
1
  {
2
2
  "name": "@xyd-js/plugin-docs",
3
- "version": "0.1.0-xyd.2",
3
+ "version": "0.1.0-xyd.3",
4
4
  "description": "",
5
5
  "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- "./package.json": "./package.json",
10
- ".": "./dist/index.js"
11
- },
12
- "files": [
13
- "dist",
14
- "package.json"
15
- ],
16
6
  "dependencies": {
17
7
  "codehike": "^1.0.3",
18
8
  "@code-hike/lighter": "^1.0.3",
19
- "@xyd-js/openapi": "0.1.0-xyd.13",
20
9
  "@xyd-js/uniform": "0.1.0-xyd.17",
10
+ "@xyd-js/sources": "0.1.1-xyd.5",
21
11
  "@xyd-js/gql": "0.1.0-xyd.15",
22
- "@xyd-js/sources": "0.1.1-xyd.5"
12
+ "@xyd-js/openapi": "0.1.0-xyd.13"
23
13
  },
24
14
  "peerDependencies": {
25
15
  "@react-router/dev": "^7.5.0",
@@ -31,8 +21,8 @@
31
21
  "@xyd-js/framework": "0.1.0-xyd.34",
32
22
  "@xyd-js/composer": "0.1.0-xyd.2",
33
23
  "@xyd-js/themes": "0.1.1-xyd.5",
34
- "@xyd-js/content": "0.1.0-xyd.16",
35
24
  "@xyd-js/components": "0.1.0-xyd.13",
25
+ "@xyd-js/content": "0.1.0-xyd.16",
36
26
  "@xyd-js/core": "0.1.0-xyd.15"
37
27
  },
38
28
  "devDependencies": {
package/src/const.ts ADDED
@@ -0,0 +1,7 @@
1
+ import {ThemePresetName} from "@xyd-js/core";
2
+
3
+ export const THEME_CONFIG_FOLDER = ".docs/theme" // TODO: in the future shared internal const like `.xyd` and `.docs` ?
4
+ // TODO: SHARED
5
+ export const VIRTUAL_CONTENT_FOLDER = ".xyd/.cache/.content"
6
+
7
+ export const DEFAULT_THEME: ThemePresetName = "poetry"
@@ -0,0 +1,23 @@
1
+ // declarations.d.ts
2
+
3
+
4
+ declare module 'virtual:xyd-settings' {
5
+ import type {Settings} from "@xyd-js/core";
6
+
7
+ const settings: Settings;
8
+ export default settings;
9
+ export {
10
+ settings as Settings
11
+ }
12
+ }
13
+
14
+ declare module 'virtual:xyd-theme' {
15
+ import {BaseTheme} from "@xyd-js/themes";
16
+ import {Theme as ThemeSettings} from "@xyd-js/core";
17
+
18
+ // Export a concrete theme class that extends BaseTheme
19
+ class ConcreteTheme extends BaseTheme {
20
+ constructor();
21
+ }
22
+ export default ConcreteTheme;
23
+ }
package/src/index.ts ADDED
@@ -0,0 +1,305 @@
1
+ import {Navigation, Settings} from "@xyd-js/core";
2
+ import type {Plugin as VitePlugin} from "vite";
3
+ import {RouteConfigEntry} from "@react-router/dev/routes";
4
+ import type {PageURL, Sidebar, SidebarRoute} from "@xyd-js/core";
5
+ import fs from "fs";
6
+ import path from "path";
7
+
8
+ import {docsPreset} from "./presets/docs";
9
+ import {graphqlPreset} from "./presets/graphql";
10
+ import {openapiPreset} from "./presets/openapi";
11
+ import {sourcesPreset} from "./presets/sources";
12
+
13
+ import type {PluginOutput, Plugin} from "./types";
14
+ import {ensureAndCleanupVirtualFolder} from "./presets/uniform";
15
+
16
+ export {readSettings} from "./presets/docs/settings"
17
+
18
+ export interface PluginDocsOptions {
19
+ disableAPIGeneration?: boolean
20
+ disableFSWrite?: boolean
21
+ }
22
+
23
+ // TODO: better plugin runner
24
+ // TODO: REFACTOR
25
+ export async function pluginDocs(options?: PluginDocsOptions): Promise<PluginOutput | null> {
26
+ let settings: Settings | null = null
27
+ const vitePlugins: VitePlugin[] = []
28
+ const routes: RouteConfigEntry[] = []
29
+ let basePath = ""
30
+
31
+ // base docs preset setup
32
+ {
33
+ const options = {
34
+ urlPrefix: "" // TODO: configurable
35
+ }
36
+
37
+ const docs = docsPreset(undefined, options)
38
+ docs.preinstall = docs.preinstall || []
39
+
40
+ let preinstallMerge = {}
41
+
42
+ for (const preinstall of docs.preinstall) {
43
+ const resp = await preinstall()({}, {
44
+ routes: docs.routes
45
+ })
46
+
47
+ if (resp && typeof resp === 'object') {
48
+ preinstallMerge = {
49
+ ...preinstallMerge,
50
+ ...resp
51
+ }
52
+ }
53
+ }
54
+
55
+ docs.vitePlugins = docs.vitePlugins || []
56
+ for (const vitePlugin of docs.vitePlugins) {
57
+ const vitePlug = await vitePlugin()({
58
+ preinstall: preinstallMerge
59
+ })
60
+
61
+ vitePlugins.push(vitePlug)
62
+ }
63
+
64
+ if ("settings" in preinstallMerge) {
65
+ settings = preinstallMerge.settings as Settings
66
+ }
67
+
68
+ docs.routes = docs.routes || []
69
+ routes.push(...docs.routes)
70
+ basePath = docs.basePath
71
+ }
72
+
73
+ if (!settings) {
74
+ return null
75
+ }
76
+
77
+ await ensureAndCleanupVirtualFolder()
78
+
79
+ // graphql preset setup
80
+ if (!options?.disableAPIGeneration && settings?.api?.graphql) {
81
+ const opt = {
82
+ disableFSWrite: options?.disableFSWrite
83
+ }
84
+
85
+ const gql = graphqlPreset(settings, opt)
86
+ gql.preinstall = gql.preinstall || []
87
+
88
+ let preinstallMerge = {}
89
+
90
+ for (const preinstall of gql.preinstall) {
91
+ const resp = await preinstall(opt)(settings, {
92
+ routes: gql.routes,
93
+ })
94
+
95
+ if (resp && typeof resp === 'object') {
96
+ preinstallMerge = {
97
+ ...preinstallMerge,
98
+ ...resp
99
+ }
100
+ }
101
+ }
102
+
103
+ gql.vitePlugins = gql.vitePlugins || []
104
+ for (const vitePlugin of gql.vitePlugins) {
105
+ const vitePlug = await vitePlugin()({
106
+ preinstall: preinstallMerge
107
+ })
108
+
109
+ vitePlugins.push(vitePlug)
110
+ }
111
+
112
+ gql.routes = gql.routes || []
113
+ routes.push(...gql.routes)
114
+ }
115
+
116
+ // openapi preset setup
117
+ if (!options?.disableAPIGeneration && settings?.api?.openapi) {
118
+ const opt = {
119
+ disableFSWrite: options?.disableFSWrite
120
+ }
121
+
122
+ const oap = openapiPreset(settings, opt)
123
+ oap.preinstall = oap.preinstall || []
124
+
125
+ let preinstallMerge = {}
126
+
127
+ for (const preinstall of oap.preinstall) {
128
+ const resp = await preinstall(opt)(settings, {
129
+ routes: oap.routes,
130
+ })
131
+
132
+ if (resp && typeof resp === 'object') {
133
+ preinstallMerge = {
134
+ ...preinstallMerge,
135
+ ...resp
136
+ }
137
+ }
138
+ }
139
+
140
+ oap.vitePlugins = oap.vitePlugins || []
141
+ for (const vitePlugin of oap.vitePlugins) {
142
+ const vitePlug = await vitePlugin()({
143
+ preinstall: preinstallMerge
144
+ })
145
+
146
+ vitePlugins.push(vitePlug)
147
+ }
148
+
149
+ oap.routes = oap.routes || []
150
+ routes.push(...oap.routes)
151
+ }
152
+
153
+ if (!options?.disableAPIGeneration && settings?.api?.sources) {
154
+ const opt = {
155
+ disableFSWrite: options?.disableFSWrite
156
+ }
157
+
158
+ const src = sourcesPreset(settings, opt)
159
+ src.preinstall = src.preinstall || []
160
+
161
+ let preinstallMerge = {}
162
+
163
+ for (const preinstall of src.preinstall) {
164
+ const resp = await preinstall(opt)(settings, {
165
+ routes: src.routes,
166
+ })
167
+
168
+ if (resp && typeof resp === 'object') {
169
+ preinstallMerge = {
170
+ ...preinstallMerge,
171
+ ...resp
172
+ }
173
+ }
174
+ }
175
+
176
+ src.vitePlugins = src.vitePlugins || []
177
+ for (const vitePlugin of src.vitePlugins) {
178
+ const vitePlug = await vitePlugin()({
179
+ preinstall: preinstallMerge
180
+ })
181
+
182
+ vitePlugins.push(vitePlug)
183
+ }
184
+
185
+ src.routes = src.routes || []
186
+ routes.push(...src.routes)
187
+ }
188
+
189
+ let pagePathMapping: Record<string, string> = {}
190
+
191
+ if (settings?.navigation) {
192
+ pagePathMapping = mapNavigationToPagePathMapping(settings?.navigation)
193
+ } else {
194
+ console.warn("No navigation found in settings")
195
+ }
196
+
197
+ sortSidebarGroups(settings?.navigation?.sidebar || [])
198
+
199
+ return {
200
+ vitePlugins,
201
+ settings,
202
+ routes,
203
+ basePath,
204
+ pagePathMapping
205
+ }
206
+ }
207
+
208
+ function sortSidebarGroups(sidebar: (SidebarRoute | Sidebar | string)[]) {
209
+ // Sort items within each SidebarRoute
210
+ for (const group of sidebar) {
211
+ if (typeof group === 'string') {
212
+ continue // Skip string entries
213
+ }
214
+ if ('pages' in group && Array.isArray(group.pages)) {
215
+ group.pages.sort((a, b) => {
216
+ // If both have numeric sort values, compare them
217
+ if (typeof a.sort === 'number' && typeof b.sort === 'number') {
218
+ return a.sort - b.sort
219
+ }
220
+ // If only a has numeric sort, it comes first
221
+ if (typeof a.sort === 'number') {
222
+ return -1
223
+ }
224
+ // If only b has numeric sort, it comes first
225
+ if (typeof b.sort === 'number') {
226
+ return 1
227
+ }
228
+ // If neither has numeric sort, maintain original order
229
+ return 0
230
+ })
231
+ }
232
+ }
233
+ }
234
+
235
+ // TODO: in the future better algorithm - we should be .md/.mdx faster than checking fs here
236
+ function mapNavigationToPagePathMapping(navigation: Navigation) {
237
+ const mapping: Record<string, string> = {}
238
+
239
+ function getExistingFilePath(basePath: string): string | null {
240
+ const mdPath = `${basePath}.md`
241
+ const mdxPath = `${basePath}.mdx`
242
+
243
+ if (fs.existsSync(mdPath)) {
244
+ return mdPath
245
+ }
246
+ if (fs.existsSync(mdxPath)) {
247
+ return mdxPath
248
+ }
249
+ return null
250
+ }
251
+
252
+ function processPages(pages: PageURL[]) {
253
+ for (const page of pages) {
254
+ if (typeof page === 'string') {
255
+ // Handle regular page
256
+ const existingPath = getExistingFilePath(page)
257
+ if (existingPath) {
258
+ mapping[page] = existingPath
259
+ }
260
+ } else if (typeof page === 'object' && 'virtual' in page) {
261
+ // Handle virtual page
262
+ const virtualPath = page.virtual
263
+ const pagePath = page.page
264
+ const existingPath = getExistingFilePath(virtualPath)
265
+ if (existingPath) {
266
+ mapping[pagePath] = existingPath
267
+ }
268
+ } else if (typeof page === 'object' && 'pages' in page) {
269
+ // Handle nested sidebar
270
+ processPages(page.pages || [])
271
+ }
272
+ }
273
+ }
274
+
275
+ let sidebarFlatOnly = false
276
+ // Process each sidebar route
277
+ for (const sidebar of navigation.sidebar) {
278
+ if (typeof sidebar === 'string') {
279
+ sidebarFlatOnly = true
280
+ break
281
+ } else if ('pages' in sidebar && "route" in sidebar) {
282
+ // Handle SidebarRoute
283
+ for (const item of sidebar.pages) {
284
+ if (item?.pages) {
285
+ processPages(item.pages)
286
+ }
287
+ }
288
+ } else if ('pages' in sidebar) {
289
+ // Handle Sidebar
290
+ processPages(sidebar.pages || [])
291
+ }
292
+ }
293
+
294
+ if (sidebarFlatOnly) {
295
+ const sidebar = navigation.sidebar as string[]
296
+ processPages(sidebar)
297
+ }
298
+
299
+ return mapping
300
+ }
301
+
302
+ export type {
303
+ Plugin,
304
+ PluginOutput
305
+ }
@@ -0,0 +1,9 @@
1
+ import { createContext } from "react";
2
+
3
+ import { BaseTheme } from "@xyd-js/themes";
4
+
5
+ export const PageContext = createContext<{
6
+ theme: BaseTheme | null
7
+ }>({
8
+ theme: null
9
+ })
@@ -0,0 +1,263 @@
1
+ import { useMemo } from "react";
2
+ import {
3
+ Outlet,
4
+ useLoaderData,
5
+ useLocation,
6
+ useNavigate,
7
+ useNavigation,
8
+ useMatches
9
+ } from "react-router";
10
+
11
+ import { mapSettingsToProps } from "@xyd-js/framework/hydration";
12
+
13
+ import type { Metadata, MetadataMap, Theme as ThemeSettings } from "@xyd-js/core";
14
+ import type { INavLinks, IBreadcrumb } from "@xyd-js/ui";
15
+ import { Framework, FwLink, useSettings, type FwSidebarGroupProps } from "@xyd-js/framework/react";
16
+ import { ReactContent } from "@xyd-js/components/content";
17
+ import { Atlas, AtlasContext, type VariantToggleConfig } from "@xyd-js/atlas";
18
+ import AtlasXydPlugin from "@xyd-js/atlas/xydPlugin";
19
+
20
+ import { Surfaces } from "@xyd-js/framework/react";
21
+ import { Composer } from "@xyd-js/composer";
22
+ // @ts-ignore
23
+ import { iconSet } from 'virtual:xyd-icon-set';
24
+
25
+ // @ts-ignore
26
+ import virtualSettings from "virtual:xyd-settings";
27
+ // @ts-ignore
28
+ const { settings: getSettings } = virtualSettings
29
+ // const settings = globalThis.__xydSettings
30
+ import Theme from "virtual:xyd-theme";
31
+
32
+ // @ts-ignore
33
+ import "virtual:xyd-theme/index.css"
34
+ import "virtual:xyd-theme-override/index.css"
35
+
36
+ import { PageContext } from "./context";
37
+ import React from "react";
38
+ import { markdownPlugins } from "@xyd-js/content/md";
39
+ import { ContentFS } from "@xyd-js/content";
40
+ import { IconProvider } from "@xyd-js/components/writer";
41
+ import { CoderProvider } from "@xyd-js/components/coder";
42
+
43
+ globalThis.__xydSettings = getSettings
44
+
45
+ new Composer() // TODO: better API
46
+ const settings = globalThis.__xydSettings
47
+
48
+ const surfaces = new Surfaces()
49
+ const atlasXyd = AtlasXydPlugin()(settings) // TODO: in the future via standard plugin API
50
+ const SidebarItemRight = atlasXyd?.customComponents?.["AtlasSidebarItemRight"]
51
+
52
+ if (SidebarItemRight) {
53
+ surfaces.define(
54
+ SidebarItemRight.surface,
55
+ SidebarItemRight.component,
56
+ )
57
+ }
58
+
59
+ const reactContent = new ReactContent(settings, {
60
+ Link: FwLink,
61
+ components: {
62
+ Atlas,
63
+ },
64
+ useLocation, // // TODO: !!!! BETTER API !!!!!
65
+ useNavigate,
66
+ useNavigation
67
+ })
68
+ globalThis.__xydThemeSettings = settings?.theme
69
+ globalThis.__xydReactContent = reactContent
70
+ globalThis.__xydSurfaces = surfaces
71
+
72
+ const theme = new Theme()
73
+
74
+ const { Layout: BaseThemeLayout } = theme
75
+
76
+ interface LoaderData {
77
+ sidebarGroups: FwSidebarGroupProps[]
78
+ breadcrumbs: IBreadcrumb[],
79
+ toc: MetadataMap,
80
+ slug: string
81
+ metadata: Metadata | null
82
+ navlinks?: INavLinks,
83
+ bannerContentCode?: string
84
+ }
85
+
86
+ export async function loader({ request }: { request: any }) {
87
+ const slug = getPathname(request.url || "index") || "index"
88
+
89
+ const {
90
+ groups: sidebarGroups,
91
+ breadcrumbs,
92
+ navlinks,
93
+ metadata
94
+ } = await mapSettingsToProps(
95
+ settings,
96
+ globalThis.__xydPagePathMapping,
97
+ slug,
98
+ )
99
+
100
+ let bannerContentCode = ""
101
+
102
+ const mdPlugins = markdownPlugins({
103
+ maxDepth: metadata?.maxTocDepth || settings?.theme?.maxTocDepth || 2,
104
+ }, settings)
105
+ const contentFs = new ContentFS(settings, mdPlugins.remarkPlugins, mdPlugins.rehypePlugins)
106
+
107
+ if (settings?.theme?.banner?.content && typeof settings?.theme?.banner?.content === "string") {
108
+ bannerContentCode = await contentFs.compileContent(
109
+ settings?.theme?.banner?.content,
110
+ )
111
+ }
112
+
113
+ return {
114
+ sidebarGroups,
115
+ breadcrumbs,
116
+ navlinks,
117
+ slug,
118
+ metadata,
119
+ bannerContentCode
120
+ } as LoaderData
121
+ }
122
+
123
+ export default function Layout() {
124
+ const loaderData = useLoaderData<LoaderData>()
125
+ const matches = useMatches()
126
+
127
+ const lastMatchId = matches[matches.length - 1]?.id || null
128
+
129
+ let atlasVariantToggles: VariantToggleConfig[] = [];
130
+
131
+ // TODO: BETTER HANDLE THAT
132
+ if (loaderData.metadata?.openapi) {
133
+ atlasVariantToggles = [
134
+ { key: "status", defaultValue: "200" },
135
+ { key: "contentType", defaultValue: "application/json" }
136
+ ];
137
+ } else {
138
+ atlasVariantToggles = [
139
+ { key: "symbolName", defaultValue: "" }
140
+ ];
141
+ }
142
+
143
+ let bannerContent: any = null
144
+ // TODO: !!!! BETTER API !!!!
145
+ if (loaderData.bannerContentCode) {
146
+ const content = mdxContent(loaderData.bannerContentCode)
147
+ const BannerContent = MemoMDXComponent(content.component)
148
+
149
+ bannerContent = function () {
150
+ return <BannerContent components={theme.reactContentComponents()} />
151
+ }
152
+ }
153
+
154
+ return <>
155
+ <IconProvider value={{
156
+ iconSet: iconSet
157
+ }}>
158
+ <Framework
159
+ settings={settings || globalThis.__xydSettings}
160
+ sidebarGroups={loaderData.sidebarGroups || []}
161
+ metadata={loaderData.metadata || {}}
162
+ surfaces={surfaces}
163
+ BannerContent={bannerContent}
164
+ >
165
+ <AtlasContext
166
+ value={{
167
+ syntaxHighlight: settings?.theme?.coder?.syntaxHighlight || null,
168
+ baseMatch: lastMatchId || "",
169
+ variantToggles: atlasVariantToggles
170
+ }}
171
+ >
172
+ <CoderProvider lines={settings?.theme?.coder?.lines} scroll={settings?.theme?.coder?.scroll}>
173
+ <BaseThemeLayout>
174
+ <PageContext value={{ theme }}>
175
+ <Outlet />
176
+ </PageContext>
177
+ </BaseThemeLayout>
178
+ </CoderProvider>
179
+ </AtlasContext>
180
+ </Framework>
181
+ </IconProvider>
182
+ </>
183
+ }
184
+
185
+ function getPathname(url: string) {
186
+ const parsedUrl = new URL(url);
187
+ return parsedUrl.pathname.replace(/^\//, '');
188
+ }
189
+
190
+
191
+ // TODO: move to content?
192
+ function mdxExport(code: string) {
193
+ // Create a wrapper around React.createElement that adds keys to elements in lists
194
+ const scope = {
195
+ Fragment: React.Fragment,
196
+ jsxs: createElementWithKeys,
197
+ jsx: createElementWithKeys,
198
+ jsxDEV: createElementWithKeys,
199
+ }
200
+ const fn = new Function(...Object.keys(scope), code)
201
+
202
+ return fn(scope)
203
+ }
204
+
205
+
206
+ // // TODO: move to content?
207
+ function mdxContent(code: string) {
208
+ const content = mdxExport(code) // TODO: fix any
209
+ if (!mdxExport) {
210
+ return {}
211
+ }
212
+
213
+ return {
214
+ component: content?.default,
215
+ }
216
+ }
217
+
218
+ const createElementWithKeys = (type: any, props: any) => {
219
+ // Process children to add keys to all elements
220
+ const processChildren = (childrenArray: any[]): any[] => {
221
+ return childrenArray.map((child, index) => {
222
+ // If the child is a React element and doesn't have a key, add one
223
+ if (React.isValidElement(child) && !child.key) {
224
+ return React.cloneElement(child, { key: `mdx-${index}` });
225
+ }
226
+ // If the child is an array, process it recursively
227
+ if (Array.isArray(child)) {
228
+ return processChildren(child);
229
+ }
230
+ return child;
231
+ });
232
+ };
233
+
234
+ // Handle both cases: children as separate args or as props.children
235
+ let processedChildren;
236
+
237
+ if (props && props.children) {
238
+ if (Array.isArray(props.children)) {
239
+ processedChildren = processChildren(props.children);
240
+ } else if (React.isValidElement(props.children) && !props.children.key) {
241
+ // Single child without key
242
+ processedChildren = React.cloneElement(props.children, { key: 'mdx-child' });
243
+ } else {
244
+ // Single child with key or non-React element
245
+ processedChildren = props.children;
246
+ }
247
+ } else {
248
+ processedChildren = [];
249
+ }
250
+
251
+ // Create the element with processed children
252
+ return React.createElement(type, {
253
+ ...props,
254
+ children: processedChildren
255
+ });
256
+ };
257
+
258
+ function MemoMDXComponent(codeComponent: any) {
259
+ return useMemo(
260
+ () => codeComponent ? codeComponent : null,
261
+ [codeComponent]
262
+ )
263
+ }