* ui: split the markdown rendering setting per surface User content and thinking get their own toggle again, so turning off markdown for a message leaves reasoning blocks formatted. Both default to markdown. A stored renderContentAsRawText unfolds onto the user key and is dropped from the config. File mentions render as badges in the raw text path too, through a narrow pass over [name](file://path) that leaves everything else untouched. * ui: let the rich chat input scroll past its max height The contenteditable renderer caps its height with max-height but had no overflow rule, so a long buffer overflowed into the input area wrapper and got clipped by its overflow-hidden, leaving no way to reach the bottom of the message. The textarea renderer scrolls natively and was never affected. * ui: apply the new lint and format config * ui: move the render keys unfolding into the migration service Address review from @allozaur: the settings store no longer rewrites persisted config on load, the raw text toggle now unfolds onto the per-surface render keys in migration.service.ts, next to the other config migrations. The mention scanner flag and the directory path suffix become named constants.
65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
// Guards the unfolding of `renderContentAsRawText` back onto the two
|
|
// per-surface render keys. The single toggle carried user content and
|
|
// thinking at once, so only the user key is restored from it and thinking
|
|
// returns to its own default. The toggle is removed from the persisted
|
|
// config so it does not stay orphaned in localStorage.
|
|
|
|
import { CONFIG_LOCALSTORAGE_KEY } from '$lib/constants/storage';
|
|
import { MigrationService } from '$lib/services/migration.service';
|
|
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
const RENDER_KEYS_MIGRATION_ID = 'render-keys-unfold-v1';
|
|
|
|
async function seedConfig(stored: Record<string, unknown>) {
|
|
localStorage.setItem(CONFIG_LOCALSTORAGE_KEY, JSON.stringify(stored));
|
|
|
|
const migration = MigrationService.getMigrations().find((m) => m.id === RENDER_KEYS_MIGRATION_ID);
|
|
|
|
await migration?.run();
|
|
settingsStore.initialize();
|
|
}
|
|
|
|
function persisted(): Record<string, unknown> {
|
|
return JSON.parse(localStorage.getItem(CONFIG_LOCALSTORAGE_KEY) ?? '{}');
|
|
}
|
|
|
|
describe('renderContentAsRawText unfolding', () => {
|
|
beforeEach(() => {
|
|
localStorage.removeItem(CONFIG_LOCALSTORAGE_KEY);
|
|
MigrationService.resetState();
|
|
settingsStore.initialize();
|
|
});
|
|
|
|
it('maps raw text to user content as plain text', async () => {
|
|
await seedConfig({ renderContentAsRawText: true });
|
|
expect(config().renderUserContentAsMarkdown).toBe(false);
|
|
});
|
|
|
|
it('maps markdown to user content as markdown', async () => {
|
|
await seedConfig({ renderContentAsRawText: false });
|
|
expect(config().renderUserContentAsMarkdown).toBe(true);
|
|
});
|
|
|
|
it('leaves thinking on its own default', async () => {
|
|
await seedConfig({ renderContentAsRawText: true });
|
|
expect(config().renderThinkingAsMarkdown).toBe(true);
|
|
});
|
|
|
|
it('keeps an explicit user preference over the toggle', async () => {
|
|
await seedConfig({ renderContentAsRawText: true, renderUserContentAsMarkdown: true });
|
|
expect(config().renderUserContentAsMarkdown).toBe(true);
|
|
});
|
|
|
|
it('drops the toggle from the persisted config', async () => {
|
|
await seedConfig({ renderContentAsRawText: true });
|
|
expect(persisted().renderContentAsRawText).toBeUndefined();
|
|
});
|
|
|
|
it('leaves both surfaces on markdown when nothing is stored', async () => {
|
|
await seedConfig({});
|
|
expect(config().renderUserContentAsMarkdown).toBe(true);
|
|
expect(config().renderThinkingAsMarkdown).toBe(true);
|
|
});
|
|
});
|