gh-here 3.0.3 → 3.2.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 (47) hide show
  1. package/.env +0 -0
  2. package/lib/constants.js +21 -16
  3. package/lib/content-search.js +212 -0
  4. package/lib/error-handler.js +39 -28
  5. package/lib/file-utils.js +438 -287
  6. package/lib/git.js +11 -55
  7. package/lib/gitignore.js +70 -41
  8. package/lib/renderers.js +17 -33
  9. package/lib/server.js +73 -196
  10. package/lib/symbol-parser.js +600 -0
  11. package/package.json +1 -1
  12. package/public/app.js +135 -68
  13. package/public/css/components/buttons.css +423 -0
  14. package/public/css/components/forms.css +171 -0
  15. package/public/css/components/modals.css +286 -0
  16. package/public/css/components/notifications.css +36 -0
  17. package/public/css/file-table.css +318 -0
  18. package/public/css/file-tree.css +269 -0
  19. package/public/css/file-viewer.css +1259 -0
  20. package/public/css/layout.css +372 -0
  21. package/public/css/main.css +35 -0
  22. package/public/css/reset.css +64 -0
  23. package/public/css/search.css +694 -0
  24. package/public/css/symbol-outline.css +279 -0
  25. package/public/css/variables.css +135 -0
  26. package/public/js/constants.js +50 -34
  27. package/public/js/content-search-handler.js +551 -0
  28. package/public/js/file-viewer.js +437 -0
  29. package/public/js/focus-mode.js +280 -0
  30. package/public/js/inline-search.js +659 -0
  31. package/public/js/modal-manager.js +14 -28
  32. package/public/js/symbol-outline.js +454 -0
  33. package/public/js/utils.js +152 -94
  34. package/.claude/settings.local.json +0 -30
  35. package/SAMPLE.md +0 -287
  36. package/lib/validation.js +0 -77
  37. package/public/app.js.backup +0 -1902
  38. package/public/highlight.css +0 -121
  39. package/public/js/draft-manager.js +0 -36
  40. package/public/js/editor-manager.js +0 -159
  41. package/public/styles.css +0 -2727
  42. package/test.js +0 -138
  43. package/tests/draftManager.test.js +0 -241
  44. package/tests/fileTypeDetection.test.js +0 -111
  45. package/tests/httpService.test.js +0 -268
  46. package/tests/languageDetection.test.js +0 -145
  47. package/tests/pathUtils.test.js +0 -136
@@ -1,121 +0,0 @@
1
- /* GitHub Theme for highlight.js - Dark/Light adaptive */
2
-
3
- .hljs {
4
- display: block;
5
- overflow-x: auto;
6
- padding: 0;
7
- background: var(--bg-primary);
8
- color: var(--text-primary);
9
- }
10
-
11
- /* Dark theme colors (default) */
12
- :root {
13
- --hljs-comment: #8b949e;
14
- --hljs-keyword: #ff7b72;
15
- --hljs-string: #a5d6ff;
16
- --hljs-number: #79c0ff;
17
- --hljs-builtin: #ffa657;
18
- --hljs-function: #d2a8ff;
19
- --hljs-tag: #7ee787;
20
- }
21
-
22
- /* Light theme colors */
23
- [data-theme="light"] {
24
- --hljs-comment: #6f42c1;
25
- --hljs-keyword: #d73a49;
26
- --hljs-string: #032f62;
27
- --hljs-number: #005cc5;
28
- --hljs-builtin: #e36209;
29
- --hljs-function: #6f42c1;
30
- --hljs-tag: #22863a;
31
- }
32
-
33
- .hljs-comment,
34
- .hljs-quote {
35
- color: var(--hljs-comment);
36
- font-style: italic;
37
- }
38
-
39
- .hljs-doctag,
40
- .hljs-keyword,
41
- .hljs-formula {
42
- color: var(--hljs-keyword);
43
- }
44
-
45
- .hljs-section,
46
- .hljs-name,
47
- .hljs-selector-tag,
48
- .hljs-deletion,
49
- .hljs-subst {
50
- color: var(--hljs-keyword);
51
- }
52
-
53
- .hljs-literal {
54
- color: var(--hljs-number);
55
- }
56
-
57
- .hljs-string,
58
- .hljs-regexp,
59
- .hljs-addition,
60
- .hljs-attribute,
61
- .hljs-meta-string {
62
- color: var(--hljs-string);
63
- }
64
-
65
- .hljs-built_in,
66
- .hljs-class .hljs-title {
67
- color: var(--hljs-builtin);
68
- }
69
-
70
- .hljs-attr,
71
- .hljs-variable,
72
- .hljs-template-variable,
73
- .hljs-type,
74
- .hljs-selector-class,
75
- .hljs-selector-attr,
76
- .hljs-selector-pseudo,
77
- .hljs-number {
78
- color: var(--hljs-number);
79
- }
80
-
81
- .hljs-symbol,
82
- .hljs-bullet,
83
- .hljs-link,
84
- .hljs-meta,
85
- .hljs-selector-id,
86
- .hljs-title {
87
- color: var(--hljs-number);
88
- }
89
-
90
- .hljs-emphasis {
91
- font-style: italic;
92
- }
93
-
94
- .hljs-strong {
95
- font-weight: bold;
96
- }
97
-
98
- .hljs-link {
99
- text-decoration: underline;
100
- }
101
-
102
- .hljs-function,
103
- .hljs-params {
104
- color: var(--hljs-function);
105
- }
106
-
107
- .hljs-property {
108
- color: var(--hljs-number);
109
- }
110
-
111
- .hljs-tag {
112
- color: var(--hljs-tag);
113
- }
114
-
115
- .hljs-title.class_ {
116
- color: var(--hljs-builtin);
117
- }
118
-
119
- .hljs-title.function_ {
120
- color: var(--hljs-function);
121
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Draft management for file editing
3
- */
4
-
5
- import { STORAGE_KEYS } from './constants.js';
6
-
7
- export const DraftManager = {
8
- saveDraft(filePath, content) {
9
- localStorage.setItem(`${STORAGE_KEYS.DRAFT_PREFIX}${filePath}`, content);
10
- },
11
-
12
- loadDraft(filePath) {
13
- return localStorage.getItem(`${STORAGE_KEYS.DRAFT_PREFIX}${filePath}`);
14
- },
15
-
16
- clearDraft(filePath) {
17
- localStorage.removeItem(`${STORAGE_KEYS.DRAFT_PREFIX}${filePath}`);
18
- },
19
-
20
- hasDraftChanges(filePath, originalContent) {
21
- const draft = this.loadDraft(filePath);
22
- return draft !== null && draft !== originalContent;
23
- },
24
-
25
- getAllDrafts() {
26
- const drafts = {};
27
- for (let i = 0; i < localStorage.length; i++) {
28
- const key = localStorage.key(i);
29
- if (key.startsWith(STORAGE_KEYS.DRAFT_PREFIX)) {
30
- const filePath = key.replace(STORAGE_KEYS.DRAFT_PREFIX, '');
31
- drafts[filePath] = localStorage.getItem(key);
32
- }
33
- }
34
- return drafts;
35
- }
36
- };
@@ -1,159 +0,0 @@
1
- /**
2
- * Monaco Editor management
3
- */
4
-
5
- import { CONFIG, EDITOR_OPTIONS } from './constants.js';
6
- import { getLanguageFromExtension } from './utils.js';
7
- import { DraftManager } from './draft-manager.js';
8
- import { showDraftDialog } from './modal-manager.js';
9
- import { showNotification } from './notification.js';
10
-
11
- export class EditorManager {
12
- constructor(theme) {
13
- this.fileEditor = null;
14
- this.newFileEditor = null;
15
- this.theme = theme;
16
- this.ready = false;
17
- this.init();
18
- }
19
-
20
- init() {
21
- if (typeof require === 'undefined') {
22
- return;
23
- }
24
-
25
- require.config({ paths: { vs: CONFIG.MONACO_CDN } });
26
-
27
- require(['vs/editor/editor.main'], () => {
28
- self.MonacoEnvironment = {
29
- getWorker: () => undefined
30
- };
31
-
32
- const monacoTheme = this.theme === 'dark' ? 'vs-dark' : 'vs';
33
- monaco.editor.setTheme(monacoTheme);
34
-
35
- this.initializeNewFileEditor();
36
- this.ready = true;
37
- window.monacoReady = true;
38
- });
39
- }
40
-
41
- initializeNewFileEditor() {
42
- const container = document.getElementById('new-file-content');
43
- if (!container) {
44
- return;
45
- }
46
-
47
- const monacoTheme = this.theme === 'dark' ? 'vs-dark' : 'vs';
48
- this.newFileEditor = monaco.editor.create(container, {
49
- ...EDITOR_OPTIONS,
50
- value: '',
51
- language: 'plaintext',
52
- theme: monacoTheme
53
- });
54
- }
55
-
56
- async createFileEditor(container, filePath, originalContent) {
57
- if (!this.ready) {
58
- await this.waitForReady();
59
- }
60
-
61
- const filename = filePath.split('/').pop() || 'file.txt';
62
- const language = getLanguageFromExtension(filename);
63
- const availableLanguages = monaco.languages.getLanguages().map(lang => lang.id);
64
- const validLanguage = availableLanguages.includes(language) ? language : 'plaintext';
65
- const monacoTheme = this.theme === 'dark' ? 'vs-dark' : 'vs';
66
-
67
- let contentToLoad = originalContent;
68
-
69
- if (DraftManager.hasDraftChanges(filePath, originalContent)) {
70
- const draftChoice = await showDraftDialog(filePath);
71
- if (draftChoice === 'load') {
72
- contentToLoad = DraftManager.loadDraft(filePath);
73
- } else if (draftChoice === 'discard') {
74
- DraftManager.clearDraft(filePath);
75
- }
76
- } else {
77
- const draft = DraftManager.loadDraft(filePath);
78
- if (draft && draft === originalContent) {
79
- DraftManager.clearDraft(filePath);
80
- }
81
- }
82
-
83
- if (!this.fileEditor) {
84
- this.fileEditor = monaco.editor.create(container, {
85
- ...EDITOR_OPTIONS,
86
- value: contentToLoad,
87
- language: validLanguage,
88
- theme: monacoTheme
89
- });
90
-
91
- this.fileEditor.onDidChangeModelContent(() => {
92
- DraftManager.saveDraft(filePath, this.fileEditor.getValue());
93
- });
94
- } else {
95
- this.fileEditor.setValue(contentToLoad);
96
- const model = this.fileEditor.getModel();
97
- if (model) {
98
- monaco.editor.setModelLanguage(model, validLanguage);
99
- }
100
- }
101
-
102
- setTimeout(() => this.fileEditor.layout(), 50);
103
-
104
- return this.fileEditor;
105
- }
106
-
107
- waitForReady() {
108
- return new Promise(resolve => {
109
- const check = () => {
110
- if (this.ready) {
111
- resolve();
112
- } else {
113
- setTimeout(check, 100);
114
- }
115
- };
116
- check();
117
- });
118
- }
119
-
120
- updateLanguage(filename) {
121
- if (this.newFileEditor) {
122
- const language = getLanguageFromExtension(filename);
123
- const model = this.newFileEditor.getModel();
124
- if (model) {
125
- monaco.editor.setModelLanguage(model, language);
126
- }
127
- }
128
- }
129
-
130
- toggleWordWrap(editor) {
131
- if (!editor) {
132
- return false;
133
- }
134
-
135
- const currentWrap = editor.getOption(monaco.editor.EditorOption.wordWrap);
136
- const newWrap = currentWrap === 'off' ? 'on' : 'off';
137
- editor.updateOptions({ wordWrap: newWrap });
138
- return newWrap === 'on';
139
- }
140
-
141
- getValue(editorType = 'file') {
142
- const editor = editorType === 'file' ? this.fileEditor : this.newFileEditor;
143
- return editor ? editor.getValue() : '';
144
- }
145
-
146
- focus(editorType = 'file') {
147
- const editor = editorType === 'file' ? this.fileEditor : this.newFileEditor;
148
- if (editor) {
149
- editor.focus();
150
- }
151
- }
152
-
153
- layout(editorType = 'file') {
154
- const editor = editorType === 'file' ? this.fileEditor : this.newFileEditor;
155
- if (editor) {
156
- editor.layout();
157
- }
158
- }
159
- }