vocs 2.1.12 → 2.2.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.
Files changed (76) hide show
  1. package/dist/internal/config.d.ts +246 -9
  2. package/dist/internal/config.d.ts.map +1 -1
  3. package/dist/internal/config.js +38 -9
  4. package/dist/internal/config.js.map +1 -1
  5. package/dist/internal/llms.d.ts.map +1 -1
  6. package/dist/internal/llms.js +5 -1
  7. package/dist/internal/llms.js.map +1 -1
  8. package/dist/internal/markdown-imports.d.ts +2 -0
  9. package/dist/internal/markdown-imports.d.ts.map +1 -0
  10. package/dist/internal/markdown-imports.js +103 -0
  11. package/dist/internal/markdown-imports.js.map +1 -0
  12. package/dist/internal/openapi/parser.d.ts +7 -1
  13. package/dist/internal/openapi/parser.d.ts.map +1 -1
  14. package/dist/internal/openapi/parser.js +30 -2
  15. package/dist/internal/openapi/parser.js.map +1 -1
  16. package/dist/internal/openapi/sidebar.d.ts.map +1 -1
  17. package/dist/internal/openapi/sidebar.js +8 -1
  18. package/dist/internal/openapi/sidebar.js.map +1 -1
  19. package/dist/internal/search.client.d.ts +6 -0
  20. package/dist/internal/search.client.d.ts.map +1 -1
  21. package/dist/internal/search.client.js +23 -0
  22. package/dist/internal/search.client.js.map +1 -1
  23. package/dist/internal/search.d.ts +2 -1
  24. package/dist/internal/search.d.ts.map +1 -1
  25. package/dist/internal/search.js +10 -14
  26. package/dist/internal/search.js.map +1 -1
  27. package/dist/internal/sidebar.d.ts +8 -2
  28. package/dist/internal/sidebar.d.ts.map +1 -1
  29. package/dist/internal/sidebar.js.map +1 -1
  30. package/dist/internal/vite-plugins.js +1 -1
  31. package/dist/internal/vite-plugins.js.map +1 -1
  32. package/dist/react/Link.d.ts.map +1 -1
  33. package/dist/react/Link.js +11 -6
  34. package/dist/react/Link.js.map +1 -1
  35. package/dist/react/internal/Outline.d.ts.map +1 -1
  36. package/dist/react/internal/Outline.js +1 -1
  37. package/dist/react/internal/Outline.js.map +1 -1
  38. package/dist/react/internal/Search.d.ts.map +1 -1
  39. package/dist/react/internal/Search.js +5 -7
  40. package/dist/react/internal/Search.js.map +1 -1
  41. package/dist/react/internal/Sidebar.d.ts.map +1 -1
  42. package/dist/react/internal/Sidebar.js +10 -3
  43. package/dist/react/internal/Sidebar.js.map +1 -1
  44. package/dist/react/internal/TwoslashHover.client.d.ts.map +1 -1
  45. package/dist/react/internal/TwoslashHover.client.js +4 -1
  46. package/dist/react/internal/TwoslashHover.client.js.map +1 -1
  47. package/dist/react/internal/openapi/Operation.d.ts.map +1 -1
  48. package/dist/react/internal/openapi/Operation.js +4 -2
  49. package/dist/react/internal/openapi/Operation.js.map +1 -1
  50. package/dist/server/openapi/assets.generated.js +4 -4
  51. package/dist/server/openapi/assets.generated.js.map +1 -1
  52. package/dist/styles/openapi.css +11 -0
  53. package/dist/styles/twoslash.css +1 -1
  54. package/package.json +1 -1
  55. package/src/internal/config.ts +294 -21
  56. package/src/internal/llms.test.ts +35 -0
  57. package/src/internal/llms.ts +6 -1
  58. package/src/internal/markdown-imports.ts +154 -0
  59. package/src/internal/openapi/parser.test.ts +39 -0
  60. package/src/internal/openapi/parser.ts +48 -3
  61. package/src/internal/openapi/sidebar.test.ts +31 -0
  62. package/src/internal/openapi/sidebar.ts +10 -1
  63. package/src/internal/search.client.ts +29 -0
  64. package/src/internal/search.test.ts +195 -0
  65. package/src/internal/search.ts +14 -14
  66. package/src/internal/sidebar.ts +8 -2
  67. package/src/internal/vite-plugins.ts +1 -1
  68. package/src/react/Link.tsx +12 -7
  69. package/src/react/internal/Outline.tsx +4 -1
  70. package/src/react/internal/Search.tsx +7 -10
  71. package/src/react/internal/Sidebar.tsx +17 -2
  72. package/src/react/internal/TwoslashHover.client.tsx +3 -0
  73. package/src/react/internal/openapi/Operation.tsx +4 -1
  74. package/src/server/openapi/assets.generated.ts +4 -4
  75. package/src/styles/openapi.css +11 -0
  76. package/src/styles/twoslash.css +1 -1
@@ -636,7 +636,7 @@ export function search(config: Config.Config): PluginOption {
636
636
  async function buildIndex(): Promise<SearchIndex.SearchIndex> {
637
637
  logger.info('Building search index...', { timestamp: true })
638
638
  const docs = await SearchDocuments.fromConfig(config)
639
- const index = SearchIndex.fromSearchDocuments(docs)
639
+ const index = SearchIndex.fromSearchDocuments(docs, config)
640
640
 
641
641
  // Populate fileIds map for HMR
642
642
  for (const doc of docs) {
@@ -1,7 +1,8 @@
1
1
  'use client'
2
2
 
3
- import { useEffect, useState } from 'react'
4
- import { useRouter, Link as WakuLink } from 'waku'
3
+ import { useContext, useEffect, useState } from 'react'
4
+ import { Link as WakuLink } from 'waku'
5
+ import { unstable_RouterContext as WakuRouterContext } from 'waku/router/client'
5
6
  import * as Path from '../internal/path.js'
6
7
 
7
8
  const viewportPrefetchDelayMs = 2_000
@@ -57,14 +58,18 @@ function useViewportPrefetchReady(enabled: boolean) {
57
58
 
58
59
  export function Link(props: Link.Props) {
59
60
  const { to, unstable_prefetchOnEnter = true, unstable_prefetchOnView = true, ...rest } = props
60
- const { path } = useRouter()
61
- const prefetchOnView = useViewportPrefetchReady(Boolean(unstable_prefetchOnView))
61
+ const router = useContext(WakuRouterContext)
62
+ const routerPath = router?.route.path
63
+ const isExternal = Path.isExternal(props.to)
64
+ const prefetchOnView = useViewportPrefetchReady(
65
+ Boolean(unstable_prefetchOnView) && !isExternal && routerPath !== undefined,
66
+ )
62
67
 
63
- if (Path.isExternal(props.to))
64
- return <a {...rest} href={props.to} rel="noopener noreferrer" target="_blank" />
68
+ if (isExternal) return <a {...rest} href={props.to} rel="noopener noreferrer" target="_blank" />
65
69
 
66
70
  const [before, after] = (props.to || '').split('#')
67
- const resolvedTo = `${before ? before : path}${after ? `#${after}` : ''}`
71
+ const resolvedTo = `${before ? before : (routerPath ?? '')}${after ? `#${after}` : ''}`
72
+ if (routerPath === undefined) return <a {...rest} href={resolvedTo || props.to} />
68
73
  return (
69
74
  <WakuLink
70
75
  {...rest}
@@ -26,7 +26,10 @@ function useOutlineItems(options: { minLevel: number; maxLevel: number }) {
26
26
  const scanHeadings = () => {
27
27
  const headingElements = Array.from(
28
28
  document.querySelectorAll('article[data-v-content] :is(h2, h3, h4, h5, h6)[id]'),
29
- )
29
+ // Changelog release bodies render as nested `[data-v-content]` inside the
30
+ // main article; their headings have their own `Versions` outline, so keep
31
+ // them out of the page outline (otherwise they flood/leak into it).
32
+ ).filter((element) => !element.closest('[data-v-changelog]'))
30
33
  const newItems = headingElements
31
34
  .map((element) => {
32
35
  const level = Number.parseInt(element.tagName[1] ?? '0', 10)
@@ -11,7 +11,7 @@ import LucideFile from '~icons/lucide/file'
11
11
  import LucideHash from '~icons/lucide/hash'
12
12
  import LucideSearch from '~icons/lucide/search'
13
13
  import * as Path from '../../internal/path.js'
14
- import { searchFields, storeFields, tokenize } from '../../internal/search.client.js'
14
+ import { SearchConfig } from '../../internal/search.client.js'
15
15
  import { Link } from '../Link.js'
16
16
  import { useConfig } from '../useConfig.js'
17
17
  import { DialogTrigger } from './DialogTrigger.js'
@@ -86,14 +86,12 @@ export function Search(props: Search.Props) {
86
86
  const json = await getSearchIndex()
87
87
  setIndex(
88
88
  MiniSearch.loadJSON<SearchResult>(json, {
89
- fields: [...searchFields],
90
- storeFields: [...storeFields],
91
- tokenize,
89
+ ...SearchConfig.getIndexOptions(config),
92
90
  }),
93
91
  )
94
92
  })
95
93
  .catch((error) => console.error('Failed to load search index:', error))
96
- }, [open, index])
94
+ }, [open, index, config])
97
95
 
98
96
  React.useEffect(() => {
99
97
  try {
@@ -108,12 +106,11 @@ export function Search(props: Search.Props) {
108
106
  return
109
107
  }
110
108
 
111
- const results = (index.search(query, { ...config.search, tokenize }) as SearchResult[]).slice(
112
- 0,
113
- 20,
114
- )
109
+ const results = (
110
+ index.search(query, SearchConfig.getQueryOptions(config)) as SearchResult[]
111
+ ).slice(0, 20)
115
112
  setSearch((s) => ({ ...s, results, selectedIndex: 0 }))
116
- }, [query, index, config.search])
113
+ }, [query, index, config])
117
114
 
118
115
  React.useEffect(() => {
119
116
  if (disableKeyboardShortcut) return
@@ -86,7 +86,12 @@ function useActiveAnchor(enabled: boolean, path: string): string | null {
86
86
 
87
87
  const observeAll = () => {
88
88
  observer.disconnect()
89
- for (const element of document.querySelectorAll(selector)) observer.observe(element)
89
+ for (const element of document.querySelectorAll(selector)) {
90
+ // Skip changelog release-body headings — they have no sidebar entry and
91
+ // would hijack the active section as you scroll through the changelog.
92
+ if (element.closest('[data-v-changelog]')) continue
93
+ observer.observe(element)
94
+ }
90
95
  }
91
96
  observeAll()
92
97
 
@@ -169,13 +174,23 @@ export declare namespace Sidebar {
169
174
 
170
175
  /** @internal */
171
176
  function ItemBadge(props: { badge: Sidebar_core.SidebarItemBadge }) {
172
- const badge = typeof props.badge === 'string' ? { text: props.badge } : props.badge
177
+ const badge =
178
+ typeof props.badge === 'string' ? { text: props.badge, icon: undefined } : props.badge
173
179
  return (
174
180
  <Badge
175
181
  className="vocs:shrink-0 vocs:ml-2"
176
182
  data-v-sidebar-item-badge
183
+ data-v-icon={badge.icon ? '' : undefined}
177
184
  variant={badge.variant ?? 'info'}
178
185
  >
186
+ {badge.icon && (
187
+ <span
188
+ aria-hidden
189
+ data-v-sidebar-item-badge-icon
190
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: server-resolved SVG markup
191
+ dangerouslySetInnerHTML={{ __html: badge.icon }}
192
+ />
193
+ )}
179
194
  {badge.text}
180
195
  </Badge>
181
196
  )
@@ -69,6 +69,9 @@ export function TwoslashHover(props: TwoslashHover.Props) {
69
69
  side="bottom"
70
70
  sideOffset={4}
71
71
  collisionAvoidance={{ side: 'none' }}
72
+ // Portaled to `body`; needs z-index or `minimal`/`blank` `[data-v-main]`
73
+ // (z-index: 10) covers it. The popup class `z-50` is inert here.
74
+ style={{ zIndex: 50 }}
72
75
  >
73
76
  <Popover.Popup className={className} initialFocus={false}>
74
77
  <Popover.Arrow className="vocs:data-[side=bottom]:top-[-8px] vocs:data-[side=left]:right-[-13px] vocs:data-[side=left]:rotate-90 vocs:data-[side=right]:left-[-13px] vocs:data-[side=right]:-rotate-90 vocs:data-[side=top]:bottom-[-8px] vocs:data-[side=top]:rotate-180">
@@ -48,7 +48,9 @@ export function Operation(props: Operation.Props) {
48
48
  const title = operation.summary || `${operation.method} ${operation.path}`
49
49
  const Heading = `h${headingLevel}` as 'h2' | 'h3'
50
50
 
51
- const samples = codeSamples(operation, server, { hideQueryParams })
51
+ // Webhooks are inbound deliveries to the consumer's URL, not callable
52
+ // endpoints — so skip the "Try" client and the request code samples.
53
+ const samples = operation.isWebhook ? [] : codeSamples(operation, server, { hideQueryParams })
52
54
  const responses = responseSamples(operation)
53
55
 
54
56
  return (
@@ -65,6 +67,7 @@ export function Operation(props: Operation.Props) {
65
67
  <HeadingAnchor id={operation.id} />
66
68
  </Heading>
67
69
  <div data-v-openapi-endpoint>
70
+ {operation.isWebhook && <Badge variant="note">Webhook</Badge>}
68
71
  <Badge variant={methodVariant(operation.method)}>{operation.method}</Badge>
69
72
  <code data-v-openapi-endpoint-path>{operation.path}</code>
70
73
  </div>