mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-08 20:58:24 +08:00
All of these were Closure-specific. R=szuend@chromium.org No-Presubmit: True Bug: 1011811 Change-Id: Ia580e21cd3b06f532bb5a63a770ccfa3d7c796ee Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2569761 Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org>
300 lines
8.3 KiB
JavaScript
300 lines
8.3 KiB
JavaScript
// Copyright 2020 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.
|
|
|
|
import * as CssOverviewModule from '../css_overview/css_overview.js';
|
|
import * as SDK from '../sdk/sdk.js';
|
|
import * as UI from '../ui/ui.js';
|
|
|
|
const computedArrayFontSizeIndex = 6;
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getPxMultiplier() {
|
|
return 1;
|
|
}
|
|
/**
|
|
* @param {boolean=} isFontSizeProperty
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getEmMultiplier(isFontSizeProperty) {
|
|
const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
|
|
let currentFontSize;
|
|
if (selectedNode && selectedNode.parentNode && selectedNode.nodeName() !== 'HTML') {
|
|
const [model] = SDK.SDKModel.TargetManager.instance().models(CssOverviewModule.CSSOverviewModel.CSSOverviewModel);
|
|
const fontSizeNodeId = isFontSizeProperty ? selectedNode.parentNode.id : selectedNode.id;
|
|
const computedFontSize = await model.getComputedStyleForNode(fontSizeNodeId).then(findFontSizeValue);
|
|
const computedFontSizeValue = computedFontSize.replace(/[a-z]/g, '');
|
|
currentFontSize = parseFloat(computedFontSizeValue);
|
|
} else {
|
|
currentFontSize = 16;
|
|
}
|
|
return currentFontSize;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getRemMultiplier() {
|
|
const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
|
|
const htmlNode = findHtmlNode(selectedNode);
|
|
if (!htmlNode || !htmlNode.id) {
|
|
return 16;
|
|
}
|
|
const [model] = SDK.SDKModel.TargetManager.instance().models(CssOverviewModule.CSSOverviewModel.CSSOverviewModel);
|
|
const computedRootFontSize = await model.getComputedStyleForNode(htmlNode.id).then(findFontSizeValue);
|
|
const rootFontSizeValue = computedRootFontSize.replace(/[a-z]/g, '');
|
|
const rootFontSize = parseFloat(rootFontSizeValue);
|
|
return rootFontSize;
|
|
}
|
|
|
|
/**
|
|
* @param {boolean=} isFontSizeProperty
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getPercentMultiplier(isFontSizeProperty) {
|
|
const emMultiplier = await getEmMultiplier(isFontSizeProperty);
|
|
const percMultiplier = emMultiplier / 100;
|
|
return percMultiplier;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getVhMultiplier() {
|
|
const viewportObject = await getViewportObject();
|
|
if (!viewportObject) {
|
|
return 1;
|
|
}
|
|
const viewportHeight = viewportObject.height;
|
|
const vhMultiplier = viewportHeight / 100;
|
|
return vhMultiplier;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getVwMultiplier() {
|
|
const viewportObject = await getViewportObject();
|
|
if (!viewportObject) {
|
|
return 1;
|
|
}
|
|
const viewportWidth = viewportObject.width;
|
|
const vwMultiplier = viewportWidth / 100;
|
|
return vwMultiplier;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getVminMultiplier() {
|
|
const viewportObject = await getViewportObject();
|
|
if (!viewportObject) {
|
|
return 1;
|
|
}
|
|
const viewportWidth = viewportObject.width;
|
|
const viewportHeight = viewportObject.height;
|
|
const minViewportSize = Math.min(viewportWidth, viewportHeight);
|
|
const vminMultiplier = minViewportSize / 100;
|
|
return vminMultiplier;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<number>}
|
|
*/
|
|
async function getVmaxMultiplier() {
|
|
const viewportObject = await getViewportObject();
|
|
if (!viewportObject) {
|
|
return 1;
|
|
}
|
|
const viewportWidth = viewportObject.width;
|
|
const viewportHeight = viewportObject.height;
|
|
const maxViewportSize = Math.max(viewportWidth, viewportHeight);
|
|
const vmaxMultiplier = maxViewportSize / 100;
|
|
return vmaxMultiplier;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getCmMultiplier() {
|
|
return 37.795;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getMmMultiplier() {
|
|
return 3.7795;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getInMultiplier() {
|
|
return 96;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getPtMultiplier() {
|
|
return 4 / 3;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
function getPcMultiplier() {
|
|
return 16;
|
|
}
|
|
|
|
/**
|
|
* @param {{computedStyle: !Array<!{name: string, value: string}>, getError: function():void}} computedObject
|
|
*/
|
|
function findFontSizeValue(computedObject) {
|
|
/** @type {!Array<{name: string, value: string}>} */
|
|
const computedArray = computedObject.computedStyle;
|
|
let index = computedArrayFontSizeIndex;
|
|
if (computedArray[index].name && computedArray[index].name !== 'font-size') {
|
|
for (let i = 0; i < computedArray.length; i++) {
|
|
if (computedArray[i].name === 'font-size') {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return computedArray[index].value;
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.DOMModel.DOMNode | null} selectedNode
|
|
* @return {!SDK.DOMModel.DOMNode | null}
|
|
*/
|
|
function findHtmlNode(selectedNode) {
|
|
let node = selectedNode;
|
|
while (node && node.nodeName() !== 'HTML') {
|
|
if (node.parentNode) {
|
|
node = node.parentNode;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
const widthEvaluateParams = {
|
|
expression: 'window.innerWidth',
|
|
objectGroup: undefined,
|
|
includeCommandLineAPI: false,
|
|
silent: true,
|
|
contextId: undefined,
|
|
returnByValue: false,
|
|
generatePreview: false,
|
|
userGesture: false,
|
|
awaitPromise: true,
|
|
throwOnSideEffect: false,
|
|
timeout: undefined,
|
|
disableBreaks: true,
|
|
replMode: false,
|
|
allowUnsafeEvalBlockedByCSP: false
|
|
};
|
|
|
|
const heightEvaluateParams = {
|
|
expression: 'window.innerHeight',
|
|
objectGroup: undefined,
|
|
includeCommandLineAPI: false,
|
|
silent: true,
|
|
contextId: undefined,
|
|
returnByValue: false,
|
|
generatePreview: false,
|
|
userGesture: false,
|
|
awaitPromise: true,
|
|
throwOnSideEffect: false,
|
|
timeout: undefined,
|
|
disableBreaks: true,
|
|
replMode: false,
|
|
allowUnsafeEvalBlockedByCSP: false
|
|
};
|
|
|
|
/**
|
|
* @return {!Promise<?{width: number, height: number}>}
|
|
*/
|
|
async function getViewportObject() {
|
|
const currentExecutionContext = UI.Context.Context.instance().flavor(SDK.RuntimeModel.ExecutionContext);
|
|
let width, height;
|
|
if (currentExecutionContext) {
|
|
const widthObject = await currentExecutionContext.evaluate(widthEvaluateParams, false, false);
|
|
const heightObject = await currentExecutionContext.evaluate(heightEvaluateParams, false, false);
|
|
if ('error' in widthObject || 'error' in heightObject) {
|
|
return null;
|
|
}
|
|
if (widthObject.object) {
|
|
width = widthObject.object.value;
|
|
}
|
|
if (heightObject.object) {
|
|
height = heightObject.object.value;
|
|
}
|
|
}
|
|
if (width === undefined || height === undefined) {
|
|
const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
|
|
if (!selectedNode) {
|
|
return null;
|
|
}
|
|
const pageLayout = await selectedNode.domModel().target().pageAgent().invoke_getLayoutMetrics();
|
|
const zoom = pageLayout.visualViewport.zoom ? pageLayout.visualViewport.zoom : 1;
|
|
height = pageLayout.visualViewport.clientHeight / zoom;
|
|
width = pageLayout.visualViewport.clientWidth / zoom;
|
|
}
|
|
return {width, height};
|
|
}
|
|
|
|
const unitConversionMap = new Map();
|
|
unitConversionMap.set('px', getPxMultiplier);
|
|
unitConversionMap.set('em', getEmMultiplier);
|
|
unitConversionMap.set('rem', getRemMultiplier);
|
|
unitConversionMap.set('%', getPercentMultiplier);
|
|
unitConversionMap.set('vh', getVhMultiplier);
|
|
unitConversionMap.set('vw', getVwMultiplier);
|
|
unitConversionMap.set('vmin', getVminMultiplier);
|
|
unitConversionMap.set('vmax', getVmaxMultiplier);
|
|
unitConversionMap.set('cm', getCmMultiplier);
|
|
unitConversionMap.set('mm', getMmMultiplier);
|
|
unitConversionMap.set('in', getInMultiplier);
|
|
unitConversionMap.set('pt', getPtMultiplier);
|
|
unitConversionMap.set('pc', getPcMultiplier);
|
|
|
|
/**
|
|
* @param {string} prevUnit
|
|
* @param {string} newUnit
|
|
* @param {boolean=} isFontSize
|
|
* @return {!Promise<number>}
|
|
*/
|
|
export async function getUnitConversionMultiplier(prevUnit, newUnit, isFontSize) {
|
|
if (prevUnit === '') {
|
|
prevUnit = 'em';
|
|
}
|
|
if (newUnit === '') {
|
|
newUnit = 'em';
|
|
}
|
|
let prevUnitMultiplier, newUnitMultiplier;
|
|
const prevUnitFunction = unitConversionMap.get(prevUnit);
|
|
const newUnitFunction = unitConversionMap.get(newUnit);
|
|
if (prevUnitFunction && newUnitFunction) {
|
|
if (prevUnit === 'em' || prevUnit === '%') {
|
|
prevUnitMultiplier = await prevUnitFunction(isFontSize);
|
|
} else {
|
|
prevUnitMultiplier = await prevUnitFunction();
|
|
}
|
|
if (newUnit === 'em' || newUnit === '%') {
|
|
newUnitMultiplier = await newUnitFunction(isFontSize);
|
|
} else {
|
|
newUnitMultiplier = await newUnitFunction();
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
return prevUnitMultiplier / newUnitMultiplier;
|
|
}
|