diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
commit | 40736c5763bf61337c8c14e16d8587db021a87d4 (patch) | |
tree | b17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/WebCore/html/HTMLViewSourceDocument.cpp | |
download | qtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz |
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/WebCore/html/HTMLViewSourceDocument.cpp')
-rw-r--r-- | Source/WebCore/html/HTMLViewSourceDocument.cpp | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/Source/WebCore/html/HTMLViewSourceDocument.cpp b/Source/WebCore/html/HTMLViewSourceDocument.cpp new file mode 100644 index 000000000..9317d2d1d --- /dev/null +++ b/Source/WebCore/html/HTMLViewSourceDocument.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2006, 2008, 2009, 2010 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, + * 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 "HTMLViewSourceDocument.h" + +#include "Attribute.h" +#include "DOMImplementation.h" +#include "HTMLAnchorElement.h" +#include "HTMLBRElement.h" +#include "HTMLBaseElement.h" +#include "HTMLBodyElement.h" +#include "HTMLDivElement.h" +#include "HTMLHtmlElement.h" +#include "HTMLNames.h" +#include "HTMLTableCellElement.h" +#include "HTMLTableElement.h" +#include "HTMLTableRowElement.h" +#include "HTMLTableSectionElement.h" +#include "HTMLToken.h" +#include "HTMLViewSourceParser.h" +#include "SegmentedString.h" +#include "Text.h" +#include "TextViewSourceParser.h" + +namespace WebCore { + +using namespace HTMLNames; + +HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const KURL& url, const String& mimeType) + : HTMLDocument(frame, url) + , m_type(mimeType) +{ + setUsesBeforeAfterRules(true); + setIsViewSource(true); + + setCompatibilityMode(QuirksMode); + lockCompatibilityMode(); +} + +PassRefPtr<DocumentParser> HTMLViewSourceDocument::createParser() +{ + if (m_type == "text/html" || m_type == "application/xhtml+xml" || m_type == "image/svg+xml" || DOMImplementation::isXMLMIMEType(m_type)) + return HTMLViewSourceParser::create(this); + + return TextViewSourceParser::create(this); +} + +void HTMLViewSourceDocument::createContainingTable() +{ + RefPtr<HTMLHtmlElement> html = HTMLHtmlElement::create(this); + parserAddChild(html); + html->attach(); + RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(this); + html->parserAddChild(body); + body->attach(); + + // Create a line gutter div that can be used to make sure the gutter extends down the height of the whole + // document. + RefPtr<HTMLDivElement> div = HTMLDivElement::create(this); + div->setAttribute(classAttr, "webkit-line-gutter-backdrop"); + body->parserAddChild(div); + div->attach(); + + RefPtr<HTMLTableElement> table = HTMLTableElement::create(this); + body->parserAddChild(table); + table->attach(); + m_tbody = HTMLTableSectionElement::create(tbodyTag, this); + table->parserAddChild(m_tbody); + m_tbody->attach(); + m_current = m_tbody; +} + +void HTMLViewSourceDocument::addSource(const String& source, HTMLToken& token) +{ + if (!m_current) + createContainingTable(); + + switch (token.type()) { + case HTMLTokenTypes::Uninitialized: + ASSERT_NOT_REACHED(); + break; + case HTMLTokenTypes::DOCTYPE: + processDoctypeToken(source, token); + break; + case HTMLTokenTypes::EndOfFile: + if (!m_tbody->hasChildNodes()) + addLine(String()); + break; + case HTMLTokenTypes::StartTag: + case HTMLTokenTypes::EndTag: + processTagToken(source, token); + break; + case HTMLTokenTypes::Comment: + processCommentToken(source, token); + break; + case HTMLTokenTypes::Character: + processCharacterToken(source, token); + break; + } +} + +void HTMLViewSourceDocument::processDoctypeToken(const String& source, HTMLToken&) +{ + if (!m_current) + createContainingTable(); + m_current = addSpanWithClassName("webkit-html-doctype"); + addText(source, "webkit-html-doctype"); + m_current = m_td; +} + +void HTMLViewSourceDocument::processTagToken(const String& source, HTMLToken& token) +{ + m_current = addSpanWithClassName("webkit-html-tag"); + + AtomicString tagName(token.name().data(), token.name().size()); + + unsigned index = 0; + HTMLToken::AttributeList::const_iterator iter = token.attributes().begin(); + while (index < source.length()) { + if (iter == token.attributes().end()) { + // We want to show the remaining characters in the token. + index = addRange(source, index, source.length(), ""); + ASSERT(index == source.length()); + break; + } + + AtomicString name(iter->m_name.data(), iter->m_name.size()); + String value(iter->m_value.data(), iter->m_value.size()); + + index = addRange(source, index, iter->m_nameRange.m_start - token.startIndex(), ""); + index = addRange(source, index, iter->m_nameRange.m_end - token.startIndex(), "webkit-html-attribute-name"); + + if (tagName == baseTag && name == hrefAttr) + m_current = addBase(value); + + index = addRange(source, index, iter->m_valueRange.m_start - token.startIndex(), ""); + + bool isLink = name == srcAttr || name == hrefAttr; + index = addRange(source, index, iter->m_valueRange.m_end - token.startIndex(), "webkit-html-attribute-value", isLink, tagName == aTag); + + ++iter; + } + m_current = m_td; +} + +void HTMLViewSourceDocument::processCommentToken(const String& source, HTMLToken&) +{ + m_current = addSpanWithClassName("webkit-html-comment"); + addText(source, "webkit-html-comment"); + m_current = m_td; +} + +void HTMLViewSourceDocument::processCharacterToken(const String& source, HTMLToken&) +{ + addText(source, ""); +} + +PassRefPtr<Element> HTMLViewSourceDocument::addSpanWithClassName(const AtomicString& className) +{ + if (m_current == m_tbody) { + addLine(className); + return m_current; + } + + RefPtr<HTMLElement> span = HTMLElement::create(spanTag, this); + span->setAttribute(classAttr, className); + m_current->parserAddChild(span); + span->attach(); + return span.release(); +} + +void HTMLViewSourceDocument::addLine(const AtomicString& className) +{ + // Create a table row. + RefPtr<HTMLTableRowElement> trow = HTMLTableRowElement::create(this); + m_tbody->parserAddChild(trow); + trow->attach(); + + // Create a cell that will hold the line number (it is generated in the stylesheet using counters). + RefPtr<HTMLTableCellElement> td = HTMLTableCellElement::create(tdTag, this); + td->setAttribute(classAttr, "webkit-line-number"); + trow->parserAddChild(td); + td->attach(); + + // Create a second cell for the line contents + td = HTMLTableCellElement::create(tdTag, this); + td->setAttribute(classAttr, "webkit-line-content"); + trow->parserAddChild(td); + td->attach(); + m_current = m_td = td; + +#ifdef DEBUG_LINE_NUMBERS + RefPtr<Text> lineNumberText = Text::create(this, String::number(parser()->lineNumber() + 1) + " "); + td->addChild(lineNumberText); + lineNumberText->attach(); +#endif + + // Open up the needed spans. + if (!className.isEmpty()) { + if (className == "webkit-html-attribute-name" || className == "webkit-html-attribute-value") + m_current = addSpanWithClassName("webkit-html-tag"); + m_current = addSpanWithClassName(className); + } +} + +void HTMLViewSourceDocument::finishLine() +{ + if (!m_current->hasChildNodes()) { + RefPtr<HTMLBRElement> br = HTMLBRElement::create(this); + m_current->parserAddChild(br); + br->attach(); + } + m_current = m_tbody; +} + +void HTMLViewSourceDocument::addText(const String& text, const AtomicString& className) +{ + if (text.isEmpty()) + return; + + // Add in the content, splitting on newlines. + Vector<String> lines; + text.split('\n', true, lines); + unsigned size = lines.size(); + for (unsigned i = 0; i < size; i++) { + String substring = lines[i]; + if (m_current == m_tbody) + addLine(className); + if (substring.isEmpty()) { + if (i == size - 1) + break; + finishLine(); + continue; + } + RefPtr<Text> t = Text::create(this, substring); + m_current->parserAddChild(t); + t->attach(); + if (i < size - 1) + finishLine(); + } +} + +int HTMLViewSourceDocument::addRange(const String& source, int start, int end, const String& className, bool isLink, bool isAnchor) +{ + ASSERT(start <= end); + if (start == end) + return start; + + String text = source.substring(start, end - start); + if (!className.isEmpty()) { + if (isLink) + m_current = addLink(text, isAnchor); + else + m_current = addSpanWithClassName(className); + } + addText(text, className); + if (!className.isEmpty() && m_current != m_tbody) + m_current = static_cast<Element*>(m_current->parentNode()); + return end; +} + +PassRefPtr<Element> HTMLViewSourceDocument::addBase(const AtomicString& href) +{ + RefPtr<HTMLBaseElement> base = HTMLBaseElement::create(baseTag, this); + base->setAttribute(hrefAttr, href); + m_current->parserAddChild(base); + base->attach(); + return base.release(); +} + +PassRefPtr<Element> HTMLViewSourceDocument::addLink(const AtomicString& url, bool isAnchor) +{ + if (m_current == m_tbody) + addLine("webkit-html-tag"); + + // Now create a link for the attribute value instead of a span. + RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::create(this); + const char* classValue; + if (isAnchor) + classValue = "webkit-html-attribute-value webkit-html-external-link"; + else + classValue = "webkit-html-attribute-value webkit-html-resource-link"; + anchor->setAttribute(classAttr, classValue); + anchor->setAttribute(targetAttr, "_blank"); + anchor->setAttribute(hrefAttr, url); + m_current->parserAddChild(anchor); + anchor->attach(); + return anchor.release(); +} + +} |