tycho-components 0.41.7 → 0.42.1

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.
@@ -11,8 +11,12 @@ export type Chunk = {
11
11
  f: number;
12
12
  l: number;
13
13
  t: string;
14
+ /** Stable chunk identity (4-char alphanumeric), mirrors token `tid`. */
15
+ kid?: string;
14
16
  coidx?: number[];
15
17
  ep?: boolean;
18
+ /** Runtime: empty-category phrase node. */
19
+ empty?: boolean;
16
20
  };
17
21
  export type Token = {
18
22
  p: number;
@@ -109,8 +109,9 @@ export function shouldSkipJunctionContinuationElement(elements, index, selectedT
109
109
  if (element.type === PageRenderElementType.JUNCTION_SPLIT &&
110
110
  splitIdx > 0 &&
111
111
  segmented) {
112
- const lastP = getGlobalLastSegmentationPos(elements, ref.uid, segmentationGroup);
113
- if (lastP !== null && ref.p < lastP) {
112
+ // Only hand later splits to a later host when that host also has junction
113
+ // (two-host diplomatic pattern). Seg-only follow-ons must not hide idx>0.
114
+ if (hasLaterJunctionHostInSegmentationGroup(elements, ref.uid, segmentationGroup, ref.p)) {
114
115
  return true;
115
116
  }
116
117
  }
@@ -196,6 +197,30 @@ function getLastSegmentationPosInGroup(elements, start, end) {
196
197
  }
197
198
  return lastP;
198
199
  }
200
+ function groupHasJunctionHost(elements, start, end) {
201
+ for (let i = start; i <= end; i += 1) {
202
+ const ref = elements[i].token;
203
+ if (ref && hasJunctionFromRef(ref)) {
204
+ return true;
205
+ }
206
+ }
207
+ return false;
208
+ }
209
+ function hasLaterJunctionHostInSegmentationGroup(elements, uid, groupKey, currentP) {
210
+ for (const element of elements) {
211
+ if (!isJunctionEditionElement(element))
212
+ continue;
213
+ const ref = element.token;
214
+ if (!sameSegmentationGroupRef(ref, uid, groupKey))
215
+ continue;
216
+ if (!hasSegmentationFromRef(ref))
217
+ continue;
218
+ if (ref.p > currentP) {
219
+ return true;
220
+ }
221
+ }
222
+ return false;
223
+ }
199
224
  export function shouldSkipSegmentationElement(elements, index, selectedTier, corpus) {
200
225
  if (!isUnderSelected(selectedTier, SEGMENTATION_TIER, corpus)) {
201
226
  return false;
@@ -205,19 +230,99 @@ export function shouldSkipSegmentationElement(elements, index, selectedTier, cor
205
230
  return false;
206
231
  }
207
232
  const { start, end } = findSegmentationGroupBounds(elements, index);
233
+ const ref = element.token;
234
+ // Junction host + seg-only pieces: diplomatic text lives on the junction host.
235
+ if (groupHasJunctionHost(elements, start, end)) {
236
+ if (hasJunctionFromRef(ref)) {
237
+ return false;
238
+ }
239
+ return true;
240
+ }
208
241
  const lastP = getLastSegmentationPosInGroup(elements, start, end);
209
- return element.token.p < lastP;
242
+ return ref.p < lastP;
210
243
  }
211
244
  /** @deprecated Use shouldSkipSegmentationElement */
212
245
  export function shouldSkipSegmentationToken(elements, index, selectedTier, corpus) {
213
246
  return shouldSkipSegmentationElement(elements, index, selectedTier, corpus);
214
247
  }
248
+ function isMidJunctionHostLineBreak(elements, index) {
249
+ if (elements[index]?.type !== PageRenderElementType.LINE_BREAK) {
250
+ return false;
251
+ }
252
+ const prev = elements[index - 1];
253
+ if (prev?.type !== PageRenderElementType.JUNCTION_SPLIT || !prev.token) {
254
+ return false;
255
+ }
256
+ let nextIdx = index + 1;
257
+ while (nextIdx < elements.length &&
258
+ elements[nextIdx].type === PageRenderElementType.LINE_NUMBER) {
259
+ nextIdx += 1;
260
+ }
261
+ const next = elements[nextIdx];
262
+ if (next?.type !== PageRenderElementType.JUNCTION_SPLIT || !next.token) {
263
+ return false;
264
+ }
265
+ return prev.token.uid === next.token.uid && prev.token.p === next.token.p;
266
+ }
267
+ function sameDeferredBreakGroup(element, group) {
268
+ const ref = element.token;
269
+ if (!ref)
270
+ return false;
271
+ if (ref.uid === group.uid && ref.p === group.p)
272
+ return true;
273
+ if (group.segGroup &&
274
+ hasSegmentationFromRef(ref) &&
275
+ sameSegmentationGroupRef(ref, group.uid, group.segGroup)) {
276
+ return true;
277
+ }
278
+ return false;
279
+ }
215
280
  export default function collapseElementsForTier(elements, selectedTier, corpus) {
216
281
  const showJunctionSplits = isUnderSelected(selectedTier, JUNCTION_TIER, corpus);
217
282
  const collapsed = [];
218
283
  let index = 0;
284
+ let deferredBreak = null;
285
+ let deferredLineNumbers = [];
286
+ let deferredBreakGroup = null;
287
+ const flushDeferredBreak = () => {
288
+ if (!deferredBreak)
289
+ return;
290
+ collapsed.push({
291
+ kind: 'single',
292
+ element: deferredBreak,
293
+ key: `LINE_BREAK_deferred_${collapsed.length}`,
294
+ });
295
+ for (const lineNumber of deferredLineNumbers) {
296
+ collapsed.push({
297
+ kind: 'single',
298
+ element: lineNumber,
299
+ key: `LINE_NUMBER_deferred_${collapsed.length}`,
300
+ });
301
+ }
302
+ deferredBreak = null;
303
+ deferredLineNumbers = [];
304
+ deferredBreakGroup = null;
305
+ };
219
306
  while (index < elements.length) {
220
307
  const element = elements[index];
308
+ if (!showJunctionSplits &&
309
+ deferredBreak === null &&
310
+ isMidJunctionHostLineBreak(elements, index)) {
311
+ const host = elements[index - 1].token;
312
+ deferredBreak = element;
313
+ deferredBreakGroup = {
314
+ uid: host.uid,
315
+ p: host.p,
316
+ segGroup: segmentationGroupKey(host),
317
+ };
318
+ index += 1;
319
+ while (index < elements.length &&
320
+ elements[index].type === PageRenderElementType.LINE_NUMBER) {
321
+ deferredLineNumbers.push(elements[index]);
322
+ index += 1;
323
+ }
324
+ continue;
325
+ }
221
326
  if (shouldSkipSegmentationElement(elements, index, selectedTier, corpus)) {
222
327
  index += 1;
223
328
  continue;
@@ -226,6 +331,12 @@ export default function collapseElementsForTier(elements, selectedTier, corpus)
226
331
  index += 1;
227
332
  continue;
228
333
  }
334
+ const inDeferredGroup = !!element.token &&
335
+ !!deferredBreakGroup &&
336
+ sameDeferredBreakGroup(element, deferredBreakGroup);
337
+ if (deferredBreak && !inDeferredGroup) {
338
+ flushDeferredBreak();
339
+ }
229
340
  if (!showJunctionSplits &&
230
341
  element.type === PageRenderElementType.JUNCTION_SPLIT &&
231
342
  element.token) {
@@ -251,6 +362,7 @@ export default function collapseElementsForTier(elements, selectedTier, corpus)
251
362
  });
252
363
  index += 1;
253
364
  }
365
+ flushDeferredBreak();
254
366
  return collapsed;
255
367
  }
256
368
  export function isTokenBearingCollapsed(item) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tycho-components",
3
3
  "private": false,
4
- "version": "0.41.7",
4
+ "version": "0.42.1",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {