mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-18 02:17:52 +00:00
[cm6] Add LineBreak to LaTeX grammar, highlight and decorate (#13742)
GitOrigin-RevId: 64c54676e0284b7187678eedcc5096b1aa284cc0
This commit is contained in:
parent
ea9a9fbe1c
commit
f8f56cea89
8 changed files with 59 additions and 12 deletions
|
@ -57,6 +57,7 @@ import { getListItems } from '../toolbar/lists'
|
|||
import { TildeWidget } from './visual-widgets/tilde'
|
||||
import { BeginTheoremWidget } from './visual-widgets/begin-theorem'
|
||||
import { parseTheoremArguments } from '../../utils/tree-operations/theorems'
|
||||
import { IndicatorWidget } from './visual-widgets/indicator'
|
||||
|
||||
type Options = {
|
||||
fileTreeManager: {
|
||||
|
@ -730,6 +731,13 @@ export const atomicDecorations = (options: Options) => {
|
|||
}).range(nodeRef.from, nodeRef.to)
|
||||
)
|
||||
}
|
||||
} else if (nodeRef.type.is('LineBreakCtrlSym')) {
|
||||
// line break
|
||||
decorations.push(
|
||||
Decoration.replace({
|
||||
widget: new IndicatorWidget('\u21A9'),
|
||||
}).range(nodeRef.from, nodeRef.to)
|
||||
)
|
||||
} else if (nodeRef.type.is('Caption')) {
|
||||
if (shouldDecorate(state, nodeRef)) {
|
||||
// a caption
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
import { EditorState } from '@codemirror/state'
|
||||
import { SyntaxNode, SyntaxNodeRef } from '@lezer/common'
|
||||
import { SyntaxNode } from '@lezer/common'
|
||||
import { isUnknownCommandWithName } from '../../../utils/tree-query'
|
||||
|
||||
function isNewline(node: SyntaxNodeRef, state: EditorState) {
|
||||
if (!node.type.is('CtrlSym')) {
|
||||
return false
|
||||
}
|
||||
const command = state.sliceDoc(node.from, node.to)
|
||||
return command === '\\\\'
|
||||
}
|
||||
import { LineBreakCtrlSym } from '../../../lezer-latex/latex.terms.mjs'
|
||||
|
||||
/**
|
||||
* Does a small amount of typesetting of LaTeX content into a DOM element.
|
||||
|
@ -78,7 +71,7 @@ export function typesetNodeIntoElement(
|
|||
// ignoring these commands
|
||||
from = childNode.to
|
||||
return false
|
||||
} else if (isNewline(childNode, state)) {
|
||||
} else if (childNode.type.is(LineBreakCtrlSym)) {
|
||||
ancestor().appendChild(document.createElement('br'))
|
||||
from = childNode.to
|
||||
}
|
||||
|
|
|
@ -104,6 +104,9 @@ export const visualTheme = EditorView.theme({
|
|||
filter: 'grayscale(1)',
|
||||
marginRight: '2px',
|
||||
},
|
||||
'.ol-cm-indicator': {
|
||||
color: 'rgba(125, 125, 125, 0.5)',
|
||||
},
|
||||
'.ol-cm-begin': {
|
||||
fontFamily: 'var(--source-font-family)',
|
||||
minHeight: '1em',
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { WidgetType } from '@codemirror/view'
|
||||
|
||||
export class IndicatorWidget extends WidgetType {
|
||||
constructor(public content: string) {
|
||||
super()
|
||||
}
|
||||
|
||||
toDOM() {
|
||||
const element = document.createElement('span')
|
||||
element.classList.add('ol-cm-indicator')
|
||||
element.textContent = this.content
|
||||
return element
|
||||
}
|
||||
|
||||
eq(widget: IndicatorWidget) {
|
||||
return widget.content === this.content
|
||||
}
|
||||
|
||||
updateDOM(element: HTMLElement): boolean {
|
||||
element.textContent = this.content
|
||||
return true
|
||||
}
|
||||
|
||||
ignoreEvent(event: Event) {
|
||||
return event.type !== 'mousedown' && event.type !== 'mouseup'
|
||||
}
|
||||
}
|
|
@ -167,6 +167,7 @@ export const LaTeXLanguage = LRLanguage.define({
|
|||
DoubleDollar: t.keyword,
|
||||
Tilde: t.keyword,
|
||||
Ampersand: t.keyword,
|
||||
LineBreakCtrlSym: t.keyword,
|
||||
Comment: t.comment,
|
||||
'UsePackage/OptionalArgument/ShortOptionalArg/Normal': t.attributeValue,
|
||||
'UsePackage/ShortTextArgument/ShortArg/Normal': t.tagName,
|
||||
|
|
|
@ -107,7 +107,8 @@
|
|||
OpenParenCtrlSym,
|
||||
CloseParenCtrlSym,
|
||||
OpenBracketCtrlSym,
|
||||
CloseBracketCtrlSym
|
||||
CloseBracketCtrlSym,
|
||||
LineBreakCtrlSym
|
||||
}
|
||||
|
||||
@tokens {
|
||||
|
@ -344,6 +345,11 @@ UnknownCommand {
|
|||
Command {
|
||||
KnownCommand
|
||||
| UnknownCommand
|
||||
| KnownCtrlSym
|
||||
}
|
||||
|
||||
KnownCtrlSym {
|
||||
LineBreakCtrlSym
|
||||
}
|
||||
|
||||
textBase {
|
||||
|
@ -464,6 +470,7 @@ DefinitionFragment {
|
|||
| CloseParenCtrlSym
|
||||
| OpenBracketCtrlSym
|
||||
| CloseBracketCtrlSym
|
||||
| KnownCtrlSym
|
||||
| BlankLine
|
||||
| NewLine
|
||||
| Normal
|
||||
|
@ -660,7 +667,7 @@ MathTextCommand {
|
|||
|
||||
MathCommand { CtrlSeq }
|
||||
|
||||
MathCtrlSym { CtrlSym }
|
||||
MathCtrlSym { CtrlSym | KnownCtrlSym }
|
||||
|
||||
MathGroup {
|
||||
OpenBrace Math? CloseBrace
|
||||
|
|
|
@ -49,6 +49,7 @@ import {
|
|||
CloseParenCtrlSym,
|
||||
OpenBracketCtrlSym,
|
||||
CloseBracketCtrlSym,
|
||||
LineBreakCtrlSym,
|
||||
// Sectioning commands
|
||||
BookCtrlSeq,
|
||||
PartCtrlSeq,
|
||||
|
@ -748,6 +749,7 @@ const otherKnownCtrlSyms = {
|
|||
'\\)': CloseParenCtrlSym,
|
||||
'\\[': OpenBracketCtrlSym,
|
||||
'\\]': CloseBracketCtrlSym,
|
||||
'\\\\': LineBreakCtrlSym,
|
||||
}
|
||||
|
||||
export const specializeCtrlSym = (name, terms) => {
|
||||
|
|
|
@ -594,6 +594,12 @@ describe('<CodeMirrorEditor/> in Visual mode', function () {
|
|||
cy.get('@first-line').type('Test\\~test')
|
||||
cy.get('@first-line').should('have.text', 'Test~test')
|
||||
})
|
||||
|
||||
it('decorates line breaks', function () {
|
||||
cy.get('@first-line').type('Test \\\\ test')
|
||||
cy.get('@second-line').click()
|
||||
cy.get('@first-line').should('have.text', 'Test ↩ test')
|
||||
})
|
||||
})
|
||||
|
||||
describe('decorates theorems', function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue