| 7004 | // Build up the DOM representation for a single token, and add it to |
| 7005 | // the line map. Takes care to render special characters separately. |
| 7006 | function buildToken(builder, text, style, startStyle, endStyle, title, css) { |
| 7007 | if (!text) return; |
| 7008 | var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text; |
| 7009 | var special = builder.cm.state.specialChars, mustWrap = false; |
| 7010 | if (!special.test(text)) { |
| 7011 | builder.col += text.length; |
| 7012 | var content = document.createTextNode(displayText); |
| 7013 | builder.map.push(builder.pos, builder.pos + text.length, content); |
| 7014 | if (ie && ie_version < 9) mustWrap = true; |
| 7015 | builder.pos += text.length; |
| 7016 | } else { |
| 7017 | var content = document.createDocumentFragment(), pos = 0; |
| 7018 | while (true) { |
| 7019 | special.lastIndex = pos; |
| 7020 | var m = special.exec(text); |
| 7021 | var skipped = m ? m.index - pos : text.length - pos; |
| 7022 | if (skipped) { |
| 7023 | var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); |
| 7024 | if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); |
| 7025 | else content.appendChild(txt); |
| 7026 | builder.map.push(builder.pos, builder.pos + skipped, txt); |
| 7027 | builder.col += skipped; |
| 7028 | builder.pos += skipped; |
| 7029 | } |
| 7030 | if (!m) break; |
| 7031 | pos += skipped + 1; |
| 7032 | if (m[0] == "\t") { |
| 7033 | var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; |
| 7034 | var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); |
| 7035 | txt.setAttribute("role", "presentation"); |
| 7036 | txt.setAttribute("cm-text", "\t"); |
| 7037 | builder.col += tabWidth; |
| 7038 | } else if (m[0] == "\r" || m[0] == "\n") { |
| 7039 | var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); |
| 7040 | txt.setAttribute("cm-text", m[0]); |
| 7041 | builder.col += 1; |
| 7042 | } else { |
| 7043 | var txt = builder.cm.options.specialCharPlaceholder(m[0]); |
| 7044 | txt.setAttribute("cm-text", m[0]); |
| 7045 | if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); |
| 7046 | else content.appendChild(txt); |
| 7047 | builder.col += 1; |
| 7048 | } |
| 7049 | builder.map.push(builder.pos, builder.pos + 1, txt); |
| 7050 | builder.pos++; |
| 7051 | } |
| 7052 | } |
| 7053 | if (style || startStyle || endStyle || mustWrap || css) { |
| 7054 | var fullStyle = style || ""; |
| 7055 | if (startStyle) fullStyle += startStyle; |
| 7056 | if (endStyle) fullStyle += endStyle; |
| 7057 | var token = elt("span", [content], fullStyle, css); |
| 7058 | if (title) token.title = title; |
| 7059 | return builder.content.appendChild(token); |
| 7060 | } |
| 7061 | builder.content.appendChild(content); |
| 7062 | } |
| 7063 | |