Fossil SCM

Reworked how style.css is emitted: all default rules first, then page-specific rules (if passed name=PAGENAME and if builtin file style.PAGENAME.css exists), then the skin. This increases the default style.css output by only approx. 800 bytes before compression (approx. 300 after compression). Has no visual impact on existing built-in skins, and none is expected on 3rd-party skin edits. See /forumpost/c659c44685 for discussion.

stephan 2020-05-28 09:18 trunk merge
Commit 064c1c95889feef29f83dba07735ed8a3ec8938658ac3d3e76656d6d36729eba
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -4,11 +4,11 @@
44
<base href="$baseurl/$current_page" />
55
<title>$<project_name>: $<title></title>
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<meta http-equiv="Content-Security-Policy" content="$default_csp"/>
88
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="$home/timeline.rss" />
9
- <link rel="stylesheet" href="$home/style.css?default" type="text/css" media="screen" />
9
+ <link rel="stylesheet" href="$stylesheet_url" type="text/css" media="screen" />
1010
<script nonce="$<nonce>">
1111
function gebi(x){
1212
if(/^#/.test(x)) x = x.substr(1);
1313
var e = document.getElementById(x);
1414
if(!e) throw new Error("Expecting element with ID "+x);
1515
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -4,11 +4,11 @@
4 <base href="$baseurl/$current_page" />
5 <title>$<project_name>: $<title></title>
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta http-equiv="Content-Security-Policy" content="$default_csp"/>
8 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="$home/timeline.rss" />
9 <link rel="stylesheet" href="$home/style.css?default" type="text/css" media="screen" />
10 <script nonce="$<nonce>">
11 function gebi(x){
12 if(/^#/.test(x)) x = x.substr(1);
13 var e = document.getElementById(x);
14 if(!e) throw new Error("Expecting element with ID "+x);
15
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -4,11 +4,11 @@
4 <base href="$baseurl/$current_page" />
5 <title>$<project_name>: $<title></title>
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta http-equiv="Content-Security-Policy" content="$default_csp"/>
8 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="$home/timeline.rss" />
9 <link rel="stylesheet" href="$stylesheet_url" type="text/css" media="screen" />
10 <script nonce="$<nonce>">
11 function gebi(x){
12 if(/^#/.test(x)) x = x.substr(1);
13 var e = document.getElementById(x);
14 if(!e) throw new Error("Expecting element with ID "+x);
15
--- src/main.mk
+++ src/main.mk
@@ -243,10 +243,11 @@
243243
$(SRCDIR)/sounds/b.wav \
244244
$(SRCDIR)/sounds/c.wav \
245245
$(SRCDIR)/sounds/d.wav \
246246
$(SRCDIR)/sounds/e.wav \
247247
$(SRCDIR)/sounds/f.wav \
248
+ $(SRCDIR)/style.admin_log.css \
248249
$(SRCDIR)/tree.js \
249250
$(SRCDIR)/useredit.js \
250251
$(SRCDIR)/wiki.wiki
251252
252253
TRANS_SRC = \
253254
--- src/main.mk
+++ src/main.mk
@@ -243,10 +243,11 @@
243 $(SRCDIR)/sounds/b.wav \
244 $(SRCDIR)/sounds/c.wav \
245 $(SRCDIR)/sounds/d.wav \
246 $(SRCDIR)/sounds/e.wav \
247 $(SRCDIR)/sounds/f.wav \
 
248 $(SRCDIR)/tree.js \
249 $(SRCDIR)/useredit.js \
250 $(SRCDIR)/wiki.wiki
251
252 TRANS_SRC = \
253
--- src/main.mk
+++ src/main.mk
@@ -243,10 +243,11 @@
243 $(SRCDIR)/sounds/b.wav \
244 $(SRCDIR)/sounds/c.wav \
245 $(SRCDIR)/sounds/d.wav \
246 $(SRCDIR)/sounds/e.wav \
247 $(SRCDIR)/sounds/f.wav \
248 $(SRCDIR)/style.admin_log.css \
249 $(SRCDIR)/tree.js \
250 $(SRCDIR)/useredit.js \
251 $(SRCDIR)/wiki.wiki
252
253 TRANS_SRC = \
254
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -175,10 +175,11 @@
175175
set extra_files {
176176
diff.tcl
177177
markdown.md
178178
wiki.wiki
179179
*.js
180
+ style.*.css
180181
../skins/*/*.txt
181182
sounds/*.wav
182183
}
183184
184185
# Options used to compile the included SQLite library.
185186
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -175,10 +175,11 @@
175 set extra_files {
176 diff.tcl
177 markdown.md
178 wiki.wiki
179 *.js
 
180 ../skins/*/*.txt
181 sounds/*.wav
182 }
183
184 # Options used to compile the included SQLite library.
185
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -175,10 +175,11 @@
175 set extra_files {
176 diff.tcl
177 markdown.md
178 wiki.wiki
179 *.js
180 style.*.css
181 ../skins/*/*.txt
182 sounds/*.wav
183 }
184
185 # Options used to compile the included SQLite library.
186
+1 -3
--- src/skins.c
+++ src/skins.c
@@ -708,13 +708,11 @@
708708
** for use only from the /setup_skinedit page.
709709
*/
710710
static void skin_emit_css_defaults(){
711711
struct strctCssDefaults const * pCss;
712712
fossil_print("<h1>CSS Defaults</h1>");
713
- fossil_print("If a skin defines any of the following CSS selectors, "
714
- "that definition replaces the default, as opposed to "
715
- "cascading from it. ");
713
+ fossil_print("Fossil's list of its own CSS classes follows. ");
716714
fossil_print("See <a href=\"https://fossil-scm.org/fossil/"
717715
"doc/trunk/www/css-tricks.md\">this "
718716
"document</a> for more details.");
719717
/* To discuss: do we want to list only the default selectors or
720718
** also their default values? The latter increases the size of the
721719
722720
ADDED src/style.admin_log.css
--- src/skins.c
+++ src/skins.c
@@ -708,13 +708,11 @@
708 ** for use only from the /setup_skinedit page.
709 */
710 static void skin_emit_css_defaults(){
711 struct strctCssDefaults const * pCss;
712 fossil_print("<h1>CSS Defaults</h1>");
713 fossil_print("If a skin defines any of the following CSS selectors, "
714 "that definition replaces the default, as opposed to "
715 "cascading from it. ");
716 fossil_print("See <a href=\"https://fossil-scm.org/fossil/"
717 "doc/trunk/www/css-tricks.md\">this "
718 "document</a> for more details.");
719 /* To discuss: do we want to list only the default selectors or
720 ** also their default values? The latter increases the size of the
721
722 DDED src/style.admin_log.css
--- src/skins.c
+++ src/skins.c
@@ -708,13 +708,11 @@
708 ** for use only from the /setup_skinedit page.
709 */
710 static void skin_emit_css_defaults(){
711 struct strctCssDefaults const * pCss;
712 fossil_print("<h1>CSS Defaults</h1>");
713 fossil_print("Fossil's list of its own CSS classes follows. ");
 
 
714 fossil_print("See <a href=\"https://fossil-scm.org/fossil/"
715 "doc/trunk/www/css-tricks.md\">this "
716 "document</a> for more details.");
717 /* To discuss: do we want to list only the default selectors or
718 ** also their default values? The latter increases the size of the
719
720 DDED src/style.admin_log.css
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -0,0 +1,6 @@
1
+/* This file is just to demonstrate/test page-specific CSS. Using
2
+ the browser dev tools, select any link, "inspect" it, and edit
3
+ this style. */
4
+a{
5
+ font-size: inherit;
6
+}
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -0,0 +1,6 @@
 
 
 
 
 
 
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -0,0 +1,6 @@
1 /* This file is just to demonstrate/test page-specific CSS. Using
2 the browser dev tools, select any link, "inspect" it, and edit
3 this style. */
4 a{
5 font-size: inherit;
6 }
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -1,7 +1,6 @@
1
-/* This file is just to demonstra*/
2
-a:hover::before {
3
- content: "[";
1
+/* This file is just to demonstrate/test page-specific CSS. Using
2
+ the browser dev tools, select any link, "inspect" it, and edit
3
+ this style. */
4
+a{
5
+ font-size: inherit;
46
}
5
-a:hover::after {
6
- content: "]";
7
-}
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -1,7 +1,6 @@
1 /* This file is just to demonstra*/
2 a:hover::before {
3 content: "[";
 
 
4 }
5 a:hover::after {
6 content: "]";
7 }
--- a/src/style.admin_log.css
+++ b/src/style.admin_log.css
@@ -1,7 +1,6 @@
1 /* This file is just to demonstrate/test page-specific CSS. Using
2 the browser dev tools, select any link, "inspect" it, and edit
3 this style. */
4 a{
5 font-size: inherit;
6 }
 
 
 
+67 -32
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340340
const struct Submenu *A = (const struct Submenu*)a;
341341
const struct Submenu *B = (const struct Submenu*)b;
342342
return fossil_strcmp(A->zLabel, B->zLabel);
343343
}
344344
345
-/* Use this for the $current_page variable if it is not NULL. If it is
346
-** NULL then use g.zPath.
345
+/* Use this for the $current_page variable if it is not NULL. If it
346
+** is NULL then use g.zPath.
347347
*/
348348
static char *local_zCurrentPage = 0;
349349
350350
/*
351351
** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361361
va_end(ap);
362362
}
363363
}
364364
365365
/*
366
-** Create a TH1 variable containing the URL for the specified config resource.
367
-** The resulting variable name will be of the form $[zVarPrefix]_url.
366
+** Create a TH1 variable containing the URL for the specified config
367
+** resource. The resulting variable name will be of the form
368
+** $[zVarPrefix]_url.
368369
*/
369370
static void url_var(
370371
const char *zVarPrefix,
371372
const char *zConfigName,
372373
const char *zPageName
373374
){
374375
char *zVarName = mprintf("%s_url", zVarPrefix);
375
- char *zUrl = mprintf("%R/%s?id=%x", zPageName,
376
- skin_id(zConfigName));
376
+ char *zUrl = 0; /* stylesheet URL */
377
+ int hasBuiltin = 0; /* true for built-in page-specific CSS */
378
+
379
+ if(0==strcmp("css",zConfigName)){
380
+ /* Account for page-specific CSS, appending a /{{g.zPath}} to the
381
+ ** url only if we have a corresponding built-in page-specific CSS
382
+ ** file. Do not append it to all pages because we would
383
+ ** effectively cache-bust all pages which do not have
384
+ ** page-specific CSS. */
385
+ char * zBuiltin = mprintf("style.%s.css", g.zPath);
386
+ hasBuiltin = builtin_file(zBuiltin,0)!=0;
387
+ fossil_free(zBuiltin);
388
+ }
389
+ zUrl = mprintf("%R/%s%s%s?id=%x", zPageName,
390
+ hasBuiltin ? "/" : "", hasBuiltin ? g.zPath : "",
391
+ skin_id(zConfigName));
377392
Th_Store(zVarName, zUrl);
378
- free(zUrl);
379
- free(zVarName);
393
+ fossil_free(zUrl);
394
+ fossil_free(zVarName);
380395
}
381396
382397
/*
383398
** Create a TH1 variable containing the URL for the specified config image.
384399
** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
10241039
** COMMAND: test-contains-selector
10251040
**
10261041
** Usage: %fossil test-contains-selector FILENAME SELECTOR
10271042
**
10281043
** Determine if the CSS stylesheet FILENAME contains SELECTOR.
1044
+**
1045
+** Note that as of 2020-05-28, the default rules are always emitted,
1046
+** so the containsSelector() logic is no longer applied when emitting
1047
+** style.css. It is unclear whether this test command is now obsolete
1048
+** or whether it may still serve a purpose.
10291049
*/
10301050
void contains_selector_cmd(void){
10311051
int found;
10321052
char *zSelector;
10331053
Blob css;
@@ -1056,44 +1076,59 @@
10561076
}
10571077
style_init_th1_vars(0);
10581078
Th_Render(zScript?zScript:"");
10591079
}
10601080
1061
-
10621081
/*
10631082
** WEBPAGE: style.css
10641083
**
10651084
** Return the style sheet.
10661085
*/
10671086
void page_style_css(void){
1068
- Blob css;
1087
+ Blob css = empty_blob;
10691088
int i;
1070
- int isInit = 0;
1089
+ const char *zPage = PD("name",P("page"));
10711090
10721091
cgi_set_content_type("text/css");
1073
- blob_init(&css,skin_get("css"),-1);
1074
-
1075
- /* add special missing definitions */
1092
+ /* Emit all default rules... */
10761093
for(i=1; cssDefaultList[i].elementClass; i++){
1077
- char *z = blob_str(&css);
1078
- if( !containsSelector(z, cssDefaultList[i].elementClass) ){
1079
- if( !isInit ){
1080
- isInit = 1;
1081
- blob_append(&css,
1082
- "\n/***********************************************************\n"
1083
- "** All CSS above is supplied by the repository \"skin\".\n"
1084
- "** That which follows is generated automatically by Fossil\n"
1085
- "** to fill in needed selectors that are missing from the\n"
1086
- "** \"skin\" CSS.\n"
1087
- "***********************************************************/\n",
1088
- -1);
1089
- }
1090
- blob_appendf(&css, "%s {\n%s}\n",
1091
- cssDefaultList[i].elementClass,
1092
- cssDefaultList[i].value);
1093
- }
1094
- }
1094
+ blob_appendf(&css, "%s {\n%s}\n",
1095
+ cssDefaultList[i].elementClass,
1096
+ cssDefaultList[i].value);
1097
+ }
1098
+ blob_append(&css,
1099
+ "\n/***********************************************************\n"
1100
+ "** All CSS above is generated automatically by Fossil to\n"
1101
+ "** provide default rule implementations which the \"skin\"\n"
1102
+ "** may cascade.\n"
1103
+ "***********************************************************/\n",
1104
+ -1);
1105
+ if(zPage!=0 && zPage[0]!=0){
1106
+ char * zFile = mprintf("style.%s.css", zPage);
1107
+ int nFile = 0;
1108
+ const char *zBuiltin = (const char *)builtin_file(zFile, &nFile);
1109
+ if(nFile>0){
1110
+ blob_appendf(&css,
1111
+ "\n/***********************************************************\n"
1112
+ "** Start of page-specific CSS for page %s...\n"
1113
+ "***********************************************************/\n",
1114
+ zPage);
1115
+ blob_append(&css, zBuiltin, nFile);
1116
+ blob_appendf(&css,
1117
+ "\n/***********************************************************\n"
1118
+ "** End of page-specific CSS for page %s.\n"
1119
+ "***********************************************************/\n",
1120
+ zPage);
1121
+ }
1122
+ fossil_free(zFile);
1123
+ }
1124
+ blob_append(&css,
1125
+ "\n/***********************************************************\n"
1126
+ "** All CSS which follows is supplied by the repository \"skin\".\n"
1127
+ "***********************************************************/\n",
1128
+ -1);
1129
+ blob_append(&css,skin_get("css"),-1);
10951130
10961131
/* Process through TH1 in order to give an opportunity to substitute
10971132
** variables such as $baseurl.
10981133
*/
10991134
Th_Store("baseurl", g.zBaseURL);
11001135
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340 const struct Submenu *A = (const struct Submenu*)a;
341 const struct Submenu *B = (const struct Submenu*)b;
342 return fossil_strcmp(A->zLabel, B->zLabel);
343 }
344
345 /* Use this for the $current_page variable if it is not NULL. If it is
346 ** NULL then use g.zPath.
347 */
348 static char *local_zCurrentPage = 0;
349
350 /*
351 ** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361 va_end(ap);
362 }
363 }
364
365 /*
366 ** Create a TH1 variable containing the URL for the specified config resource.
367 ** The resulting variable name will be of the form $[zVarPrefix]_url.
 
368 */
369 static void url_var(
370 const char *zVarPrefix,
371 const char *zConfigName,
372 const char *zPageName
373 ){
374 char *zVarName = mprintf("%s_url", zVarPrefix);
375 char *zUrl = mprintf("%R/%s?id=%x", zPageName,
376 skin_id(zConfigName));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377 Th_Store(zVarName, zUrl);
378 free(zUrl);
379 free(zVarName);
380 }
381
382 /*
383 ** Create a TH1 variable containing the URL for the specified config image.
384 ** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
1024 ** COMMAND: test-contains-selector
1025 **
1026 ** Usage: %fossil test-contains-selector FILENAME SELECTOR
1027 **
1028 ** Determine if the CSS stylesheet FILENAME contains SELECTOR.
 
 
 
 
 
1029 */
1030 void contains_selector_cmd(void){
1031 int found;
1032 char *zSelector;
1033 Blob css;
@@ -1056,44 +1076,59 @@
1056 }
1057 style_init_th1_vars(0);
1058 Th_Render(zScript?zScript:"");
1059 }
1060
1061
1062 /*
1063 ** WEBPAGE: style.css
1064 **
1065 ** Return the style sheet.
1066 */
1067 void page_style_css(void){
1068 Blob css;
1069 int i;
1070 int isInit = 0;
1071
1072 cgi_set_content_type("text/css");
1073 blob_init(&css,skin_get("css"),-1);
1074
1075 /* add special missing definitions */
1076 for(i=1; cssDefaultList[i].elementClass; i++){
1077 char *z = blob_str(&css);
1078 if( !containsSelector(z, cssDefaultList[i].elementClass) ){
1079 if( !isInit ){
1080 isInit = 1;
1081 blob_append(&css,
1082 "\n/***********************************************************\n"
1083 "** All CSS above is supplied by the repository \"skin\".\n"
1084 "** That which follows is generated automatically by Fossil\n"
1085 "** to fill in needed selectors that are missing from the\n"
1086 "** \"skin\" CSS.\n"
1087 "***********************************************************/\n",
1088 -1);
1089 }
1090 blob_appendf(&css, "%s {\n%s}\n",
1091 cssDefaultList[i].elementClass,
1092 cssDefaultList[i].value);
1093 }
1094 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1095
1096 /* Process through TH1 in order to give an opportunity to substitute
1097 ** variables such as $baseurl.
1098 */
1099 Th_Store("baseurl", g.zBaseURL);
1100
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340 const struct Submenu *A = (const struct Submenu*)a;
341 const struct Submenu *B = (const struct Submenu*)b;
342 return fossil_strcmp(A->zLabel, B->zLabel);
343 }
344
345 /* Use this for the $current_page variable if it is not NULL. If it
346 ** is NULL then use g.zPath.
347 */
348 static char *local_zCurrentPage = 0;
349
350 /*
351 ** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361 va_end(ap);
362 }
363 }
364
365 /*
366 ** Create a TH1 variable containing the URL for the specified config
367 ** resource. The resulting variable name will be of the form
368 ** $[zVarPrefix]_url.
369 */
370 static void url_var(
371 const char *zVarPrefix,
372 const char *zConfigName,
373 const char *zPageName
374 ){
375 char *zVarName = mprintf("%s_url", zVarPrefix);
376 char *zUrl = 0; /* stylesheet URL */
377 int hasBuiltin = 0; /* true for built-in page-specific CSS */
378
379 if(0==strcmp("css",zConfigName)){
380 /* Account for page-specific CSS, appending a /{{g.zPath}} to the
381 ** url only if we have a corresponding built-in page-specific CSS
382 ** file. Do not append it to all pages because we would
383 ** effectively cache-bust all pages which do not have
384 ** page-specific CSS. */
385 char * zBuiltin = mprintf("style.%s.css", g.zPath);
386 hasBuiltin = builtin_file(zBuiltin,0)!=0;
387 fossil_free(zBuiltin);
388 }
389 zUrl = mprintf("%R/%s%s%s?id=%x", zPageName,
390 hasBuiltin ? "/" : "", hasBuiltin ? g.zPath : "",
391 skin_id(zConfigName));
392 Th_Store(zVarName, zUrl);
393 fossil_free(zUrl);
394 fossil_free(zVarName);
395 }
396
397 /*
398 ** Create a TH1 variable containing the URL for the specified config image.
399 ** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
1039 ** COMMAND: test-contains-selector
1040 **
1041 ** Usage: %fossil test-contains-selector FILENAME SELECTOR
1042 **
1043 ** Determine if the CSS stylesheet FILENAME contains SELECTOR.
1044 **
1045 ** Note that as of 2020-05-28, the default rules are always emitted,
1046 ** so the containsSelector() logic is no longer applied when emitting
1047 ** style.css. It is unclear whether this test command is now obsolete
1048 ** or whether it may still serve a purpose.
1049 */
1050 void contains_selector_cmd(void){
1051 int found;
1052 char *zSelector;
1053 Blob css;
@@ -1056,44 +1076,59 @@
1076 }
1077 style_init_th1_vars(0);
1078 Th_Render(zScript?zScript:"");
1079 }
1080
 
1081 /*
1082 ** WEBPAGE: style.css
1083 **
1084 ** Return the style sheet.
1085 */
1086 void page_style_css(void){
1087 Blob css = empty_blob;
1088 int i;
1089 const char *zPage = PD("name",P("page"));
1090
1091 cgi_set_content_type("text/css");
1092 /* Emit all default rules... */
 
 
1093 for(i=1; cssDefaultList[i].elementClass; i++){
1094 blob_appendf(&css, "%s {\n%s}\n",
1095 cssDefaultList[i].elementClass,
1096 cssDefaultList[i].value);
1097 }
1098 blob_append(&css,
1099 "\n/***********************************************************\n"
1100 "** All CSS above is generated automatically by Fossil to\n"
1101 "** provide default rule implementations which the \"skin\"\n"
1102 "** may cascade.\n"
1103 "***********************************************************/\n",
1104 -1);
1105 if(zPage!=0 && zPage[0]!=0){
1106 char * zFile = mprintf("style.%s.css", zPage);
1107 int nFile = 0;
1108 const char *zBuiltin = (const char *)builtin_file(zFile, &nFile);
1109 if(nFile>0){
1110 blob_appendf(&css,
1111 "\n/***********************************************************\n"
1112 "** Start of page-specific CSS for page %s...\n"
1113 "***********************************************************/\n",
1114 zPage);
1115 blob_append(&css, zBuiltin, nFile);
1116 blob_appendf(&css,
1117 "\n/***********************************************************\n"
1118 "** End of page-specific CSS for page %s.\n"
1119 "***********************************************************/\n",
1120 zPage);
1121 }
1122 fossil_free(zFile);
1123 }
1124 blob_append(&css,
1125 "\n/***********************************************************\n"
1126 "** All CSS which follows is supplied by the repository \"skin\".\n"
1127 "***********************************************************/\n",
1128 -1);
1129 blob_append(&css,skin_get("css"),-1);
1130
1131 /* Process through TH1 in order to give an opportunity to substitute
1132 ** variables such as $baseurl.
1133 */
1134 Th_Store("baseurl", g.zBaseURL);
1135
+67 -32
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340340
const struct Submenu *A = (const struct Submenu*)a;
341341
const struct Submenu *B = (const struct Submenu*)b;
342342
return fossil_strcmp(A->zLabel, B->zLabel);
343343
}
344344
345
-/* Use this for the $current_page variable if it is not NULL. If it is
346
-** NULL then use g.zPath.
345
+/* Use this for the $current_page variable if it is not NULL. If it
346
+** is NULL then use g.zPath.
347347
*/
348348
static char *local_zCurrentPage = 0;
349349
350350
/*
351351
** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361361
va_end(ap);
362362
}
363363
}
364364
365365
/*
366
-** Create a TH1 variable containing the URL for the specified config resource.
367
-** The resulting variable name will be of the form $[zVarPrefix]_url.
366
+** Create a TH1 variable containing the URL for the specified config
367
+** resource. The resulting variable name will be of the form
368
+** $[zVarPrefix]_url.
368369
*/
369370
static void url_var(
370371
const char *zVarPrefix,
371372
const char *zConfigName,
372373
const char *zPageName
373374
){
374375
char *zVarName = mprintf("%s_url", zVarPrefix);
375
- char *zUrl = mprintf("%R/%s?id=%x", zPageName,
376
- skin_id(zConfigName));
376
+ char *zUrl = 0; /* stylesheet URL */
377
+ int hasBuiltin = 0; /* true for built-in page-specific CSS */
378
+
379
+ if(0==strcmp("css",zConfigName)){
380
+ /* Account for page-specific CSS, appending a /{{g.zPath}} to the
381
+ ** url only if we have a corresponding built-in page-specific CSS
382
+ ** file. Do not append it to all pages because we would
383
+ ** effectively cache-bust all pages which do not have
384
+ ** page-specific CSS. */
385
+ char * zBuiltin = mprintf("style.%s.css", g.zPath);
386
+ hasBuiltin = builtin_file(zBuiltin,0)!=0;
387
+ fossil_free(zBuiltin);
388
+ }
389
+ zUrl = mprintf("%R/%s%s%s?id=%x", zPageName,
390
+ hasBuiltin ? "/" : "", hasBuiltin ? g.zPath : "",
391
+ skin_id(zConfigName));
377392
Th_Store(zVarName, zUrl);
378
- free(zUrl);
379
- free(zVarName);
393
+ fossil_free(zUrl);
394
+ fossil_free(zVarName);
380395
}
381396
382397
/*
383398
** Create a TH1 variable containing the URL for the specified config image.
384399
** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
10241039
** COMMAND: test-contains-selector
10251040
**
10261041
** Usage: %fossil test-contains-selector FILENAME SELECTOR
10271042
**
10281043
** Determine if the CSS stylesheet FILENAME contains SELECTOR.
1044
+**
1045
+** Note that as of 2020-05-28, the default rules are always emitted,
1046
+** so the containsSelector() logic is no longer applied when emitting
1047
+** style.css. It is unclear whether this test command is now obsolete
1048
+** or whether it may still serve a purpose.
10291049
*/
10301050
void contains_selector_cmd(void){
10311051
int found;
10321052
char *zSelector;
10331053
Blob css;
@@ -1056,44 +1076,59 @@
10561076
}
10571077
style_init_th1_vars(0);
10581078
Th_Render(zScript?zScript:"");
10591079
}
10601080
1061
-
10621081
/*
10631082
** WEBPAGE: style.css
10641083
**
10651084
** Return the style sheet.
10661085
*/
10671086
void page_style_css(void){
1068
- Blob css;
1087
+ Blob css = empty_blob;
10691088
int i;
1070
- int isInit = 0;
1089
+ const char *zPage = PD("name",P("page"));
10711090
10721091
cgi_set_content_type("text/css");
1073
- blob_init(&css,skin_get("css"),-1);
1074
-
1075
- /* add special missing definitions */
1092
+ /* Emit all default rules... */
10761093
for(i=1; cssDefaultList[i].elementClass; i++){
1077
- char *z = blob_str(&css);
1078
- if( !containsSelector(z, cssDefaultList[i].elementClass) ){
1079
- if( !isInit ){
1080
- isInit = 1;
1081
- blob_append(&css,
1082
- "\n/***********************************************************\n"
1083
- "** All CSS above is supplied by the repository \"skin\".\n"
1084
- "** That which follows is generated automatically by Fossil\n"
1085
- "** to fill in needed selectors that are missing from the\n"
1086
- "** \"skin\" CSS.\n"
1087
- "***********************************************************/\n",
1088
- -1);
1089
- }
1090
- blob_appendf(&css, "%s {\n%s}\n",
1091
- cssDefaultList[i].elementClass,
1092
- cssDefaultList[i].value);
1093
- }
1094
- }
1094
+ blob_appendf(&css, "%s {\n%s}\n",
1095
+ cssDefaultList[i].elementClass,
1096
+ cssDefaultList[i].value);
1097
+ }
1098
+ blob_append(&css,
1099
+ "\n/***********************************************************\n"
1100
+ "** All CSS above is generated automatically by Fossil to\n"
1101
+ "** provide default rule implementations which the \"skin\"\n"
1102
+ "** may cascade.\n"
1103
+ "***********************************************************/\n",
1104
+ -1);
1105
+ if(zPage!=0 && zPage[0]!=0){
1106
+ char * zFile = mprintf("style.%s.css", zPage);
1107
+ int nFile = 0;
1108
+ const char *zBuiltin = (const char *)builtin_file(zFile, &nFile);
1109
+ if(nFile>0){
1110
+ blob_appendf(&css,
1111
+ "\n/***********************************************************\n"
1112
+ "** Start of page-specific CSS for page %s...\n"
1113
+ "***********************************************************/\n",
1114
+ zPage);
1115
+ blob_append(&css, zBuiltin, nFile);
1116
+ blob_appendf(&css,
1117
+ "\n/***********************************************************\n"
1118
+ "** End of page-specific CSS for page %s.\n"
1119
+ "***********************************************************/\n",
1120
+ zPage);
1121
+ }
1122
+ fossil_free(zFile);
1123
+ }
1124
+ blob_append(&css,
1125
+ "\n/***********************************************************\n"
1126
+ "** All CSS which follows is supplied by the repository \"skin\".\n"
1127
+ "***********************************************************/\n",
1128
+ -1);
1129
+ blob_append(&css,skin_get("css"),-1);
10951130
10961131
/* Process through TH1 in order to give an opportunity to substitute
10971132
** variables such as $baseurl.
10981133
*/
10991134
Th_Store("baseurl", g.zBaseURL);
11001135
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340 const struct Submenu *A = (const struct Submenu*)a;
341 const struct Submenu *B = (const struct Submenu*)b;
342 return fossil_strcmp(A->zLabel, B->zLabel);
343 }
344
345 /* Use this for the $current_page variable if it is not NULL. If it is
346 ** NULL then use g.zPath.
347 */
348 static char *local_zCurrentPage = 0;
349
350 /*
351 ** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361 va_end(ap);
362 }
363 }
364
365 /*
366 ** Create a TH1 variable containing the URL for the specified config resource.
367 ** The resulting variable name will be of the form $[zVarPrefix]_url.
 
368 */
369 static void url_var(
370 const char *zVarPrefix,
371 const char *zConfigName,
372 const char *zPageName
373 ){
374 char *zVarName = mprintf("%s_url", zVarPrefix);
375 char *zUrl = mprintf("%R/%s?id=%x", zPageName,
376 skin_id(zConfigName));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377 Th_Store(zVarName, zUrl);
378 free(zUrl);
379 free(zVarName);
380 }
381
382 /*
383 ** Create a TH1 variable containing the URL for the specified config image.
384 ** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
1024 ** COMMAND: test-contains-selector
1025 **
1026 ** Usage: %fossil test-contains-selector FILENAME SELECTOR
1027 **
1028 ** Determine if the CSS stylesheet FILENAME contains SELECTOR.
 
 
 
 
 
1029 */
1030 void contains_selector_cmd(void){
1031 int found;
1032 char *zSelector;
1033 Blob css;
@@ -1056,44 +1076,59 @@
1056 }
1057 style_init_th1_vars(0);
1058 Th_Render(zScript?zScript:"");
1059 }
1060
1061
1062 /*
1063 ** WEBPAGE: style.css
1064 **
1065 ** Return the style sheet.
1066 */
1067 void page_style_css(void){
1068 Blob css;
1069 int i;
1070 int isInit = 0;
1071
1072 cgi_set_content_type("text/css");
1073 blob_init(&css,skin_get("css"),-1);
1074
1075 /* add special missing definitions */
1076 for(i=1; cssDefaultList[i].elementClass; i++){
1077 char *z = blob_str(&css);
1078 if( !containsSelector(z, cssDefaultList[i].elementClass) ){
1079 if( !isInit ){
1080 isInit = 1;
1081 blob_append(&css,
1082 "\n/***********************************************************\n"
1083 "** All CSS above is supplied by the repository \"skin\".\n"
1084 "** That which follows is generated automatically by Fossil\n"
1085 "** to fill in needed selectors that are missing from the\n"
1086 "** \"skin\" CSS.\n"
1087 "***********************************************************/\n",
1088 -1);
1089 }
1090 blob_appendf(&css, "%s {\n%s}\n",
1091 cssDefaultList[i].elementClass,
1092 cssDefaultList[i].value);
1093 }
1094 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1095
1096 /* Process through TH1 in order to give an opportunity to substitute
1097 ** variables such as $baseurl.
1098 */
1099 Th_Store("baseurl", g.zBaseURL);
1100
--- src/style.c
+++ src/style.c
@@ -340,12 +340,12 @@
340 const struct Submenu *A = (const struct Submenu*)a;
341 const struct Submenu *B = (const struct Submenu*)b;
342 return fossil_strcmp(A->zLabel, B->zLabel);
343 }
344
345 /* Use this for the $current_page variable if it is not NULL. If it
346 ** is NULL then use g.zPath.
347 */
348 static char *local_zCurrentPage = 0;
349
350 /*
351 ** Set the desired $current_page to something other than g.zPath
@@ -361,24 +361,39 @@
361 va_end(ap);
362 }
363 }
364
365 /*
366 ** Create a TH1 variable containing the URL for the specified config
367 ** resource. The resulting variable name will be of the form
368 ** $[zVarPrefix]_url.
369 */
370 static void url_var(
371 const char *zVarPrefix,
372 const char *zConfigName,
373 const char *zPageName
374 ){
375 char *zVarName = mprintf("%s_url", zVarPrefix);
376 char *zUrl = 0; /* stylesheet URL */
377 int hasBuiltin = 0; /* true for built-in page-specific CSS */
378
379 if(0==strcmp("css",zConfigName)){
380 /* Account for page-specific CSS, appending a /{{g.zPath}} to the
381 ** url only if we have a corresponding built-in page-specific CSS
382 ** file. Do not append it to all pages because we would
383 ** effectively cache-bust all pages which do not have
384 ** page-specific CSS. */
385 char * zBuiltin = mprintf("style.%s.css", g.zPath);
386 hasBuiltin = builtin_file(zBuiltin,0)!=0;
387 fossil_free(zBuiltin);
388 }
389 zUrl = mprintf("%R/%s%s%s?id=%x", zPageName,
390 hasBuiltin ? "/" : "", hasBuiltin ? g.zPath : "",
391 skin_id(zConfigName));
392 Th_Store(zVarName, zUrl);
393 fossil_free(zUrl);
394 fossil_free(zVarName);
395 }
396
397 /*
398 ** Create a TH1 variable containing the URL for the specified config image.
399 ** The resulting variable name will be of the form $[zImageName]_image_url.
@@ -1024,10 +1039,15 @@
1039 ** COMMAND: test-contains-selector
1040 **
1041 ** Usage: %fossil test-contains-selector FILENAME SELECTOR
1042 **
1043 ** Determine if the CSS stylesheet FILENAME contains SELECTOR.
1044 **
1045 ** Note that as of 2020-05-28, the default rules are always emitted,
1046 ** so the containsSelector() logic is no longer applied when emitting
1047 ** style.css. It is unclear whether this test command is now obsolete
1048 ** or whether it may still serve a purpose.
1049 */
1050 void contains_selector_cmd(void){
1051 int found;
1052 char *zSelector;
1053 Blob css;
@@ -1056,44 +1076,59 @@
1076 }
1077 style_init_th1_vars(0);
1078 Th_Render(zScript?zScript:"");
1079 }
1080
 
1081 /*
1082 ** WEBPAGE: style.css
1083 **
1084 ** Return the style sheet.
1085 */
1086 void page_style_css(void){
1087 Blob css = empty_blob;
1088 int i;
1089 const char *zPage = PD("name",P("page"));
1090
1091 cgi_set_content_type("text/css");
1092 /* Emit all default rules... */
 
 
1093 for(i=1; cssDefaultList[i].elementClass; i++){
1094 blob_appendf(&css, "%s {\n%s}\n",
1095 cssDefaultList[i].elementClass,
1096 cssDefaultList[i].value);
1097 }
1098 blob_append(&css,
1099 "\n/***********************************************************\n"
1100 "** All CSS above is generated automatically by Fossil to\n"
1101 "** provide default rule implementations which the \"skin\"\n"
1102 "** may cascade.\n"
1103 "***********************************************************/\n",
1104 -1);
1105 if(zPage!=0 && zPage[0]!=0){
1106 char * zFile = mprintf("style.%s.css", zPage);
1107 int nFile = 0;
1108 const char *zBuiltin = (const char *)builtin_file(zFile, &nFile);
1109 if(nFile>0){
1110 blob_appendf(&css,
1111 "\n/***********************************************************\n"
1112 "** Start of page-specific CSS for page %s...\n"
1113 "***********************************************************/\n",
1114 zPage);
1115 blob_append(&css, zBuiltin, nFile);
1116 blob_appendf(&css,
1117 "\n/***********************************************************\n"
1118 "** End of page-specific CSS for page %s.\n"
1119 "***********************************************************/\n",
1120 zPage);
1121 }
1122 fossil_free(zFile);
1123 }
1124 blob_append(&css,
1125 "\n/***********************************************************\n"
1126 "** All CSS which follows is supplied by the repository \"skin\".\n"
1127 "***********************************************************/\n",
1128 -1);
1129 blob_append(&css,skin_get("css"),-1);
1130
1131 /* Process through TH1 in order to give an opportunity to substitute
1132 ** variables such as $baseurl.
1133 */
1134 Th_Store("baseurl", g.zBaseURL);
1135
+1 -1
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
4949
int isFile; /* True if a "file:" url */
5050
int isHttps; /* True if a "https:" url */
5151
int isSsh; /* True if an "ssh:" url */
5252
char *name; /* Hostname for http: or filename for file: */
5353
char *hostname; /* The HOST: parameter on http headers */
54
- char *protocol; /* "http" or "https" */
54
+ const char *protocol; /* "http" or "https" or "ssh" */
5555
int port; /* TCP port number for http: or https: */
5656
int dfltPort; /* The default port for the given protocol */
5757
char *path; /* Pathname for http: */
5858
char *user; /* User id for http: */
5959
char *passwd; /* Password for http: */
6060
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
49 int isFile; /* True if a "file:" url */
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 char *name; /* Hostname for http: or filename for file: */
53 char *hostname; /* The HOST: parameter on http headers */
54 char *protocol; /* "http" or "https" */
55 int port; /* TCP port number for http: or https: */
56 int dfltPort; /* The default port for the given protocol */
57 char *path; /* Pathname for http: */
58 char *user; /* User id for http: */
59 char *passwd; /* Password for http: */
60
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
49 int isFile; /* True if a "file:" url */
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 char *name; /* Hostname for http: or filename for file: */
53 char *hostname; /* The HOST: parameter on http headers */
54 const char *protocol; /* "http" or "https" or "ssh" */
55 int port; /* TCP port number for http: or https: */
56 int dfltPort; /* The default port for the given protocol */
57 char *path; /* Pathname for http: */
58 char *user; /* User id for http: */
59 char *passwd; /* Password for http: */
60
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -665,10 +665,11 @@
665665
$(SRCDIR)/sounds/b.wav \
666666
$(SRCDIR)/sounds/c.wav \
667667
$(SRCDIR)/sounds/d.wav \
668668
$(SRCDIR)/sounds/e.wav \
669669
$(SRCDIR)/sounds/f.wav \
670
+ $(SRCDIR)/style.admin_log.css \
670671
$(SRCDIR)/tree.js \
671672
$(SRCDIR)/useredit.js \
672673
$(SRCDIR)/wiki.wiki
673674
674675
TRANS_SRC = \
675676
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -665,10 +665,11 @@
665 $(SRCDIR)/sounds/b.wav \
666 $(SRCDIR)/sounds/c.wav \
667 $(SRCDIR)/sounds/d.wav \
668 $(SRCDIR)/sounds/e.wav \
669 $(SRCDIR)/sounds/f.wav \
 
670 $(SRCDIR)/tree.js \
671 $(SRCDIR)/useredit.js \
672 $(SRCDIR)/wiki.wiki
673
674 TRANS_SRC = \
675
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -665,10 +665,11 @@
665 $(SRCDIR)/sounds/b.wav \
666 $(SRCDIR)/sounds/c.wav \
667 $(SRCDIR)/sounds/d.wav \
668 $(SRCDIR)/sounds/e.wav \
669 $(SRCDIR)/sounds/f.wav \
670 $(SRCDIR)/style.admin_log.css \
671 $(SRCDIR)/tree.js \
672 $(SRCDIR)/useredit.js \
673 $(SRCDIR)/wiki.wiki
674
675 TRANS_SRC = \
676
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -572,10 +572,11 @@
572572
$(SRCDIR)\sounds\b.wav \
573573
$(SRCDIR)\sounds\c.wav \
574574
$(SRCDIR)\sounds\d.wav \
575575
$(SRCDIR)\sounds\e.wav \
576576
$(SRCDIR)\sounds\f.wav \
577
+ $(SRCDIR)\style.admin_log.css \
577578
$(SRCDIR)\tree.js \
578579
$(SRCDIR)\useredit.js \
579580
$(SRCDIR)\wiki.wiki
580581
581582
OBJ = $(OX)\add$O \
582583
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -572,10 +572,11 @@
572 $(SRCDIR)\sounds\b.wav \
573 $(SRCDIR)\sounds\c.wav \
574 $(SRCDIR)\sounds\d.wav \
575 $(SRCDIR)\sounds\e.wav \
576 $(SRCDIR)\sounds\f.wav \
 
577 $(SRCDIR)\tree.js \
578 $(SRCDIR)\useredit.js \
579 $(SRCDIR)\wiki.wiki
580
581 OBJ = $(OX)\add$O \
582
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -572,10 +572,11 @@
572 $(SRCDIR)\sounds\b.wav \
573 $(SRCDIR)\sounds\c.wav \
574 $(SRCDIR)\sounds\d.wav \
575 $(SRCDIR)\sounds\e.wav \
576 $(SRCDIR)\sounds\f.wav \
577 $(SRCDIR)\style.admin_log.css \
578 $(SRCDIR)\tree.js \
579 $(SRCDIR)\useredit.js \
580 $(SRCDIR)\wiki.wiki
581
582 OBJ = $(OX)\add$O \
583
--- www/css-tricks.md
+++ www/css-tricks.md
@@ -10,43 +10,10 @@
1010
1111
This document is *not* an introduction to CSS - the web is
1212
full of tutorials on that topic. It covers only the specifics
1313
of customizing certain CSS-based behaviors in a Fossil UI. That said...
1414
15
-# Overriding Default Rules
16
-
17
-One behavior of the skinning system works considerably differently
18
-from the cascading nature of CSS: if a skin applies a CSS selector for
19
-which Fossil has a built-in default value, Fossil elides the entire
20
-default definition for that rule. i.e., the skin's definition is the
21
-only one which is applied, rather than cascading the definition from
22
-the default value.
23
-
24
-For example, if Fossil has a default CSS rule which looks like:
25
-
26
-```css
27
-div.foo {
28
- font-size: 120%;
29
- margin-left: 1em;
30
-}
31
-```
32
-
33
-And a skin has:
34
-
35
-```css
36
-div.foo {}
37
-```
38
-
39
-Then Fossil will *not* emit its default rule and the user's copy will
40
-become the only definition of that CSS rule. This is different from
41
-normal CSS cascading rules, in which the above sequence would result
42
-in, effectively, the top set of rules being applied because the second
43
-(empty) one does not override anything from the first.
44
-
45
-If a skin applies a given selector more than once, or imports external
46
-style sheets which do, those cascade following CSS's normal rules.
47
-
4815
## Is it Really `!important`?
4916
5017
By and large, CSS's `!important` qualifier is not needed when
5118
customzing Fossil's CSS. On occasion, however, particular styles may
5219
be set directly on DOM elements when Fossil generates its HTML, and
5320
--- www/css-tricks.md
+++ www/css-tricks.md
@@ -10,43 +10,10 @@
10
11 This document is *not* an introduction to CSS - the web is
12 full of tutorials on that topic. It covers only the specifics
13 of customizing certain CSS-based behaviors in a Fossil UI. That said...
14
15 # Overriding Default Rules
16
17 One behavior of the skinning system works considerably differently
18 from the cascading nature of CSS: if a skin applies a CSS selector for
19 which Fossil has a built-in default value, Fossil elides the entire
20 default definition for that rule. i.e., the skin's definition is the
21 only one which is applied, rather than cascading the definition from
22 the default value.
23
24 For example, if Fossil has a default CSS rule which looks like:
25
26 ```css
27 div.foo {
28 font-size: 120%;
29 margin-left: 1em;
30 }
31 ```
32
33 And a skin has:
34
35 ```css
36 div.foo {}
37 ```
38
39 Then Fossil will *not* emit its default rule and the user's copy will
40 become the only definition of that CSS rule. This is different from
41 normal CSS cascading rules, in which the above sequence would result
42 in, effectively, the top set of rules being applied because the second
43 (empty) one does not override anything from the first.
44
45 If a skin applies a given selector more than once, or imports external
46 style sheets which do, those cascade following CSS's normal rules.
47
48 ## Is it Really `!important`?
49
50 By and large, CSS's `!important` qualifier is not needed when
51 customzing Fossil's CSS. On occasion, however, particular styles may
52 be set directly on DOM elements when Fossil generates its HTML, and
53
--- www/css-tricks.md
+++ www/css-tricks.md
@@ -10,43 +10,10 @@
10
11 This document is *not* an introduction to CSS - the web is
12 full of tutorials on that topic. It covers only the specifics
13 of customizing certain CSS-based behaviors in a Fossil UI. That said...
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15 ## Is it Really `!important`?
16
17 By and large, CSS's `!important` qualifier is not needed when
18 customzing Fossil's CSS. On occasion, however, particular styles may
19 be set directly on DOM elements when Fossil generates its HTML, and
20

Keyboard Shortcuts

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