collabmd 0.1.47 → 0.1.48
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.
- package/README.md +9 -6
- package/dist/client/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -0
- package/dist/client/assets/babel-CY5KOv-I.js +16 -0
- package/dist/client/assets/comment-ui-shared-DuoyznXW.js +7 -0
- package/dist/client/assets/dist-ChRoo3IB.js +9 -0
- package/dist/client/assets/document-formatter-Dxl_a8XO.js +2 -0
- package/dist/client/assets/{drawio-editor-BjrxTe3l.js → drawio-editor-BVaNNtYp.js} +2 -2
- package/dist/client/assets/{drawioEditor-DUVZjSSr.js → drawioEditor-BkIBlXx0.js} +2 -2
- package/dist/client/assets/editor-session-DMyVdHLj.js +54 -0
- package/dist/client/assets/embedded-editor-base-B3l6Xy65.css +1 -0
- package/dist/client/assets/estree-CuT_pB8K.js +44 -0
- package/dist/client/assets/{excalidraw-editor-BlcN6umJ.css → excalidraw-editor-BbSbI80a.css} +1 -1
- package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +9 -0
- package/dist/client/assets/{excalidrawEditor-B0jOK3lv.js → excalidrawEditor-ChqF_d82.js} +2 -2
- package/dist/client/assets/export-page-Dyu0XCbu.js +57 -0
- package/dist/client/assets/exportDocument-CJBx4Xjx.css +1 -0
- package/dist/client/assets/{exportDocument-Dg9MjkIk.js → exportDocument-Dgvfa2Sd.js} +2 -2
- package/dist/client/assets/{file-icon-svg-CQAjlWjK.js → file-icon-svg-Y_kpF957.js} +1 -1
- package/dist/client/assets/file-kind-BwMIcZbi.js +1 -0
- package/dist/client/assets/file-search-DDLyyLDU.js +1 -0
- package/dist/client/assets/html-Cdnr2qzU.js +25 -0
- package/dist/client/assets/index-CSNIMyOP.css +1 -0
- package/dist/client/assets/index-DG3N2Ps-.js +2 -0
- package/dist/client/assets/main-D0wCxpVn.js +903 -0
- package/dist/client/assets/markdown-CByV-4CU.js +70 -0
- package/dist/client/assets/mermaid.core-BJRLUQZE.js +11 -0
- package/dist/client/assets/{preview-render-compiler-BApvlLLo.js → preview-render-compiler-CrJIooVD.js} +2 -2
- package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +1 -0
- package/dist/client/assets/{preview-render-profile-CE-5rVTC.js → preview-render-profile-B4RWYWHt.js} +1 -1
- package/dist/client/assets/{preview-render-worker-BmN79bVc.js → preview-render-worker-_QTxqKvP.js} +22 -22
- package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +1 -0
- package/dist/client/assets/standalone-6z5x8CWe.js +29 -0
- package/dist/client/assets/{vault-api-client-_LpV1aIn.js → vault-api-client-BkwdFjx0.js} +2 -2
- package/dist/client/assets/{es-CAsWR6hG.js → vault-utils-DvoSftJT.js} +1 -1
- package/dist/client/assets/yaml-9ltHPDNO.js +154 -0
- package/dist/client/drawio-editor.html +1 -1
- package/dist/client/excalidraw-editor.html +1 -1
- package/dist/client/export-document.html +2 -2
- package/dist/client/index.html +41 -19
- package/package.json +4 -1
- package/src/client/app/index.html +39 -17
- package/src/client/application/app-shell/export-feature.js +17 -1
- package/src/client/application/app-shell/git-feature.js +28 -9
- package/src/client/application/app-shell/ui-feature-identity.js +13 -0
- package/src/client/application/app-shell/ui-feature-shell.js +164 -9
- package/src/client/application/app-shell-elements.js +4 -0
- package/src/client/application/workspace-coordinator.js +21 -4
- package/src/client/application/workspace-preview-controller.js +120 -2
- package/src/client/application/workspace-route-controller.js +4 -1
- package/src/client/assets/vendor/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
- package/src/client/assets/vendor/jetbrains-mono/OFL.txt +93 -0
- package/src/client/bootstrap/collabmd-app-shell.js +21 -5
- package/src/client/domain/document-formatter.js +193 -0
- package/src/client/domain/file-search.js +73 -0
- package/src/client/domain/git-labels.js +5 -0
- package/src/client/domain/vault-paths.js +6 -4
- package/src/client/domain/wiki-link-completions.js +20 -20
- package/src/client/drawio-editor.js +8 -3
- package/src/client/excalidraw-editor.js +152 -6
- package/src/client/export/export-host.js +56 -35
- package/src/client/export/export-page.js +14 -4
- package/src/client/export/export-pipeline.js +266 -25
- package/src/client/infrastructure/editor-session.js +4 -0
- package/src/client/infrastructure/editor-view-adapter.js +60 -14
- package/src/client/presentation/bases-preview-controller.js +35 -11
- package/src/client/presentation/file-action-controller.js +15 -2
- package/src/client/presentation/file-explorer-controller.js +3 -0
- package/src/client/presentation/file-explorer-view.js +2 -1
- package/src/client/presentation/file-history-view-controller.js +6 -1
- package/src/client/presentation/file-tree-state.js +1 -11
- package/src/client/presentation/git-diff-view-controller.js +36 -11
- package/src/client/presentation/git-panel-controller.js +10 -6
- package/src/client/presentation/quick-switcher-controller.js +54 -154
- package/src/client/styles/components/scrollbars.css +10 -0
- package/src/client/styles/export-document.css +44 -29
- package/src/client/styles/features/collaboration-presence.css +13 -1
- package/src/client/styles/features/preview-markdown.css +54 -0
- package/src/client/styles/foundation/tokens.css +8 -0
- package/src/client/styles/layout/shell.css +76 -24
- package/src/client/styles/layout/view-modes.css +2 -0
- package/src/client/styles/overrides/codemirror.css +31 -19
- package/src/client/styles/surfaces/excalidraw-editor.css +42 -0
- package/src/domain/file-kind.js +12 -1
- package/src/server/domain/ripgrep-search-service.js +110 -37
- package/src/server/infrastructure/persistence/path-utils.js +10 -4
- package/src/server/infrastructure/persistence/vault-file-store.js +2 -0
- package/dist/client/assets/comment-ui-shared-DWkk9Vh3.js +0 -7
- package/dist/client/assets/editor-session-DfZuRgB_.js +0 -54
- package/dist/client/assets/embedded-editor-base-DvMynhKu.css +0 -1
- package/dist/client/assets/excalidraw-editor-D7pnUCLH.js +0 -9
- package/dist/client/assets/export-page-Bs3xE1fg.js +0 -57
- package/dist/client/assets/exportDocument-PnYU3v1s.css +0 -1
- package/dist/client/assets/file-kind-BbqgGzpc.js +0 -1
- package/dist/client/assets/index-BIpgxyGZ.css +0 -1
- package/dist/client/assets/index-Z5sI0Bj-.js +0 -2
- package/dist/client/assets/main-Dwnj9Gaq.js +0 -903
- package/dist/client/assets/mermaid.core-CLZBlpIW.js +0 -11
- package/dist/client/assets/preview-render-compiler-BQ_3h9vD.js +0 -1
- package/dist/client/assets/quick-switcher-controller-ButWPmCI.js +0 -12
- package/dist/client/assets/vault-utils-wdQ0RNR9.js +0 -1
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
.editor-layout[data-view="preview"] .preview-content.is-base-file-preview,
|
|
31
31
|
.editor-layout[data-view="preview"] .preview-content.is-image-file-preview,
|
|
32
32
|
.editor-layout[data-view="preview"] .preview-content.is-pdf-file-preview,
|
|
33
|
+
.editor-layout[data-view="preview"] .preview-content.is-html-file-preview,
|
|
33
34
|
.editor-layout[data-view="preview"] .preview-content.is-mermaid-file-preview,
|
|
34
35
|
.editor-layout[data-view="preview"] .preview-content.is-plantuml-file-preview {
|
|
35
36
|
max-width: none;
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
.editor-layout[data-view="preview"] .preview-content p:has(> .excalidraw-embed-placeholder:only-child),
|
|
44
|
+
.editor-layout[data-view="preview"] .preview-content p:has(> .drawio-embed-placeholder:only-child),
|
|
43
45
|
.editor-layout[data-view="preview"] .preview-content p:has(> .bases-embed-placeholder:only-child),
|
|
44
46
|
.editor-layout[data-view="preview"] .preview-content p:has(> .video-embed-placeholder:only-child),
|
|
45
47
|
.editor-layout[data-view="preview"] .preview-content p:has(> .mermaid-shell:only-child),
|
|
@@ -1,55 +1,67 @@
|
|
|
1
1
|
/* ===== OVERRIDES / CODEMIRROR ===== */
|
|
2
2
|
|
|
3
|
+
.editor-container .cm-content {
|
|
4
|
+
font-variant-ligatures: none;
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
.cm-tooltip-autocomplete {
|
|
8
|
+
width: min(420px, calc(100vw - 24px));
|
|
9
|
+
max-width: calc(100vw - 24px);
|
|
4
10
|
overflow: hidden;
|
|
5
|
-
border: 1px solid var(--color-
|
|
6
|
-
border-radius: var(--radius-
|
|
7
|
-
background: var(--color-surface) !important;
|
|
8
|
-
box-shadow: var(--shadow-
|
|
11
|
+
border: 1px solid var(--color-border) !important;
|
|
12
|
+
border-radius: var(--radius-lg) !important;
|
|
13
|
+
background: oklch(from var(--color-surface) l c h / 0.98) !important;
|
|
14
|
+
box-shadow: var(--shadow-lg) !important;
|
|
15
|
+
backdrop-filter: blur(12px);
|
|
9
16
|
font-family: var(--font-body);
|
|
10
|
-
font-size: var(--text-sm);
|
|
17
|
+
font-size: var(--text-ui-sm);
|
|
11
18
|
}
|
|
12
19
|
|
|
13
20
|
.cm-tooltip-autocomplete > ul {
|
|
14
21
|
max-height: 240px !important;
|
|
15
|
-
padding: var(--space-1)
|
|
22
|
+
padding: var(--space-1);
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
.cm-tooltip-autocomplete > ul > li {
|
|
19
26
|
display: flex;
|
|
20
27
|
align-items: center;
|
|
21
28
|
gap: var(--space-2);
|
|
29
|
+
min-height: 36px;
|
|
22
30
|
padding: var(--space-2) var(--space-3) !important;
|
|
31
|
+
border-radius: var(--radius-md);
|
|
23
32
|
line-height: 1.4;
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
.cm-tooltip-autocomplete > ul > li[aria-selected] {
|
|
27
|
-
background: var(--color-
|
|
28
|
-
color: var(--color-text
|
|
36
|
+
background: var(--color-surface-offset) !important;
|
|
37
|
+
color: var(--color-text) !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.cm-tooltip-autocomplete .cm-completionIcon {
|
|
41
|
+
display: none;
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
.cm-tooltip-autocomplete .cm-completionLabel {
|
|
32
45
|
flex: 1;
|
|
33
46
|
overflow: hidden;
|
|
47
|
+
font-family: var(--font-body) !important;
|
|
48
|
+
font-weight: 600;
|
|
34
49
|
text-overflow: ellipsis;
|
|
35
50
|
white-space: nowrap;
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
.cm-tooltip-autocomplete .cm-completionDetail {
|
|
54
|
+
max-width: 45%;
|
|
39
55
|
margin-left: auto;
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
color: var(--color-text-faint);
|
|
58
|
+
direction: rtl;
|
|
59
|
+
text-align: left;
|
|
60
|
+
text-overflow: ellipsis;
|
|
42
61
|
white-space: nowrap;
|
|
62
|
+
font-family: var(--font-body) !important;
|
|
43
63
|
font-size: var(--text-xs);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.cm-tooltip-autocomplete > ul > li[aria-selected] .cm-completionDetail {
|
|
47
|
-
opacity: 0.85;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.cm-completionIcon-text::after {
|
|
51
|
-
content: '📄';
|
|
52
|
-
font-size: var(--text-ui-sm);
|
|
64
|
+
font-style: normal;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
.cm-panels-top {
|
|
@@ -38,6 +38,7 @@ body[data-surface='excalidraw-editor'][data-document-mode='preview'] .disable-vi
|
|
|
38
38
|
pointer-events: none;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
.excalidraw-editor-toolbar,
|
|
41
42
|
.diagram-comments-toolbar {
|
|
42
43
|
display: inline-flex;
|
|
43
44
|
align-items: center;
|
|
@@ -45,6 +46,47 @@ body[data-surface='excalidraw-editor'][data-document-mode='preview'] .disable-vi
|
|
|
45
46
|
pointer-events: auto;
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
.excalidraw-presentation-toggle {
|
|
50
|
+
width: var(--control-h-md);
|
|
51
|
+
min-width: var(--control-h-md);
|
|
52
|
+
height: var(--control-h-md);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.excalidraw-presentation-navigation {
|
|
56
|
+
position: absolute;
|
|
57
|
+
z-index: 30;
|
|
58
|
+
bottom: var(--space-4);
|
|
59
|
+
left: 50%;
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
gap: var(--space-2);
|
|
63
|
+
padding: var(--space-2);
|
|
64
|
+
border: 1px solid var(--color-border);
|
|
65
|
+
border-radius: var(--radius-lg);
|
|
66
|
+
background: var(--color-surface-raised);
|
|
67
|
+
box-shadow: var(--shadow-md);
|
|
68
|
+
color: var(--color-text);
|
|
69
|
+
transform: translateX(-50%);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.excalidraw-presentation-navigation .diagram-comment-button {
|
|
73
|
+
width: var(--control-h-sm);
|
|
74
|
+
min-width: var(--control-h-sm);
|
|
75
|
+
height: var(--control-h-sm);
|
|
76
|
+
padding: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.excalidraw-presentation-status {
|
|
80
|
+
min-width: 7rem;
|
|
81
|
+
max-width: min(20rem, 55vw);
|
|
82
|
+
color: var(--color-text-muted);
|
|
83
|
+
font-size: var(--text-ui-sm);
|
|
84
|
+
text-align: center;
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
text-overflow: ellipsis;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
}
|
|
89
|
+
|
|
48
90
|
.diagram-comment-button,
|
|
49
91
|
.diagram-comment-close,
|
|
50
92
|
.diagram-comment-back,
|
package/src/domain/file-kind.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const MARKDOWN_FILE_EXTENSIONS = Object.freeze(['.md', '.markdown', '.mdx']);
|
|
2
|
+
const HTML_FILE_EXTENSIONS = Object.freeze(['.html', '.htm']);
|
|
2
3
|
const BASE_FILE_EXTENSION = '.base';
|
|
3
4
|
const EXCALIDRAW_FILE_EXTENSION = '.excalidraw';
|
|
4
5
|
const DRAWIO_FILE_EXTENSION = '.drawio';
|
|
@@ -17,12 +18,13 @@ const DIAGRAM_FILE_EXTENSIONS = Object.freeze([
|
|
|
17
18
|
]);
|
|
18
19
|
const VAULT_FILE_EXTENSIONS = Object.freeze([
|
|
19
20
|
...MARKDOWN_FILE_EXTENSIONS,
|
|
21
|
+
...HTML_FILE_EXTENSIONS,
|
|
20
22
|
BASE_FILE_EXTENSION,
|
|
21
23
|
...DIAGRAM_FILE_EXTENSIONS,
|
|
22
24
|
PDF_FILE_EXTENSION,
|
|
23
25
|
...IMAGE_ATTACHMENT_EXTENSIONS,
|
|
24
26
|
]);
|
|
25
|
-
const STRIP_VAULT_EXTENSION_PATTERN = /\.(?:md|markdown|mdx|base|excalidraw|drawio|mmd|mermaid|puml|plantuml|dsl|pdf|png|jpe?g|webp|gif|svg)$/i;
|
|
27
|
+
const STRIP_VAULT_EXTENSION_PATTERN = /\.(?:md|markdown|mdx|html?|base|excalidraw|drawio|mmd|mermaid|puml|plantuml|dsl|pdf|png|jpe?g|webp|gif|svg)$/i;
|
|
26
28
|
|
|
27
29
|
function normalizeFilePath(filePath) {
|
|
28
30
|
return String(filePath ?? '').trim().toLowerCase();
|
|
@@ -38,6 +40,7 @@ export {
|
|
|
38
40
|
DIAGRAM_FILE_EXTENSIONS,
|
|
39
41
|
DRAWIO_FILE_EXTENSION,
|
|
40
42
|
EXCALIDRAW_FILE_EXTENSION,
|
|
43
|
+
HTML_FILE_EXTENSIONS,
|
|
41
44
|
IMAGE_ATTACHMENT_EXTENSIONS,
|
|
42
45
|
MARKDOWN_FILE_EXTENSIONS,
|
|
43
46
|
MERMAID_FILE_EXTENSIONS,
|
|
@@ -53,6 +56,10 @@ export function getVaultFileKind(filePath) {
|
|
|
53
56
|
return 'markdown';
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
if (hasFileExtension(filePath, HTML_FILE_EXTENSIONS)) {
|
|
60
|
+
return 'html';
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
if (hasFileExtension(filePath, [BASE_FILE_EXTENSION])) {
|
|
57
64
|
return 'base';
|
|
58
65
|
}
|
|
@@ -114,6 +121,10 @@ export function isMarkdownFilePath(filePath) {
|
|
|
114
121
|
return getVaultFileKind(filePath) === 'markdown';
|
|
115
122
|
}
|
|
116
123
|
|
|
124
|
+
export function isHtmlFilePath(filePath) {
|
|
125
|
+
return getVaultFileKind(filePath) === 'html';
|
|
126
|
+
}
|
|
127
|
+
|
|
117
128
|
export function isExcalidrawFilePath(filePath) {
|
|
118
129
|
return getVaultFileKind(filePath) === 'excalidraw';
|
|
119
130
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { glob, readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
import { promisify } from 'node:util';
|
|
3
5
|
|
|
4
6
|
import { getVaultFileKind } from '../../domain/file-kind.js';
|
|
@@ -17,6 +19,8 @@ const TEXT_SEARCH_GLOBS = Object.freeze([
|
|
|
17
19
|
'*.md',
|
|
18
20
|
'*.markdown',
|
|
19
21
|
'*.mdx',
|
|
22
|
+
'*.html',
|
|
23
|
+
'*.htm',
|
|
20
24
|
'*.base',
|
|
21
25
|
'*.mmd',
|
|
22
26
|
'*.mermaid',
|
|
@@ -24,9 +28,15 @@ const TEXT_SEARCH_GLOBS = Object.freeze([
|
|
|
24
28
|
'*.plantuml',
|
|
25
29
|
'*.dsl',
|
|
26
30
|
'*.drawio',
|
|
27
|
-
'*.excalidraw',
|
|
28
31
|
]);
|
|
29
32
|
|
|
33
|
+
function parseByteLimit(value) {
|
|
34
|
+
const match = String(value ?? '').trim().match(/^(\d+)([KMG])?$/iu);
|
|
35
|
+
if (!match) return 1024 * 1024;
|
|
36
|
+
const multipliers = { K: 1024, M: 1024 ** 2, G: 1024 ** 3 };
|
|
37
|
+
return Number(match[1]) * (multipliers[match[2]?.toUpperCase()] ?? 1);
|
|
38
|
+
}
|
|
39
|
+
|
|
30
40
|
function normalizePositiveInt(value, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
|
|
31
41
|
const parsed = Number.parseInt(value ?? '', 10);
|
|
32
42
|
if (!Number.isInteger(parsed) || parsed < min) {
|
|
@@ -216,6 +226,72 @@ export function parseRipgrepJson(stdout, {
|
|
|
216
226
|
};
|
|
217
227
|
}
|
|
218
228
|
|
|
229
|
+
async function searchExcalidrawText({ maxFileSize, maxFiles, maxSnippetsPerFile, query, signal, vaultDir }) {
|
|
230
|
+
const files = [];
|
|
231
|
+
let matchCount = 0;
|
|
232
|
+
let truncated = false;
|
|
233
|
+
const normalizedQuery = query.toLocaleLowerCase();
|
|
234
|
+
const paths = glob('**/*.excalidraw', {
|
|
235
|
+
cwd: vaultDir,
|
|
236
|
+
exclude: ['**/.*', '**/node_modules/**'],
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
for await (const filePath of paths) {
|
|
240
|
+
signal?.throwIfAborted?.();
|
|
241
|
+
const absolutePath = join(vaultDir, filePath);
|
|
242
|
+
if ((await stat(absolutePath)).size > parseByteLimit(maxFileSize)) continue;
|
|
243
|
+
|
|
244
|
+
let scene;
|
|
245
|
+
try {
|
|
246
|
+
scene = JSON.parse(await readFile(absolutePath, 'utf8'));
|
|
247
|
+
} catch {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const snippets = [];
|
|
252
|
+
let fileMatchCount = 0;
|
|
253
|
+
for (const element of Array.isArray(scene?.elements) ? scene.elements : []) {
|
|
254
|
+
if (element?.isDeleted || element?.type !== 'text' || typeof element.text !== 'string') continue;
|
|
255
|
+
const text = element.text;
|
|
256
|
+
const normalizedText = text.toLocaleLowerCase();
|
|
257
|
+
let matchStart = normalizedText.indexOf(normalizedQuery);
|
|
258
|
+
while (matchStart >= 0) {
|
|
259
|
+
fileMatchCount += 1;
|
|
260
|
+
matchCount += 1;
|
|
261
|
+
if (snippets.length < maxSnippetsPerFile) {
|
|
262
|
+
const snippet = createSnippet(text, matchStart, matchStart + query.length);
|
|
263
|
+
snippets.push({
|
|
264
|
+
column: matchStart + 1,
|
|
265
|
+
line: 1,
|
|
266
|
+
matchEnd: snippet.matchEnd,
|
|
267
|
+
matchStart: snippet.matchStart,
|
|
268
|
+
text: snippet.text,
|
|
269
|
+
});
|
|
270
|
+
} else {
|
|
271
|
+
truncated = true;
|
|
272
|
+
}
|
|
273
|
+
matchStart = normalizedText.indexOf(normalizedQuery, matchStart + Math.max(query.length, 1));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (fileMatchCount > 0) {
|
|
278
|
+
if (files.length >= maxFiles) {
|
|
279
|
+
truncated = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
files.push({
|
|
283
|
+
file: filePath.replaceAll('\\', '/'),
|
|
284
|
+
kind: 'excalidraw',
|
|
285
|
+
matchCount: fileMatchCount,
|
|
286
|
+
snippets,
|
|
287
|
+
truncated: fileMatchCount > snippets.length,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return { files, matchCount, truncated };
|
|
293
|
+
}
|
|
294
|
+
|
|
219
295
|
export class RipgrepSearchService {
|
|
220
296
|
constructor({
|
|
221
297
|
execFileImpl = execFile,
|
|
@@ -307,7 +383,7 @@ export class RipgrepSearchService {
|
|
|
307
383
|
maxFileSize: this.maxFileSize,
|
|
308
384
|
maxSnippetsPerFile: this.maxSnippetsPerFile,
|
|
309
385
|
});
|
|
310
|
-
|
|
386
|
+
let parsed;
|
|
311
387
|
try {
|
|
312
388
|
const result = await this.execFileImpl('rg', args, {
|
|
313
389
|
cwd: this.vaultDir,
|
|
@@ -316,56 +392,53 @@ export class RipgrepSearchService {
|
|
|
316
392
|
...(signal ? { signal } : {}),
|
|
317
393
|
timeout: this.timeoutMs,
|
|
318
394
|
});
|
|
319
|
-
|
|
395
|
+
parsed = parseRipgrepJson(result.stdout, {
|
|
320
396
|
maxFiles,
|
|
321
397
|
maxSnippetsPerFile: this.maxSnippetsPerFile,
|
|
322
398
|
query: normalizedQuery,
|
|
323
399
|
});
|
|
324
|
-
parsed.search = this.getClientConfig();
|
|
325
|
-
|
|
326
|
-
logPerfEvent(this.perfLoggingEnabled, 'search-query', {
|
|
327
|
-
durationMs: Date.now() - startedAt,
|
|
328
|
-
fileCount: parsed.files.length,
|
|
329
|
-
matchCount: parsed.matchCount,
|
|
330
|
-
truncated: parsed.truncated,
|
|
331
|
-
});
|
|
332
|
-
return parsed;
|
|
333
400
|
} catch (error) {
|
|
334
401
|
if (error?.code === 1) {
|
|
335
|
-
|
|
402
|
+
parsed = createEmptySearchResult({
|
|
336
403
|
query: normalizedQuery,
|
|
337
404
|
searchAvailable: this.available,
|
|
338
405
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
406
|
+
} else {
|
|
407
|
+
const isMaxBuffer = error?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER';
|
|
408
|
+
parsed = parseRipgrepJson(error?.stdout ?? '', {
|
|
409
|
+
maxFiles,
|
|
410
|
+
maxSnippetsPerFile: this.maxSnippetsPerFile,
|
|
411
|
+
query: normalizedQuery,
|
|
345
412
|
});
|
|
346
|
-
|
|
413
|
+
if (isMaxBuffer && parsed.files.length > 0) {
|
|
414
|
+
parsed.truncated = true;
|
|
415
|
+
} else {
|
|
416
|
+
error.statusCode = error?.signal === 'SIGTERM' ? 504 : 500;
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
347
419
|
}
|
|
420
|
+
}
|
|
348
421
|
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
|
|
422
|
+
if (parsed.files.length < maxFiles) {
|
|
423
|
+
const excalidraw = await searchExcalidrawText({
|
|
424
|
+
maxFileSize: this.maxFileSize,
|
|
425
|
+
maxFiles: maxFiles - parsed.files.length,
|
|
352
426
|
maxSnippetsPerFile: this.maxSnippetsPerFile,
|
|
353
427
|
query: normalizedQuery,
|
|
428
|
+
signal,
|
|
429
|
+
vaultDir: this.vaultDir,
|
|
354
430
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
logPerfEvent(this.perfLoggingEnabled, 'search-query', {
|
|
359
|
-
durationMs: Date.now() - startedAt,
|
|
360
|
-
fileCount: parsed.files.length,
|
|
361
|
-
matchCount: parsed.matchCount,
|
|
362
|
-
truncated: true,
|
|
363
|
-
});
|
|
364
|
-
return parsed;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
error.statusCode = error?.signal === 'SIGTERM' ? 504 : 500;
|
|
368
|
-
throw error;
|
|
431
|
+
parsed.files.push(...excalidraw.files);
|
|
432
|
+
parsed.matchCount += excalidraw.matchCount;
|
|
433
|
+
parsed.truncated ||= excalidraw.truncated;
|
|
369
434
|
}
|
|
435
|
+
parsed.search = this.getClientConfig();
|
|
436
|
+
logPerfEvent(this.perfLoggingEnabled, 'search-query', {
|
|
437
|
+
durationMs: Date.now() - startedAt,
|
|
438
|
+
fileCount: parsed.files.length,
|
|
439
|
+
matchCount: parsed.matchCount,
|
|
440
|
+
truncated: parsed.truncated,
|
|
441
|
+
});
|
|
442
|
+
return parsed;
|
|
370
443
|
}
|
|
371
444
|
}
|
|
@@ -3,7 +3,7 @@ import { isAbsolute, normalize, relative, resolve } from 'path';
|
|
|
3
3
|
import { isVaultFilePath } from '../../../domain/file-kind.js';
|
|
4
4
|
|
|
5
5
|
export const IGNORED_DIRECTORIES = new Set(['.git', '.obsidian', '.trash', 'node_modules', '.DS_Store']);
|
|
6
|
-
export const VAULT_FILE_PATH_REQUIREMENT = '.md, .markdown, .mdx, .base, .excalidraw, .drawio, .mmd, .mermaid, .puml, .plantuml, .dsl, .png, .jpg, .jpeg, .webp, .gif, or .svg';
|
|
6
|
+
export const VAULT_FILE_PATH_REQUIREMENT = '.md, .markdown, .mdx, .html, .htm, .base, .excalidraw, .drawio, .mmd, .mermaid, .puml, .plantuml, .dsl, .pdf, .png, .jpg, .jpeg, .webp, .gif, or .svg';
|
|
7
7
|
export const INVALID_VAULT_FILE_PATH_ERROR = `Invalid file path — must end in ${VAULT_FILE_PATH_REQUIREMENT}`;
|
|
8
8
|
export const INVALID_DIRECTORY_PATH_ERROR = 'Invalid directory path';
|
|
9
9
|
|
|
@@ -12,12 +12,18 @@ export function isIgnoredVaultEntry(name) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function normalizeRequestedPath(requestedPath) {
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const value = String(requestedPath ?? '').trim().replace(/\\/g, '/');
|
|
16
|
+
const segments = value.split('/');
|
|
17
|
+
if (
|
|
18
|
+
!value
|
|
19
|
+
|| isAbsolute(value)
|
|
20
|
+
|| segments.some((segment) => segment === '.' || segment === '..')
|
|
21
|
+
) {
|
|
17
22
|
return '';
|
|
18
23
|
}
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
const normalized = normalize(value);
|
|
26
|
+
return normalized === '.' ? '' : normalized;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
export function sanitizeVaultPath(vaultDir, requestedPath) {
|
|
@@ -28,6 +28,7 @@ const EDITABLE_VAULT_CONTENT_PATH_ERRORS = {
|
|
|
28
28
|
base: 'Invalid file path — must end in .base',
|
|
29
29
|
drawio: 'Invalid file path — must end in .drawio',
|
|
30
30
|
excalidraw: 'Invalid file path — must end in .excalidraw',
|
|
31
|
+
html: 'Invalid file path — must end in .html or .htm',
|
|
31
32
|
markdown: 'Invalid file path',
|
|
32
33
|
mermaid: 'Invalid file path — must end in .mmd or .mermaid',
|
|
33
34
|
plantuml: 'Invalid file path — must end in .puml or .plantuml',
|
|
@@ -66,6 +67,7 @@ const TEXT_FILE_MIME_TYPES = Object.freeze({
|
|
|
66
67
|
base: 'text/yaml; charset=utf-8',
|
|
67
68
|
drawio: 'application/xml; charset=utf-8',
|
|
68
69
|
excalidraw: 'application/json; charset=utf-8',
|
|
70
|
+
html: 'text/html; charset=utf-8',
|
|
69
71
|
markdown: 'text/markdown; charset=utf-8',
|
|
70
72
|
mermaid: 'text/plain; charset=utf-8',
|
|
71
73
|
pdf: 'application/pdf',
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./es-CAsWR6hG.js";import{n}from"./vault-utils-wdQ0RNR9.js";import{o as r,s as i}from"./comment-threads-9J6Em-_y.js";function a(e,t,n,r,i,a){return e?.(t,n,r,i,a)??a.renderToken(t,n,r)}function o(e=``){return`<p>${n(String(e??``)).replace(/\n/g,`<br>`)}</p>`}function s(){let r=e({breaks:!0,highlight(e,r){try{return r&&t.getLanguage(r)?t.highlight(e,{ignoreIllegals:!0,language:r}).value:t.highlightAuto(e).value}catch{return n(e)}},html:!1,linkify:!0,typographer:!0}),i=r.renderer.rules.link_open,o=r.renderer.rules.table_open,s=r.renderer.rules.table_close;return r.renderer.rules.link_open=(e,t,n,r,o)=>(e[t].attrSet(`target`,`_blank`),e[t].attrSet(`rel`,`noopener noreferrer`),a(i,e,t,n,r,o)),r.renderer.rules.table_open=(e,t,n,r,i)=>`<div class="comment-markdown-table">${a(o,e,t,n,r,i)}`,r.renderer.rules.table_close=(e,t,n,r,i)=>`${a(s,e,t,n,r,i)}</div>`,r}var c=s();function l(e=``){let t=String(e??``);try{return c.render(t)}catch{return o(t)}}var u=Object.freeze([`👍`,`❤️`,`🎉`,`👀`,`🚀`]),d=Object.freeze([`😂`,`🔥`,`✅`,`🙏`,`💡`,`🤔`,`👏`,`😄`,`🎯`,`🙌`]);function f(e=[]){return[...e].sort((e,t)=>(e.anchor?.startLine??0)-(t.anchor?.startLine??0)||e.createdAt-t.createdAt)}function p(e){return e?.anchorKind||e?.kind||`line`}function m(e){return p(e)===`text`&&Number.isFinite(e?.startIndex)&&Number.isFinite(e?.endIndex)&&e.endIndex>e.startIndex}function h(e,t){return e===t?!0:!e||!t?!1:p(e)===p(t)&&(e.startIndex??null)===(t.startIndex??null)&&(e.endIndex??null)===(t.endIndex??null)&&(e.startLine??null)===(t.startLine??null)&&(e.endLine??null)===(t.endLine??null)&&(e.anchorQuote??e.quote??``)===(t.anchorQuote??t.quote??``)}function g(e){if(p(e)===`diagram-element`)return`Diagram element`;let t=Number(e?.startLine||0),n=Number(e?.endLine||t);return!Number.isFinite(t)||t<=0?`No source anchor`:t===n?`Line ${t}`:`Lines ${t}-${n}`}function _(e={}){return[e.kind||e.anchorKind||`line`,e.startLine??0,e.endLine??0,e.quote||``].join(`::`)}function v(e){return e&&!e.querySelector(`[data-source-line]`)}function y(e){let t=Number.parseInt(e||``,10);return Number.isFinite(t)?t:null}function b(e=[]){return e.reduce((e,t)=>e?(t?.createdAt??0)>=(e?.createdAt??0)?t:e:t,null)}function x(e){return e?.threads?.reduce((e,t)=>{let n=b(t?.messages??[]);return n&&(n.createdAt??0)>=(e?.createdAt??0)?n:e},null)}function S(e,t=`comment-markdown`){let n=document.createElement(`div`);return n.className=t,n.innerHTML=l(e),n}function C({authorName:e=`Anonymous`,buttonClassName:t=`comment-overview-thread`,footerClassName:n=`comment-overview-thread-footer`,headerClassName:r=`comment-overview-thread-header`,lineClassName:i=`comment-overview-thread-line`,lineLabel:a=``,messageCount:o=0,previewBody:s=``,previewClassName:c=`comment-markdown comment-overview-thread-preview`,quote:l=`Source anchored comment`,quoteClassName:u=`comment-overview-thread-quote`,timestamp:d=``}={}){let f=document.createElement(`button`);f.type=`button`,f.className=t;let p=document.createElement(`div`);p.className=r;let m=document.createElement(`span`);m.className=i,m.textContent=a;let h=document.createElement(`span`);h.className=`comment-overview-thread-meta`,h.textContent=d,p.append(m,h);let g=document.createElement(`div`);g.className=`comment-overview-thread-body`;let _=S(s,c),v=document.createElement(`div`);v.className=`comment-overview-thread-section comment-overview-thread-reference`;let y=document.createElement(`span`);y.className=`comment-overview-thread-section-label`,y.textContent=`Reference`;let b=document.createElement(`span`);b.className=u,b.textContent=l,v.append(y,b),g.append(_,v);let x=document.createElement(`div`);x.className=n;let C=document.createElement(`span`);C.className=`comment-overview-thread-author`,C.textContent=e;let w=document.createElement(`span`);return w.className=`comment-overview-thread-message-count`,w.textContent=`${o} message${o===1?``:`s`}`,x.append(C,w),f.append(p,g,x),f}function w(e,t){return!!(t&&e?.users?.some(e=>e?.userId===t))}function T(e){return String(Array.isArray(e?.users)?e.users.length:0)}function E(e,t,n){return e?.threadId===t&&e?.messageId===n}function D(e){let t=e?.querySelector?.(`.comment-reaction-picker`),n=t?.closest?.(`.comment-reaction-picker-wrap`),r=e?.querySelector?.(`.comment-card-scroll`);return!(t instanceof HTMLElement)||!(n instanceof HTMLElement)||!(r instanceof HTMLElement)?null:{picker:t,scroll:r,wrap:n}}function O(e,t){let n=y(e?.getAttribute?.(`data-source-line`)),r=y(e?.getAttribute?.(`data-source-line-end`))??n;return!n||!r||!t?!1:t.startLine<=r&&t.endLine>=n}function k(e,t,n=``){if(!e||e.isCollapsed||e.rangeCount===0||!t?.contains(e.anchorNode)||!t.contains(e.focusNode))return null;let i=e.getRangeAt(0),a=String(e.toString()).trim(),o=r(a),s=i.commonAncestorContainer.nodeType===Node.ELEMENT_NODE?i.commonAncestorContainer:i.commonAncestorContainer.parentElement;if(!o||s?.closest?.(`.diagram-preview-shell`))return null;let c=Array.from(t.querySelectorAll(`[data-source-line]`)).filter(e=>v(e)&&i.intersectsNode(e));if(c.length===0)return null;let l=String(n).split(`
|
|
2
|
-
`),u=Math.min(Math.max(Math.min(...c.map(e=>y(e.getAttribute(`data-source-line`))??l.length)),1),l.length),d=Math.min(Math.max(...c.map(e=>y(e.getAttribute(`data-source-line-end`))??y(e.getAttribute(`data-source-line`))??1)),l.length),f=l.slice(0,u-1).reduce((e,t)=>e+t.length+1,0),p=l.slice(u-1,d).reduce((e,t,n)=>e+t.length+(n===0?0:1),f),m=`line`,h=f,g=p,_=!0;if(c.length===1){let e=String(n).slice(f,p),t=e.indexOf(a);t>=0&&t===e.lastIndexOf(a)&&(m=`text`,h=f+t,g=h+a.length,_=!1)}let b=e=>String(n).slice(0,e).split(`
|
|
3
|
-
`).length,x=_?u:b(h),S=_?d:b(Math.max(g-1,h)),C=N(Array.from(i.getClientRects()))||N(c.map(e=>e.getBoundingClientRect()));return{anchor:{anchorKind:m,anchorQuote:o,endIndex:g,endLine:S,fallbackToLines:_,kind:m,quote:o,startIndex:h,startLine:x},range:i.cloneRange(),rect:C}}function A(e){let t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),n=``,r=[],i=!0;for(;t.nextNode();){let e=t.currentNode,a=e.textContent||``;for(let t=0;t<a.length;t+=1){let o=a[t];if(/\s/.test(o)){if(i)continue;n+=` `,r.push({node:e,offset:t}),i=!0;continue}n+=o,r.push({node:e,offset:t}),i=!1}}for(;n.endsWith(` `);)n=n.slice(0,-1),r.pop();return{map:r,normalized:n}}function j(e,t){let n=i(t);if(!e||!n)return null;let r=A(e);if(!r.normalized)return null;let a=r.normalized.indexOf(n);if(a<0||r.normalized.indexOf(n,a+1)>=0)return null;let o=r.map[a],s=r.map[a+n.length-1];if(!o||!s)return null;let c=document.createRange();return c.setStart(o.node,o.offset),c.setEnd(s.node,s.offset+1),c}function M(e,t){return{bottom:e.bottom-t.top,height:e.height,left:e.left-t.left,right:e.right-t.left,top:e.top-t.top,width:e.width}}function N(e=[]){if(!Array.isArray(e)||e.length===0)return null;let t=Math.min(...e.map(e=>e.left)),n=Math.min(...e.map(e=>e.top)),r=Math.max(...e.map(e=>e.right)),i=Math.max(...e.map(e=>e.bottom));return{bottom:i,height:i-n,left:t,right:r,top:n,width:r-t}}function P(e,t,n){return n?e>=n.left&&e<=n.right&&t>=n.top&&t<=n.bottom:!1}function F(e=[]){return[...new Set(e.filter(Boolean))].sort()}function I(e=[]){return F(e).join(` `)}function L(e){let t=document.createDocumentFragment(),n=document.createElement(`span`);if(n.className=`comment-marker-icon`,n.setAttribute(`aria-hidden`,`true`),n.innerHTML=`
|
|
4
|
-
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
-
<path d="M3 4.75A1.75 1.75 0 0 1 4.75 3h6.5A1.75 1.75 0 0 1 13 4.75v4.5A1.75 1.75 0 0 1 11.25 11H8.9L6.5 13v-2H4.75A1.75 1.75 0 0 1 3 9.25v-4.5Z" stroke="currentColor" stroke-width="1.35" stroke-linejoin="round"/>
|
|
6
|
-
</svg>
|
|
7
|
-
`,t.appendChild(n),e>1){let n=document.createElement(`span`);n.className=`comment-marker-count`,n.textContent=String(e),t.appendChild(n)}return t}export{I as C,P as S,M as T,v as _,C as a,F as b,S as c,T as d,_ as f,w as g,D as h,L as i,j as l,b as m,u as n,k as o,x as p,h as r,N as s,d as t,g as u,E as v,f as w,O as x,m as y};
|