Forum Bugs

del and ins tags and block-level elements

henning
Hi,

Prince 9 doesn't handle ins and del tags correctly when they contain block-level elements.

In this example, all words should be marked as deleted, bu t they are not:

<del>Here is 
<p>deleted text in a p</p>
and more deleted text</del>

<del>Here is 
<p><del>deleted text in a p</del></p>
and more deleted text</del>


Thanks,

Henning
  1. del.png4.3 kB
mikeday
Currently Prince cannot nest block elements inside inline elements, so the inline element will be split around the block element. This makes it difficult to support ins and del when they occur in a block context.

Depending on your document markup, you could simulate the desired affect by treating ins and del as block elements unless they occur inside a paragraph:
ins, del { display: block }
p ins, p del { display: inline }

It's not a perfect solution, but might help.
henning
Hi Mike,

When you say
the inline element will be split around the block element
doesn't that mean the words "and more deleted text" should show up as deleted in this example? That's not the case, though.

<del>Here is 
<p>deleted text in a p</p>
and more deleted text</del>


Thanks!

mikeday
Because the inline element will be split, it ends up with structure basically like this:
<del>Here is</del>
<p>delete text in a p</p>
<del>and more deleted text</del>

Although CSS properties will still be inherited by the p element, so color for example will be passed down, but the text-decoration properties (of which line-through is one) are not inherited properties, and due to the broken structure they will not apply.

That suggests another way of fixing it:
del p { text-decoration: line-through }
henning
Yes, that would fix what is inside the <p> element. But I am more concerned about the text after the <p> element. If the inline element is split the way you explained then the words "and more deleted text" should be marked as deleted but they are not. Please see the attached output.

Thanks!
  1. deleted_text.pdf18.2 kB
mikeday
I have an idea: what if we use JavaScript to transform the document by splitting the ins and del tags and pushing them down the tree so they only wrap the text nodes? Then they will never contain block elements, and there will be no problem. Here is some JavaScript code to do that:
window.onload = function() {
    splitAllElements("ins");
    splitAllElements("del");
};

function splitAllElements(tagName)
{
    var i;
    var elems = [];
    var ns = document.getElementsByTagName(tagName)

    for (i = 0; i < ns.length; ++i)
    {
	elems.push(ns[i]);
    }

    for (i = 0; i < elems.length; ++i)
    {
	splitElement(elems[i]);
    }
}

function splitElement(elem)
{
    var frag = document.createDocumentFragment();

    while (elem.firstChild)
    {
	var child = elem.firstChild;
	elem.removeChild(child);
	frag.appendChild(wrapTextNodes(elem.tagName, child));
    }

    elem.parentNode.insertBefore(frag, elem);
    elem.parentNode.removeChild(elem);
}

function wrapTextNodes(tagName, node)
{
    if (node.nodeType == Node.TEXT_NODE)
    {
	var wrapElem = document.createElement(tagName);
	wrapElem.appendChild(node);
	return wrapElem;
    }
    else if (node.nodeType == Node.ELEMENT_NODE && node.tagName != tagName)
    {
	var frag = document.createDocumentFragment();

	while (node.firstChild)
	{
	    var child = node.firstChild;
	    node.removeChild(child);
	    frag.appendChild(wrapTextNodes(tagName, child));
	}

	node.appendChild(frag);

	return node;
    }
    else
    {
	return node;
    }
}

If you run this code on your example document, it transforms it like this:
<del>Here is </del>
<p><del>deleted text in a p</del></p>
<del>and more deleted text</del>

<del>Here is </del>
<p><del>deleted text in a p</del></p>
<del>and more deleted text</del>

Currently it doesn't duplicate the attributes on the ins/del elements, so it will need some tweaks if you use class or style attributes on these elements.