Patchwork [RFC] hgweb: code selection without line numbers in file source view

login
register
mail settings
Submitter Alexander Plavin
Date July 2, 2013, 10:16 p.m.
Message ID <bc3e72c2e619659e7cd7.1372803364@debian-alexander.dolgopa>
Download mbox | patch
Permalink /patch/1784/
State Superseded, archived
Headers show

Comments

Alexander Plavin - July 2, 2013, 10:16 p.m.
# HG changeset patch
# User Alexander Plavin <me@aplavin.ru>
# Date 1372180221 -14400
#      Tue Jun 25 21:10:21 2013 +0400
# Node ID bc3e72c2e619659e7cd73f28aa95dd27dd7d3812
# Parent  d7b4aa1049d3fbbc2b8d24114afad82586c49db3
hgweb: code selection without line numbers in file source view

File code is presented as HTML ordered list, so that
line numbers are not selected with the code itself.

There are different possible strategies to implement the source code view,
and they have different pros/cons. Here follows a simple comparison table for
possible implementations:

Strategy             FF              Chrome

current             D,LT,E,T,L        D,L
pre                 S,NW              S,NW
pre/div/nbsp        LT,E,T,TS,NW      TS,NW
pre/div/br          LT,E,T,NW         NW
ol/li/nbsp          LT,E,T,TS,AJ      TS,AJ
ol/li/br            LT,E,T,AJ         AJ

Legend

Strategies:
- current: implemented in hgweb before this patch, i.e. divs for each line,
and line numbers links in the div too
- pre: the whole code in one pre tag with newlines, all line numbers
in another one with 'float: left'
- pre/div/{nbsp,br}: same as just 'pre', but separate divs for each line and
&nbsp; or <br> instead of empty lines (otherwise they are not copied at all)
- ol/li/{nbsp,br}: a single ol with li's and divs for each line,
&nbsp; or <br> same as in previous strategy

Problems:
D = (very minor) display problems, like wrong width of leading tabs
LT = loses leading/trailing whitespace
E = loses embedded whitespace
B = loses blank lines
T = loses tabs
L = selects line numbers
S = no stripes (and no ability to easily highlight
lines-which-are-linked-at in the future)
TS = space copied instead of empty line
AJ = get anchor links only with JS (they work even without)
NW = no linewrap easily possible (in future)


Also, this patch changes the visual appearance of the source a little:
- line numbers have dots after them
- line numbers don't have the stripey background
- 'line source' heading above the source lines removed
- line numbers and lines have a vertical line between them
  for better distinction
Martin Geisler - July 3, 2013, 9:50 a.m.
Alexander Plavin <me@aplavin.ru> writes:

> # HG changeset patch
> # User Alexander Plavin <me@aplavin.ru>
> # Date 1372180221 -14400
> #      Tue Jun 25 21:10:21 2013 +0400
> # Node ID bc3e72c2e619659e7cd73f28aa95dd27dd7d3812
> # Parent  d7b4aa1049d3fbbc2b8d24114afad82586c49db3
> hgweb: code selection without line numbers in file source view
>
> File code is presented as HTML ordered list, so that
> line numbers are not selected with the code itself.
>
> There are different possible strategies to implement the source code view,
> and they have different pros/cons. Here follows a simple comparison table for
> possible implementations:
>
> Strategy             FF              Chrome
>
> current             D,LT,E,T,L        D,L
> pre                 S,NW              S,NW
> pre/div/nbsp        LT,E,T,TS,NW      TS,NW
> pre/div/br          LT,E,T,NW         NW
> ol/li/nbsp          LT,E,T,TS,AJ      TS,AJ
> ol/li/br            LT,E,T,AJ         AJ
>
> Legend
>
> Strategies:
> - current: implemented in hgweb before this patch, i.e. divs for each line,
> and line numbers links in the div too
> - pre: the whole code in one pre tag with newlines, all line numbers
> in another one with 'float: left'
> - pre/div/{nbsp,br}: same as just 'pre', but separate divs for each line and
> &nbsp; or <br> instead of empty lines (otherwise they are not copied at all)
> - ol/li/{nbsp,br}: a single ol with li's and divs for each line,
> &nbsp; or <br> same as in previous strategy

It is not clear to me if you have tried to simply use this strategy
coupled with CSS that adds line numbers and colors the rows:

 <pre>
    <a id="l1" href="#l1">   the line  </a>
 </pre>

That seems to work when I test it in Firefox and Chrome and supports
leading TABs, line links, highlighing the current line, styling the page
numbers independently, etc. There is a full example below -- try
clicking on differnet lines and try copy-pasting it of course.

The question is if :before, :nth-child, and :target is supported by
enough browsers. There are statistics here:

  http://caniuse.com/#feat=css-gencontent (:before)
  http://caniuse.com/#feat=css-sel3 (:nth-child, :target)

In both cases, they say that 87% of visitors should be able to see the
whole thing. If a browser doesn't support CSS generated content the line
numbers disappear, if it doesn't support CSS3 selectors, the highlight
on the linked line go away (but you can still link to it).

The version below wraps long lines, and when doing so the wrapped line
begins below the line number. I'm not sure that is a problem. Change
'white-space: pre-wrap' to 'overflow-x: hidden' to make the lines be cut
off where the background color ends (instead of bleeding out into the
parge margin).


<html>
<head>
    <style>
        pre > a {
            display: inline-block;
            width: 100%;
            white-space: pre-wrap;
            text-decoration: none;
            counter-increment: lineno;
        }
        pre > a:before {
            display: inline-block;
            width: 2em;
            margin-right: 1em;
            font-size: small;
            font-style: italic;
            text-align: right;
            content: counter(lineno);
        }
        pre > a:nth-child(even) {
            background-color: lightgrey;
        }
        pre > a:target {
            background-color: yellow;
        }
    </style>
</head>
<body>

    <p>Text before</p>

<pre>
<a id="l1" href="#l1">	Leading tab</a>
<a id="l2" href="#l2">  Leading whitespace</a>
<a id="l3" href="#l3">Trailing whitespace:   </a>
<a id="l4" href="#l4">Embedded   whitespace</a>
<a id="l5" href="#l5">Embedded	tab.</a>
<a id="l6" href="#l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</a>
<a id="l7" href="#l7">Trailing whitespace!   </a>
<a id="l8" href="#l8">More trailing whitespace...   </a>
</pre>

    <p>Text after</p>

</body>

</html>
Alexander Plavin - July 3, 2013, 10:06 a.m.
In this case the whole lines are links, which makes it impossible to
select a random region (at least I couldn't do it) and isn't a good thing
anyway as for me. Also, both embedded and leading tabs are lost on
copy (tried several times, as you state the opposite, but same
result).

2013/7/3 Martin Geisler <martin@geisler.net>:
> Alexander Plavin <me@aplavin.ru> writes:
>
>> # HG changeset patch
>> # User Alexander Plavin <me@aplavin.ru>
>> # Date 1372180221 -14400
>> #      Tue Jun 25 21:10:21 2013 +0400
>> # Node ID bc3e72c2e619659e7cd73f28aa95dd27dd7d3812
>> # Parent  d7b4aa1049d3fbbc2b8d24114afad82586c49db3
>> hgweb: code selection without line numbers in file source view
>>
>> File code is presented as HTML ordered list, so that
>> line numbers are not selected with the code itself.
>>
>> There are different possible strategies to implement the source code view,
>> and they have different pros/cons. Here follows a simple comparison table for
>> possible implementations:
>>
>> Strategy             FF              Chrome
>>
>> current             D,LT,E,T,L        D,L
>> pre                 S,NW              S,NW
>> pre/div/nbsp        LT,E,T,TS,NW      TS,NW
>> pre/div/br          LT,E,T,NW         NW
>> ol/li/nbsp          LT,E,T,TS,AJ      TS,AJ
>> ol/li/br            LT,E,T,AJ         AJ
>>
>> Legend
>>
>> Strategies:
>> - current: implemented in hgweb before this patch, i.e. divs for each line,
>> and line numbers links in the div too
>> - pre: the whole code in one pre tag with newlines, all line numbers
>> in another one with 'float: left'
>> - pre/div/{nbsp,br}: same as just 'pre', but separate divs for each line and
>> &nbsp; or <br> instead of empty lines (otherwise they are not copied at all)
>> - ol/li/{nbsp,br}: a single ol with li's and divs for each line,
>> &nbsp; or <br> same as in previous strategy
>
> It is not clear to me if you have tried to simply use this strategy
> coupled with CSS that adds line numbers and colors the rows:
>
>  <pre>
>     <a id="l1" href="#l1">   the line  </a>
>  </pre>
>
> That seems to work when I test it in Firefox and Chrome and supports
> leading TABs, line links, highlighing the current line, styling the page
> numbers independently, etc. There is a full example below -- try
> clicking on differnet lines and try copy-pasting it of course.
>
> The question is if :before, :nth-child, and :target is supported by
> enough browsers. There are statistics here:
>
>   http://caniuse.com/#feat=css-gencontent (:before)
>   http://caniuse.com/#feat=css-sel3 (:nth-child, :target)
>
> In both cases, they say that 87% of visitors should be able to see the
> whole thing. If a browser doesn't support CSS generated content the line
> numbers disappear, if it doesn't support CSS3 selectors, the highlight
> on the linked line go away (but you can still link to it).
>
> The version below wraps long lines, and when doing so the wrapped line
> begins below the line number. I'm not sure that is a problem. Change
> 'white-space: pre-wrap' to 'overflow-x: hidden' to make the lines be cut
> off where the background color ends (instead of bleeding out into the
> parge margin).
>
>
> <html>
> <head>
>     <style>
>         pre > a {
>             display: inline-block;
>             width: 100%;
>             white-space: pre-wrap;
>             text-decoration: none;
>             counter-increment: lineno;
>         }
>         pre > a:before {
>             display: inline-block;
>             width: 2em;
>             margin-right: 1em;
>             font-size: small;
>             font-style: italic;
>             text-align: right;
>             content: counter(lineno);
>         }
>         pre > a:nth-child(even) {
>             background-color: lightgrey;
>         }
>         pre > a:target {
>             background-color: yellow;
>         }
>     </style>
> </head>
> <body>
>
>     <p>Text before</p>
>
> <pre>
> <a id="l1" href="#l1">  Leading tab</a>
> <a id="l2" href="#l2">  Leading whitespace</a>
> <a id="l3" href="#l3">Trailing whitespace:   </a>
> <a id="l4" href="#l4">Embedded   whitespace</a>
> <a id="l5" href="#l5">Embedded  tab.</a>
> <a id="l6" href="#l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</a>
> <a id="l7" href="#l7">Trailing whitespace!   </a>
> <a id="l8" href="#l8">More trailing whitespace...   </a>
> </pre>
>
>     <p>Text after</p>
>
> </body>
>
> </html>
>
>
> --
> Martin Geisler
Martin Geisler - July 3, 2013, 12:05 p.m.
Alexander Plavin <me@aplavin.ru> writes:

(You're top-posting. It is more convenient if you put your comments
after the thing they apply to.)

> In this case the whole lines are links, which makes it impossible to
> select a random region (at least I couldn't do it) and isn't a good
> thing anyway as for me. Also, both embedded and leading tabs are lost
> on copy (tried several times, as you state the opposite, but same
> result).

Okay, you have a good point about the links making the text
un-selectable. What do you think about the version below where we use
JavaScript to install a click handler? I can mark text anywhere and when
doing so the URL is updated to include the relevant ID, so that one can
copy-paste the URL.

<html>
<head>
    <style>
        pre > span {
            display: inline-block;
            width: 100%;
            white-space: pre-wrap;
            counter-increment: lineno;
        }
        pre > span:before {
            display: inline-block;
            width: 2em;
            margin-right: 1em;
            font-size: small;
            font-style: italic;
            text-align: right;
            content: counter(lineno);
        }
        pre > span:nth-child(even) {
            background-color: lightgrey;
        }
        pre > span:target {
            background-color: yellow;
        }
    </style>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $("pre").on("click", "span", function (e) {
                window.location = "#" + this.id;
            });
        });
    </script>
</head>
<body>

    <p>Text before</p>

<pre>
<span id="l1">	Leading tab:  x</span>
<span id="l2">  Leading whitespace!</span>
<span id="l3">Trailing whitespace!   </span>
<span id="l4">More trailing whitespace...   </span>
<span id="l5">Embedded	tab.</span>
<span id="l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</span>
<span id="l7">Trailing whitespace!   </span>
<span id="l8">More trailing whitespace...   </span>
</pre>

    <p>Text after</p>

</body>

</html>
Alexander Plavin - July 3, 2013, 12:23 p.m.
Actually, this seems quite nice for me. Waiting for others to give
their opinion.

2013/7/3 Martin Geisler <martin@geisler.net>:
> Alexander Plavin <me@aplavin.ru> writes:
>
> (You're top-posting. It is more convenient if you put your comments
> after the thing they apply to.)
>
>> In this case the whole lines are links, which makes it impossible to
>> select a random region (at least I couldn't do it) and isn't a good
>> thing anyway as for me. Also, both embedded and leading tabs are lost
>> on copy (tried several times, as you state the opposite, but same
>> result).
>
> Okay, you have a good point about the links making the text
> un-selectable. What do you think about the version below where we use
> JavaScript to install a click handler? I can mark text anywhere and when
> doing so the URL is updated to include the relevant ID, so that one can
> copy-paste the URL.
>
> <html>
> <head>
>     <style>
>         pre > span {
>             display: inline-block;
>             width: 100%;
>             white-space: pre-wrap;
>             counter-increment: lineno;
>         }
>         pre > span:before {
>             display: inline-block;
>             width: 2em;
>             margin-right: 1em;
>             font-size: small;
>             font-style: italic;
>             text-align: right;
>             content: counter(lineno);
>         }
>         pre > span:nth-child(even) {
>             background-color: lightgrey;
>         }
>         pre > span:target {
>             background-color: yellow;
>         }
>     </style>
>
>     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
>     <script type="text/javascript">
>         $(document).ready(function () {
>             $("pre").on("click", "span", function (e) {
>                 window.location = "#" + this.id;
>             });
>         });
>     </script>
> </head>
> <body>
>
>     <p>Text before</p>
>
> <pre>
> <span id="l1">  Leading tab:  x</span>
> <span id="l2">  Leading whitespace!</span>
> <span id="l3">Trailing whitespace!   </span>
> <span id="l4">More trailing whitespace...   </span>
> <span id="l5">Embedded  tab.</span>
> <span id="l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</span>
> <span id="l7">Trailing whitespace!   </span>
> <span id="l8">More trailing whitespace...   </span>
> </pre>
>
>     <p>Text after</p>
>
> </body>
>
> </html>
>
>
> --
> Martin Geisler
Jordi Gutiérrez Hermoso - July 3, 2013, 2:19 p.m.
On 3 July 2013 08:23, Alexander Plavin <me@aplavin.ru> wrote:
> Actually, this seems quite nice for me. Waiting for others to give
> their opinion.

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

- Jordi G. H.
Matt Mackall - July 3, 2013, 4:01 p.m.
On Wed, 2013-07-03 at 14:05 +0200, Martin Geisler wrote:
> Alexander Plavin <me@aplavin.ru> writes:
> 
> (You're top-posting. It is more convenient if you put your comments
> after the thing they apply to.)
> 
> > In this case the whole lines are links, which makes it impossible to
> > select a random region (at least I couldn't do it) and isn't a good
> > thing anyway as for me. Also, both embedded and leading tabs are lost
> > on copy (tried several times, as you state the opposite, but same
> > result).
> 
> Okay, you have a good point about the links making the text
> un-selectable. What do you think about the version below where we use
> JavaScript to install a click handler? I can mark text anywhere and when
> doing so the URL is updated to include the relevant ID, so that one can
> copy-paste the URL.

This approach looks very promising indeed.

Can we avoid pulling in jquery? 
Can we make the line numbers anchor links?
Alexander Plavin - July 3, 2013, 4:07 p.m.
2013/7/3 Matt Mackall <mpm@selenic.com>:
> On Wed, 2013-07-03 at 14:05 +0200, Martin Geisler wrote:
>> Alexander Plavin <me@aplavin.ru> writes:
>>
>> (You're top-posting. It is more convenient if you put your comments
>> after the thing they apply to.)
>>
>> > In this case the whole lines are links, which makes it impossible to
>> > select a random region (at least I couldn't do it) and isn't a good
>> > thing anyway as for me. Also, both embedded and leading tabs are lost
>> > on copy (tried several times, as you state the opposite, but same
>> > result).
>>
>> Okay, you have a good point about the links making the text
>> un-selectable. What do you think about the version below where we use
>> JavaScript to install a click handler? I can mark text anywhere and when
>> doing so the URL is updated to include the relevant ID, so that one can
>> copy-paste the URL.
>
> This approach looks very promising indeed.
>
> Can we avoid pulling in jquery?

Of course, it's used in this example just for simplicity.

> Can we make the line numbers anchor links?

According to the CSS documentation, it's not possible with 'content' property.

>
> --
> Mathematics is the supreme nostalgia of our time.
>
>
Laurens Holst - July 3, 2013, 4:22 p.m.
Op 03-07-13 14:05, Martin Geisler schreef:
> Alexander Plavin <me@aplavin.ru> writes:
>
> (You're top-posting. It is more convenient if you put your comments
> after the thing they apply to.)
>
>> In this case the whole lines are links, which makes it impossible to
>> select a random region (at least I couldn't do it) and isn't a good
>> thing anyway as for me. Also, both embedded and leading tabs are lost
>> on copy (tried several times, as you state the opposite, but same
>> result).
> Okay, you have a good point about the links making the text
> un-selectable. What do you think about the version below where we use
> JavaScript to install a click handler? I can mark text anywhere and when
> doing so the URL is updated to include the relevant ID, so that one can
> copy-paste the URL.

If it fixes the copy/pasting of white space, sounds great.

However, in terms of the click handling, I'd like to refer to my earlier 
mail:

http://selenic.com/pipermail/mercurial-devel/2013-May/051431.html

" I don't like that the screen jumps when you select something. I like 
to select where I'm reading so I don't lose track, and this heavily 
interferes with that. It would be better if only clicking on the line 
number would change the target."

I think the way Alexander implemented the click handler after that was nice.

~Laurens
Alexander Plavin - July 3, 2013, 4:49 p.m.
2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
> Op 03-07-13 14:05, Martin Geisler schreef:
>
> Alexander Plavin <me@aplavin.ru> writes:
>
> (You're top-posting. It is more convenient if you put your comments
> after the thing they apply to.)
>
> In this case the whole lines are links, which makes it impossible to
> select a random region (at least I couldn't do it) and isn't a good
> thing anyway as for me. Also, both embedded and leading tabs are lost
> on copy (tried several times, as you state the opposite, but same
> result).
>
> Okay, you have a good point about the links making the text
> un-selectable. What do you think about the version below where we use
> JavaScript to install a click handler? I can mark text anywhere and when
> doing so the URL is updated to include the relevant ID, so that one can
> copy-paste the URL.
>
>
> If it fixes the copy/pasting of white space, sounds great.
>
> However, in terms of the click handling, I’d like to refer to my earlier
> mail:
>
> http://selenic.com/pipermail/mercurial-devel/2013-May/051431.html
>
> “ I don’t like that the screen jumps when you select something. I like to
> select where I’m reading so I don’t lose track, and this heavily interferes
> with that. It would be better if only clicking on the line number would
> change the target.”

Using this strategy there are no unexpected jumps. You can look at
this at hg.aplavin.ru :)

>
> I think the way Alexander implemented the click handler after that was nice.
>
> ~Laurens
>
Laurens Holst - July 3, 2013, 5:02 p.m.
Op 03-07-13 18:49, Alexander Plavin schreef:
> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>> “ I don’t like that the screen jumps when you select something. I like to
>> select where I’m reading so I don’t lose track, and this heavily interferes
>> with that. It would be better if only clicking on the line number would
>> change the target.”
> Using this strategy there are no unexpected jumps. You can look at
> this at hg.aplavin.ru :)

Thanks for pointing me to it.

I think it is the same as it was before, it jumps when you deselect... 
So it still interferes with me :). I’d rather prefer that just the line 
numbers were clickable, the way it works now.

You could communicate this to the user by styling the :before like a 
link when hovered (I suggest blue / underlined like a link, with hand 
cursor). That’d even be an improvement over the current situation where 
we provide no visual clues of this feature.

~Laurens
Alexander Plavin - July 3, 2013, 5:16 p.m.
2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
> Op 03-07-13 18:49, Alexander Plavin schreef:
>>
>> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>>
>>> “ I don’t like that the screen jumps when you select something. I like to
>>> select where I’m reading so I don’t lose track, and this heavily
>>> interferes
>>> with that. It would be better if only clicking on the line number would
>>> change the target.”
>>
>> Using this strategy there are no unexpected jumps. You can look at
>> this at hg.aplavin.ru :)
>
>
> Thanks for pointing me to it.
>
> I think it is the same as it was before, it jumps when you deselect... So it
> still interferes with me :). I’d rather prefer that just the line numbers
> were clickable, the way it works now.

It's impossible to add click handler just to the :before pseudo
element. However, I haven't noticed this before you told, as I
unselected by clicking not at the code.

>
> You could communicate this to the user by styling the :before like a link
> when hovered (I suggest blue / underlined like a link, with hand cursor).
> That’d even be an improvement over the current situation where we provide no
> visual clues of this feature.
>
> ~Laurens
>
Martin Geisler - July 3, 2013, 10:25 p.m.
Alexander Plavin <me@aplavin.ru> writes:

> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>> Op 03-07-13 18:49, Alexander Plavin schreef:
>>>
>>> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>>>
>>>> “ I don’t like that the screen jumps when you select something. I like to
>>>> select where I’m reading so I don’t lose track, and this heavily
>>>> interferes
>>>> with that. It would be better if only clicking on the line number would
>>>> change the target.”
>>>
>>> Using this strategy there are no unexpected jumps. You can look at
>>> this at hg.aplavin.ru :)
>>
>>
>> Thanks for pointing me to it.
>>
>> I think it is the same as it was before, it jumps when you deselect... So it
>> still interferes with me :). I’d rather prefer that just the line numbers
>> were clickable, the way it works now.
>
> It's impossible to add click handler just to the :before pseudo
> element.

Yes, I learned today that the pseudo elements exist outside the normal
DOM. However, we can add an element in the dom...

> However, I haven't noticed this before you told, as I
> unselected by clicking not at the code.

The version below uses no JavaScript and only lets you click in the
first 30px of each line. I've only tested it in Firefox where it seems
to work well. I experimented a bit to see if I could influence the line
numbers when hovering on the a elements, e.g., to add an underline, but
I didn't figure out a way to do that.


<html>
<head>
    <style>
        pre {
            position: relative;
        }
        pre span {
            display: inline-block;
            width: 100%;
            white-space: pre-wrap;
            counter-increment: lineno;
        }
        pre span:before {
            display: inline-block;
            width: 30px;
            margin-right: 1em;
            font-size: small;
            font-style: italic;
            text-align: right;
            content: counter(lineno);
        }
        pre span:nth-child(4n+1) {
            background-color: lightgrey;
        }
        pre span:target {
            background-color: yellow;
        }
        pre a {
            display: inline-block;
            position: absolute;
            left: 0px;
            width: 30px;
            height: 2ex;
            outline: thin dashed red;
        }
    </style>
</head>
<body>
    <p>Text before</p>
<pre>
<span id="l1">	Leading tab</span><a href="#l1"></a>
<span id="l2">  Leading whitespace</span><a href="#l2"></a>
<span id="l3">Trailing whitespace:   </span><a href="#l3"></a>
<span id="l4">More trailing whitespace...   </span><a href="#l4"></a>
<span id="l5">Embedded	tab.</span><a href="#l5"></a>
<span id="l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</span><a href="#l6"></a>
<span id="l7">Trailing whitespace!   </span><a href="#l7"></a>
<span id="l8">More trailing whitespace...   </span><a href="#l8"></a>
</pre>
    <p>Text after</p>
</body>
</html>
Alexander Plavin - July 4, 2013, 4:35 p.m.
2013/7/4 Martin Geisler <martin@geisler.net>:
> Alexander Plavin <me@aplavin.ru> writes:
>
>> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>>> Op 03-07-13 18:49, Alexander Plavin schreef:
>>>>
>>>> 2013/7/3 Laurens Holst <laurens.nospam@grauw.nl>:
>>>>
>>>>> “ I don’t like that the screen jumps when you select something. I like to
>>>>> select where I’m reading so I don’t lose track, and this heavily
>>>>> interferes
>>>>> with that. It would be better if only clicking on the line number would
>>>>> change the target.”
>>>>
>>>> Using this strategy there are no unexpected jumps. You can look at
>>>> this at hg.aplavin.ru :)
>>>
>>>
>>> Thanks for pointing me to it.
>>>
>>> I think it is the same as it was before, it jumps when you deselect... So it
>>> still interferes with me :). I’d rather prefer that just the line numbers
>>> were clickable, the way it works now.
>>
>> It's impossible to add click handler just to the :before pseudo
>> element.
>
> Yes, I learned today that the pseudo elements exist outside the normal
> DOM. However, we can add an element in the dom...
>
>> However, I haven't noticed this before you told, as I
>> unselected by clicking not at the code.
>
> The version below uses no JavaScript and only lets you click in the
> first 30px of each line. I've only tested it in Firefox where it seems
> to work well. I experimented a bit to see if I could influence the line
> numbers when hovering on the a elements, e.g., to add an underline, but
> I didn't figure out a way to do that.

As for me, it seems perfect as there is no change in accessibility and
visual appearance (if we don't enable line wrapping) compared to the
current hgweb, but all the benefits which were expected. I've tried to
implement something similar (i.e. CSS-generated numbers) at the
beginning, but didn't succeed finally. Today I have sent a patch with
such implementation (and, as usually, made it available at
hg.aplavin.ru), as it doesn't require any compromises as in
http://www.selenic.com/pipermail/mercurial-devel/2013-July/051834.html.

>
>
> <html>
> <head>
>     <style>
>         pre {
>             position: relative;
>         }
>         pre span {
>             display: inline-block;
>             width: 100%;
>             white-space: pre-wrap;
>             counter-increment: lineno;
>         }
>         pre span:before {
>             display: inline-block;
>             width: 30px;
>             margin-right: 1em;
>             font-size: small;
>             font-style: italic;
>             text-align: right;
>             content: counter(lineno);
>         }
>         pre span:nth-child(4n+1) {
>             background-color: lightgrey;
>         }
>         pre span:target {
>             background-color: yellow;
>         }
>         pre a {
>             display: inline-block;
>             position: absolute;
>             left: 0px;
>             width: 30px;
>             height: 2ex;
>             outline: thin dashed red;
>         }
>     </style>
> </head>
> <body>
>     <p>Text before</p>
> <pre>
> <span id="l1">  Leading tab</span><a href="#l1"></a>
> <span id="l2">  Leading whitespace</span><a href="#l2"></a>
> <span id="l3">Trailing whitespace:   </span><a href="#l3"></a>
> <span id="l4">More trailing whitespace...   </span><a href="#l4"></a>
> <span id="l5">Embedded  tab.</span><a href="#l5"></a>
> <span id="l6">Very, very, long, very, long, very, long, very, long, very, long, long line...</span><a href="#l6"></a>
> <span id="l7">Trailing whitespace!   </span><a href="#l7"></a>
> <span id="l8">More trailing whitespace...   </span><a href="#l8"></a>
> </pre>
>     <p>Text after</p>
> </body>
> </html>
>
> --
> Martin Geisler

Patch

diff -r d7b4aa1049d3 -r bc3e72c2e619 mercurial/templates/paper/filerevision.tmpl
--- a/mercurial/templates/paper/filerevision.tmpl	Sat Jun 29 14:36:51 2013 +0400
+++ b/mercurial/templates/paper/filerevision.tmpl	Tue Jun 25 21:10:21 2013 +0400
@@ -67,8 +67,10 @@ 
 </table>
 
 <div class="overflow">
-<div class="sourcefirst"> line source</div>
+<div class="sourcefirst"></div>
+<ol class="sourcelines">
 {text%fileline}
+</ol>
 <div class="sourcelast"></div>
 </div>
 </div>
diff -r d7b4aa1049d3 -r bc3e72c2e619 mercurial/templates/paper/map
--- a/mercurial/templates/paper/map	Sat Jun 29 14:36:51 2013 +0400
+++ b/mercurial/templates/paper/map	Tue Jun 25 21:10:21 2013 +0400
@@ -72,7 +72,7 @@ 
 filecomparison = filecomparison.tmpl
 filelog = filelog.tmpl
 fileline = '
-  <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
+  <li class="parity{parity} source" id="{lineid}"><div>{nonempty(strip(line|escape, '\r\n'), '<br/>')}</div></li>'
 filelogentry = filelogentry.tmpl
 
 annotateline = '
diff -r d7b4aa1049d3 -r bc3e72c2e619 mercurial/templates/static/style-paper.css
--- a/mercurial/templates/static/style-paper.css	Sat Jun 29 14:36:51 2013 +0400
+++ b/mercurial/templates/static/style-paper.css	Tue Jun 25 21:10:21 2013 +0400
@@ -209,6 +209,38 @@ 
 .source a { color: #999; font-size: smaller; font-family: monospace;}
 .bottomline { border-bottom: 1px solid #999; }
 
+div.source, td.source { padding: 1px 4px; }
+
+ol.sourcelines {
+  background-color: #eee;
+  font-size: 90%;
+  margin: 0;
+  padding-left: 50px;
+}
+
+li.source {
+  -moz-user-select: -moz-none;
+  -khtml-user-select: none;
+  -webkit-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  color: #999;
+  padding: 0 5px;
+}
+
+li.source div {
+  -moz-user-select: text;
+  -khtml-user-select: text;
+  -webkit-user-select: text;
+  -ms-user-select: text;
+  user-select: text;
+  padding: 1px 5px;
+  border-left: 1px solid #ccc;
+  margin: 0 0 0 -7px;
+  color: #000;
+  font-size: 111%;
+}
+
 .fileline { font-family: monospace; }
 .fileline img { border: 0; }