Fossil SCM
Cleanups in the auto-hyperlink code.
Commit
f04dde73d4a60aa10a338c4a634d4e8f3ae5f5c984139c092a644cc8a2d2e3d1
Parent
729e279a786dad8…
1 file changed
+17
-16
+17
-16
| --- tools/chat.tcl | ||
| +++ tools/chat.tcl | ||
| @@ -131,41 +131,42 @@ | ||
| 131 | 131 | }); |
| 132 | 132 | // Converts a message string to a message-containing DOM element |
| 133 | 133 | // and returns that element, which may contain child elements. |
| 134 | 134 | const messageToDOM = function f(str){ |
| 135 | 135 | "use strict"; |
| 136 | - if(!f.rx){ | |
| 137 | - f.rx = /\\b(?:https?|ftp):\\/\\/\[a-z0-9-+&@\#\\/%?=~_|!:,.;]*\[a-z0-9-+&@\#\\/%=~_|]/gim; | |
| 136 | + if(!f.rxUrl){ | |
| 137 | + f.rxUrl = /\\b(?:https?|ftp):\\/\\/\[a-z0-9-+&@\#\\/%?=~_|!:,.;]*\[a-z0-9-+&@\#\\/%=~_|]/gim; | |
| 138 | 138 | // ^^^ achtung, extra backslashes needed for the outer TCL. |
| 139 | 139 | f.ce = (T)=>document.createElement(T); |
| 140 | 140 | f.ct = (T)=>document.createTextNode(T); |
| 141 | - f.replacer = function(sub, offset){ | |
| 142 | - if(offset > f.prevStart){ | |
| 143 | - if(f.prevStart) f.accum.push(f.ct(' ')); | |
| 144 | - f.accum.push(f.ct(f.str.substring(f.prevStart, offset-1)+' ')); | |
| 141 | + f.replaceUrls = function ff(sub, off, whole){ | |
| 142 | + if(off > ff.prevStart){ | |
| 143 | + f.accum.push(f.ct((ff.prevStart?' ':'')+whole.substring(ff.prevStart, off-1)+' ')); | |
| 145 | 144 | } |
| 146 | 145 | const a = f.ce('a'); |
| 147 | 146 | a.setAttribute('href',sub); |
| 148 | 147 | a.setAttribute('target','_blank'); |
| 149 | 148 | a.appendChild(f.ct(sub)); |
| 150 | 149 | f.accum.push(a); |
| 151 | - f.prevStart = offset + sub.length + 1; | |
| 150 | + ff.prevStart = off + sub.length + 1; | |
| 152 | 151 | return sub; |
| 153 | - } | |
| 152 | + }; | |
| 154 | 153 | } |
| 155 | 154 | f.accum = []; |
| 156 | - f.rx.lastIndex = 0; | |
| 157 | - f.prevStart = 0; | |
| 158 | - f.str = str; | |
| 159 | - str.replace(f.rx, f.replacer); | |
| 160 | - f.rx.lastIndex = 0; | |
| 161 | - delete f.str; | |
| 162 | - if(f.prevStart < str.length){ | |
| 163 | - f.accum.push(f.ct((f.prevStart ? ' ' : '')+str.substring(f.prevStart))); | |
| 155 | + f.rxUrl.lastIndex = 0; | |
| 156 | + f.replaceUrls.prevStart = 0; | |
| 157 | + str.replace(f.rxUrl, f.replaceUrls); | |
| 158 | + if(f.replaceUrls.prevStart < str.length){ | |
| 159 | + f.accum.push(f.ct((f.replaceUrls.prevStart?' ':'')+str.substring(f.replaceUrls.prevStart))); | |
| 164 | 160 | } |
| 165 | 161 | const span = f.ce('span'); |
| 166 | 162 | f.accum.forEach((e)=>span.appendChild(e)); |
| 163 | + delete f.accum; | |
| 164 | + // TODO: replace @WORD refs with <span class='at-me'>@WORD</span>, but | |
| 165 | + // only when WORD==current user name. The above dissection into chunks | |
| 166 | + // complicates that somewhat, requiring a separate pass over the remaining | |
| 167 | + // TEXT nodes and a separate array to accumulate the results to. | |
| 167 | 168 | return span; |
| 168 | 169 | }; |
| 169 | 170 | function newcontent(jx){ |
| 170 | 171 | var tab = document.getElementById("dialog"); |
| 171 | 172 | var i; |
| 172 | 173 |
| --- tools/chat.tcl | |
| +++ tools/chat.tcl | |
| @@ -131,41 +131,42 @@ | |
| 131 | }); |
| 132 | // Converts a message string to a message-containing DOM element |
| 133 | // and returns that element, which may contain child elements. |
| 134 | const messageToDOM = function f(str){ |
| 135 | "use strict"; |
| 136 | if(!f.rx){ |
| 137 | f.rx = /\\b(?:https?|ftp):\\/\\/\[a-z0-9-+&@\#\\/%?=~_|!:,.;]*\[a-z0-9-+&@\#\\/%=~_|]/gim; |
| 138 | // ^^^ achtung, extra backslashes needed for the outer TCL. |
| 139 | f.ce = (T)=>document.createElement(T); |
| 140 | f.ct = (T)=>document.createTextNode(T); |
| 141 | f.replacer = function(sub, offset){ |
| 142 | if(offset > f.prevStart){ |
| 143 | if(f.prevStart) f.accum.push(f.ct(' ')); |
| 144 | f.accum.push(f.ct(f.str.substring(f.prevStart, offset-1)+' ')); |
| 145 | } |
| 146 | const a = f.ce('a'); |
| 147 | a.setAttribute('href',sub); |
| 148 | a.setAttribute('target','_blank'); |
| 149 | a.appendChild(f.ct(sub)); |
| 150 | f.accum.push(a); |
| 151 | f.prevStart = offset + sub.length + 1; |
| 152 | return sub; |
| 153 | } |
| 154 | } |
| 155 | f.accum = []; |
| 156 | f.rx.lastIndex = 0; |
| 157 | f.prevStart = 0; |
| 158 | f.str = str; |
| 159 | str.replace(f.rx, f.replacer); |
| 160 | f.rx.lastIndex = 0; |
| 161 | delete f.str; |
| 162 | if(f.prevStart < str.length){ |
| 163 | f.accum.push(f.ct((f.prevStart ? ' ' : '')+str.substring(f.prevStart))); |
| 164 | } |
| 165 | const span = f.ce('span'); |
| 166 | f.accum.forEach((e)=>span.appendChild(e)); |
| 167 | return span; |
| 168 | }; |
| 169 | function newcontent(jx){ |
| 170 | var tab = document.getElementById("dialog"); |
| 171 | var i; |
| 172 |
| --- tools/chat.tcl | |
| +++ tools/chat.tcl | |
| @@ -131,41 +131,42 @@ | |
| 131 | }); |
| 132 | // Converts a message string to a message-containing DOM element |
| 133 | // and returns that element, which may contain child elements. |
| 134 | const messageToDOM = function f(str){ |
| 135 | "use strict"; |
| 136 | if(!f.rxUrl){ |
| 137 | f.rxUrl = /\\b(?:https?|ftp):\\/\\/\[a-z0-9-+&@\#\\/%?=~_|!:,.;]*\[a-z0-9-+&@\#\\/%=~_|]/gim; |
| 138 | // ^^^ achtung, extra backslashes needed for the outer TCL. |
| 139 | f.ce = (T)=>document.createElement(T); |
| 140 | f.ct = (T)=>document.createTextNode(T); |
| 141 | f.replaceUrls = function ff(sub, off, whole){ |
| 142 | if(off > ff.prevStart){ |
| 143 | f.accum.push(f.ct((ff.prevStart?' ':'')+whole.substring(ff.prevStart, off-1)+' ')); |
| 144 | } |
| 145 | const a = f.ce('a'); |
| 146 | a.setAttribute('href',sub); |
| 147 | a.setAttribute('target','_blank'); |
| 148 | a.appendChild(f.ct(sub)); |
| 149 | f.accum.push(a); |
| 150 | ff.prevStart = off + sub.length + 1; |
| 151 | return sub; |
| 152 | }; |
| 153 | } |
| 154 | f.accum = []; |
| 155 | f.rxUrl.lastIndex = 0; |
| 156 | f.replaceUrls.prevStart = 0; |
| 157 | str.replace(f.rxUrl, f.replaceUrls); |
| 158 | if(f.replaceUrls.prevStart < str.length){ |
| 159 | f.accum.push(f.ct((f.replaceUrls.prevStart?' ':'')+str.substring(f.replaceUrls.prevStart))); |
| 160 | } |
| 161 | const span = f.ce('span'); |
| 162 | f.accum.forEach((e)=>span.appendChild(e)); |
| 163 | delete f.accum; |
| 164 | // TODO: replace @WORD refs with <span class='at-me'>@WORD</span>, but |
| 165 | // only when WORD==current user name. The above dissection into chunks |
| 166 | // complicates that somewhat, requiring a separate pass over the remaining |
| 167 | // TEXT nodes and a separate array to accumulate the results to. |
| 168 | return span; |
| 169 | }; |
| 170 | function newcontent(jx){ |
| 171 | var tab = document.getElementById("dialog"); |
| 172 | var i; |
| 173 |