From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- devtools/client/inspector/fonts/components/Font.js | 139 +++++++ .../client/inspector/fonts/components/FontAxis.js | 75 ++++ .../inspector/fonts/components/FontEditor.js | 357 +++++++++++++++++ .../client/inspector/fonts/components/FontList.js | 82 ++++ .../client/inspector/fonts/components/FontName.js | 53 +++ .../inspector/fonts/components/FontOrigin.js | 79 ++++ .../inspector/fonts/components/FontOverview.js | 80 ++++ .../inspector/fonts/components/FontPreview.js | 40 ++ .../inspector/fonts/components/FontPreviewInput.js | 77 ++++ .../fonts/components/FontPropertyValue.js | 434 +++++++++++++++++++++ .../client/inspector/fonts/components/FontSize.js | 87 +++++ .../client/inspector/fonts/components/FontStyle.js | 69 ++++ .../inspector/fonts/components/FontWeight.js | 45 +++ .../client/inspector/fonts/components/FontsApp.js | 71 ++++ .../inspector/fonts/components/LetterSpacing.js | 105 +++++ .../inspector/fonts/components/LineHeight.js | 101 +++++ .../client/inspector/fonts/components/moz.build | 24 ++ 17 files changed, 1918 insertions(+) create mode 100644 devtools/client/inspector/fonts/components/Font.js create mode 100644 devtools/client/inspector/fonts/components/FontAxis.js create mode 100644 devtools/client/inspector/fonts/components/FontEditor.js create mode 100644 devtools/client/inspector/fonts/components/FontList.js create mode 100644 devtools/client/inspector/fonts/components/FontName.js create mode 100644 devtools/client/inspector/fonts/components/FontOrigin.js create mode 100644 devtools/client/inspector/fonts/components/FontOverview.js create mode 100644 devtools/client/inspector/fonts/components/FontPreview.js create mode 100644 devtools/client/inspector/fonts/components/FontPreviewInput.js create mode 100644 devtools/client/inspector/fonts/components/FontPropertyValue.js create mode 100644 devtools/client/inspector/fonts/components/FontSize.js create mode 100644 devtools/client/inspector/fonts/components/FontStyle.js create mode 100644 devtools/client/inspector/fonts/components/FontWeight.js create mode 100644 devtools/client/inspector/fonts/components/FontsApp.js create mode 100644 devtools/client/inspector/fonts/components/LetterSpacing.js create mode 100644 devtools/client/inspector/fonts/components/LineHeight.js create mode 100644 devtools/client/inspector/fonts/components/moz.build (limited to 'devtools/client/inspector/fonts/components') diff --git a/devtools/client/inspector/fonts/components/Font.js b/devtools/client/inspector/fonts/components/Font.js new file mode 100644 index 0000000000..c761a3d2f1 --- /dev/null +++ b/devtools/client/inspector/fonts/components/Font.js @@ -0,0 +1,139 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createFactory, + PureComponent, +} = require("resource://devtools/client/shared/vendor/react.js"); +const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); + +const FontName = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontName.js") +); +const FontOrigin = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontOrigin.js") +); +const FontPreview = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontPreview.js") +); + +const Types = require("resource://devtools/client/inspector/fonts/types.js"); + +class Font extends PureComponent { + static get propTypes() { + return { + font: PropTypes.shape(Types.font).isRequired, + onPreviewClick: PropTypes.func, + onToggleFontHighlight: PropTypes.func.isRequired, + }; + } + + constructor(props) { + super(props); + + this.state = { + isFontFaceRuleExpanded: false, + }; + + this.onFontFaceRuleToggle = this.onFontFaceRuleToggle.bind(this); + } + + // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507 + UNSAFE_componentWillReceiveProps(newProps) { + if (this.props.font.name === newProps.font.name) { + return; + } + + this.setState({ + isFontFaceRuleExpanded: false, + }); + } + + onFontFaceRuleToggle(event) { + this.setState({ + isFontFaceRuleExpanded: !this.state.isFontFaceRuleExpanded, + }); + event.stopPropagation(); + } + + renderFontCSSCode(rule, ruleText) { + if (!rule) { + return null; + } + + // Cut the rule text in 3 parts: the selector, the declarations, the closing brace. + // This way we can collapse the declarations by default and display an expander icon + // to expand them again. + const leading = ruleText.substring(0, ruleText.indexOf("{") + 1); + const body = ruleText.substring( + ruleText.indexOf("{") + 1, + ruleText.lastIndexOf("}") + ); + const trailing = ruleText.substring(ruleText.lastIndexOf("}")); + + const { isFontFaceRuleExpanded } = this.state; + + return dom.pre( + { + className: "font-css-code", + }, + this.renderFontCSSCodeTwisty(), + leading, + isFontFaceRuleExpanded + ? body + : dom.span({ + className: "font-css-code-expander", + onClick: this.onFontFaceRuleToggle, + }), + trailing + ); + } + + renderFontCSSCodeTwisty() { + const { isFontFaceRuleExpanded } = this.state; + + const attributes = { + className: "theme-twisty", + onClick: this.onFontFaceRuleToggle, + }; + if (isFontFaceRuleExpanded) { + attributes.open = "true"; + } + + return dom.span(attributes); + } + + renderFontFamilyName(family) { + if (!family) { + return null; + } + + return dom.div({ className: "font-family-name" }, family); + } + + render() { + const { font, onPreviewClick, onToggleFontHighlight } = this.props; + + const { CSSFamilyName, previewUrl, rule, ruleText } = font; + + return dom.li( + { + className: "font", + }, + dom.div( + {}, + this.renderFontFamilyName(CSSFamilyName), + FontName({ font, onToggleFontHighlight }) + ), + FontOrigin({ font }), + FontPreview({ onPreviewClick, previewUrl }), + this.renderFontCSSCode(rule, ruleText) + ); + } +} + +module.exports = Font; diff --git a/devtools/client/inspector/fonts/components/FontAxis.js b/devtools/client/inspector/fonts/components/FontAxis.js new file mode 100644 index 0000000000..f695c06b29 --- /dev/null +++ b/devtools/client/inspector/fonts/components/FontAxis.js @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createFactory, + PureComponent, +} = require("resource://devtools/client/shared/vendor/react.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); + +const FontPropertyValue = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontPropertyValue.js") +); + +const Types = require("resource://devtools/client/inspector/fonts/types.js"); + +class FontAxis extends PureComponent { + static get propTypes() { + return { + axis: PropTypes.shape(Types.fontVariationAxis), + disabled: PropTypes.bool.isRequired, + onChange: PropTypes.func.isRequired, + value: PropTypes.number.isRequired, + }; + } + + /** + * Naive implementation to get increment step for variable font axis that ensures + * fine grained control based on range of values between min and max. + * + * @param {Number} min + * Minumum value for range. + * @param {Number} max + * Maximum value for range. + * @return {Number} + * Step value used in range input for font axis. + */ + getAxisStep(min, max) { + let step = 1; + const delta = parseInt(max, 10) - parseInt(min, 10); + + if (delta <= 1) { + step = 0.001; + } else if (delta <= 10) { + step = 0.01; + } else if (delta <= 100) { + step = 0.1; + } + + return step; + } + + render() { + const { axis, value, onChange } = this.props; + + return FontPropertyValue({ + className: "font-control-axis", + disabled: this.props.disabled, + label: axis.name, + min: axis.minValue, + minLabel: true, + max: axis.maxValue, + maxLabel: true, + name: axis.tag, + nameLabel: true, + onChange, + step: this.getAxisStep(axis.minValue, axis.maxValue), + value, + }); + } +} + +module.exports = FontAxis; diff --git a/devtools/client/inspector/fonts/components/FontEditor.js b/devtools/client/inspector/fonts/components/FontEditor.js new file mode 100644 index 0000000000..b98118c9fc --- /dev/null +++ b/devtools/client/inspector/fonts/components/FontEditor.js @@ -0,0 +1,357 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createFactory, + PureComponent, +} = require("resource://devtools/client/shared/vendor/react.js"); +const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); + +const FontAxis = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontAxis.js") +); +const FontName = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontName.js") +); +const FontSize = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontSize.js") +); +const FontStyle = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontStyle.js") +); +const FontWeight = createFactory( + require("resource://devtools/client/inspector/fonts/components/FontWeight.js") +); +const LetterSpacing = createFactory( + require("resource://devtools/client/inspector/fonts/components/LetterSpacing.js") +); +const LineHeight = createFactory( + require("resource://devtools/client/inspector/fonts/components/LineHeight.js") +); + +const { + getStr, +} = require("resource://devtools/client/inspector/fonts/utils/l10n.js"); +const Types = require("resource://devtools/client/inspector/fonts/types.js"); + +// Maximum number of font families to be shown by default. Any others will be hidden +// under a collapsed
element with a toggle to reveal them. +const MAX_FONTS = 3; + +class FontEditor extends PureComponent { + static get propTypes() { + return { + fontEditor: PropTypes.shape(Types.fontEditor).isRequired, + onInstanceChange: PropTypes.func.isRequired, + onPropertyChange: PropTypes.func.isRequired, + onToggleFontHighlight: PropTypes.func.isRequired, + }; + } + + /** + * Get an array of FontAxis components with editing controls for of the given variable + * font axes. If no axes were given, return null. + * If an axis' value was declared on the font-variation-settings CSS property or was + * changed using the font editor, use that value, otherwise use the axis default. + * + * @param {Array} fontAxes + * Array of font axis instances + * @param {Object} editedAxes + * Object with axes and values edited by the user or defined in the CSS + * declaration for font-variation-settings. + * @return {Array|null} + */ + renderAxes(fontAxes = [], editedAxes) { + if (!fontAxes.length) { + return null; + } + + return fontAxes.map(axis => { + return FontAxis({ + key: axis.tag, + axis, + disabled: this.props.fontEditor.disabled, + onChange: this.props.onPropertyChange, + minLabel: true, + maxLabel: true, + value: editedAxes[axis.tag] || axis.defaultValue, + }); + }); + } + + /** + * Render fonts used on the selected node grouped by font-family. + * + * @param {Array} fonts + * Fonts used on selected node. + * @return {DOMNode} + */ + renderUsedFonts(fonts) { + if (!fonts.length) { + return null; + } + + // Group fonts by family name. + const fontGroups = fonts.reduce((acc, font) => { + const family = font.CSSFamilyName.toString(); + acc[family] = acc[family] || []; + acc[family].push(font); + return acc; + }, {}); + + const renderedFontGroups = Object.keys(fontGroups).map(family => { + return this.renderFontGroup(family, fontGroups[family]); + }); + + const topFontsList = renderedFontGroups.slice(0, MAX_FONTS); + const moreFontsList = renderedFontGroups.slice( + MAX_FONTS, + renderedFontGroups.length + ); + + const moreFonts = !moreFontsList.length + ? null + : dom.details( + {}, + dom.summary( + {}, + dom.span( + { className: "label-open" }, + getStr("fontinspector.showMore") + ), + dom.span( + { className: "label-close" }, + getStr("fontinspector.showLess") + ) + ), + moreFontsList + ); + + return dom.label( + { + className: "font-control font-control-used-fonts", + }, + dom.span( + { + className: "font-control-label", + }, + getStr("fontinspector.fontsUsedLabel") + ), + dom.div( + { + className: "font-control-box", + }, + topFontsList, + moreFonts + ) + ); + } + + renderFontGroup(family, fonts = []) { + const group = fonts.map(font => { + return FontName({ + key: font.name, + font, + onToggleFontHighlight: this.props.onToggleFontHighlight, + }); + }); + + return dom.div( + { + key: family, + className: "font-group", + }, + dom.div( + { + className: "font-family-name", + }, + family + ), + group + ); + } + + renderFontSize(value) { + return ( + value !== null && + FontSize({ + key: `${this.props.fontEditor.id}:font-size`, + disabled: this.props.fontEditor.disabled, + onChange: this.props.onPropertyChange, + value, + }) + ); + } + + renderLineHeight(value) { + return ( + value !== null && + LineHeight({ + key: `${this.props.fontEditor.id}:line-height`, + disabled: this.props.fontEditor.disabled, + onChange: this.props.onPropertyChange, + value, + }) + ); + } + + renderLetterSpacing(value) { + return ( + value !== null && + LetterSpacing({ + key: `${this.props.fontEditor.id}:letter-spacing`, + disabled: this.props.fontEditor.disabled, + onChange: this.props.onPropertyChange, + value, + }) + ); + } + + renderFontStyle(value) { + return ( + value && + FontStyle({ + onChange: this.props.onPropertyChange, + disabled: this.props.fontEditor.disabled, + value, + }) + ); + } + + renderFontWeight(value) { + return ( + value !== null && + FontWeight({ + onChange: this.props.onPropertyChange, + disabled: this.props.fontEditor.disabled, + value, + }) + ); + } + + /** + * Get a dropdown which allows selecting between variation instances defined by a font. + * + * @param {Array} fontInstances + * Named variation instances as provided with the font file. + * @param {Object} selectedInstance + * Object with information about the currently selected variation instance. + * Example: + * { + * name: "Custom", + * values: [] + * } + * @return {DOMNode} + */ + renderInstances(fontInstances = [], selectedInstance = {}) { + // Append a "Custom" instance entry which represents the latest manual axes changes. + const customInstance = { + name: getStr("fontinspector.customInstanceName"), + values: this.props.fontEditor.customInstanceValues, + }; + fontInstances = [...fontInstances, customInstance]; + + // Generate the