WIP on adding htmax option (#59)

This commit is contained in:
2026-07-05 17:54:36 -04:00
parent 7c588662d2
commit 9d2277ab32
10 changed files with 81 additions and 15 deletions
+10 -1
View File
@@ -9,6 +9,14 @@ module Json =
open Newtonsoft.Json open Newtonsoft.Json
/// <summary>Converter for the <see cref="AutoHtmxType" /> type</summary>
type AutoHtmxTypeConverter() =
inherit JsonConverter<AutoHtmxType>()
override _.WriteJson(writer: JsonWriter, value: AutoHtmxType, _: JsonSerializer) =
writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: AutoHtmxType, _: bool, _: JsonSerializer) =
(string >> AutoHtmxType.Parse) reader.Value
/// <summary>Converter for the <see cref="CategoryId" /> type</summary> /// <summary>Converter for the <see cref="CategoryId" /> type</summary>
type CategoryIdConverter() = type CategoryIdConverter() =
inherit JsonConverter<CategoryId>() inherit JsonConverter<CategoryId>()
@@ -160,7 +168,8 @@ module Json =
/// <summary>Configure a serializer to use these converters (and other settings)</summary> /// <summary>Configure a serializer to use these converters (and other settings)</summary>
let configure (ser: JsonSerializer) = let configure (ser: JsonSerializer) =
// Our converters // Our converters
[ CategoryIdConverter() :> JsonConverter [ AutoHtmxTypeConverter() :> JsonConverter
CategoryIdConverter()
CommentIdConverter() CommentIdConverter()
CommentStatusConverter() CommentStatusConverter()
CustomFeedIdConverter() CustomFeedIdConverter()
+2
View File
@@ -228,6 +228,8 @@ type PostgresData(log: ILogger<PostgresData>, ser: JsonSerializer) =
let migrateV2point2ToV3 () = backgroundTask { let migrateV2point2ToV3 () = backgroundTask {
Utils.Migration.logStep log "v2.2 to v3" "Adding auto-OpenGraph flag to all web logs" Utils.Migration.logStep log "v2.2 to v3" "Adding auto-OpenGraph flag to all web logs"
do! Patch.byFields Table.WebLog Any [ Field.Exists (nameof WebLog.Empty.Id) ] {| AutoOpenGraph = true |} do! Patch.byFields Table.WebLog Any [ Field.Exists (nameof WebLog.Empty.Id) ] {| AutoOpenGraph = true |}
do! Patch.byContains Table.WebLog {| AutoHtmx = true |} {| AutoHtmx = "Yes" |}
do! Patch.byContains Table.WebLog {| AutoHtmx = false |} {| AutoHtmx = "No" |}
Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3" Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3"
return! setDbVersion "v3" return! setDbVersion "v3"
} }
+12
View File
@@ -264,6 +264,18 @@ type RethinkDbData(conn: Net.IConnection, config: DataConfig, log: ILogger<Rethi
update [ nameof WebLog.Empty.AutoOpenGraph, true :> obj ] update [ nameof WebLog.Empty.AutoOpenGraph, true :> obj ]
write; withRetryOnce; ignoreResult conn write; withRetryOnce; ignoreResult conn
} }
do! rethink {
withTable Table.WebLog
filter (nameof WebLog.Empty.AutoHtmx) true
update [ nameof WebLog.Empty.AutoHtmx, "Yes" ]
write; withRetryOnce; ignoreResult conn
}
do! rethink {
withTable Table.WebLog
filter (nameof WebLog.Empty.AutoHtmx) false
update [ nameof WebLog.Empty.AutoHtmx, "No" ]
write; withRetryOnce; ignoreResult conn
}
Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3" Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3"
do! setDbVersion "v3" do! setDbVersion "v3"
} }
+2
View File
@@ -456,6 +456,8 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
let migrateV2point2ToV3 () = backgroundTask { let migrateV2point2ToV3 () = backgroundTask {
Utils.Migration.logStep log "v2.2 to v3" "Adding auto-OpenGraph flag to all web logs" Utils.Migration.logStep log "v2.2 to v3" "Adding auto-OpenGraph flag to all web logs"
do! Patch.byFields Table.WebLog Any [ Field.Exists (nameof WebLog.Empty.Id) ] {| AutoOpenGraph = true |} do! Patch.byFields Table.WebLog Any [ Field.Exists (nameof WebLog.Empty.Id) ] {| AutoOpenGraph = true |}
do! Patch.byFields Table.WebLog Any [ Field.Equal (nameof WebLog.Empty.AutoHtmx) true ] {| AutoHtmx = "Yes" |}
do! Patch.byFields Table.WebLog Any [ Field.Equal (nameof WebLog.Empty.AutoHtmx) false ] {| AutoHtmx = "No" |}
Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3" Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3"
do! setDbVersion "v3" do! setDbVersion "v3"
} }
+2 -2
View File
@@ -341,7 +341,7 @@ type WebLog = {
Rss: RssOptions Rss: RssOptions
/// <summary>Whether to automatically load htmx</summary> /// <summary>Whether to automatically load htmx</summary>
AutoHtmx: bool AutoHtmx: AutoHtmxType
/// <summary>Where uploads are placed</summary> /// <summary>Where uploads are placed</summary>
Uploads: UploadDestination Uploads: UploadDestination
@@ -365,7 +365,7 @@ type WebLog = {
UrlBase = "" UrlBase = ""
TimeZone = "" TimeZone = ""
Rss = RssOptions.Empty Rss = RssOptions.Empty
AutoHtmx = false AutoHtmx = NoAutoHtmx
Uploads = Database Uploads = Database
RedirectRules = [] RedirectRules = []
AutoOpenGraph = true } AutoOpenGraph = true }
+32
View File
@@ -105,6 +105,38 @@ type AccessLevel =
AccessLevel.Weights[needed] <= AccessLevel.Weights[this] AccessLevel.Weights[needed] <= AccessLevel.Weights[this]
/// <summary>How the htmx library will be auto-injected in a web log's theme pages</summary>
[<Struct>]
type AutoHtmxType =
/// <summary>Do not auto-inject htmx into the web log's theme pages</summary>
| NoAutoHtmx
/// <summary>Inject the standard htmx library into the web log's theme pages</summary>
| AutoHtmx
/// <summary>Inject the htmax library bundle into the web log's theme pages</summary>
| AutoHtmax
/// <summary>Parse an auto-htmx type from its string representation</summary>
/// <param name="typ">The string representation to be parsed</param>
/// <returns>The <c>AutoHtmxType</c> instance parsed from the string</returns>
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
static member Parse typ =
match typ with
| "No" -> NoAutoHtmx
| "Yes" -> AutoHtmx
| "Max" -> AutoHtmax
| _ -> invalidArg (nameof typ) $"{typ} is not a valid auto-htmx type"
/// <inheritdoc />
override this.ToString() =
match this with
| NoAutoHtmx -> "No"
| AutoHtmx -> "Yes"
| AutoHtmax -> "Max"
/// <summary>An identifier for a category</summary> /// <summary>An identifier for a category</summary>
[<Struct>] [<Struct>]
type CategoryId = type CategoryId =
+3 -3
View File
@@ -1379,7 +1379,7 @@ type SettingsModel = {
ThemeId: string ThemeId: string
/// <summary>Whether to automatically load htmx</summary> /// <summary>Whether to automatically load htmx</summary>
AutoHtmx: bool AutoHtmx: string
/// <summary>The default location for uploads</summary> /// <summary>The default location for uploads</summary>
Uploads: string Uploads: string
@@ -1399,7 +1399,7 @@ type SettingsModel = {
PostsPerPage = webLog.PostsPerPage PostsPerPage = webLog.PostsPerPage
TimeZone = webLog.TimeZone TimeZone = webLog.TimeZone
ThemeId = string webLog.ThemeId ThemeId = string webLog.ThemeId
AutoHtmx = webLog.AutoHtmx AutoHtmx = string webLog.AutoHtmx
Uploads = string webLog.Uploads Uploads = string webLog.Uploads
AutoOpenGraph = webLog.AutoOpenGraph } AutoOpenGraph = webLog.AutoOpenGraph }
@@ -1415,7 +1415,7 @@ type SettingsModel = {
PostsPerPage = this.PostsPerPage PostsPerPage = this.PostsPerPage
TimeZone = this.TimeZone TimeZone = this.TimeZone
ThemeId = ThemeId this.ThemeId ThemeId = ThemeId this.ThemeId
AutoHtmx = this.AutoHtmx AutoHtmx = AutoHtmxType.Parse this.AutoHtmx
Uploads = UploadDestination.Parse this.Uploads Uploads = UploadDestination.Parse this.Uploads
AutoOpenGraph = this.AutoOpenGraph } AutoOpenGraph = this.AutoOpenGraph }
+7 -4
View File
@@ -5,9 +5,7 @@ open System
open System.IO open System.IO
open System.Web open System.Web
open DotLiquid open DotLiquid
open Giraffe.ViewEngine
open MyWebLog.ViewModels open MyWebLog.ViewModels
open MyWebLog.Views
/// Extensions on the DotLiquid Context object /// Extensions on the DotLiquid Context object
type Context with type Context with
@@ -158,8 +156,13 @@ type PageFootTag() =
// spacer // spacer
let s = " " let s = " "
if webLog.AutoHtmx then match webLog.AutoHtmx with
result.WriteLine $"{s}{RenderView.AsString.htmlNode Htmx.Script.local}" | NoAutoHtmx -> None
| AutoHtmx -> (Permalink >> Some) Giraffe.Htmx.Common.StaticAssetUrl.htmx[1..]
| AutoHtmax -> (Permalink >> Some) Giraffe.Htmx.Common.StaticAssetUrl.htmax[1..]
|> function
| Some url -> result.WriteLine $"""{s}<script src="{context.WebLog.RelativeUrl url}"></script>"""
| None -> ()
if assetExists "script.js" webLog then if assetExists "script.js" webLog then
result.WriteLine $"""{s}<script src="{ThemeAssetFilter.ThemeAsset(context, "script.js")}"></script>""" result.WriteLine $"""{s}<script src="{ThemeAssetFilter.ThemeAsset(context, "script.js")}"></script>"""
+3 -3
View File
@@ -240,9 +240,9 @@ let main args =
let _ = app.UseForwardedHeaders() let _ = app.UseForwardedHeaders()
(app.Services.GetRequiredService<IConfiguration>().GetSection "CanonicalDomains").Value match (app.Services.GetRequiredService<IConfiguration>().GetSection "CanonicalDomains").Value with
|> isNotNull | null -> ()
|> function true -> app.UseCanonicalDomains() |> ignore | false -> () | _ -> app.UseCanonicalDomains() |> ignore
app .UseCookiePolicy(CookiePolicyOptions(MinimumSameSitePolicy = SameSiteMode.Strict)) app .UseCookiePolicy(CookiePolicyOptions(MinimumSameSitePolicy = SameSiteMode.Strict))
.UseMiddleware<WebLogMiddleware>() .UseMiddleware<WebLogMiddleware>()
+8 -2
View File
@@ -255,10 +255,16 @@ let parser =
it.RegisterEmptyTag("page_foot", it.RegisterEmptyTag("page_foot",
fun writer encoder context -> fun writer encoder context ->
let webLog = context.App.WebLog let webLog = context.App.WebLog
if webLog.AutoHtmx then match webLog.AutoHtmx with
context.App.WebLog.RelativeUrl(Permalink StaticAssetUrl.htmx[1..]) | NoAutoHtmx -> None
| AutoHtmx -> (Permalink >> Some) StaticAssetUrl.htmx[1..]
| AutoHtmax -> (Permalink >> Some) StaticAssetUrl.htmax[1..]
|> function
| Some url ->
context.App.WebLog.RelativeUrl url
|> sprintf "%s<script src=\"%s\"></script>" s |> sprintf "%s<script src=\"%s\"></script>" s
|> writer.WriteLine |> writer.WriteLine
| None -> ()
if assetExists "script.js" webLog then if assetExists "script.js" webLog then
themeAsset (StringValue "script.js") context themeAsset (StringValue "script.js") context
|> sprintf "%s<script src=\"%s\"></script>" s |> sprintf "%s<script src=\"%s\"></script>" s