summaryrefslogtreecommitdiff
path: root/js/dojo-1.6/dojox/html/format.js
diff options
context:
space:
mode:
authorTristan Zur <tzur@web.web.ccwn.org>2014-03-27 22:27:47 +0100
committerTristan Zur <tzur@web.web.ccwn.org>2014-03-27 22:27:47 +0100
commitb62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch)
tree86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /js/dojo-1.6/dojox/html/format.js
Initial commit of intern.ccwn.org contentsHEADmaster
Diffstat (limited to 'js/dojo-1.6/dojox/html/format.js')
-rw-r--r--js/dojo-1.6/dojox/html/format.js486
1 files changed, 486 insertions, 0 deletions
diff --git a/js/dojo-1.6/dojox/html/format.js b/js/dojo-1.6/dojox/html/format.js
new file mode 100644
index 0000000..fa5d7ce
--- /dev/null
+++ b/js/dojo-1.6/dojox/html/format.js
@@ -0,0 +1,486 @@
+/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.html.format"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.html.format"] = true;
+dojo.provide("dojox.html.format");
+dojo.require("dojox.html.entities");
+
+
+
+dojox.html.format.prettyPrint = function(html/*String*/, indentBy /*Integer?*/, maxLineLength /*Integer?*/, map/*Array?*/, /*boolean*/ xhtml){
+ // summary:
+ // Function for providing a 'pretty print' version of HTML content from
+ // the provided string. It's nor perfect by any means, but it does
+ // a 'reasonable job'.
+ // html: String
+ // The string of HTML to try and generate a 'pretty' formatting.
+ // indentBy: Integer
+ // Optional input for the number of spaces to use when indenting.
+ // If not defined, zero, negative, or greater than 10, will just use tab
+ // as the indent.
+ // maxLineLength: Integer
+ // Optional input for the number of characters a text line should use in
+ // the document, including the indent if possible.
+ // map: Array
+ // Optional array of entity mapping characters to use when processing the
+ // HTML Text content. By default it uses the default set used by the
+ // dojox.html.entities.encode function.
+ // xhtml: boolean
+ // Optional parameter that declares that the returned HTML should try to be 'xhtml' compatible.
+ // This means normally unclosed tags are terminated with /> instead of >. Example: <hr> -> <hr />
+ var content = [];
+ var indentDepth = 0;
+ var closeTags = [];
+ var iTxt = "\t";
+ var textContent = "";
+ var inlineStyle = [];
+ var i;
+
+ // Compile regexps once for this call.
+ var rgxp_fixIEAttrs = /[=]([^"']+?)(\s|>)/g;
+ var rgxp_styleMatch = /style=("[^"]*"|'[^']*'|\S*)/gi;
+ var rgxp_attrsMatch = /[\w-]+=("[^"]*"|'[^']*'|\S*)/gi;
+
+ // Check to see if we want to use spaces for indent instead
+ // of tab.
+ if(indentBy && indentBy > 0 && indentBy < 10){
+ iTxt = "";
+ for(i = 0; i < indentBy; i++){
+ iTxt += " ";
+ }
+ }
+
+ //Build the content outside of the editor so we can walk
+ //via DOM and build a 'pretty' output.
+ var contentDiv = dojo.doc.createElement("div");
+ contentDiv.innerHTML = html;
+
+ // Use the entity encode/decode functions, they cache on the map,
+ // so it won't multiprocess a map.
+ var encode = dojox.html.entities.encode;
+ var decode = dojox.html.entities.decode;
+
+ /** Define a bunch of formatters to format the output. **/
+ var isInlineFormat = function(tag){
+ // summary:
+ // Function to determine if the current tag is an inline
+ // element that does formatting, as we don't want to
+ // break/indent around it, as it can screw up text.
+ // tag:
+ // The tag to examine
+ switch(tag){
+ case "a":
+ case "b":
+ case "strong":
+ case "s":
+ case "strike":
+ case "i":
+ case "u":
+ case "em":
+ case "sup":
+ case "sub":
+ case "span":
+ case "font":
+ case "big":
+ case "cite":
+ case "q":
+ case "small":
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ //Create less divs.
+ var div = contentDiv.ownerDocument.createElement("div");
+ var outerHTML = function(node){
+ // summary:
+ // Function to return the outer HTML of a node.
+ // Yes, IE has a function like this, but using cloneNode
+ // allows avoiding looking at any child nodes, because in this
+ // case, we don't want them.
+ var clone = node.cloneNode(false);
+ div.appendChild(clone);
+ var html = div.innerHTML;
+ div.innerHTML = "";
+ return html;
+ };
+
+ var sizeIndent = function(){
+ var i, txt = "";
+ for(i = 0; i < indentDepth; i++){
+ txt += iTxt;
+ }
+ return txt.length;
+ }
+
+ var indent = function(){
+ // summary:
+ // Function to handle indent depth.
+ var i;
+ for(i = 0; i < indentDepth; i++){
+ content.push(iTxt);
+ }
+ };
+ var newline = function(){
+ // summary:
+ // Function to handle newlining.
+ content.push("\n");
+ };
+
+ var processTextNode = function(n){
+ // summary:
+ // Function to process the text content for doc
+ // insertion
+ // n:
+ // The text node to process.
+ textContent += encode(n.nodeValue, map);
+ };
+
+ var formatText = function(txt){
+ // summary:
+ // Function for processing the text content encountered up to a
+ // point and inserting it into the formatted document output.
+ // txt:
+ // The text to format.
+ var i;
+ var _iTxt;
+
+ // Clean up any indention organization since we're going to rework it
+ // anyway.
+ var _lines = txt.split("\n");
+ for(i = 0; i < _lines.length; i++){
+ _lines[i] = dojo.trim(_lines[i]);
+ }
+ txt = _lines.join(" ");
+ txt = dojo.trim(txt);
+ if(txt !== ""){
+ var lines = [];
+ if(maxLineLength && maxLineLength > 0){
+ var indentSize = sizeIndent();
+ var maxLine = maxLineLength;
+ if(maxLineLength > indentSize){
+ maxLine -= indentSize;
+ }
+ while(txt){
+ if(txt.length > maxLineLength){
+ for(i = maxLine; (i > 0 && txt.charAt(i) !== " "); i--){
+ // Do nothing, we're just looking for a space to split at.
+ }
+ if(!i){
+ // Couldn't find a split going back, so go forward.
+ for(i = maxLine; (i < txt.length && txt.charAt(i) !== " "); i++){
+ // Do nothing, we're just looking for a space to split at.
+ }
+ }
+ var line = txt.substring(0, i);
+ line = dojo.trim(line);
+ // Shift up the text string to the next chunk.
+ txt = dojo.trim(txt.substring((i == txt.length)?txt.length:i + 1, txt.length));
+ if(line){
+ _iTxt = "";
+ for(i = 0; i < indentDepth; i++){
+ _iTxt += iTxt;
+ }
+ line = _iTxt + line + "\n";
+ }
+ lines.push(line);
+ }else{
+ // Line is shorter than out desired length, so use it.
+ // as/is
+ _iTxt = "";
+ for(i = 0; i < indentDepth; i++){
+ _iTxt += iTxt;
+ }
+ txt = _iTxt + txt + "\n";
+ lines.push(txt);
+ txt = null;
+ }
+ }
+ return lines.join("");
+ }else{
+ _iTxt = "";
+ for(i = 0; i < indentDepth; i++){
+ _iTxt += iTxt;
+ }
+ txt = _iTxt + txt + "\n";
+ return txt;
+ }
+ }else{
+ return "";
+ }
+ };
+
+ var processScriptText = function(txt){
+ // summary:
+ // Function to clean up potential escapes in the script code.
+ if(txt){
+ txt = txt.replace(/&quot;/gi, "\"");
+ txt = txt.replace(/&gt;/gi, ">");
+ txt = txt.replace(/&lt;/gi, "<");
+ txt = txt.replace(/&amp;/gi, "&");
+ }
+ return txt;
+ };
+
+ var formatScript = function(txt){
+ // summary:
+ // Function to rudimentary formatting of script text.
+ // Not perfect, but it helps get some level of organization
+ // in there.
+ // txt:
+ // The script text to try to format a bit.
+ if(txt){
+ txt = processScriptText(txt);
+ var i, t, c, _iTxt;
+ var indent = 0;
+ var scriptLines = txt.split("\n");
+ var newLines = [];
+ for (i = 0; i < scriptLines.length; i++){
+ var line = scriptLines[i];
+ var hasNewlines = (line.indexOf("\n") > -1);
+ line = dojo.trim(line);
+ if(line){
+ var iLevel = indent;
+ // Not all blank, so we need to process.
+ for(c = 0; c < line.length; c++){
+ var ch = line.charAt(c);
+ if(ch === "{"){
+ indent++;
+ }else if(ch === "}"){
+ indent--;
+ // We want to back up a bit before the
+ // line is written.
+ iLevel = indent;
+ }
+ }
+ _iTxt = "";
+ for(t = 0; t < indentDepth + iLevel; t++){
+ _iTxt += iTxt;
+ }
+ newLines.push(_iTxt + line + "\n");
+ }else if(hasNewlines && i === 0){
+ // Just insert a newline for blank lines as
+ // long as it's not the first newline (we
+ // already inserted that in the openTag handler)
+ newLines.push("\n");
+ }
+
+ }
+ // Okay, create the script text, hopefully reasonably
+ // formatted.
+ txt = newLines.join("");
+ }
+ return txt;
+ };
+
+ var openTag = function(node){
+ // summary:
+ // Function to open a new tag for writing content.
+ var name = node.nodeName.toLowerCase();
+ // Generate the outer node content (tag with attrs)
+ var nText = dojo.trim(outerHTML(node));
+ var tag = nText.substring(0, nText.indexOf(">") + 1);
+
+ // Also thanks to IE, we need to check for quotes around
+ // attributes and insert if missing.
+ tag = tag.replace(rgxp_fixIEAttrs,'="$1"$2');
+
+ // And lastly, thanks IE for changing style casing and end
+ // semi-colon and webkit adds spaces, so lets clean it up by
+ // sorting, etc, while we're at it.
+ tag = tag.replace(rgxp_styleMatch, function(match){
+ var sL = match.substring(0,6);
+ var style = match.substring(6, match.length);
+ var closure = style.charAt(0);
+ style = dojo.trim(style.substring(1,style.length -1));
+ style = style.split(";");
+ var trimmedStyles = [];
+ dojo.forEach(style, function(s){
+ s = dojo.trim(s);
+ if(s){
+ // Lower case the style name, leave the value alone. Mainly a fixup for IE.
+ s = s.substring(0, s.indexOf(":")).toLowerCase() + s.substring(s.indexOf(":"), s.length);
+ trimmedStyles.push(s);
+ }
+ });
+ trimmedStyles = trimmedStyles.sort();
+
+ // Reassemble and return the styles in sorted order.
+ style = trimmedStyles.join("; ");
+ var ts = dojo.trim(style);
+ if(!ts || ts === ";"){
+ // Just remove any style attrs that are empty.
+ return "";
+ }else{
+ style += ";";
+ return sL + closure + style + closure;
+ }
+ });
+
+ // Try and sort the attributes while we're at it.
+ var attrs = [];
+ tag = tag.replace(rgxp_attrsMatch, function(attr){
+ attrs.push(dojo.trim(attr));
+ return "";
+ });
+ attrs = attrs.sort();
+
+ // Reassemble the tag with sorted attributes!
+ tag = "<" + name;
+ if(attrs.length){
+ tag += " " + attrs.join(" ");
+ }
+
+ // Determine closure status. If xhtml,
+ // then close the tag properly as needed.
+ if(nText.indexOf("</") != -1){
+ closeTags.push(name);
+ tag += ">";
+ }else{
+ if(xhtml){
+ tag += " />";
+ }else{
+ tag += ">";
+ }
+ closeTags.push(false);
+ }
+
+ var inline = isInlineFormat(name);
+ inlineStyle.push(inline);
+ if(textContent && !inline){
+ // Process any text content we have that occurred
+ // before the open tag of a non-inline.
+ content.push(formatText(textContent));
+ textContent = "";
+ }
+
+ // Determine if this has a closing tag or not!
+ if(!inline){
+ indent();
+ content.push(tag);
+ newline();
+ indentDepth++;
+ }else{
+ textContent += tag;
+ }
+
+ };
+
+ var closeTag = function(){
+ // summary:
+ // Function to close out a tag if necessary.
+ var inline = inlineStyle.pop();
+ if(textContent && !inline){
+ // Process any text content we have that occurred
+ // before the close tag.
+ content.push(formatText(textContent));
+ textContent = "";
+ }
+ var ct = closeTags.pop();
+ if(ct){
+ ct = "</" + ct + ">";
+ if(!inline){
+ indentDepth--;
+ indent();
+ content.push(ct);
+ newline();
+ }else{
+ textContent += ct;
+ }
+ }else{
+ indentDepth--;
+ }
+ };
+
+ var processCommentNode = function(n){
+ // summary:
+ // Function to handle processing a comment node.
+ // n:
+ // The comment node to process.
+
+ //Make sure contents aren't double-encoded.
+ var commentText = decode(n.nodeValue, map);
+ indent();
+ content.push("<!--");
+ newline();
+ indentDepth++;
+ content.push(formatText(commentText));
+ indentDepth--;
+ indent();
+ content.push("-->");
+ newline();
+ };
+
+ var processNode = function(node) {
+ // summary:
+ // Entrypoint for processing all the text!
+ var children = node.childNodes;
+ if(children){
+ var i;
+ for(i = 0; i < children.length; i++){
+ var n = children[i];
+ if(n.nodeType === 1){
+ var tg = dojo.trim(n.tagName.toLowerCase());
+ if(dojo.isIE && n.parentNode != node){
+ // IE is broken. DOMs are supposed to be a tree.
+ // But in the case of malformed HTML, IE generates a graph
+ // meaning one node ends up with multiple references
+ // (multiple parents). This is totally wrong and invalid, but
+ // such is what it is. We have to keep track and check for
+ // this because otherwise the source output HTML will have dups.
+ continue;
+ }
+ if(tg && tg.charAt(0) === "/"){
+ // IE oddity. Malformed HTML can put in odd tags like:
+ // </ >, </span>. It treats a mismatched closure as a new
+ // start tag. So, remove them.
+ continue;
+ }else{
+ //Process non-dup, seemingly wellformed elements!
+ openTag(n);
+ if(tg === "script"){
+ content.push(formatScript(n.innerHTML));
+ }else if(tg === "pre"){
+ var preTxt = n.innerHTML;
+ if(dojo.isMoz){
+ //Mozilla screws this up, so fix it up.
+ preTxt = preTxt.replace("<br>", "\n");
+ preTxt = preTxt.replace("<pre>", "");
+ preTxt = preTxt.replace("</pre>", "");
+ }
+ // Add ending newline, if needed.
+ if(preTxt.charAt(preTxt.length - 1) !== "\n"){
+ preTxt += "\n";
+ }
+ content.push(preTxt);
+ }else{
+ processNode(n);
+ }
+ closeTag();
+ }
+ }else if(n.nodeType === 3 || n.nodeType === 4){
+ processTextNode(n);
+ }else if(n.nodeType === 8){
+ processCommentNode(n);
+ }
+ }
+ }
+ };
+
+ //Okay, finally process the input string.
+ processNode(contentDiv);
+ if(textContent){
+ // Insert any trailing text. See: #10854
+ content.push(formatText(textContent));
+ textContent = "";
+ }
+ return content.join(""); //String
+};
+
+}