Skip to content

Instantly share code, notes, and snippets.

@hyrmn
Created June 3, 2016 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyrmn/28e1cb635ad409826e433cbf7029c5e1 to your computer and use it in GitHub Desktop.
Save hyrmn/28e1cb635ad409826e433cbf7029c5e1 to your computer and use it in GitHub Desktop.
#n Wyam.Markdown -p
#n Wyam.Razor -p
#n Wyam.Yaml -p
#n Wyam.Minification -p
#n AngleSharp
#an "System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
#an "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Settings.Host = "hyr.mn";
//Process each post as /post-sluggified-name/index.html so we get what looks like extensionless pages on gh-pages
Pipelines.Add("Posts",
ReadFiles("posts/*.md"), // Read all markdown files in the "posts" directory
FrontMatter(Yaml()), // Load any frontmatter and parse it as YAML markup
Markdown(), // Render the markdown content
Meta("Post", @doc.Content), // Move the markdown content to metadata
Merge(
ReadFiles("posts/post.cshtml") // Load the Razor post page template
),
Razor(), // Compile and render the page template
Meta("PostFile", string.Format(@"{0}\index.html", ((string)@doc["Title"]).ToLower().Replace(' ', '-'))), // Use the post title as the filename and save it in metadata so we can use it in links later
Meta("PostLink", string.Format(@"{0}/", ((string)@doc["Title"]).ToLower().Replace(' ', '-'))), // Friendly link for post
WriteFiles((string)@doc["PostFile"]) // Write the post file
);
//I want the most recent post to be the home index as well.
Pipelines.Add("MostRecentAsIndex",
ReadFiles("posts/*.md"), // Read all markdown files in the "posts" directory
OrderBy(@doc.Get<DateTime>("Published")),
Take(1),
FrontMatter(Yaml()), // Load any frontmatter and parse it as YAML markup
Markdown(), // Render the markdown content
Meta("Post", @doc.Content), // Move the markdown content to metadata
Razor(), // Compile and render the page template
Meta("PostFile", string.Format(@"{0}\index.html", ((string)@doc["Title"]).ToLower().Replace(' ', '-'))), // Use the post title as the filename and save it in metadata so we can use it in links later
Meta("PostLink", string.Format(@"{0}/", ((string)@doc["Title"]).ToLower().Replace(' ', '-'))), // Friendly link for post
WriteFiles((doc, ctx) => "index.html")
);
//Process the rest of the top-level pages
Pipelines.Add("TopLevel",
ReadFiles("{!_,!index}*.cshtml"),
FrontMatter(Yaml()),
Razor(),
WriteFiles(".html")
);
//Combine and minify the css assets
Pipelines.Add("css",
ReadFiles("css/*.css"),
MinifyCss(),
Combine(),
WriteFiles((doc, ctx) => "css/style.css")
);
//Copy over the other layout assets (images, font)
Pipelines.Add("Assets",
CopyFiles("css/*{!.css,}")
);
@hyrmn
Copy link
Author

hyrmn commented Jun 3, 2016

I'd like to contribute a bit back to the getting-started/configuration section around these two things I ran into.

First question:

Is there a way to utilize the auto-lambda expansion when I'm not using doc or ctx in , for example, WriteFiles((doc, ctx) => "index.html")

Second question:

I'm not clear on how I can chain a child on a module. I see FrontMatter takes in child modules on its ctor and there was an example so that was very straightforward. The other ones like OrderBy didn't click for me though.

What do I need to do here?

    OrderBy(@doc.Get<DateTime>("Published")),
    Take(1),

I've tried

    OrderBy(@doc.Get<DateTime>("Published")).Descending(),
    Take(1),

(did nothing)

and

    OrderByDescending(@doc.Get<DateTime>("Published")),
    Take(1),

(blew up but I expected that)

and

    OrderBy(@doc.Get<DateTime>("Published")),
    Descending(),
    Take(1),

(blew up but I expected that)

I know it's something obvious I'm missing.

@daveaglick
Copy link

Is there a way to utilize the auto-lambda expansion when I'm not using doc or ctx in , for example, WriteFiles((doc, ctx) => "index.html")

Not right now, and that seems like it might be tricky in practice.

The lambda expansion is triggered by finding the magic @doc and/or @ctx identifier. Even that is a tiny bit hacky because you could technically have a variable named @doc, but that seems so unlikely I swept it under the rug. Without one of the two identifiers though, it would be really hard to know when we should expand. For example, does WriteFiles("index.html") mean to use the overload that takes a string or the overload that takes a lambda?

Perhaps we could look at whether the called method only has a single overload that takes a lambda and then only automatically expand those calls, but that would require digging into the semantic layer. Not only would there be a performance impact, the expansion happens before compilation right now. We'd need to compile to get the semantic analysis, but the compilation will have errors because the expansion hasn't happened yet. Chicken and egg. There's probably ways around that, but it'll be hard. It's not a bad idea though, and perhaps there are other ways to accomplish. Let me chew on this one...

@hyrmn
Copy link
Author

hyrmn commented Jun 3, 2016

The lambda is fine. I just wanted to make sure I'm not missing something super-obvious. I think use cases like what I have are uncommon enough that the 'pain' is not a big deal. I think a 1->1 mapping is more common and you've already got @doc or the frontmatter to handle a naming redirect.

@daveaglick
Copy link

The other ones like OrderBy didn't click for me though.

You've got the call right. I would expect the first try of yours to work:

OrderBy(@doc.Get<DateTime>("Published")).Descending(),
Take(1),

I'm assuming this is in relation to the "MostRecentAsIndex" pipeline above:

Pipelines.Add("MostRecentAsIndex",
    ReadFiles("posts/*.md"),  // Read all markdown files in the "posts" directory
    OrderBy(@doc.Get<DateTime>("Published")),
    Take(1),
    FrontMatter(Yaml()),  // Load any frontmatter and parse it as YAML markup
    Markdown(),  // Render the markdown content
        // ...

The problem is that at the point where you're calling OrderBy the front matter hasn't been processed yet, so there isn't a "Published" metadata key in the documents to order by. In that case the delegate that gets the metadata value for OrderBy is returning a default value, which is the same for every document. Change the pipeline to this and it should work:

Pipelines.Add("MostRecentAsIndex",
    ReadFiles("posts/*.md"),  // Read all markdown files in the "posts" directory
    FrontMatter(Yaml()),  // Load any frontmatter and parse it as YAML markup
    OrderBy(@doc.Get<DateTime>("Published")),
    Take(1),
    Markdown(),  // Render the markdown content
        // ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment