"xhr" is a really widespread name for this kind of things, no idea where did
"xfr" come from (the original fbf9645839e4 doesn't explain that). Let's just
change one letter so the name makes more sense.
In JavaScript, using for-in loops to access every property of an object can
have unexpected results when inheritance is involved. For example, if some
piece of code adds a property (it may be a method too) to Object.prototype,
then all for-in loops that iterate over keys of any object (also anything that
inherits Object) will get that property on one of the iterations. To filter out
such unexpected properties for-in loops have to use Object.hasOwnProperty()
method. (This corresponds to "forin" option of jshint).
In the two first cases "data" and "edges" are arrays, to it's simpler to just
switch to using a regular for-with-a-counter loop.
This patch changes "==" (equals operator) to "===" (strict equals operator).
The difference between them is that the latter doesn't do any type coercions.
It's handy to compare string '1' to number 1 sometimes, but most of the time
using "==" is inadvertent and can be replaced by an explicit type conversion.
(This corresponds to "eqeqeq" option of jshint).
Some of the changes in this patch are straightforward, e.g. when comparing
results of typeof (they could only be strings). The same goes for 'none' and
similar strings that can't be sensibly coerced to some other type. Two changes
that compare values to "1" and "0" can be clarified: getAttribute() returns
either a string or null, but comparing null to a string is always false, so no
logic is lost.
The first hunk had a non-breaking space character just before "{", it's not an
error or anything, but let's fix it while we're at it. (This corresponds to
"nonbsp" option of jshint).
Hunks 2 and 3 change "==" (equals operator) to "===" (strict equals operator).
The difference between them is that the latter doesn't do any type coercions.
It's handy to compare string '1' to number 1 sometimes, but most of the time
using "==" is inadvertent and can be replaced by an explicit type conversion.
(This corresponds to "eqeqeq" option of jshint).
Most of this file already uses strict equals operator, and in the code affected
type coercion is not needed, because tagName and selectableTag are both strings
and endId and startId are both numbers.
mercurial.js has a process_dates() function that calculates relative age for a
given date, it works for all elements with "age" css class. If those elements
also have "date" css class, the original text is preserved and age is added at
the end.
This patch adds these two css classes in some pages in gitweb and monoblue that
weren't already using this feature.
Clicking on a line link on pages that show any kind of file contents (including
diffs) should highlight that line, and in monoblue it works when there's a
<pre> element (e.g. diff), but pages that use <table> element (annotate and
compare) need this css class. It matches and highlights linked (":target")
table rows. This line is pretty much copied from gitweb theme.
There's a visual difference in hgweb between one changeset that is the tip of
its branch and another that simply belongs to that branch. But paper theme
ignored this difference on changeset page and used to always use "branchname"
css class, be that changeset the tip of its branch or not. That has been
recently fixed, so this piece of css is not needed anymore.
Let's make "instabilities" list contain items with "instability" key as opposed
to "name" key. This way it's more explicit and more consistent with the log
command-line template.
This makes graphdata() simpler by using existing code that gets common
changeset properties for showing in hgweb. graphdata() is a nested function in
graph() that prepares entries for /graph view, but there are two different
lists of changesets prepared: "jsdata" for JavaScript-rendered graph and
"nodes" for everything else.
For "jsdata", properties "node", "user", "age" and "desc" are passed through
various template filters because we don't have these filters in JavaScript, so
the data has to be prepared server-side. But now that commonentry() is used for
producing "nodes" list (and it doesn't apply any filters), these filters need
to be added to the appropriate templates (only raw at this moment, everything
else either doesn't implement graph or uses JavaScript).
This is a bit of refactoring that will hopefully simplify future patches. The
end result is to have /graph that only renders the actual graph with nodes and
vertices in JavaScript, and the rest is done server-side. This way server-side
code can focus on showing a list of changesets, which is easy because we
already have /log, /shortlog, etc, and JavaScript code can be simplified,
making it easier to add obsolescence graph and other features.
In paper, coal, gitweb and monoblue a new "tag" (or multiple, if there are many
instabilities) is added to the same line that has phase, branch, etc of a
changeset; in gitweb and monoblue this element has a light red background, in
paper and coal the element is black and underlined. In spartan theme
instabilities are shown on a separate line.
While test-obsolete.t uses first(phasedivergent()) revset to pick a changeset
to test, that particular changeset is also an orphan, so two different
instability tags are displayed.
This anchor text is problematic in two ways: first, the "back to" part
assumes that you got to the page showing it via the filelog. This is
not necessarily true, as there are other ways to get to that view
besides the filelog view, such as for example following the history of
lines from a file. Second, it uses "filelog" jargon, which refers to
how each file has its own revlog. This is internal jargon that has no
business being exposed to the end user.
I just reworded this template to improve understanding.
As with phases, spartan theme shows a simple "obsolete: yes" on its own line
(this allows replacing "yes" with something more useful in future, like output
of obsfate* template functions). Everywhere else a new "tag" is added to the
same line that has phase, branch, etc of a changeset; in gitweb and monoblue
the element has gray background, in paper and coal the element is gray with a
dashed underline.
In spartan theme phase is shown on its own table row, because there's no single
line of "tags". Everywhere else phase is prepended to the list of "tags" of a
changeset. Its element has a purple-ish color in gitweb and monoblue, and a
dotted line under it and no color in paper and coal (as these themes are frugal
with colors).
This patch intentionally doesn't touch graph, because it needs a rewrite. I'll
get to it pretty soon and in the process will add phase and everything that's
still coming (e.g. obsolescence and instabilities).
.. feature::
hgweb now displays phases of non-public changesets
This patch puts all these changeset "tags" into one template shared everywhere
in paper and coal themes. But it should be noted that some of the templates had
different sets of tags, in some cases it was intended, in others - most likely
not.
First, what's up with all these different ways to get changeset's branch. There
are actually 3 ways to do it in hgweb, they can all be seen in this patch;
"branches", "inbranch" and "branch". They are all lists that consist of 1 or 0
items:
- "branches" has ctx.branch() if current changeset is the tip of that branch
- "inbranch" has ctx.branch() if current changeset is _not_ the tip of that
branch and the branch is not "default"
- "branch" aka "changesetbranch" has ctx.branch() if the branch is not
"default"
The majority of cases (7 vs 2 + /graph) in paper theme used only option 3,
which meant that "default" was never displayed. But other parts of the theme
disagreed with this and used option 1 and option 2 together. For example, the
default view (log) displays "default" on the branch tip (can be seen right
about now on m-s.o/repo/hg), but it disappears when you click on the commit.
Also, using option 3 alone meant that there was no way to tell if a changeset
is the tip of its branch or not (it was always assumed that it's not, see how
some css classes change from "branchname" to the correct "branchhead" in tests)
-- so the two different css styles that exist in paper just for this were
underused.
I think this patch improves the situation, even though it changes the old (even
if inconsistent) behavior. The new behavior matches that of gitweb and
monoblue.
Less duplication and it's also easier to add extra "tags" everywhere at once.
These aren't tags as defined `hg help glossary` (hence the quotes), they are
simply called that. They include branch name (in different styles if changeset
is a head of that branch or not), (actual) tags and bookmarks. Good candidates
to add to this list would be changeset phase and obsoletion status.
Everything is pretty self-explanatory except the last hunk, where jshint
complains: "Misleading line break before '||'; readers may interpret this as an
expression boundary."
There is a tweakable called "laxbreak" that allows line breaks before
operators, but I think it's fine to simply join this one line and avoid extra
config for now (we can cook up and add a sensible .jshintrc later).
These new colors and styles are already used in the tooltip that gets shown
when user hovers over line numbers on annotate page. The old styles, replaced
in this patch, look completely unrelated to gitweb or any other hgweb theme.
These new colors and styles are already used in the tooltip that gets shown
when user hovers over line numbers on annotate page. The old styles, replaced
in this patch, look completely unrelated to paper or any other hgweb theme.
Use the verbosity aware template keyword introduced earlier. It has the nice
property of being verbosity dependent but in order to customize the obsfate
part, users will need to replace the lobsfate definition from default mapfile
with the one using template functions (by copying the one from test-obsmarker-
template.t for example).
As it's a more advanced use-case, I'm more inclined to have the same code for
the {obsfate} keyword, in the changeset printer and in the default mapfile for
consistency.
But, the definition in default mapfile could be replaced with one based on
template filter to obsfate output customization if it is a big need for users.
This allows us to %include map-cmdline.<style> file in our .hgrc files. The
syntax is slightly different as hgrc doesn't support loading an external
template file, but map-cmdline files don't use this feature, so the syntax
can be considered identical in practice.
Unnamed section is remapped for backward compatibility.
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.
Differential Revision: https://phab.mercurial-scm.org/D850
Without this, multiple spaces or tabs in the commit message aren't
preserved and things like tables don't align properly.
As part of adding the CSS rule, we had to cuddle the content
with the <div> to not introduce leading and trailing whitespace.
The "addbreaks" filter was also removed because it would insert
an additional newline, effectively double spacing content.
Differential Revision: https://phab.mercurial-scm.org/D113
This changeset attempts to solve two issues with the "followlines" UI in
hgweb. First the "followlines" action is currently not easily discoverable
(one has to hover on a line for some time, wait for the invite message to
appear and then perform some action). Second, it gets in the way of natural
line selection, especially in filerevision view.
This changeset introduces an additional markup element (a <button
class="btn-followlines">) alongside each content line of the view. This button
now holds events for line selection that were previously plugged onto content
lines directly. Consequently, there's no more action on content lines, hence
restoring the "natural line selection" behavior (solving the second problem).
These buttons are hidden by default and get displayed upon hover of content
lines; then upon hover of a button itself, a text inviting followlines section
shows up. This solves the first problem (discoverability) as we now have a
clear visual element indicating that "some action could be perform" (i.e. a
button) and that is self-documented.
In followlines.js, all event listeners are now attached to these <button>
elements. The custom "floating tooltip" element is dropped as <button>
elements are now self-documented through a "title" attribute that changes
depending on preceding actions (selection started or not, in particular).
The new <button> element is inserted in followlines.js script (thus only
visible if JavaScript is activated); it contains a "+" and "-" with a
"diff-semantics" style; upon hover, it scales up.
To find the parent element under which to insert the <button> we either rely
on the "data-selectabletag" attribute (which defines the HTML tag of children
of class="sourcelines" element e.g. <span> for filerevision view and <tr> for
annotate view) or use a child of the latter elements if we find an element
with class="followlines-btn-parent" (useful for annotate view, for which we
have to find the <td> in which to insert the <button>).
On noticeable change in CSS concerns the "margin-left" of span:before
pseudo-elements in filelog view that has been increased a bit in order to
leave space for the new button to appear between line number column and
line content one.
Also note the "z-index" addition for "annotate-info" box so that the latter
appears on top of new buttons (instead of getting hidden).
In some respect, the UI similar to line commenting feature that is implemented
in popular code hosting site like GitHub, BitBucket or Kallithea.
People often want to know what they are working on *now*. As part of
this, they also commonly want to know how that work is related to other
changesets in the repo so they can perform common actions like rebase,
histedit, and merge.
`hg show work` made headway into this space. However, it is geared
towards a complete repo view as opposed to just the current line of
work. If you have a lot of in-flight work or the repo has many heads,
the output can be overwhelming. The closest thing Mercurial has to
"show me the current thing I'm working on" that doesn't require custom
revsets is `hg qseries`. And this requires MQ, which completely changes
workflows and repository behavior and has horrible performance on large
repos. But as sub-optimal as MQ is, it does some things right, such as
expose a model of the repo that is easy for people to reason about.
This simplicity is why I think a lot of people prefer to use MQ, despite
its shortcomings.
One common development workflow is to author a series of linear
changesets, using bookmarks, branches, anonymous heads, or even topics
(3rd party extension). I'll call this a "stack." You periodically
rewrite history in place (using `hg histedit`) and reparent the stack
against newer changesets (using `hg rebase`). This workflow can be
difficult because there is no obvious way to quickly see the current
"stack" nor its relation to other changesets. Figuring out arguments to
`hg rebase` can be difficult and may require highlighting and pasting
multiple changeset nodes to construct a command.
The goal of this commit is to make stack based workflows simpler
by exposing a view of the current stack and its relationship to
other releant changesets, notably the parent of the base changeset
in the stack and newer heads that the stack could be rebased or merged
into.
Introduced is the `hg show stack` view. Essentially, it finds all
mutable changesets from the working directory revision in both
directions, stopping at a merge or branch point. This limits the
revisions to a DAG linear range.
The stack is rendered as a concise list of changesets. Alongside the
stack is a visualization of the DAG, similar to `hg log -G`.
Newer public heads from the branch point of the stack are rendered
above the stack. The presence of these heads helps people understand
the DAG model and the relationship between the stack and changes made
since the branch point of that stack. If the "rebase" command is
available, a `hg rebase` command is printed for each head so a user
can perform a simple copy and paste to perform a rebase.
This view is alpha quality. There are tons of TODOs documented
inline. But I think it is good enough for a first iteration.
This commit addresses a number of deficiencies in `hg show work`'s
output:
* Failure to render tags (it just wasn't implemented)
* Failure to render names associated with non-built-in namespaces
(e.g. remotenames)
* Color names were hardcoded instead of coming from the canonical
source in the namespace
This change has the intended effect of rendering tags and extra
namespaces. It solves an immediate need at Mozilla of having
names from a custom namespace printed, which is blocking us from
switching from a custom `hg wip` revset/template combo to `hg show
work`.
Note that the order of branches and bookmarks changes. This is
because bookmarks are registered before branches in namespaces.py.
We may want to register them last, after tags and branches. Or we
may want to added a weighted field to the namespace to control
display order. Something to think about.
I'm not a big fan of the complexity in the templating layer. There
is a lot of code to basically filter out the special case of
branch=='default' and tag=='tip'. Ideally, we would iterate over
a data structure that had irrelevant/unwanted names pre-filtered.
However, I wasn't sure how to best implement this. We probably
want {namespaces} to emit everything (its current behavior). I
was toying with the following:
* {namespacesnondefaults} variation that filtered values
* A filter function that operated on {namespaces} (I wasn't sure
how to implement this since the filtering layer would see a
"hybrid" instance as opposed to something that was definitely
an iterable of namespaces.)
* A namespaces(...) function where you could specify which values
to return. I like this the most. But it really wants named
arguments to control filtering and we only support named arguments
on revsets, not templates.
I figure perfect is the enemy of good and we can refine templating
support for namespaces in the future. At least now we have a
concrete example of a use case.
Previously, we constructed a formatter from a specific template
topic. Then from show() we reached into the internals of the
formatter to resolve a template string to be used to construct
a changeset templater.
A downside to this approach was it limited us to having the
entire template defined in a single entry in the map file. You
couldn't reference other entries in the map file and this would
lead to long templates and redundancy in the map file.
This commit teaches @showview how to instantiate a changeset
templater so we can construct a templater with full access to
the map file. To prove it works, we've split "showwork" into
components.
Add the followlines.js script and corresponding parameters as data attribute
on <tbody class="sourcelines"> element.
Extend CSS rules so that they also match the DOM structure of annotate view.
As previously, only address paper and gitweb styles (other styles do not have
followlines at all).
While plugging followlines.js into "annotate" view, we'll need to walk a
different DOM structure from that of "filerevision" view. In particular, the
selectable source line element is a <tr> in annotate view (in contrast with a
<span> in filerevision view). So make this tag name a parameter of
followlines.js script by passing its value as a "selectabletag" data attribute
of <pre class="sourcelines"> element.
As <pre class="sourcelines"> tags are getting quite long in templates, rewrite
them on several lines.
We will use this element to hook data attribute for the followlines.js script
to be plugged in annotate view. Also this gets symmetrical with paper style
which already has a <tbody> element.
c0593b622180 changed the styling of the "page_nav" CSS class to use
flexbox to separate elements within the <div>. I didn't realize that
this class was used outside of the links in the header. So this
resulted in incorrectly formatting links in the footer of various
pages. Fix that by introducing a new CSS class that preserves the
old CSS behavior.
gitweb was missing the hint hover box. So that was added.
Also, the positioning of the form was absolute and it didn't
vertically align on all pages. The element has been moved inline
with the navigation links (which now are contained in a div) and
flexbox is used to obtain sane alignment of the navigation links
and search form. For those new to flexbox,
"justify-content: space-between" basically says to maximize space
elements. You can use it to easily get left and right justified
containers without having to worry about width, floating, etc.
"align-items: center" centers all items in a cross-axis. I've
literally wasted hours trying to figure out both these problems
before flexbox. Flexbox is amazing.
Flexbox has been supported by Chrome and Firefox for a few years.
But it is only supported by IE 11. I'm willing to wager that
people using this either won't be using IE or will be using IE 11.
So I'm willing to be a bit aggressive in adopting flexbox because
it makes CSS alignment so much easier.
Paper has it on all pages. Not sure why gitweb doesn't. I think it
should be everywhere because it is a useful feature.
Also, we weren't consistently adding the HTML in the same place. This
was OK since the element is absolutely positioned. But this bothered
me a bit, so I went ahead and fixed it.
AFAICT this was mostly a bunch of copy pasta. The only variation is
some pages defined a "value" attribute. The "query" variable will
just be empty on pages that don't accept it. So let's consolidate
the template and remove the redundancy.