refactor: Naming (#27001)
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
// block region - closed, or still OPEN while the user is typing
|
||||
// one - plain Enter adds a line instead of submitting the message.
|
||||
// The textarea path is covered here end-to-end (the contenteditable
|
||||
// consumes the same case locally; see chat-form-contenteditable).
|
||||
// consumes the same case locally; see chat-form-input-rich).
|
||||
|
||||
import ChatFormTestWrapper from './components/ChatFormTestWrapper.svelte';
|
||||
import { SETTINGS_KEYS } from '$lib/constants';
|
||||
|
||||
+9
-9
@@ -3,7 +3,7 @@
|
||||
// serialization must fold those back into `\n` so the emitted value never
|
||||
// diverges from what is on screen.
|
||||
|
||||
import ChatFormContentEditableHarness from './components/ChatFormContentEditableHarness.svelte';
|
||||
import ChatFormInputRichHarness from './components/ChatFormInputRichHarness.svelte';
|
||||
import { tick } from 'svelte';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { render } from 'vitest-browser-svelte';
|
||||
@@ -35,9 +35,9 @@ function setCaret(node: Node, offset: number) {
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
describe('ChatFormInputRich browser newline shapes', () => {
|
||||
it('serializes a Chromium Enter <div> wrapper as a newline', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: SOURCE });
|
||||
const screen = render(ChatFormInputRichHarness, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('serializes a Firefox full <div> wrap as lines, badge included', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: SOURCE });
|
||||
const screen = render(ChatFormInputRichHarness, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('serializes a <br> as a newline', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'here' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'here' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('ignores a trailing <br> (browser caret placeholder)', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -102,7 +102,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('serializes one newline per empty-line <div><br></div>', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -121,7 +121,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('treats a <div><br></div>-only buffer as empty for the placeholder', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -138,7 +138,7 @@ describe('ChatFormContentEditable browser newline shapes', () => {
|
||||
});
|
||||
|
||||
it('maps the caret across block boundaries in both directions', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc\ndef' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc\ndef' });
|
||||
|
||||
await tick();
|
||||
|
||||
+10
-10
@@ -3,7 +3,7 @@
|
||||
// the native undo stack), and Tab is NOT intercepted (WCAG 2.1.2 no
|
||||
// keyboard trap), matching the plain textarea.
|
||||
|
||||
import ChatFormContentEditableHarness from './components/ChatFormContentEditableHarness.svelte';
|
||||
import ChatFormInputRichHarness from './components/ChatFormInputRichHarness.svelte';
|
||||
import { tick } from 'svelte';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { render } from 'vitest-browser-svelte';
|
||||
@@ -31,9 +31,9 @@ function keydown(root: HTMLElement, init: KeyboardEventInit) {
|
||||
return event;
|
||||
}
|
||||
|
||||
describe('ChatFormContentEditable undo/redo', () => {
|
||||
describe('ChatFormInputRich undo/redo', () => {
|
||||
it('undoes and redoes an edit across a badge-containing buffer', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: SOURCE });
|
||||
const screen = render(ChatFormInputRichHarness, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
|
||||
it('redoes with Ctrl+Y as well', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: SOURCE });
|
||||
const screen = render(ChatFormInputRichHarness, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
|
||||
it('coalesces a typing burst into one undo step', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -92,7 +92,7 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
|
||||
it('keeps a newline as its own undo step', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
|
||||
it('is a no-op when there is nothing to undo', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
|
||||
it('abandons the redo branch after a fresh edit', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: 'abc' });
|
||||
const screen = render(ChatFormInputRichHarness, { value: 'abc' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -147,9 +147,9 @@ describe('ChatFormContentEditable undo/redo', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ChatFormContentEditable Tab key', () => {
|
||||
describe('ChatFormInputRich Tab key', () => {
|
||||
it('does not trap Tab (focus can leave the editable)', async () => {
|
||||
const screen = render(ChatFormContentEditableHarness, { value: SOURCE });
|
||||
const screen = render(ChatFormInputRichHarness, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
+44
-44
@@ -3,7 +3,7 @@
|
||||
// contributes its full `[name](file://...)` link) and pasting such
|
||||
// markdown re-renders the badges.
|
||||
|
||||
import ChatFormContentEditable from '$lib/components/app/chat/ChatForm/ChatFormContentEditable.svelte';
|
||||
import ChatFormInputRich from '$lib/components/app/chat/ChatForm/ChatFormInput/ChatFormInputRich.svelte';
|
||||
import { rangeToTextOffset, serializeContent, textOffsetToRange } from '$lib/utils';
|
||||
import { tick } from 'svelte';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
@@ -43,9 +43,9 @@ function clipboardEvent(type: 'copy' | 'cut' | 'paste', text = '') {
|
||||
return { data, event };
|
||||
}
|
||||
|
||||
describe('ChatFormContentEditable clipboard', () => {
|
||||
describe('ChatFormInputRich clipboard', () => {
|
||||
it('copy exposes the markdown source of the selection', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('ChatFormContentEditable clipboard', () => {
|
||||
});
|
||||
|
||||
it('cut exposes the markdown source and removes the slice', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('ChatFormContentEditable clipboard', () => {
|
||||
});
|
||||
|
||||
it('paste of markdown mention links re-renders badges', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: 'hello ' });
|
||||
const { container } = render(ChatFormInputRich, { value: 'hello ' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('ChatFormContentEditable clipboard', () => {
|
||||
});
|
||||
|
||||
it('paste without mention links keeps the DOM untouched', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: 'hello ' });
|
||||
const { container } = render(ChatFormInputRich, { value: 'hello ' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -138,14 +138,14 @@ describe('ChatFormContentEditable clipboard', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ChatFormContentEditable code spans', () => {
|
||||
describe('ChatFormInputRich code spans', () => {
|
||||
it('renders inline code from the initial value', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: 'run `npm test` now' });
|
||||
const { container } = render(ChatFormInputRich, { value: 'run `npm test` now' });
|
||||
|
||||
await tick();
|
||||
|
||||
const root = editableIn(container);
|
||||
const code = root.querySelector('code[data-code-token="inline"]');
|
||||
const code = root.querySelector('code[data-code-token="code_inline"]');
|
||||
|
||||
expect(code).not.toBeNull();
|
||||
expect(code!.textContent).toBe('`npm test`');
|
||||
@@ -153,12 +153,12 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
|
||||
it('renders a fenced code block with a language', async () => {
|
||||
const source = 'before\n```js\nconst a = 1;\n```\nafter';
|
||||
const { container } = render(ChatFormContentEditable, { value: source });
|
||||
const { container } = render(ChatFormInputRich, { value: source });
|
||||
|
||||
await tick();
|
||||
|
||||
const root = editableIn(container);
|
||||
const code = root.querySelector('code[data-code-token="block"]');
|
||||
const code = root.querySelector('code[data-code-token="code_block"]');
|
||||
|
||||
expect(code).not.toBeNull();
|
||||
expect(code!.textContent).toBe('```js\nconst a = 1;\n```');
|
||||
@@ -166,7 +166,7 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
|
||||
it('copy exposes the markdown source of a selection spanning code', async () => {
|
||||
const source = 'run `npm test` now';
|
||||
const { container } = render(ChatFormContentEditable, { value: source });
|
||||
const { container } = render(ChatFormInputRich, { value: source });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -183,7 +183,7 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
});
|
||||
|
||||
it('paste of a code span renders the styled element', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: 'run ' });
|
||||
const { container } = render(ChatFormInputRich, { value: 'run ' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -201,7 +201,7 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
await tick();
|
||||
|
||||
expect(event.defaultPrevented).toBe(true);
|
||||
const code = root.querySelector('code[data-code-token="inline"]');
|
||||
const code = root.querySelector('code[data-code-token="code_inline"]');
|
||||
|
||||
expect(code).not.toBeNull();
|
||||
expect(code!.textContent).toBe('`npm test`');
|
||||
@@ -210,12 +210,12 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
|
||||
it('highlights a fenced block content and stays byte-exact', async () => {
|
||||
const source = '```js\nconst a = 1;\n```';
|
||||
const { container } = render(ChatFormContentEditable, { value: source });
|
||||
const { container } = render(ChatFormInputRich, { value: source });
|
||||
|
||||
await tick();
|
||||
|
||||
const root = editableIn(container);
|
||||
const code = root.querySelector('code[data-code-token="block"]');
|
||||
const code = root.querySelector('code[data-code-token="code_block"]');
|
||||
|
||||
expect(code).not.toBeNull();
|
||||
expect(code!.querySelector('.hljs-keyword')).not.toBeNull();
|
||||
@@ -223,7 +223,7 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
});
|
||||
|
||||
it('does not highlight inline code', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: 'run `const` now' });
|
||||
const { container } = render(ChatFormInputRich, { value: 'run `const` now' });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -233,9 +233,9 @@ describe('ChatFormContentEditable code spans', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
describe('ChatFormInputRich code block escape hatches', () => {
|
||||
const BLOCK_SOURCE = '```js\nconst a = 1;\n```';
|
||||
const BLOCK_SELECTOR = 'code[data-code-token="block"]';
|
||||
const BLOCK_SELECTOR = 'code[data-code-token="code_block"]';
|
||||
|
||||
function blockIn(root: HTMLElement): HTMLElement {
|
||||
const el = root.querySelector(BLOCK_SELECTOR);
|
||||
@@ -273,7 +273,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
}
|
||||
|
||||
it('pads a trailing code block with a br hatch that stays invisible to copy', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -292,7 +292,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('escapes a trailing code block with ArrowDown and types after it', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -318,7 +318,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('escapes a leading code block with ArrowUp and types before it', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -343,7 +343,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('escapes a leading code block with ArrowLeft from its first character', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -358,7 +358,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('removes the transient leading hatch when the caret moves back into the block', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -378,7 +378,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('extends the selection out of the block with Shift+ArrowDown', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -397,7 +397,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('line-separates text typed right after the closing fence', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -419,7 +419,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('does not double the newline when Shift+Enter already added one', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -437,7 +437,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('moves a caret stuck before the inserted newline onto the new line', async () => {
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
value: BLOCK_SOURCE + '\ntext after the code block'
|
||||
});
|
||||
|
||||
@@ -469,7 +469,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('appends the artificial trailing newline when the browser did not add one', async () => {
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
value: BLOCK_SOURCE + '\ntext after the code block'
|
||||
});
|
||||
|
||||
@@ -501,7 +501,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('lands the caret on the new line with a single Shift+Enter after text below a block', async () => {
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
value: BLOCK_SOURCE + '\ntext after the code block'
|
||||
});
|
||||
|
||||
@@ -534,7 +534,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('lets Backspace at the text start move into the block without a source fight', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -560,7 +560,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('lets forward Delete eat the text after a block normally', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -581,7 +581,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('renders text after a block without a phantom empty line', async () => {
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
value: BLOCK_SOURCE + '\nhello'
|
||||
});
|
||||
|
||||
@@ -594,7 +594,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('keeps an intentional blank line after a block out of the separator', async () => {
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
value: BLOCK_SOURCE + '\n\nhello'
|
||||
});
|
||||
|
||||
@@ -607,7 +607,7 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
|
||||
it('re-highlights while typing inside a block and keeps the caret', async () => {
|
||||
const { container } = render(ChatFormContentEditable, { value: BLOCK_SOURCE });
|
||||
const { container } = render(ChatFormInputRich, { value: BLOCK_SOURCE });
|
||||
|
||||
await tick();
|
||||
|
||||
@@ -639,12 +639,12 @@ describe('ChatFormContentEditable code block escape hatches', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
describe('ChatFormInputRich Enter in code blocks', () => {
|
||||
const BLOCK_SOURCE = '```js\nconst a = 1;\n```';
|
||||
|
||||
it('adds a line instead of submitting on plain Enter inside a block', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: BLOCK_SOURCE
|
||||
});
|
||||
@@ -670,7 +670,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
expect(onKeydown).not.toHaveBeenCalled();
|
||||
expect(serializeContent(root)).toBe('```js\n\nconst a = 1;\n```');
|
||||
|
||||
const code = root.querySelector('code[data-code-token="block"]');
|
||||
const code = root.querySelector('code[data-code-token="code_block"]');
|
||||
const selection = window.getSelection();
|
||||
|
||||
expect(code!.contains(selection!.getRangeAt(0).startContainer)).toBe(true);
|
||||
@@ -679,7 +679,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
|
||||
it('adds a line after a still-open fence (no closing ``` yet)', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: '```js\nconst a = 1;'
|
||||
});
|
||||
@@ -707,7 +707,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
|
||||
it('forwards plain Enter to the parent when the caret is outside a block', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: BLOCK_SOURCE + '\nafter'
|
||||
});
|
||||
@@ -730,7 +730,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
|
||||
it('forwards plain Enter on the trailing hatch line after a block', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: BLOCK_SOURCE
|
||||
});
|
||||
@@ -753,7 +753,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
|
||||
it('forwards Ctrl+Enter inside a block so explicit submit survives', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: BLOCK_SOURCE
|
||||
});
|
||||
@@ -780,7 +780,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
|
||||
it('forwards Enter inside an inline code span', async () => {
|
||||
const onKeydown = vi.fn();
|
||||
const { container } = render(ChatFormContentEditable, {
|
||||
const { container } = render(ChatFormInputRich, {
|
||||
onKeydown,
|
||||
value: 'run `npm test` now'
|
||||
});
|
||||
@@ -790,7 +790,7 @@ describe('ChatFormContentEditable Enter in code blocks', () => {
|
||||
const root = editableIn(container);
|
||||
|
||||
root.focus();
|
||||
const code = root.querySelector('code[data-code-token="inline"]')!;
|
||||
const code = root.querySelector('code[data-code-token="code_inline"]')!;
|
||||
|
||||
setSelection(root, (range) => {
|
||||
range.setStart(code.firstChild!, 3);
|
||||
@@ -3,7 +3,7 @@
|
||||
// it, the picker still opens but explains why instead of firing searches
|
||||
// that would only fail with "Search failed".
|
||||
|
||||
import ChatFormMentionPicker from '$lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormMentionPicker.svelte';
|
||||
import ChatFormMentionPicker from '$lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormPickerMention.svelte';
|
||||
import { DISABLED_TOOL_KEYS_LOCALSTORAGE_KEY } from '$lib/constants';
|
||||
import { BuiltInTool } from '$lib/enums';
|
||||
import { toolsStore } from '$lib/stores/tools.svelte';
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ChatFormContentEditable from '$lib/components/app/chat/ChatForm/ChatFormContentEditable.svelte';
|
||||
import ChatFormInputRich from '$lib/components/app/chat/ChatForm/ChatFormInput/ChatFormInputRich.svelte';
|
||||
import { untrack } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
@@ -9,7 +9,7 @@
|
||||
let { value: initial = '' }: Props = $props();
|
||||
|
||||
let value = $state(untrack(() => initial));
|
||||
let inputRef: ChatFormContentEditable | undefined = $state(undefined);
|
||||
let inputRef: ChatFormInputRich | undefined = $state(undefined);
|
||||
|
||||
export function getValue() {
|
||||
return value;
|
||||
@@ -24,4 +24,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ChatFormContentEditable bind:this={inputRef} bind:value />
|
||||
<ChatFormInputRich bind:this={inputRef} bind:value />
|
||||
+7
-7
@@ -97,7 +97,7 @@ describe('tokenizeContent', () => {
|
||||
it('tokenizes inline code with the backticks included', () => {
|
||||
expect(tokenizeContent('run `npm test` now')).toEqual([
|
||||
{ kind: 'text', text: 'run ' },
|
||||
{ kind: 'inlineCode', text: '`npm test`' },
|
||||
{ kind: 'code_inline', text: '`npm test`' },
|
||||
{ kind: 'text', text: ' now' }
|
||||
]);
|
||||
});
|
||||
@@ -107,7 +107,7 @@ describe('tokenizeContent', () => {
|
||||
|
||||
expect(tokenizeContent(source)).toEqual([
|
||||
{ kind: 'text', text: 'before\n' },
|
||||
{ kind: 'codeBlock', text: '```\nconst a = 1;\n```' },
|
||||
{ kind: 'code_block', text: '```\nconst a = 1;\n```' },
|
||||
{ kind: 'text', text: '\nafter' }
|
||||
]);
|
||||
});
|
||||
@@ -116,15 +116,15 @@ describe('tokenizeContent', () => {
|
||||
const source = '```js\nconst a = 1;\n```';
|
||||
|
||||
expect(tokenizeContent(source)).toEqual([
|
||||
{ kind: 'codeBlock', text: '```js\nconst a = 1;\n```' }
|
||||
{ kind: 'code_block', text: '```js\nconst a = 1;\n```' }
|
||||
]);
|
||||
});
|
||||
|
||||
it('prefers the fenced block over inline spans at triple backticks', () => {
|
||||
expect(tokenizeContent('```a``` ```b```')).toEqual([
|
||||
{ kind: 'codeBlock', text: '```a```' },
|
||||
{ kind: 'code_block', text: '```a```' },
|
||||
{ kind: 'text', text: ' ' },
|
||||
{ kind: 'codeBlock', text: '```b```' }
|
||||
{ kind: 'code_block', text: '```b```' }
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -140,7 +140,7 @@ describe('tokenizeContent', () => {
|
||||
|
||||
it('does not recognize badges inside code spans', () => {
|
||||
expect(tokenizeContent('`[a](file:///p)`')).toEqual([
|
||||
{ kind: 'inlineCode', text: '`[a](file:///p)`' }
|
||||
{ kind: 'code_inline', text: '`[a](file:///p)`' }
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('tokenizeContent', () => {
|
||||
expect(tokenizeContent('[a](file:///p) `x`')).toEqual([
|
||||
{ kind: 'badge', name: 'a', path: '/p' },
|
||||
{ kind: 'text', text: ' ' },
|
||||
{ kind: 'inlineCode', text: '`x`' }
|
||||
{ kind: 'code_inline', text: '`x`' }
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user