From: <ad...@us...> - 2010-11-15 11:08:14
|
Revision: 1190 http://jtidy.svn.sourceforge.net/jtidy/?rev=1190&view=rev Author: aditsu Date: 2010-11-15 10:02:58 +0000 (Mon, 15 Nov 2010) Log Message: ----------- fixed test 1426419 - handling of inline elements closed in the wrong order Modified Paths: -------------- branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/Lexer.java branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/ParserImpl.java Modified: branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/Lexer.java =================================================================== --- branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/Lexer.java 2010-11-15 09:49:08 UTC (rev 1189) +++ branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/Lexer.java 2010-11-15 10:02:58 UTC (rev 1190) @@ -1595,6 +1595,7 @@ } // at start of block elements, unclosed inline + // elements are inserted into the token stream if (this.insert != -1 || this.inode != null) { return insertedToken(); @@ -3835,4 +3836,64 @@ } return false; } + + /* + We have two CM_INLINE elements pushed ... the first is closing, + but, like the browser, the second should be retained ... + Like <b>bold <i>bold and italics</b> italics only</i> + This function switches the tag positions on the stack, + returning true if both were found in the expected order. + */ + protected boolean switchInline(final Node element, final Node node) { + if (element != null && element.tag != null + && node != null && node.tag != null + && isPushed(element) && isPushed(node) + && istack.size() - istackbase >= 2) { + /* we have a chance of succeeding ... */ + for (int i = (istack.size() - istackbase - 1); i >= 0; --i) { + if (istack.get(i).tag == element.tag) { + /* found the element tag - phew */ + int istack1 = i; + int istack2 = -1; + --i; /* back one more, and continue */ + for ( ; i >= 0; --i) { + if (istack.get(i).tag == node.tag) { + /* found the element tag - phew */ + istack2 = i; + break; + } + } + if (istack2 >= 0) { + /* perform the swap */ + IStack tmp = istack.get(istack2); + istack.set(istack2, istack.get(istack1)); + istack.set(istack1, tmp); + return true; + } + } + } + } + return false; + } + + /* + We want to push a specific a specific element on the stack, + but it may not be the last element, which InlineDup() + would handle. Return true if found and inserted. + */ + protected boolean inlineDup1(final Node node, final Node element) { + int n; + if (element != null && element.tag != null + && ((n = istack.size() - istackbase) > 0)) { + for (int i = n - 1; i >=0; --i ) { + if (istack.get(i).tag == element.tag) { + /* found our element tag - insert it */ + insert = i; + inode = node; + return true; + } + } + } + return false; + } } Modified: branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/ParserImpl.java =================================================================== --- branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/ParserImpl.java 2010-11-15 09:49:08 UTC (rev 1189) +++ branches/CodeUpdateAndJava5/src/main/java/org/w3c/tidy/ParserImpl.java 2010-11-15 10:02:58 UTC (rev 1190) @@ -1286,11 +1286,27 @@ continue; } } - else if ((node.tag.model & Dict.CM_INLINE) != 0 - && !node.is(TagId.A) - && !((node.tag.model & Dict.CM_OBJECT) != 0) - && (element.tag.model & Dict.CM_INLINE) != 0) - { + else if (node.hasCM(Dict.CM_INLINE) && !node.is(TagId.A) + && !node.hasCM(Dict.CM_OBJECT) && element.hasCM(Dict.CM_INLINE)) { + /* retain an earlier inline element. + This is implemented by setting the lexer into a mode + where it gets tokens from the inline stack rather than + from the input stream. Check if the scenerio fits. */ + if (!element.is(TagId.A) && node.tag != element.tag + && lexer.isPushed(node) && lexer.isPushed(element)) { + /* we have something like + <b>bold <i>bold and italic</b> italics</i> */ + if (lexer.switchInline(element, node)) { + lexer.report.warning(lexer, element, node, ErrorCode.NON_MATCHING_ENDTAG); + lexer.ungetToken(); /* put this back */ + lexer.inlineDup1(null, element); /* dupe the <i>, after </b> */ + if ((mode & Lexer.PREFORMATTED) == 0) { + Node.trimSpaces(lexer, element); + } + return; /* close <i>, but will re-open it, after </b> */ + } + } + // allow any inline end tag to end current element lexer.popInline(element); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |