Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/text-editor/src/plugins/table/ |
Upload File : |
/* eslint-disable @bitrix24/bitrix24-rules/no-native-dom-methods */ import { Type, Text, Loc } from 'main.core'; import type { BaseEvent } from 'main.core.events'; import type { BBCodeElementNode } from 'ui.bbcode.model'; import { $normalizeTextNodes, shouldWrapInParagraph, type BBCodeExportConversion, type BBCodeConversion, type BBCodeConversionFn, type BBCodeExportOutput, type BBCodeImportConversion, } from '../../bbcode'; import { DIALOG_VISIBILITY_COMMAND, HIDE_DIALOG_COMMAND } from '../../commands'; import BasePlugin from '../base-plugin'; import Button from '../../toolbar/button'; import { $isTextNode, createCommand, $getNodeByKey, $createParagraphNode, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_EDITOR, type NodeKey, type LexicalCommand, type LexicalNode, type ElementNode, } from 'ui.lexical.core'; import { TableNode, TableCellNode, TableRowNode, $isTableNode, $createTableNode, $createTableCellNode, $createTableRowNode, $createTableNodeWithDimensions, applyTableHandlers, TableCellHeaderStates, INSERT_TABLE_COMMAND, TableSelection, } from 'ui.lexical.table'; import { $insertNodeToNearestRoot } from 'ui.lexical.utils'; import { type TextEditor } from '../../text-editor'; import type { SchemeValidationOptions } from '../../types/scheme-validation-options'; import TableDialog from './table-dialog'; export const INSERT_TABLE_DIALOG_COMMAND: LexicalCommand = createCommand('INSERT_TABLE_DIALOG_COMMAND'); export class TablePlugin extends BasePlugin { #tableDialog: TableDialog = null; constructor(editor: TextEditor) { super(editor); this.#registerCommands(); this.#registerListeners(); this.#registerComponents(); } static getName(): string { return 'Table'; } static getNodes(editor: TextEditor): Array<Class<LexicalNode>> { return [ TableNode, TableCellNode, TableRowNode, ]; } importBBCode(): BBCodeImportConversion { return { table: (): BBCodeConversion => ({ conversion: (node: BBCodeElementNode): BBCodeConversionFn | null => { return { node: $createTableNode(), }; }, priority: 0, }), tr: (): BBCodeConversion => ({ conversion: (node: BBCodeElementNode): BBCodeConversionFn | null => { return { node: $createTableRowNode(), }; }, priority: 0, }), td: (): BBCodeConversion => ({ conversion: (node: BBCodeElementNode): BBCodeConversionFn | null => { return { node: $createTableCellNode(), after: (childLexicalNodes: Array<LexicalNode>): Array<LexicalNode> => { return $normalizeTextNodes(childLexicalNodes); }, }; }, priority: 0, }), th: (): BBCodeConversion => ({ conversion: (node: BBCodeElementNode): BBCodeConversionFn | null => { return { node: $createTableCellNode(TableCellHeaderStates.ROW), after: (childLexicalNodes: Array<LexicalNode>): Array<LexicalNode> => { return $normalizeTextNodes(childLexicalNodes); }, }; }, priority: 0, }), }; } exportBBCode(): BBCodeExportConversion { return { table: (): BBCodeExportOutput => { const scheme = this.getEditor().getBBCodeScheme(); return { node: scheme.createElement({ name: 'table' }), }; }, tablerow: (): BBCodeExportOutput => { const scheme = this.getEditor().getBBCodeScheme(); return { node: scheme.createElement({ name: 'tr' }), }; }, tablecell: (node: TableCellNode): BBCodeExportOutput => { const scheme = this.getEditor().getBBCodeScheme(); return { node: scheme.createElement({ name: node.hasHeader() ? 'th' : 'td' }), }; }, }; } validateScheme(): SchemeValidationOptions | null { return { nodes: [ { nodeClass: TableNode, validate: ((tableNode: TableNode) => { if (tableNode.getChildrenSize() === 0) { tableNode.remove(); return true; } return false; }), }, { nodeClass: TableCellNode, validate: ((tableCellNode: TableCellNode) => { tableCellNode.getChildren().forEach((child: LexicalNode | ElementNode) => { if (shouldWrapInParagraph(child)) { const paragraph = $createParagraphNode(); child.replace(paragraph); paragraph.append(child); } }); return false; }), }, ], bbcodeMap: { table: 'table', tablerow: 'tr', tablecell: 'td', }, }; } #registerComponents(): void { this.getEditor().getComponentRegistry().register('table', (): Button => { const button: Button = new Button(); button.setContent('<span class="ui-icon-set --table-editor"></span>'); button.setTooltip(Loc.getMessage('TEXT_EDITOR_BTN_TABLE')); button.subscribe('onClick', (): void => { this.getEditor().dispatchCommand(INSERT_TABLE_DIALOG_COMMAND, { targetNode: button.getContainer(), }); }); return button; }); } #registerCommands(): void { this.cleanUpRegister( this.getEditor().registerCommand( INSERT_TABLE_COMMAND, ({ columns, rows }) => { const rowCount = Math.max(1, Text.toNumber(rows)); const columnCount = Math.max(1, Text.toNumber(columns)); const tableNode = $createTableNodeWithDimensions(rowCount, columnCount, false); $insertNodeToNearestRoot(tableNode); const firstDescendant: LexicalNode = tableNode.getFirstDescendant(); if ($isTextNode(firstDescendant)) { firstDescendant.select(); } return true; }, COMMAND_PRIORITY_EDITOR, ), this.getEditor().registerCommand( INSERT_TABLE_DIALOG_COMMAND, (payload): boolean => { if (!Type.isPlainObject(payload) || !Type.isElementNode(payload.targetNode)) { return false; } if (this.#tableDialog !== null) { if (this.#tableDialog.getTargetNode() === payload.targetNode) { this.#tableDialog.show(); return true; } this.#tableDialog.destroy(); } this.#tableDialog = new TableDialog({ targetNode: payload.targetNode, events: { onSelect: (event: BaseEvent) => { this.getEditor().dispatchCommand(INSERT_TABLE_COMMAND, event.getData()); this.#tableDialog.hide(); }, onDestroy: () => { this.#tableDialog = null; }, }, }); this.#tableDialog.show(); return true; }, COMMAND_PRIORITY_LOW, ), this.getEditor().registerCommand( HIDE_DIALOG_COMMAND, (): boolean => { if (this.#tableDialog !== null) { this.#tableDialog.hide(); } return false; }, COMMAND_PRIORITY_LOW, ), this.getEditor().registerCommand( DIALOG_VISIBILITY_COMMAND, (): boolean => { return this.#tableDialog !== null && this.#tableDialog.isShown(); }, COMMAND_PRIORITY_LOW, ), ); } #registerListeners(): void { const tableSelections: Map<NodeKey, TableSelection> = new Map(); const initializeTableNode = (tableNode: TableNode) => { const nodeKey = tableNode.getKey(); const tableElement = this.getEditor().getElementByKey(nodeKey); if (tableElement && !tableSelections.has(nodeKey)) { const tableSelection = applyTableHandlers( tableNode, tableElement, this.getLexicalEditor(), true, ); tableSelections.set(nodeKey, tableSelection); } }; this.cleanUpRegister( this.getEditor().registerMutationListener( TableNode, (nodeMutations) => { for (const [nodeKey, mutation] of nodeMutations) { if (mutation === 'created') { this.getEditor().getEditorState().read(() => { const tableNode = $getNodeByKey(nodeKey); if ($isTableNode(tableNode)) { initializeTableNode(tableNode); } }); } else if (mutation === 'destroyed') { const tableSelection = tableSelections.get(nodeKey); if (tableSelection !== undefined) { tableSelection.removeListeners(); tableSelections.delete(nodeKey); } } } }, ), ); } destroy(): void { super.destroy(); if (this.#tableDialog !== null) { this.#tableDialog.destroy(); } } }