Search in sources :

Example 1 with Element

use of org.loboevolution.html.node.Element in project LoboEvolution by LoboEvolution.

the class HtmlPanel method scrollToElementImpl.

private void scrollToElementImpl(String nameOrId) {
    final NodeImpl node = this.rootNode;
    if (node instanceof HTMLDocumentImpl) {
        final HTMLDocumentImpl doc = (HTMLDocumentImpl) node;
        final Element element = doc.getElementById(nameOrId);
        if (element != null) {
            this.scrollTo(element);
        }
    }
}
Also used : HTMLDocumentImpl(org.loboevolution.html.dom.domimpl.HTMLDocumentImpl) NodeImpl(org.loboevolution.html.dom.nodeimpl.NodeImpl) Element(org.loboevolution.html.node.Element)

Example 2 with Element

use of org.loboevolution.html.node.Element in project LoboEvolution by LoboEvolution.

the class DOMParserImpl method parseFromString.

/**
 * {@inheritDoc}
 */
@Override
public Document parseFromString(String html, String type) {
    Element element = document.createElement("DIV");
    element.setInnerHTML(html);
    if (!"text/html".equals(type) && !"text/xml".equals(type) && !"application/xml".equals(type) && !"application/xhtml+xml".equals(type) && !"image/svg+xml".equals(type)) {
        throw Context.reportRuntimeError("Invalid 'type' parameter: " + type);
    }
    XMLDocument document = new XMLDocument();
    document.loadXML(element.getInnerHTML());
    return document;
}
Also used : Element(org.loboevolution.html.node.Element) XMLDocument(org.loboevolution.html.js.xml.XMLDocument)

Example 3 with Element

use of org.loboevolution.html.node.Element in project LoboEvolution by LoboEvolution.

the class HtmlParser method parseToken.

/**
 * Parses text followed by one element.
 *
 * @param parent
 * @param reader
 * @param stopTags    If tags in this set are encountered, the method throws
 *                    StopException.
 * @return
 * @throws IOException
 * @throws StopException
 * @throws SAXException
 */
private int parseToken(final Node parent, final LineNumberReader reader, final Set<HTMLTag> stopTags, final LinkedList<String> ancestors) throws IOException, StopException, SAXException {
    final Document doc = this.document;
    final HTMLDocumentImpl htmlDoc = (HTMLDocumentImpl) doc;
    final StringBuilder textSb = this.readUpToTagBegin(reader);
    if (textSb == null) {
        return TOKEN_EOD;
    }
    if (textSb.length() != 0) {
        // int textLine = reader.getLineNumber();
        final StringBuilder decText = entityDecode(textSb);
        final Node textNode = doc.createTextNode(decText.toString());
        try {
            safeAppendChild(parent, textNode);
        } catch (final DOMException de) {
            if ((parent.getNodeType() != NodeType.DOCUMENT_NODE) || (de.getCode() != DOMException.HIERARCHY_REQUEST_ERR)) {
                logger.log(Level.WARNING, "parseToken(): Unable to append child to " + parent + ".", de);
            }
        }
    }
    if (this.justReadTagBegin) {
        String tag = this.readTag(parent, reader);
        if (tag == null) {
            return TOKEN_EOD;
        }
        String normalTag = tag.toUpperCase();
        try {
            if (tag.startsWith("!")) {
                if ("!--".equals(tag)) {
                    final StringBuilder comment = this.passEndOfComment(reader);
                    final StringBuilder decText = entityDecode(comment);
                    safeAppendChild(parent, doc.createComment(decText.toString()));
                    return TOKEN_COMMENT;
                } else if ("!DOCTYPE".equals(tag)) {
                    final String doctypeStr = this.parseEndOfTag(reader);
                    String qName = null;
                    String publicId = null;
                    String systemId = null;
                    if (doctypeStr.contains("PUBLIC")) {
                        final Matcher doctypeMatcher = doctypePattern.matcher(doctypeStr);
                        if (doctypeMatcher.matches()) {
                            qName = doctypeMatcher.group(1);
                            publicId = doctypeMatcher.group(2);
                            systemId = doctypeMatcher.group(3);
                        }
                    } else {
                        qName = doctypeStr.replace(">", "");
                    }
                    final DocumentTypeImpl doctype = new DocumentTypeImpl(qName, publicId, systemId);
                    htmlDoc.setDoctype(doctype);
                    needRoot = false;
                    return TOKEN_BAD;
                } else {
                    passEndOfTag(reader);
                    return TOKEN_BAD;
                }
            } else if (tag.startsWith("/")) {
                tag = tag.substring(1);
                normalTag = normalTag.substring(1);
                this.passEndOfTag(reader);
                return TOKEN_END_ELEMENT;
            } else if (tag.startsWith("?")) {
                tag = tag.substring(1);
                final StringBuilder data = readProcessingInstruction(reader);
                safeAppendChild(parent, doc.createProcessingInstruction(tag, data.toString()));
                return TOKEN_FULL_ELEMENT;
            } else {
                final int localIndex = normalTag.indexOf(':');
                final boolean tagHasPrefix = localIndex > 0;
                final String localName = tagHasPrefix ? normalTag.substring(localIndex + 1) : normalTag;
                Element element = doc.createElement(localName);
                element.setUserData(MODIFYING_KEY, Boolean.TRUE, null);
                try {
                    if (!this.justReadTagEnd) {
                        while (this.readAttribute(reader, element)) {
                        // EMPTY LOOP
                        }
                    }
                    if (stopTags != null && stopTags.contains(HTMLTag.get(normalTag))) {
                        // After MODIFYING_KEY is set.
                        throw new StopException(element);
                    }
                    // Add element to parent before children are added.
                    // This is necessary for incremental rendering.
                    safeAppendChild(parent, element);
                    if (!this.justReadEmptyElement) {
                        ElementInfo einfo = HTMLEntities.ELEMENT_INFOS.get(HTMLTag.get(localName.toUpperCase()));
                        int endTagType = einfo == null ? ElementInfo.END_ELEMENT_REQUIRED : einfo.getEndElementType();
                        if (endTagType != ElementInfo.END_ELEMENT_FORBIDDEN) {
                            boolean childrenOk = einfo == null || einfo.isChildElementOk();
                            Set<HTMLTag> newStopSet = einfo == null ? null : einfo.getStopTags();
                            if (newStopSet == null) {
                                if (endTagType == ElementInfo.END_ELEMENT_OPTIONAL) {
                                    newStopSet = Collections.singleton(HTMLTag.get(normalTag));
                                }
                            }
                            if (stopTags != null) {
                                if (newStopSet != null) {
                                    final Set<HTMLTag> newStopSet2 = new HashSet<>();
                                    newStopSet2.addAll(stopTags);
                                    newStopSet2.addAll(newStopSet);
                                    newStopSet = newStopSet2;
                                } else {
                                    newStopSet = endTagType == ElementInfo.END_ELEMENT_REQUIRED ? null : stopTags;
                                }
                            }
                            ancestors.addFirst(normalTag);
                            try {
                                for (; ; ) {
                                    try {
                                        int token;
                                        if ((einfo != null) && einfo.isNoScriptElement()) {
                                            final UserAgentContext ucontext = this.ucontext;
                                            if ((ucontext == null) || ucontext.isScriptingEnabled()) {
                                                token = this.parseForEndTag(parent, reader, tag, false, shouldDecodeEntities(einfo));
                                            } else {
                                                token = this.parseToken(element, reader, newStopSet, ancestors);
                                            }
                                        } else {
                                            token = childrenOk ? this.parseToken(element, reader, newStopSet, ancestors) : this.parseForEndTag(element, reader, tag, true, shouldDecodeEntities(einfo));
                                        }
                                        if (token == TOKEN_END_ELEMENT) {
                                            final String normalLastTag = this.normalLastTag;
                                            if (normalTag.equalsIgnoreCase(normalLastTag)) {
                                                return TOKEN_FULL_ELEMENT;
                                            } else {
                                                final ElementInfo closeTagInfo = HTMLEntities.ELEMENT_INFOS.get(HTMLTag.get(normalLastTag.toUpperCase()));
                                                if ((closeTagInfo == null) || (closeTagInfo.getEndElementType() != ElementInfo.END_ELEMENT_FORBIDDEN)) {
                                                    // TODO: Rather inefficient algorithm, but it's
                                                    // probably executed infrequently?
                                                    final Iterator<String> i = ancestors.iterator();
                                                    if (i.hasNext()) {
                                                        i.next();
                                                        while (i.hasNext()) {
                                                            final String normalAncestorTag = i.next();
                                                            if (normalLastTag.equals(normalAncestorTag)) {
                                                                normalTag = normalLastTag;
                                                                return TOKEN_END_ELEMENT;
                                                            }
                                                        }
                                                    }
                                                }
                                            // TODO: Working here
                                            }
                                        } else if (token == TOKEN_EOD) {
                                            return TOKEN_EOD;
                                        }
                                    } catch (final StopException se) {
                                        // newElement does not have a parent.
                                        final Element newElement = se.getElement();
                                        tag = newElement.getTagName();
                                        normalTag = tag.toUpperCase();
                                        if (stopTags != null && stopTags.contains(HTMLTag.get(normalTag))) {
                                            throw se;
                                        }
                                        einfo = HTMLEntities.ELEMENT_INFOS.get(HTMLTag.get(normalTag.toUpperCase()));
                                        endTagType = einfo == null ? ElementInfo.END_ELEMENT_REQUIRED : einfo.getEndElementType();
                                        childrenOk = einfo == null || einfo.isChildElementOk();
                                        newStopSet = einfo == null ? null : einfo.getStopTags();
                                        if (newStopSet == null) {
                                            if (endTagType == ElementInfo.END_ELEMENT_OPTIONAL) {
                                                newStopSet = Collections.singleton(HTMLTag.get(normalTag));
                                            }
                                        }
                                        if (stopTags != null && newStopSet != null) {
                                            final Set<HTMLTag> newStopSet2 = new HashSet<>();
                                            newStopSet2.addAll(stopTags);
                                            newStopSet2.addAll(newStopSet);
                                            newStopSet = newStopSet2;
                                        }
                                        ancestors.removeFirst();
                                        ancestors.addFirst(normalTag);
                                        // Switch element
                                        element.setUserData(MODIFYING_KEY, Boolean.FALSE, null);
                                        // newElement should have been suspended.
                                        element = newElement;
                                        // Add to parent
                                        safeAppendChild(parent, element);
                                        if (this.justReadEmptyElement) {
                                            return TOKEN_BEGIN_ELEMENT;
                                        }
                                    }
                                }
                            } finally {
                                ancestors.removeFirst();
                            }
                        }
                    }
                    return TOKEN_BEGIN_ELEMENT;
                } finally {
                    // This can inform elements to continue with notifications.
                    // It can also cause Javascript to be loaded / processed.
                    // Update: Elements now use Document.addJob() to delay processing
                    element.setUserData(MODIFYING_KEY, Boolean.FALSE, null);
                }
            }
        } finally {
            this.normalLastTag = normalTag;
        }
    } else {
        this.normalLastTag = null;
        return TOKEN_TEXT;
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) UserAgentContext(org.loboevolution.http.UserAgentContext) Matcher(java.util.regex.Matcher) ElementInfo(org.loboevolution.info.ElementInfo) Node(org.loboevolution.html.node.Node) Element(org.loboevolution.html.node.Element) DocumentTypeImpl(org.loboevolution.html.dom.domimpl.DocumentTypeImpl) Document(org.loboevolution.html.node.Document) HTMLDocumentImpl(org.loboevolution.html.dom.domimpl.HTMLDocumentImpl) DOMException(com.gargoylesoftware.css.dom.DOMException) HTMLTag(org.loboevolution.html.HTMLTag) HashSet(java.util.HashSet)

Example 4 with Element

use of org.loboevolution.html.node.Element in project LoboEvolution by LoboEvolution.

the class HtmlParser method safeAppendChild.

private void safeAppendChild(final Node parent, final Node child) {
    Node newParent = parent;
    if (needRoot) {
        final String nodeName = child.getNodeName();
        if ("HTML".equalsIgnoreCase(nodeName)) {
            lastRootElement = child;
        } else if ((child instanceof Element) && (depthAtMost(parent, 1)) && (!hasAncestorTag(parent, "HTML"))) {
            ensureRootElement(parent);
            newParent = lastRootElement;
        }
    }
    ensureBodyAppendChild(newParent, child);
}
Also used : Node(org.loboevolution.html.node.Node) Element(org.loboevolution.html.node.Element)

Example 5 with Element

use of org.loboevolution.html.node.Element in project LoboEvolution by LoboEvolution.

the class DOMImplementationTest method testCreateDocument3.

@Test
public void testCreateDocument3() {
    DocumentType doctype = domImpl.createDocumentType("html", null, null);
    assertNull(doctype.getNextSibling());
    assertNull(doctype.getPreviousSibling());
    Document document = domImpl.createDocument(null, "html", doctype);
    assertEquals("CSS1Compat", document.getCompatMode());
    Element docelm = document.getDocumentElement();
    assertNotNull(docelm);
    assertSame(docelm, doctype.getNextSibling());
    assertNull(doctype.getPreviousSibling());
    assertSame(doctype, docelm.getPreviousSibling());
    assertNull(docelm.getNextSibling());
    assertSame(document, docelm.getParentNode());
    assertSame(document, docelm.getOwnerDocument());
    assertSame(document, doctype.getOwnerDocument());
}
Also used : Element(org.loboevolution.html.node.Element) DocumentType(org.loboevolution.html.node.DocumentType) Document(org.loboevolution.html.node.Document) Test(org.junit.Test) LoboUnitTest(org.loboevolution.driver.LoboUnitTest)

Aggregations

Element (org.loboevolution.html.node.Element)10 Node (org.loboevolution.html.node.Node)5 Document (org.loboevolution.html.node.Document)4 HTMLDocumentImpl (org.loboevolution.html.dom.domimpl.HTMLDocumentImpl)2 NodeListImpl (org.loboevolution.html.dom.nodeimpl.NodeListImpl)2 DOMException (com.gargoylesoftware.css.dom.DOMException)1 Shape (java.awt.Shape)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 Matcher (java.util.regex.Matcher)1 Test (org.junit.Test)1 LoboUnitTest (org.loboevolution.driver.LoboUnitTest)1 HTMLTag (org.loboevolution.html.HTMLTag)1 DocumentTypeImpl (org.loboevolution.html.dom.domimpl.DocumentTypeImpl)1 NodeImpl (org.loboevolution.html.dom.nodeimpl.NodeImpl)1 XMLDocument (org.loboevolution.html.js.xml.XMLDocument)1 DocumentType (org.loboevolution.html.node.DocumentType)1 NamedNodeMap (org.loboevolution.html.node.NamedNodeMap)1 UserAgentContext (org.loboevolution.http.UserAgentContext)1 ElementInfo (org.loboevolution.info.ElementInfo)1