dochub 1.0.3 → 2.0.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.
@@ -1,3 +1,75 @@
1
- # Guide
2
-
3
- This is a guide.
1
+ # Writing Guide
2
+
3
+ This guide covers the Markdown syntax and features available in DocHub.
4
+
5
+ ## Text Formatting
6
+
7
+ **Bold text** and *italic text* are supported. You can also use ~~strikethrough~~ and `inline code`.
8
+
9
+ ## Code Blocks
10
+
11
+ Code blocks with syntax highlighting are supported for over 190 languages:
12
+
13
+ ```javascript
14
+ function fibonacci(n) {
15
+ if (n <= 1) return n;
16
+ return fibonacci(n - 1) + fibonacci(n - 2);
17
+ }
18
+
19
+ console.log(fibonacci(10)); // 55
20
+ ```
21
+
22
+ ```python
23
+ def fibonacci(n):
24
+ if n <= 1:
25
+ return n
26
+ return fibonacci(n - 1) + fibonacci(n - 2)
27
+
28
+ print(fibonacci(10)) # 55
29
+ ```
30
+
31
+ ```rust
32
+ fn fibonacci(n: u32) -> u32 {
33
+ match n {
34
+ 0 | 1 => n,
35
+ _ => fibonacci(n - 1) + fibonacci(n - 2),
36
+ }
37
+ }
38
+
39
+ fn main() {
40
+ println!("{}", fibonacci(10)); // 55
41
+ }
42
+ ```
43
+
44
+ ## Lists
45
+
46
+ ### Unordered
47
+
48
+ - Item one
49
+ - Item two
50
+ - Nested item
51
+ - Another nested item
52
+ - Item three
53
+
54
+ ### Ordered
55
+
56
+ 1. First step
57
+ 2. Second step
58
+ 3. Third step
59
+
60
+ ## Blockquotes
61
+
62
+ > This is a blockquote. It can span multiple lines and is useful for highlighting important information or callouts.
63
+
64
+ ## Tables
65
+
66
+ | Feature | Status | Version |
67
+ |---------|--------|---------|
68
+ | Live reload | Done | 2.0.0 |
69
+ | Static build | Done | 2.0.0 |
70
+ | Full-text search | Done | 2.0.0 |
71
+ | Dark mode | Done | 2.0.0 |
72
+
73
+ ## Links
74
+
75
+ Visit the [DocHub GitHub repository](https://github.com/tyler-Github/dochub) for more information.
@@ -1,271 +0,0 @@
1
- const http = require('http');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const hljs = require('highlight.js');
5
- const socketio = require('socket.io');
6
-
7
- let htmlContent = ''; // Variable to store HTML content
8
-
9
- const configPath = path.join(__dirname, 'config.json');
10
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
11
- const projectTitle = config.title || 'Documentation Project';
12
-
13
- // Function to convert Markdown to HTML
14
- function convertMarkdownToHtml(markdownContent, filePath) {
15
- // Regular expression to match Markdown code blocks
16
- const codeBlockRegex = /```(\w+)\n([\s\S]*?)```/g;
17
-
18
- // Basic conversion: Replace Markdown syntax with HTML equivalents
19
- let htmlContent = markdownContent
20
- // Code blocks
21
- .replace(codeBlockRegex, (match, language, code) => {
22
- const validLanguage = language || 'plaintext'; // Default to plaintext if no language specified
23
- const highlightedCode = hljs.highlight(code, { language: validLanguage }).value;
24
- // Count the number of lines in the code content
25
- const lines = code.split('\n').length;
26
- return `<pre class="bg-gray-800 text-white p-4 rounded-md mb-4 code-block" style="height: ${lines * 1.5}rem;"><code class="language-${validLanguage}" data-lines="${lines}">${highlightedCode}</code></pre>`;
27
- })
28
- // Inline code
29
- .replace(/`([^`]*)`/g, '<code class="bg-gray-800 text-white rounded px-1">$1</code>')
30
- // Headers, emphasis, lists, links
31
- .replace(/^# (.*)$/gm, '<h1 class="text-4xl font-bold mt-8 mb-4">$1</h1>')
32
- .replace(/^## (.*)$/gm, '<h2 class="text-3xl font-bold mt-6 mb-3">$1</h2>')
33
- .replace(/^### (.*)$/gm, '<h3 class="text-2xl font-bold mt-4 mb-2">$1</h3>')
34
- .replace(/^#### (.*)$/gm, '<h4 class="text-xl font-bold mt-3 mb-2">$1</h4>')
35
- .replace(/^##### (.*)$/gm, '<h5 class="text-lg font-bold mt-3 mb-2">$1</h5>')
36
- .replace(/^###### (.*)$/gm, '<h6 class="text-base font-bold mt-2 mb-2">$1</h6>')
37
- .replace(/\*\*(.*)\*\*/g, '<strong class="font-bold">$1</strong>')
38
- .replace(/\*(.*)\*/g, '<em class="italic">$1</em>')
39
- .replace(/^\s*-\s(.*)$/gm, '<li class="list-disc ml-4">$1</li>')
40
- .replace(/^\s*\d\.\s(.*)$/gm, '<li class="list-decimal ml-4">$1</li>')
41
- .replace(/<li>(.*)<\/li>/g, '<ul class="list-inside list-disc mb-4">$1</ul>')
42
- .replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" class="text-blue-500 hover:underline">$1</a>')
43
- // Paragraphs and Line breaks
44
- .replace(/\n\n/gm, '</p><p class="mb-6">') // Replace double newline with closing and opening paragraph tags
45
- .replace(/^\s*$/gm, '<p class="mb-6">') // Replace empty lines with opening paragraph tag
46
- .replace(/^/gm, '') // Remove the beginning of each line
47
- .replace(/$/gm, ''); // Remove the end of each line
48
-
49
- // Generate sidebar based on file structure
50
- const sidebar = generateSidebar(path.join(__dirname, 'markdown'));
51
-
52
- // Return the entire HTML structure
53
- return `
54
- <!DOCTYPE html>
55
- <html lang="en">
56
- <head>
57
- <meta charset="UTF-8">
58
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
59
- <title>Markdown to HTML</title>
60
- <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
61
- <link href="https://cdn.jsdelivr.net/npm/highlight.js/styles/vs2015.css" rel="stylesheet">
62
- <style>
63
- /* Dark mode theme */
64
- body {
65
- background-color: #1a202c;
66
- color: #e2e8f0;
67
- }
68
- .bg-gray-200 {
69
- background-color: #2d3748;
70
- }
71
- .text-blue-500 {
72
- color: #90cdf4;
73
- }
74
- .hover\:underline:hover {
75
- text-decoration: underline;
76
- }
77
- /* Adjust sidebar height */
78
- .sidebar {
79
- min-height: 100vh; /* Ensure sidebar stretches to full viewport height */
80
- display: flex;
81
- flex-direction: column;
82
- align-items: flex-start; /* Align items to the start (left) */
83
- justify-content: flex-start; /* Start content from the top */
84
- padding: 20px;
85
- }
86
- .code-block {
87
- color: #e2e8f0; /* Match the body text color */
88
- padding: 1rem;
89
- margin-bottom: 1rem;
90
- border-radius: 0.5rem;
91
- overflow: hidden; /* Prevents scroll bars */
92
- white-space: pre-wrap; /* Preserves white space */
93
- }
94
- .search-bar {
95
- width: 100%;
96
- padding: 0.5rem;
97
- margin-bottom: 1rem;
98
- background-color: #4a5568;
99
- color: #e2e8f0;
100
- border: none;
101
- border-radius: 0.25rem;
102
- outline: none;
103
- }
104
- .search-bar:focus {
105
- background-color: #2d3748;
106
- }
107
- </style>
108
- </head>
109
- <body class="flex bg-gray-100">
110
- <aside class="w-1/5 bg-gray-800 p-4 sidebar">
111
- <h1 class="text-xl font-bold mb-4">${projectTitle}</h1>
112
- <input type="text" id="search-input" class="search-bar" placeholder="Search...">
113
- <ul id="sidebar-list" class="space-y-2">
114
- ${sidebar}
115
- </ul>
116
- </aside>
117
- <main id="main-content" class="w-4/5 p-4 bg-gray-200">
118
- ${htmlContent}
119
- </main>
120
- <script src="https://cdn.socket.io/4.3.1/socket.io.min.js"></script>
121
- <script>
122
- document.addEventListener('DOMContentLoaded', function() {
123
- const socket = io(); // Declare socket variable here
124
-
125
- socket.on('fileChange', function() {
126
- fetchCurrentPageContent();
127
- });
128
-
129
- const codeBlocks = document.querySelectorAll('.code-block');
130
- codeBlocks.forEach(block => {
131
- const code = block.querySelector('code');
132
- const lines = parseInt(code.getAttribute('data-lines'));
133
- const lineHeight = parseInt(getComputedStyle(code).lineHeight);
134
- block.style.height = (lines * lineHeight) + 'px'; // Set height using proper concatenation
135
- });
136
-
137
- // Fetch the sidebar list and handle search input
138
- const sidebarList = document.getElementById('sidebar-list');
139
- if (sidebarList) {
140
- const sidebarItems = sidebarList.getElementsByTagName('li');
141
-
142
- document.getElementById('search-input').addEventListener('input', function() {
143
- const searchValue = this.value.trim().toLowerCase();
144
-
145
- Array.from(sidebarItems).forEach(item => {
146
- const link = item.querySelector('a');
147
- if (link) {
148
- const textContent = link.textContent.trim().toLowerCase();
149
-
150
- if (textContent.includes(searchValue)) {
151
- item.style.display = 'block';
152
- } else {
153
- item.style.display = 'none';
154
- }
155
- }
156
- });
157
- });
158
- } else {
159
- console.error('Sidebar list element not found.');
160
- }
161
- });
162
-
163
- function fetchCurrentPageContent() {
164
- // Fetch the current page's HTML content
165
- fetch(window.location.href)
166
- .then(response => response.text())
167
- .then(html => {
168
- // Replace the entire HTML document with the fetched content
169
- document.open();
170
- document.write(html);
171
- document.close();
172
- })
173
- .catch(error => {
174
- console.error('Error fetching current page content:', error);
175
- });
176
- }
177
- </script>
178
-
179
- </body>
180
- </html>
181
- `;
182
- }
183
-
184
- // Function to generate sidebar links based on directory structure
185
- function generateSidebar(rootDir) {
186
- const generateLinks = (dir, baseUrl, depth = 0) => {
187
- let links = '';
188
- const items = fs.readdirSync(dir);
189
-
190
- items.forEach(item => {
191
- const itemPath = path.join(dir, item);
192
- const relativePath = path.relative(rootDir, itemPath);
193
- const urlPath = baseUrl + '/' + relativePath.replace(/\\/g, '/').replace('.md', '');
194
-
195
- if (fs.statSync(itemPath).isDirectory()) {
196
- // If directory, recursively generate nested list with increased depth
197
- links += `<li class="font-bold ml-${depth * 2}">${item}</li>\n`;
198
- links += `<ul class="ml-4 space-y-2">${generateLinks(itemPath, baseUrl, depth + 1)}</ul>\n`;
199
- } else if (item.endsWith('.md')) {
200
- // If Markdown file, generate list item with link
201
- links += `<li class="ml-${depth * 2}"><a href="${urlPath}" class="text-blue-500 hover:underline">${item.replace('.md', '')}</a></li>\n`;
202
- }
203
- });
204
-
205
- return links;
206
- };
207
-
208
- // Start generating sidebar from root directory
209
- return generateLinks(rootDir, '');
210
- }
211
-
212
- // Create HTTP server
213
- const server = http.createServer((req, res) => {
214
- let filePath = '.' + req.url;
215
-
216
- if (filePath === './' || filePath === './index.html') {
217
- filePath = './README.md'; // Default to README.md for root URL
218
- } else if (!path.extname(filePath)) {
219
- // Append '.md' for paths that do not have an extension
220
- filePath += '.md';
221
- }
222
-
223
- filePath = path.join(__dirname, 'markdown', filePath.replace(/^\//, ''));
224
-
225
- fs.readFile(filePath, (err, data) => {
226
- if (err) {
227
- if (err.code === 'ENOENT') {
228
- res.writeHead(404, { 'Content-Type': 'text/html' });
229
- res.end('<h1>404 Not Found</h1><p>The requested URL was not found on this server.</p>');
230
- } else {
231
- res.writeHead(500, { 'Content-Type': 'text/html' });
232
- res.end('<h1>500 Internal Server Error</h1><p>Sorry, something went wrong.</p>');
233
- }
234
- } else {
235
- let contentType = 'text/html';
236
-
237
- if (filePath.endsWith('.md')) {
238
- // Convert Markdown to HTML
239
- const markdownContent = data.toString();
240
- htmlContent = convertMarkdownToHtml(markdownContent, filePath);
241
-
242
- // Serve HTML with proper Tailwind CSS and sidebar
243
- res.writeHead(200, { 'Content-Type': 'text/html' });
244
- res.end(htmlContent);
245
- } else {
246
- // Serve other file types directly (e.g., CSS files)
247
- res.writeHead(200, { 'Content-Type': contentType });
248
- res.end(data);
249
- }
250
- }
251
- });
252
- });
253
-
254
- // Attach Socket.IO to the HTTP server
255
- const io = socketio(server);
256
-
257
- // Watch changes in the Markdown directory
258
- const markdownDir = path.join(__dirname, 'markdown');
259
- if (fs.existsSync(markdownDir)) {
260
- fs.watch(markdownDir, { recursive: true }, (eventType, filename) => {
261
- console.log(`File ${filename} ${eventType}`);
262
- io.emit('fileChange'); // Emit event to clients when file changes
263
- });
264
- } else {
265
- console.error('Markdown directory does not exist.');
266
- }
267
-
268
- const port = process.env.PORT || 3000;
269
- server.listen(port, () => {
270
- console.log(`Server is running on http://localhost:${port}`);
271
- });