tycho-components 0.26.1 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,8 @@ export { DocumentStatusNames } from './types/Document';
12
12
  export type { DocumentStatus, default as Document } from './types/Document';
13
13
  export { CorpusImageTypeNames } from './types/CorpusImage';
14
14
  export type { CorpusImage, CorpusImageType } from './types/CorpusImage';
15
- export { EditionTiers } from './types/EditionTiers';
15
+ export { DEFAULT_EDITION_TIERS, EditionTiers, StructuralEditionTiers, isStructuralEditionTier, } from './types/EditionTiers';
16
+ export type { EditionGroup, EditionTierDefinition, EditionTierGroup, EditionTierSymbol, } from './types/EditionTiers';
16
17
  export type { Parameter, ParameterType } from './types/Parameter';
17
18
  export { SentenceStatusNames } from './types/SentenceStatus';
18
19
  export type { SentenceStatus } from './types/SentenceStatus';
@@ -8,7 +8,7 @@ export { default as ProfileService } from './services/ProfileService';
8
8
  export { CorpusStatusNames } from './types/CorpusStatus';
9
9
  export { DocumentStatusNames } from './types/Document';
10
10
  export { CorpusImageTypeNames } from './types/CorpusImage';
11
- export { EditionTiers } from './types/EditionTiers';
11
+ export { DEFAULT_EDITION_TIERS, EditionTiers, StructuralEditionTiers, isStructuralEditionTier, } from './types/EditionTiers';
12
12
  export { SentenceStatusNames } from './types/SentenceStatus';
13
13
  export { UserStatusNames } from './types/User';
14
14
  export { useCorpusUtils } from './useCorpusUtils';
@@ -27,8 +27,8 @@ export const ParametersTexts = {
27
27
  "parameter.tooltip.useParticipantChat": "With this feature enabled, it is possible to add extra standard attributes to participants of transcriptions, as defined by the CHAT format com CHILDES project.",
28
28
  "parameter.field.useSplit": "Enable Morpheme Edition",
29
29
  "parameter.tooltip.useSplit": "Enables the use of fields related to morphemes in the corpora.",
30
- "parameter.field.useEditionTiers": "Enable Default Edition Tiers",
31
- "parameter.tooltip.useEditionTiers": "Enables the use of edition tiers to ensure maximum philological fidelity of the text.",
30
+ "parameter.field.useEditionTiers": "Enable Edition Tiers",
31
+ "parameter.tooltip.useEditionTiers": "Enables edition operations in the editor, including junction, segmentation, and configurable corpus edition tiers.",
32
32
  "parameter.field.allowPosTagInclusion": "Allow POS Tag inclusion",
33
33
  "parameter.tooltip.allowPosTagInclusion": "With this feature enabled, it is possible to add new POS tags to the list while editing sentences in the editor. A parser must be associated to the corpus.",
34
34
  "parameter.field.useGrid": "Display Documents in Grid",
@@ -67,8 +67,8 @@ export const ParametersTexts = {
67
67
  "parameter.tooltip.useParticipantChat": "Com este recurso habilitado, é possível adicionar atributos padrão extras aos participantes de transcrições, conforme definido pelo formato CHAT com o projeto CHILDES.",
68
68
  "parameter.field.useSplit": "Habilitar Edição de Morfema",
69
69
  "parameter.tooltip.useSplit": "Habilita o uso de campos relacionados a morfemas nos corpora.",
70
- "parameter.field.useEditionTiers": "Habilitar Níveis de Edição Padrão",
71
- "parameter.tooltip.useEditionTiers": "Habilita o uso de níveis de edição para garantir máxima fidelidade filológica do texto.",
70
+ "parameter.field.useEditionTiers": "Habilitar Níveis de Edição",
71
+ "parameter.tooltip.useEditionTiers": "Habilita operações de edição no editor, incluindo junção, segmentação e níveis de edição configuráveis do corpus.",
72
72
  "parameter.field.allowPosTagInclusion": "Permitir Inclusão de Tag POS",
73
73
  "parameter.tooltip.allowPosTagInclusion": "Com este recurso habilitado, é possível adicionar novas tags POS à lista durante a edição de frases no editor. Um parser deve estar associado ao corpus.",
74
74
  "parameter.field.useGrid": "Exibir Documentos em Grade",
@@ -107,8 +107,8 @@ export const ParametersTexts = {
107
107
  "parameter.tooltip.useParticipantChat": "Con questa funzione abilitata, è possibile aggiungere attributi standard extra ai partecipanti delle trascrizioni, come definito dal formato CHAT con il progetto CHILDES.",
108
108
  "parameter.field.useSplit": "Abilita Modifica Morfemi",
109
109
  "parameter.tooltip.useSplit": "Abilita l'uso di campi relativi ai morfemi nei corpora.",
110
- "parameter.field.useEditionTiers": "Abilita Livelli di Edizione Predefiniti",
111
- "parameter.tooltip.useEditionTiers": "Abilita l'uso di livelli di edizione per garantire la massima fedeltà filologica del testo.",
110
+ "parameter.field.useEditionTiers": "Abilita Livelli di Edizione",
111
+ "parameter.tooltip.useEditionTiers": "Abilita le operazioni di edizione nell'editor, inclusi giunzione, segmentazione e livelli di edizione configurabili del corpus.",
112
112
  "parameter.field.allowPosTagInclusion": "Permetti Inclusione Tag POS",
113
113
  "parameter.tooltip.allowPosTagInclusion": "Con questa funzione abilitata, è possibile aggiungere nuovi tag POS all'elenco durante l'editing delle frasi in editor. Un parser deve essere associato al corpus.",
114
114
  "parameter.field.useGrid": "Visualizza Documenti a Griglia",
@@ -1,5 +1,6 @@
1
1
  import { CorpusImage } from './CorpusImage';
2
2
  import { CorpusStatus } from './CorpusStatus';
3
+ import { EditionTierDefinition } from './EditionTiers';
3
4
  import { User } from './User';
4
5
  export type Corpus = {
5
6
  id?: number;
@@ -8,6 +9,7 @@ export type Corpus = {
8
9
  picture: string;
9
10
  uploadDir: string;
10
11
  parameters: Record<string, any>;
12
+ editionTiers?: EditionTierDefinition[];
11
13
  status: CorpusStatus;
12
14
  opened: boolean;
13
15
  featured?: boolean;
@@ -1,13 +1,36 @@
1
- export declare enum EditionTiers {
2
- ORIGINAL = "ori",
3
- JUNCTION = "jun",
4
- SEGMENTATION = "seg",
5
- SPELLING = "gra",
6
- EXPANSION = "exp",
7
- CORRECTION = "cor",
8
- PUNCTUATION = "pon",
9
- ILLEGIBLE = "ileg",
10
- MODERNIZATION = "mod",
11
- PADRONIZATION = "pad",
12
- INFLECTION = "fle"
13
- }
1
+ export type EditionTierGroup = 'semiDiplomatic' | 'modernized';
2
+ export type EditionTierDefinition = {
3
+ symbol: string;
4
+ label: string;
5
+ order: number;
6
+ group: EditionTierGroup;
7
+ abbreviation: boolean;
8
+ };
9
+ export declare const StructuralEditionTiers: {
10
+ readonly ORIGINAL: "ori";
11
+ readonly JUNCTION: "jun";
12
+ readonly SEGMENTATION: "seg";
13
+ };
14
+ /** Default configurable tier symbols (structural ops are excluded). */
15
+ export declare const EditionTiers: {
16
+ readonly ORIGINAL: "ori";
17
+ readonly JUNCTION: "jun";
18
+ readonly SEGMENTATION: "seg";
19
+ readonly SPELLING: "gra";
20
+ readonly EXPANSION: "exp";
21
+ readonly CORRECTION: "cor";
22
+ readonly PUNCTUATION: "pon";
23
+ readonly ILLEGIBLE: "ileg";
24
+ readonly MODERNIZATION: "mod";
25
+ readonly PADRONIZATION: "pad";
26
+ readonly INFLECTION: "fle";
27
+ };
28
+ export type EditionTierSymbol = (typeof EditionTiers)[keyof typeof EditionTiers];
29
+ export declare const DEFAULT_EDITION_TIERS: EditionTierDefinition[];
30
+ export type EditionGroup = {
31
+ id: string;
32
+ labelKey: string;
33
+ tiers: string[];
34
+ defaultTier: string;
35
+ };
36
+ export declare const isStructuralEditionTier: (symbol: string) => boolean;
@@ -1,14 +1,83 @@
1
- export var EditionTiers;
2
- (function (EditionTiers) {
3
- EditionTiers["ORIGINAL"] = "ori";
4
- EditionTiers["JUNCTION"] = "jun";
5
- EditionTiers["SEGMENTATION"] = "seg";
6
- EditionTiers["SPELLING"] = "gra";
7
- EditionTiers["EXPANSION"] = "exp";
8
- EditionTiers["CORRECTION"] = "cor";
9
- EditionTiers["PUNCTUATION"] = "pon";
10
- EditionTiers["ILLEGIBLE"] = "ileg";
11
- EditionTiers["MODERNIZATION"] = "mod";
12
- EditionTiers["PADRONIZATION"] = "pad";
13
- EditionTiers["INFLECTION"] = "fle";
14
- })(EditionTiers || (EditionTiers = {}));
1
+ export const StructuralEditionTiers = {
2
+ ORIGINAL: 'ori',
3
+ JUNCTION: 'jun',
4
+ SEGMENTATION: 'seg',
5
+ };
6
+ /** Default configurable tier symbols (structural ops are excluded). */
7
+ export const EditionTiers = {
8
+ ORIGINAL: 'ori',
9
+ JUNCTION: 'jun',
10
+ SEGMENTATION: 'seg',
11
+ SPELLING: 'gra',
12
+ EXPANSION: 'exp',
13
+ CORRECTION: 'cor',
14
+ PUNCTUATION: 'pon',
15
+ ILLEGIBLE: 'ileg',
16
+ MODERNIZATION: 'mod',
17
+ PADRONIZATION: 'pad',
18
+ INFLECTION: 'fle',
19
+ };
20
+ export const DEFAULT_EDITION_TIERS = [
21
+ {
22
+ symbol: EditionTiers.SPELLING,
23
+ label: 'Spelling',
24
+ order: 1,
25
+ group: 'semiDiplomatic',
26
+ abbreviation: false,
27
+ },
28
+ {
29
+ symbol: EditionTiers.EXPANSION,
30
+ label: 'Expansion',
31
+ order: 2,
32
+ group: 'semiDiplomatic',
33
+ abbreviation: true,
34
+ },
35
+ {
36
+ symbol: EditionTiers.CORRECTION,
37
+ label: 'Correction',
38
+ order: 3,
39
+ group: 'semiDiplomatic',
40
+ abbreviation: false,
41
+ },
42
+ {
43
+ symbol: EditionTiers.PUNCTUATION,
44
+ label: 'Punctuation',
45
+ order: 4,
46
+ group: 'semiDiplomatic',
47
+ abbreviation: false,
48
+ },
49
+ {
50
+ symbol: EditionTiers.ILLEGIBLE,
51
+ label: 'Illegible',
52
+ order: 5,
53
+ group: 'semiDiplomatic',
54
+ abbreviation: false,
55
+ },
56
+ {
57
+ symbol: EditionTiers.MODERNIZATION,
58
+ label: 'Modernization',
59
+ order: 6,
60
+ group: 'modernized',
61
+ abbreviation: false,
62
+ },
63
+ {
64
+ symbol: EditionTiers.PADRONIZATION,
65
+ label: 'Padronization',
66
+ order: 7,
67
+ group: 'modernized',
68
+ abbreviation: false,
69
+ },
70
+ {
71
+ symbol: EditionTiers.INFLECTION,
72
+ label: 'Inflection',
73
+ order: 8,
74
+ group: 'modernized',
75
+ abbreviation: false,
76
+ },
77
+ ];
78
+ const RESERVED_SYMBOLS = new Set([
79
+ StructuralEditionTiers.ORIGINAL,
80
+ StructuralEditionTiers.JUNCTION,
81
+ StructuralEditionTiers.SEGMENTATION,
82
+ ]);
83
+ export const isStructuralEditionTier = (symbol) => RESERVED_SYMBOLS.has(symbol);
@@ -13,7 +13,7 @@ export declare const useMessageUtils: () => {
13
13
  dispatchLoading: (val: boolean, text?: string) => void;
14
14
  dispatchError: ({ err, t, key }: ErrorDispatcher) => void;
15
15
  dispatchMessage: ({ key, ns, t }: MessageDispatcher) => void;
16
- dispatchMessageDirect: (value: string, type?: "success" | "error") => void;
16
+ dispatchMessageDirect: (value: string, type?: "success" | "error" | "warning") => void;
17
17
  isLoading: () => boolean;
18
18
  dispatchSilent: (val: boolean) => void;
19
19
  isSilentLoading: () => boolean;
@@ -1,8 +1,10 @@
1
+ import { Corpus } from '../../configs/types/Corpus';
1
2
  import { Token } from '../../configs/types/Struct';
2
3
  import './style.scss';
3
4
  type Props = {
4
5
  tokens: Token[];
5
6
  displayOriginal?: boolean;
7
+ corpus?: Corpus | null;
6
8
  };
7
- export default function SentenceEditionTiers({ tokens, displayOriginal, }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export default function SentenceEditionTiers({ tokens, displayOriginal, corpus, }: Props): import("react/jsx-runtime").JSX.Element;
8
10
  export {};
@@ -3,25 +3,22 @@ import { useTranslation } from 'react-i18next';
3
3
  import EditionTierUtils from '../../functions/EditionTierUtils';
4
4
  import SentenceUtils from '../../functions/SentenceUtils';
5
5
  import './style.scss';
6
- export default function SentenceEditionTiers({ tokens, displayOriginal, }) {
6
+ export default function SentenceEditionTiers({ tokens, displayOriginal, corpus, }) {
7
7
  const { t } = useTranslation('sentence');
8
8
  const { skipToken } = SentenceUtils;
9
- const { getIterateTiers, getEditionTierName, getEditionForToken, getOriginalValue, } = EditionTierUtils;
9
+ const { getIterateTiers, getTierLabel, getEditionForToken, getOriginalValue, } = EditionTierUtils;
10
10
  return (_jsxs(_Fragment, { children: [displayOriginal && (_jsxs("tr", { className: "word-tier", children: [_jsx("td", { children: t('label.tier.original') }), tokens.map((thisToken, idy) => {
11
11
  if (skipToken(thisToken)) {
12
12
  return true;
13
13
  }
14
14
  const value = getOriginalValue(thisToken);
15
- return (_jsx("td", { className: "text-center", colSpan: thisToken.splits ? thisToken.splits.length : 1, children: _jsx("span", { className: value ? '' : 'empty', children: value || t('label.empty') }) }));
16
- })] })), getIterateTiers().map((tier, idx) => {
17
- const key = getEditionTierName(tier);
18
- return (_jsxs("tr", { className: "word-tier", children: [_jsx("td", { children: t(`label.tier.${key.toLowerCase()}`) }), tokens.map((thisToken, idy) => {
19
- if (skipToken(thisToken)) {
20
- return true;
21
- }
22
- const tierEdition = getEditionForToken(thisToken);
23
- const value = (tierEdition?.ops || {})[tier] || '';
24
- return (_jsx("td", { className: "text-center", colSpan: thisToken.splits ? thisToken.splits.length : 1, children: _jsx("span", { className: value ? '' : 'empty', children: value || t('label.empty') }) }, `${thisToken.p}_${idx.valueOf()}_${idy.valueOf()}`));
25
- })] }, idx.valueOf()));
26
- })] }));
15
+ return (_jsx("td", { className: "text-center", colSpan: thisToken.splits ? thisToken.splits.length : 1, children: _jsx("span", { className: value ? '' : 'empty', children: value || t('label.empty') }) }, `original_${thisToken.p}_${idy}`));
16
+ })] })), getIterateTiers(corpus).map((tier, idx) => (_jsxs("tr", { className: "word-tier", children: [_jsx("td", { children: getTierLabel(tier, corpus, t) }), tokens.map((thisToken, idy) => {
17
+ if (skipToken(thisToken)) {
18
+ return true;
19
+ }
20
+ const tierEdition = getEditionForToken(thisToken);
21
+ const value = (tierEdition?.ops || {})[tier] || '';
22
+ return (_jsx("td", { className: "text-center", colSpan: thisToken.splits ? thisToken.splits.length : 1, children: _jsx("span", { className: value ? '' : 'empty', children: value || t('label.empty') }) }, `${thisToken.p}_${idx}_${idy}`));
23
+ })] }, tier)))] }));
27
24
  }
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCorpusUtils } from '../../configs/useCorpusUtils';
2
3
  import SentenceUtils from '../../functions/SentenceUtils';
3
4
  import SentenceEditionTiers from './SentenceEditionTiers';
4
5
  import SentenceMorphemeTiers from './SentenceMorphemeTiers';
@@ -8,5 +9,6 @@ import SentenceWordTiers from './SentenceWordTiers';
8
9
  import './style.scss';
9
10
  export default function SentenceView({ wordTiers, morphemeTiers, struct, useMorphemes, useEditionTiers, displayOriginal, }) {
10
11
  const tokens = SentenceUtils.sort(struct);
11
- return (_jsx("div", { className: "sentence-view-container", children: _jsx("div", { className: "body", children: _jsx("table", { className: "table table-striped", children: _jsxs("tbody", { children: [_jsx(SentenceValues, { tokens: tokens }), _jsx(SentenceTags, { tokens: tokens }), useEditionTiers && (_jsx(SentenceEditionTiers, { tokens: tokens, displayOriginal: displayOriginal })), wordTiers && (_jsx(SentenceWordTiers, { tokens: tokens, wordTiers: wordTiers })), useMorphemes && morphemeTiers && (_jsx(SentenceMorphemeTiers, { struct: struct, morphemeTiers: morphemeTiers }))] }) }) }) }));
12
+ const { getCorpus } = useCorpusUtils();
13
+ return (_jsx("div", { className: "sentence-view-container", children: _jsx("div", { className: "body", children: _jsx("table", { className: "table table-striped", children: _jsxs("tbody", { children: [_jsx(SentenceValues, { tokens: tokens }), _jsx(SentenceTags, { tokens: tokens }), useEditionTiers && (_jsx(SentenceEditionTiers, { tokens: tokens, displayOriginal: displayOriginal, corpus: getCorpus() })), wordTiers && (_jsx(SentenceWordTiers, { tokens: tokens, wordTiers: wordTiers })), useMorphemes && morphemeTiers && (_jsx(SentenceMorphemeTiers, { struct: struct, morphemeTiers: morphemeTiers }))] }) }) }) }));
12
14
  }
@@ -228,7 +228,14 @@ export default class CytoscapeTreeConverter {
228
228
  return `${token.p}`;
229
229
  }
230
230
  findParent(struct, chunk) {
231
- return this.tightestChunk(this.findContainingChunks(struct, chunk.l - 1, chunk.i, chunk.f));
231
+ if (chunk.l <= 0)
232
+ return null;
233
+ for (let level = chunk.l - 1; level >= 0; level--) {
234
+ const parent = this.tightestChunk(this.findContainingChunks(struct, level, chunk.i, chunk.f));
235
+ if (parent)
236
+ return parent;
237
+ }
238
+ return null;
232
239
  }
233
240
  findContainingChunks(struct, level, i, f) {
234
241
  return struct.chunks.filter((c) => c.l === level && i >= c.i && f <= c.f);
@@ -1,5 +1,9 @@
1
- import cytoscape, { Core } from 'cytoscape';
1
+ import cytoscape, { Core, Position } from 'cytoscape';
2
2
  import { CytoscapeTree } from '../../../configs/types/Tree';
3
+ export type CytoscapeViewport = {
4
+ zoom: number;
5
+ pan: Position;
6
+ };
3
7
  type Props = {
4
8
  selector: string;
5
9
  tree: CytoscapeTree;
@@ -8,8 +12,10 @@ type Props = {
8
12
  wheelSensitivity?: number;
9
13
  onReady?: (cy: Core) => void;
10
14
  autoungrabify?: boolean;
15
+ fit?: boolean;
16
+ viewport?: CytoscapeViewport;
11
17
  };
12
18
  declare const SyntreesCytoscape: {
13
- init: ({ selector, tree, dagre, stylesheet, wheelSensitivity, onReady, autoungrabify, }: Props) => Core;
19
+ init: ({ selector, tree, dagre, stylesheet, wheelSensitivity, onReady, autoungrabify, fit, viewport, }: Props) => Core;
14
20
  };
15
21
  export default SyntreesCytoscape;
@@ -3,7 +3,7 @@ import defaultStylesheet from './CytoscapeStylesheet';
3
3
  // @ts-ignore
4
4
  import nodeHtmlLabel from 'cytoscape-node-html-label';
5
5
  nodeHtmlLabel(cytoscape);
6
- const init = ({ selector, tree, dagre = false, stylesheet = defaultStylesheet, wheelSensitivity = 1.5, onReady, autoungrabify = true, }) => {
6
+ const init = ({ selector, tree, dagre = false, stylesheet = defaultStylesheet, wheelSensitivity = 1.5, onReady, autoungrabify = true, fit = true, viewport, }) => {
7
7
  destroy(selector);
8
8
  const cy = cytoscape({
9
9
  container: document.getElementById(selector),
@@ -57,8 +57,14 @@ const init = ({ selector, tree, dagre = false, stylesheet = defaultStylesheet, w
57
57
  ]);
58
58
  cy._htmlLabelsApplied = true;
59
59
  }
60
- cy.fit();
61
- cy.center();
60
+ if (fit) {
61
+ cy.fit();
62
+ cy.center();
63
+ }
64
+ else if (viewport) {
65
+ cy.zoom(viewport.zoom);
66
+ cy.pan(viewport.pan);
67
+ }
62
68
  dagre && cy.layout({ name: 'dagre' }).run();
63
69
  onReady && onReady(cy);
64
70
  });
@@ -1,9 +1,22 @@
1
- import { EditionTiers } from '../configs/types/EditionTiers';
1
+ import { EditionGroup, EditionTierDefinition } from '../configs/types/EditionTiers';
2
+ import { Corpus } from '../configs/types/Corpus';
2
3
  import { Token } from '../configs/types/Struct';
3
4
  declare const EditionTierUtils: {
4
- getIterateTiers: () => EditionTiers[];
5
- getEditionTierName: (k: string) => string;
5
+ getCorpusEditionTiers: (corpus?: Corpus | null) => EditionTierDefinition[];
6
+ normalizeOrder: (tiers: EditionTierDefinition[]) => EditionTierDefinition[];
7
+ getIterateTiers: (corpus?: Corpus | null) => string[];
8
+ getAbbreviationTiers: (corpus?: Corpus | null) => string[];
9
+ getParserTier: (corpus?: Corpus | null) => EditionTierDefinition | undefined;
10
+ getEditionTierName: (symbol: string) => string;
11
+ getTierLabel: (symbol: string, corpus?: Corpus | null, t?: (key: string) => string) => string;
12
+ isUnderSelected: (selected: string, tier: string, corpus?: Corpus | null) => boolean;
13
+ buildEditionGroups: (corpus?: Corpus | null) => EditionGroup[];
14
+ findGroupForTier: (tier: string, corpus?: Corpus | null) => EditionGroup | undefined;
15
+ isAbbreviationTier: (symbol: string, corpus?: Corpus | null) => boolean;
16
+ validateEditionTiers: (tiers: EditionTierDefinition[]) => string | null;
17
+ isDefaultTierSymbol: (symbol: string) => boolean;
6
18
  getEditionForToken: (token: Token) => any;
7
19
  getOriginalValue: (token: Token) => string;
20
+ getDisplayTierOrder: (corpus?: Corpus | null) => string[];
8
21
  };
9
22
  export default EditionTierUtils;
@@ -1,4 +1,95 @@
1
- import { EditionTiers } from '../configs/types/EditionTiers';
1
+ import { DEFAULT_EDITION_TIERS, EditionTiers, StructuralEditionTiers, isStructuralEditionTier, } from '../configs/types/EditionTiers';
2
+ const DEFAULT_SYMBOLS = new Set(DEFAULT_EDITION_TIERS.map((tier) => tier.symbol));
3
+ const getCorpusEditionTiers = (corpus) => {
4
+ if (!corpus?.editionTiers?.length) {
5
+ return DEFAULT_EDITION_TIERS.map((tier) => ({ ...tier }));
6
+ }
7
+ return [...corpus.editionTiers].sort((a, b) => a.order - b.order);
8
+ };
9
+ const normalizeOrder = (tiers) => tiers.map((tier, index) => ({ ...tier, order: index + 1 }));
10
+ const getIterateTiers = (corpus) => getCorpusEditionTiers(corpus).map((tier) => tier.symbol);
11
+ const getAbbreviationTiers = (corpus) => getCorpusEditionTiers(corpus)
12
+ .filter((tier) => tier.abbreviation)
13
+ .map((tier) => tier.symbol);
14
+ const getParserTier = (corpus) => {
15
+ const tiers = getCorpusEditionTiers(corpus);
16
+ return tiers[tiers.length - 1];
17
+ };
18
+ const getEditionTierName = (symbol) => {
19
+ const entry = Object.entries(EditionTiers).find(([, value]) => value === symbol);
20
+ return entry?.[0] || symbol;
21
+ };
22
+ const getTierLabel = (symbol, corpus, t) => {
23
+ const definition = getCorpusEditionTiers(corpus).find((tier) => tier.symbol === symbol);
24
+ if (definition?.label) {
25
+ return definition.label;
26
+ }
27
+ const key = getEditionTierName(symbol).toLowerCase();
28
+ if (t) {
29
+ return t(`sentence:label.tier.${key}`);
30
+ }
31
+ return key;
32
+ };
33
+ const isUnderSelected = (selected, tier, corpus) => {
34
+ const tiers = getIterateTiers(corpus);
35
+ const selectedIndex = tiers.indexOf(selected);
36
+ const tierIndex = tiers.indexOf(tier);
37
+ if (selectedIndex === -1 || tierIndex === -1) {
38
+ return false;
39
+ }
40
+ return tierIndex <= selectedIndex;
41
+ };
42
+ const buildEditionGroups = (corpus) => {
43
+ const tiers = getCorpusEditionTiers(corpus);
44
+ const semi = tiers
45
+ .filter((tier) => tier.group === 'semiDiplomatic')
46
+ .map((tier) => tier.symbol);
47
+ const modern = tiers
48
+ .filter((tier) => tier.group === 'modernized')
49
+ .map((tier) => tier.symbol);
50
+ return [
51
+ {
52
+ id: 'diplomatic',
53
+ labelKey: 'edition.group.diplomatic',
54
+ tiers: [StructuralEditionTiers.ORIGINAL],
55
+ defaultTier: StructuralEditionTiers.ORIGINAL,
56
+ },
57
+ {
58
+ id: 'semiDiplomatic',
59
+ labelKey: 'edition.group.semiDiplomatic',
60
+ tiers: semi,
61
+ defaultTier: semi[semi.length - 1] || EditionTiers.ILLEGIBLE,
62
+ },
63
+ {
64
+ id: 'modernized',
65
+ labelKey: 'edition.group.modernized',
66
+ tiers: modern,
67
+ defaultTier: modern[modern.length - 1] || EditionTiers.INFLECTION,
68
+ },
69
+ ];
70
+ };
71
+ const findGroupForTier = (tier, corpus) => buildEditionGroups(corpus).find((group) => group.tiers.includes(tier));
72
+ const isAbbreviationTier = (symbol, corpus) => getCorpusEditionTiers(corpus).some((tier) => tier.symbol === symbol && tier.abbreviation);
73
+ const validateEditionTiers = (tiers) => {
74
+ const symbols = new Set();
75
+ for (const tier of tiers) {
76
+ if (!tier.symbol?.trim()) {
77
+ return 'edition.tiers.symbol.required';
78
+ }
79
+ if (isStructuralEditionTier(tier.symbol)) {
80
+ return 'edition.tiers.symbol.reserved';
81
+ }
82
+ if (symbols.has(tier.symbol)) {
83
+ return 'edition.tiers.duplicate.symbol';
84
+ }
85
+ symbols.add(tier.symbol);
86
+ if (tier.group !== 'semiDiplomatic' && tier.group !== 'modernized') {
87
+ return 'edition.tiers.group.invalid';
88
+ }
89
+ }
90
+ return null;
91
+ };
92
+ const isDefaultTierSymbol = (symbol) => DEFAULT_SYMBOLS.has(symbol);
2
93
  const getEditionForToken = (token) => {
3
94
  if (token.eid)
4
95
  return token.edition;
@@ -9,28 +100,29 @@ const getEditionForToken = (token) => {
9
100
  }));
10
101
  return { ...edition, o: token.v };
11
102
  };
12
- const getIterateTiers = () => {
13
- const ordered = [];
14
- for (const value of Object.values(EditionTiers)) {
15
- const key = getEditionTierName(value);
16
- if (key !== 'ORIGINAL' && key !== 'JUNCTION' && key !== 'SEGMENTATION') {
17
- ordered.push(value);
18
- }
19
- }
20
- return ordered;
21
- };
22
- const getEditionTierName = (k) => {
23
- const idx = Object.values(EditionTiers).indexOf(k);
24
- const key = Object.keys(EditionTiers)[idx];
25
- return key || k;
26
- };
27
- const getOriginalValue = (token) => {
28
- return token.edition?.o || '';
29
- };
103
+ const getOriginalValue = (token) => token.edition?.o || '';
104
+ const getDisplayTierOrder = (corpus) => [
105
+ StructuralEditionTiers.ORIGINAL,
106
+ StructuralEditionTiers.JUNCTION,
107
+ StructuralEditionTiers.SEGMENTATION,
108
+ ...getIterateTiers(corpus),
109
+ ];
30
110
  const EditionTierUtils = {
111
+ getCorpusEditionTiers,
112
+ normalizeOrder,
31
113
  getIterateTiers,
114
+ getAbbreviationTiers,
115
+ getParserTier,
32
116
  getEditionTierName,
117
+ getTierLabel,
118
+ isUnderSelected,
119
+ buildEditionGroups,
120
+ findGroupForTier,
121
+ isAbbreviationTier,
122
+ validateEditionTiers,
123
+ isDefaultTierSymbol,
33
124
  getEditionForToken,
34
125
  getOriginalValue,
126
+ getDisplayTierOrder,
35
127
  };
36
128
  export default EditionTierUtils;
@@ -1,4 +1,4 @@
1
- import { EditionTiers } from '../configs/types/EditionTiers';
1
+ import EditionTierUtils from './EditionTierUtils';
2
2
  const getTag = (token) => {
3
3
  if (token.split)
4
4
  return token.split.t || '';
@@ -65,11 +65,7 @@ const isFirstFromSplit = (token) => {
65
65
  return false;
66
66
  return token.split.idx !== undefined && token.split.idx === 0;
67
67
  };
68
- const getEditionTierName = (k) => {
69
- const idx = Object.values(EditionTiers).indexOf(k);
70
- const key = Object.keys(EditionTiers)[idx];
71
- return key || k;
72
- };
68
+ const getEditionTierName = (k) => EditionTierUtils.getEditionTierName(k);
73
69
  const SentenceUtils = {
74
70
  sort,
75
71
  getAsText,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tycho-components",
3
3
  "private": false,
4
- "version": "0.26.1",
4
+ "version": "0.27.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {