buildOffsets / indexForOffset / segmentByRanges
حسابوکتاب مختصات برای وضعیتی که «محتوا به تکهها بخش شده اما یادداشتها بر پایهٔ متنِ بههمپیوسته ذخیره میشوند». برجستهسازی را بهجای «تکهٔ N، نویسهٔ M» به شکل جایگشت سراسری ذخیره کنید تا از تکهبندی دوباره جان به در ببرد: اندازهٔ قلم، پهنای صفحه یا اندازهٔ پارهها را که عوض کنید، یادداشت همچنان به همان واژهها اشاره میکند.
API
buildOffsets(lengths)
جمعهای پیشوندی: offsets[i] طول کل هر چیزی است که پیش از تکهٔ i میآید.
buildOffsets([3, 5, 2]); // [0, 3, 8]indexForOffset(offsets, offset)
با جستوجوی دودویی مییابد که یک جایگشت سراسری در کدام تکه میافتد. جایگشتهای بیرون از بازه به [0, offsets.length - 1] مهار میشوند و آرایهٔ خالی 0 میدهد. نتیجه همیشه برای نمایهگذاری امن است.
segmentByRanges(text, chunkStart, ranges)
یک تکه را به بخشهای ساده و بخشهای منطبق میشکافد تا بتوان تکهتکه ترسیمش کرد (برجستهسازی، نتیجهٔ جستوجو، رنگآمیزی تفاوتها).
| پارامتر | توضیح | نوع |
|---|---|---|
text | متن این تکه | string |
chunkStart | جایگشت سراسریِ آغاز این تکه | number |
ranges | { start, end, value }[] در مختصات سراسری | readonly OffsetRange<T>[] |
{ text, start, end, value }[] برمیگرداند که در آن value برای متن پوششدادهنشده null است. بههمپیوستن بخشها همیشه text را بازمیسازد و همواره دستکم یک بخش هست.
نمونه
import { buildOffsets, indexForOffset, segmentByRanges } from 'ranuts';
const offsets = buildOffsets(pages.map((p) => p.text.length));
// این یادداشت از کدام صفحه آغاز میشود؟
const pageIndex = indexForOffset(offsets, note.start);
// ترسیم یک صفحه همراه با برجستهسازیهایش
const segments = segmentByRanges(
pages[i].text,
offsets[i],
notes.map((n) => ({
start: n.start,
end: n.end,
value: n,
})),
);
segments.forEach((s) => container.append(s.value ? mark(s.text, s.value) : text(s.text)));یادداشتها
- بازهها نیمبازاند:
[start, end). - همپوشانیها حل میشوند، نه ادغام. بازهها به ترتیب مصرف میشوند؛ بازهٔ پسین تنها بخشی را میگیرد که هنوز پوشیده نشده، و آنکه بازهٔ پیشین یکسره بلعیده باشدش کنار گذاشته میشود. نقطههای برش اکیداً افزایشی میمانند، پس هیچ بخشی بهتصادف خالی یا تکراری نمیشود.
- بازههای بیرون از تکه نادیده گرفته و آنها که تنها بخشی همپوشانی دارند بریده میشوند، پس میتوانید همهٔ فهرست یادداشتها را به هر تکه بدهید.