Fossil SCM

Improvements to line-numbered text output.

drh 2020-08-16 13:39 trunk merge
Commit b699040d701464ced678af7a7c353871d23440dd505fb9c8ef68043eed388271
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -572,10 +572,13 @@
572572
white-space: nowrap;
573573
background: #000;
574574
border: 2px solid #bbb;
575575
border-radius: 5px
576576
}
577
+table.numbered-lines td.file-content > pre {
578
+ margin-top: -2px/*offset CODE tag border*/;
579
+}
577580
pre > code {
578581
padding: 1rem 1.5rem;
579582
white-space: pre
580583
}
581584
td,
582585
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -572,10 +572,13 @@
572 white-space: nowrap;
573 background: #000;
574 border: 2px solid #bbb;
575 border-radius: 5px
576 }
 
 
 
577 pre > code {
578 padding: 1rem 1.5rem;
579 white-space: pre
580 }
581 td,
582
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -572,10 +572,13 @@
572 white-space: nowrap;
573 background: #000;
574 border: 2px solid #bbb;
575 border-radius: 5px
576 }
577 table.numbered-lines td.file-content > pre {
578 margin-top: -2px/*offset CODE tag border*/;
579 }
580 pre > code {
581 padding: 1rem 1.5rem;
582 white-space: pre
583 }
584 td,
585
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -399,11 +399,11 @@
399399
400400
div.filetreeline:hover {
401401
background-color: #7EA2D9;
402402
}
403403
404
-div.selectedText {
404
+table.numbered-lines td.line-numbers span.selected-line {
405405
background-color: #7EA2D9;
406406
}
407407
408408
.statistics-report-graph-line {
409409
background-color: #7EA2D9;
410410
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -399,11 +399,11 @@
399
400 div.filetreeline:hover {
401 background-color: #7EA2D9;
402 }
403
404 div.selectedText {
405 background-color: #7EA2D9;
406 }
407
408 .statistics-report-graph-line {
409 background-color: #7EA2D9;
410
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -399,11 +399,11 @@
399
400 div.filetreeline:hover {
401 background-color: #7EA2D9;
402 }
403
404 table.numbered-lines td.line-numbers span.selected-line {
405 background-color: #7EA2D9;
406 }
407
408 .statistics-report-graph-line {
409 background-color: #7EA2D9;
410
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -1000,15 +1000,15 @@
10001000
/**************************************
10011001
* Did not encounter these
10021002
*/
10031003
10041004
/* selected lines of text within a linenumbered artifact display */
1005
-div.selectedText {
1005
+table.numbered-lines td.line-numbers span.selected-line {
10061006
font-weight: bold;
10071007
color: #00f;
10081008
background-color: #d5d5ff;
1009
- border: 1px #00f solid;
1009
+ border-color: #00f;
10101010
}
10111011
10121012
/* format for missing privileges note on user setup page */
10131013
p.missingPriv {
10141014
color: #00f;
10151015
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -1000,15 +1000,15 @@
1000 /**************************************
1001 * Did not encounter these
1002 */
1003
1004 /* selected lines of text within a linenumbered artifact display */
1005 div.selectedText {
1006 font-weight: bold;
1007 color: #00f;
1008 background-color: #d5d5ff;
1009 border: 1px #00f solid;
1010 }
1011
1012 /* format for missing privileges note on user setup page */
1013 p.missingPriv {
1014 color: #00f;
1015
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -1000,15 +1000,15 @@
1000 /**************************************
1001 * Did not encounter these
1002 */
1003
1004 /* selected lines of text within a linenumbered artifact display */
1005 table.numbered-lines td.line-numbers span.selected-line {
1006 font-weight: bold;
1007 color: #00f;
1008 background-color: #d5d5ff;
1009 border-color: #00f;
1010 }
1011
1012 /* format for missing privileges note on user setup page */
1013 p.missingPriv {
1014 color: #00f;
1015
+2 -1
--- src/ajax.c
+++ src/ajax.c
@@ -130,11 +130,12 @@
130130
wiki_render_by_mimetype(pContent, zMime);
131131
break;
132132
default:{
133133
const char *zContent = blob_str(pContent);
134134
if(AJAX_PREVIEW_LINE_NUMBERS & flags){
135
- output_text_with_line_numbers(zContent, "on");
135
+ output_text_with_line_numbers(zContent, blob_size(pContent),
136
+ zName, "on");
136137
}else{
137138
const char *zExt = strrchr(zName,'.');
138139
if(zExt && zExt[1]){
139140
CX("<pre><code class='language-%s'>%h</code></pre>",
140141
zExt+1, zContent);
141142
--- src/ajax.c
+++ src/ajax.c
@@ -130,11 +130,12 @@
130 wiki_render_by_mimetype(pContent, zMime);
131 break;
132 default:{
133 const char *zContent = blob_str(pContent);
134 if(AJAX_PREVIEW_LINE_NUMBERS & flags){
135 output_text_with_line_numbers(zContent, "on");
 
136 }else{
137 const char *zExt = strrchr(zName,'.');
138 if(zExt && zExt[1]){
139 CX("<pre><code class='language-%s'>%h</code></pre>",
140 zExt+1, zContent);
141
--- src/ajax.c
+++ src/ajax.c
@@ -130,11 +130,12 @@
130 wiki_render_by_mimetype(pContent, zMime);
131 break;
132 default:{
133 const char *zContent = blob_str(pContent);
134 if(AJAX_PREVIEW_LINE_NUMBERS & flags){
135 output_text_with_line_numbers(zContent, blob_size(pContent),
136 zName, "on");
137 }else{
138 const char *zExt = strrchr(zName,'.');
139 if(zExt && zExt[1]){
140 CX("<pre><code class='language-%s'>%h</code></pre>",
141 zExt+1, zContent);
142
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -617,11 +617,11 @@
617617
const char *z;
618618
content_get(ridSrc, &attach);
619619
blob_to_utf8_no_bom(&attach, 0);
620620
z = blob_str(&attach);
621621
if( zLn ){
622
- output_text_with_line_numbers(z, zLn);
622
+ output_text_with_line_numbers(z, blob_size(&attach), zName, zLn);
623623
}else{
624624
@ <pre>
625625
@ %h(z)
626626
@ </pre>
627627
}
628628
--- src/attach.c
+++ src/attach.c
@@ -617,11 +617,11 @@
617 const char *z;
618 content_get(ridSrc, &attach);
619 blob_to_utf8_no_bom(&attach, 0);
620 z = blob_str(&attach);
621 if( zLn ){
622 output_text_with_line_numbers(z, zLn);
623 }else{
624 @ <pre>
625 @ %h(z)
626 @ </pre>
627 }
628
--- src/attach.c
+++ src/attach.c
@@ -617,11 +617,11 @@
617 const char *z;
618 content_get(ridSrc, &attach);
619 blob_to_utf8_no_bom(&attach, 0);
620 z = blob_str(&attach);
621 if( zLn ){
622 output_text_with_line_numbers(z, blob_size(&attach), zName, zLn);
623 }else{
624 @ <pre>
625 @ %h(z)
626 @ </pre>
627 }
628
+135 -10
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440440
content:"'";
441441
}
442442
span.usertype:after {
443443
content:"'";
444444
}
445
-div.selectedText {
446
- font-weight: bold;
447
- color: blue;
448
- background-color: #d5d5ff;
449
- border: 1px blue solid;
450
-}
451445
p.missingPriv {
452446
color: blue;
453447
}
454448
span.wikiruleHead {
455449
font-weight: bold;
@@ -953,14 +947,19 @@
953947
color: darkred;
954948
background: yellow;
955949
opacity: 0.7;
956950
}
957951
.hidden {
958
- position: absolute;
959
- opacity: 0;
960
- pointer-events: none;
961
- display: none;
952
+ /* The framework-wide way of hiding elements is to assign them this
953
+ CSS class. To make them visible again, remove it. The !important
954
+ qualifiers are unfortunate but sometimes necessary when hidden
955
+ element has other classes which specify visibility-related
956
+ options. */
957
+ position: absolute !important;
958
+ opacity: 0 !important;
959
+ pointer-events: none !important;
960
+ display: none !important;
962961
}
963962
input {
964963
max-width: 95%;
965964
}
966965
textarea {
@@ -1148,5 +1147,131 @@
11481147
.input-with-label > label {
11491148
font-weight: initial;
11501149
margin: 0 0.25em 0 0.25em;
11511150
vertical-align: middle;
11521151
}
1152
+
1153
+table.numbered-lines {
1154
+ width: 100%;
1155
+ table-layout: fixed /* required to keep ultra-wide code from exceeding
1156
+ window width, and instead force a scrollbar
1157
+ on them. */;
1158
+}
1159
+table.numbered-lines > tbody > tr {
1160
+ font-family: monospace;
1161
+ font-size: 1.2em;
1162
+ line-height: 1.35;
1163
+ white-space: pre;
1164
+}
1165
+table.numbered-lines > tbody > tr > td {
1166
+ font-family: inherit;
1167
+ font-size: inherit;
1168
+ line-height: inherit;
1169
+ white-space: inherit;
1170
+ margin: 0;
1171
+ vertical-align: top;
1172
+ padding: 0.25em 0 0 0 /*prevents slight overlap at top */;
1173
+}
1174
+table.numbered-lines td.line-numbers {
1175
+ width: 4.5em;
1176
+}
1177
+table.numbered-lines td.line-numbers > span:first-of-type {
1178
+ margin-top: 0.25em/*must match top PADDING of
1179
+ td.file-content > pre > code*/;
1180
+}
1181
+table.numbered-lines td.line-numbers > span {
1182
+ display: block;
1183
+ margin: 0;
1184
+ padding: 0;
1185
+ line-height: inherit;
1186
+ font-size: inherit;
1187
+ font-family: inherit;
1188
+ cursor: pointer;
1189
+ white-space: pre;
1190
+ margin-right: 2px/*keep selection from nudging the right column */;
1191
+ text-align: right;
1192
+}
1193
+table.numbered-lines td.line-numbers > span:hover {
1194
+ background-color: rgba(112, 112, 112, 0.25);
1195
+}
1196
+table.numbered-lines td.file-content {
1197
+ padding-left: 0.25em;
1198
+}
1199
+table.numbered-lines td.file-content > pre,
1200
+table.numbered-lines td.file-content > pre > code {
1201
+ margin: 0;
1202
+ padding: 0;
1203
+ line-height: inherit;
1204
+ font-size: inherit;
1205
+ font-family: inherit;
1206
+ white-space: pre;
1207
+ display: block/*necessary for certain skins!*/;
1208
+}
1209
+table.numbered-lines td.file-content > pre {
1210
+}
1211
+table.numbered-lines td.file-content > pre > code {
1212
+ overflow: auto;
1213
+ padding-left: 0.5em;
1214
+ padding-right: 0.5em;
1215
+ padding-top: 0.25em/*any top padding here must match the top MARGIN of
1216
+ td.line-numbers's first span child or the
1217
+ lines/code will get misaligned. */;
1218
+ padding-bottom: 0.25em/*prevents a slight overlap at bottom from
1219
+ triggering a scroller*/;
1220
+}
1221
+table.numbered-lines td.file-content > pre > code > * {
1222
+ /* Defense against syntax highlighters indirectly messing up these
1223
+ properties... */
1224
+ line-height: inherit;
1225
+ font-size: inherit;
1226
+ font-family: inherit;
1227
+}
1228
+table.numbered-lines td.line-numbers span.selected-line/*replacement*/ {
1229
+ font-weight: bold;
1230
+ color: blue;
1231
+ background-color: #d5d5ff;
1232
+ border: 1px blue solid;
1233
+ border-top-width: 0;
1234
+ border-bottom-width: 0;
1235
+ padding: 0;
1236
+ margin: 0;
1237
+}
1238
+table.numbered-lines td.line-numbers span.selected-line.start {
1239
+ border-top-width: 1px;
1240
+ margin-top: -1px/*restore alignment*/;
1241
+}
1242
+table.numbered-lines td.line-numbers span.selected-line.end {
1243
+ border-bottom-width: 1px;
1244
+ margin-top: -1px/*restore alignment*/;
1245
+}
1246
+table.numbered-lines td.line-numbers span.selected-line.start.end {
1247
+ margin-top: -2px/*restore alignment*/;
1248
+}
1249
+
1250
+.fossil-tooltip {
1251
+ text-align: center;
1252
+ padding: 0.2em 1em;
1253
+ border: 1px solid black;
1254
+ border-radius: 0.25em;
1255
+ position: absolute;
1256
+ display: inline-block;
1257
+ z-index: 100;
1258
+ box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1259
+ background-color: inherit;
1260
+ font-size: 80%;
1261
+}
1262
+
1263
+.fossil-toast {/* "toast"-style popup message */
1264
+ padding: 0.25em 0.5em;
1265
+ margin: 0;
1266
+ border-radius: 0.25em;
1267
+ font-size: 1em;
1268
+ opacity: 0.8;
1269
+ border-size: 1px;
1270
+ border-style: dotted;
1271
+ border-color: rgb( 127, 127, 127, 0.5 );
1272
+}
1273
+
1274
+blockquote.file-content {
1275
+ /* file content block in the /file page */
1276
+ margin: 0 1em;
1277
+}
11531278
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440 content:"'";
441 }
442 span.usertype:after {
443 content:"'";
444 }
445 div.selectedText {
446 font-weight: bold;
447 color: blue;
448 background-color: #d5d5ff;
449 border: 1px blue solid;
450 }
451 p.missingPriv {
452 color: blue;
453 }
454 span.wikiruleHead {
455 font-weight: bold;
@@ -953,14 +947,19 @@
953 color: darkred;
954 background: yellow;
955 opacity: 0.7;
956 }
957 .hidden {
958 position: absolute;
959 opacity: 0;
960 pointer-events: none;
961 display: none;
 
 
 
 
 
962 }
963 input {
964 max-width: 95%;
965 }
966 textarea {
@@ -1148,5 +1147,131 @@
1148 .input-with-label > label {
1149 font-weight: initial;
1150 margin: 0 0.25em 0 0.25em;
1151 vertical-align: middle;
1152 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440 content:"'";
441 }
442 span.usertype:after {
443 content:"'";
444 }
 
 
 
 
 
 
445 p.missingPriv {
446 color: blue;
447 }
448 span.wikiruleHead {
449 font-weight: bold;
@@ -953,14 +947,19 @@
947 color: darkred;
948 background: yellow;
949 opacity: 0.7;
950 }
951 .hidden {
952 /* The framework-wide way of hiding elements is to assign them this
953 CSS class. To make them visible again, remove it. The !important
954 qualifiers are unfortunate but sometimes necessary when hidden
955 element has other classes which specify visibility-related
956 options. */
957 position: absolute !important;
958 opacity: 0 !important;
959 pointer-events: none !important;
960 display: none !important;
961 }
962 input {
963 max-width: 95%;
964 }
965 textarea {
@@ -1148,5 +1147,131 @@
1147 .input-with-label > label {
1148 font-weight: initial;
1149 margin: 0 0.25em 0 0.25em;
1150 vertical-align: middle;
1151 }
1152
1153 table.numbered-lines {
1154 width: 100%;
1155 table-layout: fixed /* required to keep ultra-wide code from exceeding
1156 window width, and instead force a scrollbar
1157 on them. */;
1158 }
1159 table.numbered-lines > tbody > tr {
1160 font-family: monospace;
1161 font-size: 1.2em;
1162 line-height: 1.35;
1163 white-space: pre;
1164 }
1165 table.numbered-lines > tbody > tr > td {
1166 font-family: inherit;
1167 font-size: inherit;
1168 line-height: inherit;
1169 white-space: inherit;
1170 margin: 0;
1171 vertical-align: top;
1172 padding: 0.25em 0 0 0 /*prevents slight overlap at top */;
1173 }
1174 table.numbered-lines td.line-numbers {
1175 width: 4.5em;
1176 }
1177 table.numbered-lines td.line-numbers > span:first-of-type {
1178 margin-top: 0.25em/*must match top PADDING of
1179 td.file-content > pre > code*/;
1180 }
1181 table.numbered-lines td.line-numbers > span {
1182 display: block;
1183 margin: 0;
1184 padding: 0;
1185 line-height: inherit;
1186 font-size: inherit;
1187 font-family: inherit;
1188 cursor: pointer;
1189 white-space: pre;
1190 margin-right: 2px/*keep selection from nudging the right column */;
1191 text-align: right;
1192 }
1193 table.numbered-lines td.line-numbers > span:hover {
1194 background-color: rgba(112, 112, 112, 0.25);
1195 }
1196 table.numbered-lines td.file-content {
1197 padding-left: 0.25em;
1198 }
1199 table.numbered-lines td.file-content > pre,
1200 table.numbered-lines td.file-content > pre > code {
1201 margin: 0;
1202 padding: 0;
1203 line-height: inherit;
1204 font-size: inherit;
1205 font-family: inherit;
1206 white-space: pre;
1207 display: block/*necessary for certain skins!*/;
1208 }
1209 table.numbered-lines td.file-content > pre {
1210 }
1211 table.numbered-lines td.file-content > pre > code {
1212 overflow: auto;
1213 padding-left: 0.5em;
1214 padding-right: 0.5em;
1215 padding-top: 0.25em/*any top padding here must match the top MARGIN of
1216 td.line-numbers's first span child or the
1217 lines/code will get misaligned. */;
1218 padding-bottom: 0.25em/*prevents a slight overlap at bottom from
1219 triggering a scroller*/;
1220 }
1221 table.numbered-lines td.file-content > pre > code > * {
1222 /* Defense against syntax highlighters indirectly messing up these
1223 properties... */
1224 line-height: inherit;
1225 font-size: inherit;
1226 font-family: inherit;
1227 }
1228 table.numbered-lines td.line-numbers span.selected-line/*replacement*/ {
1229 font-weight: bold;
1230 color: blue;
1231 background-color: #d5d5ff;
1232 border: 1px blue solid;
1233 border-top-width: 0;
1234 border-bottom-width: 0;
1235 padding: 0;
1236 margin: 0;
1237 }
1238 table.numbered-lines td.line-numbers span.selected-line.start {
1239 border-top-width: 1px;
1240 margin-top: -1px/*restore alignment*/;
1241 }
1242 table.numbered-lines td.line-numbers span.selected-line.end {
1243 border-bottom-width: 1px;
1244 margin-top: -1px/*restore alignment*/;
1245 }
1246 table.numbered-lines td.line-numbers span.selected-line.start.end {
1247 margin-top: -2px/*restore alignment*/;
1248 }
1249
1250 .fossil-tooltip {
1251 text-align: center;
1252 padding: 0.2em 1em;
1253 border: 1px solid black;
1254 border-radius: 0.25em;
1255 position: absolute;
1256 display: inline-block;
1257 z-index: 100;
1258 box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1259 background-color: inherit;
1260 font-size: 80%;
1261 }
1262
1263 .fossil-toast {/* "toast"-style popup message */
1264 padding: 0.25em 0.5em;
1265 margin: 0;
1266 border-radius: 0.25em;
1267 font-size: 1em;
1268 opacity: 0.8;
1269 border-size: 1px;
1270 border-style: dotted;
1271 border-color: rgb( 127, 127, 127, 0.5 );
1272 }
1273
1274 blockquote.file-content {
1275 /* file content block in the /file page */
1276 margin: 0 1em;
1277 }
1278
+135 -10
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440440
content:"'";
441441
}
442442
span.usertype:after {
443443
content:"'";
444444
}
445
-div.selectedText {
446
- font-weight: bold;
447
- color: blue;
448
- background-color: #d5d5ff;
449
- border: 1px blue solid;
450
-}
451445
p.missingPriv {
452446
color: blue;
453447
}
454448
span.wikiruleHead {
455449
font-weight: bold;
@@ -953,14 +947,19 @@
953947
color: darkred;
954948
background: yellow;
955949
opacity: 0.7;
956950
}
957951
.hidden {
958
- position: absolute;
959
- opacity: 0;
960
- pointer-events: none;
961
- display: none;
952
+ /* The framework-wide way of hiding elements is to assign them this
953
+ CSS class. To make them visible again, remove it. The !important
954
+ qualifiers are unfortunate but sometimes necessary when hidden
955
+ element has other classes which specify visibility-related
956
+ options. */
957
+ position: absolute !important;
958
+ opacity: 0 !important;
959
+ pointer-events: none !important;
960
+ display: none !important;
962961
}
963962
input {
964963
max-width: 95%;
965964
}
966965
textarea {
@@ -1148,5 +1147,131 @@
11481147
.input-with-label > label {
11491148
font-weight: initial;
11501149
margin: 0 0.25em 0 0.25em;
11511150
vertical-align: middle;
11521151
}
1152
+
1153
+table.numbered-lines {
1154
+ width: 100%;
1155
+ table-layout: fixed /* required to keep ultra-wide code from exceeding
1156
+ window width, and instead force a scrollbar
1157
+ on them. */;
1158
+}
1159
+table.numbered-lines > tbody > tr {
1160
+ font-family: monospace;
1161
+ font-size: 1.2em;
1162
+ line-height: 1.35;
1163
+ white-space: pre;
1164
+}
1165
+table.numbered-lines > tbody > tr > td {
1166
+ font-family: inherit;
1167
+ font-size: inherit;
1168
+ line-height: inherit;
1169
+ white-space: inherit;
1170
+ margin: 0;
1171
+ vertical-align: top;
1172
+ padding: 0.25em 0 0 0 /*prevents slight overlap at top */;
1173
+}
1174
+table.numbered-lines td.line-numbers {
1175
+ width: 4.5em;
1176
+}
1177
+table.numbered-lines td.line-numbers > span:first-of-type {
1178
+ margin-top: 0.25em/*must match top PADDING of
1179
+ td.file-content > pre > code*/;
1180
+}
1181
+table.numbered-lines td.line-numbers > span {
1182
+ display: block;
1183
+ margin: 0;
1184
+ padding: 0;
1185
+ line-height: inherit;
1186
+ font-size: inherit;
1187
+ font-family: inherit;
1188
+ cursor: pointer;
1189
+ white-space: pre;
1190
+ margin-right: 2px/*keep selection from nudging the right column */;
1191
+ text-align: right;
1192
+}
1193
+table.numbered-lines td.line-numbers > span:hover {
1194
+ background-color: rgba(112, 112, 112, 0.25);
1195
+}
1196
+table.numbered-lines td.file-content {
1197
+ padding-left: 0.25em;
1198
+}
1199
+table.numbered-lines td.file-content > pre,
1200
+table.numbered-lines td.file-content > pre > code {
1201
+ margin: 0;
1202
+ padding: 0;
1203
+ line-height: inherit;
1204
+ font-size: inherit;
1205
+ font-family: inherit;
1206
+ white-space: pre;
1207
+ display: block/*necessary for certain skins!*/;
1208
+}
1209
+table.numbered-lines td.file-content > pre {
1210
+}
1211
+table.numbered-lines td.file-content > pre > code {
1212
+ overflow: auto;
1213
+ padding-left: 0.5em;
1214
+ padding-right: 0.5em;
1215
+ padding-top: 0.25em/*any top padding here must match the top MARGIN of
1216
+ td.line-numbers's first span child or the
1217
+ lines/code will get misaligned. */;
1218
+ padding-bottom: 0.25em/*prevents a slight overlap at bottom from
1219
+ triggering a scroller*/;
1220
+}
1221
+table.numbered-lines td.file-content > pre > code > * {
1222
+ /* Defense against syntax highlighters indirectly messing up these
1223
+ properties... */
1224
+ line-height: inherit;
1225
+ font-size: inherit;
1226
+ font-family: inherit;
1227
+}
1228
+table.numbered-lines td.line-numbers span.selected-line/*replacement*/ {
1229
+ font-weight: bold;
1230
+ color: blue;
1231
+ background-color: #d5d5ff;
1232
+ border: 1px blue solid;
1233
+ border-top-width: 0;
1234
+ border-bottom-width: 0;
1235
+ padding: 0;
1236
+ margin: 0;
1237
+}
1238
+table.numbered-lines td.line-numbers span.selected-line.start {
1239
+ border-top-width: 1px;
1240
+ margin-top: -1px/*restore alignment*/;
1241
+}
1242
+table.numbered-lines td.line-numbers span.selected-line.end {
1243
+ border-bottom-width: 1px;
1244
+ margin-top: -1px/*restore alignment*/;
1245
+}
1246
+table.numbered-lines td.line-numbers span.selected-line.start.end {
1247
+ margin-top: -2px/*restore alignment*/;
1248
+}
1249
+
1250
+.fossil-tooltip {
1251
+ text-align: center;
1252
+ padding: 0.2em 1em;
1253
+ border: 1px solid black;
1254
+ border-radius: 0.25em;
1255
+ position: absolute;
1256
+ display: inline-block;
1257
+ z-index: 100;
1258
+ box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1259
+ background-color: inherit;
1260
+ font-size: 80%;
1261
+}
1262
+
1263
+.fossil-toast {/* "toast"-style popup message */
1264
+ padding: 0.25em 0.5em;
1265
+ margin: 0;
1266
+ border-radius: 0.25em;
1267
+ font-size: 1em;
1268
+ opacity: 0.8;
1269
+ border-size: 1px;
1270
+ border-style: dotted;
1271
+ border-color: rgb( 127, 127, 127, 0.5 );
1272
+}
1273
+
1274
+blockquote.file-content {
1275
+ /* file content block in the /file page */
1276
+ margin: 0 1em;
1277
+}
11531278
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440 content:"'";
441 }
442 span.usertype:after {
443 content:"'";
444 }
445 div.selectedText {
446 font-weight: bold;
447 color: blue;
448 background-color: #d5d5ff;
449 border: 1px blue solid;
450 }
451 p.missingPriv {
452 color: blue;
453 }
454 span.wikiruleHead {
455 font-weight: bold;
@@ -953,14 +947,19 @@
953 color: darkred;
954 background: yellow;
955 opacity: 0.7;
956 }
957 .hidden {
958 position: absolute;
959 opacity: 0;
960 pointer-events: none;
961 display: none;
 
 
 
 
 
962 }
963 input {
964 max-width: 95%;
965 }
966 textarea {
@@ -1148,5 +1147,131 @@
1148 .input-with-label > label {
1149 font-weight: initial;
1150 margin: 0 0.25em 0 0.25em;
1151 vertical-align: middle;
1152 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
--- src/default.css
+++ src/default.css
@@ -440,16 +440,10 @@
440 content:"'";
441 }
442 span.usertype:after {
443 content:"'";
444 }
 
 
 
 
 
 
445 p.missingPriv {
446 color: blue;
447 }
448 span.wikiruleHead {
449 font-weight: bold;
@@ -953,14 +947,19 @@
947 color: darkred;
948 background: yellow;
949 opacity: 0.7;
950 }
951 .hidden {
952 /* The framework-wide way of hiding elements is to assign them this
953 CSS class. To make them visible again, remove it. The !important
954 qualifiers are unfortunate but sometimes necessary when hidden
955 element has other classes which specify visibility-related
956 options. */
957 position: absolute !important;
958 opacity: 0 !important;
959 pointer-events: none !important;
960 display: none !important;
961 }
962 input {
963 max-width: 95%;
964 }
965 textarea {
@@ -1148,5 +1147,131 @@
1147 .input-with-label > label {
1148 font-weight: initial;
1149 margin: 0 0.25em 0 0.25em;
1150 vertical-align: middle;
1151 }
1152
1153 table.numbered-lines {
1154 width: 100%;
1155 table-layout: fixed /* required to keep ultra-wide code from exceeding
1156 window width, and instead force a scrollbar
1157 on them. */;
1158 }
1159 table.numbered-lines > tbody > tr {
1160 font-family: monospace;
1161 font-size: 1.2em;
1162 line-height: 1.35;
1163 white-space: pre;
1164 }
1165 table.numbered-lines > tbody > tr > td {
1166 font-family: inherit;
1167 font-size: inherit;
1168 line-height: inherit;
1169 white-space: inherit;
1170 margin: 0;
1171 vertical-align: top;
1172 padding: 0.25em 0 0 0 /*prevents slight overlap at top */;
1173 }
1174 table.numbered-lines td.line-numbers {
1175 width: 4.5em;
1176 }
1177 table.numbered-lines td.line-numbers > span:first-of-type {
1178 margin-top: 0.25em/*must match top PADDING of
1179 td.file-content > pre > code*/;
1180 }
1181 table.numbered-lines td.line-numbers > span {
1182 display: block;
1183 margin: 0;
1184 padding: 0;
1185 line-height: inherit;
1186 font-size: inherit;
1187 font-family: inherit;
1188 cursor: pointer;
1189 white-space: pre;
1190 margin-right: 2px/*keep selection from nudging the right column */;
1191 text-align: right;
1192 }
1193 table.numbered-lines td.line-numbers > span:hover {
1194 background-color: rgba(112, 112, 112, 0.25);
1195 }
1196 table.numbered-lines td.file-content {
1197 padding-left: 0.25em;
1198 }
1199 table.numbered-lines td.file-content > pre,
1200 table.numbered-lines td.file-content > pre > code {
1201 margin: 0;
1202 padding: 0;
1203 line-height: inherit;
1204 font-size: inherit;
1205 font-family: inherit;
1206 white-space: pre;
1207 display: block/*necessary for certain skins!*/;
1208 }
1209 table.numbered-lines td.file-content > pre {
1210 }
1211 table.numbered-lines td.file-content > pre > code {
1212 overflow: auto;
1213 padding-left: 0.5em;
1214 padding-right: 0.5em;
1215 padding-top: 0.25em/*any top padding here must match the top MARGIN of
1216 td.line-numbers's first span child or the
1217 lines/code will get misaligned. */;
1218 padding-bottom: 0.25em/*prevents a slight overlap at bottom from
1219 triggering a scroller*/;
1220 }
1221 table.numbered-lines td.file-content > pre > code > * {
1222 /* Defense against syntax highlighters indirectly messing up these
1223 properties... */
1224 line-height: inherit;
1225 font-size: inherit;
1226 font-family: inherit;
1227 }
1228 table.numbered-lines td.line-numbers span.selected-line/*replacement*/ {
1229 font-weight: bold;
1230 color: blue;
1231 background-color: #d5d5ff;
1232 border: 1px blue solid;
1233 border-top-width: 0;
1234 border-bottom-width: 0;
1235 padding: 0;
1236 margin: 0;
1237 }
1238 table.numbered-lines td.line-numbers span.selected-line.start {
1239 border-top-width: 1px;
1240 margin-top: -1px/*restore alignment*/;
1241 }
1242 table.numbered-lines td.line-numbers span.selected-line.end {
1243 border-bottom-width: 1px;
1244 margin-top: -1px/*restore alignment*/;
1245 }
1246 table.numbered-lines td.line-numbers span.selected-line.start.end {
1247 margin-top: -2px/*restore alignment*/;
1248 }
1249
1250 .fossil-tooltip {
1251 text-align: center;
1252 padding: 0.2em 1em;
1253 border: 1px solid black;
1254 border-radius: 0.25em;
1255 position: absolute;
1256 display: inline-block;
1257 z-index: 100;
1258 box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1259 background-color: inherit;
1260 font-size: 80%;
1261 }
1262
1263 .fossil-toast {/* "toast"-style popup message */
1264 padding: 0.25em 0.5em;
1265 margin: 0;
1266 border-radius: 0.25em;
1267 font-size: 1em;
1268 opacity: 0.8;
1269 border-size: 1px;
1270 border-style: dotted;
1271 border-color: rgb( 127, 127, 127, 0.5 );
1272 }
1273
1274 blockquote.file-content {
1275 /* file content block in the /file page */
1276 margin: 0 1em;
1277 }
1278
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -125,11 +125,11 @@
125125
** in the count even if it lacks the \n terminator. If an empty string
126126
** is specified, the number of lines is zero. For the purposes of this
127127
** function, a string is considered empty if it contains no characters
128128
** -OR- it contains only NUL characters.
129129
*/
130
-static int count_lines(
130
+int count_lines(
131131
const char *z,
132132
int n,
133133
int *pnLine
134134
){
135135
int nLine;
136136
--- src/diff.c
+++ src/diff.c
@@ -125,11 +125,11 @@
125 ** in the count even if it lacks the \n terminator. If an empty string
126 ** is specified, the number of lines is zero. For the purposes of this
127 ** function, a string is considered empty if it contains no characters
128 ** -OR- it contains only NUL characters.
129 */
130 static int count_lines(
131 const char *z,
132 int n,
133 int *pnLine
134 ){
135 int nLine;
136
--- src/diff.c
+++ src/diff.c
@@ -125,11 +125,11 @@
125 ** in the count even if it lacks the \n terminator. If an empty string
126 ** is specified, the number of lines is zero. For the purposes of this
127 ** function, a string is considered empty if it contains no characters
128 ** -OR- it contains only NUL characters.
129 */
130 int count_lines(
131 const char *z,
132 int n,
133 int *pnLine
134 ){
135 int nLine;
136
+9
--- src/file.c
+++ src/file.c
@@ -2397,5 +2397,14 @@
23972397
changeCount);
23982398
}else{
23992399
fossil_print("Touched %d file(s)\n", changeCount);
24002400
}
24012401
}
2402
+
2403
+/*
2404
+** If zFileName is not NULL and contains a '.', this returns a pointer
2405
+** to the position after the final '.', else it returns NULL.
2406
+*/
2407
+const char * file_extension(const char *zFileName){
2408
+ const char * zExt = strrchr(zFileName, '.');
2409
+ return zExt ? &zExt[1] : 0;
2410
+}
24022411
--- src/file.c
+++ src/file.c
@@ -2397,5 +2397,14 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -2397,5 +2397,14 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
2402
2403 /*
2404 ** If zFileName is not NULL and contains a '.', this returns a pointer
2405 ** to the position after the final '.', else it returns NULL.
2406 */
2407 const char * file_extension(const char *zFileName){
2408 const char * zExt = strrchr(zFileName, '.');
2409 return zExt ? &zExt[1] : 0;
2410 }
2411
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -1,6 +1,18 @@
11
"use strict";
2
+(function () {
3
+ /* CustomEvent polyfill, courtesy of Mozilla:
4
+ https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
5
+ */
6
+ if(typeof window.CustomEvent === "function") return false;
7
+ window.CustomEvent = function(event, params) {
8
+ if(!params) params = {bubbles: false, cancelable: false, detail: null};
9
+ const evt = document.createEvent('CustomEvent');
10
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
11
+ return evt;
12
+ };
13
+})();
214
(function(global){
315
/* Bootstrapping bits for the global.fossil object. Must be
416
loaded after style.c:style_emit_script_tag() has initialized
517
that object.
618
*/
719
820
ADDED src/fossil.copybutton.js
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -1,6 +1,18 @@
1 "use strict";
 
 
 
 
 
 
 
 
 
 
 
 
2 (function(global){
3 /* Bootstrapping bits for the global.fossil object. Must be
4 loaded after style.c:style_emit_script_tag() has initialized
5 that object.
6 */
7
8 DDED src/fossil.copybutton.js
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -1,6 +1,18 @@
1 "use strict";
2 (function () {
3 /* CustomEvent polyfill, courtesy of Mozilla:
4 https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
5 */
6 if(typeof window.CustomEvent === "function") return false;
7 window.CustomEvent = function(event, params) {
8 if(!params) params = {bubbles: false, cancelable: false, detail: null};
9 const evt = document.createEvent('CustomEvent');
10 evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
11 return evt;
12 };
13 })();
14 (function(global){
15 /* Bootstrapping bits for the global.fossil object. Must be
16 loaded after style.c:style_emit_script_tag() has initialized
17 that object.
18 */
19
20 DDED src/fossil.copybutton.js
--- a/src/fossil.copybutton.js
+++ b/src/fossil.copybutton.js
@@ -0,0 +1,3 @@
1
+(function(F/*fossil object*/){
2
+ /**
3
+ A basic API for creating and
--- a/src/fossil.copybutton.js
+++ b/src/fossil.copybutton.js
@@ -0,0 +1,3 @@
 
 
 
--- a/src/fossil.copybutton.js
+++ b/src/fossil.copybutton.js
@@ -0,0 +1,3 @@
1 (function(F/*fossil object*/){
2 /**
3 A basic API for creating and
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -465,10 +465,103 @@
465465
e = src.querySelector(x);
466466
if(!e){
467467
e = new Error("Cannot find DOM element: "+x);
468468
console.error(e, src);
469469
throw e;
470
+ }
471
+ return e;
472
+ };
473
+
474
+ /**
475
+ "Blinks" the given element a single time for the given number of
476
+ milliseconds, defaulting (if the 2nd argument is falsy or not a
477
+ number) to flashOnce.defaultTimeMs. If a 3rd argument is passed
478
+ in, it must be a function, and it gets callback back at the end
479
+ of the asynchronous flashing processes.
480
+
481
+ This will only activate once per element during that timeframe -
482
+ further calls will become no-ops until the blink is
483
+ completed. This routine adds a dataset member to the element for
484
+ the duration of the blink, to allow it to block multiple blinks.
485
+
486
+ If passed 2 arguments and the 2nd is a function, it behaves as if
487
+ it were called as (arg1, undefined, arg2).
488
+
489
+ Returns e, noting that the flash itself is asynchronous and may
490
+ still be running, or not yet started, when this function returns.
491
+ */
492
+ dom.flashOnce = function f(e,howLongMs,afterFlashCallback){
493
+ if(e.dataset.isBlinking){
494
+ return;
495
+ }
496
+ if(2===arguments.length && 'function' ===typeof howLongMs){
497
+ afterFlashCallback = howLongMs;
498
+ howLongMs = f.defaultTimeMs;
499
+ }
500
+ if(!howLongMs || 'number'!==typeof howLongMs){
501
+ howLongMs = f.defaultTimeMs;
502
+ }
503
+ e.dataset.isBlinking = true;
504
+ const transition = e.style.transition;
505
+ e.style.transition = "opacity "+howLongMs+"ms ease-in-out";
506
+ const opacity = e.style.opacity;
507
+ e.style.opacity = 0;
508
+ setTimeout(function(){
509
+ e.style.transition = transition;
510
+ e.style.opacity = opacity;
511
+ delete e.dataset.isBlinking;
512
+ if(afterFlashCallback) afterFlashCallback();
513
+ }, howLongMs);
514
+ return e;
515
+ };
516
+ dom.flashOnce.defaultTimeMs = 400;
517
+
518
+ /**
519
+ Attempts to copy the given text to the system clipboard. Returns
520
+ true if it succeeds, else false.
521
+ */
522
+ dom.copyTextToClipboard = function(text){
523
+ if( window.clipboardData && window.clipboardData.setData ){
524
+ clipboardData.setData('Text',text);
525
+ return true;
526
+ }else{
527
+ const x = document.createElement("textarea");
528
+ x.style.position = 'fixed';
529
+ x.value = text;
530
+ document.body.appendChild(x);
531
+ x.select();
532
+ var rc;
533
+ try{
534
+ document.execCommand('copy');
535
+ rc = true;
536
+ }catch(err){
537
+ rc = false;
538
+ }finally{
539
+ document.body.removeChild(x);
540
+ }
541
+ return rc;
542
+ }
543
+ };
544
+
545
+ /**
546
+ Copies all properties from the 2nd argument (a plain object) into
547
+ the style member of the first argument (DOM element or a
548
+ forEach-capable list of elements). If the 2nd argument is falsy
549
+ or empty, this is a no-op.
550
+
551
+ Returns its first argument.
552
+ */
553
+ dom.copyStyle = function f(e, style){
554
+ if(e.forEach){
555
+ e.forEach((x)=>f(x, style));
556
+ return e;
557
+ }
558
+ if(style){
559
+ let k;
560
+ for(k in style){
561
+ if(style.hasOwnProperty(k)) e.style[k] = style[k];
562
+ }
470563
}
471564
return e;
472565
};
473566
474567
return F.dom = dom;
475568
476569
ADDED src/fossil.numbered-lines.js
477570
ADDED src/fossil.popupwidget.js
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -465,10 +465,103 @@
465 e = src.querySelector(x);
466 if(!e){
467 e = new Error("Cannot find DOM element: "+x);
468 console.error(e, src);
469 throw e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470 }
471 return e;
472 };
473
474 return F.dom = dom;
475
476 DDED src/fossil.numbered-lines.js
477 DDED src/fossil.popupwidget.js
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -465,10 +465,103 @@
465 e = src.querySelector(x);
466 if(!e){
467 e = new Error("Cannot find DOM element: "+x);
468 console.error(e, src);
469 throw e;
470 }
471 return e;
472 };
473
474 /**
475 "Blinks" the given element a single time for the given number of
476 milliseconds, defaulting (if the 2nd argument is falsy or not a
477 number) to flashOnce.defaultTimeMs. If a 3rd argument is passed
478 in, it must be a function, and it gets callback back at the end
479 of the asynchronous flashing processes.
480
481 This will only activate once per element during that timeframe -
482 further calls will become no-ops until the blink is
483 completed. This routine adds a dataset member to the element for
484 the duration of the blink, to allow it to block multiple blinks.
485
486 If passed 2 arguments and the 2nd is a function, it behaves as if
487 it were called as (arg1, undefined, arg2).
488
489 Returns e, noting that the flash itself is asynchronous and may
490 still be running, or not yet started, when this function returns.
491 */
492 dom.flashOnce = function f(e,howLongMs,afterFlashCallback){
493 if(e.dataset.isBlinking){
494 return;
495 }
496 if(2===arguments.length && 'function' ===typeof howLongMs){
497 afterFlashCallback = howLongMs;
498 howLongMs = f.defaultTimeMs;
499 }
500 if(!howLongMs || 'number'!==typeof howLongMs){
501 howLongMs = f.defaultTimeMs;
502 }
503 e.dataset.isBlinking = true;
504 const transition = e.style.transition;
505 e.style.transition = "opacity "+howLongMs+"ms ease-in-out";
506 const opacity = e.style.opacity;
507 e.style.opacity = 0;
508 setTimeout(function(){
509 e.style.transition = transition;
510 e.style.opacity = opacity;
511 delete e.dataset.isBlinking;
512 if(afterFlashCallback) afterFlashCallback();
513 }, howLongMs);
514 return e;
515 };
516 dom.flashOnce.defaultTimeMs = 400;
517
518 /**
519 Attempts to copy the given text to the system clipboard. Returns
520 true if it succeeds, else false.
521 */
522 dom.copyTextToClipboard = function(text){
523 if( window.clipboardData && window.clipboardData.setData ){
524 clipboardData.setData('Text',text);
525 return true;
526 }else{
527 const x = document.createElement("textarea");
528 x.style.position = 'fixed';
529 x.value = text;
530 document.body.appendChild(x);
531 x.select();
532 var rc;
533 try{
534 document.execCommand('copy');
535 rc = true;
536 }catch(err){
537 rc = false;
538 }finally{
539 document.body.removeChild(x);
540 }
541 return rc;
542 }
543 };
544
545 /**
546 Copies all properties from the 2nd argument (a plain object) into
547 the style member of the first argument (DOM element or a
548 forEach-capable list of elements). If the 2nd argument is falsy
549 or empty, this is a no-op.
550
551 Returns its first argument.
552 */
553 dom.copyStyle = function f(e, style){
554 if(e.forEach){
555 e.forEach((x)=>f(x, style));
556 return e;
557 }
558 if(style){
559 let k;
560 for(k in style){
561 if(style.hasOwnProperty(k)) e.style[k] = style[k];
562 }
563 }
564 return e;
565 };
566
567 return F.dom = dom;
568
569 DDED src/fossil.numbered-lines.js
570 DDED src/fossil.popupwidget.js
--- a/src/fossil.numbered-lines.js
+++ b/src/fossil.numbered-lines.js
@@ -0,0 +1,8 @@
1
+(function callee(arg){
2
+ /*
3
+ JSelse if(!arg){tion callee(arg){
4
+ /*
5
+ JS(function callee(arg){
6
+ /*
7
+ JSfossil',
8
+ (
--- a/src/fossil.numbered-lines.js
+++ b/src/fossil.numbered-lines.js
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
--- a/src/fossil.numbered-lines.js
+++ b/src/fossil.numbered-lines.js
@@ -0,0 +1,8 @@
1 (function callee(arg){
2 /*
3 JSelse if(!arg){tion callee(arg){
4 /*
5 JS(function callee(arg){
6 /*
7 JSfossil',
8 (
--- a/src/fossil.popupwidget.js
+++ b/src/fossil.popupwidget.js
@@ -0,0 +1,65 @@
1
+(function(F/*fossil object*/){
2
+ 30 */
3
+ installClickToHiden or basic user intera(function(F/*fossil object*/){
4
+ 3000sClass = cssClass;
5
+ unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
6
+ 3000sClass = cssClass;
7
+ unction(F/*fossil object*/){
8
+ /**
9
+ A very basic tooltip-like widget. It's intended to be popped up
10
+ to display basic information or basic user interaction
11
+ components, e.g. a cop or movopy-to-clipboard butt
12
+ if needed,l.dom
13
+ */
14
+ const D = F.dom
15
+ base DOMwidget using the
16
+). If theallback whic
17
+ h is called just before*/){
18
+ 30 */
19
+ instfunction(F/*fossil object*/){
20
+ 30 */
21
+ installClickToHiden or basic user intera(function(F/*fossil object*/){
22
+ 3000sClass = cssClass;
23
+ unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
24
+ 3000sClass = cssClass;
25
+ unction(F/*fossil object*/){
26
+ /**
27
+ A very basic tooltip-like widget. It's intended to be popped up
28
+ to display basic information or basic user interaction
29
+ components, e.g. a copy-to-clipboard button.
30
+
31
+ Requires: fossil.bootstrap, fossil.dom
32
+ */
33
+ conbjecthe popup when either
34
+ call this
35
+ show(falseshow(falseshow(falseconst hide Just be careful to mess only with the X coordinate
36
+ and the width. The browser will try to keep the widget
37
+ from being truncated off-screen on the right, shifting it
38
+ to the left if needed, and we cannot generically be sure
39
+ that an enforced fully on-screen size will actually fit
40
+ the current help textclickHandler){const rect1unction(F/*fossil object*(function(F/*fossil object*/){})(window.fossil);
41
+deleteleft');
42
+ deletea toas(function(F/*fossil o*fossil object*/){
43
+function(F/*fossil ct*/){
44
+ 30 */
45
+ installClickToHiden or basic user intera(fun*/
46
+ F.toast = function f(/*...*/){
47
+ f.toast = function ff(argsObject){
48
+ if(!ff.toaster) f ['fossil-tooltip', 'fossil-toast']
49
+ });
50
+ i@1hi,X: D.clearElement(ff.toaster.e);9@1SA,2w:var i = 0;
51
+ for( ; i < argsObject.length; ++i ){
52
+ D.append(ff.toaster.e, argsObject[i]);
53
+ };
54
+ ff.toaster.show(f.config.position.x, f.config.position.y);
55
+ Q@1mw,1m:()=>ff.toaster.hide(), f.config.displayTimeMs);
56
+ };
57
+ }
58
+ f.toast(arguments);
59
+ };
60
+ F.toast.config = {
61
+10@1pR,i:displayTimeMs: 2500
62
+ };
63
+
64
+})(window.fossil);
65
+ZfWzX;
--- a/src/fossil.popupwidget.js
+++ b/src/fossil.popupwidget.js
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/fossil.popupwidget.js
+++ b/src/fossil.popupwidget.js
@@ -0,0 +1,65 @@
1 (function(F/*fossil object*/){
2 30 */
3 installClickToHiden or basic user intera(function(F/*fossil object*/){
4 3000sClass = cssClass;
5 unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
6 3000sClass = cssClass;
7 unction(F/*fossil object*/){
8 /**
9 A very basic tooltip-like widget. It's intended to be popped up
10 to display basic information or basic user interaction
11 components, e.g. a cop or movopy-to-clipboard butt
12 if needed,l.dom
13 */
14 const D = F.dom
15 base DOMwidget using the
16 ). If theallback whic
17 h is called just before*/){
18 30 */
19 instfunction(F/*fossil object*/){
20 30 */
21 installClickToHiden or basic user intera(function(F/*fossil object*/){
22 3000sClass = cssClass;
23 unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
24 3000sClass = cssClass;
25 unction(F/*fossil object*/){
26 /**
27 A very basic tooltip-like widget. It's intended to be popped up
28 to display basic information or basic user interaction
29 components, e.g. a copy-to-clipboard button.
30
31 Requires: fossil.bootstrap, fossil.dom
32 */
33 conbjecthe popup when either
34 call this
35 show(falseshow(falseshow(falseconst hide Just be careful to mess only with the X coordinate
36 and the width. The browser will try to keep the widget
37 from being truncated off-screen on the right, shifting it
38 to the left if needed, and we cannot generically be sure
39 that an enforced fully on-screen size will actually fit
40 the current help textclickHandler){const rect1unction(F/*fossil object*(function(F/*fossil object*/){})(window.fossil);
41 deleteleft');
42 deletea toas(function(F/*fossil o*fossil object*/){
43 function(F/*fossil ct*/){
44 30 */
45 installClickToHiden or basic user intera(fun*/
46 F.toast = function f(/*...*/){
47 f.toast = function ff(argsObject){
48 if(!ff.toaster) f ['fossil-tooltip', 'fossil-toast']
49 });
50 i@1hi,X: D.clearElement(ff.toaster.e);9@1SA,2w:var i = 0;
51 for( ; i < argsObject.length; ++i ){
52 D.append(ff.toaster.e, argsObject[i]);
53 };
54 ff.toaster.show(f.config.position.x, f.config.position.y);
55 Q@1mw,1m:()=>ff.toaster.hide(), f.config.displayTimeMs);
56 };
57 }
58 f.toast(arguments);
59 };
60 F.toast.config = {
61 10@1pR,i:displayTimeMs: 2500
62 };
63
64 })(window.fossil);
65 ZfWzX;
+100 -44
--- src/info.c
+++ src/info.c
@@ -2011,27 +2011,37 @@
20112011
manifest_destroy(pManifest);
20122012
return rid;
20132013
}
20142014
20152015
/*
2016
-** The "z" argument is a string that contains the text of a source code
2017
-** file. This routine appends that text to the HTTP reply with line numbering.
2016
+** The "z" argument is a string that contains the text of a source
2017
+** code file and nZ is its length in bytes. This routine appends that
2018
+** text to the HTTP reply with line numbering.
2019
+**
2020
+** zName is the content's file name, if any (it may be NULL). If that
2021
+** name contains a '.' then the part after the final '.' is used as
2022
+** the X part of a "language-X" CSS class on the generated CODE block.
20182023
**
20192024
** zLn is the ?ln= parameter for the HTTP query. If there is an argument,
20202025
** then highlight that line number and scroll to it once the page loads.
20212026
** If there are two line numbers, highlight the range of lines.
20222027
** Multiple ranges can be highlighed by adding additional line numbers
20232028
** separated by a non-digit character (also not one of [-,.]).
20242029
*/
20252030
void output_text_with_line_numbers(
20262031
const char *z,
2032
+ int nZ,
2033
+ const char *zName,
20272034
const char *zLn
20282035
){
20292036
int iStart, iEnd; /* Start and end of region to highlight */
20302037
int n = 0; /* Current line number */
20312038
int i = 0; /* Loop index */
20322039
int iTop = 0; /* Scroll so that this line is on top of screen. */
2040
+ int nLine = 0; /* content line count */
2041
+ int nSpans = 0; /* number of distinct zLn spans */
2042
+ const char *zExt = file_extension(zName);
20332043
Stmt q;
20342044
20352045
iStart = iEnd = atoi(zLn);
20362046
db_multi_exec(
20372047
"CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)");
@@ -2047,56 +2057,101 @@
20472057
while( fossil_isdigit(zLn[i]) ) i++;
20482058
if( iEnd<iStart ) iEnd = iStart;
20492059
db_multi_exec(
20502060
"INSERT OR REPLACE INTO lnos VALUES(%d,%d)", iStart, iEnd
20512061
);
2062
+ ++nSpans;
20522063
iStart = iEnd = atoi(&zLn[i++]);
20532064
}while( zLn[i] && iStart && iEnd );
20542065
}
2055
- db_prepare(&q, "SELECT min(iStart), max(iEnd) FROM lnos");
2056
- if( db_step(&q)==SQLITE_ROW ){
2057
- iStart = db_column_int(&q, 0);
2058
- iEnd = db_column_int(&q, 1);
2059
- iTop = iStart - 15 + (iEnd-iStart)/4;
2060
- if( iTop>iStart - 2 ) iTop = iStart-2;
2061
- }
2062
- db_finalize(&q);
2063
- @ <pre>
2064
- while( z[0] ){
2065
- n++;
2066
- db_prepare(&q,
2067
- "SELECT min(iStart), max(iEnd) FROM lnos"
2068
- " WHERE iStart <= %d AND iEnd >= %d", n, n);
2069
- if( db_step(&q)==SQLITE_ROW ){
2070
- iStart = db_column_int(&q, 0);
2071
- iEnd = db_column_int(&q, 1);
2072
- }
2073
- db_finalize(&q);
2074
- for(i=0; z[i] && z[i]!='\n'; i++){}
2075
- if( n==iTop ) cgi_append_content("<span id=\"scrollToMe\">", -1);
2076
- if( n==iStart ){
2077
- cgi_append_content("<div class=\"selectedText\">",-1);
2078
- }
2079
- cgi_printf("%6d ", n);
2080
- if( i>0 ){
2081
- char *zHtml = htmlize(z, i);
2082
- cgi_append_content(zHtml, -1);
2083
- fossil_free(zHtml);
2084
- }
2085
- if( n==iTop ) cgi_append_content("</span>", -1);
2086
- if( n==iEnd ) cgi_append_content("</div>", -1);
2087
- else cgi_append_content("\n", 1);
2088
- z += i;
2089
- if( z[0]=='\n' ) z++;
2090
- }
2091
- if( n<iEnd ) cgi_printf("</div>");
2092
- @ </pre>
2066
+ /*cgi_printf("<!-- ln span count=%d -->", nSpans);*/
2067
+ cgi_append_content("<table class='numbered-lines'><tbody>"
2068
+ "<tr><td class='line-numbers'>", -1);
2069
+ iStart = iEnd = 0;
2070
+ count_lines(z, nZ, &nLine);
2071
+ for( n=1 ; n<=nLine; ++n ){
2072
+ const char * zAttr = "";
2073
+ const char * zId = "";
2074
+ if(nSpans>0 && iEnd==0){/*Grab the next range of zLn marking*/
2075
+ db_prepare(&q, "SELECT iStart, iEnd FROM lnos "
2076
+ "WHERE iStart >= %d ORDER BY iStart", n);
2077
+ if( db_step(&q)==SQLITE_ROW ){
2078
+ iStart = db_column_int(&q, 0);
2079
+ iEnd = db_column_int(&q, 1);
2080
+ if(!iTop){
2081
+ iTop = iStart - 15 + (iEnd-iStart)/4;
2082
+ if( iTop>iStart - 2 ) iTop = iStart-2;
2083
+ }
2084
+ }else{
2085
+ /* Note that overlapping multi-spans, e.g. 10-15+12-20,
2086
+ can cause us to miss a row. */
2087
+ iStart = iEnd = 0;
2088
+ }
2089
+ db_finalize(&q);
2090
+ --nSpans;
2091
+ /*cgi_printf("<!-- iStart=%d, iEnd=%d -->", iStart, iEnd);*/
2092
+ }
2093
+ if(n==iTop) {
2094
+ zId = " id='scrollToMe'";
2095
+ }
2096
+ if(n==iStart){/*Figure out which CSS class(es) this line needs...*/
2097
+ if(n==iEnd){
2098
+ zAttr = " class='selected-line start end'";
2099
+ iEnd = 0;
2100
+ }else{
2101
+ zAttr = " class='selected-line start'";
2102
+ }
2103
+ iStart = 0;
2104
+ }else if(n==iEnd){
2105
+ zAttr = " class='selected-line end'";
2106
+ iEnd = 0;
2107
+ }else if( n>iStart && n<iEnd ){
2108
+ zAttr = " class='selected-line'";
2109
+ }
2110
+ cgi_printf("<span%s%s>%6d</span>", zId, zAttr, n);
2111
+ }
2112
+ cgi_append_content("</td><td class='file-content'><pre>",-1);
2113
+ if(zExt && *zExt){
2114
+ cgi_printf("<code class='language-%h'>",zExt);
2115
+ }else{
2116
+ cgi_append_content("<code>", -1);
2117
+ }
2118
+ cgi_printf("%z", htmlize(z, nZ));
2119
+ CX("</code></pre></td></tr></tbody></table>\n");
20932120
if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
20942121
builtin_request_js("scroll.js");
20952122
}
2123
+ style_emit_fossil_js_apis(0, "dom", "copybutton", "popupwidget",
2124
+ "numbered-lines", 0);
20962125
}
20972126
2127
+/*
2128
+** COMMAND: test-line-numbers
2129
+**
2130
+** Usage: %fossil test-line-numbers FILE ?LN-SPEC?
2131
+**
2132
+*/
2133
+void cmd_test_line_numbers(void){
2134
+ Blob content = empty_blob;
2135
+ const char * zLn = "";
2136
+ const char * zFilename = 0;
2137
+
2138
+ if(g.argc < 3){
2139
+ usage("FILE");
2140
+ }else if(g.argc>3){
2141
+ zLn = g.argv[3];
2142
+ }
2143
+ db_find_and_open_repository(0,0);
2144
+ zFilename = g.argv[2];
2145
+ fossil_print("%s %s\n", zFilename, zLn);
2146
+
2147
+ blob_read_from_file(&content, zFilename, ExtFILE);
2148
+ output_text_with_line_numbers(blob_str(&content), blob_size(&content),
2149
+ zFilename, zLn);
2150
+ blob_reset(&content);
2151
+ fossil_print("%b\n", cgi_output_blob());
2152
+}
20982153
20992154
/*
21002155
** WEBPAGE: artifact
21012156
** WEBPAGE: file
21022157
** WEBPAGE: whatis
@@ -2387,25 +2442,26 @@
23872442
if( zLn==0 || atoi(zLn)==0 ){
23882443
style_submenu_checkbox("ln", "Line Numbers", 0, 0);
23892444
}
23902445
blob_to_utf8_no_bom(&content, 0);
23912446
zMime = mimetype_from_content(&content);
2392
- @ <blockquote>
2447
+ @ <blockquote class="file-content">
23932448
if( zMime==0 ){
23942449
const char *z, *zFileName, *zExt;
23952450
z = blob_str(&content);
23962451
zFileName = db_text(0,
23972452
"SELECT name FROM mlink, filename"
23982453
" WHERE filename.fnid=mlink.fnid"
23992454
" AND mlink.fid=%d",
24002455
rid);
2401
- zExt = zFileName ? strrchr(zFileName, '.') : 0;
2456
+ zExt = file_extension(zFileName);
24022457
if( zLn ){
2403
- output_text_with_line_numbers(z, zLn);
2458
+ output_text_with_line_numbers(z, blob_size(&content),
2459
+ zFileName, zLn);
24042460
}else if( zExt && zExt[1] ){
24052461
@ <pre>
2406
- @ <code class="language-%s(zExt+1)">%h(z)</code>
2462
+ @ <code class="language-%s(zExt)">%h(z)</code>
24072463
@ </pre>
24082464
}else{
24092465
@ <pre>
24102466
@ %h(z)
24112467
@ </pre>
24122468
--- src/info.c
+++ src/info.c
@@ -2011,27 +2011,37 @@
2011 manifest_destroy(pManifest);
2012 return rid;
2013 }
2014
2015 /*
2016 ** The "z" argument is a string that contains the text of a source code
2017 ** file. This routine appends that text to the HTTP reply with line numbering.
 
 
 
 
 
2018 **
2019 ** zLn is the ?ln= parameter for the HTTP query. If there is an argument,
2020 ** then highlight that line number and scroll to it once the page loads.
2021 ** If there are two line numbers, highlight the range of lines.
2022 ** Multiple ranges can be highlighed by adding additional line numbers
2023 ** separated by a non-digit character (also not one of [-,.]).
2024 */
2025 void output_text_with_line_numbers(
2026 const char *z,
 
 
2027 const char *zLn
2028 ){
2029 int iStart, iEnd; /* Start and end of region to highlight */
2030 int n = 0; /* Current line number */
2031 int i = 0; /* Loop index */
2032 int iTop = 0; /* Scroll so that this line is on top of screen. */
 
 
 
2033 Stmt q;
2034
2035 iStart = iEnd = atoi(zLn);
2036 db_multi_exec(
2037 "CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)");
@@ -2047,56 +2057,101 @@
2047 while( fossil_isdigit(zLn[i]) ) i++;
2048 if( iEnd<iStart ) iEnd = iStart;
2049 db_multi_exec(
2050 "INSERT OR REPLACE INTO lnos VALUES(%d,%d)", iStart, iEnd
2051 );
 
2052 iStart = iEnd = atoi(&zLn[i++]);
2053 }while( zLn[i] && iStart && iEnd );
2054 }
2055 db_prepare(&q, "SELECT min(iStart), max(iEnd) FROM lnos");
2056 if( db_step(&q)==SQLITE_ROW ){
2057 iStart = db_column_int(&q, 0);
2058 iEnd = db_column_int(&q, 1);
2059 iTop = iStart - 15 + (iEnd-iStart)/4;
2060 if( iTop>iStart - 2 ) iTop = iStart-2;
2061 }
2062 db_finalize(&q);
2063 @ <pre>
2064 while( z[0] ){
2065 n++;
2066 db_prepare(&q,
2067 "SELECT min(iStart), max(iEnd) FROM lnos"
2068 " WHERE iStart <= %d AND iEnd >= %d", n, n);
2069 if( db_step(&q)==SQLITE_ROW ){
2070 iStart = db_column_int(&q, 0);
2071 iEnd = db_column_int(&q, 1);
2072 }
2073 db_finalize(&q);
2074 for(i=0; z[i] && z[i]!='\n'; i++){}
2075 if( n==iTop ) cgi_append_content("<span id=\"scrollToMe\">", -1);
2076 if( n==iStart ){
2077 cgi_append_content("<div class=\"selectedText\">",-1);
2078 }
2079 cgi_printf("%6d ", n);
2080 if( i>0 ){
2081 char *zHtml = htmlize(z, i);
2082 cgi_append_content(zHtml, -1);
2083 fossil_free(zHtml);
2084 }
2085 if( n==iTop ) cgi_append_content("</span>", -1);
2086 if( n==iEnd ) cgi_append_content("</div>", -1);
2087 else cgi_append_content("\n", 1);
2088 z += i;
2089 if( z[0]=='\n' ) z++;
2090 }
2091 if( n<iEnd ) cgi_printf("</div>");
2092 @ </pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2093 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094 builtin_request_js("scroll.js");
2095 }
 
 
2096 }
2097
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2098
2099 /*
2100 ** WEBPAGE: artifact
2101 ** WEBPAGE: file
2102 ** WEBPAGE: whatis
@@ -2387,25 +2442,26 @@
2387 if( zLn==0 || atoi(zLn)==0 ){
2388 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2389 }
2390 blob_to_utf8_no_bom(&content, 0);
2391 zMime = mimetype_from_content(&content);
2392 @ <blockquote>
2393 if( zMime==0 ){
2394 const char *z, *zFileName, *zExt;
2395 z = blob_str(&content);
2396 zFileName = db_text(0,
2397 "SELECT name FROM mlink, filename"
2398 " WHERE filename.fnid=mlink.fnid"
2399 " AND mlink.fid=%d",
2400 rid);
2401 zExt = zFileName ? strrchr(zFileName, '.') : 0;
2402 if( zLn ){
2403 output_text_with_line_numbers(z, zLn);
 
2404 }else if( zExt && zExt[1] ){
2405 @ <pre>
2406 @ <code class="language-%s(zExt+1)">%h(z)</code>
2407 @ </pre>
2408 }else{
2409 @ <pre>
2410 @ %h(z)
2411 @ </pre>
2412
--- src/info.c
+++ src/info.c
@@ -2011,27 +2011,37 @@
2011 manifest_destroy(pManifest);
2012 return rid;
2013 }
2014
2015 /*
2016 ** The "z" argument is a string that contains the text of a source
2017 ** code file and nZ is its length in bytes. This routine appends that
2018 ** text to the HTTP reply with line numbering.
2019 **
2020 ** zName is the content's file name, if any (it may be NULL). If that
2021 ** name contains a '.' then the part after the final '.' is used as
2022 ** the X part of a "language-X" CSS class on the generated CODE block.
2023 **
2024 ** zLn is the ?ln= parameter for the HTTP query. If there is an argument,
2025 ** then highlight that line number and scroll to it once the page loads.
2026 ** If there are two line numbers, highlight the range of lines.
2027 ** Multiple ranges can be highlighed by adding additional line numbers
2028 ** separated by a non-digit character (also not one of [-,.]).
2029 */
2030 void output_text_with_line_numbers(
2031 const char *z,
2032 int nZ,
2033 const char *zName,
2034 const char *zLn
2035 ){
2036 int iStart, iEnd; /* Start and end of region to highlight */
2037 int n = 0; /* Current line number */
2038 int i = 0; /* Loop index */
2039 int iTop = 0; /* Scroll so that this line is on top of screen. */
2040 int nLine = 0; /* content line count */
2041 int nSpans = 0; /* number of distinct zLn spans */
2042 const char *zExt = file_extension(zName);
2043 Stmt q;
2044
2045 iStart = iEnd = atoi(zLn);
2046 db_multi_exec(
2047 "CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)");
@@ -2047,56 +2057,101 @@
2057 while( fossil_isdigit(zLn[i]) ) i++;
2058 if( iEnd<iStart ) iEnd = iStart;
2059 db_multi_exec(
2060 "INSERT OR REPLACE INTO lnos VALUES(%d,%d)", iStart, iEnd
2061 );
2062 ++nSpans;
2063 iStart = iEnd = atoi(&zLn[i++]);
2064 }while( zLn[i] && iStart && iEnd );
2065 }
2066 /*cgi_printf("<!-- ln span count=%d -->", nSpans);*/
2067 cgi_append_content("<table class='numbered-lines'><tbody>"
2068 "<tr><td class='line-numbers'>", -1);
2069 iStart = iEnd = 0;
2070 count_lines(z, nZ, &nLine);
2071 for( n=1 ; n<=nLine; ++n ){
2072 const char * zAttr = "";
2073 const char * zId = "";
2074 if(nSpans>0 && iEnd==0){/*Grab the next range of zLn marking*/
2075 db_prepare(&q, "SELECT iStart, iEnd FROM lnos "
2076 "WHERE iStart >= %d ORDER BY iStart", n);
2077 if( db_step(&q)==SQLITE_ROW ){
2078 iStart = db_column_int(&q, 0);
2079 iEnd = db_column_int(&q, 1);
2080 if(!iTop){
2081 iTop = iStart - 15 + (iEnd-iStart)/4;
2082 if( iTop>iStart - 2 ) iTop = iStart-2;
2083 }
2084 }else{
2085 /* Note that overlapping multi-spans, e.g. 10-15+12-20,
2086 can cause us to miss a row. */
2087 iStart = iEnd = 0;
2088 }
2089 db_finalize(&q);
2090 --nSpans;
2091 /*cgi_printf("<!-- iStart=%d, iEnd=%d -->", iStart, iEnd);*/
2092 }
2093 if(n==iTop) {
2094 zId = " id='scrollToMe'";
2095 }
2096 if(n==iStart){/*Figure out which CSS class(es) this line needs...*/
2097 if(n==iEnd){
2098 zAttr = " class='selected-line start end'";
2099 iEnd = 0;
2100 }else{
2101 zAttr = " class='selected-line start'";
2102 }
2103 iStart = 0;
2104 }else if(n==iEnd){
2105 zAttr = " class='selected-line end'";
2106 iEnd = 0;
2107 }else if( n>iStart && n<iEnd ){
2108 zAttr = " class='selected-line'";
2109 }
2110 cgi_printf("<span%s%s>%6d</span>", zId, zAttr, n);
2111 }
2112 cgi_append_content("</td><td class='file-content'><pre>",-1);
2113 if(zExt && *zExt){
2114 cgi_printf("<code class='language-%h'>",zExt);
2115 }else{
2116 cgi_append_content("<code>", -1);
2117 }
2118 cgi_printf("%z", htmlize(z, nZ));
2119 CX("</code></pre></td></tr></tbody></table>\n");
2120 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2121 builtin_request_js("scroll.js");
2122 }
2123 style_emit_fossil_js_apis(0, "dom", "copybutton", "popupwidget",
2124 "numbered-lines", 0);
2125 }
2126
2127 /*
2128 ** COMMAND: test-line-numbers
2129 **
2130 ** Usage: %fossil test-line-numbers FILE ?LN-SPEC?
2131 **
2132 */
2133 void cmd_test_line_numbers(void){
2134 Blob content = empty_blob;
2135 const char * zLn = "";
2136 const char * zFilename = 0;
2137
2138 if(g.argc < 3){
2139 usage("FILE");
2140 }else if(g.argc>3){
2141 zLn = g.argv[3];
2142 }
2143 db_find_and_open_repository(0,0);
2144 zFilename = g.argv[2];
2145 fossil_print("%s %s\n", zFilename, zLn);
2146
2147 blob_read_from_file(&content, zFilename, ExtFILE);
2148 output_text_with_line_numbers(blob_str(&content), blob_size(&content),
2149 zFilename, zLn);
2150 blob_reset(&content);
2151 fossil_print("%b\n", cgi_output_blob());
2152 }
2153
2154 /*
2155 ** WEBPAGE: artifact
2156 ** WEBPAGE: file
2157 ** WEBPAGE: whatis
@@ -2387,25 +2442,26 @@
2442 if( zLn==0 || atoi(zLn)==0 ){
2443 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2444 }
2445 blob_to_utf8_no_bom(&content, 0);
2446 zMime = mimetype_from_content(&content);
2447 @ <blockquote class="file-content">
2448 if( zMime==0 ){
2449 const char *z, *zFileName, *zExt;
2450 z = blob_str(&content);
2451 zFileName = db_text(0,
2452 "SELECT name FROM mlink, filename"
2453 " WHERE filename.fnid=mlink.fnid"
2454 " AND mlink.fid=%d",
2455 rid);
2456 zExt = file_extension(zFileName);
2457 if( zLn ){
2458 output_text_with_line_numbers(z, blob_size(&content),
2459 zFileName, zLn);
2460 }else if( zExt && zExt[1] ){
2461 @ <pre>
2462 @ <code class="language-%s(zExt)">%h(z)</code>
2463 @ </pre>
2464 }else{
2465 @ <pre>
2466 @ %h(z)
2467 @ </pre>
2468
--- src/main.mk
+++ src/main.mk
@@ -223,15 +223,18 @@
223223
$(SRCDIR)/default.css \
224224
$(SRCDIR)/diff.tcl \
225225
$(SRCDIR)/forum.js \
226226
$(SRCDIR)/fossil.bootstrap.js \
227227
$(SRCDIR)/fossil.confirmer.js \
228
+ $(SRCDIR)/fossil.copybutton.js \
228229
$(SRCDIR)/fossil.dom.js \
229230
$(SRCDIR)/fossil.fetch.js \
231
+ $(SRCDIR)/fossil.numbered-lines.js \
230232
$(SRCDIR)/fossil.page.fileedit.js \
231233
$(SRCDIR)/fossil.page.forumpost.js \
232234
$(SRCDIR)/fossil.page.wikiedit.js \
235
+ $(SRCDIR)/fossil.popupwidget.js \
233236
$(SRCDIR)/fossil.storage.js \
234237
$(SRCDIR)/fossil.tabs.js \
235238
$(SRCDIR)/graph.js \
236239
$(SRCDIR)/href.js \
237240
$(SRCDIR)/login.js \
238241
--- src/main.mk
+++ src/main.mk
@@ -223,15 +223,18 @@
223 $(SRCDIR)/default.css \
224 $(SRCDIR)/diff.tcl \
225 $(SRCDIR)/forum.js \
226 $(SRCDIR)/fossil.bootstrap.js \
227 $(SRCDIR)/fossil.confirmer.js \
 
228 $(SRCDIR)/fossil.dom.js \
229 $(SRCDIR)/fossil.fetch.js \
 
230 $(SRCDIR)/fossil.page.fileedit.js \
231 $(SRCDIR)/fossil.page.forumpost.js \
232 $(SRCDIR)/fossil.page.wikiedit.js \
 
233 $(SRCDIR)/fossil.storage.js \
234 $(SRCDIR)/fossil.tabs.js \
235 $(SRCDIR)/graph.js \
236 $(SRCDIR)/href.js \
237 $(SRCDIR)/login.js \
238
--- src/main.mk
+++ src/main.mk
@@ -223,15 +223,18 @@
223 $(SRCDIR)/default.css \
224 $(SRCDIR)/diff.tcl \
225 $(SRCDIR)/forum.js \
226 $(SRCDIR)/fossil.bootstrap.js \
227 $(SRCDIR)/fossil.confirmer.js \
228 $(SRCDIR)/fossil.copybutton.js \
229 $(SRCDIR)/fossil.dom.js \
230 $(SRCDIR)/fossil.fetch.js \
231 $(SRCDIR)/fossil.numbered-lines.js \
232 $(SRCDIR)/fossil.page.fileedit.js \
233 $(SRCDIR)/fossil.page.forumpost.js \
234 $(SRCDIR)/fossil.page.wikiedit.js \
235 $(SRCDIR)/fossil.popupwidget.js \
236 $(SRCDIR)/fossil.storage.js \
237 $(SRCDIR)/fossil.tabs.js \
238 $(SRCDIR)/graph.js \
239 $(SRCDIR)/href.js \
240 $(SRCDIR)/login.js \
241
+1 -1
--- src/scroll.js
+++ src/scroll.js
@@ -1,2 +1,2 @@
11
/* Cause the page to scroll so that the #scrollToMe is visible */
2
-document.getElementById('scrollToMe').scrollIntoView(true);
2
+(document.getElementById('scrollToMe')||document.body).scrollIntoView(true);
33
--- src/scroll.js
+++ src/scroll.js
@@ -1,2 +1,2 @@
1 /* Cause the page to scroll so that the #scrollToMe is visible */
2 document.getElementById('scrollToMe').scrollIntoView(true);
3
--- src/scroll.js
+++ src/scroll.js
@@ -1,2 +1,2 @@
1 /* Cause the page to scroll so that the #scrollToMe is visible */
2 (document.getElementById('scrollToMe')||document.body).scrollIntoView(true);
3
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,15 +635,18 @@
635635
$(SRCDIR)/default.css \
636636
$(SRCDIR)/diff.tcl \
637637
$(SRCDIR)/forum.js \
638638
$(SRCDIR)/fossil.bootstrap.js \
639639
$(SRCDIR)/fossil.confirmer.js \
640
+ $(SRCDIR)/fossil.copybutton.js \
640641
$(SRCDIR)/fossil.dom.js \
641642
$(SRCDIR)/fossil.fetch.js \
643
+ $(SRCDIR)/fossil.numbered-lines.js \
642644
$(SRCDIR)/fossil.page.fileedit.js \
643645
$(SRCDIR)/fossil.page.forumpost.js \
644646
$(SRCDIR)/fossil.page.wikiedit.js \
647
+ $(SRCDIR)/fossil.popupwidget.js \
645648
$(SRCDIR)/fossil.storage.js \
646649
$(SRCDIR)/fossil.tabs.js \
647650
$(SRCDIR)/graph.js \
648651
$(SRCDIR)/href.js \
649652
$(SRCDIR)/login.js \
650653
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,15 +635,18 @@
635 $(SRCDIR)/default.css \
636 $(SRCDIR)/diff.tcl \
637 $(SRCDIR)/forum.js \
638 $(SRCDIR)/fossil.bootstrap.js \
639 $(SRCDIR)/fossil.confirmer.js \
 
640 $(SRCDIR)/fossil.dom.js \
641 $(SRCDIR)/fossil.fetch.js \
 
642 $(SRCDIR)/fossil.page.fileedit.js \
643 $(SRCDIR)/fossil.page.forumpost.js \
644 $(SRCDIR)/fossil.page.wikiedit.js \
 
645 $(SRCDIR)/fossil.storage.js \
646 $(SRCDIR)/fossil.tabs.js \
647 $(SRCDIR)/graph.js \
648 $(SRCDIR)/href.js \
649 $(SRCDIR)/login.js \
650
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,15 +635,18 @@
635 $(SRCDIR)/default.css \
636 $(SRCDIR)/diff.tcl \
637 $(SRCDIR)/forum.js \
638 $(SRCDIR)/fossil.bootstrap.js \
639 $(SRCDIR)/fossil.confirmer.js \
640 $(SRCDIR)/fossil.copybutton.js \
641 $(SRCDIR)/fossil.dom.js \
642 $(SRCDIR)/fossil.fetch.js \
643 $(SRCDIR)/fossil.numbered-lines.js \
644 $(SRCDIR)/fossil.page.fileedit.js \
645 $(SRCDIR)/fossil.page.forumpost.js \
646 $(SRCDIR)/fossil.page.wikiedit.js \
647 $(SRCDIR)/fossil.popupwidget.js \
648 $(SRCDIR)/fossil.storage.js \
649 $(SRCDIR)/fossil.tabs.js \
650 $(SRCDIR)/graph.js \
651 $(SRCDIR)/href.js \
652 $(SRCDIR)/login.js \
653
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,15 +556,18 @@
556556
"$(SRCDIR)\default.css" \
557557
"$(SRCDIR)\diff.tcl" \
558558
"$(SRCDIR)\forum.js" \
559559
"$(SRCDIR)\fossil.bootstrap.js" \
560560
"$(SRCDIR)\fossil.confirmer.js" \
561
+ "$(SRCDIR)\fossil.copybutton.js" \
561562
"$(SRCDIR)\fossil.dom.js" \
562563
"$(SRCDIR)\fossil.fetch.js" \
564
+ "$(SRCDIR)\fossil.numbered-lines.js" \
563565
"$(SRCDIR)\fossil.page.fileedit.js" \
564566
"$(SRCDIR)\fossil.page.forumpost.js" \
565567
"$(SRCDIR)\fossil.page.wikiedit.js" \
568
+ "$(SRCDIR)\fossil.popupwidget.js" \
566569
"$(SRCDIR)\fossil.storage.js" \
567570
"$(SRCDIR)\fossil.tabs.js" \
568571
"$(SRCDIR)\graph.js" \
569572
"$(SRCDIR)\href.js" \
570573
"$(SRCDIR)\login.js" \
@@ -1150,15 +1153,18 @@
11501153
echo "$(SRCDIR)\default.css" >> $@
11511154
echo "$(SRCDIR)\diff.tcl" >> $@
11521155
echo "$(SRCDIR)\forum.js" >> $@
11531156
echo "$(SRCDIR)\fossil.bootstrap.js" >> $@
11541157
echo "$(SRCDIR)\fossil.confirmer.js" >> $@
1158
+ echo "$(SRCDIR)\fossil.copybutton.js" >> $@
11551159
echo "$(SRCDIR)\fossil.dom.js" >> $@
11561160
echo "$(SRCDIR)\fossil.fetch.js" >> $@
1161
+ echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@
11571162
echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
11581163
echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
11591164
echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
1165
+ echo "$(SRCDIR)\fossil.popupwidget.js" >> $@
11601166
echo "$(SRCDIR)\fossil.storage.js" >> $@
11611167
echo "$(SRCDIR)\fossil.tabs.js" >> $@
11621168
echo "$(SRCDIR)\graph.js" >> $@
11631169
echo "$(SRCDIR)\href.js" >> $@
11641170
echo "$(SRCDIR)\login.js" >> $@
11651171
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,15 +556,18 @@
556 "$(SRCDIR)\default.css" \
557 "$(SRCDIR)\diff.tcl" \
558 "$(SRCDIR)\forum.js" \
559 "$(SRCDIR)\fossil.bootstrap.js" \
560 "$(SRCDIR)\fossil.confirmer.js" \
 
561 "$(SRCDIR)\fossil.dom.js" \
562 "$(SRCDIR)\fossil.fetch.js" \
 
563 "$(SRCDIR)\fossil.page.fileedit.js" \
564 "$(SRCDIR)\fossil.page.forumpost.js" \
565 "$(SRCDIR)\fossil.page.wikiedit.js" \
 
566 "$(SRCDIR)\fossil.storage.js" \
567 "$(SRCDIR)\fossil.tabs.js" \
568 "$(SRCDIR)\graph.js" \
569 "$(SRCDIR)\href.js" \
570 "$(SRCDIR)\login.js" \
@@ -1150,15 +1153,18 @@
1150 echo "$(SRCDIR)\default.css" >> $@
1151 echo "$(SRCDIR)\diff.tcl" >> $@
1152 echo "$(SRCDIR)\forum.js" >> $@
1153 echo "$(SRCDIR)\fossil.bootstrap.js" >> $@
1154 echo "$(SRCDIR)\fossil.confirmer.js" >> $@
 
1155 echo "$(SRCDIR)\fossil.dom.js" >> $@
1156 echo "$(SRCDIR)\fossil.fetch.js" >> $@
 
1157 echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
1158 echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
1159 echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
 
1160 echo "$(SRCDIR)\fossil.storage.js" >> $@
1161 echo "$(SRCDIR)\fossil.tabs.js" >> $@
1162 echo "$(SRCDIR)\graph.js" >> $@
1163 echo "$(SRCDIR)\href.js" >> $@
1164 echo "$(SRCDIR)\login.js" >> $@
1165
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,15 +556,18 @@
556 "$(SRCDIR)\default.css" \
557 "$(SRCDIR)\diff.tcl" \
558 "$(SRCDIR)\forum.js" \
559 "$(SRCDIR)\fossil.bootstrap.js" \
560 "$(SRCDIR)\fossil.confirmer.js" \
561 "$(SRCDIR)\fossil.copybutton.js" \
562 "$(SRCDIR)\fossil.dom.js" \
563 "$(SRCDIR)\fossil.fetch.js" \
564 "$(SRCDIR)\fossil.numbered-lines.js" \
565 "$(SRCDIR)\fossil.page.fileedit.js" \
566 "$(SRCDIR)\fossil.page.forumpost.js" \
567 "$(SRCDIR)\fossil.page.wikiedit.js" \
568 "$(SRCDIR)\fossil.popupwidget.js" \
569 "$(SRCDIR)\fossil.storage.js" \
570 "$(SRCDIR)\fossil.tabs.js" \
571 "$(SRCDIR)\graph.js" \
572 "$(SRCDIR)\href.js" \
573 "$(SRCDIR)\login.js" \
@@ -1150,15 +1153,18 @@
1153 echo "$(SRCDIR)\default.css" >> $@
1154 echo "$(SRCDIR)\diff.tcl" >> $@
1155 echo "$(SRCDIR)\forum.js" >> $@
1156 echo "$(SRCDIR)\fossil.bootstrap.js" >> $@
1157 echo "$(SRCDIR)\fossil.confirmer.js" >> $@
1158 echo "$(SRCDIR)\fossil.copybutton.js" >> $@
1159 echo "$(SRCDIR)\fossil.dom.js" >> $@
1160 echo "$(SRCDIR)\fossil.fetch.js" >> $@
1161 echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@
1162 echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
1163 echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
1164 echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
1165 echo "$(SRCDIR)\fossil.popupwidget.js" >> $@
1166 echo "$(SRCDIR)\fossil.storage.js" >> $@
1167 echo "$(SRCDIR)\fossil.tabs.js" >> $@
1168 echo "$(SRCDIR)\graph.js" >> $@
1169 echo "$(SRCDIR)\href.js" >> $@
1170 echo "$(SRCDIR)\login.js" >> $@
1171

Keyboard Shortcuts

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