Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap source lines and re-implement line numbers #14

Merged
merged 13 commits into from
Sep 9, 2017

Conversation

dbaynard
Copy link
Contributor

Fixes #13. Would be good to get into pandoc 2.0. From the changelog:

  • Wrap lines of source code in a div with display set to inline-block.
    The divs make per-line processing easier. They cannot be set as
    display: block as that introduces extra new lines when copying and pasting.
  • Render line numbers in html using css pseudo elements rather than a table.
    The line numbers are always produced, as data-line-number attributes, and
    css to display them as ::before elements are always produced. The option to
    switch on line numbering only toggles a class; this means it is possible to toggle
    line numbering without re-running skylighting.
  • If the linkAnchors option is set, wrap with an a element rather than a div,
    set so that clicking the line number (and only the line number) will jump to that
    line.
  • Code wraps by default when html is printed, with wrapped lines indented.

The new output with no line numbers

skylighting-no-lines

and with line numbers

skylighting-lines

The code matches all features of the previous, table base code, with one exception: previously, copying code from a printed pdf didn't pick up the line markers, but now it does. However, I have judged the changes are worth it, as copying from a pdf also gets line breaks wrong so is inherently imperfect.

@jgm
Copy link
Owner

jgm commented Aug 27, 2017

Can you comment on browser support? Can we rely on these features being available in browsers?

@jgm
Copy link
Owner

jgm commented Aug 27, 2017

The basic approach looks pretty clean; I guess my worries are (a) breaking existing templates that hard-code CSS (maybe acceptable, since it's better not to hard-code highlighting CSS, and going forward we have a way to define custom styles), and (b) browser support.

@jgm
Copy link
Owner

jgm commented Aug 27, 2017

I notice that with line numbers, there is also much more space between lines. Can this be fixed so that toggling line numbers doesn't change the line spacing?

@dbaynard
Copy link
Contributor Author

dbaynard commented Aug 27, 2017

I'll check the browser support shortly, and have a think about existing css. As for the line spacing, it has to be set to avoid the numbers collapsing. I can set them both to the same, though do note it's set using min-height so long lines will break correctly. What do you think?

Actually, we could add an option to wrap the lines or not so both behaviours are available, when not using line numbers. How does that sound?

@dbaynard
Copy link
Contributor Author

According to caniuse everything is supported with good coverage. I suspect screen readers don't read the numbers (I don't know how to test this) but the previous way of adding line numbers using a table likely suffered a similar problem.

I'd also like to use clay for the (limited) css generation here as it's currently quite ad-hoc (and easy to introduce bugs) — I'll raise a separate issue. That would ensure the correct browser prefixes are supplied.

Adding an option with both behaviours means touching the definition of FormatOptions. I can do it, but it might not be worthwhile — your call.

@jgm
Copy link
Owner

jgm commented Aug 28, 2017 via email

@jgm
Copy link
Owner

jgm commented Aug 28, 2017 via email

@jgm
Copy link
Owner

jgm commented Aug 28, 2017 via email

@dbaynard
Copy link
Contributor Author

By 'both behaviours' I mean wrapping each line of output in a div, or not: the act of wrapping breaks any css which relies on code > span (direct children).

When each line of displayed code is wrapped in an element it is possible to style it using css, but the element must be added during html generation by skylighting.

The change would be adding a new command line option restoring the non-wrapping behaviour (I'd prefer the default to be wrapped). It appears this could be implemented quite succinctly, but I'd be happy to bump the version without adding what would be a legacy option to the API.

It is the presence of line numbers that is controlled by css, although in order to handle setting the starting line numbers, all the line numbers must be produced by skylighting. Eventually (when attr is supported by browsers inside calc) the whole thing could be done in css, though each line would still have to be wrapped in a suitable element.

@dbaynard
Copy link
Contributor Author

I made the suggested changes, including a min-height of 1.25 em (if it isn't set there are display issues with blank lines). Again, sensible defaults. Please excuse the force push; I'm trying to keep the commits easy to follow, for my own sake as much as anything.

Also I have not yet tested these changes with pandoc. I'm building pandoc with this version of skylighting, and I'll check pandoc's tests.

@jgm
Copy link
Owner

jgm commented Aug 28, 2017

What if we just used code span instead of code > div > span and code > a > span? (EDITED)
Is this a performance issue?

@dbaynard
Copy link
Contributor Author

dbaynard commented Aug 28, 2017

The problem isn't the css in this package; the problem is that users may have their own css which uses the code > span form, and now the generated html does not match that. It is not a performance issue, though I don't know whether it could be (I doubt it). Does this answer your question?

I suspect this is a minor problem, though, as few users are likely to override the syntax highlighting, it will be obvious from the output that there's been some change, and the fix is just once find/replace operation away.

Actually, using code span here wouldn't hurt, and may be a better solution as it means any custom css users write in future is likely to rely on the exact nesting of elements.

@jgm
Copy link
Owner

jgm commented Aug 28, 2017 via email

@dbaynard
Copy link
Contributor Author

I'm changing it to code span, then. Browsers apparently match css from right to left (source: Stack Overflow) so it shouldn't make any difference to performance, never mind a significant difference.

I'm getting some test failures from pandoc's test suite, though I think the cause is my setup (I'm not certain I've bootstrapped the syntax files correctly in my local pandoc repository). I'd like to confirm whether the failures need fixing here because they are regressions, or fixing in pandoc's test suite because they are a change in the api. Once I've done that, I'd consider the code ready for consideration.

@dbaynard
Copy link
Contributor Author

I think the pandoc test failures are to do with me not bootstrapping skylighting correctly. They occur when I try to use local git commits to provide the skylighting dependency (stack doesn't like skylighting's build pattern, it seems).

  • 3534.md #1

    +   1 <p>I want to explain the interface of <code class="java">public class MyClass</code>.</p>
    -   1 <p>I want to explain the interface of <code class="sourceCode java"><span class="kw">public</span> <span class="kw">class</span> MyClass</code>.</p>
  • Old latex writer lhs to normal (lhs-test.latex)

    No highlighting defined, e.g.

    -  41 \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
  • html writer lhs to normal (lhs-test.html)

    ditto

  • lhs to lhs (lhs-test.html+lhs)

    ditto

  • Writers LaTeX inline code struck out and highlighted

    -------------------------------------------------------------- input ---
    [Plain [Strikeout [Code ("",["haskell"],[]) "foo",Space,Str "bar"]]]
    ------------------------------------------------------------- result ---
    - \sout{\mbox{\VERB|\NormalTok{foo}|} bar}
    + \sout{\mbox{\texttt{foo}} bar}
    ------------------------------------------------------------------------
  • HTML inline code haskell

    -------------------------------------------------------------- input ---
    [Plain [Code ("",["haskell"],[]) ">>="]]
    ------------------------------------------------------------- result ---
    - <code class="sourceCode haskell"><span class="fu">&gt;&gt;=</span></code>
    + <code class="haskell">&gt;&gt;=</code>
    ------------------------------------------------------------------------

@dbaynard
Copy link
Contributor Author

dbaynard commented Sep 9, 2017

I've fixed the bootstrapping in my pandoc build, and I can no confirm the downstream pandoc issues correspond to the intended changes.

I've fixed these failing pandoc tests to correspond to the changes introduced by this PR, in jgm/pandoc#3905

As a result, I'm satisfied with this PR.

In pandoc, the copy-paste now works better than with tables. It is now possible to copy a whole document, including numbered lines of source code, and the line numbers will not be copied. If the numbers are wanted this can be changed by a user, in css.

@dbaynard
Copy link
Contributor Author

dbaynard commented Sep 9, 2017

I should add, I've investigated the failing travis build, but I have no idea why it failed. I can compile fine with GHC 8.0.2.

@jgm
Copy link
Owner

jgm commented Sep 9, 2017 via email

@jgm jgm merged commit 9ff873c into jgm:master Sep 9, 2017
@jgm
Copy link
Owner

jgm commented Sep 9, 2017

Great, I've merged this!

@jgm
Copy link
Owner

jgm commented Oct 26, 2017

I'm noticing on pandoc that, with this revised version of skylighting, we get extra blank space around highlighted code blocks. (that is, significantly more blank space than with non-highlighted blocks, and too much, in my opinion) Example:

screen shot 2017-10-26 at 11 37 54 am

Any ideas about why or how to fix?

@jgm
Copy link
Owner

jgm commented Oct 26, 2017

Looks like taking out the enclosing div fixes this.
I don't think we need the enclosing div any more...it was just there to give us something uniform that applied both with line numbers (where previously we had a table) and without.

@jgm
Copy link
Owner

jgm commented Oct 26, 2017

I think the explanation is that with the bare pre we have overlapping margins with the preceding p. (See https://www.w3.org/TR/CSS21/box.html#collapsing-margins). Putting the pre in a div defeats the margin-collapsing feature, so we get the margin for the p AND the margin for the pre.

Keeping the surrounding div but adding div.sourceCode pre { margin: 0 } works for code next to a paragraph, but gives bad results when e.g. you have two code blocks in a row.

@dbaynard
Copy link
Contributor Author

I suspect it's an interaction between the spans wrapping the code identifiers and the new top level div. Should be a simple fix; I can take a look tomorrow. I presume the code producing that fragment is the obvious?

Does the issue appear with inline code, too?

@jgm
Copy link
Owner

jgm commented Oct 27, 2017 via email

@larryhynes
Copy link

Hi

I just kind of got bitten by this (no big deal! 😄), and I'm curious about it. In the intro above @dbaynard says

Wrap lines of source code in a div with display set to inline-block.

Where should this css (display: inline-block) appear? For instance, the following input:

# Foo

bar

~~~sh
for i in ls; do
	echo "$i"
done
~~~

when output with pandoc -s -t html, produces:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="generator" content="pandoc">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
                        <title>t</title>
        <!--[if lt IE 9]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->

                            </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col">
                                                                                <h1 id="foo">Foo</h1>
<p>bar</p>
<pre class="sourceCode sh" id="cb1"><code class="sourceCode bash"><div class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">for</span> <span class="ex">i</span> in ls<span class="kw">;</span> <span class="kw">do</span></div>
<div class="sourceLine" id="cb1-2" data-line-number="2">    <span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$i</span><span class="st">&quot;</span></div>
<div class="sourceLine" id="cb1-3" data-line-number="3"><span class="kw">done</span></div></code></pre>
                                    </div>
            </div>
        </div>
    </body>
</html>

So the div in question (which I'm guessing is sourceLine) doesn't appear to get the inline-block style by default (unless I'm missing something)? This means that one gets a sort of double line-spacing in code blocks with highlighting applied. Like, if I converted the sample markdown above with pandoc -s --no-highlight -t html, I would get different line spacing on my output.

Maybe recent changes to skylighting haven't made it into pandoc yet (I'm using pandoc 2.0.1.1)?

In my own case, I just had to add a rule to my stylesheet:

.sourceLine {
    display: inline-block;
}

...and all was well with the world.

@dbaynard
Copy link
Contributor Author

dbaynard commented Nov 7, 2017

The css should appear inline in head; these changes haven't touched that behavior, as far as I am aware. But yes, you are correct that the comment about inline-block refers to .sourceLine. I'm not familiar with the very recent changes to pandoc.

Given this is the skylighting tracker, though, is the output correct when just the code is converted using skylighting?

@larryhynes
Copy link

Ah, OK, thanks. (I've just spotted that pandoc now seems to have an explicit html4 output option, which seems new to me, but I'll stop mentioning pandoc now as I'm in the skylight issue tracker.)

I'm afraid I don't have a standalone skylight to test with; I grew (very) tired of haskell's stack / cabal and ripped the whole lot out some time ago; sorry I can't be more help with that.

I'll make any further enquiries in the pandoc tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants