From ffd330a908e7e8f6c652e254611942c3969d4200 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 13:38:05 +0100 Subject: [PATCH 1/9] add attempt to make in-repo and in-package locations reusable across commands --- src/fsdocs-tool/BuildCommand.fs | 15 ++++---- src/fsdocs-tool/InitCommand.fs | 9 +++++ src/fsdocs-tool/Options.fs | 58 ++++++++++++++++++++++++++++++ src/fsdocs-tool/fsdocs-tool.fsproj | 1 + 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 src/fsdocs-tool/InitCommand.fs diff --git a/src/fsdocs-tool/BuildCommand.fs b/src/fsdocs-tool/BuildCommand.fs index acca2b3ae..4aea1d094 100644 --- a/src/fsdocs-tool/BuildCommand.fs +++ b/src/fsdocs-tool/BuildCommand.fs @@ -1579,11 +1579,13 @@ type CoreBuildOptions(watch) = // to .nuget\packages\fsdocs-tool\7.1.7\templates let dir = Path.GetDirectoryName(typeof.Assembly.Location) - let defaultTemplateAttempt1 = - Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "templates", "_template.html")) + // get template locations for in-package and in-repo and decide which to use later + let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) + let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) + + let defaultTemplateAttempt1 = inPackageLocations.template_html // This is in-repo only - let defaultTemplateAttempt2 = - Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "..", "..", "docs", "_template.html")) + let defaultTemplateAttempt2 = inRepoLocations.template_html let defaultTemplate = if this.nodefaultcontent then @@ -1610,7 +1612,7 @@ type CoreBuildOptions(watch) = // The "extras" content goes in "." // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any // to .nuget\packages\fsdocs-tool\7.1.7\extras - let attempt1 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "extras")) + let attempt1 = inPackageLocations.extras if (try @@ -1624,8 +1626,7 @@ type CoreBuildOptions(watch) = // This is for in-repo use only, assuming we are executing directly from // src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe // src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe - let attempt2 = - Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "..", "..", "docs", "content")) + let attempt2 = inRepoLocations.docs_content if (try diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs new file mode 100644 index 000000000..621e5482d --- /dev/null +++ b/src/fsdocs-tool/InitCommand.fs @@ -0,0 +1,9 @@ +namespace fsdocs + +open System.IO +open CommandLine + +[] +type InitCommand() = + class + end diff --git a/src/fsdocs-tool/Options.fs b/src/fsdocs-tool/Options.fs index 97928d046..ba32e3db3 100644 --- a/src/fsdocs-tool/Options.fs +++ b/src/fsdocs-tool/Options.fs @@ -34,3 +34,61 @@ module Common = if b then printf "\nPress any key to continue ..." System.Console.ReadKey() |> ignore + + open System.IO + + /// + /// a set of default locations in this repo. + /// these files are to be used in 2 scenarios assuming we are executing directly from + /// + /// src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe + /// + /// src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe: + /// + /// - as default styles when running watch or build when there are no user equivalents present and `nodefaultcontent` is not set to true + /// + /// - as content of the output of the `init` command to initialize a default docs folder structure. + /// + /// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. + /// + type InRepoLocations(relAssemblyPath) = + + // relAssemblyPath : relative path from assemly to repo root path + + // default folder locations relative to the assembly path + member _.docs = Path.Combine(relAssemblyPath, "docs") |> Path.GetFullPath + member this.docs_content = Path.Combine(this.docs, "content") |> Path.GetFullPath + member this.docs_content_image = Path.Combine(this.docs_content, "img") |> Path.GetFullPath + + // specific files in this folder structure that might need special treatment instead of just copy pasting + member this.template_html = Path.Combine(this.docs, "_template.html") |> Path.GetFullPath + member this.template_ipynb = Path.Combine(this.docs, "_template.ipynb") |> Path.GetFullPath + member this.template_tex = Path.Combine(this.docs, "_template.tex") |> Path.GetFullPath + + /// + /// a set of default locations in the nuget package created for fsdocs-tool. + /// these files are to be used in 2 scenarios assuming the tool is invoked via cli: + /// + /// - as default styles when running watch or build when there are no user equivalents present and `nodefaultcontent` is not set to true + /// + /// - as content of the output of the `init` command to initialize a default docs folder structure. + /// + /// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. + /// + type InPackageLocations(relAssemblyPath) = + + // relAssemblyPath : relative path from assemly to package root path + + // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any + // to .nuget\packages\fsdocs-tool\7.1.7\* + + // default folder locations relative to the assembly path + member _.templates = Path.Combine(relAssemblyPath, "templates") |> Path.GetFullPath + member _.extras = Path.Combine(relAssemblyPath, "extras") |> Path.GetFullPath + member this.extras_content = Path.Combine(this.extras, "content") |> Path.GetFullPath + member this.extras_content_img = Path.Combine(this.extras_content, "img") |> Path.GetFullPath + + // specific files in this folder structure that might need special treatment instead of just copy pasting + member this.template_html = Path.Combine(this.templates, "_template.html") |> Path.GetFullPath + member this.template_ipynb = Path.Combine(this.templates, "_template.ipynb") |> Path.GetFullPath + member this.template_tex = Path.Combine(this.templates, "_template.tex") |> Path.GetFullPath diff --git a/src/fsdocs-tool/fsdocs-tool.fsproj b/src/fsdocs-tool/fsdocs-tool.fsproj index f30c81c08..6634e6bd1 100644 --- a/src/fsdocs-tool/fsdocs-tool.fsproj +++ b/src/fsdocs-tool/fsdocs-tool.fsproj @@ -19,6 +19,7 @@ + From 6a85a1b34e6ce88093a9bed2ece710a417266801 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 19:04:37 +0100 Subject: [PATCH 2/9] Further refactoring of build command using new locations --- src/fsdocs-tool/BuildCommand.fs | 70 +++++++++++---------------------- src/fsdocs-tool/Options.fs | 37 +++++++++++++++-- 2 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/fsdocs-tool/BuildCommand.fs b/src/fsdocs-tool/BuildCommand.fs index 4aea1d094..33f9a94b8 100644 --- a/src/fsdocs-tool/BuildCommand.fs +++ b/src/fsdocs-tool/BuildCommand.fs @@ -1583,27 +1583,13 @@ type CoreBuildOptions(watch) = let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) - let defaultTemplateAttempt1 = inPackageLocations.template_html - // This is in-repo only - let defaultTemplateAttempt2 = inRepoLocations.template_html - let defaultTemplate = if this.nodefaultcontent then None - else if - (try - File.Exists(defaultTemplateAttempt1) - with _ -> - false) - then - Some defaultTemplateAttempt1 - elif - (try - File.Exists(defaultTemplateAttempt2) - with _ -> - false) - then - Some defaultTemplateAttempt2 + else if inPackageLocations.Exist() then + Some inPackageLocations.template_html + elif inRepoLocations.Exist() then + Some inRepoLocations.template_html else None @@ -1612,32 +1598,22 @@ type CoreBuildOptions(watch) = // The "extras" content goes in "." // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any // to .nuget\packages\fsdocs-tool\7.1.7\extras - let attempt1 = inPackageLocations.extras - - if - (try - Directory.Exists(attempt1) - with _ -> - false) - then - printfn "using extra content from %s" attempt1 - (attempt1, ".") - else + if inPackageLocations.Exist() then + printfn "using extra content from %s" inPackageLocations.extras + (inPackageLocations.extras, ".") + else if // This is for in-repo use only, assuming we are executing directly from // src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe // src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe - let attempt2 = inRepoLocations.docs_content - - if - (try - Directory.Exists(attempt2) - with _ -> - false) - then - printfn "using extra content from %s" attempt2 - (attempt2, "content") - else - printfn "no extra content found at %s or %s" attempt1 attempt2 ] + inRepoLocations.Exist() + then + printfn "using extra content from %s" inRepoLocations.docs_content + (inRepoLocations.docs_content, "content") + else + printfn + "no extra content found at %s or %s" + inPackageLocations.extras + inRepoLocations.docs_content ] // The incremental state (as well as the files written to disk) let mutable latestApiDocModel = None @@ -1695,12 +1671,12 @@ type CoreBuildOptions(watch) = templateFiles d - OutputKind.Html, Some d - | None -> - printfn - "note, no template file '%s' found, and no default template at '%s'" - templateFiles - defaultTemplateAttempt1 + OutputKind.Html, Some d + | None -> + printfn + "note, no template file '%s' found, and no default template at '%s'" + templateFiles + inRepoLocations.template_html OutputKind.Html, None diff --git a/src/fsdocs-tool/Options.fs b/src/fsdocs-tool/Options.fs index ba32e3db3..93901aadb 100644 --- a/src/fsdocs-tool/Options.fs +++ b/src/fsdocs-tool/Options.fs @@ -54,9 +54,10 @@ module Common = type InRepoLocations(relAssemblyPath) = // relAssemblyPath : relative path from assemly to repo root path + member _.RelAssemblyPath = relAssemblyPath // default folder locations relative to the assembly path - member _.docs = Path.Combine(relAssemblyPath, "docs") |> Path.GetFullPath + member this.docs = Path.Combine(this.RelAssemblyPath, "docs") |> Path.GetFullPath member this.docs_content = Path.Combine(this.docs, "content") |> Path.GetFullPath member this.docs_content_image = Path.Combine(this.docs_content, "img") |> Path.GetFullPath @@ -65,6 +66,20 @@ module Common = member this.template_ipynb = Path.Combine(this.docs, "_template.ipynb") |> Path.GetFullPath member this.template_tex = Path.Combine(this.docs, "_template.tex") |> Path.GetFullPath + /// + /// returns true if all special files and folders of this location exist. + /// + member this.Exist() = + try + Directory.Exists(this.docs) + && Directory.Exists(this.docs_content) + && Directory.Exists(this.docs_content_image) + && File.Exists(this.template_html) + && File.Exists(this.template_ipynb) + && File.Exists(this.template_tex) + with _ -> + false + /// /// a set of default locations in the nuget package created for fsdocs-tool. /// these files are to be used in 2 scenarios assuming the tool is invoked via cli: @@ -78,13 +93,14 @@ module Common = type InPackageLocations(relAssemblyPath) = // relAssemblyPath : relative path from assemly to package root path + member _.RelAssemblyPath = relAssemblyPath // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any // to .nuget\packages\fsdocs-tool\7.1.7\* // default folder locations relative to the assembly path - member _.templates = Path.Combine(relAssemblyPath, "templates") |> Path.GetFullPath - member _.extras = Path.Combine(relAssemblyPath, "extras") |> Path.GetFullPath + member this.templates = Path.Combine(this.RelAssemblyPath, "templates") |> Path.GetFullPath + member this.extras = Path.Combine(this.RelAssemblyPath, "extras") |> Path.GetFullPath member this.extras_content = Path.Combine(this.extras, "content") |> Path.GetFullPath member this.extras_content_img = Path.Combine(this.extras_content, "img") |> Path.GetFullPath @@ -92,3 +108,18 @@ module Common = member this.template_html = Path.Combine(this.templates, "_template.html") |> Path.GetFullPath member this.template_ipynb = Path.Combine(this.templates, "_template.ipynb") |> Path.GetFullPath member this.template_tex = Path.Combine(this.templates, "_template.tex") |> Path.GetFullPath + + /// + /// returns true if all special files and folders of this location exist. + /// + member this.Exist() = + try + Directory.Exists(this.templates) + && Directory.Exists(this.extras) + && Directory.Exists(this.extras_content) + && Directory.Exists(this.extras_content_img) + && File.Exists(this.template_html) + && File.Exists(this.template_ipynb) + && File.Exists(this.template_tex) + with _ -> + false From 40fa1e0e5b2a68b035a1cd12fe6ace378cee2893 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 20:14:00 +0100 Subject: [PATCH 3/9] add init command template files and add them to location abstractions --- FSharp.Formatting.sln | 60 ++++++++++-------- docs/templates/init/.index_md_template.md | 24 +++++++ .../init/.literate_sample_template.fsx | 32 ++++++++++ docs/templates/init/.logo.png | Bin 0 -> 6646 bytes src/fsdocs-tool/Options.fs | 43 ++++++++++++- src/fsdocs-tool/fsdocs-tool.fsproj | 3 + 6 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 docs/templates/init/.index_md_template.md create mode 100644 docs/templates/init/.literate_sample_template.fsx create mode 100644 docs/templates/init/.logo.png diff --git a/FSharp.Formatting.sln b/FSharp.Formatting.sln index 14dbe4c4f..3a8feb2b9 100644 --- a/FSharp.Formatting.sln +++ b/FSharp.Formatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29724.152 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 12.0.31101.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{194BD478-0DB5-44F3-A6C2-1FC75D3F3294}" ProjectSection(SolutionItems) = preProject @@ -20,7 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{194B EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{312E452A-1068-4804-89E7-0AFBAD5F885F}" ProjectSection(SolutionItems) = preProject - docs\_template.html = docs\_template.html docs\apidocs.fsx = docs\apidocs.fsx docs\codeformat.fsx = docs\codeformat.fsx docs\commandline.md = docs\commandline.md @@ -33,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{312E452A-1 docs\upgrade.md = docs\upgrade.md docs\users.md = docs\users.md docs\zero-to-hero.md = docs\zero-to-hero.md + docs\_template.html = docs\_template.html EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{D0550510-0DCE-4B40-B4FB-091668E1C5FD}" @@ -46,77 +46,77 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "reference", "reference", "{ misc\templates\reference\type.cshtml = misc\templates\reference\type.cshtml EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.Markdown", "src\FSharp.Formatting.Markdown\FSharp.Formatting.Markdown.fsproj", "{C44C1C05-599A-40DD-9590-465EAB8960C5}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.Markdown", "src\FSharp.Formatting.Markdown\FSharp.Formatting.Markdown.fsproj", "{C44C1C05-599A-40DD-9590-465EAB8960C5}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.CodeFormat", "src\FSharp.Formatting.CodeFormat\FSharp.Formatting.CodeFormat.fsproj", "{341EBF32-D470-4C55-99E9-55F14F7FFBB1}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.CodeFormat", "src\FSharp.Formatting.CodeFormat\FSharp.Formatting.CodeFormat.fsproj", "{341EBF32-D470-4C55-99E9-55F14F7FFBB1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.ApiDocs", "src\FSharp.Formatting.ApiDocs\FSharp.Formatting.ApiDocs.fsproj", "{BC4946BA-2724-4524-AC50-DFC49EE154A1}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.ApiDocs", "src\FSharp.Formatting.ApiDocs\FSharp.Formatting.ApiDocs.fsproj", "{BC4946BA-2724-4524-AC50-DFC49EE154A1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.Literate", "src\FSharp.Formatting.Literate\FSharp.Formatting.Literate.fsproj", "{65E6D541-0486-4383-B619-5CFC5D2BA2F0}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.Literate", "src\FSharp.Formatting.Literate\FSharp.Formatting.Literate.fsproj", "{65E6D541-0486-4383-B619-5CFC5D2BA2F0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Formatting.CSharpFormat", "src\FSharp.Formatting.CSharpFormat\FSharp.Formatting.CSharpFormat.csproj", "{9AB3650B-CC24-4404-A175-A573DA928475}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "fsdocs-tool", "src\fsdocs-tool\fsdocs-tool.fsproj", "{D30F7F2B-A4E3-4A07-A1BD-ED3EB21768F8}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsdocs-tool", "src\fsdocs-tool\fsdocs-tool.fsproj", "{D30F7F2B-A4E3-4A07-A1BD-ED3EB21768F8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8D44B659-E9F7-4CE4-B5DA-D37CDDCD2525}" ProjectSection(SolutionItems) = preProject tests\commonmark_spec.json = tests\commonmark_spec.json EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.CodeFormat.Tests", "tests\FSharp.CodeFormat.Tests\FSharp.CodeFormat.Tests.fsproj", "{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.CodeFormat.Tests", "tests\FSharp.CodeFormat.Tests\FSharp.CodeFormat.Tests.fsproj", "{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Literate.Tests", "tests\FSharp.Literate.Tests\FSharp.Literate.Tests.fsproj", "{C22A18AB-6C54-48B4-AAC5-892499E93D4D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Literate.Tests", "tests\FSharp.Literate.Tests\FSharp.Literate.Tests.fsproj", "{C22A18AB-6C54-48B4-AAC5-892499E93D4D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Markdown.Tests", "tests\FSharp.Markdown.Tests\FSharp.Markdown.Tests.fsproj", "{07DE4905-050C-4378-A039-F1EF7E1F309D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Markdown.Tests", "tests\FSharp.Markdown.Tests\FSharp.Markdown.Tests.fsproj", "{07DE4905-050C-4378-A039-F1EF7E1F309D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.ApiDocs.Tests", "tests\FSharp.ApiDocs.Tests\FSharp.ApiDocs.Tests.fsproj", "{D2EC3D6A-35C0-4445-A9CB-AA18B12B6350}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.ApiDocs.Tests", "tests\FSharp.ApiDocs.Tests\FSharp.ApiDocs.Tests.fsproj", "{D2EC3D6A-35C0-4445-A9CB-AA18B12B6350}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestProjects", "TestProjects", "{4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsLib1", "tests\FSharp.ApiDocs.Tests\files\FsLib1\FsLib1.fsproj", "{AD192375-D530-40FB-A4E9-380C74CBB771}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsLib1", "tests\FSharp.ApiDocs.Tests\files\FsLib1\FsLib1.fsproj", "{AD192375-D530-40FB-A4E9-380C74CBB771}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsLib2", "tests\FSharp.ApiDocs.Tests\files\FsLib2\FsLib2.fsproj", "{768FD0E0-5CF7-4AF0-98C9-4B848F9AFB62}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsLib2", "tests\FSharp.ApiDocs.Tests\files\FsLib2\FsLib2.fsproj", "{768FD0E0-5CF7-4AF0-98C9-4B848F9AFB62}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestLib1", "tests\FSharp.ApiDocs.Tests\files\TestLib1\TestLib1.fsproj", "{86326769-3D0B-423F-AD28-A194B34318D6}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestLib1", "tests\FSharp.ApiDocs.Tests\files\TestLib1\TestLib1.fsproj", "{86326769-3D0B-423F-AD28-A194B34318D6}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestLib2", "tests\FSharp.ApiDocs.Tests\files\TestLib2\TestLib2.fsproj", "{48EFFECF-ECB0-4DF3-A704-B56AB07557BF}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestLib2", "tests\FSharp.ApiDocs.Tests\files\TestLib2\TestLib2.fsproj", "{48EFFECF-ECB0-4DF3-A704-B56AB07557BF}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestLib3", "tests\FSharp.ApiDocs.Tests\files\TestLib3\TestLib3.fsproj", "{52B949AA-A3F7-4894-B713-804BAEB71118}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestLib3", "tests\FSharp.ApiDocs.Tests\files\TestLib3\TestLib3.fsproj", "{52B949AA-A3F7-4894-B713-804BAEB71118}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "csharpSupport", "tests\FSharp.ApiDocs.Tests\files\csharpSupport\csharpSupport.csproj", "{DA7BA2FA-447E-41F3-88D9-00CF3E052E2C}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "crefLib1", "tests\FSharp.ApiDocs.Tests\files\crefLib1\crefLib1.fsproj", "{A0C8DD00-BD08-48D6-B257-5A838E5DA819}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "crefLib1", "tests\FSharp.ApiDocs.Tests\files\crefLib1\crefLib1.fsproj", "{A0C8DD00-BD08-48D6-B257-5A838E5DA819}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "crefLib2", "tests\FSharp.ApiDocs.Tests\files\crefLib2\crefLib2.fsproj", "{55728B9D-1EDE-4A40-B439-1EB0B3F77B72}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "crefLib2", "tests\FSharp.ApiDocs.Tests\files\crefLib2\crefLib2.fsproj", "{55728B9D-1EDE-4A40-B439-1EB0B3F77B72}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "crefLib3", "tests\FSharp.ApiDocs.Tests\files\crefLib3\crefLib3.csproj", "{08029B28-A5EA-42DB-AB4E-9C6BA9EF9441}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "crefLib4", "tests\FSharp.ApiDocs.Tests\files\crefLib4\crefLib4.csproj", "{98624699-1B2F-4636-A3F7-EC72343CB2FD}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.Common", "src\FSharp.Formatting.Common\FSharp.Formatting.Common.fsproj", "{91BAD90E-BF3B-4646-A1A7-1568F8F25075}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.Common", "src\FSharp.Formatting.Common\FSharp.Formatting.Common.fsproj", "{91BAD90E-BF3B-4646-A1A7-1568F8F25075}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting.TestHelpers", "tests\FSharp.Formatting.TestHelpers\FSharp.Formatting.TestHelpers.fsproj", "{0B552F94-33FE-4037-9C17-1EB2A885F263}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting.TestHelpers", "tests\FSharp.Formatting.TestHelpers\FSharp.Formatting.TestHelpers.fsproj", "{0B552F94-33FE-4037-9C17-1EB2A885F263}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AttributesTestLib", "tests\FSharp.ApiDocs.Tests\files\AttributesTestLib\AttributesTestLib.fsproj", "{B266D118-15AE-4BE6-809E-E9E30CE5C62F}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AttributesTestLib", "tests\FSharp.ApiDocs.Tests\files\AttributesTestLib\AttributesTestLib.fsproj", "{B266D118-15AE-4BE6-809E-E9E30CE5C62F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4089E333-3857-4771-B209-5673EF4EEDA3}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Formatting", "src\FSharp.Formatting\FSharp.Formatting.fsproj", "{CB78F0EA-8005-4735-A02C-B86CEDC29D85}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Formatting", "src\FSharp.Formatting\FSharp.Formatting.fsproj", "{CB78F0EA-8005-4735-A02C-B86CEDC29D85}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sidebyside", "sidebyside", "{C3E359B5-DB2D-4AA4-A08C-77BAA0E94D21}" ProjectSection(SolutionItems) = preProject - docs\templates\leftside\_template.html = docs\templates\leftside\_template.html docs\sidebyside\sideextensions.md = docs\sidebyside\sideextensions.md docs\sidebyside\sidemarkdown.md = docs\sidebyside\sidemarkdown.md docs\sidebyside\sidescript.fsx = docs\sidebyside\sidescript.fsx + docs\templates\leftside\_template.html = docs\templates\leftside\_template.html EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{C7804F57-7FC6-4CF6-BDF6-127D6F9EBEA6}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "leftside", "leftside", "{188DC91F-2202-4495-ACD2-542D7C30364E}" ProjectSection(SolutionItems) = preProject - docs\templates\leftside\_template.html = docs\templates\leftside\_template.html docs\templates\leftside\styling.md = docs\templates\leftside\styling.md + docs\templates\leftside\_template.html = docs\templates\leftside\_template.html EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{FAD5C374-4748-4A3D-A435-FFA425916F3A}" @@ -127,6 +127,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{FAD5 docs\content\fsdocs-theme-toggle.js = docs\content\fsdocs-theme-toggle.js EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "init", "init", "{A70497A6-C9C3-46D8-A9FB-0E4BB6AD3309}" + ProjectSection(SolutionItems) = preProject + docs\templates\init\.index_md_template.md = docs\templates\init\.index_md_template.md + docs\templates\init\.literate_sample_template.fsx = docs\templates\init\.literate_sample_template.fsx + docs\templates\init\.logo.svg = docs\templates\init\.logo.svg + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -250,6 +257,7 @@ Global {768FD0E0-5CF7-4AF0-98C9-4B848F9AFB62} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} {86326769-3D0B-423F-AD28-A194B34318D6} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} {48EFFECF-ECB0-4DF3-A704-B56AB07557BF} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} + {52B949AA-A3F7-4894-B713-804BAEB71118} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} {DA7BA2FA-447E-41F3-88D9-00CF3E052E2C} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} {A0C8DD00-BD08-48D6-B257-5A838E5DA819} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} {55728B9D-1EDE-4A40-B439-1EB0B3F77B72} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} @@ -263,7 +271,7 @@ Global {C7804F57-7FC6-4CF6-BDF6-127D6F9EBEA6} = {312E452A-1068-4804-89E7-0AFBAD5F885F} {188DC91F-2202-4495-ACD2-542D7C30364E} = {C7804F57-7FC6-4CF6-BDF6-127D6F9EBEA6} {FAD5C374-4748-4A3D-A435-FFA425916F3A} = {312E452A-1068-4804-89E7-0AFBAD5F885F} - {52B949AA-A3F7-4894-B713-804BAEB71118} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} + {A70497A6-C9C3-46D8-A9FB-0E4BB6AD3309} = {C7804F57-7FC6-4CF6-BDF6-127D6F9EBEA6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {76F121F8-70E0-49FB-9ADF-C7B660C0EB67} diff --git a/docs/templates/init/.index_md_template.md b/docs/templates/init/.index_md_template.md new file mode 100644 index 000000000..0f369f310 --- /dev/null +++ b/docs/templates/init/.index_md_template.md @@ -0,0 +1,24 @@ +# Welcome to your documentation with fsdocs! + +For full guides please visit [the FSharp.Formatting](https://fsprojects.github.io/FSharp.Formatting/) documentation pages. + +As a quickstart you can start with changing this file with **any** _markdown_ `content` you like. + +Assuming you have initialized fsdocs with default settings, you can start the preview server with: + +``` +fsdocs watch +``` + +This will start a local server on port 8091, meaning you should be able to see content of this file rendered on [http://localhost:8901/](http://localhost:8901/) + +while you can write code blocks in markdown like this: + +```fsharp +let a = 42 +``` + +fsdocs supports a more powerful variant of fsharp scripts called [literate scripts](https://fsprojects.github.io/FSharp.Formatting/literate.html). + +in literate scripts, you can write markdown and fsharp code in the same file, and fsdocs will render the markdown and execute the fsharp code. +Check the `literate_sample.fsx` file in this folder for an example. \ No newline at end of file diff --git a/docs/templates/init/.literate_sample_template.fsx b/docs/templates/init/.literate_sample_template.fsx new file mode 100644 index 000000000..1ab3200f9 --- /dev/null +++ b/docs/templates/init/.literate_sample_template.fsx @@ -0,0 +1,32 @@ +(** +# Literate script example + +- A multi-line comment starting with (** and ending with *) is turned into text and is processed using the F# Markdown processor (which supports standard Markdown commands). + +- A single-line comment starting with (*** and ending with ***) is treated as a special command. The command can consist of key, key: value or key=value pairs. + +The rest is just plain F# code goodness: +*) + +let helloWorld () = printfn "Hello world!" + +(** +## Using fsi evaluation + +If you run fsdocs with the `--eval` flag, literate scripts will be evaluated by fsi and the output will can be included in the documentation using special commands such as + +`(*** include-value ***)` or `(*** include-it ***)` : + +*) + +// include a value by name via (*** include-value: name ***) +let numbers = [ 0..99 ] +(*** include-value: numbers ***) + +// include the fsi output of an expression via (*** include-it ***) +List.sum numbers +(*** include-it ***) + +(** +Literate scripts can move your documentation to the next level, because you can make sure that the code in your documentation is always up-to-date and shows results from the latest version. +*) diff --git a/docs/templates/init/.logo.png b/docs/templates/init/.logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4dbbd904051b76448189d386eb9a2f0c2d74c701 GIT binary patch literal 6646 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 qBexr Path.GetFullPath + member this.docs_templates = Path.Combine(this.docs, "templates") |> Path.GetFullPath + member this.docs_templates_init = Path.Combine(this.docs_templates, "init") |> Path.GetFullPath + member this.docs_img = Path.Combine(this.docs, "img") |> Path.GetFullPath member this.docs_content = Path.Combine(this.docs, "content") |> Path.GetFullPath - member this.docs_content_image = Path.Combine(this.docs_content, "img") |> Path.GetFullPath + member this.docs_content_img = Path.Combine(this.docs_content, "img") |> Path.GetFullPath // specific files in this folder structure that might need special treatment instead of just copy pasting member this.template_html = Path.Combine(this.docs, "_template.html") |> Path.GetFullPath member this.template_ipynb = Path.Combine(this.docs, "_template.ipynb") |> Path.GetFullPath member this.template_tex = Path.Combine(this.docs, "_template.tex") |> Path.GetFullPath + member this.dockerfile = Path.Combine(this.docs, "Dockerfile") |> Path.GetFullPath + member this.nuget_config = Path.Combine(this.docs, "Nuget.config") |> Path.GetFullPath + + // specific files for the init command + member this.logo_template = Path.Combine(this.docs_templates_init, ".logo.png") |> Path.GetFullPath + + member this.index_md_template = + Path.Combine(this.docs_templates_init, ".index_md_template.md") + |> Path.GetFullPath + + member this.literate_sample_template = + Path.Combine(this.docs_templates_init, ".literate_sample_template.fsx") + |> Path.GetFullPath /// /// returns true if all special files and folders of this location exist. @@ -72,11 +88,19 @@ module Common = member this.Exist() = try Directory.Exists(this.docs) + && Directory.Exists(this.docs_templates) + && Directory.Exists(this.docs_templates_init) + && Directory.Exists(this.docs_img) && Directory.Exists(this.docs_content) - && Directory.Exists(this.docs_content_image) + && Directory.Exists(this.docs_content_img) && File.Exists(this.template_html) && File.Exists(this.template_ipynb) && File.Exists(this.template_tex) + && File.Exists(this.dockerfile) + && File.Exists(this.nuget_config) + && File.Exists(this.logo_template) + && File.Exists(this.index_md_template) + && File.Exists(this.literate_sample_template) with _ -> false @@ -108,6 +132,16 @@ module Common = member this.template_html = Path.Combine(this.templates, "_template.html") |> Path.GetFullPath member this.template_ipynb = Path.Combine(this.templates, "_template.ipynb") |> Path.GetFullPath member this.template_tex = Path.Combine(this.templates, "_template.tex") |> Path.GetFullPath + member this.dockerfile = Path.Combine(this.extras, "Dockerfile") |> Path.GetFullPath + member this.nuget_config = Path.Combine(this.extras, "Nuget.config") |> Path.GetFullPath + + // specific files for the init command + member this.logo_template = Path.Combine(this.templates, ".logo.png") |> Path.GetFullPath + member this.index_md_template = Path.Combine(this.templates, ".index_md_template.md") |> Path.GetFullPath + + member this.literate_sample_template = + Path.Combine(this.templates, ".literate_sample_template.fsx") + |> Path.GetFullPath /// /// returns true if all special files and folders of this location exist. @@ -121,5 +155,10 @@ module Common = && File.Exists(this.template_html) && File.Exists(this.template_ipynb) && File.Exists(this.template_tex) + && File.Exists(this.dockerfile) + && File.Exists(this.nuget_config) + && File.Exists(this.logo_template) + && File.Exists(this.index_md_template) + && File.Exists(this.literate_sample_template) with _ -> false diff --git a/src/fsdocs-tool/fsdocs-tool.fsproj b/src/fsdocs-tool/fsdocs-tool.fsproj index 6634e6bd1..c0a48a519 100644 --- a/src/fsdocs-tool/fsdocs-tool.fsproj +++ b/src/fsdocs-tool/fsdocs-tool.fsproj @@ -28,6 +28,9 @@ + + + From 3024e00cc71fdadc1e7f72b3f0ed225ab561c5d9 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 20:17:17 +0100 Subject: [PATCH 4/9] add first basic implementation of the init command --- src/fsdocs-tool/InitCommand.fs | 71 +++++++++++++++++++++++++++++++++- src/fsdocs-tool/Program.fs | 3 +- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs index 621e5482d..ded857682 100644 --- a/src/fsdocs-tool/InitCommand.fs +++ b/src/fsdocs-tool/InitCommand.fs @@ -5,5 +5,72 @@ open CommandLine [] type InitCommand() = - class - end + + let dir = Path.GetDirectoryName(typeof.Assembly.Location) + + // get template locations for in-package and in-repo and decide which to use later + let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) + let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) + + [] + member val output: string = "docs" with get, set + + member this.Execute() = + + let outputPath = Path.GetFullPath(this.output) + let repoRoot = Path.GetFullPath(Path.Combine(outputPath, "..")) + let initLocations = Common.InRepoLocations(repoRoot) + + let ensureOutputDirs () = + [ outputPath; initLocations.docs; initLocations.docs_img ] + |> List.iter ensureDirectory + + if inPackageLocations.Exist() then + ensureOutputDirs () + + try + [ (inPackageLocations.template_html, initLocations.template_html) + (inPackageLocations.template_ipynb, initLocations.template_ipynb) + (inPackageLocations.template_tex, initLocations.template_tex) + (inPackageLocations.dockerfile, initLocations.dockerfile) + (inPackageLocations.nuget_config, initLocations.nuget_config) + (inPackageLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) + (inPackageLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) + (inPackageLocations.literate_sample_template, + Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] + |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + + 0 + with e as exn -> + printfn "Error: %s" exn.Message + 1 + + elif inRepoLocations.Exist() then + ensureOutputDirs () + + try + [ (inRepoLocations.template_html, initLocations.template_html) + (inRepoLocations.template_ipynb, initLocations.template_ipynb) + (inRepoLocations.template_tex, initLocations.template_tex) + (inRepoLocations.dockerfile, initLocations.dockerfile) + (inRepoLocations.nuget_config, initLocations.nuget_config) + (inRepoLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) + (inRepoLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) + (inRepoLocations.literate_sample_template, + Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] + |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + + 0 + with e as exn -> + printfn "Error: %s" exn.Message + 1 + else + printfn + "no sources for default files found from either %s or %s" + inPackageLocations.RelAssemblyPath + inRepoLocations.RelAssemblyPath + + 1 diff --git a/src/fsdocs-tool/Program.fs b/src/fsdocs-tool/Program.fs index be5df76fb..b023264c0 100644 --- a/src/fsdocs-tool/Program.fs +++ b/src/fsdocs-tool/Program.fs @@ -8,9 +8,10 @@ do () [] let main argv = CommandLine.Parser.Default - .ParseArguments(argv) + .ParseArguments(argv) .MapResult( (fun (opts: BuildCommand) -> opts.Execute()), (fun (opts: WatchCommand) -> opts.Execute()), + (fun (opts: InitCommand) -> opts.Execute()), (fun _ -> 1) ) From 7a4f227164493a58fb8eb9deb6643c53c56e16ae Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 20:17:30 +0100 Subject: [PATCH 5/9] typo fix in literate script sample --- docs/templates/init/.literate_sample_template.fsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/templates/init/.literate_sample_template.fsx b/docs/templates/init/.literate_sample_template.fsx index 1ab3200f9..373e7ef2f 100644 --- a/docs/templates/init/.literate_sample_template.fsx +++ b/docs/templates/init/.literate_sample_template.fsx @@ -1,9 +1,9 @@ (** # Literate script example -- A multi-line comment starting with (** and ending with *) is turned into text and is processed using the F# Markdown processor (which supports standard Markdown commands). +- A multi-line comment starting with (`**` and ending with `*`) is turned into text and is processed using the F# Markdown processor (which supports standard Markdown commands). -- A single-line comment starting with (*** and ending with ***) is treated as a special command. The command can consist of key, key: value or key=value pairs. +- A single-line comment starting with (`***` and ending with `***`) is treated as a special command. The command can consist of key, key: value or key=value pairs. The rest is just plain F# code goodness: *) From f5bd211e1bb272eeeacf5d54121605d355699a2d Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 18 Nov 2023 20:27:07 +0100 Subject: [PATCH 6/9] add cli success messages and comment init command code a little --- src/fsdocs-tool/InitCommand.fs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs index ded857682..6cfe312c9 100644 --- a/src/fsdocs-tool/InitCommand.fs +++ b/src/fsdocs-tool/InitCommand.fs @@ -8,7 +8,7 @@ type InitCommand() = let dir = Path.GetDirectoryName(typeof.Assembly.Location) - // get template locations for in-package and in-repo and decide which to use later + // get template locations for in-package and in-repo files and decide which to use later let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) @@ -29,6 +29,7 @@ type InitCommand() = |> List.iter ensureDirectory if inPackageLocations.Exist() then + // if the in-package locations exist, this means fsdocs is run from the nuget package. ensureOutputDirs () try @@ -37,18 +38,25 @@ type InitCommand() = (inPackageLocations.template_tex, initLocations.template_tex) (inPackageLocations.dockerfile, initLocations.dockerfile) (inPackageLocations.nuget_config, initLocations.nuget_config) + // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. (inPackageLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) (inPackageLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) (inPackageLocations.literate_sample_template, Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + printfn "" + printfn "a basic fsdocs scaffold has been created in %s." this.output + printfn "" + printfn "check it out by running 'dotnet fsdocs watch' !" + 0 - with e as exn -> + with _ as exn -> printfn "Error: %s" exn.Message 1 elif inRepoLocations.Exist() then + // if the in-repo locations exist, this means fsdocs is run from inside the FSharp.Formatting repo itself. ensureOutputDirs () try @@ -57,14 +65,20 @@ type InitCommand() = (inRepoLocations.template_tex, initLocations.template_tex) (inRepoLocations.dockerfile, initLocations.dockerfile) (inRepoLocations.nuget_config, initLocations.nuget_config) + // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. (inRepoLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) (inRepoLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) (inRepoLocations.literate_sample_template, Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + printfn "" + printfn "a basic fsdocs scaffold has been created in %s." this.output + printfn "" + printfn "check it out by running 'dotnet fsdocs watch' !" + 0 - with e as exn -> + with _ as exn -> printfn "Error: %s" exn.Message 1 else From e28ee792f88515257458739f81156cd26eeedbb8 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Tue, 28 Nov 2023 09:37:00 +0100 Subject: [PATCH 7/9] improve default location abstractions - more descriptive class names - member names now reflect paths exactly - add badge svg file paths - add location descriptions --- Directory.Packages.props | 1 + build.fsx | 26 ++- src/fsdocs-tool/BuildCommand.fs | 41 ++-- src/fsdocs-tool/InitCommand.fs | 94 ++++++---- src/fsdocs-tool/Options.fs | 291 +++++++++++++++++++++-------- src/fsdocs-tool/fsdocs-tool.fsproj | 8 +- 6 files changed, 313 insertions(+), 148 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c4b67d266..fdabf4ece 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,6 +16,7 @@ + diff --git a/build.fsx b/build.fsx index 6706d59d7..a9866d70a 100644 --- a/build.fsx +++ b/build.fsx @@ -50,9 +50,13 @@ let testStage = $"dotnet test {solutionFile} --configuration {configuration} --no-build --blame --logger trx --results-directory TestResults -tl" } -pipeline "CI" { - lintStage +let buildStage = + stage "Build" { + run $"dotnet restore {solutionFile} -tl" + run $"dotnet build {solutionFile} --configuration {configuration} -tl" + } +let cleanStage = stage "Clean" { run (fun _ -> !!artifactsDir ++ "temp" |> Shell.cleanDirs @@ -60,13 +64,14 @@ pipeline "CI" { [ "bin"; "temp"; "tests/bin" ] |> Seq.iter Directory.ensure) } - stage "Build" { - run $"dotnet restore {solutionFile} -tl" - run $"dotnet build {solutionFile} --configuration {configuration} -tl" - } - +let nugetStage = stage "NuGet" { run $"dotnet pack {solutionFile} --output \"{artifactsDir}\" --configuration {configuration} -tl" } +pipeline "CI" { + lintStage + cleanStage + buildStage + nugetStage testStage stage "GenerateDocs" { @@ -93,4 +98,11 @@ pipeline "Verify" { runIfOnlySpecified true } +pipeline "BuildAndPack" { + cleanStage + buildStage + nugetStage + runIfOnlySpecified true +} + tryPrintPipelineCommandHelp () diff --git a/src/fsdocs-tool/BuildCommand.fs b/src/fsdocs-tool/BuildCommand.fs index 33f9a94b8..e94790aa6 100644 --- a/src/fsdocs-tool/BuildCommand.fs +++ b/src/fsdocs-tool/BuildCommand.fs @@ -2,6 +2,7 @@ namespace fsdocs open System.Collections.Concurrent open CommandLine +open Spectre.Console open System open System.Diagnostics @@ -1580,16 +1581,16 @@ type CoreBuildOptions(watch) = let dir = Path.GetDirectoryName(typeof.Assembly.Location) // get template locations for in-package and in-repo and decide which to use later - let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) - let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) + let inNugetPackageLocations = Common.InNugetPackageLocations(Path.Combine(dir, "..", "..", "..")) + let inThisRepoLocations = Common.InDocsFolderLocations(Path.Combine(dir, "..", "..", "..", "..", "..", "docs")) let defaultTemplate = if this.nodefaultcontent then None - else if inPackageLocations.Exist() then - Some inPackageLocations.template_html - elif inRepoLocations.Exist() then - Some inRepoLocations.template_html + else if inNugetPackageLocations.AllLocationsExist() then + Some inNugetPackageLocations.``templates/template.html``.Path + elif inThisRepoLocations.AllLocationsExist() then + Some inThisRepoLocations.``template.html``.Path else None @@ -1598,22 +1599,22 @@ type CoreBuildOptions(watch) = // The "extras" content goes in "." // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any // to .nuget\packages\fsdocs-tool\7.1.7\extras - if inPackageLocations.Exist() then - printfn "using extra content from %s" inPackageLocations.extras - (inPackageLocations.extras, ".") + if inNugetPackageLocations.AllLocationsExist() then + printfn "using extra content from %s" inNugetPackageLocations.extras.Path + (inNugetPackageLocations.extras.Path, ".") else if // This is for in-repo use only, assuming we are executing directly from // src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe // src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe - inRepoLocations.Exist() + inThisRepoLocations.AllLocationsExist() then - printfn "using extra content from %s" inRepoLocations.docs_content - (inRepoLocations.docs_content, "content") + printfn "using extra content from %s" inThisRepoLocations.content.Path + (inThisRepoLocations.content.Path, "content") else printfn "no extra content found at %s or %s" - inPackageLocations.extras - inRepoLocations.docs_content ] + inNugetPackageLocations.extras.Path + inThisRepoLocations.content.Path ] // The incremental state (as well as the files written to disk) let mutable latestApiDocModel = None @@ -1671,12 +1672,12 @@ type CoreBuildOptions(watch) = templateFiles d - OutputKind.Html, Some d - | None -> - printfn - "note, no template file '%s' found, and no default template at '%s'" - templateFiles - inRepoLocations.template_html + OutputKind.Html, Some d + | None -> + printfn + "note, no template file '%s' found, and no default template at '%s'" + templateFiles + inThisRepoLocations.``template.html``.Path OutputKind.Html, None diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs index 6cfe312c9..8a926a727 100644 --- a/src/fsdocs-tool/InitCommand.fs +++ b/src/fsdocs-tool/InitCommand.fs @@ -3,14 +3,16 @@ namespace fsdocs open System.IO open CommandLine +open Spectre.Console + [] type InitCommand() = let dir = Path.GetDirectoryName(typeof.Assembly.Location) // get template locations for in-package and in-repo files and decide which to use later - let inPackageLocations = Common.InPackageLocations(Path.Combine(dir, "..", "..", "..")) - let inRepoLocations = Common.InRepoLocations(Path.Combine(dir, "..", "..", "..", "..", "..")) + let inNugetPackageLocations = Common.InNugetPackageLocations(Path.Combine(dir, "..", "..", "..")) + let inThisRepoLocations = Common.InDocsFolderLocations(Path.Combine(dir, "..", "..", "..", "..", "..", "docs")) [] member val output: string = "docs" with get, set + [] + member val force: bool = false with get, set + member this.Execute() = - let outputPath = Path.GetFullPath(this.output) - let repoRoot = Path.GetFullPath(Path.Combine(outputPath, "..")) - let initLocations = Common.InRepoLocations(repoRoot) + let docsOutputPath = Path.GetFullPath(this.output) + let initLocations = Common.InDocsFolderLocations(docsOutputPath) let ensureOutputDirs () = - [ outputPath; initLocations.docs; initLocations.docs_img ] + [ docsOutputPath; initLocations.DocsFolder.Path; initLocations.img.Path ] |> List.iter ensureDirectory - if inPackageLocations.Exist() then + if inNugetPackageLocations.AllLocationsExist() then // if the in-package locations exist, this means fsdocs is run from the nuget package. - ensureOutputDirs () - try - [ (inPackageLocations.template_html, initLocations.template_html) - (inPackageLocations.template_ipynb, initLocations.template_ipynb) - (inPackageLocations.template_tex, initLocations.template_tex) - (inPackageLocations.dockerfile, initLocations.dockerfile) - (inPackageLocations.nuget_config, initLocations.nuget_config) - // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. - (inPackageLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) - (inPackageLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) - (inPackageLocations.literate_sample_template, - Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] - |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + ensureOutputDirs () + + let fileMap = + [ inNugetPackageLocations.``templates/template.html``, initLocations.``template.html``.Path + inNugetPackageLocations.``templates/template.ipynb``, initLocations.``template.ipynb``.Path + inNugetPackageLocations.``templates/template.tex``, initLocations.``template.tex``.Path + inNugetPackageLocations.Dockerfile, initLocations.Dockerfile.Path + inNugetPackageLocations.``Nuget.config``, initLocations.``Nuget.config``.Path + inNugetPackageLocations.``extras/content/img/badge-binder.svg``, initLocations.``img/badge-binder.svg``.Path + inNugetPackageLocations.``extras/content/img/badge-notebook.svg``, initLocations.``img/badge-notebook.svg``.Path + inNugetPackageLocations.``extras/content/img/badge-script.svg``, initLocations.``img/badge-script.svg``.Path + // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. + inNugetPackageLocations.``templates/init/.logo.png``, + Path.GetFullPath(Path.Combine(initLocations.img.Path, "logo.png")) + inNugetPackageLocations.``templates/init/.index_md_template.md``, + Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "index.md")) + inNugetPackageLocations.``templates/init/.literate_sample_template.fsx``, + Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "literate_sample.fsx")) ] + + fileMap |> List.iter (fun (src, dst) -> File.Copy(src.Path, dst, this.force)) printfn "" printfn "a basic fsdocs scaffold has been created in %s." this.output @@ -55,22 +69,32 @@ type InitCommand() = printfn "Error: %s" exn.Message 1 - elif inRepoLocations.Exist() then + elif inThisRepoLocations.AllLocationsExist() then // if the in-repo locations exist, this means fsdocs is run from inside the FSharp.Formatting repo itself. - ensureOutputDirs () try - [ (inRepoLocations.template_html, initLocations.template_html) - (inRepoLocations.template_ipynb, initLocations.template_ipynb) - (inRepoLocations.template_tex, initLocations.template_tex) - (inRepoLocations.dockerfile, initLocations.dockerfile) - (inRepoLocations.nuget_config, initLocations.nuget_config) - // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. - (inRepoLocations.logo_template, Path.GetFullPath(Path.Combine(initLocations.docs_img, "logo.png"))) - (inRepoLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) - (inRepoLocations.literate_sample_template, - Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] - |> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) + ensureOutputDirs () + + let fileMap = + [ (inThisRepoLocations.``template.html``, initLocations.``template.html``.Path) + (inThisRepoLocations.``template.ipynb``, initLocations.``template.ipynb``.Path) + (inThisRepoLocations.``template.tex``, initLocations.``template.tex``.Path) + (inThisRepoLocations.Dockerfile, initLocations.Dockerfile.Path) + (inThisRepoLocations.``Nuget.config``, initLocations.``Nuget.config``.Path) + (inThisRepoLocations.``img/badge-binder.svg``, initLocations.``img/badge-binder.svg``.Path) + (inThisRepoLocations.``img/badge-notebook.svg``, initLocations.``img/badge-notebook.svg``.Path) + (inThisRepoLocations.``img/badge-script.svg``, initLocations.``img/badge-script.svg``.Path) + // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. + (inThisRepoLocations.``templates/init/.logo.png``, + Path.GetFullPath(Path.Combine(initLocations.img.Path, "logo.png"))) + (inThisRepoLocations.``templates/init/.index_md_template.md``, + Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "index.md"))) + (inThisRepoLocations.``templates/init/.literate_sample_template.fsx``, + Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "literate_sample.fsx"))) ] + + fileMap + // |> List.map (fun (src, dst) -> ) + |> List.iter (fun (src, dst) -> File.Copy(src.Path, dst, this.force)) printfn "" printfn "a basic fsdocs scaffold has been created in %s." this.output @@ -84,7 +108,7 @@ type InitCommand() = else printfn "no sources for default files found from either %s or %s" - inPackageLocations.RelAssemblyPath - inRepoLocations.RelAssemblyPath + inNugetPackageLocations.NugetPackageRootPath.Path + inThisRepoLocations.DocsFolder.Path 1 diff --git a/src/fsdocs-tool/Options.fs b/src/fsdocs-tool/Options.fs index 57afd1303..15ff7fc62 100644 --- a/src/fsdocs-tool/Options.fs +++ b/src/fsdocs-tool/Options.fs @@ -37,128 +37,253 @@ module Common = open System.IO + [] + module DefaultLocationDescriptions = + + //folders + [] + let ``docs folder`` = "the path to the folder that contains the inputs (documentation) for fsdocs." + + let ``nuget package root path`` = "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." + + [] + let ``templates`` = "contains additional default files (e.g., default files for the `init` command)" + + [] + let ``extras`` = "contains additional default files (e.g., default files for the `init` command)" + + [] + let ``templates/init`` = "contains the default files for the init command." + + [] + let ``img`` = "base folder to contain all images for your documentation" + + [] + let ``content`` = "contains additional content (e.g., custom css themes)" + + // files in the docs folder + [] + let ``_template.html`` = "description here" + + [] + let ``_template.ipynb`` = "description here" + + [] + let ``_template.tex`` = "description here" + + [] + let ``Dockerfile`` = "description here" + + [] + let ``Nuget.config`` = "description here" + + [] + let ``img/badge-binder.svg`` = "description here" + + [] + let ``img/badge-notebook.svg`` = "description here" + + [] + let ``img/badge-script.svg`` = "description here" + + [] + let ``img/logo.png`` = "description here" + + // specific files for the init command + [] + let ``templates/init/.logo.png`` = "description here" + + [] + let ``templates/init/.index_md_template.md`` = "description here" + + [] + let ``templates/init/.literate_sample_template.fsx`` = "description here" + + type AnnotatedPath = + { Path: string + Description: string } + + static member Combine(ap: AnnotatedPath, path, ?description) = + { Path = Path.Combine(ap.Path, path) |> Path.GetFullPath + Description = defaultArg description "" } + /// - /// a set of default locations in this repo. - /// these files are to be used in 2 scenarios assuming we are executing directly from + /// A set of default locations in a folder containing documentation inputs for fsdocs. /// - /// src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe + /// When the fsdocs tool binary is called directly via /// - /// src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe: + /// `src\fsdocs-tool\bin\Debug\net6.0\fsdocs.exe` or `src\fsdocs-tool\bin\Release\net6.0\fsdocs.exe`, /// - /// - as default styles when running watch or build when there are no user equivalents present and `nodefaultcontent` is not set to true + /// these locations can also be used /// - /// - as content of the output of the `init` command to initialize a default docs folder structure. + /// - as default content for the `watch` and `build` commands when no user equivalents present and `nodefaultcontent` is not set to true. This can be achieved by using the relative assembly path (plus "/docs") of the command classes as `docsFolderPath`. /// - /// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. + /// - as output paths of the `init` command to initialize a default docs folder structure. + /// + /// because the paths will exist relative to the FSharp.Formatting repo root path. /// - type InRepoLocations(relAssemblyPath) = + type InDocsFolderLocations(docsFolderPath) = - // relAssemblyPath : relative path from assemly to repo root path - member _.RelAssemblyPath = relAssemblyPath + // DocsFolderPath : the path to the docs folder which is used as the base path to construct the other paths. + // note that this folder is not necessarily named "docs", it can be any location that is used as the base folder containing inputs for fsdocs. + member _.DocsFolder = + { Path = docsFolderPath + Description = DefaultLocationDescriptions.``docs folder`` } - // default folder locations relative to the assembly path - member this.docs = Path.Combine(this.RelAssemblyPath, "docs") |> Path.GetFullPath - member this.docs_templates = Path.Combine(this.docs, "templates") |> Path.GetFullPath - member this.docs_templates_init = Path.Combine(this.docs_templates, "init") |> Path.GetFullPath - member this.docs_img = Path.Combine(this.docs, "img") |> Path.GetFullPath - member this.docs_content = Path.Combine(this.docs, "content") |> Path.GetFullPath - member this.docs_content_img = Path.Combine(this.docs_content, "img") |> Path.GetFullPath + // default folder locations based on the docs folder path + member this.templates = + AnnotatedPath.Combine(this.DocsFolder, "templates", DefaultLocationDescriptions.``templates``) - // specific files in this folder structure that might need special treatment instead of just copy pasting - member this.template_html = Path.Combine(this.docs, "_template.html") |> Path.GetFullPath - member this.template_ipynb = Path.Combine(this.docs, "_template.ipynb") |> Path.GetFullPath - member this.template_tex = Path.Combine(this.docs, "_template.tex") |> Path.GetFullPath - member this.dockerfile = Path.Combine(this.docs, "Dockerfile") |> Path.GetFullPath - member this.nuget_config = Path.Combine(this.docs, "Nuget.config") |> Path.GetFullPath + member this.``templates/init`` = + AnnotatedPath.Combine(this.templates, "init", DefaultLocationDescriptions.``templates/init``) - // specific files for the init command - member this.logo_template = Path.Combine(this.docs_templates_init, ".logo.png") |> Path.GetFullPath + member this.content = AnnotatedPath.Combine(this.DocsFolder, "content", DefaultLocationDescriptions.content) + member this.img = AnnotatedPath.Combine(this.DocsFolder, "img", DefaultLocationDescriptions.``img``) + + // specific files in the docs folder. + member this.``template.html`` = + AnnotatedPath.Combine(this.DocsFolder, "_template.html", DefaultLocationDescriptions.``_template.html``) + + member this.``template.ipynb`` = + AnnotatedPath.Combine(this.DocsFolder, "_template.ipynb", DefaultLocationDescriptions.``_template.ipynb``) + + member this.``template.tex`` = + AnnotatedPath.Combine(this.DocsFolder, "_template.tex", DefaultLocationDescriptions.``_template.tex``) - member this.index_md_template = - Path.Combine(this.docs_templates_init, ".index_md_template.md") - |> Path.GetFullPath + member this.Dockerfile = + AnnotatedPath.Combine(this.DocsFolder, "Dockerfile", DefaultLocationDescriptions.Dockerfile) - member this.literate_sample_template = - Path.Combine(this.docs_templates_init, ".literate_sample_template.fsx") - |> Path.GetFullPath + member this.``Nuget.config`` = + AnnotatedPath.Combine(this.DocsFolder, "Nuget.config", DefaultLocationDescriptions.``Nuget.config``) + + member this.``img/badge-binder.svg`` = + AnnotatedPath.Combine(this.img, "badge-binder.svg", DefaultLocationDescriptions.``img/badge-binder.svg``) + + member this.``img/badge-notebook.svg`` = + AnnotatedPath.Combine( + this.img, + "badge-notebook.svg", + DefaultLocationDescriptions.``img/badge-notebook.svg`` + ) + + member this.``img/badge-script.svg`` = + AnnotatedPath.Combine(this.img, "badge-script.svg", DefaultLocationDescriptions.``img/badge-script.svg``) + + // specific files for the init command. Note that these typically only exist in the FSharp.Formatting repo because they are to be copied and renamed on running `fsdocs init``` + member this.``templates/init/.logo.png`` = + AnnotatedPath.Combine( + this.``templates/init``, + ".logo.png", + DefaultLocationDescriptions.``templates/init/.logo.png`` + ) + + member this.``templates/init/.index_md_template.md`` = + AnnotatedPath.Combine( + this.``templates/init``, + ".index_md_template.md", + DefaultLocationDescriptions.``templates/init/.index_md_template.md`` + ) + + member this.``templates/init/.literate_sample_template.fsx`` = + AnnotatedPath.Combine( + this.``templates/init``, + ".literate_sample_template.fsx", + DefaultLocationDescriptions.``templates/init/.literate_sample_template.fsx`` + ) /// - /// returns true if all special files and folders of this location exist. + /// returns true if all files and folders of this location exist. /// - member this.Exist() = + member this.AllLocationsExist() = try - Directory.Exists(this.docs) - && Directory.Exists(this.docs_templates) - && Directory.Exists(this.docs_templates_init) - && Directory.Exists(this.docs_img) - && Directory.Exists(this.docs_content) - && Directory.Exists(this.docs_content_img) - && File.Exists(this.template_html) - && File.Exists(this.template_ipynb) - && File.Exists(this.template_tex) - && File.Exists(this.dockerfile) - && File.Exists(this.nuget_config) - && File.Exists(this.logo_template) - && File.Exists(this.index_md_template) - && File.Exists(this.literate_sample_template) + Directory.Exists(this.DocsFolder.Path) + && Directory.Exists(this.templates.Path) + && Directory.Exists(this.``templates/init``.Path) + && Directory.Exists(this.content.Path) + && Directory.Exists(this.img.Path) + && File.Exists(this.``template.html``.Path) + && File.Exists(this.``template.ipynb``.Path) + && File.Exists(this.``template.tex``.Path) + && File.Exists(this.Dockerfile.Path) + && File.Exists(this.``img/badge-binder.svg``.Path) + && File.Exists(this.``img/badge-notebook.svg``.Path) + && File.Exists(this.``img/badge-script.svg``.Path) + && File.Exists(this.``templates/init/.logo.png``.Path) + && File.Exists(this.``templates/init/.index_md_template.md``.Path) + && File.Exists(this.``templates/init/.literate_sample_template.fsx``.Path) with _ -> false /// /// a set of default locations in the nuget package created for fsdocs-tool. - /// these files are to be used in 2 scenarios assuming the tool is invoked via cli: + /// these files are to be used when fsdocs is run as dotnet tool installed via `dotnet tool install` in the following scenarios: /// - /// - as default styles when running watch or build when there are no user equivalents present and `nodefaultcontent` is not set to true + /// - as default files when running watch or build when there are no user equivalents present and `nodefaultcontent` is not set to true /// /// - as content of the output of the `init` command to initialize a default docs folder structure. /// /// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. /// - type InPackageLocations(relAssemblyPath) = - - // relAssemblyPath : relative path from assemly to package root path - member _.RelAssemblyPath = relAssemblyPath + type InNugetPackageLocations(nugetPackageRootPath) = - // From .nuget\packages\fsdocs-tool\7.1.7\tools\net6.0\any - // to .nuget\packages\fsdocs-tool\7.1.7\* + // PackageRootPath : the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`. + // for example, default on windows would be: ~\.nuget\packages\fsdocs-tool\20.0.0-alpha-010 + member _.NugetPackageRootPath = + { + Path = nugetPackageRootPath + Description = "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." + } - // default folder locations relative to the assembly path - member this.templates = Path.Combine(this.RelAssemblyPath, "templates") |> Path.GetFullPath - member this.extras = Path.Combine(this.RelAssemblyPath, "extras") |> Path.GetFullPath - member this.extras_content = Path.Combine(this.extras, "content") |> Path.GetFullPath - member this.extras_content_img = Path.Combine(this.extras_content, "img") |> Path.GetFullPath + // default folder locations relative to the package root path + member this.templates = AnnotatedPath.Combine(this.NugetPackageRootPath, "templates", DefaultLocationDescriptions.templates) + member this.``templates/init`` = AnnotatedPath.Combine(this.templates, "init", DefaultLocationDescriptions.templates) + member this.extras = AnnotatedPath.Combine(this.NugetPackageRootPath, "extras") + member this.``extras/content`` = AnnotatedPath.Combine(this.extras, "content") + member this.``extras/content/img`` = AnnotatedPath.Combine(this.``extras/content``, "img") // specific files in this folder structure that might need special treatment instead of just copy pasting - member this.template_html = Path.Combine(this.templates, "_template.html") |> Path.GetFullPath - member this.template_ipynb = Path.Combine(this.templates, "_template.ipynb") |> Path.GetFullPath - member this.template_tex = Path.Combine(this.templates, "_template.tex") |> Path.GetFullPath - member this.dockerfile = Path.Combine(this.extras, "Dockerfile") |> Path.GetFullPath - member this.nuget_config = Path.Combine(this.extras, "Nuget.config") |> Path.GetFullPath + member this.``templates/template.html`` = AnnotatedPath.Combine(this.templates, "_template.html") + member this.``templates/template.ipynb`` = AnnotatedPath.Combine(this.templates, "_template.ipynb") + member this.``templates/template.tex`` = AnnotatedPath.Combine(this.templates, "_template.tex") + member this.Dockerfile = AnnotatedPath.Combine(this.extras, "Dockerfile") + member this.``Nuget.config`` = AnnotatedPath.Combine(this.extras, "Nuget.config") + + member this.``extras/content/img/badge-binder.svg`` = + AnnotatedPath.Combine(this.``extras/content/img``, "badge-binder.svg", DefaultLocationDescriptions.``img/badge-binder.svg``) + + member this.``extras/content/img/badge-notebook.svg`` = + AnnotatedPath.Combine( + this.``extras/content/img``, + "badge-notebook.svg", + DefaultLocationDescriptions.``img/badge-notebook.svg`` + ) + member this.``extras/content/img/badge-script.svg`` = + AnnotatedPath.Combine(this.``extras/content/img``, "badge-script.svg", DefaultLocationDescriptions.``img/badge-script.svg``) // specific files for the init command - member this.logo_template = Path.Combine(this.templates, ".logo.png") |> Path.GetFullPath - member this.index_md_template = Path.Combine(this.templates, ".index_md_template.md") |> Path.GetFullPath + member this.``templates/init/.logo.png`` = AnnotatedPath.Combine(this.``templates/init``, ".logo.png") + member this.``templates/init/.index_md_template.md`` = AnnotatedPath.Combine(this.``templates/init``, ".index_md_template.md") - member this.literate_sample_template = - Path.Combine(this.templates, ".literate_sample_template.fsx") - |> Path.GetFullPath + member this.``templates/init/.literate_sample_template.fsx`` = AnnotatedPath.Combine(this.``templates/init``, ".literate_sample_template.fsx") /// /// returns true if all special files and folders of this location exist. /// - member this.Exist() = + member this.AllLocationsExist() = try - Directory.Exists(this.templates) - && Directory.Exists(this.extras) - && Directory.Exists(this.extras_content) - && Directory.Exists(this.extras_content_img) - && File.Exists(this.template_html) - && File.Exists(this.template_ipynb) - && File.Exists(this.template_tex) - && File.Exists(this.dockerfile) - && File.Exists(this.nuget_config) - && File.Exists(this.logo_template) - && File.Exists(this.index_md_template) - && File.Exists(this.literate_sample_template) + Directory.Exists(this.templates.Path) + && Directory.Exists(this.extras.Path) + && Directory.Exists(this.``extras/content``.Path) + && Directory.Exists(this.``extras/content/img``.Path) + && File.Exists(this.``templates/template.html``.Path) + && File.Exists(this.``templates/template.ipynb``.Path) + && File.Exists(this.``templates/template.tex``.Path) + && File.Exists(this.Dockerfile.Path) + && File.Exists(this.``extras/content/img/badge-binder.svg``.Path) + && File.Exists(this.``extras/content/img/badge-notebook.svg``.Path) + && File.Exists(this.``extras/content/img/badge-script.svg``.Path) + && File.Exists(this.``templates/init/.logo.png``.Path) + && File.Exists(this.``templates/init/.index_md_template.md``.Path) + && File.Exists(this.``templates/init/.literate_sample_template.fsx``.Path) with _ -> false diff --git a/src/fsdocs-tool/fsdocs-tool.fsproj b/src/fsdocs-tool/fsdocs-tool.fsproj index c0a48a519..6e2e044af 100644 --- a/src/fsdocs-tool/fsdocs-tool.fsproj +++ b/src/fsdocs-tool/fsdocs-tool.fsproj @@ -28,13 +28,14 @@ - - - + + + + @@ -50,6 +51,7 @@ + \ No newline at end of file From 01a5567892288b73c7bb4e7bf8c1f12ba97d4436 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Tue, 28 Nov 2023 10:15:53 +0100 Subject: [PATCH 8/9] Add basic interactivity for fsdocs init --- src/fsdocs-tool/InitCommand.fs | 15 ++++-- src/fsdocs-tool/Options.fs | 92 +++++++++++++++++++++++++--------- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs index 8a926a727..11cece59c 100644 --- a/src/fsdocs-tool/InitCommand.fs +++ b/src/fsdocs-tool/InitCommand.fs @@ -46,9 +46,12 @@ type InitCommand() = inNugetPackageLocations.``templates/template.tex``, initLocations.``template.tex``.Path inNugetPackageLocations.Dockerfile, initLocations.Dockerfile.Path inNugetPackageLocations.``Nuget.config``, initLocations.``Nuget.config``.Path - inNugetPackageLocations.``extras/content/img/badge-binder.svg``, initLocations.``img/badge-binder.svg``.Path - inNugetPackageLocations.``extras/content/img/badge-notebook.svg``, initLocations.``img/badge-notebook.svg``.Path - inNugetPackageLocations.``extras/content/img/badge-script.svg``, initLocations.``img/badge-script.svg``.Path + inNugetPackageLocations.``extras/content/img/badge-binder.svg``, + initLocations.``img/badge-binder.svg``.Path + inNugetPackageLocations.``extras/content/img/badge-notebook.svg``, + initLocations.``img/badge-notebook.svg``.Path + inNugetPackageLocations.``extras/content/img/badge-script.svg``, + initLocations.``img/badge-script.svg``.Path // these files must be renamed, because files prefixed with a dot are otherwise ignored by fsdocs. We want this in the source repo, but not in the output of this command. inNugetPackageLocations.``templates/init/.logo.png``, Path.GetFullPath(Path.Combine(initLocations.img.Path, "logo.png")) @@ -93,8 +96,10 @@ type InitCommand() = Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "literate_sample.fsx"))) ] fileMap - // |> List.map (fun (src, dst) -> ) - |> List.iter (fun (src, dst) -> File.Copy(src.Path, dst, this.force)) + |> List.map (fun (src, dst) -> (src, dst, Common.CLI.confirmFileCreation dst src.Description)) + |> List.iter (fun (src, dst, copy) -> + if copy then + File.Copy(src.Path, dst, this.force)) printfn "" printfn "a basic fsdocs scaffold has been created in %s." this.output diff --git a/src/fsdocs-tool/Options.fs b/src/fsdocs-tool/Options.fs index 15ff7fc62..cba19c5ed 100644 --- a/src/fsdocs-tool/Options.fs +++ b/src/fsdocs-tool/Options.fs @@ -44,7 +44,8 @@ module Common = [] let ``docs folder`` = "the path to the folder that contains the inputs (documentation) for fsdocs." - let ``nuget package root path`` = "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." + let ``nuget package root path`` = + "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." [] let ``templates`` = "contains additional default files (e.g., default files for the `init` command)" @@ -63,41 +64,49 @@ module Common = // files in the docs folder [] - let ``_template.html`` = "description here" + let ``_template.html`` = + "The root html template used for creating web pages. Documentation pages will all be based on this file with substitutions. If you do not want to customize this file, it is recommended to NOT include it in your docs folder and therefore use the default file that comes with the tool." [] - let ``_template.ipynb`` = "description here" + let ``_template.ipynb`` = + "The root ipynb template used for creating notebooks. Notebooks of your documentation pages will all be based on this file with substitutions. If you do not want to customize this file, it is recommended to NOT include it in your docs folder and therefore use the default file that comes with the tool." [] - let ``_template.tex`` = "description here" + let ``_template.tex`` = + "The root tex template used for creating LaTeX. LaTeX versions of your documentation pages will all be based on this file with substitutions. If you do not want to customize this file, it is recommended to NOT include it in your docs folder and therefore use the default file that comes with the tool." [] - let ``Dockerfile`` = "description here" + let ``Dockerfile`` = + "Dockerfile used for setting up a binder instance that can host the generated notebooks. Include this file if you plan to provide binder links to generated notebooks." [] - let ``Nuget.config`` = "description here" + let ``Nuget.config`` = + "Additional nuget sources used for setting up a binder instance that can host the generated notebooks. Include this file if you plan to provide binder links to generated notebooks." [] - let ``img/badge-binder.svg`` = "description here" + let ``img/badge-binder.svg`` = "A badge that can be used for adding pretty link buttons to binder." [] - let ``img/badge-notebook.svg`` = "description here" + let ``img/badge-notebook.svg`` = + "A badge that can be used for adding pretty download link buttons for generated notebooks." [] - let ``img/badge-script.svg`` = "description here" + let ``img/badge-script.svg`` = "A badge that can be used for adding pretty download link buttons for scripts." [] - let ``img/logo.png`` = "description here" + let ``img/logo.png`` = "The logo of the project." // specific files for the init command [] - let ``templates/init/.logo.png`` = "description here" + let ``templates/init/.logo.png`` = "A logo placeholder for better preview of how pages will look with a logo." [] - let ``templates/init/.index_md_template.md`` = "description here" + let ``templates/init/.index_md_template.md`` = + "A basic landing page markdown template that showcases how markdown files will be rendered." [] - let ``templates/init/.literate_sample_template.fsx`` = "description here" + let ``templates/init/.literate_sample_template.fsx`` = + "A basic literate script that showcases how literate scripts will be rendered." type AnnotatedPath = { Path: string @@ -229,14 +238,17 @@ module Common = // PackageRootPath : the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`. // for example, default on windows would be: ~\.nuget\packages\fsdocs-tool\20.0.0-alpha-010 member _.NugetPackageRootPath = - { - Path = nugetPackageRootPath - Description = "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." - } + { Path = nugetPackageRootPath + Description = + "the root path of the nuget package, e.g. when the tool is installed via `dotnet tool install`." } // default folder locations relative to the package root path - member this.templates = AnnotatedPath.Combine(this.NugetPackageRootPath, "templates", DefaultLocationDescriptions.templates) - member this.``templates/init`` = AnnotatedPath.Combine(this.templates, "init", DefaultLocationDescriptions.templates) + member this.templates = + AnnotatedPath.Combine(this.NugetPackageRootPath, "templates", DefaultLocationDescriptions.templates) + + member this.``templates/init`` = + AnnotatedPath.Combine(this.templates, "init", DefaultLocationDescriptions.templates) + member this.extras = AnnotatedPath.Combine(this.NugetPackageRootPath, "extras") member this.``extras/content`` = AnnotatedPath.Combine(this.extras, "content") member this.``extras/content/img`` = AnnotatedPath.Combine(this.``extras/content``, "img") @@ -249,7 +261,11 @@ module Common = member this.``Nuget.config`` = AnnotatedPath.Combine(this.extras, "Nuget.config") member this.``extras/content/img/badge-binder.svg`` = - AnnotatedPath.Combine(this.``extras/content/img``, "badge-binder.svg", DefaultLocationDescriptions.``img/badge-binder.svg``) + AnnotatedPath.Combine( + this.``extras/content/img``, + "badge-binder.svg", + DefaultLocationDescriptions.``img/badge-binder.svg`` + ) member this.``extras/content/img/badge-notebook.svg`` = AnnotatedPath.Combine( @@ -259,12 +275,19 @@ module Common = ) member this.``extras/content/img/badge-script.svg`` = - AnnotatedPath.Combine(this.``extras/content/img``, "badge-script.svg", DefaultLocationDescriptions.``img/badge-script.svg``) + AnnotatedPath.Combine( + this.``extras/content/img``, + "badge-script.svg", + DefaultLocationDescriptions.``img/badge-script.svg`` + ) // specific files for the init command member this.``templates/init/.logo.png`` = AnnotatedPath.Combine(this.``templates/init``, ".logo.png") - member this.``templates/init/.index_md_template.md`` = AnnotatedPath.Combine(this.``templates/init``, ".index_md_template.md") - member this.``templates/init/.literate_sample_template.fsx`` = AnnotatedPath.Combine(this.``templates/init``, ".literate_sample_template.fsx") + member this.``templates/init/.index_md_template.md`` = + AnnotatedPath.Combine(this.``templates/init``, ".index_md_template.md") + + member this.``templates/init/.literate_sample_template.fsx`` = + AnnotatedPath.Combine(this.``templates/init``, ".literate_sample_template.fsx") /// /// returns true if all special files and folders of this location exist. @@ -287,3 +310,26 @@ module Common = && File.Exists(this.``templates/init/.literate_sample_template.fsx``.Path) with _ -> false + + module CLI = + open Spectre.Console + + let confirmFileCreation (path: string) (description: string) = + let table = + Table() + .AddColumn(new TableColumn("""[bold]Default file[/]""")) + .AddColumn(new TableColumn($"""[green]{Path.GetFileName(path)}[/]""")) + .AddEmptyRow() + .AddRow("""[bold]Will be created at[/]""", $"""[green]{path}[/]""") + .AddEmptyRow() + .AddRow("""[bold]Description[/]""", $"""{description}""") + + AnsiConsole.WriteLine() + // AnsiConsole.MarkupLine $"""[bold]Default file:[/] [green]{Path.GetFileName(path)}[/]""" + // AnsiConsole.MarkupLine $"""[bold]Will be created at[/] [green]{path}[/]""" + // AnsiConsole.MarkupLine $"""[bold]Description:[/] {description}""" + // AnsiConsole.WriteLine() + AnsiConsole.Write(table) + let conf = AnsiConsole.Confirm $"""[bold]Do you want to create this file?[/]""" + AnsiConsole.WriteLine() + conf From 6cea9706b9f6006ef4cef0e8c12104972f31bdfa Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Thu, 7 Dec 2023 09:34:32 +0100 Subject: [PATCH 9/9] add `non-interactive` flag to init command --- src/fsdocs-tool/InitCommand.fs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/fsdocs-tool/InitCommand.fs b/src/fsdocs-tool/InitCommand.fs index 11cece59c..a4dd05e0d 100644 --- a/src/fsdocs-tool/InitCommand.fs +++ b/src/fsdocs-tool/InitCommand.fs @@ -26,6 +26,12 @@ type InitCommand() = HelpText = "Whether to force-overwrite existing files in the output folder.")>] member val force: bool = false with get, set + [] + member val ``non-interactive``: bool = false with get, set + member this.Execute() = let docsOutputPath = Path.GetFullPath(this.output) @@ -60,7 +66,17 @@ type InitCommand() = inNugetPackageLocations.``templates/init/.literate_sample_template.fsx``, Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "literate_sample.fsx")) ] - fileMap |> List.iter (fun (src, dst) -> File.Copy(src.Path, dst, this.force)) + fileMap + |> List.map (fun (src, dst) -> + src, + dst, + if this.``non-interactive`` then + true + else + Common.CLI.confirmFileCreation dst src.Description) + |> List.iter (fun (src, dst, copy) -> + if copy then + File.Copy(src.Path, dst, this.force)) printfn "" printfn "a basic fsdocs scaffold has been created in %s." this.output @@ -96,7 +112,13 @@ type InitCommand() = Path.GetFullPath(Path.Combine(initLocations.DocsFolder.Path, "literate_sample.fsx"))) ] fileMap - |> List.map (fun (src, dst) -> (src, dst, Common.CLI.confirmFileCreation dst src.Description)) + |> List.map (fun (src, dst) -> + src, + dst, + if this.``non-interactive`` then + true + else + Common.CLI.confirmFileCreation dst src.Description) |> List.iter (fun (src, dst, copy) -> if copy then File.Copy(src.Path, dst, this.force))