sintaxi / harp

Static Web Server/Generator/Bundler
http://harpjs.com
5k stars 342 forks source link

"Dynamic pages" from metadata and a layout #217

Open archseer opened 10 years ago

archseer commented 10 years ago

Based on my IRC discussion with @silentrob, I have a quick feature request. I'm writing documentation for code, and my custom parser basically produces JSON hashes right now. So my idea was, since all of the pages have exactly the same layout, that I would create a _layout.jade file containing all of the layout (and no yield), and simply export all of the content into _data.json, essentially creating "dynamic" pages without their separate page files -- Instead of using the metadata to add to .jade pages, I'd use that metadata to create a page.

This is an example of that usage:

_data.json

{
  "class1": {
    "name": "Class1",
    "description": "Lorem ipsum"
  },

  "class2": {
    "name": "Class1",
    "description": "Lorem ipsum"
  }
}

_layout.jade

h1= name

p= description

This would make two pages accessible, /class1 and /class2.

The way Harp currently works is that each page needs it's own file, or else it 404's, so I'm circumventing that by simply creating empty .jade files for all of these pages, but I would love to be able to skip this in the future.

silentrob commented 10 years ago

So to be clear, this is nearly possible now. You would have a _layout.jade

html
  head
  body
   -yield

class1.jade

!=partial("_template")

class2.jade

!=partial("_template")

_template.jade

h1= name
p= description
archseer commented 10 years ago

Well the way I do it right now is that I just make empty files:

_data.json
{
  "class1": {
    "name": "Class1",
    "description": "Lorem ipsum"
  },

  "class2": {
    "name": "Class1",
    "description": "Lorem ipsum"
  }
}
_layout.jade
html
  head
  body
    h1= name
    p= description
class1.jade
// empty
class2.jade
// empty

The only change would be that Harp would no longer need a file per page, so that using just the metadata would be possible.

philholden commented 10 years ago

I am having the same issue for pagination and tags in my blog. I am creating empty files called 1.md and 2.md to each list 10 blog posts. I wish there were a way to pragmatically generate these files and directories by filtering and mapping the public contents object.

kennethormandy commented 10 years ago

We’ve definitely been hearing that from people and it’s something we’d like to see added. I don’t think there’s any timeline on it unless someone would like to help contribute, though.

In the meantime, one option would be to output all 100 items (or however many) on one page, and dynamically paginate client-side. This is a little unconventional, but still worth looking into, I think.

mderazon commented 10 years ago

:+1: I am too struggling to figure out how to do this.

Basically, I have /lessons folder that contains many lessons and a single _layout file Now I want to create a "printer friendly" version of these lessons.

I thought about creating a lessons/print folder, put a different stripped _layout file there without any styling. This stripped layout file will contain yield of the relevant lesson from the parent folder. Problem is that I don't see any way to make the /lessons/print/lessonX route approachable without creating empty files in the /lessons/print folder.

Any idea how to workaround it ?

jxm262 commented 9 years ago

:+1: we're currently looking into static site generators and would love this feature. For now, to achieve this functionality, our group is probably just going to use Jekyll and hook into their custom generator during the build process. I would LOVE to see this as a feature in Harp

jxm262 commented 9 years ago

@kennethormandy @archSeer I wouldn't mind trying to contribute and adding this functionality, but not sure how we would specify to output specific files.

For instance should there be additional syntax on the -yield somehow?

Some optional field like 'createStatic: jade' on each section in the data ?

"class1": {
    "createStatic": "jade",  //specify the type
    "name": "Class1",
    "description": "Lorem ipsum"
  }

Maybe some optional compile flag , but then we'd need some additional way (config file) , to specify what specific data should output a new static file.

Or what would be a good way to have the user specify that they want the static file created on the fly?

ir-g commented 9 years ago

@jxm262 @kennethormandy @archSeer I love this idea, and I think there might be an easy-ish way of implementing it.

In the parent folder of the location of the page in use, you could have an _dynamic folder.

So, if you wanted to have the page:

classes/{{className}}

you create the folder:

classes/_dynamic/

and then inside that folder you would have the following files:

thoughts?

chandu commented 9 years ago

Is there any possible workaround for this?

feedmac commented 9 years ago

+1, I also have to create empty pages as a workaround for this - which is really counter-intuitive.

Now if only we could add metadata (JSON) as pages, like Wintersmith enables you to. This means that @archSeer could just create class1.json and class2.json and put the metadata in there.

For me this would be a great start, and in my case it would be better to have seperate json files than one big data.json.

Is this something that would be easy to implement?

quanglam2807 commented 8 years ago

+1

edrex commented 8 years ago

I agree that some important use cases would be enabled by page generation from metadata (per-tag pages, paginated indexes). It's hard to come up with a design that fits with Harp.

It's still a bit fuzzy, but I think I have a design that could work, without adding too much API surface area.

The idea is to introduce a generatePage helper function, accessible from EJS/Jade templates. The calling page would cause a page to be generated in the output. This could be done inside a for loop (which would be useful for outputting a page for each tag used on the site), or recursively (useful for paging out an index).

generatePage(name, data, template) would output a page name (path relative to current page, with optional extension) by passing data to template. Template could be a Jade or EJS file. data might contain a content key which would be passed to yield, or maybe yield would just get an empty string.

I'd be up for working on an implementation of this. It would need good test coverage to make sure it works as expected and doesn't overwrite anything important/escape the output dir/etc. @sintaxi @kennethormandy what do you think?

lluishi93 commented 5 years ago

Any news on this? I love harp js, but this is really its weak point, and such a basic functionality of other frameworks