6

I am currently writing LaTeX.js to translate LaTeX to HTML in the browser. So I want it to be as exact as possible. However, TeX's alignment implementation together with LaTeX's \\ make that hard.

Simple start:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Ut enim ad minim veniam, quis nostrud\\               % centered!
exercitation ullamco laboris\\                        % centered!
nisi ut aliquip ex ea commodo consequat.\raggedleft

You would think that the whole second paragraph will now be flushright because \leftskip affects the whole current paragraph (and all the following ones). But that is not what happens; instead, the second- and third-last lines are now centered! Why is that so? Is that because \\ inserts some fill glue? I did not find or understand how LaTeX really implements \\.

Assuming that glue is the reason, why then wasn't an infinitely larger glue chosen for the \leftskip to prevent centering?

Then I found that if you move the \raggedleft to the beginning of the paragraph, it works as expected:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\raggedleft
Ut enim ad minim veniam, quis nostrud\\               % fine
exercitation ullamco laboris\\                        % fine
nisi ut aliquip ex ea commodo consequat.

How do you explain that? Is that a bug or is that intentional? I can't possibly make LaTeX.js behave that way :(

But it doesn't end there. Let's put it in a group:

{
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

  Ut enim ad minim veniam, quis nostrud\\ 
  exercitation ullamco laboris\\
  nisi ut aliquip ex ea commodo consequat.\raggedleft
}

Already \raggedleft doesn't do anything anymore. It seems that is because there is no paragraph that ends. And when the paragraph ends after the group, it has the values of \leftskip and \rightskip already reset. Correct?

If so, that would be understandable. Always the last paragraph in a group would have the alignment reset. But again, surprise if you add \\:

{
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

  Ut enim ad minim veniam, quis nostrud\\ 
  exercitation ullamco laboris\\
  nisi ut aliquip ex ea commodo consequat.\raggedleft

  Lorem ipsum dolor sit amet,\\       % ?! raggedleft
  consectetur adipiscing elit,\\      % ?! raggedleft
  sed do eiusmod tempor incididunt.   % justified
}

Here, I would have expected the the whole last paragraph to be justified, but it seems like \\ is acting as if it would start a new paragraph?! Except it doesn't because \parindent is not applied.

What is going on here?

EDIT: as David asked for it, there really isn't anything else to it. Here is the full document:

\documentclass{article}

\begin{document}

{
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    Ut enim ad minim veniam, quis nostrud\\             % centered
    exercitation ullamco laboris\\                      % centered
    nisi ut aliquip ex ea commodo consequat.\raggedleft

    Lorem ipsum dolor sit amet,\\       % ?! raggedleft
    consectetur adipiscing elit,\\      % ?! raggedleft
    sed do eiusmod tempor incididunt.   % justified
}

\end{document}

enter image description here

  • \raggedleft redefines \\ , so it should be at the begin/before the first \\ . – Ulrike Fischer Dec 10 '17 at 14:41
  • Ok, that might start to explain some things. Can you then please explain what the redefinition means, i.e., what \@centercr does and why it leads to the above results? – MiB Dec 10 '17 at 15:03
9

the initial markup is incorrect (but not flagged as an error by latex)

\raggedright and \raggedleft should be used before the paragraph, it sets ragged \rightskip (which would take effect even if the declaration is used mid paragraph) but it also sets \parindent to zero and defines \\ to give a ragged-compatible line break.

If as here you use \raggedleft late then you get the settings of \rightskip, \leftskip and \parfillskip in effect at the end of the paragraph, but you get a paragraph indent from whatever was in effect before the paragraph and similarly \\ will have expanded to be the "normal" definition.

So in your example the definition of \\for the first paragraph is completely different to the definition for the second paragraph after \raggedright,

You get a centered line because a "normal" \\ does essentially \hfil\linebreak to make a short line, but if you use that definition in the scope of raggedleft you also have \hfil on the left to give the raggedmargin, so you end up with a centred line.

So the example may be easier to see with \\ expanded out (and simplified a bit)

\documentclass{article}

\begin{document}

{
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    Ut enim ad minim veniam, quis nostrud\unskip\nobreak\hfil\break            % centered
    exercitation ullamco laboris\unskip\nobreak\hfil\break                      % centered
    nisi ut aliquip ex ea commodo consequat.\raggedleft

    Lorem ipsum dolor sit amet,\par\noindent       % ?! raggedleft
    consectetur adipiscing elit,\par\noindent      % ?! raggedleft
    sed do eiusmod tempor incididunt.   % justified
}

\end{document}
  • Ok, thanks! Now I get it, it all makes sense. And it's illegal syntax. Great, less work for me then ;) – MiB Dec 10 '17 at 17:42
  • 5
    @MiB 90% of the code of all latex-to-anything convertors are dealing with things that you think "no author would ever do that...." but they do... :-) – David Carlisle Dec 10 '17 at 17:44
  • LOL. Yeah, indeed. But you know, I still consider the centering a bug in LaTeX. This could easily be avoided by setting \@flushglue or just left-/rightskip to 0pt plus 2fil. – MiB Dec 10 '17 at 17:54
  • @MiB that would potentially change the layout of thousands of latex documents written over the last 30 years, I don't think that's a feasible suggestion. – David Carlisle Dec 10 '17 at 18:05
  • 3
    @MiB PS I think your "compatibility" claim of "LaTeX.js produces the exact same output you would get with LaTeX—except where impossible due to the nature of HTML". is stretching the truth rather more than it ought to be stretched. The output looks quite nice but "emulates a small subset of latex in pure javascript, to give a similar layout" would be more accurate. see for example texlive.js which really does implement the full tex stack in javascript, It is a design choice to limit to a sanitised latex input and to emulate that markup rather than a more complete emulation being impossible. – David Carlisle Dec 10 '17 at 18:11
4

Under normal circumstances, \\ means “break a line here”, issuing \hfil\break (it does other things when the * or an optional argument is added, but these are irrelevant for the explanation).

However, \raggedright and \raggedleft change its definition to \@centercr which, in your cases, does \unskip\par. So, let's translate your code:

{
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

  Ut enim ad minim veniam, quis nostrud\hfil\break 
  exercitation ullamco laboris\hfil\break
  nisi ut aliquip ex ea commodo consequat.\raggedleft

  Lorem ipsum dolor sit amet,\unskip\par
  consectetur adipiscing elit,\unskip\par
  sed do eiusmod tempor incididunt.
}

The first paragraph is typeset normally and there's no problem with that.

The second paragraph ends when \raggedleft has already been executed. This command, among other things, sets \leftskip to \hfil, \rightskip to zero and also \parfillskip.

At this point we should note that TeX uses the values of \leftskip, \rightskip and \parfillskip current when the paragraph ends.

Hence, each line in the second paragraph, except for the last, has effectively \hfil glue on either side, ending up centered. The last line only has \hfil glue at its left, so it ends up flush right.

The first line also has the indentation box, so the centering is visually not perfect, but it is insofar as boxes in the line are taken into account.

The next three line are three separate paragraphs; the first two lines are flush right, as expected, because \raggedleft is still in force.

The last line has the \par following the closing brace, so the effect of \raggedleft is nullified and the paragraph is typeset justified. Where is the indentation box? Nowhere, because the previous \raggedleft has set \parindent to zero and the indentation box is inserted as soon as the paragraph starts (in this case when TeX has scanned the letter s).

  • good explanation, just a little bit too late... I accepted David's answer already. Sorry. But then again, he's got some catching up to do :) – MiB Dec 10 '17 at 17:49
  • shame!......... – David Carlisle Dec 10 '17 at 18:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.