Fossil SCM

/fileedit now accommodates relative links in wiki-rendered previews by dynamically adjusting/restoring the base.href when the preview tab is selected/deselected, and the backend can now report to the client, via response header, which rendering mode was selected, allowing the UI to adjust from 'Guess' to the current format.

stephan 2020-05-12 13:25 fileedit-ajaxify
Commit 2bec2c758f5a1a1373bede86bb1ff8b1ea3424f2151a768e9cfa9cd9ccb9060b
+30 -15
--- src/fileedit.c
+++ src/fileedit.c
@@ -935,21 +935,24 @@
935935
return rc;
936936
}
937937
938938
/*
939939
** Performs the PREVIEW mode for /filepage.
940
+**
941
+** If *renderMode==FE_RENDER_GUESS then *renderMode gets set to the
942
+** mode which is guessed at for the rendering.
940943
*/
941944
static void fileedit_render_preview(Blob * pContent,
942945
const char *zFilename,
943
- int flags, int renderMode,
946
+ int flags, int * renderMode,
944947
int nIframeHeightEm){
945948
const char * zMime;
946949
zMime = mimetype_from_name(zFilename);
947
- if(FE_RENDER_GUESS==renderMode){
948
- renderMode = fileedit_render_mode_for_mimetype(zMime);
950
+ if(FE_RENDER_GUESS==*renderMode){
951
+ *renderMode = fileedit_render_mode_for_mimetype(zMime);
949952
}
950
- switch(renderMode){
953
+ switch(*renderMode){
951954
case FE_RENDER_HTML_IFRAME:{
952955
char * z64 = encode64(blob_str(pContent), blob_size(pContent));
953956
CX("<iframe width='100%%' frameborder='0' "
954957
"marginwidth='0' style='height:%dem' "
955958
"marginheight='0' sandbox='allow-same-origin' "
@@ -1239,21 +1242,41 @@
12391242
const char * zContent = P("content");
12401243
int renderMode = atoi(PD("render_mode","0"));
12411244
int ln = atoi(PD("ln","0"));
12421245
int iframeHeight = atoi(PD("iframe_height","40"));
12431246
Blob content = empty_blob;
1244
-
1247
+ const char * zRenderMode = 0;
12451248
fileedit_get_fnci_args( &zFilename, 0 );
12461249
if(!fileedit_ajax_boostrap()
12471250
|| !fileedit_ajax_check_filename(zFilename)){
12481251
return;
12491252
}
12501253
cgi_set_content_type("text/html");
12511254
blob_init(&content, zContent, -1);
12521255
fileedit_render_preview(&content, zFilename,
12531256
ln ? FE_PREVIEW_LINE_NUMBERS : 0,
1254
- renderMode, iframeHeight);
1257
+ &renderMode, iframeHeight);
1258
+ /*
1259
+ ** Now tell the caller if we did indeed use FE_RENDER_WIKI, so that
1260
+ ** they can re-set the <base href> to an appropriate value (which
1261
+ ** requires knowing the content's current checkin version, which we
1262
+ ** don't have here).
1263
+ */
1264
+ switch(renderMode){
1265
+ /* The strings used here MUST correspond to those used in the JS-side
1266
+ ** fossil.page.previewModes map.
1267
+ */
1268
+ case FE_RENDER_WIKI: zRenderMode = "wiki"; break;
1269
+ case FE_RENDER_HTML_INLINE: zRenderMode = "htmlInline"; break;
1270
+ case FE_RENDER_HTML_IFRAME: zRenderMode = "htmlIframe"; break;
1271
+ case FE_RENDER_PLAIN_TEXT: zRenderMode = "text"; break;
1272
+ case FE_RENDER_GUESS:
1273
+ assert(!"cannot happen");
1274
+ }
1275
+ if(zRenderMode!=0){
1276
+ cgi_printf_header("X-fileedit-render-mode: %s\r\n", zRenderMode);
1277
+ }
12551278
}
12561279
12571280
/*
12581281
** AJAX route /fileedit?ajax=diff
12591282
**
@@ -1786,13 +1809,11 @@
17861809
{
17871810
CX("<div id='fileedit-tab-preview' "
17881811
"data-tab-parent='fileedit-tabs' "
17891812
"data-tab-label='Preview'"
17901813
">");
1791
-
1792
- CX("<div class='fileedit-options flex-container flex-column'>");
1793
- CX("<div class='flex-container flex-row'>");
1814
+ CX("<div class='fileedit-options flex-container flex-row'>");
17941815
CX("<button id='btn-preview-refresh' "
17951816
"data-f-preview-from='fileedit-content-editor' "
17961817
/* ^^^ text source elem ID*/
17971818
"data-f-preview-via='_postPreview' "
17981819
/* ^^^ fossil.page[methodName](content, callback) */
@@ -1853,16 +1874,10 @@
18531874
"preview_ln",
18541875
"Add line numbers to plain-text previews?",
18551876
"1", P("preview_ln")!=0,
18561877
"If on, plain-text files (only) will get "
18571878
"line numbers added to the preview.");
1858
- CX("</div>"/*.flex-container.flex-row (buttons/options)*/);
1859
- CX("<div class='fileedit-hint'>"
1860
- "Note that hyperlinks in previewed HTML are relative to "
1861
- "<em>this</em> page, and therefore not correct. Clicking "
1862
- "them will leave this page, losing any edits."
1863
- "</div>");
18641879
CX("</div>"/*.fileedit-options*/);
18651880
CX("<div id='fileedit-tab-preview-wrapper'></div>");
18661881
CX("</div>"/*#fileedit-tab-preview*/);
18671882
}
18681883
18691884
--- src/fileedit.c
+++ src/fileedit.c
@@ -935,21 +935,24 @@
935 return rc;
936 }
937
938 /*
939 ** Performs the PREVIEW mode for /filepage.
 
 
 
940 */
941 static void fileedit_render_preview(Blob * pContent,
942 const char *zFilename,
943 int flags, int renderMode,
944 int nIframeHeightEm){
945 const char * zMime;
946 zMime = mimetype_from_name(zFilename);
947 if(FE_RENDER_GUESS==renderMode){
948 renderMode = fileedit_render_mode_for_mimetype(zMime);
949 }
950 switch(renderMode){
951 case FE_RENDER_HTML_IFRAME:{
952 char * z64 = encode64(blob_str(pContent), blob_size(pContent));
953 CX("<iframe width='100%%' frameborder='0' "
954 "marginwidth='0' style='height:%dem' "
955 "marginheight='0' sandbox='allow-same-origin' "
@@ -1239,21 +1242,41 @@
1239 const char * zContent = P("content");
1240 int renderMode = atoi(PD("render_mode","0"));
1241 int ln = atoi(PD("ln","0"));
1242 int iframeHeight = atoi(PD("iframe_height","40"));
1243 Blob content = empty_blob;
1244
1245 fileedit_get_fnci_args( &zFilename, 0 );
1246 if(!fileedit_ajax_boostrap()
1247 || !fileedit_ajax_check_filename(zFilename)){
1248 return;
1249 }
1250 cgi_set_content_type("text/html");
1251 blob_init(&content, zContent, -1);
1252 fileedit_render_preview(&content, zFilename,
1253 ln ? FE_PREVIEW_LINE_NUMBERS : 0,
1254 renderMode, iframeHeight);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1255 }
1256
1257 /*
1258 ** AJAX route /fileedit?ajax=diff
1259 **
@@ -1786,13 +1809,11 @@
1786 {
1787 CX("<div id='fileedit-tab-preview' "
1788 "data-tab-parent='fileedit-tabs' "
1789 "data-tab-label='Preview'"
1790 ">");
1791
1792 CX("<div class='fileedit-options flex-container flex-column'>");
1793 CX("<div class='flex-container flex-row'>");
1794 CX("<button id='btn-preview-refresh' "
1795 "data-f-preview-from='fileedit-content-editor' "
1796 /* ^^^ text source elem ID*/
1797 "data-f-preview-via='_postPreview' "
1798 /* ^^^ fossil.page[methodName](content, callback) */
@@ -1853,16 +1874,10 @@
1853 "preview_ln",
1854 "Add line numbers to plain-text previews?",
1855 "1", P("preview_ln")!=0,
1856 "If on, plain-text files (only) will get "
1857 "line numbers added to the preview.");
1858 CX("</div>"/*.flex-container.flex-row (buttons/options)*/);
1859 CX("<div class='fileedit-hint'>"
1860 "Note that hyperlinks in previewed HTML are relative to "
1861 "<em>this</em> page, and therefore not correct. Clicking "
1862 "them will leave this page, losing any edits."
1863 "</div>");
1864 CX("</div>"/*.fileedit-options*/);
1865 CX("<div id='fileedit-tab-preview-wrapper'></div>");
1866 CX("</div>"/*#fileedit-tab-preview*/);
1867 }
1868
1869
--- src/fileedit.c
+++ src/fileedit.c
@@ -935,21 +935,24 @@
935 return rc;
936 }
937
938 /*
939 ** Performs the PREVIEW mode for /filepage.
940 **
941 ** If *renderMode==FE_RENDER_GUESS then *renderMode gets set to the
942 ** mode which is guessed at for the rendering.
943 */
944 static void fileedit_render_preview(Blob * pContent,
945 const char *zFilename,
946 int flags, int * renderMode,
947 int nIframeHeightEm){
948 const char * zMime;
949 zMime = mimetype_from_name(zFilename);
950 if(FE_RENDER_GUESS==*renderMode){
951 *renderMode = fileedit_render_mode_for_mimetype(zMime);
952 }
953 switch(*renderMode){
954 case FE_RENDER_HTML_IFRAME:{
955 char * z64 = encode64(blob_str(pContent), blob_size(pContent));
956 CX("<iframe width='100%%' frameborder='0' "
957 "marginwidth='0' style='height:%dem' "
958 "marginheight='0' sandbox='allow-same-origin' "
@@ -1239,21 +1242,41 @@
1242 const char * zContent = P("content");
1243 int renderMode = atoi(PD("render_mode","0"));
1244 int ln = atoi(PD("ln","0"));
1245 int iframeHeight = atoi(PD("iframe_height","40"));
1246 Blob content = empty_blob;
1247 const char * zRenderMode = 0;
1248 fileedit_get_fnci_args( &zFilename, 0 );
1249 if(!fileedit_ajax_boostrap()
1250 || !fileedit_ajax_check_filename(zFilename)){
1251 return;
1252 }
1253 cgi_set_content_type("text/html");
1254 blob_init(&content, zContent, -1);
1255 fileedit_render_preview(&content, zFilename,
1256 ln ? FE_PREVIEW_LINE_NUMBERS : 0,
1257 &renderMode, iframeHeight);
1258 /*
1259 ** Now tell the caller if we did indeed use FE_RENDER_WIKI, so that
1260 ** they can re-set the <base href> to an appropriate value (which
1261 ** requires knowing the content's current checkin version, which we
1262 ** don't have here).
1263 */
1264 switch(renderMode){
1265 /* The strings used here MUST correspond to those used in the JS-side
1266 ** fossil.page.previewModes map.
1267 */
1268 case FE_RENDER_WIKI: zRenderMode = "wiki"; break;
1269 case FE_RENDER_HTML_INLINE: zRenderMode = "htmlInline"; break;
1270 case FE_RENDER_HTML_IFRAME: zRenderMode = "htmlIframe"; break;
1271 case FE_RENDER_PLAIN_TEXT: zRenderMode = "text"; break;
1272 case FE_RENDER_GUESS:
1273 assert(!"cannot happen");
1274 }
1275 if(zRenderMode!=0){
1276 cgi_printf_header("X-fileedit-render-mode: %s\r\n", zRenderMode);
1277 }
1278 }
1279
1280 /*
1281 ** AJAX route /fileedit?ajax=diff
1282 **
@@ -1786,13 +1809,11 @@
1809 {
1810 CX("<div id='fileedit-tab-preview' "
1811 "data-tab-parent='fileedit-tabs' "
1812 "data-tab-label='Preview'"
1813 ">");
1814 CX("<div class='fileedit-options flex-container flex-row'>");
 
 
1815 CX("<button id='btn-preview-refresh' "
1816 "data-f-preview-from='fileedit-content-editor' "
1817 /* ^^^ text source elem ID*/
1818 "data-f-preview-via='_postPreview' "
1819 /* ^^^ fossil.page[methodName](content, callback) */
@@ -1853,16 +1874,10 @@
1874 "preview_ln",
1875 "Add line numbers to plain-text previews?",
1876 "1", P("preview_ln")!=0,
1877 "If on, plain-text files (only) will get "
1878 "line numbers added to the preview.");
 
 
 
 
 
 
1879 CX("</div>"/*.fileedit-options*/);
1880 CX("<div id='fileedit-tab-preview-wrapper'></div>");
1881 CX("</div>"/*#fileedit-tab-preview*/);
1882 }
1883
1884
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -150,23 +150,43 @@
150150
btnReload.addEventListener(
151151
'click', (e)=>this.loadLeaves(), false
152152
);
153153
delete this.init;
154154
}
155
+ }/*P.fileSelector*/;
156
+
157
+ /**
158
+ Internal workaround to select the current preview mode
159
+ and fire a change event if the value actually changes
160
+ or if forceEvent is truthy.
161
+ */
162
+ P.selectPreviewMode = function(modeValue, forceEvent){
163
+ const s = this.e.selectPreviewMode;
164
+ if(!modeValue) modeValue = s.value;
165
+ else if(s.value != modeValue){
166
+ s.value = modeValue;
167
+ forceEvent = true;
168
+ }
169
+ if(forceEvent){
170
+ // Force UI update
171
+ s.dispatchEvent(new Event('change',{target:s}));
172
+ }
155173
};
156174
157175
window.addEventListener("load", function() {
176
+ P.base = {tag: E('base')};
177
+ P.base.originalHref = P.base.tag.href;
158178
P.tabs = new fossil.TabManager('#fileedit-tabs');
159179
P.e = {
160180
taEditor: E('#fileedit-content-editor'),
161181
taCommentSmall: E('#fileedit-comment'),
162182
taCommentBig: E('#fileedit-comment-big'),
163183
ajaxContentTarget: E('#ajax-target'),
164184
btnCommit: E("#fileedit-btn-commit"),
165185
btnReload: E("#fileedit-tab-content > .fileedit-options > "
166186
+"button.fileedit-content-reload"),
167
- selectPreviewModeWrap: E('#select-preview-mode'),
187
+ selectPreviewMode: E('#select-preview-mode select'),
168188
selectHtmlEmsWrap: E('#select-preview-html-ems'),
169189
selectEolWrap: E('#select-preview-html-ems'),
170190
cbLineNumbersWrap: E('#cb-line-numbers'),
171191
cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
172192
tabs:{
@@ -199,13 +219,21 @@
199219
);
200220
201221
P.tabs.addEventListener(
202222
/* Set up auto-refresh of the preview tab... */
203223
'before-switch-to', function(ev){
204
- if(ev.detail===P.e.tabs.preview
205
- && P.e.cbAutoPreview.checked){
206
- P.preview();
224
+ if(ev.detail===P.e.tabs.preview){
225
+ P.baseHrefForFile();
226
+ if(P.e.cbAutoPreview.checked) P.preview();
227
+ }
228
+ }
229
+ );
230
+ P.tabs.addEventListener(
231
+ /* Set up auto-refresh of the preview tab... */
232
+ 'before-switch-from', function(ev){
233
+ if(ev.detail===P.e.tabs.preview){
234
+ P.baseHrefRestore();
207235
}
208236
}
209237
);
210238
211239
F.connectPagePreviewers(
@@ -236,17 +264,16 @@
236264
/**
237265
Cosmetic: jump through some hoops to enable/disable
238266
certain preview options depending on the current
239267
preview mode...
240268
*/
241
- const selectPreviewMode =
242
- P.e.selectPreviewModeWrap.querySelector('select');
243
- selectPreviewMode.addEventListener(
269
+ P.e.selectPreviewMode.addEventListener(
244270
"change", function(e){
245271
const mode = e.target.value,
246272
name = P.previewModes[mode],
247273
hide = [], unhide = [];
274
+ P.previewModes.current = name;
248275
if('guess'===name){
249276
unhide.push(P.e.cbLineNumbersWrap,
250277
P.e.selectHtmlEmsWrap);
251278
}else{
252279
if('text'===name) unhide.push(P.e.cbLineNumbersWrap);
@@ -256,14 +283,11 @@
256283
}
257284
hide.forEach((e)=>e.classList.add('hidden'));
258285
unhide.forEach((e)=>e.classList.remove('hidden'));
259286
}, false
260287
);
261
- selectPreviewMode.dispatchEvent(
262
- // Force UI update
263
- new Event('change',{target:selectPreviewMode})
264
- );
288
+ P.selectPreviewMode(false, true);
265289
const selectFontSize = E('select[name=editor_font_size]');
266290
if(selectFontSize){
267291
selectFontSize.addEventListener(
268292
"change",function(e){
269293
const ed = P.e.taEditor;
@@ -294,10 +318,51 @@
294318
}else{
295319
this.e.taEditor.value = arguments[0];
296320
return this;
297321
}
298322
};
323
+
324
+ /**
325
+ If either of...
326
+
327
+ - P.previewModes.current==='wiki'
328
+
329
+ - P.previewModes.current==='guess' AND the currently-loaded
330
+ file has an extension of (md|wiki)
331
+
332
+ ... then this function updates the document's base.href to a
333
+ repo-relative /doc/{{this.finfo.checkin}}/{{directory part of
334
+ this.finfo.filename}}/
335
+
336
+ If neither of those conditions applies, this is a no-op.
337
+ */
338
+ P.baseHrefForFile = function f(){
339
+ const fn = this.finfo ? this.finfo.filename : undefined;
340
+ if(!fn) return this;
341
+ if(!f.rxWiki){
342
+ f.rxWiki = /\.(wiki|md)$/i;
343
+ }
344
+ if('wiki'===P.previewModes.current
345
+ || ('guess'===P.previewModes.current
346
+ && f.rxWiki.test(fn))){
347
+ const a = fn.split('/');
348
+ a.pop();
349
+ this.base.tag.href = F.repoUrl(
350
+ 'doc/'+F.hashDigits(this.finfo.checkin)
351
+ +'/'+(a.length ? a.join('/')+'/' : '')
352
+ );
353
+ }
354
+ return this;
355
+ };
356
+
357
+ /**
358
+ Sets the document's base.href value to its page-load-time
359
+ setting.
360
+ */
361
+ P.baseHrefRestore = function(){
362
+ P.base.tag.href = P.base.originalHref;
363
+ };
299364
300365
/**
301366
Toggles between single- and multi-line comment
302367
mode.
303368
*/
@@ -433,21 +498,25 @@
433498
if(!content){
434499
callback(content);
435500
return this;
436501
}
437502
const fd = new FormData();
438
- fd.append('render_mode',E('select[name=preview_render_mode]').value);
503
+ fd.append('render_mode',this.e.selectPreviewMode.value);
439504
fd.append('filename',this.finfo.filename);
440505
fd.append('ln',E('[name=preview_ln]').checked ? 1 : 0);
441506
fd.append('iframe_height', E('[name=preview_html_ems]').value);
442507
fd.append('content',content || '');
443508
F.message(
444509
"Fetching preview..."
445510
).fetch('fileedit',{
446511
urlParams: {ajax: 'preview'},
447512
payload: fd,
448
- onload: (r)=>{
513
+ responseHeaders: 'x-fileedit-render-mode',
514
+ onload: (r,header)=>{
515
+ P.selectPreviewMode(P.previewModes[header]);
516
+ if('wiki'===header) P.baseHrefForFile();
517
+ else P.baseHrefRestore();
449518
callback(r);
450519
F.message('Updated preview.');
451520
},
452521
onerror: (e)=>{
453522
fossil.fetch.onerror(e);
454523
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -150,23 +150,43 @@
150 btnReload.addEventListener(
151 'click', (e)=>this.loadLeaves(), false
152 );
153 delete this.init;
154 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155 };
156
157 window.addEventListener("load", function() {
 
 
158 P.tabs = new fossil.TabManager('#fileedit-tabs');
159 P.e = {
160 taEditor: E('#fileedit-content-editor'),
161 taCommentSmall: E('#fileedit-comment'),
162 taCommentBig: E('#fileedit-comment-big'),
163 ajaxContentTarget: E('#ajax-target'),
164 btnCommit: E("#fileedit-btn-commit"),
165 btnReload: E("#fileedit-tab-content > .fileedit-options > "
166 +"button.fileedit-content-reload"),
167 selectPreviewModeWrap: E('#select-preview-mode'),
168 selectHtmlEmsWrap: E('#select-preview-html-ems'),
169 selectEolWrap: E('#select-preview-html-ems'),
170 cbLineNumbersWrap: E('#cb-line-numbers'),
171 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
172 tabs:{
@@ -199,13 +219,21 @@
199 );
200
201 P.tabs.addEventListener(
202 /* Set up auto-refresh of the preview tab... */
203 'before-switch-to', function(ev){
204 if(ev.detail===P.e.tabs.preview
205 && P.e.cbAutoPreview.checked){
206 P.preview();
 
 
 
 
 
 
 
 
207 }
208 }
209 );
210
211 F.connectPagePreviewers(
@@ -236,17 +264,16 @@
236 /**
237 Cosmetic: jump through some hoops to enable/disable
238 certain preview options depending on the current
239 preview mode...
240 */
241 const selectPreviewMode =
242 P.e.selectPreviewModeWrap.querySelector('select');
243 selectPreviewMode.addEventListener(
244 "change", function(e){
245 const mode = e.target.value,
246 name = P.previewModes[mode],
247 hide = [], unhide = [];
 
248 if('guess'===name){
249 unhide.push(P.e.cbLineNumbersWrap,
250 P.e.selectHtmlEmsWrap);
251 }else{
252 if('text'===name) unhide.push(P.e.cbLineNumbersWrap);
@@ -256,14 +283,11 @@
256 }
257 hide.forEach((e)=>e.classList.add('hidden'));
258 unhide.forEach((e)=>e.classList.remove('hidden'));
259 }, false
260 );
261 selectPreviewMode.dispatchEvent(
262 // Force UI update
263 new Event('change',{target:selectPreviewMode})
264 );
265 const selectFontSize = E('select[name=editor_font_size]');
266 if(selectFontSize){
267 selectFontSize.addEventListener(
268 "change",function(e){
269 const ed = P.e.taEditor;
@@ -294,10 +318,51 @@
294 }else{
295 this.e.taEditor.value = arguments[0];
296 return this;
297 }
298 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
300 /**
301 Toggles between single- and multi-line comment
302 mode.
303 */
@@ -433,21 +498,25 @@
433 if(!content){
434 callback(content);
435 return this;
436 }
437 const fd = new FormData();
438 fd.append('render_mode',E('select[name=preview_render_mode]').value);
439 fd.append('filename',this.finfo.filename);
440 fd.append('ln',E('[name=preview_ln]').checked ? 1 : 0);
441 fd.append('iframe_height', E('[name=preview_html_ems]').value);
442 fd.append('content',content || '');
443 F.message(
444 "Fetching preview..."
445 ).fetch('fileedit',{
446 urlParams: {ajax: 'preview'},
447 payload: fd,
448 onload: (r)=>{
 
 
 
 
449 callback(r);
450 F.message('Updated preview.');
451 },
452 onerror: (e)=>{
453 fossil.fetch.onerror(e);
454
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -150,23 +150,43 @@
150 btnReload.addEventListener(
151 'click', (e)=>this.loadLeaves(), false
152 );
153 delete this.init;
154 }
155 }/*P.fileSelector*/;
156
157 /**
158 Internal workaround to select the current preview mode
159 and fire a change event if the value actually changes
160 or if forceEvent is truthy.
161 */
162 P.selectPreviewMode = function(modeValue, forceEvent){
163 const s = this.e.selectPreviewMode;
164 if(!modeValue) modeValue = s.value;
165 else if(s.value != modeValue){
166 s.value = modeValue;
167 forceEvent = true;
168 }
169 if(forceEvent){
170 // Force UI update
171 s.dispatchEvent(new Event('change',{target:s}));
172 }
173 };
174
175 window.addEventListener("load", function() {
176 P.base = {tag: E('base')};
177 P.base.originalHref = P.base.tag.href;
178 P.tabs = new fossil.TabManager('#fileedit-tabs');
179 P.e = {
180 taEditor: E('#fileedit-content-editor'),
181 taCommentSmall: E('#fileedit-comment'),
182 taCommentBig: E('#fileedit-comment-big'),
183 ajaxContentTarget: E('#ajax-target'),
184 btnCommit: E("#fileedit-btn-commit"),
185 btnReload: E("#fileedit-tab-content > .fileedit-options > "
186 +"button.fileedit-content-reload"),
187 selectPreviewMode: E('#select-preview-mode select'),
188 selectHtmlEmsWrap: E('#select-preview-html-ems'),
189 selectEolWrap: E('#select-preview-html-ems'),
190 cbLineNumbersWrap: E('#cb-line-numbers'),
191 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
192 tabs:{
@@ -199,13 +219,21 @@
219 );
220
221 P.tabs.addEventListener(
222 /* Set up auto-refresh of the preview tab... */
223 'before-switch-to', function(ev){
224 if(ev.detail===P.e.tabs.preview){
225 P.baseHrefForFile();
226 if(P.e.cbAutoPreview.checked) P.preview();
227 }
228 }
229 );
230 P.tabs.addEventListener(
231 /* Set up auto-refresh of the preview tab... */
232 'before-switch-from', function(ev){
233 if(ev.detail===P.e.tabs.preview){
234 P.baseHrefRestore();
235 }
236 }
237 );
238
239 F.connectPagePreviewers(
@@ -236,17 +264,16 @@
264 /**
265 Cosmetic: jump through some hoops to enable/disable
266 certain preview options depending on the current
267 preview mode...
268 */
269 P.e.selectPreviewMode.addEventListener(
 
 
270 "change", function(e){
271 const mode = e.target.value,
272 name = P.previewModes[mode],
273 hide = [], unhide = [];
274 P.previewModes.current = name;
275 if('guess'===name){
276 unhide.push(P.e.cbLineNumbersWrap,
277 P.e.selectHtmlEmsWrap);
278 }else{
279 if('text'===name) unhide.push(P.e.cbLineNumbersWrap);
@@ -256,14 +283,11 @@
283 }
284 hide.forEach((e)=>e.classList.add('hidden'));
285 unhide.forEach((e)=>e.classList.remove('hidden'));
286 }, false
287 );
288 P.selectPreviewMode(false, true);
 
 
 
289 const selectFontSize = E('select[name=editor_font_size]');
290 if(selectFontSize){
291 selectFontSize.addEventListener(
292 "change",function(e){
293 const ed = P.e.taEditor;
@@ -294,10 +318,51 @@
318 }else{
319 this.e.taEditor.value = arguments[0];
320 return this;
321 }
322 };
323
324 /**
325 If either of...
326
327 - P.previewModes.current==='wiki'
328
329 - P.previewModes.current==='guess' AND the currently-loaded
330 file has an extension of (md|wiki)
331
332 ... then this function updates the document's base.href to a
333 repo-relative /doc/{{this.finfo.checkin}}/{{directory part of
334 this.finfo.filename}}/
335
336 If neither of those conditions applies, this is a no-op.
337 */
338 P.baseHrefForFile = function f(){
339 const fn = this.finfo ? this.finfo.filename : undefined;
340 if(!fn) return this;
341 if(!f.rxWiki){
342 f.rxWiki = /\.(wiki|md)$/i;
343 }
344 if('wiki'===P.previewModes.current
345 || ('guess'===P.previewModes.current
346 && f.rxWiki.test(fn))){
347 const a = fn.split('/');
348 a.pop();
349 this.base.tag.href = F.repoUrl(
350 'doc/'+F.hashDigits(this.finfo.checkin)
351 +'/'+(a.length ? a.join('/')+'/' : '')
352 );
353 }
354 return this;
355 };
356
357 /**
358 Sets the document's base.href value to its page-load-time
359 setting.
360 */
361 P.baseHrefRestore = function(){
362 P.base.tag.href = P.base.originalHref;
363 };
364
365 /**
366 Toggles between single- and multi-line comment
367 mode.
368 */
@@ -433,21 +498,25 @@
498 if(!content){
499 callback(content);
500 return this;
501 }
502 const fd = new FormData();
503 fd.append('render_mode',this.e.selectPreviewMode.value);
504 fd.append('filename',this.finfo.filename);
505 fd.append('ln',E('[name=preview_ln]').checked ? 1 : 0);
506 fd.append('iframe_height', E('[name=preview_html_ems]').value);
507 fd.append('content',content || '');
508 F.message(
509 "Fetching preview..."
510 ).fetch('fileedit',{
511 urlParams: {ajax: 'preview'},
512 payload: fd,
513 responseHeaders: 'x-fileedit-render-mode',
514 onload: (r,header)=>{
515 P.selectPreviewMode(P.previewModes[header]);
516 if('wiki'===header) P.baseHrefForFile();
517 else P.baseHrefRestore();
518 callback(r);
519 F.message('Updated preview.');
520 },
521 onerror: (e)=>{
522 fossil.fetch.onerror(e);
523

Keyboard Shortcuts

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