Fix for overlapping inline elements
"Geoff Air" <[email protected]> Sun, 08 Jan 2006 07:11:04 +1100
| Newsgroups | gmane.comp.web.html-tidy.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Charles and Arnaud,
Have written a 'patch' to fix the browser view
problem with -
<b>Bold <i>Bold-Italics</b> Italics only</i>
With this patch, Tidy now produces -
<b>Bold <i>Bold-Italics</i></b> <i>Italics only</i>
which is then rendered correctly in a browser,
but not exactly as your email suggested ...
It involved applying some of the same logic in the
following fix -
<i>Italics <p>paragraph-block</b> plain</p>
That 'fix' seems to have created two istack.c services,
namely InlineDup(...) and Node *InsertedToken(...)
Of course, in that fix, one could rely on that <i>
is a CM_INLINE, while <p> is a CM_BLOCK ... and
that fix uses this fact ...
In the Bold-Italics case, they are BOTH CM_INLINE ...
I too had to create two istack.c functions, namely
Bool SwitchInline( TidyDocImpl * doc, Node * element, Node * node ){}
As my comment on the function states -
/*
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 'yes' if both were found in the expected order.
*/
and
Bool InlineDup1( TidyDocImpl* doc, Node* node, Node* element ){}
/*
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 yes, if found and inserted ...
*/
Your email post said 'The above example is one of the oldest
bugs in the bug tracker', but I could not specifically find
this BUG in the 'bugs', or 'support requests', with just inline
elements like this, but I often only scanned the titles ...
I have added a compiler switch, ADD_INLINE_FIX2, around
each and all of the changes ...
And to make life easier for checking and testing I made the
fix sort of stand-alone, so it can be dropped into the code
easily, at the right point ... with some more fiddling it
could be 'combined' with existing code, but that is NOT so
easy since the PopInline() that is there must be avoided ...
Attached below is a full DIFF of the changes, as applied
to the CURRENT (2005.01.07) CVS source ... I put the compiler
switch in 'platform.h', so it can be turned off if others
do not like this new behaviour ...
Maybe it should also be controlled by an 'option' switch?
Advise, and suggest a switch, and I will add this also ...
Not that it says much, but my new binary, with this 'fix',
which I called tidydev2.exe, passes all the testcases.txt
and xmltest.txt suites ... sans problem ...
And FWIIW, I have also put a copy of my new binary,
containing this fix, on my site, at -
http://geoffmclane.com/tidy/tidy_02.htm#tidydev2
so others can give it a try, at least in WIN32 ...
together with a write up about its VERY SPECIFIC
intention ...
Hope this helps ... what to work on next? suggestions
solicited ... I like HTML Tidy, now that I am
understanding the code ;=))
Regards,
Geoff.
<diff2.txt>
An ADD_INLINE_FIX2 DIFF file
diff C:\FGCVS\Tidy\include\platform.h include\platform.h
52a53,60
>/* =====================================================
> Define ADD_INLINE_FIX2 to provide a fix for the
> following html
> <b>bold <i>bold and italics</b> italics only</i>
> Tidy will then convert this to
> <b>bold <i>bold and italics</i></b> <i>italics only</i>
> ====================================================== */
>#define ADD_INLINE_FIX2
diff C:\FGCVS\Tidy\src\istack.c src\istack.c
270a271,323
>#ifdef ADD_INLINE_FIX2
>/* Bool SwitchInline( TidyDocImpl * doc, Node * element, Node * node )
> 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 'yes' if both were found in the expected order.
>*/
>Bool SwitchInline( TidyDocImpl * doc, Node * element, Node * node )
>{
> Lexer* lexer = doc->lexer;
> if ( lexer
> && element
> && node
> && (element->tag != NULL)
> && (node->tag != NULL)
> && IsPushed( doc, element )
> && IsPushed( doc, node ) && ((lexer->istacksize -
>lexer->istackbase) >= 2) )
> {
> /* we have a chance of succeeding ... */
> int i;
> for (i = (lexer->istacksize - lexer->istackbase - 1); i >= 0; --i)
> {
> if (lexer->istack[i].tag == element->tag) {
> /* found the element tag - phew */
> IStack * istack1 = &lexer->istack[i];
> IStack * istack2 = 0;
> --i; /* back one more, and continue */
> for ( ; i >= 0; --i)
> {
> if (lexer->istack[i].tag == node->tag)
> {
> /* found the node tag - phew */
> istack2 = &lexer->istack[i];
> break;
> }
> }
> if( istack2 )
> {
> /* perform the SWAP ... */
> static IStack _tmp_istack;
> IStack * istack3 = &_tmp_istack; /* establish a temp */
> *istack3 = *istack2; /* copy 2nd to temp */
> *istack2 = *istack1; /* copy 1st to 2nd */
> *istack1 = *istack3; /* copy temp to 1st */
> return yes; /* return success */
> }
> }
> }
> }
> return no;
>}
271a325,348
>/* Bool InlineDup1( TidyDocImpl* doc, Node* node, Node* element )
> 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 yes, if found and inserted ... */
>Bool InlineDup1( TidyDocImpl* doc, Node* node, Node* element )
>{
> Lexer* lexer = doc->lexer;
> int n;
> if ( element
> && (element->tag != NULL)
> && ((n = lexer->istacksize - lexer->istackbase) > 0) )
> {
> int i;
> for ( i = n - 1; i >=0; --i ) {
> if (lexer->istack[i].tag == element->tag) {
> /* found our element tag - insert it */
> lexer->insert = &(lexer->istack[i]);
> lexer->inode = node;
> return yes; /* return success */
> }
> }
> }
> return no;
>}
272a350
>#endif /* #ifdef ADD_INLINE_FIX2 */
diff C:\FGCVS\Tidy\src\lexer.h src\lexer.h
620a621,642
>
>#ifdef ADD_INLINE_FIX2
>/* 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 'yes' if both were found in the expected order.
>*/
>Bool SwitchInline( TidyDocImpl * doc, Node * element, Node * node );
>
>/*
> We want to push a specific a specific element on the stack,
> but it may not be the LAST element, which InlineDup()
> would handle.
>*/
>Bool InlineDup1( TidyDocImpl* doc, Node* node, Node* element );
>
>#endif /* #ifdef ADD_INLINE_FIX2 */
>
>
>
diff C:\FGCVS\Tidy\src\parser.c src\parser.c
1499a1500,1522
>#ifdef ADD_INLINE_FIX2
> /* but, like the browser, 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 the scenario fits ... */
> if( !nodeIsA(element)
> && (node->tag != element->tag)
> && IsPushed( doc, node )
> && IsPushed( doc, element ) )
> {
> /* we have something like <b>bold <i>bold and italic</b>
>italics</i> */
> if( SwitchInline( doc, element, node ) )
> {
> ReportError(doc, element, node, NON_MATCHING_ENDTAG);
> UngetToken( doc ); /* put this back */
> InlineDup1( doc, NULL, element ); /* dupe the <i>,
>after </b> */
> if (!(mode & Preformatted))
> TrimSpaces(doc, element);
> return; /* close <i>, but will re-open it, after </b>
>*/
> }
> }
>#endif /* #ifdef ADD_INLINE_FIX2 */
>
</diff2.txt>
EOF - Tidy-07.doc
_________________________________________________________________
Buy now @ Tradingpost.com.au
http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fad%2Eau%2Edoubleclick%2Enet%2Fclk%3B24875379%3B12369854%3Ba%3Fhttp%3A%2F%2Fwww%2Etradingpost%2Ecom%2Eau%3Freferrer%3DnmsnHMetagv1&_t=752643439&_r=hotmailtagline&_m=EXT
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click