• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

worktile / slate-angular / e02f8021-e943-4537-a25c-fab0fba679a7

12 Jan 2026 03:29AM UTC coverage: 36.956% (-0.02%) from 36.974%
e02f8021-e943-4537-a25c-fab0fba679a7

push

circleci

pubuzhixing8
fix(virtual-scroll): getRealHeightByElement will return null if it never been measured.

401 of 1281 branches covered (31.3%)

Branch coverage included in aggregate %.

1 of 6 new or added lines in 2 files covered. (16.67%)

1102 of 2786 relevant lines covered (39.55%)

24.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.29
/packages/src/utils/virtual-scroll.ts
1
import { Element } from 'slate';
2
import { AngularEditor } from '../plugins/angular-editor';
3
import { SLATE_DEBUG_KEY, SLATE_DEBUG_KEY_SCROLL_TOP } from './environment';
4
import { ELEMENT_TO_COMPONENT } from './weak-maps';
5
import { BaseElementComponent } from '../view/base';
6
import { BaseElementFlavour } from '../view/flavour/element';
7
import { VirtualScrollDebugOverlay } from '../components/editable/debug';
8

9
export const isDebug = localStorage.getItem(SLATE_DEBUG_KEY) === 'true';
1✔
10
export const isDebugScrollTop = localStorage.getItem(SLATE_DEBUG_KEY_SCROLL_TOP) === 'true';
1✔
11

12
export const ELEMENT_KEY_TO_HEIGHTS = new WeakMap<AngularEditor, Map<string, number>>();
1✔
13

14
export const EDITOR_TO_BUSINESS_TOP = new WeakMap<AngularEditor, number>();
1✔
15

16
export const EDITOR_TO_ROOT_NODE_WIDTH = new WeakMap<AngularEditor, number>();
1✔
17

18
export const debugLog = (type: 'log' | 'warn', ...args: any[]) => {
1✔
19
    const doc = document;
×
20
    VirtualScrollDebugOverlay.log(doc, type, ...args);
×
21
};
22

23
export const measureHeightByElement = (editor: AngularEditor, element: Element) => {
1✔
24
    const key = AngularEditor.findKey(editor, element);
×
25
    const view = ELEMENT_TO_COMPONENT.get(element);
×
26
    if (!view) {
×
27
        return;
×
28
    }
29
    const ret = (view as BaseElementComponent | BaseElementFlavour).getRealHeight();
×
30
    const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
×
31
    heights.set(key.id, ret as number);
×
32
    return ret as number;
×
33
};
34

35
export const measureHeightByIndics = (editor: AngularEditor, indics: number[], force = false) => {
1!
36
    let hasChanged = false;
×
37
    indics.forEach((index, i) => {
×
38
        const element = editor.children[index] as Element;
×
NEW
39
        const preHeight = getRealHeightByElement(editor, element);
×
40
        if (preHeight && !force) {
×
41
            if (isDebug) {
×
42
                const height = measureHeightByElement(editor, element);
×
43
                if (height !== preHeight) {
×
44
                    debugLog(
×
45
                        'warn',
46
                        'measureHeightByElement: height not equal, index: ',
47
                        index,
48
                        'preHeight: ',
49
                        preHeight,
50
                        'height: ',
51
                        height
52
                    );
53
                }
54
            }
55
            return;
×
56
        }
57
        hasChanged = true;
×
58
        measureHeightByElement(editor, element);
×
59
    });
60
    return hasChanged;
×
61
};
62

63
export const getBusinessTop = (editor: AngularEditor) => {
1✔
64
    return EDITOR_TO_BUSINESS_TOP.get(editor) ?? 0;
×
65
};
66

67
export const getRealHeightByElement = (editor: AngularEditor, element: Element) => {
1✔
68
    const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
×
69
    const key = AngularEditor.findKey(editor, element);
×
70
    const height = heights?.get(key.id);
×
71
    if (typeof height === 'number') {
×
72
        return height;
×
73
    }
74
    if (heights?.has(key.id)) {
×
75
        console.error('getBlockHeight: invalid height value', key.id, height);
×
76
    }
NEW
77
    return null;
×
78
};
79

80
export const buildHeightsAndAccumulatedHeights = (editor: AngularEditor) => {
1✔
81
    const children = (editor.children || []) as Element[];
×
82
    const heights = new Array(children.length);
×
83
    const accumulatedHeights = new Array(children.length + 1);
×
84
    accumulatedHeights[0] = 0;
×
85
    for (let i = 0; i < children.length; i++) {
×
NEW
86
        const height = getRealHeightByElement(editor, children[i]) || editor.getRoughHeight(children[i]);
×
87
        heights[i] = height;
×
88
        accumulatedHeights[i + 1] = accumulatedHeights[i] + height;
×
89
    }
90
    return { heights, accumulatedHeights };
×
91
};
92

93
export const calculateVirtualTopHeight = (editor: AngularEditor, startIndex: number) => {
1✔
94
    const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
×
95
    return accumulatedHeights[startIndex] ?? 0;
×
96
};
97

98
export const scrollToElement = (editor: AngularEditor, element: Element, scrollTo: (scrollTop: number) => void) => {
1✔
99
    const children = editor.children;
×
100
    if (!children.length) {
×
101
        return;
×
102
    }
103
    const anchorIndex = children.findIndex(item => item === element);
×
104
    if (anchorIndex < 0) {
×
105
        return;
×
106
    }
107

108
    const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
×
109
    scrollTo((accumulatedHeights[anchorIndex] ?? 0) + getBusinessTop(editor));
×
110
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc