mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-06 20:11:38 +08:00
This also enables the ESLint rule for this folder R=jacktfranklin@chromium.org Bug: 1222126 Change-Id: I872ac654d4a37946aba75def17cc1f1aa8ad893c Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3341610 Commit-Queue: Tim Van der Lippe <tvanderlippe@chromium.org> Reviewed-by: Jack Franklin <jacktfranklin@chromium.org> Auto-Submit: Tim Van der Lippe <tvanderlippe@chromium.org>
130 lines
3.2 KiB
TypeScript
130 lines
3.2 KiB
TypeScript
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
export class FormattedContentBuilder {
|
|
#lastOriginalPosition = 0;
|
|
#formattedContent: string[] = [];
|
|
#formattedContentLength = 0;
|
|
#lastFormattedPosition = 0;
|
|
#nestingLevel = 0;
|
|
#newLines = 0;
|
|
#enforceSpaceBetweenWords = true;
|
|
#softSpace = false;
|
|
#hardSpaces = 0;
|
|
#cachedIndents = new Map<number, string>();
|
|
|
|
mapping = {original: [0], formatted: [0]};
|
|
|
|
constructor(private indentString: string) {
|
|
}
|
|
|
|
setEnforceSpaceBetweenWords(value: boolean): boolean {
|
|
const oldValue = this.#enforceSpaceBetweenWords;
|
|
this.#enforceSpaceBetweenWords = value;
|
|
return oldValue;
|
|
}
|
|
|
|
addToken(token: string, offset: number): void {
|
|
const last = this.#formattedContent[this.#formattedContent.length - 1];
|
|
if (this.#enforceSpaceBetweenWords && last && /\w/.test(last[last.length - 1]) && /\w/.test(token)) {
|
|
this.addSoftSpace();
|
|
}
|
|
|
|
this.#appendFormatting();
|
|
|
|
// Insert token.
|
|
this.#addMappingIfNeeded(offset);
|
|
this.#addText(token);
|
|
}
|
|
|
|
addSoftSpace(): void {
|
|
if (!this.#hardSpaces) {
|
|
this.#softSpace = true;
|
|
}
|
|
}
|
|
|
|
addHardSpace(): void {
|
|
this.#softSpace = false;
|
|
++this.#hardSpaces;
|
|
}
|
|
|
|
addNewLine(noSquash?: boolean): void {
|
|
// Avoid leading newlines.
|
|
if (!this.#formattedContentLength) {
|
|
return;
|
|
}
|
|
if (noSquash) {
|
|
++this.#newLines;
|
|
} else {
|
|
this.#newLines = this.#newLines || 1;
|
|
}
|
|
}
|
|
|
|
increaseNestingLevel(): void {
|
|
this.#nestingLevel += 1;
|
|
}
|
|
|
|
decreaseNestingLevel(): void {
|
|
if (this.#nestingLevel > 0) {
|
|
this.#nestingLevel -= 1;
|
|
}
|
|
}
|
|
|
|
content(): string {
|
|
return this.#formattedContent.join('') + (this.#newLines ? '\n' : '');
|
|
}
|
|
|
|
#appendFormatting(): void {
|
|
if (this.#newLines) {
|
|
for (let i = 0; i < this.#newLines; ++i) {
|
|
this.#addText('\n');
|
|
}
|
|
this.#addText(this.#indent());
|
|
} else if (this.#softSpace) {
|
|
this.#addText(' ');
|
|
}
|
|
if (this.#hardSpaces) {
|
|
for (let i = 0; i < this.#hardSpaces; ++i) {
|
|
this.#addText(' ');
|
|
}
|
|
}
|
|
this.#newLines = 0;
|
|
this.#softSpace = false;
|
|
this.#hardSpaces = 0;
|
|
}
|
|
|
|
#indent(): string {
|
|
const cachedValue = this.#cachedIndents.get(this.#nestingLevel);
|
|
if (cachedValue) {
|
|
return cachedValue;
|
|
}
|
|
|
|
let fullIndent = '';
|
|
for (let i = 0; i < this.#nestingLevel; ++i) {
|
|
fullIndent += this.indentString;
|
|
}
|
|
|
|
// Cache a maximum of 20 nesting level indents.
|
|
if (this.#nestingLevel <= 20) {
|
|
this.#cachedIndents.set(this.#nestingLevel, fullIndent);
|
|
}
|
|
return fullIndent;
|
|
}
|
|
|
|
#addText(text: string): void {
|
|
this.#formattedContent.push(text);
|
|
this.#formattedContentLength += text.length;
|
|
}
|
|
|
|
#addMappingIfNeeded(originalPosition: number): void {
|
|
if (originalPosition - this.#lastOriginalPosition === this.#formattedContentLength - this.#lastFormattedPosition) {
|
|
return;
|
|
}
|
|
this.mapping.original.push(originalPosition);
|
|
this.#lastOriginalPosition = originalPosition;
|
|
this.mapping.formatted.push(this.#formattedContentLength);
|
|
this.#lastFormattedPosition = this.#formattedContentLength;
|
|
}
|
|
}
|