11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.24k stars 495 forks source link

Markdown not rendering code properly when using a template #512

Closed nikhiljha closed 5 years ago

nikhiljha commented 5 years ago
```bash
# Change hostname
echo MY_HOSTNAME > /etc/hostname
hostname MY_HOSTNAME

# Add user
adduser MY_USER # INTERACTIVE
usermod -aG sudo MY_USER

# Disable Xorg
sudo systemctl set-default multi-user.target

# Update
apt update
apt full-upgrade
reboot
\```

(no backslash there, just to escape github's formatting)

... is turning into ...

Screen Shot 2019-04-28 at 8 44 20 AM

... instead of ...

# Change hostname
echo MY_HOSTNAME > /etc/hostname
hostname MY_HOSTNAME

# Add user
adduser MY_USER # INTERACTIVE
usermod -aG sudo MY_USER

# Disable Xorg
sudo systemctl set-default multi-user.target

# Update
apt update
apt full-upgrade
reboot
nikhiljha commented 5 years ago

Meaning, it's in a code block, but for some reason it's rendering the # as titles instead of just as #.

kleinfreund commented 5 years ago

What's the filename of the file containing that code block? What does your .eleventy.js file look like?

nikhiljha commented 5 years ago

.eleventy.js looks like

const { DateTime } = require("luxon");
const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function(config) {

  // A useful way to reference to the contect we are runing eleventy in
  let env = process.env.ELEVENTY_ENV;

  // Layout aliases can make templates more portable
  config.addLayoutAlias('default', 'layouts/base.njk');

  // Add some utiliuty filters
  config.addFilter("squash", require("./src/filters/squash.js") );
  config.addFilter("dateDisplay", (dateObj, format = "LLL d, y") => {
    return DateTime.fromJSDate(dateObj, {
      zone: "utc"
    }).toFormat(format);
  });
  config.addPlugin(pluginRss);

  // minify the html output
  config.addTransform("htmlmin", require("./src/utils/minify-html.js"));

  // pass some assets right through
  config.addPassthroughCopy("./src/site/images");
  config.addPassthroughCopy("./src/site/school");
  config.addPassthroughCopy("./src/site/keybase.txt");

  // make the seed target act like prod
  env = (env=="seed") ? "prod" : env;
  return {
    dir: {
      input: "src/site",
      output: "dist",
      data: `_data/${env}`
    },
    templateFormats : ["njk", "md"],
    htmlTemplateEngine : "njk",
    markdownTemplateEngine : "njk",
    passthroughFileCopy: true
  };

};

and the filename is armclustertutorial.md

You can see the site source (without the broken article posted, for obvious reasons) here: https://github.com/nikhiljha/blog

kleinfreund commented 5 years ago

Could this be caused by the markdown engine being set to Nunjucks? (I'm on a train right now)

nikhiljha commented 5 years ago

Hmm... I added

  var hljs = require('highlight.js'); // https://highlightjs.org/

  // Actual default values
  var md = require('markdown-it')({
    html: true,
    breaks: true,
    highlight: function (str, lang) {
      if (lang && hljs.getLanguage(lang)) {
      try {
        return '<pre class="hljs"><code>' +
                 hljs.highlight(lang, str, true).value +
                 '</code></pre>';
        } catch (__) {}
      }
      return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
    }
  });

  config.setLibrary("md", md);

to my .eleventy.js and now it looks like this ...

Screen Shot 2019-04-28 at 10 58 11 AM

... but only when breaks: true,

if breaks: false, then it looks like this...

Screen Shot 2019-04-28 at 10 59 08 AM

I don't think the breaks setting should be affecting things in code blocks, so it's still broken but less broken.

nikhiljha commented 5 years ago

Actually, even with breaks: true some of the code blocks are still broken.

Screen Shot 2019-04-28 at 11 04 41 AM

is supposed to be

# Use proper locale
locale-gen en_US.UTF-8
dpkg-reconfigure locales
dpkg-reconfigure keyboard-configuration
localedef -i en_US -c -f UTF-8 en_US.UTF-8
reboot
nikhiljha commented 5 years ago

Found another weird behavior, it's only the first line that's broken.

\```bash
# this will be weird

# everything here is
echo ok
\```
Screen Shot 2019-04-28 at 7 25 44 PM
zachleat commented 5 years ago

Having trouble reproducing this:

image

outputs:

image

which seems correct to me.

Are you using a layout? Can you attach the input markdown file and the output HTML file it generates?

nikhiljha commented 5 years ago

@zachleat I'm using the eleventyone scaffold; my full source is at https://github.com/nikhiljha/blog and you can find the HTML output at https://nikhiljha.com/.

(An example page with the broken tags can be found at https://nikhiljha.com/posts/neuralnetbaseline/ - which corresponds to posts/neuralnetbaseline.md).

nikhiljha commented 5 years ago

@zachleat I found a simpler test case.

Just render this page...

---
title: "demo"
---

## This text is required or the bug will not happen.

I'm not sure why, but I think its something to do with nunjucks escaping.

```bash
# Change hostname
echo MY_HOSTNAME > /etc/hostname
hostname MY_HOSTNAME

# Add user
adduser MY_USER # INTERACTIVE
usermod -aG sudo MY_USER

# Disable Xorg
sudo systemctl set-default multi-user.target

# Update
apt update
apt full-upgrade
reboot
\```

... through this nunjucks template...

{{ content | safe }}

... it outputs ...

<h2>This text is required or the bug will not happen.</h2>
<p>I'm not sure why, but I think its something to do with nunjucks escaping.</p>
<pre class="hljs"><code><span class="hljs-comment"># Change hostname</span>
<span class="hljs-built_in">echo</span> MY_HOSTNAME &gt; /etc/hostname
hostname MY_HOSTNAME
<p><span class="hljs-comment"># Add user</span><br>
adduser MY_USER <span class="hljs-comment"># INTERACTIVE</span><br>
usermod -aG sudo MY_USER</p>
<p><span class="hljs-comment"># Disable Xorg</span><br>
sudo systemctl <span class="hljs-built_in">set</span>-default multi-user.target</p>
<p><span class="hljs-comment"># Update</span><br>
apt update<br>
apt full-upgrade<br>
reboot<br>
</code></pre></p>

... which is clearly wrong. It's doing HTML formatting inside my code snippet. If you remove the text and title above it, it renders as expected.

Ryuno-Ki commented 5 years ago

Hm, markdown-it implements Commonmark.

Your example looks fine there.

nikhiljha commented 5 years ago

@Ryuno-Ki As mentioned in my last comment, the bug only happens when you render it through a nunjucks template that looks like {{ content | safe }}. It renders perfectly if I don't use templating.

Ryuno-Ki commented 5 years ago

Thanks for clarifying the title :-)

I tried to further isolate the issue (to see, which dependency might be offending).

I'm aware that it might sound like heresy, but have you tried adding console.logs in the downloaded eleventy dependency? That is, checked, what compiled markdown gets fed into Nunjucks.

nikhiljha commented 5 years ago

Just tried that and it looks like it's being parsed twice: first the Markdown (which parses correctly), and then when it's parsed again as part of the template, the offending <p>s are added.

Here's a really long paste that shows what's happening: https://hastebin.com/ogifuxoqab.log

(The relevant bit is all the way to the right. There's a code segment at the end of the article which you can see.)

zachleat commented 5 years ago

Hmm, I tried to check out your repo and go through it but got a bunch of errors unrelated to this issue?

I even tried to make my own test case and use your custom syntax highlighting code from your .eleventy.js file, using a markdown file with a nunjucks layout.

I got this:

image

That seems right to me?

Sorry about this but if you can fix the other unrelated errors in your repo, please ping this issue again and I’ll be happy to retest with your full repo.

nikhiljha commented 5 years ago

@zachleat It was fixed in the template I was using: https://github.com/philhawksworth/eleventyone

Not sure what the underlying problem is though, but it was fixed.