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

Getting it working #1

Merged
merged 1 commit into from
Mar 27, 2019
Merged

Getting it working #1

merged 1 commit into from
Mar 27, 2019

Conversation

daveaglick
Copy link
Contributor

No description provided.

@@ -330,5 +330,5 @@ ASALocalRun/
.mfractor/

# Ignore the Wyam files
output/*
Wyam/output/*
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sure the output ignore rule applies to the Wyam subfolder you're using

@Html.Raw(Model.Get<Newsletter>("NewsletterContent").IssueNumber + ": " + Model.Get("NewsletterTo") + " - " + Model.Get("NewsletterFrom"))

@RenderBody()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Razor either needs a RenderBody() or IgnoreBody() call - the later would have worked here just fine since the document content is empty, but I usually prefer RenderBody() in case I add document content later and want to render it out

Pipelines.Add(
"Newsletter",
NewsTopicModule(newscollectionFilePath),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice work on writing a module! You were so close to getting everything wired up - I'll explain my changes to the next few lines inline. With regard to the module, putting it in a separate assembly is totally fine and works well, especially when the module needs other supporting classes. Just in case you weren't aware, you can also put the code for new modules directly in your config file (I usually add them at the bottom).

The important thing to note is that at the conclusion of this module you have a collection of IDocument objects, each with metadata keys like "NewsletterFrom" and empty content. In this example code, you're only outputting one IDocument right now, but it looks like the intent is for NewsTopicModule to output several documents.

Copy link
Member

Choose a reason for hiding this comment

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

I did h\ve it inline first time around, but moved it into a project do that I could hit Debugger.Launch() to see what was going on...

I love how you've build a C#-y DSL - I need to look at the source and figure out how you've done that. Last time I tried doing something similar, it was with Boo and it was quite painful.

Copy link
Contributor Author

@daveaglick daveaglick Mar 27, 2019

Choose a reason for hiding this comment

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

I love how you've build a C#-y DSL

Umm...about that 🤣 It's totally going away in the next major version (v3). Instead "custom config" will be done entirely via a normal .NET project and bootstrapped as a console app. That's mostly in reaction to lots of feedback regarding lack of Intellisense and debugging support as well as a desire to limit the amount of Roslyn/NuGet maintenance I have to do (though I do love Roslyn). Making everything build via the normal .NET project system also has some advantages over a runtime config file and dynamic assembly loading that will make life easier on me.

There will definitely be some porting required when it comes out, but it'll mostly be mechanical so you're safe using the current version until then. I'll be helping the community move to the new version when it's ready. For more information, see this issue: https://github.com/Wyamio/Wyam/issues/668

And here's an early look at what bootstrapping your custom Wyam generator might look like:
D1-gwL9UwAENKJ6

Copy link
Member

Choose a reason for hiding this comment

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

I think that's the right approach - it does make life a lot simpler for all the reasons you've outlined. I also like the fact that you can either use as a .NET Global Tool or to integrate into your own tool / platform. I've been thinking about how I integrate this directly into the content platform we've build for the Azure Weekly Newsletter - directly outputting into Azure Blob Storage or some such...

"Newsletter",
NewsTopicModule(newscollectionFilePath),
Razor().WithLayout("/_Index.cshtml"),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The trick here is to realize that each IDocument output by the NewsTopicModule is similar to a file, but because the documents being output don't have any content, they're like totally empty files. So running the Razor engine on it's own against files with empty content wouldn't actually render anything. That's where the WithLayout() method comes in - it tells the Razor engine "render these documents but use the following layout". You could have also used a _ViewStart.cshtml file for the same purpose, but since the documents being output from the NewsTopicModule don't have a IDocument.Source set, the Razor engine doesn't know where they're (virtually) located in the file system and so wouldn't know where to look for the _ViewStart.cshtml.

This is a common pattern - I use it all over the place in Discover .NET. The idea is that you create IDocument objects without content but with lots of metadata and then use a common layout file to render each of those documents, the layout making use of the metadata. The RenderBody() call in the layout ends up being a no-op. Note that if you added content to each of the output IDocument documents in NewsTopicModule, that content would be interpreted as Razor code and rendered inside the RenderBody() call, though I usually find it easier to put all the data for my "page" in metadata in the document and then let the layout deal with rendering it from the metadata.

NewsTopicModule(newscollectionFilePath),
Razor().WithLayout("/_Index.cshtml"),
WriteFiles((doc, ctx) => doc.Get<DateTime>("NewsletterFrom").ToString("yyyyMMdd") + ".html"));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since the documents being output by NewsTopicModule don't actually exist on disk and we didn't give them a source when we created them, we have to tell the WriteFiles module exactly where you write each one. You can do that by using the lambda constructor for the module which gives you total control. In this case, I'm outputting each document to a location equal to it's "NewsletterFrom" date (that looks like it's getting set as metadata in your NewsTopicModule module, but as far as I can tell, it's not currently present in the JSON so the value ends up being default). You can change this output path to whatever you need.

@daveaglick
Copy link
Contributor Author

This should get you up and running. I added a bunch of comments in code review to try and explain what's going on.

One more thing you might get confused by is how to deal with multiple articles per JSON file as processed and output as a single IDocument by NewsTopicModule. The trick is to add the list/array/collection of articles as a single metadata value in the module:

new KeyValuePair<string, object>("Articles", newscollection.Articles),

Then inside your _Index.cshtml file you can iterate over that:

@foreach(ProcessedArticle article in Model.List<ProcessedArticle>("Articles"))
{
    <h3>@article.Title</h3>
    etc...
}

Feel free to ask follow-up questions!

@HowardvanRooijen HowardvanRooijen merged commit 9ebb505 into endjin:master Mar 27, 2019
@HowardvanRooijen
Copy link
Member

If I wanted to scaffold a full, blog-like site, would I use WithLayout('/_Layout.cshtml') and that would deal with rendering the layout, and then the body?

If I wanted to port over http://azureweekly.info/ and write out then content under the fold, and produce a blog front page style ToC where "archive" currently is - how would you recommend I structure the theme?

@HowardvanRooijen
Copy link
Member

I've just tried to apply the above learnings to the template for the site I'm building. (I've pushed the files into this repo).

  • How do you copy the asset files into the output path?
  • Does Wyam support the <environment> tags? They still seem to be present in the rendered output. Or is it just best to remove these and stick with "non-production" configurations?
  • Do I need to create 2 pipelines? One for the front page / TOC another for each "issue"?

Thanks!

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

Successfully merging this pull request may close these issues.

2 participants