mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-05 11:31:31 +08:00
Remove prototype wrangling for String formatters
They are now moved to the StringUtilities file. Sadly, `String.sprintf` is still used in the TestRunners that can't use ES modules. The Multimap required exporting, as the NetworkManager has a reference to it as well. Bug: 1050549 Change-Id: Ia7b38dc212282a9800ee8c3083dac7f4a5e046e1 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2067057 Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org> Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
This commit is contained in:
committed by
Commit Bot
parent
b1f2b6cce6
commit
93b57c3bbc
@@ -28,6 +28,7 @@
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
|
||||
@@ -414,7 +415,8 @@ export class Spectrum extends UI.Widget.VBox {
|
||||
*/
|
||||
_createPaletteColor(colorText, colorName, animationDelay) {
|
||||
const element = createElementWithClass('div', 'spectrum-palette-color');
|
||||
element.style.background = String.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
|
||||
element.style.background =
|
||||
Platform.StringUtilities.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
|
||||
if (animationDelay) {
|
||||
element.animate([{opacity: 0}, {opacity: 1}], {duration: 100, delay: animationDelay, fill: 'backwards'});
|
||||
}
|
||||
@@ -1018,8 +1020,8 @@ export class Spectrum extends UI.Widget.VBox {
|
||||
this._colorDragElement.style.backgroundColor =
|
||||
/** @type {string} */ (this._color().asString(Common.Color.Format.RGBA));
|
||||
const noAlpha = Common.Color.Color.fromHSVA(this._hsv.slice(0, 3).concat(1));
|
||||
this._alphaElementBackground.style.backgroundImage =
|
||||
String.sprintf('linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.asString(Common.Color.Format.RGB));
|
||||
this._alphaElementBackground.style.backgroundImage = Platform.StringUtilities.sprintf(
|
||||
'linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.asString(Common.Color.Format.RGB));
|
||||
}
|
||||
|
||||
_formatViewSwitch() {
|
||||
@@ -1061,7 +1063,7 @@ export class Spectrum extends UI.Widget.VBox {
|
||||
} else {
|
||||
const format = this._colorFormat === cf.RGB ? 'rgba' : 'hsla';
|
||||
const values = this._textValues.map(elementValue).join(', ');
|
||||
colorString = String.sprintf('%s(%s)', format, values);
|
||||
colorString = Platform.StringUtilities.sprintf('%s(%s)', format, values);
|
||||
}
|
||||
|
||||
const color = Common.Color.Color.parse(colorString);
|
||||
|
||||
@@ -17,4 +17,6 @@ ts_library("trie") {
|
||||
|
||||
ts_library("color") {
|
||||
sources = [ "Color.js" ]
|
||||
|
||||
deps = [ "../platform" ]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import * as Platform from '../platform/platform.js';
|
||||
|
||||
/** @type {?Map<string, string>} */
|
||||
let _rgbaToNickname;
|
||||
|
||||
@@ -579,10 +581,10 @@ export class Color {
|
||||
if (this.hasAlpha()) {
|
||||
return null;
|
||||
}
|
||||
return String.sprintf(
|
||||
return Platform.StringUtilities.sprintf(
|
||||
'rgb(%d, %d, %d)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]));
|
||||
case Format.RGBA:
|
||||
return String.sprintf(
|
||||
return Platform.StringUtilities.sprintf(
|
||||
'rgba(%d, %d, %d, %f)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]),
|
||||
this._rgba[3]);
|
||||
case Format.HSL:
|
||||
@@ -590,15 +592,15 @@ export class Color {
|
||||
return null;
|
||||
}
|
||||
const hsl = this.hsla();
|
||||
return String.sprintf(
|
||||
return Platform.StringUtilities.sprintf(
|
||||
'hsl(%d, %d%, %d%)', Math.round(hsl[0] * 360), Math.round(hsl[1] * 100), Math.round(hsl[2] * 100));
|
||||
case Format.HSLA:
|
||||
const hsla = this.hsla();
|
||||
return String.sprintf(
|
||||
return Platform.StringUtilities.sprintf(
|
||||
'hsla(%d, %d%, %d%, %f)', Math.round(hsla[0] * 360), Math.round(hsla[1] * 100), Math.round(hsla[2] * 100),
|
||||
hsla[3]);
|
||||
case Format.HEXA:
|
||||
return String
|
||||
return Platform.StringUtilities
|
||||
.sprintf(
|
||||
'#%s%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]),
|
||||
toHexValue(this._rgba[3]))
|
||||
@@ -607,7 +609,7 @@ export class Color {
|
||||
if (this.hasAlpha()) {
|
||||
return null;
|
||||
}
|
||||
return String
|
||||
return Platform.StringUtilities
|
||||
.sprintf('#%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]))
|
||||
.toLowerCase();
|
||||
case Format.ShortHEXA:
|
||||
@@ -615,7 +617,7 @@ export class Color {
|
||||
if (hexFormat !== Format.ShortHEXA && hexFormat !== Format.ShortHEX) {
|
||||
return null;
|
||||
}
|
||||
return String
|
||||
return Platform.StringUtilities
|
||||
.sprintf(
|
||||
'#%s%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
|
||||
toShortHexValue(this._rgba[2]), toShortHexValue(this._rgba[3]))
|
||||
@@ -627,7 +629,7 @@ export class Color {
|
||||
if (this.detectHEXFormat() !== Format.ShortHEX) {
|
||||
return null;
|
||||
}
|
||||
return String
|
||||
return Platform.StringUtilities
|
||||
.sprintf(
|
||||
'#%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
|
||||
toShortHexValue(this._rgba[2]))
|
||||
|
||||
@@ -29,13 +29,15 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import * as Platform from '../platform/platform.js';
|
||||
|
||||
/**
|
||||
* @param {string} string
|
||||
* @param {...*} vararg
|
||||
* @return {string}
|
||||
*/
|
||||
export function UIString(string, vararg) {
|
||||
return String.vsprintf(localize(string), Array.prototype.slice.call(arguments, 1));
|
||||
return Platform.StringUtilities.vsprintf(localize(string), Array.prototype.slice.call(arguments, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +82,8 @@ export class UIStringFormat {
|
||||
/** @type {string} */
|
||||
this._localizedFormat = localize(format);
|
||||
/** @type {!Array.<!Object>} */
|
||||
this._tokenizedFormat = String.tokenizeFormatString(this._localizedFormat, String.standardFormatters);
|
||||
this._tokenizedFormat = Platform.StringUtilities.tokenizeFormatString(
|
||||
this._localizedFormat, Platform.StringUtilities.standardFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +100,9 @@ export class UIStringFormat {
|
||||
* @return {string}
|
||||
*/
|
||||
format(vararg) {
|
||||
return String
|
||||
return Platform.StringUtilities
|
||||
.format(
|
||||
this._localizedFormat, arguments, String.standardFormatters, '', UIStringFormat._append,
|
||||
this._localizedFormat, arguments, Platform.StringUtilities.standardFormatters, '', UIStringFormat._append,
|
||||
this._tokenizedFormat)
|
||||
.formattedResult;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
|
||||
export class ImagePreview {
|
||||
@@ -72,7 +73,7 @@ export class ImagePreview {
|
||||
}
|
||||
if (imageURL !== originalImageURL) {
|
||||
container.createChild('tr').createChild('td').createChild('span', 'description').textContent =
|
||||
String.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
|
||||
Platform.StringUtilities.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
|
||||
}
|
||||
fulfill(container);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
|
||||
import * as UI from '../ui/ui.js';
|
||||
@@ -172,7 +173,7 @@ export class FilterTreeElement extends UI.TreeOutline.TreeElement {
|
||||
} else if (this._messageCount === 1) {
|
||||
this.title = _groupSingularTitleMap.get(this._filter.name);
|
||||
} else {
|
||||
this.title = String.sprintf(_groupPluralTitleMap.get(this._filter.name), this._messageCount);
|
||||
this.title = Platform.StringUtilities.sprintf(_groupPluralTitleMap.get(this._filter.name), this._messageCount);
|
||||
}
|
||||
|
||||
this.setExpandable(!!this.childCount());
|
||||
|
||||
@@ -31,6 +31,7 @@ import * as Bindings from '../bindings/bindings.js';
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Components from '../components/components.js';
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
@@ -760,7 +761,7 @@ export class ConsoleView extends UI.Widget.VBox {
|
||||
async _saveConsole() {
|
||||
const url = self.SDK.targetManager.mainTarget().inspectedURL();
|
||||
const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
|
||||
const filename = String.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now());
|
||||
const filename = Platform.StringUtilities.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now());
|
||||
const stream = new Bindings.FileUtils.FileOutputStream();
|
||||
|
||||
const progressIndicator = new UI.ProgressIndicator.ProgressIndicator();
|
||||
|
||||
@@ -32,6 +32,7 @@ import * as Common from '../common/common.js';
|
||||
import * as Components from '../components/components.js';
|
||||
import * as DataGrid from '../data_grid/data_grid.js';
|
||||
import * as ObjectUI from '../object_ui/object_ui.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
@@ -963,8 +964,8 @@ export class ConsoleViewMessage {
|
||||
}
|
||||
}
|
||||
|
||||
// String.format does treat formattedResult like a Builder, result is an object.
|
||||
return String.format(format, parameters, formatters, formattedResult, append.bind(this));
|
||||
// Platform.StringUtilities.format does treat formattedResult like a Builder, result is an object.
|
||||
return Platform.StringUtilities.format(format, parameters, formatters, formattedResult, append.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
import * as Workspace from '../workspace/workspace.js'; // eslint-disable-line no-unused-vars
|
||||
@@ -122,7 +123,7 @@ export class MediaQueryInspector extends UI.Widget.Widget {
|
||||
if (!uiLocation) {
|
||||
continue;
|
||||
}
|
||||
const descriptor = String.sprintf(
|
||||
const descriptor = Platform.StringUtilities.sprintf(
|
||||
'%s:%d:%d', uiLocation.uiSourceCode.url(), uiLocation.lineNumber + 1, uiLocation.columnNumber + 1);
|
||||
uiLocations.set(descriptor, uiLocation);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import * as Bindings from '../bindings/bindings.js';
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Components from '../components/components.js';
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as ProtocolModule from '../protocol/protocol.js'; // eslint-disable-line no-unused-vars
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
|
||||
@@ -1027,7 +1028,7 @@ export class ExtensionStatus {
|
||||
const status = {code: code, description: description, details: details};
|
||||
if (code !== 'OK') {
|
||||
status.isError = true;
|
||||
console.error('Extension server error: ' + String.vsprintf(description, details));
|
||||
console.error('Extension server error: ' + Platform.StringUtilities.vsprintf(description, details));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Components from '../components/components.js'; // eslint-disable-line no-unused-vars
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
@@ -1178,7 +1179,7 @@ export class ArrayGroupingTreeElement extends UI.TreeOutline.TreeElement {
|
||||
* @param {!Components.Linkifier.Linkifier=} linkifier
|
||||
*/
|
||||
constructor(object, fromIndex, toIndex, propertyCount, linkifier) {
|
||||
super(String.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
|
||||
super(Platform.StringUtilities.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
|
||||
this.toggleOnClick = true;
|
||||
this._fromIndex = fromIndex;
|
||||
this._toIndex = toIndex;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import("../../third_party/typescript/typescript.gni")
|
||||
|
||||
ts_library("platform") {
|
||||
sources = [
|
||||
"platform.js",
|
||||
"string-utilities.js",
|
||||
"utilities.js",
|
||||
]
|
||||
}
|
||||
@@ -32,4 +32,5 @@ import './utilities.js';
|
||||
|
||||
import * as StringUtilities from './string-utilities.js';
|
||||
|
||||
export {Multimap} from './utilities.js';
|
||||
export {StringUtilities};
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
/**
|
||||
* @param {string} inputString
|
||||
* @param {string} charsToEscape
|
||||
@@ -30,3 +32,203 @@ export const escapeCharacters = (inputString, charsToEscape) => {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} formatString
|
||||
* @param {!Object.<string, function(string, ...):*>} formatters
|
||||
* @return {!Array.<!Object>}
|
||||
*/
|
||||
export const tokenizeFormatString = function(formatString, formatters) {
|
||||
const tokens = [];
|
||||
|
||||
function addStringToken(str) {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
if (tokens.length && tokens[tokens.length - 1].type === 'string') {
|
||||
tokens[tokens.length - 1].value += str;
|
||||
} else {
|
||||
tokens.push({type: 'string', value: str});
|
||||
}
|
||||
}
|
||||
|
||||
function addSpecifierToken(specifier, precision, substitutionIndex) {
|
||||
tokens.push({type: 'specifier', specifier: specifier, precision: precision, substitutionIndex: substitutionIndex});
|
||||
}
|
||||
|
||||
function addAnsiColor(code) {
|
||||
const types = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
|
||||
const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
|
||||
const colorCodesLight =
|
||||
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
|
||||
const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
|
||||
const type = types[Math.floor(code / 10)];
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
const color = colors[type][code % 10];
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
tokens.push({
|
||||
type: 'specifier',
|
||||
specifier: 'c',
|
||||
value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color}
|
||||
});
|
||||
}
|
||||
|
||||
let textStart = 0;
|
||||
let substitutionIndex = 0;
|
||||
const re =
|
||||
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
|
||||
for (let match = re.exec(formatString); !!match; match = re.exec(formatString)) {
|
||||
const matchStart = match.index;
|
||||
if (matchStart > textStart) {
|
||||
addStringToken(formatString.substring(textStart, matchStart));
|
||||
}
|
||||
|
||||
if (match[0] === '%%') {
|
||||
addStringToken('%');
|
||||
} else if (match[0].startsWith('%')) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const [_, substitionString, precisionString, specifierString] = match;
|
||||
if (substitionString && Number(substitionString) > 0) {
|
||||
substitutionIndex = Number(substitionString) - 1;
|
||||
}
|
||||
const precision = precisionString ? Number(precisionString) : -1;
|
||||
addSpecifierToken(specifierString, precision, substitutionIndex);
|
||||
++substitutionIndex;
|
||||
} else {
|
||||
const code = Number(match[4]);
|
||||
addAnsiColor(code);
|
||||
}
|
||||
textStart = matchStart + match[0].length;
|
||||
}
|
||||
addStringToken(formatString.substring(textStart));
|
||||
return tokens;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} formatString
|
||||
* @param {?ArrayLike} substitutions
|
||||
* @param {!Object.<string, function(string, ...):Q>} formatters
|
||||
* @param {!T} initialValue
|
||||
* @param {function(T, Q): T|undefined} append
|
||||
* @param {!Array.<!Object>=} tokenizedFormat
|
||||
* @return {!{formattedResult: T, unusedSubstitutions: ?ArrayLike}};
|
||||
* @template T, Q
|
||||
*/
|
||||
export const format = function(formatString, substitutions, formatters, initialValue, append, tokenizedFormat) {
|
||||
if (!formatString || ((!substitutions || !substitutions.length) && formatString.search(/\u001b\[(\d+)m/) === -1)) {
|
||||
return {formattedResult: append(initialValue, formatString), unusedSubstitutions: substitutions};
|
||||
}
|
||||
|
||||
function prettyFunctionName() {
|
||||
return 'String.format("' + formatString + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
|
||||
}
|
||||
|
||||
function warn(msg) {
|
||||
console.warn(prettyFunctionName() + ': ' + msg);
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
console.error(prettyFunctionName() + ': ' + msg);
|
||||
}
|
||||
|
||||
let result = initialValue;
|
||||
const tokens = tokenizedFormat || tokenizeFormatString(formatString, formatters);
|
||||
const usedSubstitutionIndexes = {};
|
||||
|
||||
for (let i = 0; i < tokens.length; ++i) {
|
||||
const token = tokens[i];
|
||||
|
||||
if (token.type === 'string') {
|
||||
result = append(result, token.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.type !== 'specifier') {
|
||||
error('Unknown token type "' + token.type + '" found.');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!token.value && token.substitutionIndex >= substitutions.length) {
|
||||
// If there are not enough substitutions for the current substitutionIndex
|
||||
// just output the format specifier literally and move on.
|
||||
error(
|
||||
'not enough substitution arguments. Had ' + substitutions.length + ' but needed ' +
|
||||
(token.substitutionIndex + 1) + ', so substitution was skipped.');
|
||||
result = append(result, '%' + (token.precision > -1 ? token.precision : '') + token.specifier);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!token.value) {
|
||||
usedSubstitutionIndexes[token.substitutionIndex] = true;
|
||||
}
|
||||
|
||||
if (!(token.specifier in formatters)) {
|
||||
// Encountered an unsupported format character, treat as a string.
|
||||
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
|
||||
result = append(result, token.value ? '' : substitutions[token.substitutionIndex]);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = append(result, formatters[token.specifier](token.value || substitutions[token.substitutionIndex], token));
|
||||
}
|
||||
|
||||
const unusedSubstitutions = [];
|
||||
for (let i = 0; i < substitutions.length; ++i) {
|
||||
if (i in usedSubstitutionIndexes) {
|
||||
continue;
|
||||
}
|
||||
unusedSubstitutions.push(substitutions[i]);
|
||||
}
|
||||
|
||||
return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
|
||||
};
|
||||
|
||||
export const standardFormatters = {
|
||||
/**
|
||||
* @return {number}
|
||||
*/
|
||||
d: function(substitution) {
|
||||
return !isNaN(substitution) ? substitution : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
*/
|
||||
f: function(substitution, token) {
|
||||
if (substitution && token.precision > -1) {
|
||||
substitution = substitution.toFixed(token.precision);
|
||||
}
|
||||
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
s: function(substitution) {
|
||||
return substitution;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} formatString
|
||||
* @param {!Array.<*>} substitutions
|
||||
* @return {string}
|
||||
*/
|
||||
export const vsprintf = function(formatString, substitutions) {
|
||||
return format(formatString, substitutions, standardFormatters, '', function(a, b) {
|
||||
return a + b;
|
||||
}).formattedResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} format
|
||||
* @param {...*} var_arg
|
||||
* @return {string}
|
||||
*/
|
||||
export const sprintf = function(format, var_arg) {
|
||||
return vsprintf(format, Array.prototype.slice.call(arguments, 1));
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
// @ts-nocheck
|
||||
|
||||
/* the long term goal here is to remove all functions in this file and
|
||||
* replace them with ES Module functions rather than prototype
|
||||
@@ -34,6 +35,10 @@
|
||||
*/
|
||||
import * as StringUtilities from './string-utilities.js';
|
||||
|
||||
|
||||
// Still used in the test runners that can't use ES modules :(
|
||||
String.sprintf = StringUtilities.sprintf;
|
||||
|
||||
/**
|
||||
* @param {number} m
|
||||
* @param {number} n
|
||||
@@ -702,210 +707,6 @@ Object.defineProperty(Array.prototype, 'peekLast', {
|
||||
});
|
||||
})();
|
||||
|
||||
/**
|
||||
* @param {string} format
|
||||
* @param {...*} var_arg
|
||||
* @return {string}
|
||||
*/
|
||||
String.sprintf = function(format, var_arg) {
|
||||
return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} format
|
||||
* @param {!Object.<string, function(string, ...):*>} formatters
|
||||
* @return {!Array.<!Object>}
|
||||
*/
|
||||
String.tokenizeFormatString = function(format, formatters) {
|
||||
const tokens = [];
|
||||
|
||||
function addStringToken(str) {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
if (tokens.length && tokens[tokens.length - 1].type === 'string') {
|
||||
tokens[tokens.length - 1].value += str;
|
||||
} else {
|
||||
tokens.push({type: 'string', value: str});
|
||||
}
|
||||
}
|
||||
|
||||
function addSpecifierToken(specifier, precision, substitutionIndex) {
|
||||
tokens.push({type: 'specifier', specifier: specifier, precision: precision, substitutionIndex: substitutionIndex});
|
||||
}
|
||||
|
||||
function addAnsiColor(code) {
|
||||
const types = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
|
||||
const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
|
||||
const colorCodesLight =
|
||||
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
|
||||
const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
|
||||
const type = types[Math.floor(code / 10)];
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
const color = colors[type][code % 10];
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
tokens.push({
|
||||
type: 'specifier',
|
||||
specifier: 'c',
|
||||
value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color}
|
||||
});
|
||||
}
|
||||
|
||||
let textStart = 0;
|
||||
let substitutionIndex = 0;
|
||||
const re =
|
||||
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
|
||||
for (let match = re.exec(format); !!match; match = re.exec(format)) {
|
||||
const matchStart = match.index;
|
||||
if (matchStart > textStart) {
|
||||
addStringToken(format.substring(textStart, matchStart));
|
||||
}
|
||||
|
||||
if (match[0] === '%%') {
|
||||
addStringToken('%');
|
||||
} else if (match[0].startsWith('%')) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const [_, substitionString, precisionString, specifierString] = match;
|
||||
if (substitionString && Number(substitionString) > 0) {
|
||||
substitutionIndex = Number(substitionString) - 1;
|
||||
}
|
||||
const precision = precisionString ? Number(precisionString) : -1;
|
||||
addSpecifierToken(specifierString, precision, substitutionIndex);
|
||||
++substitutionIndex;
|
||||
} else {
|
||||
const code = Number(match[4]);
|
||||
addAnsiColor(code);
|
||||
}
|
||||
textStart = matchStart + match[0].length;
|
||||
}
|
||||
addStringToken(format.substring(textStart));
|
||||
return tokens;
|
||||
};
|
||||
|
||||
String.standardFormatters = {
|
||||
/**
|
||||
* @return {number}
|
||||
*/
|
||||
d: function(substitution) {
|
||||
return !isNaN(substitution) ? substitution : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
*/
|
||||
f: function(substitution, token) {
|
||||
if (substitution && token.precision > -1) {
|
||||
substitution = substitution.toFixed(token.precision);
|
||||
}
|
||||
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
s: function(substitution) {
|
||||
return substitution;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} format
|
||||
* @param {!Array.<*>} substitutions
|
||||
* @return {string}
|
||||
*/
|
||||
String.vsprintf = function(format, substitutions) {
|
||||
return String
|
||||
.format(
|
||||
format, substitutions, String.standardFormatters, '',
|
||||
function(a, b) {
|
||||
return a + b;
|
||||
})
|
||||
.formattedResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} format
|
||||
* @param {?ArrayLike} substitutions
|
||||
* @param {!Object.<string, function(string, ...):Q>} formatters
|
||||
* @param {!T} initialValue
|
||||
* @param {function(T, Q): T|undefined} append
|
||||
* @param {!Array.<!Object>=} tokenizedFormat
|
||||
* @return {!{formattedResult: T, unusedSubstitutions: ?ArrayLike}};
|
||||
* @template T, Q
|
||||
*/
|
||||
String.format = function(format, substitutions, formatters, initialValue, append, tokenizedFormat) {
|
||||
if (!format || ((!substitutions || !substitutions.length) && format.search(/\u001b\[(\d+)m/) === -1)) {
|
||||
return {formattedResult: append(initialValue, format), unusedSubstitutions: substitutions};
|
||||
}
|
||||
|
||||
function prettyFunctionName() {
|
||||
return 'String.format("' + format + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
|
||||
}
|
||||
|
||||
function warn(msg) {
|
||||
console.warn(prettyFunctionName() + ': ' + msg);
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
console.error(prettyFunctionName() + ': ' + msg);
|
||||
}
|
||||
|
||||
let result = initialValue;
|
||||
const tokens = tokenizedFormat || String.tokenizeFormatString(format, formatters);
|
||||
const usedSubstitutionIndexes = {};
|
||||
|
||||
for (let i = 0; i < tokens.length; ++i) {
|
||||
const token = tokens[i];
|
||||
|
||||
if (token.type === 'string') {
|
||||
result = append(result, token.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.type !== 'specifier') {
|
||||
error('Unknown token type "' + token.type + '" found.');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!token.value && token.substitutionIndex >= substitutions.length) {
|
||||
// If there are not enough substitutions for the current substitutionIndex
|
||||
// just output the format specifier literally and move on.
|
||||
error(
|
||||
'not enough substitution arguments. Had ' + substitutions.length + ' but needed ' +
|
||||
(token.substitutionIndex + 1) + ', so substitution was skipped.');
|
||||
result = append(result, '%' + (token.precision > -1 ? token.precision : '') + token.specifier);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!token.value) {
|
||||
usedSubstitutionIndexes[token.substitutionIndex] = true;
|
||||
}
|
||||
|
||||
if (!(token.specifier in formatters)) {
|
||||
// Encountered an unsupported format character, treat as a string.
|
||||
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
|
||||
result = append(result, token.value ? '' : substitutions[token.substitutionIndex]);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = append(result, formatters[token.specifier](token.value || substitutions[token.substitutionIndex], token));
|
||||
}
|
||||
|
||||
const unusedSubstitutions = [];
|
||||
for (let i = 0; i < substitutions.length; ++i) {
|
||||
if (i in usedSubstitutionIndexes) {
|
||||
continue;
|
||||
}
|
||||
unusedSubstitutions.push(substitutions[i]);
|
||||
}
|
||||
|
||||
return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} query
|
||||
* @param {boolean} caseSensitive
|
||||
@@ -1015,7 +816,7 @@ Map.prototype.inverse = function() {
|
||||
/**
|
||||
* @template K, V
|
||||
*/
|
||||
const Multimap = class {
|
||||
export class Multimap {
|
||||
constructor() {
|
||||
/** @type {!Map.<K, !Set.<!V>>} */
|
||||
this._map = new Map();
|
||||
@@ -1115,7 +916,7 @@ const Multimap = class {
|
||||
clear() {
|
||||
this._map.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
@@ -1176,6 +977,7 @@ Promise.prototype.catchException = function(defaultValue) {
|
||||
/**
|
||||
* TODO: move into its own module
|
||||
* @param {function()} callback
|
||||
* @suppressGlobalPropertiesCheck
|
||||
*/
|
||||
self.runOnWindowLoad = function(callback) {
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as HostModule from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
|
||||
import {cssMetadata, GridAreaRowRegex} from './CSSMetadata.js';
|
||||
import {Edit} from './CSSModel.js'; // eslint-disable-line no-unused-vars
|
||||
@@ -183,7 +184,7 @@ export class CSSProperty {
|
||||
self.Common.settings.moduleSetting('textEditorIndent').get();
|
||||
const endIndentation = this.ownerStyle.cssText ? indentation.substring(0, this.ownerStyle.range.endColumn) : '';
|
||||
const text = new TextUtils.Text(this.ownerStyle.cssText || '');
|
||||
const newStyleText = text.replaceRange(range, String.sprintf(';%s;', propertyText));
|
||||
const newStyleText = text.replaceRange(range, Platform.StringUtilities.sprintf(';%s;', propertyText));
|
||||
|
||||
const tokenizerFactory = await self.runtime.extension(TextUtils.TokenizerFactory).instance();
|
||||
const styleText = CSSProperty._formatStyle(newStyleText, indentation, endIndentation, tokenizerFactory);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as ProtocolModule from '../protocol/protocol.js';
|
||||
|
||||
import {Cookie} from './Cookie.js';
|
||||
@@ -1047,7 +1048,7 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
|
||||
if (chromeMatch && chromeMatch.length > 1) {
|
||||
// "1.2.3.4" becomes "1.0.100.0"
|
||||
const additionalAppVersion = chromeMatch[1].split('.', 1)[0] + '.0.100.0';
|
||||
return String.sprintf(uaString, chromeMatch[1], additionalAppVersion);
|
||||
return Platform.StringUtilities.sprintf(uaString, chromeMatch[1], additionalAppVersion);
|
||||
}
|
||||
return uaString;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
|
||||
/**
|
||||
@@ -64,7 +65,7 @@ export class FontView extends UI.View.SimpleView {
|
||||
const {content} = deferredContent;
|
||||
const url = content ? Common.ContentProvider.contentAsDataURL(content, this._mimeType, true) : this._url;
|
||||
this.fontStyleElement.textContent =
|
||||
String.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
|
||||
Platform.StringUtilities.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
|
||||
}
|
||||
|
||||
_createContentIfNeeded() {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
import * as ColorPicker from '../color_picker/color_picker.js';
|
||||
import * as Common from '../common/common.js';
|
||||
import * as InlineEditor from '../inline_editor/inline_editor.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as SourceFrame from '../source_frame/source_frame.js';
|
||||
import * as TextUtils from '../text_utils/text_utils.js';
|
||||
@@ -123,7 +124,7 @@ export class CSSPlugin extends Plugin {
|
||||
return null;
|
||||
}
|
||||
const tail = unit.substring((unitValue).toString().length);
|
||||
return String.sprintf('%d%s', unitValue + change, tail);
|
||||
return Platform.StringUtilities.sprintf('%d%s', unitValue + change, tail);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,6 +33,7 @@ import * as Bindings from '../bindings/bindings.js';
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Components from '../components/components.js';
|
||||
import * as PerfUI from '../perf_ui/perf_ui.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
import * as SDK from '../sdk/sdk.js';
|
||||
import * as TimelineModel from '../timeline_model/timeline_model.js';
|
||||
import * as UI from '../ui/ui.js';
|
||||
@@ -2496,7 +2497,8 @@ export class TimelineDetailsContentHelper {
|
||||
return;
|
||||
}
|
||||
locationContent.appendChild(link);
|
||||
locationContent.createTextChild(String.sprintf(' [%s\u2026%s]', startLine + 1, endLine + 1 || ''));
|
||||
locationContent.createTextChild(
|
||||
Platform.StringUtilities.sprintf(' [%s\u2026%s]', startLine + 1, endLine + 1 || ''));
|
||||
this.appendElementRow(title, locationContent);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
import * as Common from '../common/common.js';
|
||||
import * as Host from '../host/host.js';
|
||||
import * as Platform from '../platform/platform.js';
|
||||
|
||||
import * as ARIAUtils from './ARIAUtils.js';
|
||||
import {Dialog} from './Dialog.js';
|
||||
@@ -711,7 +712,8 @@ export function formatLocalized(format, substitutions) {
|
||||
a.appendChild(typeof b === 'string' ? createTextNode(b) : b);
|
||||
return a;
|
||||
}
|
||||
return String.format(Common.UIString.UIString(format), substitutions, formatters, createElement('span'), append)
|
||||
return Platform.StringUtilities
|
||||
.format(Common.UIString.UIString(format), substitutions, formatters, createElement('span'), append)
|
||||
.formattedResult;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user