function _getCssList(css) { css = css.replace(/"/g, '"'); var list = {}, reg = /\s*([\w\-]+)\s*:([^;]*)(;|$)/g, match; while ((match = reg.exec(css))) { var key = _trim(match[1].toLowerCase()), val = _trim(_toHex(match[2])); list[key] = val; } return list; } function _getAttrList(tag) { var list = {}, reg = /\s+(?:([\w\-:]+)|(?:([\w\-:]+)=([^\s"'<>]+))|(?:([\w\-:"]+)="([^"]*)")|(?:([\w\-:"]+)='([^']*)'))(?=(?:\s|\/|>)+)/g, match; while ((match = reg.exec(tag))) { var key = (match[1] || match[2] || match[4] || match[6]).toLowerCase(), val = (match[2] ? match[3] : (match[4] ? match[5] : match[7])) || ''; list[key] = val; } return list; } function _addClassToTag(tag, className) { if (/\s+class\s*=/.test(tag)) { tag = tag.replace(/(\s+class=["']?)([^"']*)(["']?[\s>])/, function($0, $1, $2, $3) { if ((' ' + $2 + ' ').indexOf(' ' + className + ' ') < 0) { return $2 === '' ? $1 + className + $3 : $1 + $2 + ' ' + className + $3; } else { return $0; } }); } else { tag = tag.substr(0, tag.length - 1) + ' class="' + className + '">'; } return tag; } function _formatCss(css) { var str = ''; _each(_getCssList(css), function(key, val) { str += key + ':' + val + ';'; }); return str; } function _formatUrl(url, mode, host, pathname) { mode = _undef(mode, '').toLowerCase(); // 移除连续斜线,比如,http://localhost/upload/file/201205//maincus.swf // base64 data 除外 if (url.substr(0, 5) != 'data:') { url = url.replace(/([^:])\/\//g, '$1/'); } if (_inArray(mode, ['absolute', 'relative', 'domain']) < 0) { return url; } host = host || location.protocol + '//' + location.host; if (pathname === undefined) { var m = location.pathname.match(/^(\/.*)\//); pathname = m ? m[1] : ''; } var match; if ((match = /^(\w+:\/\/[^\/]*)/.exec(url))) { if (match[1] !== host) { return url; } } else if (/^\w+:/.test(url)) { return url; } function getRealPath(path) { var parts = path.split('/'), paths = []; for (var i = 0, len = parts.length; i < len; i++) { var part = parts[i]; if (part == '..') { if (paths.length > 0) { paths.pop(); } } else if (part !== '' && part != '.') { paths.push(part); } } return '/' + paths.join('/'); } if (/^\//.test(url)) { url = host + getRealPath(url.substr(1)); } else if (!/^\w+:\/\//.test(url)) { url = host + getRealPath(pathname + '/' + url); } function getRelativePath(path, depth) { if (url.substr(0, path.length) === path) { var arr = []; for (var i = 0; i < depth; i++) { arr.push('..'); } var prefix = '.'; if (arr.length > 0) { prefix += '/' + arr.join('/'); } if (pathname == '/') { prefix += '/'; } return prefix + url.substr(path.length); } else { if ((match = /^(.*)\//.exec(path))) { return getRelativePath(match[1], ++depth); } } } if (mode === 'relative') { url = getRelativePath(host + pathname, 0).substr(2); } else if (mode === 'absolute') { if (url.substr(0, host.length) === host) { url = url.substr(host.length); } } return url; } function _formatHtml(html, htmlTags, urlType, wellFormatted, indentChar) { // null or undefined: object == null if (html == null) { html = ''; } urlType = urlType || ''; wellFormatted = _undef(wellFormatted, false); indentChar = _undef(indentChar, '\t'); var fontSizeList = 'xx-small,x-small,small,medium,large,x-large,xx-large'.split(','); // 将pre里的br转换成\n html = html.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig, function($0, $1, $2, $3) { return $1 + $2.replace(/<(?:br|br\s[^>]*)>/ig, '\n') + $3; }); //

to

html = html.replace(/<(?:br|br\s[^>]*)\s*\/?>\s*<\/p>/ig, '

'); //

to


html = html.replace(/(<(?:p|p\s[^>]*)>)\s*(<\/p>)/ig, '$1
$2'); // empty char html = html.replace(/\u200B/g, ''); // © html = html.replace(/\u00A9/g, '©'); // ® html = html.replace(/\u00AE/g, '®'); // Bugfix: // https://github.com/kindsoft/kindeditor/issues/147 html = html.replace(/\u2003/g, ' '); html = html.replace(/\u3000/g, ' '); // Bugfix: // https://github.com/kindsoft/kindeditor/issues/116 // https://github.com/kindsoft/kindeditor/issues/145 html = html.replace(/<[^>]+/g, function($0) { return $0.replace(/\s+/g, ' '); }); var htmlTagMap = {}; if (htmlTags) { // 展开htmlTags里的key _each(htmlTags, function(key, val) { var arr = key.split(','); for (var i = 0, len = arr.length; i < len; i++) { htmlTagMap[arr[i]] = _toMap(val); } }); // 删除script和style里的内容 if (!htmlTagMap.script) { html = html.replace(/(<(?:script|script\s[^>]*)>)([\s\S]*?)(<\/script>)/ig, ''); } if (!htmlTagMap.style) { html = html.replace(/(<(?:style|style\s[^>]*)>)([\s\S]*?)(<\/style>)/ig, ''); } } var re = /(\s*)<(\/)?([\w\-:]+)((?:\s+|(?:\s+[\w\-:]+)|(?:\s+[\w\-:]+=[^\s"'<>]+)|(?:\s+[\w\-:"]+="[^"]*")|(?:\s+[\w\-:"]+='[^']*'))*)(\/)?>(\s*)/g; var tagStack = []; html = html.replace(re, function($0, $1, $2, $3, $4, $5, $6) { var full = $0, startNewline = $1 || '', startSlash = $2 || '', tagName = $3.toLowerCase(), attr = $4 || '', endSlash = $5 ? ' ' + $5 : '', endNewline = $6 || ''; // 不在名单里的过滤掉 if (htmlTags && !htmlTagMap[tagName]) { return ''; } // 无闭合标签的自动添加斜线 if (endSlash === '' && _SINGLE_TAG_MAP[tagName]) { endSlash = ' /'; } // inline tag时自动将多个空白转换成一个空格 if (_INLINE_TAG_MAP[tagName]) { if (startNewline) { startNewline = ' '; } if (endNewline) { endNewline = ' '; } } // pre,style,script tag的格式化 if (_PRE_TAG_MAP[tagName]) { if (startSlash) { endNewline = '\n'; } else { startNewline = '\n'; } } // br tag if (wellFormatted && tagName == 'br') { endNewline = '\n'; } // block tag的格式化 if (_BLOCK_TAG_MAP[tagName] && !_PRE_TAG_MAP[tagName]) { if (wellFormatted) { if (startSlash && tagStack.length > 0 && tagStack[tagStack.length - 1] === tagName) { tagStack.pop(); } else { tagStack.push(tagName); } startNewline = '\n'; endNewline = '\n'; for (var i = 0, len = startSlash ? tagStack.length : tagStack.length - 1; i < len; i++) { startNewline += indentChar; if (!startSlash) { endNewline += indentChar; } } if (endSlash) { tagStack.pop(); } else if (!startSlash) { endNewline += indentChar; } } else { startNewline = endNewline = ''; } } if (attr !== '') { var attrMap = _getAttrList(full); // 将font tag转换成span tag if (tagName === 'font') { var fontStyleMap = {}, fontStyle = ''; _each(attrMap, function(key, val) { if (key === 'color') { fontStyleMap.color = val; delete attrMap[key]; } if (key === 'size') { fontStyleMap['font-size'] = fontSizeList[parseInt(val, 10) - 1] || ''; delete attrMap[key]; } if (key === 'face') { fontStyleMap['font-family'] = val; delete attrMap[key]; } if (key === 'style') { fontStyle = val; } }); if (fontStyle && !/;$/.test(fontStyle)) { fontStyle += ';'; } _each(fontStyleMap, function(key, val) { if (val === '') { return; } if (/\s/.test(val)) { val = "'" + val + "'"; } fontStyle += key + ':' + val + ';'; }); attrMap.style = fontStyle; } // 处理attribute和style _each(attrMap, function(key, val) { // 补全单独属性 if (_FILL_ATTR_MAP[key]) { attrMap[key] = key; } // 处理URL if (_inArray(key, ['src', 'href']) >= 0) { attrMap[key] = _formatUrl(val, urlType); } // 过滤属性 if (htmlTags && key !== 'style' && !htmlTagMap[tagName]['*'] && !htmlTagMap[tagName][key] || tagName === 'body' && key === 'contenteditable' || /^kindeditor_\d+$/.test(key)) { delete attrMap[key]; } if (key === 'style' && val !== '') { var styleMap = _getCssList(val); _each(styleMap, function(k, v) { // 过滤样式 if (htmlTags && !htmlTagMap[tagName].style && !htmlTagMap[tagName]['.' + k]) { delete styleMap[k]; } }); var style = ''; _each(styleMap, function(k, v) { style += k + ':' + v + ';'; }); attrMap.style = style; } }); attr = ''; _each(attrMap, function(key, val) { if (key === 'style' && val === '') { return; } val = val.replace(/"/g, '"'); attr += ' ' + key + '="' + val + '"'; }); } if (tagName === 'font') { tagName = 'span'; } return startNewline + '<' + startSlash + tagName + attr + endSlash + '>' + endNewline; }); // 将pre里的\n转换成 临时标签 + \n,防止被替换 html = html.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig, function($0, $1, $2, $3) { return $1 + $2.replace(/\n/g, '\n') + $3; }); html = html.replace(/\n\s*\n/g, '\n'); // 删除临时标签 html = html.replace(/\n/g, '\n'); return _trim(html); } // 清理MS Word专用标签 function _clearMsWord(html, htmlTags) { html = html.replace(//ig, '') .replace(//ig, '') .replace(/]*>[\s\S]*?<\/style>/ig, '') .replace(/]*>[\s\S]*?<\/script>/ig, '') .replace(/]+>[\s\S]*?<\/w:[^>]+>/ig, '') .replace(/]+>[\s\S]*?<\/o:[^>]+>/ig, '') .replace(/[\s\S]*?<\/xml>/ig, '') .replace(/<(?:table|td)[^>]*>/ig, function(full) { return full.replace(/border-bottom:([#\w\s]+)/ig, 'border:$1'); }); return _formatHtml(html, htmlTags); } // 根据URL判断 media type function _mediaType(src) { if (/\.(rm|rmvb)(\?|$)/i.test(src)) { return 'audio/x-pn-realaudio-plugin'; } if (/\.(swf|flv)(\?|$)/i.test(src)) { return 'application/x-shockwave-flash'; } return 'video/x-ms-asf-plugin'; } // 根据 media type取得className function _mediaClass(type) { if (/realaudio/i.test(type)) { return 'ke-rm'; } if (/flash/i.test(type)) { return 'ke-flash'; } return 'ke-media'; } function _mediaAttrs(srcTag) { return _getAttrList(unescape(srcTag)); } function _mediaEmbed(attrs) { var html = ' 0) { style += 'width:' + width + 'px;'; } if (/\D/.test(height)) { style += 'height:' + height + ';'; } else if (height > 0) { style += 'height:' + height + 'px;'; } var html = ''; return html; } // Simple JavaScript Templating // John Resig - http://ejohn.org/ - MIT Licensed // http://ejohn.org/blog/javascript-micro-templating/ function _tmpl(str, data) { // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var fn = new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + // Introduce the data as local variables using with(){} "with(obj){p.push('" + // Convert the template into pure JavaScript str.replace(/[\r\t\n]/g, " ") .split("<%").join("\t") .replace(/((^|%>)[^\t]*)'/g, "$1\r") .replace(/\t=(.*?)%>/g, "',$1,'") .split("\t").join("');") .split("%>").join("p.push('") .split("\r").join("\\'") + "');}return p.join('');"); // Provide some basic currying to the user return data ? fn(data) : fn; } K.formatUrl = _formatUrl; K.formatHtml = _formatHtml; K.getCssList = _getCssList; K.getAttrList = _getAttrList; K.mediaType = _mediaType; K.mediaAttrs = _mediaAttrs; K.mediaEmbed = _mediaEmbed; K.mediaImg = _mediaImg; K.clearMsWord = _clearMsWord; K.tmpl = _tmpl;