rspress-plugin-file-tree 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/0~301.js ADDED
@@ -0,0 +1,2 @@
1
+ const htmlraw_namespaceObject = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><path fill=\"#e65100\" d=\"m4 4 2 22 10 2 10-2 2-22Zm19.72 7H11.28l.29 3h11.86l-.802 9.335L15.99 25l-6.635-1.646L8.93 19h3.02l.19 2 3.86.77 3.84-.77.29-4H8.84L8 8h16Z\"/></svg>";
2
+ export { htmlraw_namespaceObject };
@@ -4,6 +4,7 @@
4
4
  border: var(--rp-code-block-border, 1px solid var(--rp-c-divider-light));
5
5
  min-height: 100%;
6
6
  box-shadow: var(--rp-code-block-shadow, none);
7
+ background-color: var(--rp-code-block-bg);
7
8
  padding: 8px;
8
9
  font-family: inherit;
9
10
  font-size: 13px;
@@ -64,6 +65,15 @@
64
65
  overflow: hidden;
65
66
  }
66
67
 
68
+ .comment-_zMtnb {
69
+ color: var(--rp-c-text-2);
70
+ white-space: nowrap;
71
+ text-overflow: ellipsis;
72
+ margin-left: 8px;
73
+ font-style: italic;
74
+ overflow: hidden;
75
+ }
76
+
67
77
  .children-yp3kEz {
68
78
  flex-direction: column;
69
79
  display: flex;
@@ -141,6 +141,18 @@ const SUPPORTED_LANGUAGES = [
141
141
  matcher: /^.*\.(md|mdx)$/
142
142
  }
143
143
  ]
144
+ },
145
+ {
146
+ id: 'html',
147
+ icons: [
148
+ {
149
+ name: 'html',
150
+ content: ()=>import("../../0~301.js").then((mod)=>({
151
+ default: mod.htmlraw_namespaceObject
152
+ })),
153
+ matcher: /^.*\.html?$/
154
+ }
155
+ ]
144
156
  }
145
157
  ];
146
158
  const FOLDER_ICONS = {
@@ -404,6 +416,7 @@ const FileTreeItem_module = {
404
416
  chevron: "chevron-Zi120f",
405
417
  iconWrapper: "iconWrapper-SwAXs4",
406
418
  name: "name-ItNtUc",
419
+ comment: "comment-_zMtnb",
407
420
  children: "children-yp3kEz",
408
421
  indentGuide: "indentGuide-bjr2fi"
409
422
  };
@@ -432,7 +445,8 @@ const RemoteSvgIcon = ({ content, className })=>{
432
445
  };
433
446
  const INDENT_SIZE = 12;
434
447
  const FileTreeItem = ({ node, depth })=>{
435
- const [expanded, setExpanded] = useState(true);
448
+ const hasChildren = 'directory' === node.type && node.children.length > 0;
449
+ const [expanded, setExpanded] = useState(hasChildren);
436
450
  const icon = useMemo(()=>{
437
451
  if ('directory' === node.type) return getFolderIcon(node.name);
438
452
  return getFileIcon(node.name);
@@ -483,6 +497,10 @@ const FileTreeItem = ({ node, depth })=>{
483
497
  /*#__PURE__*/ jsx("span", {
484
498
  className: FileTreeItem_module.name,
485
499
  children: node.name
500
+ }),
501
+ node.comment && /*#__PURE__*/ jsx("span", {
502
+ className: FileTreeItem_module.comment,
503
+ children: node.comment
486
504
  })
487
505
  ]
488
506
  }),
@@ -3,6 +3,7 @@ export interface TreeNode {
3
3
  type: 'file' | 'directory';
4
4
  children: TreeNode[];
5
5
  extension?: string;
6
+ comment?: string;
6
7
  }
7
8
  export interface ParsedTree {
8
9
  nodes: TreeNode[];
package/dist/index.js CHANGED
@@ -1,21 +1,22 @@
1
1
  import node_path from "node:path";
2
2
  import { RemarkCodeBlockToGlobalComponentPluginFactory } from "rspress-plugin-devkit";
3
3
  function parseTreeContent(content) {
4
- const lines = content.split('\n').filter((line)=>line.trim());
4
+ let lines = content.split('\n').filter((line)=>line.trim());
5
+ if (lines.length > 0 && '.' === lines[0].trim()) lines = lines.slice(1);
5
6
  const nodes = [];
6
7
  const stack = [];
7
8
  for (const line of lines){
8
9
  const indent = calculateIndent(line);
9
10
  const fullName = extractName(line);
10
- const commentMatch = fullName.match(/^(.*?)(?:\s*\/\/\s*(.*))?$/);
11
- const name = commentMatch ? commentMatch[1].trim() : fullName;
11
+ const { name, comment } = extractNameAndComment(fullName);
12
12
  if (!name) continue;
13
13
  const isDirectory = isDirectoryName(name);
14
14
  const node = {
15
15
  name: name.replace(/\/$/, ''),
16
16
  type: isDirectory ? 'directory' : 'file',
17
17
  children: [],
18
- extension: isDirectory ? void 0 : getExtension(name)
18
+ extension: isDirectory ? void 0 : getExtension(name),
19
+ comment
19
20
  };
20
21
  while(stack.length > 0 && stack[stack.length - 1].indent >= indent)stack.pop();
21
22
  if (0 === stack.length) nodes.push(node);
@@ -40,11 +41,21 @@ function calculateIndent(line) {
40
41
  i += 4;
41
42
  continue;
42
43
  }
44
+ if ('│' === char && ' ' === line[i + 1]) {
45
+ indent++;
46
+ i += 2;
47
+ continue;
48
+ }
43
49
  if (' ' === line.substring(i, i + 4)) {
44
50
  indent++;
45
51
  i += 4;
46
52
  continue;
47
53
  }
54
+ if (' ' === line.substring(i, i + 2)) {
55
+ indent++;
56
+ i += 2;
57
+ continue;
58
+ }
48
59
  if ('├' === char || '└' === char) {
49
60
  if ('├──' === line.substring(i, i + 3) || '└──' === line.substring(i, i + 3)) indent++;
50
61
  }
@@ -55,10 +66,64 @@ function calculateIndent(line) {
55
66
  function extractName(line) {
56
67
  return line.replace(/^[\s│]*/g, '').replace(/^[├└]──\s*/, '').trim();
57
68
  }
69
+ function extractNameAndComment(fullName) {
70
+ const trimmed = fullName.trim();
71
+ if (!trimmed) return {
72
+ name: '',
73
+ comment: void 0
74
+ };
75
+ if (/^\.{2,}$/.test(trimmed)) return {
76
+ name: trimmed,
77
+ comment: void 0
78
+ };
79
+ const doubleSpaceMatch = trimmed.match(/^(.+?)\s{2,}(.+)$/);
80
+ if (doubleSpaceMatch) {
81
+ const potentialName = doubleSpaceMatch[1].trim();
82
+ const potentialComment = doubleSpaceMatch[2].trim();
83
+ if (isValidName(potentialName)) return {
84
+ name: potentialName,
85
+ comment: potentialComment
86
+ };
87
+ }
88
+ const singleSpaceMatch = trimmed.match(/^(.+?\.[a-zA-Z0-9]+)\s+([^.].*)$/);
89
+ if (singleSpaceMatch) {
90
+ const potentialName = singleSpaceMatch[1].trim();
91
+ const potentialComment = singleSpaceMatch[2].trim();
92
+ return {
93
+ name: potentialName,
94
+ comment: potentialComment
95
+ };
96
+ }
97
+ const hiddenFileMatch = trimmed.match(/^(\.[^\s]+)\s+(.+)$/);
98
+ if (hiddenFileMatch) return {
99
+ name: hiddenFileMatch[1].trim(),
100
+ comment: hiddenFileMatch[2].trim()
101
+ };
102
+ const dirCommentMatch = trimmed.match(/^([\w][\w.\s-]*?)\s+([^a-zA-Z0-9].*)$/);
103
+ if (dirCommentMatch) {
104
+ const potentialName = dirCommentMatch[1].trim();
105
+ if (!/\.[a-zA-Z0-9]+$/.test(potentialName)) return {
106
+ name: potentialName,
107
+ comment: dirCommentMatch[2].trim()
108
+ };
109
+ }
110
+ return {
111
+ name: trimmed,
112
+ comment: void 0
113
+ };
114
+ }
115
+ function isValidName(name) {
116
+ if (!name) return false;
117
+ if (name.endsWith('/')) return true;
118
+ if (/\.[a-zA-Z0-9]+$/.test(name)) return true;
119
+ if (name.startsWith('.')) return true;
120
+ if (/^[\w\s.-]+$/.test(name)) return true;
121
+ return false;
122
+ }
58
123
  function isDirectoryName(name) {
59
- const cleanName = name.split(/\s+\/\//)[0].trim();
60
- if (cleanName.endsWith('/')) return true;
61
- const lastPart = cleanName.split('/').pop() || cleanName;
124
+ if (name.endsWith('/')) return true;
125
+ const lastPart = name.split('/').pop() || name;
126
+ if (/^\.{2,}$/.test(lastPart)) return false;
62
127
  if (lastPart.startsWith('.')) return false;
63
128
  if (/\.[a-zA-Z0-9]+$/.test(lastPart)) return false;
64
129
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rspress-plugin-file-tree",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Rspress plugin that add support for file tree component.",
5
5
  "files": [
6
6
  "dist"