diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index ec22815..fe4dd39 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -1,4 +1,4 @@
-name: Pull Request
+name: Pull Request
on:
pull_request:
paths-ignore:
@@ -8,14 +8,44 @@ jobs:
name: Test
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup dotnet
- uses: actions/setup-dotnet@v4
+ uses: actions/setup-dotnet@v5
with:
- dotnet-version: 8.x
+ dotnet-version: 10.0.x
- name: Install Tools
run: dotnet tool restore
+ working-directory: ./fsharp-view-engine
- name: Install Packages
run: dotnet paket install
+ working-directory: ./fsharp-view-engine
- name: Test
run: ./fake.sh Test
+ working-directory: ./fsharp-view-engine
+ preview:
+ name: Preview
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ needs:
+ - test
+ steps:
+ - uses: actions/checkout@v5
+ - name: Setup Node
+ uses: actions/setup-node@v5
+ with:
+ node-version: 24
+ - name: Install Packages
+ run: npm install
+ working-directory: ./pulumi
+ - name: Preview
+ uses: pulumi/actions@v6
+ with:
+ work-dir: ./pulumi
+ command: preview
+ stack-name: prod
+ diff: true
+ comment-on-pr: true
+ env:
+ PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7db891c..8a5a16e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,4 +1,4 @@
-name: Release
+name: Release
on:
release:
branches:
@@ -10,16 +10,41 @@ jobs:
name: Publish
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup dotnet
- uses: actions/setup-dotnet@v4
+ uses: actions/setup-dotnet@v5
with:
- dotnet-version: 8.x
+ dotnet-version: 10.0.x
- name: Restore Tools
run: dotnet tool restore
+ working-directory: ./fsharp-view-engine
- name: Install Packages
run: dotnet paket install
+ working-directory: ./fsharp-view-engine
- name: Publish
run: ./fake.sh Publish
+ working-directory: ./fsharp-view-engine
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ deploy:
+ name: Deploy
+ runs-on: ubuntu-latest
+ needs:
+ - publish
+ steps:
+ - uses: actions/checkout@v5
+ - name: Setup Node
+ uses: actions/setup-node@v5
+ with:
+ node-version: 24
+ - name: Install Packages
+ run: npm install
+ working-directory: ./pulumi
+ - name: Update
+ uses: pulumi/actions@v6
+ with:
+ work-dir: ./pulumi
+ command: up
+ stack-name: prod
+ env:
+ PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 7017895..5eec986 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1 @@
-.idea
-.vscode
-.paket
-obj
-bin
-nugets
-paket-files
-*DotSettings.user
+.claude
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..3dd6247
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,94 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+FSharp.ViewEngine is a view engine for F# web applications. It provides a functional approach to generating HTML with type-safe F# code, including integrated support for HTMX, Alpine.js, Tailwind CSS, and SVG elements.
+
+## Repository Structure
+- `fsharp-view-engine/` — F# library, app, tests, and build system
+- `pulumi/` — Pulumi infrastructure (TypeScript) for deploying the demo app
+- `.github/` — CI workflows (at repo root, with `working-directory: fsharp-view-engine`)
+- `.claude/` — Claude Code settings
+
+## Common Development Commands
+
+**Important:** When running in a bash shell (including Claude Code), always use `./fake.sh` instead of `fake.cmd`.
+
+```bash
+# All dotnet/fake commands run from fsharp-view-engine/
+cd fsharp-view-engine
+
+# Restore tools and packages
+dotnet tool restore
+dotnet paket install
+
+# Run tests (uses Expecto, so dotnet run, not dotnet test)
+./fake.sh Test
+dotnet run --project src/Tests/Tests.fsproj # Direct
+
+# Run a single test by name
+dotnet run --project src/Tests/Tests.fsproj -- --filter "Should render html document"
+
+# Run demo app with Tailwind watch
+./fake.sh Watch
+
+# Create NuGet package (needs GITHUB_REF_NAME env var)
+./fake.sh Pack
+
+# Pulumi deployment
+cd pulumi
+npm install
+pulumi up -s prod
+```
+
+## Architecture
+
+### Core Type System (`fsharp-view-engine/src/FSharp.ViewEngine/Core.fs`)
+Two discriminated unions form the foundation:
+- **Element**: `Text | Tag | Void | Fragment | Raw | Noop` — represents DOM nodes
+- **Attribute**: `KeyValue | Boolean | Children | Noop` — represents HTML attributes
+
+Rendering uses `StringBuilder` with recursive pattern matching. `Text` is HTML-encoded; `Raw` is not. `Void` elements (e.g., `br`, `img`) are self-closing and reject children.
+
+### Module Organization
+- `Html.fs` — Standard HTML elements and attributes as static members on `Html` type
+- `Htmx.fs` — HTMX attributes (`_hxGet`, `_hxPost`, etc.) on `Htmx` type
+- `Alpine.fs` — Alpine.js directives (`_xData`, `_xShow`, etc.) on `Alpine` type
+- `Tailwind.fs` — Tailwind UI custom elements on `Tailwind` type
+- `Svg.fs` — SVG elements and attributes on `Svg` type
+
+### Usage Pattern
+```fsharp
+open FSharp.ViewEngine
+open type Html
+open type Htmx
+
+div [ _class "container"; _hxGet "/api"; _children [ h1 "Hello" ] ]
+|> Element.render
+```
+
+### Project Structure
+- `fsharp-view-engine/src/FSharp.ViewEngine/` — Core library (NuGet package)
+- `fsharp-view-engine/src/Tests/` — xUnit tests
+- `fsharp-view-engine/src/Build/` — FAKE build system (`Program.fs` defines targets)
+- `fsharp-view-engine/src/App/` — Demo Giraffe web app with Markdown docs
+- `pulumi/` — Infrastructure as code (Pulumi + TypeScript)
+
+## Development Patterns
+
+- **New HTML elements** in `Html.fs`: use `Tag` for normal elements, `Void` for self-closing. Add convenience overloads (e.g., `p (text:string)`).
+- **Framework attributes**: HTMX → `Htmx.fs` with `_hx` prefix; Alpine → `Alpine.fs` with `_x` prefix.
+- **Tests** compare rendered HTML strings using `String.clean` for whitespace normalization. Use `// language=HTML` comment for IDE syntax highlighting in expected strings.
+
+## Build System
+- FAKE build scripts invoked via `fake.cmd`/`fake.sh`
+- Paket for package management (`paket.dependencies` at root of `fsharp-view-engine/`)
+- .NET 10.0 SDK (`global.json`)
+- CI: GitHub Actions — tests on PRs, NuGet publish on release tags (`v*.*.*`)
+
+## Infrastructure (Pulumi)
+- TypeScript Pulumi project in `pulumi/`
+- Deploys demo app to Kubernetes via AWS ECR + Cloudflare Tunnel
+- Domain: `fsharpviewengine.meiermade.com`
+- Stack references: `identity`, `infrastructure`, `fsharp-view-engine-identity`
diff --git a/WARP.md b/WARP.md
deleted file mode 100644
index 8d8a49a..0000000
--- a/WARP.md
+++ /dev/null
@@ -1,115 +0,0 @@
-# WARP.md
-
-This file provides guidance to WARP (warp.dev) when working with code in this repository.
-
-## Project Overview
-FSharp.ViewEngine is a view engine for F# web applications, inspired by Giraffe.ViewEngine and Feliz.ViewEngine. It provides a functional approach to generating HTML with type-safe F# code, including integrated support for HTMX, Alpine.js, Tailwind CSS, and SVG elements.
-
-## Core Architecture
-
-### Element System
-The view engine is built around a discriminated union system:
-- **Element**: The core type representing DOM elements (Text, Tag, Void, Fragment, Raw, Noop)
-- **Attribute**: Represents HTML attributes (KeyValue, Boolean, Children, Noop)
-- All HTML is generated through composition of these types
-
-### Module Structure
-- `Core.fs`: Defines the core Element and Attribute types, plus the rendering engine
-- `Html.fs`: Standard HTML elements and attributes (div, p, h1, _class, _id, etc.)
-- `Htmx.fs`: HTMX-specific attributes (_hxGet, _hxPost, _hxTarget, etc.)
-- `Alpine.fs`: Alpine.js directives (_xData, _xShow, _xModel, etc.)
-- `Tailwind.fs`: Tailwind UI custom elements (el-select, el-dialog, etc.)
-- `Svg.fs`: SVG elements and attributes
-
-## Common Development Commands
-
-### Build and Test
-```bash
-# Restore tools and packages
-dotnet tool restore
-dotnet paket install
-
-# Run tests (cross-platform)
-./fake.sh Test # Linux/macOS
-./fake.cmd Test # Windows
-
-# Alternative direct test command
-dotnet test src/Tests/Tests.fsproj
-```
-
-### Package Management
-```bash
-# Add NuGet package dependencies
-# Edit paket.dependencies file, then:
-dotnet paket install
-
-# Update packages
-dotnet paket update
-```
-
-### Building and Packaging
-```bash
-# Clean build artifacts
-./fake.sh Clean # Linux/macOS
-./fake.cmd Clean # Windows
-
-# Create NuGet package (requires GITHUB_REF_NAME environment variable)
-./fake.sh Pack # Linux/macOS
-./fake.cmd Pack # Windows
-```
-
-### Single Test Execution
-To run a specific test, use xunit's filtering:
-```bash
-# Run specific test by name pattern
-dotnet test src/Tests/Tests.fsproj --filter "Should render html document"
-```
-
-## Development Patterns
-
-### Creating New HTML Elements
-When adding HTML elements to `Html.fs`, follow the established patterns:
-- Standard elements: `static member elementName (attrs:Attribute seq) = Tag ("elementname", attrs)`
-- Void elements (self-closing): Use `Void` instead of `Tag`
-- Convenience overloads for common cases (e.g., `p (text:string)` for simple text paragraphs)
-
-### Adding Framework-Specific Attributes
-- HTMX attributes go in `Htmx.fs` with `_hx` prefix
-- Alpine.js directives go in `Alpine.fs` with `_x` prefix
-- Use the `_frameworkPrefix` function pattern for consistency
-
-### Testing HTML Output
-Tests use string comparison with whitespace normalization. The `String.clean` helper removes excess whitespace for reliable comparisons. Use the `// language=HTML` comment for syntax highlighting in expected output strings.
-
-## Key Dependencies
-- **Paket**: Package management
-- **FAKE**: Build automation via F# DSL
-- **xUnit**: Testing framework
-- **System.Web**: HTML encoding utilities
-
-## Usage Pattern
-The library uses F# static type extensions with `open type` declarations:
-```fsharp
-open FSharp.ViewEngine
-open type Html
-open type Htmx
-open type Alpine
-
-// Creates type-safe, composable HTML
-div [
- _class "container"
- _hxGet "/api/data"
- _xData "{loading: false}"
- _children [
- h1 [ _children "Hello World" ]
- ]
-]
-|> Element.render
-```
-
-## Build System Notes
-- Uses FAKE build system with F# build scripts in `src/Build/Program.fs`
-- Cross-platform build scripts: `fake.sh` (Unix) and `fake.cmd` (Windows)
-- Targets: Test, Clean, Pack, Publish
-- Version extraction from Git tags for packaging
-- CI/CD via GitHub Actions for PR validation and releases
\ No newline at end of file
diff --git a/etc/logo.svg b/etc/logo.svg
deleted file mode 100644
index 27cb1cf..0000000
--- a/etc/logo.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
\ No newline at end of file
diff --git a/.config/dotnet-tools.json b/fsharp-view-engine/.config/dotnet-tools.json
similarity index 63%
rename from .config/dotnet-tools.json
rename to fsharp-view-engine/.config/dotnet-tools.json
index b9052bc..4321530 100644
--- a/.config/dotnet-tools.json
+++ b/fsharp-view-engine/.config/dotnet-tools.json
@@ -3,10 +3,11 @@
"isRoot": true,
"tools": {
"paket": {
- "version": "8.0.3",
+ "version": "10.3.1",
"commands": [
"paket"
- ]
+ ],
+ "rollForward": false
}
}
}
\ No newline at end of file
diff --git a/fsharp-view-engine/.dockerignore b/fsharp-view-engine/.dockerignore
new file mode 100644
index 0000000..a2233c6
--- /dev/null
+++ b/fsharp-view-engine/.dockerignore
@@ -0,0 +1,8 @@
+**/.git
+**/.idea
+**/.vs
+**/bin
+**/obj
+**/nugets
+**/nul
+**/.claude
diff --git a/fsharp-view-engine/.gitignore b/fsharp-view-engine/.gitignore
new file mode 100644
index 0000000..7017895
--- /dev/null
+++ b/fsharp-view-engine/.gitignore
@@ -0,0 +1,8 @@
+.idea
+.vscode
+.paket
+obj
+bin
+nugets
+paket-files
+*DotSettings.user
diff --git a/fsharp-view-engine/AGENTS.md b/fsharp-view-engine/AGENTS.md
new file mode 100644
index 0000000..dd9837d
--- /dev/null
+++ b/fsharp-view-engine/AGENTS.md
@@ -0,0 +1 @@
+See [CLAUDE.md](CLAUDE.md) for project guidance.
diff --git a/fsharp-view-engine/Dockerfile b/fsharp-view-engine/Dockerfile
new file mode 100644
index 0000000..1f72440
--- /dev/null
+++ b/fsharp-view-engine/Dockerfile
@@ -0,0 +1,31 @@
+FROM mcr.microsoft.com/dotnet/sdk:10.0-noble-amd64 AS build
+
+WORKDIR /app
+
+# Install tailwindcss
+RUN curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/download/v4.1.18/tailwindcss-linux-x64 \
+ && chmod +x tailwindcss-linux-x64 \
+ && mv tailwindcss-linux-x64 /usr/local/bin/tailwindcss
+
+RUN tailwindcss --version
+
+# Restore paket dependencies
+COPY .config/ .config/
+RUN dotnet tool restore
+
+# Install F# dependencies
+COPY paket.dependencies paket.lock ./
+RUN dotnet paket install && dotnet paket restore
+
+COPY src src
+COPY fake.sh ./
+RUN chmod +x fake.sh
+RUN ./fake.sh PublishApp
+
+FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled
+
+WORKDIR /app
+
+COPY --from=build /app/src/App/out .
+
+ENTRYPOINT ["dotnet", "App.dll"]
diff --git a/FSharp.ViewEngine.sln b/fsharp-view-engine/FSharp.ViewEngine.sln
similarity index 81%
rename from FSharp.ViewEngine.sln
rename to fsharp-view-engine/FSharp.ViewEngine.sln
index bc6045c..01a0d46 100644
--- a/FSharp.ViewEngine.sln
+++ b/fsharp-view-engine/FSharp.ViewEngine.sln
@@ -11,6 +11,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Build", "src\Build\Build.fs
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tests", "src\Tests\Tests.fsproj", "{65C2946A-1B1E-45AB-8196-DFE772FA9240}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "App", "src\App\App.fsproj", "{ADA5276C-21C3-4633-B83F-F50A93D5FF36}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -32,10 +34,15 @@ Global
{65C2946A-1B1E-45AB-8196-DFE772FA9240}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65C2946A-1B1E-45AB-8196-DFE772FA9240}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65C2946A-1B1E-45AB-8196-DFE772FA9240}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ADA5276C-21C3-4633-B83F-F50A93D5FF36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ADA5276C-21C3-4633-B83F-F50A93D5FF36}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ADA5276C-21C3-4633-B83F-F50A93D5FF36}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ADA5276C-21C3-4633-B83F-F50A93D5FF36}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4093E9E9-D923-4945-A458-C1F861C3FD1D} = {EA093A44-5365-45ED-B8FB-C506C95405A6}
{2562C7E1-2366-4DB0-9A86-278B8AA5117B} = {EA093A44-5365-45ED-B8FB-C506C95405A6}
{65C2946A-1B1E-45AB-8196-DFE772FA9240} = {EA093A44-5365-45ED-B8FB-C506C95405A6}
+ {ADA5276C-21C3-4633-B83F-F50A93D5FF36} = {EA093A44-5365-45ED-B8FB-C506C95405A6}
EndGlobalSection
EndGlobal
diff --git a/LICENSE b/fsharp-view-engine/LICENSE
similarity index 100%
rename from LICENSE
rename to fsharp-view-engine/LICENSE
diff --git a/README.md b/fsharp-view-engine/README.md
similarity index 86%
rename from README.md
rename to fsharp-view-engine/README.md
index ba451c3..2214ce8 100644
--- a/README.md
+++ b/fsharp-view-engine/README.md
@@ -1,10 +1,10 @@
-[](https://github.com/ameier38/FSharp.ViewEngine/actions/workflows/release.yml)
-
-
+[](https://github.com/meiermade/FSharp.ViewEngine/actions/workflows/release.yml)
# FSharp.ViewEngine
View engine for F#. Inspired by [Giraffe.ViewEngine](https://github.com/giraffe-fsharp/Giraffe.ViewEngine) and
[Feliz.ViewEngine](https://github.com/dbrattli/Feliz.ViewEngine).
+Documentation site built using FSharp.ViewEngine available at [https://fsharpviewengine.meiermade.com](https://fsharpviewengine.meiermade.com).
+> See [App](./src/App) for the source code.
## Installation
Add the core view engine package.
diff --git a/fake.cmd b/fsharp-view-engine/fake.cmd
similarity index 100%
rename from fake.cmd
rename to fsharp-view-engine/fake.cmd
diff --git a/fake.sh b/fsharp-view-engine/fake.sh
similarity index 100%
rename from fake.sh
rename to fsharp-view-engine/fake.sh
diff --git a/global.json b/fsharp-view-engine/global.json
similarity index 66%
rename from global.json
rename to fsharp-view-engine/global.json
index 501e79a..f72210c 100644
--- a/global.json
+++ b/fsharp-view-engine/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "8.0.100",
+ "version": "10.0.100",
"rollForward": "latestFeature"
}
}
\ No newline at end of file
diff --git a/fsharp-view-engine/paket.dependencies b/fsharp-view-engine/paket.dependencies
new file mode 100644
index 0000000..17c8c0d
--- /dev/null
+++ b/fsharp-view-engine/paket.dependencies
@@ -0,0 +1,8 @@
+source https://api.nuget.org/v3/index.json
+storage: none
+
+nuget Fake.Core.Target
+nuget Giraffe
+nuget JetBrains.Annotations
+nuget Markdig
+nuget Expecto
diff --git a/fsharp-view-engine/paket.lock b/fsharp-view-engine/paket.lock
new file mode 100644
index 0000000..6047145
--- /dev/null
+++ b/fsharp-view-engine/paket.lock
@@ -0,0 +1,104 @@
+STORAGE: NONE
+NUGET
+ remote: https://api.nuget.org/v3/index.json
+ Expecto (10.2.3)
+ FSharp.Core (>= 7.0.200) - restriction: >= net6.0
+ Mono.Cecil (>= 0.11.4 < 1.0) - restriction: >= net6.0
+ Fake.Core.CommandLineParsing (6.1.4) - restriction: >= netstandard2.0
+ FParsec (>= 1.1.1) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.Context (6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.Environment (6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.FakeVar (6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Context (>= 6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.Process (6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Environment (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.FakeVar (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.String (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Trace (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.IO.FileSystem (>= 6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ System.Collections.Immutable (>= 8.0) - restriction: >= netstandard2.0
+ Fake.Core.String (6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.Target (6.1.4)
+ Fake.Core.CommandLineParsing (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Context (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Environment (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.FakeVar (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Process (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.String (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Trace (>= 6.1.4) - restriction: >= netstandard2.0
+ FSharp.Control.Reactive (>= 5.0.2) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.Core.Trace (6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Environment (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.FakeVar (>= 6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ Fake.IO.FileSystem (6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.String (>= 6.1.4) - restriction: >= netstandard2.0
+ Fake.Core.Trace (>= 6.1.4) - restriction: >= netstandard2.0
+ FSharp.Core (>= 8.0.400) - restriction: >= netstandard2.0
+ FParsec (1.1.1) - restriction: >= netstandard2.0
+ FSharp.Core (>= 4.3.4) - restriction: || (>= net45) (>= netstandard2.0)
+ System.ValueTuple (>= 4.4) - restriction: >= net45
+ FSharp.Control.Reactive (6.1.2) - restriction: >= netstandard2.0
+ FSharp.Core (>= 6.0.7) - restriction: >= netstandard2.0
+ System.Reactive (>= 6.0.1) - restriction: >= netstandard2.0
+ FSharp.Core (10.0.102) - restriction: >= netstandard2.0
+ FSharp.SystemTextJson (1.4.36) - restriction: >= net6.0
+ FSharp.Core (>= 4.7) - restriction: >= netstandard2.0
+ System.Text.Json (>= 6.0.10) - restriction: >= netstandard2.0
+ Giraffe (8.2)
+ FSharp.Core (>= 6.0) - restriction: >= net6.0
+ FSharp.SystemTextJson (>= 1.3.13) - restriction: >= net6.0
+ Giraffe.ViewEngine (>= 1.4) - restriction: >= net6.0
+ Microsoft.IO.RecyclableMemoryStream (>= 3.0.1) - restriction: >= net6.0
+ System.Text.Json (>= 8.0.6) - restriction: >= net6.0
+ Giraffe.ViewEngine (1.4) - restriction: >= net6.0
+ FSharp.Core (>= 5.0) - restriction: >= netstandard2.0
+ JetBrains.Annotations (2025.2.4)
+ System.Runtime (>= 4.1) - restriction: && (< net20) (>= netstandard1.0) (< netstandard2.0)
+ Markdig (0.44)
+ System.Memory (>= 4.6.3) - restriction: || (>= net462) (&& (>= netstandard2.0) (< netstandard2.1))
+ Microsoft.Bcl.AsyncInterfaces (10.0.2) - restriction: || (&& (>= net462) (>= net6.0)) (&& (>= net6.0) (< net8.0))
+ Microsoft.IO.RecyclableMemoryStream (3.0.1) - restriction: >= net6.0
+ Microsoft.NETCore.Platforms (7.0.4) - restriction: || (&& (< monoandroid) (< net20) (>= netstandard1.0) (< netstandard1.2) (< win8) (< wp8)) (&& (< monoandroid) (< net20) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net20) (>= netstandard1.3) (< netstandard1.5) (< win8) (< wpa81)) (&& (< monotouch) (< net20) (>= netstandard1.5) (< netstandard2.0) (< win8) (< wpa81) (< xamarintvos) (< xamarinwatchos))
+ Microsoft.NETCore.Targets (5.0) - restriction: || (&& (< monoandroid) (< net20) (>= netstandard1.0) (< netstandard1.2) (< win8) (< wp8)) (&& (< monoandroid) (< net20) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net20) (>= netstandard1.3) (< netstandard1.5) (< win8) (< wpa81)) (&& (< monotouch) (< net20) (>= netstandard1.5) (< netstandard2.0) (< win8) (< wpa81) (< xamarintvos) (< xamarinwatchos))
+ Mono.Cecil (0.11.6) - restriction: >= net6.0
+ System.Buffers (4.6.1) - restriction: || (>= net462) (&& (>= net6.0) (< net8.0)) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Collections.Immutable (10.0.2) - restriction: >= netstandard2.0
+ System.Memory (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Runtime.CompilerServices.Unsafe (>= 6.1.2) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.IO.Pipelines (10.0.2) - restriction: || (&& (< net10.0) (>= net9.0)) (&& (>= net462) (>= net6.0)) (&& (>= net6.0) (< net8.0)) (&& (>= net8.0) (< net9.0))
+ System.Buffers (>= 4.6.1) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Memory (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Threading.Tasks.Extensions (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Memory (4.6.3) - restriction: || (>= net462) (&& (>= net6.0) (< net8.0)) (&& (< net8.0) (>= netstandard2.0)) (&& (>= netstandard2.0) (< netstandard2.1))
+ System.Buffers (>= 4.6.1) - restriction: || (>= net462) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Numerics.Vectors (>= 4.6.1) - restriction: || (>= net462) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Runtime.CompilerServices.Unsafe (>= 6.1.2) - restriction: || (>= net462) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Numerics.Vectors (4.6.1) - restriction: || (>= net462) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Reactive (6.1) - restriction: >= netstandard2.0
+ System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (>= net472) (&& (< net6.0) (>= netstandard2.0)) (>= uap10.1)
+ System.Runtime (4.3.1) - restriction: && (< net20) (>= netstandard1.0) (< netstandard2.0)
+ Microsoft.NETCore.Platforms (>= 1.1.1) - restriction: || (&& (< monoandroid) (< net45) (>= netstandard1.0) (< netstandard1.2) (< win8) (< wp8)) (&& (< monoandroid) (< net45) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.5) (< win8) (< wpa81)) (&& (< monotouch) (< net45) (>= netstandard1.5) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos))
+ Microsoft.NETCore.Targets (>= 1.1.3) - restriction: || (&& (< monoandroid) (< net45) (>= netstandard1.0) (< netstandard1.2) (< win8) (< wp8)) (&& (< monoandroid) (< net45) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.5) (< win8) (< wpa81)) (&& (< monotouch) (< net45) (>= netstandard1.5) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos))
+ System.Runtime.CompilerServices.Unsafe (6.1.2) - restriction: || (>= net462) (&& (>= net6.0) (< net8.0)) (&& (< net8.0) (>= netstandard2.0)) (&& (< netcoreapp2.1) (>= netstandard2.0) (< netstandard2.1))
+ System.Text.Encodings.Web (10.0.2) - restriction: || (&& (< net10.0) (>= net9.0)) (&& (>= net462) (>= net6.0)) (&& (>= net6.0) (< net8.0)) (&& (>= net8.0) (< net9.0))
+ System.Buffers (>= 4.6.1) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Memory (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Runtime.CompilerServices.Unsafe (>= 6.1.2) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Text.Json (10.0.2) - restriction: >= net6.0
+ Microsoft.Bcl.AsyncInterfaces (>= 10.0.2) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Buffers (>= 4.6.1) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.IO.Pipelines (>= 10.0.2) - restriction: || (&& (< net10.0) (>= net9.0)) (>= net462) (&& (>= net8.0) (< net9.0)) (&& (< net8.0) (>= netstandard2.0))
+ System.Memory (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Runtime.CompilerServices.Unsafe (>= 6.1.2) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Text.Encodings.Web (>= 10.0.2) - restriction: || (&& (< net10.0) (>= net9.0)) (>= net462) (&& (>= net8.0) (< net9.0)) (&& (< net8.0) (>= netstandard2.0))
+ System.Threading.Tasks.Extensions (>= 4.6.3) - restriction: || (>= net462) (&& (< net8.0) (>= netstandard2.0))
+ System.Threading.Tasks.Extensions (4.6.3) - restriction: || (&& (>= net462) (>= net6.0)) (>= net472) (&& (>= net6.0) (< net8.0)) (&& (< net6.0) (>= netstandard2.0)) (&& (>= netstandard2.0) (>= uap10.1))
+ System.ValueTuple (4.6.1) - restriction: && (>= net45) (>= netstandard2.0)
diff --git a/fsharp-view-engine/src/App/App.fsproj b/fsharp-view-engine/src/App/App.fsproj
new file mode 100644
index 0000000..7548c50
--- /dev/null
+++ b/fsharp-view-engine/src/App/App.fsproj
@@ -0,0 +1,33 @@
+
+
The requested page could not be found.
" + + let private renderPage (title: string) (fileName: string) : HttpHandler = + fun next ctx -> task { + let currentPath = ctx.Request.Path.Value + let markdownContent = readMarkdownFile fileName + let content = Views.layout title currentPath markdownContent + let html = Element.render content + return! htmlString html next ctx + } + + // Route handlers + let homeHandler : HttpHandler = + renderPage "FSharp.ViewEngine Documentation" "home" + + let installationHandler : HttpHandler = + renderPage "Installation - FSharp.ViewEngine" "installation" + + let quickstartHandler : HttpHandler = + renderPage "Quickstart - FSharp.ViewEngine" "quickstart" diff --git a/fsharp-view-engine/src/App/Program.fs b/fsharp-view-engine/src/App/Program.fs new file mode 100644 index 0000000..306730c --- /dev/null +++ b/fsharp-view-engine/src/App/Program.fs @@ -0,0 +1,39 @@ +open Microsoft.AspNetCore.Builder +open Microsoft.Extensions.Hosting +open Microsoft.Extensions.DependencyInjection +open Giraffe +open App.Handlers + +let webApp = + choose [ + GET >=> choose [ + route "/" >=> homeHandler + route "/installation" >=> installationHandler + route "/quickstart" >=> quickstartHandler + ] + ] + +let configureApp (app : IApplicationBuilder) = + app.UseStaticFiles() |> ignore + app.UseGiraffe(webApp) + +let configureServices (services : IServiceCollection) = + services.AddGiraffe() |> ignore + +[Welcome to FSharp.ViewEngine
+