403Webshell
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/image/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/text-editor/src/plugins/image/image-plugin.js
import { Event, Loc, Type } from 'main.core';
import type { BBCodeElementNode } from 'ui.bbcode.model';

import {
	type BBCodeConversion,
	type BBCodeImportConversion,
	type BBCodeExportConversion,
	type BBCodeExportOutput,
	type BBCodeConversionFn,
} from '../../bbcode';

import { DIALOG_VISIBILITY_COMMAND, HIDE_DIALOG_COMMAND } from '../../commands';
import { $adjustDialogPosition } from '../../helpers/adjust-dialog-position';
import {
	createCommand,
	$createTextNode,
	$insertNodes,
	$isRootOrShadowRoot,
	$createParagraphNode,
	$getSelection,
	$setSelection,
	$isRangeSelection,
	COMMAND_PRIORITY_EDITOR,
	COMMAND_PRIORITY_LOW,
	type LexicalNode,
	type LexicalCommand,
	type RangeSelection,
} from 'ui.lexical.core';

import { $wrapNodeInElement, mergeRegister } from 'ui.lexical.utils';
import { registerDraggableNode } from '../../helpers/register-draggable-node';
import { validateImageUrl } from '../../helpers/validate-image-url';

import Button from '../../toolbar/button';
import BasePlugin from '../base-plugin';
import ImageDialog from './image-dialog';
import { $createImageNode, ImageNode, type ImagePayload } from './image-node';

import { type TextEditor } from '../../text-editor';
import type { SchemeValidationOptions } from '../../types/scheme-validation-options';

import './image-plugin.css';

export type InsertImagePayload = Readonly<ImagePayload>;
export const INSERT_IMAGE_COMMAND: LexicalCommand<InsertImagePayload> = createCommand('INSERT_IMAGE_COMMAND');
export const INSERT_IMAGE_DIALOG_COMMAND: LexicalCommand = createCommand('INSERT_IMAGE_DIALOG_COMMAND');

export class ImagePlugin extends BasePlugin
{
	#imageDialog: ImageDialog = null;
	#onEditorScroll: Function = this.#handleEditorScroll.bind(this);
	#lastSelection: RangeSelection = null;

	constructor(editor: TextEditor)
	{
		super(editor);

		this.cleanUpRegister(
			this.#registerCommands(),
			registerDraggableNode(
				this.getEditor(),
				ImageNode,
				(data) => {
					this.getEditor().dispatchCommand(INSERT_IMAGE_COMMAND, data);
				},
			),
		);

		this.#registerComponents();
	}

	static getName(): string
	{
		return 'Image';
	}

	static getNodes(editor: TextEditor): Array<Class<LexicalNode>>
	{
		return [ImageNode];
	}

	importBBCode(): BBCodeImportConversion
	{
		return {
			img: (): BBCodeConversion => ({
				conversion: (node: BBCodeElementNode): BBCodeConversionFn | null => {
					// [img]{url}[/img]
					// [img width={width} height={height}]{url}[/img]
					const src = node.getContent().trim();
					const width = Number(node.getAttribute('width'));
					const height = Number(node.getAttribute('height'));

					if (validateImageUrl(src))
					{
						return {
							node: $createImageNode({ src, width, height }),
						};
					}

					return {
						node: $createTextNode(node.toString()),
					};
				},
				priority: 0,
			}),
		};
	}

	exportBBCode(): BBCodeExportConversion
	{
		return {
			image: (lexicalNode: ImageNode): BBCodeExportOutput => {
				const attributes = {};
				const width = lexicalNode.getWidth();
				const height = lexicalNode.getHeight();
				if (Type.isNumber(width) && Type.isNumber(height))
				{
					attributes.width = width;
					attributes.height = height;
				}

				const scheme = this.getEditor().getBBCodeScheme();

				return {
					node: scheme.createElement({
						name: 'img',
						inline: true,
						attributes,
					}),
					after: (elementNode: BBCodeElementNode) => {
						elementNode.setChildren([scheme.createText(lexicalNode.getSrc())]);
					},
				};
			},
		};
	}

	validateScheme(): SchemeValidationOptions | null
	{
		return {
			nodes: [{
				nodeClass: ImageNode,
			}],
			bbcodeMap: {
				image: 'img',
			},
		};
	}

	#registerCommands(): () => void
	{
		return mergeRegister(
			this.getEditor().registerCommand(
				INSERT_IMAGE_COMMAND,
				(payload: InsertImagePayload) => {
					if (!validateImageUrl(payload?.src))
					{
						return false;
					}

					const imageNode = $createImageNode(payload);
					$insertNodes([imageNode]);
					if ($isRootOrShadowRoot(imageNode.getParentOrThrow()))
					{
						$wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
					}

					return true;
				},
				COMMAND_PRIORITY_EDITOR,
			),
			this.getEditor().registerCommand(
				INSERT_IMAGE_DIALOG_COMMAND,
				(): boolean => {
					const selection: RangeSelection = $getSelection();
					if (!$isRangeSelection(selection))
					{
						return false;
					}

					this.#lastSelection = selection.clone();
					if (this.#imageDialog !== null)
					{
						this.#imageDialog.destroy();
					}

					this.getEditor().dispatchCommand(HIDE_DIALOG_COMMAND);

					this.#imageDialog = new ImageDialog({
						// for an embedded popup: document.body -> this.getEditor().getScrollerContainer()
						targetContainer: document.body,
						events: {
							onSave: () => {
								const url = this.#imageDialog.getImageUrl();
								if (!Type.isStringFilled(url))
								{
									this.#imageDialog.hide();

									return;
								}

								this.getEditor().dispatchCommand(INSERT_IMAGE_COMMAND, { src: url });

								this.#imageDialog.hide();
							},
							onCancel: () => {
								this.#imageDialog.hide();
							},
							onClose: () => {
								this.#handleDialogDestroy();
							},
							onDestroy: () => {
								this.#handleDialogDestroy();
							},
							onShow: () => {
								if ($adjustDialogPosition(this.#imageDialog.getPopup(), this.getEditor()))
								{
									Event.bind(this.getEditor().getScrollerContainer(), 'scroll', this.#onEditorScroll);
									this.getEditor().highlightSelection();
								}
							},
							onAfterShow: () => {
								this.#imageDialog.getUrlTextBox().focus();
							},
						},
					});

					this.#imageDialog.show();

					return true;
				},
				COMMAND_PRIORITY_LOW,
			),
			this.getEditor().registerCommand(
				HIDE_DIALOG_COMMAND,
				(): boolean => {
					if (this.#imageDialog !== null)
					{
						this.#imageDialog.destroy();
					}

					return false;
				},
				COMMAND_PRIORITY_LOW,
			),
			this.getEditor().registerCommand(
				DIALOG_VISIBILITY_COMMAND,
				(): boolean => {
					return this.#imageDialog !== null && this.#imageDialog.isShown();
				},
				COMMAND_PRIORITY_LOW,
			),
		);
	}

	#restoreSelection(): boolean
	{
		const selection = $getSelection();
		if (!$isRangeSelection(selection) && this.#lastSelection !== null)
		{
			$setSelection(this.#lastSelection);
			this.#lastSelection = null;

			return true;
		}

		return false;
	}

	#handleDialogDestroy(): void
	{
		this.#imageDialog = null;
		Event.unbind(this.getEditor().getScrollerContainer(), 'scroll', this.#onEditorScroll);
		this.getEditor().resetHighlightSelection();

		this.getEditor().update(() => {
			if (!this.#restoreSelection())
			{
				this.getEditor().focus();
			}
		});
	}

	#handleEditorScroll(): void
	{
		this.getEditor().update(() => {
			$adjustDialogPosition(this.#imageDialog.getPopup(), this.getEditor());
		});
	}

	#registerComponents(): void
	{
		this.getEditor().getComponentRegistry().register('image', (): Button => {
			const button: Button = new Button();
			button.setContent('<span class="ui-icon-set --incert-image"></span>');
			button.setTooltip(Loc.getMessage('TEXT_EDITOR_BTN_IMAGE'));
			button.disableInsideUnformatted();
			button.subscribe('onClick', (): void => {
				if (this.#imageDialog !== null && this.#imageDialog.isShown())
				{
					return;
				}

				this.getEditor().focus(() => {
					this.getEditor().dispatchCommand(INSERT_IMAGE_DIALOG_COMMAND);
				});
			});

			return button;
		});
	}

	destroy(): void
	{
		super.destroy();

		if (this.#imageDialog !== null)
		{
			this.#imageDialog.destroy();
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit