mdts 0.7.0 → 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 +14 -12
- package/dist/cli.js +11 -3
- package/dist/frontend/bundle.js +6 -6
- package/dist/server/routes/filetree.js +32 -10
- package/dist/server/server.js +4 -3
- package/dist/server/watcher.js +7 -7
- package/dist/utils/logger.js +40 -3
- package/package.json +3 -1
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="
|
|
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
|
-
|
|
32
|
-
|
|
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
|
});
|
package/dist/frontend/bundle.js
CHANGED
|
@@ -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.
|
|
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 =
|
|
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 (
|
|
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
|
|
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 (
|
|
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
|
-
|
|
13
|
-
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
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) {
|
|
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
|
-
|
|
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
|
+
});
|
package/dist/server/server.js
CHANGED
|
@@ -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(
|
|
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;
|
package/dist/server/watcher.js
CHANGED
|
@@ -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) => {
|
package/dist/utils/logger.js
CHANGED
|
@@ -2,11 +2,48 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.logger = void 0;
|
|
4
4
|
class Logger {
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
}
|