Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support page top header #733

Merged
merged 15 commits into from
Mar 28, 2019
Merged

Conversation

Chng-Zhi-Xuan
Copy link
Contributor

@Chng-Zhi-Xuan Chng-Zhi-Xuan commented Feb 27, 2019

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] New feature
• [x] Enhancement to an existing feature

Resolves #636
Resolves #549
Fixes #755

What changes did you make? (Give an overview)

  • Changed MarkBind template to adopt the Holy Grail Layout, implemented using Flex Box (See No.1 in References).
  • site-nav and page-nav are now in the same flex-body-div as the content, and are using position: sticky to have it follow the user as they are scrolling through content.
  • Abstracted content wrapper handling from both site-nav.css and page-nav.css to the #content-wrapper ID within markbind.css.
  • All authored sections (site-nav, header, footer) is appended to the page content so that we only call MarkBind parser once.
  • The Page then collects the appended sections from the content, stored in a Page variable before mapping to the template variables.

Removals (Justification in Discussion)

  • Removed site-nav button
  • Removed support for inline footers
  • Removed scrollIntoView

Implementation Discussion

  • In the new layout, expanding site-nav using the button (on smaller screens) will cause the content to shift, causing stuttering of the page.

    • Solution 1, change to position: fixed instead of flex box when screen is small.
      Maintain existing behaviour. However, when transitioning from position: sticky to position: fixed has stuttering and animation issues.
    • Solution 2, duplicate site navigation content to a dropdown list in the top nav
      This solution becomes complex if we want to automate this, by inserting into an existing top nav or to render a top nav responsively if there isn't any.
  • Removed scrollIntoView within setup.js#pageNavSetup()

    • Reason being that it breaks with position: sticky elements
  • Remove any inline <header> or <footer> elements

    • The main index.md file should contain content for the <main> part of the page, and should not overlap with <header> or <footer>
    • Encourage re-usability of headers and footers
    • Compatibility with content-wrapper for searching and indexing headings

Is there anything you'd like reviewers to focus on?

  • Code style
  • Edge cases that will break current layout
  • Naming of variables / functions
To Do List Done ?
Add initial template for header file ✔️
Update Site.test.js ✔️
Extended PR to fix #755 ✔️
Allow scrolling of sticky navigation bars ✔️
Update documentation for Footers and Headers ✔️
References
1. Holy Grail Layout with Flex Box
2. Holy Grail Layout
3. Complete guide to Flex Box
4. Making Elements Stick in CSS
5. overflow: hidden breaks position: sticky

Testing instructions:

  • Download holy-grail-demo-v2.zip
  • Extract and run markbind serve in the directory
  • Test new layout, header file support etc.

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Feb 27, 2019

CS3282 Team members are welcome to provide reviews 😄

Since the To Do is minimal, you can start reviewing even though it is still [WIP]

@acjh
Copy link
Contributor

acjh commented Feb 27, 2019

What changes did you make? (Give an overview)

  • ...
  • ...
  • All authored sections (site-nav, header, footer) is appended to the page content so that we only call MarkBind parser once.
  • Does this affect [[toc]] in page if there are headings in footer? (Should not.)
    I suppose this doesn't affect search indexing.

  • Does this affect variables in footer that are undefined in variables.md? (Should not.)

  • How about pre-parsing header and footer, so that they are only ever parsed once?

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Feb 27, 2019

  • Does this affect [[toc]] in page if there are headings in footer? (Should not.)
    I suppose this doesn't affect search indexing.

Headings are only collected within the content wrapper after the page is finished generating. It will exclude page-nav, site-nav, header and footer sections as they will have been separated from the content before the file write. (From collection methods)

  • Does this affect variables in footer that are undefined in variables.md? (Should not.)

I did not change anything other than removing inline footers, so existing behaviour (not affecting) should be preserved for file footers.

  • How about pre-parsing header and footer, so that they are only ever parsed once?

This is a great idea, but would require us to pre-parse all site-nav, footers and headings as well as those contained within layout folders before generating the pages.

As the changes required to Site.js seems extensive, should we push this to a separate issue?

/**
* Inserts the footer specified in front matter to the end of the page
* @param pageData a page with its front matter collected
*/
Page.prototype.insertFooter = function (pageData) {
Page.prototype.insertFooterFile = function (pageData) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was thinking if this can be refactored into a plugin? Similar to #714 ? Just a side thought though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will take a look if it is feasible.

Although I am thinking that specifying plugins is less user intuitive compared to the current implementation of specifying via <frontmatter> or using layouts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already pass frontMatter to plugins right?

@pyokagan
Copy link

@Chng-Zhi-Xuan Thanks so much for taking a look at this 👍

As an aside, seems like the site nav links in https://deploy-preview-733--markbind-master.netlify.com/userguide/ are broken.

@damithc
Copy link
Contributor

damithc commented Feb 27, 2019

@Chng-Zhi-Xuan Thanks so much for taking a look at this 👍

yup, thanks for tackling this major feature @Chng-Zhi-Xuan

Copy link
Contributor

@marvinchin marvinchin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of questions! 🙂

Page.prototype.insertHeaderFile = function (pageData) {
const { header } = this.frontMatter;
let headerFile;
if (header) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering - could header be an empty string'' (this would resolve to false)? If so, should do a check for header === undefined here instead to be more explicit?

Copy link
Contributor Author

@Chng-Zhi-Xuan Chng-Zhi-Xuan Feb 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it could be an empty string but the user would have to explicitly specify a header field in <frontmatter> and leave it empty.

Also, empty string is a falsy value, so it will still go to the else statement.

Note that the first statement is to check for any value specified within <frontmatter>, the logic of header === undefined is not correct (since it will be false when a valid string is given).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think it should have been header !== undefined instead, but if the way we handle an empty header is the same as the way we handle the case where no header is defined, it might not be necessary.

Thanks for the clarification! 🙂

src/Page.js Outdated
this.content = htmlBeautify($.html(), { indent_size: 2 });
};

Page.prototype.collectSiteNavigation = function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method seems rather similar to collectHeader. Would it make sense to abstract this behaviour into another method?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same applies for the collectFooter method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you mentioned it, we could abstract it to

Page.prototype.collectPageSection = function (section) {
  const $ = cheerio.load(this.content, { xmlMode: false });
  const selectedSection = $(section)
  ....
  this.pageSections[section] = $.html(section);
}

Page.collectAllPageSection = function () {
  this.collectPageSection('header');
  this.collectPageSection(`#${SITE_NAV_ID}`);
  this.collectPageSection('footer');
}

<div id="app">
<div id="content-wrapper">
<div id="app">

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if the empty lines here are intended? 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely due to the line break between template variables within Page.ejs, might look into it (since it is kind of ugly :P)

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Feb 27, 2019

As an aside, seems like the site nav links in https://deploy-preview-733--markbind-master.netlify.com/userguide/ are broken.

@pyokagan , thanks for helping me find a bug!

Due to the positioning of collectSiteNavigation, the site navigation contents did not get parsed through the critical line here:

this.content = nunjucks.renderString(this.content, { baseUrl, hostBaseUrl });

Likewise for the other collected sections.

jQuery(window).on('activate.bs.scrollspy', (event, obj) => {
document.querySelectorAll(`a[href='${obj.relatedTarget}']`).item(0).scrollIntoView(false);
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you planning any workarounds to restore this feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new layout, the sticky page-nav now has the height of the <content> instead of the viewport. So scrollIntoView would not work.

A different work around would need to be implemented, which is an independently scrollable sticky element.

References
Scrollable Sticky Element
Sticky Sidebar

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Mar 13, 2019

Update

Ready for review

  • Updated testing file holy-grail-demo-v2

Would like reviewers to focus on the following:

  • Code style / variable names
  • Commit messages

To Do (Separate PR?)

  • Documentation for Footers has to be updated to reflect the removal of inline footers.
  • Headers documentation has not yet been done.

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Mar 14, 2019

Requesting for CS3282 Team Members Review

@Xenonym @marvinchin @amad-person @sijie123 @luyangkenneth

This is a large feature PR, so it is good exposure to look through and comment/review it :)

Copy link
Contributor

@marvinchin marvinchin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple more (minor minor) questions 🙂

}

/* Responsive site navigation */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the number of blank lines here intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not intended, looks like eslint did not complain about this :P

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ESLint doesn't check CSS files. 🙈

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any interest in adding a linter for css? (e.g. https://stylelint.io) 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any interest in adding a linter for css? (e.g. https://stylelint.io) 🙂

@marvinchin PR is welcome for a css linter.

@@ -78,12 +78,53 @@ code.hljs.inline {
background-color: #fff;
}

/** Holy Grail Layout **/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if the/** is intended instead of /*? I can't seem to find any other comments that use this convention in the codebase 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it was intended for /** Holy Grail Layout **/ to be the main section and for /* Header */, /* Footer */ etc to be sub-sections under the main section.

I agree that it is subtle and not intuitive. Might change the commenting style to something more widely recognised.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After digging around, this seems much better :)

/**
  * Holy Grail Layout 
  *
  * This section covers the common styles used within Header, Footer and Side Navigation bars
  */

<div id="app">
<div id="content-wrapper">
<div id="app">

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a number of extraneous blank lines in the output html. Is this intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not looked into this in depth but I might suspect it is due to prepareTemplateData defaulting to empty string values.

I should test using the <%_ if %> syntax to avoid inserting empty strings and see if there are improvements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update

Tested with <% if (...) %> syntax but does not get rid of the blank lines.

However, adding either -%> or _%> to the end of the template variable insertion works.

Interesting finding:
The indentation before the template variables is only applied to the first line of the inserted html instead of all the lines within the inserted html. I would assume page.ejs is not smart enough to tell apart simple strings vs proper html :P

<div class="text-center">
Default footer
</div>
</footer>
</div>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation here seems off too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be due to the indentation within page.ejs. Seems like a legacy issue since we have been using 4 space indentation within page.ejs but 2 space indentation for htmlBeautify.

src/Page.js Outdated
@@ -150,7 +131,7 @@ function formatSiteNav(renderedSiteNav, src) {
return renderedSiteNav;
}
// Tidy up the style of the unordered list <ul>
listItems.parent().attr('style', 'list-style-type: none; margin-left:-1em');
listItems.parent().addClass('site-nav-list');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move site-nav-list to a constant? (similar to page-nav)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this brings up an interesting point.

Relating to Webstorm IDE (maybe other IDEs as well), where if you refactor CSS names, it will automatically change the name of that class within html strings or function parameters that take in CSS names. However, constant strings with the same name will not be refactored.

Also, we shouldn't use a constant for a string if it is only used once throughout the whole file.

So we should be finding single use constants and changing them back to be used inline? (site-nav-list only appears once)

Copy link
Member

@yamgent yamgent Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I would say that there's still value in refactoring it even if it is a single use now, because in case in the future we need to use this somewhere else in the code, we need not do the refactoring again (which is also provided that we even realise that the same class is used here. If we forgot about it EDIT: because not everyone uses IDE, then we are using "magic values" everywhere).

+ '</nav>\n';

return `${wrappedSiteNav}`
+ `${pageData}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would return `${wrappedSiteNav}${pageData}`; work instead? 🙂

Copy link
Contributor Author

@Chng-Zhi-Xuan Chng-Zhi-Xuan Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would work. However, within wrappedSiteNav there is a line break at the end of the string. So I wrote it in this manner to visually represent that wrappedSiteNav and pageData is separated by one line break.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move the \n out of wrappedSiteNav to here, so that the visual representation is consistent.

Copy link
Contributor

@sijie123 sijie123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @Chng-Zhi-Xuan!

I'm not very well versed with CSS, so I can't accurately tell whether the added CSS formatting work correctly in achieving the intended outcome. However, I previewed the netlify site and it looks pretty okay to me.
Edit: Hmm there seems to be a big gap here :O
image
The gap goes away when I start scrolling. I presume it's something to do with the sticky display?

For my review, I will focus more on the back-end side of parsing things. Other than the extra indentations probably caused by the beautifier (thanks @marvinchin!), I just have one small comment w.r.t Page.js

There's also something that I noticed, but it's not relevant to this PR. I'll open up a new issue in a bit.

}
const headerPath = path.join(this.rootPath, headerFile);
if (!fs.existsSync(headerPath)) {
return pageData;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we log an error here?
Otherwise, there would be no header content but the user won't know why.

Copy link
Contributor Author

@Chng-Zhi-Xuan Chng-Zhi-Xuan Mar 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since headers and footers are optional, an explicit error should not be logged.

To add on, other optional items such as site-nav and page-nav are also not logged if they are not added.

Furthermore, if we do log it then the console will be filled with messages if there are a significant amount of pages with missing header files.

Although I can see explicit logging useful for debugging purposes. E.G.

header file skipped: header file not found
page navigation added: {Title: Test Title} {headingIndexingLevel: 2}
footer file skipped: footer not specified, layout not specified

But alas, not in the scope of this PR :)

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Mar 20, 2019

@sijie123 , Thanks for looking through. To reply the CSS part:

.spacer-top {
    /*
      spacer-top class is a work around for MarkBind <navbar> component using "position: fixed".
      This class can be removed once the component's position type is changed.
    */
    padding-top: 70px;
}

Both site-nav and page-nav are using .spacer-top class for the reason stated in the comment 😄. If this is not added, then the top part of both site-nav and page-nav will be blocked behind the <navbar> component.

@Chng-Zhi-Xuan Chng-Zhi-Xuan force-pushed the 636-holygrail-layout branch 4 times, most recently from 1e7b75f to 2072f33 Compare March 20, 2019 08:58
@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Mar 20, 2019

Update

Review Amendments:

  • Removed additional blank lines in page-nav.css
  • Modified comments in markbind.css
  • Added _%> to template variable insertions within page.ejs to fix blank lines in output html
  • Refactored site-nav-list and page-nav-nav title to constants
  • Moved last \n from wrappedSiteNav to return statement

Modifications:

  • Rebased to latest master
  • Changed footers.mbdf to reflect new behaviour
  • Added headers.mbdf for new feature

Documentation links
Headers
Reader Facing Features
Full Syntax Reference

Follow up:

  • Create pull request in vue-strap repository to change any components using position: fixed. Specifically, <navbar> is the priority.

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a glance at all of the commits except the last commit (the test files update commit), don't think I spot any major issues so far, will look at the rest at a later time.

@Chng-Zhi-Xuan
Copy link
Contributor Author

Update

  • Rebase to latest master

@Chng-Zhi-Xuan
Copy link
Contributor Author

Update

  • Added html formatting after output html is generated, before file write. Fixes indentation issues caused by new layout within Page.ejs.

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments are mostly cosmetic changes, but otherwise I think this PR is mostly fine 👍.


**You can specify a <tooltip content="Content to be placed at the top of a page.">page header</tooltip>** above your page contents and <tooltip content="Site Navigation and <br>Page Navigation menus">navigation menus</tooltip> using a `header file`.

You can save multiple `header files` in the `_markbind/headers` folder and specify it in the `<frontmatter>` of the pages in which it should appear.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of code rendering for the words header files and footer files looks out of place.

Change header files -> header files? And do the same for footer files.

@@ -94,9 +95,19 @@ const FOOTER_DEFAULT = '<footer>\n'
+ ' </div>\n'
+ '</footer>\n';

const HEADER_DEFAULT = '<header>\n'
+ ' <div class="bg-primary display-4 text-center text-white">\n'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is subjective, but the default header generated seems to be too dominating compared to the rest of the parts of the webpage. :P

This is how it looks like now with a markbind init website:

Copy link
Contributor Author

@Chng-Zhi-Xuan Chng-Zhi-Xuan Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended to be a large banner / Jumbotron. Similar to the one in Markdown Guide.

Also, display-4 is the smallest banner text on Bootstrap without adding additional styles into .scss ( >_<)

@@ -1,58 +1,64 @@
<!DOCTYPE html>
<html>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test site doesn't seem to have a page that uses our new headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I avoided placing a Jumbotron on the test site as the current top nav bar will block it.

After a PR is done to modify <navbar> in the vue-strap repo, we require another PR here to update our usage of <navbar>. Within that PR, we can add testing header elements.

The current functionality of the site nav expand button
is to change the width of site nav to either hide or show
it on smaller screen widths.

Under the new layout, changing the width of any side
navigation menus will result in content shifting within
the main content page. This is not reader friendly so let's
remove the functionality.
Inline styles cannot be overwritten by authors, so let's
refactor them into classes for easy overwritting.
Modifications to the previous implementation of site nav
is necessary for compatibility with the new holy grail layout.
Using position sticky breaks the functionality of
scrollIntoView() so let's remove it.
Modifications to the previous implementation of page nav
is necessary for compatibility with the new holy grail layout.

page nav wrapper was removed as altering the margin of
the page content is no longer necessary.
With the new template requiring the page sections to be
individually accessable via a variable, a collection method
is necessary.

Another benefit is that it decouples the page content
from any other page section elements.
Most of the layout styles that were related to flexbox
has been ported to markbind.css as site-nav and page-nav
both require it.
The behaviour of inline footers has changed in this pull request.

Let's update the documentation to reflect that.
As Headers is a new feature supported in this pull request,
we should have documentation to describe how it works.
Within Page.ejs, it has indentations before insertion of template
variables to represent the holy grail layout. However, due to
limitations of the .ejs API, the additional white spaces
can't be trimmed if a certain template variable was not inserted.

Let's call htmlBeautify after the output html is fully generated
before doing a file write to ensure consistent formatting.
@damithc
Copy link
Contributor

damithc commented Mar 27, 2019

@Chng-Zhi-Xuan What if I want to have the same navbar in multiple pages but I also want a different jumbotron in each page e.g., https://www.markdownguide.org? Do I need to create many different header files and duplicate the navbar code in each (as include is not allowed in header files)?

@damithc
Copy link
Contributor

damithc commented Mar 27, 2019

image

With respect to the above, why not allow the header to be cumulative, in the order they are specified?

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Mar 28, 2019

@damithc

What if I want to have the same navbar in multiple pages but I also want a different jumbotron in each page? ...

Unfortunately yes, you have to have multiple header files if the content is different as there is no way to add content to the header file outside of authoring it.

Although supporting includes within site-nav, footers and headers can be done if we preprocess those files first before generating pages.

This was mentioned by Aaron above, "How about pre-parsing header and footer, so that they are only ever parsed once?".

With respect to the above, why not allow the header to be cumulative, in the order they are specified?

I found a relevant discussion, "Should header and footer tags be inside main tag?".

Unless the inline <header> tag has content relevant to the <main> of the page, it should be placed outside of <main>. Since shifting <header> tags breaks the author layout, removing it ensures consistency with the pre-defined holy grail layout.

Consecutive header tags are supported in the current implementation, as long as it is within the same header file.

<!-- within my-header.md -->
<header class"top-nav-stuff">
   ...
</header>
<header class="jumboBlue">
  ...
</header>

@yamgent yamgent merged commit 0efb692 into MarkBind:master Mar 28, 2019
@damithc
Copy link
Contributor

damithc commented Mar 28, 2019

What I'm trying to do is something like this:

<frontmatter>
header: top-nav.md
</frontmatter>

<header class="jumboBlue">
  ...
</header>

That way, I can put the topnav in the header file (as it is common to all pages) and then add on a page specific-jumbotron below it in each page.

The documentation says inline headers will be removed. Do we even support inline headers? The docs doesn't say how to use an inline header.

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Apr 1, 2019

@damithc Sorry, missed this comment

What I'm trying to do is something like this: ...

This is definitely possible. but can be confusing for the user. E.G

<!-- Input by author -->
<frontmatter>
  header: shared-header.md
<frontmatter>

<header class=jumboBlue>
   Text 1
</header>

Some content 1

<header class="detailed-desc">
    Description text
</header>

Some content 2 
<!-- Output by MarkBind -->
<header>
   sharedHeader
</header>
<header class="JumboBlue">
  Text 1
</header>
<header class="detailed-desc">
  Description text
</header>
<div id="content-wrapper">
  Some Content 1
  Some Content 2 
</div>

As we have to shift every header outside the content-wrapper, we might mess up what the author intended.

Alternatives to this are less elegant than enforcing strict use of footer/header files:

  • Add support for multiple inline footers and headers. However the inline headers and footer boundaries will be restricted to <div id="content-wrapper"> and won't span the entire page if either site-nav or page-nav is specified.
  • Have only top level headers (above content and below front matter) be shifted outside. A bit hacky, requires a lot of edge case checking / testing (headers in components, empty content, etc).

The documentation says inline headers will be removed. Do we even support inline headers? The docs doesn't say how to use an inline header.

Existing documentation specified use of Inline footers but was removed. It was supported prior to this PR. Specifically it was for inline footers. Where inline footers will override specified footers. This feature has been removed, and the new behaviour is ported over to headers as well, thus the notes being almost identical.

I would agree that adding some context of what are inline headers and footers to the user guide would be better.

@yamgent
Copy link
Member

yamgent commented Apr 1, 2019

I would agree that adding some context of what are inline headers and footers to the user guide would be better.

It is strange to explain a feature that no longer works though.

@Chng-Zhi-Xuan
Copy link
Contributor Author

It is strange to explain a feature that no longer works though.

It is not really a feature, but something that can be created by the author. As inline headers and footers (within the <body> tag) can exist in normal HTML web pages.

@damithc
Copy link
Contributor

damithc commented Apr 1, 2019

It is not really a feature, but something that can be created by the author. As inline headers and footers (within the <body> tag) can exist in normal HTML web pages.

Oh? Didn't realize they are normal HTML tags. In that case shouldn't we have used some other tags e.g., <md-header> to avoid confusion?

@Chng-Zhi-Xuan
Copy link
Contributor Author

Chng-Zhi-Xuan commented Apr 1, 2019

I would like to clarify what would be the purpose of a custom tag for headers? (For inline headers or for the tag used within header.md?)

Since functionally there is no special operations being performed on <header> tags other than insertion and collection (same as <footer>).

@damithc
Copy link
Contributor

damithc commented Apr 1, 2019

Since functionally there is no special operations being performed on <header> tags other than insertion and collection (same as <footer>).

If there is no difference, then it makes sense to use the same tag. 👍
However, it feels like we ended up defining two types of headers: those that are put outside content-wrapper and those that will not be put outside the content-wrapper?

This is definitely possible. but can be confusing for the user. E.G

<!-- Input by author -->
<frontmatter>
  header: shared-header.md
<frontmatter>

<header class=jumboBlue>
   Text 1
</header>

Some content 1

<header class="detailed-desc">
    Description text
</header>

Some content 2 
<!-- Output by MarkBind -->
<header>
   sharedHeader
</header>
<header class="JumboBlue">
  Text 1
</header>
<header class="detailed-desc">
  Description text
</header>
<div id="content-wrapper">
  Some Content 1
  Some Content 2 
</div>

As we have to shift every header outside the content-wrapper, we might mess up what the author intended.

I can live with that, as it would solve my immediate problem. :-)
In other words, we move all headers outside of content wrapper.

Alternatively, we can provide some attribute (or a different tag) to differentiate between the two types of headers.

What do you think?

@Chng-Zhi-Xuan
Copy link
Contributor Author

A different tag would be appropriate (since we will be shifting the position of that tag)

Implementation should be simple, by using Cheerio to select and shift the headers with that specific tag to the top. It will be appended sequentially and keeping any classes authored on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants