Fossil SCM

chat: hyperlink URL-looking patterns in messages.

stephan 2020-12-22 07:11 chatroom-dev
Commit 729e279a786dad89696110171cff843ce99b6dc0e0afbb7f2ccdaf797904cfb1
1 file changed +42 -2
+42 -2
--- tools/chat.tcl
+++ tools/chat.tcl
@@ -73,10 +73,13 @@
7373
padding: 0.5em;
7474
border-radius: 1em;
7575
background-color: #d2dde1;
7676
border: 1px solid black;
7777
}
78
+\#dialog {
79
+ width: 97%;
80
+}
7881
\#chat-input-area {
7982
width: 100%;
8083
display: flex;
8184
flex-direction: column;
8285
}
@@ -124,10 +127,47 @@
124127
}
125128
form.msg.value = "";
126129
form.file.value = "";
127130
form.msg.focus();
128131
});
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
+ };
129169
function newcontent(jx){
130170
var tab = document.getElementById("dialog");
131171
var i;
132172
for(i=0; i<jx.msgs.length; ++i){
133173
let m = jx.msgs[i];
@@ -157,12 +197,12 @@
157197
}
158198
let br = document.createElement("br");
159199
br.style.clear = "both";
160200
span.appendChild(br);
161201
}
162
- //console.debug("m =",m);
163
- span.appendChild(document.createTextNode(m.xmsg));
202
+ const dmsg = messageToDOM(m.xmsg || "??empty??");
203
+ span.appendChild(dmsg);
164204
if( m.xfrom!=_me ){
165205
span.classList.add('chat-mx');
166206
}else{
167207
span.classList.add('chat-ms');
168208
}
169209
--- tools/chat.tcl
+++ tools/chat.tcl
@@ -73,10 +73,13 @@
73 padding: 0.5em;
74 border-radius: 1em;
75 background-color: #d2dde1;
76 border: 1px solid black;
77 }
 
 
 
78 \#chat-input-area {
79 width: 100%;
80 display: flex;
81 flex-direction: column;
82 }
@@ -124,10 +127,47 @@
124 }
125 form.msg.value = "";
126 form.file.value = "";
127 form.msg.focus();
128 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129 function newcontent(jx){
130 var tab = document.getElementById("dialog");
131 var i;
132 for(i=0; i<jx.msgs.length; ++i){
133 let m = jx.msgs[i];
@@ -157,12 +197,12 @@
157 }
158 let br = document.createElement("br");
159 br.style.clear = "both";
160 span.appendChild(br);
161 }
162 //console.debug("m =",m);
163 span.appendChild(document.createTextNode(m.xmsg));
164 if( m.xfrom!=_me ){
165 span.classList.add('chat-mx');
166 }else{
167 span.classList.add('chat-ms');
168 }
169
--- tools/chat.tcl
+++ tools/chat.tcl
@@ -73,10 +73,13 @@
73 padding: 0.5em;
74 border-radius: 1em;
75 background-color: #d2dde1;
76 border: 1px solid black;
77 }
78 \#dialog {
79 width: 97%;
80 }
81 \#chat-input-area {
82 width: 100%;
83 display: flex;
84 flex-direction: column;
85 }
@@ -124,10 +127,47 @@
127 }
128 form.msg.value = "";
129 form.file.value = "";
130 form.msg.focus();
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 for(i=0; i<jx.msgs.length; ++i){
173 let m = jx.msgs[i];
@@ -157,12 +197,12 @@
197 }
198 let br = document.createElement("br");
199 br.style.clear = "both";
200 span.appendChild(br);
201 }
202 const dmsg = messageToDOM(m.xmsg || "??empty??");
203 span.appendChild(dmsg);
204 if( m.xfrom!=_me ){
205 span.classList.add('chat-mx');
206 }else{
207 span.classList.add('chat-ms');
208 }
209

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button