Difference in rendering order between local and online

Site: https://docs.json-everything.net/

This is what I see when I run the site locally. Note the two <hr>s are visible. This is because they exist outside of the <li>s. This is what I expect to happen.

I’ll post a screenshot of what I’m getting in a comment. (I’m only allowed one media item in a post.)

My code for the sidebar is here.

I don’t understand why it’s different on GitHub. I’ve checked versions as best I know how, and everything seems to be right. The only difference I can think of is that my local environment is Windows, whereas it’s Ubuntu on GitHub.

When the build runs on GitHub, I get this. The <hr> tags are contained within the <li>s.

You might look at the source (under Sources tab), rather than the DOM tree view (Elements tab). It’s possible there is some extra/missing HTML that causes the browser to generate the DOM tree you see. For example, maybe the logic around doc.close is causing extra/missing list tags?

Looking at the source on the live site, it appears that almost every <li> is missing a closing </li>. The sidebar code seems to have closing </li> tags, so it is odd that they’re missing.

Re Windows vs Unix, one difference that might have an effect is the default sorting of files/folders. Unix will sort capitals first (A1 B1 C1 a2 b2 c2), while I believe Window’s sort is relatively case insensitive (A1 a2 B1 b2 C1 c2). Could that be interacting badly with doc.close or something?

Nice call on viewing the source. I didn’t even know that the DOM viewer would insert missing tags like that.

Regarding the file sorting, they’re all lower-case, so I doubt that casing is an issue. Additionally, I’m explicitly sorting the files by their order YAML property.

However, you pointing out the close.md files, made me consider them a bit more. Looks like this build warning actually might be biting me. I was ignoring it because it didn’t seem to have any problems locally, but it may actually be a problem online.

Conflict: The following destination is shared by multiple files.
        The written file may end up with unexpected contents.
        C:/projects/json-everything-docs/_site/api/JsonSchema.Net/close/index.html
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net.Data/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net.UniqueKeys/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net.OpenApi/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net.Generation/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonSchema.Net.DataGeneration/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonPath.Net/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonPatch.Net/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonPointer.Net/close.md
            - C:/projects/json-everything-docs/_docs/api/JsonLogic/close.md
            - C:/projects/json-everything-docs/_docs/api/Json.More/close.md
            - C:/projects/json-everything-docs/_docs/api/Yaml2JsonNode/close.md

I’ll set unique hrefs for all of these files and report back.

Nope. I was able to address the warnings, but the problem persists.

I haven’t taken much time to actually understand the if / elseif / else logic but it looks like you don’t have a closing li tag in one of the situations.

Not sure the elseif in the middle is correct? seems like that should be another if?

or you might just need an closing li down where the closing ul is?

The logic is right as it’s generating correctly locally.

It seems like the </li> closing tag is always being ignored by the generation on GitHub. There are none in that file. I’m not sure why.

Local Generation:

<li class="nav-item">
  <a href="/schema/examples/managing-options/" class="nav-link">
    <i class="fa-solid fa-file fa-margin-adjust"></i>
    <span>Configuration</span>
  </a>
</li>
<li class="nav-item">
  <a href="/schema/examples/external-schemas/" class="nav-link">
    <i class="fa-solid fa-file fa-margin-adjust"></i>
    <span>External References</span>
  </a>
</li>
<li class="nav-item">
  <a href="/schema/examples/version-selection/" class="nav-link">
    <i class="fa-solid fa-file fa-margin-adjust"></i>
    <span>Schema Version</span>
  </a>
</li>
<li class="nav-item">
  <a href="/schema/examples/custom-vocabs/" class="nav-link">
    <i class="fa-solid fa-file fa-margin-adjust"></i>
    <span>Custom Vocabs</span>
  </a>
</li>

GitHub:

<li class="nav-item"><a href="/schema/examples/managing-options/" class="nav-link"><i
      class="fa-solid fa-file fa-margin-adjust"></i><span>Configuration</span></a>
<li class="nav-item"><a href="/schema/examples/external-schemas/" class="nav-link"><i
      class="fa-solid fa-file fa-margin-adjust"></i><span>External References</span></a>
<li class="nav-item"><a href="/schema/examples/version-selection/" class="nav-link"><i
      class="fa-solid fa-file fa-margin-adjust"></i><span>Schema Version</span></a>
<li class="nav-item"><a href="/schema/examples/custom-vocabs/" class="nav-link"><i
      class="fa-solid fa-file fa-margin-adjust"></i><span>Custom Vocabs</span></a>

(both examples prettified by VSCode)

this part seems wrong to me -regardless if it works locally but not somewhere else:

 {% elsif doc.close %}
          </ul>
        </li>

the if above it opens the li but doesn’t close it - since this is elsif won’t it be skipped even if it is true? since the if is true this won’t run? I could be wrong on this, I’m not actually sure. But I am assuming they are both true in which case I think this should be an if with an endif rather than an elsif - I’m thinking the first if is true and then it skips the else as there is no else if the if is true? then there is no closing li.

As for your last code snip - where are you getting it where you say it is the local version and has the closing li’s? from the actual file? or from the browser dev tools?

I also have seen dev tools insert missing tags, so make sure locally you are seeing the closing li by looking at the actual rendered file in the site folder.

What are the values of doc.close and doc.open? it looks like they are both false and all of this is coming from the else part?

I’m poking around a bit and I have to say the site is fairly imposing / impressive / complicated. The way it looks like you are looping over the collections to make the sidebar is interesting, I’m not sure I understand it completely so my advice above may be totally wrong as I was assuming one file would have all those values but it looks like different files do different things in regard to the final output of the sidebar.

In each folder I have two marker files with the order property specified so that one marks the start of a folder (folder: true) and the other marks the end (close: true). So for every folder:

  • I get a start marker ({% if doc.folder %}), which creates a <li>, then opens a <ul> for the contents.
  • I get a number of regular files ({% else %}), which just adds a complete <li>...</li> (but the </li> isn’t being added here).
  • I get a close marker ({% elsif doc.close %}), which closes the nested list with </ul> and closes the containing </li> opened for the folder (and the </li> isn’t added here either).

I have to have the last two swapped because of how the if/else logic works, so it’s a little hard to follow.

When jekyll runs, it only gives me a flat collection of the files. I don’t have (know of) a way to get the hierarchy information, so this is what I’ve done.

I’m definitely a newbie at this. I’m a backend pro, but a frontend novice. And I’m most comfortable in .Net.

If there’s a better way to build this, I’m very open to it, but I haven’t found anything, so I had to get inventive.

I’ve never done a nested nav structure like you have, so I am not going to be the best source of how to do that. At a glance I would say there is a better way but that isn’t helpful.

But like I said I have not done it and it is possible you are far ahead of me in getting it to do what you want.

But none of that addresses your issue of why it builds different locally.

When you deploy it to GH how is it building it - looks like you are using an action?

when you build locally are you using node? I see a package.json file but there isn’t much in it other than the chirpy stuff and I am not familiar with it.

And to be clear - when you do it locally and look at the site folder files themselves in VS Code (or whatever) the li is closed properly? your example code above is from that right? not from the browser?

for a docs website I always liked this guys theme:

and it has a fairly complex sidebar, could be good inspiration.

I used chirpy as a base since I used the full template for my blog (another subdomain on the same site). The sidebar was completely reworked, though, to do… this.

Yeah, I’m using a GH Action to build and deploy this. It doesn’t show much in the logs, though. I’m not sure if (or how) I can set it up for verbose logging.

I looked at that theme for inspiration and it was a lot more complex than I could figure out. I need the theme from chirpy though, again, to match the blog and main site.

All the missing </li> tags on the production site suggest some sort of HTML minification. In HTML, some end tags (</li>, </p>, etc) can (sometimes) be optional. Is it possible the production build is using a minifying plugin or something?

I see that the _config.yml has some setting for HTML compression, which are only run for production (i.e. JEKYLL_ENV=production). You might try commenting that out (or locally remove the ignore development to see the compression locally):

compress_html:
  clippings: all
  comments: all
  endings: all
  profile: false
  blanklines: false
  ignore:
    envs: [development]

I think the problem may be that the HTML compressor assumes 100% syntactically valid HTML and so stumbles when it encounters <hr> between li elements. Technically, the <hr> is not allowed between the list elements (i.e. lists can only contain list elements), so the compressor blithely removes the close tag </li> before an <hr>, which changes the resulting DOM structure.

1 Like

remove the ignore development to see the compression locally

That definitely reproduced it locally for me. Thanks.

Now that I have a direction, I should be able to figure out a way to make this work. I really like having the <hr> in there, so if it’s not “correct” HTML, I’ll have to just work around that.

Ultimately, I just commented out the endings line, so it’s no longer removing optional tags. That did the trick. Thanks so much.

2 Likes