@clidey/dory 0.27.0 → 0.30.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.
Files changed (95) hide show
  1. package/bin/dist/dory.js +115 -29
  2. package/bin/dist/dory.js.map +1 -1
  3. package/package.json +12 -4
  4. package/.dockerignore +0 -4
  5. package/CLAUDE.md +0 -178
  6. package/CODE_OF_CONDUCT.md +0 -128
  7. package/CONTRIBUTING.md +0 -91
  8. package/SECURITY.md +0 -11
  9. package/bin/dory.ts +0 -433
  10. package/dist/favicon.svg +0 -75
  11. package/dist/frontmatter.json +0 -77
  12. package/dist/index.html +0 -55
  13. package/dist/llms.txt +0 -561
  14. package/dist/logo/logo.svg +0 -18
  15. package/docs/api-playground-demo.mdx +0 -119
  16. package/docs/api-reference/asyncapi.json +0 -324
  17. package/docs/api-reference/openapi.json +0 -366
  18. package/docs/api-reference/operations/create.mdx +0 -5
  19. package/docs/api-reference/operations/delete.mdx +0 -5
  20. package/docs/api-reference/operations/get.mdx +0 -5
  21. package/docs/api-reference/operations/update.mdx +0 -5
  22. package/docs/api-reference/websocket-operations/receive-chat-message.mdx +0 -5
  23. package/docs/api-reference/websocket-operations/receive-notifications.mdx +0 -5
  24. package/docs/api-reference/websocket-operations/receive-presence-update.mdx +0 -5
  25. package/docs/api-reference/websocket-operations/send-chat-message.mdx +0 -5
  26. package/docs/api-reference/websocket-operations/send-presence-update.mdx +0 -5
  27. package/docs/dory.json +0 -64
  28. package/docs/favicon.svg +0 -75
  29. package/docs/features.mdx +0 -440
  30. package/docs/introduction.mdx +0 -44
  31. package/docs/logo/logo.svg +0 -18
  32. package/docs/websocket-playground-demo.mdx +0 -135
  33. package/index.html +0 -54
  34. package/scripts/generate-frontmatter-json.js +0 -154
  35. package/scripts/generate-llm-txt.js +0 -115
  36. package/src/app.css +0 -5
  37. package/src/app.tsx +0 -13
  38. package/src/components/dropdown.tsx +0 -53
  39. package/src/components/hooks.tsx +0 -28
  40. package/src/components/loading.tsx +0 -21
  41. package/src/components/mdx-provider.tsx +0 -13
  42. package/src/components/navigation.tsx +0 -58
  43. package/src/components/notification.tsx +0 -13
  44. package/src/components/routes.tsx +0 -92
  45. package/src/components/search-index.ts +0 -43
  46. package/src/components/search.tsx +0 -435
  47. package/src/components/store.ts +0 -216
  48. package/src/config/mdx.js +0 -12
  49. package/src/config/mdx.ts +0 -12
  50. package/src/main.tsx +0 -22
  51. package/src/mdx/accordion.tsx +0 -41
  52. package/src/mdx/api-playground.tsx +0 -659
  53. package/src/mdx/api.tsx +0 -354
  54. package/src/mdx/async-api.tsx +0 -353
  55. package/src/mdx/callout.tsx +0 -64
  56. package/src/mdx/card.tsx +0 -54
  57. package/src/mdx/code.tsx +0 -289
  58. package/src/mdx/expandable.tsx +0 -36
  59. package/src/mdx/fence.tsx +0 -74
  60. package/src/mdx/icon.tsx +0 -73
  61. package/src/mdx/latex.tsx +0 -26
  62. package/src/mdx/list.tsx +0 -7
  63. package/src/mdx/mdx.tsx +0 -47
  64. package/src/mdx/mermaid.tsx +0 -147
  65. package/src/mdx/open-api.tsx +0 -311
  66. package/src/mdx/processor.ts +0 -174
  67. package/src/mdx/source.tsx +0 -58
  68. package/src/mdx/step.tsx +0 -51
  69. package/src/mdx/table.tsx +0 -20
  70. package/src/mdx/tag.tsx +0 -53
  71. package/src/mdx/text.tsx +0 -99
  72. package/src/mdx/websocket-playground.tsx +0 -824
  73. package/src/plugins/docs-assets.ts +0 -79
  74. package/src/plugins/frontmatter-dev-server.ts +0 -158
  75. package/src/plugins/frontmatter-generator.ts +0 -157
  76. package/src/plugins/llm-txt-dev-server.ts +0 -183
  77. package/src/plugins/llm-txt-generator.ts +0 -186
  78. package/src/plugins/sanitize.ts +0 -163
  79. package/src/plugins/unified-mdx-plugin.ts +0 -35
  80. package/src/theme.scss +0 -72
  81. package/src/types/config.ts +0 -47
  82. package/src/ui/header.tsx +0 -91
  83. package/src/ui/layout.tsx +0 -193
  84. package/src/ui/mobile-navigation.tsx +0 -64
  85. package/src/ui/prev-next-link.tsx +0 -74
  86. package/src/ui/table-of-content.tsx +0 -166
  87. package/src/utils/colors.ts +0 -54
  88. package/src/utils/fonts.ts +0 -23
  89. package/src/utils/functions.ts +0 -12
  90. package/src/vite-env.d.ts +0 -1
  91. package/tsconfig.app.json +0 -33
  92. package/tsconfig.bin.json +0 -24
  93. package/tsconfig.json +0 -7
  94. package/tsconfig.node.json +0 -26
  95. package/vite.config.ts +0 -41
package/src/ui/layout.tsx DELETED
@@ -1,193 +0,0 @@
1
- import type { ComponentChildren } from 'preact';
2
- import { useCallback, useEffect, useMemo, useState } from 'preact/hooks';
3
- import { useLocation } from 'wouter-preact';
4
- import { Navigation } from '../components/navigation';
5
- import { ALL_NAVIGATION, ALL_OPENAPI, completeFrontMatter, loadMDXFrontMatterForPath, loadAllMDXFrontMatter, ALL_PAGES, pathFromFilename, preloadFrontmatter, ALL_ASYNCAPI } from '../components/store';
6
- import { OpenAPI } from '../mdx/open-api';
7
- import { AsyncAPI } from '../mdx/async-api';
8
- import { Header } from './header';
9
- import { PrevNextLinks } from './prev-next-link';
10
- import { TableOfContents } from './table-of-content';
11
- import { Loading } from '../components/loading';
12
- import Dropdown from '../components/dropdown';
13
- import { useNotification } from '../components/notification';
14
- import { SparkleIcon } from 'lucide-react';
15
-
16
- interface LayoutProps {
17
- children: ComponentChildren;
18
- }
19
-
20
- const prompt = (pathname: string) => `Please read and analyze the content from this documentation page: ${window.location.origin}${pathname}.mdx\n\n` +
21
- `Then, help me understand and answer any questions I have about it. ` +
22
- `Please provide clear, detailed explanations and examples where relevant.`;
23
-
24
- export default function Layout({ children }: LayoutProps) {
25
- const [loading, setLoading] = useState(true);
26
- const [pathname] = useLocation();
27
- const { showNotification } = useNotification();
28
-
29
- const handleOpenMDX = useCallback(() => {
30
- window.open(`${window.location.origin}${pathname}.mdx`, '_blank');
31
- }, [pathname]);
32
-
33
- const handleCopyMDX = useCallback(() => {
34
- ALL_PAGES[pathFromFilename(pathname)]().then((mdx) => {
35
- navigator.clipboard.writeText(mdx.default.toString());
36
- });
37
- showNotification('Copied to clipboard');
38
- }, []);
39
- const handleOpenChatGPT = useCallback(() => {
40
- const url = `https://chat.openai.com/?q=${encodeURIComponent(prompt(pathname))}`;
41
- window.open(url, '_blank');
42
- }, [pathname]);
43
- const handleOpenAnthropic = useCallback(() => {
44
- const url = `https://claude.ai/new?q=${encodeURIComponent(prompt(pathname))}`;
45
- window.open(url, '_blank');
46
- }, [pathname]);
47
-
48
- const dropdownItems = useMemo(() => [
49
- {
50
- label: 'Open MDX',
51
- onClick: handleOpenMDX,
52
- },
53
- {
54
- label: 'Copy MDX',
55
- onClick: handleCopyMDX
56
- },
57
- {
58
- label: 'Open in ChatGPT',
59
- onClick: handleOpenChatGPT
60
- },
61
- {
62
- label: 'Open in Anthropic',
63
- onClick: handleOpenAnthropic
64
- }
65
- ], [handleOpenMDX, handleCopyMDX, handleOpenChatGPT, handleOpenAnthropic]);
66
-
67
- useEffect(() => {
68
- // Try to preload frontmatter first (optimized approach)
69
- preloadFrontmatter().then(() => {
70
- // If preloading succeeds, we're done
71
- setLoading(false);
72
- }).catch(() => {
73
- // Fallback to the original approach
74
- loadMDXFrontMatterForPath(pathname).then(() => {
75
- loadAllMDXFrontMatter(pathname).then(() => {
76
- setLoading(false);
77
- }).catch(() => {
78
- setLoading(false);
79
- });
80
- }).catch(() => {
81
- setLoading(false);
82
- });
83
- });
84
- }, [pathname]);
85
-
86
- const { title: group, group: title } = useMemo(() => {
87
- const group = ALL_NAVIGATION.flatMap((tab) =>
88
- tab.groups.find((group) =>
89
- group.pages.some((page) => page.href === pathname)
90
- )
91
- );
92
- const page = completeFrontMatter.find((page) => page.path === pathname);
93
-
94
- useEffect(() => {
95
- if (page?.title) {
96
- document.title = page.title;
97
- }
98
- if (page?.description) {
99
- const metaDescription = document.querySelector('meta[name="description"]');
100
- if (metaDescription) {
101
- metaDescription.setAttribute('content', page.description);
102
- }
103
- }
104
- }, [page]);
105
-
106
- return { group: group[0]?.title, title: page?.title, };
107
- }, [pathname, loading]);
108
-
109
- const tab = useMemo(() => {
110
- return completeFrontMatter.find((page) => page.path === pathname);
111
- }, [pathname, loading]);
112
-
113
- const openAPIJSON = useMemo(() => {
114
- if (tab == null || tab.openapi == null) {
115
- return null;
116
- }
117
- const firstDirectory = `/${tab.path.split('/')[1]}`;
118
- return ALL_OPENAPI[`${firstDirectory}/openapi.json`].default;
119
- }, [tab, loading]);
120
-
121
- const { method, path } = useMemo(() => {
122
- if (tab == null || tab.openapi == null) {
123
- return { method: '', path: '' };
124
- }
125
- return { method: tab.openapi.split(' ')[0], path: tab.openapi.split(' ')[1] };
126
- }, [tab, loading]);
127
-
128
- const asyncAPIJSON = useMemo(() => {
129
- if (tab == null || tab.asyncapi == null) {
130
- return null;
131
- }
132
- const firstDirectory = `/${tab.path.split('/')[1]}`;
133
- return ALL_ASYNCAPI[`${firstDirectory}/asyncapi.json`].default;
134
- }, [tab, loading]);
135
-
136
- const { operation, channel } = useMemo(() => {
137
- if (tab == null || tab.asyncapi == null) {
138
- return { operation: '', channel: '' };
139
- }
140
- return { operation: tab.asyncapi.split(' ')[0].toLowerCase(), channel: tab.asyncapi.split(' ')[1] };
141
- }, [tab, loading]);
142
-
143
- if (loading) return <div className="h-[25vh] flex grow"><Loading /></div>;
144
-
145
- return (
146
- <div className="flex w-full flex-col">
147
- <Header />
148
- <div id="container" className="relative flex w-full max-w-8xl sm:px-2 lg:px-8">
149
- <div className="hidden lg:relative lg:block lg:flex-none">
150
- <div className="sticky top-[4.75rem] -ml-0.5 h-[calc(100vh-4.75rem)] w-64 overflow-x-hidden overflow-y-auto py-16 pr-8 pl-0.5 xl:w-72 xl:pr-16">
151
- <Navigation />
152
- </div>
153
- </div>
154
- <main className="flex px-4 py-16 sm:px-6 lg:px-8 grow">
155
- <div className="min-w-0 w-full">
156
- <article className="h-full flex flex-1 flex-col">
157
- <div className="flex justify-between items-start">
158
- <header className="mb-8">
159
- {title && (
160
- <h1 className="font-display text-lg tracking-tight">
161
- {title}
162
- </h1>
163
- )}
164
- {group && (
165
- <p className="text-4xl tracking-tight">
166
- {group}
167
- </p>
168
- )}
169
- </header>
170
- {
171
- openAPIJSON == null && asyncAPIJSON == null &&
172
- <Dropdown className="gap-0" buttonLabel={<SparkleIcon className="w-4 h-4" />} items={dropdownItems} />
173
- }
174
- </div>
175
- <div className="flex-1 min-h-[calc(100vh-2rem)]">
176
- {openAPIJSON && tab && "openapi" in tab && method && path ?
177
- <OpenAPI openAPIJson={JSON.parse(openAPIJSON)} method={method} path={path} />
178
- : asyncAPIJSON && tab && "asyncapi" in tab && operation && channel ?
179
- <AsyncAPI asyncAPIJson={JSON.parse(asyncAPIJSON)} operation={operation} channel={channel} />
180
- : children}
181
- </div>
182
- <PrevNextLinks />
183
- </article>
184
- </div>
185
- {
186
- openAPIJSON == null && asyncAPIJSON == null &&
187
- <TableOfContents />
188
- }
189
- </main>
190
- </div>
191
- </div>
192
- );
193
- }
@@ -1,64 +0,0 @@
1
- 'use client'
2
-
3
- import { Sheet, SheetContent, Button } from '@clidey/ux'
4
- import { createContext, Suspense, useCallback, useContext, useRef, useState } from 'react'
5
-
6
- import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
7
- import { Navigation } from '../components/navigation'
8
-
9
- const IsInsideMobileNavigationContext = createContext(false)
10
-
11
- export function useIsInsideMobileNavigation() {
12
- return useContext(IsInsideMobileNavigationContext)
13
- }
14
-
15
- export function useMobileNavigation() {
16
- const [isOpen, setIsOpen] = useState(false)
17
- const isOpenRef = useRef(isOpen)
18
- isOpenRef.current = isOpen
19
-
20
- const open = useCallback(() => setIsOpen(true), [])
21
- const close = useCallback(() => setIsOpen(false), [])
22
- const toggle = useCallback(() => setIsOpen(prev => !prev), [])
23
-
24
- return {
25
- isOpen,
26
- isOpenRef,
27
- open,
28
- close,
29
- toggle,
30
- }
31
- }
32
-
33
- export function MobileNavigation() {
34
- const isInsideMobileNavigation = useIsInsideMobileNavigation()
35
- const { isOpen, open, close } = useMobileNavigation()
36
- const ToggleIcon = isOpen ? XMarkIcon : Bars3Icon;
37
-
38
- return (
39
- <IsInsideMobileNavigationContext.Provider value={true}>
40
- <Sheet open={isOpen} onOpenChange={(status) => {
41
- if (!status) {
42
- close();
43
- }
44
- }}>
45
- <Button
46
- variant="outline"
47
- size="icon"
48
- className="relative flex size-6 lg:hidden p-4"
49
- aria-label="Toggle navigation"
50
- onClick={open}
51
- >
52
- <ToggleIcon className="w-8 stroke-zinc-900 dark:stroke-white" />
53
- </Button>
54
- {!isInsideMobileNavigation && (
55
- <Suspense fallback={null}>
56
- <SheetContent side="left" className="w-full sm:max-w-sm p-8 overflow-y-auto flex flex-col justify-between">
57
- <Navigation />
58
- </SheetContent>
59
- </Suspense>
60
- )}
61
- </Sheet>
62
- </IsInsideMobileNavigationContext.Provider>
63
- )
64
- }
@@ -1,74 +0,0 @@
1
- import { ArrowRightIcon } from "@heroicons/react/24/outline";
2
- import classNames from "classnames";
3
- import { ALL_NAVIGATION } from "../components/store";
4
- import { usePathname } from "../components/hooks";
5
-
6
- function PageLink({
7
- title,
8
- href,
9
- dir = 'next',
10
- ...props
11
- }: Omit<React.ComponentPropsWithoutRef<'div'>, 'dir' | 'title'> & {
12
- title: string
13
- href: string
14
- dir?: 'previous' | 'next'
15
- }) {
16
- return (
17
- <div {...props}>
18
- <p className="font-display text-sm font-medium">
19
- {dir === 'next' ? 'Next' : 'Previous'}
20
- </p>
21
- <div className="mt-1">
22
- <a href={href} className={classNames('flex items-center gap-x-1 text-base font-semibold hover:opacity-80', {
23
- 'flex-row-reverse': dir === 'previous',
24
- },
25
- )}>
26
- <p className={classNames("flex items-center gap-x-1 text-base font-semibold hover:opacity-80", {
27
- "flex-row-reverse": dir === "previous"
28
- })}>
29
- {title}
30
- <ArrowRightIcon
31
- className={classNames(
32
- 'h-4 w-4 flex-none fill-current',
33
- {
34
- 'rotate-180': dir === 'previous',
35
- },
36
- )}
37
- />
38
- </p>
39
- </a>
40
- </div>
41
- </div>
42
- )
43
- }
44
- export function PrevNextLinks() {
45
- const pathname = usePathname();
46
- const allLinks = ALL_NAVIGATION.flatMap(tab =>
47
- tab.groups.flatMap(group =>
48
- group.pages.map(page => page.href)
49
- )
50
- );
51
- const linkIndex = allLinks.findIndex(link => link === pathname);
52
- const previousPage = linkIndex > -1 ? allLinks[linkIndex - 1] : null;
53
- const nextPage = linkIndex > -1 ? allLinks[linkIndex + 1] : null;
54
-
55
- const previousPageTitle = previousPage ? ALL_NAVIGATION
56
- .flatMap(tab => tab.groups)
57
- .flatMap(group => group.pages)
58
- .find(page => page.href === previousPage)?.title : null;
59
- const nextPageTitle = nextPage ? ALL_NAVIGATION
60
- .flatMap(tab => tab.groups)
61
- .flatMap(group => group.pages)
62
- .find(page => page.href === nextPage)?.title : null;
63
-
64
- if (!nextPage && !previousPage) {
65
- return null;
66
- }
67
-
68
- return (
69
- <div className="mt-12 pt-6 flex border-t border-black/20 dark:border-white/20">
70
- {previousPage && <PageLink dir="previous" title={previousPageTitle ?? ''} href={previousPage} />}
71
- {nextPage && <PageLink className="ml-auto text-right" title={nextPageTitle ?? ''} href={nextPage} />}
72
- </div>
73
- )
74
- }
@@ -1,166 +0,0 @@
1
- import { useCallback, useEffect, useState } from 'react'
2
- import classNames from 'classnames'
3
-
4
- export type Section = {
5
- id: string
6
- title: string
7
- children: Array<Subsection>
8
- }
9
-
10
- export type Subsection = {
11
- id: string
12
- title: string
13
- }
14
-
15
- export function TableOfContents() {
16
- const [currentSection, setCurrentSection] = useState<string>('')
17
- const [sections, setSections] = useState<Section[]>([])
18
- const [isContentLoaded, setIsContentLoaded] = useState(false)
19
-
20
- const collectHeadings = useCallback(() => {
21
- const article = document.querySelector('article')
22
- if (!article) return
23
-
24
- // Wait for content to be loaded
25
- const observer = new MutationObserver(() => {
26
- const headings = article.querySelectorAll('h2:not([style*="display: none"]), h3:not([style*="display: none"])')
27
- const sections: Section[] = []
28
- let currentSection: Section | null = null
29
-
30
- headings.forEach((heading) => {
31
- // Check if heading is visible
32
- const style = window.getComputedStyle(heading)
33
- if (style.display === 'none' || style.visibility === 'hidden') return
34
-
35
- const id = heading.id || heading.textContent?.toLowerCase().replace(/\s+/g, '-') || ''
36
- heading.id = id
37
-
38
- if (heading.tagName === 'H2') {
39
- currentSection = {
40
- id,
41
- title: heading.textContent || '',
42
- children: []
43
- }
44
- sections.push(currentSection)
45
- } else if (heading.tagName === 'H3' && currentSection) {
46
- currentSection.children.push({
47
- id,
48
- title: heading.textContent || ''
49
- })
50
- }
51
- })
52
-
53
- setSections(sections)
54
- setIsContentLoaded(true)
55
- })
56
-
57
- observer.observe(article, {
58
- childList: true,
59
- subtree: true,
60
- attributes: true,
61
- attributeFilter: ['style', 'class']
62
- })
63
-
64
- return () => observer.disconnect()
65
- }, [])
66
-
67
- useEffect(() => {
68
- const cleanup = collectHeadings()
69
- return () => cleanup?.()
70
- }, [collectHeadings])
71
-
72
- const getHeadings = useCallback(() => {
73
- return sections
74
- .flatMap((section) => [section.id, ...section.children.map((child) => child.id)])
75
- .map((id) => {
76
- const el = document.getElementById(id)
77
- if (!el) return null
78
- const top = window.scrollY + el.getBoundingClientRect().top
79
- return { id, top }
80
- })
81
- .filter((x): x is { id: string; top: number } => x !== null)
82
- }, [sections])
83
-
84
- useEffect(() => {
85
- if (!isContentLoaded || sections.length === 0) return
86
- const headings = getHeadings()
87
-
88
- function onScroll() {
89
- const top = window.scrollY
90
- let current = headings[0].id
91
- for (const heading of headings) {
92
- if (top >= heading.top - 10) {
93
- current = heading.id
94
- } else {
95
- break
96
- }
97
- }
98
- setCurrentSection(current)
99
- }
100
-
101
- window.addEventListener('scroll', onScroll, { passive: true })
102
- onScroll()
103
- return () => {
104
- window.removeEventListener('scroll', onScroll)
105
- }
106
- }, [getHeadings, sections, isContentLoaded])
107
-
108
- function isActive(section: Section | Subsection) {
109
- return section.id === currentSection
110
- }
111
-
112
- if (!isContentLoaded) {
113
- return null
114
- }
115
-
116
- return (
117
- <div className="hidden xl:sticky xl:top-[4.75rem] xl:-mr-6 xl:block xl:h-[calc(100vh-4.75rem)] xl:flex-none xl:overflow-y-auto xl:py-16 xl:pr-6 pl-8">
118
- <nav aria-labelledby="on-this-page-title" className="w-56">
119
- {sections.length > 0 && (
120
- <>
121
- <h2
122
- id="on-this-page-title"
123
- className="font-display text-sm font-medium text-slate-900 dark:text-white"
124
- >
125
- On this page
126
- </h2>
127
- <ol role="list" className="mt-4 space-y-3 text-sm">
128
- {sections.map((section) => (
129
- <li key={section.id}>
130
- <h3>
131
- <a
132
- href={`#${section.id}`}
133
- className={classNames({
134
- "text-brand-foreground": isActive(section),
135
- "font-normal text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-300": !isActive(section),
136
- })}>
137
- {section.title}
138
- </a>
139
- </h3>
140
- {section.children.length > 0 && (
141
- <ol role="list" className="mt-2 space-y-3 pl-5 text-slate-500 dark:text-slate-400">
142
- {section.children.map((subSection) => (
143
- <li key={subSection.id}>
144
- <a
145
- href={`#${subSection.id}`}
146
- className={
147
- isActive(subSection)
148
- ? 'text-brand-foreground'
149
- : 'hover:text-slate-600 dark:hover:text-slate-300'
150
- }
151
- >
152
- {subSection.title}
153
- </a>
154
- </li>
155
- ))}
156
- </ol>
157
- )}
158
- </li>
159
- ))}
160
- </ol>
161
- </>
162
- )}
163
- </nav>
164
- </div>
165
- )
166
- }
@@ -1,54 +0,0 @@
1
- import docsConfig from '../../docs/dory.json' with { type: 'json' };
2
- import type { DoryConfig } from '../types/config';
3
-
4
- const config = docsConfig as DoryConfig;
5
-
6
- /**
7
- * Converts hex color to RGB values for CSS variable usage
8
- */
9
- function hexToRgb(hex: string): string {
10
- // Remove # if present
11
- const cleanHex = hex.replace('#', '');
12
-
13
- // Parse hex values
14
- const r = parseInt(cleanHex.substring(0, 2), 16);
15
- const g = parseInt(cleanHex.substring(2, 4), 16);
16
- const b = parseInt(cleanHex.substring(4, 6), 16);
17
-
18
- return `${r} ${g} ${b}`;
19
- }
20
-
21
- /**
22
- * Load and apply brand colors from dory.json configuration
23
- * Sets CSS variables for use throughout the application
24
- */
25
- export function loadColors() {
26
- const { colors } = config;
27
- if (!colors) return;
28
-
29
- // Set CSS variables on the root element for both light and dark modes
30
- const root = document.documentElement;
31
-
32
- // Set primary color (used in both light and dark mode)
33
- if (colors.primary) {
34
- root.style.setProperty('--brand-primary', colors.primary);
35
- root.style.setProperty('--brand-primary-rgb', hexToRgb(colors.primary));
36
- }
37
-
38
- // Set light mode brand color
39
- if (colors.light) {
40
- root.style.setProperty('--brand-light', colors.light);
41
- root.style.setProperty('--brand-light-rgb', hexToRgb(colors.light));
42
- }
43
-
44
- // Set dark mode brand color
45
- if (colors.dark) {
46
- root.style.setProperty('--brand-dark', colors.dark);
47
- root.style.setProperty('--brand-dark-rgb', hexToRgb(colors.dark));
48
- }
49
-
50
- // Set the legacy variable for backward compatibility
51
- if (colors.primary) {
52
- root.style.setProperty('--brand-foreground', colors.primary);
53
- }
54
- }
@@ -1,23 +0,0 @@
1
- import docsConfig from '../../docs/dory.json' with { type: 'json' };
2
- import type { DoryConfig } from '../types/config';
3
-
4
- const config = docsConfig as DoryConfig;
5
-
6
- export function loadFonts() {
7
- const { fonts } = config;
8
- if (!fonts) return;
9
-
10
- // Create a style element for the font face
11
- const style = document.createElement('style');
12
- style.textContent = `
13
- @font-face {
14
- font-family: '${fonts.family}';
15
- src: url('${fonts.source}') format('${fonts.format}');
16
- font-display: swap;
17
- }
18
- `;
19
- document.head.appendChild(style);
20
-
21
- // Apply the font family to the root element
22
- document.documentElement.style.fontFamily = fonts.family;
23
- }
@@ -1,12 +0,0 @@
1
- export function slugifyWithCounter() {
2
- const counter = new Map<string, number>();
3
- return (text: string) => {
4
- const count = counter.get(text) ?? 0;
5
- counter.set(text, count + 1);
6
- return count === 0 ? text : `${text}-${count}`;
7
- }
8
- }
9
-
10
- export function toTitleCase(text: string) {
11
- return text.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
12
- }
package/src/vite-env.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
package/tsconfig.app.json DELETED
@@ -1,33 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
- "target": "ES2020",
5
- "useDefineForClassFields": true,
6
- "module": "ESNext",
7
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
- "skipLibCheck": true,
9
- "paths": {
10
- "react": ["./node_modules/preact/compat/"],
11
- "react-dom": ["./node_modules/preact/compat/"]
12
- },
13
-
14
- /* Bundler mode */
15
- "moduleResolution": "bundler",
16
- "allowImportingTsExtensions": true,
17
- "verbatimModuleSyntax": true,
18
- "moduleDetection": "force",
19
- "noEmit": true,
20
- "jsx": "react-jsx",
21
- "jsxImportSource": "preact",
22
-
23
- /* Linting */
24
- "strict": true,
25
- "noUnusedLocals": true,
26
- "noUnusedParameters": true,
27
- "erasableSyntaxOnly": true,
28
- "noFallthroughCasesInSwitch": true,
29
- "noUncheckedSideEffectImports": true
30
- },
31
- "include": ["src"],
32
- "exclude": ["src/plugins"]
33
- }
package/tsconfig.bin.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2023"],
5
- "module": "ESNext",
6
- "moduleResolution": "node",
7
- "skipLibCheck": true,
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "allowSyntheticDefaultImports": true,
11
- "noEmit": false,
12
- "outDir": "./bin/dist",
13
- "rootDir": "./bin",
14
- "declaration": true,
15
- "declarationMap": true,
16
- "sourceMap": true
17
- },
18
- "include": [
19
- "bin/**/*.ts"
20
- ],
21
- "exclude": [
22
- "bin/dist"
23
- ]
24
- }
package/tsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.app.json" },
5
- { "path": "./tsconfig.node.json" }
6
- ]
7
- }
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
- "target": "ES2022",
5
- "lib": ["ES2023"],
6
- "module": "ESNext",
7
- "skipLibCheck": true,
8
- "types": ["node"],
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "verbatimModuleSyntax": true,
14
- "moduleDetection": "force",
15
- "noEmit": true,
16
-
17
- /* Linting */
18
- "strict": true,
19
- "noUnusedLocals": true,
20
- "noUnusedParameters": true,
21
- "erasableSyntaxOnly": true,
22
- "noFallthroughCasesInSwitch": true,
23
- "noUncheckedSideEffectImports": true
24
- },
25
- "include": ["vite.config.ts", "src/plugins/**/*.ts", "bin/**/*.ts"]
26
- }