Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3258,6 +3258,19 @@ app.whenReady().then(async () => {
return
}

// Force Chromium's renderer accessibility tree on. By default Chromium builds
// it lazily, only once it detects an assistive client through the macOS
// accessibility activation handshake. Tools that read the tree without
// performing that handshake are otherwise left blind: they find the native
// window but never see the CodeMirror contentEditable text. Enabling it
// unconditionally exposes editor content to that whole class of accessibility
// clients (e.g. the Grammarly desktop app and similar proofreaders, which
// would otherwise show their UI but report nothing). macOS-only to avoid the
// small always-on cost where it isn't needed.
if (process.platform === 'darwin') {
app.setAccessibilitySupportEnabled(true)
}

await migrateLegacyRemoteWorkspaceSecrets()

protocol.handle(LOCAL_ASSET_SCHEME, async (request) => {
Expand Down
6 changes: 6 additions & 0 deletions packages/app-core/src/components/EditorPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,12 @@ export function EditorPane({ pane }: { pane: PaneLeaf }): JSX.Element {
doc: initialBody,
extensions: [
appMarkdownSnippetExtension(),
// Give the editable surface an accessible name so accessibility
// clients (screen readers, proofreaders such as Grammarly) identify
// it as a text field.
EditorView.contentAttributes.of({
'aria-label': 'Note editor'
}),
vimCompartment.of(s0.vimMode ? vim() : []),
historyCompartment.of(history()),
drawSelection(),
Expand Down
8 changes: 8 additions & 0 deletions packages/app-core/src/lib/cm-heading-fold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ class HeadingFoldArrow extends WidgetType {
el.setAttribute('role', 'button')
el.setAttribute('aria-label', this.folded ? 'Expand heading' : 'Collapse heading')
el.setAttribute('aria-expanded', String(!this.folded))
// Keep this decorative affordance out of the accessibility tree. It sits
// (via side:-1) at the very start of the heading line, so as an AX-visible
// `role="button"` it becomes the editable field's leading element. Some
// accessibility clients (e.g. Grammarly) inspect a field's leading content
// and, finding a button, treat the whole field as a non-prose control and
// disengage. Folding stays reachable by mouse, keyboard, and vim, so hiding
// it from the accessibility tree costs nothing.
el.setAttribute('aria-hidden', 'true')
el.textContent = this.folded ? '▸' : '▾'
// Eat mousedown so CodeMirror's own handler doesn't interpret the
// click as a caret position and steal focus before we dispatch
Expand Down
4 changes: 4 additions & 0 deletions packages/app-core/src/lib/cm-wysiwyg-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class BulletWidget extends WidgetType {
const span = document.createElement('span')
span.className = 'cm-wq-bullet'
span.textContent = '•'
// Decorative marker only — keep it out of the accessibility tree so it
// doesn't pollute the field's text value for clients that read it (screen
// readers, proofreaders). The underlying `- ` is still the source text.
span.setAttribute('aria-hidden', 'true')
return span
}
ignoreEvent(): boolean {
Expand Down