@writedocs/generator 0.1.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/LICENSE +15 -0
  2. package/README.md +17 -0
  3. package/astro.config.mjs +419 -0
  4. package/bin/writedocs.js +73 -0
  5. package/package.json +79 -0
  6. package/src/assets/wd_watermark.png +0 -0
  7. package/src/assets/wd_watermark_dark.png +0 -0
  8. package/src/cli/build-auth.js +53 -0
  9. package/src/cli/build.js +40 -0
  10. package/src/cli/dev.js +12 -0
  11. package/src/cli/generate-api-pages.js +359 -0
  12. package/src/cli/init.js +81 -0
  13. package/src/cli/preflight.js +40 -0
  14. package/src/cli/run-astro.js +57 -0
  15. package/src/cli/run-pagefind.js +66 -0
  16. package/src/cli/write-redirects-file.js +80 -0
  17. package/src/components/Accordion.astro +164 -0
  18. package/src/components/AccordionGroup.astro +40 -0
  19. package/src/components/ApiLangSelect.astro +168 -0
  20. package/src/components/ApiPlayground.astro +281 -0
  21. package/src/components/ApiReferencePanel.astro +1754 -0
  22. package/src/components/ApiSchemaField.astro +54 -0
  23. package/src/components/AppIcon.astro +32 -0
  24. package/src/components/Badge.astro +128 -0
  25. package/src/components/Callout.astro +168 -0
  26. package/src/components/Card.astro +136 -0
  27. package/src/components/CardGroup.astro +20 -0
  28. package/src/components/CodeGroup.astro +184 -0
  29. package/src/components/CopyPageMenu.astro +246 -0
  30. package/src/components/Danger.astro +12 -0
  31. package/src/components/Expandable.astro +126 -0
  32. package/src/components/Frame.astro +102 -0
  33. package/src/components/Hint.astro +99 -0
  34. package/src/components/Icon.astro +70 -0
  35. package/src/components/Image.astro +147 -0
  36. package/src/components/Info.astro +12 -0
  37. package/src/components/Note.astro +12 -0
  38. package/src/components/Parameter.astro +119 -0
  39. package/src/components/RequestExample.astro +33 -0
  40. package/src/components/ResponseExample.astro +19 -0
  41. package/src/components/Searchbar.astro +117 -0
  42. package/src/components/Step.astro +10 -0
  43. package/src/components/Steps.astro +32 -0
  44. package/src/components/Tab.astro +9 -0
  45. package/src/components/Tabs.astro +52 -0
  46. package/src/components/Tip.astro +12 -0
  47. package/src/components/Video.astro +135 -0
  48. package/src/components/Warning.astro +12 -0
  49. package/src/components/index.ts +48 -0
  50. package/src/content.config.ts +223 -0
  51. package/src/layout/BaseLayout.astro +750 -0
  52. package/src/layout/components/AnalyticsScripts.astro +77 -0
  53. package/src/layout/components/AskAiWidget.astro +37 -0
  54. package/src/layout/components/Breadcrumbs.astro +97 -0
  55. package/src/layout/components/ImageZoom.astro +19 -0
  56. package/src/layout/components/MobileMenu.astro +200 -0
  57. package/src/layout/components/NavTree.astro +351 -0
  58. package/src/layout/components/SearchModal.astro +42 -0
  59. package/src/layout/components/Sidebar.astro +122 -0
  60. package/src/layout/components/SiteFooter.astro +85 -0
  61. package/src/layout/components/TableOfContents.astro +117 -0
  62. package/src/layout/components/TopBar.astro +311 -0
  63. package/src/layout/styles/banner.css +44 -0
  64. package/src/layout/styles/base.css +234 -0
  65. package/src/layout/styles/dropdown.css +133 -0
  66. package/src/layout/styles/footer.css +108 -0
  67. package/src/layout/styles/image-zoom.css +50 -0
  68. package/src/layout/styles/mobile-menu.css +258 -0
  69. package/src/layout/styles/search-modal.css +122 -0
  70. package/src/layout/styles/topbar.css +437 -0
  71. package/src/lib/config.ts +2131 -0
  72. package/src/lib/mdx-auto-hydrate.js +70 -0
  73. package/src/lib/mdx-inject-builtins.js +87 -0
  74. package/src/lib/mdx-substitute-variables.js +66 -0
  75. package/src/lib/mdx-title-anchor-ids.js +84 -0
  76. package/src/lib/mermaid-rehype.js +72 -0
  77. package/src/lib/openapi-render.ts +479 -0
  78. package/src/lib/shiki-code-block.js +102 -0
  79. package/src/lib/shiki-copy-button.js +45 -0
  80. package/src/lib/styles-asset-integration.js +210 -0
  81. package/src/lib/writedocs-temp-dir.js +93 -0
  82. package/src/pages/404.astro +62 -0
  83. package/src/pages/[...slug].astro +1270 -0
  84. package/src/pages/[...slug].md.ts +78 -0
  85. package/src/pages/llms-full.txt.ts +71 -0
  86. package/src/pages/llms.txt.ts +141 -0
  87. package/src/scripts/banner.ts +20 -0
  88. package/src/scripts/dropdowns.ts +61 -0
  89. package/src/scripts/image-zoom.ts +66 -0
  90. package/src/scripts/mobile-menu.ts +55 -0
  91. package/src/scripts/search.ts +155 -0
  92. package/src/scripts/sidebar-scroll.ts +65 -0
  93. package/src/scripts/theme-toggle.ts +35 -0
  94. package/src/scripts/topbar-offset.ts +141 -0
  95. package/src/styles/global.css +18 -0
@@ -0,0 +1,258 @@
1
+ /* MobileMenu.astro's own styling - the <= 860px drawer panel itself (not
2
+ the hamburger toggle button that opens it, which lives in topbar.css
3
+ alongside the rest of TopBar.astro's own markup). */
4
+
5
+ .wd-mobile-menu { display: none; }
6
+ @media (max-width: 860px) {
7
+ .wd-mobile-menu {
8
+ display: block;
9
+ /* Always laid out (positioned off-screen via the panel's own
10
+ transform below), not display:none, so .open can transition
11
+ smoothly instead of snapping - a transition can't animate *out of*
12
+ display:none. visibility is what keeps it non-visible/out of the
13
+ tab order while closed (visibility: hidden also removes descendants
14
+ from hit-testing and the accessibility tree); initMobileMenu()
15
+ (src/scripts/mobile-menu.ts) toggles the `inert` attribute
16
+ alongside .open as a second, JS-driven layer of the same
17
+ guarantee, since not every browser/AT combination is guaranteed to
18
+ treat visibility:hidden identically. pointer-events is deliberately
19
+ NOT toggled here on the container itself - see the comment below
20
+ for why: this element's own box spans the *entire* viewport
21
+ (position: fixed; inset: 0), so giving *it* pointer-events: auto
22
+ would make its empty top strip (behind the topbar) swallow clicks
23
+ meant for the topbar underneath, even though nothing of this
24
+ element's own visible content is painted there. */
25
+ visibility: hidden;
26
+ }
27
+ .wd-mobile-menu.open {
28
+ visibility: visible;
29
+ }
30
+ }
31
+ .wd-mobile-menu {
32
+ position: fixed;
33
+ inset: 0;
34
+ z-index: 40;
35
+ /* Never toggled: this box covers the full viewport (inset: 0). If this
36
+ were pointer-events: auto while open, its own box would be a valid
37
+ hit target everywhere within it (an element with no background is
38
+ not "invisible" to hit-testing - only pointer-events: none makes it
39
+ click-through), and being a higher z-index than the topbar, would
40
+ swallow clicks meant for whatever's underneath. Interactivity is
41
+ granted instead to the backdrop and panel individually below. */
42
+ pointer-events: none;
43
+ }
44
+ .wd-mobile-menu-backdrop,
45
+ .wd-mobile-menu-panel {
46
+ pointer-events: none;
47
+ }
48
+ .wd-mobile-menu.open .wd-mobile-menu-backdrop,
49
+ .wd-mobile-menu.open .wd-mobile-menu-panel {
50
+ pointer-events: auto;
51
+ }
52
+ .wd-mobile-menu-backdrop {
53
+ position: absolute;
54
+ /* Full viewport (top: 0, not 5rem) - the panel itself also reaches
55
+ top: 0 with its own header (brand/close/theme, see
56
+ .wd-mobile-menu-header below) replicating the real topbar's row, so
57
+ there's nothing under the backdrop still worth keeping
58
+ un-dimmed/interactive: the real topbar is either fully covered by the
59
+ panel's own opaque background (its width) or genuinely just dimmed
60
+ decoration past it. */
61
+ inset: 0;
62
+ background: rgba(0, 0, 0, 0.4);
63
+ opacity: 0;
64
+ transition: opacity 0.25s ease;
65
+ }
66
+ .wd-mobile-menu.open .wd-mobile-menu-backdrop {
67
+ opacity: 1;
68
+ }
69
+ /* A left-anchored drawer (Mintlify's own mobile nav - the reference this
70
+ was built against - works the same way), not a centered/inset floating
71
+ card: flush to the screen's left edge, full viewport height top to
72
+ bottom (top: 0, not just below the topbar - see .wd-mobile-menu-header
73
+ below for why), sliding in from off-screen rather than just appearing. */
74
+ .wd-mobile-menu-panel {
75
+ position: absolute;
76
+ inset: 0 auto 0 0;
77
+ width: min(88vw, 340px);
78
+ display: flex;
79
+ flex-direction: column;
80
+ /* Same --wd-navbar-background as .wd-topbar (topbar.css) - this panel's
81
+ own header row replicates the real topbar's brand row (see the
82
+ comment on .wd-mobile-menu-header below), so it should share its
83
+ background too rather than looking like a separate, differently-
84
+ colored surface once a site configures theme.colors.navbar. */
85
+ background: var(--wd-navbar-background);
86
+ border-right: 1px solid var(--wd-border);
87
+ box-shadow: 8px 0 24px rgba(0, 0, 0, 0.15);
88
+ transform: translateX(-100%);
89
+ transition: transform 0.25s ease;
90
+ }
91
+ .wd-mobile-menu.open .wd-mobile-menu-panel {
92
+ transform: translateX(0);
93
+ }
94
+ /* Replicates the real topbar's brand row - same left-to-right order
95
+ (close-toggle, brand, theme) - as a fixed header pinned to the top of
96
+ the panel, so it reads as one continuous navbar with the real one
97
+ underneath rather than a separate piece with a seam. `flex-shrink: 0`
98
+ keeps it pinned above .wd-mobile-menu-scroll's own independent
99
+ scrolling below. .wd-topbar-brand and .wd-theme-toggle themselves are
100
+ defined in topbar.css, imported by this component too - see this
101
+ file's own top comment. */
102
+ .wd-mobile-menu-header {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 0.5rem;
106
+ flex-shrink: 0;
107
+ padding: 0.75rem 1rem;
108
+ border-bottom: 1px solid var(--wd-border);
109
+ }
110
+ .wd-mobile-menu-header .wd-topbar-brand {
111
+ flex: 1;
112
+ min-width: 0;
113
+ }
114
+ .wd-mobile-menu-close {
115
+ display: flex;
116
+ align-items: center;
117
+ justify-content: center;
118
+ width: 2rem;
119
+ height: 2rem;
120
+ padding: 0;
121
+ border: none;
122
+ border-radius: 0.4rem;
123
+ background: none;
124
+ cursor: pointer;
125
+ /* --wd-navbar-foreground-muted, not --wd-text-muted - this button sits
126
+ on the panel's own --wd-navbar-background (see .wd-mobile-menu-panel
127
+ above), same reasoning as topbar.css's identical swap for its
128
+ desktop-row counterparts. Falls back to var(--wd-text-muted) when
129
+ theme.navbar has no `foreground` set, so this is a no-op unless a
130
+ site actually configures one. */
131
+ color: var(--wd-navbar-foreground-muted);
132
+ flex-shrink: 0;
133
+ }
134
+ .wd-mobile-menu-close:hover { color: var(--wd-navbar-foreground); background: var(--wd-surface); }
135
+ .wd-mobile-menu-scroll {
136
+ flex: 1;
137
+ min-height: 0;
138
+ overflow-y: auto;
139
+ padding: 1rem 0.75rem;
140
+ }
141
+ .wd-mobile-menu-selectors {
142
+ display: flex;
143
+ flex-direction: column;
144
+ gap: 0.5rem;
145
+ margin-bottom: 0.75rem;
146
+ padding-bottom: 0.75rem;
147
+ border-bottom: 1px solid var(--wd-border);
148
+ }
149
+ /* position: relative makes this the containing block for its own
150
+ .wd-mobile-accordion-options panel below, which floats over whatever
151
+ comes after it instead of pushing it down the page - a `<details>`'s
152
+ open content is normal, in-flow block content by default, which *would*
153
+ push later siblings down; taking the options panel out of flow via
154
+ position: absolute is what avoids that. The [open] z-index bump is what
155
+ then guarantees *this* accordion's floating panel paints above the
156
+ *later*, still-closed accordion rows below it: any position: relative
157
+ element - open or not - already paints above its plain in-flow siblings
158
+ regardless of z-index (per CSS's stacking rules), but two position:
159
+ relative siblings with no z-index of their own paint in DOM order, i.e.
160
+ a later closed row would otherwise sit on top of an earlier open one's
161
+ panel despite being visually "behind" it. */
162
+ .wd-mobile-accordion {
163
+ position: relative;
164
+ border: 1px solid var(--wd-border);
165
+ border-radius: 0.5rem;
166
+ }
167
+ .wd-mobile-accordion[open] {
168
+ z-index: 5;
169
+ }
170
+ /* --wd-navbar-foreground, not --wd-text: this row (and every other
171
+ selector row/link directly inside .wd-mobile-menu-scroll, down through
172
+ .wd-mobile-menu-link below) sits directly on .wd-mobile-menu-panel's own
173
+ --wd-navbar-background, same as the header above - only the *floating*
174
+ .wd-mobile-accordion-options-panel a click reveals (further down this
175
+ file) sits on the ordinary --wd-background instead, which is why that
176
+ one's own rules are deliberately left on --wd-text/--wd-primary,
177
+ unchanged. */
178
+ .wd-mobile-accordion-trigger {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 0.5rem;
182
+ padding: 0.65rem 0.75rem;
183
+ cursor: pointer;
184
+ font-size: 0.9rem;
185
+ color: var(--wd-navbar-foreground);
186
+ list-style: none;
187
+ }
188
+ .wd-mobile-accordion-trigger::-webkit-details-marker { display: none; }
189
+ .wd-mobile-accordion-trigger::marker { content: ''; }
190
+ .wd-mobile-accordion-label { flex: 1; min-width: 0; }
191
+ .wd-mobile-accordion-caret {
192
+ flex-shrink: 0;
193
+ color: var(--wd-navbar-foreground-muted);
194
+ transition: transform 0.15s ease;
195
+ }
196
+ .wd-mobile-accordion[open] > .wd-mobile-accordion-trigger .wd-mobile-accordion-caret {
197
+ transform: rotate(180deg);
198
+ }
199
+ /* Floats directly below the trigger (top: 100%, same "padding-top for the
200
+ gap, not a top offset, so there's no dead unhoverable/untappable strip
201
+ between them" reasoning as .wd-dropdown-menu in dropdown.css) rather
202
+ than sitting in normal flow beneath it, so opening one of these
203
+ overlays the accordion rows/sidebar content below it instead of shoving
204
+ them further down the page. */
205
+ .wd-mobile-accordion-options {
206
+ position: absolute;
207
+ top: 100%;
208
+ left: 0;
209
+ right: 0;
210
+ padding-top: 0.35rem;
211
+ }
212
+ .wd-mobile-accordion-options-panel {
213
+ display: flex;
214
+ flex-direction: column;
215
+ gap: 0.3rem;
216
+ max-height: 45vh;
217
+ overflow-y: auto;
218
+ background: var(--wd-background);
219
+ border: 1px solid var(--wd-border);
220
+ border-radius: 0.5rem;
221
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
222
+ padding: 0.4rem;
223
+ }
224
+ .wd-mobile-accordion-options a {
225
+ display: flex;
226
+ align-items: center;
227
+ gap: 0.5rem;
228
+ padding: 0.55rem 0.65rem;
229
+ border: 1.5px solid transparent;
230
+ border-radius: 0.4rem;
231
+ text-decoration: none;
232
+ color: var(--wd-text);
233
+ font-size: 0.9rem;
234
+ }
235
+ .wd-mobile-accordion-options a:hover { background: var(--wd-surface); }
236
+ .wd-mobile-accordion-options a.active {
237
+ border-color: var(--wd-primary);
238
+ color: var(--wd-primary);
239
+ font-weight: 500;
240
+ }
241
+ .wd-mobile-accordion-option-label { flex: 1; min-width: 0; }
242
+ .wd-mobile-accordion-check { flex-shrink: 0; color: var(--wd-primary); }
243
+ .wd-mobile-menu-link {
244
+ display: flex;
245
+ align-items: center;
246
+ gap: 0.5rem;
247
+ padding: 0.65rem 0.75rem;
248
+ border: 1px solid var(--wd-border);
249
+ border-radius: 0.5rem;
250
+ text-decoration: none;
251
+ color: var(--wd-navbar-foreground);
252
+ font-size: 0.9rem;
253
+ }
254
+ .wd-mobile-menu-link:hover { background: var(--wd-surface); }
255
+ /* The sidebar copy living in here needs none of .wd-sidebar-col's own
256
+ column sizing (width/border/min-height) - it's just flowing content
257
+ inside an already-padded, already-scrollable panel. */
258
+ .wd-mobile-menu-sidebar .wd-sidebar { padding: 0; }
@@ -0,0 +1,122 @@
1
+ /* SearchModal.astro's own styling - the overlay/modal itself, opened by
2
+ TopBar.astro's .wd-search-trigger button (styled in topbar.css) via
3
+ src/scripts/search.ts. */
4
+
5
+ .wd-search-overlay {
6
+ position: fixed;
7
+ inset: 0;
8
+ z-index: 100;
9
+ display: flex;
10
+ align-items: flex-start;
11
+ justify-content: center;
12
+ padding: 10vh 1rem 2rem;
13
+ background: rgba(15, 23, 42, 0.5);
14
+ }
15
+ .wd-search-overlay[hidden] { display: none; }
16
+ .wd-search-modal {
17
+ width: 100%;
18
+ max-width: 560px;
19
+ max-height: 70vh;
20
+ display: flex;
21
+ flex-direction: column;
22
+ background: var(--wd-background);
23
+ border: 1px solid var(--wd-border);
24
+ border-radius: 0.75rem;
25
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
26
+ overflow: hidden;
27
+ }
28
+ .wd-search-input-row {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 0.6rem;
32
+ padding: 0.85rem 1rem;
33
+ border-bottom: 1px solid var(--wd-border);
34
+ flex-shrink: 0;
35
+ color: var(--wd-text-muted);
36
+ }
37
+ /* Same one-line rule as topbar.css's own copy for the trigger's icon -
38
+ not worth a shared file over. */
39
+ .wd-search-icon { flex-shrink: 0; }
40
+ .wd-search-input {
41
+ flex: 1;
42
+ min-width: 0;
43
+ border: none;
44
+ outline: none;
45
+ background: none;
46
+ color: var(--wd-text);
47
+ font-size: 0.95rem;
48
+ font-family: inherit;
49
+ }
50
+ .wd-search-input::placeholder { color: var(--wd-text-muted); }
51
+ .wd-search-results {
52
+ overflow-y: auto;
53
+ padding: 0.5rem;
54
+ }
55
+ /* All of .wd-search-result's contents are built with
56
+ document.createElement()/innerHTML in src/scripts/search.ts
57
+ (runSearch()), not by this component's own template - these selectors
58
+ still need to be here regardless, since a plain imported .css file
59
+ applies to the whole document either way. */
60
+ .wd-search-result {
61
+ display: block;
62
+ padding: 0.65rem 0.8rem;
63
+ border-radius: 0.55rem;
64
+ text-decoration: none;
65
+ color: inherit;
66
+ }
67
+ .wd-search-result:hover,
68
+ .wd-search-result.wd-search-result-active {
69
+ background: var(--wd-surface);
70
+ }
71
+ .wd-search-result-title {
72
+ font-size: 0.92rem;
73
+ font-weight: 600;
74
+ color: var(--wd-text);
75
+ margin-bottom: 0.3rem;
76
+ white-space: nowrap;
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ }
80
+ /* Clamped to 2 lines rather than left to run however long the matched
81
+ excerpt happens to be - keeps every result the same rough height so the
82
+ list reads as a scannable set of rows instead of a wall of wrapped
83
+ text. */
84
+ .wd-search-result-excerpt {
85
+ font-size: 0.82rem;
86
+ color: var(--wd-text-muted);
87
+ line-height: 1.5;
88
+ display: -webkit-box;
89
+ -webkit-line-clamp: 2;
90
+ -webkit-box-orient: vertical;
91
+ overflow: hidden;
92
+ }
93
+ /* Pagefind returns each excerpt as sanitized HTML with <mark> around
94
+ matched terms - restyled to a tinted-primary weight instead of the
95
+ browser's default yellow highlight, to match the rest of the site's own
96
+ "tint primary" pattern for active/matched state (sidebar links,
97
+ selector options, ...). */
98
+ .wd-search-result-excerpt mark {
99
+ background: none;
100
+ color: var(--wd-primary);
101
+ font-weight: 600;
102
+ }
103
+ .wd-search-empty,
104
+ .wd-search-hint {
105
+ padding: 2rem 1rem;
106
+ text-align: center;
107
+ color: var(--wd-text-muted);
108
+ font-size: 0.85rem;
109
+ }
110
+ /* Same declaration block as topbar.css's own .wd-search-kbd (this
111
+ component's "Esc" hint instead of the trigger's "⌘K") - duplicated
112
+ rather than factored into a third shared file for six lines. */
113
+ .wd-search-esc {
114
+ flex-shrink: 0;
115
+ font-family: inherit;
116
+ font-size: 0.7rem;
117
+ padding: 0.15rem 0.4rem;
118
+ border-radius: 0.3rem;
119
+ border: 1px solid var(--wd-border);
120
+ background: var(--wd-background);
121
+ color: var(--wd-text-muted);
122
+ }