1

I have something simple that I'd like to align. Following this answer I saw I could use use white-space:pre; https://stackoverflow.com/a/6752736

So I wrote

doctype html
html(lang="en")
  head
    meta(charset="utf-8")
  body
    p.
      Jade is terse

    #Foo
      p(style='white-space:pre;')
        |    One: #[span.A]
        |    Two: #[span.B]
        |  Three: #[span.C]
        |   Four: #[span.D]
        | blah blah blah 

and got this in my output

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body><p>Jade is terse
</p><div id="Foo"><p style="white-space:pre;">   One: <span class="A"></span>   Two: <span class="B"></span> Three: <span class="C"></span>  Four: <span class="D"></span>blah blah blah </p></div></body></html>

which completely destroys the point of using white-space:pre. I could clean it up by hand (see blow) but then there isn't a point to using jade. I don't use HTML or jade much. Whats the best way to fix this? Using a table? (If so how) use a ul?

<p style="white-space:pre;">
   One: <span class="A"></span>
   Two: <span class="B"></span>
 Three: <span class="C"></span>
  Four: <span class="D"></span>
  blah blah blah </p>
Community
  • 1
  • 1

1 Answers1

3

Alas, white-space:pre; and piping can only preserve the formatting if there are no nested tags (i.e. your spans). To get the output to print exactly as you might like with piping and inline tags, you have to get a little hacky and use some manner of escaped character string interpolation (#{}) that renders inline JavaScript.

The basic interpolation expression you'll need somewhere is #{'\n\t\t'} to ensure it lines up with the tag. As with regular JavaScript, \n will return the string to the beginning of the next line, hence the need for \ts.

There are a variety of ways you can implement this interpolation, however.

Inline

p(style='white-space:pre;')
  |#{'\n\t\t'}    One: #[span.A]
  |#{'\n\t\t'}    Two: #[span.B]
  |#{'\n\t\t'}  Three: #[span.C]
  |#{'\n\t\t'}   Four: #[span.D]
  |#{'\n\t\t'} blah blah blah 

In your example, all of the colons prefacing the span are indented 8 characters, so you can line them up using some simple math and .repeat without having to figure out the particulars of how many spaces to have.

Function

Note the - in front of the function, which is necessary to run a line of JavaScript.

-function whiteSpaceFunc(str) { return '\n\t' + ' '.repeat(8-str.length) + str + ': ';}

p(style='white-space:pre;')
  |#{whiteSpaceFunc('One')}#[span.A]
  |#{whiteSpaceFunc('Two')}#[span.B]
  |#{whiteSpaceFunc('Three')}#[span.C]
  |#{whiteSpaceFunc('Four')}#[span.D]
  |#{'\n\t\t'}  blah blah blah

Mixin

A more native approach of functions. Note the use of className rather than class as a parameter; class seems to be reserved and throws an error.

   p(style='white-space:pre;')
        mixin whiteSpacedLine(str,className)
          |  #{'\n\t\t' + ' '.repeat(8-str.length)}#{str}: #[span(class=className)]
      +whiteSpaceLine('One','A')
      +whiteSpaceLine('Two','B')
      +whiteSpaceLine('Three','C')
      +whiteSpaceLine('Four','D')

Mixin + Iteration

Perhaps the most simple way to do this. If you spread the vals array across multiple lines as in the code below, make sure to wrap them inside a code block indented under a -, and ensure the - does not have any space afterward. (You could, of course, contain it to one line.)

  p(style='white-space:pre;')
            mixin whiteSpacedLine(str,className)
              |  #{'\n\t\t' + ' '.repeat(8-str.length)}#{str}: #[span(class=className)]
            -
              var vals = [
                     {char: 'A', num: 'One'},
                     {char: 'B', num: 'Two'},
                     {char: 'C', num: 'Three'},
                     {char: 'D', num: 'Four'}
                     ];
            - each item in vals
              +whiteSpacedLine(item.num,item.char)
            |#{'\n\t\t'} blah blah blah
litel
  • 3,790
  • 3
  • 20
  • 29