[visual] Decorate horizontal spacing macros (#19200)

GitOrigin-RevId: 9ca1be0c00d1483b5d3a9baa214445ce4e3cf36c
This commit is contained in:
Alf Eaton 2024-07-01 10:43:25 +01:00 committed by Copybot
parent 6efd5eb0b4
commit b156fb24d3
4 changed files with 96 additions and 0 deletions

View file

@ -78,6 +78,10 @@ import {
} from '../../components/table-generator/utils'
import { debugConsole } from '@/utils/debugging'
import { DescriptionItemWidget } from './visual-widgets/description-item'
import {
createSpaceCommand,
hasSpaceSubstitution,
} from '@/features/source-editor/extensions/visual/visual-widgets/space'
type Options = {
previewByPath: (path: string) => PreviewPath | null
@ -1199,6 +1203,18 @@ export const atomicDecorations = (options: Options) => {
return false
}
}
} else if (hasSpaceSubstitution(commandName)) {
if (shouldDecorate(state, nodeRef)) {
const replacement = createSpaceCommand(commandName)
if (replacement) {
decorations.push(
Decoration.replace({
widget: replacement,
}).range(nodeRef.from, nodeRef.to)
)
return false
}
}
}
}
}

View file

@ -288,6 +288,9 @@ const mainVisualTheme = EditorView.theme({
overflowWrap: 'break-word',
hyphens: 'auto',
},
'.ol-cm-space': {
display: 'inline-block',
},
'.ol-cm-environment-centered': {
'&.ol-cm-label-line, &.ol-cm-caption-line': {
textAlign: 'center',

View file

@ -0,0 +1,61 @@
import { WidgetType } from '@codemirror/view'
export class SpaceWidget extends WidgetType {
constructor(public width: string) {
super()
}
toDOM() {
const element = document.createElement('span')
element.classList.add('ol-cm-space')
element.style.width = this.width
return element
}
eq(widget: SpaceWidget) {
return widget.width === this.width
}
updateDOM(element: HTMLElement): boolean {
element.style.width = this.width
return true
}
ignoreEvent(event: Event) {
return event.type !== 'mousedown' && event.type !== 'mouseup'
}
}
// https://tex.stackexchange.com/a/74354
export const COMMAND_WIDTHS = new Map([
// thin space
['\\thinspace', 'calc(3em / 18)'],
['\\,', 'calc(3em / 18)'],
// negative thin space
['\\negthinspace', 'calc(-3em / 18)'],
['\\!', 'calc(-3em / 18)'],
// medium space
['\\medspace', 'calc(4em / 18)'],
['\\:', 'calc(4em / 18)'],
['\\>', 'calc(4em / 18)'],
// thick space
['\\thickspace', 'calc(5em / 18)'],
['\\;', 'calc(5em / 18)'],
// negative thick space
['\\negthickspace', 'calc(-5em / 18)'],
// en, em and 2xem spaces
['\\enspace', '0.5em'],
['\\quad', '1em'],
['\\qquad', '2em'],
])
export function createSpaceCommand(command: string): SpaceWidget | undefined {
const width = COMMAND_WIDTHS.get(command)
if (width !== undefined) {
return new SpaceWidget(width)
}
}
export function hasSpaceSubstitution(command: string): boolean {
return COMMAND_WIDTHS.has(command)
}

View file

@ -642,6 +642,22 @@ describe('<CodeMirrorEditor/> in Visual mode', function () {
cy.get('@second-line').click()
cy.get('@first-line').should('have.text', 'Test ↩ test')
})
it('decorates spacing commands', function () {
cy.get('@first-line').type('\\thinspace')
cy.get('@second-line').click()
cy.get('@first-line')
.find('.ol-cm-space')
.should('have.attr', 'style', 'width: calc(0.166667em);')
})
it('decorates spacing symbols', function () {
cy.get('@first-line').type('\\,')
cy.get('@second-line').click()
cy.get('@first-line')
.find('.ol-cm-space')
.should('have.attr', 'style', 'width: calc(0.166667em);')
})
})
describe('decorates theorems', function () {