Private
Public Access
Markdown support was already complete and documented, but nothing in the composer pointed at it -- unlike @, # and : (which advertise themselves when typed), formatting syntax was only discoverable via Help, buried in the account menu. The composer stays a plain markdown textarea; a new "Aa" button opens a toolbar that inserts the syntax for you: bold, italic, strikethrough, inline code, code block, link, quote, bulleted/numbered lists, H1-H3, sub/superscript. Collapsed by default, remembered across reloads and room switches. Clicking a button again removes the formatting (native undo doesn't track programmatic edits), and bold/italic/sub/strike toggles are run-length aware so "***x***" is handled correctly. The selection math is pure functions in lib/markdownFormat.ts, unit-tested. The "?" opens /help#formatting in a new tab so the draft isn't lost; HelpPage now scrolls to the hash once the guide has loaded, since the browser's own hash scroll fired before the async-fetched headings existed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
32 lines
1008 B
TypeScript
32 lines
1008 B
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { getFormattingToolbarOpen, setFormattingToolbarOpen } from './formattingToolbarPref'
|
|
|
|
afterEach(() => {
|
|
localStorage.clear()
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
describe('formatting toolbar preference', () => {
|
|
it('is collapsed by default', () => {
|
|
expect(getFormattingToolbarOpen()).toBe(false)
|
|
})
|
|
|
|
it('remembers being opened and closed', () => {
|
|
setFormattingToolbarOpen(true)
|
|
expect(getFormattingToolbarOpen()).toBe(true)
|
|
setFormattingToolbarOpen(false)
|
|
expect(getFormattingToolbarOpen()).toBe(false)
|
|
})
|
|
|
|
it('falls back to collapsed when storage is unavailable', () => {
|
|
vi.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {
|
|
throw new Error('blocked')
|
|
})
|
|
vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {
|
|
throw new Error('blocked')
|
|
})
|
|
expect(getFormattingToolbarOpen()).toBe(false)
|
|
expect(() => setFormattingToolbarOpen(true)).not.toThrow()
|
|
})
|
|
})
|