* This is based loosely on tinymce
* @class Roo.htmleditor.TidyWriter
* https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
+ *
+ * Known issues?
+ * - not tested much with 'PRE' formated elements.
+ *
+ *
+ *
*/
Roo.htmleditor.TidyWriter = function(settings)
}
Roo.htmleditor.TidyWriter.prototype = {
-
-
- makeMap : function (items, delim, map) {
- var i;
- items = items || [];
- delim = delim || ',';
- if (typeof items == "string") {
- items = items.split(delim);
- }
- map = map || {};
- i = items.length;
- while (i--) {
- map[items[i]] = {};
- }
- return map;
- },
-
+
state : false,
indent : ' ',
indentstr : '',
in_pre: false,
in_inline : false,
-
+ last_inline : false,
encode : false,
var is_short = empty ? Roo.htmleditor.TidyWriter.shortend_elements.indexOf(name) > -1 : false;
+ var add_lb = name == 'BR' ? false : in_inline;
+
+ if (!add_lb && !this.in_pre && this.lastElementEndsWS()) {
+ i_inline = false;
+ }
- var indentstr = this.in_inline || this.in_pre ? '' : this.indentstr;
+ var indentstr = this.indentstr;
- if (!this.in_inline && !this.in_pre) {
- this.addLine();
+ // e_inline = elements that can be inline, but still allow \n before and after?
+ // only 'BR' ??? any others?
+
+ // ADD LINE BEFORE tage
+ if (!this.in_pre) {
+ if (in_inline) {
+ //code
+ if (name == 'BR') {
+ this.addLine();
+ } else if (this.lastElementEndsWS()) {
+ this.addLine();
+ } else{
+ // otherwise - no new line. (and dont indent.)
+ indentstr = '';
+ }
+
+ } else {
+ this.addLine();
+ }
+ } else {
+ indentstr = '';
}
this.html.push(indentstr + '<', name.toLowerCase());
} else {
this.html[this.html.length] = '></' + name.toLowerCase() + '>';
}
+ var e_inline = name == 'BR' ? false : this.in_inline;
- if (!this.in_inline && !this.in_pre) {
+ if (!e_inline && !this.in_pre) {
this.addLine();
}
return;
this.pushState({
- indentstr : in_pre || in_inline ? '' : (this.indentstr + this.indent),
+ indentstr : in_pre ? '' : (this.indentstr + this.indent),
in_pre : in_pre,
in_inline : in_inline
});
},
+
+ lastElementEndsWS : function()
+ {
+ var value = this.html.length > 0 ? this.html[this.html.length-1] : false;
+ if (value === false) {
+ return true;
+ }
+ return value.match(/\s+$/);
+
+ },
+
/**
* Writes the a end element such as </p>.
*
end: function(name) {
var value;
this.popState();
- var indentstr = '';
- if (!this.in_pre && !this.in_inline) {
+ var indentstr = '';
+ var in_inline = this.in_inline || Roo.htmleditor.TidyWriter.inline_elements.indexOf(name) > -1;
+
+ if (!this.in_pre && !in_inline) {
this.addLine();
indentstr = this.indentstr;
}
this.html.push(indentstr + '</', name.toLowerCase(), '>');
-
+ this.last_inline = in_inline;
// pop the indent state..
},
* @param {String} text String to write out.
* @param {Boolean} raw Optional raw state if true the contents wont get encoded.
*/
- text: function(text )
+ text: function(text, node)
{
// if not in whitespace critical
if (text.length < 1) {
return;
}
- if (this.in_pre || this.is_inline) {
+ if (this.in_pre) {
this.html[this.html.length] = text;
- return;
-
+ return;
}
- // see if last line is a line break
- this.addLine();
+ if (this.in_inline) {
+ text = text.replace(/\s+/g,' '); // all white space inc line breaks to a slingle' '
+ if (text != ' ') {
+ text = text.replace(/\s+/,' '); // all white space to single white space
+
+
+ // if next tag is '<BR>', then we can trim right..
+ if (node.nextSibling &&
+ node.nextSibling.nodeType == 1 &&
+ node.nextSibling.nodeName == 'BR' )
+ {
+ text = text.replace(/\s+$/g,'');
+ }
+ // if previous tag was a BR, we can also trim..
+ if (node.previousSibling &&
+ node.previousSibling.nodeType == 1 &&
+ node.previousSibling.nodeName == 'BR' )
+ {
+ text = this.indentstr + text.replace(/^\s+/g,'');
+ }
+ if (text.match(/\n/)) {
+ text = text.replace(
+ /(?![^\n]{1,64}$)([^\n]{1,64})\s/g, '$1\n' + this.indentstr
+ );
+ // remoeve the last whitespace / line break.
+ text = text.replace(/\n\s+$/,'');
+ }
+ // repace long lines
+
+ }
+
+ this.html[this.html.length] = text;
+ return;
+ }
+ // see if previous element was a inline element.
+ var indentstr = this.indentstr;
+
+ text = text.replace(/\s+/g," "); // all whitespace into single white space.
+
+ // should trim left?
+ if (node.previousSibling &&
+ node.previousSibling.nodeType == 1 &&
+ Roo.htmleditor.TidyWriter.inline_elements.indexOf(node.previousSibling.nodeName) > -1)
+ {
+ indentstr = '';
+
+ } else {
+ this.addLine();
+ text = text.replace(/^\s+/,''); // trim left
+
+ }
+ // should trim right?
+ if (node.nextSibling &&
+ node.nextSibling.nodeType == 1 &&
+ Roo.htmleditor.TidyWriter.inline_elements.indexOf(node.nextSibling.nodeName) > -1)
+ {
+ // noop
+ } else {
+ text = text.replace(/\s+$/,''); // trim right
+ }
+
+
- text = text.replace(/\s/g," ") // all line breaks to ' '
- .replace(/^\s+/,'') // leding white space
- .replace(/\s+$/,''); // clean trailing white space
if (text.length < 1) {
return;
}
if (!text.match(/\n/)) {
- this.html.push(this.indentstr + text);
+ this.html.push(indentstr + text);
return;
}
Roo.htmleditor.TidyWriter.inline_elements = [
'SPAN','STRONG','B','EM','I','FONT','STRIKE','U','VAR',
- 'CITE','DFN','CODE','MARK','Q','SUP','SUB','SAMP'
+ 'CITE','DFN','CODE','MARK','Q','SUP','SUB','SAMP', 'A'
];
Roo.htmleditor.TidyWriter.shortend_elements = [
'AREA','BASE','BASEFONT','BR','COL','FRAME','HR','IMG','INPUT',