11

I'm building a Shiny app with some dynamically generated HTML which includes a link in mid-sentence. Unfortunately if I use the tags functions to do this, every element has a space around it whether I want it or not.

For example, if I wanted to write

This is my favorite link ever!

One might think you could do this

p('This is my ', a(href = 'https://stackoverflow.com/', 'favorite link ever'), '!')

But this results in each element being on a separate line, which by the HTML spec means there will be a space rendered between each.

<p>
  This is my 
  <a href="https://stackoverflow.com/">favorite link ever</a>
  !
</p>

Which looks like this (note the space before the exclamation mark)

This is my favorite link ever !

Do I have to resort to using HTML(paste0(...)) to construct my HTML, or is there some technique to using the tags functions that I'm missing?

Thanks..

Community
  • 1
  • 1
Brian Stamper
  • 2,143
  • 1
  • 18
  • 41

2 Answers2

6

This has been resolved by a new feature, a parameter called .noWS. Quoting Carson Sievert:

you can now do:

p('This is my ', a(href = 'https://stackoverflow.com/', 'favorite link ever', .noWS = "outside"), '!', .noWS = c("after-begin", "before-end")) 

which yields

<p>This is my <a href="https://stackoverflow.com/">favorite link ever</a>!</p>

More information on the .noWS parameter can be found at the pull request.

Brian Stamper
  • 2,143
  • 1
  • 18
  • 41
3

I think you have to use paste. Otherwise nesting wouldn't work like expected.

div(p('hi'),p('what up'),p(HTML(paste0('This is my ',a(href = 'https://stackoverflow.com/', 'favorite link ever'),'!'))))

Result:

<div>
  <p>hi</p>
  <p>what up</p>
  <p>This is my <a href="https://stackoverflow.com/">favorite link ever</a>!</p>
</div>

You wouldn't want all those on the same line.

From the help: Named arguments become attributes, and positional arguments become children.

It would be more complexity to have positional arguments to also sometimes not be children; and probably wouldn't be as simple, flexible, and powerful as just constructing it yourself.

ARobertson
  • 2,857
  • 18
  • 24
  • 1. Why would a Shiny developer using HTML builder functions care if the resultant HTML is all on one line? For all we care the whole output could be minified. 2. Even with keeping line breaks, I don't see any reason that we couldn't have some functions place children on separate lines and some would not - `div` would, `p` would not, for example. I don't think this is particularly complex or surprising. 3. When using dynamically generated content, the helper functions actually produce much cleaner looking code than pasting explicit HTML. These functions do exist for a reason. – Brian Stamper Dec 06 '17 at 14:24
  • BTW, I really should make this a feature request because there isn't an actual answer at present. The source of this issue I believe is upstream in the `htmltools` package, here: https://github.com/rstudio/htmltools/blob/02678ee19192f406d1aa5c360916f54df09802a1/R/tags.R#L429 – Brian Stamper Dec 06 '17 at 16:42
  • I wrote this up as an issue: https://github.com/rstudio/htmltools/issues/92 – Brian Stamper Dec 06 '17 at 17:15