Unexpected HTML output from raco pollen start #164

Closed
opened 6 years ago by clozach · 5 comments
clozach commented 6 years ago (Migrated from github.com)

Steps to reproduce:

  • In a new, empty directory, create a Pollen Markup file with HTML output, e.g., test.html.pm
  • Open the test file in DrRacket
  • Paste in the following content:
#lang pollen

◊(require pollen/decode txexpr)
◊(define (root . elements)
   (txexpr 'root empty (decode-elements elements
     #:txexpr-elements-proc decode-paragraphs)))

I want to attend ◊event{RacketCon} this year.

Second paragraph.

◊custom{
  Here's another ◊event{Event tag}.

  Fourth paragraph.
}
  • Run to get the following txexpr. Note how the custom tag encloses the "Here's another…" and "Fourth paragraph" lines.
'(root
  (p "I want to attend " (event "RacketCon") " this year.")
  (p "Second paragraph.")
  (p
    (custom
      (p "Here's another " (event "Event tag") ".")
      (p "Fourth paragraph."))))

Expected:

<root>
  <p>I want to attend
    <event>RacketCon</event> this year.</p>
  <p>Second paragraph.</p>
  <p>
    <custom>
      <p>Here's another <event>Event tag</event>.</p>
      <p>Fourth paragraph.</p>
    </custom>
  </p>
</root>

Actual (note the empty custom tag):

<root>
  <p>I want to attend
    <event>RacketCon</event> this year.</p>
  <p>Second paragraph.</p>
  <p>
    <custom></custom>
  </p>
  <p>Here's another <event>Event tag</event>.</p>
  <p>Fourth paragraph.</p>
  <p></p>
</root>```
Steps to reproduce: * In a new, empty directory, create a Pollen Markup file with HTML output, e.g., `test.html.pm` * Open the test file in DrRacket * Paste in the following content: ```pollen #lang pollen ◊(require pollen/decode txexpr) ◊(define (root . elements) (txexpr 'root empty (decode-elements elements #:txexpr-elements-proc decode-paragraphs))) I want to attend ◊event{RacketCon} this year. Second paragraph. ◊custom{ Here's another ◊event{Event tag}. Fourth paragraph. } ``` * Run to get the following txexpr. Note how the custom tag encloses the "Here's another…" and "Fourth paragraph" lines. ```racket '(root (p "I want to attend " (event "RacketCon") " this year.") (p "Second paragraph.") (p (custom (p "Here's another " (event "Event tag") ".") (p "Fourth paragraph.")))) ``` * In the test directory, `raco pollen start` * Visit _http://localhost:8080/index.ptree_ * Click on `test.html.pm` _Expected:_ ```html <root> <p>I want to attend <event>RacketCon</event> this year.</p> <p>Second paragraph.</p> <p> <custom> <p>Here's another <event>Event tag</event>.</p> <p>Fourth paragraph.</p> </custom> </p> </root> ``` _Actual_ (note the empty `custom` tag): ```html <root> <p>I want to attend <event>RacketCon</event> this year.</p> <p>Second paragraph.</p> <p> <custom></custom> </p> <p>Here's another <event>Event tag</event>.</p> <p>Fourth paragraph.</p> <p></p> </root>```
mbutterick commented 6 years ago (Migrated from github.com)

custom is a nonstandard tag so the browser treats it as an inline tag. Inline tags can’t contain block tags like p. So when the HTML is parsed by the browser, it moves the p blocks outside.

On Jan 10, 2018, at 11:07 AM, clozach notifications@github.com wrote:

Steps to reproduce:

In a new, empty directory, create a Pollen Markup file with HTML output, e.g., test.html.pm
Open the test file in DrRacket
Paste in the following content:
#lang pollen

◊(require pollen/decode txexpr)
◊(define (root . elements)
(txexpr 'root empty (decode-elements elements
#:txexpr-elements-proc decode-paragraphs)))

I want to attend ◊event{RacketCon} this year.

Second paragraph.

◊custom{
Here's another ◊event{Event tag}.

Fourth paragraph.
}
Run to get the following txexpr. Note how the custom tag encloses the "Here's another…" and "Fourth paragraph" lines.
'(root
(p "I want to attend " (event "RacketCon") " this year.")
(p "Second paragraph.")
(p
(custom
(p "Here's another " (event "Event tag") ".")
(p "Fourth paragraph."))))
In the test directory, raco pollen start
Visit http://localhost:8080/index.ptree
Click on test.html.pm
Expected:

I want to attend RacketCon this year.

Second paragraph.

Here's another Event tag.

Fourth paragraph.

Actual (note the empty custom tag):

I want to attend RacketCon this year.

Second paragraph.

Here's another Event tag.

Fourth paragraph.

``` — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
`custom` is a nonstandard tag so the browser treats it as an inline tag. Inline tags can’t contain block tags like `p`. So when the HTML is parsed by the browser, it moves the `p` blocks outside. > On Jan 10, 2018, at 11:07 AM, clozach <notifications@github.com> wrote: > > Steps to reproduce: > > In a new, empty directory, create a Pollen Markup file with HTML output, e.g., test.html.pm > Open the test file in DrRacket > Paste in the following content: > #lang pollen > > ◊(require pollen/decode txexpr) > ◊(define (root . elements) > (txexpr 'root empty (decode-elements elements > #:txexpr-elements-proc decode-paragraphs))) > > I want to attend ◊event{RacketCon} this year. > > Second paragraph. > > ◊custom{ > Here's another ◊event{Event tag}. > > Fourth paragraph. > } > Run to get the following txexpr. Note how the custom tag encloses the "Here's another…" and "Fourth paragraph" lines. > '(root > (p "I want to attend " (event "RacketCon") " this year.") > (p "Second paragraph.") > (p > (custom > (p "Here's another " (event "Event tag") ".") > (p "Fourth paragraph.")))) > In the test directory, raco pollen start > Visit http://localhost:8080/index.ptree > Click on test.html.pm > Expected: > > <root> > <p>I want to attend > <event>RacketCon</event> this year.</p> > <p>Second paragraph.</p> > <p> > <custom> > <p>Here's another <event>Event tag</event>.</p> > <p>Fourth paragraph.</p> > </custom> > </p> > </root> > Actual (note the empty custom tag): > > <root> > <p>I want to attend > <event>RacketCon</event> this year.</p> > <p>Second paragraph.</p> > <p> > <custom></custom> > </p> > <p>Here's another <event>Event tag</event>.</p> > <p>Fourth paragraph.</p> > <p></p> > </root>``` > — > You are receiving this because you are subscribed to this thread. > Reply to this email directly, view it on GitHub, or mute the thread. >
clozach commented 6 years ago (Migrated from github.com)

Does this mean that pollen can only generate standard and inline tags, so I can get this output…

<div class="custom"></div>

…but not this…

<custom></custom>

…or am I missing something in the behavior of tag functions that would allow a custom block-level tag?

Does this mean that pollen can only generate standard and inline tags, so I can get this output… ```html <div class="custom">…</div> ``` …but not this… ```html <custom>…</custom> ``` …or am I missing something in the behavior of [tag functions](https://docs.racket-lang.org/pollen/Tag.html) that would allow a custom block-level tag?
mbutterick commented 6 years ago (Migrated from github.com)

Pollen is behaving correctly. (Look at the generated HTML in a text editor, rather than doing “view source” in the browser — the custom tag is where you expect it.)

If you want the web browser to treat custom as a block tag rather than inline, you have to notate that explicitly, either in CSS or in the tag itself. For instance, try this one:

#lang pollen

◊(require pollen/decode txexpr)
◊(define (root . elements)
   (txexpr 'root empty (decode-elements elements
     #:txexpr-elements-proc decode-paragraphs)))

I want to attend ◊event{RacketCon} this year.

Second paragraph.

◊custom[#:style "display:block"]{
  Here's another ◊event{Event tag}.

  Fourth paragraph.
}

Pollen has its own setting for block-tags, but that’s an internal idea of block-ness that cooperates with functions like detect-paragraphs. So even if you define something as a block tag within Pollen, you still have to tell the web browser to treat it as a block tag (using CSS).

“So why doesn’t Pollen just drop display:block into the HTML for every Pollen-defined block tag?“ It could. But —

  1. My policy is to minimize magic behavior.

  2. Beyond the most vanilla situations, it backfires, because CSS properties that are in the tag itself will override anything in an external CSS declaration.

  3. Anyone who wants that behavior can easily put it in a tag function:

#lang pollen

◊(require pollen/decode pollen/tag txexpr)
◊(define (root . elements)
   (txexpr 'root empty (decode-elements elements
     #:txexpr-elements-proc decode-paragraphs)))

◊(define-tag-function (custom attrs elems)
  (attr-set (txexpr 'custom attrs elems) 'style "display:block"))

I want to attend ◊event{RacketCon} this year.

Second paragraph.

◊custom{
  Here's another ◊event{Event tag}.

  Fourth paragraph.
}
Pollen is behaving correctly. (Look at the generated HTML in a text editor, rather than doing “view source” in the browser — the `custom` tag is where you expect it.) If you want *the web browser* to treat `custom` as a block tag rather than inline, you have to notate that explicitly, either in CSS or in the tag itself. For instance, try this one: ``` #lang pollen ◊(require pollen/decode txexpr) ◊(define (root . elements) (txexpr 'root empty (decode-elements elements #:txexpr-elements-proc decode-paragraphs))) I want to attend ◊event{RacketCon} this year. Second paragraph. ◊custom[#:style "display:block"]{ Here's another ◊event{Event tag}. Fourth paragraph. } ``` Pollen has its own setting for [`block-tags`](https://docs.racket-lang.org/pollen/Setup.html?q=block-tag#%28def._%28%28lib._pollen%2Fsetup..rkt%29._default-block-tags%29%29), but that’s an internal idea of block-ness that cooperates with functions like `detect-paragraphs`. So even if you define something as a block tag within Pollen, you still have to tell the web browser to treat it as a block tag (using CSS). “So why doesn’t Pollen just drop `display:block` into the HTML for every Pollen-defined block tag?“ It could. But — 1) My policy is to minimize magic behavior. 2) Beyond the most vanilla situations, it backfires, because CSS properties that are in the tag itself will override anything in an external CSS declaration. 3) Anyone who wants that behavior can easily put it in a tag function: ``` #lang pollen ◊(require pollen/decode pollen/tag txexpr) ◊(define (root . elements) (txexpr 'root empty (decode-elements elements #:txexpr-elements-proc decode-paragraphs))) ◊(define-tag-function (custom attrs elems) (attr-set (txexpr 'custom attrs elems) 'style "display:block")) I want to attend ◊event{RacketCon} this year. Second paragraph. ◊custom{ Here's another ◊event{Event tag}. Fourth paragraph. } ```
clozach commented 6 years ago (Migrated from github.com)

Ah, I'm starting to see it a little more clearly. (Thanks, by the way!)

To be clear, I wasn't thinking that Pollen should drop display:block as a side effect…agree 100% that it shouldn't. In case it helps you see any other problems with my understanding, here's how I first arrived at this issue.

I wanted to try my hand at laying out a short story in Pollen, and the story in question is written in sections, each section having a different "voice". So I naively threw some Pollen tags around the relevant paragraphs, similar to the ◊custom{…} tag used above. I wasn't looking at the in-browser source just yet. Instead, I added a template.html.p to load a styles.css, and, in the latter, a display: block; within each of the custom tags, and was surprised by the style's seeming failure to be applied.

It seems that my chief misunderstanding was in believing the bug to be in Pollen when you could argue that the issue is with Firefox, Safari, and Chrome, all of which transform this:

<html>

<head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" type="text/css" href="styles.css" />
</head>

<body>
  <root>
    <p>
      <custom>
        <p>First paragraph</p>
        <p>Second paragraph.</p>
      </custom>
    </p>
  </root>
</body>

</html>

into this:

<html>

<head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" type="text/css" href="styles.css" />
</head>

<body>
  <root>
    <p>
      <custom>
      </custom>
    </p>
    <p>First paragraph</p>
    <p>Second paragraph.</p>
    <p></p>
  </root>
</body>

</html>

I guess the browsers do a first pass at loading the dom before applying styles, and then, rather than communicate the apparent inline-can't-contain-block-tag error, they silently rearrange the tags. Ugh!

Thanks again for your help, Matthew.

Ah, I'm starting to see it a little more clearly. (Thanks, by the way!) To be clear, I wasn't thinking that Pollen should drop `display:block` as a side effect…agree 100% that it shouldn't. In case it helps you see any other problems with my understanding, here's how I first arrived at this issue. I wanted to try my hand at laying out a short story in Pollen, and the story in question is written in sections, each section having a different "voice". So I naively threw some Pollen tags around the relevant paragraphs, similar to the `◊custom{…}` tag used above. I wasn't looking at the in-browser source just yet. Instead, I added a _template.html.p_ to load a _styles.css_, and, in the latter, a `display: block;` within each of the custom tags, and was surprised by the style's seeming failure to be applied. It seems that my chief misunderstanding was in believing the bug to be in Pollen when you could argue that the issue is with Firefox, Safari, and Chrome, all of which transform this: ```html <html> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body> <root> <p> <custom> <p>First paragraph</p> <p>Second paragraph.</p> </custom> </p> </root> </body> </html> ``` into this: ```html <html> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body> <root> <p> <custom> </custom> </p> <p>First paragraph</p> <p>Second paragraph.</p> <p></p> </root> </body> </html> ``` I guess the browsers do a first pass at loading the dom before applying styles, and then, rather than communicate the apparent inline-can't-contain-block-tag error, they silently rearrange the tags. Ugh! Thanks again for your help, Matthew.
mbutterick commented 6 years ago (Migrated from github.com)

Yes, the behavior is surprising. But to be a little fair to web browsers, this behavior is a feature not a bug. They’re designed to recover gracefully from malformed & illogical input. Though if you want a rule of thumb: make your block-level tag functions emit div elements qualified with class or id attributes.

Yes, the behavior is surprising. But to be a little fair to web browsers, this behavior is a feature not a bug. They’re designed to recover gracefully from malformed & illogical input. Though if you want a rule of thumb: make your block-level tag functions emit `div` elements qualified with `class` or `id` attributes.
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: mbutterick/pollen#164
Loading…
There is no content yet.