diff --git a/rsconcept/frontend/eslint.config.js b/rsconcept/frontend/eslint.config.js index ee457525..0f00372e 100644 --- a/rsconcept/frontend/eslint.config.js +++ b/rsconcept/frontend/eslint.config.js @@ -8,6 +8,33 @@ import importPlugin from 'eslint-plugin-import'; import simpleImportSort from 'eslint-plugin-simple-import-sort'; import playwright from 'eslint-plugin-playwright'; +const basicRules = { + 'no-console': 'off', + 'require-jsdoc': 'off', + + '@typescript-eslint/consistent-type-imports': [ + 'warn', + { + fixStyle: 'inline-type-imports' + } + ], + '@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }], + '@typescript-eslint/prefer-nullish-coalescing': 'off', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_' + } + ], + + 'simple-import-sort/exports': 'error', + 'import/no-duplicates': 'warn' +}; + export default [ ...typescriptPlugin.configs.recommendedTypeChecked, ...typescriptPlugin.configs.stylisticTypeChecked, @@ -45,33 +72,9 @@ export default [ }, settings: { react: { version: 'detect' } }, rules: { - 'no-console': 'off', - 'require-jsdoc': 'off', - + ...basicRules, 'react-compiler/react-compiler': 'error', 'react-refresh/only-export-components': ['off', { allowConstantExport: true }], - - '@typescript-eslint/consistent-type-imports': [ - 'warn', - { - fixStyle: 'inline-type-imports' - } - ], - '@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }], - '@typescript-eslint/prefer-nullish-coalescing': 'off', - '@typescript-eslint/no-inferrable-types': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - caughtErrorsIgnorePattern: '^_', - destructuredArrayIgnorePattern: '^_' - } - ], - - 'simple-import-sort/exports': 'error', - 'import/no-duplicates': 'warn', 'simple-import-sort/imports': [ 'warn', { @@ -113,13 +116,8 @@ export default [ }, rules: { + ...basicRules, ...playwright.configs['flat/recommended'].rules, - - 'no-console': 'off', - 'require-jsdoc': 'off', - - 'simple-import-sort/exports': 'error', - 'import/no-duplicates': 'warn', 'simple-import-sort/imports': 'warn' } } diff --git a/rsconcept/frontend/src/features/library/backend/types.ts b/rsconcept/frontend/src/features/library/backend/types.ts index 4ca2e6a5..042aa233 100644 --- a/rsconcept/frontend/src/features/library/backend/types.ts +++ b/rsconcept/frontend/src/features/library/backend/types.ts @@ -5,17 +5,19 @@ import { errorMsg } from '@/utils/labels'; import { validateLocation } from '../models/library-api'; /** Represents type of library items. */ -export enum LibraryItemType { - RSFORM = 'rsform', - OSS = 'oss' -} +export const LibraryItemType = { + RSFORM: 'rsform', + OSS: 'oss' +} as const; +export type LibraryItemType = (typeof LibraryItemType)[keyof typeof LibraryItemType]; /** Represents Access policy for library items.*/ -export enum AccessPolicy { - PUBLIC = 'public', - PROTECTED = 'protected', - PRIVATE = 'private' -} +export const AccessPolicy = { + PUBLIC: 'public', + PROTECTED: 'protected', + PRIVATE: 'private' +} as const; +export type AccessPolicy = (typeof AccessPolicy)[keyof typeof AccessPolicy]; /** Represents library item common data typical for all item types. */ export type ILibraryItem = z.infer; @@ -53,17 +55,19 @@ export type IVersionCreateDTO = z.infer; export type IVersionUpdateDTO = z.infer; // ======= SCHEMAS ========= +export const schemaLibraryItemType = z.enum(Object.values(LibraryItemType) as [LibraryItemType, ...LibraryItemType[]]); +export const schemaAccessPolicy = z.enum(Object.values(AccessPolicy) as [AccessPolicy, ...AccessPolicy[]]); export const schemaLibraryItem = z.strictObject({ id: z.coerce.number(), - item_type: z.nativeEnum(LibraryItemType), + item_type: schemaLibraryItemType, title: z.string(), alias: z.string().nonempty(), comment: z.string(), visible: z.boolean(), read_only: z.boolean(), location: z.string(), - access_policy: z.nativeEnum(AccessPolicy), + access_policy: schemaAccessPolicy, time_create: z.string().datetime({ offset: true }), time_update: z.string().datetime({ offset: true }), @@ -94,14 +98,14 @@ export const schemaCloneLibraryItem = schemaLibraryItem export const schemaCreateLibraryItem = z .object({ - item_type: z.nativeEnum(LibraryItemType), + item_type: schemaLibraryItemType, title: z.string().optional(), alias: z.string().optional(), comment: z.string(), visible: z.boolean(), read_only: z.boolean(), location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }), - access_policy: z.nativeEnum(AccessPolicy), + access_policy: schemaAccessPolicy, file: z.instanceof(File).optional(), fileName: z.string().optional() @@ -117,7 +121,7 @@ export const schemaCreateLibraryItem = z export const schemaUpdateLibraryItem = z.strictObject({ id: z.number(), - item_type: z.nativeEnum(LibraryItemType), + item_type: schemaLibraryItemType, title: z.string().nonempty(errorMsg.requiredField), alias: z.string().nonempty(errorMsg.requiredField), comment: z.string(), diff --git a/rsconcept/frontend/src/features/library/models/library.ts b/rsconcept/frontend/src/features/library/models/library.ts index 0e7052ff..aebece58 100644 --- a/rsconcept/frontend/src/features/library/models/library.ts +++ b/rsconcept/frontend/src/features/library/models/library.ts @@ -5,12 +5,13 @@ /** * Represents valid location headers. */ -export enum LocationHead { - USER = '/U', - COMMON = '/S', - PROJECTS = '/P', - LIBRARY = '/L' -} +export const LocationHead = { + USER: '/U', + COMMON: '/S', + PROJECTS: '/P', + LIBRARY: '/L' +} as const; +export type LocationHead = (typeof LocationHead)[keyof typeof LocationHead]; export const BASIC_SCHEMAS = '/L/Базовые'; diff --git a/rsconcept/frontend/src/features/oss/backend/types.ts b/rsconcept/frontend/src/features/oss/backend/types.ts index 74a425bd..bb94ce17 100644 --- a/rsconcept/frontend/src/features/oss/backend/types.ts +++ b/rsconcept/frontend/src/features/oss/backend/types.ts @@ -8,10 +8,11 @@ import { errorMsg } from '@/utils/labels'; /** * Represents {@link IOperation} type. */ -export enum OperationType { - INPUT = 'input', - SYNTHESIS = 'synthesis' -} +export const OperationType = { + INPUT: 'input', + SYNTHESIS: 'synthesis' +} as const; +export type OperationType = (typeof OperationType)[keyof typeof OperationType]; /** Represents {@link ICstSubstitute} extended data. */ export type ICstSubstituteInfo = z.infer; @@ -57,10 +58,11 @@ export type ICstRelocateDTO = z.infer; export type IConstituentaReference = z.infer; // ====== Schemas ====== +export const schemaOperationType = z.enum(Object.values(OperationType) as [OperationType, ...OperationType[]]); export const schemaOperation = z.strictObject({ id: z.number(), - operation_type: z.nativeEnum(OperationType), + operation_type: schemaOperationType, oss: z.number(), alias: z.string(), @@ -103,7 +105,7 @@ export const schemaOperationCreate = z.strictObject({ positions: z.array(schemaOperationPosition), item_data: z.strictObject({ alias: z.string().nonempty(), - operation_type: z.nativeEnum(OperationType), + operation_type: schemaOperationType, title: z.string(), comment: z.string(), position_x: z.number(), diff --git a/rsconcept/frontend/src/features/oss/dialogs/dlg-create-operation/dlg-create-operation.tsx b/rsconcept/frontend/src/features/oss/dialogs/dlg-create-operation/dlg-create-operation.tsx index d29a5a4f..d3bbe977 100644 --- a/rsconcept/frontend/src/features/oss/dialogs/dlg-create-operation/dlg-create-operation.tsx +++ b/rsconcept/frontend/src/features/oss/dialogs/dlg-create-operation/dlg-create-operation.tsx @@ -33,10 +33,11 @@ export interface DlgCreateOperationProps { onCreate?: (newID: number) => void; } -enum TabID { - INPUT = 0, - SYNTHESIS = 1 -} +export const TabID = { + INPUT: 0, + SYNTHESIS: 1 +} as const; +export type TabID = (typeof TabID)[keyof typeof TabID]; export function DlgCreateOperation() { const { operationCreate } = useOperationCreate(); @@ -101,7 +102,12 @@ export function DlgCreateOperation() { className='w-160 px-6 h-128' helpTopic={HelpTopic.CC_OSS} > - + handleSelectTab(index as TabID, last as TabID)} + > state.props as DlgEditOperationProps); @@ -58,7 +59,7 @@ export function DlgEditOperation() { }, mode: 'onChange' }); - const [activeTab, setActiveTab] = useState(TabID.CARD); + const [activeTab, setActiveTab] = useState(TabID.CARD); function onSubmit(data: IOperationUpdateDTO) { return operationUpdate({ itemID: oss.id, data }); @@ -74,7 +75,12 @@ export function DlgEditOperation() { helpTopic={HelpTopic.UI_SUBSTITUTIONS} hideHelpWhen={() => activeTab !== TabID.SUBSTITUTION} > - + setActiveTab(index as TabID)} + > {target.operation_type === OperationType.SYNTHESIS ? ( diff --git a/rsconcept/frontend/src/features/oss/models/oss.ts b/rsconcept/frontend/src/features/oss/models/oss.ts index 56cfd8b1..b0651a70 100644 --- a/rsconcept/frontend/src/features/oss/models/oss.ts +++ b/rsconcept/frontend/src/features/oss/models/oss.ts @@ -6,9 +6,7 @@ import { type Graph } from '@/models/graph'; import { type ICstSubstituteInfo, type IOperationDTO, type IOperationSchemaDTO } from '../backend/types'; -/** - * Represents Operation. - */ +/** Represents Operation. */ export interface IOperation extends IOperationDTO { is_owned: boolean; is_consolidation: boolean; // aka 'diamond synthesis' @@ -16,9 +14,7 @@ export interface IOperation extends IOperationDTO { arguments: number[]; } -/** - * Represents {@link IOperationSchema} statistics. - */ +/** Represents {@link IOperationSchema} statistics. */ export interface IOperationSchemaStats { count_operations: number; count_inputs: number; @@ -27,9 +23,7 @@ export interface IOperationSchemaStats { count_owned: number; } -/** - * Represents OperationSchema. - */ +/** Represents OperationSchema. */ export interface IOperationSchema extends IOperationSchemaDTO { items: IOperation[]; @@ -39,27 +33,25 @@ export interface IOperationSchema extends IOperationSchemaDTO { operationByID: Map; } -/** - * Represents substitution error description. - */ +/** Represents substitution error description. */ export interface ISubstitutionErrorDescription { errorType: SubstitutionErrorType; params: string[]; } -/** - * Represents Substitution table error types. - */ -export enum SubstitutionErrorType { - invalidIDs, - incorrectCst, - invalidClasses, - invalidBasic, - invalidConstant, - typificationCycle, - baseSubstitutionNotSet, - unequalTypification, - unequalExpressions, - unequalArgsCount, - unequalArgs -} +/** Represents Substitution table error types. */ +export const SubstitutionErrorType = { + invalidIDs: 0, + incorrectCst: 1, + invalidClasses: 2, + invalidBasic: 3, + invalidConstant: 4, + typificationCycle: 5, + baseSubstitutionNotSet: 6, + unequalTypification: 7, + unequalExpressions: 8, + unequalArgsCount: 9, + unequalArgs: 10 +} as const; + +export type SubstitutionErrorType = (typeof SubstitutionErrorType)[keyof typeof SubstitutionErrorType]; diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/oss-edit-context.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/oss-edit-context.tsx index b0c94163..5853d7c5 100644 --- a/rsconcept/frontend/src/features/oss/pages/oss-page/oss-edit-context.tsx +++ b/rsconcept/frontend/src/features/oss/pages/oss-page/oss-edit-context.tsx @@ -16,10 +16,11 @@ import { OperationType } from '../../backend/types'; import { useOssSuspense } from '../../backend/use-oss'; import { type IOperation, type IOperationSchema } from '../../models/oss'; -export enum OssTabID { - CARD = 0, - GRAPH = 1 -} +export const OssTabID = { + CARD: 0, + GRAPH: 1 +} as const; +export type OssTabID = (typeof OssTabID)[keyof typeof OssTabID]; export interface IOssEditContext { schema: IOperationSchema; diff --git a/rsconcept/frontend/src/features/oss/pages/oss-page/oss-tabs.tsx b/rsconcept/frontend/src/features/oss/pages/oss-page/oss-tabs.tsx index 00d7cce5..a7c07208 100644 --- a/rsconcept/frontend/src/features/oss/pages/oss-page/oss-tabs.tsx +++ b/rsconcept/frontend/src/features/oss/pages/oss-page/oss-tabs.tsx @@ -50,7 +50,7 @@ export function OssTabs({ activeTab }: OssTabsProps) { } } } - navigateTab(index); + navigateTab(index as OssTabID); } return ( diff --git a/rsconcept/frontend/src/features/rsform/backend/types.ts b/rsconcept/frontend/src/features/rsform/backend/types.ts index fc5a5141..0d975e09 100644 --- a/rsconcept/frontend/src/features/rsform/backend/types.ts +++ b/rsconcept/frontend/src/features/rsform/backend/types.ts @@ -5,37 +5,41 @@ import { schemaLibraryItem, schemaVersionInfo } from '@/features/library/backend import { errorMsg } from '@/utils/labels'; /** Represents {@link IConstituenta} type. */ -export enum CstType { - BASE = 'basic', - STRUCTURED = 'structure', - TERM = 'term', - AXIOM = 'axiom', - FUNCTION = 'function', - PREDICATE = 'predicate', - CONSTANT = 'constant', - THEOREM = 'theorem' -} +export const CstType = { + BASE: 'basic', + STRUCTURED: 'structure', + TERM: 'term', + AXIOM: 'axiom', + FUNCTION: 'function', + PREDICATE: 'predicate', + CONSTANT: 'constant', + THEOREM: 'theorem' +} as const; +export type CstType = (typeof CstType)[keyof typeof CstType]; /** Represents syntax type. */ -export enum Syntax { - UNDEF = 'undefined', - ASCII = 'ascii', - MATH = 'math' -} +export const Syntax = { + UNDEF: 'undefined', + ASCII: 'ascii', + MATH: 'math' +} as const; +export type Syntax = (typeof Syntax)[keyof typeof Syntax]; /** Represents computability class. */ -export enum ValueClass { - INVALID = 'invalid', // incalculable - VALUE = 'value', - PROPERTY = 'property' -} +export const ValueClass = { + INVALID: 'invalid', // incalculable + VALUE: 'value', + PROPERTY: 'property' +} as const; +export type ValueClass = (typeof ValueClass)[keyof typeof ValueClass]; /** Represents parsing status. */ -export enum ParsingStatus { - UNDEF = 'undefined', - VERIFIED = 'verified', - INCORRECT = 'incorrect' -} +export const ParsingStatus = { + UNDEF: 'undefined', + VERIFIED: 'verified', + INCORRECT: 'incorrect' +} as const; +export type ParsingStatus = (typeof ParsingStatus)[keyof typeof ParsingStatus]; /** Represents Constituenta basic persistent data. */ export type IConstituentaBasicsDTO = z.infer; @@ -108,169 +112,178 @@ export type IExpressionParseDTO = z.infer; export type IVersionCreatedResponse = z.infer; /** Represents RSLang token types. */ -export enum TokenID { +export const TokenID = { // Global, local IDs and literals - ID_LOCAL = 258, - ID_GLOBAL, - ID_FUNCTION, - ID_PREDICATE, - ID_RADICAL, - LIT_INTEGER, - LIT_WHOLE_NUMBERS, - LIT_EMPTYSET, + ID_LOCAL: 258, + ID_GLOBAL: 259, + ID_FUNCTION: 260, + ID_PREDICATE: 261, + ID_RADICAL: 262, + LIT_INTEGER: 263, + LIT_WHOLE_NUMBERS: 264, + LIT_EMPTYSET: 265, // Arithmetic - PLUS, - MINUS, - MULTIPLY, + PLUS: 266, + MINUS: 267, + MULTIPLY: 268, // Integer predicate symbols - GREATER, - LESSER, - GREATER_OR_EQ, - LESSER_OR_EQ, + GREATER: 269, + LESSER: 270, + GREATER_OR_EQ: 271, + LESSER_OR_EQ: 272, // Equality comparison - EQUAL, - NOTEQUAL, + EQUAL: 273, + NOTEQUAL: 274, // Logic predicate symbols - QUANTOR_UNIVERSAL, - QUANTOR_EXISTS, - LOGIC_NOT, - LOGIC_EQUIVALENT, - LOGIC_IMPLICATION, - LOGIC_OR, - LOGIC_AND, + QUANTOR_UNIVERSAL: 275, + QUANTOR_EXISTS: 276, + LOGIC_NOT: 277, + LOGIC_EQUIVALENT: 278, + LOGIC_IMPLICATION: 279, + LOGIC_OR: 280, + LOGIC_AND: 281, // Set theory predicate symbols - SET_IN, - SET_NOT_IN, - SUBSET, - SUBSET_OR_EQ, - NOT_SUBSET, + SET_IN: 282, + SET_NOT_IN: 283, + SUBSET: 284, + SUBSET_OR_EQ: 285, + NOT_SUBSET: 286, // Set theory operators - DECART, - SET_UNION, - SET_INTERSECTION, - SET_MINUS, - SET_SYMMETRIC_MINUS, - BOOLEAN, + DECART: 287, + SET_UNION: 288, + SET_INTERSECTION: 289, + SET_MINUS: 290, + SET_SYMMETRIC_MINUS: 291, + BOOLEAN: 292, // Structure operations - BIGPR, - SMALLPR, - FILTER, - CARD, - BOOL, - DEBOOL, - REDUCE, + BIGPR: 293, + SMALLPR: 294, + FILTER: 295, + CARD: 296, + BOOL: 297, + DEBOOL: 298, + REDUCE: 299, // Term constructions prefixes - DECLARATIVE, - RECURSIVE, - IMPERATIVE, + DECLARATIVE: 300, + RECURSIVE: 301, + IMPERATIVE: 302, - ITERATE, - ASSIGN, + ITERATE: 303, + ASSIGN: 304, // Punctuation - PUNCTUATION_DEFINE, - PUNCTUATION_STRUCT, - PUNCTUATION_PL, - PUNCTUATION_PR, - PUNCTUATION_CL, - PUNCTUATION_CR, - PUNCTUATION_SL, - PUNCTUATION_SR, - PUNCTUATION_BAR, - PUNCTUATION_COMMA, - PUNCTUATION_SEMICOLON, + PUNCTUATION_DEFINE: 305, + PUNCTUATION_STRUCT: 306, + PUNCTUATION_PL: 307, + PUNCTUATION_PR: 308, + PUNCTUATION_CL: 309, + PUNCTUATION_CR: 310, + PUNCTUATION_SL: 311, + PUNCTUATION_SR: 312, + PUNCTUATION_BAR: 313, + PUNCTUATION_COMMA: 314, + PUNCTUATION_SEMICOLON: 315, // ======= Non-terminal tokens ========= - NT_ENUM_DECL, - NT_TUPLE, - NT_ENUMERATION, - NT_TUPLE_DECL, - NT_ARG_DECL, + NT_ENUM_DECL: 316, + NT_TUPLE: 317, + NT_ENUMERATION: 318, + NT_TUPLE_DECL: 319, + NT_ARG_DECL: 320, - NT_FUNC_DEFINITION, - NT_ARGUMENTS, - NT_FUNC_CALL, + NT_FUNC_DEFINITION: 321, + NT_ARGUMENTS: 322, + NT_FUNC_CALL: 323, - NT_DECLARATIVE_EXPR, - NT_IMPERATIVE_EXPR, - NT_RECURSIVE_FULL, - NT_RECURSIVE_SHORT, + NT_DECLARATIVE_EXPR: 324, + NT_IMPERATIVE_EXPR: 325, + NT_RECURSIVE_FULL: 326, + NT_RECURSIVE_SHORT: 327, // ======= Helper tokens ======== - INTERRUPT, - END -} + INTERRUPT: 328, + END: 329 +} as const; +export type TokenID = (typeof TokenID)[keyof typeof TokenID]; /** Represents RSLang expression error types. */ -export enum RSErrorType { - unknownSymbol = 33283, - syntax = 33792, - missingParenthesis = 33798, - missingCurlyBrace = 33799, - invalidQuantifier = 33800, - invalidImperative = 33801, - expectedArgDeclaration = 33812, - expectedLocal = 33813, - localDoubleDeclare = 10241, - localNotUsed = 10242, +export const RSErrorType = { + unknownSymbol: 33283, + syntax: 33792, + missingParenthesis: 33798, + missingCurlyBrace: 33799, + invalidQuantifier: 33800, + invalidImperative: 33801, + expectedArgDeclaration: 33812, + expectedLocal: 33813, + localDoubleDeclare: 10241, + localNotUsed: 10242, - localUndeclared = 34817, - localShadowing = 34818, + localUndeclared: 34817, + localShadowing: 34818, - typesNotEqual = 34819, - globalNotTyped = 34820, - invalidDecart = 34821, - invalidBoolean = 34822, - invalidTypeOperation = 34823, - invalidCard = 34824, - invalidDebool = 34825, - globalFuncMissing = 34826, - globalFuncWithoutArgs = 34827, - invalidReduce = 34832, - invalidProjectionTuple = 34833, - invalidProjectionSet = 34834, - invalidEnumeration = 34835, - invalidBinding = 34836, - localOutOfScope = 34837, - invalidElementPredicate = 34838, - invalidEmptySetUsage = 34839, - invalidArgsArity = 34840, - invalidArgumentType = 34841, - globalStructure = 34844, - radicalUsage = 34849, - invalidFilterArgumentType = 34850, - invalidFilterArity = 34851, - arithmeticNotSupported = 34852, - typesNotCompatible = 34853, - orderingNotSupported = 34854, + typesNotEqual: 34819, + globalNotTyped: 34820, + invalidDecart: 34821, + invalidBoolean: 34822, + invalidTypeOperation: 34823, + invalidCard: 34824, + invalidDebool: 34825, + globalFuncMissing: 34826, + globalFuncWithoutArgs: 34827, + invalidReduce: 34832, + invalidProjectionTuple: 34833, + invalidProjectionSet: 34834, + invalidEnumeration: 34835, + invalidBinding: 34836, + localOutOfScope: 34837, + invalidElementPredicate: 34838, + invalidEmptySetUsage: 34839, + invalidArgsArity: 34840, + invalidArgumentType: 34841, + globalStructure: 34844, + radicalUsage: 34849, + invalidFilterArgumentType: 34850, + invalidFilterArity: 34851, + arithmeticNotSupported: 34852, + typesNotCompatible: 34853, + orderingNotSupported: 34854, - globalNoValue = 34880, - invalidPropertyUsage = 34881, - globalMissingAST = 34882, - globalFuncNoInterpretation = 34883, + globalNoValue: 34880, + invalidPropertyUsage: 34881, + globalMissingAST: 34882, + globalFuncNoInterpretation: 34883, - cstNonemptyBase = 34912, - cstEmptyDerived = 34913, - cstCallableNoArgs = 34914, - cstNonCallableHasArgs = 34915, - cstExpectedLogical = 34916, - cstExpectedTyped = 34917 -} + cstNonemptyBase: 34912, + cstEmptyDerived: 34913, + cstCallableNoArgs: 34914, + cstNonCallableHasArgs: 34915, + cstExpectedLogical: 34916, + cstExpectedTyped: 34917 +} as const; +export type RSErrorType = (typeof RSErrorType)[keyof typeof RSErrorType]; // ========= SCHEMAS ======== +export const schemaCstType = z.enum(Object.values(CstType) as [CstType, ...CstType[]]); +export const schemaSyntax = z.enum(Object.values(Syntax) as [Syntax, ...Syntax[]]); +export const schemaValueClass = z.enum(Object.values(ValueClass) as [ValueClass, ...ValueClass[]]); +export const schemaParsingStatus = z.enum(Object.values(ParsingStatus) as [ParsingStatus, ...ParsingStatus[]]); +export const schemaTokenID = z.nativeEnum(TokenID); +export const schemaRSErrorType = z.nativeEnum(RSErrorType); + export const schemaConstituentaBasics = z.strictObject({ id: z.coerce.number(), alias: z.string().nonempty(errorMsg.requiredField), convention: z.string(), - cst_type: z.nativeEnum(CstType), + cst_type: schemaCstType, definition_formal: z.string(), definition_raw: z.string(), definition_resolved: z.string(), @@ -281,8 +294,8 @@ export const schemaConstituentaBasics = z.strictObject({ export const schemaConstituenta = schemaConstituentaBasics.extend({ parse: z.strictObject({ - status: z.nativeEnum(ParsingStatus), - valueClass: z.nativeEnum(ValueClass), + status: schemaParsingStatus, + valueClass: schemaValueClass, typification: z.string(), syntaxTree: z.string(), args: z.array(z.strictObject({ alias: z.string(), typification: z.string() })) @@ -345,7 +358,7 @@ export const schemaCstUpdate = z.strictObject({ export const schemaCstRename = z.strictObject({ target: z.number(), alias: z.string(), - cst_type: z.nativeEnum(CstType) + cst_type: schemaCstType }); export const schemaProduceStructureResponse = z.strictObject({ @@ -370,7 +383,7 @@ export const schemaInlineSynthesis = z.strictObject({ }); export const schemaRSErrorDescription = z.strictObject({ - errorType: z.nativeEnum(RSErrorType), + errorType: schemaRSErrorType, position: z.number(), isCritical: z.boolean(), params: z.array(z.string()) @@ -379,16 +392,16 @@ export const schemaRSErrorDescription = z.strictObject({ export const schemaExpressionParse = z.strictObject({ parseResult: z.boolean(), prefixLen: z.number(), - syntax: z.nativeEnum(Syntax), + syntax: schemaSyntax, typification: z.string(), - valueClass: z.nativeEnum(ValueClass), + valueClass: schemaValueClass, errors: z.array(schemaRSErrorDescription), astText: z.string(), ast: z.array( z.strictObject({ uid: z.number(), parent: z.number(), - typeID: z.nativeEnum(TokenID), + typeID: schemaTokenID, start: z.number(), finish: z.number(), data: z.strictObject({ dataType: z.string(), value: z.unknown().refine(value => value !== undefined) }) diff --git a/rsconcept/frontend/src/features/rsform/colors.ts b/rsconcept/frontend/src/features/rsform/colors.ts index c4ce4336..3c1cd918 100644 --- a/rsconcept/frontend/src/features/rsform/colors.ts +++ b/rsconcept/frontend/src/features/rsform/colors.ts @@ -2,15 +2,13 @@ import { APP_COLORS } from '@/styling/colors'; import { PARAMETER } from '@/utils/constants'; import { TokenID } from './backend/types'; -import { type GramData, Grammeme, NounGrams, PartOfSpeech, VerbGrams } from './models/language'; +import { Grammeme, NounGrams, PartOfSpeech, VerbGrams } from './models/language'; import { CstClass, ExpressionStatus, type IConstituenta } from './models/rsform'; import { type ISyntaxTreeNode } from './models/rslang'; import { type TypificationGraphNode } from './models/typification-graph'; import { type GraphColoring } from './stores/term-graph'; -/** - * Represents Brackets highlights theme. - */ +/** Represents Brackets highlights theme. */ export const BRACKETS_THEME = { '.cc-nonmatchingBracket': { color: APP_COLORS.fgRed, @@ -22,9 +20,7 @@ export const BRACKETS_THEME = { } }; -/** - * Determines background color for {@link ISyntaxTreeNode} based on its type. - */ +/** Determines background color for {@link ISyntaxTreeNode} based on its type. */ export function colorBgSyntaxTree(node: ISyntaxTreeNode): string { switch (node.typeID) { case TokenID.PUNCTUATION_DEFINE: @@ -158,9 +154,7 @@ export function colorBgSyntaxTree(node: ISyntaxTreeNode): string { return APP_COLORS.bgPurple; } -/** - * Determines background color for {@link ExpressionStatus}. - */ +/** Determines background color for {@link ExpressionStatus}. */ export function colorBgCstStatus(status: ExpressionStatus): string { // prettier-ignore switch (status) { @@ -173,9 +167,7 @@ export function colorBgCstStatus(status: ExpressionStatus): string { } } -/** - * Determines statusbar color for {@link ExpressionStatus}. - */ +/** Determines statusbar color for {@link ExpressionStatus}. */ export function colorStatusBar(status: ExpressionStatus): string { // prettier-ignore switch (status) { @@ -188,9 +180,7 @@ export function colorStatusBar(status: ExpressionStatus): string { } } -/** - * Determines foreground color for {@link ExpressionStatus}. - */ +/** Determines foreground color for {@link ExpressionStatus}. */ export function colorFgCstStatus(status: ExpressionStatus): string { // prettier-ignore switch (status) { @@ -203,9 +193,7 @@ export function colorFgCstStatus(status: ExpressionStatus): string { } } -/** - * Determines background color for {@link IConstituenta} depending on its {@link CstClass}. - */ +/** Determines background color for {@link IConstituenta} depending on its {@link CstClass}. */ export function colorBgCstClass(cstClass: CstClass): string { // prettier-ignore switch (cstClass) { @@ -216,9 +204,7 @@ export function colorBgCstClass(cstClass: CstClass): string { } } -/** - * Determines background color for {@link IConstituenta} depending on its parent schema index. - */ +/** Determines background color for {@link IConstituenta} depending on its parent schema index. */ export function colorBgSchemas(schema_index: number): string { if (schema_index === 0) { return APP_COLORS.bgGreen; @@ -233,29 +219,25 @@ export function colorBgSchemas(schema_index: number): string { return APP_COLORS.bgBlue; } -/** - * Determines foreground color for {@link GramData}. - */ -export function colorFgGrammeme(gram: GramData): string { - if (PartOfSpeech.includes(gram as Grammeme)) { +/** Determines foreground color for {@link Grammeme}. */ +export function colorFgGrammeme(gram: Grammeme): string { + if (PartOfSpeech.includes(gram)) { return APP_COLORS.fgBlue; } - if (NounGrams.includes(gram as Grammeme)) { + if (NounGrams.includes(gram)) { return APP_COLORS.fgGreen; } - if (VerbGrams.includes(gram as Grammeme)) { + if (VerbGrams.includes(gram)) { return APP_COLORS.fgTeal; } - if (!Object.values(Grammeme).includes(gram as Grammeme)) { + if (!Object.values(Grammeme).includes(gram)) { return APP_COLORS.fgRed; } else { return APP_COLORS.fgPurple; } } -/** - * Determines graph color for {@link IConstituenta}. - */ +/** Determines graph color for {@link IConstituenta}. */ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColoring): string { if (coloringScheme === 'type') { return colorBgCstClass(cst.cst_class); @@ -269,9 +251,7 @@ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColori return APP_COLORS.bgGreen50; } -/** - * Determines m-graph color for {@link TypificationGraphNode}. - */ +/** Determines m-graph color for {@link TypificationGraphNode}. */ export function colorBgTMGraphNode(node: TypificationGraphNode): string { if (node.rank === 0) { return APP_COLORS.bgControls; diff --git a/rsconcept/frontend/src/features/rsform/components/badge-grammeme.tsx b/rsconcept/frontend/src/features/rsform/components/badge-grammeme.tsx index c6c5ffbb..7e410330 100644 --- a/rsconcept/frontend/src/features/rsform/components/badge-grammeme.tsx +++ b/rsconcept/frontend/src/features/rsform/components/badge-grammeme.tsx @@ -1,10 +1,10 @@ import { colorFgGrammeme } from '../colors'; import { labelGrammeme } from '../labels'; -import { type GramData } from '../models/language'; +import { type Grammeme } from '../models/language'; interface BadgeGrammemeProps { /** Grammeme to display. */ - grammeme: GramData; + grammeme: Grammeme; } /** diff --git a/rsconcept/frontend/src/features/rsform/components/refs-input/parse/parser.ts b/rsconcept/frontend/src/features/rsform/components/refs-input/parse/parser.ts index e7d332b3..0aab7c64 100644 --- a/rsconcept/frontend/src/features/rsform/components/refs-input/parse/parser.ts +++ b/rsconcept/frontend/src/features/rsform/components/refs-input/parse/parser.ts @@ -1,18 +1,20 @@ // This file was generated by lezer-generator. You probably shouldn't edit it. -import {LRParser} from "@lezer/lr" -import {highlighting} from "./highlight" +import { LRParser } from '@lezer/lr'; +import { highlighting } from './highlight'; export const parser = LRParser.deserialize({ version: 14, - states: "$nQVQPOOObQQO'#C^OOQO'#Cl'#ClOjQPO'#CuOxQPO'#CdOOQO'#Ce'#CeOOQO'#Ck'#CkOOQO'#Cf'#CfQVQPOOO}QPO,58xO!SQPO,58{OOQO,59a,59aO!XQPO,59OOOQO-E6d-E6dO!^QSO1G.dO!cQPO1G.gOOQO1G.j1G.jO!hQQO'#CpOOQO'#C`'#C`O!pQPO7+$OOOQO'#Cg'#CgO!uQPO'#CcO!}QPO7+$RO!^QSO,59[OOQO<QQPO1G/lOOQO1G/n1G/nO*|QPO,5:TOOQO1G/k1G/kO*|QPO1G/{OOQO1G/x1G/xO>qQPO1G/yO*|QPO1G/zO>xQPO1G/{O>}QPO1G/|O?UQPO1G0OO?ZQPO1G/qO?cQPO1G/qO?jQPO1G0WO*^QPO,5:mO*|QPO1G0WOOQO1G0Y1G0YO@^QPO1G0YO@eQPO1G0YO@lQPO1G0YO*|QPO,5:qO*wQPO,5:pOVQPO1G0ZOAZQPO1G/oOAkQPO7+%gOOQO7+%e7+%eOArQPO7+%fO*|QPO7+%gOVQPO7+%hO*|QPO7+%jOOQO7+%]7+%]OOQO7+%r7+%rOOQO1G0X1G0XOAzQPO7+%rOBhQPO1G0]OOQO1G0[1G0[OOQO7+%u7+%uOVQPO<mO*|QPOAN>lOVQPOAN>mOVQPO,5:cOOQOAN>nAN>nOVQPOAN>pOOQOG24XG24XODsQPOG24WODzQPOG24XOE]QPO1G/}OEqQPOG24[OExQPOG24[OOQOLD)rLD)rOOQOLD)sLD)sOOQOLD)vLD)vO*|QPOLD)vOFZQPO!$'MbOOQO!)9B|!)9B|", - stateData: "Fs~O!VOS~OQQORTOTROURO`UObVOcWOiXOjYOlZOnaO{dO|eO}fO!OfO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OeiO~PVOV!cXW!cXX!cXY!cXZ!cX[!cX]!cX^!cX!s!cXa!cX~Og!cXm!ZXp!ZXq!cXr!cXs!cXt!cXu!cXv!cXw!cXx!cXy!cXz!cX!T!cX~P!zOVkOWlOXmOYnOZoO[pO]qO^rOgsOqsOrsOssOtsOusOvsOwsOxsOysOzsO~O!T!WX~P$lOR{OTROURO`UObVOcWOiXOjYOlZOnaO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OQyO~P&QOR!OObVO~Od!QO~O`!RO~O`!SO~O`!TO~OV!eXW!eXX!eXY!eXZ!eX[!eX]!eX^!eXg!eXm!ZXp!ZXq!eXr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX!T!eX!s!eXa!eX~Od!UO~Oe!VO~OR!WO~OmsOpsO~Oe!ZO~OQ!]OR![O~O!P!`O!Q!aO!R!bO!S!cO!T!WX~OQ!dO~OQRO~P&QO!s!^X~P$lO_!gOV!_XW!_XX!_XY!_XZ!_X[!_X]!_X^!_Xg!_Xq!_Xr!_Xs!_Xt!_Xu!_Xv!_Xw!_Xx!_Xy!_Xz!_X!s!_X~O_!pO!s!^X~O!s!qO~O_!rO!P!`O!Q!aO!R!bO!S!cO~Og!sO~P!zOVkOWlOXmOYnOZoO[pO]qO^rO~Oa!^X!s!^Xf!^X~P-fOa!tO!s!qO~Oe!vO~Og#OO!s!}O~Og#TO~Of#VO!s#UO~OVkOX!diY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OW!di~P/ROWlO~P/ROVkOWlOXmO^rOZ!di[!di]!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OY!di~P2xOVkOWlOXmOYnO]qO^rO[!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OZ!di~P6hOZoO~P6hOYnO~P2xOVkOWlOXmOY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~O!P!Yi!Q!Yi!R!Yi!S!Yi!T!Yi_!Yia!Yik!Yih!Yi~P-fO_#YO~P-fOg#[O~Oh#]O~P-fOm#^O~Of#_O!s!qO~O_#_O~P-fOf#`O!s!qO~O!P!`O!R!vi!S!vi!T!vi_!via!vik!vih!vi~O!Q!vi~P?rO!Q!aO~P?rO!P!`O!Q!aO!R!bO!S!vi!T!vi_!via!vik!vih!vi~O_!]i!s!]ia!]if!]i~P-fOh#fO~P-fOf#gO!s!qO~OVkOWlOXmOYnOZoO[pO]qO^rO~PVOf!yi!s!yi~P-fOR#nO~Oh#oO~P-fO!P!`O!Q!aO!R!bO!S!cOa!kXk!kX~Oa#qOk#pO~Oh#rO~P-fO!P!`O!Q!aO!R!bO!S!cO!T!ty_!tya!tyk!tyh!ty~Oa#sO!P!`O!Q!aO!R!bO!S!cO~O_#yO~P-fOa#zO!P!`O!Q!aO!R!bO!S!cO~O!P!`O!Q!aO!R!bO!S!cOa!kik!ki~Oa#{O~P$lOh#|O!P!`O!Q!aO!R!bO!S!cO~Oa$OO~P-fOc!m|nTU!o!p!q!r!nQljij~", + states: + "3UO!sQPOOOOQO'#C`'#C`O#lQPO'#DoOOQO'#Do'#DoO%yQPO'#DdOVQPO'#DpO'_QPO'#DrO'fQPO'#DsO'nQQO'#DtO'sQPO'#DuO'xQPO'#DvO'}QPO'#DxOOQO'#Dq'#DqO(SQPO'#DqO)pQQO'#C{OOQO'#C{'#C{OOQO'#Dk'#DkO)uQPO'#DkO)zQPO'#DkO*PQPO'#DfOVQPO'#EQO*XQPO'#EQO*^QPO'#EQO*fQPO'#DdOOQO'#De'#DeO*wQPO'#ETQOQPOOO*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:QO+TQPO'#DjO+[QPO,5:[O,oQPO,5:SO,wQPO'#DiO,|QPO,5:PO-_QPO,5:aO.QQPO'#DjO*|QPO'#DpO._QPO,5:^OOQO'#Dj'#DjO*|QPO,5:_OOQO,5:_,5:_O.gQPO,5:`O*^QPO,5:aO*|QPO,5:bO*^QPO,5:dOOQO,59g,59gO*|QPO,5:VO*|QPO,5:VO$lQPO'#DfOOQO,5:l,5:lO*|QPO,5:lO*|QPO'#DhOOQO'#Dg'#DgOOQO'#ER'#ERO.lQPO,5:lOVQPO,5:nOVQPO,5:nOVQPO,5:nOVQPO,5:nO.tQPO'#EVOOQO'#EU'#EUO.yQPO,5:oOOQO1G/v1G/vO2jQPO1G/vO2qQPO1G/vO6aQPO1G/vO:PQPO1G/vO:WQPO1G/vO:_QPO1G/vO:fQPO1G/vO>QQPO1G/lOOQO1G/n1G/nO*|QPO,5:TOOQO1G/k1G/kO*|QPO1G/{OOQO1G/x1G/xO>qQPO1G/yO*|QPO1G/zO>xQPO1G/{O>}QPO1G/|O?UQPO1G0OO?ZQPO1G/qO?cQPO1G/qO?jQPO1G0WO*^QPO,5:mO*|QPO1G0WOOQO1G0Y1G0YO@^QPO1G0YO@eQPO1G0YO@lQPO1G0YO*|QPO,5:qO*wQPO,5:pOVQPO1G0ZOAZQPO1G/oOAkQPO7+%gOOQO7+%e7+%eOArQPO7+%fO*|QPO7+%gOVQPO7+%hO*|QPO7+%jOOQO7+%]7+%]OOQO7+%r7+%rOOQO1G0X1G0XOAzQPO7+%rOBhQPO1G0]OOQO1G0[1G0[OOQO7+%u7+%uOVQPO<mO*|QPOAN>lOVQPOAN>mOVQPO,5:cOOQOAN>nAN>nOVQPOAN>pOOQOG24XG24XODsQPOG24WODzQPOG24XOE]QPO1G/}OEqQPOG24[OExQPOG24[OOQOLD)rLD)rOOQOLD)sLD)sOOQOLD)vLD)vO*|QPOLD)vOFZQPO!$'MbOOQO!)9B|!)9B|", + stateData: + 'Fs~O!VOS~OQQORTOTROURO`UObVOcWOiXOjYOlZOnaO{dO|eO}fO!OfO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OeiO~PVOV!cXW!cXX!cXY!cXZ!cX[!cX]!cX^!cX!s!cXa!cX~Og!cXm!ZXp!ZXq!cXr!cXs!cXt!cXu!cXv!cXw!cXx!cXy!cXz!cX!T!cX~P!zOVkOWlOXmOYnOZoO[pO]qO^rOgsOqsOrsOssOtsOusOvsOwsOxsOysOzsO~O!T!WX~P$lOR{OTROURO`UObVOcWOiXOjYOlZOnaO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OQyO~P&QOR!OObVO~Od!QO~O`!RO~O`!SO~O`!TO~OV!eXW!eXX!eXY!eXZ!eX[!eX]!eX^!eXg!eXm!ZXp!ZXq!eXr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX!T!eX!s!eXa!eX~Od!UO~Oe!VO~OR!WO~OmsOpsO~Oe!ZO~OQ!]OR![O~O!P!`O!Q!aO!R!bO!S!cO!T!WX~OQ!dO~OQRO~P&QO!s!^X~P$lO_!gOV!_XW!_XX!_XY!_XZ!_X[!_X]!_X^!_Xg!_Xq!_Xr!_Xs!_Xt!_Xu!_Xv!_Xw!_Xx!_Xy!_Xz!_X!s!_X~O_!pO!s!^X~O!s!qO~O_!rO!P!`O!Q!aO!R!bO!S!cO~Og!sO~P!zOVkOWlOXmOYnOZoO[pO]qO^rO~Oa!^X!s!^Xf!^X~P-fOa!tO!s!qO~Oe!vO~Og#OO!s!}O~Og#TO~Of#VO!s#UO~OVkOX!diY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OW!di~P/ROWlO~P/ROVkOWlOXmO^rOZ!di[!di]!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OY!di~P2xOVkOWlOXmOYnO]qO^rO[!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OZ!di~P6hOZoO~P6hOYnO~P2xOVkOWlOXmOY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~O!P!Yi!Q!Yi!R!Yi!S!Yi!T!Yi_!Yia!Yik!Yih!Yi~P-fO_#YO~P-fOg#[O~Oh#]O~P-fOm#^O~Of#_O!s!qO~O_#_O~P-fOf#`O!s!qO~O!P!`O!R!vi!S!vi!T!vi_!via!vik!vih!vi~O!Q!vi~P?rO!Q!aO~P?rO!P!`O!Q!aO!R!bO!S!vi!T!vi_!via!vik!vih!vi~O_!]i!s!]ia!]if!]i~P-fOh#fO~P-fOf#gO!s!qO~OVkOWlOXmOYnOZoO[pO]qO^rO~PVOf!yi!s!yi~P-fOR#nO~Oh#oO~P-fO!P!`O!Q!aO!R!bO!S!cOa!kXk!kX~Oa#qOk#pO~Oh#rO~P-fO!P!`O!Q!aO!R!bO!S!cO!T!ty_!tya!tyk!tyh!ty~Oa#sO!P!`O!Q!aO!R!bO!S!cO~O_#yO~P-fOa#zO!P!`O!Q!aO!R!bO!S!cO~O!P!`O!Q!aO!R!bO!S!cOa!kik!ki~Oa#{O~P$lOh#|O!P!`O!Q!aO!R!bO!S!cO~Oa$OO~P-fOc!m|nTU!o!p!q!r!nQljij~', goto: "-l!zPPPP!{PPPPPPPPPPPPPPPPPPPPPPPPPP#wPPPPPPPPPPPPPPPPPPPPPP$s$y%s&T&q'u(Q(cPPP!{*a!{+_,Z+_+_+_-Y+_PPPPPPP%s-]%s-`-c-f!s`OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!sbOTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|QjOR#e#VSgO#VQxTQ!YdQ#P!`Q#Q!aQ#R!bQ#S!cQ#i#]Q#l#bQ#m#fQ#u#oQ#v#pR#x#rmhOTd!`!a!b!c#V#]#b#f#o#p#rlcOTd!`!a!b!c#V#]#b#f#o#p#rQ!^fQ!w!RQ!y!TR#a!}!U[Uklmnopqrs{!O!S!V!W!Z![!q!s!v#O#T#[#^#n#|l]OTd!`!a!b!c#V#]#b#f#o#p#rX!]f!R!T!}UvT{![X}U!V!Z!vUwT{![Q|UQ!z!VQ!|!ZR#Z!vSSO#VQtT[zU{!V!Z![!vd!Xd!`!a!b!c#]#b#f#o#pQ!gkQ!hlQ!imQ!jnQ!koQ!lpQ!mqQ!nrQ!osQ!u!OQ!x!SQ!{!WQ#W!qQ#X!sQ#b#OQ#c#TQ#h#[Q#k#^Q#t#nQ#w#rR#}#|!n`OUdklmnopqrs!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|TuT{!s[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!r[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|R!PVR#j#]R!_fRjOR!fiQ!eiR#d#U", - nodeNames: "⚠ Expression Local ( Literal Global Radical + - * ∪ \\ ∆ ∩ × ) { } ℬ Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ ∨ &", + nodeNames: + '⚠ Expression Local ( Literal Global Radical + - * ∪ \\ ∆ ∩ × ) { } ℬ Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ ∨ &', maxTerm: 87, propSources: [highlighting], skippedNodes: [0], repeatNodeCount: 0, - tokenData: "6P~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+s#V#W-c#W#X/O#X#d+]#d#e1h#e#f+]#f#g2^#g#o+]#o#p3h#p#q3m#q#r3r#y#z%s$f$g%s$r$s3w%o%p3|5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m4R%%Y%%Z4W%%[%%]4]%&Y%&Z4b%&]%&^4g%&_%&`4l%&`%&a4q%&b%&c4v%&c%&d4{%'S%'T5Q%'T%'U5V%'U%'V5[%(^%(_5a%(b%(c5f%(c%(d5k%)Q%)R5p%)S%)T5u%)U%)V5z&FU&FV%s~%xY!V~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!S~~&rOR~~&wO_~~&|OX~~'ROV~~'WO!s~~']OW~P'bP!`P!Q![']R'lQdQ!`P|}'r!Q!['eQ'uP!R!['xQ'}QdQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOm~~(hOp~~(mOk~~(rOw~~(wOz~~(|Ou~~)PP!Q![)S~)XPT~!Q![)S~)aPi~!Q![)S~)gQ!Q![)m#]#^)u~)rPn~!Q![)m~)zOc~~*POj~~*SQ!Q![*Y#f#g*b~*_P|~!Q![*Y~*gO!m~~*lPl~!Q![*o~*tPU~!Q![*o~*|O!b~~+ROe~~+WOZ~~+]Of~~+bRQ~!Q![+k#T#o+]5i6S+]~+pPQ~!Q![+k~+xTQ~!Q![+k#T#c+]#c#d,X#d#o+]5i6S+]~,^TQ~!Q![+k#T#c+]#c#d,m#d#o+]5i6S+]~,rTQ~!Q![+k#T#`+]#`#a-R#a#o+]5i6S+]~-YR!p~Q~!Q![+k#T#o+]5i6S+]~-hSQ~!Q![+k#T#U-t#U#o+]5i6S+]~-yTQ~!Q![+k#T#f+]#f#g.Y#g#o+]5i6S+]~._TQ~!Q![+k#T#W+]#W#X.n#X#o+]5i6S+]~.uR!o~Q~!Q![+k#T#o+]5i6S+]~/TTQ~!Q![+k#T#X+]#X#Y/d#Y#o+]5i6S+]~/iTQ~!Q![+k#T#U+]#U#V/x#V#o+]5i6S+]~/}TQ~!Q![+k#T#c+]#c#d0^#d#o+]5i6S+]~0cTQ~!Q![+k#T#c+]#c#d0r#d#o+]5i6S+]~0wTQ~!Q![+k#T#`+]#`#a1W#a#o+]5i6S+]~1_R!q~Q~!Q![+k#T#o+]5i6S+]~1mTQ~!Q![+k#T#f+]#f#g1|#g#o+]5i6S+]~2TR!n~Q~!Q![+k#T#o+]5i6S+]~2cTQ~!Q![+k#T#X+]#X#Y2r#Y#o+]5i6S+]~2wTQ~!Q![+k#T#W+]#W#X3W#X#o+]5i6S+]~3_R!r~Q~!Q![+k#T#o+]5i6S+]~3mO`~~3rOh~~3wOa~~3|O{~~4RO^~~4WOb~~4]O!Q~~4bO!P~~4gO}~~4lO!O~~4qO!a~~4vO[~~4{Og~~5QOq~~5VO!R~~5[O]~~5aOY~~5fOy~~5kOx~~5pOv~~5uOt~~5zOs~~6POr~", + tokenData: + "6P~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+s#V#W-c#W#X/O#X#d+]#d#e1h#e#f+]#f#g2^#g#o+]#o#p3h#p#q3m#q#r3r#y#z%s$f$g%s$r$s3w%o%p3|5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m4R%%Y%%Z4W%%[%%]4]%&Y%&Z4b%&]%&^4g%&_%&`4l%&`%&a4q%&b%&c4v%&c%&d4{%'S%'T5Q%'T%'U5V%'U%'V5[%(^%(_5a%(b%(c5f%(c%(d5k%)Q%)R5p%)S%)T5u%)U%)V5z&FU&FV%s~%xY!V~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!S~~&rOR~~&wO_~~&|OX~~'ROV~~'WO!s~~']OW~P'bP!`P!Q![']R'lQdQ!`P|}'r!Q!['eQ'uP!R!['xQ'}QdQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOm~~(hOp~~(mOk~~(rOw~~(wOz~~(|Ou~~)PP!Q![)S~)XPT~!Q![)S~)aPi~!Q![)S~)gQ!Q![)m#]#^)u~)rPn~!Q![)m~)zOc~~*POj~~*SQ!Q![*Y#f#g*b~*_P|~!Q![*Y~*gO!m~~*lPl~!Q![*o~*tPU~!Q![*o~*|O!b~~+ROe~~+WOZ~~+]Of~~+bRQ~!Q![+k#T#o+]5i6S+]~+pPQ~!Q![+k~+xTQ~!Q![+k#T#c+]#c#d,X#d#o+]5i6S+]~,^TQ~!Q![+k#T#c+]#c#d,m#d#o+]5i6S+]~,rTQ~!Q![+k#T#`+]#`#a-R#a#o+]5i6S+]~-YR!p~Q~!Q![+k#T#o+]5i6S+]~-hSQ~!Q![+k#T#U-t#U#o+]5i6S+]~-yTQ~!Q![+k#T#f+]#f#g.Y#g#o+]5i6S+]~._TQ~!Q![+k#T#W+]#W#X.n#X#o+]5i6S+]~.uR!o~Q~!Q![+k#T#o+]5i6S+]~/TTQ~!Q![+k#T#X+]#X#Y/d#Y#o+]5i6S+]~/iTQ~!Q![+k#T#U+]#U#V/x#V#o+]5i6S+]~/}TQ~!Q![+k#T#c+]#c#d0^#d#o+]5i6S+]~0cTQ~!Q![+k#T#c+]#c#d0r#d#o+]5i6S+]~0wTQ~!Q![+k#T#`+]#`#a1W#a#o+]5i6S+]~1_R!q~Q~!Q![+k#T#o+]5i6S+]~1mTQ~!Q![+k#T#f+]#f#g1|#g#o+]5i6S+]~2TR!n~Q~!Q![+k#T#o+]5i6S+]~2cTQ~!Q![+k#T#X+]#X#Y2r#Y#o+]5i6S+]~2wTQ~!Q![+k#T#W+]#W#X3W#X#o+]5i6S+]~3_R!r~Q~!Q![+k#T#o+]5i6S+]~3mO`~~3rOh~~3wOa~~3|O{~~4RO^~~4WOb~~4]O!Q~~4bO!P~~4gO}~~4lO!O~~4qO!a~~4vO[~~4{Og~~5QOq~~5VO!R~~5[O]~~5aOY~~5fOy~~5kOx~~5pOv~~5uOt~~5zOs~~6POr~", tokenizers: [0, 1], - topRules: {"Expression":[0,1]}, + topRules: { Expression: [0, 1] }, tokenPrec: 1720 -}) +}); diff --git a/rsconcept/frontend/src/features/rsform/components/select-multi-grammeme.tsx b/rsconcept/frontend/src/features/rsform/components/select-multi-grammeme.tsx index 5fe48a94..6f0c2ff7 100644 --- a/rsconcept/frontend/src/features/rsform/components/select-multi-grammeme.tsx +++ b/rsconcept/frontend/src/features/rsform/components/select-multi-grammeme.tsx @@ -12,9 +12,9 @@ interface SelectMultiGrammemeProps extends Omit Object.values(Grammeme).includes(data.value as Grammeme)).map(data => data.value as Grammeme) + value.filter(data => Object.values(Grammeme).includes(data.value)).map(data => data.value) ); - const options = supportedGrammeOptions.filter(({ value }) => compatible.includes(value as Grammeme)); + const options = supportedGrammeOptions.filter(({ value }) => compatible.includes(value)); return ( grams.includes(value as Grammeme))); + onChange(supportedGrammeOptions.filter(({ value }) => grams.includes(value))); } return ( @@ -47,7 +47,7 @@ export function SelectWordForm({ value, onChange, className, ...restProps }: Sel text={data.text} example={data.example} grams={data.grams} - isSelected={data.grams.every(gram => value.find(item => (item.value as Grammeme) === gram))} + isSelected={data.grams.every(gram => value.find(item => item.value === gram))} onSelectGrams={handleSelect} /> ))} diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/dlg-cst-template.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/dlg-cst-template.tsx index 274edbdc..12e90992 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/dlg-cst-template.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-cst-template/dlg-cst-template.tsx @@ -27,11 +27,12 @@ export interface DlgCstTemplateProps { insertAfter?: number; } -enum TabID { - TEMPLATE = 0, - ARGUMENTS = 1, - CONSTITUENTA = 2 -} +export const TabID = { + TEMPLATE: 0, + ARGUMENTS: 1, + CONSTITUENTA: 2 +} as const; +export type TabID = (typeof TabID)[keyof typeof TabID]; export function DlgCstTemplate() { const { schema, onCreate, insertAfter } = useDialogsStore(state => state.props as DlgCstTemplateProps); @@ -54,7 +55,7 @@ export function DlgCstTemplate() { const cst_type = useWatch({ control: methods.control, name: 'cst_type' }); const isValid = validateNewAlias(alias, cst_type, schema); - const [activeTab, setActiveTab] = useState(TabID.TEMPLATE); + const [activeTab, setActiveTab] = useState(TabID.TEMPLATE); function onSubmit(data: ICstCreateDTO) { return cstCreate({ itemID: schema.id, data }).then(onCreate); @@ -69,7 +70,12 @@ export function DlgCstTemplate() { onSubmit={event => void methods.handleSubmit(onSubmit)(event)} helpTopic={HelpTopic.RSL_TEMPLATES} > - + setActiveTab(index as TabID)} + > diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-reference/dlg-edit-reference.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-reference/dlg-edit-reference.tsx index a951c360..70d0910b 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-reference/dlg-edit-reference.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-reference/dlg-edit-reference.tsx @@ -12,7 +12,7 @@ import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs'; import { useDialogsStore } from '@/stores/dialogs'; import { labelReferenceType } from '../../labels'; -import { type IReference, ReferenceType } from '../../models/language'; +import { type IReference, ReferenceType, schemaGrammemeOption, schemaReferenceType } from '../../models/language'; import { parseEntityReference, parseGrammemes, @@ -34,10 +34,10 @@ export interface IReferenceInputState { const schemaEditReferenceState = z .object({ - type: z.nativeEnum(ReferenceType), + type: schemaReferenceType, entity: z.strictObject({ entity: z.string(), - grams: z.array(z.strictObject({ value: z.string(), label: z.string() })) + grams: z.array(schemaGrammemeOption) }), syntactic: z.strictObject({ offset: z.coerce.number(), nominal: z.string() }) }) @@ -56,10 +56,11 @@ export interface DlgEditReferenceProps { onCancel: () => void; } -enum TabID { - ENTITY = 0, - SYNTACTIC = 1 -} +const TabID = { + ENTITY: 0, + SYNTACTIC: 1 +} as const; +type TabID = (typeof TabID)[keyof typeof TabID]; export function DlgEditReference() { const { initial, onSave, onCancel } = useDialogsStore(state => state.props as DlgEditReferenceProps); @@ -89,9 +90,9 @@ export function DlgEditReference() { } } - function handleChangeTab(tab: TabID) { + function handleChangeTab(tab: number) { methods.setValue('type', tab === TabID.ENTITY ? ReferenceType.ENTITY : ReferenceType.SYNTACTIC); - setActiveTab(tab); + setActiveTab(tab as TabID); } return ( diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-word-forms/dlg-edit-word-forms.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-word-forms/dlg-edit-word-forms.tsx index e54690f4..4ffd53cc 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-word-forms/dlg-edit-word-forms.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-edit-word-forms/dlg-edit-word-forms.tsx @@ -17,7 +17,7 @@ import { useIsProcessingCctext } from '../../backend/cctext/use-is-processing-cc import { useParseText } from '../../backend/cctext/use-parse-text'; import { useCstUpdate } from '../../backend/use-cst-update'; import { SelectMultiGrammeme } from '../../components/select-multi-grammeme'; -import { type Grammeme, type IGrammemeOption, type IWordForm, supportedGrammemes } from '../../models/language'; +import { type IGrammemeOption, type IWordForm, supportedGrammemes } from '../../models/language'; import { parseGrammemes, supportedGrammeOptions, wordFormEquals } from '../../models/language-api'; import { type IConstituenta } from '../../models/rsform'; @@ -98,9 +98,7 @@ export function DlgEditWordForms() { void generateLexeme({ text: inputText }).then(response => { const lexeme: IWordForm[] = []; response.items.forEach(form => { - const grams = parseGrammemes(form.grams).filter(gram => - supportedGrammemes.find(item => item === (gram as Grammeme)) - ); + const grams = parseGrammemes(form.grams).filter(gram => supportedGrammemes.find(item => item === gram)); const newForm: IWordForm = { text: form.text, grams: grams diff --git a/rsconcept/frontend/src/features/rsform/dialogs/dlg-inline-synthesis/dlg-inline-synthesis.tsx b/rsconcept/frontend/src/features/rsform/dialogs/dlg-inline-synthesis/dlg-inline-synthesis.tsx index 9e9a8db4..382891f0 100644 --- a/rsconcept/frontend/src/features/rsform/dialogs/dlg-inline-synthesis/dlg-inline-synthesis.tsx +++ b/rsconcept/frontend/src/features/rsform/dialogs/dlg-inline-synthesis/dlg-inline-synthesis.tsx @@ -22,15 +22,16 @@ export interface DlgInlineSynthesisProps { onSynthesis: () => void; } -enum TabID { - SCHEMA = 0, - SELECTIONS = 1, - SUBSTITUTIONS = 2 -} +export const TabID = { + SCHEMA: 0, + SELECTIONS: 1, + SUBSTITUTIONS: 2 +} as const; +export type TabID = (typeof TabID)[keyof typeof TabID]; export function DlgInlineSynthesis() { const { receiver, onSynthesis } = useDialogsStore(state => state.props as DlgInlineSynthesisProps); - const [activeTab, setActiveTab] = useState(TabID.SCHEMA); + const [activeTab, setActiveTab] = useState(TabID.SCHEMA); const { inlineSynthesis } = useInlineSynthesis(); const methods = useForm({ @@ -57,7 +58,12 @@ export function DlgInlineSynthesis() { canSubmit={methods.formState.isValid && sourceID !== null} onSubmit={event => void methods.handleSubmit(onSubmit)(event)} > - + setActiveTab(index as TabID)} + > { expect(wordFormEquals({ text: '', grams: ['nomn', 'sing'] }, { text: '', grams: ['nomn'] })).toEqual(false); expect(wordFormEquals({ text: '', grams: ['nomn', 'nomn'] }, { text: '', grams: ['nomn'] })).toEqual(false); }); - - test('custom grammemes', () => { - expect(wordFormEquals({ text: '', grams: ['с1'] }, { text: '', grams: ['с1'] })).toEqual(true); - expect(wordFormEquals({ text: '', grams: ['с1'] }, { text: '', grams: ['с2'] })).toEqual(false); - expect(wordFormEquals({ text: '', grams: ['sing'] }, { text: '', grams: ['с1'] })).toEqual(false); - }); }); describe('Testing grammeme ordering', () => { - test('empty input', () => { - expect(grammemeCompare('', '')).toEqual(0); - expect(grammemeCompare(' ', ' ')).toEqual(0); - expect(grammemeCompare('', '123')).toBeLessThan(0); - expect(grammemeCompare('123', '')).toBeGreaterThan(0); - }); - test('regular grammemes', () => { expect(grammemeCompare('NOUN', 'NOUN')).toEqual(0); expect(grammemeCompare('NOUN', Grammeme.NOUN)).toEqual(0); @@ -75,16 +62,6 @@ describe('Testing grammeme ordering', () => { expect(grammemeCompare('datv', 'gent')).toBeGreaterThan(0); expect(grammemeCompare('gent', 'nomn')).toBeGreaterThan(0); }); - - test('custom grammemes', () => { - expect(grammemeCompare('noun', 'noun')).toEqual(0); - expect(grammemeCompare('NOUN', 'noun')).toBeLessThan(0); - expect(grammemeCompare('PRTF', 'noun')).toBeLessThan(0); - expect(grammemeCompare('noun', 'NOUN')).toBeGreaterThan(0); - expect(grammemeCompare('aab', 'aaa')).toBeGreaterThan(0); - expect(grammemeCompare('aaa', 'aab')).toBeLessThan(0); - expect(grammemeCompare('test', 'abcd')).toBeGreaterThan(0); - }); }); describe('Testing grammeme parsing', () => { diff --git a/rsconcept/frontend/src/features/rsform/models/language-api.ts b/rsconcept/frontend/src/features/rsform/models/language-api.ts index 3ac7a9db..e9968580 100644 --- a/rsconcept/frontend/src/features/rsform/models/language-api.ts +++ b/rsconcept/frontend/src/features/rsform/models/language-api.ts @@ -5,7 +5,6 @@ import { labelGrammeme } from '../labels'; import { - type GramData, Grammeme, GrammemeGroups, type IEntityReference, @@ -35,11 +34,11 @@ export function wordFormEquals(left: IWordForm, right: IWordForm): boolean { } /** - * Compares {@link GramData} based on Grammeme enum and alpha order for strings. + * Compares {@link Grammeme} based on Grammeme enum and alpha order for strings. */ -export function grammemeCompare(left: GramData, right: GramData): number { - const indexLeft = Object.values(Grammeme).findIndex(gram => gram === (left as Grammeme)); - const indexRight = Object.values(Grammeme).findIndex(gram => gram === (right as Grammeme)); +export function grammemeCompare(left: Grammeme, right: Grammeme): number { + const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left); + const indexRight = Object.values(Grammeme).findIndex(gram => gram === right); if (indexLeft === -1 && indexRight === -1) { return left.localeCompare(right); } else if (indexLeft === -1 && indexRight !== -1) { @@ -52,15 +51,15 @@ export function grammemeCompare(left: GramData, right: GramData): number { } /** - * Transforms {@link Grammeme} enumeration to {@link GramData}. + * Transforms {@link Grammeme} enumeration to {@link Grammeme}. */ -export function parseGrammemes(termForm: string): GramData[] { - const result: GramData[] = []; +export function parseGrammemes(termForm: string): Grammeme[] { + const result: Grammeme[] = []; const chunks = termForm.split(','); chunks.forEach(chunk => { const gram = chunk.trim(); if (gram !== '') { - result.push(gram); + result.push(gram as Grammeme); } }); return result.sort(grammemeCompare); diff --git a/rsconcept/frontend/src/features/rsform/models/language.ts b/rsconcept/frontend/src/features/rsform/models/language.ts index 78a6d9eb..5d061925 100644 --- a/rsconcept/frontend/src/features/rsform/models/language.ts +++ b/rsconcept/frontend/src/features/rsform/models/language.ts @@ -8,64 +8,66 @@ import { z } from 'zod'; * Represents single unit of language Morphology. */ // prettier-ignore -export enum Grammeme { +export const Grammeme = { // Части речи - NOUN = 'NOUN', ADJF = 'ADJF', ADJS = 'ADJS', COMP = 'COMP', - VERB = 'VERB', INFN = 'INFN', PRTF = 'PRTF', PRTS = 'PRTS', - GRND = 'GRND', NUMR = 'NUMR', ADVB = 'ADVB', NPRO = 'NPRO', - PRED = 'PRED', PREP = 'PREP', CONJ = 'CONJ', PRCL = 'PRCL', - INTJ = 'INTJ', + NOUN: 'NOUN', ADJF: 'ADJF', ADJS: 'ADJS', COMP: 'COMP', + VERB: 'VERB', INFN: 'INFN', PRTF: 'PRTF', PRTS: 'PRTS', + GRND: 'GRND', NUMR: 'NUMR', ADVB: 'ADVB', NPRO: 'NPRO', + PRED: 'PRED', PREP: 'PREP', CONJ: 'CONJ', PRCL: 'PRCL', + INTJ: 'INTJ', // Одушевленность - anim = 'anim', inan = 'inan', + anim: 'anim', inan: 'inan', // Род - masc = 'masc', femn = 'femn', neut = 'neut', + masc: 'masc', femn: 'femn', neut: 'neut', // Число - sing = 'sing', plur = 'plur', + sing: 'sing', plur: 'plur', // Падеж (основные) - nomn = 'nomn', gent = 'gent', datv = 'datv', - accs = 'accs', ablt = 'ablt', loct = 'loct', + nomn: 'nomn', gent: 'gent', datv: 'datv', + accs: 'accs', ablt: 'ablt', loct: 'loct', // Совершенный / несовершенный вид - perf = 'perf', impf = 'impf', + perf: 'perf', impf: 'impf', // Переходность - tran = 'tran', intr = 'intr', + tran: 'tran', intr: 'intr', // Время - pres = 'pres', past = 'past', futr = 'futr', + pres: 'pres', past: 'past', futr: 'futr', // Лицо - per1 = '1per', per2 = '2per', per3 = '3per', + per1: '1per', per2: '2per', per3: '3per', // Наклонение - indc = 'indc', impr = 'impr', + indc: 'indc', impr: 'impr', // Включение говорящего в действие - incl = 'incl', excl = 'excl', + incl: 'incl', excl: 'excl', // Залог - actv = 'actv', pssv = 'pssv', + actv: 'actv', pssv: 'pssv', // Стиль речи - Infr = 'Infr', // Неформальный - Slng = 'Slng', // Жаргон - Arch = 'Arch', // Устаревший - Litr = 'Litr', // Литературный + Infr: 'Infr', // Неформальный + Slng: 'Slng', // Жаргон + Arch: 'Arch', // Устаревший + Litr: 'Litr', // Литературный // Аббревиатура - Abbr = 'Abbr' -} + Abbr: 'Abbr' +} as const; +export type Grammeme = (typeof Grammeme)[keyof typeof Grammeme]; +export const schemaGrammeme = z.enum(Object.values(Grammeme) as [Grammeme, ...Grammeme[]]); /** * Represents part of speech language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const PartOfSpeech = [ +export const PartOfSpeech: Grammeme[] = [ Grammeme.NOUN, Grammeme.ADJF, Grammeme.ADJS, @@ -82,84 +84,91 @@ export const PartOfSpeech = [ Grammeme.CONJ, Grammeme.PRCL, Grammeme.INTJ -]; +] as const; /** * Represents gender language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Gender = [Grammeme.masc, Grammeme.femn, Grammeme.neut]; +export const Gender: Grammeme[] = [Grammeme.masc, Grammeme.femn, Grammeme.neut] as const; /** * Represents case language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Case = [Grammeme.nomn, Grammeme.gent, Grammeme.datv, Grammeme.accs, Grammeme.ablt, Grammeme.loct]; +export const Case: Grammeme[] = [ + Grammeme.nomn, + Grammeme.gent, + Grammeme.datv, + Grammeme.accs, + Grammeme.ablt, + Grammeme.loct +] as const; /** * Represents plurality language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Plurality = [Grammeme.sing, Grammeme.plur]; +export const Plurality: Grammeme[] = [Grammeme.sing, Grammeme.plur] as const; /** * Represents verb perfectivity language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Perfectivity = [Grammeme.perf, Grammeme.impf]; +export const Perfectivity: Grammeme[] = [Grammeme.perf, Grammeme.impf] as const; /** * Represents verb transitivity language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Transitivity = [Grammeme.tran, Grammeme.intr]; +export const Transitivity: Grammeme[] = [Grammeme.tran, Grammeme.intr] as const; /** * Represents verb mood language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Mood = [Grammeme.indc, Grammeme.impr]; +export const Mood: Grammeme[] = [Grammeme.indc, Grammeme.impr] as const; /** * Represents verb self-inclusion language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Inclusion = [Grammeme.incl, Grammeme.excl]; +export const Inclusion: Grammeme[] = [Grammeme.incl, Grammeme.excl] as const; /** * Represents verb voice language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Voice = [Grammeme.actv, Grammeme.pssv]; +export const Voice: Grammeme[] = [Grammeme.actv, Grammeme.pssv] as const; /** * Represents verb tense language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Tense = [Grammeme.pres, Grammeme.past, Grammeme.futr]; +export const Tense: Grammeme[] = [Grammeme.pres, Grammeme.past, Grammeme.futr] as const; /** * Represents verb person language concept. * * Implemented as a list of mutually exclusive {@link Grammeme}s. */ -export const Person = [Grammeme.per1, Grammeme.per2, Grammeme.per3]; +export const Person: Grammeme[] = [Grammeme.per1, Grammeme.per2, Grammeme.per3] as const; /** * Represents complete list of language concepts. * * Implemented as a list of lists of {@link Grammeme}s. */ -export const GrammemeGroups = [ +export const GrammemeGroups: Grammeme[][] = [ PartOfSpeech, Gender, Case, @@ -171,7 +180,7 @@ export const GrammemeGroups = [ Voice, Tense, Person -]; +] as const; /** * Represents NOUN-ish list of language concepts. @@ -180,7 +189,7 @@ export const GrammemeGroups = [ * * Implemented as a list of lists of {@link Grammeme}s. */ -export const NounGrams = [Grammeme.NOUN, Grammeme.ADJF, Grammeme.ADJS, ...Case, ...Plurality]; +export const NounGrams: Grammeme[] = [Grammeme.NOUN, Grammeme.ADJF, Grammeme.ADJS, ...Case, ...Plurality] as const; /** * Represents VERB-ish list of language concepts. @@ -201,19 +210,14 @@ export const VerbGrams = [ ...Voice, ...Tense, ...Person -]; - -/** - * Represents {@link Grammeme} parse data. - */ -export type GramData = Grammeme | string; +] as const; /** * Represents specific wordform attached to {@link Grammeme}s. */ export interface IWordForm { text: string; - grams: GramData[]; + grams: Grammeme[]; } /** @@ -224,51 +228,45 @@ export const supportedGrammemes = [ Grammeme.sing, Grammeme.plur, Grammeme.nomn, Grammeme.gent, Grammeme.datv, Grammeme.accs, Grammeme.ablt, Grammeme.loct, -]; +] as const; -/** - * Represents single option for {@link Grammeme} selector. - */ -export interface IGrammemeOption { - value: GramData; - label: string; -} +export const schemaGrammemeOption = z.strictObject({ + value: schemaGrammeme, + label: z.string() +}); + +export type IGrammemeOption = z.infer; // ====== Reference resolution ===== -/** - * Represents text reference type. - */ -export enum ReferenceType { - ENTITY = 'entity', - SYNTACTIC = 'syntax' -} +/** Represents text reference type. */ +export const ReferenceType = { + ENTITY: 'entity', + SYNTACTIC: 'syntax' +} as const; +export type ReferenceType = (typeof ReferenceType)[keyof typeof ReferenceType]; -/** - * Represents entity reference payload. - */ +/** Represents entity reference payload. */ export interface IEntityReference { entity: string; form: string; } -/** - * Represents syntactic reference payload. - */ +/** Represents syntactic reference payload. */ export interface ISyntacticReference { offset: number; nominal: string; } +export const schemaReferenceType = z.enum(Object.values(ReferenceType) as [ReferenceType, ...ReferenceType[]]); + export const schemaReference = z.strictObject({ - type: z.nativeEnum(ReferenceType), + type: schemaReferenceType, data: z.union([ z.strictObject({ entity: z.string(), form: z.string() }), z.strictObject({ offset: z.number(), nominal: z.string() }) ]) }); -/** - * Represents abstract reference data. - */ +/** Represents abstract reference data. */ export type IReference = z.infer; diff --git a/rsconcept/frontend/src/features/rsform/models/rsform.ts b/rsconcept/frontend/src/features/rsform/models/rsform.ts index e3923927..b3bcb144 100644 --- a/rsconcept/frontend/src/features/rsform/models/rsform.ts +++ b/rsconcept/frontend/src/features/rsform/models/rsform.ts @@ -14,39 +14,33 @@ import { type IArgumentInfo } from './rslang'; // CstType constant for category dividers in TemplateSchemas export const CATEGORY_CST_TYPE = CstType.THEOREM; -/** - * Represents Constituenta classification in terms of system of concepts. - */ -export enum CstClass { - BASIC = 'basic', - DERIVED = 'derived', - STATEMENT = 'statement', - TEMPLATE = 'template' -} +/** Represents Constituenta classification in terms of system of concepts. */ +export const CstClass = { + BASIC: 'basic', + DERIVED: 'derived', + STATEMENT: 'statement', + TEMPLATE: 'template' +} as const; +export type CstClass = (typeof CstClass)[keyof typeof CstClass]; -/** - * Represents formal expression Status. - */ -export enum ExpressionStatus { - VERIFIED = 'verified', - INCORRECT = 'incorrect', - INCALCULABLE = 'incalculable', - PROPERTY = 'property', - UNDEFINED = 'undefined', - UNKNOWN = 'unknown' -} +/** Represents formal expression Status. */ +export const ExpressionStatus = { + VERIFIED: 'verified', + INCORRECT: 'incorrect', + INCALCULABLE: 'incalculable', + PROPERTY: 'property', + UNDEFINED: 'undefined', + UNKNOWN: 'unknown' +} as const; +export type ExpressionStatus = (typeof ExpressionStatus)[keyof typeof ExpressionStatus]; -/** - * Represents word form for natural language. - */ +/** Represents word form for natural language. */ export interface TermForm { text: string; tags: string; } -/** - * Represents Constituenta. - */ +/** Represents Constituenta. */ export interface IConstituenta { id: number; alias: string; @@ -101,9 +95,7 @@ export interface IConstituenta { spawn_alias: string[]; } -/** - * Represents {@link IRSForm} statistics. - */ +/** Represents {@link IRSForm} statistics. */ export interface IRSFormStats { count_all: number; count_errors: number; @@ -125,9 +117,7 @@ export interface IRSFormStats { count_theorem: number; } -/** - * Represents inheritance data for {@link IRSForm}. - */ +/** Represents inheritance data for {@link IRSForm}. */ export interface IInheritanceInfo { child: number; child_source: number; @@ -135,9 +125,7 @@ export interface IInheritanceInfo { parent_source: number; } -/** - * Represents formal explication for set of concepts. - */ +/** Represents formal explication for set of concepts. */ export interface IRSForm extends ILibraryItemData { version: CurrentVersion; versions: IVersionInfo[]; diff --git a/rsconcept/frontend/src/features/rsform/models/rslang.ts b/rsconcept/frontend/src/features/rsform/models/rslang.ts index 849feb52..a4b801a8 100644 --- a/rsconcept/frontend/src/features/rsform/models/rslang.ts +++ b/rsconcept/frontend/src/features/rsform/models/rslang.ts @@ -2,20 +2,14 @@ * Module: Models for RSLanguage. */ -import { type TokenID } from '../backend/types'; - -/** - * Represents alias mapping. - */ +/** Represents alias mapping. */ export type AliasMapping = Record; -/** - * Represents AST node. - */ +/** Represents AST node. */ export interface ISyntaxTreeNode { uid: number; parent: number; - typeID: TokenID; + typeID: number; start: number; finish: number; data: { @@ -24,14 +18,10 @@ export interface ISyntaxTreeNode { }; } -/** - * Represents Syntax tree for RSLang expression. - */ +/** Represents Syntax tree for RSLang expression. */ export type SyntaxTree = ISyntaxTreeNode[]; -/** - * Represents function argument definition. - */ +/** Represents function argument definition. */ export interface IArgumentInfo { alias: string; typification: string; @@ -44,17 +34,16 @@ export interface ITypeInfo { args: IArgumentInfo[]; } -/** - * Represents function argument value. - */ +/** Represents function argument value. */ export interface IArgumentValue extends IArgumentInfo { value?: string; } /** Represents error class. */ -export enum RSErrorClass { - LEXER, - PARSER, - SEMANTIC, - UNKNOWN -} +export const RSErrorClass = { + LEXER: 0, + PARSER: 1, + SEMANTIC: 2, + UNKNOWN: 3 +} as const; +export type RSErrorClass = (typeof RSErrorClass)[keyof typeof RSErrorClass]; diff --git a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsedit-context.tsx b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsedit-context.tsx index 322fb9b3..ff086975 100644 --- a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsedit-context.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsedit-context.tsx @@ -22,12 +22,13 @@ import { useRSFormSuspense } from '../../backend/use-rsform'; import { type IConstituenta, type IRSForm } from '../../models/rsform'; import { generateAlias } from '../../models/rsform-api'; -export enum RSTabID { - CARD = 0, - CST_LIST = 1, - CST_EDIT = 2, - TERM_GRAPH = 3 -} +export const RSTabID = { + CARD: 0, + CST_LIST: 1, + CST_EDIT: 2, + TERM_GRAPH: 3 +} as const; +export type RSTabID = (typeof RSTabID)[keyof typeof RSTabID]; export interface IRSEditContext { schema: IRSForm; diff --git a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsform-page.tsx b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsform-page.tsx index b9db2ae5..050ae3e8 100644 --- a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsform-page.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rsform-page.tsx @@ -17,7 +17,7 @@ import { useModificationStore } from '@/stores/modification'; import { ConstituentaTooltip } from '../../components/constituenta-tooltip'; import { RSEditState, RSTabID } from './rsedit-context'; -import { RSTabs } from './rstabs1'; +import { RSTabs } from './rstabs'; const paramsSchema = z.strictObject({ id: z.coerce.number(), diff --git a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs1.tsx b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs.tsx similarity index 96% rename from rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs1.tsx rename to rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs.tsx index 25c184f7..c7d3ddef 100644 --- a/rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs1.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/rsform-page/rstabs.tsx @@ -66,7 +66,7 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) { } } } - navigateRSForm({ tab: index, activeID: selected.length > 0 ? selected.at(-1) : undefined }); + navigateRSForm({ tab: index as RSTabID, activeID: selected.length > 0 ? selected.at(-1) : undefined }); } return ( diff --git a/rsconcept/frontend/src/features/rsform/stores/cst-search.ts b/rsconcept/frontend/src/features/rsform/stores/cst-search.ts index 3f4e1715..b546e8e4 100644 --- a/rsconcept/frontend/src/features/rsform/stores/cst-search.ts +++ b/rsconcept/frontend/src/features/rsform/stores/cst-search.ts @@ -1,27 +1,25 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -/** - * Represents graph dependency mode. - */ -export enum DependencyMode { - ALL = 0, - OUTPUTS, - INPUTS, - EXPAND_OUTPUTS, - EXPAND_INPUTS -} +/** Represents graph dependency mode. */ +export const DependencyMode = { + ALL: 0, + OUTPUTS: 1, + INPUTS: 2, + EXPAND_OUTPUTS: 3, + EXPAND_INPUTS: 4 +} as const; +export type DependencyMode = (typeof DependencyMode)[keyof typeof DependencyMode]; -/** - * Represents {@link IConstituenta} matching mode. - */ -export enum CstMatchMode { - ALL = 1, - EXPR, - TERM, - TEXT, - NAME -} +/** Represents {@link IConstituenta} matching mode. */ +export const CstMatchMode = { + ALL: 1, + EXPR: 2, + TERM: 3, + TEXT: 4, + NAME: 5 +} as const; +export type CstMatchMode = (typeof CstMatchMode)[keyof typeof CstMatchMode]; interface CstSearchStore { query: string; diff --git a/rsconcept/frontend/src/features/users/stores/role.ts b/rsconcept/frontend/src/features/users/stores/role.ts index 2f7b1e4b..495e30ba 100644 --- a/rsconcept/frontend/src/features/users/stores/role.ts +++ b/rsconcept/frontend/src/features/users/stores/role.ts @@ -1,15 +1,15 @@ import { create } from 'zustand'; -/** - * Represents user access mode. - */ -export enum UserRole { - READER = 0, - EDITOR, - OWNER, - ADMIN -} +/** Represents user access mode. */ +export const UserRole = { + READER: 0, + EDITOR: 1, + OWNER: 2, + ADMIN: 3 +} as const; +export type UserRole = (typeof UserRole)[keyof typeof UserRole]; +/** Represents user access mode flags. */ export interface RoleFlags { isOwner: boolean; isEditor: boolean; diff --git a/rsconcept/frontend/src/stores/dialogs.ts b/rsconcept/frontend/src/stores/dialogs.ts index c2632e29..9287e252 100644 --- a/rsconcept/frontend/src/stores/dialogs.ts +++ b/rsconcept/frontend/src/stores/dialogs.ts @@ -23,34 +23,33 @@ import { type DlgShowTypeGraphProps } from '@/features/rsform/dialogs/dlg-show-t import { type DlgSubstituteCstProps } from '@/features/rsform/dialogs/dlg-substitute-cst'; import { type DlgUploadRSFormProps } from '@/features/rsform/dialogs/dlg-upload-rsform'; -/** - * Represents global dialog. - */ -export enum DialogType { - CONSTITUENTA_TEMPLATE = 1, - CREATE_CONSTITUENTA, - CREATE_OPERATION, - DELETE_CONSTITUENTA, - EDIT_EDITORS, - EDIT_OPERATION, - EDIT_REFERENCE, - EDIT_VERSIONS, - EDIT_WORD_FORMS, - INLINE_SYNTHESIS, - SHOW_AST, - SHOW_TYPE_GRAPH, - CHANGE_INPUT_SCHEMA, - CHANGE_LOCATION, - CLONE_LIBRARY_ITEM, - CREATE_VERSION, - DELETE_OPERATION, - GRAPH_PARAMETERS, - RELOCATE_CONSTITUENTS, - RENAME_CONSTITUENTA, - SHOW_QR_CODE, - SUBSTITUTE_CONSTITUENTS, - UPLOAD_RSFORM -} +/** Represents global dialog. */ +export const DialogType = { + CONSTITUENTA_TEMPLATE: 1, + CREATE_CONSTITUENTA: 2, + CREATE_OPERATION: 3, + DELETE_CONSTITUENTA: 4, + EDIT_EDITORS: 5, + EDIT_OPERATION: 6, + EDIT_REFERENCE: 7, + EDIT_VERSIONS: 8, + EDIT_WORD_FORMS: 9, + INLINE_SYNTHESIS: 10, + SHOW_AST: 11, + SHOW_TYPE_GRAPH: 12, + CHANGE_INPUT_SCHEMA: 13, + CHANGE_LOCATION: 14, + CLONE_LIBRARY_ITEM: 15, + CREATE_VERSION: 16, + DELETE_OPERATION: 17, + GRAPH_PARAMETERS: 18, + RELOCATE_CONSTITUENTS: 19, + RENAME_CONSTITUENTA: 20, + SHOW_QR_CODE: 21, + SUBSTITUTE_CONSTITUENTS: 22, + UPLOAD_RSFORM: 23 +} as const; +export type DialogType = (typeof DialogType)[keyof typeof DialogType]; interface DialogProps { onHide?: () => void; diff --git a/rsconcept/frontend/tests/mocks/auth.ts b/rsconcept/frontend/tests/mocks/auth.ts index 4f0ecd6d..5072a86a 100644 --- a/rsconcept/frontend/tests/mocks/auth.ts +++ b/rsconcept/frontend/tests/mocks/auth.ts @@ -1,6 +1,6 @@ import { type Page } from '@playwright/test'; -import { type ICurrentUser, IUserLoginDTO } from '../../src/features/auth/backend/types'; +import { type ICurrentUser, type IUserLoginDTO } from '../../src/features/auth/backend/types'; import { BACKEND_URL } from './constants'; const dataAnonymousAuth: ICurrentUser = { diff --git a/rsconcept/frontend/tsconfig.json b/rsconcept/frontend/tsconfig.json index 6a2810eb..de91534a 100644 --- a/rsconcept/frontend/tsconfig.json +++ b/rsconcept/frontend/tsconfig.json @@ -7,14 +7,17 @@ "skipLibCheck": true, "esModuleInterop": true, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, + /* Language features */ + "erasableSyntaxOnly": true, "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true, "jsx": "react-jsx", + /* Bundler mode */ + "allowImportingTsExtensions": true, + "moduleResolution": "bundler", + "noEmit": true, + /* Linting */ "strict": true, "noUnusedLocals": true,