mdts 0.7.1 → 0.8.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/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  <h1 align="center">
2
- <img src="docs/logo.svg" alt="mdts" width="400">
2
+ <img src="docs/images/logo.svg" alt="mdts" width="400">
3
3
  </h1>
4
4
 
5
5
  **A zero-config CLI tool to preview your local Markdown files in a browser.** **`npx mdts` — and you're done.**
6
6
 
7
7
  <p align="center">
8
- <img src="docs/screen_animation.gif" width="600" alt="mdts demo">
8
+ <img src="docs/images/screen_animation.gif" width="640" alt="mdts demo">
9
9
  </p>
10
10
 
11
11
  ## 🔧 Features
@@ -31,14 +31,6 @@ Your current directory becomes a browsable Markdown tree.
31
31
  - Quickly checking README or note folders
32
32
  - Lightweight local Markdown wiki
33
33
 
34
- ## 🖼 Screenshot
35
-
36
- > Browsable file tree + rendered Markdown with live reload
37
-
38
- <p align="center">
39
- <img src="docs/screenshot.png" width="800" alt="mdts screenshot">
40
- </p>
41
-
42
34
  ## 📦 Requirements
43
35
 
44
36
  - Node.js
@@ -47,11 +39,21 @@ Your current directory becomes a browsable Markdown tree.
47
39
  ## 🛠 Options
48
40
 
49
41
  ```bash
50
- npx mdts <directory> --port 3000
42
+ npx mdts <directory> --host 0.0.0.0 --port 3000 --silent
51
43
  ```
52
44
 
53
45
  | Option | Description | Example |
54
- | -------------- | ------------------------------------- | --------|
46
+ | -------------- | ------------------------------------- |---------|
55
47
  | `<directory>` | Specify root directory (default .) | ./docs |
48
+ | `--host` | Host to listen on (default localhost) | 0.0.0.0 |
56
49
  | `--port` | Change the server port (default 8521) | 8000 |
50
+ | `--silent` | Suppress server logs | false |
51
+
52
+ ## 📚 Documentation
57
53
 
54
+ - [Use Cases](docs/usecases.md)
55
+ - [Markdown Features](docs/markdown_features.md)
56
+ - [Frontend Features](docs/frontend_features.md)
57
+ - [Screenshots](docs/screenshots.md)
58
+ - [Comparison with other tools](docs/comparison.md)
59
+ - [FAQ](docs/faq.md)
package/dist/cli.js CHANGED
@@ -20,16 +20,24 @@ class CLI {
20
20
  const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf8'));
21
21
  program
22
22
  .version(packageJson.version)
23
+ .option('-H, --host <host>', 'Host to listen on', 'localhost')
23
24
  .option('-p, --port <port>', 'Port to serve on', String(DEFAULT_PORT))
25
+ .option('-s, --silent', 'Suppress server logs', false)
24
26
  .argument('[directory]', 'Directory to serve', DEFAULT_DIRECTORY)
25
27
  .action((directory, options) => {
28
+ logger_1.logger.setSilent(options.silent);
29
+ logger_1.logger.log('Announcement', '🎉 Thanks for using mdts!');
30
+ logger_1.logger.log('Announcement', '✨ Like it? Star it on GitHub: https://github.com/unhappychoice/mdts');
31
+ logger_1.logger.log('CLI', '⚙ Options: ' + JSON.stringify(options));
26
32
  const port = parseInt(options.port, 10);
33
+ const host = options.host;
27
34
  const absoluteDirectory = path_1.default.resolve(process.cwd(), directory);
28
- (0, server_1.serve)(absoluteDirectory, port);
35
+ (0, server_1.serve)(absoluteDirectory, port, host);
29
36
  const readmePath = path_1.default.join(absoluteDirectory, 'README.md');
30
37
  const initialPath = (0, fs_1.existsSync)(readmePath) ? '/README.md' : '';
31
- logger_1.logger.log(`🌐 Opening browser at http://localhost:${port}${initialPath}...`);
32
- open(`http://localhost:${port}${initialPath}`);
38
+ const displayHost = (host === '0.0.0.0' || host === '::') ? 'localhost' : host;
39
+ logger_1.logger.log('CLI', `🌐 Opening browser at http://${displayHost}:${port}${initialPath}`);
40
+ open(`http://${displayHost}:${port}${initialPath}`);
33
41
  });
34
42
  program.parse(process.argv);
35
43
  });
@@ -19769,7 +19769,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
19769
19769
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19770
19770
 
19771
19771
  "use strict";
19772
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/CssBaseline/CssBaseline.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/styles/ThemeProvider.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/development/chunk-EF7DTUVF.mjs\");\n/* harmony import */ var _hooks_useTheme__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./hooks/useTheme */ \"./src/hooks/useTheme.ts\");\n/* harmony import */ var _hooks_useWebSocket__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./hooks/useWebSocket */ \"./src/hooks/useWebSocket.ts\");\n/* harmony import */ var _Layout__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Layout */ \"./src/Layout.tsx\");\n/* harmony import */ var _store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./store/slices/fileTreeSlice */ \"./src/store/slices/fileTreeSlice.ts\");\n/* harmony import */ var _store_slices_historySlice__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./store/slices/historySlice */ \"./src/store/slices/historySlice.ts\");\n\n\n\n\n\n\n\n\n\nconst App = () => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_3__.useDispatch)();\n const location = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useLocation)();\n const {\n currentPath\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_3__.useSelector)(state => state.history);\n const theme = (0,_hooks_useTheme__WEBPACK_IMPORTED_MODULE_5__.useTheme)();\n (0,_hooks_useWebSocket__WEBPACK_IMPORTED_MODULE_6__.useWebSocket)(currentPath);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_8__.fetchFileTree)());\n }, [dispatch]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {\n dispatch((0,_store_slices_historySlice__WEBPACK_IMPORTED_MODULE_9__.updateHistoryFromLocation)(location.pathname));\n }, [location, dispatch]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n theme: theme\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_Layout__WEBPACK_IMPORTED_MODULE_7__[\"default\"], null));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);\n\n//# sourceURL=webpack://@mdts/frontend/./src/App.tsx?\n}");
19772
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/CssBaseline/CssBaseline.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/styles/ThemeProvider.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/development/chunk-EF7DTUVF.mjs\");\n/* harmony import */ var _hooks_useTheme__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./hooks/useTheme */ \"./src/hooks/useTheme.ts\");\n/* harmony import */ var _hooks_useWebSocket__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./hooks/useWebSocket */ \"./src/hooks/useWebSocket.ts\");\n/* harmony import */ var _Layout__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Layout */ \"./src/Layout.tsx\");\n/* harmony import */ var _store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./store/slices/fileTreeSlice */ \"./src/store/slices/fileTreeSlice.ts\");\n/* harmony import */ var _store_slices_historySlice__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./store/slices/historySlice */ \"./src/store/slices/historySlice.ts\");\n\n\n\n\n\n\n\n\n\nconst App = () => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_3__.useDispatch)();\n const location = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useLocation)();\n const {\n currentPath\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_3__.useSelector)(state => state.history);\n const theme = (0,_hooks_useTheme__WEBPACK_IMPORTED_MODULE_5__.useTheme)();\n (0,_hooks_useWebSocket__WEBPACK_IMPORTED_MODULE_6__.useWebSocket)(currentPath);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_8__.fetchFileTree)());\n }, [dispatch, location]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {\n dispatch((0,_store_slices_historySlice__WEBPACK_IMPORTED_MODULE_9__.updateHistoryFromLocation)(location.pathname));\n }, [location, dispatch]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n theme: theme\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2___default().createElement(_Layout__WEBPACK_IMPORTED_MODULE_7__[\"default\"], null));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);\n\n//# sourceURL=webpack://@mdts/frontend/./src/App.tsx?\n}");
19773
19773
 
19774
19774
  /***/ }),
19775
19775
 
@@ -19802,7 +19802,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
19802
19802
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19803
19803
 
19804
19804
  "use strict";
19805
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material_Brightness4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material/Brightness4 */ \"./node_modules/@mui/icons-material/esm/Brightness4.js\");\n/* harmony import */ var _mui_icons_material_Brightness7__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material/Brightness7 */ \"./node_modules/@mui/icons-material/esm/Brightness7.js\");\n/* harmony import */ var _mui_icons_material_CropFree__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/icons-material/CropFree */ \"./node_modules/@mui/icons-material/esm/CropFree.js\");\n/* harmony import */ var _mui_icons_material_Fullscreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/icons-material/Fullscreen */ \"./node_modules/@mui/icons-material/esm/Fullscreen.js\");\n/* harmony import */ var _mui_icons_material_GitHub__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/icons-material/GitHub */ \"./node_modules/@mui/icons-material/esm/GitHub.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/AppBar/AppBar.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Toolbar/Toolbar.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Tooltip/Tooltip.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/IconButton/IconButton.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Link/Link.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../store/slices/appSettingSlice */ \"./src/store/slices/appSettingSlice.ts\");\n\n\n\n\n\n\n\n\n\nconst AppHeader = ({\n darkMode,\n contentMode,\n handleFileSelect\n}) => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_12__.useDispatch)();\n const handleFileSelectClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n handleFileSelect('');\n }, [dispatch, handleFileSelect]);\n const handleContentModeClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n dispatch((0,_store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleContentMode)());\n }, [dispatch, _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleContentMode]);\n const handleDarkModeClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n dispatch((0,_store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleDarkMode)());\n }, [dispatch, _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleDarkMode]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n position: \"static\",\n elevation: 0,\n sx: theme => ({\n bgcolor: theme.palette.background.paper,\n color: theme.palette.text.primary,\n borderBottom: `1px solid ${theme.palette.divider}`\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n sx: {\n flexGrow: 1\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"Top page\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n disableRipple: true,\n onClick: handleFileSelectClick,\n color: \"inherit\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(\"img\", {\n src: \"/logo.svg\",\n alt: \"mdts logo\",\n style: {\n height: '56px',\n marginTop: '-8px',\n marginLeft: '-36px'\n }\n })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: contentMode === 'fixed' ? 'Exit Fullscreen' : 'Fullscreen'\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n onClick: handleContentModeClick,\n color: \"inherit\",\n sx: {\n mr: 2\n }\n }, contentMode === 'fixed' ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_CropFree__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Fullscreen__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n sx: {\n mr: 2\n },\n onClick: handleDarkModeClick,\n color: \"inherit\"\n }, darkMode ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Brightness7__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Brightness4__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"GitHub Repository\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n color: \"inherit\",\n href: \"https://github.com/unhappychoice/mdts\",\n target: \"_blank\",\n rel: \"noopener\",\n sx: {\n mr: 2\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_GitHub__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n sx: {\n fontSize: '0.9rem',\n pt: '2px',\n fontFamily: 'monospace'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"Changelog\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__[\"default\"], {\n href: \"https://github.com/unhappychoice/mdts/blob/main/CHANGELOG.md\",\n target: \"_blank\",\n rel: \"noopener\"\n }, \"v\", \"0.7.1\")))));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AppHeader);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/AppHeader.tsx?\n}");
19805
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material_Brightness4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material/Brightness4 */ \"./node_modules/@mui/icons-material/esm/Brightness4.js\");\n/* harmony import */ var _mui_icons_material_Brightness7__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material/Brightness7 */ \"./node_modules/@mui/icons-material/esm/Brightness7.js\");\n/* harmony import */ var _mui_icons_material_CropFree__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/icons-material/CropFree */ \"./node_modules/@mui/icons-material/esm/CropFree.js\");\n/* harmony import */ var _mui_icons_material_Fullscreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/icons-material/Fullscreen */ \"./node_modules/@mui/icons-material/esm/Fullscreen.js\");\n/* harmony import */ var _mui_icons_material_GitHub__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/icons-material/GitHub */ \"./node_modules/@mui/icons-material/esm/GitHub.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/AppBar/AppBar.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Toolbar/Toolbar.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Tooltip/Tooltip.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/IconButton/IconButton.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Link/Link.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../store/slices/appSettingSlice */ \"./src/store/slices/appSettingSlice.ts\");\n\n\n\n\n\n\n\n\n\nconst AppHeader = ({\n darkMode,\n contentMode,\n handleFileSelect\n}) => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_12__.useDispatch)();\n const handleFileSelectClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n handleFileSelect('');\n }, [dispatch, handleFileSelect]);\n const handleContentModeClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n dispatch((0,_store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleContentMode)());\n }, [dispatch, _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleContentMode]);\n const handleDarkModeClick = (0,react__WEBPACK_IMPORTED_MODULE_11__.useCallback)(() => {\n dispatch((0,_store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleDarkMode)());\n }, [dispatch, _store_slices_appSettingSlice__WEBPACK_IMPORTED_MODULE_13__.toggleDarkMode]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n position: \"static\",\n elevation: 0,\n sx: theme => ({\n bgcolor: theme.palette.background.paper,\n color: theme.palette.text.primary,\n borderBottom: `1px solid ${theme.palette.divider}`\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n sx: {\n flexGrow: 1\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"Top page\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n disableRipple: true,\n onClick: handleFileSelectClick,\n color: \"inherit\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(\"img\", {\n src: \"/logo.svg\",\n alt: \"mdts logo\",\n style: {\n height: '56px',\n marginTop: '-8px',\n marginLeft: '-36px'\n }\n })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: contentMode === 'fixed' ? 'Exit Fullscreen' : 'Fullscreen'\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n onClick: handleContentModeClick,\n color: \"inherit\",\n sx: {\n mr: 2\n }\n }, contentMode === 'fixed' ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_CropFree__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Fullscreen__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n sx: {\n mr: 2\n },\n onClick: handleDarkModeClick,\n color: \"inherit\"\n }, darkMode ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Brightness7__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_Brightness4__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"GitHub Repository\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n color: \"inherit\",\n href: \"https://github.com/unhappychoice/mdts\",\n target: \"_blank\",\n rel: \"noopener\",\n sx: {\n mr: 2\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_icons_material_GitHub__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n sx: {\n fontSize: '0.9rem',\n pt: '2px',\n fontFamily: 'monospace'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n title: \"Changelog\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_11___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__[\"default\"], {\n href: \"https://github.com/unhappychoice/mdts/blob/main/CHANGELOG.md\",\n target: \"_blank\",\n rel: \"noopener\"\n }, \"v\", \"0.8.0\")))));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AppHeader);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/AppHeader.tsx?\n}");
19806
19806
 
19807
19807
  /***/ }),
19808
19808
 
@@ -19846,7 +19846,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
19846
19846
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19847
19847
 
19848
19848
  "use strict";
19849
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ FileTreeList: () => (/* binding */ FileTreeList)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/ArticleOutlined.js\");\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/FolderOutlined.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/List/List.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItem/ListItem.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItemIcon/ListItemIcon.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItemText/ListItemText.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n\n\n\n\nconst FileTreeList = ({\n fileTree,\n handleItemClick\n}) => {\n const {\n currentPath\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_7__.useSelector)(state => state.history);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n sx: {\n mr: -2,\n ml: -2\n }\n }, fileTree.map(item => {\n const isDirectory = typeof item !== 'string';\n const name = isDirectory ? Object.keys(item)[0] : item;\n const itemPath = currentPath === '' ? name : `${currentPath}/${name}`;\n const handleClick = () => {\n handleItemClick(itemPath, isDirectory);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n key: itemPath,\n button: true,\n onClick: handleClick\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n minWidth: \"38px\"\n }\n }, isDirectory ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n color: \"primary\"\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n primary: name\n }));\n }));\n};\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/Content/DirectoryContent/FileTreeList.tsx?\n}");
19849
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ FileTreeList: () => (/* binding */ FileTreeList)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/ArticleOutlined.js\");\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/FolderOutlined.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/List/List.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItem/ListItem.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItemIcon/ListItemIcon.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/ListItemText/ListItemText.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n\n\n\n\nconst FileTreeList = ({\n fileTree,\n handleItemClick\n}) => {\n const {\n currentPath\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_7__.useSelector)(state => state.history);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n sx: {\n mr: -2,\n ml: -2\n }\n }, fileTree.map(item => {\n const isDirectory = !('path' in item);\n const name = isDirectory ? Object.keys(item)[0] : item.path.split('/').pop();\n const itemPath = currentPath === '' ? name : `${currentPath}/${name}`;\n const handleClick = () => {\n handleItemClick(itemPath, isDirectory);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n key: itemPath,\n button: true,\n onClick: handleClick\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n minWidth: \"38px\"\n }\n }, isDirectory ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n color: \"primary\"\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_6___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n primary: name\n }));\n }));\n};\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/Content/DirectoryContent/FileTreeList.tsx?\n}");
19850
19850
 
19851
19851
  /***/ }),
19852
19852
 
@@ -19923,7 +19923,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
19923
19923
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19924
19924
 
19925
19925
  "use strict";
19926
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var _store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../store/slices/fileTreeSlice */ \"./src/store/slices/fileTreeSlice.ts\");\n/* harmony import */ var _FileTreeHeader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FileTreeHeader */ \"./src/components/LeftPane/FileTreeHeader.tsx\");\n/* harmony import */ var _FileTreeSearch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FileTreeSearch */ \"./src/components/LeftPane/FileTreeSearch.tsx\");\n/* harmony import */ var _FileTreeContent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FileTreeContent */ \"./src/components/LeftPane/FileTreeContent.tsx\");\n\n\n\n\n\n\n\nconst FileTree = ({\n onFileSelect,\n isOpen,\n onToggle\n}) => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_2__.useDispatch)();\n const {\n fileTree,\n filteredFileTree,\n loading,\n error,\n searchQuery,\n expandedNodes\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_2__.useSelector)(state => state.fileTree);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.fetchFileTree)());\n }, [dispatch]);\n const handleSearchChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(event => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setSearchQuery)(event.target.value));\n }, [dispatch]);\n const handleClearSearch = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setSearchQuery)(''));\n }, [dispatch]);\n const handleExpandAllClick = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.expandAllNodes)(fileTree));\n }, [dispatch, fileTree]);\n const handleCollapseAll = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)([]));\n }, [dispatch]);\n const handleExpandedItemsChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((event, itemIds) => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)(itemIds));\n }, [dispatch]);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n if (!searchQuery) return;\n const newExpanded = [];\n const collectExpandedPaths = (items, parentPath = '') => {\n items.forEach(item => {\n if (typeof item !== 'string') {\n // It's a folder\n const key = Object.keys(item)[0];\n const value = item[key];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n if (!newExpanded.includes(currentPath)) {\n newExpanded.push(currentPath);\n }\n if (Array.isArray(value)) {\n collectExpandedPaths(value, currentPath);\n }\n }\n });\n };\n if (filteredFileTree) {\n collectExpandedPaths(filteredFileTree);\n }\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)(newExpanded));\n }, [searchQuery, filteredFileTree, dispatch]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], {\n sx: {\n width: isOpen ? '300px' : '66px',\n bgcolor: 'background.paper',\n p: isOpen ? 2 : 0.5,\n borderRight: '1px solid',\n borderColor: 'divider',\n minHeight: '100%',\n flexShrink: 0\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeHeader__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n isOpen: isOpen,\n onToggle: onToggle,\n onExpandAllClick: handleExpandAllClick,\n onCollapseAll: handleCollapseAll\n }), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeSearch__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n searchQuery: searchQuery,\n onSearchChange: handleSearchChange,\n onClearSearch: handleClearSearch\n }), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeContent__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n filteredFileTree: filteredFileTree,\n loading: loading,\n error: error,\n expandedNodes: expandedNodes,\n onFileSelect: onFileSelect,\n onExpandedItemsChange: handleExpandedItemsChange,\n dispatch: dispatch\n }));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FileTree);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/LeftPane/FileTree.tsx?\n}");
19926
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-redux */ \"./node_modules/react-redux/dist/react-redux.mjs\");\n/* harmony import */ var _store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../store/slices/fileTreeSlice */ \"./src/store/slices/fileTreeSlice.ts\");\n/* harmony import */ var _FileTreeHeader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FileTreeHeader */ \"./src/components/LeftPane/FileTreeHeader.tsx\");\n/* harmony import */ var _FileTreeSearch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FileTreeSearch */ \"./src/components/LeftPane/FileTreeSearch.tsx\");\n/* harmony import */ var _FileTreeContent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FileTreeContent */ \"./src/components/LeftPane/FileTreeContent.tsx\");\n\n\n\n\n\n\n\nconst FileTree = ({\n onFileSelect,\n isOpen,\n onToggle\n}) => {\n const dispatch = (0,react_redux__WEBPACK_IMPORTED_MODULE_2__.useDispatch)();\n const {\n fileTree,\n filteredFileTree,\n loading,\n error,\n searchQuery,\n expandedNodes\n } = (0,react_redux__WEBPACK_IMPORTED_MODULE_2__.useSelector)(state => state.fileTree);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.fetchFileTree)());\n }, [dispatch]);\n const handleSearchChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(event => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setSearchQuery)(event.target.value));\n }, [dispatch]);\n const handleClearSearch = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setSearchQuery)(''));\n }, [dispatch]);\n const handleExpandAllClick = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.expandAllNodes)(fileTree));\n }, [dispatch, fileTree]);\n const handleCollapseAll = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(() => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)([]));\n }, [dispatch]);\n const handleExpandedItemsChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((event, itemIds) => {\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)(itemIds));\n }, [dispatch]);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n if (!searchQuery) return;\n const newExpanded = [];\n const collectExpandedPaths = (items, parentPath = '') => {\n items.forEach(item => {\n if (!('path' in item)) {\n // It's a folder\n const key = Object.keys(item)[0];\n const value = item[key];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n if (!newExpanded.includes(currentPath)) {\n newExpanded.push(currentPath);\n }\n if (Array.isArray(value)) {\n collectExpandedPaths(value, currentPath);\n }\n }\n });\n };\n if (filteredFileTree) {\n collectExpandedPaths(filteredFileTree);\n }\n dispatch((0,_store_slices_fileTreeSlice__WEBPACK_IMPORTED_MODULE_3__.setExpandedNodes)(newExpanded));\n }, [searchQuery, filteredFileTree, dispatch]);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], {\n sx: {\n width: isOpen ? '300px' : '66px',\n bgcolor: 'background.paper',\n p: isOpen ? 2 : 0.5,\n borderRight: '1px solid',\n borderColor: 'divider',\n minHeight: '100%',\n flexShrink: 0\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeHeader__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n isOpen: isOpen,\n onToggle: onToggle,\n onExpandAllClick: handleExpandAllClick,\n onCollapseAll: handleCollapseAll\n }), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeSearch__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n searchQuery: searchQuery,\n onSearchChange: handleSearchChange,\n onClearSearch: handleClearSearch\n }), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_FileTreeContent__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n filteredFileTree: filteredFileTree,\n loading: loading,\n error: error,\n expandedNodes: expandedNodes,\n onFileSelect: onFileSelect,\n onExpandedItemsChange: handleExpandedItemsChange,\n dispatch: dispatch\n }));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FileTree);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/LeftPane/FileTree.tsx?\n}");
19927
19927
 
19928
19928
  /***/ }),
19929
19929
 
@@ -19934,7 +19934,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
19934
19934
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19935
19935
 
19936
19936
  "use strict";
19937
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/ArticleOutlined.js\");\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/FolderOutlined.js\");\n/* harmony import */ var _mui_icons_material_ExpandMore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/icons-material/ExpandMore */ \"./node_modules/@mui/icons-material/esm/ExpandMore.js\");\n/* harmony import */ var _mui_icons_material_ChevronRight__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/icons-material/ChevronRight */ \"./node_modules/@mui/icons-material/esm/ChevronRight.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Typography/Typography.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/CircularProgress/CircularProgress.js\");\n/* harmony import */ var _mui_x_tree_view__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @mui/x-tree-view */ \"./node_modules/@mui/x-tree-view/esm/TreeItem/TreeItem.js\");\n/* harmony import */ var _mui_x_tree_view_SimpleTreeView__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @mui/x-tree-view/SimpleTreeView */ \"./node_modules/@mui/x-tree-view/esm/SimpleTreeView/SimpleTreeView.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_9__);\n\n\n\n\n\n\n\nconst FileTreeContent = ({\n filteredFileTree,\n loading,\n error,\n expandedNodes,\n onFileSelect,\n onExpandedItemsChange\n}) => {\n const renderTreeItems = (tree, onFileSelect, parentPath = '') => {\n if (!tree) {\n return null;\n }\n return tree.map(item => {\n if (typeof item === 'string') {\n const fileName = item.split('/').pop();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_x_tree_view__WEBPACK_IMPORTED_MODULE_7__.TreeItem, {\n key: item,\n itemId: item,\n label: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n alignItems: 'center'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], {\n sx: {\n mr: 1,\n fontSize: 'small'\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n variant: \"body2\",\n sx: {\n fontSize: '0.875rem'\n }\n }, fileName)),\n onClick: () => onFileSelect(item)\n });\n } else {\n const key = Object.keys(item)[0];\n const value = item[key];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_x_tree_view__WEBPACK_IMPORTED_MODULE_7__.TreeItem, {\n key: currentPath,\n itemId: currentPath,\n label: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n alignItems: 'center'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n sx: {\n mr: 1,\n fontSize: 'small'\n },\n color: \"primary\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n variant: \"body2\",\n sx: {\n fontSize: '0.875rem'\n }\n }, key))\n }, Array.isArray(value) && value.length > 0 && renderTreeItems(value, onFileSelect, currentPath));\n }\n });\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement((react__WEBPACK_IMPORTED_MODULE_9___default().Fragment), null, loading ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '100vh'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null)) : error ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n color: \"error\"\n }, \"Error: \", error) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_x_tree_view_SimpleTreeView__WEBPACK_IMPORTED_MODULE_8__.SimpleTreeView, {\n defaultCollapseIcon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_icons_material_ExpandMore__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null),\n defaultExpandIcon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_9___default().createElement(_mui_icons_material_ChevronRight__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null),\n expandedItems: expandedNodes,\n onExpandedItemsChange: onExpandedItemsChange,\n sx: {\n flexGrow: 1,\n maxWidth: 400,\n overflowY: 'auto'\n }\n }, renderTreeItems(filteredFileTree, onFileSelect)));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FileTreeContent);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/LeftPane/FileTreeContent.tsx?\n}");
19937
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/ArticleOutlined.js\");\n/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/icons-material */ \"./node_modules/@mui/icons-material/esm/FolderOutlined.js\");\n/* harmony import */ var _mui_icons_material_ExpandMore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/icons-material/ExpandMore */ \"./node_modules/@mui/icons-material/esm/ExpandMore.js\");\n/* harmony import */ var _mui_icons_material_ChevronRight__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/icons-material/ChevronRight */ \"./node_modules/@mui/icons-material/esm/ChevronRight.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Box/Box.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/Typography/Typography.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/CircularProgress/CircularProgress.js\");\n/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @mui/material */ \"./node_modules/@mui/material/esm/styles/useTheme.js\");\n/* harmony import */ var _mui_x_tree_view__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @mui/x-tree-view */ \"./node_modules/@mui/x-tree-view/esm/TreeItem/TreeItem.js\");\n/* harmony import */ var _mui_x_tree_view_SimpleTreeView__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @mui/x-tree-view/SimpleTreeView */ \"./node_modules/@mui/x-tree-view/esm/SimpleTreeView/SimpleTreeView.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_10__);\n\n\n\n\n\n\n\nconst FileTreeContent = ({\n filteredFileTree,\n loading,\n error,\n expandedNodes,\n onFileSelect,\n onExpandedItemsChange\n}) => {\n const theme = (0,_mui_material__WEBPACK_IMPORTED_MODULE_7__[\"default\"])();\n const getStatusColor = status => {\n switch (status) {\n case 'M':\n return theme.palette.info.main;\n case '?':\n case 'A':\n return theme.palette.success.main;\n case 'D':\n return theme.palette.error.main;\n case 'R':\n return theme.palette.warning.main;\n case 'C':\n return theme.palette.secondary.main;\n default:\n return theme.palette.text.primary;\n }\n };\n const renderTreeItems = (tree, onFileSelect, parentPath = '') => {\n if (!tree) {\n return null;\n }\n return tree.map(item => {\n if ('path' in item) {\n const fileItem = item;\n const fileName = fileItem.path.split('/').pop();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_x_tree_view__WEBPACK_IMPORTED_MODULE_8__.TreeItem, {\n key: fileItem.path,\n itemId: fileItem.path,\n label: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n alignItems: 'center'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_0__[\"default\"], {\n sx: {\n mr: 1,\n fontSize: 'small'\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n variant: \"body2\",\n sx: {\n fontSize: '0.875rem',\n color: getStatusColor(fileItem.status)\n }\n }, fileName), fileItem.status && fileItem.status !== ' ' && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n variant: \"body2\",\n sx: {\n fontSize: '0.75rem',\n color: getStatusColor(fileItem.status),\n ml: 1\n }\n }, fileItem.status)),\n onClick: () => onFileSelect(fileItem.path)\n });\n } else {\n const key = Object.keys(item)[0];\n const value = item[key];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_x_tree_view__WEBPACK_IMPORTED_MODULE_8__.TreeItem, {\n key: currentPath,\n itemId: currentPath,\n label: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n alignItems: 'center'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n sx: {\n mr: 1,\n fontSize: 'small'\n },\n color: \"primary\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n variant: \"body2\",\n sx: {\n fontSize: '0.875rem'\n }\n }, key))\n }, Array.isArray(value) && value.length > 0 && renderTreeItems(value, onFileSelect, currentPath));\n }\n });\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement((react__WEBPACK_IMPORTED_MODULE_10___default().Fragment), null, loading ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n sx: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '100vh'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null)) : error ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n color: \"error\"\n }, \"Error: \", error) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_x_tree_view_SimpleTreeView__WEBPACK_IMPORTED_MODULE_9__.SimpleTreeView, {\n defaultCollapseIcon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_icons_material_ExpandMore__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null),\n defaultExpandIcon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_10___default().createElement(_mui_icons_material_ChevronRight__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null),\n expandedItems: expandedNodes,\n onExpandedItemsChange: onExpandedItemsChange,\n sx: {\n flexGrow: 1,\n maxWidth: 400,\n overflowY: 'auto'\n }\n }, renderTreeItems(filteredFileTree, onFileSelect)));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FileTreeContent);\n\n//# sourceURL=webpack://@mdts/frontend/./src/components/LeftPane/FileTreeContent.tsx?\n}");
19938
19938
 
19939
19939
  /***/ }),
19940
19940
 
@@ -20077,7 +20077,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
20077
20077
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
20078
20078
 
20079
20079
  "use strict";
20080
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ expandAllNodes: () => (/* binding */ expandAllNodes),\n/* harmony export */ fetchFileTree: () => (/* binding */ fetchFileTree),\n/* harmony export */ selectFilteredFileTree: () => (/* binding */ selectFilteredFileTree),\n/* harmony export */ setExpandedNodes: () => (/* binding */ setExpandedNodes),\n/* harmony export */ setMountedDirectoryPath: () => (/* binding */ setMountedDirectoryPath),\n/* harmony export */ setSearchQuery: () => (/* binding */ setSearchQuery),\n/* harmony export */ toggleNode: () => (/* binding */ toggleNode)\n/* harmony export */ });\n/* harmony import */ var _reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @reduxjs/toolkit */ \"./node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../api */ \"./src/api.ts\");\n\n\nconst initialState = {\n fileTree: [],\n filteredFileTree: [],\n searchQuery: '',\n expandedNodes: [],\n mountedDirectoryPath: '',\n loading: true,\n error: null\n};\nconst LOCAL_STORAGE_KEY_PREFIX = 'mdts_expanded_nodes_';\nconst LOCAL_STORAGE_RECENT_PATHS_KEY = 'mdts_recent_paths';\nconst MAX_RECENT_PATHS = 10;\nconst saveExpandedNodes = (path, nodes) => {\n try {\n localStorage.setItem(`${LOCAL_STORAGE_KEY_PREFIX}${path}`, JSON.stringify(nodes));\n let recentPaths = JSON.parse(localStorage.getItem(LOCAL_STORAGE_RECENT_PATHS_KEY) || '[]');\n recentPaths = recentPaths.filter(p => p !== path);\n recentPaths.unshift(path);\n if (recentPaths.length > MAX_RECENT_PATHS) {\n const oldPath = recentPaths.pop();\n if (oldPath) {\n localStorage.removeItem(`${LOCAL_STORAGE_KEY_PREFIX}${oldPath}`);\n }\n }\n localStorage.setItem(LOCAL_STORAGE_RECENT_PATHS_KEY, JSON.stringify(recentPaths));\n } catch (e) {\n console.error('Failed to save expanded nodes to local storage', e);\n }\n};\nconst loadExpandedNodes = path => {\n try {\n const storedNodes = localStorage.getItem(`${LOCAL_STORAGE_KEY_PREFIX}${path}`);\n return storedNodes ? JSON.parse(storedNodes) : [];\n } catch (e) {\n console.error('Failed to load expanded nodes from local storage', e);\n return [];\n }\n};\nconst filterTree = (tree, searchQuery) => {\n if (!searchQuery) return tree;\n return tree.reduce((acc, item) => {\n if (typeof item === 'string') {\n const fileName = item.split('/').pop() || '';\n return fileName.toLowerCase().includes(searchQuery.toLowerCase()) ? [...acc, item] : acc;\n } else {\n const key = Object.keys(item)[0];\n const value = item[key];\n const children = Array.isArray(value) ? filterTree(value, searchQuery) : [];\n return children.length > 0 ? [...acc, {\n [key]: children\n }] : acc;\n }\n }, []);\n};\nconst fetchFileTree = (0,_reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__.createAsyncThunk)('fileTree/fetchFileTree', async () => {\n const data = await (0,_api__WEBPACK_IMPORTED_MODULE_1__.fetchData)('/api/filetree', 'json');\n return {\n fileTree: data?.fileTree || [],\n mountedDirectoryPath: data?.mountedDirectoryPath\n };\n});\nconst fileTreeSlice = (0,_reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__.createSlice)({\n name: 'fileTree',\n initialState,\n reducers: {\n setSearchQuery: (state, action) => {\n state.searchQuery = action.payload;\n state.filteredFileTree = filterTree(state.fileTree, action.payload);\n },\n toggleNode: (state, action) => {\n const path = action.payload;\n if (state.expandedNodes.includes(path)) {\n state.expandedNodes = state.expandedNodes.filter(nodePath => nodePath !== path);\n } else {\n state.expandedNodes.push(path);\n }\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n setExpandedNodes: (state, action) => {\n state.expandedNodes = action.payload;\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n expandAllNodes: (state, action) => {\n const allItemIds = [];\n const collectIds = (items, parentPath = '') => {\n items.forEach(item => {\n if (typeof item !== 'string') {\n const key = Object.keys(item)[0];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n allItemIds.push(currentPath);\n collectIds(item[key], currentPath);\n }\n });\n };\n if (action.payload) {\n collectIds(action.payload);\n }\n state.expandedNodes = allItemIds;\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n setMountedDirectoryPath: (state, action) => {\n state.mountedDirectoryPath = action.payload;\n }\n },\n extraReducers: builder => {\n builder.addCase(fetchFileTree.pending, state => {\n state.loading = true;\n state.error = null;\n }).addCase(fetchFileTree.fulfilled, (state, action) => {\n state.loading = false;\n state.fileTree = action.payload.fileTree;\n state.mountedDirectoryPath = action.payload.mountedDirectoryPath;\n state.filteredFileTree = filterTree(action.payload.fileTree, state.searchQuery);\n state.expandedNodes = loadExpandedNodes(action.payload.mountedDirectoryPath);\n }).addCase(fetchFileTree.rejected, (state, action) => {\n state.loading = false;\n state.error = action.error.message || 'Failed to fetch file tree';\n });\n }\n});\nconst selectFilteredFileTree = (fullFileTree, targetPath) => {\n if (targetPath === '') {\n const result = [];\n fullFileTree.forEach(item => {\n if (typeof item === 'string') {\n result.push(item.split('/').pop() || item);\n } else {\n const key = Object.keys(item)[0];\n const newObject = {};\n newObject[key.split('/').pop() || key] = item[key];\n result.push(newObject);\n }\n });\n return result;\n }\n const findChildren = (currentTree, pathSegments, currentSegmentIndex) => {\n if (currentSegmentIndex === pathSegments.length) {\n return currentTree;\n }\n const segment = pathSegments[currentSegmentIndex];\n for (const item of currentTree) {\n if (typeof item !== 'string') {\n const key = Object.keys(item)[0];\n const itemSegments = key.split('/');\n if (itemSegments[itemSegments.length - 1] === segment) {\n const children = item[key];\n if (Array.isArray(children)) {\n return findChildren(children, pathSegments, currentSegmentIndex + 1);\n }\n }\n }\n }\n return null;\n };\n const pathSegments = targetPath.split('/').filter(s => s !== '');\n const children = findChildren(fullFileTree, pathSegments, 0);\n if (children) {\n const result = [];\n children.forEach(item => {\n if (typeof item === 'string') {\n result.push(item.split('/').pop() || item);\n } else {\n const key = Object.keys(item)[0];\n const newObject = {};\n newObject[key.split('/').pop() || key] = item[key];\n result.push(newObject);\n }\n });\n return result;\n }\n return [];\n};\nconst {\n setSearchQuery,\n toggleNode,\n setExpandedNodes,\n expandAllNodes,\n setMountedDirectoryPath\n} = fileTreeSlice.actions;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (fileTreeSlice.reducer);\n\n//# sourceURL=webpack://@mdts/frontend/./src/store/slices/fileTreeSlice.ts?\n}");
20080
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ expandAllNodes: () => (/* binding */ expandAllNodes),\n/* harmony export */ fetchFileTree: () => (/* binding */ fetchFileTree),\n/* harmony export */ selectFilteredFileTree: () => (/* binding */ selectFilteredFileTree),\n/* harmony export */ setExpandedNodes: () => (/* binding */ setExpandedNodes),\n/* harmony export */ setMountedDirectoryPath: () => (/* binding */ setMountedDirectoryPath),\n/* harmony export */ setSearchQuery: () => (/* binding */ setSearchQuery),\n/* harmony export */ toggleNode: () => (/* binding */ toggleNode)\n/* harmony export */ });\n/* harmony import */ var _reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @reduxjs/toolkit */ \"./node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs\");\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../api */ \"./src/api.ts\");\n\n\nconst initialState = {\n fileTree: [],\n filteredFileTree: [],\n searchQuery: '',\n expandedNodes: [],\n mountedDirectoryPath: '',\n loading: true,\n error: null\n};\nconst LOCAL_STORAGE_KEY_PREFIX = 'mdts_expanded_nodes_';\nconst LOCAL_STORAGE_RECENT_PATHS_KEY = 'mdts_recent_paths';\nconst MAX_RECENT_PATHS = 10;\nconst saveExpandedNodes = (path, nodes) => {\n try {\n localStorage.setItem(`${LOCAL_STORAGE_KEY_PREFIX}${path}`, JSON.stringify(nodes));\n let recentPaths = JSON.parse(localStorage.getItem(LOCAL_STORAGE_RECENT_PATHS_KEY) || '[]');\n recentPaths = recentPaths.filter(p => p !== path);\n recentPaths.unshift(path);\n if (recentPaths.length > MAX_RECENT_PATHS) {\n const oldPath = recentPaths.pop();\n if (oldPath) {\n localStorage.removeItem(`${LOCAL_STORAGE_KEY_PREFIX}${oldPath}`);\n }\n }\n localStorage.setItem(LOCAL_STORAGE_RECENT_PATHS_KEY, JSON.stringify(recentPaths));\n } catch (e) {\n console.error('Failed to save expanded nodes to local storage', e);\n }\n};\nconst loadExpandedNodes = path => {\n try {\n const storedNodes = localStorage.getItem(`${LOCAL_STORAGE_KEY_PREFIX}${path}`);\n return storedNodes ? JSON.parse(storedNodes) : [];\n } catch (e) {\n console.error('Failed to load expanded nodes from local storage', e);\n return [];\n }\n};\nconst filterTree = (tree, searchQuery) => {\n if (!searchQuery) return tree;\n return tree.reduce((acc, item) => {\n if ('path' in item) {\n const fileItem = item;\n const fileName = fileItem.path.split('/').pop() || '';\n return fileName.toLowerCase().includes(searchQuery.toLowerCase()) ? [...acc, item] : acc;\n } else {\n const key = Object.keys(item)[0];\n const value = item[key];\n const children = Array.isArray(value) ? filterTree(value, searchQuery) : [];\n return children.length > 0 ? [...acc, {\n [key]: children\n }] : acc;\n }\n }, []);\n};\nconst fetchFileTree = (0,_reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__.createAsyncThunk)('fileTree/fetchFileTree', async () => {\n const data = await (0,_api__WEBPACK_IMPORTED_MODULE_1__.fetchData)('/api/filetree', 'json');\n return {\n fileTree: data?.fileTree || [],\n mountedDirectoryPath: data?.mountedDirectoryPath\n };\n});\nconst fileTreeSlice = (0,_reduxjs_toolkit__WEBPACK_IMPORTED_MODULE_0__.createSlice)({\n name: 'fileTree',\n initialState,\n reducers: {\n setSearchQuery: (state, action) => {\n state.searchQuery = action.payload;\n state.filteredFileTree = filterTree(state.fileTree, action.payload);\n },\n toggleNode: (state, action) => {\n const path = action.payload;\n if (state.expandedNodes.includes(path)) {\n state.expandedNodes = state.expandedNodes.filter(nodePath => nodePath !== path);\n } else {\n state.expandedNodes.push(path);\n }\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n setExpandedNodes: (state, action) => {\n state.expandedNodes = action.payload;\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n expandAllNodes: (state, action) => {\n const allItemIds = [];\n const collectIds = (items, parentPath = '') => {\n items.forEach(item => {\n if (!('path' in item)) {\n const key = Object.keys(item)[0];\n const currentPath = parentPath ? `${parentPath}/${key}` : key;\n allItemIds.push(currentPath);\n collectIds(item[key], currentPath);\n }\n });\n };\n if (action.payload) {\n collectIds(action.payload);\n }\n state.expandedNodes = allItemIds;\n saveExpandedNodes(state.mountedDirectoryPath, state.expandedNodes);\n },\n setMountedDirectoryPath: (state, action) => {\n state.mountedDirectoryPath = action.payload;\n }\n },\n extraReducers: builder => {\n builder.addCase(fetchFileTree.pending, state => {\n state.loading = true;\n state.error = null;\n }).addCase(fetchFileTree.fulfilled, (state, action) => {\n state.loading = false;\n state.fileTree = action.payload.fileTree;\n state.mountedDirectoryPath = action.payload.mountedDirectoryPath;\n state.filteredFileTree = filterTree(action.payload.fileTree, state.searchQuery);\n state.expandedNodes = loadExpandedNodes(action.payload.mountedDirectoryPath);\n }).addCase(fetchFileTree.rejected, (state, action) => {\n state.loading = false;\n state.error = action.error.message || 'Failed to fetch file tree';\n });\n }\n});\nconst selectFilteredFileTree = (fullFileTree, targetPath) => {\n if (targetPath === '') {\n const result = [];\n fullFileTree.forEach(item => {\n if ('path' in item) {\n result.push({\n path: item.path.split('/').pop() || item.path,\n status: item.status\n });\n } else {\n const key = Object.keys(item)[0];\n const newObject = {};\n newObject[key.split('/').pop() || key] = item[key];\n result.push(newObject);\n }\n });\n return result;\n }\n const findChildren = (currentTree, pathSegments, currentSegmentIndex) => {\n if (currentSegmentIndex === pathSegments.length) {\n return currentTree;\n }\n const segment = pathSegments[currentSegmentIndex];\n for (const item of currentTree) {\n if (!('path' in item)) {\n const key = Object.keys(item)[0];\n const itemSegments = key.split('/');\n if (itemSegments[itemSegments.length - 1] === segment) {\n const children = item[key];\n if (Array.isArray(children)) {\n return findChildren(children, pathSegments, currentSegmentIndex + 1);\n }\n }\n }\n }\n return null;\n };\n const pathSegments = targetPath.split('/').filter(s => s !== '');\n const children = findChildren(fullFileTree, pathSegments, 0);\n if (children) {\n const result = [];\n children.forEach(item => {\n if ('path' in item) {\n result.push({\n path: item.path.split('/').pop() || item.path,\n status: item.status\n });\n } else {\n const key = Object.keys(item)[0];\n const newObject = {};\n newObject[key.split('/').pop() || key] = item[key];\n result.push(newObject);\n }\n });\n return result;\n }\n return [];\n};\nconst {\n setSearchQuery,\n toggleNode,\n setExpandedNodes,\n expandAllNodes,\n setMountedDirectoryPath\n} = fileTreeSlice.actions;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (fileTreeSlice.reducer);\n\n//# sourceURL=webpack://@mdts/frontend/./src/store/slices/fileTreeSlice.ts?\n}");
20081
20081
 
20082
20082
  /***/ }),
20083
20083
 
@@ -1,4 +1,13 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
@@ -7,11 +16,15 @@ exports.fileTreeRouter = void 0;
7
16
  const express_1 = require("express");
8
17
  const fs_1 = __importDefault(require("fs"));
9
18
  const path_1 = __importDefault(require("path"));
19
+ const simple_git_1 = __importDefault(require("simple-git"));
10
20
  const fileTreeRouter = (directory) => {
11
21
  const router = (0, express_1.Router)();
12
- router.get('/', (req, res) => {
13
- res.json({ fileTree: getFileTree(directory, ''), mountedDirectoryPath: directory });
14
- });
22
+ const git = (0, simple_git_1.default)({ baseDir: directory });
23
+ router.get('/', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const gitStatus = yield git.status();
25
+ const fileTree = yield getFileTree(directory, '', gitStatus);
26
+ res.json({ fileTree, mountedDirectoryPath: directory });
27
+ }));
15
28
  return router;
16
29
  };
17
30
  exports.fileTreeRouter = fileTreeRouter;
@@ -22,21 +35,30 @@ const isLibraryDirectory = (entryName) => {
22
35
  const libraryDirs = ['node_modules', 'vendor', 'bundle', 'venv', 'env', 'site-packages'];
23
36
  return libraryDirs.includes(entryName);
24
37
  };
25
- const getFileTree = (baseDirectory, currentRelativePath) => {
26
- const entries = fs_1.default.readdirSync(path_1.default.join(baseDirectory, currentRelativePath), { withFileTypes: true })
27
- .filter(entry => !isDotFileOrDirectory(entry.name) && !isLibraryDirectory(entry.name));
38
+ const shouldIncludeEntry = (entry) => {
39
+ return !isDotFileOrDirectory(entry.name) && !isLibraryDirectory(entry.name);
40
+ };
41
+ const getFileTree = (baseDirectory, currentRelativePath, gitStatus) => __awaiter(void 0, void 0, void 0, function* () {
42
+ const fullPath = path_1.default.join(baseDirectory, currentRelativePath);
43
+ const entriesInDir = fs_1.default.readdirSync(fullPath, { withFileTypes: true });
44
+ const entries = entriesInDir.filter(shouldIncludeEntry);
28
45
  const tree = [];
29
46
  for (const entry of entries) {
30
47
  const entryPath = path_1.default.join(currentRelativePath, entry.name);
31
48
  if (entry.isDirectory()) {
32
- const subTree = getFileTree(baseDirectory, entryPath);
33
- if (subTree.length > 0) { // Only include directory if it contains markdown files
49
+ const subTree = yield getFileTree(baseDirectory, entryPath, gitStatus);
50
+ if (subTree.length > 0) {
34
51
  tree.push({ [entry.name]: subTree });
35
52
  }
36
53
  }
37
54
  else if (entry.name.endsWith('.md') || entry.name.endsWith('.markdown')) {
38
- tree.push(entryPath);
55
+ const fileStatus = gitStatus.files.find((f) => f.path === entryPath);
56
+ let status = ' ';
57
+ if (fileStatus) {
58
+ status = fileStatus.index !== ' ' ? fileStatus.index : fileStatus.working_dir;
59
+ }
60
+ tree.push({ path: entryPath, status });
39
61
  }
40
62
  }
41
63
  return tree;
42
- };
64
+ });
@@ -53,10 +53,11 @@ const logger_1 = require("../utils/logger");
53
53
  const filetree_1 = require("./routes/filetree");
54
54
  const outline_1 = require("./routes/outline");
55
55
  const watcher_1 = require("./watcher");
56
- const serve = (directory, port) => {
56
+ const serve = (directory, port, host) => {
57
57
  const app = (0, exports.createApp)(directory);
58
- const server = app.listen(port, () => {
59
- logger_1.logger.log(`🚀 Server listening at http://localhost:${port}`);
58
+ const server = app.listen(port, host, () => {
59
+ logger_1.logger.log('Server', `📁 Mounted directory: ${directory}`);
60
+ logger_1.logger.log('Server', `🚀 Server listening at http://${host}:${port}`);
60
61
  });
61
62
  (0, watcher_1.setupWatcher)(directory, server, port);
62
63
  return server;
@@ -46,10 +46,10 @@ let currentWatchedFile = null;
46
46
  const setupWatcher = (directory, server, port) => {
47
47
  const wss = new ws_1.WebSocketServer({ server });
48
48
  wss.on('listening', () => {
49
- logger_1.logger.log(`🚀 WebSocket server listening at ws://localhost:${port}`);
49
+ logger_1.logger.log('Livereload', `🚀 WebSocket server listening at ws://localhost:${port}`);
50
50
  });
51
51
  wss.on('connection', (ws) => {
52
- logger_1.logger.log('🤝 Livereload Client connected');
52
+ logger_1.logger.log('Livereload', '🤝 Livereload Client connected');
53
53
  ws.on('message', (message) => handleWebSocketMessage(ws, message.toString()));
54
54
  ws.on('close', () => handleWebSocketClose(wss));
55
55
  ws.on('error', (e) => logger_1.logger.error('🚫 Error on WebSocket client:', e));
@@ -69,7 +69,7 @@ const handleWebSocketMessage = (ws, message) => {
69
69
  }
70
70
  };
71
71
  const handleWebSocketClose = (wss) => {
72
- logger_1.logger.log('👋 Livereload Client closed');
72
+ logger_1.logger.log('Livereload', '👋 Livereload Client closed');
73
73
  if (wss.clients.size === 0) {
74
74
  contentWatcher === null || contentWatcher === void 0 ? void 0 : contentWatcher.close();
75
75
  contentWatcher = null;
@@ -96,13 +96,13 @@ const setupDirectoryWatcher = (directory, wss) => {
96
96
  ignoreInitial: true,
97
97
  });
98
98
  watcher.on('add', (filePath) => {
99
- logger_1.logger.log(`🌲 File added: ${filePath}, reloading tree...`);
99
+ logger_1.logger.log('Livereload', `🌲 File added: ${filePath}, reloading tree...`);
100
100
  wss.clients.forEach((client) => {
101
101
  client.send(JSON.stringify({ type: 'reload-tree' }));
102
102
  });
103
103
  });
104
104
  watcher.on('unlink', (filePath) => {
105
- logger_1.logger.log(`🌲 File removed: ${filePath}, reloading tree...`);
105
+ logger_1.logger.log('Livereload', `🌲 File removed: ${filePath}, reloading tree...`);
106
106
  wss.clients.forEach((client) => {
107
107
  client.send(JSON.stringify({ type: 'reload-tree' }));
108
108
  });
@@ -117,12 +117,12 @@ const setupDirectoryWatcher = (directory, wss) => {
117
117
  };
118
118
  const setupContentWatcher = (ws, filePath) => {
119
119
  if (filePath !== currentWatchedFile) {
120
- logger_1.logger.log(`👀 Watching file: ${filePath}`);
120
+ logger_1.logger.log('Livereload', `👀 Watching file: ${filePath}`);
121
121
  currentWatchedFile = filePath;
122
122
  contentWatcher === null || contentWatcher === void 0 ? void 0 : contentWatcher.close(); // Close existing content watcher if any
123
123
  contentWatcher = chokidar_1.default.watch(filePath, { ignoreInitial: true });
124
124
  contentWatcher.on('change', (changedFilePath) => {
125
- logger_1.logger.log(`🔃 File changed: ${changedFilePath}, reloading content...`);
125
+ logger_1.logger.log('Livereload', `🔃 File changed: ${changedFilePath}, reloading content...`);
126
126
  ws.send(JSON.stringify({ type: 'reload-content' }));
127
127
  });
128
128
  contentWatcher.on('error', (e) => {
@@ -2,11 +2,48 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.logger = void 0;
4
4
  class Logger {
5
- log(message, ...args) {
6
- console.log(message, ...args);
5
+ constructor() {
6
+ this.silent = false;
7
+ }
8
+ setSilent(silent) {
9
+ this.silent = silent;
10
+ }
11
+ log(tag, message, ...args) {
12
+ if (this.silent) {
13
+ return;
14
+ }
15
+ this.getTagColor(tag)
16
+ .then(chalk => {
17
+ const paddedTag = tag.padEnd(12, ' '); // Pad to 12 characters
18
+ const tagColored = chalk(` ${paddedTag} `);
19
+ const formattedMessage = message.replace(/(https?:\/\/\S+)/g, (url) => {
20
+ // Apply OSC 8 for clickable link and chalk for styling
21
+ const styledUrl = chalk.reset.blue.underline(url);
22
+ return `\x1b]8;;${url}\x1b\\${styledUrl}\x1b]8;;\x1b\\`;
23
+ });
24
+ console.log(`${tagColored} ${formattedMessage}`, ...args);
25
+ });
7
26
  }
8
27
  error(message, ...args) {
9
- console.error(message, ...args);
28
+ import('chalk')
29
+ .then((module) => module.default)
30
+ .then(chalk => { console.error(chalk.bgRed.white(' Error '), message, ...args); });
31
+ }
32
+ getTagColor(tag) {
33
+ return import('chalk').then((module) => module.default).then(chalk => {
34
+ switch (tag) {
35
+ case 'CLI':
36
+ return chalk.bgGreen.white;
37
+ case 'Server':
38
+ return chalk.bgCyan.white;
39
+ case 'Livereload':
40
+ return chalk.bgBlue.white;
41
+ case 'Announcement':
42
+ return chalk.bgYellow.white;
43
+ default:
44
+ return chalk.bgWhite.black;
45
+ }
46
+ });
10
47
  }
11
48
  }
12
49
  exports.logger = new Logger();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdts",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "A markdown preview server.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,11 +57,13 @@
57
57
  "typescript-eslint": "^8.37.0"
58
58
  },
59
59
  "dependencies": {
60
+ "chalk": "^5.4.1",
60
61
  "chokidar": "^4.0.3",
61
62
  "commander": "^14.0.0",
62
63
  "express": "^4.19.2",
63
64
  "markdown-it": "^14.1.0",
64
65
  "open": "^10.2.0",
66
+ "simple-git": "^3.28.0",
65
67
  "ws": "^8.18.3"
66
68
  }
67
69
  }