diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/utils.ts b/services/web/frontend/js/features/source-editor/components/table-generator/utils.ts
index 86872c987e..7842a80586 100644
--- a/services/web/frontend/js/features/source-editor/components/table-generator/utils.ts
+++ b/services/web/frontend/js/features/source-editor/components/table-generator/utils.ts
@@ -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 },
diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts b/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts
index 9e520394f1..5bd75cf5f2 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts
@@ -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(
- tabularNode,
- state.doc.sliceString(
- (tableNode ?? tabularNode).from,
- (tableNode ?? tabularNode).to
- ),
- tableNode,
- directChild,
- state
- )
- if (tabularWidget.isValid()) {
+ 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: tabularWidget,
+ widget: new TabularWidget(
+ parsedTableData,
+ tabularNode,
+ state.doc.sliceString(
+ (tableNode ?? tabularNode).from,
+ (tableNode ?? tabularNode).to
+ ),
+ tableNode,
+ directChild
+ ),
block: true,
}).range(nodeRef.from, nodeRef.to)
)
diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx
index 7ec606570b..ae286cf025 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx
@@ -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(
- ,
- this.element
- )
- }
- return this.element
+ ReactDOM.render(
+ ,
+ 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(
,
- this.element
+ element
)
return true
}
- destroy() {
- if (this.element) {
- ReactDOM.unmountComponentAtNode(this.element)
- }
+ destroy(element: HTMLElement) {
+ ReactDOM.unmountComponentAtNode(element)
}
}