gh-here 3.0.3 → 3.1.0

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.
Files changed (41) hide show
  1. package/.env +0 -0
  2. package/.playwright-mcp/fixed-alignment.png +0 -0
  3. package/.playwright-mcp/fixed-layout.png +0 -0
  4. package/.playwright-mcp/gh-here-home-header-table.png +0 -0
  5. package/.playwright-mcp/gh-here-home.png +0 -0
  6. package/.playwright-mcp/line-selection-multiline.png +0 -0
  7. package/.playwright-mcp/line-selection-test-after.png +0 -0
  8. package/.playwright-mcp/line-selection-test-before.png +0 -0
  9. package/.playwright-mcp/page-2026-01-03T17-58-21-336Z.png +0 -0
  10. package/lib/constants.js +25 -15
  11. package/lib/content-search.js +212 -0
  12. package/lib/error-handler.js +39 -28
  13. package/lib/file-utils.js +438 -287
  14. package/lib/git.js +10 -54
  15. package/lib/gitignore.js +70 -41
  16. package/lib/renderers.js +15 -19
  17. package/lib/server.js +70 -193
  18. package/lib/symbol-parser.js +600 -0
  19. package/package.json +1 -1
  20. package/public/app.js +134 -68
  21. package/public/js/constants.js +50 -34
  22. package/public/js/content-search-handler.js +551 -0
  23. package/public/js/file-viewer.js +437 -0
  24. package/public/js/focus-mode.js +280 -0
  25. package/public/js/inline-search.js +659 -0
  26. package/public/js/modal-manager.js +14 -28
  27. package/public/js/symbol-outline.js +454 -0
  28. package/public/js/utils.js +152 -94
  29. package/public/styles.css +2049 -296
  30. package/.claude/settings.local.json +0 -30
  31. package/SAMPLE.md +0 -287
  32. package/lib/validation.js +0 -77
  33. package/public/app.js.backup +0 -1902
  34. package/public/js/draft-manager.js +0 -36
  35. package/public/js/editor-manager.js +0 -159
  36. package/test.js +0 -138
  37. package/tests/draftManager.test.js +0 -241
  38. package/tests/fileTypeDetection.test.js +0 -111
  39. package/tests/httpService.test.js +0 -268
  40. package/tests/languageDetection.test.js +0 -145
  41. package/tests/pathUtils.test.js +0 -136
@@ -1,30 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(chmod:*)",
5
- "Bash(npm install)",
6
- "Bash(npm start)",
7
- "Bash(pkill:*)",
8
- "Bash(node:*)",
9
- "Bash(curl:*)",
10
- "Bash(npm install:*)",
11
- "Bash(git init:*)",
12
- "Bash(git add:*)",
13
- "Bash(git commit:*)",
14
- "Bash(git rm:*)",
15
- "Bash(ssh:*)",
16
- "Bash(git restore:*)",
17
- "Bash(npx gh-here:*)",
18
- "Bash(git checkout:*)",
19
- "Bash(git push:*)",
20
- "Bash(git pull:*)",
21
- "Bash(npm publish:*)",
22
- "Bash(timeout:*)",
23
- "Bash(npm version:*)",
24
- "Bash(gh release create:*)",
25
- "Bash(tree:*)"
26
- ],
27
- "deny": [],
28
- "ask": []
29
- }
30
- }
package/SAMPLE.md DELETED
@@ -1,287 +0,0 @@
1
- # Syntax Highlighting Test
2
-
3
- This file contains code samples in various languages to test syntax highlighting in markdown rendering.
4
-
5
- ## JavaScript
6
-
7
- ```javascript
8
- function greet(name) {
9
- const message = `Hello, ${name}!`;
10
- console.log(message);
11
- return message;
12
- }
13
-
14
- class Person {
15
- constructor(name, age) {
16
- this.name = name;
17
- this.age = age;
18
- }
19
-
20
- introduce() {
21
- return `My name is ${this.name} and I'm ${this.age} years old.`;
22
- }
23
- }
24
- ```
25
-
26
- ## Python
27
-
28
- ```python
29
- def calculate_fibonacci(n):
30
- """Calculate the nth Fibonacci number."""
31
- if n <= 1:
32
- return n
33
- return calculate_fibonacci(n - 1) + calculate_fibonacci(n - 2)
34
-
35
- class Animal:
36
- def __init__(self, name, species):
37
- self.name = name
38
- self.species = species
39
-
40
- def make_sound(self):
41
- return f"{self.name} the {self.species} makes a sound"
42
- ```
43
-
44
- ## Go
45
-
46
- ```go
47
- package main
48
-
49
- import (
50
- "fmt"
51
- "time"
52
- )
53
-
54
- type User struct {
55
- Name string
56
- Email string
57
- CreatedAt time.Time
58
- }
59
-
60
- func (u *User) SendEmail(message string) error {
61
- fmt.Printf("Sending email to %s: %s\n", u.Email, message)
62
- return nil
63
- }
64
-
65
- func main() {
66
- user := &User{
67
- Name: "John Doe",
68
- Email: "john@example.com",
69
- CreatedAt: time.Now(),
70
- }
71
- user.SendEmail("Welcome!")
72
- }
73
- ```
74
-
75
- ## Rust
76
-
77
- ```rust
78
- use std::collections::HashMap;
79
-
80
- fn main() {
81
- let mut scores = HashMap::new();
82
- scores.insert(String::from("Blue"), 10);
83
- scores.insert(String::from("Red"), 50);
84
-
85
- for (key, value) in &scores {
86
- println!("{}: {}", key, value);
87
- }
88
- }
89
-
90
- struct Rectangle {
91
- width: u32,
92
- height: u32,
93
- }
94
-
95
- impl Rectangle {
96
- fn area(&self) -> u32 {
97
- self.width * self.height
98
- }
99
- }
100
- ```
101
-
102
- ## TypeScript
103
-
104
- ```typescript
105
- interface User {
106
- id: number;
107
- name: string;
108
- email: string;
109
- }
110
-
111
- async function fetchUser(id: number): Promise<User> {
112
- const response = await fetch(`/api/users/${id}`);
113
- const data: User = await response.json();
114
- return data;
115
- }
116
-
117
- class UserService {
118
- private users: Map<number, User> = new Map();
119
-
120
- addUser(user: User): void {
121
- this.users.set(user.id, user);
122
- }
123
-
124
- getUser(id: number): User | undefined {
125
- return this.users.get(id);
126
- }
127
- }
128
- ```
129
-
130
- ## Bash
131
-
132
- ```bash
133
- #!/bin/bash
134
-
135
- # Function to backup files
136
- backup_files() {
137
- local source_dir=$1
138
- local backup_dir=$2
139
-
140
- if [ ! -d "$backup_dir" ]; then
141
- mkdir -p "$backup_dir"
142
- fi
143
-
144
- tar -czf "$backup_dir/backup-$(date +%Y%m%d).tar.gz" "$source_dir"
145
- echo "Backup completed successfully!"
146
- }
147
-
148
- backup_files "/home/user/documents" "/home/user/backups"
149
- ```
150
-
151
- ## SQL
152
-
153
- ```sql
154
- -- Create users table
155
- CREATE TABLE users (
156
- id SERIAL PRIMARY KEY,
157
- username VARCHAR(50) UNIQUE NOT NULL,
158
- email VARCHAR(100) UNIQUE NOT NULL,
159
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
160
- );
161
-
162
- -- Insert some data
163
- INSERT INTO users (username, email) VALUES
164
- ('john_doe', 'john@example.com'),
165
- ('jane_smith', 'jane@example.com');
166
-
167
- -- Query with JOIN
168
- SELECT u.username, o.order_date, o.total
169
- FROM users u
170
- INNER JOIN orders o ON u.id = o.user_id
171
- WHERE o.total > 100
172
- ORDER BY o.order_date DESC;
173
- ```
174
-
175
- ## JSON
176
-
177
- ```json
178
- {
179
- "name": "gh-here",
180
- "version": "2.0.0",
181
- "description": "A local GitHub-like file browser",
182
- "dependencies": {
183
- "express": "^4.18.2",
184
- "highlight.js": "^11.9.0",
185
- "marked": "^12.0.0"
186
- },
187
- "scripts": {
188
- "start": "node bin/gh-here.js",
189
- "test": "jest"
190
- }
191
- }
192
- ```
193
-
194
- ## CSS
195
-
196
- ```css
197
- :root {
198
- --primary-color: #0366d6;
199
- --background-color: #ffffff;
200
- --text-color: #24292e;
201
- }
202
-
203
- .container {
204
- max-width: 1200px;
205
- margin: 0 auto;
206
- padding: 20px;
207
- }
208
-
209
- .button {
210
- display: inline-block;
211
- padding: 10px 20px;
212
- background-color: var(--primary-color);
213
- color: white;
214
- border-radius: 5px;
215
- transition: background-color 0.3s ease;
216
- }
217
-
218
- .button:hover {
219
- background-color: #0256c7;
220
- cursor: pointer;
221
- }
222
- ```
223
-
224
- ## HTML
225
-
226
- ```html
227
- <!DOCTYPE html>
228
- <html lang="en">
229
- <head>
230
- <meta charset="UTF-8">
231
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
232
- <title>Sample Page</title>
233
- <link rel="stylesheet" href="styles.css">
234
- </head>
235
- <body>
236
- <header>
237
- <h1>Welcome to My Site</h1>
238
- <nav>
239
- <ul>
240
- <li><a href="#home">Home</a></li>
241
- <li><a href="#about">About</a></li>
242
- <li><a href="#contact">Contact</a></li>
243
- </ul>
244
- </nav>
245
- </header>
246
- <main>
247
- <p>This is the main content area.</p>
248
- </main>
249
- <script src="script.js"></script>
250
- </body>
251
- </html>
252
- ```
253
-
254
- ## Java
255
-
256
- ```java
257
- import java.util.ArrayList;
258
- import java.util.List;
259
-
260
- public class BankAccount {
261
- private String accountNumber;
262
- private double balance;
263
- private List<Transaction> transactions;
264
-
265
- public BankAccount(String accountNumber, double initialBalance) {
266
- this.accountNumber = accountNumber;
267
- this.balance = initialBalance;
268
- this.transactions = new ArrayList<>();
269
- }
270
-
271
- public void deposit(double amount) {
272
- if (amount > 0) {
273
- balance += amount;
274
- transactions.add(new Transaction("DEPOSIT", amount));
275
- }
276
- }
277
-
278
- public boolean withdraw(double amount) {
279
- if (amount > 0 && balance >= amount) {
280
- balance -= amount;
281
- transactions.add(new Transaction("WITHDRAWAL", amount));
282
- return true;
283
- }
284
- return false;
285
- }
286
- }
287
- ```
package/lib/validation.js DELETED
@@ -1,77 +0,0 @@
1
- /**
2
- * Input validation and security utilities
3
- */
4
-
5
- const path = require('path');
6
-
7
- /**
8
- * Validates that a path is within the allowed working directory
9
- * Prevents path traversal attacks
10
- */
11
- function validatePath(requestPath, workingDir) {
12
- const fullPath = path.resolve(path.join(workingDir, requestPath || ''));
13
- return fullPath.startsWith(workingDir);
14
- }
15
-
16
- /**
17
- * Sanitizes file paths to prevent injection
18
- */
19
- function sanitizePath(filePath) {
20
- if (!filePath) {
21
- return '';
22
- }
23
- return filePath.replace(/\.\./g, '').replace(/[<>:"|?*]/g, '');
24
- }
25
-
26
- /**
27
- * Validates commit message
28
- */
29
- function validateCommitMessage(message) {
30
- if (!message || typeof message !== 'string') {
31
- return false;
32
- }
33
- return message.trim().length > 0 && message.trim().length <= 5000;
34
- }
35
-
36
- /**
37
- * Validates filename
38
- */
39
- function validateFilename(filename) {
40
- if (!filename || typeof filename !== 'string') {
41
- return false;
42
- }
43
-
44
- const sanitized = filename.trim();
45
-
46
- if (sanitized.length === 0 || sanitized.length > 255) {
47
- return false;
48
- }
49
-
50
- const invalidChars = /[<>:"|?*\x00-\x1F]/;
51
- if (invalidChars.test(sanitized)) {
52
- return false;
53
- }
54
-
55
- return true;
56
- }
57
-
58
- /**
59
- * Validates an array of file paths
60
- */
61
- function validateFilePaths(files) {
62
- if (!Array.isArray(files) || files.length === 0) {
63
- return false;
64
- }
65
-
66
- return files.every(file => {
67
- return typeof file === 'string' && file.trim().length > 0;
68
- });
69
- }
70
-
71
- module.exports = {
72
- validatePath,
73
- sanitizePath,
74
- validateCommitMessage,
75
- validateFilename,
76
- validateFilePaths
77
- };