From 9132222438f0e703a34cabffefb99e6eec26cd26 Mon Sep 17 00:00:00 2001 From: Kevin F Date: Mon, 13 Jun 2022 11:14:23 +0200 Subject: [PATCH] Add build project :sparkles: --- .gitignore | 1 + Nfdi4Plants.Fornax.sln | 52 ++++++ RELEASE_NOTES.md | 3 + build.cmd | 4 + build/BasicTasks.fs | 30 ++++ build/Build.fs | 33 ++++ build/Helpers.fs | 28 ++++ build/MessagePrompts.fs | 18 +++ build/PackageTasks.fs | 57 +++++++ build/ProjectInfo.fs | 38 +++++ build/ReleaseNotesTasks.fs | 27 ++++ build/ReleaseTasks.fs | 58 +++++++ build/TestTasks.fs | 43 +++++ build/build.fsproj | 33 ++++ src/loaders/docsloader.fsx | 323 +++++++++++++++++++------------------ 15 files changed, 587 insertions(+), 161 deletions(-) create mode 100644 Nfdi4Plants.Fornax.sln create mode 100644 RELEASE_NOTES.md create mode 100644 build.cmd create mode 100644 build/BasicTasks.fs create mode 100644 build/Build.fs create mode 100644 build/Helpers.fs create mode 100644 build/MessagePrompts.fs create mode 100644 build/PackageTasks.fs create mode 100644 build/ProjectInfo.fs create mode 100644 build/ReleaseNotesTasks.fs create mode 100644 build/ReleaseTasks.fs create mode 100644 build/TestTasks.fs create mode 100644 build/build.fsproj diff --git a/.gitignore b/.gitignore index e1c992f..18518a0 100644 --- a/.gitignore +++ b/.gitignore @@ -350,3 +350,4 @@ MigrationBackup/ .ionide/ src/_public .vscode/settings.json +.vscode/ \ No newline at end of file diff --git a/Nfdi4Plants.Fornax.sln b/Nfdi4Plants.Fornax.sln new file mode 100644 index 0000000..e69cc36 --- /dev/null +++ b/Nfdi4Plants.Fornax.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32505.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2B672946-D10B-4804-93DE-B11DE6B85259}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fornax.Nfdi4Plants", "src\Fornax.Nfdi4Plants\Fornax.Nfdi4Plants.fsproj", "{CFC6EB06-696A-4542-94CF-4D607A2E1225}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{569B21DD-E434-48EF-9D28-FC864B6A7EC3}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fornax.Nfdi4Plants.Tests", "tests\Fornax.Nfdi4Plants.Tests\Fornax.Nfdi4Plants.Tests.fsproj", "{1FA65D34-DF8B-4B24-8A11-084219DDC133}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "build", "build\build.fsproj", "{C125CB69-05E3-4D86-B099-55B213B624DB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{698B3036-4F3E-451C-AEFA-6BE8117B322E}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + RELEASE_NOTES.md = RELEASE_NOTES.md + rollup.config.js = rollup.config.js + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CFC6EB06-696A-4542-94CF-4D607A2E1225}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFC6EB06-696A-4542-94CF-4D607A2E1225}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFC6EB06-696A-4542-94CF-4D607A2E1225}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFC6EB06-696A-4542-94CF-4D607A2E1225}.Release|Any CPU.Build.0 = Release|Any CPU + {1FA65D34-DF8B-4B24-8A11-084219DDC133}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FA65D34-DF8B-4B24-8A11-084219DDC133}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FA65D34-DF8B-4B24-8A11-084219DDC133}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FA65D34-DF8B-4B24-8A11-084219DDC133}.Release|Any CPU.Build.0 = Release|Any CPU + {C125CB69-05E3-4D86-B099-55B213B624DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C125CB69-05E3-4D86-B099-55B213B624DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C125CB69-05E3-4D86-B099-55B213B624DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C125CB69-05E3-4D86-B099-55B213B624DB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CFC6EB06-696A-4542-94CF-4D607A2E1225} = {2B672946-D10B-4804-93DE-B11DE6B85259} + {1FA65D34-DF8B-4B24-8A11-084219DDC133} = {569B21DD-E434-48EF-9D28-FC864B6A7EC3} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9591E7EB-8243-4661-BA6B-3DD822EB60EB} + EndGlobalSection +EndGlobal diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..13601ab --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,3 @@ +### 0.0.0 (Released 2022-6-13) +* Additions: + * Initial set up for RELEASE_Notes.md diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..97d967d --- /dev/null +++ b/build.cmd @@ -0,0 +1,4 @@ +@echo off +cls + +dotnet run --project ./build/build.fsproj %* \ No newline at end of file diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs new file mode 100644 index 0000000..d7f28ad --- /dev/null +++ b/build/BasicTasks.fs @@ -0,0 +1,30 @@ +module BasicTasks + +open BlackFox.Fake +open Fake.IO +open Fake.DotNet +open Fake.IO.Globbing.Operators + +open ProjectInfo + +let setPrereleaseTag = BuildTask.create "SetPrereleaseTag" [] { + printfn "Please enter pre-release package suffix" + let suffix = System.Console.ReadLine() + prereleaseSuffix <- suffix + prereleaseTag <- (sprintf "%s-%s" release.NugetVersion suffix) + isPrerelease <- true +} + +let clean = BuildTask.create "Clean" [] { + !! "src/**/bin" + ++ "src/**/obj" + ++ "tests/**/bin" + ++ "tests/**/obj" + ++ "pkg" + |> Shell.cleanDirs +} + +let build = BuildTask.create "Build" [clean] { + solutionFile + |> DotNet.build id +} \ No newline at end of file diff --git a/build/Build.fs b/build/Build.fs new file mode 100644 index 0000000..8d00ddc --- /dev/null +++ b/build/Build.fs @@ -0,0 +1,33 @@ +open BlackFox.Fake +open System.IO +open Fake.Core +open Fake.DotNet +open Fake.IO +open Fake.IO.FileSystemOperators +open Fake.IO.Globbing.Operators +open Fake.Tools + +open Helpers + +initializeContext() + +open BasicTasks +open TestTasks +open PackageTasks +open ReleaseTasks + +/// Full release of nuget package for the prerelease version. +let _release = + BuildTask.createEmpty + "ReleaseNoDocs" + [clean; build; runTests; pack; createTag; publishNuget;] + +/// Full release of nuget package for the prerelease version. +let _preRelease = + BuildTask.createEmpty + "PreReleaseNoDocs" + [setPrereleaseTag; clean; build; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease] + +[] +let main args = + runOrDefault build args diff --git a/build/Helpers.fs b/build/Helpers.fs new file mode 100644 index 0000000..5dd1ed8 --- /dev/null +++ b/build/Helpers.fs @@ -0,0 +1,28 @@ +module Helpers + +open BlackFox.Fake +open Fake.Core +open Fake.DotNet + +let initializeContext () = + let execContext = Context.FakeExecutionContext.Create false "build.fsx" [ ] + Context.setExecutionContext (Context.RuntimeContext.Fake execContext) + +/// Executes a dotnet command in the given working directory +let runDotNet cmd workingDir = + let result = + DotNet.exec (DotNet.Options.withWorkingDirectory workingDir) cmd "" + if result.ExitCode <> 0 then failwithf "'dotnet %s' failed in %s" cmd workingDir + +let runOrDefault defaultTarget args = + Trace.trace (sprintf "%A" args) + try + match args with + | [| target |] -> Target.runOrDefault target + | arr when args.Length > 1 -> + Target.run 0 (Array.head arr) ( Array.tail arr |> List.ofArray ) + | _ -> BuildTask.runOrDefault defaultTarget + 0 + with e -> + printfn "%A" e + 1 \ No newline at end of file diff --git a/build/MessagePrompts.fs b/build/MessagePrompts.fs new file mode 100644 index 0000000..afa3708 --- /dev/null +++ b/build/MessagePrompts.fs @@ -0,0 +1,18 @@ +module MessagePrompts + +let prompt (msg:string) = + System.Console.Write(msg) + System.Console.ReadLine().Trim() + |> function | "" -> None | s -> Some s + |> Option.map (fun s -> s.Replace ("\"","\\\"")) + +let rec promptYesNo msg = + match prompt (sprintf "%s [Yn]: " msg) with + | Some "Y" | Some "y" -> true + | Some "N" | Some "n" -> false + | _ -> System.Console.WriteLine("Sorry, invalid answer"); promptYesNo msg + +let releaseMsg = """This will stage all uncommitted changes, push them to the origin and bump the release version to the latest number in the RELEASE_NOTES.md file. + Do you want to continue?""" + +let releaseDocsMsg = """This will push the docs to gh-pages. Remember building the docs prior to this. Do you want to continue?""" \ No newline at end of file diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs new file mode 100644 index 0000000..d51d99a --- /dev/null +++ b/build/PackageTasks.fs @@ -0,0 +1,57 @@ +module PackageTasks + +open ProjectInfo + +open MessagePrompts +open BasicTasks +open TestTasks + +open BlackFox.Fake +open Fake.Core +open Fake.IO.Globbing.Operators + +let pack = BuildTask.create "Pack" [clean; build; runTests] { + if promptYesNo (sprintf "creating stable package with version %s OK?" stableVersionTag ) + then + !! "src/**/*.*proj" + -- "src/bin/*" + |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> + let msBuildParams = + {p.MSBuildParams with + Properties = ([ + "Version",stableVersionTag + "PackageReleaseNotes", (release.Notes |> String.concat "\r\n") + ] @ p.MSBuildParams.Properties) + } + { + p with + MSBuildParams = msBuildParams + OutputPath = Some pkgDir + } + )) + else failwith "aborted" +} + +let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; build; runTests] { + if promptYesNo (sprintf "package tag will be %s OK?" prereleaseTag ) + then + !! "src/**/*.*proj" + -- "src/bin/*" + |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> + let msBuildParams = + {p.MSBuildParams with + Properties = ([ + "Version", prereleaseTag + "PackageReleaseNotes", (release.Notes |> String.toLines ) + ] @ p.MSBuildParams.Properties) + } + { + p with + VersionSuffix = Some prereleaseSuffix + OutputPath = Some pkgDir + MSBuildParams = msBuildParams + } + )) + else + failwith "aborted" +} \ No newline at end of file diff --git a/build/ProjectInfo.fs b/build/ProjectInfo.fs new file mode 100644 index 0000000..d70da15 --- /dev/null +++ b/build/ProjectInfo.fs @@ -0,0 +1,38 @@ +module ProjectInfo + +open Fake.Core +open Fake.Extensions.Release + +Release.exists() + +let project = "Nfdi4Plants.Fornax" + +let testProjects = + [ + // add relative paths (from project root) to your testprojects here + @"tests\Fornax.Nfdi4Plants.Tests\Fornax.Nfdi4Plants.Tests.fsproj" + ] + +let solutionFile = $"{project}.sln" + +let configuration = "Release" + +let gitOwner = "Freymaurer" + +let gitHome = $"https://github.com/{gitOwner}" + +let projectRepo = $"https://github.com/{gitOwner}/{project}" + +let pkgDir = "pkg" + +let release = ReleaseNotes.load "RELEASE_NOTES.md" + +let stableVersion = SemVer.parse release.NugetVersion + +let stableVersionTag = (sprintf "%i.%i.%i" stableVersion.Major stableVersion.Minor stableVersion.Patch ) + +let mutable prereleaseSuffix = "" + +let mutable prereleaseTag = "" + +let mutable isPrerelease = false \ No newline at end of file diff --git a/build/ReleaseNotesTasks.fs b/build/ReleaseNotesTasks.fs new file mode 100644 index 0000000..f1f95a9 --- /dev/null +++ b/build/ReleaseNotesTasks.fs @@ -0,0 +1,27 @@ +module ReleaseNotesTasks + +open Fake.Extensions.Release +open BlackFox.Fake + +let createAssemblyVersion = BuildTask.create "createvfs" [] { + AssemblyVersion.create ProjectInfo.project +} + +let updateReleaseNotes = BuildTask.createFn "ReleaseNotes" [] (fun config -> + Release.exists() + + Release.update(ProjectInfo.gitOwner, ProjectInfo.project, config) +) + +let githubDraft = BuildTask.createFn "GithubDraft" [] (fun config -> + + let body = "We are ready to go for the first release!" + + Github.draft( + ProjectInfo.gitOwner, + ProjectInfo.project, + (Some body), + None, + config + ) +) \ No newline at end of file diff --git a/build/ReleaseTasks.fs b/build/ReleaseTasks.fs new file mode 100644 index 0000000..038c7d9 --- /dev/null +++ b/build/ReleaseTasks.fs @@ -0,0 +1,58 @@ +module ReleaseTasks + +open MessagePrompts +open ProjectInfo +open BasicTasks +open TestTasks +open PackageTasks + +open BlackFox.Fake +open Fake.Core +open Fake.DotNet +open Fake.Api +open Fake.Tools +open Fake.IO +open Fake.IO.Globbing.Operators + +let createTag = BuildTask.create "CreateTag" [clean; build; runTests; pack] { + if promptYesNo (sprintf "tagging branch with %s OK?" stableVersionTag ) then + Git.Branches.tag "" stableVersionTag + Git.Branches.pushTag "" projectRepo stableVersionTag + else + failwith "aborted" +} + +let createPrereleaseTag = BuildTask.create "CreatePrereleaseTag" [setPrereleaseTag; clean; build; runTests; packPrerelease] { + if promptYesNo (sprintf "tagging branch with %s OK?" prereleaseTag ) then + Git.Branches.tag "" prereleaseTag + Git.Branches.pushTag "" projectRepo prereleaseTag + else + failwith "aborted" +} + + +let publishNuget = BuildTask.create "PublishNuget" [clean; build; runTests; pack] { + let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) + for target in targets do printfn "%A" target + let msg = sprintf "release package with version %s?" stableVersionTag + if promptYesNo msg then + let source = "https://api.nuget.org/v3/index.json" + let apikey = Environment.environVar "NUGET_KEY_CSB" + for artifact in targets do + let result = DotNet.exec id "nuget" (sprintf "push -s %s -k %s %s --skip-duplicate" source apikey artifact) + if not result.OK then failwith "failed to push packages" + else failwith "aborted" +} + +let publishNugetPrerelease = BuildTask.create "PublishNugetPrerelease" [clean; build; runTests; packPrerelease] { + let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) + for target in targets do printfn "%A" target + let msg = sprintf "release package with version %s?" prereleaseTag + if promptYesNo msg then + let source = "https://api.nuget.org/v3/index.json" + let apikey = Environment.environVar "NUGET_KEY_CSB" + for artifact in targets do + let result = DotNet.exec id "nuget" (sprintf "push -s %s -k %s %s --skip-duplicate" source apikey artifact) + if not result.OK then failwith "failed to push packages" + else failwith "aborted" +} \ No newline at end of file diff --git a/build/TestTasks.fs b/build/TestTasks.fs new file mode 100644 index 0000000..113f964 --- /dev/null +++ b/build/TestTasks.fs @@ -0,0 +1,43 @@ +module TestTasks + +open BlackFox.Fake +open Fake.DotNet + +open ProjectInfo +open BasicTasks + +let runTests = BuildTask.create "RunTests" [clean; build] { + testProjects + |> Seq.iter (fun testProject -> + Fake.DotNet.DotNet.test(fun testParams -> + { + testParams with + Logger = Some "console;verbosity=detailed" + Configuration = DotNet.BuildConfiguration.fromString configuration + NoBuild = true + } + ) testProject + ) +} + +// to do: use this once we have actual tests +let runTestsWithCodeCov = BuildTask.create "RunTestsWithCodeCov" [clean; build] { + let standardParams = Fake.DotNet.MSBuild.CliArguments.Create () + testProjects + |> Seq.iter(fun testProject -> + Fake.DotNet.DotNet.test(fun testParams -> + { + testParams with + MSBuildParams = { + standardParams with + Properties = [ + "AltCover","true" + "AltCoverCobertura","../../codeCov.xml" + "AltCoverForce","true" + ] + }; + Logger = Some "console;verbosity=detailed" + } + ) testProject + ) +} \ No newline at end of file diff --git a/build/build.fsproj b/build/build.fsproj new file mode 100644 index 0000000..3943ef2 --- /dev/null +++ b/build/build.fsproj @@ -0,0 +1,33 @@ + + + + net6.0 + Exe + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/loaders/docsloader.fsx b/src/loaders/docsloader.fsx index 352cd52..76ec8bf 100644 --- a/src/loaders/docsloader.fsx +++ b/src/loaders/docsloader.fsx @@ -1,171 +1,172 @@ #r "../_lib/Fornax.Core.dll" #r "../_lib/Markdig.dll" -#load "nfdi-header-extension.fsx" -#load "sidebar-header-extension.fsx" +#r @"..\Fornax.Nfdi4Plants\bin\Debug\net5.0\Fornax.Nfdi4Plants.dll" open System.IO -open Markdig - -type DocsConfig = { - disableLiveRefresh: bool -} - -type SidebarElement = { - Title: string - Content: string -} - -type Docs = { - file: string - link : string - title: string - author: string option - published: System.DateTime option - add_toc: bool - sidebar: SidebarElement [] - content: string -} +open Fornax.Nfdi4Plants + +// type DocsConfig = { +// disableLiveRefresh: bool +// } + +// type SidebarElement = { +// Title: string +// Content: string +// } + +// type Docs = { +// file: string +// link : string +// title: string +// author: string option +// published: System.DateTime option +// add_toc: bool +// sidebar: SidebarElement [] +// content: string +// } let contentDir = "docs" -open ``Nfdi-header-extension`` -open ``Sidebar-header-extension`` - -let markdownPipeline = - MarkdownPipelineBuilder() - .UseAdvancedExtensions() - .UseEmojiAndSmiley() - .UseNFDIHeader() - .Build() - -let isSeparator (input : string) = - input.StartsWith "---" - -let splitKey (line: string) = - let seperatorIndex = line.IndexOf(':') - if seperatorIndex > 0 then - let key = line.[.. seperatorIndex - 1].Trim().ToLower() - let value = line.[seperatorIndex + 1 ..].Trim() - Some(key, value) - else - None - -// Parse over line to find area between "---". Parse input, very simple by separating by ":" -///`fileConfig` - Metadata at the top of an .md file -let getConfig (fileContent : string) = - let fileContent = fileContent.Split '\n' - let fileContent = fileContent |> Array.skip 1 //First line must be --- - let indexOfSeperator = fileContent |> Array.findIndex isSeparator - fileContent - |> Array.splitAt indexOfSeperator - |> fst - |> Seq.choose splitKey - |> Map.ofSeq - -let sidebarMarkdownPipeline = - MarkdownPipelineBuilder() - .UseSidebarHeader() - .Build() - -let getSidebar (sidebarPath: string) = - let fileContent = - let docsPath = Path.Combine(contentDir, sidebarPath) - File.ReadAllLines(docsPath) - |> Array.skip 1 //First line must be --- - let indexOfSeperator = fileContent |> Array.findIndex isSeparator - let content = - fileContent - |> Array.splitAt indexOfSeperator - |> snd - |> Array.skip 1 // starts with --- - let sidebar = - content - |> List.ofArray - |> List.fold (fun acc line -> - // opens new sidebar element with title - // ` = '\096' - if line.Trim() = "```" then - acc - elif line.StartsWith "```" then - // get sidebar element title - let title = line.Replace("`", "").Trim() - // add to list collection with empty list. - // empty list will be used to add all related lines - (title, List.empty)::acc - elif line.Trim() <> "" then - // match with list collection to check if it is empty (should not be empty, this is error prediction) - match acc with - // if has element, add line to sidebar element - | h::t -> (fst h, line::snd h)::t - // if is empty add sidebar placeholder - | [] -> ("Sidebar", line::[])::acc - else - acc - ) [] - |> List.map (fun (title, lines) -> - let c = lines |> List.rev |> String.concat "\n" - { - Title = title - Content = Markdown.ToHtml(c, sidebarMarkdownPipeline) - } - ) - |> List.rev - |> Array.ofList - sidebar - -///`fileContent` - content of page to parse. Usually whole content of `.md` file -///returns HTML version of content of the page -let getContent (fileContent : string) = - let fileContent = fileContent.Split '\n' - let fileContent = fileContent |> Array.skip 1 //First line must be --- - let indexOfSeperator = fileContent |> Array.findIndex isSeparator - let content = - fileContent - |> Array.splitAt indexOfSeperator - |> snd - |> Array.skip 1 // starts with --- - |> String.concat "\n" - - Markdown.ToHtml(content, markdownPipeline) - -let trimString (str : string) = - str.Trim().TrimEnd('"').TrimStart('"') - -let loadFile (rootDir: string) (filePath: string) = - let text = File.ReadAllText filePath - - let config = getConfig text - - let title = config |> Map.find "title" |> trimString - let author = config |> Map.tryFind "author" |> Option.map trimString - let published = config |> Map.tryFind "published" |> Option.map (trimString >> System.DateTime.Parse) - let addToc = config |> Map.tryFind "add toc" |> Option.map (trimString >> System.Boolean.Parse) |> Option.defaultValue true - let addSidebar = - let docsPath = Path.Combine(rootDir, contentDir) - config |> Map.tryFind "add sidebar" |> Option.map (trimString >> fun x -> Path.Combine(docsPath, x.Replace('\\','/'))) - - let content = getContent text - let sidebar = addSidebar |> Option.map getSidebar - 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 [||] } +// open ``Nfdi-header-extension`` +// open ``Sidebar-header-extension`` + +// let markdownPipeline = +// MarkdownPipelineBuilder() +// .UseAdvancedExtensions() +// .UseEmojiAndSmiley() +// .UseNFDIHeader() +// .Build() + +// let isSeparator (input : string) = +// input.StartsWith "---" + +// let splitKey (line: string) = +// let seperatorIndex = line.IndexOf(':') +// if seperatorIndex > 0 then +// let key = line.[.. seperatorIndex - 1].Trim().ToLower() +// let value = line.[seperatorIndex + 1 ..].Trim() +// Some(key, value) +// else +// None + +// // Parse over line to find area between "---". Parse input, very simple by separating by ":" +// ///`fileConfig` - Metadata at the top of an .md file +// let getConfig (fileContent : string) = +// let fileContent = fileContent.Split '\n' +// let fileContent = fileContent |> Array.skip 1 //First line must be --- +// let indexOfSeperator = fileContent |> Array.findIndex isSeparator +// fileContent +// |> Array.splitAt indexOfSeperator +// |> fst +// |> Seq.choose splitKey +// |> Map.ofSeq + +// let sidebarMarkdownPipeline = +// MarkdownPipelineBuilder() +// .UseSidebarHeader() +// .Build() + +// let getSidebar (sidebarPath: string) = +// let fileContent = +// let docsPath = Path.Combine(contentDir, sidebarPath) +// File.ReadAllLines(docsPath) +// |> Array.skip 1 //First line must be --- +// let indexOfSeperator = fileContent |> Array.findIndex isSeparator +// let content = +// fileContent +// |> Array.splitAt indexOfSeperator +// |> snd +// |> Array.skip 1 // starts with --- +// let sidebar = +// content +// |> List.ofArray +// |> List.fold (fun acc line -> +// // opens new sidebar element with title +// // ` = '\096' +// if line.Trim() = "```" then +// acc +// elif line.StartsWith "```" then +// // get sidebar element title +// let title = line.Replace("`", "").Trim() +// // add to list collection with empty list. +// // empty list will be used to add all related lines +// (title, List.empty)::acc +// elif line.Trim() <> "" then +// // match with list collection to check if it is empty (should not be empty, this is error prediction) +// match acc with +// // if has element, add line to sidebar element +// | h::t -> (fst h, line::snd h)::t +// // if is empty add sidebar placeholder +// | [] -> ("Sidebar", line::[])::acc +// else +// acc +// ) [] +// |> List.map (fun (title, lines) -> +// let c = lines |> List.rev |> String.concat "\n" +// { +// Title = title +// Content = Markdown.ToHtml(c, sidebarMarkdownPipeline) +// } +// ) +// |> List.rev +// |> Array.ofList +// sidebar + +// ///`fileContent` - content of page to parse. Usually whole content of `.md` file +// ///returns HTML version of content of the page +// let getContent (fileContent : string) = +// let fileContent = fileContent.Split '\n' +// let fileContent = fileContent |> Array.skip 1 //First line must be --- +// let indexOfSeperator = fileContent |> Array.findIndex isSeparator +// let content = +// fileContent +// |> Array.splitAt indexOfSeperator +// |> snd +// |> Array.skip 1 // starts with --- +// |> String.concat "\n" + +// Markdown.ToHtml(content, markdownPipeline) + +// let trimString (str : string) = +// str.Trim().TrimEnd('"').TrimStart('"') + +// let loadFile (rootDir: string) (filePath: string) = +// let text = File.ReadAllText filePath + +// let config = getConfig text + +// let title = config |> Map.find "title" |> trimString +// let author = config |> Map.tryFind "author" |> Option.map trimString +// let published = config |> Map.tryFind "published" |> Option.map (trimString >> System.DateTime.Parse) +// let addToc = config |> Map.tryFind "add toc" |> Option.map (trimString >> System.Boolean.Parse) |> Option.defaultValue true +// let addSidebar = +// let docsPath = Path.Combine(rootDir, contentDir) +// config |> Map.tryFind "add sidebar" |> Option.map (trimString >> fun x -> Path.Combine(docsPath, x.Replace('\\','/'))) + +// let content = getContent text +// let sidebar = addSidebar |> Option.map getSidebar +// 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 [||] } + +open Types let loader (projectRoot: string) (siteContent: SiteContents) = let docsPath = Path.Combine(projectRoot, contentDir)