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;