drf-to-mkdoc 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl

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.

Potentially problematic release.


This version of drf-to-mkdoc might be problematic. Click here for more details.

Files changed (47) hide show
  1. drf_to_mkdoc/conf/defaults.py +1 -0
  2. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/field-sections-loader.js +29 -0
  3. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/query-parameters-loader.js +16 -0
  4. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/field-extractor.js +200 -0
  5. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/form-manager.js +465 -0
  6. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/main.js +50 -0
  7. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/modal.js +359 -0
  8. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/query-parameters-extractor.js +94 -0
  9. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/request-executor.js +327 -0
  10. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/response-modal.js +173 -0
  11. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/suggestions.js +123 -0
  12. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/tabs.js +77 -0
  13. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/badges.css +13 -5
  14. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/theme-toggle.css +297 -25
  15. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/fab.css +204 -0
  16. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/response.css +323 -0
  17. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/variables.css +139 -0
  18. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/field-sections.css +136 -0
  19. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/buttons.css +71 -0
  20. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/fab.css +47 -0
  21. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/form.css +663 -0
  22. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/key-value.css +161 -0
  23. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/main.css +57 -0
  24. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/modal.css +334 -0
  25. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/response.css +618 -0
  26. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/tabs.css +114 -0
  27. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/variables.css +94 -0
  28. drf_to_mkdoc/templates/endpoints/detail/base.html +3 -1
  29. drf_to_mkdoc/templates/endpoints/detail/query_parameters.html +1 -8
  30. drf_to_mkdoc/templates/endpoints/detail/request_body.html +2 -0
  31. drf_to_mkdoc/templates/endpoints/detail/responses.html +4 -4
  32. drf_to_mkdoc/templates/try-out/fab.html +68 -0
  33. drf_to_mkdoc/templates/try-out/form.html +260 -0
  34. drf_to_mkdoc/templates/try-out/main.html +4 -0
  35. drf_to_mkdoc/templates/try-out/modal.html +82 -0
  36. drf_to_mkdoc/templates/try-out/response-modal.html +149 -0
  37. drf_to_mkdoc/templatetags/custom_filters.py +33 -1
  38. drf_to_mkdoc/utils/commons/schema_utils.py +5 -14
  39. drf_to_mkdoc/utils/endpoint_detail_generator.py +141 -21
  40. drf_to_mkdoc/utils/extractors/query_parameter_extractors.py +0 -15
  41. {drf_to_mkdoc-0.2.2.dist-info → drf_to_mkdoc-0.2.4.dist-info}/METADATA +68 -9
  42. {drf_to_mkdoc-0.2.2.dist-info → drf_to_mkdoc-0.2.4.dist-info}/RECORD +45 -18
  43. drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out-sidebar.js +0 -879
  44. drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out-sidebar.css +0 -728
  45. {drf_to_mkdoc-0.2.2.dist-info → drf_to_mkdoc-0.2.4.dist-info}/WHEEL +0 -0
  46. {drf_to_mkdoc-0.2.2.dist-info → drf_to_mkdoc-0.2.4.dist-info}/licenses/LICENSE +0 -0
  47. {drf_to_mkdoc-0.2.2.dist-info → drf_to_mkdoc-0.2.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,359 @@
1
+ // Modal management functionality
2
+ const ModalManager = {
3
+ init: function() {
4
+ this.setupKeyboardTraps();
5
+ this.setupEventListeners();
6
+ },
7
+
8
+ setupKeyboardTraps: function() {
9
+ const modal = document.getElementById('tryOutModal');
10
+ if (!modal) return;
11
+
12
+ // Trap focus within modal when open
13
+ modal.addEventListener('keydown', (e) => {
14
+ if (e.key === 'Escape') {
15
+ this.closeTryOut();
16
+ }
17
+
18
+ if (e.key === 'Tab') {
19
+ const focusableElements = modal.querySelectorAll(
20
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
21
+ );
22
+ const firstFocusable = focusableElements[0];
23
+ const lastFocusable = focusableElements[focusableElements.length - 1];
24
+
25
+ if (e.shiftKey) {
26
+ if (document.activeElement === firstFocusable) {
27
+ lastFocusable.focus();
28
+ e.preventDefault();
29
+ }
30
+ } else {
31
+ if (document.activeElement === lastFocusable) {
32
+ firstFocusable.focus();
33
+ e.preventDefault();
34
+ }
35
+ }
36
+ }
37
+ });
38
+ },
39
+
40
+ setupEventListeners: function() {
41
+ // Close modal when clicking overlay
42
+ const overlay = document.querySelector('.modal-overlay');
43
+ if (overlay) {
44
+ overlay.addEventListener('click', () => this.closeTryOut());
45
+ }
46
+
47
+ // Close modal with close button
48
+ const closeButtons = document.querySelectorAll('.modal-close');
49
+ closeButtons.forEach(btn => {
50
+ btn.addEventListener('click', () => this.closeTryOut());
51
+ });
52
+ },
53
+ openTryOut: function() {
54
+ const modal = document.getElementById('tryOutModal');
55
+ if (modal) {
56
+ modal.classList.add('show');
57
+ modal.style.display = 'flex';
58
+ document.body.classList.add('modal-open');
59
+
60
+ // Focus management
61
+ setTimeout(() => {
62
+ const firstInput = modal.querySelector('input, button');
63
+ if (firstInput) {
64
+ firstInput.focus();
65
+ }
66
+ }, 100);
67
+
68
+ // Reinitialize components for dynamic content
69
+ setTimeout(() => {
70
+ if (window.FormManager) {
71
+ window.FormManager.init();
72
+ }
73
+ if (window.TryOutSuggestions) {
74
+ window.TryOutSuggestions.init();
75
+ }
76
+ }, 150);
77
+ }
78
+ },
79
+
80
+ closeTryOut: function() {
81
+ const modal = document.getElementById('tryOutModal');
82
+ if (modal) {
83
+ modal.classList.remove('show');
84
+ modal.style.display = 'none';
85
+ document.body.classList.remove('modal-open');
86
+
87
+ // Hide response section
88
+ const responseSection = document.querySelector('.response-section');
89
+ if (responseSection) {
90
+ responseSection.hidden = true;
91
+ }
92
+ }
93
+ },
94
+
95
+ openResponseModal: function() {
96
+ const modal = document.getElementById('responseModal');
97
+ if (modal) {
98
+ modal.classList.add('show');
99
+ modal.style.display = 'flex';
100
+
101
+ // Reinitialize tabs for response modal
102
+ setTimeout(() => {
103
+ if (window.TabManager) {
104
+ window.TabManager.init();
105
+ }
106
+ }, 100);
107
+ }
108
+ },
109
+
110
+ closeResponseModal: function() {
111
+ const modal = document.getElementById('responseModal');
112
+ if (modal) {
113
+ modal.classList.remove('show');
114
+ modal.style.display = 'none';
115
+ }
116
+ },
117
+
118
+ showResponseModal: function(status, responseText, responseTime, responseHeaders, requestHeaders) {
119
+ const modal = document.getElementById('responseModal');
120
+ const statusBadge = document.getElementById('modalStatusBadge');
121
+ const responseBody = document.getElementById('modalResponseBody');
122
+ const responseInfo = document.getElementById('responseInfo');
123
+ const headersList = document.getElementById('responseHeadersList');
124
+ const timeElement = document.getElementById('responseTime');
125
+ const sizeElement = document.getElementById('responseSize');
126
+
127
+ if (modal && statusBadge && responseBody) {
128
+ // Update time and size stats
129
+ if (timeElement && responseTime !== null && responseTime !== undefined) {
130
+ timeElement.textContent = `${responseTime} ms`;
131
+ }
132
+
133
+ if (sizeElement && responseText) {
134
+ const sizeInBytes = new Blob([responseText]).size;
135
+ const formattedSize = this.formatSize(sizeInBytes);
136
+ sizeElement.textContent = formattedSize;
137
+ }
138
+
139
+ // Handle error status
140
+ if (status === 'Error') {
141
+ statusBadge.textContent = 'Error';
142
+ statusBadge.className = 'status-badge status-error';
143
+ responseBody.textContent = responseText;
144
+ if (responseInfo) {
145
+ responseInfo.textContent = 'Request failed';
146
+ }
147
+ } else {
148
+ // Handle regular response
149
+ statusBadge.textContent = String(status);
150
+ const code = Number(status);
151
+ statusBadge.className = 'status-badge' + (Number.isFinite(code) ? ` status-${Math.floor(code/100)}xx` : '');
152
+
153
+ try {
154
+ const jsonResponse = JSON.parse(responseText);
155
+
156
+ // Show formatted JSON response
157
+ responseBody.textContent = JSON.stringify(jsonResponse, null, 2);
158
+ } catch (e) {
159
+ // Handle non-JSON response
160
+ if (code >= 400) {
161
+ responseBody.innerHTML = `<div class="error-message">
162
+ <div class="error-title">Error Response</div>
163
+ <pre class="error-content">${responseText}</pre>
164
+ </div>`;
165
+ } else {
166
+ responseBody.innerHTML = `<pre class="error-content">${responseText}</pre>`;
167
+ }
168
+ }
169
+
170
+ if (responseInfo) {
171
+ responseInfo.textContent = '';
172
+ }
173
+ }
174
+
175
+ // Display headers
176
+ if (headersList) {
177
+ this.displayHeaders(headersList, responseHeaders, requestHeaders);
178
+ }
179
+
180
+ this.openResponseModal();
181
+ }
182
+ },
183
+
184
+ displayHeaders: function(headersList, responseHeaders, requestHeaders) {
185
+ headersList.innerHTML = '';
186
+
187
+ // Create response headers section
188
+ if (responseHeaders && Object.keys(responseHeaders).length > 0) {
189
+ const responseSection = document.createElement('div');
190
+ responseSection.className = 'headers-section';
191
+
192
+ const responseTitle = document.createElement('h4');
193
+ responseTitle.textContent = `Response Headers (${Object.keys(responseHeaders).length})`;
194
+ responseTitle.className = 'headers-title';
195
+ responseSection.appendChild(responseTitle);
196
+
197
+ const responseList = document.createElement('div');
198
+ responseList.className = 'headers-grid';
199
+
200
+ // Sort headers alphabetically
201
+ const sortedResponseHeaders = Object.entries(responseHeaders).sort(([a], [b]) => a.toLowerCase().localeCompare(b.toLowerCase()));
202
+
203
+ sortedResponseHeaders.forEach(([key, value]) => {
204
+ const headerItem = document.createElement('div');
205
+ headerItem.className = 'header-item';
206
+
207
+ const headerKey = document.createElement('div');
208
+ headerKey.className = 'header-key';
209
+ headerKey.textContent = key;
210
+
211
+ const headerValue = document.createElement('div');
212
+ headerValue.className = 'header-value';
213
+
214
+ // Special formatting for cookies
215
+ if (key.toLowerCase() === 'set-cookie') {
216
+ const cookieList = document.createElement('div');
217
+ cookieList.className = 'cookie-list';
218
+
219
+ // Handle multiple Set-Cookie headers
220
+ const cookies = Array.isArray(value) ? value : [value];
221
+ cookies.forEach(cookie => {
222
+ const cookieItem = document.createElement('div');
223
+ cookieItem.className = 'cookie-item';
224
+ cookieItem.textContent = cookie;
225
+ cookieList.appendChild(cookieItem);
226
+ });
227
+
228
+ headerValue.appendChild(cookieList);
229
+ } else {
230
+ headerValue.textContent = value;
231
+ }
232
+
233
+ headerItem.appendChild(headerKey);
234
+ headerItem.appendChild(headerValue);
235
+ responseList.appendChild(headerItem);
236
+ });
237
+
238
+ responseSection.appendChild(responseList);
239
+ headersList.appendChild(responseSection);
240
+ }
241
+
242
+ // Create request headers section
243
+ if (requestHeaders && Object.keys(requestHeaders).length > 0) {
244
+ const requestSection = document.createElement('div');
245
+ requestSection.className = 'headers-section';
246
+
247
+ const requestTitle = document.createElement('h4');
248
+ requestTitle.textContent = `Request Headers (${Object.keys(requestHeaders).length})`;
249
+ requestTitle.className = 'headers-title';
250
+ requestSection.appendChild(requestTitle);
251
+
252
+ const requestList = document.createElement('div');
253
+ requestList.className = 'headers-grid';
254
+
255
+ // Sort headers alphabetically
256
+ const sortedRequestHeaders = Object.entries(requestHeaders).sort(([a], [b]) => a.toLowerCase().localeCompare(b.toLowerCase()));
257
+
258
+ sortedRequestHeaders.forEach(([key, value]) => {
259
+ const headerItem = document.createElement('div');
260
+ headerItem.className = 'header-item';
261
+
262
+ const headerKey = document.createElement('div');
263
+ headerKey.className = 'header-key';
264
+ headerKey.textContent = key;
265
+
266
+ const headerValue = document.createElement('div');
267
+ headerValue.className = 'header-value';
268
+
269
+ // Special formatting for cookies
270
+ if (key.toLowerCase() === 'cookie') {
271
+ const cookieList = document.createElement('div');
272
+ cookieList.className = 'cookie-list';
273
+
274
+ // Split cookies by semicolon and display each on a new line
275
+ const cookies = value.split(';').map(c => c.trim()).filter(c => c);
276
+ cookies.forEach(cookie => {
277
+ const cookieItem = document.createElement('div');
278
+ cookieItem.className = 'cookie-item';
279
+ cookieItem.textContent = cookie;
280
+ cookieList.appendChild(cookieItem);
281
+ });
282
+
283
+ headerValue.appendChild(cookieList);
284
+ } else {
285
+ headerValue.textContent = value;
286
+ }
287
+
288
+ headerItem.appendChild(headerKey);
289
+ headerItem.appendChild(headerValue);
290
+ requestList.appendChild(headerItem);
291
+ });
292
+
293
+ requestSection.appendChild(requestList);
294
+ headersList.appendChild(requestSection);
295
+ }
296
+
297
+ // Show message if no headers
298
+ if ((!responseHeaders || Object.keys(responseHeaders).length === 0) &&
299
+ (!requestHeaders || Object.keys(requestHeaders).length === 0)) {
300
+ const noHeadersMsg = document.createElement('div');
301
+ noHeadersMsg.className = 'no-headers-message';
302
+ noHeadersMsg.textContent = 'No headers available';
303
+ headersList.appendChild(noHeadersMsg);
304
+ }
305
+ },
306
+
307
+ formatSize: function(bytes) {
308
+ if (bytes === 0) return '0 B';
309
+
310
+ const k = 1024;
311
+ const sizes = ['B', 'KB', 'MB', 'GB'];
312
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
313
+
314
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
315
+ }
316
+ };
317
+
318
+ // Initialize modal functionality when DOM is loaded
319
+ document.addEventListener('DOMContentLoaded', function() {
320
+ ModalManager.init();
321
+ });
322
+
323
+ // Global keyboard navigation
324
+ document.addEventListener('keydown', function(e) {
325
+ if (e.key === 'Escape') {
326
+ // Only close if not already handled by modal's keyboard trap
327
+ const modal = document.getElementById('tryOutModal');
328
+ const responseModal = document.getElementById('responseModal');
329
+
330
+ if (modal && !modal.contains(document.activeElement)) {
331
+ ModalManager.closeTryOut();
332
+ }
333
+ if (responseModal && !responseModal.contains(document.activeElement)) {
334
+ ModalManager.closeResponseModal();
335
+ }
336
+ }
337
+ });
338
+
339
+ // Export for global access
340
+ window.ModalManager = ModalManager;
341
+
342
+ // Create TryOutSidebar alias for backward compatibility
343
+ window.TryOutSidebar = {
344
+ closeResponseModal: function() {
345
+ ModalManager.closeResponseModal();
346
+ },
347
+
348
+ addQueryParam: function(paramName) {
349
+ if (window.FormManager && window.FormManager.addQueryParam) {
350
+ return window.FormManager.addQueryParam(paramName);
351
+ }
352
+ },
353
+
354
+ removeKvItem: function(button) {
355
+ if (window.FormManager && window.FormManager.removeKvItem) {
356
+ return window.FormManager.removeKvItem(button);
357
+ }
358
+ }
359
+ };
@@ -0,0 +1,94 @@
1
+ // Query parameters extractor
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ const QueryParametersExtractor = {
4
+ init: function() {
5
+ // Extract parameters directly from HTML content
6
+ const parameters = this.extractParametersFromHTML();
7
+
8
+ // Make parameters available for suggestions
9
+ if (parameters) {
10
+ window.queryParametersData = parameters;
11
+
12
+ // Initialize suggestions if TryOutSuggestions is available
13
+ if (window.TryOutSuggestions) {
14
+ window.TryOutSuggestions.init();
15
+ }
16
+ }
17
+ },
18
+
19
+ extractParametersFromHTML: function() {
20
+ const data = {
21
+ filter_fields: [],
22
+ search_fields: [],
23
+ ordering_fields: [],
24
+ pagination_fields: [],
25
+ special_keys: []
26
+ };
27
+
28
+ // Extract filter fields
29
+ this.extractFieldsFromSection('filter-fields', data.filter_fields);
30
+
31
+ // Extract search fields
32
+ this.extractFieldsFromSection('search-fields', data.search_fields);
33
+
34
+ // Extract ordering fields
35
+ this.extractFieldsFromSection('ordering-fields', data.ordering_fields);
36
+
37
+ // Extract pagination fields
38
+ this.extractFieldsFromSection('pagination-fields', data.pagination_fields);
39
+
40
+ // Add special keys
41
+ this.addSpecialKeys(data);
42
+
43
+ return data;
44
+ },
45
+
46
+ extractFieldsFromSection: function(sectionId, targetArray) {
47
+ const heading = document.querySelector(`h3#${sectionId}`);
48
+ if (!heading) return;
49
+
50
+ // Find the next UL element after the heading
51
+ let currentElement = heading.nextElementSibling;
52
+ while (currentElement && currentElement.tagName !== 'UL') {
53
+ currentElement = currentElement.nextElementSibling;
54
+ }
55
+
56
+ if (!currentElement || currentElement.tagName !== 'UL') return;
57
+
58
+ // Extract field names from code elements
59
+ const codeElements = currentElement.querySelectorAll('code');
60
+ codeElements.forEach(code => {
61
+ const fieldName = code.textContent.trim();
62
+ if (fieldName && !targetArray.includes(fieldName)) {
63
+ targetArray.push(fieldName);
64
+ }
65
+ });
66
+ },
67
+
68
+ addSpecialKeys: function(data) {
69
+ // Add special keys for common query parameter types
70
+
71
+ // Add special keys for each parameter type
72
+ if (data) {
73
+ // Special keys for search fields
74
+ if (data.search_fields && data.search_fields.length > 0) {
75
+ if (!data.special_keys.includes('search')) {
76
+ data.special_keys.push('search');
77
+ }
78
+ }
79
+
80
+ // Special keys for ordering fields
81
+ if (data.ordering_fields && data.ordering_fields.length > 0) {
82
+ if (!data.special_keys.includes('ordering')) {
83
+ data.special_keys.push('ordering');
84
+ }
85
+ }
86
+ }
87
+
88
+ return data;
89
+ }
90
+ };
91
+
92
+ // Initialize extractor
93
+ QueryParametersExtractor.init();
94
+ });