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/bbcode/model/src/scheme/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/bbcode/model/src/scheme/bbcode-scheme.js
import { Type } from 'main.core';
import { BBCodeEncoder } from 'ui.bbcode.encoder';
import { BBCodeTagScheme } from './node-schemes/tag-scheme';
import { BBCodeNode, type BBCodeNodeOptions } from '../nodes/node';
import { BBCodeRootNode, type RootNodeOptions } from '../nodes/root-node';
import { BBCodeFragmentNode, type FragmentNodeOptions } from '../nodes/fragment-node';
import { BBCodeElementNode, type BBCodeElementNodeOptions } from '../nodes/element-node';
import { BBCodeTextNode, type BBCodeTextNodeOptions } from '../nodes/text-node';
import { BBCodeNewLineNode } from '../nodes/new-line-node';
import { BBCodeTabNode } from '../nodes/tab-node';
import { BBCodeNodeScheme } from './node-schemes/node-scheme';
import type { BBCodeGroupName, BBCodeNodeName } from './node-schemes/node-scheme';

export type OutputTagCases = $Values<BBCodeScheme.Case>;

export type ParentChildMap = Map<
	BBCodeNodeName | BBCodeGroupName,
	{
		allowedChildren: Array<BBCodeNodeName | BBCodeGroupName>,
		allowedIn: Array<BBCodeNodeName | BBCodeGroupName>,
		aliases: Array<BBCodeNodeName | BBCodeGroupName>,
	},
>;

export type BBCodeSchemeOptions = {
	tagSchemes: Array<BBCodeTagScheme>,
	outputTagCase?: OutputTagCases,
	unresolvedNodesHoisting?: boolean,
	encoder?: BBCodeEncoder,
};

export class BBCodeScheme
{
	static Case: {[key: string]: string} = {
		LOWER: 'lower',
		UPPER: 'upper',
	};

	tagSchemes: Array<BBCodeTagScheme> = [];
	outputTagCase: OutputTagCases = BBCodeScheme.Case.LOWER;
	unresolvedNodesHoisting: boolean = true;
	encoder: BBCodeEncoder = new BBCodeEncoder();
	parentChildMap: ?ParentChildMap = null;

	static isNodeScheme(value: any): boolean
	{
		return value instanceof BBCodeNodeScheme;
	}

	static getTagName(node: string | BBCodeNode): string | null
	{
		if (Type.isString(node))
		{
			return node;
		}

		if (Type.isObject(node) && node instanceof BBCodeNode)
		{
			return node.getName();
		}

		return null;
	}

	constructor(options: BBCodeSchemeOptions = {})
	{
		if (!Type.isPlainObject(options))
		{
			throw new TypeError('options is not a object');
		}

		this.onTagSchemeChange = this.onTagSchemeChange.bind(this);

		this.setTagSchemes(options.tagSchemes);
		this.setOutputTagCase(options.outputTagCase);
		this.setUnresolvedNodesHoisting(options.unresolvedNodesHoisting);
		this.setEncoder(options.encoder);
	}

	onTagSchemeChange()
	{
		this.parentChildMap = null;
	}

	setTagSchemes(tagSchemes: Array<BBCodeTagScheme>)
	{
		if (Type.isArray(tagSchemes))
		{
			const invalidSchemeIndex: number = tagSchemes.findIndex((scheme: BBCodeTagScheme): boolean => {
				return !BBCodeScheme.isNodeScheme(scheme);
			});

			if (invalidSchemeIndex > -1)
			{
				throw new TypeError(`tagScheme #${invalidSchemeIndex} is not TagScheme instance`);
			}

			tagSchemes.forEach((tagScheme: BBCodeTagScheme) => {
				tagScheme.setOnChangeHandler(this.onTagSchemeChange);
			});

			this.tagSchemes = [...tagSchemes];
		}
	}

	setTagScheme(...tagSchemes: Array<BBCodeTagScheme>)
	{
		const invalidSchemeIndex: number = tagSchemes.findIndex((scheme: BBCodeTagScheme): boolean => {
			return !BBCodeScheme.isNodeScheme(scheme);
		});

		if (invalidSchemeIndex > -1)
		{
			throw new TypeError(`tagScheme #${invalidSchemeIndex} is not TagScheme instance`);
		}

		const newTagSchemesNames: Array<string> = tagSchemes.flatMap((scheme: BBCodeTagScheme) => {
			return scheme.getName();
		});

		const currentTagSchemes: Array<BBCodeTagScheme> = this.getTagSchemes();
		currentTagSchemes.forEach((scheme: BBCodeTagScheme) => {
			scheme.removeName(...newTagSchemesNames);
		});

		const filteredCurrentTagSchemes: Array<BBCodeTagScheme> = currentTagSchemes.filter((scheme: BBCodeTagScheme) => {
			return Type.isArrayFilled(scheme.getName());
		});

		this.setTagSchemes([
			...filteredCurrentTagSchemes,
			...tagSchemes,
		]);
	}

	getTagSchemes(): Array<BBCodeTagScheme>
	{
		return [...this.tagSchemes];
	}

	getTagScheme(node: string | BBCodeNode): ?BBCodeTagScheme
	{
		const tagName: ?string = BBCodeScheme.getTagName(node);
		if (Type.isString(tagName))
		{
			return this.getTagSchemes().find((scheme: BBCodeTagScheme): boolean => {
				return scheme.getName().includes(tagName.toLowerCase());
			});
		}

		return null;
	}

	setOutputTagCase(tagCase: $Values<BBCodeScheme.Case>)
	{
		if (!Type.isNil(tagCase))
		{
			const allowedCases = Object.values(BBCodeScheme.Case);
			if (allowedCases.includes(tagCase))
			{
				this.outputTagCase = tagCase;
			}
			else
			{
				throw new TypeError(`'${tagCase}' is not allowed`);
			}
		}
	}

	getOutputTagCase(): $Values<BBCodeScheme.Case>
	{
		return this.outputTagCase;
	}

	setUnresolvedNodesHoisting(value: boolean)
	{
		if (!Type.isNil(value))
		{
			if (Type.isBoolean(value))
			{
				this.unresolvedNodesHoisting = value;
			}
			else
			{
				throw new TypeError(`'${value}' is not allowed value`);
			}
		}
	}

	isAllowedUnresolvedNodesHoisting(): boolean
	{
		return this.unresolvedNodesHoisting;
	}

	setEncoder(encoder: BBCodeEncoder)
	{
		if (encoder instanceof BBCodeEncoder)
		{
			this.encoder = encoder;
		}
	}

	getEncoder(): BBCodeEncoder
	{
		return this.encoder;
	}

	getAllowedTags(): Array<string>
	{
		return this.getTagSchemes().flatMap((tagScheme: BBCodeTagScheme) => {
			return tagScheme.getName();
		});
	}

	isAllowedTag(node: string | BBCodeNode): boolean
	{
		const allowedTags: Array<string> = this.getAllowedTags();
		const tagName: ?string = BBCodeScheme.getTagName(node);

		return allowedTags.includes(String(tagName).toLowerCase());
	}

	isVoid(node: string | BBCodeNode): boolean
	{
		const tagScheme: ?BBCodeTagScheme = this.getTagScheme(node);
		if (tagScheme)
		{
			return tagScheme.isVoid();
		}

		return false;
	}

	isElement(node: BBCodeNode): boolean
	{
		return node && node.getType() === BBCodeNode.ELEMENT_NODE;
	}

	isRoot(node: BBCodeNode): boolean
	{
		return node && node.getName() === '#root';
	}

	isFragment(node: BBCodeNode): boolean
	{
		return node && node.getName() === '#fragment';
	}

	isAnyText(node: BBCodeNode): boolean
	{
		return node && node.getType() === BBCodeNode.TEXT_NODE;
	}

	isText(node: BBCodeNode): boolean
	{
		return node && node.getName() === '#text';
	}

	isNewLine(node: BBCodeNode): boolean
	{
		return node && node.getName() === '#linebreak';
	}

	isTab(node: BBCodeNode): boolean
	{
		return node && node.getName() === '#tab';
	}

	getParentChildMap(): ParentChildMap
	{
		if (Type.isNull(this.parentChildMap))
		{
			const tagSchemes: Array<BBCodeTagScheme> = this.getTagSchemes();
			const map = new Map();

			tagSchemes.forEach((tagScheme: BBCodeTagScheme) => {
				const groups: Array<BBCodeGroupName> = tagScheme.getGroup();
				const schemeNames: Array<string> = [
					...tagScheme.getName(),
					...groups,
					...(tagScheme.isVoid() ? ['#void'] : []),
				];

				const allowedChildren = tagScheme.getAllowedChildren();
				const allowedIn = tagScheme.getAllowedIn();

				schemeNames.forEach((name) => {
					if (!map.has(name))
					{
						map.set(
							name,
							{
								allowedChildren: new Set(),
								allowedIn: new Set(),
								aliases: new Set(),
							},
						);
					}

					const entry: {
						allowedChildren: Set,
						allowedIn: Set,
						aliases: Set,
					} = map.get(name);

					const newEntry = {
						allowedChildren: new Set([...entry.allowedChildren, ...allowedChildren]),
						allowedIn: new Set([...entry.allowedIn, ...allowedIn]),
						aliases: new Set([name, ...groups, ...(tagScheme.isVoid() ? ['#void'] : [])]),
					};

					map.set(name, newEntry);
				});
			});

			this.parentChildMap = map;
		}

		return this.parentChildMap;
	}

	isChildAllowed(parent: string | BBCodeNode, child: string | BBCodeNode): boolean
	{
		const parentName: ?string = BBCodeScheme.getTagName(parent);
		const childName: ?string = BBCodeScheme.getTagName(child);

		if (
			Type.isStringFilled(parentName)
			&& Type.isStringFilled(childName)
		)
		{
			if (parentName === '#fragment')
			{
				return true;
			}

			const parentChildMap = this.getParentChildMap();
			const parentMap = parentChildMap.get(parentName);
			const childMap = parentChildMap.get(childName);

			if (
				Type.isPlainObject(parentMap)
				&& Type.isPlainObject(childMap)
			)
			{
				return (
					(
						parentMap.allowedChildren.size === 0
						|| [...childMap.aliases].some((name) => {
							return parentMap.allowedChildren.has(name);
						})
					)
					&& (
						childMap.allowedIn.size === 0
						|| [...parentMap.aliases].some((name) => {
							return childMap.allowedIn.has(name);
						})
					)
				);
			}
		}

		return false;
	}

	createRoot(options: RootNodeOptions = {}): BBCodeRootNode
	{
		return new BBCodeRootNode({
			...options,
			scheme: this,
		});
	}

	createNode(options: BBCodeNodeOptions): BBCodeNode
	{
		if (!Type.isPlainObject(options))
		{
			throw new TypeError('options is not a object');
		}

		if (!Type.isStringFilled(options.name))
		{
			throw new TypeError('options.name is required');
		}

		if (!this.isAllowedTag(options.name))
		{
			throw new TypeError(`Scheme for "${options.name}" tag is not specified.`);
		}

		return new BBCodeNode({
			...options,
			scheme: this,
		});
	}

	createElement(options: BBCodeElementNodeOptions = {}): BBCodeElementNode
	{
		if (!Type.isPlainObject(options))
		{
			throw new TypeError('options is not a object');
		}

		if (!Type.isStringFilled(options.name))
		{
			throw new TypeError('options.name is required');
		}

		if (!this.isAllowedTag(options.name))
		{
			throw new TypeError(`Scheme for "${options.name}" tag is not specified.`);
		}

		return new BBCodeElementNode({
			...options,
			scheme: this,
		});
	}

	createText(options: BBCodeTextNodeOptions = {}): BBCodeTextNode
	{
		const preparedOptions = Type.isPlainObject(options) ? options : { content: options };

		return new BBCodeTextNode({
			...preparedOptions,
			scheme: this,
		});
	}

	createNewLine(options: BBCodeTextNodeOptions = {}): BBCodeNewLineNode
	{
		const preparedOptions = Type.isPlainObject(options) ? options : { content: options };

		return new BBCodeNewLineNode({
			...preparedOptions,
			scheme: this,
		});
	}

	createTab(options: BBCodeTextNodeOptions = {}): BBCodeTabNode
	{
		const preparedOptions = Type.isPlainObject(options) ? options : { content: options };

		return new BBCodeTabNode({
			...preparedOptions,
			scheme: this,
		});
	}

	createFragment(options: FragmentNodeOptions = {}): BBCodeFragmentNode
	{
		return new BBCodeFragmentNode({
			...options,
			scheme: this,
		});
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit