Fornax 0.2.0
See the version list below for details.
dotnet tool install --global Fornax --version 0.2.0
dotnet new tool-manifest # if you are setting up this repo dotnet tool install --local Fornax --version 0.2.0
#tool dotnet:?package=Fornax&version=0.2.0
nuke :add-package Fornax --version 0.2.0
Fornax is a static site generator using type safe F# DSL to define page templates.
Working features
- Defining templates in F# DSL
- Creating pages using templates from
.md
files withlayout
entry - Creating plain pages without templates from
md
files withoutlayout
entry - Transforming
.less
files to.css
files - Transforming
.scss
files to.css
files (require havingsass
installed) - Coping other static content to output directory
Planned features
- Defining
.css
styles using F# DSL - Handling site settings defined in multiple files (a la Jekyll's
_data
folder) (multiple models? unified model?)
Installation.
Fornax is released as a global .Net Core tool. You can install it with dotnet tool install fornax -g
CLI Application
The main functionality of Fornax comes from CLI applications that lets user scaffold, and generate webpages.
fornax new
- scaffolds new blog in current working directory using really simple templatefornax build
- builds webpage, puts output to_public
folderfornax watch
- starts small webserver that host your blog post, and background process that recompiles blog whenever any changes are detected. That's suggested way of working with Fornaxfornax clean
- removes output directory and any temp files.fornax version
- prints out version of Fornaxfornax help
- prints out help
Website definition
Fornax is using normal F# code (F# script files) to define templates and data types representing content, and yaml and Markdown to provide content (fitting defined models) for the templates. Sample webpage can be found in samples
folder - to build sample webpage run fornax build
in this folder.
Site Settings
Site settings are information passed to every page during generation - every template has access to this data.
The model representing site settings is defined in siteModel.fsx
file in the root folder of the webpage, content of settings is defined in _config.yml
file in the root folder of the webpage.
Sample siteModel.fsx
:
type SiteModel = {
SomeGlobalValue : string
}
Sample _config.yml
:
SomeGlobalValue: "Test global value"
Templates
Templates are F# script files representing different templates that can be used in the website. They need to #load
siteModel.fsx
file, and #r
Fornax.Core.dll
. They need to define F# record called Model
which defines additional settings passed to this particular template, and generate
function of following signature: SiteModel -> Model -> Post list -> string -> HtmlElement
. SiteModel
is type representing global settings of webpage, Model
is type representing settings for this template, Post list
contains simplified information about all available posts in the blog (useful for navigation, creating tag cloud etc.) string
is main content of post (already compiled to html
).
Templates are defined using DSL defined in Html
module of Fornax.Core
.
All templates should be defined in templates
folder.
Sample template:
#r "../lib/Fornax.Core.dll"
#load "../siteModel.fsx"
open Html
open SiteModel
type Model = {
Name : string
Surname : string
}
let generate (siteModel : SiteModel) (mdl : Model) (posts: Post list) (content : string) =
html [] [
div [] [
span [] [ !! ("Hello world " + mdl.Name) ]
span [] [ !! content ]
span [] [ !! siteModel.SomeGlobalValue ]
]
]
Page content
Content files are .md
files containing page content, and header with settings (defined using yaml). Header part is parsed, and passed to template generate
function as Model
. Content part is compiled to html and also passed to generate
function. Header part needs to have layout
entry which defines which template will be used for the page.
Sample page:
---
layout: post
Name: Ja3
Surname: Ja4
---
# Something else
Some blog post written in Markdown
Post list
Templates are getting Post list
as one of the input parameter that can be used for navigation, creating tag clouds etc. The Post
is a record of following structure:
type Post = {
link : string
title: string
author: string option
published: System.DateTime option
tags: string list
content: string
}
It's filled based on respective entries in layout
part of the post content file. link
is using name of the file - it's usually something like \posts\post1.html
FAQ
- Hmmm... it looks similar to Jekyll, doesn't it?
- Yes, indeed. But the main advantage over Jekyll is type safe DSL for defining templates, and fact it's using normal programming language - no additional syntax to things like loops or conditional statements, it's also very easy to compose templates - you just
#load
other template and execute as normal F# function
- What about F# Formatting?
- F# Formatting is really good project, but it doesn't provide own rendering / templating engine - it's using Razor for that. Fornax right now is handling only rendering / templating - hopefully, it should work pretty well as rendering engine for F# Formatting.
How to contribute
Imposter syndrome disclaimer: I want your help. No really, I do.
There might be a little voice inside that tells you you're not ready; that you need to do one more tutorial, or learn another framework, or write a few more blog posts before you can help me with this project.
I assure you, that's not the case.
This project has some clear Contribution Guidelines and expectations that you can read here.
The contribution guidelines outline the process that you'll need to follow to get a patch merged. By making expectations and process explicit, I hope it will make it easier for you to contribute.
And you don't just have to write code. You can help out by writing documentation, tests, or even by giving feedback about this work. (And yes, that includes giving feedback about the contribution guidelines.)
Thank you for contributing!
Contributing and copyright
The project is hosted on GitHub where you can report issues, fork the project and submit pull requests. Please read Contribution Guide
The library is available under MIT license, which allows modification and redistribution for both commercial and non-commercial purposes.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.2 is compatible. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
This package has no dependencies.
Version | Downloads | Last updated |
---|---|---|
0.15.1 | 1,949 | 3/7/2023 |
0.15.1-beta002 | 354 | 3/7/2023 |
0.15.1-beta001 | 322 | 3/7/2023 |
0.14.3 | 5,854 | 5/7/2022 |
0.14.2 | 597 | 5/7/2022 |
0.14.1 | 604 | 5/5/2022 |
0.14.0 | 1,825 | 1/15/2022 |
0.13.1 | 45,112 | 4/24/2020 |
0.13.0 | 614 | 4/20/2020 |
0.12.0 | 584 | 4/14/2020 |
0.11.1 | 867 | 4/7/2020 |
0.11.0 | 1,002 | 3/2/2020 |
0.10.0 | 607 | 2/20/2020 |
0.2.0 | 852 | 8/5/2019 |
Update to .Net Core
Distribute as .Net Core global tool