void MarkupFormatter::appendOpenTag(StringBuilder& result, const Element& element, Namespaces* namespaces) { result.append('<'); result.append(element.tagQName().toString()); if (!serializeAsHTMLDocument(element) && namespaces && shouldAddNamespaceElement(element, *namespaces)) appendNamespace(result, element.prefix(), element.namespaceURI(), *namespaces); }
void MarkupAccumulator::appendOpenTag(StringBuilder& result, const Element& element, Namespaces* namespaces) { result.append('<'); result.append(nodeNamePreservingCase(element)); if (!serializeAsHTMLDocument(element) && namespaces && shouldAddNamespaceElement(element, *namespaces)) appendNamespace(result, element.prefix(), element.namespaceURI(), *namespaces); }
void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, EChildrenOnly childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNamesToSkip) { if (tagNamesToSkip) { for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { if (targetNode.hasTagName(tagNamesToSkip->at(i))) return; } } Namespaces namespaceHash; if (namespaces) namespaceHash = *namespaces; if (!childrenOnly) appendStartTag(targetNode, &namespaceHash); if (!(serializeAsHTMLDocument(targetNode) && elementCannotHaveEndTag(targetNode))) { Node* current = isHTMLTemplateElement(targetNode) ? toHTMLTemplateElement(targetNode).content()->firstChild() : targetNode.firstChild(); for ( ; current; current = current->nextSibling()) serializeNodesWithNamespaces(*current, IncludeNode, &namespaceHash, tagNamesToSkip); } if (!childrenOnly) appendEndTag(targetNode); }
void MarkupFormatter::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces) { bool documentIsHTML = serializeAsHTMLDocument(element); QualifiedName prefixedName = attribute.name(); if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { result.append(' '); result.append(attribute.name().localName()); } else { if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { if (!attribute.prefix() && attribute.localName() != xmlnsAtom) prefixedName.setPrefix(xmlnsAtom); if (namespaces) { // Account for the namespace attribute we're about to append. const AtomicString& lookupKey = (!attribute.prefix()) ? emptyAtom : attribute.localName(); namespaces->set(lookupKey, attribute.value()); } } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xmlAtom); } else { if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xlinkAtom); } if (namespaces && shouldAddNamespaceAttribute(attribute, element)) { if (!prefixedName.prefix()) { // This behavior is in process of being standardized. See crbug.com/248044 and https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208 String prefixPrefix("ns", 2); for (unsigned i = attribute.namespaceURI().impl()->existingHash(); ; ++i) { AtomicString newPrefix(String(prefixPrefix + String::number(i))); AtomicString foundURI = namespaces->get(newPrefix); if (foundURI == attribute.namespaceURI() || foundURI == nullAtom) { // We already generated a prefix for this namespace. prefixedName.setPrefix(newPrefix); break; } } } ASSERT(prefixedName.prefix()); appendNamespace(result, prefixedName.prefix(), attribute.namespaceURI(), *namespaces); } } result.append(' '); result.append(prefixedName.toString()); } result.append('='); if (element.isURLAttribute(attribute)) { appendQuotedURLAttributeValue(result, element, attribute); } else { result.append('"'); appendAttributeValue(result, attribute.value(), documentIsHTML); result.append('"'); } }
// Rules of self-closure // 1. No elements in HTML documents use the self-closing syntax. // 2. Elements w/ children never self-close because they use a separate end tag. // 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag. // 4. Other elements self-close. bool MarkupAccumulator::shouldSelfClose(const Node& node) { if (serializeAsHTMLDocument(node)) return false; if (node.hasChildren()) return false; if (node.isHTMLElement() && !elementCannotHaveEndTag(node)) return false; return true; }
// Rules of self-closure // 1. No elements in HTML documents use the self-closing syntax. // 2. Elements w/ children never self-close because they use a separate end tag. // 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag. // 4. Other elements self-close. bool MarkupFormatter::shouldSelfClose(const Element& element) const { if (serializeAsHTMLDocument(element)) return false; if (element.hasChildren()) return false; if (element.isHTMLElement() && !elementCannotHaveEndTag(element)) return false; return true; }
EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const { if (!serializeAsHTMLDocument(text)) return EntityMaskInPCDATA; const QualifiedName* parentName = 0; if (text.parentElement()) parentName = &(text.parentElement())->tagQName(); if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag)) return EntityMaskInCDATA; return EntityMaskInHTMLPCDATA; }
String MarkupAccumulator::serializeNodes(Node& targetNode, EChildrenOnly childrenOnly, Vector<QualifiedName>* tagNamesToSkip) { Namespaces* namespaces = 0; Namespaces namespaceHash; if (!serializeAsHTMLDocument(targetNode)) { // Add pre-bound namespaces for XML fragments. namespaceHash.set(xmlAtom, XMLNames::xmlNamespaceURI); namespaces = &namespaceHash; } serializeNodesWithNamespaces(targetNode, childrenOnly, namespaces, tagNamesToSkip); return m_markup.toString(); }
EntityMask MarkupFormatter::entityMaskForText(const Text& text) const { if (!serializeAsHTMLDocument(text)) return EntityMaskInPCDATA; // TODO(hajimehoshi): We need to switch EditingStrategy. const QualifiedName* parentName = nullptr; if (text.parentElement()) parentName = &(text.parentElement())->tagQName(); if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag)) return EntityMaskInCDATA; return EntityMaskInHTMLPCDATA; }
void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces) { bool documentIsHTML = serializeAsHTMLDocument(element); result.append(' '); QualifiedName prefixedName = attribute.name(); if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { result.append(attribute.name().localName()); } else { if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xlinkAtom); } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xmlAtom); } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix()) prefixedName.setPrefix(xmlnsAtom); } result.append(prefixedName.toString()); } result.append('='); if (element.isURLAttribute(attribute)) { appendQuotedURLAttributeValue(result, element, attribute); } else { result.append('"'); appendAttributeValue(result, attribute.value(), documentIsHTML); result.append('"'); } if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) appendNamespace(result, prefixedName.prefix(), prefixedName.namespaceURI(), *namespaces); }