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

naver / billboard.js / 27122665529

08 Jun 2026 07:32AM UTC coverage: 92.54% (-1.1%) from 93.621%
27122665529

push

github

web-flow
feat(canvas): add canvas rendering mode

Add canvas entry, renderer engine, axis renderer, theme probing, and hit detection.
Support canvas flow, subchart, zoom, selection, grid/regions, export, tooltip, and focus.
Add tests, benchmarks, types, and docs for canvas mode limitations.

10455 of 11840 branches covered (88.3%)

Branch coverage included in aggregate %.

5094 of 5363 new or added lines in 68 files covered. (94.98%)

19 existing lines in 3 files now uncovered.

13349 of 13883 relevant lines covered (96.15%)

26556.19 hits per line

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

84.91
/src/ChartInternal/shape/core/dataRegion.ts
1
/**
2
 * Copyright (c) 2017 ~ present NAVER Corp.
3
 * billboard.js project is licensed under the MIT license
4
 */
5
import {isUndefined, isValue, parseDate} from "../../../module/util";
6

7
type DataRegionStyle = {dasharray?: string};
8

9
type DataRegion = {
10
        start?: number | string | Date,
11
        end?: number | string | Date,
12
        style?: DataRegionStyle
13
};
14

15
type NormalizedDataRegion = {
16
        start: number | string | Date,
17
        end: number | string | Date,
18
        style: DataRegionStyle
19
};
20

21
export type LineRegionSegment = {
22
        start?: number[],
23
        end?: number[],
24
        dash?: number[],
25
        isBreak?: boolean
26
};
27

28
const DEFAULT_DASHARRAY = "2 2";
249✔
29

30
/**
31
 * Normalize data.regions start/end values against chart axis type.
32
 * @param {object} $$ ChartInternal instance
33
 * @param {Array} values Target values
34
 * @param {Array} regions Regions to normalize
35
 * @returns {Array} Normalized regions
36
 * @private
37
 */
38
export function normalizeDataRegions($$, values, regions?: DataRegion[]): NormalizedDataRegion[] {
39
        const isTimeSeries = $$.axis.isTimeSeries();
102✔
40
        const getValue = (value, fallback) => (
102✔
41
                isUndefined(value) ? fallback : (isTimeSeries ? parseDate.call($$, value) : value)
300✔
42
        );
43

44
        return (regions || []).map(region => ({
150!
45
                start: getValue(region.start, values[0]?.x),
46
                end: getValue(region.end, values[values.length - 1]?.x),
47
                style: region.style || {dasharray: DEFAULT_DASHARRAY}
177✔
48
        }));
49
}
50

51
/**
52
 * Get region style for an x value.
53
 * @param {number|string|Date} x X value
54
 * @param {Array} regions Normalized regions
55
 * @returns {object|boolean} Region style or false
56
 * @private
57
 */
58
export function getDataRegionStyle(
59
        x: number | string | Date,
60
        regions: NormalizedDataRegion[]
61
): DataRegionStyle | false {
62
        for (let i = 0, region; (region = regions[i]); i++) {
552✔
63
                if (region.start < x && x <= region.end) {
783✔
64
                        return region.style;
198✔
65
                }
66
        }
67

68
        return false;
354✔
69
}
70

71
/**
72
 * Parse a data region dasharray value for canvas.
73
 * @param {object} style Region style
74
 * @returns {Array} Canvas line dash
75
 * @private
76
 */
77
export function getDataRegionDash(style?: DataRegionStyle): number[] {
78
        const dash = String(style?.dasharray || DEFAULT_DASHARRAY)
18!
79
                .split(/[\s,]+/)
80
                .map(Number)
81
                .filter(Number.isFinite);
82

83
        return dash.length ? dash : [2, 2];
18!
84
}
85

86
/**
87
 * Get line segments annotated with region dash settings.
88
 * @param {object} $$ ChartInternal instance
89
 * @param {Array} values Target values
90
 * @param {function} x X scale
91
 * @param {function} y Y scale
92
 * @param {Array} regions Regions to apply
93
 * @returns {Array} Line region segments
94
 * @private
95
 */
96
export function getLineRegionSegments($$, values, x, y, regions): LineRegionSegment[] {
97
        const isRotated = $$.config.axis_rotated;
12✔
98
        const normalizedRegions = normalizeDataRegions($$, values, regions);
12✔
99
        const segments: LineRegionSegment[] = [];
12✔
100

101
        for (let i = 1; i < values.length; i++) {
12✔
102
                const prev = values[i - 1];
42✔
103
                const current = values[i];
42✔
104

105
                if (!isValue(prev.value) || !isValue(current.value)) {
42!
NEW
106
                        segments.push({isBreak: true});
×
NEW
107
                        continue;
×
108
                }
109

110
                const style = getDataRegionStyle(current.x, normalizedRegions);
42✔
111
                const x0 = x(prev.x);
42✔
112
                const y0 = y(prev.value);
42✔
113
                const x1 = x(current.x);
42✔
114
                const y1 = y(current.value);
42✔
115

116
                segments.push({
42✔
117
                        start: isRotated ? [y0, x0] : [x0, y0],
42!
118
                        end: isRotated ? [y1, x1] : [x1, y1],
42!
119
                        dash: style ? getDataRegionDash(style) : []
42✔
120
                });
121
        }
122

123
        return segments;
12✔
124
}
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