Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fetching of /jchunk lines by clicking on the '...' separator of a diff is now working but the fetched lines still need to be integrated into the UI. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | diff-js-refactoring |
| Files: | files | file ages | folders |
| SHA3-256: |
41ef416e778ea9c3c85e9fa0e335823a |
| User & Date: | stephan 2021-09-09 03:23:51.686 |
Context
|
2021-09-09
| ||
| 04:58 | /jchunk code lines are now injected into the diff view but the line numbers are still TODO. ... (check-in: 49a60a580d user: stephan tags: diff-js-refactoring) | |
| 03:23 | Fetching of /jchunk lines by clicking on the '...' separator of a diff is now working but the fetched lines still need to be integrated into the UI. ... (check-in: 41ef416e77 user: stephan tags: diff-js-refactoring) | |
|
2021-09-08
| ||
| 18:42 | /jchunk now always uses a JSON response, even for permissions problems. Doc improvements for the jchunk interface. ... (check-in: 1fec5f4abc user: stephan tags: diff-js-refactoring) | |
Changes
Changes to src/builtin.c.
| ︙ | ︙ | |||
700 701 702 703 704 705 706 |
** entries: all known deps of this one. Each
** REQUIRES an EXPLICIT trailing \0, including
** the final one! */
} fjs[] = {
/* This list ordering isn't strictly important. */
{"confirmer", 0, 0},
{"copybutton", 0, "dom\0"},
| | | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 |
** entries: all known deps of this one. Each
** REQUIRES an EXPLICIT trailing \0, including
** the final one! */
} fjs[] = {
/* This list ordering isn't strictly important. */
{"confirmer", 0, 0},
{"copybutton", 0, "dom\0"},
{"diff", 0, "dom\0fetch\0popupwidget\0"},
{"dom", 0, 0},
{"fetch", 0, 0},
{"info-diff", 0, "dom\0"},
{"numbered-lines", 0, "popupwidget\0copybutton\0"},
{"pikchr", 0, "dom\0"},
{"popupwidget", 0, "dom\0"},
{"storage", 0, 0},
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
padding: 0 0.5em;
}
table.diff td {
vertical-align: top;
}
table.diff pre {
margin: 0 0 0 0;
}
td.diffln {
width: 1px;
text-align: right;
padding: 0 1em 0 0;
}
td.difflne {
| > > > > > > > | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
padding: 0 0.5em;
}
table.diff td {
vertical-align: top;
}
table.diff pre {
margin: 0 0 0 0;
}
tr.diffskip.jchunk:hover {
/* jchunk gets added from JS to diffskip rows when they are
plugged into the /jchunk route and removed after that data
is fetched. */
background-color: rgba(127,127,127,0.5);
cursor: pointer;
}
td.diffln {
width: 1px;
text-align: right;
padding: 0 1em 0 0;
}
td.difflne {
|
| ︙ | ︙ |
Changes to src/fossil.diff.js.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
}, false);
};
document.querySelectorAll('table.diff').forEach(addToggle);
});
window.fossil.onPageLoad(function(){
const F = window.fossil, D = F.dom;
| > > > > > > > > > > | > > > | > | > > > | > > > > | | | > | | | > > > > > > > | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > > > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
}, false);
};
document.querySelectorAll('table.diff').forEach(addToggle);
});
window.fossil.onPageLoad(function(){
const F = window.fossil, D = F.dom;
const Diff = F.diff = {
config: {
chunkLoadLines: 20,
chunkFetch: {
/* Default callack handlers for Diff.fetchArtifactChunk(),
unless overridden by options passeed to that function. */
beforesend: function(){},
aftersend: function(){},
onerror: function(e){
F.toast.error("XHR error: ",e.message);
}
}
}
};
/**
Uses the /jchunk AJAX route to fetch specific lines of a given
artifact. The argument must be an Object suitable for passing as
the second argument to fossil.fetch(). Its urlParams property
must be an object with these properties:
{
name: full hash of the target file,
from: first 1-based line number of the file to fetch (inclusive),
to: last 1-based line number of the file to fetch (inclusive)
}
The fetchOpt object is NOT cloned for use by the call: it is used
as-is and may be modified by this call. Thus callers "really
should" pass a temporary object, not a long-lived one.
If fetchOpt does not define any of the (beforesend, aftersend,
onerror) callbacks, the defaults from fossil.diff.config.chunkFetch
are used, so any given client page may override those to provide
page-level default handling.
Note that onload callback is ostensibly optional but this
function is not of much use without an onload
handler. Conversely, the default onerror handler is often
customized on a per-page basis to send the error output somewhere
where the user can see it.
The response, on success, will be an array of strings, each entry
being one line from the requested artifact. If the 'to' line is
greater than the length of the file, the array will be shorter
than (to-from) lines.
The /jchunk route reports errors via JSON objects with
an "error" string property describing the problem.
This is an async operation. Returns the fossil object.
*/
Diff.fetchArtifactChunk = function(fetchOpt){
if(!fetchOpt.beforesend) fetchOpt.beforesend = Diff.config.chunkFetch.beforesend;
if(!fetchOpt.aftersend) fetchOpt.aftersend = Diff.config.chunkFetch.aftersend;
if(!fetchOpt.onerror) fetchOpt.onerror = Diff.config.chunkFetch.onerror;
fetchOpt.responseType = 'json';
return F.fetch('jchunk', fetchOpt);
};
/**
Fetches /jchunk for the given TR element then replaces the TR's
contents with data from the result of that request.
*/
const fetchTrChunk = function(tr){
if(tr.dataset.xfer /* already being fetched */) return;
const table = tr.parentElement.parentElement;
const hash = table.dataset.lefthash;
if(!hash) return;
const isSbs = table.classList.contains('splitdiff')/*else udiff*/;
tr.dataset.xfer = 1 /* sentinel against multiple concurrent ajax requests */;
const lineTo = +tr.dataset.endln;
var lnFrom = +tr.dataset.startln;
/* TODO: for the time being, for simplicity, we'll read the whole
[startln, endln] chunk. "Later on" we'll maybe want to read it in
chunks of, say, 20 lines or so, adjusting lnFrom to be 1 if it would
be less than 1. */
Diff.fetchArtifactChunk({
urlParams:{
name: hash,
from: lnFrom,
to: lineTo
},
aftersend: function(){
delete tr.dataset.xfer;
Diff.config.chunkFetch.aftersend.apply(
this, Array.prototype.slice.call(arguments,0)
);
},
onload: function(result){
console.debug("Chunk result: ",result);
D.clearElement(tr);
D.append(
D.attr(D.td(tr), 'colspan', isSbs ? 5 : 4),
"Fetched chunk of ",result.length," line(s). TODO: insert it here."
);
/*
At this point we need to:
- Read the previous TR, if any, to get the preceeding LHS/RHS
line numbers so that we know where to start counting.
- If there is no previous TR, we're at the top and we
instead need to get the LHS/RHS line numbers from the
following TR's children.
- D.clearElement(tr) and insert columns appropriate for the
parent table's diff type.
We can fish the line numbers out of the PRE columns with something
like this inefficient but effective hack:
theElement.innerText.split(/\n+/)
(need /\n+/ instead of '\n' b/c of INS/DEL elements)
Noting that the result array will end with an empty element
due to the trailing \n character, so a call to pop() will be
needed.
SBS diff col layout:
<td><pre>...LHS line numbers...</pre></td>
<td>...code lines...</td>
<td></td> empty for this case.
<td><pre>...RHS line numbers...</pre></td>
<td>...dupe of col 2</td>
Unified diff col layout:
<td>LHS line numbers</td>
<td>RHS line numbers</td>
<td>blank in this case</td>
<td>code line</td>
*/
}
});
};
Diff.addDiffSkipHandlers = function(){
const tables = document.querySelectorAll('table.diff[data-lefthash]');
if(!tables.length) return F;
const addDiffSkipToTr = function f(tr){
D.addClass(tr, 'jchunk');
if(!f._handler){
f._handler = function ff(event){
var e = event.target;
while(e && 'TR' !== e.tagName) e = e.parentElement;
if(!e){
console.error("Internal event-handling error: didn't find TR target.");
return;
}
e.removeEventListener('click',ff);
D.removeClass(e, 'jchunk');
//console.debug("addDiffSkipToTr() Event:",e, event);
fetchTrChunk(e);
};
}
tr.addEventListener('click', f._handler, false);
};
tables.forEach(function(t){
t.querySelectorAll('tr.diffskip[data-startln]').forEach(addDiffSkipToTr);
});
};
F.diff.addDiffSkipHandlers();
});
/**
2021-09-07: refactoring the following for use in the higher-level
fossil.*.js framework is pending. For now it's a copy/paste copy
of diff.js.
*/
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
1897 1898 1899 1900 1901 1902 1903 | ** ** This page is intended to be used in an XHR from javascript on a ** diff page, to return unseen context to fill in additional context ** when the user clicks on the appropriate button. The response is ** always in JSON form and errors are reported as documented for ** ajax_route_error(). */ | | > > > > > | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 |
**
** This page is intended to be used in an XHR from javascript on a
** diff page, to return unseen context to fill in additional context
** when the user clicks on the appropriate button. The response is
** always in JSON form and errors are reported as documented for
** ajax_route_error().
*/
void jchunk_page(void){
int rid = 0;
const char *zName = PD("name", "");
int iFrom = atoi(PD("from","0"));
int iTo = atoi(PD("to","0"));
int ln;
int go = 1;
const char *zSep;
Blob content;
Blob line;
Blob *pOut;
if(0){
ajax_route_error(400, "Just testing client-side error handling.");
return;
}
login_check_credentials();
if( !g.perm.Read ){
ajax_route_error(403, "Access requires Read permissions.");
return;
}
#if 0
/* Re-enable this block once this code is integrated somewhere into
|
| ︙ | ︙ |