mdts 0.4.4 → 0.5.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.
@@ -54,22 +54,71 @@
54
54
  }
55
55
 
56
56
  hr {
57
- color: rgba(0, 0, 0, .12);
57
+ margin: 48px 0;
58
+ border: 0;
59
+ border-bottom: 1px solid rgba(0, 0, 0, .12);
58
60
  }
59
61
 
60
62
  img {
61
63
  max-width: 100%;
62
64
  }
63
65
 
66
+ table {
67
+ display: block;
68
+ margin: 48px 0;
69
+ width: max-content;
70
+ overflow: auto;
71
+ border-spacing: 0;
72
+ border-collapse: collapse;
73
+
74
+ thead {
75
+ text-align: left;
76
+ }
77
+
78
+ tr {
79
+ border-top: 1px solid rgba(0, 0, 0, .12);
80
+ }
81
+
82
+ td, th {
83
+ padding: 6px 12px;
84
+ border: 1px solid rgba(0, 0, 0, .12);
85
+ }
86
+ }
87
+
64
88
  pre {
65
89
  padding: 16px;
66
90
  overflow: auto;
67
91
  background-color: #f4f5f7;
92
+
93
+ code {
94
+ padding: 0;
95
+ font-size: 100%;
96
+ word-break: normal;
97
+ white-space: pre;
98
+ background: transparent;
99
+ border: 0;
100
+ }
101
+ }
102
+
103
+ code {
104
+ display: inline-block;
105
+ padding: .1em .6em;
106
+ margin: 0;
107
+ font-size: 80%;
108
+ background-color: #f4f5f7;
109
+ border-radius: 2px;
68
110
  }
69
111
 
70
112
  blockquote {
113
+ margin: 24px 0;
71
114
  padding: 5px 16px;
72
115
  font-size: 14px;
116
+ color: rgba(0, 0, 0, .24);
117
+ border-left: 4px solid rgba(0, 0, 0, .12);
118
+
119
+ blockquote {
120
+ margin: 12px 0;
121
+ }
73
122
 
74
123
  p {
75
124
  margin: 0;
@@ -89,18 +138,37 @@
89
138
 
90
139
  .markdown-body.dark {
91
140
  h1 {
92
- border-bottom: 1px solid rgba(255, 255, 255, .12);
141
+ border-color: rgba(255, 255, 255, .12);
93
142
  }
94
143
 
95
144
  h2 {
96
- border-bottom: 1px solid rgba(255, 255, 255, .12);
145
+ border-color: rgba(255, 255, 255, .12);
146
+ }
147
+
148
+ table {
149
+ tr {
150
+ border-color: rgba(255, 255, 255, .12);
151
+ }
152
+
153
+ td, th {
154
+ border-color: rgba(255, 255, 255, .12);
155
+ }
97
156
  }
98
157
 
99
158
  pre {
100
159
  background-color: #20252c;
101
160
  }
102
161
 
162
+ code {
163
+ background-color: #20252c;
164
+ }
165
+
166
+ blockquote {
167
+ color: rgba(255, 255, 255, .24);
168
+ border-color: rgba(255, 255, 255, .12);
169
+ }
170
+
103
171
  hr {
104
- color: rgba(255, 255, 255, .12);
172
+ border-color: rgba(255, 255, 255, .12);
105
173
  }
106
174
  }
@@ -1,5 +1,5 @@
1
1
  <h1 align="center">
2
- <img src="./logo.svg" alt="mdts" width="400">
2
+ <img src="/logo.svg" alt="mdts" width="400">
3
3
  </h1>
4
4
 
5
5
  mdts (Markdown Tree Server) is a simple and efficient tool for serving and viewing markdown files with an interactive file tree and outline. It's designed to help you navigate and read your markdown-based documentation or notes with ease.
@@ -35,7 +35,7 @@ const getFileTree = (baseDirectory, currentRelativePath) => {
35
35
  const fileTreeRouter = (directory) => {
36
36
  const router = (0, express_1.Router)();
37
37
  router.get('/', (req, res) => {
38
- res.json(getFileTree(directory, ''));
38
+ res.json({ fileTree: getFileTree(directory, ''), mountedDirectoryPath: directory });
39
39
  });
40
40
  return router;
41
41
  };
@@ -1,11 +1,44 @@
1
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
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.outlineRouter = void 0;
7
40
  const express_1 = require("express");
8
- const fs_1 = __importDefault(require("fs"));
41
+ const fs = __importStar(require("fs"));
9
42
  const markdown_it_1 = __importDefault(require("markdown-it"));
10
43
  const path_1 = __importDefault(require("path"));
11
44
  const md = new markdown_it_1.default();
@@ -18,7 +51,10 @@ const slugify = (text) => {
18
51
  .replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens
19
52
  };
20
53
  const getMarkdownOutline = (filePath) => {
21
- const fileContent = fs_1.default.readFileSync(filePath, 'utf-8');
54
+ if (!fs.existsSync(filePath)) {
55
+ return [];
56
+ }
57
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
22
58
  const tokens = md.parse(fileContent, {});
23
59
  const outline = [];
24
60
  for (const token of tokens) {
@@ -1,4 +1,37 @@
1
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
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -15,7 +48,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
48
  exports.createApp = exports.serve = void 0;
16
49
  const chokidar_1 = __importDefault(require("chokidar"));
17
50
  const express_1 = __importDefault(require("express"));
18
- const fs_1 = require("fs");
51
+ const fs = __importStar(require("fs"));
19
52
  const path_1 = __importDefault(require("path"));
20
53
  const ws_1 = require("ws");
21
54
  const filetree_1 = require("./routes/filetree");
@@ -25,7 +58,7 @@ const serve = (directory, port) => {
25
58
  const server = app.listen(port, () => {
26
59
  console.log(`🚀 Server listening at http://localhost:${port}`);
27
60
  });
28
- setupWatcher(directory, server);
61
+ setupWatcher(directory, server, port);
29
62
  return server;
30
63
  };
31
64
  exports.serve = serve;
@@ -41,13 +74,21 @@ const createApp = (directory, currentLocation = __dirname) => {
41
74
  res.setHeader('Content-Type', 'text/plain');
42
75
  res.sendFile(path_1.default.join(currentLocation, './public/welcome.md'));
43
76
  });
77
+ app.use('/api/markdown', (req, res, next) => {
78
+ const filePath = path_1.default.join(directory, req.path);
79
+ if (!fs.existsSync(filePath)) {
80
+ console.error(`🚫 File not found: ${filePath}`);
81
+ return res.status(404).send('File not found');
82
+ }
83
+ next();
84
+ });
44
85
  app.use('/api/markdown', express_1.default.static(directory));
45
86
  // Catch-all route to serve index.html for any other requests
46
87
  app.get('*', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
47
88
  const filePath = path_1.default.join(directory, req.path);
48
89
  let isDirectory = false;
49
90
  try {
50
- const stats = yield fs_1.promises.stat(filePath);
91
+ const stats = fs.statSync(filePath);
51
92
  isDirectory = stats.isDirectory();
52
93
  }
53
94
  catch (_a) {
@@ -59,32 +100,60 @@ const createApp = (directory, currentLocation = __dirname) => {
59
100
  return res.sendFile(path_1.default.join(currentLocation, '../frontend/index.html'));
60
101
  }
61
102
  else {
62
- return res.sendFile(req.path, { root: directory });
103
+ return res.sendFile(req.path, { root: directory }, (err) => {
104
+ if (err) {
105
+ if ('code' in err && err.code === 'ENOENT') {
106
+ console.error(`🚫 File not found: ${path_1.default.join(directory, req.path)}`);
107
+ res.status(404).send('File not found');
108
+ }
109
+ else {
110
+ console.error(`🚫 Error serving file ${path_1.default.join(directory, req.path)}:`, err);
111
+ res.status(500).send('Internal Server Error');
112
+ }
113
+ }
114
+ });
63
115
  }
64
116
  }));
65
117
  return app;
66
118
  };
67
119
  exports.createApp = createApp;
68
- const setupWatcher = (directory, server) => {
120
+ const setupWatcher = (directory, server, port) => {
69
121
  const wss = new ws_1.WebSocketServer({ server });
122
+ wss.on('listening', () => {
123
+ console.log(`🚀 WebSocket server listening at ws://localhost:${port}`);
124
+ });
125
+ wss.on('connection', () => {
126
+ console.log('🤝 Livereload Client connected');
127
+ wss.on('close', () => {
128
+ console.log('👋 Livereload Client closed');
129
+ });
130
+ wss.on('wsClientError', (e) => {
131
+ console.error('🚫 Error on WebSocket server:', e);
132
+ });
133
+ wss.on('error', (e) => {
134
+ console.error('🚫 Error on WebSocket server:', e);
135
+ });
136
+ });
70
137
  const isMarkdownOrSimpleAsset = (filePath) => {
71
138
  const ext = filePath.toLowerCase().split('.').pop();
72
- return (ext &&
73
- (ext === 'md' ||
74
- ext === 'markdown' ||
75
- ext === 'png' ||
76
- ext === 'jpg' ||
77
- ext === 'jpeg' ||
78
- ext === 'gif' ||
79
- ext === 'svg'));
139
+ return ext && (ext === 'md' || ext === 'markdown');
80
140
  };
81
- let watcher;
141
+ let watcher = null;
82
142
  try {
83
143
  watcher = chokidar_1.default.watch(directory, {
84
144
  ignored: (watchedFilePath) => {
85
145
  if (watchedFilePath.includes('node_modules')) {
86
146
  return true;
87
147
  }
148
+ try {
149
+ if (fs.statSync(watchedFilePath).isDirectory()) {
150
+ return false; // Don't ignore directories
151
+ }
152
+ }
153
+ catch (_a) {
154
+ // On error (e.g., file not found), let chokidar handle it
155
+ return false;
156
+ }
88
157
  return !isMarkdownOrSimpleAsset(watchedFilePath);
89
158
  },
90
159
  ignoreInitial: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdts",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "A markdown preview server.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",