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

Proposal: multiple formats per page using layouts #3041

Open
Floppy opened this issue Oct 30, 2014 · 103 comments
Open

Proposal: multiple formats per page using layouts #3041

Floppy opened this issue Oct 30, 2014 · 103 comments
Labels
feature help-wanted pinned up-for-grabs ☕ You're welcome to work on this issue
Milestone

Comments

@Floppy
Copy link
Contributor

Floppy commented Oct 30, 2014

As far as I can tell, it's not possible to have two output formats for a single page/post at the moment.

We have a case where we'd like to generate an iCal file for each post, as well as the HTML version. It seems to me that a nice way to do this would be to allow multiple extensions for each layout, and generate a file for each extension in the specified layout.

For instance, if we had a post 2014-10-30-hello-world.md, and two layouts, _layouts/post.html and _layouts/post.ical, you would end up with output in both /2014/10/30/hello-world.html and /2014/10/30/hello-world.ical.

I'll have a go at this when I find time, but I was wondering if anyone could highlight any fundamental reasons why this wouldn't work, or problems that might be encountered when writing it?

@pikesley
Copy link

+1 for this, I'd like to generate static JSON for some of my pages too...

@Floppy
Copy link
Contributor Author

Floppy commented Nov 5, 2014

@benbalter any thoughts on this? Seems the kind of thing you might find useful.

@benbalter
Copy link
Contributor

Yesssssss. I swear I opened an issue for this a while back, but can't seem to find it.

All for this (json is my use case), but can't think of a sane ux. Perhaps a layouts key which accepts an array?

@Floppy
Copy link
Contributor Author

Floppy commented Nov 5, 2014

I figure you have the same layout name, so nothing changes post-side, but you just render all layout formats with the same base name, i.e. 'layout.html' and 'layout.json'.

@Floppy
Copy link
Contributor Author

Floppy commented Nov 5, 2014

Obviously this would only work well for pages and posts that have most of their data in the yaml front matter, otherwise rendering to JSON would be kind of meaningless anyway.

@benbalter
Copy link
Contributor

render all layout formats with the same base name, i.e. 'layout.html' and 'layout.json'.

Makes sense. @parkr any strong opinion on this? To me it's in line with Jekyll's do what I ask, no more, no less philosophy, and does exactly what you'd expect.

@parkr
Copy link
Member

parkr commented Nov 5, 2014

@parkr any strong opinion on this?

Only strong opinion is that it's backwards-compatible. A layout like default will have to ask for default.html, whereas a layout like default.json will have to ask for default.json. We'll have to do a File.file?(layout_key) to see if it's there and ensure security is tight around this check, but other than that this is doable. It'd have to be in the layout key for this to work and we'll have to mostly rewrite the way we render to keep track of a content list rather than a content string. It redefines what we call a Page, Post or Document as a one-input-many-outputs (where many is >= 1) document. The 1-1 relationship could no longer be assumed but would still have to be supported. They'll just be 2 files sitting side-by-side with different file extensions. Is that what you're looking for?

In general I'm 👍, but it's going to be a pretty heavy lift. Any help would be greatly appreciated.

@Floppy
Copy link
Contributor Author

Floppy commented Nov 6, 2014

@parkr: I'm thinking more that the pages would remain the same, just referencing layout: default, and then Jekyll would render output for each of _layouts\default.*. Does that make sense?
I'll try to get a PR together soon with a first implementation - I'm not expecting anyone else to do this just because I want it, though obviously feel free if you do want to :)

@kbrock
Copy link

kbrock commented Nov 15, 2014

very cool 👍

@parkr
Copy link
Member

parkr commented Nov 18, 2014

I'm thinking more that the pages would remain the same, just referencing layout: default, and then Jekyll would render output for each of _layouts\default.*. Does that make sense?

Interesting! What happens when I have layout: default for one page and want html and csv, but I have another that ought to have the html but only the HTML with my default layout? Seems like automatically filling all the default.* layouts would lead to issues.

@benbalter
Copy link
Contributor

I'm liking @Floppy's implementation. Sure there's an edge case where I only want one and get both, but I'd argue that (A) that's an edge case (I can't think of an example), and (B) there's no risk to having an extra CSV file that nobody views (and (C) just make a new layout). Not worth the 10 fold complexity to handle it.

@parkr
Copy link
Member

parkr commented Nov 18, 2014

I'll definitely look at an implementation, but I'm skeptical that it's the best UX going forward. Any magic causes confusion and makes Jekyll harder to use. This is borderline magic. How does it work when a layout has a layout and the parent layout has two extensions?

@benbalter
Copy link
Contributor

This is borderline magic.

Ugh. Hate working with @parkr. Always crushes my dreams with his "logic". Jekyll philosophy dictates:

Jekyll does what you tell it to do — no more, no less. It doesn't try to outsmart users by making bold assumptions, nor does it burden them with needless complexity and configuration. Put simply, Jekyll gets out of your way and allows you to concentrate on what truly matters: your content.

Is this an inaccurate description of current user practice?: Users create a layout (let's call it layout.html) and then reference it in the post as layout: layout, assuming the html is implied. Are there many non-HTML use cases? Is that a primary use case we want to support?

What if we extend the design pattern of plurals and say layout: layout or layouts: [layout.html, layout.csv], again with HTML implied?

@Floppy
Copy link
Contributor Author

Floppy commented Nov 19, 2014

I think, for the nested layout case, if we had my_layout.html and my_layout.json nested inside default, if default.json doesn't exist then it wouldn't be used. But that may seem unpredictable, I'm not sure.

@parkr
Copy link
Member

parkr commented Nov 21, 2014

Are there many non-HTML use cases?

Not many, in my opinion. A json layout is the only compelling use case I can think of for this feature. It's something I'd use, but is it something 80% of our users would use? Not sure. It would certainly make API-ifying your posts, for example, a whole lot easier. Layouts are meant to make it all easier. We just have to make sure it's still easy to understand – i.e. keep the cognitive load as low as possible.

What if we extend the design pattern of plurals and say layout: layout or layouts: [layout.html, layout.csv], again with HTML implied?

Imagine writing a page you want for both layouts and you type layout: [layout.html, layout.csv] and "my gosh, jekyll keeps failing!!! what gives?!?!" If you didn't need the extra s, you'd be fine. I like how redirect_from can take either null, a String, or an Array. It's so nice to have that freedom, and it makes the layouts you're using explicit. This can be paired with front matter defaults to reduce duplication. Essentially, I want the user to know "this page is going through the HTML and the JSON layouts, and I know that because I see it right here in the file." Boom, explicit, transparent, and simple.

@Floppy
Copy link
Contributor Author

Floppy commented Nov 21, 2014

If you want formats to be explicit in the frontmatter, then perhaps it's better to leave layouts alone and add a format(s): [html, csv] option to the frontmatter? Jekyll would explode in the usual way with unknown layout if the right layout extension didn't exist...

As for use cases, a couple of thoughts;

  • https://github.com/rawfunkmaharishi/rawfunkmaharishi.github.io uses posts for gig dates. They want an add to calendar option, so having an ICS view of each post would be great. That's the idea that originally prompted this for me.
  • As you say, JSON views for posts, so people can publish data derived from their site content, as well as vice versa as they can already.
  • Vcard files generated from pages from individual people.
  • SVG, perhaps?

I'm sure there are more, but these are the ones that spring to mind quickly. I'm interested in seeing just how data-capable we can make github/jekyll/pages etc, and so these are all things that I'd love to be able to do.

@kbrock
Copy link

kbrock commented Nov 21, 2014

@Floppy I possibly want multiple html views of the same documents. (e.g.: one formatted as a presentation, and the other as a blog post.)

I like your idea of explicitly specifying the layouts to use in the frontmatter. (whether directly specifying the layout or indirectly by specifying the format)
I wonder where the naming convention comes from. Would the format would be used to derive a new name?


ASIDE:

If you want an ical for the whole site, you could generated one like rss and sitemaps. Just add calendar.ical to the root and go through posts.categories.gigs to formatting them appropriately.

@Floppy
Copy link
Contributor Author

Floppy commented Nov 21, 2014

That's interesting, and would suggest that @parkr's idea of having multiple layouts with optional extensions might be better, so you could have presentation.html and blog_post.html at the same time.

Also, good point on the ical :)

@pikesley
Copy link

That was an astonishingly useful suggestion, I have implemented it here: http://rawfunkmaharishi.uk/calendar.ical , https://github.com/rawfunkmaharishi/rawfunkmaharishi.github.io/blob/master/calendar.ical (this may not be 100% correct, I have just Cargo-Culted my way around iCal)

Thanks :)

@Floppy
Copy link
Contributor Author

Floppy commented Nov 26, 2014

@kbrock Actually two layouts with the same extension would cause name conflicts on the generated files, so that shouldn't be allowed unless we allowed layouts to specify their naming convention for the output, which is a whole other matter.

@parkr
Copy link
Member

parkr commented Nov 29, 2014

PR in the works? Thoughts?

@Floppy
Copy link
Contributor Author

Floppy commented Nov 29, 2014

I've not had time to spend on this yet, but I've not forgotten about it...

@ericmwalsh
Copy link

Is there a PR for this yet?

@kbrock
Copy link

kbrock commented Jan 29, 2015

(I withdraw my request to allow multiple html files from one document)

Anyone able to share the current proposal?

  • How did it know to generate multiple pages?
  • Where is the extension determined? The layout's extension or the front matter of the post?

@ericmwalsh
Copy link

Some thoughts on the proposal:

  • You should be able to choose to generate multiple pages in the config file, the layout file, and the page file (with rules of precedence applying)
  • Layouts can be listed out... ex. layout: page-article page-article.json
  • For backward compatibility layouts listed without an extension (*.whatever) should default to HTML (or whichever user default is already specified)

@dominikwilkowski
Copy link

👍

@saclark
Copy link

saclark commented Apr 21, 2015

👍 I wrote a plugin a while back to accomplish this (https://github.com/saclark/jekyll-multipost) but standard support for this would be ten times better.

@IssueHuntBot
Copy link

@0maxxam0 has funded $60.00 to this issue. See it on IssueHunt

@Floppy
Copy link
Contributor Author

Floppy commented Dec 4, 2018

Wow, 4 years old and I've still not started working on this. It'll be old enough to go to school soon. 🍰

@kbrock
Copy link

kbrock commented Dec 4, 2018

@Floppy the multipost code looks like a good start.
Also looks like they have an answer for multiple of the same format (html) and conflicting layouts

@IssueHuntBot
Copy link

@issuehuntfest has funded $100.00 to this issue. See it on IssueHunt

@jekyll jekyll deleted a comment from IssueHuntBot Jan 22, 2019
@jekyll jekyll deleted a comment from IssueHuntBot Jan 22, 2019
@IssueHuntBot
Copy link

@rororofff has funded $2.00 to this issue.


@IssueHuntBot
Copy link

@0maxxam0 has funded $40.00 to this issue.


@IssueHuntBot
Copy link

@serima has funded $2.00 to this issue.


@IssueHuntBot
Copy link

@amthe has funded $2.00 to this issue.


@Chetabahana
Copy link

Chetabahana commented Oct 29, 2019

I would like to share an alternative way using a plug in called jekyll-redirect-from that also available on github pages via this setting on _config.yml:

whitelist:
  - jekyll-redirect-from
plugins:
  - jekyll-redirect-from

Based on your case of a post called 2014-10-30-hello-world.md, and two layouts, _layouts/post.html and _layouts/post.ical with an expected different output in both /2014/10/30/hello-world.html and /2014/10/30/hello-world.ical.

Using different extension but with the same name of layout will not be possible, so we will need to move them in a different folder than _layouts. In this case _includes folder will be used.

In _includes/post.html

move the contents of your _layouts/post.html here..

In _includes/post.ical

move the contents of your _layouts/post.ical here..

Arrange redirection in your post 2014-10-30-hello-world.md

---
redirect_from:
  - /2014/10/30/hello-world.html
  - /2014/10/30/hello-world.ical
---
Hello World

In _layouts/redirect.html

---
layout: my_layout
---
{% include {{ page.redirect.from | split: "." | last | prepend: "post." }} %}

In _layouts/my_layout.html use {{ content }} to render the content

{{ content }}

As result the output of /2014/10/30/hello-world.html and /2014/10/30/hello-world.ical will take _includes/post.html and _includes/post.ical respectively that act here as their layout.

@Floppy
Copy link
Contributor Author

Floppy commented Oct 29, 2019

Oh, @Chetabahana, that is a clever hack - I love it :)

@katcaola
Copy link

A bit late to the party, but I would also like to see this feature implemented.

I would like to have multiple layouts available per post so that I can branch what a post looks like based on how you got to it.

Example: All posts list -> post -> post list still show all posts while viewing post. Simultaneously: Filtered posts list -> post -> post list still show filtered posts while viewing post

wireFrame

@bloombar
Copy link

bloombar commented Jan 18, 2023

Almost a decade later, the generalized plural option for layouts, where either layout: first or layouts: [first, second] seems like it would still work and would be valuable and necessary. The complication from a user's perspective would be the conflict of permalinks - if a single source document, say foo.md (which would usually have a single permalink such as /foo) specifies the use of two or more layouts, how are permalinks handled to avoid conflict?

I propose the following:

  • if only one layout, e.g. layout: first, use the usual permalink, e.g. /foo
  • if two or more layouts, e.g. layouts: [first, second], the first layout in the list uses the usual permalink, e.g. /foo, while the subsequent layouts have the layout name suffix on the permalink, e.g. /foo-second

@ashmaroli
Copy link
Member

Wow! This issue has been incubating for almost a decade now.. Wonder how many of the those desired this feature is still using Jekyll...

@elisehein
Copy link

Wow! This issue has been incubating for almost a decade now.. Wonder how many of the those desired this feature is still using Jekyll...

🖐️

@FrankKooij
Copy link

Wow! This issue has been incubating for almost a decade now.. Wonder how many of the those desired this feature is still using Jekyll...

We are using Jekyll for NSDI data specifications and need this feature for content negotiation.

@Convincible
Copy link

Convincible commented Jan 18, 2023

Still using Jekyll. Still desire this feature!

Agree with @bloombar's approach which should apply only in the case of a filename clash. E.g.

Files in _layouts:

  • a.html
  • b.amp
  • c.json
  • d.html

Inside c.json is also the frontmatter: layout: d (i.e. this layout nests itself in another)

So:

Input file Layouts Output files Note
page.md a, b page.html, page.amp
page.md a, d page.html, page_d.html Filename clash
page.md a, c page.html, page_d.html Filename clash

This allows you to preserve simple filenames for the use case of "one piece of content in multiple formats". In the case where you specify two layouts with the same format, the latter layouts are considered "alternatives" and so the filename is appended with the name of that alternative (the first layout specified is considered "primary").

@bloombar
Copy link

@Convincible - thanks for the detailed description. There are two issues here that might be best kept separate:

  1. allowing multiple layouts (regardless of file extension)
  2. supporting layouts with other content types and file extensions besides just text/html and .html.

The first seems relatively straightforward, if a simple rule is devised like the one you and I have suggested. I believe the second issue might be a bit more challenging, since jekyll does not seem to currently support any content type besides text/html (correct me if that's just my own machine) and I suspect from briefly wrangling with the jeyll-redirect-from plugin (which has problems related to non-HTML content types and file extensions in the redirect-to or redirect-from directives) that the problem is not with jekyll itself, but rather with whichever web server is used to serve the Jekyll pages, webrick or other.

@cycomachead
Copy link

Put me in the camp of someone who also wants this, and who has used Jekyll (off and on) for much of this time. :)

What have other folks been doing in the meantime to get multiple outputs?

I might have a slightly unexpected use case for a project soon, which is to generate both a PDF and HTML version of page.
In that sense, a format of sorts is probably more useful to me than just text layouts, since it could more clearly hook into a converter.

However, it seems like Hooks should be able to do this, perhaps :pre_render or :post_render depending on which format it's easier to write the secondary output from?

@fauno
Copy link
Member

fauno commented Nov 15, 2023

What have other folks been doing in the meantime to get multiple outputs?

What I usually do is create a hook plugin that filters the documents that need another format and create a Jekyll::PageWithoutAFile, Jekyll::Page, or Jekyll::Document.

@seshrs
Copy link
Contributor

seshrs commented Nov 15, 2023

I might have a slightly unexpected use case for a project soon, which is to generate both a PDF and HTML version of page.

I have a similar use case, but rather than create a Jekyll plugin, I personally found it easier to use my own custom GitHub Actions workflow to render the PDFs after running Jekyll.

https://github.com/seshrs/build-primer-spec-action/blob/62703e09107f7d70f6e83f2a60b2690bbe33d98d/action.yml#L77,L92

@bloombar
Copy link

bloombar commented Nov 17, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature help-wanted pinned up-for-grabs ☕ You're welcome to work on this issue
Projects
None yet
Development

No branches or pull requests