restty 0.1.12 → 0.1.13
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/README.md +9 -0
- package/dist/app/index.js +156 -35
- package/dist/fonts/index.js +0 -1
- package/dist/index.js +156 -35
- package/dist/internal.js +156 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,15 @@ Powered by:
|
|
|
9
9
|
- `WebGPU` (with WebGL2 fallback)
|
|
10
10
|
- `text-shaper` (shaping + raster)
|
|
11
11
|
|
|
12
|
+
## Release Status
|
|
13
|
+
|
|
14
|
+
`restty` is in an early release stage.
|
|
15
|
+
|
|
16
|
+
- Known issue: kitty image protocol handling can still fail in some edge cases.
|
|
17
|
+
- API note: high-level APIs are usable now, but some APIs may still change to improve DX.
|
|
18
|
+
|
|
19
|
+
If you hit an issue, please open one on GitHub with repro steps.
|
|
20
|
+
|
|
12
21
|
## Install
|
|
13
22
|
|
|
14
23
|
```bash
|
package/dist/app/index.js
CHANGED
|
@@ -8672,7 +8672,6 @@ var COLOR_EMOJI_FONT_HINTS = [
|
|
|
8672
8672
|
/apple color emoji/i,
|
|
8673
8673
|
/noto color emoji/i,
|
|
8674
8674
|
/segoe ui emoji/i,
|
|
8675
|
-
/openmoji/i,
|
|
8676
8675
|
/twemoji/i
|
|
8677
8676
|
];
|
|
8678
8677
|
var WIDE_FONT_HINTS = [
|
|
@@ -25641,9 +25640,17 @@ var DEFAULT_FONT_SOURCES = [
|
|
|
25641
25640
|
type: "url",
|
|
25642
25641
|
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-fonts@main/unhinted/ttf/NotoSansSymbols2/NotoSansSymbols2-Regular.ttf"
|
|
25643
25642
|
},
|
|
25643
|
+
{
|
|
25644
|
+
type: "url",
|
|
25645
|
+
url: "https://cdn.jsdelivr.net/gh/googlefonts/noto-emoji@main/fonts/NotoColorEmoji.ttf"
|
|
25646
|
+
},
|
|
25644
25647
|
{
|
|
25645
25648
|
type: "url",
|
|
25646
25649
|
url: "https://cdn.jsdelivr.net/gh/hfg-gmuend/openmoji@master/font/OpenMoji-black-glyf/OpenMoji-black-glyf.ttf"
|
|
25650
|
+
},
|
|
25651
|
+
{
|
|
25652
|
+
type: "url",
|
|
25653
|
+
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf"
|
|
25647
25654
|
}
|
|
25648
25655
|
];
|
|
25649
25656
|
function validateFontSource(source, index) {
|
|
@@ -53192,6 +53199,46 @@ function createResttyApp(options) {
|
|
|
53192
53199
|
const firstCp = text.codePointAt(0) ?? 0;
|
|
53193
53200
|
const nerdSymbol = isNerdSymbolCodepoint(firstCp);
|
|
53194
53201
|
const preferSymbol = nerdSymbol || isSymbolCp(firstCp);
|
|
53202
|
+
const preferEmoji = text.includes("") || chars.some((ch) => {
|
|
53203
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
53204
|
+
if (cp >= 127462 && cp <= 127487)
|
|
53205
|
+
return true;
|
|
53206
|
+
if (cp >= 127744 && cp <= 129791)
|
|
53207
|
+
return true;
|
|
53208
|
+
return false;
|
|
53209
|
+
});
|
|
53210
|
+
if (preferEmoji) {
|
|
53211
|
+
let bestEmojiIndex = -1;
|
|
53212
|
+
let bestEmojiScore = Number.POSITIVE_INFINITY;
|
|
53213
|
+
for (let i3 = 0;i3 < fontState.fonts.length; i3 += 1) {
|
|
53214
|
+
const entry = fontState.fonts[i3];
|
|
53215
|
+
if (!entry?.font || !isColorEmojiFont(entry))
|
|
53216
|
+
continue;
|
|
53217
|
+
let ok = true;
|
|
53218
|
+
for (const ch of chars) {
|
|
53219
|
+
if (!fontHasGlyph2(entry.font, ch)) {
|
|
53220
|
+
ok = false;
|
|
53221
|
+
break;
|
|
53222
|
+
}
|
|
53223
|
+
}
|
|
53224
|
+
if (!ok)
|
|
53225
|
+
continue;
|
|
53226
|
+
const shaped = shapeClusterWithFont(entry, text);
|
|
53227
|
+
let score = shaped.glyphs.length;
|
|
53228
|
+
if (/noto color emoji/i.test(entry.label))
|
|
53229
|
+
score -= 0.25;
|
|
53230
|
+
if (score < bestEmojiScore) {
|
|
53231
|
+
bestEmojiScore = score;
|
|
53232
|
+
bestEmojiIndex = i3;
|
|
53233
|
+
if (score <= 0.75)
|
|
53234
|
+
break;
|
|
53235
|
+
}
|
|
53236
|
+
}
|
|
53237
|
+
if (bestEmojiIndex >= 0) {
|
|
53238
|
+
setBoundedMap(fontState.fontPickCache, cacheKey, bestEmojiIndex, FONT_PICK_CACHE_LIMIT);
|
|
53239
|
+
return bestEmojiIndex;
|
|
53240
|
+
}
|
|
53241
|
+
}
|
|
53195
53242
|
if (nerdSymbol) {
|
|
53196
53243
|
const symbolIndex = fontState.fonts.findIndex((entry) => isSymbolFont(entry));
|
|
53197
53244
|
if (symbolIndex >= 0) {
|
|
@@ -53639,6 +53686,29 @@ function createResttyApp(options) {
|
|
|
53639
53686
|
} = render;
|
|
53640
53687
|
if (!codepoints || !fgBytes)
|
|
53641
53688
|
return;
|
|
53689
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
53690
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
53691
|
+
const readCellCluster = (cellIndex) => {
|
|
53692
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
53693
|
+
if (flag === 2 || flag === 3)
|
|
53694
|
+
return null;
|
|
53695
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
53696
|
+
if (!cp)
|
|
53697
|
+
return null;
|
|
53698
|
+
let text = String.fromCodePoint(cp);
|
|
53699
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
53700
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
53701
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
53702
|
+
const cps = [cp];
|
|
53703
|
+
for (let j = 0;j < extra; j += 1) {
|
|
53704
|
+
const extraCp = graphemeBuffer[start + j];
|
|
53705
|
+
if (extraCp)
|
|
53706
|
+
cps.push(extraCp);
|
|
53707
|
+
}
|
|
53708
|
+
text = String.fromCodePoint(...cps);
|
|
53709
|
+
}
|
|
53710
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
53711
|
+
};
|
|
53642
53712
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgpu", state);
|
|
53643
53713
|
const clearColor = useLinearBlending ? srgbToLinearColor(defaultBg) : defaultBg;
|
|
53644
53714
|
reportTermSize(cols, rows);
|
|
@@ -53874,28 +53944,43 @@ function createResttyApp(options) {
|
|
|
53874
53944
|
}
|
|
53875
53945
|
if (bgOnly || textHidden)
|
|
53876
53946
|
continue;
|
|
53877
|
-
|
|
53878
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
53947
|
+
if (mergedEmojiSkip[idx])
|
|
53879
53948
|
continue;
|
|
53880
|
-
const
|
|
53881
|
-
if (!
|
|
53949
|
+
const cluster = readCellCluster(idx);
|
|
53950
|
+
if (!cluster)
|
|
53882
53951
|
continue;
|
|
53952
|
+
const cp = cluster.cp;
|
|
53883
53953
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
53884
53954
|
continue;
|
|
53885
|
-
|
|
53886
|
-
|
|
53887
|
-
|
|
53888
|
-
|
|
53889
|
-
|
|
53890
|
-
|
|
53891
|
-
|
|
53892
|
-
|
|
53893
|
-
|
|
53894
|
-
|
|
53895
|
-
|
|
53955
|
+
let text = cluster.text;
|
|
53956
|
+
let baseSpan = cluster.span;
|
|
53957
|
+
const rowEnd = row * cols + cols;
|
|
53958
|
+
if (isRegionalIndicator(cp)) {
|
|
53959
|
+
const nextIdx = idx + baseSpan;
|
|
53960
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
53961
|
+
const next = readCellCluster(nextIdx);
|
|
53962
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
53963
|
+
text += next.text;
|
|
53964
|
+
baseSpan += next.span;
|
|
53965
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
53966
|
+
}
|
|
53896
53967
|
}
|
|
53897
|
-
text = String.fromCodePoint(...cps);
|
|
53898
53968
|
}
|
|
53969
|
+
let nextSeqIdx = idx + baseSpan;
|
|
53970
|
+
let guard = 0;
|
|
53971
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
53972
|
+
const next = readCellCluster(nextSeqIdx);
|
|
53973
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
53974
|
+
break;
|
|
53975
|
+
text += next.text;
|
|
53976
|
+
baseSpan += next.span;
|
|
53977
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
53978
|
+
nextSeqIdx += next.span;
|
|
53979
|
+
guard += 1;
|
|
53980
|
+
}
|
|
53981
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
53982
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
53983
|
+
continue;
|
|
53899
53984
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
53900
53985
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
53901
53986
|
}
|
|
@@ -53917,7 +54002,6 @@ function createResttyApp(options) {
|
|
|
53917
54002
|
}
|
|
53918
54003
|
if (extra > 0 && text.trim() === "")
|
|
53919
54004
|
continue;
|
|
53920
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
53921
54005
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
53922
54006
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
53923
54007
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
|
@@ -54515,6 +54599,29 @@ function createResttyApp(options) {
|
|
|
54515
54599
|
clearKittyOverlay();
|
|
54516
54600
|
return;
|
|
54517
54601
|
}
|
|
54602
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
54603
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
54604
|
+
const readCellCluster = (cellIndex) => {
|
|
54605
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
54606
|
+
if (flag === 2 || flag === 3)
|
|
54607
|
+
return null;
|
|
54608
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
54609
|
+
if (!cp)
|
|
54610
|
+
return null;
|
|
54611
|
+
let text = String.fromCodePoint(cp);
|
|
54612
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
54613
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
54614
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
54615
|
+
const cps = [cp];
|
|
54616
|
+
for (let j = 0;j < extra; j += 1) {
|
|
54617
|
+
const extraCp = graphemeBuffer[start + j];
|
|
54618
|
+
if (extraCp)
|
|
54619
|
+
cps.push(extraCp);
|
|
54620
|
+
}
|
|
54621
|
+
text = String.fromCodePoint(...cps);
|
|
54622
|
+
}
|
|
54623
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
54624
|
+
};
|
|
54518
54625
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgl2");
|
|
54519
54626
|
reportTermSize(cols, rows);
|
|
54520
54627
|
const cursorPos = cursor ? resolveCursorPosition(cursor) : null;
|
|
@@ -54735,28 +54842,43 @@ function createResttyApp(options) {
|
|
|
54735
54842
|
}
|
|
54736
54843
|
if (bgOnly || textHidden)
|
|
54737
54844
|
continue;
|
|
54738
|
-
|
|
54739
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
54845
|
+
if (mergedEmojiSkip[idx])
|
|
54740
54846
|
continue;
|
|
54741
|
-
const
|
|
54742
|
-
if (!
|
|
54847
|
+
const cluster = readCellCluster(idx);
|
|
54848
|
+
if (!cluster)
|
|
54743
54849
|
continue;
|
|
54850
|
+
const cp = cluster.cp;
|
|
54744
54851
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
54745
54852
|
continue;
|
|
54746
|
-
|
|
54747
|
-
|
|
54748
|
-
|
|
54749
|
-
|
|
54750
|
-
|
|
54751
|
-
|
|
54752
|
-
|
|
54753
|
-
|
|
54754
|
-
|
|
54755
|
-
|
|
54756
|
-
|
|
54853
|
+
let text = cluster.text;
|
|
54854
|
+
let baseSpan = cluster.span;
|
|
54855
|
+
const rowEnd = row * cols + cols;
|
|
54856
|
+
if (isRegionalIndicator(cp)) {
|
|
54857
|
+
const nextIdx = idx + baseSpan;
|
|
54858
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
54859
|
+
const next = readCellCluster(nextIdx);
|
|
54860
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
54861
|
+
text += next.text;
|
|
54862
|
+
baseSpan += next.span;
|
|
54863
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
54864
|
+
}
|
|
54757
54865
|
}
|
|
54758
|
-
text = String.fromCodePoint(...cps);
|
|
54759
54866
|
}
|
|
54867
|
+
let nextSeqIdx = idx + baseSpan;
|
|
54868
|
+
let guard = 0;
|
|
54869
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
54870
|
+
const next = readCellCluster(nextSeqIdx);
|
|
54871
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
54872
|
+
break;
|
|
54873
|
+
text += next.text;
|
|
54874
|
+
baseSpan += next.span;
|
|
54875
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
54876
|
+
nextSeqIdx += next.span;
|
|
54877
|
+
guard += 1;
|
|
54878
|
+
}
|
|
54879
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
54880
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
54881
|
+
continue;
|
|
54760
54882
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
54761
54883
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
54762
54884
|
}
|
|
@@ -54778,7 +54900,6 @@ function createResttyApp(options) {
|
|
|
54778
54900
|
}
|
|
54779
54901
|
if (extra > 0 && text.trim() === "")
|
|
54780
54902
|
continue;
|
|
54781
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
54782
54903
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
54783
54904
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
54784
54905
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
package/dist/fonts/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -8672,7 +8672,6 @@ var COLOR_EMOJI_FONT_HINTS = [
|
|
|
8672
8672
|
/apple color emoji/i,
|
|
8673
8673
|
/noto color emoji/i,
|
|
8674
8674
|
/segoe ui emoji/i,
|
|
8675
|
-
/openmoji/i,
|
|
8676
8675
|
/twemoji/i
|
|
8677
8676
|
];
|
|
8678
8677
|
var WIDE_FONT_HINTS = [
|
|
@@ -25641,9 +25640,17 @@ var DEFAULT_FONT_SOURCES = [
|
|
|
25641
25640
|
type: "url",
|
|
25642
25641
|
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-fonts@main/unhinted/ttf/NotoSansSymbols2/NotoSansSymbols2-Regular.ttf"
|
|
25643
25642
|
},
|
|
25643
|
+
{
|
|
25644
|
+
type: "url",
|
|
25645
|
+
url: "https://cdn.jsdelivr.net/gh/googlefonts/noto-emoji@main/fonts/NotoColorEmoji.ttf"
|
|
25646
|
+
},
|
|
25644
25647
|
{
|
|
25645
25648
|
type: "url",
|
|
25646
25649
|
url: "https://cdn.jsdelivr.net/gh/hfg-gmuend/openmoji@master/font/OpenMoji-black-glyf/OpenMoji-black-glyf.ttf"
|
|
25650
|
+
},
|
|
25651
|
+
{
|
|
25652
|
+
type: "url",
|
|
25653
|
+
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf"
|
|
25647
25654
|
}
|
|
25648
25655
|
];
|
|
25649
25656
|
function validateFontSource(source, index) {
|
|
@@ -53192,6 +53199,46 @@ function createResttyApp(options) {
|
|
|
53192
53199
|
const firstCp = text.codePointAt(0) ?? 0;
|
|
53193
53200
|
const nerdSymbol = isNerdSymbolCodepoint(firstCp);
|
|
53194
53201
|
const preferSymbol = nerdSymbol || isSymbolCp(firstCp);
|
|
53202
|
+
const preferEmoji = text.includes("") || chars.some((ch) => {
|
|
53203
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
53204
|
+
if (cp >= 127462 && cp <= 127487)
|
|
53205
|
+
return true;
|
|
53206
|
+
if (cp >= 127744 && cp <= 129791)
|
|
53207
|
+
return true;
|
|
53208
|
+
return false;
|
|
53209
|
+
});
|
|
53210
|
+
if (preferEmoji) {
|
|
53211
|
+
let bestEmojiIndex = -1;
|
|
53212
|
+
let bestEmojiScore = Number.POSITIVE_INFINITY;
|
|
53213
|
+
for (let i3 = 0;i3 < fontState.fonts.length; i3 += 1) {
|
|
53214
|
+
const entry = fontState.fonts[i3];
|
|
53215
|
+
if (!entry?.font || !isColorEmojiFont(entry))
|
|
53216
|
+
continue;
|
|
53217
|
+
let ok = true;
|
|
53218
|
+
for (const ch of chars) {
|
|
53219
|
+
if (!fontHasGlyph2(entry.font, ch)) {
|
|
53220
|
+
ok = false;
|
|
53221
|
+
break;
|
|
53222
|
+
}
|
|
53223
|
+
}
|
|
53224
|
+
if (!ok)
|
|
53225
|
+
continue;
|
|
53226
|
+
const shaped = shapeClusterWithFont(entry, text);
|
|
53227
|
+
let score = shaped.glyphs.length;
|
|
53228
|
+
if (/noto color emoji/i.test(entry.label))
|
|
53229
|
+
score -= 0.25;
|
|
53230
|
+
if (score < bestEmojiScore) {
|
|
53231
|
+
bestEmojiScore = score;
|
|
53232
|
+
bestEmojiIndex = i3;
|
|
53233
|
+
if (score <= 0.75)
|
|
53234
|
+
break;
|
|
53235
|
+
}
|
|
53236
|
+
}
|
|
53237
|
+
if (bestEmojiIndex >= 0) {
|
|
53238
|
+
setBoundedMap(fontState.fontPickCache, cacheKey, bestEmojiIndex, FONT_PICK_CACHE_LIMIT);
|
|
53239
|
+
return bestEmojiIndex;
|
|
53240
|
+
}
|
|
53241
|
+
}
|
|
53195
53242
|
if (nerdSymbol) {
|
|
53196
53243
|
const symbolIndex = fontState.fonts.findIndex((entry) => isSymbolFont(entry));
|
|
53197
53244
|
if (symbolIndex >= 0) {
|
|
@@ -53639,6 +53686,29 @@ function createResttyApp(options) {
|
|
|
53639
53686
|
} = render;
|
|
53640
53687
|
if (!codepoints || !fgBytes)
|
|
53641
53688
|
return;
|
|
53689
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
53690
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
53691
|
+
const readCellCluster = (cellIndex) => {
|
|
53692
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
53693
|
+
if (flag === 2 || flag === 3)
|
|
53694
|
+
return null;
|
|
53695
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
53696
|
+
if (!cp)
|
|
53697
|
+
return null;
|
|
53698
|
+
let text = String.fromCodePoint(cp);
|
|
53699
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
53700
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
53701
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
53702
|
+
const cps = [cp];
|
|
53703
|
+
for (let j = 0;j < extra; j += 1) {
|
|
53704
|
+
const extraCp = graphemeBuffer[start + j];
|
|
53705
|
+
if (extraCp)
|
|
53706
|
+
cps.push(extraCp);
|
|
53707
|
+
}
|
|
53708
|
+
text = String.fromCodePoint(...cps);
|
|
53709
|
+
}
|
|
53710
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
53711
|
+
};
|
|
53642
53712
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgpu", state);
|
|
53643
53713
|
const clearColor = useLinearBlending ? srgbToLinearColor(defaultBg) : defaultBg;
|
|
53644
53714
|
reportTermSize(cols, rows);
|
|
@@ -53874,28 +53944,43 @@ function createResttyApp(options) {
|
|
|
53874
53944
|
}
|
|
53875
53945
|
if (bgOnly || textHidden)
|
|
53876
53946
|
continue;
|
|
53877
|
-
|
|
53878
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
53947
|
+
if (mergedEmojiSkip[idx])
|
|
53879
53948
|
continue;
|
|
53880
|
-
const
|
|
53881
|
-
if (!
|
|
53949
|
+
const cluster = readCellCluster(idx);
|
|
53950
|
+
if (!cluster)
|
|
53882
53951
|
continue;
|
|
53952
|
+
const cp = cluster.cp;
|
|
53883
53953
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
53884
53954
|
continue;
|
|
53885
|
-
|
|
53886
|
-
|
|
53887
|
-
|
|
53888
|
-
|
|
53889
|
-
|
|
53890
|
-
|
|
53891
|
-
|
|
53892
|
-
|
|
53893
|
-
|
|
53894
|
-
|
|
53895
|
-
|
|
53955
|
+
let text = cluster.text;
|
|
53956
|
+
let baseSpan = cluster.span;
|
|
53957
|
+
const rowEnd = row * cols + cols;
|
|
53958
|
+
if (isRegionalIndicator(cp)) {
|
|
53959
|
+
const nextIdx = idx + baseSpan;
|
|
53960
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
53961
|
+
const next = readCellCluster(nextIdx);
|
|
53962
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
53963
|
+
text += next.text;
|
|
53964
|
+
baseSpan += next.span;
|
|
53965
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
53966
|
+
}
|
|
53896
53967
|
}
|
|
53897
|
-
text = String.fromCodePoint(...cps);
|
|
53898
53968
|
}
|
|
53969
|
+
let nextSeqIdx = idx + baseSpan;
|
|
53970
|
+
let guard = 0;
|
|
53971
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
53972
|
+
const next = readCellCluster(nextSeqIdx);
|
|
53973
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
53974
|
+
break;
|
|
53975
|
+
text += next.text;
|
|
53976
|
+
baseSpan += next.span;
|
|
53977
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
53978
|
+
nextSeqIdx += next.span;
|
|
53979
|
+
guard += 1;
|
|
53980
|
+
}
|
|
53981
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
53982
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
53983
|
+
continue;
|
|
53899
53984
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
53900
53985
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
53901
53986
|
}
|
|
@@ -53917,7 +54002,6 @@ function createResttyApp(options) {
|
|
|
53917
54002
|
}
|
|
53918
54003
|
if (extra > 0 && text.trim() === "")
|
|
53919
54004
|
continue;
|
|
53920
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
53921
54005
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
53922
54006
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
53923
54007
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
|
@@ -54515,6 +54599,29 @@ function createResttyApp(options) {
|
|
|
54515
54599
|
clearKittyOverlay();
|
|
54516
54600
|
return;
|
|
54517
54601
|
}
|
|
54602
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
54603
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
54604
|
+
const readCellCluster = (cellIndex) => {
|
|
54605
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
54606
|
+
if (flag === 2 || flag === 3)
|
|
54607
|
+
return null;
|
|
54608
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
54609
|
+
if (!cp)
|
|
54610
|
+
return null;
|
|
54611
|
+
let text = String.fromCodePoint(cp);
|
|
54612
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
54613
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
54614
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
54615
|
+
const cps = [cp];
|
|
54616
|
+
for (let j = 0;j < extra; j += 1) {
|
|
54617
|
+
const extraCp = graphemeBuffer[start + j];
|
|
54618
|
+
if (extraCp)
|
|
54619
|
+
cps.push(extraCp);
|
|
54620
|
+
}
|
|
54621
|
+
text = String.fromCodePoint(...cps);
|
|
54622
|
+
}
|
|
54623
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
54624
|
+
};
|
|
54518
54625
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgl2");
|
|
54519
54626
|
reportTermSize(cols, rows);
|
|
54520
54627
|
const cursorPos = cursor ? resolveCursorPosition(cursor) : null;
|
|
@@ -54735,28 +54842,43 @@ function createResttyApp(options) {
|
|
|
54735
54842
|
}
|
|
54736
54843
|
if (bgOnly || textHidden)
|
|
54737
54844
|
continue;
|
|
54738
|
-
|
|
54739
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
54845
|
+
if (mergedEmojiSkip[idx])
|
|
54740
54846
|
continue;
|
|
54741
|
-
const
|
|
54742
|
-
if (!
|
|
54847
|
+
const cluster = readCellCluster(idx);
|
|
54848
|
+
if (!cluster)
|
|
54743
54849
|
continue;
|
|
54850
|
+
const cp = cluster.cp;
|
|
54744
54851
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
54745
54852
|
continue;
|
|
54746
|
-
|
|
54747
|
-
|
|
54748
|
-
|
|
54749
|
-
|
|
54750
|
-
|
|
54751
|
-
|
|
54752
|
-
|
|
54753
|
-
|
|
54754
|
-
|
|
54755
|
-
|
|
54756
|
-
|
|
54853
|
+
let text = cluster.text;
|
|
54854
|
+
let baseSpan = cluster.span;
|
|
54855
|
+
const rowEnd = row * cols + cols;
|
|
54856
|
+
if (isRegionalIndicator(cp)) {
|
|
54857
|
+
const nextIdx = idx + baseSpan;
|
|
54858
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
54859
|
+
const next = readCellCluster(nextIdx);
|
|
54860
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
54861
|
+
text += next.text;
|
|
54862
|
+
baseSpan += next.span;
|
|
54863
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
54864
|
+
}
|
|
54757
54865
|
}
|
|
54758
|
-
text = String.fromCodePoint(...cps);
|
|
54759
54866
|
}
|
|
54867
|
+
let nextSeqIdx = idx + baseSpan;
|
|
54868
|
+
let guard = 0;
|
|
54869
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
54870
|
+
const next = readCellCluster(nextSeqIdx);
|
|
54871
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
54872
|
+
break;
|
|
54873
|
+
text += next.text;
|
|
54874
|
+
baseSpan += next.span;
|
|
54875
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
54876
|
+
nextSeqIdx += next.span;
|
|
54877
|
+
guard += 1;
|
|
54878
|
+
}
|
|
54879
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
54880
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
54881
|
+
continue;
|
|
54760
54882
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
54761
54883
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
54762
54884
|
}
|
|
@@ -54778,7 +54900,6 @@ function createResttyApp(options) {
|
|
|
54778
54900
|
}
|
|
54779
54901
|
if (extra > 0 && text.trim() === "")
|
|
54780
54902
|
continue;
|
|
54781
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
54782
54903
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
54783
54904
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
54784
54905
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
package/dist/internal.js
CHANGED
|
@@ -8672,7 +8672,6 @@ var COLOR_EMOJI_FONT_HINTS = [
|
|
|
8672
8672
|
/apple color emoji/i,
|
|
8673
8673
|
/noto color emoji/i,
|
|
8674
8674
|
/segoe ui emoji/i,
|
|
8675
|
-
/openmoji/i,
|
|
8676
8675
|
/twemoji/i
|
|
8677
8676
|
];
|
|
8678
8677
|
var WIDE_FONT_HINTS = [
|
|
@@ -25641,9 +25640,17 @@ var DEFAULT_FONT_SOURCES = [
|
|
|
25641
25640
|
type: "url",
|
|
25642
25641
|
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-fonts@main/unhinted/ttf/NotoSansSymbols2/NotoSansSymbols2-Regular.ttf"
|
|
25643
25642
|
},
|
|
25643
|
+
{
|
|
25644
|
+
type: "url",
|
|
25645
|
+
url: "https://cdn.jsdelivr.net/gh/googlefonts/noto-emoji@main/fonts/NotoColorEmoji.ttf"
|
|
25646
|
+
},
|
|
25644
25647
|
{
|
|
25645
25648
|
type: "url",
|
|
25646
25649
|
url: "https://cdn.jsdelivr.net/gh/hfg-gmuend/openmoji@master/font/OpenMoji-black-glyf/OpenMoji-black-glyf.ttf"
|
|
25650
|
+
},
|
|
25651
|
+
{
|
|
25652
|
+
type: "url",
|
|
25653
|
+
url: "https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf"
|
|
25647
25654
|
}
|
|
25648
25655
|
];
|
|
25649
25656
|
function validateFontSource(source, index) {
|
|
@@ -53192,6 +53199,46 @@ function createResttyApp(options) {
|
|
|
53192
53199
|
const firstCp = text.codePointAt(0) ?? 0;
|
|
53193
53200
|
const nerdSymbol = isNerdSymbolCodepoint(firstCp);
|
|
53194
53201
|
const preferSymbol = nerdSymbol || isSymbolCp(firstCp);
|
|
53202
|
+
const preferEmoji = text.includes("") || chars.some((ch) => {
|
|
53203
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
53204
|
+
if (cp >= 127462 && cp <= 127487)
|
|
53205
|
+
return true;
|
|
53206
|
+
if (cp >= 127744 && cp <= 129791)
|
|
53207
|
+
return true;
|
|
53208
|
+
return false;
|
|
53209
|
+
});
|
|
53210
|
+
if (preferEmoji) {
|
|
53211
|
+
let bestEmojiIndex = -1;
|
|
53212
|
+
let bestEmojiScore = Number.POSITIVE_INFINITY;
|
|
53213
|
+
for (let i3 = 0;i3 < fontState.fonts.length; i3 += 1) {
|
|
53214
|
+
const entry = fontState.fonts[i3];
|
|
53215
|
+
if (!entry?.font || !isColorEmojiFont(entry))
|
|
53216
|
+
continue;
|
|
53217
|
+
let ok = true;
|
|
53218
|
+
for (const ch of chars) {
|
|
53219
|
+
if (!fontHasGlyph2(entry.font, ch)) {
|
|
53220
|
+
ok = false;
|
|
53221
|
+
break;
|
|
53222
|
+
}
|
|
53223
|
+
}
|
|
53224
|
+
if (!ok)
|
|
53225
|
+
continue;
|
|
53226
|
+
const shaped = shapeClusterWithFont(entry, text);
|
|
53227
|
+
let score = shaped.glyphs.length;
|
|
53228
|
+
if (/noto color emoji/i.test(entry.label))
|
|
53229
|
+
score -= 0.25;
|
|
53230
|
+
if (score < bestEmojiScore) {
|
|
53231
|
+
bestEmojiScore = score;
|
|
53232
|
+
bestEmojiIndex = i3;
|
|
53233
|
+
if (score <= 0.75)
|
|
53234
|
+
break;
|
|
53235
|
+
}
|
|
53236
|
+
}
|
|
53237
|
+
if (bestEmojiIndex >= 0) {
|
|
53238
|
+
setBoundedMap(fontState.fontPickCache, cacheKey, bestEmojiIndex, FONT_PICK_CACHE_LIMIT);
|
|
53239
|
+
return bestEmojiIndex;
|
|
53240
|
+
}
|
|
53241
|
+
}
|
|
53195
53242
|
if (nerdSymbol) {
|
|
53196
53243
|
const symbolIndex = fontState.fonts.findIndex((entry) => isSymbolFont(entry));
|
|
53197
53244
|
if (symbolIndex >= 0) {
|
|
@@ -53639,6 +53686,29 @@ function createResttyApp(options) {
|
|
|
53639
53686
|
} = render;
|
|
53640
53687
|
if (!codepoints || !fgBytes)
|
|
53641
53688
|
return;
|
|
53689
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
53690
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
53691
|
+
const readCellCluster = (cellIndex) => {
|
|
53692
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
53693
|
+
if (flag === 2 || flag === 3)
|
|
53694
|
+
return null;
|
|
53695
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
53696
|
+
if (!cp)
|
|
53697
|
+
return null;
|
|
53698
|
+
let text = String.fromCodePoint(cp);
|
|
53699
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
53700
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
53701
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
53702
|
+
const cps = [cp];
|
|
53703
|
+
for (let j = 0;j < extra; j += 1) {
|
|
53704
|
+
const extraCp = graphemeBuffer[start + j];
|
|
53705
|
+
if (extraCp)
|
|
53706
|
+
cps.push(extraCp);
|
|
53707
|
+
}
|
|
53708
|
+
text = String.fromCodePoint(...cps);
|
|
53709
|
+
}
|
|
53710
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
53711
|
+
};
|
|
53642
53712
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgpu", state);
|
|
53643
53713
|
const clearColor = useLinearBlending ? srgbToLinearColor(defaultBg) : defaultBg;
|
|
53644
53714
|
reportTermSize(cols, rows);
|
|
@@ -53874,28 +53944,43 @@ function createResttyApp(options) {
|
|
|
53874
53944
|
}
|
|
53875
53945
|
if (bgOnly || textHidden)
|
|
53876
53946
|
continue;
|
|
53877
|
-
|
|
53878
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
53947
|
+
if (mergedEmojiSkip[idx])
|
|
53879
53948
|
continue;
|
|
53880
|
-
const
|
|
53881
|
-
if (!
|
|
53949
|
+
const cluster = readCellCluster(idx);
|
|
53950
|
+
if (!cluster)
|
|
53882
53951
|
continue;
|
|
53952
|
+
const cp = cluster.cp;
|
|
53883
53953
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
53884
53954
|
continue;
|
|
53885
|
-
|
|
53886
|
-
|
|
53887
|
-
|
|
53888
|
-
|
|
53889
|
-
|
|
53890
|
-
|
|
53891
|
-
|
|
53892
|
-
|
|
53893
|
-
|
|
53894
|
-
|
|
53895
|
-
|
|
53955
|
+
let text = cluster.text;
|
|
53956
|
+
let baseSpan = cluster.span;
|
|
53957
|
+
const rowEnd = row * cols + cols;
|
|
53958
|
+
if (isRegionalIndicator(cp)) {
|
|
53959
|
+
const nextIdx = idx + baseSpan;
|
|
53960
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
53961
|
+
const next = readCellCluster(nextIdx);
|
|
53962
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
53963
|
+
text += next.text;
|
|
53964
|
+
baseSpan += next.span;
|
|
53965
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
53966
|
+
}
|
|
53896
53967
|
}
|
|
53897
|
-
text = String.fromCodePoint(...cps);
|
|
53898
53968
|
}
|
|
53969
|
+
let nextSeqIdx = idx + baseSpan;
|
|
53970
|
+
let guard = 0;
|
|
53971
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
53972
|
+
const next = readCellCluster(nextSeqIdx);
|
|
53973
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
53974
|
+
break;
|
|
53975
|
+
text += next.text;
|
|
53976
|
+
baseSpan += next.span;
|
|
53977
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
53978
|
+
nextSeqIdx += next.span;
|
|
53979
|
+
guard += 1;
|
|
53980
|
+
}
|
|
53981
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
53982
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
53983
|
+
continue;
|
|
53899
53984
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
53900
53985
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
53901
53986
|
}
|
|
@@ -53917,7 +54002,6 @@ function createResttyApp(options) {
|
|
|
53917
54002
|
}
|
|
53918
54003
|
if (extra > 0 && text.trim() === "")
|
|
53919
54004
|
continue;
|
|
53920
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
53921
54005
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
53922
54006
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
53923
54007
|
const shaped = shapeClusterWithFont(fontEntry, text);
|
|
@@ -54515,6 +54599,29 @@ function createResttyApp(options) {
|
|
|
54515
54599
|
clearKittyOverlay();
|
|
54516
54600
|
return;
|
|
54517
54601
|
}
|
|
54602
|
+
const mergedEmojiSkip = new Uint8Array(codepoints.length);
|
|
54603
|
+
const isRegionalIndicator = (value) => value >= 127462 && value <= 127487;
|
|
54604
|
+
const readCellCluster = (cellIndex) => {
|
|
54605
|
+
const flag = wide ? wide[cellIndex] ?? 0 : 0;
|
|
54606
|
+
if (flag === 2 || flag === 3)
|
|
54607
|
+
return null;
|
|
54608
|
+
const cp = codepoints[cellIndex] ?? 0;
|
|
54609
|
+
if (!cp)
|
|
54610
|
+
return null;
|
|
54611
|
+
let text = String.fromCodePoint(cp);
|
|
54612
|
+
const extra = graphemeLen && graphemeOffset && graphemeBuffer ? graphemeLen[cellIndex] ?? 0 : 0;
|
|
54613
|
+
if (extra > 0 && graphemeOffset && graphemeBuffer) {
|
|
54614
|
+
const start = graphemeOffset[cellIndex] ?? 0;
|
|
54615
|
+
const cps = [cp];
|
|
54616
|
+
for (let j = 0;j < extra; j += 1) {
|
|
54617
|
+
const extraCp = graphemeBuffer[start + j];
|
|
54618
|
+
if (extraCp)
|
|
54619
|
+
cps.push(extraCp);
|
|
54620
|
+
}
|
|
54621
|
+
text = String.fromCodePoint(...cps);
|
|
54622
|
+
}
|
|
54623
|
+
return { cp, text, span: flag === 1 ? 2 : 1 };
|
|
54624
|
+
};
|
|
54518
54625
|
const { useLinearBlending, useLinearCorrection } = resolveBlendFlags("webgl2");
|
|
54519
54626
|
reportTermSize(cols, rows);
|
|
54520
54627
|
const cursorPos = cursor ? resolveCursorPosition(cursor) : null;
|
|
@@ -54735,28 +54842,43 @@ function createResttyApp(options) {
|
|
|
54735
54842
|
}
|
|
54736
54843
|
if (bgOnly || textHidden)
|
|
54737
54844
|
continue;
|
|
54738
|
-
|
|
54739
|
-
if (wideFlag === 2 || wideFlag === 3)
|
|
54845
|
+
if (mergedEmojiSkip[idx])
|
|
54740
54846
|
continue;
|
|
54741
|
-
const
|
|
54742
|
-
if (!
|
|
54847
|
+
const cluster = readCellCluster(idx);
|
|
54848
|
+
if (!cluster)
|
|
54743
54849
|
continue;
|
|
54850
|
+
const cp = cluster.cp;
|
|
54744
54851
|
if (cp === KITTY_PLACEHOLDER_CP)
|
|
54745
54852
|
continue;
|
|
54746
|
-
|
|
54747
|
-
|
|
54748
|
-
|
|
54749
|
-
|
|
54750
|
-
|
|
54751
|
-
|
|
54752
|
-
|
|
54753
|
-
|
|
54754
|
-
|
|
54755
|
-
|
|
54756
|
-
|
|
54853
|
+
let text = cluster.text;
|
|
54854
|
+
let baseSpan = cluster.span;
|
|
54855
|
+
const rowEnd = row * cols + cols;
|
|
54856
|
+
if (isRegionalIndicator(cp)) {
|
|
54857
|
+
const nextIdx = idx + baseSpan;
|
|
54858
|
+
if (nextIdx < rowEnd && !mergedEmojiSkip[nextIdx]) {
|
|
54859
|
+
const next = readCellCluster(nextIdx);
|
|
54860
|
+
if (next && isRegionalIndicator(next.cp)) {
|
|
54861
|
+
text += next.text;
|
|
54862
|
+
baseSpan += next.span;
|
|
54863
|
+
mergedEmojiSkip[nextIdx] = 1;
|
|
54864
|
+
}
|
|
54757
54865
|
}
|
|
54758
|
-
text = String.fromCodePoint(...cps);
|
|
54759
54866
|
}
|
|
54867
|
+
let nextSeqIdx = idx + baseSpan;
|
|
54868
|
+
let guard = 0;
|
|
54869
|
+
while ((text.codePointAt(text.length - 1) ?? 0) === 8205 && nextSeqIdx < rowEnd && guard < 8) {
|
|
54870
|
+
const next = readCellCluster(nextSeqIdx);
|
|
54871
|
+
if (!next || !next.cp || isSpaceCp(next.cp))
|
|
54872
|
+
break;
|
|
54873
|
+
text += next.text;
|
|
54874
|
+
baseSpan += next.span;
|
|
54875
|
+
mergedEmojiSkip[nextSeqIdx] = 1;
|
|
54876
|
+
nextSeqIdx += next.span;
|
|
54877
|
+
guard += 1;
|
|
54878
|
+
}
|
|
54879
|
+
const extra = text.length > String.fromCodePoint(cp).length ? 1 : 0;
|
|
54880
|
+
if (extra === 0 && isSpaceCp(cp))
|
|
54881
|
+
continue;
|
|
54760
54882
|
if (cursorBlock && cursorCell && row === cursorCell.row && col >= cursorCell.col && col < cursorCell.col + (cursorCell.wide ? 2 : 1)) {
|
|
54761
54883
|
fg = [bgForText[0], bgForText[1], bgForText[2], 1];
|
|
54762
54884
|
}
|
|
@@ -54778,7 +54900,6 @@ function createResttyApp(options) {
|
|
|
54778
54900
|
}
|
|
54779
54901
|
if (extra > 0 && text.trim() === "")
|
|
54780
54902
|
continue;
|
|
54781
|
-
const baseSpan = wideFlag === 1 ? 2 : 1;
|
|
54782
54903
|
const fontIndex = pickFontIndexForText2(text, baseSpan);
|
|
54783
54904
|
const fontEntry = fontState.fonts[fontIndex] ?? fontState.fonts[0];
|
|
54784
54905
|
const shaped = shapeClusterWithFont(fontEntry, text);
|