D850: hgweb: add HTML elements to control whitespace settings for annotate

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Sat Sep 30 08:08:45 UTC 2017


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Building on top of the new URL query string arguments to control
  whitespace settings for annotate, this commit adds HTML checkboxes
  reflecting the values of these arguments to the paper and gitweb
  themes.
  
  The actual diff settings are now exported to the templating layer.
  The HTML templates add these as data-* attributes so they are
  accessible to the DOM.
  
  A new <form> with various <input> elements is added. The <form>
  is initially hidden via CSS. A shared JavaScript function (which
  runs after the <form> has been rendered but before the annotate
  HTML (because annotate HTML could take a while to load and we want
  the form to render quickly) takes care of setting the checked state
  of each box from the data-* attributes. It also registers an event
  handler to modify the URL and refresh the page whenever the checkbox
  state is changed.
  
  I'm using the URLSearchParams interface to perform URL manipulation.
  https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams tells
  me this may not be supported on older web browsers. Yes, apparently
  the web API didn't have a standard API to parse and format query
  strings until recently. Hence the check for the presence of this
  feature in the JavaScript. If the browser doesn't support the
  feature, the <form> will remain hidden and behavior will like it
  currently is. We could polyfill this feature or implement our own
  query string parsing. But I'm lazy and this could be done as a
  follow-up if people miss it.
  
  We could certainly expand this feature to support more diff options
  (such as lines of context). That's why the potentially reusable code
  is stored in a reusable place. It is also certainly possible to
  add diff controls to other pages that display diffs. But since
  Mozillians are making noise about controlling which revisions
  annotate shows, I figured I'd start there.
  
  .. feature::
  
    Control whitespace settings for annotation on hgweb
    
    /annotate URLs on hgweb now accept query string arguments to
    influence how whitespace changes impact results.
    
    The arguments "ignorews," "ignorewsamount," "ignorewseol," and
    "ignoreblanklines" now have the same meaning as their [annotate]
    config section counterparts. Any provided setting overrides the
    server default.
    
    HTML checkboxes have been added to the paper and gitweb themes
    to expose current whitespace settings and to easily modify the
    current view.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D850

AFFECTED FILES
  mercurial/hgweb/webcommands.py
  mercurial/templates/gitweb/fileannotate.tmpl
  mercurial/templates/gitweb/map
  mercurial/templates/paper/fileannotate.tmpl
  mercurial/templates/paper/map
  mercurial/templates/static/mercurial.js
  mercurial/templates/static/style-gitweb.css
  mercurial/templates/static/style-paper.css
  tests/test-hgweb.t

CHANGE DETAILS

diff --git a/tests/test-hgweb.t b/tests/test-hgweb.t
--- a/tests/test-hgweb.t
+++ b/tests/test-hgweb.t
@@ -340,7 +340,7 @@
 
   $ get-with-headers.py --twice localhost:$HGPORT 'static/style-gitweb.css' - date etag server
   200 Script output follows
-  content-length: 9007
+  content-length: 9066
   content-type: text/css
   
   body { font-family: sans-serif; font-size: 12px; border:solid #d9d8d1; border-width:1px; margin:10px; background: white; color: black; }
@@ -442,6 +442,12 @@
   }
   div.annotate-info a { color: #0000FF; text-decoration: underline; }
   td.annotate:hover div.annotate-info { display: inline; }
+  
+  #diffopts-form {
+    padding-left: 8px;
+    display: none;
+  }
+  
   .linenr { color:#999999; text-decoration:none }
   div.rss_logo { float: right; white-space: nowrap; }
   div.rss_logo a {
diff --git a/mercurial/templates/static/style-paper.css b/mercurial/templates/static/style-paper.css
--- a/mercurial/templates/static/style-paper.css
+++ b/mercurial/templates/static/style-paper.css
@@ -226,6 +226,13 @@
 div.annotate-info a { color: #0000FF; }
 td.annotate:hover div.annotate-info { display: inline; }
 
+#diffopts-form {
+  font-size: smaller;
+  color: #424242;
+  padding-bottom: 10px;
+  display: none;
+}
+
 .source, .sourcefirst {
   font-family: monospace;
   white-space: pre;
diff --git a/mercurial/templates/static/style-gitweb.css b/mercurial/templates/static/style-gitweb.css
--- a/mercurial/templates/static/style-gitweb.css
+++ b/mercurial/templates/static/style-gitweb.css
@@ -97,6 +97,12 @@
 }
 div.annotate-info a { color: #0000FF; text-decoration: underline; }
 td.annotate:hover div.annotate-info { display: inline; }
+
+#diffopts-form {
+  padding-left: 8px;
+  display: none;
+}
+
 .linenr { color:#999999; text-decoration:none }
 div.rss_logo { float: right; white-space: nowrap; }
 div.rss_logo a {
diff --git a/mercurial/templates/static/mercurial.js b/mercurial/templates/static/mercurial.js
--- a/mercurial/templates/static/mercurial.js
+++ b/mercurial/templates/static/mercurial.js
@@ -434,6 +434,56 @@
     scrollHandler();
 }
 
+function renderDiffOptsForm() {
+    // We use URLSearchParams for query string manipulation. Old browsers don't
+    // support this API.
+    if (!("URLSearchParams" in window)) {
+        return;
+    }
+
+    var form = document.getElementById("diffopts-form");
+
+    var KEYS = [
+        "ignorews",
+        "ignorewsamount",
+        "ignorewseol",
+        "ignoreblanklines",
+    ];
+
+    var urlParams = new URLSearchParams(window.location.search);
+
+    function updateAndRefresh(e) {
+        var checkbox = e.target;
+        var name = checkbox.id.substr(0, checkbox.id.indexOf("-"));
+        urlParams.set(name, checkbox.checked ? "1" : "0");
+        window.location.search = urlParams.toString();
+    }
+
+    var allChecked = form.getAttribute("data-ignorews") == "1";
+
+    for (var i = 0; i < KEYS.length; i++) {
+        var key = KEYS[i];
+
+        var checkbox = document.getElementById(key + "-checkbox");
+        if (!checkbox) {
+            continue;
+        }
+
+        currentValue = form.getAttribute("data-" + key);
+        checkbox.checked = currentValue != "0";
+
+        // ignorews implies ignorewsamount and ignorewseol.
+        if (allChecked && (key == "ignorewsamount" || key == "ignorewseol")) {
+            checkbox.checked = true;
+            checkbox.disabled = true;
+        }
+
+        checkbox.addEventListener("change", updateAndRefresh, false);
+    }
+
+    form.style.display = 'block';
+}
+
 document.addEventListener('DOMContentLoaded', function() {
    process_dates();
 }, false);
diff --git a/mercurial/templates/paper/map b/mercurial/templates/paper/map
--- a/mercurial/templates/paper/map
+++ b/mercurial/templates/paper/map
@@ -251,3 +251,18 @@
   </form>'
 searchhint = 'Find changesets by keywords (author, files, the commit message), revision
   number or hash, or <a href="{url|urlescape}help/revsets">revset expression</a>.'
+
+diffoptsform = '
+  <form id="diffopts-form"
+    data-ignorews="{if(get(diffopts, 'ignorews'), '1', '0')}"
+    data-ignorewsamount="{if(get(diffopts, 'ignorewsamount'), '1', '0')}"
+    data-ignorewseol="{if(get(diffopts, 'ignorewseol'), '1', '0')}"
+    data-ignoreblanklines="{if(get(diffopts, 'ignoreblanklines'), '1', '0')}">
+    <span>Ignore whitespace changes - </span>
+    <span>Everywhere:</span>
+    <input id="ignorews-checkbox" type="checkbox" />
+    <span>Within whitespace:</span>
+    <input id="ignorewsamount-checkbox" type="checkbox" />
+    <span>At end of lines:</span>
+    <input id="ignorewseol-checkbox" type="checkbox" />
+  </form>'
diff --git a/mercurial/templates/paper/fileannotate.tmpl b/mercurial/templates/paper/fileannotate.tmpl
--- a/mercurial/templates/paper/fileannotate.tmpl
+++ b/mercurial/templates/paper/fileannotate.tmpl
@@ -65,6 +65,12 @@
 </tr>
 </table>
 
+{diffoptsform}
+
+<script type="text/javascript"{if(nonce, ' nonce="{nonce}"')}>
+    renderDiffOptsForm();
+</script>
+
 <div class="overflow">
 <table class="bigtable">
 <thead>
diff --git a/mercurial/templates/gitweb/map b/mercurial/templates/gitweb/map
--- a/mercurial/templates/gitweb/map
+++ b/mercurial/templates/gitweb/map
@@ -334,3 +334,19 @@
   </div>'
 searchhint = 'Find changesets by keywords (author, files, the commit message), revision
   number or hash, or <a href="{url|urlescape}help/revsets">revset expression</a>.'
+
+diffoptsform = '
+  <form id="diffopts-form"
+    data-ignorews="{if(get(diffopts, 'ignorews'), '1', '0')}"
+    data-ignorewsamount="{if(get(diffopts, 'ignorewsamount'), '1', '0')}"
+    data-ignorewseol="{if(get(diffopts, 'ignorewseol'), '1', '0')}"
+    data-ignoreblanklines="{if(get(diffopts, 'ignoreblanklines'), '1', '0')}">
+    <span>Ignore whitespace changes - </span>
+    <span>Everywhere:</span>
+    <input id="ignorews-checkbox" type="checkbox" />
+    <span>Within whitespace:</span>
+    <input id="ignorewsamount-checkbox" type="checkbox" />
+    <span>At end of lines:</span>
+    <input id="ignorewseol-checkbox" type="checkbox" />
+  </form>
+  </div>'
diff --git a/mercurial/templates/gitweb/fileannotate.tmpl b/mercurial/templates/gitweb/fileannotate.tmpl
--- a/mercurial/templates/gitweb/fileannotate.tmpl
+++ b/mercurial/templates/gitweb/fileannotate.tmpl
@@ -62,6 +62,13 @@
 </div>
 
 <div class="page_path description">{desc|strip|escape|websub|nonempty}</div>
+
+{diffoptsform}
+
+<script type="text/javascript"{if(nonce, ' nonce="{nonce}"')}>
+    renderDiffOptsForm();
+</script>
+
 <div class="page_body">
 <table>
 <tbody class="sourcelines"
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -930,14 +930,18 @@
                    "linenumber": "% 6d" % (lineno + 1),
                    "revdate": f.date()}
 
+    diffopts = webutil.difffeatureopts(req, web.repo.ui, 'annotate')
+    diffopts = {k: getattr(diffopts, k) for k in diffopts.defaults}
+
     return tmpl("fileannotate",
                 file=f,
                 annotate=annotate,
                 path=webutil.up(f),
                 symrev=webutil.symrevorshortnode(req, fctx),
                 rename=webutil.renamelink(fctx),
                 permissions=fctx.manifest().flags(f),
                 ishead=int(ishead),
+                diffopts=diffopts,
                 **webutil.commonentry(web.repo, fctx))
 
 @webcommand('filelog')



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list