File size: 12,950 Bytes
184bd4a
 
 
 
 
 
 
 
550be8d
184bd4a
550be8d
184bd4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550be8d
184bd4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550be8d
 
184bd4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON Markdown Renderer</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github.min.css">
    <script src="https://unpkg.com/highlight.js@11.7.0/lib/core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/2.1.0/showdown.min.js"></script>
    
    <style>
        .markdown-body {
            box-sizing: border-box;
            min-width: 200px;
            max-width: 980px;
            margin: 0 auto;
            padding: 45px;
        }
        
        @media (max-width: 767px) {
            .markdown-body {
                padding: 15px;
            }
        }
        
        .hidden {
            display: none;
        }
        
        .dropzone {
            border: 2px dashed #6b7280;
            transition: all 0.3s ease;
        }
        
        .dropzone.active {
            border-color: #3b82f6;
            background-color: rgba(59, 130, 246, 0.05);
        }
        
        pre {
            border-radius: 6px;
            overflow-x: auto;
            padding: 16px;
            background-color: #f6f8fa;
        }
        
        code {
            font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
        }
    </style>
</head>
<body class="bg-gray-50 min-h-screen">
    <div class="container mx-auto px-4 py-8">
        <div class="max-w-4xl mx-auto">
            <header class="text-center mb-10">
                <h1 class="text-3xl font-bold text-gray-800 mb-2">JSON Markdown Renderer</h1>
                <p class="text-gray-600">Upload a JSON file containing markdown content and see it rendered beautifully</p>
            </header>
            
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 transition-all duration-300">
                <div id="upload-container" class="p-8">
                    <div id="dropzone" class="dropzone rounded-lg p-12 text-center cursor-pointer mb-6">
                        <div class="mx-auto w-16 h-16 text-blue-500 mb-4">
                            <i class="fas fa-cloud-upload-alt text-5xl"></i>
                        </div>
                        <h3 class="text-lg font-medium text-gray-700 mb-1">Drag & drop your JSON file here</h3>
                        <p class="text-sm text-gray-500 mb-4">or</p>
                        <label for="file-upload" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors cursor-pointer">
                            <span class="font-medium">Browse Files</span>
                            <input id="file-upload" type="file" accept=".json,application/json" class="hidden">
                        </label>
                        <p class="text-xs text-gray-500 mt-4">Supports single JSON file with markdown content</p>
                    </div>
                    
                    <div class="text-center">
                        <p class="text-gray-500 mb-2">Don't have a JSON file? Try with our sample:</p>
                        <button id="sample-btn" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors">
                            <i class="fas fa-file-alt mr-2"></i> Load Sample JSON
                        </button>
                    </div>
                </div>
                
                <div id="error-container" class="hidden p-4 bg-red-50 text-red-700 rounded-md mb-4">
                    <div class="flex items-center">
                        <i class="fas fa-exclamation-circle mr-2"></i>
                        <span id="error-message"></span>
                    </div>
                </div>
            </div>
            
            <div id="result-container" class="hidden bg-white rounded-xl shadow-md overflow-hidden transition-all duration-300">
                <div class="border-b border-gray-200 px-6 py-4 flex justify-between items-center bg-gray-50">
                    <h2 class="text-lg font-medium text-gray-800">Rendered Markdown</h2>
                    <button id="back-btn" class="px-3 py-1 bg-gray-200 text-gray-700 rounded-md text-sm hover:bg-gray-300 transition-colors">
                        <i class="fas fa-arrow-left mr-1"></i> Back
                    </button>
                </div>
                <div id="markdown-content" class="markdown-body p-6">
                    <!-- Markdown content will be rendered here -->
                </div>
            </div>
        </div>
    </div>
    
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            
            // Get DOM elements
            const dropzone = document.getElementById('dropzone');
            const fileUpload = document.getElementById('file-upload');
            const uploadContainer = document.getElementById('upload-container');
            const resultContainer = document.getElementById('result-container');
            const markdownContent = document.getElementById('markdown-content');
            const backBtn = document.getElementById('back-btn');
            const sampleBtn = document.getElementById('sample-btn');
            const errorContainer = document.getElementById('error-container');
            const errorMessage = document.getElementById('error-message');
            
            // Handle drag and drop events
            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                dropzone.addEventListener(eventName, preventDefaults, false);
            });
            
            function preventDefaults(e) {
                e.preventDefault();
                e.stopPropagation();
            }
            
            ['dragenter', 'dragover'].forEach(eventName => {
                dropzone.addEventListener(eventName, highlight, false);
            });
            
            ['dragleave', 'drop'].forEach(eventName => {
                dropzone.addEventListener(eventName, unhighlight, false);
            });
            
            function highlight() {
                dropzone.classList.add('active');
            }
            
            function unhighlight() {
                dropzone.classList.remove('active');
            }
            
            // Handle file drop
            dropzone.addEventListener('drop', handleDrop, false);
            
            function handleDrop(e) {
                const dt = e.dataTransfer;
                const files = dt.files;
                
                if (files.length > 0) {
                    handleFiles(files);
                }
            }
            
            // Handle file selection via input
            fileUpload.addEventListener('change', function() {
                if (this.files.length > 0) {
                    handleFiles(this.files);
                }
            });
            
            // Handle back button
            backBtn.addEventListener('click', function() {
                resultContainer.classList.add('hidden');
                uploadContainer.classList.remove('hidden');
                markdownContent.innerHTML = '';
                fileUpload.value = '';
            });
            
            // Handle sample button
            sampleBtn.addEventListener('click', renderSample);
            
            // Process uploaded files
            function handleFiles(files) {
                const file = files[0];
                
                if (file.type !== 'application/json' && !file.name.endsWith('.json')) {
                    showError('Please upload a valid JSON file.');
                    return;
                }
                
                const reader = new FileReader();
                
                reader.onload = function(e) {
                    try {
                        const jsonData = JSON.parse(e.target.result);
                        processJsonData(jsonData);
                    } catch (error) {
                        showError('Invalid JSON content: ' + error.message);
                    }
                };
                
                reader.onerror = function() {
                    showError('Error reading the file.');
                };
                
                reader.readAsText(file);
            }
            
            // Process JSON data and render markdown
            function processJsonData(jsonData) {
                hideError();
                
                // Find the first markdown string in the JSON
                let markdownText = findFirstMarkdownString(jsonData);
                
                if (!markdownText) {
                    showError('No markdown content found in the JSON file.');
                    return;
                }
                
                // Show loading state
                markdownContent.innerHTML = '<div class="text-center py-8"><i class="fas fa-spinner fa-spin text-3xl text-blue-500"></i><p class="mt-4 text-gray-600">Rendering markdown...</p></div>';
                
                // Process markdown with Showdown.js
                const converter = new showdown.Converter();
                const html = converter.makeHtml(markdownText);
                markdownContent.innerHTML = html;
                
                // Switch to result view
                uploadContainer.classList.add('hidden');
                resultContainer.classList.remove('hidden');
            }
            
            // Recursively find the first string that looks like markdown
            function findFirstMarkdownString(obj) {
                if (typeof obj === 'string') {
                    // Check if this looks like markdown
                    if (obj.includes('##') || obj.includes('*') || obj.includes('`') || obj.includes('![')) {
                        return obj;
                    }
                } else if (Array.isArray(obj)) {
                    for (let item of obj) {
                        const result = findFirstMarkdownString(item);
                        if (result) return result;
                    }
                } else if (typeof obj === 'object' && obj !== null) {
                    for (let key in obj) {
                        const result = findFirstMarkdownString(obj[key]);
                        if (result) return result;
                    }
                }
                return null;
            }
            
            // Display sample markdown
            function renderSample() {
                const sampleJson = {
                    "document": {
                        "title": "Sample Markdown",
                        "content": `# Welcome to JSON Markdown Renderer

This is a **sample markdown** content rendered from JSON.

## Features

- Render markdown from JSON files
- Drag and drop interface
- Syntax highlighting for code blocks
- Mobile responsive design

### Code Example

\`\`\`javascript
function greet(name) {
    return 'Hello, ' + name + '!';
}

console.log(greet('World'));
\`\`\`

## Usage

1. Upload a JSON file containing markdown content
2. The system will extract and render the markdown
3. Enjoy beautifully formatted content!

[Learn more about Markdown](https://www.markdownguide.org)`,
                        "metadata": {
                            "author": "John Doe",
                            "created": "2023-06-01"
                        }
                    }
                };
                
                processJsonData(sampleJson);
            }
            
            // Show error message
            function showError(message) {
                errorMessage.textContent = message;
                errorContainer.classList.remove('hidden');
            }
            
            // Hide error message
            function hideError() {
                errorContainer.classList.add('hidden');
            }
        });
    </script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=tatht/render-markdown" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>