Fossil SCM

Merge in pikchrshow-wasm branch: reimplement /pikchrshow using a client-side WASM build of pikchr.c, plus related feature-adjacent tweaks in mimetype handling.

stephan 2022-06-08 23:27 trunk merge
Commit 7fcb462680ce63ae8a9be120c00f46147370b0d006338bfcf58458e80270bff1
+11
--- Makefile.in
+++ Makefile.in
@@ -72,10 +72,21 @@
7272
USE_SEE = @USE_SEE@
7373
APPNAME = fossil
7474
#
7575
# APPNAME = fossil-fuzz
7676
# may be more appropriate for fuzzing.
77
+
78
+#### Emscripten stuff for optionally doing in-tree builds
79
+# of any WASM components. We store precompiled WASM in the the SCM, so
80
+# this is only useful for people who actively work on WASM
81
+# components. EMSDK_ENV refers to the "environment" script which comes
82
+# with the Emscripten SDK package:
83
+# https://emscripten.org/docs/getting_started/downloads.html
84
+EMSDK_HOME = @EMSDK_HOME@
85
+EMSDK_ENV = @EMSDK_ENV@
86
+EMCC_OPT = @EMCC_OPT@
87
+EMCC_WRAPPER = $(SRCDIR_tools)/emcc.sh
7788
7889
.PHONY: all tags
7990
8091
include $(SRCDIR)/main.mk
8192
8293
--- Makefile.in
+++ Makefile.in
@@ -72,10 +72,21 @@
72 USE_SEE = @USE_SEE@
73 APPNAME = fossil
74 #
75 # APPNAME = fossil-fuzz
76 # may be more appropriate for fuzzing.
 
 
 
 
 
 
 
 
 
 
 
77
78 .PHONY: all tags
79
80 include $(SRCDIR)/main.mk
81
82
--- Makefile.in
+++ Makefile.in
@@ -72,10 +72,21 @@
72 USE_SEE = @USE_SEE@
73 APPNAME = fossil
74 #
75 # APPNAME = fossil-fuzz
76 # may be more appropriate for fuzzing.
77
78 #### Emscripten stuff for optionally doing in-tree builds
79 # of any WASM components. We store precompiled WASM in the the SCM, so
80 # this is only useful for people who actively work on WASM
81 # components. EMSDK_ENV refers to the "environment" script which comes
82 # with the Emscripten SDK package:
83 # https://emscripten.org/docs/getting_started/downloads.html
84 EMSDK_HOME = @EMSDK_HOME@
85 EMSDK_ENV = @EMSDK_ENV@
86 EMCC_OPT = @EMCC_OPT@
87 EMCC_WRAPPER = $(SRCDIR_tools)/emcc.sh
88
89 .PHONY: all tags
90
91 include $(SRCDIR)/main.mk
92
93
+36
--- auto.def
+++ auto.def
@@ -28,10 +28,11 @@
2828
static=0 => {Link a static executable}
2929
fusefs=1 => {Disable the Fuse Filesystem}
3030
fossil-debug=0 => {Build with fossil debugging enabled}
3131
no-opt=0 => {Build without optimization}
3232
json=0 => {Build with fossil JSON API enabled}
33
+ with-emsdk:path => {Directory containing the Emscripten SDK}
3334
}
3435
3536
# Update the minimum required SQLite version number here, and also
3637
# in src/main.c near the sqlite3_libversion_number() call. Take care
3738
# that both places agree!
@@ -632,10 +633,37 @@
632633
set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \
633634
$tclconfig(TCL_LD_FLAGS)]
634635
define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
635636
define FOSSIL_ENABLE_TCL
636637
}
638
+
639
+# Emscripten is a purely optional component used only for doing
640
+# in-tree builds of WASM stuff, as opposed to WASM binaries we import
641
+# from other places. This is only set up for Unix-style OSes and is
642
+# untested anywhere but Linux.
643
+set emsdkHome [opt-val with-emsdk]
644
+define EMSDK_HOME ""
645
+define EMSDK_ENV ""
646
+define EMCC_OPT "-Oz"
647
+if {$emsdkHome eq "" && [info exists ::env(EMSDK)]} {
648
+ # Fall back to checking the environment. $EMSDK gets set
649
+ # by sourcing emsdk_env.sh.
650
+ set emsdkHome $::env(EMSDK)
651
+}
652
+if {$emsdkHome ne ""} {
653
+ define EMSDK_HOME $emsdkHome
654
+ set emsdkEnv "$emsdkHome/emsdk_env.sh"
655
+ if {[file exists $emsdkEnv]} {
656
+ puts "Using Emscripten SDK environment from $emsdkEnv."
657
+ define EMSDK_ENV $emsdkEnv
658
+ if {[info exists ::env(EMCC_OPT)]} {
659
+ define EMCC_OPT $::env(EMCC_OPT)
660
+ }
661
+ } else {
662
+ puts "emsdk_env.sh not found. Assuming emcc is in the PATH."
663
+ }
664
+}
637665
638666
# Network functions require libraries on some systems
639667
cc-check-function-in-lib gethostbyname nsl
640668
if {![cc-check-function-in-lib socket {socket network}]} {
641669
# Last resort, may be Windows
@@ -726,8 +754,16 @@
726754
# Linux can only infer the dependency on pthread from OpenSSL when
727755
# doing dynamic linkage.
728756
define-append LIBS -lpthread
729757
}
730758
759
+if {[get-define EMSDK_HOME] ne ""} {
760
+ define EMCC_WRAPPER $::autosetup(dir)/../tools/emcc.sh
761
+ make-template tools/emcc.sh.in
762
+ catch {exec chmod u+x tools/emcc.sh}
763
+} else {
764
+ define EMCC_WRAPPER ""
765
+ catch {exec rm -f tools/emcc.sh}
766
+}
731767
732768
make-template Makefile.in
733769
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
734770
735771
ADDED extsrc/pikchr-worker.js
736772
ADDED extsrc/pikchr.js
737773
ADDED extsrc/pikchr.wasm
--- auto.def
+++ auto.def
@@ -28,10 +28,11 @@
28 static=0 => {Link a static executable}
29 fusefs=1 => {Disable the Fuse Filesystem}
30 fossil-debug=0 => {Build with fossil debugging enabled}
31 no-opt=0 => {Build without optimization}
32 json=0 => {Build with fossil JSON API enabled}
 
33 }
34
35 # Update the minimum required SQLite version number here, and also
36 # in src/main.c near the sqlite3_libversion_number() call. Take care
37 # that both places agree!
@@ -632,10 +633,37 @@
632 set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \
633 $tclconfig(TCL_LD_FLAGS)]
634 define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
635 define FOSSIL_ENABLE_TCL
636 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
638 # Network functions require libraries on some systems
639 cc-check-function-in-lib gethostbyname nsl
640 if {![cc-check-function-in-lib socket {socket network}]} {
641 # Last resort, may be Windows
@@ -726,8 +754,16 @@
726 # Linux can only infer the dependency on pthread from OpenSSL when
727 # doing dynamic linkage.
728 define-append LIBS -lpthread
729 }
730
 
 
 
 
 
 
 
 
731
732 make-template Makefile.in
733 make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
734
735 DDED extsrc/pikchr-worker.js
736 DDED extsrc/pikchr.js
737 DDED extsrc/pikchr.wasm
--- auto.def
+++ auto.def
@@ -28,10 +28,11 @@
28 static=0 => {Link a static executable}
29 fusefs=1 => {Disable the Fuse Filesystem}
30 fossil-debug=0 => {Build with fossil debugging enabled}
31 no-opt=0 => {Build without optimization}
32 json=0 => {Build with fossil JSON API enabled}
33 with-emsdk:path => {Directory containing the Emscripten SDK}
34 }
35
36 # Update the minimum required SQLite version number here, and also
37 # in src/main.c near the sqlite3_libversion_number() call. Take care
38 # that both places agree!
@@ -632,10 +633,37 @@
633 set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \
634 $tclconfig(TCL_LD_FLAGS)]
635 define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)
636 define FOSSIL_ENABLE_TCL
637 }
638
639 # Emscripten is a purely optional component used only for doing
640 # in-tree builds of WASM stuff, as opposed to WASM binaries we import
641 # from other places. This is only set up for Unix-style OSes and is
642 # untested anywhere but Linux.
643 set emsdkHome [opt-val with-emsdk]
644 define EMSDK_HOME ""
645 define EMSDK_ENV ""
646 define EMCC_OPT "-Oz"
647 if {$emsdkHome eq "" && [info exists ::env(EMSDK)]} {
648 # Fall back to checking the environment. $EMSDK gets set
649 # by sourcing emsdk_env.sh.
650 set emsdkHome $::env(EMSDK)
651 }
652 if {$emsdkHome ne ""} {
653 define EMSDK_HOME $emsdkHome
654 set emsdkEnv "$emsdkHome/emsdk_env.sh"
655 if {[file exists $emsdkEnv]} {
656 puts "Using Emscripten SDK environment from $emsdkEnv."
657 define EMSDK_ENV $emsdkEnv
658 if {[info exists ::env(EMCC_OPT)]} {
659 define EMCC_OPT $::env(EMCC_OPT)
660 }
661 } else {
662 puts "emsdk_env.sh not found. Assuming emcc is in the PATH."
663 }
664 }
665
666 # Network functions require libraries on some systems
667 cc-check-function-in-lib gethostbyname nsl
668 if {![cc-check-function-in-lib socket {socket network}]} {
669 # Last resort, may be Windows
@@ -726,8 +754,16 @@
754 # Linux can only infer the dependency on pthread from OpenSSL when
755 # doing dynamic linkage.
756 define-append LIBS -lpthread
757 }
758
759 if {[get-define EMSDK_HOME] ne ""} {
760 define EMCC_WRAPPER $::autosetup(dir)/../tools/emcc.sh
761 make-template tools/emcc.sh.in
762 catch {exec chmod u+x tools/emcc.sh}
763 } else {
764 define EMCC_WRAPPER ""
765 catch {exec rm -f tools/emcc.sh}
766 }
767
768 make-template Makefile.in
769 make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
770
771 DDED extsrc/pikchr-worker.js
772 DDED extsrc/pikchr.js
773 DDED extsrc/pikchr.wasm
--- a/extsrc/pikchr-worker.js
+++ b/extsrc/pikchr-worker.js
@@ -0,0 +1,108 @@
1
+/*
2
+ 2022-05-20
3
+
4
+ The author disresult like with DOM elements,
5
+ we have to define a lower-level message API. Messages abstractly
6
+ look like:
7
+
8
+ { type: string, data: type-specific value }
9
+
10
+ Where 'type' is used for dispatching and 'data' is a
11
+ 'type'-dependent value.
12
+
13
+ The 'type' values expected by each side of the main/worker
14
+ connection vary. The types are described below but subject to
15
+ change at any time as this experiment evolves.
16
+
17
+ Main-to-Worker message types:
18
+
19
+ - pikchr: data=pikchr-format text to render or an object:
20
+
21
+ {
22
+ pikchr: source code for the pikchr,
23
+ darkMode: boolean true to adjust colors for a dark color scheme,
24
+ cssClass: CSS class name to add to the typeshe author disclaims copyright to this source code. In place of a
25
+ legal notice, here is a blessing:
26
+
27
+ * May you do good and not evil.
28
+ * May you find forgiveness for yourself and forgive others.
29
+ * May you share freely, never taking more than you give.
30
+
31
+ ***********************************************************************
32
+
33
+ This is a JS Worker file for use with the pikchr wasm build. It
34
+ loads the pikchr wasm module and offers access to it via the Worker
35
+ message-passing interface.
36
+
37
+ Because we can have only a single message handler, as opposed to an
38
+ arbitrary n/* messages come in the form
39
+
40
+ {type:'module', data:{
41
+ type:'status',
42
+ data: {text:string|null, step:1-based-integer}
43
+ }
44
+
45
+ with an incrementing step value for each subsequent message. When
46
+ the module loading is complete, a message with a text value of
47
+ n ull is posted.
48
+
49
+ - pikchr:
50
+
51
+ {type: 'pikchr',
52
+ data:{
53
+ pikchr: input text,
54
+ result: rendered result (SVG on success, HTML on error),
55
+ isError: bool, true if .pikchr holds an error report,
56
+ flags: integer: flags used to configure the pikchr rendering,
57
+ width: if !isError, width (integer pixels) of the SVG,
58
+ height: if !isError, height (integer pixels) of the SVG
59
+ }
60
+ }
61
+
62
+*/
63
+
64
+"use strict";
65
+(function(){
66
+ /**
67
+ Posts a message in the form {type,data} unless passed more than
68
+ 2 args, in which case it posts {type, data:[arg1...argN]}.
69
+ */
70
+ const wMsg = function(type,data){
71
+ postMessage({
72
+ type,
73
+ data: arguments.length<3
74
+ ? data
75
+ : Array.prototype.slice.call(arguments,1)
76
+ });
77
+ };
78
+
79
+ const stderr = function(){wMsg('stderr', Array.prototype.slice.call(arguments));};
80
+
81
+ self.onerror = function(/*message, source, lineno, colno, error*/) {
82
+ const err = arguments[4];
83
+ if(err && 'ExitStatus'==err.name){
84
+ /* This "cannot happen" for this wasm binding, but just in
85
+ case... */
86
+ pikchrModule.isDead = true;
87
+ stderr("FATAL ERROR:", err.message);
88
+ stderr("Restarting the app requires reloading the page.");
89
+ wMsg('error', err);
90
+ }
91
+ pikchrModule.setStatus('Exception thrown, see JavaScript console: '+err);
92
+ };
93
+
94
+ self.onmessage = function f(ev){
95
+ ev = ev.data;
96
+ switch(ev.type){
97
+ /**
98
+ Runs the given text through pikchr and emits a 'pikchr'
99
+ message result (output format documented above).
100
+
101
+ Fires a working/start event before it starts and
102
+ working/end event when it finishes.
103
+ */
104
+ case 'pikchr':
105
+ if(pikchrModule.isDead){
106
+ stderr( show-ready');
107
+ });
108
+})();
--- a/extsrc/pikchr-worker.js
+++ b/extsrc/pikchr-worker.js
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/extsrc/pikchr-worker.js
+++ b/extsrc/pikchr-worker.js
@@ -0,0 +1,108 @@
1 /*
2 2022-05-20
3
4 The author disresult like with DOM elements,
5 we have to define a lower-level message API. Messages abstractly
6 look like:
7
8 { type: string, data: type-specific value }
9
10 Where 'type' is used for dispatching and 'data' is a
11 'type'-dependent value.
12
13 The 'type' values expected by each side of the main/worker
14 connection vary. The types are described below but subject to
15 change at any time as this experiment evolves.
16
17 Main-to-Worker message types:
18
19 - pikchr: data=pikchr-format text to render or an object:
20
21 {
22 pikchr: source code for the pikchr,
23 darkMode: boolean true to adjust colors for a dark color scheme,
24 cssClass: CSS class name to add to the typeshe author disclaims copyright to this source code. In place of a
25 legal notice, here is a blessing:
26
27 * May you do good and not evil.
28 * May you find forgiveness for yourself and forgive others.
29 * May you share freely, never taking more than you give.
30
31 ***********************************************************************
32
33 This is a JS Worker file for use with the pikchr wasm build. It
34 loads the pikchr wasm module and offers access to it via the Worker
35 message-passing interface.
36
37 Because we can have only a single message handler, as opposed to an
38 arbitrary n/* messages come in the form
39
40 {type:'module', data:{
41 type:'status',
42 data: {text:string|null, step:1-based-integer}
43 }
44
45 with an incrementing step value for each subsequent message. When
46 the module loading is complete, a message with a text value of
47 n ull is posted.
48
49 - pikchr:
50
51 {type: 'pikchr',
52 data:{
53 pikchr: input text,
54 result: rendered result (SVG on success, HTML on error),
55 isError: bool, true if .pikchr holds an error report,
56 flags: integer: flags used to configure the pikchr rendering,
57 width: if !isError, width (integer pixels) of the SVG,
58 height: if !isError, height (integer pixels) of the SVG
59 }
60 }
61
62 */
63
64 "use strict";
65 (function(){
66 /**
67 Posts a message in the form {type,data} unless passed more than
68 2 args, in which case it posts {type, data:[arg1...argN]}.
69 */
70 const wMsg = function(type,data){
71 postMessage({
72 type,
73 data: arguments.length<3
74 ? data
75 : Array.prototype.slice.call(arguments,1)
76 });
77 };
78
79 const stderr = function(){wMsg('stderr', Array.prototype.slice.call(arguments));};
80
81 self.onerror = function(/*message, source, lineno, colno, error*/) {
82 const err = arguments[4];
83 if(err && 'ExitStatus'==err.name){
84 /* This "cannot happen" for this wasm binding, but just in
85 case... */
86 pikchrModule.isDead = true;
87 stderr("FATAL ERROR:", err.message);
88 stderr("Restarting the app requires reloading the page.");
89 wMsg('error', err);
90 }
91 pikchrModule.setStatus('Exception thrown, see JavaScript console: '+err);
92 };
93
94 self.onmessage = function f(ev){
95 ev = ev.data;
96 switch(ev.type){
97 /**
98 Runs the given text through pikchr and emits a 'pikchr'
99 message result (output format documented above).
100
101 Fires a working/start event before it starts and
102 working/end event when it finishes.
103 */
104 case 'pikchr':
105 if(pikchrModule.isDead){
106 stderr( show-ready');
107 });
108 })();
--- a/extsrc/pikchr.js
+++ b/extsrc/pikchr.js
@@ -0,0 +1,42 @@
1
+) {
2
+ r initPikchrModuDi
3
+var initPikchrMod || {};e["ready"] = new Promise(fhis by
4
+// setting the ENVIRONMENT// setting the ENVIRONMENT settingow) => {
5
+ throw toT(resolve, reject) =>e present at the end iffunction(resolve, reject) end if `scriptDirectory` is lice"";
6
+
7
+function locateFile(path) {
8
+ if (Module["locaeFile"]) {
9
+ retut they can
10
+// refer to Module (if they choose; th// Sometimes an exivartory` is lice"";
11
+
12
+fnse = awaitirectory + path;
13
+}
14
+
15
+
16
+
17
+/aitirectory + path;
18
+}
19
+
20
+
21
+
22
+// Ho);nt runtime environments.}
23
+var initPikchrModule = (() => {
24
+ vchrModule var initPikchrModule =, setWindowTitle;
25
+ed in the code, and you
26
+//d in the code, and yORKER) {
27
+iseResvar readomiseResolve = resolveft());
28
+ }
29
+ }
30
+ // = reject;
31
+});
32
+
33
+// Determine nvironment we are in}
34
+ if (_scriptDir) {
35
+iseResvar readyPromi_scriptDir;
36
+ }
37
+Throw) => {
38
+ throw tindexOf("blob:") !== 0) {
39
+iseResvar readyPromiscriptDirectory.substr(0, ) => {
40
+ thrvar runtimeKeepavar buffer,aliveCounter = 0 || runtimeKeepaliveCounter > 0binaryFilevar initPikchrModuDir = typGlobalBufferAn ENVIRONME.src : undefined;
41
+ nresponse =>b() =>var function(str)function(arr)function(type) {
42
+ r
--- a/extsrc/pikchr.js
+++ b/extsrc/pikchr.js
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/extsrc/pikchr.js
+++ b/extsrc/pikchr.js
@@ -0,0 +1,42 @@
1 ) {
2 r initPikchrModuDi
3 var initPikchrMod || {};e["ready"] = new Promise(fhis by
4 // setting the ENVIRONMENT// setting the ENVIRONMENT settingow) => {
5 throw toT(resolve, reject) =>e present at the end iffunction(resolve, reject) end if `scriptDirectory` is lice"";
6
7 function locateFile(path) {
8 if (Module["locaeFile"]) {
9 retut they can
10 // refer to Module (if they choose; th// Sometimes an exivartory` is lice"";
11
12 fnse = awaitirectory + path;
13 }
14
15
16
17 /aitirectory + path;
18 }
19
20
21
22 // Ho);nt runtime environments.}
23 var initPikchrModule = (() => {
24 vchrModule var initPikchrModule =, setWindowTitle;
25 ed in the code, and you
26 //d in the code, and yORKER) {
27 iseResvar readomiseResolve = resolveft());
28 }
29 }
30 // = reject;
31 });
32
33 // Determine nvironment we are in}
34 if (_scriptDir) {
35 iseResvar readyPromi_scriptDir;
36 }
37 Throw) => {
38 throw tindexOf("blob:") !== 0) {
39 iseResvar readyPromiscriptDirectory.substr(0, ) => {
40 thrvar runtimeKeepavar buffer,aliveCounter = 0 || runtimeKeepaliveCounter > 0binaryFilevar initPikchrModuDir = typGlobalBufferAn ENVIRONME.src : undefined;
41 nresponse =>b() =>var function(str)function(arr)function(type) {
42 r

Binary file

--- skins/darkmode/css.txt
+++ skins/darkmode/css.txt
@@ -131,13 +131,12 @@
131131
.button:focus,
132132
button:focus,
133133
input[type=button]:focus,
134134
input[type=reset]:focus,
135135
input[type=submit]:focus {
136
- color: #333;
136
+ outline: 2px outset #333;
137137
border-color: #888;
138
- outline: 0
139138
}
140139
141140
/* All page content from the bottom of the menu or submenu down to
142141
** the footer */
143142
div.content {
144143
--- skins/darkmode/css.txt
+++ skins/darkmode/css.txt
@@ -131,13 +131,12 @@
131 .button:focus,
132 button:focus,
133 input[type=button]:focus,
134 input[type=reset]:focus,
135 input[type=submit]:focus {
136 color: #333;
137 border-color: #888;
138 outline: 0
139 }
140
141 /* All page content from the bottom of the menu or submenu down to
142 ** the footer */
143 div.content {
144
--- skins/darkmode/css.txt
+++ skins/darkmode/css.txt
@@ -131,13 +131,12 @@
131 .button:focus,
132 button:focus,
133 input[type=button]:focus,
134 input[type=reset]:focus,
135 input[type=submit]:focus {
136 outline: 2px outset #333;
137 border-color: #888;
 
138 }
139
140 /* All page content from the bottom of the menu or submenu down to
141 ** the footer */
142 div.content {
143
+4 -5
--- src/builtin.c
+++ src/builtin.c
@@ -130,20 +130,19 @@
130130
blob_reset(&x);
131131
}
132132
133133
/*
134134
** Input zList is a list of numeric identifiers for files in
135
-** aBuiltinFiles[]. Return the concatenation of all of those
136
-** files using mimetype zType, or as application/javascript if
137
-** zType is 0.
135
+** aBuiltinFiles[]. Return the concatenation of all of those files
136
+** using mimetype zType, or as text/javascript if zType is 0.
138137
*/
139138
static void builtin_deliver_multiple_js_files(
140139
const char *zList, /* List of numeric identifiers */
141140
const char *zType /* Override mimetype */
142141
){
143142
Blob *pOut;
144
- if( zType==0 ) zType = "application/javascript";
143
+ if( zType==0 ) zType = "text/javascript";
145144
cgi_set_content_type(zType);
146145
pOut = cgi_output_blob();
147146
while( zList[0] ){
148147
int i = atoi(zList);
149148
if( i>0 && i<=count(aBuiltinFiles) ){
@@ -203,11 +202,11 @@
203202
@ File "%h(zName)" not found
204203
return;
205204
}
206205
if( zType==0 ){
207206
if( sqlite3_strglob("*.js", zName)==0 ){
208
- zType = "application/javascript";
207
+ zType = "text/javascript";
209208
}else{
210209
zType = mimetype_from_name(zName);
211210
}
212211
}
213212
cgi_set_content_type(zType);
214213
--- src/builtin.c
+++ src/builtin.c
@@ -130,20 +130,19 @@
130 blob_reset(&x);
131 }
132
133 /*
134 ** Input zList is a list of numeric identifiers for files in
135 ** aBuiltinFiles[]. Return the concatenation of all of those
136 ** files using mimetype zType, or as application/javascript if
137 ** zType is 0.
138 */
139 static void builtin_deliver_multiple_js_files(
140 const char *zList, /* List of numeric identifiers */
141 const char *zType /* Override mimetype */
142 ){
143 Blob *pOut;
144 if( zType==0 ) zType = "application/javascript";
145 cgi_set_content_type(zType);
146 pOut = cgi_output_blob();
147 while( zList[0] ){
148 int i = atoi(zList);
149 if( i>0 && i<=count(aBuiltinFiles) ){
@@ -203,11 +202,11 @@
203 @ File "%h(zName)" not found
204 return;
205 }
206 if( zType==0 ){
207 if( sqlite3_strglob("*.js", zName)==0 ){
208 zType = "application/javascript";
209 }else{
210 zType = mimetype_from_name(zName);
211 }
212 }
213 cgi_set_content_type(zType);
214
--- src/builtin.c
+++ src/builtin.c
@@ -130,20 +130,19 @@
130 blob_reset(&x);
131 }
132
133 /*
134 ** Input zList is a list of numeric identifiers for files in
135 ** aBuiltinFiles[]. Return the concatenation of all of those files
136 ** using mimetype zType, or as text/javascript if zType is 0.
 
137 */
138 static void builtin_deliver_multiple_js_files(
139 const char *zList, /* List of numeric identifiers */
140 const char *zType /* Override mimetype */
141 ){
142 Blob *pOut;
143 if( zType==0 ) zType = "text/javascript";
144 cgi_set_content_type(zType);
145 pOut = cgi_output_blob();
146 while( zList[0] ){
147 int i = atoi(zList);
148 if( i>0 && i<=count(aBuiltinFiles) ){
@@ -203,11 +202,11 @@
202 @ File "%h(zName)" not found
203 return;
204 }
205 if( zType==0 ){
206 if( sqlite3_strglob("*.js", zName)==0 ){
207 zType = "text/javascript";
208 }else{
209 zType = mimetype_from_name(zName);
210 }
211 }
212 cgi_set_content_type(zType);
213
+57 -11
--- src/cgi.c
+++ src/cgi.c
@@ -307,11 +307,11 @@
307307
if(!g.isHTTP) return /* e.g. JSON CLI mode, where g.zTop is not set */;
308308
else if( zPath==0 ){
309309
zPath = g.zTop;
310310
if( zPath[0]==0 ) zPath = "/";
311311
}
312
- if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
312
+ if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
313313
zSecure = " secure;";
314314
}
315315
if( lifetime!=0 ){
316316
blob_appendf(&extraHeader,
317317
"Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; "
@@ -330,13 +330,37 @@
330330
** Return true if the response should be sent with Content-Encoding: gzip.
331331
*/
332332
static int is_gzippable(void){
333333
if( g.fNoHttpCompress ) return 0;
334334
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
335
- return strncmp(zContentType, "text/", 5)==0
336
- || sqlite3_strglob("application/*xml", zContentType)==0
337
- || sqlite3_strglob("application/*javascript", zContentType)==0;
335
+ /* Maintenance note: this oddball structure is intended to make
336
+ ** adding new mimetypes to this list less of a performance hit than
337
+ ** doing a strcmp/glob over a growing set of compressible types. */
338
+ switch(zContentType ? *zContentType : 0){
339
+ case (int)'a':
340
+ if(0==fossil_strncmp("application/",zContentType,12)){
341
+ const char * z = &zContentType[12];
342
+ switch(*z){
343
+ case (int)'j':
344
+ return fossil_strcmp("javascript", z)==0
345
+ || fossil_strcmp("json", z)==0;
346
+ case (int)'w': return fossil_strcmp("wasm", z)==0;
347
+ case (int)'x':
348
+ return fossil_strcmp("x-tcl", z)==0
349
+ || fossil_strcmp("x-tar", z)==0;
350
+ default:
351
+ return sqlite3_strglob("*xml", z)==0;
352
+ }
353
+ }
354
+ break;
355
+ case (int)'i':
356
+ return fossil_strcmp(zContentType, "image/svg+xml")==0
357
+ || fossil_strcmp(zContentType, "image/vnd.microsoft.icon")==0;
358
+ case (int)'t':
359
+ return fossil_strncmp(zContentType, "text/", 5)==0;
360
+ }
361
+ return 0;
338362
}
339363
340364
341365
/*
342366
** The following routines read or write content from/to the wire for
@@ -419,10 +443,29 @@
419443
if( !g.httpUseSSL ){
420444
fflush(g.httpOut);
421445
}
422446
}
423447
448
+/*
449
+** Given a Content-Type value, returns a string suitable for appending
450
+** to the Content-Type header for adding (or not) the "; charset=..."
451
+** part. It returns an empty string for most types or if zContentType
452
+** is NULL.
453
+**
454
+** See forum post f60dece061c364d1 for the discussions which lead to
455
+** this. Previously we always appended the charset, but WASM loaders
456
+** are pedantic and refuse to load any responses which have a
457
+** charset. Also, adding a charset is not strictly appropriate for
458
+** most types (and not required for many others which may ostensibly
459
+** benefit from one, as detailed in that forum post).
460
+*/
461
+static const char * content_type_charset(const char *zContentType){
462
+ if(0==fossil_strncmp(zContentType,"text/",5)){
463
+ return "; charset=utf-8";
464
+ }
465
+ return "";
466
+}
424467
425468
/*
426469
** Generate the reply to a web request. The output might be an
427470
** full HTTP response, or a CGI response, depending on how things have
428471
** be set up.
@@ -493,11 +536,12 @@
493536
494537
/* Content intended for logged in users should only be cached in
495538
** the browser, not some shared location.
496539
*/
497540
if( iReplyStatus!=304 ) {
498
- blob_appendf(&hdr, "Content-Type: %s; charset=utf-8\r\n", zContentType);
541
+ blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
542
+ content_type_charset(zContentType));
499543
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
500544
cgi_combine_header_and_body();
501545
blob_compress(&cgiContent[0], &cgiContent[0]);
502546
}
503547
@@ -569,11 +613,12 @@
569613
int iStat,
570614
const char *zStat
571615
){
572616
char *zLocation;
573617
CGIDEBUG(("redirect to %s\n", zURL));
574
- if( strncmp(zURL,"http:",5)==0 || strncmp(zURL,"https:",6)==0 ){
618
+ if( fossil_strncmp(zURL,"http:",5)==0
619
+ || fossil_strncmp(zURL,"https:",6)==0 ){
575620
zLocation = mprintf("Location: %s\r\n", zURL);
576621
}else if( *zURL=='/' ){
577622
int n1 = (int)strlen(g.zBaseURL);
578623
int n2 = (int)strlen(g.zTop);
579624
if( g.zBaseURL[n1-1]=='/' ) zURL++;
@@ -653,11 +698,11 @@
653698
const char *zMethod = P("REQUEST_METHOD");
654699
if( zMethod==0 ) return 0;
655700
if( strcmp(zMethod,"POST")!=0 ) return 0;
656701
}
657702
nBase = (int)strlen(g.zBaseURL);
658
- if( strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
703
+ if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
659704
if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
660705
return 1;
661706
}
662707
663708
/*
@@ -920,11 +965,12 @@
920965
int len = *pLen;
921966
int i;
922967
int nBoundary = strlen(zBoundary);
923968
*pnContent = len;
924969
for(i=0; i<len; i++){
925
- if( z[i]=='\n' && strncmp(zBoundary, &z[i+1], nBoundary)==0 ){
970
+ if( z[i]=='\n' && fossil_strncmp(zBoundary, &z[i+1],
971
+ nBoundary)==0 ){
926972
if( i>0 && z[i-1]=='\r' ) i--;
927973
z[i] = 0;
928974
*pnContent = i;
929975
i += nBoundary;
930976
break;
@@ -1348,11 +1394,11 @@
13481394
*/
13491395
void cgi_decode_post_parameters(void){
13501396
int len = blob_size(&g.cgiIn);
13511397
if( len==0 ) return;
13521398
if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
1353
- || strncmp(g.zContentType,"multipart/form-data",19)==0
1399
+ || fossil_strncmp(g.zContentType,"multipart/form-data",19)==0
13541400
){
13551401
char *z = blob_str(&g.cgiIn);
13561402
cgi_trace(z);
13571403
if( g.zContentType[0]=='a' ){
13581404
add_param_list(z, '&');
@@ -2326,11 +2372,11 @@
23262372
if( zBrowser ){
23272373
assert( strstr(zBrowser,"%d")!=0 );
23282374
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
23292375
#if defined(__CYGWIN__)
23302376
/* On Cygwin, we can do better than "echo" */
2331
- if( strncmp(zBrowser, "echo ", 5)==0 ){
2377
+ if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){
23322378
wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
23332379
wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
23342380
if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
23352381
fossil_warning("cannot start browser\n");
23362382
}
@@ -2486,11 +2532,11 @@
24862532
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
24872533
if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
24882534
&mday, zMonth, &year, &hour, &min, &sec)){
24892535
if( year > 1900 ) year -= 1900;
24902536
for(mon=0; azMonths[mon]; mon++){
2491
- if( !strncmp( azMonths[mon], zMonth, 3 )){
2537
+ if( !fossil_strncmp( azMonths[mon], zMonth, 3 )){
24922538
int nDay;
24932539
int isLeapYr;
24942540
static int priorDays[] =
24952541
{ 0, 31, 59, 90,120,151,181,212,243,273,304,334 };
24962542
if( mon<0 ){
24972543
--- src/cgi.c
+++ src/cgi.c
@@ -307,11 +307,11 @@
307 if(!g.isHTTP) return /* e.g. JSON CLI mode, where g.zTop is not set */;
308 else if( zPath==0 ){
309 zPath = g.zTop;
310 if( zPath[0]==0 ) zPath = "/";
311 }
312 if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
313 zSecure = " secure;";
314 }
315 if( lifetime!=0 ){
316 blob_appendf(&extraHeader,
317 "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; "
@@ -330,13 +330,37 @@
330 ** Return true if the response should be sent with Content-Encoding: gzip.
331 */
332 static int is_gzippable(void){
333 if( g.fNoHttpCompress ) return 0;
334 if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
335 return strncmp(zContentType, "text/", 5)==0
336 || sqlite3_strglob("application/*xml", zContentType)==0
337 || sqlite3_strglob("application/*javascript", zContentType)==0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338 }
339
340
341 /*
342 ** The following routines read or write content from/to the wire for
@@ -419,10 +443,29 @@
419 if( !g.httpUseSSL ){
420 fflush(g.httpOut);
421 }
422 }
423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
425 /*
426 ** Generate the reply to a web request. The output might be an
427 ** full HTTP response, or a CGI response, depending on how things have
428 ** be set up.
@@ -493,11 +536,12 @@
493
494 /* Content intended for logged in users should only be cached in
495 ** the browser, not some shared location.
496 */
497 if( iReplyStatus!=304 ) {
498 blob_appendf(&hdr, "Content-Type: %s; charset=utf-8\r\n", zContentType);
 
499 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
500 cgi_combine_header_and_body();
501 blob_compress(&cgiContent[0], &cgiContent[0]);
502 }
503
@@ -569,11 +613,12 @@
569 int iStat,
570 const char *zStat
571 ){
572 char *zLocation;
573 CGIDEBUG(("redirect to %s\n", zURL));
574 if( strncmp(zURL,"http:",5)==0 || strncmp(zURL,"https:",6)==0 ){
 
575 zLocation = mprintf("Location: %s\r\n", zURL);
576 }else if( *zURL=='/' ){
577 int n1 = (int)strlen(g.zBaseURL);
578 int n2 = (int)strlen(g.zTop);
579 if( g.zBaseURL[n1-1]=='/' ) zURL++;
@@ -653,11 +698,11 @@
653 const char *zMethod = P("REQUEST_METHOD");
654 if( zMethod==0 ) return 0;
655 if( strcmp(zMethod,"POST")!=0 ) return 0;
656 }
657 nBase = (int)strlen(g.zBaseURL);
658 if( strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
659 if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
660 return 1;
661 }
662
663 /*
@@ -920,11 +965,12 @@
920 int len = *pLen;
921 int i;
922 int nBoundary = strlen(zBoundary);
923 *pnContent = len;
924 for(i=0; i<len; i++){
925 if( z[i]=='\n' && strncmp(zBoundary, &z[i+1], nBoundary)==0 ){
 
926 if( i>0 && z[i-1]=='\r' ) i--;
927 z[i] = 0;
928 *pnContent = i;
929 i += nBoundary;
930 break;
@@ -1348,11 +1394,11 @@
1348 */
1349 void cgi_decode_post_parameters(void){
1350 int len = blob_size(&g.cgiIn);
1351 if( len==0 ) return;
1352 if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
1353 || strncmp(g.zContentType,"multipart/form-data",19)==0
1354 ){
1355 char *z = blob_str(&g.cgiIn);
1356 cgi_trace(z);
1357 if( g.zContentType[0]=='a' ){
1358 add_param_list(z, '&');
@@ -2326,11 +2372,11 @@
2326 if( zBrowser ){
2327 assert( strstr(zBrowser,"%d")!=0 );
2328 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
2329 #if defined(__CYGWIN__)
2330 /* On Cygwin, we can do better than "echo" */
2331 if( strncmp(zBrowser, "echo ", 5)==0 ){
2332 wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
2333 wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
2334 if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
2335 fossil_warning("cannot start browser\n");
2336 }
@@ -2486,11 +2532,11 @@
2486 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
2487 if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
2488 &mday, zMonth, &year, &hour, &min, &sec)){
2489 if( year > 1900 ) year -= 1900;
2490 for(mon=0; azMonths[mon]; mon++){
2491 if( !strncmp( azMonths[mon], zMonth, 3 )){
2492 int nDay;
2493 int isLeapYr;
2494 static int priorDays[] =
2495 { 0, 31, 59, 90,120,151,181,212,243,273,304,334 };
2496 if( mon<0 ){
2497
--- src/cgi.c
+++ src/cgi.c
@@ -307,11 +307,11 @@
307 if(!g.isHTTP) return /* e.g. JSON CLI mode, where g.zTop is not set */;
308 else if( zPath==0 ){
309 zPath = g.zTop;
310 if( zPath[0]==0 ) zPath = "/";
311 }
312 if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
313 zSecure = " secure;";
314 }
315 if( lifetime!=0 ){
316 blob_appendf(&extraHeader,
317 "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; "
@@ -330,13 +330,37 @@
330 ** Return true if the response should be sent with Content-Encoding: gzip.
331 */
332 static int is_gzippable(void){
333 if( g.fNoHttpCompress ) return 0;
334 if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
335 /* Maintenance note: this oddball structure is intended to make
336 ** adding new mimetypes to this list less of a performance hit than
337 ** doing a strcmp/glob over a growing set of compressible types. */
338 switch(zContentType ? *zContentType : 0){
339 case (int)'a':
340 if(0==fossil_strncmp("application/",zContentType,12)){
341 const char * z = &zContentType[12];
342 switch(*z){
343 case (int)'j':
344 return fossil_strcmp("javascript", z)==0
345 || fossil_strcmp("json", z)==0;
346 case (int)'w': return fossil_strcmp("wasm", z)==0;
347 case (int)'x':
348 return fossil_strcmp("x-tcl", z)==0
349 || fossil_strcmp("x-tar", z)==0;
350 default:
351 return sqlite3_strglob("*xml", z)==0;
352 }
353 }
354 break;
355 case (int)'i':
356 return fossil_strcmp(zContentType, "image/svg+xml")==0
357 || fossil_strcmp(zContentType, "image/vnd.microsoft.icon")==0;
358 case (int)'t':
359 return fossil_strncmp(zContentType, "text/", 5)==0;
360 }
361 return 0;
362 }
363
364
365 /*
366 ** The following routines read or write content from/to the wire for
@@ -419,10 +443,29 @@
443 if( !g.httpUseSSL ){
444 fflush(g.httpOut);
445 }
446 }
447
448 /*
449 ** Given a Content-Type value, returns a string suitable for appending
450 ** to the Content-Type header for adding (or not) the "; charset=..."
451 ** part. It returns an empty string for most types or if zContentType
452 ** is NULL.
453 **
454 ** See forum post f60dece061c364d1 for the discussions which lead to
455 ** this. Previously we always appended the charset, but WASM loaders
456 ** are pedantic and refuse to load any responses which have a
457 ** charset. Also, adding a charset is not strictly appropriate for
458 ** most types (and not required for many others which may ostensibly
459 ** benefit from one, as detailed in that forum post).
460 */
461 static const char * content_type_charset(const char *zContentType){
462 if(0==fossil_strncmp(zContentType,"text/",5)){
463 return "; charset=utf-8";
464 }
465 return "";
466 }
467
468 /*
469 ** Generate the reply to a web request. The output might be an
470 ** full HTTP response, or a CGI response, depending on how things have
471 ** be set up.
@@ -493,11 +536,12 @@
536
537 /* Content intended for logged in users should only be cached in
538 ** the browser, not some shared location.
539 */
540 if( iReplyStatus!=304 ) {
541 blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
542 content_type_charset(zContentType));
543 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
544 cgi_combine_header_and_body();
545 blob_compress(&cgiContent[0], &cgiContent[0]);
546 }
547
@@ -569,11 +613,12 @@
613 int iStat,
614 const char *zStat
615 ){
616 char *zLocation;
617 CGIDEBUG(("redirect to %s\n", zURL));
618 if( fossil_strncmp(zURL,"http:",5)==0
619 || fossil_strncmp(zURL,"https:",6)==0 ){
620 zLocation = mprintf("Location: %s\r\n", zURL);
621 }else if( *zURL=='/' ){
622 int n1 = (int)strlen(g.zBaseURL);
623 int n2 = (int)strlen(g.zTop);
624 if( g.zBaseURL[n1-1]=='/' ) zURL++;
@@ -653,11 +698,11 @@
698 const char *zMethod = P("REQUEST_METHOD");
699 if( zMethod==0 ) return 0;
700 if( strcmp(zMethod,"POST")!=0 ) return 0;
701 }
702 nBase = (int)strlen(g.zBaseURL);
703 if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
704 if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
705 return 1;
706 }
707
708 /*
@@ -920,11 +965,12 @@
965 int len = *pLen;
966 int i;
967 int nBoundary = strlen(zBoundary);
968 *pnContent = len;
969 for(i=0; i<len; i++){
970 if( z[i]=='\n' && fossil_strncmp(zBoundary, &z[i+1],
971 nBoundary)==0 ){
972 if( i>0 && z[i-1]=='\r' ) i--;
973 z[i] = 0;
974 *pnContent = i;
975 i += nBoundary;
976 break;
@@ -1348,11 +1394,11 @@
1394 */
1395 void cgi_decode_post_parameters(void){
1396 int len = blob_size(&g.cgiIn);
1397 if( len==0 ) return;
1398 if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
1399 || fossil_strncmp(g.zContentType,"multipart/form-data",19)==0
1400 ){
1401 char *z = blob_str(&g.cgiIn);
1402 cgi_trace(z);
1403 if( g.zContentType[0]=='a' ){
1404 add_param_list(z, '&');
@@ -2326,11 +2372,11 @@
2372 if( zBrowser ){
2373 assert( strstr(zBrowser,"%d")!=0 );
2374 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
2375 #if defined(__CYGWIN__)
2376 /* On Cygwin, we can do better than "echo" */
2377 if( fossil_strncmp(zBrowser, "echo ", 5)==0 ){
2378 wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
2379 wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
2380 if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
2381 fossil_warning("cannot start browser\n");
2382 }
@@ -2486,11 +2532,11 @@
2532 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
2533 if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
2534 &mday, zMonth, &year, &hour, &min, &sec)){
2535 if( year > 1900 ) year -= 1900;
2536 for(mon=0; azMonths[mon]; mon++){
2537 if( !fossil_strncmp( azMonths[mon], zMonth, 3 )){
2538 int nDay;
2539 int isLeapYr;
2540 static int priorDays[] =
2541 { 0, 31, 59, 90,120,151,181,212,243,273,304,334 };
2542 if( mon<0 ){
2543
+14 -6
--- src/default.css
+++ src/default.css
@@ -1007,10 +1007,13 @@
10071007
background-color: #ffb;
10081008
}
10091009
label {
10101010
white-space: nowrap;
10111011
}
1012
+label[for] {
1013
+ cursor: pointer;
1014
+}
10121015
.copy-button {
10131016
display: inline-block;
10141017
width: 14px;
10151018
height: 14px;
10161019
/*Note: .24em is slightly smaller than the average width of a normal space.*/
@@ -1075,16 +1078,21 @@
10751078
}
10761079
.warning {
10771080
color: black;
10781081
background: yellow;
10791082
}
1080
-.hidden {
1081
- /* The framework-wide way of hiding elements is to assign them this
1082
- CSS class. To make them visible again, remove it. The !important
1083
- qualifiers are unfortunate but sometimes necessary when hidden
1084
- element has other classes which specify visibility-related
1085
- options. */
1083
+.hidden, .initially-hidden {
1084
+ /* The framework-wide way of hiding elements is to assign them th
1085
+ .hidden class. To make them visible again, remove it. The
1086
+ !important qualifiers are unfortunate but sometimes necessary
1087
+ when hidden element has other classes which specify
1088
+ visibility-related options. The .initially-hidden class is for
1089
+ pages which need to show, e.g., a progress widget while a large
1090
+ WASM blob loads. Elements aside from that load-time widget can be
1091
+ made .initially-hidden and then have that class removed once the
1092
+ long-running startup process is done. See /pikchrshow for an
1093
+ example. */
10861094
position: absolute !important;
10871095
opacity: 0 !important;
10881096
pointer-events: none !important;
10891097
display: none !important;
10901098
}
10911099
--- src/default.css
+++ src/default.css
@@ -1007,10 +1007,13 @@
1007 background-color: #ffb;
1008 }
1009 label {
1010 white-space: nowrap;
1011 }
 
 
 
1012 .copy-button {
1013 display: inline-block;
1014 width: 14px;
1015 height: 14px;
1016 /*Note: .24em is slightly smaller than the average width of a normal space.*/
@@ -1075,16 +1078,21 @@
1075 }
1076 .warning {
1077 color: black;
1078 background: yellow;
1079 }
1080 .hidden {
1081 /* The framework-wide way of hiding elements is to assign them this
1082 CSS class. To make them visible again, remove it. The !important
1083 qualifiers are unfortunate but sometimes necessary when hidden
1084 element has other classes which specify visibility-related
1085 options. */
 
 
 
 
 
1086 position: absolute !important;
1087 opacity: 0 !important;
1088 pointer-events: none !important;
1089 display: none !important;
1090 }
1091
--- src/default.css
+++ src/default.css
@@ -1007,10 +1007,13 @@
1007 background-color: #ffb;
1008 }
1009 label {
1010 white-space: nowrap;
1011 }
1012 label[for] {
1013 cursor: pointer;
1014 }
1015 .copy-button {
1016 display: inline-block;
1017 width: 14px;
1018 height: 14px;
1019 /*Note: .24em is slightly smaller than the average width of a normal space.*/
@@ -1075,16 +1078,21 @@
1078 }
1079 .warning {
1080 color: black;
1081 background: yellow;
1082 }
1083 .hidden, .initially-hidden {
1084 /* The framework-wide way of hiding elements is to assign them th
1085 .hidden class. To make them visible again, remove it. The
1086 !important qualifiers are unfortunate but sometimes necessary
1087 when hidden element has other classes which specify
1088 visibility-related options. The .initially-hidden class is for
1089 pages which need to show, e.g., a progress widget while a large
1090 WASM blob loads. Elements aside from that load-time widget can be
1091 made .initially-hidden and then have that class removed once the
1092 long-running startup process is done. See /pikchrshow for an
1093 example. */
1094 position: absolute !important;
1095 opacity: 0 !important;
1096 pointer-events: none !important;
1097 display: none !important;
1098 }
1099
+7 -1
--- src/doc.c
+++ src/doc.c
@@ -156,11 +156,16 @@
156156
{ "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157157
{ "jar", 3, "application/java-archive" },
158158
{ "jpe", 3, "image/jpeg" },
159159
{ "jpeg", 4, "image/jpeg" },
160160
{ "jpg", 3, "image/jpeg" },
161
- { "js", 2, "application/javascript" },
161
+ { "js", 2, "text/javascript" },
162
+ /* application/javascript is commonly used for JS, but the
163
+ ** spec says text/javascript is correct:
164
+ ** https://html.spec.whatwg.org/multipage/scripting.html
165
+ ** #scriptingLanguages:javascript-mime-type */
166
+ { "json", 4, "application/json" },
162167
{ "kar", 3, "audio/midi" },
163168
{ "latex", 5, "application/x-latex" },
164169
{ "lha", 3, "application/octet-stream" },
165170
{ "lsp", 3, "application/x-lisp" },
166171
{ "lzh", 3, "application/octet-stream" },
@@ -173,10 +178,11 @@
173178
{ "mesh", 4, "model/mesh" },
174179
{ "mid", 3, "audio/midi" },
175180
{ "midi", 4, "audio/midi" },
176181
{ "mif", 3, "application/x-mif" },
177182
{ "mime", 4, "www/mime" },
183
+ { "mjs", 3, "text/javascript" /*EM6 modules*/ },
178184
{ "mkd", 3, "text/x-markdown" },
179185
{ "mov", 3, "video/quicktime" },
180186
{ "movie", 5, "video/x-sgi-movie" },
181187
{ "mp2", 3, "audio/mpeg" },
182188
{ "mp3", 3, "audio/mpeg" },
183189
--- src/doc.c
+++ src/doc.c
@@ -156,11 +156,16 @@
156 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157 { "jar", 3, "application/java-archive" },
158 { "jpe", 3, "image/jpeg" },
159 { "jpeg", 4, "image/jpeg" },
160 { "jpg", 3, "image/jpeg" },
161 { "js", 2, "application/javascript" },
 
 
 
 
 
162 { "kar", 3, "audio/midi" },
163 { "latex", 5, "application/x-latex" },
164 { "lha", 3, "application/octet-stream" },
165 { "lsp", 3, "application/x-lisp" },
166 { "lzh", 3, "application/octet-stream" },
@@ -173,10 +178,11 @@
173 { "mesh", 4, "model/mesh" },
174 { "mid", 3, "audio/midi" },
175 { "midi", 4, "audio/midi" },
176 { "mif", 3, "application/x-mif" },
177 { "mime", 4, "www/mime" },
 
178 { "mkd", 3, "text/x-markdown" },
179 { "mov", 3, "video/quicktime" },
180 { "movie", 5, "video/x-sgi-movie" },
181 { "mp2", 3, "audio/mpeg" },
182 { "mp3", 3, "audio/mpeg" },
183
--- src/doc.c
+++ src/doc.c
@@ -156,11 +156,16 @@
156 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
157 { "jar", 3, "application/java-archive" },
158 { "jpe", 3, "image/jpeg" },
159 { "jpeg", 4, "image/jpeg" },
160 { "jpg", 3, "image/jpeg" },
161 { "js", 2, "text/javascript" },
162 /* application/javascript is commonly used for JS, but the
163 ** spec says text/javascript is correct:
164 ** https://html.spec.whatwg.org/multipage/scripting.html
165 ** #scriptingLanguages:javascript-mime-type */
166 { "json", 4, "application/json" },
167 { "kar", 3, "audio/midi" },
168 { "latex", 5, "application/x-latex" },
169 { "lha", 3, "application/octet-stream" },
170 { "lsp", 3, "application/x-lisp" },
171 { "lzh", 3, "application/octet-stream" },
@@ -173,10 +178,11 @@
178 { "mesh", 4, "model/mesh" },
179 { "mid", 3, "audio/midi" },
180 { "midi", 4, "audio/midi" },
181 { "mif", 3, "application/x-mif" },
182 { "mime", 4, "www/mime" },
183 { "mjs", 3, "text/javascript" /*EM6 modules*/ },
184 { "mkd", 3, "text/x-markdown" },
185 { "mov", 3, "video/quicktime" },
186 { "movie", 5, "video/x-sgi-movie" },
187 { "mp2", 3, "audio/mpeg" },
188 { "mp3", 3, "audio/mpeg" },
189
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -1,12 +1,20 @@
11
(function(F/*the fossil object*/){
22
"use strict";
33
/**
4
- Client-side implementation of the /pikchrshow app. Requires that
4
+ Client-side implementation of the /pikchrshowcs app. Requires that
55
the fossil JS bootstrapping is complete and that these fossil JS
66
APIs have been installed: fossil.fetch, fossil.dom,
77
fossil.copybutton, fossil.popupwidget, fossil.storage
8
+
9
+ Maintenance funkiness note: this file is for the legacy
10
+ /pikchrshowcs app, which was formerly named /pikchrshow. This
11
+ file and its replacement were not renamed because the replacement
12
+ impl would end up getting this file's name and cause confusion in
13
+ the file history. Whether that confusion would be less than this
14
+ file's name matching the _other_ /pikchrshow impl will cause more
15
+ or less confusion than that remains to be seen.
816
*/
917
const E = (s)=>document.querySelector(s),
1018
D = F.dom,
1119
P = F.page;
1220
1321
1422
ADDED src/fossil.page.pikchrshowasm.js
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -1,12 +1,20 @@
1 (function(F/*the fossil object*/){
2 "use strict";
3 /**
4 Client-side implementation of the /pikchrshow app. Requires that
5 the fossil JS bootstrapping is complete and that these fossil JS
6 APIs have been installed: fossil.fetch, fossil.dom,
7 fossil.copybutton, fossil.popupwidget, fossil.storage
 
 
 
 
 
 
 
 
8 */
9 const E = (s)=>document.querySelector(s),
10 D = F.dom,
11 P = F.page;
12
13
14 DDED src/fossil.page.pikchrshowasm.js
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -1,12 +1,20 @@
1 (function(F/*the fossil object*/){
2 "use strict";
3 /**
4 Client-side implementation of the /pikchrshowcs app. Requires that
5 the fossil JS bootstrapping is complete and that these fossil JS
6 APIs have been installed: fossil.fetch, fossil.dom,
7 fossil.copybutton, fossil.popupwidget, fossil.storage
8
9 Maintenance funkiness note: this file is for the legacy
10 /pikchrshowcs app, which was formerly named /pikchrshow. This
11 file and its replacement were not renamed because the replacement
12 impl would end up getting this file's name and cause confusion in
13 the file history. Whether that confusion would be less than this
14 file's name matching the _other_ /pikchrshow impl will cause more
15 or less confusion than that remains to be seen.
16 */
17 const E = (s)=>document.querySelector(s),
18 D = F.dom,
19 P = F.page;
20
21
22 DDED src/fossil.page.pikchrshowasm.js
--- a/src/fossil.page.pikchrshowasm.js
+++ b/src/fossil.page.pikchrshowasm.js
@@ -0,0 +1,24 @@
1
+/*
2
+ 2022-05-20
3
+
4
+ The author disclaims copyright to this source code. In place of a
5
+ legal notice, here is a blessing:
6
+
7
+ * May you do good and not evil.
8
+ * May you find forgiveness for yourself and forgive others.
9
+ * May you share freely, never taking more than you give.
10
+
11
+ ***********************************************************************
12
+
13
+ This is the main entry point for the WASM r
14
+ * May you share fre/*
15
+ :div.didiv. ttr(selectScript, 'aria-label', 'Example Scripts');
16
+ D.attr(selectScript,...EAll('body > *:not(.content)let ht = whht -= F.dom.effectiveHeight(e))
17
+ ];
18
+
19
+
20
+})(window.fossil);
21
+E('body > header.header'),
22
+ E('body > nav.mainmenu'),
23
+ E('body > footer.footervar ht;
24
+ var extra = 0e ? extra + ht = wh - extradivdidivshowshow-ready',show#btn-options
--- a/src/fossil.page.pikchrshowasm.js
+++ b/src/fossil.page.pikchrshowasm.js
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/fossil.page.pikchrshowasm.js
+++ b/src/fossil.page.pikchrshowasm.js
@@ -0,0 +1,24 @@
1 /*
2 2022-05-20
3
4 The author disclaims copyright to this source code. In place of a
5 legal notice, here is a blessing:
6
7 * May you do good and not evil.
8 * May you find forgiveness for yourself and forgive others.
9 * May you share freely, never taking more than you give.
10
11 ***********************************************************************
12
13 This is the main entry point for the WASM r
14 * May you share fre/*
15 :div.didiv. ttr(selectScript, 'aria-label', 'Example Scripts');
16 D.attr(selectScript,...EAll('body > *:not(.content)let ht = whht -= F.dom.effectiveHeight(e))
17 ];
18
19
20 })(window.fossil);
21 E('body > header.header'),
22 E('body > nav.mainmenu'),
23 E('body > footer.footervar ht;
24 var extra = 0e ? extra + ht = wh - extradivdidivshowshow-ready',show#btn-options
+10 -8
--- src/json.c
+++ src/json.c
@@ -558,11 +558,11 @@
558558
/*
559559
** Guesses a RESPONSE Content-Type value based (primarily) on the
560560
** HTTP_ACCEPT header.
561561
**
562562
** It will try to figure out if the client can support
563
-** application/json or application/javascript, and will fall back to
563
+** application/json, text/javascript, and will fall back to
564564
** text/plain if it cannot figure out anything more specific.
565565
**
566566
** Returned memory is static and immutable, but if the environment
567567
** changes after calling this then subsequent calls to this function
568568
** might return different (also static/immutable) values.
@@ -573,12 +573,12 @@
573573
cset = PD("HTTP_ACCEPT_CHARSET",NULL);
574574
doUtf8 = ((NULL == cset) || (NULL!=strstr("utf-8",cset)))
575575
? 1 : 0;
576576
if( g.json.jsonp ){
577577
return doUtf8
578
- ? "application/javascript; charset=utf-8"
579
- : "application/javascript";
578
+ ? "text/javascript; charset=utf-8"
579
+ : "text/javascript";
580580
}else{
581581
/*
582582
Content-type
583583
584584
If the browser does not sent an ACCEPT for application/json
@@ -605,18 +605,19 @@
605605
606606
/*
607607
** Given a request CONTENT_TYPE value, this function returns true
608608
** if it is of a type which the JSON API can ostensibly read.
609609
**
610
- ** It accepts any of application/json, text/plain, or
611
- ** application/javascript. The former is preferred, but was not
612
- ** widespread when this API was initially built, so the latter forms
613
- ** are permitted as fallbacks.
610
+ ** It accepts any of application/json, text/plain,
611
+ ** application/javascript, or text/javascript. The former is
612
+ ** preferred, but was not widespread when this API was initially
613
+ ** built, so the latter forms are permitted as fallbacks.
614614
*/
615615
int json_can_consume_content_type(const char * zType){
616616
return fossil_strcmp(zType, "application/json")==0
617617
|| fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
618
+ || fossil_strcmp(zType,"text/javascript")==0
618619
|| fossil_strcmp(zType,"application/javascript")==0;
619620
}
620621
621622
/*
622623
** Sends pResponse to the output stream as the response object. This
@@ -627,18 +628,19 @@
627628
** In CLI mode pResponse is sent to stdout immediately. In HTTP
628629
** mode pResponse replaces any current CGI content but cgi_reply()
629630
** is not called to flush the output.
630631
**
631632
** If g.json.jsonp is not NULL then the content type is set to
632
-** application/javascript and the output is wrapped in a jsonp
633
+** text/javascript and the output is wrapped in a jsonp
633634
** wrapper.
634635
*/
635636
void json_send_response( cson_value const * pResponse ){
636637
assert( NULL != pResponse );
637638
if( g.isHTTP ){
638639
cgi_reset_content();
639640
if( g.json.jsonp ){
641
+ cgi_set_content_type("text/javascript");
640642
cgi_printf("%s(",g.json.jsonp);
641643
}
642644
cson_output( pResponse, cson_data_dest_cgi, NULL, &g.json.outOpt );
643645
if( g.json.jsonp ){
644646
cgi_append_content(")",1);
645647
--- src/json.c
+++ src/json.c
@@ -558,11 +558,11 @@
558 /*
559 ** Guesses a RESPONSE Content-Type value based (primarily) on the
560 ** HTTP_ACCEPT header.
561 **
562 ** It will try to figure out if the client can support
563 ** application/json or application/javascript, and will fall back to
564 ** text/plain if it cannot figure out anything more specific.
565 **
566 ** Returned memory is static and immutable, but if the environment
567 ** changes after calling this then subsequent calls to this function
568 ** might return different (also static/immutable) values.
@@ -573,12 +573,12 @@
573 cset = PD("HTTP_ACCEPT_CHARSET",NULL);
574 doUtf8 = ((NULL == cset) || (NULL!=strstr("utf-8",cset)))
575 ? 1 : 0;
576 if( g.json.jsonp ){
577 return doUtf8
578 ? "application/javascript; charset=utf-8"
579 : "application/javascript";
580 }else{
581 /*
582 Content-type
583
584 If the browser does not sent an ACCEPT for application/json
@@ -605,18 +605,19 @@
605
606 /*
607 ** Given a request CONTENT_TYPE value, this function returns true
608 ** if it is of a type which the JSON API can ostensibly read.
609 **
610 ** It accepts any of application/json, text/plain, or
611 ** application/javascript. The former is preferred, but was not
612 ** widespread when this API was initially built, so the latter forms
613 ** are permitted as fallbacks.
614 */
615 int json_can_consume_content_type(const char * zType){
616 return fossil_strcmp(zType, "application/json")==0
617 || fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
 
618 || fossil_strcmp(zType,"application/javascript")==0;
619 }
620
621 /*
622 ** Sends pResponse to the output stream as the response object. This
@@ -627,18 +628,19 @@
627 ** In CLI mode pResponse is sent to stdout immediately. In HTTP
628 ** mode pResponse replaces any current CGI content but cgi_reply()
629 ** is not called to flush the output.
630 **
631 ** If g.json.jsonp is not NULL then the content type is set to
632 ** application/javascript and the output is wrapped in a jsonp
633 ** wrapper.
634 */
635 void json_send_response( cson_value const * pResponse ){
636 assert( NULL != pResponse );
637 if( g.isHTTP ){
638 cgi_reset_content();
639 if( g.json.jsonp ){
 
640 cgi_printf("%s(",g.json.jsonp);
641 }
642 cson_output( pResponse, cson_data_dest_cgi, NULL, &g.json.outOpt );
643 if( g.json.jsonp ){
644 cgi_append_content(")",1);
645
--- src/json.c
+++ src/json.c
@@ -558,11 +558,11 @@
558 /*
559 ** Guesses a RESPONSE Content-Type value based (primarily) on the
560 ** HTTP_ACCEPT header.
561 **
562 ** It will try to figure out if the client can support
563 ** application/json, text/javascript, and will fall back to
564 ** text/plain if it cannot figure out anything more specific.
565 **
566 ** Returned memory is static and immutable, but if the environment
567 ** changes after calling this then subsequent calls to this function
568 ** might return different (also static/immutable) values.
@@ -573,12 +573,12 @@
573 cset = PD("HTTP_ACCEPT_CHARSET",NULL);
574 doUtf8 = ((NULL == cset) || (NULL!=strstr("utf-8",cset)))
575 ? 1 : 0;
576 if( g.json.jsonp ){
577 return doUtf8
578 ? "text/javascript; charset=utf-8"
579 : "text/javascript";
580 }else{
581 /*
582 Content-type
583
584 If the browser does not sent an ACCEPT for application/json
@@ -605,18 +605,19 @@
605
606 /*
607 ** Given a request CONTENT_TYPE value, this function returns true
608 ** if it is of a type which the JSON API can ostensibly read.
609 **
610 ** It accepts any of application/json, text/plain,
611 ** application/javascript, or text/javascript. The former is
612 ** preferred, but was not widespread when this API was initially
613 ** built, so the latter forms are permitted as fallbacks.
614 */
615 int json_can_consume_content_type(const char * zType){
616 return fossil_strcmp(zType, "application/json")==0
617 || fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
618 || fossil_strcmp(zType,"text/javascript")==0
619 || fossil_strcmp(zType,"application/javascript")==0;
620 }
621
622 /*
623 ** Sends pResponse to the output stream as the response object. This
@@ -627,18 +628,19 @@
628 ** In CLI mode pResponse is sent to stdout immediately. In HTTP
629 ** mode pResponse replaces any current CGI content but cgi_reply()
630 ** is not called to flush the output.
631 **
632 ** If g.json.jsonp is not NULL then the content type is set to
633 ** text/javascript and the output is wrapped in a jsonp
634 ** wrapper.
635 */
636 void json_send_response( cson_value const * pResponse ){
637 assert( NULL != pResponse );
638 if( g.isHTTP ){
639 cgi_reset_content();
640 if( g.json.jsonp ){
641 cgi_set_content_type("text/javascript");
642 cgi_printf("%s(",g.json.jsonp);
643 }
644 cson_output( pResponse, cson_data_dest_cgi, NULL, &g.json.outOpt );
645 if( g.json.jsonp ){
646 cgi_append_content(")",1);
647
+10
--- src/main.mk
+++ src/main.mk
@@ -163,10 +163,13 @@
163163
$(SRCDIR)/xfer.c \
164164
$(SRCDIR)/xfersetup.c \
165165
$(SRCDIR)/zip.c
166166
167167
EXTRA_FILES = \
168
+ $(SRCDIR)/../extsrc/pikchr-worker.js \
169
+ $(SRCDIR)/../extsrc/pikchr.js \
170
+ $(SRCDIR)/../extsrc/pikchr.wasm \
168171
$(SRCDIR)/../skins/ardoise/css.txt \
169172
$(SRCDIR)/../skins/ardoise/details.txt \
170173
$(SRCDIR)/../skins/ardoise/footer.txt \
171174
$(SRCDIR)/../skins/ardoise/header.txt \
172175
$(SRCDIR)/../skins/black_and_white/css.txt \
@@ -231,10 +234,11 @@
231234
$(SRCDIR)/fossil.page.brlist.js \
232235
$(SRCDIR)/fossil.page.chat.js \
233236
$(SRCDIR)/fossil.page.fileedit.js \
234237
$(SRCDIR)/fossil.page.forumpost.js \
235238
$(SRCDIR)/fossil.page.pikchrshow.js \
239
+ $(SRCDIR)/fossil.page.pikchrshowasm.js \
236240
$(SRCDIR)/fossil.page.whistory.js \
237241
$(SRCDIR)/fossil.page.wikiedit.js \
238242
$(SRCDIR)/fossil.pikchr.js \
239243
$(SRCDIR)/fossil.popupwidget.js \
240244
$(SRCDIR)/fossil.storage.js \
@@ -266,10 +270,11 @@
266270
$(SRCDIR)/sounds/e.wav \
267271
$(SRCDIR)/sounds/f.wav \
268272
$(SRCDIR)/style.admin_log.css \
269273
$(SRCDIR)/style.chat.css \
270274
$(SRCDIR)/style.fileedit.css \
275
+ $(SRCDIR)/style.pikchrshow.css \
271276
$(SRCDIR)/style.wikiedit.css \
272277
$(SRCDIR)/tree.js \
273278
$(SRCDIR)/useredit.js \
274279
$(SRCDIR)/wiki.wiki
275280
@@ -2108,13 +2113,18 @@
21082113
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
21092114
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
21102115
21112116
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
21122117
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2118
+
2119
+$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c
2120
+ $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry -sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore -sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c -sENVIRONMENT=web -sMODULARIZE -sEXPORT_NAME=initPikchrModule --minify 0
2121
+ @chmod -x $(SRCDIR_extsrc)/pikchr.wasm
2122
+wasm: $(SRCDIR_extsrc)/pikchr.js
21132123
21142124
#
21152125
# The list of all the targets that do not correspond to real files. This stops
21162126
# 'make' from getting confused when someone makes an error in a rule.
21172127
#
21182128
21192129
.PHONY: all install test clean
21202130
21212131
--- src/main.mk
+++ src/main.mk
@@ -163,10 +163,13 @@
163 $(SRCDIR)/xfer.c \
164 $(SRCDIR)/xfersetup.c \
165 $(SRCDIR)/zip.c
166
167 EXTRA_FILES = \
 
 
 
168 $(SRCDIR)/../skins/ardoise/css.txt \
169 $(SRCDIR)/../skins/ardoise/details.txt \
170 $(SRCDIR)/../skins/ardoise/footer.txt \
171 $(SRCDIR)/../skins/ardoise/header.txt \
172 $(SRCDIR)/../skins/black_and_white/css.txt \
@@ -231,10 +234,11 @@
231 $(SRCDIR)/fossil.page.brlist.js \
232 $(SRCDIR)/fossil.page.chat.js \
233 $(SRCDIR)/fossil.page.fileedit.js \
234 $(SRCDIR)/fossil.page.forumpost.js \
235 $(SRCDIR)/fossil.page.pikchrshow.js \
 
236 $(SRCDIR)/fossil.page.whistory.js \
237 $(SRCDIR)/fossil.page.wikiedit.js \
238 $(SRCDIR)/fossil.pikchr.js \
239 $(SRCDIR)/fossil.popupwidget.js \
240 $(SRCDIR)/fossil.storage.js \
@@ -266,10 +270,11 @@
266 $(SRCDIR)/sounds/e.wav \
267 $(SRCDIR)/sounds/f.wav \
268 $(SRCDIR)/style.admin_log.css \
269 $(SRCDIR)/style.chat.css \
270 $(SRCDIR)/style.fileedit.css \
 
271 $(SRCDIR)/style.wikiedit.css \
272 $(SRCDIR)/tree.js \
273 $(SRCDIR)/useredit.js \
274 $(SRCDIR)/wiki.wiki
275
@@ -2108,13 +2113,18 @@
2108 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2109 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2110
2111 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2112 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
 
 
 
 
 
2113
2114 #
2115 # The list of all the targets that do not correspond to real files. This stops
2116 # 'make' from getting confused when someone makes an error in a rule.
2117 #
2118
2119 .PHONY: all install test clean
2120
2121
--- src/main.mk
+++ src/main.mk
@@ -163,10 +163,13 @@
163 $(SRCDIR)/xfer.c \
164 $(SRCDIR)/xfersetup.c \
165 $(SRCDIR)/zip.c
166
167 EXTRA_FILES = \
168 $(SRCDIR)/../extsrc/pikchr-worker.js \
169 $(SRCDIR)/../extsrc/pikchr.js \
170 $(SRCDIR)/../extsrc/pikchr.wasm \
171 $(SRCDIR)/../skins/ardoise/css.txt \
172 $(SRCDIR)/../skins/ardoise/details.txt \
173 $(SRCDIR)/../skins/ardoise/footer.txt \
174 $(SRCDIR)/../skins/ardoise/header.txt \
175 $(SRCDIR)/../skins/black_and_white/css.txt \
@@ -231,10 +234,11 @@
234 $(SRCDIR)/fossil.page.brlist.js \
235 $(SRCDIR)/fossil.page.chat.js \
236 $(SRCDIR)/fossil.page.fileedit.js \
237 $(SRCDIR)/fossil.page.forumpost.js \
238 $(SRCDIR)/fossil.page.pikchrshow.js \
239 $(SRCDIR)/fossil.page.pikchrshowasm.js \
240 $(SRCDIR)/fossil.page.whistory.js \
241 $(SRCDIR)/fossil.page.wikiedit.js \
242 $(SRCDIR)/fossil.pikchr.js \
243 $(SRCDIR)/fossil.popupwidget.js \
244 $(SRCDIR)/fossil.storage.js \
@@ -266,10 +270,11 @@
270 $(SRCDIR)/sounds/e.wav \
271 $(SRCDIR)/sounds/f.wav \
272 $(SRCDIR)/style.admin_log.css \
273 $(SRCDIR)/style.chat.css \
274 $(SRCDIR)/style.fileedit.css \
275 $(SRCDIR)/style.pikchrshow.css \
276 $(SRCDIR)/style.wikiedit.css \
277 $(SRCDIR)/tree.js \
278 $(SRCDIR)/useredit.js \
279 $(SRCDIR)/wiki.wiki
280
@@ -2108,13 +2113,18 @@
2113 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2114 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2115
2116 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2117 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2118
2119 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c
2120 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry -sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore -sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c -sENVIRONMENT=web -sMODULARIZE -sEXPORT_NAME=initPikchrModule --minify 0
2121 @chmod -x $(SRCDIR_extsrc)/pikchr.wasm
2122 wasm: $(SRCDIR_extsrc)/pikchr.js
2123
2124 #
2125 # The list of all the targets that do not correspond to real files. This stops
2126 # 'make' from getting confused when someone makes an error in a rule.
2127 #
2128
2129 .PHONY: all install test clean
2130
2131
+147 -9
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -230,30 +230,36 @@
230230
blob_reset(&bIn);
231231
return isErr;
232232
}
233233
234234
/*
235
-** WEBPAGE: pikchrshow
235
+** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
236
+** this one if the "legacy" or "ajax" request arguments are set.
236237
**
237238
** A pikchr code editor and previewer, allowing users to experiment
238239
** with pikchr code or prototype it for use in copy/pasting into forum
239
-** posts, wiki pages, or embedded docs.
240
-**
241
-** It optionally accepts a p=pikchr-script-code URL parameter or POST
242
-** value to pre-populate the editor with that code.
240
+** posts, wiki pages, or embedded docs. This version of pikchrshow
241
+** uses JavaScript to send pikchr code to the server for
242
+** processing. The newer /pikchrshow applications runs pikchr on the
243
+** client machine, without the need for back-and-forth network
244
+** traffic.
243245
*/
244
-void pikchrshow_page(void){
246
+void pikchrshowcs_page(void){
245247
const char *zContent = 0;
246248
int isDark; /* true if the current skin is "dark" */
247249
int pikFlags =
248250
PIKCHR_PROCESS_DIV
249251
| PIKCHR_PROCESS_SRC
250252
| PIKCHR_PROCESS_ERR_PRE;
251253
252254
login_check_credentials();
253255
if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
254
- cgi_redirectf("%R/login?g=pikchrshow");
256
+ cgi_redirectf("%R/login?g=pikchrshowcs");
257
+ }
258
+ if(P("wasm")){
259
+ pikchrshow_page();
260
+ return;
255261
}
256262
zContent = PD("content",P("p"));
257263
if(P("ajax")!=0){
258264
/* Called from the JS-side preview updater.
259265
TODO: respond with JSON instead.*/
@@ -279,11 +285,11 @@
279285
"box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
280286
"arrow right 200% \"HTML+SVG\" \"Output\"\n"
281287
"arrow <-> down from last box.s\n"
282288
"box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
283289
}
284
- style_header("PikchrShow");
290
+ style_header("PikchrShow Client/Server");
285291
CX("<style>"); {
286292
CX("div.content { padding-top: 0.5em }\n");
287293
CX("#sbs-wrapper {"
288294
"display: flex; flex-direction: column;"
289295
"}\n");
@@ -336,11 +342,11 @@
336342
"vertical-align: middle"
337343
"}\n");
338344
CX(".dragover {border: 3px dotted rgba(0,255,0,0.6)}\n");
339345
} CX("</style>");
340346
CX("<div>Input pikchr code and tap Preview (or Shift-Enter) to render "
341
- "it:</div>");
347
+ "it. <a href='?wasm'>Switch to WASM mode</a>.</div>");
342348
CX("<div id='sbs-wrapper'>"); {
343349
CX("<div id='pikchrshow-form'>"); {
344350
CX("<textarea id='content' name='content' rows='15'>"
345351
"%s</textarea>",zContent/*safe-for-%s*/);
346352
CX("<div id='pikchrshow-controls'>"); {
@@ -376,10 +382,142 @@
376382
"storage", "pikchr", NULL);
377383
builtin_request_js("fossil.page.pikchrshow.js");
378384
builtin_fulfill_js_requests();
379385
style_finish_page();
380386
}
387
+
388
+/*
389
+** WEBPAGE: pikchrshow
390
+**
391
+** A pikchr code editor and previewer, allowing users to experiment
392
+** with pikchr code or prototype it for use in copy/pasting into forum
393
+** posts, wiki pages, or embedded docs. This version of pikchrshow
394
+** uses WebAssembly to run entirely in the client browser, without a
395
+** need for back-and-forth client/server traffic to perform the
396
+** rendering. The "legacy" version of this application, which sends
397
+** all input to the server for rendering, can be accessed by adding
398
+** the "legacy" URL argument.
399
+**
400
+** It optionally accepts a p=pikchr-script-code URL parameter or POST
401
+** value to pre-populate the editor with that code.
402
+*/
403
+void pikchrshow_page(void){
404
+ const char *zContent = 0;
405
+
406
+ if(P("legacy") || P("ajax")){
407
+ pikchrshowcs_page();
408
+ return;
409
+ }
410
+ login_check_credentials();
411
+ if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
412
+ cgi_redirectf("%R/login?g=pikchrshow");
413
+ }
414
+ style_emit_noscript_for_js_page();
415
+ style_header("PikchrShow");
416
+ zContent = PD("content",P("p"));
417
+ if(!zContent){
418
+ zContent = "arrow right 200% \"Markdown\" \"Source\"\n"
419
+ "box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
420
+ "arrow right 200% \"HTML+SVG\" \"Output\"\n"
421
+ "arrow <-> down from last box.s\n"
422
+ "box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
423
+ }
424
+ /* Wasm load/init progress widget... */
425
+ CX("<div class='emscripten'>"); {
426
+ CX("<figure id='module-spinner'>");
427
+ CX("<div class='spinner'></div>");
428
+ CX("<div class='center'><strong>Initializing app...</strong></div>");
429
+ CX("<div class='center'>");
430
+ CX("On a slow internet connection this may take a moment. If this ");
431
+ CX("message displays for \"a long time\", intialization may have ");
432
+ CX("failed and the JavaScript console may contain clues as to why. ");
433
+ CX("</div>");
434
+ CX("<div><a href='?legacy'>Switch to legacy mode</a></div>");
435
+ CX("</figure>");
436
+ CX("<div class='emscripten' id='module-status'>Downloading...</div>");
437
+ CX("<progress value='0' max='100' id='module-progress' hidden='1'>"
438
+ "</progress>");
439
+ } CX("</div><!-- .emscripten -->");
440
+ /* Main view... */
441
+ CX("<div id='view-split' class='app-view initially-hidden'>"); {
442
+ CX("<fieldset class='options collapsible'>"); {
443
+ CX("<legend><button id='btn-options-toggle'>Options</button></legend>");
444
+ CX("<div>");
445
+ CX("<span class='labeled-input'>");
446
+ CX("<input type='checkbox' id='opt-cb-sbs' ");
447
+ CX("data-csstgt='#main-wrapper' ");
448
+ CX("data-cssclass='side-by-side' ");
449
+ CX("data-config='sideBySide'>");
450
+ CX("<label for='opt-cb-sbs'>Side-by-side</label>");
451
+ CX("</span>");
452
+ CX("<span class='labeled-input'>");
453
+ CX("<input type='checkbox' id='opt-cb-swapio' ");
454
+ CX("data-csstgt='#main-wrapper' ");
455
+ CX("data-cssclass='swapio' ");
456
+ CX("data-config='swapInOut'>");
457
+ CX("<label for='opt-cb-swapio'>Swap in/out</label>");
458
+ CX("</span>");
459
+ CX("<span class='labeled-input'>");
460
+ CX("<input type='checkbox' id='opt-cb-autofit' ");
461
+ CX("data-config='renderAutofit'>");
462
+ CX("<label for='opt-cb-autofit' "
463
+ "title='Attempt to scale SVG to fit viewport. "
464
+ "Whether it will work depends in part on the size "
465
+ "and shape of the image and the viewport.'"
466
+ ">Auto-fit SVG</label>");
467
+ CX("</span>");
468
+ CX("<span class='labeled-input'>");
469
+ CX("<input type='checkbox' id='opt-cb-autorender' ");
470
+ CX("data-csstgt='#main-wrapper' ");
471
+ CX("data-cssclass='auto-render' ");
472
+ CX("data-config='renderWhileTyping'>");
473
+ CX("<label for='opt-cb-autorender'>Render while typing</label>");
474
+ CX("</span>");
475
+ CX("<span class='labeled-input'>");
476
+ CX("<a href='?legacy'>Legacy mode</a>");
477
+ CX("</span>");
478
+ CX("</div><!-- options wrapper -->");
479
+ } CX("</fieldset>");
480
+ CX("<div id='main-wrapper' class=''>"); {
481
+ CX("<fieldset class='zone-wrapper input'>"); {
482
+ CX("<legend><div class='button-bar'>");
483
+ CX("<button id='btn-render' "
484
+ "title='Ctrl-Enter/Shift-Enter'>Render</button>");
485
+ CX("<button id='btn-clear'>Clear Input</button>");
486
+ CX("</div></legend>");
487
+ CX("<div><textarea id='input'");
488
+ CX("placeholder='Pikchr input. Ctrl-enter/shift-enter runs it.'>");
489
+ CX("/**\n");
490
+ CX(" Use ctrl-enter or shift-enter to execute\n");
491
+ CX(" pikchr code. If only a subset is currently\n");
492
+ CX(" selected, only that part is evaluated.\n*/\n");
493
+ CX("%s</textarea></div>",zContent/*safe-for-%s*/);
494
+ } CX("</fieldset><!-- .zone-wrapper.input -->");
495
+ /*CX("<div class='splitter-handle hidden'></div>");*/
496
+ CX("<fieldset class='zone-wrapper output'>"); {
497
+ CX("<legend><div class='button-bar'>");
498
+ CX("<button id='btn-render-mode'>Render Mode</button> ");
499
+ CX("<span style='white-space:nowrap'>"
500
+ "<span id='preview-copy-button' "
501
+ "title='Tap to copy to clipboard.'></span>"
502
+ "<label for='preview-copy-button' "
503
+ "title='Tap to copy to clipboard.'></label>"
504
+ "</span>");
505
+ CX("</div></legend>");
506
+ CX("<div id='pikchr-output-wrapper'>");
507
+ CX("<div id='pikchr-output'></div>");
508
+ CX("<textarea class='hidden' id='pikchr-output-text'></textarea>");
509
+ CX("</div>");
510
+ } CX("</fieldset> <!-- .zone-wrapper.output -->");
511
+ } CX("</div><!-- #main-wrapper -->");
512
+ } CX("</div><!-- #view-split -->");
513
+ builtin_fossil_js_bundle_or("dom", "storage", "copybutton", NULL);
514
+ builtin_request_js("fossil.page.pikchrshowasm.js");
515
+ builtin_fulfill_js_requests();
516
+ style_finish_page();
517
+}
518
+
381519
382520
/*
383521
** COMMAND: pikchr*
384522
**
385523
** Usage: %fossil pikchr [options] ?INFILE? ?OUTFILE?
386524
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -230,30 +230,36 @@
230 blob_reset(&bIn);
231 return isErr;
232 }
233
234 /*
235 ** WEBPAGE: pikchrshow
 
236 **
237 ** A pikchr code editor and previewer, allowing users to experiment
238 ** with pikchr code or prototype it for use in copy/pasting into forum
239 ** posts, wiki pages, or embedded docs.
240 **
241 ** It optionally accepts a p=pikchr-script-code URL parameter or POST
242 ** value to pre-populate the editor with that code.
 
243 */
244 void pikchrshow_page(void){
245 const char *zContent = 0;
246 int isDark; /* true if the current skin is "dark" */
247 int pikFlags =
248 PIKCHR_PROCESS_DIV
249 | PIKCHR_PROCESS_SRC
250 | PIKCHR_PROCESS_ERR_PRE;
251
252 login_check_credentials();
253 if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
254 cgi_redirectf("%R/login?g=pikchrshow");
 
 
 
 
255 }
256 zContent = PD("content",P("p"));
257 if(P("ajax")!=0){
258 /* Called from the JS-side preview updater.
259 TODO: respond with JSON instead.*/
@@ -279,11 +285,11 @@
279 "box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
280 "arrow right 200% \"HTML+SVG\" \"Output\"\n"
281 "arrow <-> down from last box.s\n"
282 "box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
283 }
284 style_header("PikchrShow");
285 CX("<style>"); {
286 CX("div.content { padding-top: 0.5em }\n");
287 CX("#sbs-wrapper {"
288 "display: flex; flex-direction: column;"
289 "}\n");
@@ -336,11 +342,11 @@
336 "vertical-align: middle"
337 "}\n");
338 CX(".dragover {border: 3px dotted rgba(0,255,0,0.6)}\n");
339 } CX("</style>");
340 CX("<div>Input pikchr code and tap Preview (or Shift-Enter) to render "
341 "it:</div>");
342 CX("<div id='sbs-wrapper'>"); {
343 CX("<div id='pikchrshow-form'>"); {
344 CX("<textarea id='content' name='content' rows='15'>"
345 "%s</textarea>",zContent/*safe-for-%s*/);
346 CX("<div id='pikchrshow-controls'>"); {
@@ -376,10 +382,142 @@
376 "storage", "pikchr", NULL);
377 builtin_request_js("fossil.page.pikchrshow.js");
378 builtin_fulfill_js_requests();
379 style_finish_page();
380 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
382 /*
383 ** COMMAND: pikchr*
384 **
385 ** Usage: %fossil pikchr [options] ?INFILE? ?OUTFILE?
386
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -230,30 +230,36 @@
230 blob_reset(&bIn);
231 return isErr;
232 }
233
234 /*
235 ** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
236 ** this one if the "legacy" or "ajax" request arguments are set.
237 **
238 ** A pikchr code editor and previewer, allowing users to experiment
239 ** with pikchr code or prototype it for use in copy/pasting into forum
240 ** posts, wiki pages, or embedded docs. This version of pikchrshow
241 ** uses JavaScript to send pikchr code to the server for
242 ** processing. The newer /pikchrshow applications runs pikchr on the
243 ** client machine, without the need for back-and-forth network
244 ** traffic.
245 */
246 void pikchrshowcs_page(void){
247 const char *zContent = 0;
248 int isDark; /* true if the current skin is "dark" */
249 int pikFlags =
250 PIKCHR_PROCESS_DIV
251 | PIKCHR_PROCESS_SRC
252 | PIKCHR_PROCESS_ERR_PRE;
253
254 login_check_credentials();
255 if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
256 cgi_redirectf("%R/login?g=pikchrshowcs");
257 }
258 if(P("wasm")){
259 pikchrshow_page();
260 return;
261 }
262 zContent = PD("content",P("p"));
263 if(P("ajax")!=0){
264 /* Called from the JS-side preview updater.
265 TODO: respond with JSON instead.*/
@@ -279,11 +285,11 @@
285 "box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
286 "arrow right 200% \"HTML+SVG\" \"Output\"\n"
287 "arrow <-> down from last box.s\n"
288 "box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
289 }
290 style_header("PikchrShow Client/Server");
291 CX("<style>"); {
292 CX("div.content { padding-top: 0.5em }\n");
293 CX("#sbs-wrapper {"
294 "display: flex; flex-direction: column;"
295 "}\n");
@@ -336,11 +342,11 @@
342 "vertical-align: middle"
343 "}\n");
344 CX(".dragover {border: 3px dotted rgba(0,255,0,0.6)}\n");
345 } CX("</style>");
346 CX("<div>Input pikchr code and tap Preview (or Shift-Enter) to render "
347 "it. <a href='?wasm'>Switch to WASM mode</a>.</div>");
348 CX("<div id='sbs-wrapper'>"); {
349 CX("<div id='pikchrshow-form'>"); {
350 CX("<textarea id='content' name='content' rows='15'>"
351 "%s</textarea>",zContent/*safe-for-%s*/);
352 CX("<div id='pikchrshow-controls'>"); {
@@ -376,10 +382,142 @@
382 "storage", "pikchr", NULL);
383 builtin_request_js("fossil.page.pikchrshow.js");
384 builtin_fulfill_js_requests();
385 style_finish_page();
386 }
387
388 /*
389 ** WEBPAGE: pikchrshow
390 **
391 ** A pikchr code editor and previewer, allowing users to experiment
392 ** with pikchr code or prototype it for use in copy/pasting into forum
393 ** posts, wiki pages, or embedded docs. This version of pikchrshow
394 ** uses WebAssembly to run entirely in the client browser, without a
395 ** need for back-and-forth client/server traffic to perform the
396 ** rendering. The "legacy" version of this application, which sends
397 ** all input to the server for rendering, can be accessed by adding
398 ** the "legacy" URL argument.
399 **
400 ** It optionally accepts a p=pikchr-script-code URL parameter or POST
401 ** value to pre-populate the editor with that code.
402 */
403 void pikchrshow_page(void){
404 const char *zContent = 0;
405
406 if(P("legacy") || P("ajax")){
407 pikchrshowcs_page();
408 return;
409 }
410 login_check_credentials();
411 if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
412 cgi_redirectf("%R/login?g=pikchrshow");
413 }
414 style_emit_noscript_for_js_page();
415 style_header("PikchrShow");
416 zContent = PD("content",P("p"));
417 if(!zContent){
418 zContent = "arrow right 200% \"Markdown\" \"Source\"\n"
419 "box rad 10px \"Markdown\" \"Formatter\" \"(markdown.c)\" fit\n"
420 "arrow right 200% \"HTML+SVG\" \"Output\"\n"
421 "arrow <-> down from last box.s\n"
422 "box same \"Pikchr\" \"Formatter\" \"(pikchr.c)\" fit\n";
423 }
424 /* Wasm load/init progress widget... */
425 CX("<div class='emscripten'>"); {
426 CX("<figure id='module-spinner'>");
427 CX("<div class='spinner'></div>");
428 CX("<div class='center'><strong>Initializing app...</strong></div>");
429 CX("<div class='center'>");
430 CX("On a slow internet connection this may take a moment. If this ");
431 CX("message displays for \"a long time\", intialization may have ");
432 CX("failed and the JavaScript console may contain clues as to why. ");
433 CX("</div>");
434 CX("<div><a href='?legacy'>Switch to legacy mode</a></div>");
435 CX("</figure>");
436 CX("<div class='emscripten' id='module-status'>Downloading...</div>");
437 CX("<progress value='0' max='100' id='module-progress' hidden='1'>"
438 "</progress>");
439 } CX("</div><!-- .emscripten -->");
440 /* Main view... */
441 CX("<div id='view-split' class='app-view initially-hidden'>"); {
442 CX("<fieldset class='options collapsible'>"); {
443 CX("<legend><button id='btn-options-toggle'>Options</button></legend>");
444 CX("<div>");
445 CX("<span class='labeled-input'>");
446 CX("<input type='checkbox' id='opt-cb-sbs' ");
447 CX("data-csstgt='#main-wrapper' ");
448 CX("data-cssclass='side-by-side' ");
449 CX("data-config='sideBySide'>");
450 CX("<label for='opt-cb-sbs'>Side-by-side</label>");
451 CX("</span>");
452 CX("<span class='labeled-input'>");
453 CX("<input type='checkbox' id='opt-cb-swapio' ");
454 CX("data-csstgt='#main-wrapper' ");
455 CX("data-cssclass='swapio' ");
456 CX("data-config='swapInOut'>");
457 CX("<label for='opt-cb-swapio'>Swap in/out</label>");
458 CX("</span>");
459 CX("<span class='labeled-input'>");
460 CX("<input type='checkbox' id='opt-cb-autofit' ");
461 CX("data-config='renderAutofit'>");
462 CX("<label for='opt-cb-autofit' "
463 "title='Attempt to scale SVG to fit viewport. "
464 "Whether it will work depends in part on the size "
465 "and shape of the image and the viewport.'"
466 ">Auto-fit SVG</label>");
467 CX("</span>");
468 CX("<span class='labeled-input'>");
469 CX("<input type='checkbox' id='opt-cb-autorender' ");
470 CX("data-csstgt='#main-wrapper' ");
471 CX("data-cssclass='auto-render' ");
472 CX("data-config='renderWhileTyping'>");
473 CX("<label for='opt-cb-autorender'>Render while typing</label>");
474 CX("</span>");
475 CX("<span class='labeled-input'>");
476 CX("<a href='?legacy'>Legacy mode</a>");
477 CX("</span>");
478 CX("</div><!-- options wrapper -->");
479 } CX("</fieldset>");
480 CX("<div id='main-wrapper' class=''>"); {
481 CX("<fieldset class='zone-wrapper input'>"); {
482 CX("<legend><div class='button-bar'>");
483 CX("<button id='btn-render' "
484 "title='Ctrl-Enter/Shift-Enter'>Render</button>");
485 CX("<button id='btn-clear'>Clear Input</button>");
486 CX("</div></legend>");
487 CX("<div><textarea id='input'");
488 CX("placeholder='Pikchr input. Ctrl-enter/shift-enter runs it.'>");
489 CX("/**\n");
490 CX(" Use ctrl-enter or shift-enter to execute\n");
491 CX(" pikchr code. If only a subset is currently\n");
492 CX(" selected, only that part is evaluated.\n*/\n");
493 CX("%s</textarea></div>",zContent/*safe-for-%s*/);
494 } CX("</fieldset><!-- .zone-wrapper.input -->");
495 /*CX("<div class='splitter-handle hidden'></div>");*/
496 CX("<fieldset class='zone-wrapper output'>"); {
497 CX("<legend><div class='button-bar'>");
498 CX("<button id='btn-render-mode'>Render Mode</button> ");
499 CX("<span style='white-space:nowrap'>"
500 "<span id='preview-copy-button' "
501 "title='Tap to copy to clipboard.'></span>"
502 "<label for='preview-copy-button' "
503 "title='Tap to copy to clipboard.'></label>"
504 "</span>");
505 CX("</div></legend>");
506 CX("<div id='pikchr-output-wrapper'>");
507 CX("<div id='pikchr-output'></div>");
508 CX("<textarea class='hidden' id='pikchr-output-text'></textarea>");
509 CX("</div>");
510 } CX("</fieldset> <!-- .zone-wrapper.output -->");
511 } CX("</div><!-- #main-wrapper -->");
512 } CX("</div><!-- #view-split -->");
513 builtin_fossil_js_bundle_or("dom", "storage", "copybutton", NULL);
514 builtin_request_js("fossil.page.pikchrshowasm.js");
515 builtin_fulfill_js_requests();
516 style_finish_page();
517 }
518
519
520 /*
521 ** COMMAND: pikchr*
522 **
523 ** Usage: %fossil pikchr [options] ?INFILE? ?OUTFILE?
524
+2 -2
--- src/style.c
+++ src/style.c
@@ -901,11 +901,11 @@
901901
static void style_load_all_js_files(void){
902902
if( needHrefJs && g.perm.Hyperlink ){
903903
int nDelay = db_get_int("auto-hyperlink-delay",0);
904904
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0)
905905
&& sqlite3_strglob("*Android*",PD("HTTP_USER_AGENT",""));
906
- @ <script id='href-data' type='application/json'>\
906
+ @ <script id='href-data' type='text/json'>\
907907
@ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
908908
}
909909
@ <script nonce="%h(style_nonce())">/* style.c:%d(__LINE__) */
910910
@ function debugMsg(msg){
911911
@ var n = document.getElementById("debugMsg");
@@ -1220,11 +1220,11 @@
12201220
/* Render the script as plain-text for testing purposes, if the "test"
12211221
** query parameter is present */
12221222
cgi_set_content_type("text/plain");
12231223
}else{
12241224
/* Default behavior is to return javascript */
1225
- cgi_set_content_type("application/javascript");
1225
+ cgi_set_content_type("text/javascript");
12261226
}
12271227
style_init_th1_vars(0);
12281228
Th_Render(zScript?zScript:"");
12291229
}
12301230
12311231
12321232
ADDED src/style.pikchrshow.css
12331233
ADDED tools/emcc.sh.in
--- src/style.c
+++ src/style.c
@@ -901,11 +901,11 @@
901 static void style_load_all_js_files(void){
902 if( needHrefJs && g.perm.Hyperlink ){
903 int nDelay = db_get_int("auto-hyperlink-delay",0);
904 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0)
905 && sqlite3_strglob("*Android*",PD("HTTP_USER_AGENT",""));
906 @ <script id='href-data' type='application/json'>\
907 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
908 }
909 @ <script nonce="%h(style_nonce())">/* style.c:%d(__LINE__) */
910 @ function debugMsg(msg){
911 @ var n = document.getElementById("debugMsg");
@@ -1220,11 +1220,11 @@
1220 /* Render the script as plain-text for testing purposes, if the "test"
1221 ** query parameter is present */
1222 cgi_set_content_type("text/plain");
1223 }else{
1224 /* Default behavior is to return javascript */
1225 cgi_set_content_type("application/javascript");
1226 }
1227 style_init_th1_vars(0);
1228 Th_Render(zScript?zScript:"");
1229 }
1230
1231
1232 DDED src/style.pikchrshow.css
1233 DDED tools/emcc.sh.in
--- src/style.c
+++ src/style.c
@@ -901,11 +901,11 @@
901 static void style_load_all_js_files(void){
902 if( needHrefJs && g.perm.Hyperlink ){
903 int nDelay = db_get_int("auto-hyperlink-delay",0);
904 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0)
905 && sqlite3_strglob("*Android*",PD("HTTP_USER_AGENT",""));
906 @ <script id='href-data' type='text/json'>\
907 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
908 }
909 @ <script nonce="%h(style_nonce())">/* style.c:%d(__LINE__) */
910 @ function debugMsg(msg){
911 @ var n = document.getElementById("debugMsg");
@@ -1220,11 +1220,11 @@
1220 /* Render the script as plain-text for testing purposes, if the "test"
1221 ** query parameter is present */
1222 cgi_set_content_type("text/plain");
1223 }else{
1224 /* Default behavior is to return javascript */
1225 cgi_set_content_type("text/javascript");
1226 }
1227 style_init_th1_vars(0);
1228 Th_Render(zScript?zScript:"");
1229 }
1230
1231
1232 DDED src/style.pikchrshow.css
1233 DDED tools/emcc.sh.in
--- a/src/style.pikchrshow.css
+++ b/src/style.pikchrshow.css
@@ -0,0 +1,64 @@
1
+ during the module load/initialization processes... */
2
+.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
3
+div.emscripten { text-align: center; }
4
+div.emscripten_border { border: 1px solid black; }
5
+#module-spinner { overflow: visible; }
6
+#module-spinner > * {
7
+ margin-top: 1em;
8
+}
9
+.spinner {
10
+ height: 50px;
11
+ width: 50px;
12
+ margin: 0px auto;
13
+ animation: rotation 0.8s linear infinite;
14
+ border-left: 10px solid rgb(0,150,240);
15
+ border-right: 10px solid rgb(0,150,240);
16
+ border-bottom: 10px solid rgb(0,150,240);
17
+ border-top: 10px solid rgb(100,0,200);
18
+ border-radius: 100%;
19
+ background-color: rgb(200,100,250);
20
+}
21
+@keyframes rotation {
22
+ from {transform: rotate(0deg);}
23
+ to {transform: rotate(360deg);}
24
+}
25
+
26
+/* The following styles are for app-level use. */
27
+/* TODO: consolidate the WASM- and legacy-mode CSS into this file.
28
+ Since both versions of /pikchrshow share a URI, they both load this
29
+ file. */theytextarea {
30
+ font-family: monospawrapper {
31
+ display: flex;
32
+ flex-direction: column-reverse;
33
+ flex: 1 1 auto;
34
+ margin: 0.5em 0;
35
+ overflow: hidden;
36
+}
37
+#main-wrapper.side-by-side {
38
+ flex-direction: row;
39
+}
40
+#main-wrapper.side-by-side > fieldset {
41
+ margin-left: 0.25em;
42
+ margin-right: 0.25em;
43
+}
44
+#main-wrapper:not(.side-by-side) > fieldset {
45
+ margin-bottom: 0.25em;
46
+}
47
+#main-wrapper.swapio {
48
+ flex-direction: column;
49
+}
50
+#main-wrapper.side-by-side.swapio {
51
+ flex-direction: row-reverse;
52
+}
53
+.zone-wrapper{
54
+ display: flex;
55
+ margin: 0;
56
+ flex: 1 1 0%;
57
+ border-rad#main-wrapper .splitter-ha 1px outsetR@vq,T@JC,V:.splitter-handle {
58
+ width: 2pxH@K0,13::not(.side-by-side) .splitter-handle {
59
+ width: 100%;
60
+ height: 2px3u@OQ,M@pR,Y@aB,2:0%R@jE,T@JC,IS@TJ,2:/*H@ZW,c@l0,2:*/T@mb,2T:-top: 0.1em/*avoid crowding if the controls wrap*/;
61
+ vertical-align: middle;
62
+}
63
+.button-bar > * + * /*all children except the first*/ {
64
+ margin-left: 0.65em3U@o0,V:options > legend > #btn-optionsV@tt,4:hideS@uR,n:fieldset.options.collapsed > legend > #btn-options~@tt,7B@ur,Rr7eC;
--- a/src/style.pikchrshow.css
+++ b/src/style.pikchrshow.css
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/style.pikchrshow.css
+++ b/src/style.pikchrshow.css
@@ -0,0 +1,64 @@
1 during the module load/initialization processes... */
2 .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
3 div.emscripten { text-align: center; }
4 div.emscripten_border { border: 1px solid black; }
5 #module-spinner { overflow: visible; }
6 #module-spinner > * {
7 margin-top: 1em;
8 }
9 .spinner {
10 height: 50px;
11 width: 50px;
12 margin: 0px auto;
13 animation: rotation 0.8s linear infinite;
14 border-left: 10px solid rgb(0,150,240);
15 border-right: 10px solid rgb(0,150,240);
16 border-bottom: 10px solid rgb(0,150,240);
17 border-top: 10px solid rgb(100,0,200);
18 border-radius: 100%;
19 background-color: rgb(200,100,250);
20 }
21 @keyframes rotation {
22 from {transform: rotate(0deg);}
23 to {transform: rotate(360deg);}
24 }
25
26 /* The following styles are for app-level use. */
27 /* TODO: consolidate the WASM- and legacy-mode CSS into this file.
28 Since both versions of /pikchrshow share a URI, they both load this
29 file. */theytextarea {
30 font-family: monospawrapper {
31 display: flex;
32 flex-direction: column-reverse;
33 flex: 1 1 auto;
34 margin: 0.5em 0;
35 overflow: hidden;
36 }
37 #main-wrapper.side-by-side {
38 flex-direction: row;
39 }
40 #main-wrapper.side-by-side > fieldset {
41 margin-left: 0.25em;
42 margin-right: 0.25em;
43 }
44 #main-wrapper:not(.side-by-side) > fieldset {
45 margin-bottom: 0.25em;
46 }
47 #main-wrapper.swapio {
48 flex-direction: column;
49 }
50 #main-wrapper.side-by-side.swapio {
51 flex-direction: row-reverse;
52 }
53 .zone-wrapper{
54 display: flex;
55 margin: 0;
56 flex: 1 1 0%;
57 border-rad#main-wrapper .splitter-ha 1px outsetR@vq,T@JC,V:.splitter-handle {
58 width: 2pxH@K0,13::not(.side-by-side) .splitter-handle {
59 width: 100%;
60 height: 2px3u@OQ,M@pR,Y@aB,2:0%R@jE,T@JC,IS@TJ,2:/*H@ZW,c@l0,2:*/T@mb,2T:-top: 0.1em/*avoid crowding if the controls wrap*/;
61 vertical-align: middle;
62 }
63 .button-bar > * + * /*all children except the first*/ {
64 margin-left: 0.65em3U@o0,V:options > legend > #btn-optionsV@tt,4:hideS@uR,n:fieldset.options.collapsed > legend > #btn-options~@tt,7B@ur,Rr7eC;
--- a/tools/emcc.sh.in
+++ b/tools/emcc.sh.in
@@ -0,0 +1,65 @@
1
+#!/usr/bin/bash
2
+#############################################
3
+# WARNING: emcc.sh is generated from emcc.sh.in by the configure
4
+# process. Do not edit emcc.sh directly, as it may be deleted or
5
+# overwritten by the configure script.
6
+#
7
+# A wrapper around the emcc compiler which uses configure-time state
8
+# to locate the Emscripten SDK and import the SDK's environment
9
+# script, if needed.
10
+########################################################################
11
+# EMSDK_HOME comes from the configure --with-emsdk=/dir flag.
12
+# EMSDK_ENVk=/dir flag.
13
+# EMSDK_ENV_SH is ${thatDir}/emsdk_env.sh and is also set by the
14
+# ="@EMSDK_ENV@"
15
+
16
+emc`which emcc 2>/dev/null`
17
+fi
18
+
19
+if [ x = "x${emcc}" ]; then
20
+ # If emcc is not found in the path, try to find it via an emsdk
21
+ # installation. The SDK variant i
22
+ # style^^^^ Please try to keep this #!/bin/sh
23
+ emcc is also available
24
+ # via package managers on some OSes.
25
+ if [ x = "x${EMSDK_HOME}" ]; then
26
+ echo "EMSDK_HOME is not set. Pass --with-emsdk=/path/to/emsdk" \
27
+ "to the configure script." 1>&2
28
+ exit 1
29
+ fi
30
+
31
+ if [ x = "x${EMSDK_ENV_SH}" ]; then
32
+ if [ -f "${EMSDK_HOME}/emsdk_env.sh" ]; then
33
+ EMSDK_ENV_SH="${EMSDK_HOME}/emsdk_env.sh"
34
+ else
35
+ echo "EMSDK_ENV_SH is not set. Expecting configure script to set it." 1>&2
36
+ exit 2
37
+ fi
38
+ fi
39
+
40
+ if [ ! -f "${EMSDK_ENV_SH}" ]; then
41
+ echo "emsdk_env script not found: $EMSDK_ENV_SH" 1>&2
42
+ exit 3
43
+ fi
44
+
45
+ # $EMSDK is part of the state set by emsdk_env.sh.
46
+ if [ x = "x${EMSDK}" ]; then
47
+ EMSDK_QUIET=1
48
+ export EMSDK_QUIET
49
+ # ^^^ Squelches informational output from ${EMSDK_ENV_SH}.
50
+ source "${EMSDK_ENV_SH}" || {
51
+ rc=$?
52
+ echo "Error sourcing ${EMSDK_ENV_SH}"
53
+ exit $rc
54
+ }
55
+ fi
56
+ emcc=`which emcc 2>/dev/null`
57
+ if [ x = "x${emcc}" ]; then
58
+ echo "emcc not found in PATH. Normally that's set up by ${EMSDK_ENV_SH}." 1>&2
59
+ exit 4
60
+ fi
61
+fi
62
+
63
+exec $emcc "$@"
64
+}" ]; then
65
+ emcc "$@"
--- a/tools/emcc.sh.in
+++ b/tools/emcc.sh.in
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/tools/emcc.sh.in
+++ b/tools/emcc.sh.in
@@ -0,0 +1,65 @@
1 #!/usr/bin/bash
2 #############################################
3 # WARNING: emcc.sh is generated from emcc.sh.in by the configure
4 # process. Do not edit emcc.sh directly, as it may be deleted or
5 # overwritten by the configure script.
6 #
7 # A wrapper around the emcc compiler which uses configure-time state
8 # to locate the Emscripten SDK and import the SDK's environment
9 # script, if needed.
10 ########################################################################
11 # EMSDK_HOME comes from the configure --with-emsdk=/dir flag.
12 # EMSDK_ENVk=/dir flag.
13 # EMSDK_ENV_SH is ${thatDir}/emsdk_env.sh and is also set by the
14 # ="@EMSDK_ENV@"
15
16 emc`which emcc 2>/dev/null`
17 fi
18
19 if [ x = "x${emcc}" ]; then
20 # If emcc is not found in the path, try to find it via an emsdk
21 # installation. The SDK variant i
22 # style^^^^ Please try to keep this #!/bin/sh
23 emcc is also available
24 # via package managers on some OSes.
25 if [ x = "x${EMSDK_HOME}" ]; then
26 echo "EMSDK_HOME is not set. Pass --with-emsdk=/path/to/emsdk" \
27 "to the configure script." 1>&2
28 exit 1
29 fi
30
31 if [ x = "x${EMSDK_ENV_SH}" ]; then
32 if [ -f "${EMSDK_HOME}/emsdk_env.sh" ]; then
33 EMSDK_ENV_SH="${EMSDK_HOME}/emsdk_env.sh"
34 else
35 echo "EMSDK_ENV_SH is not set. Expecting configure script to set it." 1>&2
36 exit 2
37 fi
38 fi
39
40 if [ ! -f "${EMSDK_ENV_SH}" ]; then
41 echo "emsdk_env script not found: $EMSDK_ENV_SH" 1>&2
42 exit 3
43 fi
44
45 # $EMSDK is part of the state set by emsdk_env.sh.
46 if [ x = "x${EMSDK}" ]; then
47 EMSDK_QUIET=1
48 export EMSDK_QUIET
49 # ^^^ Squelches informational output from ${EMSDK_ENV_SH}.
50 source "${EMSDK_ENV_SH}" || {
51 rc=$?
52 echo "Error sourcing ${EMSDK_ENV_SH}"
53 exit $rc
54 }
55 fi
56 emcc=`which emcc 2>/dev/null`
57 if [ x = "x${emcc}" ]; then
58 echo "emcc not found in PATH. Normally that's set up by ${EMSDK_ENV_SH}." 1>&2
59 exit 4
60 fi
61 fi
62
63 exec $emcc "$@"
64 }" ]; then
65 emcc "$@"
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -217,10 +217,12 @@
217217
default.css
218218
style.*.css
219219
../skins/*/*.txt
220220
sounds/*.wav
221221
alerts/*.wav
222
+ ../extsrc/pikchr.wasm
223
+ ../extsrc/pikchr*.js
222224
}
223225
224226
# Options used to compile the included SQLite library.
225227
#
226228
set SQLITE_OPTIONS {
@@ -559,10 +561,21 @@
559561
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
560562
561563
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
562564
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
563565
566
+$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c
567
+ $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
568
+ -sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore \
569
+ -sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c \
570
+ -sENVIRONMENT=web \
571
+ -sMODULARIZE \
572
+ -sEXPORT_NAME=initPikchrModule \
573
+ --minify 0
574
+ @chmod -x $(SRCDIR_extsrc)/pikchr.wasm
575
+wasm: $(SRCDIR_extsrc)/pikchr.js
576
+
564577
#
565578
# The list of all the targets that do not correspond to real files. This stops
566579
# 'make' from getting confused when someone makes an error in a rule.
567580
#
568581
@@ -637,11 +650,11 @@
637650
638651
#### Enable compiling with debug symbols (much larger binary)
639652
#
640653
# FOSSIL_ENABLE_SYMBOLS = 1
641654
642
-#### Enable JSON (http://www.json.org) support using "cson"
655
+#### Enable JSON (https://www.json.org) support using "cson"
643656
#
644657
# FOSSIL_ENABLE_JSON = 1
645658
646659
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
647660
#
648661
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -217,10 +217,12 @@
217 default.css
218 style.*.css
219 ../skins/*/*.txt
220 sounds/*.wav
221 alerts/*.wav
 
 
222 }
223
224 # Options used to compile the included SQLite library.
225 #
226 set SQLITE_OPTIONS {
@@ -559,10 +561,21 @@
559 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
560
561 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
562 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
563
 
 
 
 
 
 
 
 
 
 
 
564 #
565 # The list of all the targets that do not correspond to real files. This stops
566 # 'make' from getting confused when someone makes an error in a rule.
567 #
568
@@ -637,11 +650,11 @@
637
638 #### Enable compiling with debug symbols (much larger binary)
639 #
640 # FOSSIL_ENABLE_SYMBOLS = 1
641
642 #### Enable JSON (http://www.json.org) support using "cson"
643 #
644 # FOSSIL_ENABLE_JSON = 1
645
646 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
647 #
648
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -217,10 +217,12 @@
217 default.css
218 style.*.css
219 ../skins/*/*.txt
220 sounds/*.wav
221 alerts/*.wav
222 ../extsrc/pikchr.wasm
223 ../extsrc/pikchr*.js
224 }
225
226 # Options used to compile the included SQLite library.
227 #
228 set SQLITE_OPTIONS {
@@ -559,10 +561,21 @@
561 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
562
563 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
564 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
565
566 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c
567 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
568 -sEXPORTED_RUNTIME_METHODS=cwrap,setValue,getValue,stackSave,stackRestore \
569 -sEXPORTED_FUNCTIONS=_pikchr $(SRCDIR_extsrc)/pikchr.c \
570 -sENVIRONMENT=web \
571 -sMODULARIZE \
572 -sEXPORT_NAME=initPikchrModule \
573 --minify 0
574 @chmod -x $(SRCDIR_extsrc)/pikchr.wasm
575 wasm: $(SRCDIR_extsrc)/pikchr.js
576
577 #
578 # The list of all the targets that do not correspond to real files. This stops
579 # 'make' from getting confused when someone makes an error in a rule.
580 #
581
@@ -637,11 +650,11 @@
650
651 #### Enable compiling with debug symbols (much larger binary)
652 #
653 # FOSSIL_ENABLE_SYMBOLS = 1
654
655 #### Enable JSON (https://www.json.org) support using "cson"
656 #
657 # FOSSIL_ENABLE_JSON = 1
658
659 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
660 #
661
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -54,11 +54,11 @@
5454
5555
#### Enable compiling with debug symbols (much larger binary)
5656
#
5757
# FOSSIL_ENABLE_SYMBOLS = 1
5858
59
-#### Enable JSON (http://www.json.org) support using "cson"
59
+#### Enable JSON (https://www.json.org) support using "cson"
6060
#
6161
# FOSSIL_ENABLE_JSON = 1
6262
6363
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
6464
#
@@ -549,10 +549,13 @@
549549
$(SRCDIR)/xfer.c \
550550
$(SRCDIR)/xfersetup.c \
551551
$(SRCDIR)/zip.c
552552
553553
EXTRA_FILES = \
554
+ $(SRCDIR)/../extsrc/pikchr-worker.js \
555
+ $(SRCDIR)/../extsrc/pikchr.js \
556
+ $(SRCDIR)/../extsrc/pikchr.wasm \
554557
$(SRCDIR)/../skins/ardoise/css.txt \
555558
$(SRCDIR)/../skins/ardoise/details.txt \
556559
$(SRCDIR)/../skins/ardoise/footer.txt \
557560
$(SRCDIR)/../skins/ardoise/header.txt \
558561
$(SRCDIR)/../skins/black_and_white/css.txt \
@@ -617,10 +620,11 @@
617620
$(SRCDIR)/fossil.page.brlist.js \
618621
$(SRCDIR)/fossil.page.chat.js \
619622
$(SRCDIR)/fossil.page.fileedit.js \
620623
$(SRCDIR)/fossil.page.forumpost.js \
621624
$(SRCDIR)/fossil.page.pikchrshow.js \
625
+ $(SRCDIR)/fossil.page.pikchrshowasm.js \
622626
$(SRCDIR)/fossil.page.whistory.js \
623627
$(SRCDIR)/fossil.page.wikiedit.js \
624628
$(SRCDIR)/fossil.pikchr.js \
625629
$(SRCDIR)/fossil.popupwidget.js \
626630
$(SRCDIR)/fossil.storage.js \
@@ -652,10 +656,11 @@
652656
$(SRCDIR)/sounds/e.wav \
653657
$(SRCDIR)/sounds/f.wav \
654658
$(SRCDIR)/style.admin_log.css \
655659
$(SRCDIR)/style.chat.css \
656660
$(SRCDIR)/style.fileedit.css \
661
+ $(SRCDIR)/style.pikchrshow.css \
657662
$(SRCDIR)/style.wikiedit.css \
658663
$(SRCDIR)/tree.js \
659664
$(SRCDIR)/useredit.js \
660665
$(SRCDIR)/wiki.wiki
661666
662667
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -54,11 +54,11 @@
54
55 #### Enable compiling with debug symbols (much larger binary)
56 #
57 # FOSSIL_ENABLE_SYMBOLS = 1
58
59 #### Enable JSON (http://www.json.org) support using "cson"
60 #
61 # FOSSIL_ENABLE_JSON = 1
62
63 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
64 #
@@ -549,10 +549,13 @@
549 $(SRCDIR)/xfer.c \
550 $(SRCDIR)/xfersetup.c \
551 $(SRCDIR)/zip.c
552
553 EXTRA_FILES = \
 
 
 
554 $(SRCDIR)/../skins/ardoise/css.txt \
555 $(SRCDIR)/../skins/ardoise/details.txt \
556 $(SRCDIR)/../skins/ardoise/footer.txt \
557 $(SRCDIR)/../skins/ardoise/header.txt \
558 $(SRCDIR)/../skins/black_and_white/css.txt \
@@ -617,10 +620,11 @@
617 $(SRCDIR)/fossil.page.brlist.js \
618 $(SRCDIR)/fossil.page.chat.js \
619 $(SRCDIR)/fossil.page.fileedit.js \
620 $(SRCDIR)/fossil.page.forumpost.js \
621 $(SRCDIR)/fossil.page.pikchrshow.js \
 
622 $(SRCDIR)/fossil.page.whistory.js \
623 $(SRCDIR)/fossil.page.wikiedit.js \
624 $(SRCDIR)/fossil.pikchr.js \
625 $(SRCDIR)/fossil.popupwidget.js \
626 $(SRCDIR)/fossil.storage.js \
@@ -652,10 +656,11 @@
652 $(SRCDIR)/sounds/e.wav \
653 $(SRCDIR)/sounds/f.wav \
654 $(SRCDIR)/style.admin_log.css \
655 $(SRCDIR)/style.chat.css \
656 $(SRCDIR)/style.fileedit.css \
 
657 $(SRCDIR)/style.wikiedit.css \
658 $(SRCDIR)/tree.js \
659 $(SRCDIR)/useredit.js \
660 $(SRCDIR)/wiki.wiki
661
662
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -54,11 +54,11 @@
54
55 #### Enable compiling with debug symbols (much larger binary)
56 #
57 # FOSSIL_ENABLE_SYMBOLS = 1
58
59 #### Enable JSON (https://www.json.org) support using "cson"
60 #
61 # FOSSIL_ENABLE_JSON = 1
62
63 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
64 #
@@ -549,10 +549,13 @@
549 $(SRCDIR)/xfer.c \
550 $(SRCDIR)/xfersetup.c \
551 $(SRCDIR)/zip.c
552
553 EXTRA_FILES = \
554 $(SRCDIR)/../extsrc/pikchr-worker.js \
555 $(SRCDIR)/../extsrc/pikchr.js \
556 $(SRCDIR)/../extsrc/pikchr.wasm \
557 $(SRCDIR)/../skins/ardoise/css.txt \
558 $(SRCDIR)/../skins/ardoise/details.txt \
559 $(SRCDIR)/../skins/ardoise/footer.txt \
560 $(SRCDIR)/../skins/ardoise/header.txt \
561 $(SRCDIR)/../skins/black_and_white/css.txt \
@@ -617,10 +620,11 @@
620 $(SRCDIR)/fossil.page.brlist.js \
621 $(SRCDIR)/fossil.page.chat.js \
622 $(SRCDIR)/fossil.page.fileedit.js \
623 $(SRCDIR)/fossil.page.forumpost.js \
624 $(SRCDIR)/fossil.page.pikchrshow.js \
625 $(SRCDIR)/fossil.page.pikchrshowasm.js \
626 $(SRCDIR)/fossil.page.whistory.js \
627 $(SRCDIR)/fossil.page.wikiedit.js \
628 $(SRCDIR)/fossil.pikchr.js \
629 $(SRCDIR)/fossil.popupwidget.js \
630 $(SRCDIR)/fossil.storage.js \
@@ -652,10 +656,11 @@
656 $(SRCDIR)/sounds/e.wav \
657 $(SRCDIR)/sounds/f.wav \
658 $(SRCDIR)/style.admin_log.css \
659 $(SRCDIR)/style.chat.css \
660 $(SRCDIR)/style.fileedit.css \
661 $(SRCDIR)/style.pikchrshow.css \
662 $(SRCDIR)/style.wikiedit.css \
663 $(SRCDIR)/tree.js \
664 $(SRCDIR)/useredit.js \
665 $(SRCDIR)/wiki.wiki
666
667
+12 -2
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -505,11 +505,14 @@
505505
"$(OX)\xfer_.c" \
506506
"$(OX)\xfersetup_.c" \
507507
"$(OX)\zip_.c" \
508508
"$(SRCDIR_extsrc)\pikchr.c"
509509
510
-EXTRA_FILES = "$(SRCDIR)\..\skins\ardoise\css.txt" \
510
+EXTRA_FILES = "$(SRCDIR)\..\extsrc\pikchr-worker.js" \
511
+ "$(SRCDIR)\..\extsrc\pikchr.js" \
512
+ "$(SRCDIR)\..\extsrc\pikchr.wasm" \
513
+ "$(SRCDIR)\..\skins\ardoise\css.txt" \
511514
"$(SRCDIR)\..\skins\ardoise\details.txt" \
512515
"$(SRCDIR)\..\skins\ardoise\footer.txt" \
513516
"$(SRCDIR)\..\skins\ardoise\header.txt" \
514517
"$(SRCDIR)\..\skins\black_and_white\css.txt" \
515518
"$(SRCDIR)\..\skins\black_and_white\details.txt" \
@@ -573,10 +576,11 @@
573576
"$(SRCDIR)\fossil.page.brlist.js" \
574577
"$(SRCDIR)\fossil.page.chat.js" \
575578
"$(SRCDIR)\fossil.page.fileedit.js" \
576579
"$(SRCDIR)\fossil.page.forumpost.js" \
577580
"$(SRCDIR)\fossil.page.pikchrshow.js" \
581
+ "$(SRCDIR)\fossil.page.pikchrshowasm.js" \
578582
"$(SRCDIR)\fossil.page.whistory.js" \
579583
"$(SRCDIR)\fossil.page.wikiedit.js" \
580584
"$(SRCDIR)\fossil.pikchr.js" \
581585
"$(SRCDIR)\fossil.popupwidget.js" \
582586
"$(SRCDIR)\fossil.storage.js" \
@@ -608,10 +612,11 @@
608612
"$(SRCDIR)\sounds\e.wav" \
609613
"$(SRCDIR)\sounds\f.wav" \
610614
"$(SRCDIR)\style.admin_log.css" \
611615
"$(SRCDIR)\style.chat.css" \
612616
"$(SRCDIR)\style.fileedit.css" \
617
+ "$(SRCDIR)\style.pikchrshow.css" \
613618
"$(SRCDIR)\style.wikiedit.css" \
614619
"$(SRCDIR)\tree.js" \
615620
"$(SRCDIR)\useredit.js" \
616621
"$(SRCDIR)\wiki.wiki"
617622
@@ -1129,11 +1134,14 @@
11291134
"$(OBJDIR)\json_timeline$O" : "$(SRCDIR)\json_detail.h"
11301135
"$(OBJDIR)\json_user$O" : "$(SRCDIR)\json_detail.h"
11311136
"$(OBJDIR)\json_wiki$O" : "$(SRCDIR)\json_detail.h"
11321137
11331138
"$(OX)\builtin_data.reslist": $(EXTRA_FILES) "$(B)\win\Makefile.msc"
1134
- echo "$(SRCDIR)\../skins/ardoise/css.txt" > $@
1139
+ echo "$(SRCDIR)\../extsrc/pikchr-worker.js" > $@
1140
+ echo "$(SRCDIR)\../extsrc/pikchr.js" >> $@
1141
+ echo "$(SRCDIR)\../extsrc/pikchr.wasm" >> $@
1142
+ echo "$(SRCDIR)\../skins/ardoise/css.txt" >> $@
11351143
echo "$(SRCDIR)\../skins/ardoise/details.txt" >> $@
11361144
echo "$(SRCDIR)\../skins/ardoise/footer.txt" >> $@
11371145
echo "$(SRCDIR)\../skins/ardoise/header.txt" >> $@
11381146
echo "$(SRCDIR)\../skins/black_and_white/css.txt" >> $@
11391147
echo "$(SRCDIR)\../skins/black_and_white/details.txt" >> $@
@@ -1197,10 +1205,11 @@
11971205
echo "$(SRCDIR)\fossil.page.brlist.js" >> $@
11981206
echo "$(SRCDIR)\fossil.page.chat.js" >> $@
11991207
echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
12001208
echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
12011209
echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@
1210
+ echo "$(SRCDIR)\fossil.page.pikchrshowasm.js" >> $@
12021211
echo "$(SRCDIR)\fossil.page.whistory.js" >> $@
12031212
echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
12041213
echo "$(SRCDIR)\fossil.pikchr.js" >> $@
12051214
echo "$(SRCDIR)\fossil.popupwidget.js" >> $@
12061215
echo "$(SRCDIR)\fossil.storage.js" >> $@
@@ -1232,10 +1241,11 @@
12321241
echo "$(SRCDIR)\sounds/e.wav" >> $@
12331242
echo "$(SRCDIR)\sounds/f.wav" >> $@
12341243
echo "$(SRCDIR)\style.admin_log.css" >> $@
12351244
echo "$(SRCDIR)\style.chat.css" >> $@
12361245
echo "$(SRCDIR)\style.fileedit.css" >> $@
1246
+ echo "$(SRCDIR)\style.pikchrshow.css" >> $@
12371247
echo "$(SRCDIR)\style.wikiedit.css" >> $@
12381248
echo "$(SRCDIR)\tree.js" >> $@
12391249
echo "$(SRCDIR)\useredit.js" >> $@
12401250
echo "$(SRCDIR)\wiki.wiki" >> $@
12411251
12421252
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -505,11 +505,14 @@
505 "$(OX)\xfer_.c" \
506 "$(OX)\xfersetup_.c" \
507 "$(OX)\zip_.c" \
508 "$(SRCDIR_extsrc)\pikchr.c"
509
510 EXTRA_FILES = "$(SRCDIR)\..\skins\ardoise\css.txt" \
 
 
 
511 "$(SRCDIR)\..\skins\ardoise\details.txt" \
512 "$(SRCDIR)\..\skins\ardoise\footer.txt" \
513 "$(SRCDIR)\..\skins\ardoise\header.txt" \
514 "$(SRCDIR)\..\skins\black_and_white\css.txt" \
515 "$(SRCDIR)\..\skins\black_and_white\details.txt" \
@@ -573,10 +576,11 @@
573 "$(SRCDIR)\fossil.page.brlist.js" \
574 "$(SRCDIR)\fossil.page.chat.js" \
575 "$(SRCDIR)\fossil.page.fileedit.js" \
576 "$(SRCDIR)\fossil.page.forumpost.js" \
577 "$(SRCDIR)\fossil.page.pikchrshow.js" \
 
578 "$(SRCDIR)\fossil.page.whistory.js" \
579 "$(SRCDIR)\fossil.page.wikiedit.js" \
580 "$(SRCDIR)\fossil.pikchr.js" \
581 "$(SRCDIR)\fossil.popupwidget.js" \
582 "$(SRCDIR)\fossil.storage.js" \
@@ -608,10 +612,11 @@
608 "$(SRCDIR)\sounds\e.wav" \
609 "$(SRCDIR)\sounds\f.wav" \
610 "$(SRCDIR)\style.admin_log.css" \
611 "$(SRCDIR)\style.chat.css" \
612 "$(SRCDIR)\style.fileedit.css" \
 
613 "$(SRCDIR)\style.wikiedit.css" \
614 "$(SRCDIR)\tree.js" \
615 "$(SRCDIR)\useredit.js" \
616 "$(SRCDIR)\wiki.wiki"
617
@@ -1129,11 +1134,14 @@
1129 "$(OBJDIR)\json_timeline$O" : "$(SRCDIR)\json_detail.h"
1130 "$(OBJDIR)\json_user$O" : "$(SRCDIR)\json_detail.h"
1131 "$(OBJDIR)\json_wiki$O" : "$(SRCDIR)\json_detail.h"
1132
1133 "$(OX)\builtin_data.reslist": $(EXTRA_FILES) "$(B)\win\Makefile.msc"
1134 echo "$(SRCDIR)\../skins/ardoise/css.txt" > $@
 
 
 
1135 echo "$(SRCDIR)\../skins/ardoise/details.txt" >> $@
1136 echo "$(SRCDIR)\../skins/ardoise/footer.txt" >> $@
1137 echo "$(SRCDIR)\../skins/ardoise/header.txt" >> $@
1138 echo "$(SRCDIR)\../skins/black_and_white/css.txt" >> $@
1139 echo "$(SRCDIR)\../skins/black_and_white/details.txt" >> $@
@@ -1197,10 +1205,11 @@
1197 echo "$(SRCDIR)\fossil.page.brlist.js" >> $@
1198 echo "$(SRCDIR)\fossil.page.chat.js" >> $@
1199 echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
1200 echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
1201 echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@
 
1202 echo "$(SRCDIR)\fossil.page.whistory.js" >> $@
1203 echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
1204 echo "$(SRCDIR)\fossil.pikchr.js" >> $@
1205 echo "$(SRCDIR)\fossil.popupwidget.js" >> $@
1206 echo "$(SRCDIR)\fossil.storage.js" >> $@
@@ -1232,10 +1241,11 @@
1232 echo "$(SRCDIR)\sounds/e.wav" >> $@
1233 echo "$(SRCDIR)\sounds/f.wav" >> $@
1234 echo "$(SRCDIR)\style.admin_log.css" >> $@
1235 echo "$(SRCDIR)\style.chat.css" >> $@
1236 echo "$(SRCDIR)\style.fileedit.css" >> $@
 
1237 echo "$(SRCDIR)\style.wikiedit.css" >> $@
1238 echo "$(SRCDIR)\tree.js" >> $@
1239 echo "$(SRCDIR)\useredit.js" >> $@
1240 echo "$(SRCDIR)\wiki.wiki" >> $@
1241
1242
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -505,11 +505,14 @@
505 "$(OX)\xfer_.c" \
506 "$(OX)\xfersetup_.c" \
507 "$(OX)\zip_.c" \
508 "$(SRCDIR_extsrc)\pikchr.c"
509
510 EXTRA_FILES = "$(SRCDIR)\..\extsrc\pikchr-worker.js" \
511 "$(SRCDIR)\..\extsrc\pikchr.js" \
512 "$(SRCDIR)\..\extsrc\pikchr.wasm" \
513 "$(SRCDIR)\..\skins\ardoise\css.txt" \
514 "$(SRCDIR)\..\skins\ardoise\details.txt" \
515 "$(SRCDIR)\..\skins\ardoise\footer.txt" \
516 "$(SRCDIR)\..\skins\ardoise\header.txt" \
517 "$(SRCDIR)\..\skins\black_and_white\css.txt" \
518 "$(SRCDIR)\..\skins\black_and_white\details.txt" \
@@ -573,10 +576,11 @@
576 "$(SRCDIR)\fossil.page.brlist.js" \
577 "$(SRCDIR)\fossil.page.chat.js" \
578 "$(SRCDIR)\fossil.page.fileedit.js" \
579 "$(SRCDIR)\fossil.page.forumpost.js" \
580 "$(SRCDIR)\fossil.page.pikchrshow.js" \
581 "$(SRCDIR)\fossil.page.pikchrshowasm.js" \
582 "$(SRCDIR)\fossil.page.whistory.js" \
583 "$(SRCDIR)\fossil.page.wikiedit.js" \
584 "$(SRCDIR)\fossil.pikchr.js" \
585 "$(SRCDIR)\fossil.popupwidget.js" \
586 "$(SRCDIR)\fossil.storage.js" \
@@ -608,10 +612,11 @@
612 "$(SRCDIR)\sounds\e.wav" \
613 "$(SRCDIR)\sounds\f.wav" \
614 "$(SRCDIR)\style.admin_log.css" \
615 "$(SRCDIR)\style.chat.css" \
616 "$(SRCDIR)\style.fileedit.css" \
617 "$(SRCDIR)\style.pikchrshow.css" \
618 "$(SRCDIR)\style.wikiedit.css" \
619 "$(SRCDIR)\tree.js" \
620 "$(SRCDIR)\useredit.js" \
621 "$(SRCDIR)\wiki.wiki"
622
@@ -1129,11 +1134,14 @@
1134 "$(OBJDIR)\json_timeline$O" : "$(SRCDIR)\json_detail.h"
1135 "$(OBJDIR)\json_user$O" : "$(SRCDIR)\json_detail.h"
1136 "$(OBJDIR)\json_wiki$O" : "$(SRCDIR)\json_detail.h"
1137
1138 "$(OX)\builtin_data.reslist": $(EXTRA_FILES) "$(B)\win\Makefile.msc"
1139 echo "$(SRCDIR)\../extsrc/pikchr-worker.js" > $@
1140 echo "$(SRCDIR)\../extsrc/pikchr.js" >> $@
1141 echo "$(SRCDIR)\../extsrc/pikchr.wasm" >> $@
1142 echo "$(SRCDIR)\../skins/ardoise/css.txt" >> $@
1143 echo "$(SRCDIR)\../skins/ardoise/details.txt" >> $@
1144 echo "$(SRCDIR)\../skins/ardoise/footer.txt" >> $@
1145 echo "$(SRCDIR)\../skins/ardoise/header.txt" >> $@
1146 echo "$(SRCDIR)\../skins/black_and_white/css.txt" >> $@
1147 echo "$(SRCDIR)\../skins/black_and_white/details.txt" >> $@
@@ -1197,10 +1205,11 @@
1205 echo "$(SRCDIR)\fossil.page.brlist.js" >> $@
1206 echo "$(SRCDIR)\fossil.page.chat.js" >> $@
1207 echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
1208 echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
1209 echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@
1210 echo "$(SRCDIR)\fossil.page.pikchrshowasm.js" >> $@
1211 echo "$(SRCDIR)\fossil.page.whistory.js" >> $@
1212 echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
1213 echo "$(SRCDIR)\fossil.pikchr.js" >> $@
1214 echo "$(SRCDIR)\fossil.popupwidget.js" >> $@
1215 echo "$(SRCDIR)\fossil.storage.js" >> $@
@@ -1232,10 +1241,11 @@
1241 echo "$(SRCDIR)\sounds/e.wav" >> $@
1242 echo "$(SRCDIR)\sounds/f.wav" >> $@
1243 echo "$(SRCDIR)\style.admin_log.css" >> $@
1244 echo "$(SRCDIR)\style.chat.css" >> $@
1245 echo "$(SRCDIR)\style.fileedit.css" >> $@
1246 echo "$(SRCDIR)\style.pikchrshow.css" >> $@
1247 echo "$(SRCDIR)\style.wikiedit.css" >> $@
1248 echo "$(SRCDIR)\tree.js" >> $@
1249 echo "$(SRCDIR)\useredit.js" >> $@
1250 echo "$(SRCDIR)\wiki.wiki" >> $@
1251
1252
+123 -3
--- www/build.wiki
+++ www/build.wiki
@@ -332,11 +332,11 @@
332332
333333
<h2>6.0 Building on/for Android</h2>
334334
335335
<h3>6.1 Cross-compiling from Linux</h3>
336336
337
-The following instructions for building Fossil for Android,
337
+The following instructions for building Fossil for Android via Linux,
338338
without requiring a rooted OS, are adapted from
339339
[https://fossil-scm.org/forum/forumpost/e0e9de4a7e | forumpost/e0e9de4a7e].
340340
341341
On the development machine, from the fossil source tree:
342342
@@ -381,13 +381,12 @@
381381
Some information about these (reportedly harmless) warnings can
382382
be found
383383
[https://stackoverflow.com/a/41900551 | on this StackOverflow post].
384384
385385
386
-
387386
<a id='fuzzer'></a>
388
-<h2>Building for Fuzz Testing</h2>
387
+<h2>7.0 Building for Fuzz Testing</h2>
389388
390389
This feature is primarily intended for fossil's developers and may
391390
change at any time. It is only known to work on Linux systems and has
392391
been seen to work on x86/64 and ARM.
393392
@@ -460,5 +459,126 @@
460459
e.g. <tt>-jobs=4</tt> to start four fuzzer jobs in parallel, but doing
461460
so may cause the fuzzer to <em>strip the --fuzztype flag</em>, leading
462461
to it testing the wrong thing. When passing on fuzzer-specific flags
463462
along with <tt>--fuzztype</tt>, be sure to check your system's process
464463
list to ensure that your <tt>--fuzztype</tt> flag is there.
464
+
465
+
466
+<a id='wasm'></a>
467
+<h2>8.0 Building WebAssembly Components</h2>
468
+
469
+As of version 2.19, fossil uses one component built as
470
+[https://developer.mozilla.org/en-US/docs/WebAssembly | WebAssembly]
471
+a.k.a. WASM. Because compiling WASM code requires non-trivial
472
+client-side tooling, the repository includes compiled copies of these
473
+pieces. Most Fossil hackers should never need to concern themselves
474
+with the WASM parts, but this section describes how to for those who
475
+want or need to do so.
476
+
477
+<strong>The bits described in this section are necessary when updating
478
+<tt>extsrc/pikchr.c</tt></strong> from the upstream source, or the
479
+fossil binary will use a different version of pikchr than
480
+[/pikchrshow] does (as the latter runs the WASM build of pikchr).
481
+
482
+These instructions have only ever been tested on Linux systems. They
483
+"should" work on any Unix-like system supported by Emscripten. The
484
+fossil makefiles for Windows builds <em>do not</em> include any of the
485
+WASM-related components (patches to add that would be welcomed, of
486
+course).
487
+
488
+The first step is to configure the tree with support for
489
+[https://emscripten.org/|Emscripten]. This requires that the system
490
+has the Emscripten SDK (a.k.a. emsdk) installed, as documented at:
491
+
492
+[https://emscripten.org/docs/getting_started/downloads.html]
493
+
494
+For instructions on keeping the SDK up to date, see:
495
+
496
+[https://emscripten.org/docs/tools_reference/emsdk.html]
497
+
498
+ Sidebar: getting Emscripten up and running is trivial and
499
+ painless, at least on Linux systems, but the installer downloads
500
+ many hundreds of megabytes of tools and dependencies, all of which
501
+ will be installed under the single SDK directory (as opposed to
502
+ being installed at the system level). It does, however, require
503
+ that python3 be installed at the system level and it can
504
+ optionally make use of a system-level cmake for certain tasks
505
+ unrelated to how fossil uses the SDK.
506
+
507
+After installing the SDK, configure the fossil tree with emsdk
508
+support:
509
+
510
+<pre><code>$ ./configure --with-emsdk=/path/to/emsdk ...other options...
511
+</code></pre>
512
+
513
+If the <tt>--with-emsdk</tt> flag is not provided, the configure
514
+script will check for the environment variable <tt>EMSDK</tt>, which
515
+is one of the standard variables the SDK environment uses. If that
516
+variable is found, its value will implicitly be used in place of the
517
+missing <tt>--with-emsdk</tt> flag. Thus, if the <tt>emsdk_env.sh</tt>
518
+script is sourced into the shell before running the configure script,
519
+the SDK will be detected even without the config flag.
520
+
521
+The configure script installs some makefile variables which tell the
522
+build where to find the SDK and it generates a script named
523
+<tt>tools/emcc.sh</tt> (from the template file
524
+<tt>[/file/tools/emcc.sh.in|/tools/emcc.sh.in]</tt>), which is a
525
+wrapper around the Emscripten C compiler (<tt>emcc</tt>). The wrapper
526
+script uses the configure-time state to attempt to set up the various
527
+environment variables which are required by <tt>emcc</tt> and will
528
+fail if it cannot do so. Once it's set up the environment, it passes
529
+on all of its arguments to <tt>emcc</tt>.
530
+
531
+The WASM-related build parts are set up such that none of them should
532
+ever trigger implicity (e.g. via dependencies resolution) in a normal
533
+build cycle. They are instead explicitly built as described below.
534
+
535
+From the top of the source tree, all WASM-related components can be
536
+built with:
537
+
538
+<pre><code>$ make wasm</code></pre>
539
+
540
+As of this writing, those parts include:
541
+
542
+ * <tt>extsrc/pikchr.wasm</tt> is a WASM-compiled form of
543
+ <tt>extsrc/pikchr.c</tt>.
544
+ * <tt>extsrc/pikchr.js</tt> is JS/WASM glue code generated by Emscripten
545
+ to give JS code access to the API exported by the WASM file.
546
+
547
+ Sidebar: The file
548
+ <tt>[/file/extsrc/pikcher-worker.js|extsrc/pikcher-worker.js]</tt>
549
+ is hand-coded and intended to be loaded as a "Worker" in
550
+ JavaScript. That file loads the main module and provides an
551
+ interface via which a main JavaScript thread can communicate with
552
+ pikchr running in a Worker thread. The file
553
+ <tt>[/file/src/fossil.page.pikchrshowasm.js|src/fossil.page.pikchrshowasm.js]</tt>
554
+ implements the [/pikchrshow] app and demonstrates how
555
+ <tt>pikchr-worker.js</tt> is used.
556
+
557
+When a new version of <tt>extsrc/pikchr.c</tt> is installed, the
558
+files <tt>pikchr.{js,wasm}</tt> will need to be recompiled to account
559
+for that. Running <tt>make wasm</tt> will, if the build is set up for
560
+the emsdk, recompile those:
561
+
562
+<pre><code>$ make wasm
563
+./tools/emcc.sh -o extsrc/pikchr.js ...
564
+$ ls -la extsrc/pikchr.{js,wasm}
565
+-rw-rw-r-- 1 stephan stephan 17263 Jun 8 03:59 extsrc/pikchr.js
566
+-rw-rw-r-- 1 stephan stephan 97578 Jun 8 03:59 extsrc/pikchr.wasm
567
+</code></pre>
568
+
569
+Then run the normal build so that those files can be compiled in to
570
+the fossil binary, accessible via the [/help?cmd=/builtin|/builtin page]:
571
+
572
+<pre><code>$ make</code></pre>
573
+
574
+Before checking in those newly-built files, they need to be tested by
575
+running the [/pikchrshow] page. If that page loads, the compilation
576
+process fundamentally worked (a load failure will be made obvious to
577
+the viewer). If it fails to load then the browser's dev tools console
578
+likely provides at least a small hint (and <em>sometimes</em> a useful
579
+hint) about the nature of the problem. Don't check those files in
580
+until [/pikchrshow] runs, though!
581
+
582
+Should pikchr's C interface ever changes, <tt>pikchr-worker.js</tt>
583
+will need to be updated to accommodate it, but such modification is
584
+typically trivial.
465585
--- www/build.wiki
+++ www/build.wiki
@@ -332,11 +332,11 @@
332
333 <h2>6.0 Building on/for Android</h2>
334
335 <h3>6.1 Cross-compiling from Linux</h3>
336
337 The following instructions for building Fossil for Android,
338 without requiring a rooted OS, are adapted from
339 [https://fossil-scm.org/forum/forumpost/e0e9de4a7e | forumpost/e0e9de4a7e].
340
341 On the development machine, from the fossil source tree:
342
@@ -381,13 +381,12 @@
381 Some information about these (reportedly harmless) warnings can
382 be found
383 [https://stackoverflow.com/a/41900551 | on this StackOverflow post].
384
385
386
387 <a id='fuzzer'></a>
388 <h2>Building for Fuzz Testing</h2>
389
390 This feature is primarily intended for fossil's developers and may
391 change at any time. It is only known to work on Linux systems and has
392 been seen to work on x86/64 and ARM.
393
@@ -460,5 +459,126 @@
460 e.g. <tt>-jobs=4</tt> to start four fuzzer jobs in parallel, but doing
461 so may cause the fuzzer to <em>strip the --fuzztype flag</em>, leading
462 to it testing the wrong thing. When passing on fuzzer-specific flags
463 along with <tt>--fuzztype</tt>, be sure to check your system's process
464 list to ensure that your <tt>--fuzztype</tt> flag is there.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
--- www/build.wiki
+++ www/build.wiki
@@ -332,11 +332,11 @@
332
333 <h2>6.0 Building on/for Android</h2>
334
335 <h3>6.1 Cross-compiling from Linux</h3>
336
337 The following instructions for building Fossil for Android via Linux,
338 without requiring a rooted OS, are adapted from
339 [https://fossil-scm.org/forum/forumpost/e0e9de4a7e | forumpost/e0e9de4a7e].
340
341 On the development machine, from the fossil source tree:
342
@@ -381,13 +381,12 @@
381 Some information about these (reportedly harmless) warnings can
382 be found
383 [https://stackoverflow.com/a/41900551 | on this StackOverflow post].
384
385
 
386 <a id='fuzzer'></a>
387 <h2>7.0 Building for Fuzz Testing</h2>
388
389 This feature is primarily intended for fossil's developers and may
390 change at any time. It is only known to work on Linux systems and has
391 been seen to work on x86/64 and ARM.
392
@@ -460,5 +459,126 @@
459 e.g. <tt>-jobs=4</tt> to start four fuzzer jobs in parallel, but doing
460 so may cause the fuzzer to <em>strip the --fuzztype flag</em>, leading
461 to it testing the wrong thing. When passing on fuzzer-specific flags
462 along with <tt>--fuzztype</tt>, be sure to check your system's process
463 list to ensure that your <tt>--fuzztype</tt> flag is there.
464
465
466 <a id='wasm'></a>
467 <h2>8.0 Building WebAssembly Components</h2>
468
469 As of version 2.19, fossil uses one component built as
470 [https://developer.mozilla.org/en-US/docs/WebAssembly | WebAssembly]
471 a.k.a. WASM. Because compiling WASM code requires non-trivial
472 client-side tooling, the repository includes compiled copies of these
473 pieces. Most Fossil hackers should never need to concern themselves
474 with the WASM parts, but this section describes how to for those who
475 want or need to do so.
476
477 <strong>The bits described in this section are necessary when updating
478 <tt>extsrc/pikchr.c</tt></strong> from the upstream source, or the
479 fossil binary will use a different version of pikchr than
480 [/pikchrshow] does (as the latter runs the WASM build of pikchr).
481
482 These instructions have only ever been tested on Linux systems. They
483 "should" work on any Unix-like system supported by Emscripten. The
484 fossil makefiles for Windows builds <em>do not</em> include any of the
485 WASM-related components (patches to add that would be welcomed, of
486 course).
487
488 The first step is to configure the tree with support for
489 [https://emscripten.org/|Emscripten]. This requires that the system
490 has the Emscripten SDK (a.k.a. emsdk) installed, as documented at:
491
492 [https://emscripten.org/docs/getting_started/downloads.html]
493
494 For instructions on keeping the SDK up to date, see:
495
496 [https://emscripten.org/docs/tools_reference/emsdk.html]
497
498 Sidebar: getting Emscripten up and running is trivial and
499 painless, at least on Linux systems, but the installer downloads
500 many hundreds of megabytes of tools and dependencies, all of which
501 will be installed under the single SDK directory (as opposed to
502 being installed at the system level). It does, however, require
503 that python3 be installed at the system level and it can
504 optionally make use of a system-level cmake for certain tasks
505 unrelated to how fossil uses the SDK.
506
507 After installing the SDK, configure the fossil tree with emsdk
508 support:
509
510 <pre><code>$ ./configure --with-emsdk=/path/to/emsdk ...other options...
511 </code></pre>
512
513 If the <tt>--with-emsdk</tt> flag is not provided, the configure
514 script will check for the environment variable <tt>EMSDK</tt>, which
515 is one of the standard variables the SDK environment uses. If that
516 variable is found, its value will implicitly be used in place of the
517 missing <tt>--with-emsdk</tt> flag. Thus, if the <tt>emsdk_env.sh</tt>
518 script is sourced into the shell before running the configure script,
519 the SDK will be detected even without the config flag.
520
521 The configure script installs some makefile variables which tell the
522 build where to find the SDK and it generates a script named
523 <tt>tools/emcc.sh</tt> (from the template file
524 <tt>[/file/tools/emcc.sh.in|/tools/emcc.sh.in]</tt>), which is a
525 wrapper around the Emscripten C compiler (<tt>emcc</tt>). The wrapper
526 script uses the configure-time state to attempt to set up the various
527 environment variables which are required by <tt>emcc</tt> and will
528 fail if it cannot do so. Once it's set up the environment, it passes
529 on all of its arguments to <tt>emcc</tt>.
530
531 The WASM-related build parts are set up such that none of them should
532 ever trigger implicity (e.g. via dependencies resolution) in a normal
533 build cycle. They are instead explicitly built as described below.
534
535 From the top of the source tree, all WASM-related components can be
536 built with:
537
538 <pre><code>$ make wasm</code></pre>
539
540 As of this writing, those parts include:
541
542 * <tt>extsrc/pikchr.wasm</tt> is a WASM-compiled form of
543 <tt>extsrc/pikchr.c</tt>.
544 * <tt>extsrc/pikchr.js</tt> is JS/WASM glue code generated by Emscripten
545 to give JS code access to the API exported by the WASM file.
546
547 Sidebar: The file
548 <tt>[/file/extsrc/pikcher-worker.js|extsrc/pikcher-worker.js]</tt>
549 is hand-coded and intended to be loaded as a "Worker" in
550 JavaScript. That file loads the main module and provides an
551 interface via which a main JavaScript thread can communicate with
552 pikchr running in a Worker thread. The file
553 <tt>[/file/src/fossil.page.pikchrshowasm.js|src/fossil.page.pikchrshowasm.js]</tt>
554 implements the [/pikchrshow] app and demonstrates how
555 <tt>pikchr-worker.js</tt> is used.
556
557 When a new version of <tt>extsrc/pikchr.c</tt> is installed, the
558 files <tt>pikchr.{js,wasm}</tt> will need to be recompiled to account
559 for that. Running <tt>make wasm</tt> will, if the build is set up for
560 the emsdk, recompile those:
561
562 <pre><code>$ make wasm
563 ./tools/emcc.sh -o extsrc/pikchr.js ...
564 $ ls -la extsrc/pikchr.{js,wasm}
565 -rw-rw-r-- 1 stephan stephan 17263 Jun 8 03:59 extsrc/pikchr.js
566 -rw-rw-r-- 1 stephan stephan 97578 Jun 8 03:59 extsrc/pikchr.wasm
567 </code></pre>
568
569 Then run the normal build so that those files can be compiled in to
570 the fossil binary, accessible via the [/help?cmd=/builtin|/builtin page]:
571
572 <pre><code>$ make</code></pre>
573
574 Before checking in those newly-built files, they need to be tested by
575 running the [/pikchrshow] page. If that page loads, the compilation
576 process fundamentally worked (a load failure will be made obvious to
577 the viewer). If it fails to load then the browser's dev tools console
578 likely provides at least a small hint (and <em>sometimes</em> a useful
579 hint) about the nature of the problem. Don't check those files in
580 until [/pikchrshow] runs, though!
581
582 Should pikchr's C interface ever changes, <tt>pikchr-worker.js</tt>
583 will need to be updated to accommodate it, but such modification is
584 typically trivial.
585
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
2525
* Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
2626
columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
2727
* Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
2828
bug where remote-url is overwritten by the proxy setting during sync
2929
operation. Also require explicit "system" proxy setting to use
30
- "http_proxy" environment variable.
30
+ "http_proxy" environment variable.
31
+ * Reimplemented the [/pikchrshow] app to use a WebAssembly build of
32
+ pikchr so that it can render pikchrs on the client instead of requiring
33
+ a server round-trip.
3134
* Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
3235
used as the List-ID header for all outbound notification emails.
3336
3437
<h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
3538
* Added support for [./ssl-server.md|SSL/TLS server mode] for commands
3639
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
25 * Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
26 columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
27 * Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
28 bug where remote-url is overwritten by the proxy setting during sync
29 operation. Also require explicit "system" proxy setting to use
30 "http_proxy" environment variable.
 
 
 
31 * Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
32 used as the List-ID header for all outbound notification emails.
33
34 <h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
35 * Added support for [./ssl-server.md|SSL/TLS server mode] for commands
36
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
25 * Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
26 columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
27 * Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
28 bug where remote-url is overwritten by the proxy setting during sync
29 operation. Also require explicit "system" proxy setting to use
30 "http_proxy" environment variable.
31 * Reimplemented the [/pikchrshow] app to use a WebAssembly build of
32 pikchr so that it can render pikchrs on the client instead of requiring
33 a server round-trip.
34 * Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
35 used as the List-ID header for all outbound notification emails.
36
37 <h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
38 * Added support for [./ssl-server.md|SSL/TLS server mode] for commands
39
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
2525
* Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
2626
columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
2727
* Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
2828
bug where remote-url is overwritten by the proxy setting during sync
2929
operation. Also require explicit "system" proxy setting to use
30
- "http_proxy" environment variable.
30
+ "http_proxy" environment variable.
31
+ * Reimplemented the [/pikchrshow] app to use a WebAssembly build of
32
+ pikchr so that it can render pikchrs on the client instead of requiring
33
+ a server round-trip.
3134
* Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
3235
used as the List-ID header for all outbound notification emails.
3336
3437
<h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
3538
* Added support for [./ssl-server.md|SSL/TLS server mode] for commands
3639
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
25 * Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
26 columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
27 * Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
28 bug where remote-url is overwritten by the proxy setting during sync
29 operation. Also require explicit "system" proxy setting to use
30 "http_proxy" environment variable.
 
 
 
31 * Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
32 used as the List-ID header for all outbound notification emails.
33
34 <h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
35 * Added support for [./ssl-server.md|SSL/TLS server mode] for commands
36
--- www/changes.wiki
+++ www/changes.wiki
@@ -25,11 +25,14 @@
25 * Support [/wiki?name=branch/generated-tkt-mimetype&p|generated "mimetype"]
26 columns in the <var>TICKET</var> and <var>TICKETCHNG</var> tables.
27 * Fix [/timeline?r=fix_remote_url_overwrite_with_proxy|remote-url-overwrite]
28 bug where remote-url is overwritten by the proxy setting during sync
29 operation. Also require explicit "system" proxy setting to use
30 "http_proxy" environment variable.
31 * Reimplemented the [/pikchrshow] app to use a WebAssembly build of
32 pikchr so that it can render pikchrs on the client instead of requiring
33 a server round-trip.
34 * Add the [/help?cmd=email-listid|email-listid setting]. If set, it is
35 used as the List-ID header for all outbound notification emails.
36
37 <h2 id='v2_18'>Changes for version 2.18 (2022-02-23)</h2>
38 * Added support for [./ssl-server.md|SSL/TLS server mode] for commands
39

Keyboard Shortcuts

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