mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Move responsibility for parsing and validating table data out of the tabular widget (#15152)
GitOrigin-RevId: bba823ca036501a527f08746cffb155641d3becf
This commit is contained in:
parent
621bae03ca
commit
4f5ca6624e
3 changed files with 72 additions and 81 deletions
|
@ -451,6 +451,27 @@ export function generateTable(
|
|||
}
|
||||
}
|
||||
|
||||
export const validateParsedTable = (parseResult: ParsedTableData) => {
|
||||
for (const row of parseResult.table.rows) {
|
||||
const rowLength = row.cells.reduce(
|
||||
(acc, cell) => acc + (cell.multiColumn?.columnSpan ?? 1),
|
||||
0
|
||||
)
|
||||
for (const cell of row.cells) {
|
||||
if (
|
||||
cell.multiColumn?.columns.specification &&
|
||||
cell.multiColumn.columns.specification.length !== 1
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (rowLength !== parseResult.table.columns.length) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export function parseTableEnvironment(tableNode: SyntaxNode) {
|
||||
const tableEnvironment: TableEnvironmentData = {
|
||||
table: { from: tableNode.from, to: tableNode.to },
|
||||
|
|
|
@ -67,6 +67,12 @@ import { TableRenderingErrorWidget } from './visual-widgets/table-rendering-erro
|
|||
import { GraphicsWidget } from './visual-widgets/graphics'
|
||||
import { InlineGraphicsWidget } from './visual-widgets/inline-graphics'
|
||||
import { PreviewPath } from '../../../../../../types/preview-path'
|
||||
import {
|
||||
generateTable,
|
||||
ParsedTableData,
|
||||
validateParsedTable,
|
||||
} from '../../components/table-generator/utils'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
type Options = {
|
||||
previewByPath: (path: string) => PreviewPath | null
|
||||
|
@ -324,21 +330,29 @@ export const atomicDecorations = (options: Options) => {
|
|||
tabularNode.parent,
|
||||
tableNode
|
||||
)
|
||||
const tabularWidget = new TabularWidget(
|
||||
|
||||
let parsedTableData: ParsedTableData | null = null
|
||||
let validTable = false
|
||||
try {
|
||||
parsedTableData = generateTable(tabularNode, state)
|
||||
validTable = validateParsedTable(parsedTableData)
|
||||
} catch (e) {
|
||||
debugConsole.error(e)
|
||||
}
|
||||
|
||||
if (parsedTableData && validTable) {
|
||||
decorations.push(
|
||||
Decoration.replace({
|
||||
widget: new TabularWidget(
|
||||
parsedTableData,
|
||||
tabularNode,
|
||||
state.doc.sliceString(
|
||||
(tableNode ?? tabularNode).from,
|
||||
(tableNode ?? tabularNode).to
|
||||
),
|
||||
tableNode,
|
||||
directChild,
|
||||
state
|
||||
)
|
||||
|
||||
if (tabularWidget.isValid()) {
|
||||
decorations.push(
|
||||
Decoration.replace({
|
||||
widget: tabularWidget,
|
||||
directChild
|
||||
),
|
||||
block: true,
|
||||
}).range(nodeRef.from, nodeRef.to)
|
||||
)
|
||||
|
|
|
@ -1,77 +1,37 @@
|
|||
import { EditorView, WidgetType } from '@codemirror/view'
|
||||
import { EditorState } from '@codemirror/state'
|
||||
import { SyntaxNode } from '@lezer/common'
|
||||
import * as ReactDOM from 'react-dom'
|
||||
import { Tabular } from '../../../components/table-generator/tabular'
|
||||
import {
|
||||
ParsedTableData,
|
||||
generateTable,
|
||||
} from '../../../components/table-generator/utils'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { ParsedTableData } from '../../../components/table-generator/utils'
|
||||
|
||||
export class TabularWidget extends WidgetType {
|
||||
private element: HTMLElement | undefined
|
||||
private readonly parseResult: ParsedTableData | null = null
|
||||
|
||||
constructor(
|
||||
private parsedTableData: ParsedTableData,
|
||||
private tabularNode: SyntaxNode,
|
||||
private content: string,
|
||||
private tableNode: SyntaxNode | null,
|
||||
private isDirectChildOfTableEnvironment: boolean,
|
||||
state: EditorState
|
||||
private isDirectChildOfTableEnvironment: boolean
|
||||
) {
|
||||
super()
|
||||
try {
|
||||
this.parseResult = generateTable(tabularNode, state)
|
||||
} catch (e) {
|
||||
debugConsole.error(e)
|
||||
this.parseResult = null
|
||||
}
|
||||
}
|
||||
|
||||
isValid() {
|
||||
if (!this.parseResult) {
|
||||
return false
|
||||
}
|
||||
for (const row of this.parseResult.table.rows) {
|
||||
const rowLength = row.cells.reduce(
|
||||
(acc, cell) => acc + (cell.multiColumn?.columnSpan ?? 1),
|
||||
0
|
||||
)
|
||||
for (const cell of row.cells) {
|
||||
if (
|
||||
cell.multiColumn?.columns.specification &&
|
||||
cell.multiColumn.columns.specification.length !== 1
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (rowLength !== this.parseResult.table.columns.length) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
toDOM(view: EditorView) {
|
||||
this.element = document.createElement('div')
|
||||
this.element.classList.add('ol-cm-tabular')
|
||||
const element = document.createElement('div')
|
||||
element.classList.add('ol-cm-tabular')
|
||||
if (this.tableNode) {
|
||||
this.element.classList.add('ol-cm-environment-table')
|
||||
element.classList.add('ol-cm-environment-table')
|
||||
}
|
||||
if (this.parseResult) {
|
||||
ReactDOM.render(
|
||||
<Tabular
|
||||
view={view}
|
||||
tabularNode={this.tabularNode}
|
||||
parsedTableData={this.parseResult}
|
||||
parsedTableData={this.parsedTableData}
|
||||
tableNode={this.tableNode}
|
||||
directTableChild={this.isDirectChildOfTableEnvironment}
|
||||
/>,
|
||||
this.element
|
||||
element
|
||||
)
|
||||
}
|
||||
return this.element
|
||||
return element
|
||||
}
|
||||
|
||||
eq(widget: TabularWidget): boolean {
|
||||
|
@ -79,31 +39,27 @@ export class TabularWidget extends WidgetType {
|
|||
this.tabularNode.from === widget.tabularNode.from &&
|
||||
this.tableNode?.from === widget.tableNode?.from &&
|
||||
this.tableNode?.to === widget.tableNode?.to &&
|
||||
this.content === widget.content
|
||||
this.content === widget.content &&
|
||||
this.isDirectChildOfTableEnvironment ===
|
||||
widget.isDirectChildOfTableEnvironment
|
||||
)
|
||||
}
|
||||
|
||||
updateDOM(dom: HTMLElement, view: EditorView): boolean {
|
||||
if (!this.parseResult) {
|
||||
return false
|
||||
}
|
||||
this.element = dom
|
||||
updateDOM(element: HTMLElement, view: EditorView): boolean {
|
||||
ReactDOM.render(
|
||||
<Tabular
|
||||
view={view}
|
||||
tabularNode={this.tabularNode}
|
||||
parsedTableData={this.parseResult}
|
||||
parsedTableData={this.parsedTableData}
|
||||
tableNode={this.tableNode}
|
||||
directTableChild={this.isDirectChildOfTableEnvironment}
|
||||
/>,
|
||||
this.element
|
||||
element
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.element) {
|
||||
ReactDOM.unmountComponentAtNode(this.element)
|
||||
}
|
||||
destroy(element: HTMLElement) {
|
||||
ReactDOM.unmountComponentAtNode(element)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue