| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- import {
- Decoration,
- DecorationSet,
- EditorView,
- ViewPlugin,
- ViewUpdate,
- WidgetType,
- } from '@codemirror/view'
- import browser from './browser'
- class EmptyLineWidget extends WidgetType {
- toDOM(view: EditorView): HTMLElement {
- const element = document.createElement('span')
- element.className = 'ol-cm-filler'
- return element
- }
- eq(widget: EmptyLineWidget) {
- return true
- }
- }
- /**
- * A custom extension which adds a widget decoration at the start of each empty line in the viewport,
- * so that the line is highlighted when part of tracked changes.
- */
- export const emptyLineFiller = () => {
- if (browser.ios) {
- // disable on iOS as it breaks Backspace across empty lines
- // https://github.com/overleaf/internal/issues/12192
- return []
- }
- return [
- ViewPlugin.fromClass(
- class {
- decorations: DecorationSet
- constructor(view: EditorView) {
- this.decorations = this.buildDecorations(view)
- }
- update(update: ViewUpdate) {
- if (update.docChanged || update.viewportChanged)
- this.decorations = this.buildDecorations(update.view)
- }
- buildDecorations(view: EditorView) {
- const decorations = []
- const { from, to } = view.viewport
- const { doc } = view.state
- let pos = from
- while (pos <= to) {
- const line = doc.lineAt(pos)
- if (line.length === 0) {
- const decoration = Decoration.widget({
- widget: new EmptyLineWidget(),
- side: 1,
- })
- decorations.push(decoration.range(pos))
- }
- pos = line.to + 1
- }
- return Decoration.set(decorations)
- }
- },
- {
- decorations(value) {
- return value.decorations
- },
- }
- ),
- EditorView.baseTheme({
- '.ol-cm-filler': {
- padding: '0 2px',
- },
- }),
- ]
- }
|