Skip to content

Commit 5b6aff8

Browse files
Merge pull request #1 from HichemTab-tech/add-more-control-over-selection
feat: Expand folder selection options with advanced context menu controls
2 parents 694574d + 54b8246 commit 5b6aff8

24 files changed

+1900
-425
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ on:
44
- master
55
release:
66
types:
7-
- created
7+
- released
8+
pull_request:
9+
branches:
10+
- master
811

912
jobs:
1013
build:

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# JetTreeMark for VS Code
22

33
![Build](https://github.com/HichemTab-tech/JetTreeMark-vscode/actions/workflows/ci.yml/badge.svg)
4-
[![Version](https://img.shields.io/badge/version-1.0.1-blue.svg)](https://github.com/HichemTab-tech/JetTreeMark-vscode/releases) [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/HichemTab-tech/JetTreeMark-vscode/blob/master/LICENSE)
4+
[![Version](https://img.shields.io/badge/version-1.1.0-blue.svg)](https://github.com/HichemTab-tech/JetTreeMark-vscode/releases) [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/HichemTab-tech/JetTreeMark-vscode/blob/master/LICENSE)
55

66
---
77

@@ -10,7 +10,7 @@
1010
**JetTreeMark** for VS Code brings the same lightning-fast,
1111
one-click tree-view generation you know from the IntelliJ plugin into your favorite editor.
1212
Right-click any folder in the Explorer, choose **Show Tree View**,
13-
and youll instantly get a clean, customizable markdown-compatible tree of your project—ready to copy, share,
13+
and you'll instantly get a clean, customizable markdown-compatible tree of your project—ready to copy, share,
1414
or document.
1515
😉
1616

@@ -24,6 +24,7 @@ or document.
2424
- 📂 **Generate** a neat tree view of any selected folder
2525
- 📋 **Copy** the filtered structure to clipboard with one click
2626
- ✔️ **Tri-state checkboxes** let you include/exclude subfolders & files
27+
- 🖱️ **Context menu** with powerful selection operations (check/uncheck folders, files, levels)
2728
-**Lightweight**—built as a native VS Code Webview extension
2829
- 🎨 **Tailwind-powered** UI for a clean, responsive look
2930

@@ -48,7 +49,7 @@ or document.
4849
### From the Marketplace
4950

5051
JetTreeMark is now available on the Visual Studio Marketplace!
51-
Install it directly from VS Codes Extensions view—just search for **JetTreeMark** and click **Install**.
52+
Install it directly from VS Code's Extensions view—just search for **JetTreeMark** and click **Install**.
5253

5354

5455
### Manual Installation
@@ -93,7 +94,7 @@ vsce package
9394
## 🎯 How to Use
9495

9596
1. **Right-click** on any folder in the Explorer.
96-
2. Select **Show Tree View** from the context menu.
97+
2. Select **"Show Tree View"** from the context menu.
9798

9899
![How to use the JetTreeMark plugin from folder context menu](https://github.com/HichemTab-tech/JetTreeMark-vscode/blob/master/meta/screenshot-1.png "Screenshot -JetTreeMark in context menu-")
99100

@@ -102,7 +103,15 @@ vsce package
102103

103104
![How to use the JetTreeMark plugin to exclude nodes from the tree view result](https://github.com/HichemTab-tech/JetTreeMark-vscode/blob/master/meta/screenshot-2.png "Screenshot - filter nodes from tree results -")
104105

105-
5. Click **“Copy Selected Structure”** at the top to copy your markdown tree.
106+
5. **Right-click** on any node to access the context menu with powerful selection operations:
107+
- **Check All Children** - Include all files and folders under this node
108+
- **Check All Folders** - Include only folders under this node
109+
- **Uncheck All Children** - Exclude all files and folders under this node
110+
- **Check Without Children** - Include only this node, not its children
111+
- **Level-Specific Operations** - Apply operations only to the current level
112+
- **Expand/Collapse** - Control node visibility
113+
114+
6. Click **"Copy Selected Structure"** at the top to copy your markdown tree.
106115

107116
---
108117

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "jettreemark",
33
"displayName": "JetTreeMark",
44
"description": "JetTreeMark is a VS Code plugin that generates a markdown-compatible structure tree for selected files and folders",
5-
"version": "1.0.1",
5+
"version": "1.1.0",
66
"publisher": "HichemTab-tech",
77
"homepage": "https://github.com/HichemTab-tech/JetTreeMark-vscode",
88
"repository": {
@@ -81,6 +81,7 @@
8181
"@vscode/test-cli": "^0.0.10",
8282
"@vscode/test-electron": "^2.4.1",
8383
"@vscode/vsce": "^3.3.2",
84+
"cross-env": "^7.0.3",
8485
"eslint": "^9.23.0",
8586
"ts-loader": "^9.5.2",
8687
"typescript": "^5.8.2",

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/test/extension.test.ts

Lines changed: 157 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ import * as path from 'path';
55
import { buildTreeNode } from '../extension';
66
import * as fs from 'fs';
77
import * as os from "os";
8+
// Import tree-utils functions for testing context menu options
9+
import {
10+
checkAllChildren,
11+
checkAllFolders,
12+
uncheckAllChildren,
13+
checkWithoutChildren,
14+
checkOnlyFoldersAtLevel,
15+
checkOnlyFilesAtLevel,
16+
checkAllChildrenAtLevel
17+
} from './tree-utils';
818

919
suite('JetTreeMark-vscode Test Suite', () => {
1020
test('Extension is present in the registry', () => {
@@ -63,4 +73,150 @@ suite('JetTreeMark-vscode Test Suite', () => {
6373
assert.ok(bNode && bNode.type === 'file', 'b.txt should exist in subdir');
6474
});
6575
});
66-
});
76+
// Test suite for context menu options
77+
suite('Context Menu Options Tests', () => {
78+
// Sample tree structure for testing
79+
let sampleTree: any[];
80+
81+
setup(() => {
82+
// Create a sample tree structure before each test
83+
sampleTree = [
84+
{
85+
id: 'root',
86+
name: 'root',
87+
type: 'folder',
88+
checked: false,
89+
indeterminate: false,
90+
children: [
91+
{
92+
id: 'folder1',
93+
name: 'folder1',
94+
type: 'folder',
95+
checked: false,
96+
indeterminate: false,
97+
children: [
98+
{
99+
id: 'file1',
100+
name: 'file1.txt',
101+
type: 'file',
102+
checked: false
103+
},
104+
{
105+
id: 'file2',
106+
name: 'file2.txt',
107+
type: 'file',
108+
checked: false
109+
}
110+
]
111+
},
112+
{
113+
id: 'folder2',
114+
name: 'folder2',
115+
type: 'folder',
116+
checked: false,
117+
indeterminate: false,
118+
children: [
119+
{
120+
id: 'file3',
121+
name: 'file3.txt',
122+
type: 'file',
123+
checked: false
124+
}
125+
]
126+
},
127+
{
128+
id: 'file4',
129+
name: 'file4.txt',
130+
type: 'file',
131+
checked: false
132+
}
133+
]
134+
}
135+
];
136+
});
137+
138+
test('checkAllChildren sets all nodes to checked', () => {
139+
const result = checkAllChildren(sampleTree);
140+
141+
// Check that all nodes are checked
142+
assert.strictEqual(result[0].checked, true, 'Root node should be checked');
143+
assert.strictEqual(result[0].children![0].checked, true, 'folder1 should be checked');
144+
assert.strictEqual(result[0].children![0].children![0].checked, true, 'file1 should be checked');
145+
assert.strictEqual(result[0].children![0].children![1].checked, true, 'file2 should be checked');
146+
assert.strictEqual(result[0].children![1].checked, true, 'folder2 should be checked');
147+
assert.strictEqual(result[0].children![1].children![0].checked, true, 'file3 should be checked');
148+
assert.strictEqual(result[0].children![2].checked, true, 'file4 should be checked');
149+
});
150+
151+
test('checkAllFolders sets only folder nodes to checked', () => {
152+
const result = checkAllFolders(sampleTree);
153+
154+
// Check that only folder nodes are checked
155+
assert.strictEqual(result[0].checked, true, 'Root node should be checked');
156+
assert.strictEqual(result[0].children![0].checked, true, 'folder1 should be checked');
157+
assert.strictEqual(result[0].children![0].children![0].checked, false, 'file1 should not be checked');
158+
assert.strictEqual(result[0].children![0].children![1].checked, false, 'file2 should not be checked');
159+
assert.strictEqual(result[0].children![1].checked, true, 'folder2 should be checked');
160+
assert.strictEqual(result[0].children![1].children![0].checked, false, 'file3 should not be checked');
161+
assert.strictEqual(result[0].children![2].checked, false, 'file4 should not be checked');
162+
});
163+
164+
test('uncheckAllChildren sets all nodes to unchecked', () => {
165+
// First check all nodes
166+
sampleTree = checkAllChildren(sampleTree);
167+
168+
// Then uncheck all nodes
169+
const result = uncheckAllChildren(sampleTree);
170+
171+
// Check that all nodes are unchecked
172+
assert.strictEqual(result[0].checked, false, 'Root node should be unchecked');
173+
assert.strictEqual(result[0].children![0].checked, false, 'folder1 should be unchecked');
174+
assert.strictEqual(result[0].children![0].children![0].checked, false, 'file1 should be unchecked');
175+
assert.strictEqual(result[0].children![0].children![1].checked, false, 'file2 should be unchecked');
176+
assert.strictEqual(result[0].children![1].checked, false, 'folder2 should be unchecked');
177+
assert.strictEqual(result[0].children![1].children![0].checked, false, 'file3 should be unchecked');
178+
assert.strictEqual(result[0].children![2].checked, false, 'file4 should be unchecked');
179+
});
180+
181+
test('checkWithoutChildren checks a node without affecting its children', () => {
182+
// Apply checkWithoutChildren to folder1
183+
const folder1 = sampleTree[0].children![0];
184+
const result = checkWithoutChildren(folder1);
185+
186+
// Check that folder1 is checked but its children are not
187+
assert.strictEqual(result.checked, true, 'folder1 should be checked');
188+
assert.strictEqual(result.children![0].checked, false, 'file1 should not be checked');
189+
assert.strictEqual(result.children![1].checked, false, 'file2 should not be checked');
190+
});
191+
192+
test('checkOnlyFoldersAtLevel checks only folder nodes at a specific level', () => {
193+
// Apply checkOnlyFoldersAtLevel to root's children
194+
const result = checkOnlyFoldersAtLevel(sampleTree[0].children!);
195+
196+
// Check that only folder nodes at this level are checked
197+
assert.strictEqual(result[0].checked, true, 'folder1 should be checked');
198+
assert.strictEqual(result[1].checked, true, 'folder2 should be checked');
199+
assert.strictEqual(result[2].checked, false, 'file4 should not be checked');
200+
});
201+
202+
test('checkOnlyFilesAtLevel checks only file nodes at a specific level', () => {
203+
// Apply checkOnlyFilesAtLevel to root's children
204+
const result = checkOnlyFilesAtLevel(sampleTree[0].children!);
205+
206+
// Check that only file nodes at this level are checked
207+
assert.strictEqual(result[0].checked, false, 'folder1 should not be checked');
208+
assert.strictEqual(result[1].checked, false, 'folder2 should not be checked');
209+
assert.strictEqual(result[2].checked, true, 'file4 should be checked');
210+
});
211+
212+
test('checkAllChildrenAtLevel checks all nodes at a specific level', () => {
213+
// Apply checkAllChildrenAtLevel to root's children
214+
const result = checkAllChildrenAtLevel(sampleTree[0].children!);
215+
216+
// Check that all nodes at this level are checked
217+
assert.strictEqual(result[0].checked, true, 'folder1 should be checked');
218+
assert.strictEqual(result[1].checked, true, 'folder2 should be checked');
219+
assert.strictEqual(result[2].checked, true, 'file4 should be checked');
220+
});
221+
});
222+
});

0 commit comments

Comments
 (0)