tor-browser

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

HTMLEditHelpers.cpp (6330B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "HTMLEditHelpers.h"
      7 
      8 #include "CSSEditUtils.h"
      9 #include "HTMLEditor.h"
     10 #include "HTMLEditUtils.h"
     11 #include "PendingStyles.h"
     12 
     13 #include "mozilla/ContentIterator.h"
     14 #include "mozilla/OwningNonNull.h"
     15 #include "nsIContent.h"
     16 #include "nsINode.h"
     17 #include "nsRange.h"
     18 
     19 class nsISupports;
     20 
     21 namespace mozilla {
     22 
     23 using namespace dom;
     24 
     25 template void DOMIterator::AppendAllNodesToArray(
     26    nsTArray<OwningNonNull<nsIContent>>& aArrayOfNodes) const;
     27 template void DOMIterator::AppendAllNodesToArray(
     28    nsTArray<OwningNonNull<HTMLBRElement>>& aArrayOfNodes) const;
     29 template void DOMIterator::AppendNodesToArray(
     30    BoolFunctor aFunctor, nsTArray<OwningNonNull<nsIContent>>& aArrayOfNodes,
     31    void* aClosure) const;
     32 template void DOMIterator::AppendNodesToArray(
     33    BoolFunctor aFunctor, nsTArray<OwningNonNull<Element>>& aArrayOfNodes,
     34    void* aClosure) const;
     35 template void DOMIterator::AppendNodesToArray(
     36    BoolFunctor aFunctor, nsTArray<OwningNonNull<Text>>& aArrayOfNodes,
     37    void* aClosure) const;
     38 
     39 /******************************************************************************
     40 * some helper classes for iterating the dom tree
     41 *****************************************************************************/
     42 
     43 DOMIterator::DOMIterator(nsINode& aNode) : mIter(&mPostOrderIter) {
     44  DebugOnly<nsresult> rv = mIter->Init(&aNode);
     45  MOZ_ASSERT(NS_SUCCEEDED(rv));
     46 }
     47 
     48 nsresult DOMIterator::Init(nsRange& aRange) { return mIter->Init(&aRange); }
     49 
     50 nsresult DOMIterator::Init(const RawRangeBoundary& aStartRef,
     51                           const RawRangeBoundary& aEndRef) {
     52  return mIter->Init(aStartRef, aEndRef);
     53 }
     54 
     55 DOMIterator::DOMIterator() : mIter(&mPostOrderIter) {}
     56 
     57 template <class NodeClass>
     58 void DOMIterator::AppendAllNodesToArray(
     59    nsTArray<OwningNonNull<NodeClass>>& aArrayOfNodes) const {
     60  for (; !mIter->IsDone(); mIter->Next()) {
     61    if (NodeClass* node = NodeClass::FromNode(mIter->GetCurrentNode())) {
     62      aArrayOfNodes.AppendElement(*node);
     63    }
     64  }
     65 }
     66 
     67 template <class NodeClass>
     68 void DOMIterator::AppendNodesToArray(
     69    BoolFunctor aFunctor, nsTArray<OwningNonNull<NodeClass>>& aArrayOfNodes,
     70    void* aClosure /* = nullptr */) const {
     71  for (; !mIter->IsDone(); mIter->Next()) {
     72    NodeClass* node = NodeClass::FromNode(mIter->GetCurrentNode());
     73    if (node && aFunctor(*node, aClosure)) {
     74      aArrayOfNodes.AppendElement(*node);
     75    }
     76  }
     77 }
     78 
     79 DOMSubtreeIterator::DOMSubtreeIterator() { mIter = &mSubtreeIter; }
     80 
     81 nsresult DOMSubtreeIterator::Init(nsRange& aRange) {
     82  return mIter->Init(&aRange);
     83 }
     84 
     85 /******************************************************************************
     86 * mozilla::EditorElementStyle
     87 *****************************************************************************/
     88 
     89 bool EditorElementStyle::IsCSSSettable(const nsStaticAtom& aTagName) const {
     90  return CSSEditUtils::IsCSSEditableStyle(aTagName, *this);
     91 }
     92 
     93 bool EditorElementStyle::IsCSSSettable(const Element& aElement) const {
     94  return CSSEditUtils::IsCSSEditableStyle(aElement, *this);
     95 }
     96 
     97 bool EditorElementStyle::IsCSSRemovable(const nsStaticAtom& aTagName) const {
     98  // <font size> cannot be applied with CSS font-size for now, but it should be
     99  // removable.
    100  return EditorElementStyle::IsCSSSettable(aTagName) ||
    101         (IsInlineStyle() && AsInlineStyle().IsStyleOfFontSize());
    102 }
    103 
    104 bool EditorElementStyle::IsCSSRemovable(const Element& aElement) const {
    105  // <font size> cannot be applied with CSS font-size for now, but it should be
    106  // removable.
    107  return EditorElementStyle::IsCSSSettable(aElement) ||
    108         (IsInlineStyle() && AsInlineStyle().IsStyleOfFontSize());
    109 }
    110 
    111 /******************************************************************************
    112 * mozilla::EditorInlineStyle
    113 *****************************************************************************/
    114 
    115 PendingStyleCache EditorInlineStyle::ToPendingStyleCache(
    116    nsAString&& aValue) const {
    117  return PendingStyleCache(*mHTMLProperty,
    118                           mAttribute ? mAttribute->AsStatic() : nullptr,
    119                           std::move(aValue));
    120 }
    121 
    122 bool EditorInlineStyle::IsRepresentedBy(const nsIContent& aContent) const {
    123  MOZ_ASSERT(!IsStyleToClearAllInlineStyles());
    124 
    125  if (!aContent.IsHTMLElement()) {
    126    return false;
    127  }
    128  const Element& element = *aContent.AsElement();
    129  if (mHTMLProperty == element.NodeInfo()->NameAtom() ||
    130      mHTMLProperty == GetSimilarElementNameAtom()) {
    131    // <a> cannot be nested.  Therefore, if we're the style of <a>, we should
    132    // treat existing it even if the attribute does not match.
    133    if (mHTMLProperty == nsGkAtoms::a) {
    134      return true;
    135    }
    136    return !mAttribute || element.HasAttr(mAttribute);
    137  }
    138  // Special case for linking or naming an <a> element.
    139  if ((mHTMLProperty == nsGkAtoms::href &&
    140       HTMLEditUtils::IsHyperlinkElement(element)) ||
    141      (mHTMLProperty == nsGkAtoms::name &&
    142       HTMLEditUtils::IsNamedAnchorElement(element))) {
    143    return true;
    144  }
    145  // If the style is font size, it's also represented by <big> or <small>.
    146  if (mHTMLProperty == nsGkAtoms::font && mAttribute == nsGkAtoms::size &&
    147      aContent.IsAnyOfHTMLElements(nsGkAtoms::big, nsGkAtoms::small)) {
    148    return true;
    149  }
    150  return false;
    151 }
    152 
    153 Result<bool, nsresult> EditorInlineStyle::IsSpecifiedBy(
    154    const HTMLEditor& aHTMLEditor, Element& aElement) const {
    155  MOZ_ASSERT(!IsStyleToClearAllInlineStyles());
    156  if (!IsCSSSettable(aElement) && !IsCSSRemovable(aElement)) {
    157    return false;
    158  }
    159  // Special case in the CSS mode.  We should treat <u>, <s>, <strike>, <ins>
    160  // and <del> specifies text-decoration (bug 1802668).
    161  if (aHTMLEditor.IsCSSEnabled() &&
    162      IsStyleOfTextDecoration(IgnoreSElement::No) &&
    163      aElement.IsAnyOfHTMLElements(nsGkAtoms::u, nsGkAtoms::s,
    164                                   nsGkAtoms::strike, nsGkAtoms::ins,
    165                                   nsGkAtoms::del)) {
    166    return true;
    167  }
    168  return CSSEditUtils::HaveSpecifiedCSSEquivalentStyles(aHTMLEditor, aElement,
    169                                                        *this);
    170 }
    171 
    172 }  // namespace mozilla