📄 markup.cpp
字号:
/* * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "markup.h"#include "CDATASection.h"#include "CharacterNames.h"#include "Comment.h"#include "CSSComputedStyleDeclaration.h"#include "CSSPrimitiveValue.h"#include "CSSProperty.h"#include "CSSPropertyNames.h"#include "CSSRule.h"#include "CSSRuleList.h"#include "CSSStyleRule.h"#include "CSSStyleSelector.h"#include "CSSValue.h"#include "CSSValueKeywords.h"#include "DeleteButtonController.h"#include "Document.h"#include "DocumentFragment.h"#include "DocumentType.h"#include "Editor.h"#include "Frame.h"#include "HTMLElement.h"#include "HTMLNames.h"#include "InlineTextBox.h"#include "Logging.h"#include "ProcessingInstruction.h"#include "QualifiedName.h"#include "Range.h"#include "VisibleSelection.h"#include "TextIterator.h"#include "htmlediting.h"#include "visible_units.h"#include <wtf/StdLibExtras.h>using namespace std;namespace WebCore {using namespace HTMLNames;static inline bool shouldSelfClose(const Node *node);class AttributeChange {public: AttributeChange() : m_name(nullAtom, nullAtom, nullAtom) { } AttributeChange(PassRefPtr<Element> element, const QualifiedName& name, const String& value) : m_element(element), m_name(name), m_value(value) { } void apply() { m_element->setAttribute(m_name, m_value); }private: RefPtr<Element> m_element; QualifiedName m_name; String m_value;};static void appendAttributeValue(Vector<UChar>& result, const String& attr, bool escapeNBSP){ const UChar* uchars = attr.characters(); unsigned len = attr.length(); unsigned lastCopiedFrom = 0; DEFINE_STATIC_LOCAL(const String, ampEntity, ("&")); DEFINE_STATIC_LOCAL(const String, gtEntity, (">")); DEFINE_STATIC_LOCAL(const String, ltEntity, ("<")); DEFINE_STATIC_LOCAL(const String, quotEntity, (""")); DEFINE_STATIC_LOCAL(const String, nbspEntity, (" ")); for (unsigned i = 0; i < len; ++i) { UChar c = uchars[i]; switch (c) { case '&': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, ampEntity); lastCopiedFrom = i + 1; break; case '<': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, ltEntity); lastCopiedFrom = i + 1; break; case '>': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, gtEntity); lastCopiedFrom = i + 1; break; case '"': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, quotEntity); lastCopiedFrom = i + 1; break; case noBreakSpace: if (escapeNBSP) { result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, nbspEntity); lastCopiedFrom = i + 1; } break; } } result.append(uchars + lastCopiedFrom, len - lastCopiedFrom);}static void appendEscapedContent(Vector<UChar>& result, pair<const UChar*, size_t> range, bool escapeNBSP){ const UChar* uchars = range.first; unsigned len = range.second; unsigned lastCopiedFrom = 0; DEFINE_STATIC_LOCAL(const String, ampEntity, ("&")); DEFINE_STATIC_LOCAL(const String, gtEntity, (">")); DEFINE_STATIC_LOCAL(const String, ltEntity, ("<")); DEFINE_STATIC_LOCAL(const String, nbspEntity, (" ")); for (unsigned i = 0; i < len; ++i) { UChar c = uchars[i]; switch (c) { case '&': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, ampEntity); lastCopiedFrom = i + 1; break; case '<': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, ltEntity); lastCopiedFrom = i + 1; break; case '>': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, gtEntity); lastCopiedFrom = i + 1; break; case noBreakSpace: if (escapeNBSP) { result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); append(result, nbspEntity); lastCopiedFrom = i + 1; } break; } } result.append(uchars + lastCopiedFrom, len - lastCopiedFrom);} static String escapeContentText(const String& in, bool escapeNBSP){ Vector<UChar> buffer; appendEscapedContent(buffer, make_pair(in.characters(), in.length()), escapeNBSP); return String::adopt(buffer);} static void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString){ UChar quoteChar = '\"'; String strippedURLString = urlString.stripWhiteSpace(); if (protocolIs(strippedURLString, "javascript")) { // minimal escaping for javascript urls if (strippedURLString.contains('"')) { if (strippedURLString.contains('\'')) strippedURLString.replace('\"', """); else quoteChar = '\''; } result.append(quoteChar); append(result, strippedURLString); result.append(quoteChar); return; } // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML. result.append(quoteChar); appendAttributeValue(result, urlString, false); result.append(quoteChar); } static String stringValueForRange(const Node* node, const Range* range){ if (!range) return node->nodeValue(); String str = node->nodeValue(); ExceptionCode ec; if (node == range->endContainer(ec)) str.truncate(range->endOffset(ec)); if (node == range->startContainer(ec)) str.remove(0, range->startOffset(ec)); return str;}static inline pair<const UChar*, size_t> ucharRange(const Node *node, const Range *range){ String str = node->nodeValue(); const UChar* characters = str.characters(); size_t length = str.length(); if (range) { ExceptionCode ec; if (node == range->endContainer(ec)) length = range->endOffset(ec); if (node == range->startContainer(ec)) { size_t start = range->startOffset(ec); characters += start; length -= start; } } return make_pair(characters, length);} static inline void appendUCharRange(Vector<UChar>& result, const pair<const UChar*, size_t> range){ result.append(range.first, range.second);} static String renderedText(const Node* node, const Range* range){ if (!node->isTextNode()) return String(); ExceptionCode ec; const Text* textNode = static_cast<const Text*>(node); unsigned startOffset = 0; unsigned endOffset = textNode->length(); if (range && node == range->startContainer(ec)) startOffset = range->startOffset(ec); if (range && node == range->endContainer(ec)) endOffset = range->endOffset(ec); Position start(const_cast<Node*>(node), startOffset); Position end(const_cast<Node*>(node), endOffset); return plainText(Range::create(node->document(), start, end).get());}static PassRefPtr<CSSMutableStyleDeclaration> styleFromMatchedRulesForElement(Element* element, bool authorOnly = true){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); RefPtr<CSSRuleList> matchedRules = element->document()->styleSelector()->styleRulesForElement(element, authorOnly); if (matchedRules) { for (unsigned i = 0; i < matchedRules->length(); i++) { if (matchedRules->item(i)->type() == CSSRule::STYLE_RULE) { RefPtr<CSSMutableStyleDeclaration> s = static_cast<CSSStyleRule*>(matchedRules->item(i))->style(); style->merge(s.get(), true); } } } return style.release();}static void removeEnclosingMailBlockquoteStyle(CSSMutableStyleDeclaration* style, Node* node){ Node* blockquote = nearestMailBlockquote(node); if (!blockquote || !blockquote->parentNode()) return; RefPtr<CSSMutableStyleDeclaration> parentStyle = Position(blockquote->parentNode(), 0).computedStyle()->copyInheritableProperties(); RefPtr<CSSMutableStyleDeclaration> blockquoteStyle = Position(blockquote, 0).computedStyle()->copyInheritableProperties(); parentStyle->diff(blockquoteStyle.get()); blockquoteStyle->diff(style);}static void removeDefaultStyles(CSSMutableStyleDeclaration* style, Document* document){ if (!document || !document->documentElement()) return; RefPtr<CSSMutableStyleDeclaration> documentStyle = computedStyle(document->documentElement())->copyInheritableProperties(); documentStyle->diff(style);}static bool shouldAddNamespaceElem(const Element* elem){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -