@prauga/flexdoc-backend 2.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.
- package/README.md +227 -0
- package/dist/flexdoc.module.d.ts +14 -0
- package/dist/flexdoc.module.js +77 -0
- package/dist/flexdoc.module.js.map +1 -0
- package/dist/flexdoc.module.test.d.ts +1 -0
- package/dist/flexdoc.module.test.js +72 -0
- package/dist/flexdoc.module.test.js.map +1 -0
- package/dist/flexdoc.service.d.ts +5 -0
- package/dist/flexdoc.service.js +24 -0
- package/dist/flexdoc.service.js.map +1 -0
- package/dist/framework-adapters.d.ts +25 -0
- package/dist/framework-adapters.js +163 -0
- package/dist/framework-adapters.js.map +1 -0
- package/dist/framework-adapters.test.d.ts +1 -0
- package/dist/framework-adapters.test.js +37 -0
- package/dist/framework-adapters.test.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +169 -0
- package/dist/interfaces.js +3 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/renderer/flexdoc.standalone.css +1 -0
- package/dist/renderer/flexdoc.standalone.js +200 -0
- package/dist/renderer-assets.d.ts +5 -0
- package/dist/renderer-assets.js +60 -0
- package/dist/renderer-assets.js.map +1 -0
- package/dist/scripts/generate-auth.d.ts +2 -0
- package/dist/scripts/generate-auth.js +107 -0
- package/dist/scripts/generate-auth.js.map +1 -0
- package/dist/setup.d.ts +6 -0
- package/dist/setup.js +220 -0
- package/dist/setup.js.map +1 -0
- package/dist/setup.test.d.ts +1 -0
- package/dist/setup.test.js +89 -0
- package/dist/setup.test.js.map +1 -0
- package/dist/template.d.ts +15 -0
- package/dist/template.js +64 -0
- package/dist/template.js.map +1 -0
- package/dist/template.test.d.ts +1 -0
- package/dist/template.test.js +38 -0
- package/dist/template.test.js.map +1 -0
- package/dist/templates/code-examples.njk +106 -0
- package/dist/templates/content.njk +272 -0
- package/dist/templates/footer.njk +38 -0
- package/dist/templates/header.njk +57 -0
- package/dist/templates/layout.njk +647 -0
- package/dist/templates/parameters.njk +64 -0
- package/dist/templates/request-body.njk +63 -0
- package/dist/templates/responses.njk +78 -0
- package/dist/templates/sidebar.njk +117 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="{{ themeMode }}">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>{{ title }}</title>
|
|
7
|
+
<meta name="description" content="{{ description }}">
|
|
8
|
+
{% if favicon %}
|
|
9
|
+
<link rel="icon" href="{{ favicon }}">
|
|
10
|
+
{% endif %}
|
|
11
|
+
|
|
12
|
+
<!-- Tailwind CSS -->
|
|
13
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
14
|
+
<script>
|
|
15
|
+
tailwind.config = {
|
|
16
|
+
darkMode: 'class',
|
|
17
|
+
theme: {
|
|
18
|
+
extend: {
|
|
19
|
+
colors: {
|
|
20
|
+
primary: {
|
|
21
|
+
50: '{{ themeConfig.colors.primary.light | default("#eff6ff") }}',
|
|
22
|
+
100: '#dbeafe',
|
|
23
|
+
200: '#bfdbfe',
|
|
24
|
+
300: '#93c5fd',
|
|
25
|
+
400: '#60a5fa',
|
|
26
|
+
500: '{{ themeConfig.colors.primary.main | default("#3b82f6") }}',
|
|
27
|
+
600: '{{ themeConfig.colors.primary.dark | default("#2563eb") }}',
|
|
28
|
+
700: '#1d4ed8',
|
|
29
|
+
800: '#1e40af',
|
|
30
|
+
900: '#1e3a8a',
|
|
31
|
+
},
|
|
32
|
+
success: {
|
|
33
|
+
500: '{{ themeConfig.colors.success.main | default("#10b981") }}',
|
|
34
|
+
600: '{{ themeConfig.colors.success.dark | default("#059669") }}',
|
|
35
|
+
},
|
|
36
|
+
error: {
|
|
37
|
+
500: '{{ themeConfig.colors.error.main | default("#ef4444") }}',
|
|
38
|
+
600: '{{ themeConfig.colors.error.dark | default("#dc2626") }}',
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
fontFamily: {
|
|
42
|
+
sans: ['{{ themeConfig.typography.fontFamily | default("Inter, system-ui, sans-serif") }}'],
|
|
43
|
+
mono: ['{{ themeConfig.typography.code.fontFamily | default("Monaco, Menlo, monospace") }}'],
|
|
44
|
+
},
|
|
45
|
+
fontSize: {
|
|
46
|
+
base: '{{ themeConfig.typography.fontSize | default("14px") }}',
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<!-- Lucide Icons -->
|
|
54
|
+
<script src="https://unpkg.com/lucide@latest"></script>
|
|
55
|
+
|
|
56
|
+
<!-- Custom Styles -->
|
|
57
|
+
<style>
|
|
58
|
+
:root {
|
|
59
|
+
/* Primary Colors */
|
|
60
|
+
--flexdoc-primary: {{ themeConfig.colors.primary.main | default('#3b82f6') }};
|
|
61
|
+
--flexdoc-primary-light: {{ themeConfig.colors.primary.light | default('#60a5fa') }};
|
|
62
|
+
--flexdoc-primary-dark: {{ themeConfig.colors.primary.dark | default('#2563eb') }};
|
|
63
|
+
|
|
64
|
+
/* Success Colors */
|
|
65
|
+
--flexdoc-success: {{ themeConfig.colors.success.main | default('#10b981') }};
|
|
66
|
+
--flexdoc-success-light: {{ themeConfig.colors.success.light | default('#34d399') }};
|
|
67
|
+
--flexdoc-success-dark: {{ themeConfig.colors.success.dark | default('#059669') }};
|
|
68
|
+
|
|
69
|
+
/* Error Colors */
|
|
70
|
+
--flexdoc-error: {{ themeConfig.colors.error.main | default('#ef4444') }};
|
|
71
|
+
--flexdoc-error-light: {{ themeConfig.colors.error.light | default('#f87171') }};
|
|
72
|
+
--flexdoc-error-dark: {{ themeConfig.colors.error.dark | default('#dc2626') }};
|
|
73
|
+
|
|
74
|
+
/* Text Colors */
|
|
75
|
+
--flexdoc-text-primary: {{ themeConfig.colors.text.primary | default('#111827') }};
|
|
76
|
+
--flexdoc-text-secondary: {{ themeConfig.colors.text.secondary | default('#6b7280') }};
|
|
77
|
+
|
|
78
|
+
/* Gray Colors */
|
|
79
|
+
--flexdoc-gray-50: {{ themeConfig.colors.gray[50] | default('#f9fafb') }};
|
|
80
|
+
--flexdoc-gray-100: {{ themeConfig.colors.gray[100] | default('#f3f4f6') }};
|
|
81
|
+
|
|
82
|
+
/* Border Colors */
|
|
83
|
+
--flexdoc-border-light: {{ themeConfig.colors.border.light | default('#e5e7eb') }};
|
|
84
|
+
--flexdoc-border-dark: {{ themeConfig.colors.border.dark | default('#374151') }};
|
|
85
|
+
|
|
86
|
+
/* Typography */
|
|
87
|
+
--flexdoc-font-size: {{ themeConfig.typography.fontSize | default('14px') }};
|
|
88
|
+
--flexdoc-line-height: {{ themeConfig.typography.lineHeight | default('1.5') }};
|
|
89
|
+
--flexdoc-font-family: {{ themeConfig.typography.fontFamily | default('Inter, system-ui, sans-serif') }};
|
|
90
|
+
|
|
91
|
+
/* Headings */
|
|
92
|
+
--flexdoc-headings-font-family: {{ themeConfig.typography.headings.fontFamily | default('inherit') }};
|
|
93
|
+
--flexdoc-headings-font-weight: {{ themeConfig.typography.headings.fontWeight | default('600') }};
|
|
94
|
+
|
|
95
|
+
/* Code */
|
|
96
|
+
--flexdoc-code-font-size: {{ themeConfig.typography.code.fontSize | default('13px') }};
|
|
97
|
+
--flexdoc-code-font-family: {{ themeConfig.typography.code.fontFamily | default('Monaco, Menlo, monospace') }};
|
|
98
|
+
--flexdoc-code-line-height: {{ themeConfig.typography.code.lineHeight | default('1.4') }};
|
|
99
|
+
--flexdoc-code-color: {{ themeConfig.typography.code.colorLight | default('#374151') }};
|
|
100
|
+
--flexdoc-code-bg: {{ themeConfig.typography.code.backgroundColorLight | default('#f3f4f6') }};
|
|
101
|
+
|
|
102
|
+
/* Sidebar */
|
|
103
|
+
--flexdoc-sidebar-bg: {{ themeConfig.sidebar.backgroundColor | default('#ffffff') }};
|
|
104
|
+
--flexdoc-sidebar-text: {{ themeConfig.sidebar.textColor | default('#374151') }};
|
|
105
|
+
--flexdoc-sidebar-active: {{ themeConfig.sidebar.activeTextColor | default('#3b82f6') }};
|
|
106
|
+
--flexdoc-sidebar-border: {{ themeConfig.sidebar.borderColor | default('#e5e7eb') }};
|
|
107
|
+
|
|
108
|
+
/* Method Colors */
|
|
109
|
+
--flexdoc-method-get-bg: {{ themeConfig.methodColors.get.bg | default('#dbeafe') }};
|
|
110
|
+
--flexdoc-method-get-border: {{ themeConfig.methodColors.get.border | default('#93c5fd') }};
|
|
111
|
+
--flexdoc-method-post-bg: {{ themeConfig.methodColors.post.bg | default('#d1fae5') }};
|
|
112
|
+
--flexdoc-method-post-border: {{ themeConfig.methodColors.post.border | default('#6ee7b7') }};
|
|
113
|
+
--flexdoc-method-put-bg: {{ themeConfig.methodColors.put.bg | default('#fed7aa') }};
|
|
114
|
+
--flexdoc-method-put-border: {{ themeConfig.methodColors.put.border | default('#fdba74') }};
|
|
115
|
+
--flexdoc-method-delete-bg: {{ themeConfig.methodColors.delete.bg | default('#fecaca') }};
|
|
116
|
+
--flexdoc-method-delete-border: {{ themeConfig.methodColors.delete.border | default('#f87171') }};
|
|
117
|
+
--flexdoc-method-patch-bg: {{ themeConfig.methodColors.patch.bg | default('#e9d5ff') }};
|
|
118
|
+
--flexdoc-method-patch-border: {{ themeConfig.methodColors.patch.border | default('#c4b5fd') }};
|
|
119
|
+
--flexdoc-method-options-bg: {{ themeConfig.methodColors.options.bg | default('#f3f4f6') }};
|
|
120
|
+
--flexdoc-method-options-border: {{ themeConfig.methodColors.options.border | default('#d1d5db') }};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.dark {
|
|
124
|
+
/* Dark mode overrides */
|
|
125
|
+
--flexdoc-sidebar-bg: {{ themeConfig.sidebar.backgroundColorDark | default('#1f2937') }};
|
|
126
|
+
--flexdoc-sidebar-text: {{ themeConfig.sidebar.textColorDark | default('#d1d5db') }};
|
|
127
|
+
--flexdoc-sidebar-active: {{ themeConfig.sidebar.activeTextColorDark | default('#60a5fa') }};
|
|
128
|
+
--flexdoc-sidebar-border: {{ themeConfig.sidebar.borderColorDark | default('#374151') }};
|
|
129
|
+
|
|
130
|
+
/* Code dark mode overrides */
|
|
131
|
+
--flexdoc-code-color: {{ themeConfig.typography.code.color | default('#e5e7eb') }};
|
|
132
|
+
--flexdoc-code-bg: {{ themeConfig.typography.code.backgroundColor | default('#2d3748') }};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Apply custom variables */
|
|
136
|
+
body {
|
|
137
|
+
font-family: var(--flexdoc-font-family);
|
|
138
|
+
font-size: var(--flexdoc-font-size);
|
|
139
|
+
line-height: var(--flexdoc-line-height);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
h1, h2, h3, h4, h5, h6 {
|
|
143
|
+
font-family: var(--flexdoc-headings-font-family);
|
|
144
|
+
font-weight: var(--flexdoc-headings-font-weight);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
code, pre {
|
|
148
|
+
font-family: var(--flexdoc-code-font-family);
|
|
149
|
+
font-size: var(--flexdoc-code-font-size);
|
|
150
|
+
line-height: var(--flexdoc-code-line-height);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Smooth transitions */
|
|
154
|
+
* {
|
|
155
|
+
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Custom scrollbar */
|
|
159
|
+
::-webkit-scrollbar {
|
|
160
|
+
width: 6px;
|
|
161
|
+
height: 6px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
::-webkit-scrollbar-track {
|
|
165
|
+
background: transparent;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
::-webkit-scrollbar-thumb {
|
|
169
|
+
background: rgba(156, 163, 175, 0.5);
|
|
170
|
+
border-radius: 3px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
::-webkit-scrollbar-thumb:hover {
|
|
174
|
+
background: rgba(156, 163, 175, 0.7);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.dark ::-webkit-scrollbar-thumb {
|
|
178
|
+
background: rgba(75, 85, 99, 0.5);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.dark ::-webkit-scrollbar-thumb:hover {
|
|
182
|
+
background: rgba(75, 85, 99, 0.7);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Code block styling */
|
|
186
|
+
.code-block {
|
|
187
|
+
background: var(--flexdoc-code-bg);
|
|
188
|
+
border-radius: 8px;
|
|
189
|
+
overflow: hidden;
|
|
190
|
+
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.dark .code-block {
|
|
194
|
+
border-color: transparent;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.code-block pre {
|
|
198
|
+
margin: 0;
|
|
199
|
+
padding: 1rem;
|
|
200
|
+
overflow-x: auto;
|
|
201
|
+
color: var(--flexdoc-code-color);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Method badges using custom colors */
|
|
205
|
+
.method-get {
|
|
206
|
+
background-color: var(--flexdoc-method-get-bg);
|
|
207
|
+
border-color: var(--flexdoc-method-get-border);
|
|
208
|
+
color: #1e40af;
|
|
209
|
+
}
|
|
210
|
+
.method-post {
|
|
211
|
+
background-color: var(--flexdoc-method-post-bg);
|
|
212
|
+
border-color: var(--flexdoc-method-post-border);
|
|
213
|
+
color: #065f46;
|
|
214
|
+
}
|
|
215
|
+
.method-put {
|
|
216
|
+
background-color: var(--flexdoc-method-put-bg);
|
|
217
|
+
border-color: var(--flexdoc-method-put-border);
|
|
218
|
+
color: #9a3412;
|
|
219
|
+
}
|
|
220
|
+
.method-delete {
|
|
221
|
+
background-color: var(--flexdoc-method-delete-bg);
|
|
222
|
+
border-color: var(--flexdoc-method-delete-border);
|
|
223
|
+
color: #991b1b;
|
|
224
|
+
}
|
|
225
|
+
.method-patch {
|
|
226
|
+
background-color: var(--flexdoc-method-patch-bg);
|
|
227
|
+
border-color: var(--flexdoc-method-patch-border);
|
|
228
|
+
color: #581c87;
|
|
229
|
+
}
|
|
230
|
+
.method-options {
|
|
231
|
+
background-color: var(--flexdoc-method-options-bg);
|
|
232
|
+
border-color: var(--flexdoc-method-options-border);
|
|
233
|
+
color: #4b5563;
|
|
234
|
+
}
|
|
235
|
+
.method-head {
|
|
236
|
+
background-color: #f3f4f6; /* gray-100 */
|
|
237
|
+
color: #1f2937; /* gray-800 */
|
|
238
|
+
border-color: #e5e7eb; /* gray-200 */
|
|
239
|
+
}
|
|
240
|
+
.dark .method-head {
|
|
241
|
+
background-color: #374151; /* gray-700 */
|
|
242
|
+
color: #e5e7eb; /* gray-200 */
|
|
243
|
+
border-color: #4b5563; /* gray-600 */
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Status code badges (no @apply; works with CDN) */
|
|
247
|
+
.status-2xx {
|
|
248
|
+
background-color: #dcfce7; /* green-100 */
|
|
249
|
+
color: #166534; /* green-800 */
|
|
250
|
+
border-color: #bbf7d0; /* green-200 */
|
|
251
|
+
}
|
|
252
|
+
.dark .status-2xx {
|
|
253
|
+
background-color: #14532d; /* green-900 */
|
|
254
|
+
color: #bbf7d0; /* green-200 */
|
|
255
|
+
}
|
|
256
|
+
.status-3xx {
|
|
257
|
+
background-color: #dbeafe; /* blue-100 */
|
|
258
|
+
color: #1e40af; /* blue-800 */
|
|
259
|
+
border-color: #bfdbfe; /* blue-200 */
|
|
260
|
+
}
|
|
261
|
+
.dark .status-3xx {
|
|
262
|
+
background-color: #1e3a8a; /* blue-900 */
|
|
263
|
+
color: #bfdbfe; /* blue-200 */
|
|
264
|
+
}
|
|
265
|
+
.status-4xx {
|
|
266
|
+
background-color: #ffedd5; /* orange-100 */
|
|
267
|
+
color: #9a3412; /* orange-800 */
|
|
268
|
+
border-color: #fed7aa; /* orange-200 */
|
|
269
|
+
}
|
|
270
|
+
.dark .status-4xx {
|
|
271
|
+
background-color: #7c2d12; /* orange-900 */
|
|
272
|
+
color: #fed7aa; /* orange-200 */
|
|
273
|
+
}
|
|
274
|
+
.status-5xx {
|
|
275
|
+
background-color: #fee2e2; /* red-100 */
|
|
276
|
+
color: #991b1b; /* red-800 */
|
|
277
|
+
border-color: #fecaca; /* red-200 */
|
|
278
|
+
}
|
|
279
|
+
.dark .status-5xx {
|
|
280
|
+
background-color: #7f1d1d; /* red-900 */
|
|
281
|
+
color: #fecaca; /* red-200 */
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Hover effects */
|
|
285
|
+
.hover-lift {
|
|
286
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.hover-lift:hover {
|
|
290
|
+
transform: translateY(-1px);
|
|
291
|
+
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.dark .hover-lift:hover {
|
|
295
|
+
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/* Animation for collapsible sections */
|
|
299
|
+
.collapsible-content {
|
|
300
|
+
max-height: 0;
|
|
301
|
+
overflow: hidden;
|
|
302
|
+
transition: max-height 0.3s ease;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.collapsible-content.expanded {
|
|
306
|
+
max-height: 2000px;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Sidebar styling */
|
|
310
|
+
.sidebar {
|
|
311
|
+
background-color: var(--flexdoc-sidebar-bg);
|
|
312
|
+
color: var(--flexdoc-sidebar-text);
|
|
313
|
+
border-color: var(--flexdoc-sidebar-border);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.sidebar .endpoint-item.active {
|
|
317
|
+
color: var(--flexdoc-sidebar-active);
|
|
318
|
+
background-color: rgba(59, 130, 246, 0.1);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* Hide all endpoint details by default */
|
|
322
|
+
.endpoint-detail {
|
|
323
|
+
display: none;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.endpoint-detail.active {
|
|
327
|
+
display: block;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* Overview is shown by default */
|
|
331
|
+
.overview-content {
|
|
332
|
+
display: block;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.overview-content.hidden {
|
|
336
|
+
display: none;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Custom Theme CSS */
|
|
340
|
+
{{ customThemeCSS }}
|
|
341
|
+
|
|
342
|
+
/* Custom CSS */
|
|
343
|
+
{{ customCss }}
|
|
344
|
+
</style>
|
|
345
|
+
</head>
|
|
346
|
+
<body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white" style="{{ cssVarsString }}">
|
|
347
|
+
{% include "header.njk" %}
|
|
348
|
+
{% include "sidebar.njk" %}
|
|
349
|
+
|
|
350
|
+
<div class="flex flex-col min-h-screen">
|
|
351
|
+
<!-- Main content with left margin to account for fixed sidebar -->
|
|
352
|
+
<main class="flex-1 overflow-y-auto pb-16 ml-80">
|
|
353
|
+
{% block content %}{% endblock %}
|
|
354
|
+
</main>
|
|
355
|
+
|
|
356
|
+
<!-- Footer is already fixed in footer.njk -->
|
|
357
|
+
</div>
|
|
358
|
+
{% include "footer.njk" %}
|
|
359
|
+
|
|
360
|
+
<script>
|
|
361
|
+
// Initialize Lucide icons
|
|
362
|
+
lucide.createIcons();
|
|
363
|
+
|
|
364
|
+
// Global state
|
|
365
|
+
let currentEndpoint = null;
|
|
366
|
+
|
|
367
|
+
// Copy to clipboard function
|
|
368
|
+
async function copyToClipboard(text) {
|
|
369
|
+
try {
|
|
370
|
+
await navigator.clipboard.writeText(text);
|
|
371
|
+
// Show success feedback
|
|
372
|
+
const event = new CustomEvent('clipboard-success');
|
|
373
|
+
document.dispatchEvent(event);
|
|
374
|
+
} catch (err) {
|
|
375
|
+
console.error('Failed to copy text: ', err);
|
|
376
|
+
// Fallback for older browsers
|
|
377
|
+
const textArea = document.createElement('textarea');
|
|
378
|
+
textArea.value = text;
|
|
379
|
+
document.body.appendChild(textArea);
|
|
380
|
+
textArea.select();
|
|
381
|
+
document.execCommand('copy');
|
|
382
|
+
document.body.removeChild(textArea);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Setup event listeners when DOM is loaded
|
|
387
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
388
|
+
// Setup search functionality
|
|
389
|
+
const searchInput = document.getElementById('search-input');
|
|
390
|
+
if (searchInput) {
|
|
391
|
+
searchInput.addEventListener('input', (e) => {
|
|
392
|
+
const searchTerm = e.target.value.toLowerCase();
|
|
393
|
+
const endpoints = document.querySelectorAll('.endpoint-item');
|
|
394
|
+
const tagSections = document.querySelectorAll('.tag-section');
|
|
395
|
+
|
|
396
|
+
endpoints.forEach(endpoint => {
|
|
397
|
+
const text = endpoint.textContent.toLowerCase();
|
|
398
|
+
const parent = endpoint.closest('.tag-section');
|
|
399
|
+
|
|
400
|
+
if (text.includes(searchTerm)) {
|
|
401
|
+
endpoint.style.display = '';
|
|
402
|
+
if (parent) parent.style.display = '';
|
|
403
|
+
} else {
|
|
404
|
+
endpoint.style.display = 'none';
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Hide empty tag sections
|
|
409
|
+
tagSections.forEach(section => {
|
|
410
|
+
const visibleEndpoints = section.querySelectorAll('.endpoint-item:not([style*="display: none"])');
|
|
411
|
+
section.style.display = visibleEndpoints.length > 0 ? '' : 'none';
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
lucide.createIcons();
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Theme toggle functionality
|
|
419
|
+
const themeToggle = document.getElementById('theme-toggle');
|
|
420
|
+
if (themeToggle) {
|
|
421
|
+
themeToggle.addEventListener('click', () => {
|
|
422
|
+
document.documentElement.classList.toggle('dark');
|
|
423
|
+
lucide.createIcons();
|
|
424
|
+
localStorage.setItem('flexdoc-theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Check for saved theme preference
|
|
429
|
+
const savedTheme = localStorage.getItem('flexdoc-theme');
|
|
430
|
+
if (savedTheme === 'dark' && !document.documentElement.classList.contains('dark')) {
|
|
431
|
+
document.documentElement.classList.add('dark');
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Setup endpoint navigation
|
|
435
|
+
setupEndpointNavigation();
|
|
436
|
+
|
|
437
|
+
// Setup collapsible sections
|
|
438
|
+
setupCollapsibleSections();
|
|
439
|
+
|
|
440
|
+
// Setup code tabs
|
|
441
|
+
setupCodeTabs();
|
|
442
|
+
|
|
443
|
+
// Setup copy buttons
|
|
444
|
+
setupCopyButtons();
|
|
445
|
+
|
|
446
|
+
// Setup tag toggles
|
|
447
|
+
setupTagToggles();
|
|
448
|
+
|
|
449
|
+
// Setup download spec button functionality
|
|
450
|
+
setupDownloadSpecButton();
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// Endpoint navigation functionality
|
|
454
|
+
function setupEndpointNavigation() {
|
|
455
|
+
const endpointLinks = document.querySelectorAll('.endpoint-link');
|
|
456
|
+
const overviewContent = document.querySelector('.overview-content');
|
|
457
|
+
const endpointDetails = document.querySelectorAll('.endpoint-detail');
|
|
458
|
+
|
|
459
|
+
endpointLinks.forEach(link => {
|
|
460
|
+
link.addEventListener('click', (e) => {
|
|
461
|
+
e.preventDefault();
|
|
462
|
+
|
|
463
|
+
const targetId = link.getAttribute('data-endpoint');
|
|
464
|
+
|
|
465
|
+
// Remove active class from all links
|
|
466
|
+
endpointLinks.forEach(l => l.classList.remove('active'));
|
|
467
|
+
|
|
468
|
+
// Add active class to clicked link
|
|
469
|
+
link.classList.add('active');
|
|
470
|
+
|
|
471
|
+
// Hide overview
|
|
472
|
+
if (overviewContent) {
|
|
473
|
+
overviewContent.classList.add('hidden');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Hide all endpoint details
|
|
477
|
+
endpointDetails.forEach(detail => {
|
|
478
|
+
detail.classList.remove('active');
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
// Show target endpoint detail
|
|
482
|
+
const targetDetail = document.getElementById(targetId);
|
|
483
|
+
if (targetDetail) {
|
|
484
|
+
targetDetail.classList.add('active');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
currentEndpoint = targetId;
|
|
488
|
+
});
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Handle hash navigation
|
|
492
|
+
if (window.location.hash) {
|
|
493
|
+
const targetId = window.location.hash.substring(1);
|
|
494
|
+
const targetLink = document.querySelector(`[data-endpoint="${targetId}"]`);
|
|
495
|
+
if (targetLink) {
|
|
496
|
+
targetLink.click();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Tag toggle functionality
|
|
502
|
+
function setupTagToggles() {
|
|
503
|
+
const tagToggles = document.querySelectorAll('.tag-toggle');
|
|
504
|
+
|
|
505
|
+
tagToggles.forEach(toggle => {
|
|
506
|
+
toggle.addEventListener('click', () => {
|
|
507
|
+
const targetId = toggle.getAttribute('data-target');
|
|
508
|
+
const target = document.getElementById(targetId);
|
|
509
|
+
const icon = toggle.querySelector('[data-lucide]');
|
|
510
|
+
|
|
511
|
+
if (target) {
|
|
512
|
+
target.classList.toggle('expanded');
|
|
513
|
+
|
|
514
|
+
// Update icon
|
|
515
|
+
if (target.classList.contains('expanded')) {
|
|
516
|
+
icon.setAttribute('data-lucide', 'chevron-down');
|
|
517
|
+
} else {
|
|
518
|
+
icon.setAttribute('data-lucide', 'chevron-right');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
lucide.createIcons();
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Collapsible sections functionality
|
|
528
|
+
function setupCollapsibleSections() {
|
|
529
|
+
const toggleButtons = document.querySelectorAll('[data-toggle]');
|
|
530
|
+
toggleButtons.forEach(button => {
|
|
531
|
+
button.addEventListener('click', () => {
|
|
532
|
+
const targetId = button.getAttribute('data-toggle');
|
|
533
|
+
const target = document.getElementById(targetId);
|
|
534
|
+
const icon = button.querySelector('[data-lucide]');
|
|
535
|
+
|
|
536
|
+
if (target) {
|
|
537
|
+
target.classList.toggle('expanded');
|
|
538
|
+
|
|
539
|
+
// Update icon
|
|
540
|
+
if (target.classList.contains('expanded')) {
|
|
541
|
+
icon.setAttribute('data-lucide', 'chevron-down');
|
|
542
|
+
} else {
|
|
543
|
+
icon.setAttribute('data-lucide', 'chevron-right');
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
lucide.createIcons();
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Code tabs functionality
|
|
553
|
+
function setupCodeTabs() {
|
|
554
|
+
const codeTabs = document.querySelectorAll('.code-tab');
|
|
555
|
+
codeTabs.forEach(tab => {
|
|
556
|
+
tab.addEventListener('click', () => {
|
|
557
|
+
const targetId = tab.getAttribute('data-target');
|
|
558
|
+
if (!targetId) return;
|
|
559
|
+
|
|
560
|
+
const tabGroup = tab.closest('.code-tabs');
|
|
561
|
+
if (!tabGroup) return;
|
|
562
|
+
|
|
563
|
+
// Deactivate all tabs in this group
|
|
564
|
+
const tabs = tabGroup.querySelectorAll('.code-tab');
|
|
565
|
+
tabs.forEach(t => {
|
|
566
|
+
t.classList.remove('border-primary-500', 'text-primary-600');
|
|
567
|
+
t.classList.add('border-transparent', 'text-gray-500');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// Activate clicked tab
|
|
571
|
+
tab.classList.remove('border-transparent', 'text-gray-500');
|
|
572
|
+
tab.classList.add('border-primary-500', 'text-primary-600');
|
|
573
|
+
|
|
574
|
+
// Hide all panels in this group
|
|
575
|
+
const panels = tabGroup.querySelectorAll('.code-panel');
|
|
576
|
+
panels.forEach(panel => panel.classList.add('hidden'));
|
|
577
|
+
|
|
578
|
+
// Show target panel
|
|
579
|
+
const targetPanel = document.getElementById(targetId);
|
|
580
|
+
if (targetPanel) {
|
|
581
|
+
targetPanel.classList.remove('hidden');
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Copy buttons functionality
|
|
588
|
+
function setupCopyButtons() {
|
|
589
|
+
const copyButtons = document.querySelectorAll('[data-copy]');
|
|
590
|
+
copyButtons.forEach(button => {
|
|
591
|
+
button.addEventListener('click', async () => {
|
|
592
|
+
const text = button.getAttribute('data-copy');
|
|
593
|
+
await copyToClipboard(text);
|
|
594
|
+
|
|
595
|
+
// Visual feedback
|
|
596
|
+
const originalText = button.textContent;
|
|
597
|
+
const icon = button.querySelector('[data-lucide]');
|
|
598
|
+
|
|
599
|
+
button.textContent = 'Copied!';
|
|
600
|
+
if (icon) {
|
|
601
|
+
icon.setAttribute('data-lucide', 'check');
|
|
602
|
+
lucide.createIcons();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
setTimeout(() => {
|
|
606
|
+
button.textContent = originalText;
|
|
607
|
+
if (icon) {
|
|
608
|
+
icon.setAttribute('data-lucide', 'copy');
|
|
609
|
+
lucide.createIcons();
|
|
610
|
+
}
|
|
611
|
+
}, 2000);
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Setup download spec button functionality
|
|
617
|
+
function setupDownloadSpecButton() {
|
|
618
|
+
const downloadBtn = document.getElementById('download-spec-btn');
|
|
619
|
+
if (downloadBtn) {
|
|
620
|
+
downloadBtn.addEventListener('click', () => {
|
|
621
|
+
// Create a blob with the spec JSON
|
|
622
|
+
const specJson = `{{ specJsonString | safe }}`;
|
|
623
|
+
const blob = new Blob([specJson], { type: 'application/json' });
|
|
624
|
+
|
|
625
|
+
// Create a download link
|
|
626
|
+
const url = URL.createObjectURL(blob);
|
|
627
|
+
const a = document.createElement('a');
|
|
628
|
+
a.href = url;
|
|
629
|
+
a.download = '{{ title | default("openapi-spec") }}.json';
|
|
630
|
+
|
|
631
|
+
// Trigger the download
|
|
632
|
+
document.body.appendChild(a);
|
|
633
|
+
a.click();
|
|
634
|
+
|
|
635
|
+
// Clean up
|
|
636
|
+
setTimeout(() => {
|
|
637
|
+
document.body.removeChild(a);
|
|
638
|
+
URL.revokeObjectURL(url);
|
|
639
|
+
}, 0);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
{{ customJs }}
|
|
645
|
+
</script>
|
|
646
|
+
</body>
|
|
647
|
+
</html>
|