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