-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
127 lines (110 loc) · 5.04 KB
/
script.js
File metadata and controls
127 lines (110 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const selectFolderBtn = document.getElementById('selectFolderBtn');
const outputArea = document.getElementById('outputArea');
const statusDiv = document.getElementById('status');
const copyBtn = document.getElementById('copyBtn');
// --- Configuration ---
const TEXT_FILE_EXTENSIONS = new Set([
'.py', '.js', '.html', '.css', '.json', '.md', '.txt',
'.cfg', '.ini', '.yaml', '.yml', '.sh', '.bat', '.xml',
'.java', '.c', '.cpp', '.h', '.hpp', '.cs', '.go', '.php',
'.rb', '.rs', '.swift', '.kt', '.kts', '.sql', '.dockerfile',
'readme', '.gitignore', '.env', '.config', '.toml'
]);
const IGNORE_LIST = new Set([
'.git', '.vscode', '.idea', 'node_modules', '__pycache__',
'.DS_Store', 'venv', '.env', 'dist', 'build', 'target',
]);
// --- Event Listener ---
selectFolderBtn.addEventListener('click', async () => {
try {
const directoryHandle = await window.showDirectoryPicker();
if (!directoryHandle) {
statusDiv.textContent = 'Status: Folder selection cancelled.';
return;
}
statusDiv.textContent = 'Status: Processing folder...';
outputArea.value = '';
copyBtn.style.display = 'none';
// Start processing - Pass empty string for initial relative path
const { tree, fileContents } = await processDirectory(directoryHandle, '', ''); // Pass '' for relativePath
// Combine and display results in the new desired format
const fullOutput = `${directoryHandle.name}/\n${tree}\n\n${fileContents}`;
outputArea.value = fullOutput;
statusDiv.textContent = `Status: Done processing folder "${directoryHandle.name}".`;
copyBtn.style.display = 'inline-block';
} catch (error) {
if (error.name === 'AbortError') {
statusDiv.textContent = 'Status: Folder selection cancelled.';
} else {
statusDiv.textContent = `Status: Error - ${error.message}`;
console.error('Error accessing directory:', error);
}
outputArea.value = `Error: ${error.message}\n\nPlease ensure your browser supports the File System Access API and you grant permission.`;
copyBtn.style.display = 'none';
}
});
copyBtn.addEventListener('click', () => {
outputArea.select();
try {
document.execCommand('copy');
statusDiv.textContent = 'Status: Copied to clipboard!';
} catch (err) {
statusDiv.textContent = 'Status: Failed to copy (try manual copy).';
console.error('Copy failed:', err);
}
window.getSelection().removeAllRanges();
});
// --- Core Processing Function ---
async function processDirectory(directoryHandle, relativePath, indent) {
let tree = '';
let fileContents = '';
const entries = [];
for await (const entry of directoryHandle.values()) {
if (!IGNORE_LIST.has(entry.name.toLowerCase())) {
entries.push(entry);
}
}
entries.sort((a, b) => {
if (a.kind !== b.kind) {
return a.kind === 'directory' ? -1 : 1;
}
return a.name.localeCompare(b.name);
});
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
const isLast = i === entries.length - 1;
const connector = isLast ? '└── ' : '├── ';
const currentRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
if (entry.kind === 'directory') {
tree += `${indent}${connector}${entry.name}/\n`;
const subIndent = indent + (isLast ? ' ' : '│ ');
const subResult = await processDirectory(entry, currentRelativePath, subIndent);
tree += subResult.tree;
fileContents += subResult.fileContents;
} else if (entry.kind === 'file') {
tree += `${indent}${connector}${entry.name}\n`;
if (isTextFile(entry.name)) {
try {
const file = await entry.getFile();
const content = await file.text();
// **MODIFIED LINES HERE** - Using start and end markers
fileContents += `# ${currentRelativePath}\n=== FILE CONTENT START ===\n${content}\n=== FILE CONTENT END ===\n\n`;
} catch (readError) {
console.warn(`Could not read file: ${currentRelativePath}`, readError);
// **MODIFIED LINES HERE** - Using start and end markers in error message
fileContents += `# ${currentRelativePath}\n=== FILE CONTENT START ===\n# --- Error reading file: ${readError.message} ---\n=== FILE CONTENT END ===\n\n`;
}
}
}
}
return { tree, fileContents };
}
// --- Helper Function ---
function isTextFile(filename) {
const lowerFilename = filename.toLowerCase();
if (TEXT_FILE_EXTENSIONS.has(lowerFilename)) {
return true;
}
const extension = '.' + lowerFilename.split('.').pop();
return TEXT_FILE_EXTENSIONS.has(extension);
}