tor-browser

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

utils.js (4716B)


      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 FLASH_TARGETS_SELECTOR = "[class*=theme-fg-color], .force-color-on-flash";
      8 
      9 /**
     10 * Apply a 'flashed' background and foreground color to elements. Intended
     11 * to be used with flashElementOff as a way of drawing attention to an element.
     12 *
     13 * @param  {Node} backgroundElt
     14 *         The element to set the highlighted background color on.
     15 * @param  {object} options
     16 * @param  {Node} options.foregroundElt
     17 *         The element to set the matching foreground color on. This will equal
     18 *         backgroundElt if not set.
     19 * @param  {string} options.backgroundClass
     20 *         The background highlight color class to set on the element.
     21 */
     22 function flashElementOn(
     23  backgroundElt,
     24  { foregroundElt = backgroundElt, backgroundClass = "theme-bg-contrast" } = {}
     25 ) {
     26  if (!backgroundElt || !foregroundElt) {
     27    return;
     28  }
     29 
     30  // Make sure the animation class is not here
     31  backgroundElt.classList.remove("flash-out");
     32 
     33  // Change the background
     34  backgroundElt.classList.add(backgroundClass);
     35 
     36  foregroundElt.classList.add("theme-fg-contrast");
     37  foregroundElt
     38    .querySelectorAll(FLASH_TARGETS_SELECTOR)
     39    .forEach(span => span.classList.add("theme-fg-contrast"));
     40 }
     41 
     42 /**
     43 * Remove a 'flashed' background and foreground color to elements.
     44 * See flashElementOn.
     45 *
     46 * @param  {Node} backgroundElt
     47 *         The element to remove the highlighted background color on.
     48 * @param  {object} options
     49 * @param  {Node} options.foregroundElt
     50 *         The element to remove the matching foreground color on. This will equal
     51 *         backgroundElt if not set.
     52 * @param  {string} options.backgroundClass
     53 *         The background highlight color class to remove on the element.
     54 */
     55 function flashElementOff(
     56  backgroundElt,
     57  { foregroundElt = backgroundElt, backgroundClass = "theme-bg-contrast" } = {}
     58 ) {
     59  if (!backgroundElt || !foregroundElt) {
     60    return;
     61  }
     62 
     63  // Add the animation class to smoothly remove the background
     64  backgroundElt.classList.add("flash-out");
     65 
     66  // Remove the background
     67  backgroundElt.classList.remove(backgroundClass);
     68 
     69  foregroundElt.classList.remove("theme-fg-contrast");
     70  // Make sure the foreground animation class is removed
     71  foregroundElt.classList.remove("flash-out");
     72  foregroundElt
     73    .querySelectorAll(FLASH_TARGETS_SELECTOR)
     74    .forEach(span => span.classList.remove("theme-fg-contrast"));
     75 }
     76 
     77 /**
     78 * Retrieve the available width between a provided element left edge and a container right
     79 * edge. This used can be used as a max-width for inplace-editor (autocomplete) widgets
     80 * replacing Editor elements of the the markup-view;
     81 */
     82 function getAutocompleteMaxWidth(element, container) {
     83  const elementRect = element.getBoundingClientRect();
     84  const containerRect = container.getBoundingClientRect();
     85  return containerRect.right - elementRect.left - 2;
     86 }
     87 
     88 /**
     89 * Parse attribute names and values from a string.
     90 *
     91 * @param  {string} attr
     92 *         The input string for which names/values are to be parsed.
     93 * @param  {HTMLDocument} doc
     94 *         A document that can be used to test valid attributes.
     95 * @return {Array}
     96 *         An array of attribute names and their values.
     97 */
     98 function parseAttributeValues(attr, doc) {
     99  attr = attr.trim();
    100 
    101  const parseAndGetNode = str => {
    102    return new DOMParser().parseFromString(str, "text/html").body.childNodes[0];
    103  };
    104 
    105  // Handle bad user inputs by appending a " or ' if it fails to parse without
    106  // them. Also note that a SVG tag is used to make sure the HTML parser
    107  // preserves mixed-case attributes
    108  const el =
    109    parseAndGetNode("<svg " + attr + "></svg>") ||
    110    parseAndGetNode("<svg " + attr + '"></svg>') ||
    111    parseAndGetNode("<svg " + attr + "'></svg>");
    112 
    113  // Create <div> in new document to work around CSP blocking inline styles.
    114  const htmlDoc = doc.implementation.createHTMLDocument();
    115  const div = htmlDoc.createElement("div");
    116  const attributes = [];
    117  for (const { name, value } of el.attributes) {
    118    // Try to set on an element in the document, throws exception on bad input.
    119    // Prevents InvalidCharacterError - "String contains an invalid character".
    120    try {
    121      div.setAttribute(name, value);
    122      attributes.push({ name, value });
    123    } catch (e) {
    124      // This may throw exceptions on bad input.
    125      // Prevents InvalidCharacterError - "String contains an invalid
    126      // character".
    127    }
    128  }
    129 
    130  return attributes;
    131 }
    132 
    133 module.exports = {
    134  flashElementOn,
    135  flashElementOff,
    136  getAutocompleteMaxWidth,
    137  parseAttributeValues,
    138 };