@adecore/editor-react 0.31.11 → 0.32.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 (137) hide show
  1. package/dist/AnchoredPopup.js +73 -19
  2. package/dist/AttributionCard.js +162 -4
  3. package/dist/BaselineStatus.js +62 -8
  4. package/dist/CallHierarchyPanel.js +977 -60
  5. package/dist/ChangeReview.js +76 -25
  6. package/dist/CodeAuthorsCard.js +314 -14
  7. package/dist/CompletionPopup.js +490 -83
  8. package/dist/DiffView.js +548 -181
  9. package/dist/EditorContextMenu.js +352 -34
  10. package/dist/EditorView.js +276 -99
  11. package/dist/FindReplace.js +525 -67
  12. package/dist/HoverCard.js +378 -38
  13. package/dist/HoverSections.js +367 -56
  14. package/dist/LanguagePopups.js +95 -34
  15. package/dist/Markdown.js +41 -6
  16. package/dist/PanelResizeHandle.js +199 -66
  17. package/dist/PathText.js +49 -7
  18. package/dist/PeekPanel.js +675 -72
  19. package/dist/PickPopup.js +304 -34
  20. package/dist/RenameCard.js +679 -85
  21. package/dist/RenderedDocs.js +329 -58
  22. package/dist/SignatureCard.js +91 -7
  23. package/dist/SplitDiffView.js +344 -254
  24. package/dist/SymbolPicker.js +440 -85
  25. package/dist/call-hierarchy-model.js +102 -68
  26. package/dist/call-hierarchy.js +458 -359
  27. package/dist/code-actions-model.js +88 -76
  28. package/dist/code-actions.js +372 -283
  29. package/dist/code-authors.js +64 -55
  30. package/dist/code-vision-model.js +134 -127
  31. package/dist/code-vision.js +224 -206
  32. package/dist/completion-call.js +94 -67
  33. package/dist/completion-model.js +334 -244
  34. package/dist/completion.js +840 -649
  35. package/dist/conflict-model.js +35 -29
  36. package/dist/context-menu-rows.js +42 -17
  37. package/dist/context-menu.js +64 -46
  38. package/dist/definition-link.js +88 -85
  39. package/dist/diagnostics-model.js +74 -55
  40. package/dist/diagnostics.js +121 -100
  41. package/dist/diff-expansion.js +38 -35
  42. package/dist/diff-overlays.js +144 -22
  43. package/dist/diff-syntax.js +65 -42
  44. package/dist/diff-wordmarks.js +26 -23
  45. package/dist/doc-comment-model.js +265 -216
  46. package/dist/editor-language.js +177 -152
  47. package/dist/error-message.js +2 -2
  48. package/dist/find-query.js +49 -36
  49. package/dist/folding.js +81 -62
  50. package/dist/format-on-type.js +86 -67
  51. package/dist/highlight-layers.js +19 -20
  52. package/dist/highlights.js +105 -83
  53. package/dist/history.js +44 -38
  54. package/dist/holder.js +18 -18
  55. package/dist/host-types.js +1 -1
  56. package/dist/hover-content.js +167 -129
  57. package/dist/hover.js +285 -245
  58. package/dist/index.js +10 -10
  59. package/dist/inlay-hints.js +369 -324
  60. package/dist/key-priority.js +34 -31
  61. package/dist/language-ids.js +45 -42
  62. package/dist/line-edits.js +74 -28
  63. package/dist/line-text.js +18 -3
  64. package/dist/locales/en.json +38 -38
  65. package/dist/locales/nl.json +41 -41
  66. package/dist/models.js +1 -1
  67. package/dist/navigation-history.js +40 -41
  68. package/dist/navigation.js +141 -123
  69. package/dist/panel-size.js +8 -8
  70. package/dist/patch-decorations.js +236 -160
  71. package/dist/patch-layout.js +331 -262
  72. package/dist/paths.js +3 -3
  73. package/dist/peek-model.js +86 -69
  74. package/dist/peek.js +254 -192
  75. package/dist/pick.js +164 -157
  76. package/dist/popup-focus.js +5 -5
  77. package/dist/popup-placement.js +36 -21
  78. package/dist/popups.js +13 -13
  79. package/dist/project-language.js +228 -211
  80. package/dist/project-problems.js +81 -69
  81. package/dist/proposal-model.js +163 -126
  82. package/dist/recent-choices.js +25 -25
  83. package/dist/refresher.js +44 -49
  84. package/dist/rename-model.js +113 -113
  85. package/dist/rename.js +321 -233
  86. package/dist/rendered-docs.d.ts +4 -2
  87. package/dist/rendered-docs.js +384 -318
  88. package/dist/rendering-context.js +5 -3
  89. package/dist/rendering.js +22 -4
  90. package/dist/review-group.js +42 -39
  91. package/dist/row-host.d.ts +4 -2
  92. package/dist/row-host.js +90 -78
  93. package/dist/selection-ranges.js +21 -17
  94. package/dist/semantic-delta.js +22 -19
  95. package/dist/semantic-model.js +86 -73
  96. package/dist/semantic-tokens.js +201 -162
  97. package/dist/shortcut-keys.js +16 -10
  98. package/dist/signature-model.js +34 -28
  99. package/dist/signature.js +177 -129
  100. package/dist/snippet-field-transforms.js +118 -106
  101. package/dist/snippet-indent.js +48 -43
  102. package/dist/snippet-range-order.js +11 -11
  103. package/dist/snippet-session.js +703 -667
  104. package/dist/snippet-transform-client.js +59 -59
  105. package/dist/snippet-transform-format.js +285 -263
  106. package/dist/snippet-transform-protocol.js +1 -1
  107. package/dist/snippet-transform-queue.js +163 -153
  108. package/dist/snippet-transform-worker.js +42 -35
  109. package/dist/snippet-variable-names.js +1 -36
  110. package/dist/snippet-variables.js +53 -63
  111. package/dist/snippet.js +477 -405
  112. package/dist/split-alignment.js +47 -35
  113. package/dist/split-scroll.js +42 -40
  114. package/dist/symbol-links.js +33 -25
  115. package/dist/symbol-picker-model.js +126 -116
  116. package/dist/symbol-picker.js +98 -59
  117. package/dist/symbols.js +117 -88
  118. package/dist/testing.js +248 -165
  119. package/dist/timers.js +35 -30
  120. package/dist/use-panel-body.js +49 -8
  121. package/dist/use-problem-counts.js +29 -15
  122. package/dist/view-state.js +54 -33
  123. package/dist/word-diff.js +18 -18
  124. package/dist/workspace-edit.js +300 -249
  125. package/package.json +6 -6
  126. package/src/CallHierarchyPanel.tsx +2 -2
  127. package/src/DiffView.tsx +3 -3
  128. package/src/FindReplace.tsx +2 -2
  129. package/src/LanguagePopups.tsx +2 -0
  130. package/src/PeekPanel.tsx +3 -3
  131. package/src/RenderedDocs.tsx +9 -10
  132. package/src/SymbolPicker.tsx +2 -2
  133. package/src/diff-overlays.tsx +6 -4
  134. package/src/locales/en.json +38 -38
  135. package/src/locales/nl.json +41 -41
  136. package/src/rendered-docs.ts +14 -3
  137. package/src/row-host.ts +14 -3
@@ -63,7 +63,7 @@ function Line({ row, id, active, expanded, position, size, ref, children, onClic
63
63
  );
64
64
  }
65
65
 
66
- function Symbol({ language, row, active, id, ref }: { language: EditorLanguage; row: NodeRow; active: boolean; id: string; ref?: Ref<HTMLDivElement> }) {
66
+ function SymbolRow({ language, row, active, id, ref }: { language: EditorLanguage; row: NodeRow; active: boolean; id: string; ref?: Ref<HTMLDivElement> }) {
67
67
  const { t } = useTranslation('editor');
68
68
  const { item } = row;
69
69
  const path = relativeTo(fileUriToPath(item.uri) ?? item.uri, language.project.folder);
@@ -130,7 +130,7 @@ function Tree({ language, view }: { language: EditorLanguage; view: CallHierarch
130
130
  const active = row.id === view.active;
131
131
  const ref = active ? activeRow : undefined;
132
132
  if (row.kind === 'node') {
133
- return <Symbol key={row.id} ref={ref} language={language} row={row} active={active} id={idOf(row)} />;
133
+ return <SymbolRow key={row.id} ref={ref} language={language} row={row} active={active} id={idOf(row)} />;
134
134
  }
135
135
  if (row.kind === 'more') {
136
136
  const next = Math.min(row.hidden, CALL_LEVEL_LIMIT);
package/src/DiffView.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useLayoutEffect, useMemo, useRef, useState, type Ref } from 'react';
1
+ import { useLayoutEffect, useRef, useState, type Ref } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import type { Editor, EditorEngine, EditorLineHighlight, EditorTheme } from '@adecore/editor';
4
4
  import { parseChord } from '@adecore/editor/keymap';
@@ -54,7 +54,7 @@ function UnifiedDiffView({
54
54
  onMount
55
55
  }: UnifiedViewProps) {
56
56
  const { t } = useTranslation('editor');
57
- const emphasis = useMemo(() => wordMarks(document), [document]);
57
+ const emphasis = wordMarks(document);
58
58
  const element = useRef<HTMLDivElement>(null);
59
59
  const current = useRef({ display, tokens, theme, wrap, label });
60
60
  const applied = useRef({ theme, wrap, label });
@@ -240,7 +240,7 @@ export function DiffView(props: DiffViewProps) {
240
240
  }));
241
241
  const gaps = expanded.document === document ? expanded.gaps : undefined;
242
242
  const blocked = expanded.document === document ? expanded.blocked : new Set<number>();
243
- const projection = useMemo(() => (props.layout === 'split' ? diffSplit(document, gaps) : diffDisplay(document, gaps)), [props.layout, document, gaps]);
243
+ const projection = props.layout === 'split' ? diffSplit(document, gaps) : diffDisplay(document, gaps);
244
244
  const unfold = (id: number): void =>
245
245
  setExpanded((previous) => {
246
246
  const gaps = previous.document === document ? previous.gaps : new Map<number, number>();
@@ -1,4 +1,4 @@
1
- import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
1
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { Button } from '@adecore/ui';
4
4
  import { formatNumber } from '@adecore/ui/format';
@@ -12,7 +12,7 @@ export function FindReplace({ editor, className, onClose }: { editor: Editor; cl
12
12
  const [preserveCase, setPreserveCase] = useState(false);
13
13
  const [state, setState] = useState<EditorFindState>({ count: 0, current: null });
14
14
  const root = useRef<HTMLDivElement>(null);
15
- const compiled = useMemo(() => compileFind(query), [query]);
15
+ const compiled = compileFind(query);
16
16
  useEffect(() => editor.onFind(setState), [editor]);
17
17
  useEffect(() => {
18
18
  editor.find(compiled.kind === 'pattern' ? query : null);
@@ -31,6 +31,8 @@ export interface LanguagePopupsProps<Language extends EditorLanguage = EditorLan
31
31
  * whenever the editor scrolls or resizes.
32
32
  */
33
33
  export function LanguagePopups<Language extends EditorLanguage>({ language, contextMenuItems, hoverFooter, children }: LanguagePopupsProps<Language>) {
34
+ // The React Compiler would keep each card's place from the render before; it is read from the editor again on every scroll.
35
+ 'use no memo';
34
36
  const [, redraw] = useReducer((count: number) => count + 1, 0);
35
37
  const hover = useStore(language.popups, (state) => state.hover);
36
38
  const completion = useStore(language.popups, (state) => state.completion);
package/src/PeekPanel.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useEffect, useMemo, useRef, useState } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { ChevronDown, ChevronRight, X } from 'lucide-react';
@@ -123,8 +123,8 @@ function Places({ language, view }: { language: EditorLanguage; view: PeekView }
123
123
  const { t } = useTranslation('editor');
124
124
  const activeRow = useRef<HTMLButtonElement>(null);
125
125
  const folder = language.project.folder;
126
- const paths = useMemo(() => view.files.map((file) => relativeTo(fileUriToPath(file.uri) ?? file.uri, folder)), [view.files, folder]);
127
- const folders = useMemo(() => distinguishingFolders(paths), [paths]);
126
+ const paths = view.files.map((file) => relativeTo(fileUriToPath(file.uri) ?? file.uri, folder));
127
+ const folders = distinguishingFolders(paths);
128
128
 
129
129
  useEffect(() => {
130
130
  activeRow.current?.scrollIntoView({ block: 'nearest' });
@@ -159,19 +159,18 @@ export const RenderedDocBlock = memo(DocBlock);
159
159
  */
160
160
  export function RenderedDocs({ language }: { language: EditorLanguage }) {
161
161
  const feature = language.renderedDocs;
162
- useSyncExternalStore(feature.subscribe, feature.getVersion, feature.getVersion);
162
+ const getEntries = () => feature.getEntries();
163
+ const entries = useSyncExternalStore((listener) => feature.subscribe(listener), getEntries, getEntries);
163
164
  const linkable = feature.canFollow;
164
165
  return (
165
166
  <>
166
- {feature
167
- .entries()
168
- .map((entry) =>
169
- createPortal(
170
- <RenderedDocBlock language={language} comment={entry.comment} parsed={entry.parsed} linkable={linkable} />,
171
- entry.container,
172
- entry.id
173
- )
174
- )}
167
+ {entries.map((entry) =>
168
+ createPortal(
169
+ <RenderedDocBlock language={language} comment={entry.comment} parsed={entry.parsed} linkable={linkable} />,
170
+ entry.container,
171
+ entry.id
172
+ )
173
+ )}
175
174
  </>
176
175
  );
177
176
  }
@@ -1,4 +1,4 @@
1
- import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react';
1
+ import { useEffect, useRef, useState, type KeyboardEvent } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { AtSign, Hash } from 'lucide-react';
@@ -51,7 +51,7 @@ export function SymbolPicker({ language, view }: { language: EditorLanguage; vie
51
51
  const filterText = mode.mode === 'symbol' ? mode.text : '';
52
52
  const searchText = mode.mode === 'workspace' ? mode.text : '';
53
53
 
54
- const groups = useMemo(() => groupEntries(filterEntries(view.entries, filterText)), [view.entries, filterText]);
54
+ const groups = groupEntries(filterEntries(view.entries, filterText));
55
55
  const flat: SymbolEntry[] = groups.flatMap((group) => group.entries);
56
56
  const places = mode.mode === 'workspace' && found.text === mode.text ? found.entries : [];
57
57
  const count = mode.mode === 'workspace' ? places.length : mode.mode === 'line' ? (mode.line === null ? 0 : 1) : flat.length;
@@ -26,12 +26,14 @@ export function DiffOverlays({
26
26
  blocked?: ReadonlySet<number>;
27
27
  }) {
28
28
  const { t } = useTranslation('editor');
29
- useSyncExternalStore(mounted.rows.subscribe, mounted.rows.getVersion, mounted.rows.getVersion);
30
- useSyncExternalStore(mounted.actions.subscribe, mounted.actions.getVersion, mounted.actions.getVersion);
29
+ const getRows = () => mounted.rows.getContainers();
30
+ const getActions = () => mounted.actions.getContainers();
31
+ const rows = useSyncExternalStore((listener) => mounted.rows.subscribe(listener), getRows, getRows);
32
+ const actions = useSyncExternalStore((listener) => mounted.actions.subscribe(listener), getActions, getActions);
31
33
  return (
32
34
  <>
33
35
  {display.gaps.map(({ row }) => {
34
- const container = mounted.rows.container(`gap-${row.id}`);
36
+ const container = rows.get(`gap-${row.id}`);
35
37
  if (container === undefined) {
36
38
  return null;
37
39
  }
@@ -63,7 +65,7 @@ export function DiffOverlays({
63
65
  if (row.noNewline === undefined) {
64
66
  return null;
65
67
  }
66
- const container = mounted.actions.container(`no-newline-${index}`);
68
+ const container = actions.get(`no-newline-${index}`);
67
69
  return container === undefined
68
70
  ? null
69
71
  : createPortal(<span className="adecore-editor-diff-no-newline">{t('diff.noNewline')}</span>, container, `no-newline-${index}`);
@@ -2,32 +2,32 @@
2
2
  "language": {
3
3
  "hover": {
4
4
  "quickFix": "Quick fix…",
5
- "quickFixNone": "This language server offers no quick fixes",
5
+ "quickFixNone": "No quick fixes",
6
6
  "definition": "Go to definition",
7
7
  "references_one": "{{formatted}} reference",
8
8
  "references_other": "{{formatted}} references",
9
9
  "line": "Line {{line}}",
10
- "none": "No information for this position"
10
+ "none": "No information here"
11
11
  },
12
12
  "inlay": {
13
- "failed": "The hint's action failed: {{message}}"
13
+ "failed": "Could not run hint action: {{message}}"
14
14
  },
15
15
  "edit": {
16
- "staged_one": "{{count}} file changed and not saved yet",
17
- "staged_other": "{{count}} files changed and not saved yet",
16
+ "staged_one": "{{count}} unsaved file",
17
+ "staged_other": "{{count}} unsaved files",
18
18
  "stagedMore": "{{names}} and {{count}} more",
19
19
  "saveAll": "Save all",
20
- "notSaved": "{{name}} could not be saved"
20
+ "notSaved": "Could not save {{name}}"
21
21
  },
22
22
  "actions": {
23
23
  "show": "Show code actions",
24
24
  "none": "No code actions here",
25
- "unavailable": "No language server offers code actions here",
26
- "organized": "The imports are already organized",
27
- "noFormatter": "No language server formats this file",
28
- "readOnly": "This file is read only",
29
- "failed": "Could not apply the action: {{message}}",
30
- "refused": "The edit was refused",
25
+ "unavailable": "Code actions unavailable here",
26
+ "organized": "Imports already organized",
27
+ "noFormatter": "No formatter for this file",
28
+ "readOnly": "Read-only file",
29
+ "failed": "Could not apply action: {{message}}",
30
+ "refused": "Edit refused",
31
31
  "moreLines": "{{count}} more lines",
32
32
  "otherFiles_one": "and {{count}} other file",
33
33
  "otherFiles_other": "and {{count}} other files",
@@ -49,10 +49,10 @@
49
49
  }
50
50
  },
51
51
  "rename": {
52
- "unavailable": "No language server renames in this file",
53
- "nothing": "There is nothing to rename here",
54
- "refused": "The language server refused the new name",
55
- "stale": "The text changed while the rename was being asked for",
52
+ "unavailable": "Rename unavailable in this file",
53
+ "nothing": "Nothing to rename here",
54
+ "refused": "New name refused",
55
+ "stale": "The text changed before the rename finished. Try again.",
56
56
  "failed": "Could not rename: {{message}}",
57
57
  "occurrences_one": "{{formatted}} occurrence",
58
58
  "occurrences_other": "{{formatted}} occurrences",
@@ -71,7 +71,7 @@
71
71
  }
72
72
  },
73
73
  "navigation": {
74
- "unavailable": "No language server answers that here",
74
+ "unavailable": "Not available here",
75
75
  "none": "Nothing found",
76
76
  "failed": "Could not look it up: {{message}}",
77
77
  "titles": {
@@ -86,9 +86,9 @@
86
86
  "resize": "Resize panel"
87
87
  },
88
88
  "peek": {
89
- "unavailable": "No language server finds references in this file",
89
+ "unavailable": "References unavailable in this file",
90
90
  "none": "No references found",
91
- "failed": "Could not look up the references: {{message}}",
91
+ "failed": "Could not look up references: {{message}}",
92
92
  "references_one": "{{formatted}} reference",
93
93
  "references_other": "{{formatted}} references",
94
94
  "close": "Close",
@@ -97,12 +97,12 @@
97
97
  "definitions_one": "{{formatted}} definition",
98
98
  "definitions_other": "{{formatted}} definitions",
99
99
  "noDefinition": "No definition found",
100
- "unavailableDefinition": "No language server finds definitions in this file"
100
+ "unavailableDefinition": "Definitions unavailable in this file"
101
101
  },
102
102
  "callHierarchy": {
103
- "unavailable": "No language server finds calls in this file",
104
- "none": "No symbol with calls found here",
105
- "failed": "Could not look up the calls: {{message}}",
103
+ "unavailable": "Calls unavailable in this file",
104
+ "none": "No calls here",
105
+ "failed": "Could not look up calls: {{message}}",
106
106
  "label": "Call hierarchy",
107
107
  "direction": "Direction",
108
108
  "incoming": "Callers",
@@ -111,7 +111,7 @@
111
111
  "loading": "Loading…",
112
112
  "noIncoming": "No callers",
113
113
  "noOutgoing": "No callees",
114
- "retry": "Could not load the calls: {{message}}. Press to try again",
114
+ "retry": "Could not load calls: {{message}}. Click to try again",
115
115
  "more_one": "Show {{formatted}} more call ({{hidden}} left)",
116
116
  "more_other": "Show {{formatted}} more calls ({{hidden}} left)",
117
117
  "sites_one": "{{formatted}} call",
@@ -133,20 +133,20 @@
133
133
  "newCode": "new *",
134
134
  "lines_one": "{{formatted}} line",
135
135
  "lines_other": "{{formatted}} lines",
136
- "uncommitted": "Not committed yet",
136
+ "uncommitted": "Uncommitted",
137
137
  "latest": "Latest change",
138
138
  "showCommit": "Show commit"
139
139
  },
140
140
  "symbols": {
141
- "unavailable": "No language server knows the symbols of this file",
142
- "failed": "Could not read the symbols: {{message}}",
141
+ "unavailable": "Symbols unavailable in this file",
142
+ "failed": "Could not read symbols: {{message}}",
143
143
  "placeholder": "Go to symbol in {{file}}",
144
144
  "navigate": "Navigate",
145
145
  "open": "Open",
146
146
  "workspace": "Workspace symbols",
147
147
  "line": "Go to line",
148
148
  "none": "No matching symbols",
149
- "workspaceHint": "Type the name of a symbol in the project",
149
+ "workspaceHint": "Type a symbol name",
150
150
  "lineHint": "Type a line number",
151
151
  "goToLine": "Go to line {{line}}",
152
152
  "groups": {
@@ -180,14 +180,14 @@
180
180
  "choices": "Snippet choice"
181
181
  },
182
182
  "completion": {
183
- "tooLarge": "Completion is too large to insert",
183
+ "tooLarge": "Too large to insert",
184
184
  "insert": "Insert",
185
185
  "replace": "Replace",
186
186
  "details": "Details",
187
187
  "none": "No suggestions",
188
- "transformBusy": "Snippet transforms are busy; try again",
189
- "transformFailed": "Snippet transform could not be applied",
190
- "failed": "Could not insert the suggestion: {{message}}"
188
+ "transformBusy": "The snippet is not ready yet. Try again.",
189
+ "transformFailed": "Could not fill in the snippet",
190
+ "failed": "Could not insert suggestion: {{message}}"
191
191
  },
192
192
  "history": {
193
193
  "recent": "Recent locations"
@@ -265,18 +265,18 @@
265
265
  "toggle": "Show replace",
266
266
  "hide": "Hide replace",
267
267
  "failed": {
268
- "limit": "Too much to replace at once ({{edits}} edits or {{characters}} output characters)",
269
- "timeout": "Replacement timed out; the text was not changed",
270
- "unavailable": "Replacement needs the search worker",
271
- "error": "Could not replace; the text was not changed"
268
+ "limit": "Too much to replace at once (more than {{edits}} matches or {{characters}} characters)",
269
+ "timeout": "Replace timed out. Nothing changed",
270
+ "unavailable": "Replace is not available right now",
271
+ "error": "Could not replace. Nothing changed"
272
272
  }
273
273
  },
274
274
  "countMore": "{{total}}+ matches",
275
275
  "searching": "Searching…",
276
- "large": "Large document: press Enter to search",
276
+ "large": "This document is large. Press Enter to search",
277
277
  "replaced": "Replaced {{count}} matches",
278
278
  "failed": {
279
- "timeout": "Search timed out; press Enter to retry",
279
+ "timeout": "Search timed out. Press Enter to try again",
280
280
  "unavailable": "Regex search is unavailable",
281
281
  "invalid": "Invalid regular expression",
282
282
  "error": "Could not finish the search"
@@ -2,32 +2,32 @@
2
2
  "language": {
3
3
  "hover": {
4
4
  "quickFix": "Quick fix…",
5
- "quickFixNone": "Deze language server biedt geen quick fixes",
5
+ "quickFixNone": "Geen quick fixes",
6
6
  "definition": "Ga naar definitie",
7
7
  "references_one": "{{formatted}} referentie",
8
8
  "references_other": "{{formatted}} referenties",
9
9
  "line": "Regel {{line}}",
10
- "none": "Geen informatie voor deze plek"
10
+ "none": "Hier geen informatie"
11
11
  },
12
12
  "inlay": {
13
- "failed": "De actie van de hint is mislukt: {{message}}"
13
+ "failed": "Kon de hintactie niet uitvoeren: {{message}}"
14
14
  },
15
15
  "edit": {
16
- "staged_one": "{{count}} bestand gewijzigd en nog niet opgeslagen",
17
- "staged_other": "{{count}} bestanden gewijzigd en nog niet opgeslagen",
16
+ "staged_one": "{{count}} niet-opgeslagen bestand",
17
+ "staged_other": "{{count}} niet-opgeslagen bestanden",
18
18
  "stagedMore": "{{names}} en nog {{count}}",
19
19
  "saveAll": "Alles opslaan",
20
- "notSaved": "{{name}} kon niet worden opgeslagen"
20
+ "notSaved": "Kon {{name}} niet opslaan"
21
21
  },
22
22
  "actions": {
23
23
  "show": "Toon code actions",
24
24
  "none": "Geen code actions hier",
25
- "unavailable": "Geen language server biedt hier code actions",
26
- "organized": "De imports zijn al georganiseerd",
27
- "noFormatter": "Geen language server formatteert dit bestand",
28
- "readOnly": "Dit bestand is alleen-lezen",
29
- "failed": "De actie kon niet worden toegepast: {{message}}",
30
- "refused": "De wijziging is geweigerd",
25
+ "unavailable": "Hier geen code actions beschikbaar",
26
+ "organized": "Imports zijn al georganiseerd",
27
+ "noFormatter": "Geen formatter voor dit bestand",
28
+ "readOnly": "Bestand is alleen-lezen",
29
+ "failed": "Kon de actie niet toepassen: {{message}}",
30
+ "refused": "Wijziging geweigerd",
31
31
  "moreLines": "nog {{count}} regels",
32
32
  "otherFiles_one": "en nog {{count}} bestand",
33
33
  "otherFiles_other": "en nog {{count}} bestanden",
@@ -49,11 +49,11 @@
49
49
  }
50
50
  },
51
51
  "rename": {
52
- "unavailable": "Geen language server hernoemt in dit bestand",
53
- "nothing": "Hier is niets om te hernoemen",
54
- "refused": "De language server weigerde de nieuwe naam",
55
- "stale": "De tekst veranderde terwijl de hernoeming werd opgevraagd",
56
- "failed": "Hernoemen mislukt: {{message}}",
52
+ "unavailable": "Hernoemen niet beschikbaar in dit bestand",
53
+ "nothing": "Niets om te hernoemen",
54
+ "refused": "Nieuwe naam geweigerd",
55
+ "stale": "De tekst veranderde voordat de hernoeming klaar was. Probeer het opnieuw.",
56
+ "failed": "Kon niet hernoemen: {{message}}",
57
57
  "occurrences_one": "{{formatted}} voorkomen",
58
58
  "occurrences_other": "{{formatted}} voorkomens",
59
59
  "occurrencesFiles_one": "{{formatted}} voorkomen in {{files}} bestanden",
@@ -71,9 +71,9 @@
71
71
  }
72
72
  },
73
73
  "navigation": {
74
- "unavailable": "Geen language server die dat hier beantwoordt",
74
+ "unavailable": "Hier niet beschikbaar",
75
75
  "none": "Niets gevonden",
76
- "failed": "Opzoeken mislukt: {{message}}",
76
+ "failed": "Kon het niet opzoeken: {{message}}",
77
77
  "titles": {
78
78
  "definition": "Definities",
79
79
  "declaration": "Declaraties",
@@ -86,9 +86,9 @@
86
86
  "resize": "Paneel vergroten of verkleinen"
87
87
  },
88
88
  "peek": {
89
- "unavailable": "Geen language server vindt referenties in dit bestand",
89
+ "unavailable": "Referenties niet beschikbaar in dit bestand",
90
90
  "none": "Geen referenties gevonden",
91
- "failed": "Referenties opzoeken mislukt: {{message}}",
91
+ "failed": "Kon de referenties niet opzoeken: {{message}}",
92
92
  "references_one": "{{formatted}} referentie",
93
93
  "references_other": "{{formatted}} referenties",
94
94
  "close": "Sluit",
@@ -97,12 +97,12 @@
97
97
  "definitions_one": "{{formatted}} definitie",
98
98
  "definitions_other": "{{formatted}} definities",
99
99
  "noDefinition": "Geen definitie gevonden",
100
- "unavailableDefinition": "Geen language server vindt definities in dit bestand"
100
+ "unavailableDefinition": "Definities niet beschikbaar in dit bestand"
101
101
  },
102
102
  "callHierarchy": {
103
- "unavailable": "Geen language server vindt aanroepen in dit bestand",
104
- "none": "Hier is geen symbool met aanroepen gevonden",
105
- "failed": "Aanroepen opzoeken mislukt: {{message}}",
103
+ "unavailable": "Aanroepen niet beschikbaar in dit bestand",
104
+ "none": "Hier geen aanroepen",
105
+ "failed": "Kon de aanroepen niet opzoeken: {{message}}",
106
106
  "label": "Aanroephiërarchie",
107
107
  "direction": "Richting",
108
108
  "incoming": "Aanroepers",
@@ -111,7 +111,7 @@
111
111
  "loading": "Laden…",
112
112
  "noIncoming": "Geen aanroepers",
113
113
  "noOutgoing": "Roept niets aan",
114
- "retry": "Aanroepen laden mislukt: {{message}}. Druk om opnieuw te proberen",
114
+ "retry": "Kon de aanroepen niet laden: {{message}}. Klik om het opnieuw te proberen",
115
115
  "more_one": "Toon nog {{formatted}} aanroep ({{hidden}} over)",
116
116
  "more_other": "Toon nog {{formatted}} aanroepen ({{hidden}} over)",
117
117
  "sites_one": "{{formatted}} aanroep",
@@ -133,20 +133,20 @@
133
133
  "newCode": "nieuw *",
134
134
  "lines_one": "{{formatted}} regel",
135
135
  "lines_other": "{{formatted}} regels",
136
- "uncommitted": "Nog niet gecommit",
136
+ "uncommitted": "Niet gecommit",
137
137
  "latest": "Laatste wijziging",
138
138
  "showCommit": "Commit tonen"
139
139
  },
140
140
  "symbols": {
141
- "unavailable": "Geen language server kent de symbolen van dit bestand",
142
- "failed": "De symbolen konden niet worden gelezen: {{message}}",
141
+ "unavailable": "Symbolen niet beschikbaar in dit bestand",
142
+ "failed": "Kon de symbolen niet lezen: {{message}}",
143
143
  "placeholder": "Ga naar symbool in {{file}}",
144
144
  "navigate": "Navigeer",
145
145
  "open": "Open",
146
146
  "workspace": "Symbolen in het project",
147
147
  "line": "Ga naar regel",
148
148
  "none": "Geen symbolen gevonden",
149
- "workspaceHint": "Typ de naam van een symbool in het project",
149
+ "workspaceHint": "Typ een symboolnaam",
150
150
  "lineHint": "Typ een regelnummer",
151
151
  "goToLine": "Ga naar regel {{line}}",
152
152
  "groups": {
@@ -180,14 +180,14 @@
180
180
  "choices": "Snippetkeuze"
181
181
  },
182
182
  "completion": {
183
- "tooLarge": "Deze aanvulling is te groot om in te voegen",
183
+ "tooLarge": "Te groot om in te voegen",
184
184
  "insert": "Invoegen",
185
185
  "replace": "Vervangen",
186
186
  "details": "Details",
187
187
  "none": "Geen suggesties",
188
- "transformBusy": "Snippettransformaties zijn bezig; probeer het opnieuw",
189
- "transformFailed": "Snippettransformatie kon niet worden toegepast",
190
- "failed": "De suggestie kon niet worden ingevoegd: {{message}}"
188
+ "transformBusy": "Het snippet is nog niet klaar. Probeer het opnieuw.",
189
+ "transformFailed": "Kon het snippet niet invullen",
190
+ "failed": "Kon de suggestie niet invoegen: {{message}}"
191
191
  },
192
192
  "history": {
193
193
  "recent": "Recente plekken"
@@ -265,21 +265,21 @@
265
265
  "toggle": "Vervangen tonen",
266
266
  "hide": "Vervangen verbergen",
267
267
  "failed": {
268
- "limit": "Te veel om ineens te vervangen ({{edits}} edits of {{characters}} uitvoertekens)",
269
- "timeout": "Vervangen duurde te lang; de tekst is niet gewijzigd",
270
- "unavailable": "Vervangen vereist de zoekworker",
271
- "error": "Vervangen is niet gelukt; de tekst is niet gewijzigd"
268
+ "limit": "Te veel om ineens te vervangen (meer dan {{edits}} treffers of {{characters}} tekens)",
269
+ "timeout": "Vervangen duurde te lang. Er is niets gewijzigd",
270
+ "unavailable": "Vervangen is nu niet beschikbaar",
271
+ "error": "Kon niet vervangen. Er is niets gewijzigd"
272
272
  }
273
273
  },
274
274
  "countMore": "{{total}}+ resultaten",
275
275
  "searching": "Zoeken…",
276
- "large": "Groot document: druk op Enter om te zoeken",
276
+ "large": "Dit document is groot. Druk op Enter om te zoeken",
277
277
  "replaced": "{{count}} resultaten vervangen",
278
278
  "failed": {
279
- "timeout": "Zoeken duurde te lang; druk op Enter om opnieuw te proberen",
279
+ "timeout": "Zoeken duurde te lang. Druk op Enter om het opnieuw te proberen",
280
280
  "unavailable": "Zoeken met regex is niet beschikbaar",
281
281
  "invalid": "Ongeldige reguliere expressie",
282
- "error": "Zoeken kon niet worden voltooid"
282
+ "error": "Kon de zoekopdracht niet voltooien"
283
283
  }
284
284
  },
285
285
  "diff": {
@@ -83,6 +83,7 @@ export class RenderedDocsFeature {
83
83
  private readonly revealed = new Set<DocComment>();
84
84
  private readonly listeners = new Set<() => void>();
85
85
  private version = 0;
86
+ private shown: { version: number; entries: readonly RenderedDocEntry[] } | null = null;
86
87
  private settleTimer: unknown;
87
88
  private caretTimer: unknown;
88
89
  private drawn = '';
@@ -201,14 +202,24 @@ export class RenderedDocsFeature {
201
202
  return result;
202
203
  }
203
204
 
204
- getVersion = (): number => this.version;
205
+ getVersion(): number {
206
+ return this.version;
207
+ }
205
208
 
206
- subscribe = (listener: () => void): (() => void) => {
209
+ /* What `entries` answers, one array until the version moves, so React can read it as a snapshot. */
210
+ getEntries(): readonly RenderedDocEntry[] {
211
+ if (this.shown?.version !== this.version) {
212
+ this.shown = { version: this.version, entries: this.entries() };
213
+ }
214
+ return this.shown.entries;
215
+ }
216
+
217
+ subscribe(listener: () => void): () => void {
207
218
  this.listeners.add(listener);
208
219
  return () => {
209
220
  this.listeners.delete(listener);
210
221
  };
211
- };
222
+ }
212
223
 
213
224
  /* Whether names in `{@link}` and `@see` can be followed, which takes a server that finds symbols by name. */
214
225
  get canFollow(): boolean {
package/src/row-host.ts CHANGED
@@ -24,20 +24,31 @@ abstract class ContainerHost {
24
24
  private readonly listeners = new Set<() => void>();
25
25
  private version = 0;
26
26
  private signature = '';
27
+ private shown: { version: number; containers: ReadonlyMap<string, HTMLElement> } | null = null;
27
28
 
28
29
  constructor(editor: Editor, owner: string) {
29
30
  this.editor = editor;
30
31
  this.owner = owner;
31
32
  }
32
33
 
33
- getVersion = (): number => this.version;
34
+ getVersion(): number {
35
+ return this.version;
36
+ }
34
37
 
35
- subscribe = (listener: () => void): (() => void) => {
38
+ /* The elements by id as they stand now, one map until they change, so React can read them as a snapshot. */
39
+ getContainers(): ReadonlyMap<string, HTMLElement> {
40
+ if (this.shown?.version !== this.version) {
41
+ this.shown = { version: this.version, containers: new Map(this.containers) };
42
+ }
43
+ return this.shown.containers;
44
+ }
45
+
46
+ subscribe(listener: () => void): () => void {
36
47
  this.listeners.add(listener);
37
48
  return () => {
38
49
  this.listeners.delete(listener);
39
50
  };
40
- };
51
+ }
41
52
 
42
53
  container(id: string): HTMLElement | undefined {
43
54
  return this.containers.get(id);