Fossil SCM

Implemented dynamic mouse selection of source lines and clipboard tooltip to copy the line range URL.

stephan 2020-08-15 07:41 line-number-selection
Commit 3942eb600aedd12aafb4de57710160c47dedc115123c031a4164375b18bba934
+18 -2
--- src/default.css
+++ src/default.css
@@ -1171,14 +1171,14 @@
11711171
line-height: inherit;
11721172
font-size: inherit;
11731173
font-family: inherit;
11741174
cursor: pointer;
11751175
white-space: pre;
1176
+ margin-right: 2px/*keep selection from nudging the right column */;
11761177
}
11771178
table.numbered-lines td.line-numbers > span:hover {
1178
- background-color: #777;
1179
- opacity: 0.25;
1179
+ background-color: rgba(112, 112, 112, 0.25);
11801180
}
11811181
table.numbered-lines td.file-content {
11821182
padding-left: 1em;
11831183
}
11841184
table.numbered-lines td.file-content > pre {
@@ -1215,6 +1215,22 @@
12151215
margin-top: -1px/*restore alignment*/;
12161216
}
12171217
table.numbered-lines td.line-numbers span.selected-line.end {
12181218
border-bottom-width: 1px;
12191219
margin-top: -1px/*restore alignment*/;
1220
+}
1221
+table.numbered-lines td.line-numbers span.selected-line.start.end {
1222
+ margin-top: -2px/*restore alignment*/;
1223
+}
1224
+
1225
+.fossil-tooltip {
1226
+ text-align: center;
1227
+ padding: 0.2em 1em;
1228
+ border: 1px solid black;
1229
+ border-radius: 0.25em;
1230
+ position: absolute;
1231
+ display: inline-block;
1232
+ z-index: 100;
1233
+ box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1234
+ background-color: inherit;
1235
+ font-size: 80%;
12201236
}
12211237
--- src/default.css
+++ src/default.css
@@ -1171,14 +1171,14 @@
1171 line-height: inherit;
1172 font-size: inherit;
1173 font-family: inherit;
1174 cursor: pointer;
1175 white-space: pre;
 
1176 }
1177 table.numbered-lines td.line-numbers > span:hover {
1178 background-color: #777;
1179 opacity: 0.25;
1180 }
1181 table.numbered-lines td.file-content {
1182 padding-left: 1em;
1183 }
1184 table.numbered-lines td.file-content > pre {
@@ -1215,6 +1215,22 @@
1215 margin-top: -1px/*restore alignment*/;
1216 }
1217 table.numbered-lines td.line-numbers span.selected-line.end {
1218 border-bottom-width: 1px;
1219 margin-top: -1px/*restore alignment*/;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1220 }
1221
--- src/default.css
+++ src/default.css
@@ -1171,14 +1171,14 @@
1171 line-height: inherit;
1172 font-size: inherit;
1173 font-family: inherit;
1174 cursor: pointer;
1175 white-space: pre;
1176 margin-right: 2px/*keep selection from nudging the right column */;
1177 }
1178 table.numbered-lines td.line-numbers > span:hover {
1179 background-color: rgba(112, 112, 112, 0.25);
 
1180 }
1181 table.numbered-lines td.file-content {
1182 padding-left: 1em;
1183 }
1184 table.numbered-lines td.file-content > pre {
@@ -1215,6 +1215,22 @@
1215 margin-top: -1px/*restore alignment*/;
1216 }
1217 table.numbered-lines td.line-numbers span.selected-line.end {
1218 border-bottom-width: 1px;
1219 margin-top: -1px/*restore alignment*/;
1220 }
1221 table.numbered-lines td.line-numbers span.selected-line.start.end {
1222 margin-top: -2px/*restore alignment*/;
1223 }
1224
1225 .fossil-tooltip {
1226 text-align: center;
1227 padding: 0.2em 1em;
1228 border: 1px solid black;
1229 border-radius: 0.25em;
1230 position: absolute;
1231 display: inline-block;
1232 z-index: 100;
1233 box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75);
1234 background-color: inherit;
1235 font-size: 80%;
1236 }
1237
--- src/fossil.numbered-lines.js
+++ src/fossil.numbered-lines.js
@@ -1,9 +1,13 @@
11
(function callee(arg){
2
- /* JS counterpart of info.c:output_text_with_line_numbers()
3
- which ties an event handler to the line numbers to allow
4
- selection of individual lines or ranges. */
2
+ /*
3
+ JS counterpart of info.c:output_text_with_line_numbers()
4
+ which ties an event handler to the line numbers to allow
5
+ selection of individual lines or ranges.
6
+
7
+ Requires: fossil.bootstrap, fossil.dom, fossil.tooltip
8
+ */
59
var tbl = arg || document.querySelectorAll('table.numbered-lines');
610
if(!tbl) return /* no matching elements */;
711
else if(!arg){
812
if(tbl.length>1){ /* multiple query results: recurse */
913
tbl.forEach( (t)=>callee(t) );
@@ -10,47 +14,105 @@
1014
return;
1115
}else{/* single query result */
1216
tbl = tbl[0];
1317
}
1418
}
15
- const tdLn = tbl.querySelector('td'),
16
- urlArgs = (window.location.search||'').replace(/&?\bln=[^&]*/,'');
17
- console.debug("urlArgs =",urlArgs);
19
+ const F = window.fossil, D = F.dom;
20
+ const tdLn = tbl.querySelector('td.line-numbers');
21
+ const lineState = {
22
+ urlArgs: (window.location.search||'').replace(/&?\bln=[^&]*/,''),
23
+ start: 0, end: 0
24
+ };
25
+
26
+ const lineTip = new fossil.TooltipWidget({
27
+ refresh: function(){
28
+ const link = this.state.link;
29
+ D.clearElement(link);
30
+ if(lineState.start){
31
+ const ls = [lineState.start];
32
+ if(lineState.end) ls.push(lineState.end);
33
+ link.dataset.url = (
34
+ window.location.toString().split('?')[0]
35
+ + lineState.urlArgs + '&ln='+ls.join('-')
36
+ );
37
+ D.append(
38
+ D.clearElement(link),
39
+ ' ',
40
+ (ls.length===1 ? 'line ' : 'lines ')+ls.join('-')
41
+ );
42
+ }else{
43
+ D.append(link, "No lines selected.");
44
+ }
45
+ },
46
+ adjustX: function(x){
47
+ return x + 20;
48
+ },
49
+ adjustY: function(y){
50
+ return y - this.e.clientHeight/2;
51
+ },
52
+ init: function(){
53
+ const e = this.e;
54
+ const btnCopy = D.addClass(D.span(), 'copy-button');
55
+ const link = D.attr(D.span(), 'id', 'fossil-ln-link');
56
+ this.state = {link};
57
+ F.copyButton(btnCopy,{
58
+ copyFromElement: link,
59
+ extractText: ()=>link.dataset.url
60
+ });
61
+ D.append(this.e, btnCopy, link)
62
+ }
63
+ });
64
+
65
+ tbl.addEventListener('click', function f(ev){
66
+ lineTip.show(false);
67
+ }, false);
68
+
1869
tdLn.addEventListener('click', function f(ev){
19
- if(!f.selectedRange){
20
- f.selectedRange = [0,0];
70
+ if('SPAN'!==ev.target.tagName) return;
71
+ else if('number' !== typeof f.mode){
2172
f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
2273
}
23
- if('SPAN'===ev.target.tagName){
24
- const rng = f.selectedRange;
25
- const ln = +ev.target.innerText;
26
- if(2===f.mode){/*reset selection*/
27
- f.mode = 0;
28
- //rng[0] = rng[1] = 0;
29
- }
30
- if(0===f.mode){
31
- rng[1] = 0;
32
- rng[0] = ln;
33
- //console.debug("Selected line #"+ln);
34
- history.pushState(undefined,'',urlArgs+'&ln='+ln);
35
- f.mode = 1;
36
- }else if(1===f.mode){
37
- if(ln === rng[0]){/*unselect line*/
38
- //console.debug("Unselected line #"+ln);
39
- history.pushState(undefined,'',urlArgs+'&ln=on');
40
- rng[0] = 0;
41
- f.mode = 0;
42
- }else{
43
- if(ln<rng[0]){
44
- rng[1] = rng[0];
45
- rng[0] = ln;
46
- }else{
47
- rng[1] = ln;
48
- }
49
- //console.debug("Selected range: ",rng);
50
- history.pushState(undefined,'',urlArgs+'&ln='+rng.join('-'));
51
- f.mode = 2;
52
- }
53
- }
74
+ ev.stopPropagation();
75
+ const ln = +ev.target.innerText;
76
+ if(2===f.mode){/*reset selection*/
77
+ f.mode = 0;
78
+ }
79
+ if(0===f.mode){
80
+ lineState.end = 0;
81
+ lineState.start = ln;
82
+ f.mode = 1;
83
+ }else if(1===f.mode){
84
+ if(ln === lineState.start){/*unselect line*/
85
+ //console.debug("Unselected line #"+ln);
86
+ lineState.start = 0;
87
+ f.mode = 0;
88
+ }else{
89
+ if(ln<lineState.start){
90
+ lineState.end = lineState.start;
91
+ lineState.start = ln;
92
+ }else{
93
+ lineState.end = ln;
94
+ }
95
+ //console.debug("Selected range: ",rng);
96
+ f.mode = 2;
97
+ }
98
+ }
99
+ tdLn.querySelectorAll('span.selected-line').forEach(
100
+ (e)=>D.removeClass(e, 'selected-line','start','end'));
101
+ if(f.mode>0){
102
+ lineTip.show(ev.clientX, ev.clientY);
103
+ const spans = tdLn.querySelectorAll('span');
104
+ if(spans.length>=lineState.start){
105
+ let i = lineState.start, end = lineState.end || lineState.start, span = spans[i-1];
106
+ for( ; i<=end && span; span = spans[i++] ){
107
+ span.classList.add('selected-line');
108
+ if(i===lineState.start) span.classList.add('start');
109
+ if(i===end) span.classList.add('end');
110
+ }
111
+ }
112
+ lineTip.refresh();
113
+ }else{
114
+ lineTip.show(false);
54115
}
55116
}, false);
117
+
56118
})();
57119
58120
ADDED src/fossil.tooltip.js
--- src/fossil.numbered-lines.js
+++ src/fossil.numbered-lines.js
@@ -1,9 +1,13 @@
1 (function callee(arg){
2 /* JS counterpart of info.c:output_text_with_line_numbers()
3 which ties an event handler to the line numbers to allow
4 selection of individual lines or ranges. */
 
 
 
 
5 var tbl = arg || document.querySelectorAll('table.numbered-lines');
6 if(!tbl) return /* no matching elements */;
7 else if(!arg){
8 if(tbl.length>1){ /* multiple query results: recurse */
9 tbl.forEach( (t)=>callee(t) );
@@ -10,47 +14,105 @@
10 return;
11 }else{/* single query result */
12 tbl = tbl[0];
13 }
14 }
15 const tdLn = tbl.querySelector('td'),
16 urlArgs = (window.location.search||'').replace(/&?\bln=[^&]*/,'');
17 console.debug("urlArgs =",urlArgs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18 tdLn.addEventListener('click', function f(ev){
19 if(!f.selectedRange){
20 f.selectedRange = [0,0];
21 f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
22 }
23 if('SPAN'===ev.target.tagName){
24 const rng = f.selectedRange;
25 const ln = +ev.target.innerText;
26 if(2===f.mode){/*reset selection*/
27 f.mode = 0;
28 //rng[0] = rng[1] = 0;
29 }
30 if(0===f.mode){
31 rng[1] = 0;
32 rng[0] = ln;
33 //console.debug("Selected line #"+ln);
34 history.pushState(undefined,'',urlArgs+'&ln='+ln);
35 f.mode = 1;
36 }else if(1===f.mode){
37 if(ln === rng[0]){/*unselect line*/
38 //console.debug("Unselected line #"+ln);
39 history.pushState(undefined,'',urlArgs+'&ln=on');
40 rng[0] = 0;
41 f.mode = 0;
42 }else{
43 if(ln<rng[0]){
44 rng[1] = rng[0];
45 rng[0] = ln;
46 }else{
47 rng[1] = ln;
48 }
49 //console.debug("Selected range: ",rng);
50 history.pushState(undefined,'',urlArgs+'&ln='+rng.join('-'));
51 f.mode = 2;
52 }
53 }
 
 
 
 
 
 
 
 
 
 
54 }
55 }, false);
 
56 })();
57
58 DDED src/fossil.tooltip.js
--- src/fossil.numbered-lines.js
+++ src/fossil.numbered-lines.js
@@ -1,9 +1,13 @@
1 (function callee(arg){
2 /*
3 JS counterpart of info.c:output_text_with_line_numbers()
4 which ties an event handler to the line numbers to allow
5 selection of individual lines or ranges.
6
7 Requires: fossil.bootstrap, fossil.dom, fossil.tooltip
8 */
9 var tbl = arg || document.querySelectorAll('table.numbered-lines');
10 if(!tbl) return /* no matching elements */;
11 else if(!arg){
12 if(tbl.length>1){ /* multiple query results: recurse */
13 tbl.forEach( (t)=>callee(t) );
@@ -10,47 +14,105 @@
14 return;
15 }else{/* single query result */
16 tbl = tbl[0];
17 }
18 }
19 const F = window.fossil, D = F.dom;
20 const tdLn = tbl.querySelector('td.line-numbers');
21 const lineState = {
22 urlArgs: (window.location.search||'').replace(/&?\bln=[^&]*/,''),
23 start: 0, end: 0
24 };
25
26 const lineTip = new fossil.TooltipWidget({
27 refresh: function(){
28 const link = this.state.link;
29 D.clearElement(link);
30 if(lineState.start){
31 const ls = [lineState.start];
32 if(lineState.end) ls.push(lineState.end);
33 link.dataset.url = (
34 window.location.toString().split('?')[0]
35 + lineState.urlArgs + '&ln='+ls.join('-')
36 );
37 D.append(
38 D.clearElement(link),
39 ' ',
40 (ls.length===1 ? 'line ' : 'lines ')+ls.join('-')
41 );
42 }else{
43 D.append(link, "No lines selected.");
44 }
45 },
46 adjustX: function(x){
47 return x + 20;
48 },
49 adjustY: function(y){
50 return y - this.e.clientHeight/2;
51 },
52 init: function(){
53 const e = this.e;
54 const btnCopy = D.addClass(D.span(), 'copy-button');
55 const link = D.attr(D.span(), 'id', 'fossil-ln-link');
56 this.state = {link};
57 F.copyButton(btnCopy,{
58 copyFromElement: link,
59 extractText: ()=>link.dataset.url
60 });
61 D.append(this.e, btnCopy, link)
62 }
63 });
64
65 tbl.addEventListener('click', function f(ev){
66 lineTip.show(false);
67 }, false);
68
69 tdLn.addEventListener('click', function f(ev){
70 if('SPAN'!==ev.target.tagName) return;
71 else if('number' !== typeof f.mode){
72 f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
73 }
74 ev.stopPropagation();
75 const ln = +ev.target.innerText;
76 if(2===f.mode){/*reset selection*/
77 f.mode = 0;
78 }
79 if(0===f.mode){
80 lineState.end = 0;
81 lineState.start = ln;
82 f.mode = 1;
83 }else if(1===f.mode){
84 if(ln === lineState.start){/*unselect line*/
85 //console.debug("Unselected line #"+ln);
86 lineState.start = 0;
87 f.mode = 0;
88 }else{
89 if(ln<lineState.start){
90 lineState.end = lineState.start;
91 lineState.start = ln;
92 }else{
93 lineState.end = ln;
94 }
95 //console.debug("Selected range: ",rng);
96 f.mode = 2;
97 }
98 }
99 tdLn.querySelectorAll('span.selected-line').forEach(
100 (e)=>D.removeClass(e, 'selected-line','start','end'));
101 if(f.mode>0){
102 lineTip.show(ev.clientX, ev.clientY);
103 const spans = tdLn.querySelectorAll('span');
104 if(spans.length>=lineState.start){
105 let i = lineState.start, end = lineState.end || lineState.start, span = spans[i-1];
106 for( ; i<=end && span; span = spans[i++] ){
107 span.classList.add('selected-line');
108 if(i===lineState.start) span.classList.add('start');
109 if(i===end) span.classList.add('end');
110 }
111 }
112 lineTip.refresh();
113 }else{
114 lineTip.show(false);
115 }
116 }, false);
117
118 })();
119
120 DDED src/fossil.tooltip.js
--- a/src/fossil.tooltip.js
+++ b/src/fossil.tooltip.js
@@ -0,0 +1,62 @@
1
+(function(F/*fossil object*/){
2
+ 30 widgetbject*/fossil object*/){
3
+ 3000sClass = cssClass;
4
+ unction(F/*fossil objecoltip-like widget. The options are available to clients after this returns via
5
+ theTooltip.options, and
6
+ D.append(any 30 */
7
+ installClicknents, e.g. a cop or movopy-to-clipboard butt
8
+ if needed,l.dom
9
+ */
10
+ const D = F.dom
11
+ base DOMwidget using the
12
+). If theallback whic
13
+ h is cal){
14
+ 30it to this.e, up via theintera(
15
+ ){
16
+ 3000sClass = cssClass;
17
+ unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
18
+ 3000sClass =tion(F/*fossil objec argument as-is
19
+ et. It's intended to be clients give itn(F/*fossil object*/){
20
+ /**
21
+ s, and it will tstrap, fossil.dom
22
+ */
23
+ conbjecthe popup when either
24
+ call this
25
+ show(falseshow(falseshow(falseconst hide Just be careful to mess only with the X coordinate
26
+ and the width. The browser will try to keep the widget
27
+ tually fit
28
+ the current help textclickHandler){const rect1unction(F/*fossconst rect1unction(F/*fossil object*(function(F/*fossil object*/){})(window.fossil);
29
+deleteleft');
30
+ deletea toas(function(F/*fossil o*fossil object*/){
31
+function(F/*fossil ct*/){
32
+ 30 */
33
+ installClickToHiden or basic user intera(fun*/
34
+ F.toast = function f(/*...*/){
35
+ f.toast = function ff(argsObject){
36
+ if(!ff.toaster) f ['fossil-tooltip', 'fossil-toast']
37
+ });
38
+ i@1hi,X: D.clearElement(ff.toaster.e);9@1SA,2w:var i = 0;
39
+ for( ; i < argsObject.length; ++i ){
40
+ D.append(ff.toaster.e, argsObject[i]);
41
+ };
42
+ ff.toaster.show(f.config.position.x, f.config.position.y);
43
+ Q@1mw,1m:()=>ff.toaster.hide(), f.config.displayTimeMs);
44
+ };
45
+ }
46
+ f.toast(arguments);
47
+ };
48
+ F.toast.config = {
49
+10@1pR,i:displayTimeMs: 2500
50
+ };
51
+
52
+})(window.fossil);
53
+ZfWzX;(function(F/*fossil object*/){
54
+ 30 */
55
+ installClickToHiden or basic user intera(function(F/*fossil object*/){
56
+ 3000sClass = cssClass;
57
+ unct}, true);isplay basic information ClickToHide(nhw cssClass;
58
+ unction(F/ very basic tooltip-like widget. It's intended to be popped up
59
+ to display basic information or basic user interaction
60
+ components, e.g. a copy-to-clipboard button.
61
+
62
+ Requires: fossil.bootstrap,
--- a/src/fossil.tooltip.js
+++ b/src/fossil.tooltip.js
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/fossil.tooltip.js
+++ b/src/fossil.tooltip.js
@@ -0,0 +1,62 @@
1 (function(F/*fossil object*/){
2 30 widgetbject*/fossil object*/){
3 3000sClass = cssClass;
4 unction(F/*fossil objecoltip-like widget. The options are available to clients after this returns via
5 theTooltip.options, and
6 D.append(any 30 */
7 installClicknents, e.g. a cop or movopy-to-clipboard butt
8 if needed,l.dom
9 */
10 const D = F.dom
11 base DOMwidget using the
12 ). If theallback whic
13 h is cal){
14 30it to this.e, up via theintera(
15 ){
16 3000sClass = cssClass;
17 unct}, true);isplay basic information ClickToHide(nction(F/*fossil object*/fossil object*/){
18 3000sClass =tion(F/*fossil objec argument as-is
19 et. It's intended to be clients give itn(F/*fossil object*/){
20 /**
21 s, and it will tstrap, fossil.dom
22 */
23 conbjecthe popup when either
24 call this
25 show(falseshow(falseshow(falseconst hide Just be careful to mess only with the X coordinate
26 and the width. The browser will try to keep the widget
27 tually fit
28 the current help textclickHandler){const rect1unction(F/*fossconst rect1unction(F/*fossil object*(function(F/*fossil object*/){})(window.fossil);
29 deleteleft');
30 deletea toas(function(F/*fossil o*fossil object*/){
31 function(F/*fossil ct*/){
32 30 */
33 installClickToHiden or basic user intera(fun*/
34 F.toast = function f(/*...*/){
35 f.toast = function ff(argsObject){
36 if(!ff.toaster) f ['fossil-tooltip', 'fossil-toast']
37 });
38 i@1hi,X: D.clearElement(ff.toaster.e);9@1SA,2w:var i = 0;
39 for( ; i < argsObject.length; ++i ){
40 D.append(ff.toaster.e, argsObject[i]);
41 };
42 ff.toaster.show(f.config.position.x, f.config.position.y);
43 Q@1mw,1m:()=>ff.toaster.hide(), f.config.displayTimeMs);
44 };
45 }
46 f.toast(arguments);
47 };
48 F.toast.config = {
49 10@1pR,i:displayTimeMs: 2500
50 };
51
52 })(window.fossil);
53 ZfWzX;(function(F/*fossil object*/){
54 30 */
55 installClickToHiden or basic user intera(function(F/*fossil object*/){
56 3000sClass = cssClass;
57 unct}, true);isplay basic information ClickToHide(nhw cssClass;
58 unction(F/ very basic tooltip-like widget. It's intended to be popped up
59 to display basic information or basic user interaction
60 components, e.g. a copy-to-clipboard button.
61
62 Requires: fossil.bootstrap,
+3 -2
--- src/info.c
+++ src/info.c
@@ -2113,16 +2113,17 @@
21132113
if(zExt && *zExt){
21142114
cgi_printf("<code class='language-%h'>",zExt);
21152115
}else{
21162116
cgi_append_content("<code>", -1);
21172117
}
2118
- cgi_printf("%.*h", nZ, z);
2118
+ cgi_printf("%z", htmlize(z, nZ));
21192119
CX("</code></pre></td></tr></tbody></table>\n");
21202120
if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
21212121
builtin_request_js("scroll.js");
21222122
}
2123
- builtin_request_js("fossil.numbered-lines.js");
2123
+ style_emit_fossil_js_apis(0, "dom", "copybutton", "tooltip",
2124
+ "numbered-lines", 0);
21242125
}
21252126
21262127
/*
21272128
** COMMAND: test-line-numbers
21282129
**
21292130
--- src/info.c
+++ src/info.c
@@ -2113,16 +2113,17 @@
2113 if(zExt && *zExt){
2114 cgi_printf("<code class='language-%h'>",zExt);
2115 }else{
2116 cgi_append_content("<code>", -1);
2117 }
2118 cgi_printf("%.*h", nZ, z);
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 builtin_request_js("fossil.numbered-lines.js");
 
2124 }
2125
2126 /*
2127 ** COMMAND: test-line-numbers
2128 **
2129
--- src/info.c
+++ src/info.c
@@ -2113,16 +2113,17 @@
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", "tooltip",
2124 "numbered-lines", 0);
2125 }
2126
2127 /*
2128 ** COMMAND: test-line-numbers
2129 **
2130
--- src/main.mk
+++ src/main.mk
@@ -223,18 +223,20 @@
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 \
230231
$(SRCDIR)/fossil.numbered-lines.js \
231232
$(SRCDIR)/fossil.page.fileedit.js \
232233
$(SRCDIR)/fossil.page.forumpost.js \
233234
$(SRCDIR)/fossil.page.wikiedit.js \
234235
$(SRCDIR)/fossil.storage.js \
235236
$(SRCDIR)/fossil.tabs.js \
237
+ $(SRCDIR)/fossil.tooltip.js \
236238
$(SRCDIR)/graph.js \
237239
$(SRCDIR)/href.js \
238240
$(SRCDIR)/login.js \
239241
$(SRCDIR)/markdown.md \
240242
$(SRCDIR)/menu.js \
241243
--- src/main.mk
+++ src/main.mk
@@ -223,18 +223,20 @@
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.numbered-lines.js \
231 $(SRCDIR)/fossil.page.fileedit.js \
232 $(SRCDIR)/fossil.page.forumpost.js \
233 $(SRCDIR)/fossil.page.wikiedit.js \
234 $(SRCDIR)/fossil.storage.js \
235 $(SRCDIR)/fossil.tabs.js \
 
236 $(SRCDIR)/graph.js \
237 $(SRCDIR)/href.js \
238 $(SRCDIR)/login.js \
239 $(SRCDIR)/markdown.md \
240 $(SRCDIR)/menu.js \
241
--- src/main.mk
+++ src/main.mk
@@ -223,18 +223,20 @@
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.storage.js \
236 $(SRCDIR)/fossil.tabs.js \
237 $(SRCDIR)/fossil.tooltip.js \
238 $(SRCDIR)/graph.js \
239 $(SRCDIR)/href.js \
240 $(SRCDIR)/login.js \
241 $(SRCDIR)/markdown.md \
242 $(SRCDIR)/menu.js \
243
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,18 +635,20 @@
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 \
642643
$(SRCDIR)/fossil.numbered-lines.js \
643644
$(SRCDIR)/fossil.page.fileedit.js \
644645
$(SRCDIR)/fossil.page.forumpost.js \
645646
$(SRCDIR)/fossil.page.wikiedit.js \
646647
$(SRCDIR)/fossil.storage.js \
647648
$(SRCDIR)/fossil.tabs.js \
649
+ $(SRCDIR)/fossil.tooltip.js \
648650
$(SRCDIR)/graph.js \
649651
$(SRCDIR)/href.js \
650652
$(SRCDIR)/login.js \
651653
$(SRCDIR)/markdown.md \
652654
$(SRCDIR)/menu.js \
653655
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,18 +635,20 @@
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.numbered-lines.js \
643 $(SRCDIR)/fossil.page.fileedit.js \
644 $(SRCDIR)/fossil.page.forumpost.js \
645 $(SRCDIR)/fossil.page.wikiedit.js \
646 $(SRCDIR)/fossil.storage.js \
647 $(SRCDIR)/fossil.tabs.js \
 
648 $(SRCDIR)/graph.js \
649 $(SRCDIR)/href.js \
650 $(SRCDIR)/login.js \
651 $(SRCDIR)/markdown.md \
652 $(SRCDIR)/menu.js \
653
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -635,18 +635,20 @@
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.storage.js \
648 $(SRCDIR)/fossil.tabs.js \
649 $(SRCDIR)/fossil.tooltip.js \
650 $(SRCDIR)/graph.js \
651 $(SRCDIR)/href.js \
652 $(SRCDIR)/login.js \
653 $(SRCDIR)/markdown.md \
654 $(SRCDIR)/menu.js \
655
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,18 +556,20 @@
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" \
563564
"$(SRCDIR)\fossil.numbered-lines.js" \
564565
"$(SRCDIR)\fossil.page.fileedit.js" \
565566
"$(SRCDIR)\fossil.page.forumpost.js" \
566567
"$(SRCDIR)\fossil.page.wikiedit.js" \
567568
"$(SRCDIR)\fossil.storage.js" \
568569
"$(SRCDIR)\fossil.tabs.js" \
570
+ "$(SRCDIR)\fossil.tooltip.js" \
569571
"$(SRCDIR)\graph.js" \
570572
"$(SRCDIR)\href.js" \
571573
"$(SRCDIR)\login.js" \
572574
"$(SRCDIR)\markdown.md" \
573575
"$(SRCDIR)\menu.js" \
@@ -1151,18 +1153,20 @@
11511153
echo "$(SRCDIR)\default.css" >> $@
11521154
echo "$(SRCDIR)\diff.tcl" >> $@
11531155
echo "$(SRCDIR)\forum.js" >> $@
11541156
echo "$(SRCDIR)\fossil.bootstrap.js" >> $@
11551157
echo "$(SRCDIR)\fossil.confirmer.js" >> $@
1158
+ echo "$(SRCDIR)\fossil.copybutton.js" >> $@
11561159
echo "$(SRCDIR)\fossil.dom.js" >> $@
11571160
echo "$(SRCDIR)\fossil.fetch.js" >> $@
11581161
echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@
11591162
echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
11601163
echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
11611164
echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
11621165
echo "$(SRCDIR)\fossil.storage.js" >> $@
11631166
echo "$(SRCDIR)\fossil.tabs.js" >> $@
1167
+ echo "$(SRCDIR)\fossil.tooltip.js" >> $@
11641168
echo "$(SRCDIR)\graph.js" >> $@
11651169
echo "$(SRCDIR)\href.js" >> $@
11661170
echo "$(SRCDIR)\login.js" >> $@
11671171
echo "$(SRCDIR)\markdown.md" >> $@
11681172
echo "$(SRCDIR)\menu.js" >> $@
11691173
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,18 +556,20 @@
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.numbered-lines.js" \
564 "$(SRCDIR)\fossil.page.fileedit.js" \
565 "$(SRCDIR)\fossil.page.forumpost.js" \
566 "$(SRCDIR)\fossil.page.wikiedit.js" \
567 "$(SRCDIR)\fossil.storage.js" \
568 "$(SRCDIR)\fossil.tabs.js" \
 
569 "$(SRCDIR)\graph.js" \
570 "$(SRCDIR)\href.js" \
571 "$(SRCDIR)\login.js" \
572 "$(SRCDIR)\markdown.md" \
573 "$(SRCDIR)\menu.js" \
@@ -1151,18 +1153,20 @@
1151 echo "$(SRCDIR)\default.css" >> $@
1152 echo "$(SRCDIR)\diff.tcl" >> $@
1153 echo "$(SRCDIR)\forum.js" >> $@
1154 echo "$(SRCDIR)\fossil.bootstrap.js" >> $@
1155 echo "$(SRCDIR)\fossil.confirmer.js" >> $@
 
1156 echo "$(SRCDIR)\fossil.dom.js" >> $@
1157 echo "$(SRCDIR)\fossil.fetch.js" >> $@
1158 echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@
1159 echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@
1160 echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@
1161 echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@
1162 echo "$(SRCDIR)\fossil.storage.js" >> $@
1163 echo "$(SRCDIR)\fossil.tabs.js" >> $@
 
1164 echo "$(SRCDIR)\graph.js" >> $@
1165 echo "$(SRCDIR)\href.js" >> $@
1166 echo "$(SRCDIR)\login.js" >> $@
1167 echo "$(SRCDIR)\markdown.md" >> $@
1168 echo "$(SRCDIR)\menu.js" >> $@
1169
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -556,18 +556,20 @@
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.storage.js" \
569 "$(SRCDIR)\fossil.tabs.js" \
570 "$(SRCDIR)\fossil.tooltip.js" \
571 "$(SRCDIR)\graph.js" \
572 "$(SRCDIR)\href.js" \
573 "$(SRCDIR)\login.js" \
574 "$(SRCDIR)\markdown.md" \
575 "$(SRCDIR)\menu.js" \
@@ -1151,18 +1153,20 @@
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.storage.js" >> $@
1166 echo "$(SRCDIR)\fossil.tabs.js" >> $@
1167 echo "$(SRCDIR)\fossil.tooltip.js" >> $@
1168 echo "$(SRCDIR)\graph.js" >> $@
1169 echo "$(SRCDIR)\href.js" >> $@
1170 echo "$(SRCDIR)\login.js" >> $@
1171 echo "$(SRCDIR)\markdown.md" >> $@
1172 echo "$(SRCDIR)\menu.js" >> $@
1173

Keyboard Shortcuts

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