UNPKG

chrome-devtools-frontend

Version:
78 lines (68 loc) 2.77 kB
// Copyright 2025 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as TextUtils from '../../../models/text_utils/text_utils.js'; import {HighlightManager} from './HighlightManager.js'; export class HighlightElement extends HTMLElement { static readonly observedAttributes = ['ranges', 'current-range']; #ranges: TextUtils.TextRange.SourceRange[] = []; #currentRange: TextUtils.TextRange.SourceRange|undefined; attributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void { if (oldValue === newValue) { return; } switch (name) { case 'ranges': this.#ranges = parseRanges(newValue); break; case 'current-range': this.#currentRange = parseRanges(newValue)[0]; break; } HighlightManager.instance().set(this, this.#ranges, this.#currentRange); } } function parseRanges(value: string|null): TextUtils.TextRange.SourceRange[] { if (!value) { return []; } const ranges = value.split(' ') .filter(rangeString => { const parts = rangeString.split(','); // A valid range string must have exactly two parts. if (parts.length !== 2) { return false; } // Both parts must be convertible to valid numbers. const num1 = Number(parts[0]); const num2 = Number(parts[1]); return !isNaN(num1) && !isNaN(num2); }) .map(rangeString => { const parts = rangeString.split(',').map(part => Number(part)); return new TextUtils.TextRange.SourceRange(parts[0], parts[1]); }); return sortAndMergeRanges(ranges); } function sortAndMergeRanges(ranges: TextUtils.TextRange.SourceRange[]): TextUtils.TextRange.SourceRange[] { // Sort by start position. ranges.sort((a, b) => a.offset - b.offset); if (ranges.length === 0) { return []; } // Merge overlapping ranges. const merged = [ranges[0]]; for (let i = 1; i < ranges.length; i++) { const last = merged[merged.length - 1]; const current = ranges[i]; if (current.offset <= last.offset + last.length) { const newEnd = Math.max(last.offset + last.length, current.offset + current.length); const newLength = newEnd - last.offset; merged[merged.length - 1] = new TextUtils.TextRange.SourceRange(last.offset, newLength); } else { merged.push(current); } } return merged; } customElements.define('devtools-highlight', HighlightElement);