Fossil SCM

Added hash_digits() info to fossil.config object and added fossil.hashDigits(). Factored out fileedit JS use of innerHTML where possible. Reworked the Version Info tab a bit.

stephan 2020-05-07 01:19 fileedit-ajaxify
Commit 29567e6e7ef1b05adaa9b5b4b33115c5b3c59f08c5fae04f076304b7e227412e
+1 -2
--- src/fileedit.c
+++ src/fileedit.c
@@ -1553,14 +1553,13 @@
15531553
CX("<div id='fileedit-tab-version' "
15541554
"data-tab-parent='fileedit-tabs' "
15551555
"data-tab-label='Version Info'"
15561556
">");
15571557
CX("File: "
1558
- "[<a id='finfo-link' href='#'>/finfo</a>] "
1559
- /* %R/finfo?name=%T&m=%!S */
15601558
"<code id='finfo-file-name'>(loading)</code><br>");
15611559
CX("Checkin Version: "
1560
+ "[<a id='timeline-link' href='#'>/timeline</a>] "
15621561
"[<a id='r-link' href='#'>/info</a>] "
15631562
/* %R/info/%!S */
15641563
"<code id='r-label'>(loading...)</code><br>"
15651564
);
15661565
CX("Permalink: <code>"
15671566
--- src/fileedit.c
+++ src/fileedit.c
@@ -1553,14 +1553,13 @@
1553 CX("<div id='fileedit-tab-version' "
1554 "data-tab-parent='fileedit-tabs' "
1555 "data-tab-label='Version Info'"
1556 ">");
1557 CX("File: "
1558 "[<a id='finfo-link' href='#'>/finfo</a>] "
1559 /* %R/finfo?name=%T&m=%!S */
1560 "<code id='finfo-file-name'>(loading)</code><br>");
1561 CX("Checkin Version: "
 
1562 "[<a id='r-link' href='#'>/info</a>] "
1563 /* %R/info/%!S */
1564 "<code id='r-label'>(loading...)</code><br>"
1565 );
1566 CX("Permalink: <code>"
1567
--- src/fileedit.c
+++ src/fileedit.c
@@ -1553,14 +1553,13 @@
1553 CX("<div id='fileedit-tab-version' "
1554 "data-tab-parent='fileedit-tabs' "
1555 "data-tab-label='Version Info'"
1556 ">");
1557 CX("File: "
 
 
1558 "<code id='finfo-file-name'>(loading)</code><br>");
1559 CX("Checkin Version: "
1560 "[<a id='timeline-link' href='#'>/timeline</a>] "
1561 "[<a id='r-link' href='#'>/info</a>] "
1562 /* %R/info/%!S */
1563 "<code id='r-label'>(loading...)</code><br>"
1564 );
1565 CX("Permalink: <code>"
1566
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -141,10 +141,27 @@
141141
if(o.hasOwnProperty(k)) rc[k] = o[k];
142142
}
143143
}
144144
return rc;
145145
};
146
+
147
+ /**
148
+ Expects to be passed as hash code as its first argument. It
149
+ returns a "shortened" form of hash, with a length which depends
150
+ on the 2nd argument: truthy = fossil.config.hashDigitsUrl, falsy
151
+ = fossil.config.hashDigits. Both of those values are derived from
152
+ the 'hash-digits' repo-level config setting or the
153
+ FOSSIL_HASH_DIGITS_URL/FOSSIL_HASH_DIGITS compile-time options.
154
+
155
+ If its first arugment is a non-string, that value is returned
156
+ as-is.
157
+ */
158
+ F.hashDigits = function(hash,forUrl){
159
+ return ('string'==typeof hash ? hash.substr(
160
+ 0, F.config[forUrl ? 'hashDigitsUrl' : 'hashDigits']
161
+ ) : hash);
162
+ };
146163
147164
/**
148165
Sets up pseudo-automatic content preview handling between a
149166
source element (typically a TEXTAREA) and a target rendering
150167
element (typically a DIV). The selector argument must be one of:
@@ -250,8 +267,7 @@
250267
}, false
251268
);
252269
});
253270
return this;
254271
};
255
-
256272
257273
})(window);
258274
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -141,10 +141,27 @@
141 if(o.hasOwnProperty(k)) rc[k] = o[k];
142 }
143 }
144 return rc;
145 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
147 /**
148 Sets up pseudo-automatic content preview handling between a
149 source element (typically a TEXTAREA) and a target rendering
150 element (typically a DIV). The selector argument must be one of:
@@ -250,8 +267,7 @@
250 }, false
251 );
252 });
253 return this;
254 };
255
256
257 })(window);
258
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -141,10 +141,27 @@
141 if(o.hasOwnProperty(k)) rc[k] = o[k];
142 }
143 }
144 return rc;
145 };
146
147 /**
148 Expects to be passed as hash code as its first argument. It
149 returns a "shortened" form of hash, with a length which depends
150 on the 2nd argument: truthy = fossil.config.hashDigitsUrl, falsy
151 = fossil.config.hashDigits. Both of those values are derived from
152 the 'hash-digits' repo-level config setting or the
153 FOSSIL_HASH_DIGITS_URL/FOSSIL_HASH_DIGITS compile-time options.
154
155 If its first arugment is a non-string, that value is returned
156 as-is.
157 */
158 F.hashDigits = function(hash,forUrl){
159 return ('string'==typeof hash ? hash.substr(
160 0, F.config[forUrl ? 'hashDigitsUrl' : 'hashDigits']
161 ) : hash);
162 };
163
164 /**
165 Sets up pseudo-automatic content preview handling between a
166 source element (typically a TEXTAREA) and a target rendering
167 element (typically a DIV). The selector argument must be one of:
@@ -250,8 +267,7 @@
267 }, false
268 );
269 });
270 return this;
271 };
 
272
273 })(window);
274
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -1,10 +1,12 @@
11
"use strict";
22
(function(F/*fossil object*/){
33
/**
4
- A collection of HTML DOM utilities to simplify, a bit,
5
- using the DOM API.
4
+ A collection of HTML DOM utilities to simplify, a bit, using the
5
+ DOM API. It is focused on manipulation of the DOM, but one of its
6
+ core mantras is "No innerHTML." Using innerHTML in this code, in
7
+ particular assigning to it, is absolutely verboten.
68
*/
79
const argsToArray = (a)=>Array.prototype.slice.call(a,0);
810
const isArray = (v)=>v instanceof Array;
911
1012
const dom = {
1113
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -1,10 +1,12 @@
1 "use strict";
2 (function(F/*fossil object*/){
3 /**
4 A collection of HTML DOM utilities to simplify, a bit,
5 using the DOM API.
 
 
6 */
7 const argsToArray = (a)=>Array.prototype.slice.call(a,0);
8 const isArray = (v)=>v instanceof Array;
9
10 const dom = {
11
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -1,10 +1,12 @@
1 "use strict";
2 (function(F/*fossil object*/){
3 /**
4 A collection of HTML DOM utilities to simplify, a bit, using the
5 DOM API. It is focused on manipulation of the DOM, but one of its
6 core mantras is "No innerHTML." Using innerHTML in this code, in
7 particular assigning to it, is absolutely verboten.
8 */
9 const argsToArray = (a)=>Array.prototype.slice.call(a,0);
10 const isArray = (v)=>v instanceof Array;
11
12 const dom = {
13
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -53,18 +53,15 @@
5353
"click",(e)=>P.diff(false), false
5454
);
5555
P.e.btnCommit.addEventListener(
5656
"click",(e)=>P.commit(), false
5757
);
58
- if(P.e.btnReload){
59
- const label = "Really reload, losing edits?";
60
- F.confirmer(P.e.btnReload, {
61
- confirmText: label,
62
- onconfirm: (e)=>P.loadFile(),
63
- ticks: 3
64
- });
65
- }
58
+ F.confirmer(P.e.btnReload, {
59
+ confirmText: "Really reload, losing edits?",
60
+ onconfirm: (e)=>P.loadFile(),
61
+ ticks: 3
62
+ });
6663
/**
6764
Cosmetic: jump through some hoops to enable/disable
6865
certain preview options depending on the current
6966
preview mode...
7067
*/
@@ -105,11 +102,10 @@
105102
selectFontSize.dispatchEvent(
106103
// Force UI update
107104
new Event('change',{target:selectFontSize})
108105
);
109106
}
110
-
111107
}, false)/*onload event handler*/;
112108
113109
/**
114110
updateVersion() updates the filename and version in various UI
115111
elements...
@@ -118,30 +114,35 @@
118114
*/
119115
P.updateVersion = function(file,rev){
120116
this.finfo = {filename:file,checkin:rev};
121117
const E = (s)=>document.querySelector(s),
122118
euc = encodeURIComponent,
123
- rShort = rev.substr(0,16);
124
- E('#r-label').innerText=rev;
125
- E('#finfo-link').setAttribute(
126
- 'href',
127
- F.repoUrl('finfo',{name:file, m:rShort})
128
- );
129
- E('#finfo-file-name').innerText=file;
130
- E('#r-link').setAttribute(
131
- 'href',
132
- F.repoUrl('info/'+rev)
133
- );
134
- E('#r-label').innerText = rev;
119
+ rHuman = F.hashDigits(rev),
120
+ rUrl = F.hashDigits(rev,true);
121
+ D.append(
122
+ D.clearElement(E('#r-label')),
123
+ rHuman
124
+ );
125
+ var e;
126
+ e = E('#timeline-link');
127
+ D.attr(e, 'href',F.repoUrl('timeline',{c:rUrl}));
128
+ e = E('#finfo-file-name');
129
+ D.append(
130
+ D.clearElement(e),
131
+ D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)
132
+ );
133
+ e = E('#r-link');
134
+ D.attr(e, 'href', F.repoUrl('info/'+rUrl));
135
+ e = E('#r-label');
136
+ D.append(D.clearElement(e),rHuman);
135137
const purlArgs = F.encodeUrlArgs({
136138
filename: this.finfo.filename,
137
- checkin: this.finfo.checkin
139
+ checkin: rUrl
138140
},false,true);
139141
const purl = F.repoUrl('fileedit',purlArgs);
140
- const e = E('#permalink');
141
- e.innerText='fileedit?'+purlArgs;
142
- e.setAttribute('href',purl);
142
+ e = E('#permalink');
143
+ D.attr(D.append(D.clearElement(e),'?'+purlArgs),'href', purl);
143144
return this;
144145
};
145146
146147
/**
147148
loadFile() loads (file,checkinVersion) and updates the relevant
@@ -187,13 +188,11 @@
187188
'#fileedit-tab-preview-wrapper'
188189
);
189190
const self = this;
190191
const updateView = function(c){
191192
D.clearElement(target);
192
- if('string'===typeof c){
193
- target.innerHTML = c;
194
- }
193
+ if('string'===typeof c) target.innerHTML = c;
195194
if(switchToTab) self.tabs.switchToTab(self.e.tabs.preview);
196195
};
197196
const content = this.e.taEditor.value;
198197
if(!content){
199198
updateView('');
@@ -290,19 +289,19 @@
290289
if(!f.updateView){
291290
f.updateView = function(c){
292291
target.innerHTML = [
293292
"<h3>Manifest",
294293
(c.dryRun?" (dry run)":""),
295
- ": ", c.uuid.substring(0,16),"</h3>",
294
+ ": ", F.hashDigits(c.uuid),"</h3>",
296295
"<code class='fileedit-manifest'>",
297296
c.manifest,
298297
"</code></pre>"
299298
].join('');
300299
const msg = [
301300
'Committed',
302301
c.dryRun ? '(dry run)' : '',
303
- '[', c.uuid,'].'
302
+ '[', F.hashDigits(c.uuid) ,'].'
304303
];
305304
if(!c.dryRun){
306305
msg.push('Re-activating dry-run mode.');
307306
self.e.taComment.value = '';
308307
cbDryRun.checked = true;
309308
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -53,18 +53,15 @@
53 "click",(e)=>P.diff(false), false
54 );
55 P.e.btnCommit.addEventListener(
56 "click",(e)=>P.commit(), false
57 );
58 if(P.e.btnReload){
59 const label = "Really reload, losing edits?";
60 F.confirmer(P.e.btnReload, {
61 confirmText: label,
62 onconfirm: (e)=>P.loadFile(),
63 ticks: 3
64 });
65 }
66 /**
67 Cosmetic: jump through some hoops to enable/disable
68 certain preview options depending on the current
69 preview mode...
70 */
@@ -105,11 +102,10 @@
105 selectFontSize.dispatchEvent(
106 // Force UI update
107 new Event('change',{target:selectFontSize})
108 );
109 }
110
111 }, false)/*onload event handler*/;
112
113 /**
114 updateVersion() updates the filename and version in various UI
115 elements...
@@ -118,30 +114,35 @@
118 */
119 P.updateVersion = function(file,rev){
120 this.finfo = {filename:file,checkin:rev};
121 const E = (s)=>document.querySelector(s),
122 euc = encodeURIComponent,
123 rShort = rev.substr(0,16);
124 E('#r-label').innerText=rev;
125 E('#finfo-link').setAttribute(
126 'href',
127 F.repoUrl('finfo',{name:file, m:rShort})
128 );
129 E('#finfo-file-name').innerText=file;
130 E('#r-link').setAttribute(
131 'href',
132 F.repoUrl('info/'+rev)
133 );
134 E('#r-label').innerText = rev;
 
 
 
 
 
 
135 const purlArgs = F.encodeUrlArgs({
136 filename: this.finfo.filename,
137 checkin: this.finfo.checkin
138 },false,true);
139 const purl = F.repoUrl('fileedit',purlArgs);
140 const e = E('#permalink');
141 e.innerText='fileedit?'+purlArgs;
142 e.setAttribute('href',purl);
143 return this;
144 };
145
146 /**
147 loadFile() loads (file,checkinVersion) and updates the relevant
@@ -187,13 +188,11 @@
187 '#fileedit-tab-preview-wrapper'
188 );
189 const self = this;
190 const updateView = function(c){
191 D.clearElement(target);
192 if('string'===typeof c){
193 target.innerHTML = c;
194 }
195 if(switchToTab) self.tabs.switchToTab(self.e.tabs.preview);
196 };
197 const content = this.e.taEditor.value;
198 if(!content){
199 updateView('');
@@ -290,19 +289,19 @@
290 if(!f.updateView){
291 f.updateView = function(c){
292 target.innerHTML = [
293 "<h3>Manifest",
294 (c.dryRun?" (dry run)":""),
295 ": ", c.uuid.substring(0,16),"</h3>",
296 "<code class='fileedit-manifest'>",
297 c.manifest,
298 "</code></pre>"
299 ].join('');
300 const msg = [
301 'Committed',
302 c.dryRun ? '(dry run)' : '',
303 '[', c.uuid,'].'
304 ];
305 if(!c.dryRun){
306 msg.push('Re-activating dry-run mode.');
307 self.e.taComment.value = '';
308 cbDryRun.checked = true;
309
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -53,18 +53,15 @@
53 "click",(e)=>P.diff(false), false
54 );
55 P.e.btnCommit.addEventListener(
56 "click",(e)=>P.commit(), false
57 );
58 F.confirmer(P.e.btnReload, {
59 confirmText: "Really reload, losing edits?",
60 onconfirm: (e)=>P.loadFile(),
61 ticks: 3
62 });
 
 
 
63 /**
64 Cosmetic: jump through some hoops to enable/disable
65 certain preview options depending on the current
66 preview mode...
67 */
@@ -105,11 +102,10 @@
102 selectFontSize.dispatchEvent(
103 // Force UI update
104 new Event('change',{target:selectFontSize})
105 );
106 }
 
107 }, false)/*onload event handler*/;
108
109 /**
110 updateVersion() updates the filename and version in various UI
111 elements...
@@ -118,30 +114,35 @@
114 */
115 P.updateVersion = function(file,rev){
116 this.finfo = {filename:file,checkin:rev};
117 const E = (s)=>document.querySelector(s),
118 euc = encodeURIComponent,
119 rHuman = F.hashDigits(rev),
120 rUrl = F.hashDigits(rev,true);
121 D.append(
122 D.clearElement(E('#r-label')),
123 rHuman
124 );
125 var e;
126 e = E('#timeline-link');
127 D.attr(e, 'href',F.repoUrl('timeline',{c:rUrl}));
128 e = E('#finfo-file-name');
129 D.append(
130 D.clearElement(e),
131 D.a(F.repoUrl('finfo',{name:file, m:rUrl}), file)
132 );
133 e = E('#r-link');
134 D.attr(e, 'href', F.repoUrl('info/'+rUrl));
135 e = E('#r-label');
136 D.append(D.clearElement(e),rHuman);
137 const purlArgs = F.encodeUrlArgs({
138 filename: this.finfo.filename,
139 checkin: rUrl
140 },false,true);
141 const purl = F.repoUrl('fileedit',purlArgs);
142 e = E('#permalink');
143 D.attr(D.append(D.clearElement(e),'?'+purlArgs),'href', purl);
 
144 return this;
145 };
146
147 /**
148 loadFile() loads (file,checkinVersion) and updates the relevant
@@ -187,13 +188,11 @@
188 '#fileedit-tab-preview-wrapper'
189 );
190 const self = this;
191 const updateView = function(c){
192 D.clearElement(target);
193 if('string'===typeof c) target.innerHTML = c;
 
 
194 if(switchToTab) self.tabs.switchToTab(self.e.tabs.preview);
195 };
196 const content = this.e.taEditor.value;
197 if(!content){
198 updateView('');
@@ -290,19 +289,19 @@
289 if(!f.updateView){
290 f.updateView = function(c){
291 target.innerHTML = [
292 "<h3>Manifest",
293 (c.dryRun?" (dry run)":""),
294 ": ", F.hashDigits(c.uuid),"</h3>",
295 "<code class='fileedit-manifest'>",
296 c.manifest,
297 "</code></pre>"
298 ].join('');
299 const msg = [
300 'Committed',
301 c.dryRun ? '(dry run)' : '',
302 '[', F.hashDigits(c.uuid) ,'].'
303 ];
304 if(!c.dryRun){
305 msg.push('Re-activating dry-run mode.');
306 self.e.taComment.value = '';
307 cbDryRun.checked = true;
308
+10 -5
--- src/style.c
+++ src/style.c
@@ -1447,23 +1447,28 @@
14471447
style_emit_script_tag(0,0);
14481448
CX("(function(){\n"
14491449
"if(!window.fossil) window.fossil={};\n"
14501450
"window.fossil.version = \"%j\";\n"
14511451
/* fossil.rootPath is the top-most CGI/server path,
1452
- including a trailing slash. */
1452
+ ** including a trailing slash. */
14531453
"window.fossil.rootPath = \"%j\"+'/';\n",
14541454
get_version(), g.zTop);
1455
+ /* fossil.config = {...various config-level options...} */
1456
+ CX("window.fossil.config = {"
1457
+ "hashDigits: %d, hashDigitsUrl: %d"
1458
+ "};\n", hash_digits(0), hash_digits(1));
14551459
/*
1456
- ** fossil.page holds info about the current page. This is
1457
- ** also where the current page "should" store any of its
1458
- ** own page-specific state.
1460
+ ** fossil.page holds info about the current page. This is also
1461
+ ** where the current page "should" store any of its own
1462
+ ** page-specific state, and it is reserved for that purpose.
14591463
*/
14601464
CX("window.fossil.page = {"
14611465
"page:\"%T\""
14621466
"};\n", g.zPath);
14631467
CX("})();\n");
1464
- /* The remaining code is not dependent on C-runtime state... */
1468
+ /* The remaining fossil object bootstrap code is not dependent on
1469
+ ** C-runtime state... */
14651470
if(asInline){
14661471
CX("%s\n", builtin_text("fossil.bootstrap.js"));
14671472
}
14681473
style_emit_script_tag(1,0);
14691474
if(asInline==0){
14701475
--- src/style.c
+++ src/style.c
@@ -1447,23 +1447,28 @@
1447 style_emit_script_tag(0,0);
1448 CX("(function(){\n"
1449 "if(!window.fossil) window.fossil={};\n"
1450 "window.fossil.version = \"%j\";\n"
1451 /* fossil.rootPath is the top-most CGI/server path,
1452 including a trailing slash. */
1453 "window.fossil.rootPath = \"%j\"+'/';\n",
1454 get_version(), g.zTop);
 
 
 
 
1455 /*
1456 ** fossil.page holds info about the current page. This is
1457 ** also where the current page "should" store any of its
1458 ** own page-specific state.
1459 */
1460 CX("window.fossil.page = {"
1461 "page:\"%T\""
1462 "};\n", g.zPath);
1463 CX("})();\n");
1464 /* The remaining code is not dependent on C-runtime state... */
 
1465 if(asInline){
1466 CX("%s\n", builtin_text("fossil.bootstrap.js"));
1467 }
1468 style_emit_script_tag(1,0);
1469 if(asInline==0){
1470
--- src/style.c
+++ src/style.c
@@ -1447,23 +1447,28 @@
1447 style_emit_script_tag(0,0);
1448 CX("(function(){\n"
1449 "if(!window.fossil) window.fossil={};\n"
1450 "window.fossil.version = \"%j\";\n"
1451 /* fossil.rootPath is the top-most CGI/server path,
1452 ** including a trailing slash. */
1453 "window.fossil.rootPath = \"%j\"+'/';\n",
1454 get_version(), g.zTop);
1455 /* fossil.config = {...various config-level options...} */
1456 CX("window.fossil.config = {"
1457 "hashDigits: %d, hashDigitsUrl: %d"
1458 "};\n", hash_digits(0), hash_digits(1));
1459 /*
1460 ** fossil.page holds info about the current page. This is also
1461 ** where the current page "should" store any of its own
1462 ** page-specific state, and it is reserved for that purpose.
1463 */
1464 CX("window.fossil.page = {"
1465 "page:\"%T\""
1466 "};\n", g.zPath);
1467 CX("})();\n");
1468 /* The remaining fossil object bootstrap code is not dependent on
1469 ** C-runtime state... */
1470 if(asInline){
1471 CX("%s\n", builtin_text("fossil.bootstrap.js"));
1472 }
1473 style_emit_script_tag(1,0);
1474 if(asInline==0){
1475

Keyboard Shortcuts

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