Falco.Markup
1.0.2
dotnet add package Falco.Markup --version 1.0.2
NuGet\Install-Package Falco.Markup -Version 1.0.2
<PackageReference Include="Falco.Markup" Version="1.0.2" />
paket add Falco.Markup --version 1.0.2
#r "nuget: Falco.Markup, 1.0.2"
// Install Falco.Markup as a Cake Addin
#addin nuget:?package=Falco.Markup&version=1.0.2
// Install Falco.Markup as a Cake Tool
#tool nuget:?package=Falco.Markup&version=1.0.2
Falco.Markup
open Falco.Markup
let doc =
Elem.html [] [
Elem.body [ Attr.class' "100-vh" ] [
Elem.h1 [] [ Text.raw "Hello world!" ] ] ]
renderHtml doc
Falco.Markup is an XML markup module that can be used to produce any form of angle-bracket markup (i.e. HTML, SVG, XML etc.).
Key Features
- Use native F# to produce any form of angle-bracket markup.
- Very simple to create reusable blocks of code (i.e., partial views and components).
- Easily extended by creating custom tags and attributes.
- Compiled as part of your assembly, leading to improved performance and simpler deployments.
Design Goals
- Provide a tool to generate any form of angle-bracket markup.
- Should be simple, extensible and integrate with existing .NET libraries.
- Can be easily learned.
Overview
Falco.Markup is broken down into three primary modules. Elem
, Attr
and Text
, which are used to generate elements, attributes and text nodes respectively. Each module contain a suite of functions mapping to the various element/attribute/node names. But can also be extended to create custom elements and attributes.
Primary elements are broken down into two types, ParentNode
or SelfClosingNode
.
ParentNode
elements are those that can contain other elements. Represented as functions that receive two inputs: attributes and optionally elements.
let markup =
Elem.div [ Attr.class' "heading" ] [
Elem.h1 [] [ Text.raw "Hello world!" ] ]
SelfClosingNode
elements are self-closing tags. Represented as functions that receive one input: attributes.
let markup =
Elem.div [ Attr.class' "divider" ] [
Elem.hr [] ]
Text is represented using the TextNode
and created using one of the functions in the Text
module.
let markup =
Elem.div [] [
Text.comment "An HTML comment"
Elem.p [] [ Text.raw "A paragraph" ]
Elem.p [] [ Text.rawf "Hello %s" "Jim" ]
Elem.code [] [ Text.enc "<div>Hello</div>" ] // HTML encodes text before rendering
]
Attributes contain two subtypes as well, KeyValueAttr
which represent key/value attributes or NonValueAttr
which represent boolean attributes.
let markup =
Elem.input [ Attr.type' "text"; Attr.required ]
Most JavaScript Events have also been mapped in the Attr
module. All of these events are prefixed with the word "on" (i.e., Attr.onclick
, Attr.onfocus
etc.)
let markup =
Elem.button [ Attr.onclick "console.log(\"hello world\")" ] [ Text.raw "Click me" ]
HTML
Though Falco.Markup can be used to produce any markup. It is first and foremost an HTML library.
Combining views to create complex output
open Falco.Markup
// Components
let divider =
Elem.hr [ Attr.class' "divider" ]
// Template
let master (title : string) (content : XmlNode list) =
Elem.html [ Attr.lang "en" ] [
Elem.head [] [
Elem.title [] [ Text.raw title ]
]
Elem.body [] content
]
// Views
let homeView =
master "Homepage" [
Elem.h1 [] [ Text.raw "Homepage" ]
divider
Elem.p [] [ Text.raw "Lorem ipsum dolor sit amet, consectetur adipiscing."]
]
let aboutView =
master "About Us" [
Elem.h1 [] [ Text.raw "About" ]
divider
Elem.p [] [ Text.raw "Lorem ipsum dolor sit amet, consectetur adipiscing."]
]
Strongly-typed views
open Falco.Markup
type Person =
{ FirstName : string
LastName : string }
let doc (person : Person) =
Elem.html [ Attr.lang "en" ] [
Elem.head [] [
Elem.title [] [ Text.raw "Sample App" ]
]
Elem.body [] [
Elem.main [] [
Elem.h1 [] [ Text.raw "Sample App" ]
Elem.p [] [ Text.rawf "%s %s" person.First person.Last ]
]
]
]
Merging Attributes
The markup module allows you to easily create components, an excellent way to reduce code repetition in your UI. To support runtime customization, it is advisable to ensure components (or reusable markup blocks) retain a similar function "shape" to standard elements. That being, XmlAttribute list -> XmlNode list -> XmlNode
.
This means that you will inevitably end up needing to combine your predefined XmlAttribute list
with a list provided at runtime. To facilitate this, the Attr.merge
function will group attributes by key, and concatenate the values in the case of KeyValueAttribute
.
open Falco.Markup
// Components
let heading (attrs : XmlAttribute list) (content : XmlNode list) =
// safely combine the default XmlAttribute list with those provided
// at runtime
let attrs' =
Attr.merge [ Attr.class' "text-large" ] attrs
Elem.div [] [
Elem.h1 [ attrs' ] content
]
// Template
let master (title : string) (content : XmlNode list) =
Elem.html [ Attr.lang "en" ] [
Elem.head [] [
Elem.title [] [ Text.raw title ]
]
Elem.body [] content
]
// Views
let homepage =
master "Homepage" [
heading [ Attr.class' "red" ] [ Text.raw "Welcome to the homepage" ]
Elem.p [] [ Text.raw "Lorem ipsum dolor sit amet, consectetur adipiscing."]
]
let homepage =
master "About Us" [
heading [ Attr.class' "purple" ] [ Text.raw "This is what we're all about" ]
Elem.p [] [ Text.raw "Lorem ipsum dolor sit amet, consectetur adipiscing."]
]
Custom Elements & Attributes
Every effort has been taken to ensure the HTML and SVG specs are mapped to functions in the module. In the event an element or attribute you need is missing, you can either file an issue, or more simply extend the module in your project.
An example creating custom XML elements and using them to create a structured XML document:
open Falco.Makrup
module Elem =
let books = Elem.create "books"
let book = Elem.create "book"
let name = Elem.create "name"
module Attr =
let soldOut = Attr.createBool "soldOut"
let xmlDoc =
Elem.books [] [
Elem.book [ Attr.soldOut ] [
Elem.name [] [ Text.raw "To Kill A Mockingbird" ]
]
]
let xml = renderXml xmlDoc
SVG
Much of the SVG spec has been mapped to element and attributes functions. There is also an SVG template to help initialize a new drawing with a valid viewbox.
open Falco.Markup
open Falco.Markup.Svg
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text#example
let svgDrawing =
Templates.svg (0, 0, 240, 80) [
Elem.style [] [
Text.raw ".small { font: italic 13px sans-serif; }"
Text.raw ".heavy { font: bold 30px sans-serif; }"
Text.raw ".Rrrrr { font: italic 40px serif; fill: red; }"
]
Elem.text [ Attr.x "20"; Attr.y "35"; Attr.class' "small" ] [ Text.raw "My" ]
Elem.text [ Attr.x "40"; Attr.y "35"; Attr.class' "heavy" ] [ Text.raw "cat" ]
Elem.text [ Attr.x "55"; Attr.y "55"; Attr.class' "small" ] [ Text.raw "is" ]
Elem.text [ Attr.x "65"; Attr.y "55"; Attr.class' "Rrrrr" ] [ Text.raw "Grumpy!" ]
]
let svg = renderNode svgDrawing
Find a bug?
There's an issue for that.
License
Built with ♥ by Pim Brouwers in Toronto, ON. Licensed under Apache License 2.0.
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-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.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- FSharp.Core (>= 4.5.2)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Falco.Markup:
Package | Downloads |
---|---|
Falco
A functional-first toolkit for building brilliant ASP.NET Core applications using F#. |
|
Fss-lib.Falco
Provides helper functions for using Fss with Falco View Engine. |
|
Falco.Bulma
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.0.2 | 4,524 | 2/3/2023 |
1.0.1 | 2,057 | 9/14/2022 |
1.0.0 | 377 | 9/13/2022 |
1.0.0-alpha1 | 152 | 8/17/2022 |