@react-x11/components 0.10.0 → 0.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/dist/code/index.d.ts.map +1 -1
- package/dist/code/index.js +25 -24
- package/dist/code/index.js.map +1 -1
- package/dist/code-language/index.d.ts +1 -1
- package/dist/code-language/index.d.ts.map +1 -1
- package/dist/code-language/index.js +1 -1
- package/dist/code-language/index.js.map +1 -1
- package/dist/code-language/runs.d.ts +31 -0
- package/dist/code-language/runs.d.ts.map +1 -1
- package/dist/code-language/runs.js +105 -0
- package/dist/code-language/runs.js.map +1 -1
- package/dist/codeblock/index.d.ts +13 -0
- package/dist/codeblock/index.d.ts.map +1 -1
- package/dist/codeblock/index.js +37 -1
- package/dist/codeblock/index.js.map +1 -1
- package/dist/html/css/cascade.d.ts +32 -10
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +72 -27
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/style.d.ts +7 -4
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +37 -6
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.js +8 -5
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +127 -9
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +27 -0
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +30 -2
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/inline.d.ts +3 -0
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +236 -14
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +118 -57
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +203 -37
- package/dist/html/paint.js.map +1 -1
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +27 -20
- package/dist/html/svg.js.map +1 -1
- package/dist/internal/codelines.d.ts +42 -0
- package/dist/internal/codelines.d.ts.map +1 -0
- package/dist/internal/codelines.js +170 -0
- package/dist/internal/codelines.js.map +1 -0
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +98 -26
- package/dist/markdown/index.js.map +1 -1
- package/dist/rich-text-editor/index.d.ts.map +1 -1
- package/dist/rich-text-editor/index.js +3 -8
- package/dist/rich-text-editor/index.js.map +1 -1
- package/dist/rich-text-editor/markdown.d.ts.map +1 -1
- package/dist/rich-text-editor/markdown.js +30 -1
- package/dist/rich-text-editor/markdown.js.map +1 -1
- package/dist/rich-text-editor/replace.d.ts +13 -0
- package/dist/rich-text-editor/replace.d.ts.map +1 -0
- package/dist/rich-text-editor/replace.js +64 -0
- package/dist/rich-text-editor/replace.js.map +1 -0
- package/dist/terminal-output/index.d.ts.map +1 -1
- package/dist/terminal-output/index.js +100 -25
- package/dist/terminal-output/index.js.map +1 -1
- package/dist/terminal-output/runs.d.ts +4 -1
- package/dist/terminal-output/runs.d.ts.map +1 -1
- package/dist/terminal-output/runs.js +5 -1
- package/dist/terminal-output/runs.js.map +1 -1
- package/package.json +1 -1
- package/src/code/index.ts +34 -32
- package/src/code-language/index.ts +1 -1
- package/src/code-language/runs.ts +111 -1
- package/src/codeblock/index.ts +48 -1
- package/src/html/css/cascade.ts +117 -39
- package/src/html/css/style.ts +43 -15
- package/src/html/css/ua.ts +8 -5
- package/src/html/layout/block.ts +134 -8
- package/src/html/layout/boxes.ts +43 -2
- package/src/html/layout/inline.ts +257 -13
- package/src/html/node.ts +145 -79
- package/src/html/paint.ts +236 -45
- package/src/html/svg.ts +30 -19
- package/src/internal/codelines.ts +200 -0
- package/src/markdown/index.ts +145 -26
- package/src/rich-text-editor/index.ts +3 -11
- package/src/rich-text-editor/markdown.ts +36 -1
- package/src/rich-text-editor/replace.ts +85 -0
- package/src/terminal-output/index.ts +127 -34
- package/src/terminal-output/runs.ts +16 -2
package/src/html/node.ts
CHANGED
|
@@ -51,14 +51,22 @@ import { codePointAtOffset, codeUnitOffsets } from '../internal/text.js';
|
|
|
51
51
|
import { attr, HtmlSource, imageUrlOf, isElement, tagOf } from './dom.js';
|
|
52
52
|
import type { Document } from './dom.js';
|
|
53
53
|
import { Cascade } from './css/cascade.js';
|
|
54
|
+
import type { MetricFace } from './css/cascade.js';
|
|
54
55
|
import { mediaMatches, parseStylesheet } from './css/parse.js';
|
|
55
56
|
import type { Stylesheet } from './css/parse.js';
|
|
56
57
|
import { uaStylesheet } from './css/ua.js';
|
|
57
58
|
import type { ComputedStyle, RootLook } from './css/style.js';
|
|
58
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
BOX_RAISES,
|
|
61
|
+
buildBoxes,
|
|
62
|
+
CONTENT_IMAGES,
|
|
63
|
+
LINE_BOX_RAISES,
|
|
64
|
+
SHIFTED_LINES,
|
|
65
|
+
} from './layout/boxes.js';
|
|
59
66
|
import type {
|
|
60
67
|
Box,
|
|
61
68
|
BoxTree,
|
|
69
|
+
LineBox,
|
|
62
70
|
LineText,
|
|
63
71
|
ReplacedKind,
|
|
64
72
|
TextLayoutLike,
|
|
@@ -67,7 +75,7 @@ import { layoutDocument } from './layout/block.js';
|
|
|
67
75
|
import { TextLayoutCache } from './layout/cache.js';
|
|
68
76
|
import { shapingSafe } from './layout/shaping.js';
|
|
69
77
|
import { SurfaceCache } from './surfaces.js';
|
|
70
|
-
import { inlineDecoration, runFor } from './layout/inline.js';
|
|
78
|
+
import { faceExtentOf, inlineDecoration, runFor } from './layout/inline.js';
|
|
71
79
|
import type { FontsLike } from './layout/inline.js';
|
|
72
80
|
import type { TextRun } from '../richtext/index.js';
|
|
73
81
|
// Through the inline module rather than a second cache: the offsets table for
|
|
@@ -583,9 +591,9 @@ export class HtmlViewNode extends Node {
|
|
|
583
591
|
width,
|
|
584
592
|
this._viewportHeight(),
|
|
585
593
|
this._scale,
|
|
586
|
-
fonts ? (
|
|
587
|
-
fonts ? (
|
|
588
|
-
fonts ? (
|
|
594
|
+
fonts ? (face) => xHeightOf(fonts, face) : null,
|
|
595
|
+
fonts ? (face) => zeroWidthOf(fonts, face) : null,
|
|
596
|
+
fonts ? (face) => normalLineOf(fonts, face) : null,
|
|
589
597
|
faces.length ? this._webFonts : null,
|
|
590
598
|
);
|
|
591
599
|
this._sheetsRead = {
|
|
@@ -1188,17 +1196,38 @@ export class HtmlViewNode extends Node {
|
|
|
1188
1196
|
rect = { x: box.x, y: box.y, width: box.width, height: box.height };
|
|
1189
1197
|
} else {
|
|
1190
1198
|
const bands: Rect[] = [];
|
|
1199
|
+
// an inline box's fragments are on the lines of the block it is laid
|
|
1200
|
+
// out in, and no text of a float or a positioned box inside it — on
|
|
1201
|
+
// lines of their own — is one of them (CSSOM View 6.1): a list item
|
|
1202
|
+
// made inline around an absolute link measured as the link
|
|
1203
|
+
let block: Box | null = box.parent;
|
|
1204
|
+
while (block && !block.lines) block = block.parent;
|
|
1191
1205
|
if (box.subtreeTextEnd > box.subtreeTextStart) {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1206
|
+
if (box.kind === 'inline' && block?.lines) {
|
|
1207
|
+
lineBands(
|
|
1208
|
+
block.lines,
|
|
1209
|
+
box.subtreeTextStart,
|
|
1210
|
+
box.subtreeTextEnd,
|
|
1211
|
+
0,
|
|
1212
|
+
0,
|
|
1213
|
+
bands,
|
|
1214
|
+
);
|
|
1215
|
+
} else {
|
|
1216
|
+
collectBands(
|
|
1217
|
+
tree.root,
|
|
1218
|
+
box.subtreeTextStart,
|
|
1219
|
+
box.subtreeTextEnd,
|
|
1220
|
+
0,
|
|
1221
|
+
0,
|
|
1222
|
+
bands,
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
if (box.kind === 'inline') {
|
|
1227
|
+
fragmentReach(box, bands);
|
|
1228
|
+
const fonts = this._layouts?.fonts;
|
|
1229
|
+
if (fonts) fragmentHeights(box, bands, fonts);
|
|
1200
1230
|
}
|
|
1201
|
-
if (box.kind === 'inline') fragmentReach(box, bands);
|
|
1202
1231
|
for (const band of bands) rect = rect ? unionRect(rect, band) : band;
|
|
1203
1232
|
if (!rect) {
|
|
1204
1233
|
// an empty subtree's range is `[0, 0)`, wherever it stands: where
|
|
@@ -1936,56 +1965,96 @@ function fragmentReach(box: Box, out: Rect[]): void {
|
|
|
1936
1965
|
}
|
|
1937
1966
|
}
|
|
1938
1967
|
|
|
1939
|
-
|
|
1940
|
-
|
|
1968
|
+
/**
|
|
1969
|
+
* An inline element's bands made as tall as its fragments' border boxes,
|
|
1970
|
+
* as CSSOM View takes an inline box's client rects (6.1): its font's
|
|
1971
|
+
* content area about its own baseline, with the padding and the border
|
|
1972
|
+
* above and below it, which take no room on the line (CSS 2.1 10.6.1) and
|
|
1973
|
+
* which paint draws the background over (`paintInlineBoxes`). A band is a
|
|
1974
|
+
* line's height across until then: a link padded 10px below measured as
|
|
1975
|
+
* tall as its line and no taller.
|
|
1976
|
+
*/
|
|
1977
|
+
function fragmentHeights(box: Box, bands: Rect[], fonts: FontsLike): void {
|
|
1978
|
+
let block = box.parent;
|
|
1979
|
+
while (block && !block.lines) block = block.parent;
|
|
1980
|
+
if (!block?.lines?.length) return;
|
|
1981
|
+
const face = faceExtentOf(fonts, box.style);
|
|
1982
|
+
const byTop = new Map<number, LineBox>();
|
|
1983
|
+
for (const line of block.lines) byTop.set(line.y, line);
|
|
1984
|
+
for (let i = 0; i < bands.length; i += 1) {
|
|
1985
|
+
const band = bands[i];
|
|
1986
|
+
const line = byTop.get(band.y);
|
|
1987
|
+
if (!line) continue;
|
|
1988
|
+
// on its own baseline, which `vertical-align` may raise off the line's
|
|
1989
|
+
const raise = SHIFTED_LINES.has(line)
|
|
1990
|
+
? (LINE_BOX_RAISES.get(line)?.get(box) ?? BOX_RAISES.get(box) ?? 0)
|
|
1991
|
+
: 0;
|
|
1992
|
+
const baseline = line.y + line.baseline - raise;
|
|
1993
|
+
const top = baseline - face.ascent - box.padTop - box.borderTop;
|
|
1994
|
+
const bottom = baseline + face.descent + box.padBottom + box.borderBottom;
|
|
1995
|
+
bands[i] = { x: band.x, y: top, width: band.width, height: bottom - top };
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
/** The bands of a text range on one block's own lines. */
|
|
2000
|
+
function lineBands(
|
|
2001
|
+
lines: readonly LineBox[],
|
|
1941
2002
|
from: number,
|
|
1942
2003
|
to: number,
|
|
1943
2004
|
dx: number,
|
|
1944
2005
|
dy: number,
|
|
1945
2006
|
out: Rect[],
|
|
1946
2007
|
): void {
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
y: dy + line.y,
|
|
1981
|
-
width: band.width,
|
|
1982
|
-
height: line.height,
|
|
1983
|
-
});
|
|
1984
|
-
}
|
|
2008
|
+
// First line whose text can reach `from`, by binary search over the
|
|
2009
|
+
// sorted text starts; stop at the first line past `to`.
|
|
2010
|
+
let lo = 0;
|
|
2011
|
+
let hi = lines.length;
|
|
2012
|
+
while (lo < hi) {
|
|
2013
|
+
const mid = (lo + hi) >> 1;
|
|
2014
|
+
if (lines[mid].textEnd > from) hi = mid;
|
|
2015
|
+
else lo = mid + 1;
|
|
2016
|
+
}
|
|
2017
|
+
for (let i = lo; i < lines.length; i += 1) {
|
|
2018
|
+
const line = lines[i];
|
|
2019
|
+
if (line.textStart >= to) break;
|
|
2020
|
+
if (line.textEnd > from && line.textStart < to) {
|
|
2021
|
+
for (const text of line.texts) {
|
|
2022
|
+
const natural = text.layout.lines[text.layoutLine];
|
|
2023
|
+
if (!natural) continue;
|
|
2024
|
+
const a = Math.max(from, text.textStart);
|
|
2025
|
+
const b = Math.min(to, text.textEnd);
|
|
2026
|
+
if (b <= a) continue;
|
|
2027
|
+
const offsets = layoutOffsetsOf(text.layout);
|
|
2028
|
+
for (const band of bandsFor(
|
|
2029
|
+
text.layout,
|
|
2030
|
+
natural,
|
|
2031
|
+
offsets,
|
|
2032
|
+
layoutOffsetOf(text, a),
|
|
2033
|
+
layoutOffsetOf(text, b, true),
|
|
2034
|
+
)) {
|
|
2035
|
+
out.push({
|
|
2036
|
+
x: dx + band.x + text.drawX,
|
|
2037
|
+
y: dy + line.y,
|
|
2038
|
+
width: band.width,
|
|
2039
|
+
height: line.height,
|
|
2040
|
+
});
|
|
1985
2041
|
}
|
|
1986
2042
|
}
|
|
1987
2043
|
}
|
|
1988
2044
|
}
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
function collectBands(
|
|
2048
|
+
box: Box,
|
|
2049
|
+
from: number,
|
|
2050
|
+
to: number,
|
|
2051
|
+
dx: number,
|
|
2052
|
+
dy: number,
|
|
2053
|
+
out: Rect[],
|
|
2054
|
+
): void {
|
|
2055
|
+
if (box.subtreeTextEnd <= box.subtreeTextStart) return;
|
|
2056
|
+
if (box.subtreeTextEnd <= from || box.subtreeTextStart >= to) return;
|
|
2057
|
+
if (box.lines) lineBands(box.lines, from, to, dx, dy, out);
|
|
1989
2058
|
// Atomics are ordinary children, reached below.
|
|
1990
2059
|
for (const child of box.children) {
|
|
1991
2060
|
if (child.kind === 'text' || child.kind === 'break') continue;
|
|
@@ -2375,45 +2444,42 @@ function ownerOf(boxes: readonly Box[], index: number): Element | null {
|
|
|
2375
2444
|
|
|
2376
2445
|
export type { ControlRect, ReplacedKind, ResourceRequest, ResourceResult };
|
|
2377
2446
|
|
|
2378
|
-
/** The advance of a
|
|
2379
|
-
*
|
|
2380
|
-
function zeroWidthOf(
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
): number | null {
|
|
2447
|
+
/** The advance of a face's "0", laid out: null where the engine cannot
|
|
2448
|
+
* lay it out. */
|
|
2449
|
+
function zeroWidthOf(fonts: FontsLike, face: MetricFace): number | null {
|
|
2450
|
+
const { family, size, weight } = face;
|
|
2451
|
+
// a run is upright or slanted, as `inline.ts` sets one
|
|
2452
|
+
const style = face.style === 'normal' ? 'normal' : 'italic';
|
|
2385
2453
|
try {
|
|
2386
|
-
|
|
2387
|
-
|
|
2454
|
+
const run = { family, size, weight, style } as const;
|
|
2455
|
+
return fonts.layout([{ text: '0', ...run }], run, {}).width;
|
|
2388
2456
|
} catch {
|
|
2389
2457
|
return null;
|
|
2390
2458
|
}
|
|
2391
2459
|
}
|
|
2392
2460
|
|
|
2393
|
-
/** A
|
|
2394
|
-
*
|
|
2395
|
-
function normalLineOf(
|
|
2396
|
-
|
|
2397
|
-
family: string,
|
|
2398
|
-
size: number,
|
|
2399
|
-
): number | null {
|
|
2461
|
+
/** A face's own line height, as the engine reports it: null where it
|
|
2462
|
+
* cannot say. */
|
|
2463
|
+
function normalLineOf(fonts: FontsLike, face: MetricFace): number | null {
|
|
2464
|
+
const { family, size, weight, style } = face;
|
|
2400
2465
|
try {
|
|
2401
|
-
const line = fonts
|
|
2466
|
+
const line = fonts
|
|
2467
|
+
.match(family, { size, weight, style })
|
|
2468
|
+
.metrics(size).lineHeight;
|
|
2402
2469
|
return line > 0 ? line : null;
|
|
2403
2470
|
} catch {
|
|
2404
2471
|
return null;
|
|
2405
2472
|
}
|
|
2406
2473
|
}
|
|
2407
2474
|
|
|
2408
|
-
/** A
|
|
2409
|
-
*
|
|
2410
|
-
function xHeightOf(
|
|
2411
|
-
|
|
2412
|
-
family: string,
|
|
2413
|
-
size: number,
|
|
2414
|
-
): number | null {
|
|
2475
|
+
/** A face's x-height, as the engine reports it: null where the face
|
|
2476
|
+
* states none, or the engine does not say. */
|
|
2477
|
+
function xHeightOf(fonts: FontsLike, face: MetricFace): number | null {
|
|
2478
|
+
const { family, size, weight, style } = face;
|
|
2415
2479
|
try {
|
|
2416
|
-
const metrics = fonts
|
|
2480
|
+
const metrics = fonts
|
|
2481
|
+
.match(family, { size, weight, style })
|
|
2482
|
+
.metrics(size) as {
|
|
2417
2483
|
xHeight?: number | null;
|
|
2418
2484
|
};
|
|
2419
2485
|
const x = metrics.xHeight;
|