Reputation: 1672
I am using a utility called FresherEditor which uses the ContentEditable plugin for jQuery to create an editable document in the browser window. I then need to take that output and generate SVG graphics from the rules obtained by parsing the HTML governed style into CSS.
The freshereditor will produce output that looks somewhat like:
<div>
<p>
<i>
<u>
<b>
<font face="Verdana">
Hello, World!
</font>
</b>
</u>
</i>
</p>
</div>
When what I would prefer is something that looks like:
<div>
<p style="font-weight: bold; font-style: italic; text-decoration: underline; font-family: Verdana;">
Hello, World!
</p>
</div>
Any suggestions would be helpful.
Upvotes: 1
Views: 935
Reputation: 303421
This was a very fun problem; thanks! Following are scripts that add html2style()
and style2html()
methods. The test case shows that you can convert between the two with no visual change (though the ordering of the element nesting may be different after a round trip).
(function(scope){
var HTML2CSS = {
strong: function(e){ this.style.fontWeight = "bold"; },
b: function(e){ this.style.fontWeight = "bold"; },
em: function(e){ this.style.fontStyle = "italic"; },
i: function(e){ this.style.fontStyle = "italic"; },
font: function(e){ this.style.fontFamily = e.getAttribute('face'); },
u: function(e){ this.style.textDecoration += ' underline'; },
strike: function(e){ this.style.textDecoration += ' line-through'; }
};
scope.html2style = function(root){
for (var name in HTML2CSS){
var elements = root.querySelectorAll(name);
var styler = HTML2CSS[name];
for (var i=elements.length;i--;){
var toKill = elements[i],
parent = toKill.parentNode;
// Only swap out nodes that are the sole element child of the parent
if (!toKill.nextElementSibling && !toKill.previousElementSibling){
parent.removeChild(toKill);
// Move contents into the parent
for (var kids=toKill.childNodes,j=kids.length;j--;){
parent.insertBefore(kids[j],parent.firstChild);
}
// Merge existing styles from this node onto the parent
parent.style.cssText += toKill.style.cssText;
// Hard set the style for this node onto the parent
styler.call(parent,toKill);
}
}
}
}
})(this);
(function(scope){
var CSS2HTML = {
"fontWeight:bold": "b",
"fontStyle:italic": "i",
"textDecoration:underline": "u",
"textDecoration:line-through": "strike",
"font-family:*": function(value){ var e=document.createElement('font'); e.setAttribute('face',value); return e; }
};
scope.style2html = function(root){
var leaf = root;
for (var style in CSS2HTML){
var elName = CSS2HTML[style],
parts = style.split(':'),
name = parts[0],
wild = parts[1]=="*",
regex = !wild && new RegExp("(^|\\s)"+parts[1]+"(\\s|$)"),
before = root.style[name];
if (before && (wild || regex.test(before))){
var el = (typeof elName==='function') ? elName(before) : document.createElement(elName);
for (var kids=leaf.childNodes,j=kids.length;j--;){
el.insertBefore(kids[j],el.firstChild);
}
leaf = leaf.appendChild(el);
root.style[name]=wild ? "" : before.replace(regex,"");
}
}
if (root.getAttribute('style')=="") root.removeAttribute('style');
}
})(this);
Upvotes: 1