diff --git a/rsconcept/frontend/src/features/rsform/components/RSInput/tooltip.ts b/rsconcept/frontend/src/features/rsform/components/RSInput/tooltip.ts
index ea38c29f..07e5e76d 100644
--- a/rsconcept/frontend/src/features/rsform/components/RSInput/tooltip.ts
+++ b/rsconcept/frontend/src/features/rsform/components/RSInput/tooltip.ts
@@ -1,10 +1,12 @@
import { Extension } from '@codemirror/state';
-import { hoverTooltip } from '@codemirror/view';
+import { hoverTooltip, TooltipView } from '@codemirror/view';
+import clsx from 'clsx';
import { findAliasAt } from '@/utils/codemirror';
-import { domTooltipConstituenta } from '@/utils/codemirror';
+import { labelCstTypification } from '@/utils/labels';
-import { IRSForm } from '../../models/rsform';
+import { IConstituenta, IRSForm } from '../../models/rsform';
+import { isBasicConcept } from '../../models/rsformAPI';
const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
return hoverTooltip((view, pos) => {
@@ -25,3 +27,78 @@ const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
export function rsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension {
return [tooltipProducer(schema, canClick)];
}
+
+/**
+ * Create DOM tooltip for {@link Constituenta}.
+ */
+function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView {
+ const dom = document.createElement('div');
+ dom.className = clsx(
+ 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
+ 'dense',
+ 'p-2',
+ 'border shadow-md',
+ 'cc-scroll-y',
+ 'text-sm font-main'
+ );
+
+ if (!cst) {
+ const text = document.createElement('p');
+ text.innerText = 'Конституента не определена';
+ dom.appendChild(text);
+ } else {
+ const alias = document.createElement('p');
+ alias.className = 'font-math';
+ alias.style.overflowWrap = 'anywhere';
+ alias.innerHTML = `${cst.alias}: ${labelCstTypification(cst)}`;
+ dom.appendChild(alias);
+
+ if (cst.term_resolved) {
+ const term = document.createElement('p');
+ term.innerHTML = `Термин: ${cst.term_resolved}`;
+ dom.appendChild(term);
+ }
+
+ if (cst.definition_formal) {
+ const expression = document.createElement('p');
+ expression.innerHTML = `Выражение: ${cst.definition_formal}`;
+ dom.appendChild(expression);
+ }
+
+ if (cst.definition_resolved) {
+ const definition = document.createElement('p');
+ definition.innerHTML = `Определение: ${cst.definition_resolved}`;
+ dom.appendChild(definition);
+ }
+
+ if (cst.convention) {
+ const convention = document.createElement('p');
+ if (isBasicConcept(cst.cst_type)) {
+ convention.innerHTML = `Конвенция: ${cst.convention}`;
+ } else {
+ convention.innerHTML = `Комментарий: ${cst.convention}`;
+ }
+ dom.appendChild(convention);
+ }
+
+ if (cst.spawner_alias) {
+ const derived = document.createElement('p');
+ derived.innerHTML = `Основание: ${cst.spawner_alias}`;
+ dom.appendChild(derived);
+ }
+
+ if (cst.spawn_alias.length > 0) {
+ const children = document.createElement('p');
+ children.innerHTML = `Порождает: ${cst.spawn_alias.join(', ')}`;
+ dom.appendChild(children);
+ }
+
+ if (canClick) {
+ const clickTip = document.createElement('p');
+ clickTip.className = 'text-center text-xs mt-1';
+ clickTip.innerText = 'Ctrl + клик для перехода';
+ dom.appendChild(clickTip);
+ }
+ }
+ return { dom: dom };
+}
diff --git a/rsconcept/frontend/src/features/rsform/components/RefsInput/tooltip.ts b/rsconcept/frontend/src/features/rsform/components/RefsInput/tooltip.ts
index 4a91032f..845fae9e 100644
--- a/rsconcept/frontend/src/features/rsform/components/RefsInput/tooltip.ts
+++ b/rsconcept/frontend/src/features/rsform/components/RefsInput/tooltip.ts
@@ -1,16 +1,15 @@
import { syntaxTree } from '@codemirror/language';
import { Extension } from '@codemirror/state';
-import { hoverTooltip } from '@codemirror/view';
+import { hoverTooltip, TooltipView } from '@codemirror/view';
+import clsx from 'clsx';
-import {
- domTooltipEntityReference,
- domTooltipSyntacticReference,
- findContainedNodes,
- findReferenceAt
-} from '@/utils/codemirror';
+import { APP_COLORS, colorFgGrammeme } from '@/styling/color';
+import { findContainedNodes, findReferenceAt } from '@/utils/codemirror';
+import { describeConstituentaTerm, labelGrammeme } from '@/utils/labels';
import { IEntityReference, ISyntacticReference } from '../../models/language';
-import { IRSForm } from '../../models/rsform';
+import { parseGrammemes } from '../../models/languageAPI';
+import { IConstituenta, IRSForm } from '../../models/rsform';
import { RefEntity } from './parse/parser.terms';
export const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
@@ -56,3 +55,106 @@ export const tooltipProducer = (schema: IRSForm, canClick?: boolean) => {
export function refsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension {
return [tooltipProducer(schema, canClick)];
}
+
+/**
+ * Create DOM tooltip for {@link IEntityReference}.
+ */
+function domTooltipEntityReference(
+ ref: IEntityReference,
+ cst: IConstituenta | undefined,
+ canClick?: boolean
+): TooltipView {
+ const dom = document.createElement('div');
+ dom.className = clsx(
+ 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
+ 'dense',
+ 'p-2 flex flex-col',
+ 'border shadow-md',
+ 'cc-scroll-y',
+ 'text-sm',
+ 'select-none cursor-auto'
+ );
+
+ const header = document.createElement('p');
+ header.innerHTML = 'Ссылка на конституенту';
+ dom.appendChild(header);
+
+ const term = document.createElement('p');
+ term.innerHTML = `${ref.entity}: ${describeConstituentaTerm(cst)}`;
+ dom.appendChild(term);
+
+ const grams = document.createElement('div');
+ grams.className = 'flex flex-wrap gap-1 mt-1';
+ parseGrammemes(ref.form).forEach(gramStr => {
+ const gram = document.createElement('div');
+ gram.id = `tooltip-${gramStr}`;
+ gram.className = clsx(
+ 'min-w-[3rem]', //
+ 'px-1',
+ 'border rounded-md',
+ 'text-sm text-center whitespace-nowrap'
+ );
+ gram.style.borderWidth = '1px';
+ gram.style.borderColor = colorFgGrammeme(gramStr);
+ gram.style.color = colorFgGrammeme(gramStr);
+ gram.style.fontWeight = '600';
+ gram.style.backgroundColor = APP_COLORS.bgInput;
+ gram.innerText = labelGrammeme(gramStr);
+ grams.appendChild(gram);
+ });
+ dom.appendChild(grams);
+
+ if (canClick) {
+ const clickTip = document.createElement('p');
+ clickTip.className = 'text-center text-xs mt-1';
+ clickTip.innerHTML = 'Ctrl + клик для переходаCtrl + пробел для редактирования';
+ dom.appendChild(clickTip);
+ }
+
+ return { dom: dom };
+}
+
+/**
+ * Create DOM tooltip for {@link ISyntacticReference}.
+ */
+function domTooltipSyntacticReference(
+ ref: ISyntacticReference,
+ masterRef: string | undefined,
+ canClick?: boolean
+): TooltipView {
+ const dom = document.createElement('div');
+ dom.className = clsx(
+ 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
+ 'dense',
+ 'p-2 flex flex-col',
+ 'border shadow-md',
+ 'cc-scroll-y',
+ 'text-sm',
+ 'select-none cursor-auto'
+ );
+
+ const header = document.createElement('p');
+ header.innerHTML = 'Связывание слов';
+ dom.appendChild(header);
+
+ const offset = document.createElement('p');
+ offset.innerHTML = `Смещение: ${ref.offset}`;
+ dom.appendChild(offset);
+
+ const master = document.createElement('p');
+ master.innerHTML = `Основная ссылка: ${masterRef ?? 'не определена'}`;
+ dom.appendChild(master);
+
+ const nominal = document.createElement('p');
+ nominal.innerHTML = `Начальная форма: ${ref.nominal}`;
+ dom.appendChild(nominal);
+
+ if (canClick) {
+ const clickTip = document.createElement('p');
+ clickTip.className = 'text-center text-xs mt-1';
+ clickTip.innerHTML = 'Ctrl + пробел для редактирования';
+ dom.appendChild(clickTip);
+ }
+
+ return { dom: dom };
+}
diff --git a/rsconcept/frontend/src/utils/codemirror.ts b/rsconcept/frontend/src/utils/codemirror.ts
index adf778f2..5d6e6521 100644
--- a/rsconcept/frontend/src/utils/codemirror.ts
+++ b/rsconcept/frontend/src/utils/codemirror.ts
@@ -3,26 +3,20 @@
*/
import { syntaxTree } from '@codemirror/language';
import { NodeType, Tree, TreeCursor } from '@lezer/common';
-import { EditorState, ReactCodeMirrorRef, SelectionRange, TooltipView } from '@uiw/react-codemirror';
-import clsx from 'clsx';
+import { EditorState, ReactCodeMirrorRef, SelectionRange } from '@uiw/react-codemirror';
import { ReferenceTokens } from '@/features/rsform/components/RefsInput/parse';
import { RefEntity } from '@/features/rsform/components/RefsInput/parse/parser.terms';
import { GlobalTokens } from '@/features/rsform/components/RSInput/rslang';
-import { IEntityReference, ISyntacticReference } from '@/features/rsform/models/language';
-import { parseEntityReference, parseGrammemes, parseSyntacticReference } from '@/features/rsform/models/languageAPI';
-import { IConstituenta } from '@/features/rsform/models/rsform';
-import { isBasicConcept } from '@/features/rsform/models/rsformAPI';
+import { parseEntityReference, parseSyntacticReference } from '@/features/rsform/models/languageAPI';
import { SyntaxTree } from '@/features/rsform/models/rslang';
-import { APP_COLORS, colorFgGrammeme } from '@/styling/color';
import { PARAMETER } from './constants';
-import { describeConstituentaTerm, labelCstTypification, labelGrammeme } from './labels';
/**
* Represents syntax tree node data.
*/
-export interface SyntaxNode {
+interface SyntaxNode {
type: NodeType;
from: number;
to: number;
@@ -31,7 +25,7 @@ export interface SyntaxNode {
/**
* Represents syntax tree cursor data.
*/
-export interface CursorNode extends SyntaxNode {
+interface CursorNode extends SyntaxNode {
isLeaf: boolean;
}
@@ -214,184 +208,6 @@ export function findReferenceAt(pos: number, state: EditorState) {
}
}
-/**
- * Create DOM tooltip for {@link Constituenta}.
- */
-export function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView {
- const dom = document.createElement('div');
- dom.className = clsx(
- 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
- 'dense',
- 'p-2',
- 'border shadow-md',
- 'cc-scroll-y',
- 'text-sm font-main'
- );
-
- if (!cst) {
- const text = document.createElement('p');
- text.innerText = 'Конституента не определена';
- dom.appendChild(text);
- } else {
- const alias = document.createElement('p');
- alias.className = 'font-math';
- alias.style.overflowWrap = 'anywhere';
- alias.innerHTML = `${cst.alias}: ${labelCstTypification(cst)}`;
- dom.appendChild(alias);
-
- if (cst.term_resolved) {
- const term = document.createElement('p');
- term.innerHTML = `Термин: ${cst.term_resolved}`;
- dom.appendChild(term);
- }
-
- if (cst.definition_formal) {
- const expression = document.createElement('p');
- expression.innerHTML = `Выражение: ${cst.definition_formal}`;
- dom.appendChild(expression);
- }
-
- if (cst.definition_resolved) {
- const definition = document.createElement('p');
- definition.innerHTML = `Определение: ${cst.definition_resolved}`;
- dom.appendChild(definition);
- }
-
- if (cst.convention) {
- const convention = document.createElement('p');
- if (isBasicConcept(cst.cst_type)) {
- convention.innerHTML = `Конвенция: ${cst.convention}`;
- } else {
- convention.innerHTML = `Комментарий: ${cst.convention}`;
- }
- dom.appendChild(convention);
- }
-
- if (cst.spawner_alias) {
- const derived = document.createElement('p');
- derived.innerHTML = `Основание: ${cst.spawner_alias}`;
- dom.appendChild(derived);
- }
-
- if (cst.spawn_alias.length > 0) {
- const children = document.createElement('p');
- children.innerHTML = `Порождает: ${cst.spawn_alias.join(', ')}`;
- dom.appendChild(children);
- }
-
- if (canClick) {
- const clickTip = document.createElement('p');
- clickTip.className = 'text-center text-xs mt-1';
- clickTip.innerText = 'Ctrl + клик для перехода';
- dom.appendChild(clickTip);
- }
- }
- return { dom: dom };
-}
-
-/**
- * Create DOM tooltip for {@link IEntityReference}.
- */
-export function domTooltipEntityReference(
- ref: IEntityReference,
- cst: IConstituenta | undefined,
- canClick?: boolean
-): TooltipView {
- const dom = document.createElement('div');
- dom.className = clsx(
- 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
- 'dense',
- 'p-2 flex flex-col',
- 'border shadow-md',
- 'cc-scroll-y',
- 'text-sm',
- 'select-none cursor-auto'
- );
-
- const header = document.createElement('p');
- header.innerHTML = 'Ссылка на конституенту';
- dom.appendChild(header);
-
- const term = document.createElement('p');
- term.innerHTML = `${ref.entity}: ${describeConstituentaTerm(cst)}`;
- dom.appendChild(term);
-
- const grams = document.createElement('div');
- grams.className = 'flex flex-wrap gap-1 mt-1';
- parseGrammemes(ref.form).forEach(gramStr => {
- const gram = document.createElement('div');
- gram.id = `tooltip-${gramStr}`;
- gram.className = clsx(
- 'min-w-[3rem]', //
- 'px-1',
- 'border rounded-md',
- 'text-sm text-center whitespace-nowrap'
- );
- gram.style.borderWidth = '1px';
- gram.style.borderColor = colorFgGrammeme(gramStr);
- gram.style.color = colorFgGrammeme(gramStr);
- gram.style.fontWeight = '600';
- gram.style.backgroundColor = APP_COLORS.bgInput;
- gram.innerText = labelGrammeme(gramStr);
- grams.appendChild(gram);
- });
- dom.appendChild(grams);
-
- if (canClick) {
- const clickTip = document.createElement('p');
- clickTip.className = 'text-center text-xs mt-1';
- clickTip.innerHTML = 'Ctrl + клик для переходаCtrl + пробел для редактирования';
- dom.appendChild(clickTip);
- }
-
- return { dom: dom };
-}
-
-/**
- * Create DOM tooltip for {@link ISyntacticReference}.
- */
-export function domTooltipSyntacticReference(
- ref: ISyntacticReference,
- masterRef: string | undefined,
- canClick?: boolean
-): TooltipView {
- const dom = document.createElement('div');
- dom.className = clsx(
- 'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
- 'dense',
- 'p-2 flex flex-col',
- 'border shadow-md',
- 'cc-scroll-y',
- 'text-sm',
- 'select-none cursor-auto'
- );
-
- const header = document.createElement('p');
- header.innerHTML = 'Связывание слов';
- dom.appendChild(header);
-
- const offset = document.createElement('p');
- offset.innerHTML = `Смещение: ${ref.offset}`;
- dom.appendChild(offset);
-
- const master = document.createElement('p');
- master.innerHTML = `Основная ссылка: ${masterRef ?? 'не определена'}`;
- dom.appendChild(master);
-
- const nominal = document.createElement('p');
- nominal.innerHTML = `Начальная форма: ${ref.nominal}`;
- dom.appendChild(nominal);
-
- if (canClick) {
- const clickTip = document.createElement('p');
- clickTip.className = 'text-center text-xs mt-1';
- clickTip.innerHTML = 'Ctrl + пробел для редактирования';
- dom.appendChild(clickTip);
- }
-
- return { dom: dom };
-}
-
/**
* Wrapper class for CodeMirror editor.
*