Skip to content

Commit 6617d45

Browse files
committed
Merge branch 'feat/folder-tree' into chore/all-my-stuffs
# Conflicts: # package.json # pnpm-lock.yaml # src/tools/index.ts
2 parents 615cdd0 + 6e113a8 commit 6617d45

File tree

12 files changed

+715
-1
lines changed

12 files changed

+715
-1
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
"@types/figlet": "^1.5.8",
5353
"@types/luxon": "^3.4.2",
5454
"@types/markdown-it": "^13.0.7",
55+
"@types/lodash.defaultsdeep": "^4.6.9",
56+
"@types/lodash.flattendeep": "^4.4.9",
57+
"@types/lodash.last": "^3.0.9",
5558
"@vicons/material": "^0.12.0",
5659
"@vicons/tabler": "^0.12.0",
5760
"@vueuse/core": "^10.11.1",
@@ -104,6 +107,9 @@
104107
"lodash": "^4.17.21",
105108
"luxon": "^3.5.0",
106109
"markdown-it": "^14.0.0",
110+
"lodash.defaultsdeep": "^4.6.1",
111+
"lodash.flattendeep": "^4.4.0",
112+
"lodash.last": "^3.0.0",
107113
"marked": "^10.0.0",
108114
"mathjs": "^11.9.1",
109115
"mime-types": "^2.1.35",

pnpm-lock.yaml

Lines changed: 48 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<script setup lang="ts">
2+
import { generateTree } from './lib/generate-tree';
3+
import { parseInput } from './lib/parse-input';
4+
import { withDefaultOnError } from '@/utils/defaults';
5+
6+
const inputStructure = ref([
7+
'my-app',
8+
' src',
9+
' index.html',
10+
' main.ts',
11+
' main.scss',
12+
' - build',
13+
' - index.html',
14+
' main.js',
15+
' main.css',
16+
'',
17+
' ',
18+
' .prettierrc.json',
19+
' .gitlab-ci.yml',
20+
' README.md',
21+
'empty dir',
22+
].join('\n'));
23+
const outputTree = computed(() => withDefaultOnError(() => generateTree(parseInput(inputStructure.value)), ''));
24+
</script>
25+
26+
<template>
27+
<div>
28+
<c-input-text
29+
v-model:value="inputStructure"
30+
label="Your indented structure"
31+
placeholder="Paste your indented structure here..."
32+
rows="20"
33+
multiline
34+
raw-text
35+
monospace
36+
/>
37+
38+
<n-divider />
39+
40+
<n-form-item label="Your tree-like structure:">
41+
<TextareaCopyable :value="outputTree" />
42+
</n-form-item>
43+
</div>
44+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Folder } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Folder Structure Diagram',
6+
path: '/folder-structure-diagram',
7+
description: 'tree-like utility for generating ASCII folder structure diagrams',
8+
keywords: ['folder', 'structure', 'diagram', 'tree', 'ascii'],
9+
component: () => import('./folder-structure-diagram.vue'),
10+
icon: Folder,
11+
createdAt: new Date('2024-04-20'),
12+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Represents a single item in a file system
3+
* (i.e. a file or a folder)
4+
*/
5+
export interface FileStructure {
6+
/** The name of the file or folder */
7+
name: string
8+
9+
/** If a folder, the contents of the folder */
10+
children: FileStructure[]
11+
12+
/**
13+
* The number of spaces in front of the name
14+
* in the original source string
15+
*/
16+
indentCount: number
17+
18+
/** The parent directory of this file or folder */
19+
parent: FileStructure | null
20+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { generateTree } from './generate-tree';
3+
import { mockInput } from './mock-input';
4+
import { parseInput } from './parse-input';
5+
6+
describe('generateTree', () => {
7+
it('returns an UTF-8 representation of the provided FileStructure object', () => {
8+
const actual = generateTree(parseInput(mockInput));
9+
10+
const expected = `
11+
.
12+
├── my-app
13+
│ ├── src
14+
│ │ ├── index.html
15+
│ │ ├── main.ts
16+
│ │ └── main.scss
17+
│ ├── build
18+
│ │ ├── index.html
19+
│ │ ├── main.js
20+
│ │ └── main.css
21+
│ ├── .prettierrc.json
22+
│ ├── .gitlab-ci.yml
23+
│ └── README.md
24+
└── empty dir
25+
26+
`.trim();
27+
28+
expect(actual).toEqual(expected);
29+
});
30+
31+
it('returns an ASCII representation of the provided FileStructure object', () => {
32+
const actual = generateTree(parseInput(mockInput), { charset: 'ascii' });
33+
34+
const expected = `
35+
.
36+
|-- my-app
37+
| |-- src
38+
| | |-- index.html
39+
| | |-- main.ts
40+
| | \`-- main.scss
41+
| |-- build
42+
| | |-- index.html
43+
| | |-- main.js
44+
| | \`-- main.css
45+
| |-- .prettierrc.json
46+
| |-- .gitlab-ci.yml
47+
| \`-- README.md
48+
\`-- empty dir
49+
50+
`.trim();
51+
52+
expect(actual).toEqual(expected);
53+
});
54+
55+
it('does not render lines for parent directories that have already printed all of their children', () => {
56+
const input = `
57+
58+
grandparent
59+
parent
60+
child
61+
parent
62+
child
63+
grandchild
64+
65+
`;
66+
67+
const actual = generateTree(parseInput(input));
68+
69+
const expected = `
70+
.
71+
└── grandparent
72+
├── parent
73+
│ └── child
74+
└── parent
75+
└── child
76+
└── grandchild
77+
78+
`.trim();
79+
80+
expect(actual).toEqual(expected);
81+
});
82+
83+
it('appends a trailing slash to directories if trailingDirSlash === true', () => {
84+
const input = `
85+
86+
grandparent
87+
parent/
88+
child
89+
parent//
90+
child
91+
grandchild
92+
93+
`;
94+
95+
const actual = generateTree(parseInput(input), { trailingDirSlash: true });
96+
97+
const expected = `
98+
.
99+
└── grandparent/
100+
├── parent/
101+
│ └── child
102+
└── parent//
103+
└── child/
104+
└── grandchild
105+
106+
`.trim();
107+
108+
expect(actual).toEqual(expected);
109+
});
110+
111+
it('prints each items\' full path if fullPath === true', () => {
112+
const input = `
113+
114+
grandparent
115+
parent/
116+
child
117+
parent//
118+
child
119+
grandchild
120+
121+
`;
122+
123+
const actual = generateTree(parseInput(input), { fullPath: true });
124+
125+
const expected = `
126+
.
127+
└── ./grandparent
128+
├── ./grandparent/parent/
129+
│ └── ./grandparent/parent/child
130+
└── ./grandparent/parent//
131+
└── ./grandparent/parent//child
132+
└── ./grandparent/parent//child/grandchild
133+
134+
`.trim();
135+
136+
expect(actual).toEqual(expected);
137+
});
138+
139+
it('does not render the root dot if rootDot === false', () => {
140+
const input = `
141+
142+
grandparent
143+
parent
144+
child
145+
parent
146+
child
147+
grandchild
148+
149+
`;
150+
151+
const actual = generateTree(parseInput(input), { rootDot: false });
152+
153+
const expected = `
154+
grandparent
155+
├── parent
156+
│ └── child
157+
└── parent
158+
└── child
159+
└── grandchild
160+
161+
`.trim();
162+
163+
expect(actual).toEqual(expected);
164+
});
165+
});

0 commit comments

Comments
 (0)