@lukoweb/apitogo 0.1.24 → 0.1.38
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/README.md +92 -0
- package/cli.js +13 -13
- package/client.d.ts +8 -8
- package/dist/cli/cli.js +1117 -624
- package/dist/declarations/config/config.d.ts +4 -0
- package/dist/declarations/config/loader.d.ts +2 -0
- package/dist/declarations/config/resolve-modules.d.ts +34 -0
- package/dist/declarations/config/validators/InputNavigationSchema.d.ts +7 -7
- package/dist/declarations/config/validators/ModulesSchema.d.ts +417 -0
- package/dist/declarations/config/validators/ZudokuConfig.d.ts +123 -4
- package/dist/declarations/index.d.ts +3 -1
- package/dist/declarations/lib/authentication/components/ProductionUnlockPage.d.ts +1 -0
- package/dist/declarations/lib/authentication/hook.d.ts +3 -19
- package/dist/declarations/lib/authentication/providers/dev-portal-constants.d.ts +16 -0
- package/dist/declarations/lib/authentication/providers/dev-portal-utils.d.ts +9 -0
- package/dist/declarations/lib/authentication/providers/dev-portal.d.ts +39 -0
- package/dist/declarations/lib/authentication/state.d.ts +12 -26
- package/dist/declarations/lib/components/LandingLayout.d.ts +4 -0
- package/dist/declarations/lib/components/index.d.ts +2 -0
- package/dist/declarations/lib/plugins/api-keys/index.d.ts +2 -1
- package/dist/flat-config.d.ts +209 -24
- package/docs/components/alert.mdx +130 -0
- package/docs/components/badge.mdx +70 -0
- package/docs/components/button.mdx +132 -0
- package/docs/components/callout.mdx +112 -0
- package/docs/components/card.mdx +104 -0
- package/docs/components/checkbox.mdx +72 -0
- package/docs/components/client-only.mdx +79 -0
- package/docs/components/code-tabs.mdx +179 -0
- package/docs/components/dialog.mdx +167 -0
- package/docs/components/head.mdx +200 -0
- package/docs/components/icons.mdx +27 -0
- package/docs/components/input.mdx +96 -0
- package/docs/components/label.mdx +86 -0
- package/docs/components/link.mdx +242 -0
- package/docs/components/markdown.mdx +151 -0
- package/docs/components/mermaid.mdx +81 -0
- package/docs/components/playground.mdx +87 -0
- package/docs/components/secret.mdx +79 -0
- package/docs/components/select.mdx +176 -0
- package/docs/components/shadcn.mdx +73 -0
- package/docs/components/slider.mdx +108 -0
- package/docs/components/slot.mdx +119 -0
- package/docs/components/stepper.mdx +138 -0
- package/docs/components/switch.mdx +96 -0
- package/docs/components/syntax-highlight.mdx +602 -0
- package/docs/components/textarea.mdx +78 -0
- package/docs/components/tooltip.mdx +195 -0
- package/docs/components/typography.mdx +61 -0
- package/docs/concepts/auth-provider-api-identities.md +109 -0
- package/docs/configuration/ai-assistants.md +65 -0
- package/docs/configuration/api-catalog.md +109 -0
- package/docs/configuration/api-reference.md +397 -0
- package/docs/configuration/authentication-auth0.md +174 -0
- package/docs/configuration/authentication-azure-ad.md +238 -0
- package/docs/configuration/authentication-clerk.md +110 -0
- package/docs/configuration/authentication-firebase.md +62 -0
- package/docs/configuration/authentication-pingfederate.md +136 -0
- package/docs/configuration/authentication-supabase.md +226 -0
- package/docs/configuration/authentication.md +231 -0
- package/docs/configuration/build-configuration.mdx +147 -0
- package/docs/configuration/docs.md +282 -0
- package/docs/configuration/footer.mdx +214 -0
- package/docs/configuration/llms.md +90 -0
- package/docs/configuration/make-config.mdx +90 -0
- package/docs/configuration/navigation.mdx +422 -0
- package/docs/configuration/overview.md +380 -0
- package/docs/configuration/protected-routes.md +150 -0
- package/docs/configuration/search.md +163 -0
- package/docs/configuration/sentry.mdx +44 -0
- package/docs/configuration/site.md +124 -0
- package/docs/configuration/slots.mdx +125 -0
- package/docs/configuration/vite-config.md +18 -0
- package/docs/custom-plugins.md +285 -0
- package/docs/customization/colors-theme.mdx +276 -0
- package/docs/customization/fonts.md +110 -0
- package/docs/deploy/apache-nginx.md +41 -0
- package/docs/deploy/apitogo.md +139 -0
- package/docs/deploy/cloudflare-pages.md +75 -0
- package/docs/deploy/direct-upload.md +18 -0
- package/docs/deploy/github-pages.md +50 -0
- package/docs/deploy/vercel.md +103 -0
- package/docs/deployment.md +21 -0
- package/docs/extending/events.md +124 -0
- package/docs/guides/custom-pages.md +106 -0
- package/docs/guides/environment-variables.md +99 -0
- package/docs/guides/managing-api-keys-and-identities.md +172 -0
- package/docs/guides/mermaid.mdx +70 -0
- package/docs/guides/navigation-migration.md +87 -0
- package/docs/guides/navigation-rules.mdx +203 -0
- package/docs/guides/processors.mdx +234 -0
- package/docs/guides/static-files.md +55 -0
- package/docs/guides/transforming-examples.md +156 -0
- package/docs/guides/using-multiple-apis.md +87 -0
- package/docs/markdown/admonitions.md +128 -0
- package/docs/markdown/code-blocks.md +196 -0
- package/docs/markdown/frontmatter.md +173 -0
- package/docs/markdown/mdx.md +68 -0
- package/docs/markdown/overview.md +275 -0
- package/docs/plugins.md +5 -0
- package/docs/quickstart.md +87 -0
- package/docs/writing.mdx +72 -0
- package/package.json +170 -116
- package/src/app/ZuploBuildConfig.ts +36 -36
- package/src/app/defaultTheme.css +77 -77
- package/src/app/demo-cdn.html +37 -37
- package/src/app/demo.html +21 -21
- package/src/app/demo.tsx +77 -77
- package/src/app/entry.client.tsx +118 -118
- package/src/app/entry.server.tsx +160 -160
- package/src/app/env.ts +40 -40
- package/src/app/font.geist.css +73 -73
- package/src/app/main.css +390 -390
- package/src/app/main.tsx +8 -1
- package/src/app/polyfills.ts +47 -47
- package/src/app/processRoutes.tsx +51 -25
- package/src/app/sentry.ts +24 -24
- package/src/app/standalone.html +23 -23
- package/src/app/standalone.tsx +60 -60
- package/src/app/utils/createRedirectRoutes.ts +11 -11
- package/src/config/config.ts +32 -0
- package/src/config/create-plugin.ts +71 -71
- package/src/config/file-exists.ts +6 -6
- package/src/config/loader.ts +11 -1
- package/src/config/resolve-modules.ts +260 -0
- package/src/config/validators/BuildSchema.ts +95 -95
- package/src/config/validators/HeaderNavigationSchema.ts +41 -41
- package/src/config/validators/InputNavigationSchema.test-d.ts +178 -178
- package/src/config/validators/InputNavigationSchema.ts +206 -206
- package/src/config/validators/ModulesSchema.ts +312 -0
- package/src/config/validators/ProtectedRoutesSchema.ts +35 -35
- package/src/config/validators/ZudokuConfig.ts +766 -729
- package/src/config/validators/auth.ts +3 -3
- package/src/config/validators/reason-codes.ts +7 -7
- package/src/env.d.ts +11 -11
- package/src/index.ts +31 -0
- package/src/lib/MissingIcon.tsx +22 -22
- package/src/lib/assets/language-icons/bun.tsx +50 -50
- package/src/lib/assets/language-icons/c.tsx +31 -31
- package/src/lib/assets/language-icons/commonlisp.tsx +22 -22
- package/src/lib/assets/language-icons/cpp.tsx +35 -35
- package/src/lib/assets/language-icons/csharp.tsx +35 -35
- package/src/lib/assets/language-icons/css.tsx +36 -36
- package/src/lib/assets/language-icons/dart.tsx +39 -39
- package/src/lib/assets/language-icons/elixir.tsx +19 -19
- package/src/lib/assets/language-icons/go.tsx +19 -19
- package/src/lib/assets/language-icons/graphql.tsx +19 -19
- package/src/lib/assets/language-icons/html.tsx +24 -24
- package/src/lib/assets/language-icons/java.tsx +35 -35
- package/src/lib/assets/language-icons/javascript.tsx +11 -11
- package/src/lib/assets/language-icons/json.tsx +19 -19
- package/src/lib/assets/language-icons/kotlin.tsx +30 -30
- package/src/lib/assets/language-icons/markdown.tsx +19 -19
- package/src/lib/assets/language-icons/mdx.tsx +23 -23
- package/src/lib/assets/language-icons/npm.tsx +15 -15
- package/src/lib/assets/language-icons/objectivec.tsx +23 -23
- package/src/lib/assets/language-icons/ocaml.tsx +34 -34
- package/src/lib/assets/language-icons/php.tsx +19 -19
- package/src/lib/assets/language-icons/pnpm.tsx +32 -32
- package/src/lib/assets/language-icons/powershell.tsx +27 -27
- package/src/lib/assets/language-icons/python.tsx +23 -23
- package/src/lib/assets/language-icons/react.tsx +21 -21
- package/src/lib/assets/language-icons/ruby.tsx +19 -19
- package/src/lib/assets/language-icons/rust.tsx +19 -19
- package/src/lib/assets/language-icons/scala.tsx +19 -19
- package/src/lib/assets/language-icons/shell.tsx +19 -19
- package/src/lib/assets/language-icons/swift.tsx +19 -19
- package/src/lib/assets/language-icons/toml.tsx +23 -23
- package/src/lib/assets/language-icons/typescript.tsx +23 -23
- package/src/lib/assets/language-icons/xml.tsx +19 -19
- package/src/lib/assets/language-icons/yaml.tsx +23 -23
- package/src/lib/assets/language-icons/yarn.tsx +17 -17
- package/src/lib/assets/language-icons/zig.tsx +32 -32
- package/src/lib/auth/issuer.ts +34 -31
- package/src/lib/authentication/AuthenticationPlugin.tsx +33 -33
- package/src/lib/authentication/authentication.ts +48 -48
- package/src/lib/authentication/components/OAuthErrorPage.tsx +197 -197
- package/src/lib/authentication/components/ProductionUnlockPage.tsx +27 -0
- package/src/lib/authentication/components/SignOut.tsx +15 -15
- package/src/lib/authentication/constants.ts +1 -1
- package/src/lib/authentication/errors.ts +34 -34
- package/src/lib/authentication/hook.ts +141 -139
- package/src/lib/authentication/providers/auth0.tsx +91 -91
- package/src/lib/authentication/providers/azureb2c.tsx +223 -223
- package/src/lib/authentication/providers/dev-portal-constants.ts +21 -0
- package/src/lib/authentication/providers/dev-portal-utils.ts +107 -0
- package/src/lib/authentication/providers/dev-portal.tsx +270 -0
- package/src/lib/authentication/providers/firebase.tsx +486 -486
- package/src/lib/authentication/providers/openid.tsx +516 -516
- package/src/lib/authentication/providers/supabase.tsx +412 -412
- package/src/lib/authentication/providers/util.ts +26 -26
- package/src/lib/authentication/state.ts +179 -91
- package/src/lib/authentication/ui/icons/Apple.tsx +10 -10
- package/src/lib/authentication/ui/icons/Facebook.tsx +15 -15
- package/src/lib/authentication/ui/icons/Github.tsx +16 -16
- package/src/lib/authentication/ui/icons/Google.tsx +16 -16
- package/src/lib/authentication/ui/icons/Microsoft.tsx +12 -12
- package/src/lib/authentication/ui/icons/X.tsx +10 -10
- package/src/lib/authentication/utils/relativeRedirectUrl.ts +16 -16
- package/src/lib/components/AnchorLink.tsx +24 -24
- package/src/lib/components/Banner.tsx +52 -52
- package/src/lib/components/Bootstrap.tsx +77 -77
- package/src/lib/components/BuildCheck.tsx +87 -87
- package/src/lib/components/CategoryHeading.tsx +19 -19
- package/src/lib/components/ClientOnly.tsx +19 -19
- package/src/lib/components/ErrorPage.tsx +26 -26
- package/src/lib/components/Footer.tsx +140 -140
- package/src/lib/components/Framed.tsx +51 -51
- package/src/lib/components/Header.tsx +11 -3
- package/src/lib/components/HeaderNavigation.tsx +148 -148
- package/src/lib/components/Heading.tsx +84 -84
- package/src/lib/components/InlineCode.tsx +15 -15
- package/src/lib/components/LandingLayout.tsx +21 -0
- package/src/lib/components/LanguageIcon.tsx +199 -199
- package/src/lib/components/Markdown.tsx +55 -55
- package/src/lib/components/Meta.tsx +46 -46
- package/src/lib/components/MobileTopNavigation.tsx +11 -3
- package/src/lib/components/NotFoundPage.tsx +37 -37
- package/src/lib/components/PageProgress.tsx +28 -28
- package/src/lib/components/PagefindSearchMeta.tsx +14 -14
- package/src/lib/components/Pagination.tsx +44 -44
- package/src/lib/components/PathRenderer.tsx +61 -61
- package/src/lib/components/PluginHeads.tsx +17 -17
- package/src/lib/components/Search.tsx +70 -70
- package/src/lib/components/Slot.tsx +64 -64
- package/src/lib/components/Spinner.tsx +5 -5
- package/src/lib/components/StatusPage.tsx +96 -96
- package/src/lib/components/ThemeSwitch.tsx +49 -49
- package/src/lib/components/Typography.tsx +12 -12
- package/src/lib/components/Zudoku.tsx +106 -106
- package/src/lib/components/cache.ts +27 -27
- package/src/lib/components/context/RenderContext.ts +11 -11
- package/src/lib/components/context/RouterEventsEmitter.tsx +19 -19
- package/src/lib/components/context/SlotProvider.tsx +149 -149
- package/src/lib/components/context/ViewportAnchorContext.tsx +137 -137
- package/src/lib/components/context/ZudokuContext.ts +140 -140
- package/src/lib/components/context/ZudokuProvider.tsx +22 -22
- package/src/lib/components/context/ZudokuReactContext.tsx +17 -17
- package/src/lib/components/index.ts +2 -0
- package/src/lib/components/navigation/Navigation.tsx +51 -51
- package/src/lib/components/navigation/NavigationBadge.tsx +48 -48
- package/src/lib/components/navigation/NavigationFilterContext.tsx +28 -28
- package/src/lib/components/navigation/NavigationWrapper.tsx +49 -49
- package/src/lib/components/navigation/Toc.tsx +137 -137
- package/src/lib/components/navigation/ZudokuLogo.tsx +25 -25
- package/src/lib/components/navigation/ZuploLogo.tsx +14 -14
- package/src/lib/components/navigation/utils.ts +234 -234
- package/src/lib/core/RouteGuard.tsx +11 -1
- package/src/lib/core/ZudokuContext.ts +271 -271
- package/src/lib/core/plugins.ts +138 -138
- package/src/lib/core/react-query.ts +1 -1
- package/src/lib/core/router.ts +1 -1
- package/src/lib/core/transform-config.ts +67 -67
- package/src/lib/demo/DemoAnnouncement.tsx +17 -17
- package/src/lib/errors/ErrorAlert.tsx +28 -28
- package/src/lib/errors/RouterError.tsx +18 -18
- package/src/lib/errors/ServerError.tsx +5 -5
- package/src/lib/errors/TopLevelError.tsx +6 -6
- package/src/lib/hooks/index.ts +13 -13
- package/src/lib/hooks/useEvent.ts +41 -41
- package/src/lib/hooks/useHighlighter.ts +15 -15
- package/src/lib/hooks/useHotkey.ts +70 -70
- package/src/lib/icons.ts +2 -2
- package/src/lib/navigation/applyRules.ts +127 -127
- package/src/lib/navigation/pathMatcher.ts +81 -81
- package/src/lib/oas/graphql/circular.ts +69 -69
- package/src/lib/oas/graphql/constants.ts +2 -2
- package/src/lib/oas/graphql/index.ts +791 -791
- package/src/lib/oas/parser/dereference/index.ts +84 -84
- package/src/lib/oas/parser/dereference/resolveRef.ts +32 -32
- package/src/lib/oas/parser/index.ts +129 -129
- package/src/lib/oas/parser/schemas/v3.0.json +1489 -1489
- package/src/lib/oas/parser/schemas/v3.1.json +1298 -1298
- package/src/lib/oas/parser/upgrade/index.ts +174 -174
- package/src/lib/plugins/api-catalog/index.tsx +119 -119
- package/src/lib/plugins/api-keys/ProtectedRoute.tsx +33 -33
- package/src/lib/plugins/api-keys/index.tsx +274 -272
- package/src/lib/plugins/api-keys/settings/ApiKeyList.tsx +67 -67
- package/src/lib/plugins/custom-pages/index.tsx +32 -32
- package/src/lib/plugins/markdown/assets/ChatGPTLogo.tsx +11 -11
- package/src/lib/plugins/markdown/assets/ClaudeLogo.tsx +19 -19
- package/src/lib/plugins/markdown/index.tsx +62 -62
- package/src/lib/plugins/openapi/ColorizedParam.tsx +115 -115
- package/src/lib/plugins/openapi/Endpoint.tsx +85 -85
- package/src/lib/plugins/openapi/MCPEndpoint.tsx +273 -273
- package/src/lib/plugins/openapi/OasProvider.tsx +74 -74
- package/src/lib/plugins/openapi/OperationList.tsx +275 -275
- package/src/lib/plugins/openapi/ParamInfos.tsx +96 -96
- package/src/lib/plugins/openapi/ParameterList.tsx +53 -53
- package/src/lib/plugins/openapi/ParameterListItem.tsx +161 -161
- package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +67 -67
- package/src/lib/plugins/openapi/SidecarBox.tsx +57 -57
- package/src/lib/plugins/openapi/SimpleSelect.tsx +46 -46
- package/src/lib/plugins/openapi/client/GraphQLClient.tsx +73 -73
- package/src/lib/plugins/openapi/client/GraphQLContext.tsx +16 -16
- package/src/lib/plugins/openapi/client/createServer.ts +35 -35
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +44 -44
- package/src/lib/plugins/openapi/components/ConstValue.tsx +24 -24
- package/src/lib/plugins/openapi/components/NonHighlightedCode.tsx +22 -22
- package/src/lib/plugins/openapi/components/SelectOnClick.tsx +29 -29
- package/src/lib/plugins/openapi/context.tsx +16 -16
- package/src/lib/plugins/openapi/graphql/fragment-masking.ts +104 -104
- package/src/lib/plugins/openapi/graphql/gql.ts +95 -95
- package/src/lib/plugins/openapi/graphql/graphql.ts +835 -835
- package/src/lib/plugins/openapi/graphql/index.ts +2 -2
- package/src/lib/plugins/openapi/index.tsx +221 -221
- package/src/lib/plugins/openapi/interfaces.ts +100 -100
- package/src/lib/plugins/openapi/playground/Headers.tsx +6 -6
- package/src/lib/plugins/openapi/playground/PathParams.tsx +53 -53
- package/src/lib/plugins/openapi/playground/Spinner.tsx +87 -87
- package/src/lib/plugins/openapi/playground/createUrl.ts +25 -25
- package/src/lib/plugins/openapi/playground/fileUtils.ts +36 -36
- package/src/lib/plugins/openapi/playground/rememberedIdentity.ts +26 -26
- package/src/lib/plugins/openapi/playground/request-panel/UrlPath.tsx +31 -31
- package/src/lib/plugins/openapi/playground/request-panel/UrlQueryParams.tsx +29 -29
- package/src/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.ts +340 -340
- package/src/lib/plugins/openapi/playground/result-panel/ResponseStatusBar.tsx +117 -117
- package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +36 -36
- package/src/lib/plugins/openapi/playground/serializeQueryParams.ts +125 -125
- package/src/lib/plugins/openapi/playground/useRememberSkipLoginDialog.tsx +23 -23
- package/src/lib/plugins/openapi/processors/removeExtensions.ts +29 -29
- package/src/lib/plugins/openapi/processors/removeParameters.ts +103 -103
- package/src/lib/plugins/openapi/processors/removePaths.ts +57 -57
- package/src/lib/plugins/openapi/processors/traverse.ts +1 -1
- package/src/lib/plugins/openapi/schema/SchemaExampleAndDefault.tsx +39 -39
- package/src/lib/plugins/openapi/schema/UnionView.tsx +132 -132
- package/src/lib/plugins/openapi/schema/union-helpers.ts +123 -123
- package/src/lib/plugins/openapi/schema/utils.ts +49 -49
- package/src/lib/plugins/openapi/state.ts +36 -36
- package/src/lib/plugins/openapi/util/buildTagCategories.ts +54 -54
- package/src/lib/plugins/openapi/util/createHttpSnippet.ts +135 -135
- package/src/lib/plugins/openapi/util/createNavigationCategory.tsx +39 -39
- package/src/lib/plugins/openapi/util/generateSchemaExample.ts +191 -191
- package/src/lib/plugins/openapi/util/getRoutes.tsx +265 -265
- package/src/lib/plugins/openapi/util/methodColorMap.tsx +11 -11
- package/src/lib/plugins/openapi/util/methodToColor.ts +27 -27
- package/src/lib/plugins/openapi/util/sanitizeMarkdownForMetatag.tsx +32 -32
- package/src/lib/plugins/openapi/util/useWarmupSchema.ts +23 -23
- package/src/lib/plugins/search-inkeep/index.tsx +108 -108
- package/src/lib/plugins/search-inkeep/inkeep.ts +24 -24
- package/src/lib/plugins/search-pagefind/get-results.tsx +74 -74
- package/src/lib/plugins/search-pagefind/index.tsx +21 -21
- package/src/lib/plugins/search-pagefind/types.ts +118 -118
- package/src/lib/shiki-constants.ts +24 -24
- package/src/lib/testing/index.tsx +146 -146
- package/src/lib/ui/Accordion.tsx +55 -55
- package/src/lib/ui/Alert.tsx +84 -84
- package/src/lib/ui/AlertDialog.tsx +195 -195
- package/src/lib/ui/AspectRatio.tsx +5 -5
- package/src/lib/ui/Badge.tsx +48 -48
- package/src/lib/ui/Breadcrumb.tsx +115 -115
- package/src/lib/ui/Button.tsx +65 -65
- package/src/lib/ui/ButtonGroup.tsx +80 -80
- package/src/lib/ui/Callout.tsx +113 -113
- package/src/lib/ui/Card.tsx +95 -95
- package/src/lib/ui/Carousel.tsx +259 -259
- package/src/lib/ui/Checkbox.tsx +28 -28
- package/src/lib/ui/CodeBlock.tsx +92 -92
- package/src/lib/ui/CodeTabPanel.tsx +13 -13
- package/src/lib/ui/CodeTabs.tsx +161 -161
- package/src/lib/ui/Collapsible.tsx +31 -31
- package/src/lib/ui/Dialog.tsx +138 -138
- package/src/lib/ui/DismissibleAlert.tsx +74 -74
- package/src/lib/ui/Drawer.tsx +121 -121
- package/src/lib/ui/DropdownMenu.tsx +254 -254
- package/src/lib/ui/EmbeddedCodeBlock.tsx +99 -99
- package/src/lib/ui/Form.tsx +176 -176
- package/src/lib/ui/Frame.tsx +81 -81
- package/src/lib/ui/HoverCard.tsx +26 -26
- package/src/lib/ui/Input.tsx +23 -23
- package/src/lib/ui/InputGroup.tsx +168 -168
- package/src/lib/ui/Item.tsx +213 -213
- package/src/lib/ui/Kbd.tsx +28 -28
- package/src/lib/ui/Label.tsx +23 -23
- package/src/lib/ui/NativeSelect.tsx +48 -48
- package/src/lib/ui/NavigationMenu.tsx +169 -169
- package/src/lib/ui/Pagination.tsx +115 -115
- package/src/lib/ui/Popover.tsx +28 -28
- package/src/lib/ui/Progress.tsx +25 -25
- package/src/lib/ui/RadioGroup.tsx +41 -41
- package/src/lib/ui/ReactComponentDoc.tsx +68 -68
- package/src/lib/ui/ScrollArea.tsx +45 -45
- package/src/lib/ui/Secret.tsx +133 -133
- package/src/lib/ui/Select.tsx +184 -184
- package/src/lib/ui/Separator.tsx +25 -25
- package/src/lib/ui/Skeleton.tsx +15 -15
- package/src/lib/ui/Slider.tsx +25 -25
- package/src/lib/ui/Stepper.tsx +8 -8
- package/src/lib/ui/Switch.tsx +26 -26
- package/src/lib/ui/SyntaxHighlight.tsx +54 -54
- package/src/lib/ui/Tabs.tsx +52 -52
- package/src/lib/ui/Textarea.tsx +22 -22
- package/src/lib/ui/Toggle.tsx +42 -42
- package/src/lib/ui/ToggleGroup.tsx +58 -58
- package/src/lib/ui/Tooltip.tsx +65 -65
- package/src/lib/ui/Value.tsx +42 -42
- package/src/lib/ui/util.tsx +8 -8
- package/src/lib/util/cn.ts +6 -6
- package/src/lib/util/createVariantComponent.tsx +61 -61
- package/src/lib/util/ensureArray.ts +3 -3
- package/src/lib/util/flattenAllOf.ts +72 -72
- package/src/lib/util/flattenAllOfProcessor.ts +74 -74
- package/src/lib/util/hastToJsx.tsx +67 -67
- package/src/lib/util/humanFileSize.ts +15 -15
- package/src/lib/util/invariant.ts +52 -52
- package/src/lib/util/joinUrl.ts +60 -60
- package/src/lib/util/logInit.ts +9 -9
- package/src/lib/util/objectEntries.ts +5 -5
- package/src/lib/util/os.ts +18 -18
- package/src/lib/util/pastellize.ts +25 -25
- package/src/lib/util/problemJson.ts +63 -63
- package/src/lib/util/readFrontmatter.ts +14 -14
- package/src/lib/util/renderIf.ts +4 -4
- package/src/lib/util/scrollIntoViewIfNeeded.ts +18 -18
- package/src/lib/util/slugify.ts +21 -21
- package/src/lib/util/syncZustandState.ts +22 -22
- package/src/lib/util/traverse.ts +70 -70
- package/src/lib/util/types.ts +7 -7
- package/src/lib/util/url.ts +18 -18
- package/src/lib/util/useCopyToClipboard.ts +17 -17
- package/src/lib/util/useExposedProps.tsx +27 -27
- package/src/lib/util/useIsomorphicLayoutEffect.ts +6 -6
- package/src/lib/util/useLatest.ts +18 -18
- package/src/lib/util/useOnScreen.ts +34 -34
- package/src/lib/util/useScrollToAnchor.ts +70 -70
- package/src/lib/util/useScrollToTop.ts +18 -18
- package/src/types.d.ts +57 -53
- package/src/vite/api/SchemaManager.ts +371 -371
- package/src/vite/api/schema-codegen.ts +163 -163
- package/src/vite/config.ts +5 -1
- package/src/vite/css/collect.ts +42 -42
- package/src/vite/css/plugin.ts +105 -105
- package/src/vite/debug.ts +18 -18
- package/src/vite/dev-portal-env.ts +93 -0
- package/src/vite/html.ts +54 -54
- package/src/vite/index.ts +2 -2
- package/src/vite/mdx/rehype-extract-toc-with-jsx-export.ts +19 -19
- package/src/vite/mdx/rehype-extract-toc-with-jsx.ts +70 -70
- package/src/vite/mdx/remark-code-tabs.ts +47 -47
- package/src/vite/mdx/remark-inject-filepath.ts +13 -13
- package/src/vite/mdx/remark-last-modified.ts +103 -103
- package/src/vite/mdx/remark-link-rewrite.ts +23 -23
- package/src/vite/mdx/remark-normalize-image-url.ts +15 -15
- package/src/vite/mdx/remark-static-generation.ts +149 -149
- package/src/vite/mdx/utils.ts +32 -32
- package/src/vite/output.ts +261 -261
- package/src/vite/package-root.ts +12 -12
- package/src/vite/pagefind-dev-index.ts +100 -100
- package/src/vite/plugin-api-keys.ts +6 -1
- package/src/vite/plugin-api.ts +4 -1
- package/src/vite/plugin-auth.ts +5 -1
- package/src/vite/plugin-component.ts +1 -1
- package/src/vite/plugin-config-reload.ts +49 -49
- package/src/vite/plugin-doc-metadata.ts +45 -45
- package/src/vite/plugin-docs.ts +4 -1
- package/src/vite/plugin-metadata.ts +30 -30
- package/src/vite/plugin-modules.ts +144 -0
- package/src/vite/plugin-shiki-register.ts +97 -97
- package/src/vite/plugin-theme.ts +399 -399
- package/src/vite/plugin.ts +2 -0
- package/src/vite/prerender/utils.ts +76 -76
- package/src/vite/prerender/worker.ts +118 -118
- package/src/vite/reporter.ts +34 -34
- package/src/vite/shadcn-registry.ts +48 -48
- package/src/vite/sitemap.ts +78 -78
- package/src/vite/ssr-templates/cloudflare.ts +19 -19
- package/src/vite/ssr-templates/node.ts +25 -25
- package/src/vite/ssr-templates/vercel.ts +22 -22
- package/src/vite/zuplo.ts +30 -30
- package/src/vite-env.d.ts +6 -6
- package/src/zuplo/enrich-with-zuplo-mcp.ts +168 -168
- package/src/zuplo/enrich-with-zuplo.ts +256 -256
- package/src/zuplo/policy-types.ts +46 -46
- package/src/zuplo/with-zuplo-processors.ts +36 -36
- package/src/zuplo/with-zuplo.ts +14 -14
- package/LICENSE.md +0 -18
- package/dist/declarations/lib/components/navigation/ZudokuLogo.d.ts +0 -6
package/src/vite/plugin-theme.ts
CHANGED
|
@@ -1,399 +1,399 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { normalizeTheme, type ThemeRegistration } from "shiki";
|
|
3
|
-
import type { Plugin } from "vite";
|
|
4
|
-
import { getCurrentConfig } from "../config/loader.js";
|
|
5
|
-
import type {
|
|
6
|
-
FontConfig,
|
|
7
|
-
ZudokuConfig,
|
|
8
|
-
} from "../config/validators/ZudokuConfig.js";
|
|
9
|
-
import { defaultHighlightOptions } from "../lib/shiki.js";
|
|
10
|
-
import { objectEntries } from "../lib/util/objectEntries.js";
|
|
11
|
-
import {
|
|
12
|
-
fetchShadcnRegistryItem,
|
|
13
|
-
type RegistryItemCss,
|
|
14
|
-
} from "./shadcn-registry.js";
|
|
15
|
-
|
|
16
|
-
// prettier-ignore
|
|
17
|
-
const THEME_VARIABLES = [
|
|
18
|
-
"background", "foreground", "card", "cardForeground", "popover", "popoverForeground", "primary",
|
|
19
|
-
"primaryForeground", "secondary", "secondaryForeground", "muted", "mutedForeground", "accent",
|
|
20
|
-
"accentForeground", "destructive", "destructiveForeground", "border", "input", "ring", "radius",
|
|
21
|
-
] as const;
|
|
22
|
-
|
|
23
|
-
const uncamelize = (str: string) =>
|
|
24
|
-
str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
25
|
-
|
|
26
|
-
export type Theme = Partial<Record<(typeof THEME_VARIABLES)[number], string>>;
|
|
27
|
-
|
|
28
|
-
const processColorValue = (value: string | undefined): string => {
|
|
29
|
-
if (!value) return "";
|
|
30
|
-
const color =
|
|
31
|
-
!value.startsWith("#") &&
|
|
32
|
-
!value.includes("(") &&
|
|
33
|
-
value.split(" ").length >= 3
|
|
34
|
-
? // Assume legacy tailwind hsl format
|
|
35
|
-
`hsl(${value})`
|
|
36
|
-
: value;
|
|
37
|
-
|
|
38
|
-
return color;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const generateCss = (theme: Theme) =>
|
|
42
|
-
objectEntries(theme)
|
|
43
|
-
.filter(([key]) => THEME_VARIABLES.includes(key))
|
|
44
|
-
.map(([key, value]) => `--${uncamelize(key)}: ${processColorValue(value)};`)
|
|
45
|
-
.join("\n");
|
|
46
|
-
|
|
47
|
-
const generateRegistryCss = (cssVars: Record<string, string>) =>
|
|
48
|
-
Object.entries(cssVars)
|
|
49
|
-
.map(([key, value]) => ` --${key}: ${value};`)
|
|
50
|
-
.join("\n");
|
|
51
|
-
|
|
52
|
-
const processCustomCss = (css: string | RegistryItemCss): string => {
|
|
53
|
-
if (typeof css === "string") {
|
|
54
|
-
return css;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const processStyles = (
|
|
58
|
-
styles: RegistryItemCss | string,
|
|
59
|
-
indent = "",
|
|
60
|
-
): string[] => {
|
|
61
|
-
if (typeof styles === "string") {
|
|
62
|
-
return [`${indent}${styles}`];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const rules = [];
|
|
66
|
-
for (const [key, value] of Object.entries(styles)) {
|
|
67
|
-
if (typeof value === "string") {
|
|
68
|
-
rules.push(`${indent}${key}: ${value};`);
|
|
69
|
-
} else {
|
|
70
|
-
rules.push(`${indent}${key} {`);
|
|
71
|
-
rules.push(...processStyles(value, `${indent} `));
|
|
72
|
-
rules.push(`${indent}}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return rules;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return processStyles(css).join("\n");
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const MAIN_REPLACE = "/* @vite-plugin-inject main */";
|
|
82
|
-
const DEFAULT_THEME_REPLACE = "/* @vite-plugin-inject defaultTheme */";
|
|
83
|
-
|
|
84
|
-
// prettier-ignore
|
|
85
|
-
export const GOOGLE_FONTS = [
|
|
86
|
-
"Inter", "Roboto", "Open Sans", "Poppins", "Montserrat", "Outfit",
|
|
87
|
-
"Plus Jakarta Sans", "DM Sans", "IBM Plex Sans", "Geist", "Oxanium",
|
|
88
|
-
"Architects Daughter", "Merriweather", "Playfair Display", "Lora",
|
|
89
|
-
"Source Serif Pro", "Libre Baskerville", "Space Grotesk", "JetBrains Mono",
|
|
90
|
-
"Fira Code", "Source Code Pro", "IBM Plex Mono", "Roboto Mono", "Space Mono", "Geist Mono",
|
|
91
|
-
] as const;
|
|
92
|
-
type GoogleFont = (typeof GOOGLE_FONTS)[number];
|
|
93
|
-
|
|
94
|
-
const getGoogleFontUrl = (font: string) =>
|
|
95
|
-
`https://fonts.googleapis.com/css2?family=${font.replaceAll(/\s+/g, "+")}:wght@400;500;600;700&display=swap`;
|
|
96
|
-
|
|
97
|
-
const processFont = (fontValue: string) => {
|
|
98
|
-
const families = fontValue
|
|
99
|
-
.split(",")
|
|
100
|
-
.map((f) => f.trim().replaceAll(/['"]/g, ""));
|
|
101
|
-
|
|
102
|
-
return families
|
|
103
|
-
.filter((family) => GOOGLE_FONTS.includes(family as GoogleFont))
|
|
104
|
-
.map((family) => getGoogleFontUrl(family));
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const processFontConfig = (fontConfig?: FontConfig) => {
|
|
108
|
-
if (!fontConfig) return { url: undefined, fontFamily: undefined };
|
|
109
|
-
|
|
110
|
-
if (typeof fontConfig === "string") {
|
|
111
|
-
if (GOOGLE_FONTS.includes(fontConfig as GoogleFont)) {
|
|
112
|
-
return {
|
|
113
|
-
url: getGoogleFontUrl(fontConfig),
|
|
114
|
-
fontFamily: fontConfig,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
return { url: undefined, fontFamily: fontConfig };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
url: fontConfig.url,
|
|
122
|
-
fontFamily: fontConfig.fontFamily,
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const processFonts = async (themeConfig: ZudokuConfig["theme"]) => {
|
|
127
|
-
const imports: string[] = [];
|
|
128
|
-
const families = {
|
|
129
|
-
sans: "Geist, sans-serif",
|
|
130
|
-
serif: undefined as string | undefined,
|
|
131
|
-
mono: '"Geist Mono", monospace',
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Process user fonts
|
|
135
|
-
const userFonts = {
|
|
136
|
-
sans: processFontConfig(themeConfig?.fonts?.sans),
|
|
137
|
-
serif: processFontConfig(themeConfig?.fonts?.serif),
|
|
138
|
-
mono: processFontConfig(themeConfig?.fonts?.mono),
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// Add user font imports
|
|
142
|
-
for (const font of Object.values(userFonts)) {
|
|
143
|
-
if (font.url) {
|
|
144
|
-
imports.push(font.url);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Process registry fonts if available
|
|
149
|
-
let registryFonts = {
|
|
150
|
-
sans: undefined as string | undefined,
|
|
151
|
-
serif: undefined as string | undefined,
|
|
152
|
-
mono: undefined as string | undefined,
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
if (themeConfig?.registryUrl) {
|
|
156
|
-
try {
|
|
157
|
-
const registryItem = await fetchShadcnRegistryItem(
|
|
158
|
-
themeConfig.registryUrl,
|
|
159
|
-
);
|
|
160
|
-
const { cssVars = {} } = registryItem;
|
|
161
|
-
const { theme: regThemeVars = {}, light: regLightVars = {} } = cssVars;
|
|
162
|
-
|
|
163
|
-
registryFonts = {
|
|
164
|
-
sans: regLightVars["font-sans"] ?? regThemeVars["font-sans"],
|
|
165
|
-
serif: regLightVars["font-serif"] ?? regThemeVars["font-serif"],
|
|
166
|
-
mono: regLightVars["font-mono"] ?? regThemeVars["font-mono"],
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Add registry font imports
|
|
170
|
-
for (const font of Object.values(registryFonts)) {
|
|
171
|
-
if (font) {
|
|
172
|
-
imports.push(...processFont(font));
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
} catch {
|
|
176
|
-
// Registry fonts failed to load, continue with user fonts and defaults
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Determine final font families with priority: user > registry > defaults
|
|
181
|
-
families.sans =
|
|
182
|
-
userFonts.sans.fontFamily || registryFonts.sans || "Geist, sans-serif";
|
|
183
|
-
families.serif = userFonts.serif.fontFamily || registryFonts.serif;
|
|
184
|
-
families.mono =
|
|
185
|
-
userFonts.mono.fontFamily ||
|
|
186
|
-
registryFonts.mono ||
|
|
187
|
-
'"Geist Mono", monospace';
|
|
188
|
-
|
|
189
|
-
// Add default font imports if no user or registry fonts
|
|
190
|
-
if (!userFonts.sans.fontFamily && !registryFonts.sans) {
|
|
191
|
-
imports.push(getGoogleFontUrl("Geist"));
|
|
192
|
-
}
|
|
193
|
-
if (!userFonts.serif.fontFamily && !registryFonts.serif) {
|
|
194
|
-
imports.push(getGoogleFontUrl("Playfair Display"));
|
|
195
|
-
}
|
|
196
|
-
if (!userFonts.mono.fontFamily && !registryFonts.mono) {
|
|
197
|
-
imports.push(getGoogleFontUrl("Geist Mono"));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return { imports, families };
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
export const virtualModuleId = "virtual:zudoku-theme.css";
|
|
204
|
-
export const resolvedVirtualModuleId = `\0${virtualModuleId}`;
|
|
205
|
-
|
|
206
|
-
export const viteThemePlugin = (): Plugin => {
|
|
207
|
-
return {
|
|
208
|
-
// It is important to run before the Tailwind plugin
|
|
209
|
-
enforce: "pre",
|
|
210
|
-
name: "zudoku-css-theme",
|
|
211
|
-
|
|
212
|
-
resolveId(id) {
|
|
213
|
-
if (id === "virtual:zudoku-theme.css") {
|
|
214
|
-
return resolvedVirtualModuleId;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
// Handle the virtual module for dynamic theme content
|
|
218
|
-
async load(id) {
|
|
219
|
-
if (id !== resolvedVirtualModuleId) return;
|
|
220
|
-
|
|
221
|
-
const config = getCurrentConfig();
|
|
222
|
-
|
|
223
|
-
const themeConfig = config.theme ?? {};
|
|
224
|
-
const themeCss: string[] = [];
|
|
225
|
-
|
|
226
|
-
// Consolidate all font processing
|
|
227
|
-
const fonts = await processFonts(themeConfig);
|
|
228
|
-
|
|
229
|
-
// Add all font imports at once
|
|
230
|
-
if (fonts.imports.length > 0) {
|
|
231
|
-
themeCss.push(...fonts.imports.map((url) => `@import url('${url}');`));
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Handle registry theme variables
|
|
235
|
-
if (themeConfig.registryUrl) {
|
|
236
|
-
try {
|
|
237
|
-
const registryItem = await fetchShadcnRegistryItem(
|
|
238
|
-
themeConfig.registryUrl,
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
// Extract theme variables from registry
|
|
242
|
-
const { cssVars = {}, css = {} } = registryItem;
|
|
243
|
-
const { light: regLightVars = {}, dark: regDarkVars = {} } = cssVars;
|
|
244
|
-
|
|
245
|
-
// Process custom CSS from registry
|
|
246
|
-
if (Object.keys(css).length > 0) {
|
|
247
|
-
themeCss.push(processCustomCss(css));
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Merge registry variables with user overrides
|
|
251
|
-
const applyOverrides = (
|
|
252
|
-
vars: Record<string, string>,
|
|
253
|
-
overrides?: Theme,
|
|
254
|
-
) => {
|
|
255
|
-
if (!overrides) return vars;
|
|
256
|
-
|
|
257
|
-
const result = { ...vars };
|
|
258
|
-
for (const [key, value] of objectEntries(overrides)) {
|
|
259
|
-
if (value && THEME_VARIABLES.includes(key)) {
|
|
260
|
-
result[uncamelize(key)] = processColorValue(value);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return result;
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
const lightVars = applyOverrides(regLightVars, themeConfig.light);
|
|
267
|
-
const darkVars = applyOverrides(regDarkVars, themeConfig.dark);
|
|
268
|
-
|
|
269
|
-
// Generate CSS for light and dark themes
|
|
270
|
-
if (Object.keys(lightVars).length > 0) {
|
|
271
|
-
themeCss.push(`:root {\n${generateRegistryCss(lightVars)}\n}`);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (Object.keys(darkVars).length > 0) {
|
|
275
|
-
themeCss.push(`.dark {\n${generateRegistryCss(darkVars)}\n}`);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (lightVars["letter-spacing"] !== "0em") {
|
|
279
|
-
themeCss.push(
|
|
280
|
-
"@theme inline {",
|
|
281
|
-
" --tracking-tighter: calc(var(--tracking-normal) - 0.05em);",
|
|
282
|
-
" --tracking-tight: calc(var(--tracking-normal) - 0.025em);",
|
|
283
|
-
" --tracking-normal: var(--tracking-normal);",
|
|
284
|
-
" --tracking-wide: calc(var(--tracking-normal) + 0.025em);",
|
|
285
|
-
" --tracking-wider: calc(var(--tracking-normal) + 0.05em);",
|
|
286
|
-
" --tracking-widest: calc(var(--tracking-normal) + 0.1em);",
|
|
287
|
-
"}",
|
|
288
|
-
);
|
|
289
|
-
themeCss.push(
|
|
290
|
-
`body {\n letter-spacing: var(--tracking-normal);\n}`,
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
} catch (error) {
|
|
294
|
-
// biome-ignore lint/suspicious/noConsole: Logging allowed here
|
|
295
|
-
console.error("Failed to load shadcn registry theme:", error);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (themeConfig.light) {
|
|
300
|
-
themeCss.push(`:root {\n${generateCss(themeConfig.light)}\n}`);
|
|
301
|
-
}
|
|
302
|
-
if (themeConfig.dark) {
|
|
303
|
-
themeCss.push(`.dark {\n${generateCss(themeConfig.dark)}\n}`);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Add font family CSS variables
|
|
307
|
-
const rootVars = [
|
|
308
|
-
` --font-sans: ${fonts.families.sans};`,
|
|
309
|
-
` --font-mono: ${fonts.families.mono};`,
|
|
310
|
-
];
|
|
311
|
-
|
|
312
|
-
if (fonts.families.serif) {
|
|
313
|
-
rootVars.push(` --font-serif: ${fonts.families.serif};`);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Make shiki theme background colors available as CSS variables
|
|
317
|
-
const shikiThemes =
|
|
318
|
-
config.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes;
|
|
319
|
-
|
|
320
|
-
const [lightTheme, darkTheme] = (
|
|
321
|
-
await Promise.all<ThemeRegistration>([
|
|
322
|
-
import(`@shikijs/themes/${shikiThemes.light}`).then((m) => m.default),
|
|
323
|
-
import(`@shikijs/themes/${shikiThemes.dark}`).then((m) => m.default),
|
|
324
|
-
])
|
|
325
|
-
).map(normalizeTheme);
|
|
326
|
-
|
|
327
|
-
rootVars.push(
|
|
328
|
-
` --shiki-light: ${lightTheme?.fg ?? "#000"};`,
|
|
329
|
-
` --shiki-dark: ${darkTheme?.fg ?? "#fff"};`,
|
|
330
|
-
` --shiki-light-bg: ${lightTheme?.bg ?? "#fff"};`,
|
|
331
|
-
` --shiki-dark-bg: ${darkTheme?.bg ?? "#000"};`,
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
themeCss.push(`:root {\n${rootVars.join("\n")}\n}`);
|
|
335
|
-
|
|
336
|
-
return themeCss.join("\n");
|
|
337
|
-
},
|
|
338
|
-
|
|
339
|
-
// Handle static theme content in main.css
|
|
340
|
-
// This goes through the normal CSS pipeline so Tailwind can process it
|
|
341
|
-
async transform(src, id) {
|
|
342
|
-
if (!id.endsWith("/src/app/main.css")) return;
|
|
343
|
-
|
|
344
|
-
const config = getCurrentConfig();
|
|
345
|
-
|
|
346
|
-
const files = new Set(
|
|
347
|
-
[
|
|
348
|
-
config.__meta.rootDir,
|
|
349
|
-
...config.__meta.dependencies,
|
|
350
|
-
...(config.__pluginDirs ?? []),
|
|
351
|
-
].map((file) => path.relative(path.dirname(id), file)),
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
const code = [...files].map((file) => `@source "${file}";`);
|
|
355
|
-
|
|
356
|
-
// NOTE: Font imports and declarations are handled by virtual:zudoku-theme.css
|
|
357
|
-
// This @theme block only maps CSS variables to Tailwind utilities
|
|
358
|
-
code.push("@theme inline {");
|
|
359
|
-
|
|
360
|
-
// prettier-ignore
|
|
361
|
-
const colorVars = [
|
|
362
|
-
"background", "foreground", "card", "card-foreground", "popover", "popover-foreground", "primary",
|
|
363
|
-
"primary-foreground", "secondary", "secondary-foreground", "muted", "muted-foreground", "accent",
|
|
364
|
-
"accent-foreground", "destructive", "destructive-foreground", "border", "input", "ring", "chart-1",
|
|
365
|
-
"chart-2", "chart-3", "chart-4", "chart-5", "sidebar", "sidebar-foreground", "sidebar-primary",
|
|
366
|
-
"sidebar-primary-foreground", "sidebar-accent", "sidebar-accent-foreground", "sidebar-border", "sidebar-ring",
|
|
367
|
-
];
|
|
368
|
-
|
|
369
|
-
code.push(
|
|
370
|
-
...colorVars.map((color) => ` --color-${color}: var(--${color});`),
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
code.push(
|
|
374
|
-
` --radius-sm: calc(var(--radius) - 4px);`,
|
|
375
|
-
` --radius-md: calc(var(--radius) - 2px);`,
|
|
376
|
-
` --radius-lg: var(--radius);`,
|
|
377
|
-
` --radius-xl: calc(var(--radius) + 4px);`,
|
|
378
|
-
` --font-sans: var(--font-sans);`,
|
|
379
|
-
` --font-mono: var(--font-mono);`,
|
|
380
|
-
` --font-serif: var(--font-serif);`,
|
|
381
|
-
);
|
|
382
|
-
|
|
383
|
-
code.push("}");
|
|
384
|
-
|
|
385
|
-
const customCss = config.theme?.customCss;
|
|
386
|
-
if (customCss) {
|
|
387
|
-
code.push(processCustomCss(customCss));
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
const defaultThemeImport = config.theme?.noDefaultTheme
|
|
391
|
-
? ""
|
|
392
|
-
: '@import "./defaultTheme.css" layer(theme);';
|
|
393
|
-
|
|
394
|
-
return src
|
|
395
|
-
.replace(DEFAULT_THEME_REPLACE, defaultThemeImport)
|
|
396
|
-
.replace(MAIN_REPLACE, code.join("\n"));
|
|
397
|
-
},
|
|
398
|
-
};
|
|
399
|
-
};
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { normalizeTheme, type ThemeRegistration } from "shiki";
|
|
3
|
+
import type { Plugin } from "vite";
|
|
4
|
+
import { getCurrentConfig } from "../config/loader.js";
|
|
5
|
+
import type {
|
|
6
|
+
FontConfig,
|
|
7
|
+
ZudokuConfig,
|
|
8
|
+
} from "../config/validators/ZudokuConfig.js";
|
|
9
|
+
import { defaultHighlightOptions } from "../lib/shiki.js";
|
|
10
|
+
import { objectEntries } from "../lib/util/objectEntries.js";
|
|
11
|
+
import {
|
|
12
|
+
fetchShadcnRegistryItem,
|
|
13
|
+
type RegistryItemCss,
|
|
14
|
+
} from "./shadcn-registry.js";
|
|
15
|
+
|
|
16
|
+
// prettier-ignore
|
|
17
|
+
const THEME_VARIABLES = [
|
|
18
|
+
"background", "foreground", "card", "cardForeground", "popover", "popoverForeground", "primary",
|
|
19
|
+
"primaryForeground", "secondary", "secondaryForeground", "muted", "mutedForeground", "accent",
|
|
20
|
+
"accentForeground", "destructive", "destructiveForeground", "border", "input", "ring", "radius",
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
const uncamelize = (str: string) =>
|
|
24
|
+
str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
25
|
+
|
|
26
|
+
export type Theme = Partial<Record<(typeof THEME_VARIABLES)[number], string>>;
|
|
27
|
+
|
|
28
|
+
const processColorValue = (value: string | undefined): string => {
|
|
29
|
+
if (!value) return "";
|
|
30
|
+
const color =
|
|
31
|
+
!value.startsWith("#") &&
|
|
32
|
+
!value.includes("(") &&
|
|
33
|
+
value.split(" ").length >= 3
|
|
34
|
+
? // Assume legacy tailwind hsl format
|
|
35
|
+
`hsl(${value})`
|
|
36
|
+
: value;
|
|
37
|
+
|
|
38
|
+
return color;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const generateCss = (theme: Theme) =>
|
|
42
|
+
objectEntries(theme)
|
|
43
|
+
.filter(([key]) => THEME_VARIABLES.includes(key))
|
|
44
|
+
.map(([key, value]) => `--${uncamelize(key)}: ${processColorValue(value)};`)
|
|
45
|
+
.join("\n");
|
|
46
|
+
|
|
47
|
+
const generateRegistryCss = (cssVars: Record<string, string>) =>
|
|
48
|
+
Object.entries(cssVars)
|
|
49
|
+
.map(([key, value]) => ` --${key}: ${value};`)
|
|
50
|
+
.join("\n");
|
|
51
|
+
|
|
52
|
+
const processCustomCss = (css: string | RegistryItemCss): string => {
|
|
53
|
+
if (typeof css === "string") {
|
|
54
|
+
return css;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const processStyles = (
|
|
58
|
+
styles: RegistryItemCss | string,
|
|
59
|
+
indent = "",
|
|
60
|
+
): string[] => {
|
|
61
|
+
if (typeof styles === "string") {
|
|
62
|
+
return [`${indent}${styles}`];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const rules = [];
|
|
66
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
67
|
+
if (typeof value === "string") {
|
|
68
|
+
rules.push(`${indent}${key}: ${value};`);
|
|
69
|
+
} else {
|
|
70
|
+
rules.push(`${indent}${key} {`);
|
|
71
|
+
rules.push(...processStyles(value, `${indent} `));
|
|
72
|
+
rules.push(`${indent}}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return rules;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return processStyles(css).join("\n");
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const MAIN_REPLACE = "/* @vite-plugin-inject main */";
|
|
82
|
+
const DEFAULT_THEME_REPLACE = "/* @vite-plugin-inject defaultTheme */";
|
|
83
|
+
|
|
84
|
+
// prettier-ignore
|
|
85
|
+
export const GOOGLE_FONTS = [
|
|
86
|
+
"Inter", "Roboto", "Open Sans", "Poppins", "Montserrat", "Outfit",
|
|
87
|
+
"Plus Jakarta Sans", "DM Sans", "IBM Plex Sans", "Geist", "Oxanium",
|
|
88
|
+
"Architects Daughter", "Merriweather", "Playfair Display", "Lora",
|
|
89
|
+
"Source Serif Pro", "Libre Baskerville", "Space Grotesk", "JetBrains Mono",
|
|
90
|
+
"Fira Code", "Source Code Pro", "IBM Plex Mono", "Roboto Mono", "Space Mono", "Geist Mono",
|
|
91
|
+
] as const;
|
|
92
|
+
type GoogleFont = (typeof GOOGLE_FONTS)[number];
|
|
93
|
+
|
|
94
|
+
const getGoogleFontUrl = (font: string) =>
|
|
95
|
+
`https://fonts.googleapis.com/css2?family=${font.replaceAll(/\s+/g, "+")}:wght@400;500;600;700&display=swap`;
|
|
96
|
+
|
|
97
|
+
const processFont = (fontValue: string) => {
|
|
98
|
+
const families = fontValue
|
|
99
|
+
.split(",")
|
|
100
|
+
.map((f) => f.trim().replaceAll(/['"]/g, ""));
|
|
101
|
+
|
|
102
|
+
return families
|
|
103
|
+
.filter((family) => GOOGLE_FONTS.includes(family as GoogleFont))
|
|
104
|
+
.map((family) => getGoogleFontUrl(family));
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const processFontConfig = (fontConfig?: FontConfig) => {
|
|
108
|
+
if (!fontConfig) return { url: undefined, fontFamily: undefined };
|
|
109
|
+
|
|
110
|
+
if (typeof fontConfig === "string") {
|
|
111
|
+
if (GOOGLE_FONTS.includes(fontConfig as GoogleFont)) {
|
|
112
|
+
return {
|
|
113
|
+
url: getGoogleFontUrl(fontConfig),
|
|
114
|
+
fontFamily: fontConfig,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return { url: undefined, fontFamily: fontConfig };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
url: fontConfig.url,
|
|
122
|
+
fontFamily: fontConfig.fontFamily,
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const processFonts = async (themeConfig: ZudokuConfig["theme"]) => {
|
|
127
|
+
const imports: string[] = [];
|
|
128
|
+
const families = {
|
|
129
|
+
sans: "Geist, sans-serif",
|
|
130
|
+
serif: undefined as string | undefined,
|
|
131
|
+
mono: '"Geist Mono", monospace',
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Process user fonts
|
|
135
|
+
const userFonts = {
|
|
136
|
+
sans: processFontConfig(themeConfig?.fonts?.sans),
|
|
137
|
+
serif: processFontConfig(themeConfig?.fonts?.serif),
|
|
138
|
+
mono: processFontConfig(themeConfig?.fonts?.mono),
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Add user font imports
|
|
142
|
+
for (const font of Object.values(userFonts)) {
|
|
143
|
+
if (font.url) {
|
|
144
|
+
imports.push(font.url);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Process registry fonts if available
|
|
149
|
+
let registryFonts = {
|
|
150
|
+
sans: undefined as string | undefined,
|
|
151
|
+
serif: undefined as string | undefined,
|
|
152
|
+
mono: undefined as string | undefined,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
if (themeConfig?.registryUrl) {
|
|
156
|
+
try {
|
|
157
|
+
const registryItem = await fetchShadcnRegistryItem(
|
|
158
|
+
themeConfig.registryUrl,
|
|
159
|
+
);
|
|
160
|
+
const { cssVars = {} } = registryItem;
|
|
161
|
+
const { theme: regThemeVars = {}, light: regLightVars = {} } = cssVars;
|
|
162
|
+
|
|
163
|
+
registryFonts = {
|
|
164
|
+
sans: regLightVars["font-sans"] ?? regThemeVars["font-sans"],
|
|
165
|
+
serif: regLightVars["font-serif"] ?? regThemeVars["font-serif"],
|
|
166
|
+
mono: regLightVars["font-mono"] ?? regThemeVars["font-mono"],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Add registry font imports
|
|
170
|
+
for (const font of Object.values(registryFonts)) {
|
|
171
|
+
if (font) {
|
|
172
|
+
imports.push(...processFont(font));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
// Registry fonts failed to load, continue with user fonts and defaults
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Determine final font families with priority: user > registry > defaults
|
|
181
|
+
families.sans =
|
|
182
|
+
userFonts.sans.fontFamily || registryFonts.sans || "Geist, sans-serif";
|
|
183
|
+
families.serif = userFonts.serif.fontFamily || registryFonts.serif;
|
|
184
|
+
families.mono =
|
|
185
|
+
userFonts.mono.fontFamily ||
|
|
186
|
+
registryFonts.mono ||
|
|
187
|
+
'"Geist Mono", monospace';
|
|
188
|
+
|
|
189
|
+
// Add default font imports if no user or registry fonts
|
|
190
|
+
if (!userFonts.sans.fontFamily && !registryFonts.sans) {
|
|
191
|
+
imports.push(getGoogleFontUrl("Geist"));
|
|
192
|
+
}
|
|
193
|
+
if (!userFonts.serif.fontFamily && !registryFonts.serif) {
|
|
194
|
+
imports.push(getGoogleFontUrl("Playfair Display"));
|
|
195
|
+
}
|
|
196
|
+
if (!userFonts.mono.fontFamily && !registryFonts.mono) {
|
|
197
|
+
imports.push(getGoogleFontUrl("Geist Mono"));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return { imports, families };
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const virtualModuleId = "virtual:zudoku-theme.css";
|
|
204
|
+
export const resolvedVirtualModuleId = `\0${virtualModuleId}`;
|
|
205
|
+
|
|
206
|
+
export const viteThemePlugin = (): Plugin => {
|
|
207
|
+
return {
|
|
208
|
+
// It is important to run before the Tailwind plugin
|
|
209
|
+
enforce: "pre",
|
|
210
|
+
name: "zudoku-css-theme",
|
|
211
|
+
|
|
212
|
+
resolveId(id) {
|
|
213
|
+
if (id === "virtual:zudoku-theme.css") {
|
|
214
|
+
return resolvedVirtualModuleId;
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
// Handle the virtual module for dynamic theme content
|
|
218
|
+
async load(id) {
|
|
219
|
+
if (id !== resolvedVirtualModuleId) return;
|
|
220
|
+
|
|
221
|
+
const config = getCurrentConfig();
|
|
222
|
+
|
|
223
|
+
const themeConfig = config.theme ?? {};
|
|
224
|
+
const themeCss: string[] = [];
|
|
225
|
+
|
|
226
|
+
// Consolidate all font processing
|
|
227
|
+
const fonts = await processFonts(themeConfig);
|
|
228
|
+
|
|
229
|
+
// Add all font imports at once
|
|
230
|
+
if (fonts.imports.length > 0) {
|
|
231
|
+
themeCss.push(...fonts.imports.map((url) => `@import url('${url}');`));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Handle registry theme variables
|
|
235
|
+
if (themeConfig.registryUrl) {
|
|
236
|
+
try {
|
|
237
|
+
const registryItem = await fetchShadcnRegistryItem(
|
|
238
|
+
themeConfig.registryUrl,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Extract theme variables from registry
|
|
242
|
+
const { cssVars = {}, css = {} } = registryItem;
|
|
243
|
+
const { light: regLightVars = {}, dark: regDarkVars = {} } = cssVars;
|
|
244
|
+
|
|
245
|
+
// Process custom CSS from registry
|
|
246
|
+
if (Object.keys(css).length > 0) {
|
|
247
|
+
themeCss.push(processCustomCss(css));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Merge registry variables with user overrides
|
|
251
|
+
const applyOverrides = (
|
|
252
|
+
vars: Record<string, string>,
|
|
253
|
+
overrides?: Theme,
|
|
254
|
+
) => {
|
|
255
|
+
if (!overrides) return vars;
|
|
256
|
+
|
|
257
|
+
const result = { ...vars };
|
|
258
|
+
for (const [key, value] of objectEntries(overrides)) {
|
|
259
|
+
if (value && THEME_VARIABLES.includes(key)) {
|
|
260
|
+
result[uncamelize(key)] = processColorValue(value);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return result;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const lightVars = applyOverrides(regLightVars, themeConfig.light);
|
|
267
|
+
const darkVars = applyOverrides(regDarkVars, themeConfig.dark);
|
|
268
|
+
|
|
269
|
+
// Generate CSS for light and dark themes
|
|
270
|
+
if (Object.keys(lightVars).length > 0) {
|
|
271
|
+
themeCss.push(`:root {\n${generateRegistryCss(lightVars)}\n}`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (Object.keys(darkVars).length > 0) {
|
|
275
|
+
themeCss.push(`.dark {\n${generateRegistryCss(darkVars)}\n}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (lightVars["letter-spacing"] !== "0em") {
|
|
279
|
+
themeCss.push(
|
|
280
|
+
"@theme inline {",
|
|
281
|
+
" --tracking-tighter: calc(var(--tracking-normal) - 0.05em);",
|
|
282
|
+
" --tracking-tight: calc(var(--tracking-normal) - 0.025em);",
|
|
283
|
+
" --tracking-normal: var(--tracking-normal);",
|
|
284
|
+
" --tracking-wide: calc(var(--tracking-normal) + 0.025em);",
|
|
285
|
+
" --tracking-wider: calc(var(--tracking-normal) + 0.05em);",
|
|
286
|
+
" --tracking-widest: calc(var(--tracking-normal) + 0.1em);",
|
|
287
|
+
"}",
|
|
288
|
+
);
|
|
289
|
+
themeCss.push(
|
|
290
|
+
`body {\n letter-spacing: var(--tracking-normal);\n}`,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
} catch (error) {
|
|
294
|
+
// biome-ignore lint/suspicious/noConsole: Logging allowed here
|
|
295
|
+
console.error("Failed to load shadcn registry theme:", error);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (themeConfig.light) {
|
|
300
|
+
themeCss.push(`:root {\n${generateCss(themeConfig.light)}\n}`);
|
|
301
|
+
}
|
|
302
|
+
if (themeConfig.dark) {
|
|
303
|
+
themeCss.push(`.dark {\n${generateCss(themeConfig.dark)}\n}`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Add font family CSS variables
|
|
307
|
+
const rootVars = [
|
|
308
|
+
` --font-sans: ${fonts.families.sans};`,
|
|
309
|
+
` --font-mono: ${fonts.families.mono};`,
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
if (fonts.families.serif) {
|
|
313
|
+
rootVars.push(` --font-serif: ${fonts.families.serif};`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Make shiki theme background colors available as CSS variables
|
|
317
|
+
const shikiThemes =
|
|
318
|
+
config.syntaxHighlighting?.themes ?? defaultHighlightOptions.themes;
|
|
319
|
+
|
|
320
|
+
const [lightTheme, darkTheme] = (
|
|
321
|
+
await Promise.all<ThemeRegistration>([
|
|
322
|
+
import(`@shikijs/themes/${shikiThemes.light}`).then((m) => m.default),
|
|
323
|
+
import(`@shikijs/themes/${shikiThemes.dark}`).then((m) => m.default),
|
|
324
|
+
])
|
|
325
|
+
).map(normalizeTheme);
|
|
326
|
+
|
|
327
|
+
rootVars.push(
|
|
328
|
+
` --shiki-light: ${lightTheme?.fg ?? "#000"};`,
|
|
329
|
+
` --shiki-dark: ${darkTheme?.fg ?? "#fff"};`,
|
|
330
|
+
` --shiki-light-bg: ${lightTheme?.bg ?? "#fff"};`,
|
|
331
|
+
` --shiki-dark-bg: ${darkTheme?.bg ?? "#000"};`,
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
themeCss.push(`:root {\n${rootVars.join("\n")}\n}`);
|
|
335
|
+
|
|
336
|
+
return themeCss.join("\n");
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
// Handle static theme content in main.css
|
|
340
|
+
// This goes through the normal CSS pipeline so Tailwind can process it
|
|
341
|
+
async transform(src, id) {
|
|
342
|
+
if (!id.endsWith("/src/app/main.css")) return;
|
|
343
|
+
|
|
344
|
+
const config = getCurrentConfig();
|
|
345
|
+
|
|
346
|
+
const files = new Set(
|
|
347
|
+
[
|
|
348
|
+
config.__meta.rootDir,
|
|
349
|
+
...config.__meta.dependencies,
|
|
350
|
+
...(config.__pluginDirs ?? []),
|
|
351
|
+
].map((file) => path.relative(path.dirname(id), file)),
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
const code = [...files].map((file) => `@source "${file}";`);
|
|
355
|
+
|
|
356
|
+
// NOTE: Font imports and declarations are handled by virtual:zudoku-theme.css
|
|
357
|
+
// This @theme block only maps CSS variables to Tailwind utilities
|
|
358
|
+
code.push("@theme inline {");
|
|
359
|
+
|
|
360
|
+
// prettier-ignore
|
|
361
|
+
const colorVars = [
|
|
362
|
+
"background", "foreground", "card", "card-foreground", "popover", "popover-foreground", "primary",
|
|
363
|
+
"primary-foreground", "secondary", "secondary-foreground", "muted", "muted-foreground", "accent",
|
|
364
|
+
"accent-foreground", "destructive", "destructive-foreground", "border", "input", "ring", "chart-1",
|
|
365
|
+
"chart-2", "chart-3", "chart-4", "chart-5", "sidebar", "sidebar-foreground", "sidebar-primary",
|
|
366
|
+
"sidebar-primary-foreground", "sidebar-accent", "sidebar-accent-foreground", "sidebar-border", "sidebar-ring",
|
|
367
|
+
];
|
|
368
|
+
|
|
369
|
+
code.push(
|
|
370
|
+
...colorVars.map((color) => ` --color-${color}: var(--${color});`),
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
code.push(
|
|
374
|
+
` --radius-sm: calc(var(--radius) - 4px);`,
|
|
375
|
+
` --radius-md: calc(var(--radius) - 2px);`,
|
|
376
|
+
` --radius-lg: var(--radius);`,
|
|
377
|
+
` --radius-xl: calc(var(--radius) + 4px);`,
|
|
378
|
+
` --font-sans: var(--font-sans);`,
|
|
379
|
+
` --font-mono: var(--font-mono);`,
|
|
380
|
+
` --font-serif: var(--font-serif);`,
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
code.push("}");
|
|
384
|
+
|
|
385
|
+
const customCss = config.theme?.customCss;
|
|
386
|
+
if (customCss) {
|
|
387
|
+
code.push(processCustomCss(customCss));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const defaultThemeImport = config.theme?.noDefaultTheme
|
|
391
|
+
? ""
|
|
392
|
+
: '@import "./defaultTheme.css" layer(theme);';
|
|
393
|
+
|
|
394
|
+
return src
|
|
395
|
+
.replace(DEFAULT_THEME_REPLACE, defaultThemeImport)
|
|
396
|
+
.replace(MAIN_REPLACE, code.join("\n"));
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
};
|