diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9b2a750..6de1547 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,11 @@ +### 0.3.0+e40d9be (Released 2022-7-8) +* Additions: + * latest commit #e40d9be + * [[#01008e1](https://github.com/Freymaurer/Nfdi4Plants.Fornax/commit/01008e1bf83787fba955f13eaaee662471729e65)] Push testing. + * [[#e40d9be](https://github.com/Freymaurer/Nfdi4Plants.Fornax/commit/e40d9be8cea57956e2bd4f4d421ccdc44f08d02d)] Add more descriptive error messages. +* Bugfixes: + * [[#0af7b87](https://github.com/Freymaurer/Nfdi4Plants.Fornax/commit/0af7b87f6aede5f02ee87fe1af58327aa8cf3a8b)] try fix hot reload issue + ### 0.2.2+03ba89a (Released 2022-6-21) * Additions: * latest commit #03ba89a diff --git a/src/Nfdi4Plants.Fornax/Components.fs b/src/Nfdi4Plants.Fornax/Components.fs index 22c81c5..d1af045 100644 --- a/src/Nfdi4Plants.Fornax/Components.fs +++ b/src/Nfdi4Plants.Fornax/Components.fs @@ -1,15 +1,66 @@ namespace Fornax.Nfdi4Plants open Html -open Docs +[] module Components = + open Docs /// Creates nfdi-webcomponent layout for documentation. /// Base path of fornax client. Is used to generate "Edit this page"-link /// `DocsData` from generated by loaders. /// Returns `HtmlElement`. Best put as direct child of `<body>` element. let docsLayout (contentGithubUrl:string) (docs: DocsData) = + + let publishedDate = docs.published.Value.ToString("yyyy-MM-dd") + let sidebar = [ + if Array.isEmpty docs.sidebar |> not then + for sidebarEle in docs.sidebar do + yield custom "nfdi-sidebar-element" [HtmlProperties.Custom ("slot", "sidebar"); HtmlProperties.Custom ("isActive","true") ] [ + div [HtmlProperties.Custom ("slot", "title")] [!! sidebarEle.Title] + !! sidebarEle.Content + ] + else () + ] + custom "nfdi-body" [Class "content"; if Array.isEmpty docs.sidebar |> not then HtmlProperties.Custom("hasSidebar", "true")] [ + yield! sidebar + + h1 [Class "front-header"] [!! docs.title] + i [Class "help" ] [!! $"last updated at {publishedDate}" ] + + if docs.add_toc then custom "nfdi-toc" [] [] + !! docs.content + + // support contact + h3 [] [!! "Dataplant Support"] + div [] [ + !! "Besides these technical solutions, DataPLANT supports you with community-engaged data stewardship. For further assistance, feel free to reach out via our " + a [Href "https://support.nfdi4plants.org"] [!! "helpdesk"] + !! " or by contacting us " + a [Href "javascript:location='mailto:\u0069\u006e\u0066\u006f\u0040\u006e\u0066\u0064\u0069\u0034\u0070\u006c\u0061\u006e\u0074\u0073\u002e\u006f\u0072\u0067';void 0"] [!! "directly"] + !! "." + ] + + // Edit this page link + // https://github.com/nfdi4plants/nfdi4plants.github.io/tree/main/src/ + let editUrl = System.IO.Path.Combine(contentGithubUrl, docs.file) + div [] [ + a [ + Target "_blank" + Href editUrl; + HtmlProperties.Style [MarginLeft "auto"; Display "block"; CSSProperties.Width "130px"] + ] [!! "✏️ Edit this page"] + ] + ] + +type Components = class end + with + /// Creates nfdi-webcomponent layout for documentation. + /// Base path of fornax client. Is used to generate "Edit this page"-link + /// `DocsData` from generated by loaders. + /// Returns `HtmlElement`. Best put as direct child of `<body>` element. + static member docsLayout (contentGithubUrl:string, docs: Docs) = + let publishedDate = docs.published.Value.ToString("yyyy-MM-dd") let sidebar = [ if Array.isEmpty docs.sidebar |> not then @@ -49,4 +100,4 @@ module Components = HtmlProperties.Style [MarginLeft "auto"; Display "block"; CSSProperties.Width "130px"] ] [!! "✏️ Edit this page"] ] - ] \ No newline at end of file + ] diff --git a/src/Nfdi4Plants.Fornax/Loaders.fs b/src/Nfdi4Plants.Fornax/Loaders.fs index 3d5c665..2e29419 100644 --- a/src/Nfdi4Plants.Fornax/Loaders.fs +++ b/src/Nfdi4Plants.Fornax/Loaders.fs @@ -1,4 +1,5 @@ namespace Fornax.Nfdi4Plants +open System.IO module Pipelines = open Markdig @@ -24,6 +25,7 @@ type SidebarElement = { Content: string } +[] type DocsData = { file: string link : string @@ -35,6 +37,18 @@ type DocsData = { content: string } +type Docs = + { + file: string + link : string + title: string + author: string option + published: System.DateTime option + add_toc: bool + sidebar: SidebarElement [] + content: string + } + module internal Aux = let private isSeparator (input : string) = @@ -69,7 +83,7 @@ module internal Aux = /// Name of the subfolder in which the docs files are. /// Relative path to sidebar file. /// Array of all sidebar elements processed to html and metadata. - let getSidebar (contentDir: string) (sidebarPath: string)= + let getSidebar (contentDir: string) (productionBasePath: string option) (sidebarPath: string) = let fileContent = let docsPath = Path.Combine(contentDir, sidebarPath) File.ReadAllLines(docsPath) @@ -131,6 +145,7 @@ module internal Aux = Markdig.Markdown.ToHtml(content, Pipelines.markdownPipeline) +[] module Docs = open System.IO @@ -140,7 +155,61 @@ module Docs = /// Folder which to search for docs .md files. This folder will be used a relative root for sidebars. /// Relative path to specific `.md` file. /// Returns html as string. - let loadFile (rootDir: string) (contentDir: string) (filePath: string) = + [] + let loadFile (rootDir: string) (contentDir: string) (filePath: string) : DocsData = + try + let text = File.ReadAllText filePath + + let config = Aux.getConfig text + + let title = + config |> Map.tryFind "title" + // same as "fun x -> match x with" + |> function | Some title -> Aux.trimString title | None -> failwith $"""Could not find "Title"-metadata.""" + let author = + config |> Map.tryFind "author" |> Option.map Aux.trimString + let published = + config |> Map.tryFind "published" |> Option.map (Aux.trimString >> System.DateTime.Parse) + let addToc = + config |> Map.tryFind "add toc" |> Option.map (Aux.trimString >> System.Boolean.Parse) |> Option.defaultValue true + let addSidebar = + let docsPath = Path.Combine(rootDir, contentDir) + config |> Map.tryFind "add sidebar" |> Option.map (Aux.trimString >> fun x -> Path.Combine(docsPath, x.Replace('\\','/'))) + + let content = Aux.getContent text + let sidebar = addSidebar |> Option.map (Aux.getSidebar contentDir None) + let chopLength = + if rootDir.EndsWith(Path.DirectorySeparatorChar) then rootDir.Length + else rootDir.Length + 1 + + let dirPart = + filePath + |> Path.GetDirectoryName + |> fun x -> x.[chopLength .. ] + + let file = Path.Combine(dirPart, (filePath |> Path.GetFileNameWithoutExtension) + ".md").Replace("\\", "/") + let link = "/" + Path.Combine(dirPart, (filePath |> Path.GetFileNameWithoutExtension) + ".html").Replace("\\", "/") + + { file = file + link = link + title = title + author = author + published = published + content = content + add_toc = addToc + sidebar = if sidebar.IsSome then sidebar.Value else [||] } + with + | e -> failwith $"""[Error in file {filePath}] {e.Message}""" + +type Docs with + + /// Parse markdown `fileContent` to HTML with markdig and custom nfdi-webcomponent converter. + /// Base root directory path, will be appended to 'contentDir'. + /// Folder which to search for docs .md files. This folder will be used a relative root for sidebars. + /// Relative path to specific `.md` file. + /// This path can be used if the base path in production is not `/`. This happens in some gh-pages projects. + /// Returns html as string. + static member loadFile(rootDir: string, contentDir: string, filePath: string, ?productionBasePath) : Docs = try let text = File.ReadAllText filePath @@ -161,7 +230,12 @@ module Docs = config |> Map.tryFind "add sidebar" |> Option.map (Aux.trimString >> fun x -> Path.Combine(docsPath, x.Replace('\\','/'))) let content = Aux.getContent text - let sidebar = addSidebar |> Option.map (Aux.getSidebar contentDir) + let sidebar = + #if WATCH + addSidebar |> Option.map (Aux.getSidebar contentDir None) + #else + addSidebar |> Option.map (Aux.getSidebar contentDir productionBasePath) + #endif let chopLength = if rootDir.EndsWith(Path.DirectorySeparatorChar) then rootDir.Length else rootDir.Length + 1 @@ -183,4 +257,5 @@ module Docs = add_toc = addToc sidebar = if sidebar.IsSome then sidebar.Value else [||] } with - | e -> failwith $"""[Error in file {filePath}] {e.Message}""" \ No newline at end of file + | e -> failwith $"""[Error in file {filePath}] {e.Message}""" + \ No newline at end of file