flappa-doormal 2.10.0 → 2.11.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.
- package/AGENTS.md +91 -0
- package/LICENSE.md +1 -1
- package/README.md +110 -2
- package/dist/index.d.mts +12 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +210 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -117,6 +117,8 @@ src/
|
|
|
117
117
|
- `hasExcludedPageInRange()` - Check if range contains excluded pages
|
|
118
118
|
- `findNextPagePosition()` - Find next page content position
|
|
119
119
|
- `findPatternBreakPosition()` - Find pattern match by preference
|
|
120
|
+
- `findSafeBreakPosition()` - Search backward for a safe linguistic split point (whitespace/punctuation)
|
|
121
|
+
- `adjustForSurrogate()` - Ensure split position doesn't corrupt Unicode surrogate pairs
|
|
120
122
|
|
|
121
123
|
10. **`types.ts`** - Type definitions
|
|
122
124
|
- `Logger` interface - Optional logging for debugging
|
|
@@ -260,6 +262,19 @@ segmentPages(pages, {
|
|
|
260
262
|
|
|
261
263
|
> **Note**: Older per-rule span limiting approaches were removed in favor of post-processing `breakpoints`.
|
|
262
264
|
|
|
265
|
+
### 5. Safety-Hardened Content Splitting (NEW)
|
|
266
|
+
|
|
267
|
+
When using `maxContentLength`, the segmenter prevents text corruption through several layers of fallback logic.
|
|
268
|
+
|
|
269
|
+
**Algorithm:**
|
|
270
|
+
1. **Windowed Pattern Match**: Attempt to find a user-provided `breakpoint` pattern within the character window.
|
|
271
|
+
2. **Safe Fallback (Linguistic)**: If no pattern matches, use `findSafeBreakPosition()` to search backward (100 chars) for whitespace or punctuation `[\s\n.,;!?؛،۔]`.
|
|
272
|
+
3. **Safe Fallback (Technical)**: If still no safe break found, use `adjustForSurrogate()` to ensure the split doesn't fall between a High and Low Unicode surrogate pair.
|
|
273
|
+
4. **Hard Split**: Only as a final resort is a character-exact split performed.
|
|
274
|
+
|
|
275
|
+
**Progress Guarantee**:
|
|
276
|
+
The loop in `processOversizedSegment` has been refactored to remove fixed iteration limits (e.g., 10k). Instead, it relies on strict `cursorPos` progression and input validation (`maxContentLength >= 50`) to support processing infinitely large content streams without risk of truncation.
|
|
277
|
+
|
|
263
278
|
## Design Decisions
|
|
264
279
|
|
|
265
280
|
### 1. Why `{{double-braces}}`?
|
|
@@ -383,6 +398,8 @@ bunx biome lint .
|
|
|
383
398
|
|
|
384
399
|
11. **Boundary-position algorithm improves page attribution**: Building a position map of page boundaries once per segment (O(n)) enables binary search for O(log n) lookups per piece. Key insight: when a segment starts mid-page (common after structural rules), expected boundary estimates must account for the offset into the starting page. Without this adjustment, position-based lookups can return the wrong page when pages have identical content prefixes.
|
|
385
400
|
|
|
401
|
+
12. **Prefix matching fails with duplicated content**: When using `indexOf()` to find page boundaries by matching prefixes, false positives occur when pages have identical prefixes AND content is duplicated within pages. Solution: use cumulative byte offsets as the source of truth for expected boundaries, and only accept prefix matches within a strict deviation threshold (2000 chars). When content-based detection fails, fall back directly to the calculated offset rather than returning `remainingContent.length` (which merges all remaining pages).
|
|
402
|
+
|
|
386
403
|
### For Future AI Agents (Recovery + Repo gotchas)
|
|
387
404
|
|
|
388
405
|
1. **`lineStartsAfter` vs `lineStartsWith` is not “cosmetic”**: `lineStartsAfter` changes output by stripping the matched marker via an internal `contentStartOffset` during segment construction. If a client used it by accident, you cannot reconstruct the exact stripped prefix from output alone without referencing the original pages and re-matching the marker.
|
|
@@ -412,6 +429,14 @@ bunx biome lint .
|
|
|
412
429
|
|
|
413
430
|
10. **Prefer library utilities for UI tasks**: Instead of re-implementing rule merging, validation, or token mapping in client code, use `optimizeRules`, `validateRules`/`formatValidationReport`, and `applyTokenMappings`. They handle edge cases (like duplicate patterns, regex safety, or diacritic handling) that ad-hoc implementations might miss.
|
|
414
431
|
|
|
432
|
+
11. **Safety Fallback (Search-back)**: When forced to split at a hard character limit, searching backward for whitespace/punctuation (`[\s\n.,;!?؛،۔]`) prevents word-chopping and improves readability significantly.
|
|
433
|
+
|
|
434
|
+
12. **Unicode Surrogate Safety**: Multi-byte characters (like Emojis) can be corrupted if split in the middle of a surrogate pair. Always use a helper like `adjustForSurrogate` to ensure the split point falls on a valid character boundary.
|
|
435
|
+
|
|
436
|
+
13. **Recursion/Iteration Safety**: Using a progress-based guard (comparing `cursorPos` before and after loop iteration) is safer than fixed iteration limits for supporting arbitrary-sized content without truncation risks.
|
|
437
|
+
|
|
438
|
+
14. **Accidental File Overwrites**: Be extremely careful when using tools like `replace_file_content` with large ranges. Verify file integrity frequently (e.g., `git diff`) to catch accidental deletions of existing code or tests. Merging new tests into existing files is a high-risk operation for AI agents.
|
|
439
|
+
|
|
415
440
|
### Process Template (Multi-agent design review, TDD-first)
|
|
416
441
|
|
|
417
442
|
If you want to repeat the “write a plan → get multiple AI critiques → synthesize → update plan → implement TDD-first” workflow, use:
|
|
@@ -538,4 +563,70 @@ Use analysis functions to discover patterns, then pass to `segmentPages()`:
|
|
|
538
563
|
|
|
539
564
|
See README.md for complete examples.
|
|
540
565
|
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
## Debugging Page Boundary Detection (Added 2026-01-04)
|
|
569
|
+
|
|
570
|
+
### The Problem: False Positives in Prefix Matching
|
|
571
|
+
|
|
572
|
+
When using `maxPages=0` with empty breakpoint `['']` (page boundary breaks), the segmenter can fail when:
|
|
573
|
+
1. **Pages have identical prefixes** - All pages start with the same text
|
|
574
|
+
2. **Duplicated content within pages** - The same phrase appears multiple times in a single page
|
|
575
|
+
3. **Long content** - Pages are thousands of characters, putting false matches closer to expected boundaries
|
|
576
|
+
|
|
577
|
+
**Root cause**: The `findPageStartNearExpectedBoundary` function in `breakpoint-utils.ts` uses prefix matching to find page boundaries. When content is duplicated, it finds matches at incorrect positions within the current page instead of at the actual page boundary.
|
|
578
|
+
|
|
579
|
+
### Key Functions in the Breakpoint Chain
|
|
580
|
+
|
|
581
|
+
1. **`applyBreakpoints()`** - Entry point for breakpoint processing
|
|
582
|
+
2. **`processOversizedSegment()`** - Iteratively breaks segments exceeding `maxPages`
|
|
583
|
+
3. **`computeWindowEndIdx()`** - Calculates max page index for current window
|
|
584
|
+
4. **`findBreakpointWindowEndPosition()`** - Finds the byte position where the window ends
|
|
585
|
+
5. **`findPageStartNearExpectedBoundary()`** - Content-based search for page start position
|
|
586
|
+
6. **`handlePageBoundaryBreak()`** - Handles empty pattern `''` (page boundary)
|
|
587
|
+
7. **`buildCumulativeOffsets()`** - Pre-computes exact byte positions for each page
|
|
541
588
|
|
|
589
|
+
### Debug Strategy
|
|
590
|
+
|
|
591
|
+
1. **Check cumulative offsets first** - `buildCumulativeOffsets()` returns correct positions from `pages.join('\n')`
|
|
592
|
+
2. **Trace `expectedBoundary`** - This is calculated correctly from cumulative offsets
|
|
593
|
+
3. **Check `findPageStartNearExpectedBoundary` candidates** - The bug is usually here; it finds false matches
|
|
594
|
+
4. **Verify the deviation check** - Matches must be within `MAX_DEVIATION` (2000 chars) of expected boundary
|
|
595
|
+
|
|
596
|
+
### The Fix Applied
|
|
597
|
+
|
|
598
|
+
Two changes in `breakpoint-utils.ts`:
|
|
599
|
+
|
|
600
|
+
1. **`findPageStartNearExpectedBoundary`** - Added `MAX_DEVIATION` check to reject matches too far from expected boundary:
|
|
601
|
+
```typescript
|
|
602
|
+
const MAX_DEVIATION = 2000;
|
|
603
|
+
if (bestDistance <= MAX_DEVIATION) {
|
|
604
|
+
return bestCandidate.pos;
|
|
605
|
+
}
|
|
606
|
+
// Continue trying shorter prefixes or return -1
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
2. **`findBreakpointWindowEndPosition`** - Changed fallback from `remainingContent.length` to `bestExpectedBoundary`:
|
|
610
|
+
```typescript
|
|
611
|
+
// Before (bug): return remainingContent.length; // Merges all remaining pages!
|
|
612
|
+
// After (fix): return Math.min(bestExpectedBoundary, remainingContent.length);
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Test Case Pattern for This Bug
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
it('should correctly split pages with identical prefixes and duplicated content', () => {
|
|
619
|
+
const sharedPrefix = 'SHARED PREFIX ';
|
|
620
|
+
const filler = 'Lorem ipsum. '.repeat(200); // ~6000 chars
|
|
621
|
+
const pages: Page[] = [
|
|
622
|
+
{ content: sharedPrefix + 'start ' + filler + sharedPrefix + 'end', id: 0 },
|
|
623
|
+
{ content: sharedPrefix + 'page1', id: 1 },
|
|
624
|
+
{ content: sharedPrefix + 'page2', id: 2 },
|
|
625
|
+
];
|
|
626
|
+
const result = segmentPages(pages, { breakpoints: [''], maxPages: 0 });
|
|
627
|
+
expect(result).toHaveLength(3); // Without fix: 2 or 1
|
|
628
|
+
});
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
15. **Use Synthesized AI Reviews**: For complex safety features, getting reviews from multiple models (Claude, GPT, etc.) and synthesizing them into a single action plan (see `docs/reviews/max-content-length-review-synthesis.md`) revealed critical edge cases like Arabic diacritic corruption and surrogate pair safety that a single model might miss.
|
package/LICENSE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2025 Ragaeeb Haq>
|
|
1
|
+
Copyright 2025-2026 Ragaeeb Haq>
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ Working with Arabic hadith and Islamic text collections requires splitting conti
|
|
|
51
51
|
✅ **Readable templates**: `{{raqms}} {{dash}}` instead of cryptic regex
|
|
52
52
|
✅ **Named captures**: `{{raqms:hadithNum}}` auto-extracts to `meta.hadithNum`
|
|
53
53
|
✅ **Fuzzy matching**: Auto-enabled for `{{bab}}`, `{{kitab}}`, `{{basmalah}}`, `{{fasl}}`, `{{naql}}` (override with `fuzzy: false`)
|
|
54
|
+
✅ **Content limits**: `maxPages` and `maxContentLength` (safety-hardened) control segment size
|
|
54
55
|
✅ **Page tracking**: Know which page each segment came from
|
|
55
56
|
✅ **Declarative rules**: Describe *what* to match, not *how*
|
|
56
57
|
|
|
@@ -236,7 +237,92 @@ Limit rules to specific page ranges:
|
|
|
236
237
|
}
|
|
237
238
|
```
|
|
238
239
|
|
|
239
|
-
### 7.
|
|
240
|
+
### 7. Max Content Length (Safety Hardened)
|
|
241
|
+
|
|
242
|
+
Split oversized segments based on character count:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
{
|
|
246
|
+
maxContentLength: 500, // Split after 500 characters
|
|
247
|
+
prefer: 'longer', // Try to fill the character bucket
|
|
248
|
+
breakpoints: ['\\.'], // Recommended: split on punctuation within window
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The library implements **safety hardening** for character-based splits:
|
|
253
|
+
- **Safe Fallback**: If no breakpoint matches, it searches backward up to 100 characters for a delimiter (whitespace or punctuation) to avoid chopping words.
|
|
254
|
+
- **Unicode Safety**: Automatically prevents splitting inside Unicode surrogate pairs (e.g., emojis), preventing text corruption.
|
|
255
|
+
- **Validation**: `maxContentLength` must be at least **50**.
|
|
256
|
+
|
|
257
|
+
### 8. Advanced Structural Filters
|
|
258
|
+
|
|
259
|
+
Refine rule matching with page-specific constraints:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
{
|
|
263
|
+
lineStartsWith: ['### '],
|
|
264
|
+
split: 'at',
|
|
265
|
+
// Range constraints
|
|
266
|
+
min: 10, // Only match on pages 10 and above
|
|
267
|
+
max: 500, // Only match on pages 500 and below
|
|
268
|
+
exclude: [50, [100, 110]], // Skip page 50 and range 100-110
|
|
269
|
+
|
|
270
|
+
// Negative lookahead: skip rule if content matches this pattern
|
|
271
|
+
// (e.g. skip chapter marker if it appears inside a table/list)
|
|
272
|
+
skipWhen: '^\s*- ',
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 9. Debugging & Logging
|
|
277
|
+
|
|
278
|
+
Pass an optional `logger` to trace segmentation decisions or enable `debug` to attach match metadata to segments:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const segments = segmentPages(pages, {
|
|
282
|
+
rules: [...],
|
|
283
|
+
debug: true, // Attaches .meta.debug with regex and match indices
|
|
284
|
+
logger: {
|
|
285
|
+
debug: (msg, data) => console.log(`[DEBUG] ${msg}`, data),
|
|
286
|
+
info: (msg, data) => console.info(`[INFO] ${msg}`, data),
|
|
287
|
+
warn: (msg, data) => console.warn(`[WARN] ${msg}`, data),
|
|
288
|
+
error: (msg, data) => console.error(`[ERROR] ${msg}`, data),
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 10. Page Joiners
|
|
294
|
+
|
|
295
|
+
Control how text from different pages is stitched together:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Default: space ' ' joiner
|
|
299
|
+
// Result: "...end of page 1. Start of page 2..."
|
|
300
|
+
segmentPages(pages, { pageJoiner: 'space' });
|
|
301
|
+
|
|
302
|
+
// Result: "...end of page 1.\nStart of page 2..."
|
|
303
|
+
segmentPages(pages, { pageJoiner: 'newline' });
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 11. Breakpoint Preferences
|
|
307
|
+
|
|
308
|
+
When a segment exceeds `maxPages` or `maxContentLength`, breakpoints split it at the "best" available match:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
{
|
|
312
|
+
maxPages: 1, // Minimum segment size (page span)
|
|
313
|
+
breakpoints: ['{{tarqim}}'],
|
|
314
|
+
|
|
315
|
+
// 'longer' (default): Greedy. Finds the match furthest in the window.
|
|
316
|
+
// Result: Segments stay close to the max limit.
|
|
317
|
+
prefer: 'longer',
|
|
318
|
+
|
|
319
|
+
// 'shorter': Conservative. Finds the first available match.
|
|
320
|
+
// Result: Segments split as early as possible.
|
|
321
|
+
prefer: 'shorter',
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 12. Occurrence Filtering
|
|
240
326
|
|
|
241
327
|
Control which matches to use:
|
|
242
328
|
|
|
@@ -831,7 +917,27 @@ const options: SegmentationOptions = {
|
|
|
831
917
|
// How to join content across page boundaries in OUTPUT segments:
|
|
832
918
|
// - 'space' (default): page boundaries become spaces
|
|
833
919
|
// - 'newline': preserve page boundaries as newlines
|
|
834
|
-
pageJoiner: '
|
|
920
|
+
pageJoiner: 'newline',
|
|
921
|
+
|
|
922
|
+
// Breakpoint preferences for resizing oversized segments:
|
|
923
|
+
// - 'longer' (default): maximizes segment size within limits
|
|
924
|
+
// - 'shorter': minimizes segment size (splits at first match)
|
|
925
|
+
prefer: 'longer',
|
|
926
|
+
|
|
927
|
+
// Post-structural limit: split if segment spans more than 2 pages
|
|
928
|
+
maxPages: 2,
|
|
929
|
+
|
|
930
|
+
// Post-structural limit: split if segment exceeds 5000 characters
|
|
931
|
+
maxContentLength: 5000,
|
|
932
|
+
|
|
933
|
+
// Enable match metadata in segments (meta.debug)
|
|
934
|
+
debug: true,
|
|
935
|
+
|
|
936
|
+
// Custom logger for tracing
|
|
937
|
+
logger: {
|
|
938
|
+
info: (m) => console.log(m),
|
|
939
|
+
warn: (m) => console.warn(m),
|
|
940
|
+
}
|
|
835
941
|
};
|
|
836
942
|
|
|
837
943
|
const segments: Segment[] = segmentPages(pages, options);
|
|
@@ -1057,6 +1163,8 @@ type SplitRule = {
|
|
|
1057
1163
|
// Constraints
|
|
1058
1164
|
min?: number;
|
|
1059
1165
|
max?: number;
|
|
1166
|
+
exclude?: (number | [number, number])[]; // Single page or [start, end] range
|
|
1167
|
+
skipWhen?: string; // Regex pattern (tokens supported)
|
|
1060
1168
|
meta?: Record<string, unknown>;
|
|
1061
1169
|
};
|
|
1062
1170
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -641,6 +641,18 @@ type SegmentationOptions = {
|
|
|
641
641
|
* { maxPages: 2, breakpoints: ['{{tarqim}}', ''] }
|
|
642
642
|
*/
|
|
643
643
|
maxPages?: number;
|
|
644
|
+
/**
|
|
645
|
+
* Maximum length (in characters) per segment.
|
|
646
|
+
*
|
|
647
|
+
* When a segment exceeds this length, breakpoints are applied to split it.
|
|
648
|
+
* This can typically be used in conjunction with `maxPages`, where the
|
|
649
|
+
* strictest constraint (intersection) determines the split window.
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* // Break segments that exceed 2000 chars
|
|
653
|
+
* { maxContentLength: 2000, breakpoints: ['{{tarqim}}'] }
|
|
654
|
+
*/
|
|
655
|
+
maxContentLength?: number;
|
|
644
656
|
/**
|
|
645
657
|
* Patterns tried in order to break oversized segments.
|
|
646
658
|
*
|
|
@@ -894,20 +906,6 @@ type ReplaceRule = NonNullable<SegmentationOptions['replace']>[number];
|
|
|
894
906
|
declare const applyReplacements: (pages: Page[], rules?: ReplaceRule[]) => Page[];
|
|
895
907
|
//#endregion
|
|
896
908
|
//#region src/segmentation/segmenter.d.ts
|
|
897
|
-
/**
|
|
898
|
-
* Applies breakpoints to oversized segments.
|
|
899
|
-
*
|
|
900
|
-
* For each segment that spans more than maxPages, tries the breakpoint patterns
|
|
901
|
-
* in order to find a suitable split point. Structural markers (from rules) are
|
|
902
|
-
* always respected - segments are only broken within their boundaries.
|
|
903
|
-
*
|
|
904
|
-
* @param segments - Initial segments from rule processing
|
|
905
|
-
* @param pages - Original pages for page lookup
|
|
906
|
-
* @param maxPages - Maximum pages before breakpoints apply
|
|
907
|
-
* @param breakpoints - Patterns to try in order (tokens supported)
|
|
908
|
-
* @param prefer - 'longer' for last match, 'shorter' for first match
|
|
909
|
-
* @returns Processed segments with oversized ones broken up
|
|
910
|
-
*/
|
|
911
909
|
/**
|
|
912
910
|
* Segments pages of content based on pattern-matching rules.
|
|
913
911
|
*
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/segmentation/fuzzy.ts","../src/segmentation/types.ts","../src/segmentation/optimize-rules.ts","../src/segmentation/pattern-validator.ts","../src/segmentation/replace.ts","../src/segmentation/segmenter.ts","../src/segmentation/tokens.ts","../src/analysis/line-starts.ts","../src/analysis/repeating-sequences.ts","../src/detection.ts","../src/recovery.ts"],"sourcesContent":[],"mappings":";;AAkEA;AA+FA;;;;;ACnIiB;AA4BG;AA8BM;AAiCC;AAwBH;;;;;;;AAqCxB;AAOA;AAAgE;AA6DhE;AAAkD;AAyHlD;;;;;AAkBY,cDnUC,WCmUG,EAAA,CAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAoChB;AA0EA;AA8BA;AAuBA;AA+CA;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/segmentation/fuzzy.ts","../src/segmentation/types.ts","../src/segmentation/optimize-rules.ts","../src/segmentation/pattern-validator.ts","../src/segmentation/replace.ts","../src/segmentation/segmenter.ts","../src/segmentation/tokens.ts","../src/analysis/line-starts.ts","../src/analysis/repeating-sequences.ts","../src/detection.ts","../src/recovery.ts"],"sourcesContent":[],"mappings":"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"}
|