tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Font.js (4399B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  createFactory,
      9  PureComponent,
     10 } = require("resource://devtools/client/shared/vendor/react.mjs");
     11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     12 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     13 
     14 const {
     15  getStr,
     16 } = require("resource://devtools/client/inspector/fonts/utils/l10n.js");
     17 const FontName = createFactory(
     18  require("resource://devtools/client/inspector/fonts/components/FontName.js")
     19 );
     20 const FontOrigin = createFactory(
     21  require("resource://devtools/client/inspector/fonts/components/FontOrigin.js")
     22 );
     23 const FontPreview = createFactory(
     24  require("resource://devtools/client/inspector/fonts/components/FontPreview.js")
     25 );
     26 const FontMetadata = createFactory(
     27  require("resource://devtools/client/inspector/fonts/components/FontMetadata.js")
     28 );
     29 
     30 const Types = require("resource://devtools/client/inspector/fonts/types.js");
     31 
     32 class Font extends PureComponent {
     33  static get propTypes() {
     34    return {
     35      font: PropTypes.shape(Types.font).isRequired,
     36      onPreviewClick: PropTypes.func,
     37      onToggleFontHighlight: PropTypes.func.isRequired,
     38    };
     39  }
     40 
     41  constructor(props) {
     42    super(props);
     43 
     44    this.state = {
     45      isFontFaceRuleExpanded: false,
     46    };
     47 
     48    this.onFontFaceRuleToggle = this.onFontFaceRuleToggle.bind(this);
     49  }
     50 
     51  onFontFaceRuleToggle(event) {
     52    this.setState({
     53      isFontFaceRuleExpanded: !this.state.isFontFaceRuleExpanded,
     54    });
     55    event.stopPropagation();
     56  }
     57 
     58  renderFontCSSCode(rule, ruleText) {
     59    if (!rule) {
     60      return null;
     61    }
     62 
     63    const { isFontFaceRuleExpanded } = this.state;
     64 
     65    // Cut the rule text in 3 parts: the selector, the declarations, the closing brace.
     66    // This way we can collapse the declarations by default and display an expander icon
     67    // to expand them again.
     68    const leading = ruleText.substring(0, ruleText.indexOf("{") + 1);
     69 
     70    const trailing = ruleText.substring(ruleText.lastIndexOf("}"));
     71 
     72    let body;
     73    if (isFontFaceRuleExpanded) {
     74      const ruleBodyText = ruleText
     75        .substring(ruleText.indexOf("{") + 1, ruleText.lastIndexOf("}"))
     76        .trim();
     77 
     78      const indent = "  ";
     79      body = "\n";
     80      const lexer = new InspectorCSSParser(ruleBodyText);
     81      let token;
     82      let isNewLine = true;
     83      while ((token = lexer.nextToken())) {
     84        if (isNewLine) {
     85          // If we just added a new line, ignore any whitespace as we'll handle the
     86          // indentation ourselves.
     87          if (token.tokenType === "WhiteSpace") {
     88            continue;
     89          }
     90          body += indent;
     91          isNewLine = false;
     92        }
     93 
     94        body += token.text;
     95        if (token.tokenType === "Semicolon") {
     96          body += "\n";
     97          isNewLine = true;
     98        }
     99      }
    100    }
    101 
    102    return dom.pre(
    103      {
    104        className: "font-css-code",
    105      },
    106      this.renderFontCSSCodeTwisty(),
    107      leading,
    108      isFontFaceRuleExpanded
    109        ? body
    110        : dom.button({
    111            className: "font-truncated-string-expander",
    112            onClick: this.onFontFaceRuleToggle,
    113            title: getStr("fontinspector.showFullText"),
    114          }),
    115      trailing
    116    );
    117  }
    118 
    119  renderFontCSSCodeTwisty() {
    120    const { isFontFaceRuleExpanded } = this.state;
    121 
    122    return dom.button({
    123      className: "theme-twisty",
    124      onClick: this.onFontFaceRuleToggle,
    125      "aria-expanded": isFontFaceRuleExpanded,
    126      title: getStr("fontinspector.showFullText"),
    127    });
    128  }
    129 
    130  renderFontFamilyName(family) {
    131    if (!family) {
    132      return null;
    133    }
    134 
    135    return dom.div({ className: "font-family-name" }, family);
    136  }
    137 
    138  render() {
    139    const { font, onPreviewClick, onToggleFontHighlight } = this.props;
    140 
    141    const { CSSFamilyName, previewUrl, rule, ruleText } = font;
    142 
    143    return dom.li(
    144      {
    145        className: "font",
    146      },
    147      dom.div(
    148        {},
    149        this.renderFontFamilyName(CSSFamilyName),
    150        FontName({ font, onToggleFontHighlight })
    151      ),
    152      FontOrigin({ font }),
    153      FontPreview({ onPreviewClick, previewUrl }),
    154      this.renderFontCSSCode(rule, ruleText),
    155      FontMetadata({ font })
    156    );
    157  }
    158 }
    159 
    160 module.exports = Font;