3

I am trying to clean up user entered HTML code that has a lot of inline CSS especially spans with styles and I'm not sure where to start. Does anyone know of a way to merge the spans and the styling using JavaScript? I have found ways to convert inline styles by moving all the styling to a style sheet, but that is not yet possible to store the CSS page in our system as it is right now. (Hopefully that will be a goal in the near future, but not my call)

An example - turn this mess:

<span style="font-size: large;"><span style="font-family: arial black,avant garde;"><span style="font-size: xx-large;"><span style="font-size: large;"><span style="font-family: arial black,avant garde;"><span style="font-size: xx-large;"><span style="color: #000000;"><span style="font-size: x-large;"><span style="font-size: large;"><span style="font-family: arial black,avant garde;"><span style="font-size: xx-large;"><span style="color: #000000;"><span style="font-size: x-large;"><a href="index.php?p=75">Home</a></span></span></span></span></span></span></span></span></span></span></span></span></span>

into this:

<span style="font-size: x-large;color: #000000;font-family: arial black,avant garde;"><a href="index.php?p=75">Home</a></span>
mercator
  • 28,290
  • 8
  • 63
  • 72
jncw
  • 39
  • 2
  • dear god, that might be the ugliest thing I've ever seen.. – Greg Guida Jul 15 '11 at 19:33
  • I would agree, but unfortunately, our users have entered worse. That's why I'm trying to find a way to at least clean it up a bit until there is time to refactor and split out the css to a stylesheet. – jncw Jul 15 '11 at 19:36
  • is this from some sort of wysiwyg editor? – Greg Guida Jul 15 '11 at 19:38
  • Yes. InnovaStudio WYSIWYG Editor. I'm not with them, we just use it in our CMS. Trying to improve on what code we get from it. – jncw Jul 15 '11 at 19:42
  • can you switch to a different editor, such as [tinyMCE](http://tinymce.moxiecode.com/index.php) or [aloha](http://www.aloha-editor.org/)? – Greg Guida Jul 15 '11 at 19:54
  • In the process of switching to tinyMCE (and liking it alot so far). Plan on also using whatever cleanup I end up with to add to tinyMCE's cleanup since it does not clean up the example code either. It creates nicer code to start with, but I am trying to deal with already existing code. I'd like to add a button where we could clean that code up. – jncw Jul 15 '11 at 20:01

1 Answers1

1

How about this?

window.onload = function(){
    var spans = document.querySelectorAll('span');

    for (var i = 0; i < spans.length; i++)
    {
        if (spans[i].hasChildNodes() && spans[i].childNodes.length == 1
            && spans[i].firstChild.tagName == 'SPAN')
        {
            var parent = spans[i];
            var child = spans[i].firstChild;

            // Copy new properties to child.
            for (var j = 0; j < parent.style.length; j++)
            {
                var prop = parent.style[j];
                if (child.style.getPropertyValue(prop) === "")
                {
                    child.style.setProperty(
                        prop,
                        parent.style.getPropertyValue(prop),
                        ''
                    );
                }
            }

            // Replace parent with child.
            parent.parentNode.insertBefore(child, parent);
            parent.parentNode.removeChild(parent);
        }
    }
}

This will find all spans, and merges those which only have a single span child.

This will disregard the use of !important, but I presume that's not being used anyway.

Also, it won't return exactly the same property values since getPropertyValue normalizes them.

Edit:

The above example code reduces the 13 spans in your example down to just one for me, though, Safari throws away some of the styles in the process.

It's fairly simplistic, of course, and just based on one example, since I have no idea what kind of span soup you might be running into, or what kind of results exactly you might be looking for.

For example, you might want to merge spans like this too: <p>foo<span style="font-size: x-large"> <span style="font-size: small">bar</span></span></p>? You'd end up losing the font size on that space, but that'll only make a tiny difference.

I'm sure there are plenty more cases like that, so it'll come down to how clean you want the end result to be, and how much time you want to spend on fixing all the corner cases.

You can find more information about the DOM methods I used in Mozilla's DOM reference for CSSStyleDeclaration and element, for example.

Community
  • 1
  • 1
mercator
  • 28,290
  • 8
  • 63
  • 72
  • Thanks. That is a start. It takes it from 13 to 7 spans. I did have to change the line child.style.setProperty(prop,parent.style.getPropertyValue(prop)); to child.style.setProperty(prop,parent.style.getPropertyValue(prop),''); or it would error out with a 'not enough arguments' exception. – jncw Jul 19 '11 at 18:52
  • I added the missing argument, and some reference info. – mercator Jul 19 '11 at 21:14