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/. */
6 #include "HTMLEditHelpers.h"
8 #include "CSSEditUtils.h"
9 #include "EditorDOMPoint.h"
10 #include "HTMLEditor.h"
11 #include "PendingStyles.h"
12 #include "WSRunObject.h"
14 #include "mozilla/ContentIterator.h"
15 #include "mozilla/OwningNonNull.h"
16 #include "mozilla/dom/HTMLBRElement.h"
17 #include "mozilla/dom/Text.h"
18 #include "nsIContent.h"
28 template void DOMIterator::AppendAllNodesToArray(
29 nsTArray
<OwningNonNull
<nsIContent
>>& aArrayOfNodes
) const;
30 template void DOMIterator::AppendAllNodesToArray(
31 nsTArray
<OwningNonNull
<HTMLBRElement
>>& aArrayOfNodes
) const;
32 template void DOMIterator::AppendNodesToArray(
33 BoolFunctor aFunctor
, nsTArray
<OwningNonNull
<nsIContent
>>& aArrayOfNodes
,
34 void* aClosure
) const;
35 template void DOMIterator::AppendNodesToArray(
36 BoolFunctor aFunctor
, nsTArray
<OwningNonNull
<Element
>>& aArrayOfNodes
,
37 void* aClosure
) const;
38 template void DOMIterator::AppendNodesToArray(
39 BoolFunctor aFunctor
, nsTArray
<OwningNonNull
<Text
>>& aArrayOfNodes
,
40 void* aClosure
) const;
42 /******************************************************************************
43 * some helper classes for iterating the dom tree
44 *****************************************************************************/
46 DOMIterator::DOMIterator(nsINode
& aNode
) : mIter(&mPostOrderIter
) {
47 DebugOnly
<nsresult
> rv
= mIter
->Init(&aNode
);
48 MOZ_ASSERT(NS_SUCCEEDED(rv
));
51 nsresult
DOMIterator::Init(nsRange
& aRange
) { return mIter
->Init(&aRange
); }
53 nsresult
DOMIterator::Init(const RawRangeBoundary
& aStartRef
,
54 const RawRangeBoundary
& aEndRef
) {
55 return mIter
->Init(aStartRef
, aEndRef
);
58 DOMIterator::DOMIterator() : mIter(&mPostOrderIter
) {}
60 template <class NodeClass
>
61 void DOMIterator::AppendAllNodesToArray(
62 nsTArray
<OwningNonNull
<NodeClass
>>& aArrayOfNodes
) const {
63 for (; !mIter
->IsDone(); mIter
->Next()) {
64 if (NodeClass
* node
= NodeClass::FromNode(mIter
->GetCurrentNode())) {
65 aArrayOfNodes
.AppendElement(*node
);
70 template <class NodeClass
>
71 void DOMIterator::AppendNodesToArray(
72 BoolFunctor aFunctor
, nsTArray
<OwningNonNull
<NodeClass
>>& aArrayOfNodes
,
73 void* aClosure
/* = nullptr */) const {
74 for (; !mIter
->IsDone(); mIter
->Next()) {
75 NodeClass
* node
= NodeClass::FromNode(mIter
->GetCurrentNode());
76 if (node
&& aFunctor(*node
, aClosure
)) {
77 aArrayOfNodes
.AppendElement(*node
);
82 DOMSubtreeIterator::DOMSubtreeIterator() { mIter
= &mSubtreeIter
; }
84 nsresult
DOMSubtreeIterator::Init(nsRange
& aRange
) {
85 return mIter
->Init(&aRange
);
88 /******************************************************************************
89 * mozilla::EditorElementStyle
90 *****************************************************************************/
92 bool EditorElementStyle::IsCSSSettable(const nsStaticAtom
& aTagName
) const {
93 return CSSEditUtils::IsCSSEditableStyle(aTagName
, *this);
96 bool EditorElementStyle::IsCSSSettable(const Element
& aElement
) const {
97 return CSSEditUtils::IsCSSEditableStyle(aElement
, *this);
100 bool EditorElementStyle::IsCSSRemovable(const nsStaticAtom
& aTagName
) const {
101 // <font size> cannot be applied with CSS font-size for now, but it should be
103 return EditorElementStyle::IsCSSSettable(aTagName
) ||
104 (IsInlineStyle() && AsInlineStyle().IsStyleOfFontSize());
107 bool EditorElementStyle::IsCSSRemovable(const Element
& aElement
) const {
108 // <font size> cannot be applied with CSS font-size for now, but it should be
110 return EditorElementStyle::IsCSSSettable(aElement
) ||
111 (IsInlineStyle() && AsInlineStyle().IsStyleOfFontSize());
114 /******************************************************************************
115 * mozilla::EditorInlineStyle
116 *****************************************************************************/
118 PendingStyleCache
EditorInlineStyle::ToPendingStyleCache(
119 nsAString
&& aValue
) const {
120 return PendingStyleCache(*mHTMLProperty
,
121 mAttribute
? mAttribute
->AsStatic() : nullptr,
125 bool EditorInlineStyle::IsRepresentedBy(const nsIContent
& aContent
) const {
126 MOZ_ASSERT(!IsStyleToClearAllInlineStyles());
128 if (!aContent
.IsHTMLElement()) {
131 const Element
& element
= *aContent
.AsElement();
132 if (mHTMLProperty
== element
.NodeInfo()->NameAtom() ||
133 mHTMLProperty
== GetSimilarElementNameAtom()) {
134 // <a> cannot be nested. Therefore, if we're the style of <a>, we should
135 // treat existing it even if the attribute does not match.
136 if (mHTMLProperty
== nsGkAtoms::a
) {
139 return !mAttribute
|| element
.HasAttr(mAttribute
);
141 // Special case for linking or naming an <a> element.
142 if ((mHTMLProperty
== nsGkAtoms::href
&& HTMLEditUtils::IsLink(&element
)) ||
143 (mHTMLProperty
== nsGkAtoms::name
&&
144 HTMLEditUtils::IsNamedAnchor(&element
))) {
147 // If the style is font size, it's also represented by <big> or <small>.
148 if (mHTMLProperty
== nsGkAtoms::font
&& mAttribute
== nsGkAtoms::size
&&
149 aContent
.IsAnyOfHTMLElements(nsGkAtoms::big
, nsGkAtoms::small
)) {
155 Result
<bool, nsresult
> EditorInlineStyle::IsSpecifiedBy(
156 const HTMLEditor
& aHTMLEditor
, Element
& aElement
) const {
157 MOZ_ASSERT(!IsStyleToClearAllInlineStyles());
158 if (!IsCSSSettable(aElement
) && !IsCSSRemovable(aElement
)) {
161 // Special case in the CSS mode. We should treat <u>, <s>, <strike>, <ins>
162 // and <del> specifies text-decoration (bug 1802668).
163 if (aHTMLEditor
.IsCSSEnabled() &&
164 IsStyleOfTextDecoration(IgnoreSElement::No
) &&
165 aElement
.IsAnyOfHTMLElements(nsGkAtoms::u
, nsGkAtoms::s
,
166 nsGkAtoms::strike
, nsGkAtoms::ins
,
170 return CSSEditUtils::HaveSpecifiedCSSEquivalentStyles(aHTMLEditor
, aElement
,
174 } // namespace mozilla