mdts 0.6.0 → 0.7.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/dist/cli.js +3 -0
- package/dist/frontend/bundle.js +1028 -115
- package/dist/server/routes/filetree.js +8 -8
- package/dist/server/routes/outline.js +22 -22
- package/dist/server/server.js +3 -69
- package/dist/server/watcher.js +136 -0
- package/package.json +4 -3
|
@@ -7,6 +7,14 @@ exports.fileTreeRouter = void 0;
|
|
|
7
7
|
const express_1 = require("express");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fileTreeRouter = (directory) => {
|
|
11
|
+
const router = (0, express_1.Router)();
|
|
12
|
+
router.get('/', (req, res) => {
|
|
13
|
+
res.json({ fileTree: getFileTree(directory, ''), mountedDirectoryPath: directory });
|
|
14
|
+
});
|
|
15
|
+
return router;
|
|
16
|
+
};
|
|
17
|
+
exports.fileTreeRouter = fileTreeRouter;
|
|
10
18
|
const isDotFileOrDirectory = (entryName) => {
|
|
11
19
|
return entryName.startsWith('.');
|
|
12
20
|
};
|
|
@@ -32,11 +40,3 @@ const getFileTree = (baseDirectory, currentRelativePath) => {
|
|
|
32
40
|
}
|
|
33
41
|
return tree;
|
|
34
42
|
};
|
|
35
|
-
const fileTreeRouter = (directory) => {
|
|
36
|
-
const router = (0, express_1.Router)();
|
|
37
|
-
router.get('/', (req, res) => {
|
|
38
|
-
res.json({ fileTree: getFileTree(directory, ''), mountedDirectoryPath: directory });
|
|
39
|
-
});
|
|
40
|
-
return router;
|
|
41
|
-
};
|
|
42
|
-
exports.fileTreeRouter = fileTreeRouter;
|
|
@@ -43,6 +43,28 @@ const markdown_it_1 = __importDefault(require("markdown-it"));
|
|
|
43
43
|
const path_1 = __importDefault(require("path"));
|
|
44
44
|
const logger_1 = require("../../utils/logger");
|
|
45
45
|
const md = new markdown_it_1.default();
|
|
46
|
+
const outlineRouter = (directory) => {
|
|
47
|
+
const router = (0, express_1.Router)();
|
|
48
|
+
router.get('/', (req, res) => {
|
|
49
|
+
const filePath = req.query.filePath;
|
|
50
|
+
if (!filePath) {
|
|
51
|
+
return res.status(400).send('filePath query parameter is required.');
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const absolutePath = filePath === 'mdts-welcome-markdown.md'
|
|
55
|
+
? path_1.default.join(__dirname, '../public/welcome.md')
|
|
56
|
+
: path_1.default.join(directory, filePath);
|
|
57
|
+
const outline = getMarkdownOutline(absolutePath);
|
|
58
|
+
res.json(outline);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger_1.logger.error(`Error getting outline for ${filePath}:`, error);
|
|
62
|
+
res.status(500).send('Error getting outline.');
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return router;
|
|
66
|
+
};
|
|
67
|
+
exports.outlineRouter = outlineRouter;
|
|
46
68
|
const slugify = (text) => {
|
|
47
69
|
return text
|
|
48
70
|
.toLowerCase()
|
|
@@ -71,25 +93,3 @@ const getMarkdownOutline = (filePath) => {
|
|
|
71
93
|
}
|
|
72
94
|
return outline;
|
|
73
95
|
};
|
|
74
|
-
const outlineRouter = (directory) => {
|
|
75
|
-
const router = (0, express_1.Router)();
|
|
76
|
-
router.get('/', (req, res) => {
|
|
77
|
-
const filePath = req.query.filePath;
|
|
78
|
-
if (!filePath) {
|
|
79
|
-
return res.status(400).send('filePath query parameter is required.');
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
const absolutePath = filePath === 'mdts-welcome-markdown.md'
|
|
83
|
-
? path_1.default.join(__dirname, '../public/welcome.md')
|
|
84
|
-
: path_1.default.join(directory, filePath);
|
|
85
|
-
const outline = getMarkdownOutline(absolutePath);
|
|
86
|
-
res.json(outline);
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
logger_1.logger.error(`Error getting outline for ${filePath}:`, error);
|
|
90
|
-
res.status(500).send('Error getting outline.');
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
return router;
|
|
94
|
-
};
|
|
95
|
-
exports.outlineRouter = outlineRouter;
|
package/dist/server/server.js
CHANGED
|
@@ -46,20 +46,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.createApp = exports.serve = void 0;
|
|
49
|
-
const chokidar_1 = __importDefault(require("chokidar"));
|
|
50
49
|
const express_1 = __importDefault(require("express"));
|
|
51
50
|
const fs = __importStar(require("fs"));
|
|
52
51
|
const path_1 = __importDefault(require("path"));
|
|
53
|
-
const
|
|
52
|
+
const logger_1 = require("../utils/logger");
|
|
54
53
|
const filetree_1 = require("./routes/filetree");
|
|
55
54
|
const outline_1 = require("./routes/outline");
|
|
56
|
-
const
|
|
55
|
+
const watcher_1 = require("./watcher");
|
|
57
56
|
const serve = (directory, port) => {
|
|
58
57
|
const app = (0, exports.createApp)(directory);
|
|
59
58
|
const server = app.listen(port, () => {
|
|
60
59
|
logger_1.logger.log(`🚀 Server listening at http://localhost:${port}`);
|
|
61
60
|
});
|
|
62
|
-
setupWatcher(directory, server, port);
|
|
61
|
+
(0, watcher_1.setupWatcher)(directory, server, port);
|
|
63
62
|
return server;
|
|
64
63
|
};
|
|
65
64
|
exports.serve = serve;
|
|
@@ -129,68 +128,3 @@ const createApp = (directory, currentLocation = __dirname) => {
|
|
|
129
128
|
return app;
|
|
130
129
|
};
|
|
131
130
|
exports.createApp = createApp;
|
|
132
|
-
const setupWatcher = (directory, server, port) => {
|
|
133
|
-
const wss = new ws_1.WebSocketServer({ server });
|
|
134
|
-
wss.on('listening', () => {
|
|
135
|
-
logger_1.logger.log(`🚀 WebSocket server listening at ws://localhost:${port}`);
|
|
136
|
-
});
|
|
137
|
-
wss.on('connection', () => {
|
|
138
|
-
logger_1.logger.log('🤝 Livereload Client connected');
|
|
139
|
-
wss.on('close', () => {
|
|
140
|
-
logger_1.logger.log('👋 Livereload Client closed');
|
|
141
|
-
});
|
|
142
|
-
wss.on('wsClientError', (e) => {
|
|
143
|
-
logger_1.logger.error('🚫 Error on WebSocket server:', e);
|
|
144
|
-
});
|
|
145
|
-
wss.on('error', (e) => {
|
|
146
|
-
logger_1.logger.error('🚫 Error on WebSocket server:', e);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
const isMarkdownOrSimpleAsset = (filePath) => {
|
|
150
|
-
const ext = filePath.toLowerCase().split('.').pop();
|
|
151
|
-
return ext && (ext === 'md' || ext === 'markdown');
|
|
152
|
-
};
|
|
153
|
-
let watcher = null;
|
|
154
|
-
try {
|
|
155
|
-
watcher = chokidar_1.default.watch(directory, {
|
|
156
|
-
ignored: (watchedFilePath) => {
|
|
157
|
-
if (watchedFilePath.includes('node_modules')) {
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
if (fs.statSync(watchedFilePath).isDirectory()) {
|
|
162
|
-
return false; // Don't ignore directories
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch (_a) {
|
|
166
|
-
// On error (e.g., file not found), let chokidar handle it
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
return !isMarkdownOrSimpleAsset(watchedFilePath);
|
|
170
|
-
},
|
|
171
|
-
ignoreInitial: true,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
catch (e) {
|
|
175
|
-
logger_1.logger.error('🚫 Error watching directory:', e);
|
|
176
|
-
logger_1.logger.error('Livereload will be disabled');
|
|
177
|
-
}
|
|
178
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.on('change', (filePath) => {
|
|
179
|
-
logger_1.logger.log(`🔃 File changed: ${filePath}, reloading...`);
|
|
180
|
-
wss.clients.forEach((client) => {
|
|
181
|
-
client.send(JSON.stringify({ type: 'reload-content' }));
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.on('add', (filePath) => {
|
|
185
|
-
logger_1.logger.log(`🌲 File added: ${filePath}, reloading tree...`);
|
|
186
|
-
wss.clients.forEach((client) => {
|
|
187
|
-
client.send(JSON.stringify({ type: 'reload-tree' }));
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.on('unlink', (filePath) => {
|
|
191
|
-
logger_1.logger.log(`🌲 File removed: ${filePath}, reloading tree...`);
|
|
192
|
-
wss.clients.forEach((client) => {
|
|
193
|
-
client.send(JSON.stringify({ type: 'reload-tree' }));
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.setupWatcher = void 0;
|
|
40
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const ws_1 = require("ws");
|
|
43
|
+
const logger_1 = require("../utils/logger");
|
|
44
|
+
let contentWatcher = null;
|
|
45
|
+
let currentWatchedFile = null;
|
|
46
|
+
const setupWatcher = (directory, server, port) => {
|
|
47
|
+
const wss = new ws_1.WebSocketServer({ server });
|
|
48
|
+
wss.on('listening', () => {
|
|
49
|
+
logger_1.logger.log(`🚀 WebSocket server listening at ws://localhost:${port}`);
|
|
50
|
+
});
|
|
51
|
+
wss.on('connection', (ws) => {
|
|
52
|
+
logger_1.logger.log('🤝 Livereload Client connected');
|
|
53
|
+
ws.on('message', (message) => handleWebSocketMessage(ws, message.toString()));
|
|
54
|
+
ws.on('close', () => handleWebSocketClose(wss));
|
|
55
|
+
ws.on('error', (e) => logger_1.logger.error('🚫 Error on WebSocket client:', e));
|
|
56
|
+
});
|
|
57
|
+
setupDirectoryWatcher(directory, wss);
|
|
58
|
+
};
|
|
59
|
+
exports.setupWatcher = setupWatcher;
|
|
60
|
+
const handleWebSocketMessage = (ws, message) => {
|
|
61
|
+
try {
|
|
62
|
+
const data = JSON.parse(message);
|
|
63
|
+
if (data.type === 'watch-file' && typeof data.filePath === 'string') {
|
|
64
|
+
setupContentWatcher(ws, data.filePath);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
logger_1.logger.error('🚫 Error parsing WebSocket message:', e);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const handleWebSocketClose = (wss) => {
|
|
72
|
+
logger_1.logger.log('👋 Livereload Client closed');
|
|
73
|
+
if (wss.clients.size === 0) {
|
|
74
|
+
contentWatcher === null || contentWatcher === void 0 ? void 0 : contentWatcher.close();
|
|
75
|
+
contentWatcher = null;
|
|
76
|
+
currentWatchedFile = null;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const setupDirectoryWatcher = (directory, wss) => {
|
|
80
|
+
try {
|
|
81
|
+
const watcher = chokidar_1.default.watch(directory, {
|
|
82
|
+
ignored: (watchedFilePath) => {
|
|
83
|
+
if (watchedFilePath.includes('node_modules')) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
if (fs.statSync(watchedFilePath).isDirectory()) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (_a) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return !isMarkdownOrSimpleAsset(watchedFilePath);
|
|
95
|
+
},
|
|
96
|
+
ignoreInitial: true,
|
|
97
|
+
});
|
|
98
|
+
watcher.on('add', (filePath) => {
|
|
99
|
+
logger_1.logger.log(`🌲 File added: ${filePath}, reloading tree...`);
|
|
100
|
+
wss.clients.forEach((client) => {
|
|
101
|
+
client.send(JSON.stringify({ type: 'reload-tree' }));
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
watcher.on('unlink', (filePath) => {
|
|
105
|
+
logger_1.logger.log(`🌲 File removed: ${filePath}, reloading tree...`);
|
|
106
|
+
wss.clients.forEach((client) => {
|
|
107
|
+
client.send(JSON.stringify({ type: 'reload-tree' }));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
return watcher;
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
logger_1.logger.error('🚫 Error watching directory:', e);
|
|
114
|
+
logger_1.logger.error('Livereload will be disabled');
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const setupContentWatcher = (ws, filePath) => {
|
|
119
|
+
if (filePath !== currentWatchedFile) {
|
|
120
|
+
logger_1.logger.log(`👀 Watching file: ${filePath}`);
|
|
121
|
+
currentWatchedFile = filePath;
|
|
122
|
+
contentWatcher === null || contentWatcher === void 0 ? void 0 : contentWatcher.close(); // Close existing content watcher if any
|
|
123
|
+
contentWatcher = chokidar_1.default.watch(filePath, { ignoreInitial: true });
|
|
124
|
+
contentWatcher.on('change', (changedFilePath) => {
|
|
125
|
+
logger_1.logger.log(`🔃 File changed: ${changedFilePath}, reloading content...`);
|
|
126
|
+
ws.send(JSON.stringify({ type: 'reload-content' }));
|
|
127
|
+
});
|
|
128
|
+
contentWatcher.on('error', (e) => {
|
|
129
|
+
logger_1.logger.error(`🚫 Error watching content file ${filePath}:`, e);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const isMarkdownOrSimpleAsset = (filePath) => {
|
|
134
|
+
const ext = filePath.toLowerCase().split('.').pop();
|
|
135
|
+
return !!ext && (ext === 'md' || ext === 'markdown');
|
|
136
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A markdown preview server.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc && cp -R public/. dist/server/public",
|
|
15
|
-
"build:frontend": "cd packages/frontend && npm run build
|
|
15
|
+
"build:frontend": "cd packages/frontend && npm run build",
|
|
16
16
|
"jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.js",
|
|
17
17
|
"watch": "npm run jest -- --watch",
|
|
18
18
|
"test": "npm run jest -- --selectProjects test",
|
|
19
19
|
"lint": "npm run jest -- --selectProjects lint",
|
|
20
|
-
"start": "npm run build && npm run build:frontend && node dist/index.js"
|
|
20
|
+
"start": "npm run build && npm run build:frontend && node dist/index.js",
|
|
21
|
+
"dev": "npm run build && npm run build:frontend && tsc --watch --preserveWatchOutput & cd packages/frontend && npm run build -- --watch & node dist/index.js"
|
|
21
22
|
},
|
|
22
23
|
"repository": {
|
|
23
24
|
"type": "git",
|