statiqdev / Statiq.Web

Statiq Web is a flexible static site generator written in .NET.
https://statiq.dev/web
Other
1.65k stars 235 forks source link

Creating a new Recipe #440

Open JonDouglas opened 7 years ago

JonDouglas commented 7 years ago

I'm running into a few issues regarding creating a new Recipe with Wyam.

I've taken the existing Wyam.Docs project and created my own by copying the same structure and calling it Wyam.EBook. There is nothing different to the project other than a new GUID and names of classes to reflect EBook naming.

I have then added a KnownRecipe of the following:

public static readonly KnownRecipe EBook = new KnownRecipe("Wyam.EBook", nameof(KnownTheme.Bookie));

Finally I've created a KnownTheme of Bookie:

public static readonly KnownTheme Bookie = new KnownTheme(nameof(KnownRecipe.EBook), null, new[] { "Wyam.EBook.Bookie" });

However whenever I run my custom Wyam.exe, it seems it cannot be found. I've double checked quite a bit of code already but I have a feeling it's something simple that I missed. I even went as far as to look at a few Unit Tests in the ConfigurationFixture.cs in which the SetsDefaultTheme() fails within the AddRecipePackageAndSetTheme() method.

System.NullReferenceException : Object reference not set to an instance of an object.
   at Wyam.Configuration.Configurator.AddRecipePackageAndSetTheme() in C:\Users\dougl\Documents\GitHub\Wyam\src\core\Wyam.Configuration\Configurator.cs:line 149
   at Wyam.Configuration.Tests.ConfiguratorFixture.AddRecipePackageAndSetThemeTests.SetsDefaultTheme() in C:\Users\dougl\Documents\GitHub\Wyam\tests\core\Wyam.Configuration.Tests\ConfiguratorFixture.cs:line 374

This of course fails on the following line of Configurator.cs:

                        if (!string.IsNullOrEmpty(knownRecipe.PackageId) && !PackageInstaller.ContainsPackage(knownRecipe.PackageId))
                        {
                            PackageInstaller.AddPackage(knownRecipe.PackageId);
                        }

Thus I'm not quite sure why my recipe is not being picked up here. It seems like I'm missing something!

Wyam.exe output when trying to use this recipe:

Error while loading configuration: System.Exception: The recipe "EBook" could not be found
   at Wyam.Configuration.Configurator.ApplyRecipe() in E:\Code\Wyam\src\core\Wyam.Configuration\Configurator.cs:line 293
   at Wyam.Configuration.Configurator.Configure(String script) in E:\Code\Wyam\src\core\Wyam.Configuration\Configurator.
cs:line 128
   at Wyam.EngineManager.Configure() in E:\Code\Wyam\src\clients\Wyam\EngineManager.cs:line 118
daveaglick commented 7 years ago

Let's see if I can help here...

First off, the KnownRecipe and KnownTheme are unnecessary. They essentially map plain recipe and theme names to the actual NuGet packages that contain them. These two objects get "baked in" the Wyam distribution. I suspect that the reason you can't find the recipe (and/or theme) is that some custom code generation magic takes the KnownRecipe and KnownTheme instances and makes them available. But none of this is really all that important for a custom recipe and theme. The "known" stuff is only so that recipes and themes distributed with Wyam get picked up. If you get to the point that you want to submit a PR with the new recipe, yay! And also, I'd help verify the lookups are working at that point.

All you really need to understand about recipes and themes is that they're just assemblies and folders respectively.

Let's start with the recipe. Without the lookup, you just have to make sure that the assembly that contains your recipe is referenced by Wyam. That can be done on the command line using the -a argument or in your configuration file with the #a preprocessor directive. Just use one of those two methods and point it to your recipe assembly. As long as the recipe name is the same as the class that implements IRecipe it should pick it up.

A theme is even simpler. By convention, theme files are placed as "Content" in a NuGet package. When Wyam loads a NuGet package with a content folder, it just adds the content folder to the set of input folders. That's it. To use a custom theme, all you have to do is add the folder that contains your theme files to the set of input paths. There's even a pre-defined theme folder for just this purpose. If you place your theme in a folder called "theme" alongside your "input" folder, everything inside of it will be treated as a custom theme. If you want to place the theme files somewhere external, just use the -t command line argument or the #theme preprocessor directive and give it a folder path instead of a common name.

Hopefully this gets you on the right track. Just let me know if you continue to have problems.

JonDouglas commented 7 years ago

Thanks for the response Dave.

So assuming I wanted to create a Recipe and a default theme for that recipe, does this approach seem overkill?

In the sense that I'm editing directly in the Wyam source code and trying to make this a "KnownRecipe" in the distro that has a default theme. AFAIK the cake script generates these nugets for me just fine(However note they aren't published).

Or would it be more ideal to just create my own NuGet packages that have dependencies on the respective Wyam NuGet packages? (Common/Core/Whatever extension I need)

This is somewhat the approach I'm trying to take by baking it directly in my fork of Wyam, but I still cannot get the Recipe to pickup after installing the Setup.exe from a fresh Windows build. I've looked through the code, but I haven't really figured out if the default Recipes and Themes are loaded through NuGet or from source. Perhaps the issue is that the directive ignores packages for known recipes and that package hasn't been loaded in the first place?

Silvenga commented 7 years ago

@JonDouglas I've created a custom theme/recipe for my blog if you want to look at a working example - https://github.com/Silvenga/silvenga.com. Since I don't care about distributing my packages I have the CI server build my recipe that's referenced directly by Wyam.

daveaglick commented 7 years ago

@JonDouglas Did you ever get this sorted out? If not, where are you at in terms of getting it to work? Let's see if we can't get you up and running...

JonDouglas commented 7 years ago

@Silvenga Thanks for this! My original plan was just to create a IRecipe that would be default in a future build of Wyam via PR. I ran out of time trying to figure how to get that to populate though!

@daveaglick I ended up giving up on my pursuit for what I wanted to do which was create a recipe inside the Wyam project itself. I think my shortcoming was the fact that I needed to create a NuGet for my recipe. However I just haven't had time to look back into this.