Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ on:
- master
release:
types:
- created
- released
pull_request:
branches:
- master

jobs:
build:
Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# JetTreeMark for VS Code

![Build](https://github.com/HichemTab-tech/JetTreeMark-vscode/actions/workflows/ci.yml/badge.svg)
[![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)
[![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)

---

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

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

Expand All @@ -48,7 +49,7 @@ or document.
### From the Marketplace

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


### Manual Installation
Expand Down Expand Up @@ -93,7 +94,7 @@ vsce package
## 🎯 How to Use

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

![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-")

Expand All @@ -102,7 +103,15 @@ vsce package

![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 -")

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

6. Click **"Copy Selected Structure"** at the top to copy your markdown tree.

---

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "jettreemark",
"displayName": "JetTreeMark",
"description": "JetTreeMark is a VS Code plugin that generates a markdown-compatible structure tree for selected files and folders",
"version": "1.0.1",
"version": "1.1.0",
"publisher": "HichemTab-tech",
"homepage": "https://github.com/HichemTab-tech/JetTreeMark-vscode",
"repository": {
Expand Down Expand Up @@ -81,6 +81,7 @@
"@vscode/test-cli": "^0.0.10",
"@vscode/test-electron": "^2.4.1",
"@vscode/vsce": "^3.3.2",
"cross-env": "^7.0.3",
"eslint": "^9.23.0",
"ts-loader": "^9.5.2",
"typescript": "^5.8.2",
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

158 changes: 157 additions & 1 deletion src/test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ import * as path from 'path';
import { buildTreeNode } from '../extension';
import * as fs from 'fs';
import * as os from "os";
// Import tree-utils functions for testing context menu options
import {
checkAllChildren,
checkAllFolders,
uncheckAllChildren,
checkWithoutChildren,
checkOnlyFoldersAtLevel,
checkOnlyFilesAtLevel,
checkAllChildrenAtLevel
} from './tree-utils';

suite('JetTreeMark-vscode Test Suite', () => {
test('Extension is present in the registry', () => {
Expand Down Expand Up @@ -63,4 +73,150 @@ suite('JetTreeMark-vscode Test Suite', () => {
assert.ok(bNode && bNode.type === 'file', 'b.txt should exist in subdir');
});
});
});
// Test suite for context menu options
suite('Context Menu Options Tests', () => {
// Sample tree structure for testing
let sampleTree: any[];

setup(() => {
// Create a sample tree structure before each test
sampleTree = [
{
id: 'root',
name: 'root',
type: 'folder',
checked: false,
indeterminate: false,
children: [
{
id: 'folder1',
name: 'folder1',
type: 'folder',
checked: false,
indeterminate: false,
children: [
{
id: 'file1',
name: 'file1.txt',
type: 'file',
checked: false
},
{
id: 'file2',
name: 'file2.txt',
type: 'file',
checked: false
}
]
},
{
id: 'folder2',
name: 'folder2',
type: 'folder',
checked: false,
indeterminate: false,
children: [
{
id: 'file3',
name: 'file3.txt',
type: 'file',
checked: false
}
]
},
{
id: 'file4',
name: 'file4.txt',
type: 'file',
checked: false
}
]
}
];
});

test('checkAllChildren sets all nodes to checked', () => {
const result = checkAllChildren(sampleTree);

// Check that all nodes are checked
assert.strictEqual(result[0].checked, true, 'Root node should be checked');
assert.strictEqual(result[0].children![0].checked, true, 'folder1 should be checked');
assert.strictEqual(result[0].children![0].children![0].checked, true, 'file1 should be checked');
assert.strictEqual(result[0].children![0].children![1].checked, true, 'file2 should be checked');
assert.strictEqual(result[0].children![1].checked, true, 'folder2 should be checked');
assert.strictEqual(result[0].children![1].children![0].checked, true, 'file3 should be checked');
assert.strictEqual(result[0].children![2].checked, true, 'file4 should be checked');
});

test('checkAllFolders sets only folder nodes to checked', () => {
const result = checkAllFolders(sampleTree);

// Check that only folder nodes are checked
assert.strictEqual(result[0].checked, true, 'Root node should be checked');
assert.strictEqual(result[0].children![0].checked, true, 'folder1 should be checked');
assert.strictEqual(result[0].children![0].children![0].checked, false, 'file1 should not be checked');
assert.strictEqual(result[0].children![0].children![1].checked, false, 'file2 should not be checked');
assert.strictEqual(result[0].children![1].checked, true, 'folder2 should be checked');
assert.strictEqual(result[0].children![1].children![0].checked, false, 'file3 should not be checked');
assert.strictEqual(result[0].children![2].checked, false, 'file4 should not be checked');
});

test('uncheckAllChildren sets all nodes to unchecked', () => {
// First check all nodes
sampleTree = checkAllChildren(sampleTree);

// Then uncheck all nodes
const result = uncheckAllChildren(sampleTree);

// Check that all nodes are unchecked
assert.strictEqual(result[0].checked, false, 'Root node should be unchecked');
assert.strictEqual(result[0].children![0].checked, false, 'folder1 should be unchecked');
assert.strictEqual(result[0].children![0].children![0].checked, false, 'file1 should be unchecked');
assert.strictEqual(result[0].children![0].children![1].checked, false, 'file2 should be unchecked');
assert.strictEqual(result[0].children![1].checked, false, 'folder2 should be unchecked');
assert.strictEqual(result[0].children![1].children![0].checked, false, 'file3 should be unchecked');
assert.strictEqual(result[0].children![2].checked, false, 'file4 should be unchecked');
});

test('checkWithoutChildren checks a node without affecting its children', () => {
// Apply checkWithoutChildren to folder1
const folder1 = sampleTree[0].children![0];
const result = checkWithoutChildren(folder1);

// Check that folder1 is checked but its children are not
assert.strictEqual(result.checked, true, 'folder1 should be checked');
assert.strictEqual(result.children![0].checked, false, 'file1 should not be checked');
assert.strictEqual(result.children![1].checked, false, 'file2 should not be checked');
});

test('checkOnlyFoldersAtLevel checks only folder nodes at a specific level', () => {
// Apply checkOnlyFoldersAtLevel to root's children
const result = checkOnlyFoldersAtLevel(sampleTree[0].children!);

// Check that only folder nodes at this level are checked
assert.strictEqual(result[0].checked, true, 'folder1 should be checked');
assert.strictEqual(result[1].checked, true, 'folder2 should be checked');
assert.strictEqual(result[2].checked, false, 'file4 should not be checked');
});

test('checkOnlyFilesAtLevel checks only file nodes at a specific level', () => {
// Apply checkOnlyFilesAtLevel to root's children
const result = checkOnlyFilesAtLevel(sampleTree[0].children!);

// Check that only file nodes at this level are checked
assert.strictEqual(result[0].checked, false, 'folder1 should not be checked');
assert.strictEqual(result[1].checked, false, 'folder2 should not be checked');
assert.strictEqual(result[2].checked, true, 'file4 should be checked');
});

test('checkAllChildrenAtLevel checks all nodes at a specific level', () => {
// Apply checkAllChildrenAtLevel to root's children
const result = checkAllChildrenAtLevel(sampleTree[0].children!);

// Check that all nodes at this level are checked
assert.strictEqual(result[0].checked, true, 'folder1 should be checked');
assert.strictEqual(result[1].checked, true, 'folder2 should be checked');
assert.strictEqual(result[2].checked, true, 'file4 should be checked');
});
});
});
Loading