diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 069dfed..bc5d297 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,20 +2,8 @@ "version": 1, "isRoot": true, "tools": { - "fake-cli": { - "version": "5.20.4", - "commands": [ - "fake" - ] - }, - "excubo.webcompiler": { - "version": "2.7.14", - "commands": [ - "webcompiler" - ] - }, - "fsharp.formatting.commandtool": { - "version": "11.4.0", + "fsdocs-tool": { + "version": "20.0.0-alpha-010", "commands": [ "fsdocs" ] diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 700b96d..0bb4797 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,26 +10,17 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: - dotnet-version: '3.1.x' - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: '12' - - name: install node packages - run: npm install + dotnet-version: 8.x.x - name: Restore tools run: dotnet tool restore + - name: make script executable + run: chmod u+x build.sh - name: Build example docs - run: dotnet fake build -t buildDocs + run: build.sh buildDocs - name: deploy uses: JamesIves/github-pages-deploy-action@3.7.1 with: diff --git a/.gitignore b/.gitignore index 6861d4a..a6b187d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ [Dd]ebug/ [Rr]elease/ x64/ -build/ [Bb]in/ [Oo]bj/ diff --git a/Content/docs-template.fsproj b/Content/docs-template.fsproj index 379fedc..9533c4b 100644 --- a/Content/docs-template.fsproj +++ b/Content/docs-template.fsproj @@ -1,7 +1,7 @@  - net5.0 + net8.0 true diff --git a/Content/docs/_template.html b/Content/docs/_template.html deleted file mode 100644 index c349961..0000000 --- a/Content/docs/_template.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - {{fsdocs-page-title}} - - - - - - - - - - - - - - - - {{fsdocs-watch-script}} - - - -
-
- -
-
-
-
- {{fsdocs-content}} -
-
-
- {{fsdocs-tooltips}} -
- - - - - - - - - - - \ No newline at end of file diff --git a/Content/docs/content/fsdocs-custom.scss b/Content/docs/content/fsdocs-custom.scss deleted file mode 100644 index 4dcc1de..0000000 --- a/Content/docs/content/fsdocs-custom.scss +++ /dev/null @@ -1,399 +0,0 @@ -@charset "utf-8"; -@import url('https://fonts.googleapis.com/css?family=Nunito+Sans:400,700'); - -// Set your brand colors -$transparent: rgba(0,0,0,0); - -$fslabMagentaDarkest: #200117; -$fslabDarkMagenta: #3D1244; -$fslabMagenta: #A00975; -$fslabLightMagenta: #F99BDE; -$fslabRose: #D12F67; // rose -$fslabLightRose: #ff9b9b; // light rose -$fslabOrange: #d59a1b; -$fslabLightOrange: #d2c572; -$fslabDarkGreen:#6A9955; -$fslabGreen: #44d57f; // green -$fslabLightGreen: #c6ffdd; // light green -$fslabDarkAquamarine: #2c5392; // light aquamarine -$fslabAquamarine: #438AFE; -$fslabLightAquamarine: #00d4ff; // light aquamarine - -$fslightblue:#30B9DB; -$fsdarkblue:#378BBA; - -// Update Bulma's global variables -$family-sans-serif: "Nunito", sans-serif; - -// global bulma overrides -$primary: $fslabMagenta; -$dark: $fslabMagentaDarkest; -$link-hover: $fslabMagenta; -$link: $fsdarkblue; - -// specific bulma overrides -$divider-background-color: $fslabMagenta; -$table-cell-border: 1px solid $dark; -$table-head-cell-color: $primary; -$table-cell-heading-color: $primary; - - -//import bulma -@import "../../../node_modules/bulma/bulma.sass"; - -//Possible classes and elements to set styles for in FSharp.Formatting - -//generated tooltips -.fsdocs-tip {} - -//generated member lists -.fsdocs-member-list {} - -//generated member names -.fsdocs-member-name {} - -//generated tooltips for members -.fsdocs-member-tooltip {} - -//generated xmldoc sections -.fsdocs-xmldoc {} - -//generated entity lists -.fsdocs-entity-list {} - -//generated exception lists -.fsdocs-exception-list {} - -//the 'summary' section of an XML doc -.fsdocs-summary {} - -//the 'remarks' section of an XML doc -.fsdocs-remarks {} - -//the 'parameters' section of an XML doc -.fsdocs-params {} - -//a 'parameter' section of an XML doc -.fsdocs-param {} - -//a 'parameter' name of an XML doc -.fsdocs-param-name {} - -//the 'returns' section of an XML doc -.fsdocs-returns {} - -//the 'example' section of an XML doc -.fsdocs-example {} - -//the 'notes' section of an XML doc -.fsdocs-note {} - -//a paragraph of an XML doc -.fsdocs-para {} - -//The search box -#fsdocs-searchbox { - margin: 0 auto; -} - -//The logo -#fsdocs-logo {} - -//The navigation-bar -#fsdocs-menu { - @media screen and (min-width: 768px) { - border-right: 1px solid $dark; - position: sticky; - display: inline-block; - vertical-align: top; - height: 100vh; - top: 0; - bottom: 0; - overflow-y: auto; - background-color: $white-ter; - } - @media screen and (max-width: 768px) { - #fsdocs-menu {border:none}; - background-color: $grey-lightest; - } -} -.navbar-nav { - @extend .menu-list; -} -.nav-header { - @extend .menu-label; - border-bottom: 1px dashed $primary; - list-style: none; - color: $primary; -} - -.active { - @extend .is-active; -} - -#fsdocs-content h1 a, #fsdocs-content h1 a:hover, #fsdocs-content h1 a:focus, -#fsdocs-content h2 a, #fsdocs-content h2 a:hover, #fsdocs-content h2 a:focus, -#fsdocs-content h3 a, #fsdocs-content h3 a:hover, #fsdocs-content h3 a:focus, -#fsdocs-content h4 a, #fsdocs-content h4 a:hover, #fsdocs-content h4 a:focus, -#fsdocs-content h5 a, #fsdocs-content h5 a:hover, #fsdocs-content h5 a:focus, -#fsdocs-content h6 a, #fsdocs-content h6 a:hover, #fsdocs-content h6 a:focus { - color: $primary; -} - -#fsdocs-content p { - @extend .my-2 -} - -#fsdocs-content h1 a { - border-bottom: 8px solid $dark; -} -#fsdocs-content h2 a { - border-bottom: 5px solid $dark; -} -#fsdocs-content h3 a, -#fsdocs-content h4 a { - border-bottom: 2px solid $dark; -} - -#fsdocs-content h5 a, -#fsdocs-content h6 a { - border-bottom: 1px solid $dark; -} - -#fsdocs-content li { - margin: initial; -} - -strong { - border-bottom: 2px solid $primary; -} - -em { - color: $primary; -} - - -table { - @extend .table, .is-striped; -} - -#fsdocs-content ul { - padding-inline-start: 40px; - list-style-type: disc; -} -#fsdocs-content ol{ - padding-inline-start: 40px; - list-style-type: decimal; -} - -#fsdocs-content blockquote { - @extend .p-4; - display: block; - margin-block-start: 1em; - margin-block-end: 1em; - margin-inline-start: 40px; - margin-inline-end: 40px; - background-color: $white-ter; - border-left: 4px solid $primary; -} - -#fsdocs-content table.pre, #fsdocs-content pre.fssnip, #fsdocs-content pre { - background-color: $dark !important; - color: $white-bis !important; - overflow-x: auto; - display:block; - font-weight: initial; -} - -#fsdocs-content pre.fssnip code { - font: 0.85rem 'Roboto Mono', monospace; - font-weight: initial; -} - -#fsdocs-menu::-webkit-scrollbar{ - width: 1px; -} - -#fsdocs-menu::-webkit-scrollbar-thumb { - border-radius: 5px; - background-color: $dark; -} - -#fsdocs-content table.pre::-webkit-scrollbar-track, -#fsdocs-content pre.fssnip ::-webkit-scrollbar-track, -#fsdocs-content pre ::-webkit-scrollbar-track -{ - box-shadow: inset 0 0 6px rgba(0,0,0,0.3); - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); - border-radius: 5px; - background-color: $dark; -} - -#fsdocs-content table.pre::-webkit-scrollbar, -#fsdocs-content pre.fssnip ::-webkit-scrollbar, -#fsdocs-content pre ::-webkit-scrollbar -{ - height: 8px; - background-color: $dark; - border-radius:5px -} - -#fsdocs-content table.pre::-webkit-scrollbar-thumb, -#fsdocs-content pre.fssnip ::-webkit-scrollbar-thumb, -#fsdocs-content pre ::-webkit-scrollbar-thumb -{ - border-radius: 5px; - box-shadow: inset 0 0 6px rgba(0,0,0,0.3); - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); - background-color: $primary; -} - -/*-------------------------------------------------------------------------- - Formatting for F# code snippets -/*--------------------------------------------------------------------------*/ - -.fsdocs-param-name, -.fsdocs-return-name, -.fsdocs-param { - font-weight: 900; - font-size: 0.85rem; - font-family: 'Roboto Mono', monospace; -} - -/* strings --- and stlyes for other string related formats */ -#fsdocs-content span.s { - color: $fslabOrange; -} - -/* printf formatters */ -#fsdocs-content span.pf { - color: $primary ; -} - -/* escaped chars */ -#fsdocs-content span.e { - color: $fslabOrange; -} - -/* identifiers --- and styles for more specific identifier types */ -#fsdocs-content span.id { - color: $white-bis; -} -/* module */ -#fsdocs-content span.m { - color: $fslabGreen; -} -/* reference type */ -#fsdocs-content span.rt { - color: $fslabGreen; -} -/* value type */ -#fsdocs-content span.vt { - color: $fslabGreen; -} -/* interface */ -#fsdocs-content span.if { - color: $fslabGreen; -} -/* type argument */ -#fsdocs-content span.ta { - color: $fslabGreen; -} -/* disposable */ -#fsdocs-content span.d { - color: $fslabLightGreen; -} - -/* property */ -#fsdocs-content span.prop { - color: $white-bis; -} -/* punctuation */ -#fsdocs-content span.p { - color: $white-bis; -} - -#fsdocs-content span.pn { - color: $white-bis; -} - -// /* function */ -#fsdocs-content span.f { - color: $white-bis; -} - -#fsdocs-content span.fn { - color: $fslabLightOrange; -} -/* active pattern */ -#fsdocs-content span.pat { - color: $fslabAquamarine; -} -/* union case */ -#fsdocs-content span.u { - color: $fslabGreen; -} -/* enumeration */ -#fsdocs-content span.e { - color: $fslabGreen; -} -/* keywords */ -#fsdocs-content span.k { - color: $fslabLightMagenta; -} -/* comment */ -#fsdocs-content span.c { - color: $fslabDarkGreen; -} -// /* operators */ -#fsdocs-content span.o { - color: $fslabRose; -} -/* numbers */ -#fsdocs-content span.n { - color: $fslabLightGreen; -} - -/* line number */ -#fsdocs-content span.l { - color: $white-bis; -} - -/* mutable var or ref cell */ -#fsdocs-content span.v { - color: $fslabLightOrange; - font-weight: bold; -} -/* inactive code */ -#fsdocs-content span.inactive { - color: #808080; -} -/* preprocessor */ -#fsdocs-content span.prep { - color: $fslabLightRose; -} - -/* fsi output */ -#fsdocs-content span.fsi { - color: $white-bis; -} - -/* tool tip */ -div.fsdocs-tip { - background: #475b5f; - border-radius: 4px; - font: 11pt 'Droid Sans', arial, sans-serif; - padding: 6px 8px 6px 8px; - display: none; - color: #d1d1d1; - pointer-events: none; -} - - div.fsdocs-tip code { - color: #d1d1d1; - font: 11pt 'Droid Sans', arial, sans-serif; - } - - div.fsdocs-tip em { - color: $fslabDarkGreen; - } \ No newline at end of file diff --git a/Content/docs/content/fsdocs-theme.css b/Content/docs/content/fsdocs-theme.css new file mode 100644 index 0000000..23c7612 --- /dev/null +++ b/Content/docs/content/fsdocs-theme.css @@ -0,0 +1,114 @@ +:root { + + /* fslab colors */ + --fslab-magenta: #A00975; + --fslab-magenta-light: #F99BDE; + --fslab-magenta-dark: #3D1244; + --fslab-magenta-darkest: #200117;; + --fslab-blue: #438AFE; + --fslab-yellow: #FABC2A; + + /* light theme */ + --primary: var(--fslab-magenta); + --text-color: var(--fslab-magenta-darkest); + --text-hover: var(--fslab-magenta-light); + --heading-color: var(--fslab-magenta-dark); + --code-color: var(--fslab-magenta); + --header-border: var(--fslab-magenta-light); + --menu-item-hover-background: var(--fslab-magenta-light); + --mobile-menu-background: var(--header-background); + --link-color: var(--fslab-blue); + --link-hover: var(--fslab-magenta); + --nav-category: rgb(156, 163, 175); + --aside-background: var(--header-background); + --menu-color: var(--text-color); + --fsdocs-theme-toggle-light-color: var(--fslab-magenta-dark); + --fsdocs-theme-toggle-dark-color: #FFF; + --header-link-color: var(--fslab-magenta); + --nav-item-active-border-color: var(--fslab-magenta); + + /* --code-strings-color: #0093A1; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #6B2FBA; + --code-module-color: #009999; + --code-reference-color: #4974D1; + --code-value-color: #1B6600; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #43AEC6; + --code-property-color: #43AEC6; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #6B2FBA; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #0F54D6; + --code-comment-color: #707070; + --code-operators-color: #0F54D6; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; */ +} + +.pre { + border: 1px solid var(--fslab-magenta-light); +} + +:not(td) > .fssnip { + border: 1px solid var(--fslab-magenta-light); +} + +[data-theme=dark] { + --text-color: #F7F7F7; + --heading-color: var(--fslab-magenta); + --header-border: var(--fslab-magenta-dark); + --code-color: #f5f5f6; + --menu-item-hover-background: var(--fslab-magenta-dark); + --doc-tip-background: #2e293a; + --search-background: #020202; + --nav-category: rgb(207, 211, 215); + --nav-item-active-border-color: var(--fslab-magenta); + /* --code-strings-color: #86b4b9; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #d1b3f5; + --code-module-color: #15e1e1; + --code-reference-color: #40fddd; + --code-value-color: #ffb4e9; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #6dd6f1; + --code-property-color: #6acfe7; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #cbda9d; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #a7c2f8; + --code-comment-color: #84d16e; + --code-operators-color: #b4c6ee; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; */ + + .pre { + border: 1px solid var(--fslab-magenta-dark); + } + + :not(td) > .fssnip { + border: 1px solid var(--fslab-magenta-dark); + } +} \ No newline at end of file diff --git a/Content/docs/4_download-badges.fsx b/Content/docs/download-badges.fsx similarity index 60% rename from Content/docs/4_download-badges.fsx rename to Content/docs/download-badges.fsx index 632555e..655b818 100644 --- a/Content/docs/4_download-badges.fsx +++ b/Content/docs/download-badges.fsx @@ -10,9 +10,11 @@ index: 5 (** # Adding download badges -## Notebook download +## Script download -`[![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx)` +```no-highlight +[![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx)` +``` becomes @@ -20,9 +22,11 @@ becomes (you might need to adjust the paths if there are any more levels between `{{root}}` and `img/badge-script.svg` or `{{fsdocs-source-basename}}`) -## Script download +## Notebook download -`[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb)` +```no-highlight +[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) +``` becomes @@ -34,16 +38,13 @@ becomes To add multiple badges to appear on the same line like this: -[![Binder]({{root}}img/badge-binder.svg)](https://mybinder.org/v2/gh/plotly/Plotly.NET/gh-pages?filepath={{fsdocs-source-basename}}.ipynb)  [![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx)  [![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) add a ` ` after the first two badges in you markdown: -`[![Binder]({{root}}img/badge-binder.svg)](https://mybinder.org/v2/gh/plotly/Plotly.NET/gh-pages?filepath={{fsdocs-source-basename}}.ipynb) ` - -`[![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx) ` - -`[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb)` - +```no-highlight +[![Script]({{root}}img/badge-script.svg)]({{root}}{{fsdocs-source-basename}}.fsx)  +[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) +``` *) \ No newline at end of file diff --git a/Content/docs/1_fsharp-code-example.fsx b/Content/docs/fsharp-code-example.fsx similarity index 100% rename from Content/docs/1_fsharp-code-example.fsx rename to Content/docs/fsharp-code-example.fsx diff --git a/Content/docs/index.fsx b/Content/docs/index.fsx index 463462e..0173ffd 100644 --- a/Content/docs/index.fsx +++ b/Content/docs/index.fsx @@ -1,12 +1,9 @@ (** # The fslab documentation template -This template scaffolds the necessary folder structure for FSharp.Formatting +This template scaffolds the necessary folder structure for documentation with FSharp.Formatting and it's `fsdocs` tool, and adds custom styles in the **fslab** theme. -The provided stylesheet was compiled from sass (before uploading the nuget package) and -uses the [Bulma](https://bulma.io/) CSS framework instead of bootstrap which is used by FSharp.Formatting per default. - #### Table of contents - [Installation](#Installation) @@ -47,16 +44,15 @@ The default template initializes the following folder structure when you initial See [further below](#Customization-options) for command line customization options of the template. -
+```no-highlight
 docs
 │   index.fsx
 │   _template.html
-|   _template.ipynb
-|   
-│   0_Markdown-Cheatsheet.md
-│   1_fsharp-code-example.fsx
-│   2_inline-references.fsx
-│   3_notebooks.fsx
+│   _template.ipynb
+│
+│   fsharp-code-example.fsx
+│   inline-references.fsx
+│   notebooks.fsx
 |
 ├───content
 │   fsdocs-custom.css
@@ -67,7 +63,7 @@ docs
 │
 └───reference
         _template.html
-
+``` - `index.fsx` is the file you are reading just now. It contains the very content you are reading at the moment in a markdown block indicated by `(** *)` guards. It will be rendered as the root `index.html` file of your documentation. diff --git a/Content/docs/2_inline-references.fsx b/Content/docs/inline-references.fsx similarity index 100% rename from Content/docs/2_inline-references.fsx rename to Content/docs/inline-references.fsx diff --git a/Content/docs/0_Markdown-Cheatsheet.md b/Content/docs/markdown-cheetsheet.md similarity index 94% rename from Content/docs/0_Markdown-Cheatsheet.md rename to Content/docs/markdown-cheetsheet.md index fb5fa51..1414650 100644 --- a/Content/docs/0_Markdown-Cheatsheet.md +++ b/Content/docs/markdown-cheetsheet.md @@ -13,18 +13,28 @@ This is intended as a quick reference and showcase. For more complete info, see ### Table of Contents -- [Headers](#Headers) -- [Emphasis](#Emphasis) -- [Lists](#Lists) -- [Links](#Links) -- [Images](#Images) -- [Code and Syntax Highlighting](#Code-and-Syntax-Highlighting) -- [Tables](#Tables) -- [Blockquotes](#Blockquotes) -- [Inline HTML](#Inline-HTML) -- [Horizontal Rule](#Horizontal-Rule) -- [Line Breaks](#Line-Breaks) -- [YouTube Videos](#YouTube-Videos) +- [Markdown cheatsheet](#markdown-cheatsheet) + - [Table of Contents](#table-of-contents) + - [Headers](#headers) +- [H1](#h1) + - [H2](#h2) + - [H3](#h3) + - [H4](#h4) + - [H5](#h5) + - [H6](#h6) +- [Alt-H1](#alt-h1) + - [Alt-H2](#alt-h2) + - [Emphasis](#emphasis) + - [Lists](#lists) + - [Links](#links) + - [Images](#images) + - [Code and Syntax Highlighting](#code-and-syntax-highlighting) + - [Tables](#tables) + - [Blockquotes](#blockquotes) + - [Inline HTML](#inline-html) + - [Horizontal Rule](#horizontal-rule) + - [Line Breaks](#line-breaks) + - [YouTube Videos](#youtube-videos) ## Headers @@ -189,11 +199,6 @@ Here's our logo (hover to see the title text): Inline-style: ![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1") -Reference-style: -![alt text][logo] - -[logo]: https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 2" - ## Code and Syntax Highlighting Code blocks are part of the Markdown spec, but syntax highlighting isn't. However, many renderers -- like Github's and *FSharp.Formatting* -- support syntax highlighting. Which languages are supported and how those language names should be written will vary from renderer to renderer. diff --git a/Content/docs/3_notebooks.fsx b/Content/docs/notebooks.fsx similarity index 100% rename from Content/docs/3_notebooks.fsx rename to Content/docs/notebooks.fsx diff --git a/build.cmd b/build.cmd index f1a5d82..8d82883 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,3 @@ -dotnet tool restore -dotnet fake build %* \ No newline at end of file +@echo off + +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..5585859 --- /dev/null +++ b/build/BasicTasks.fs @@ -0,0 +1,34 @@ +module BasicTasks + +open BlackFox.Fake +open Fake.IO +open Fake.DotNet +open Fake.IO.Globbing.Operators + +open ProjectInfo + +let clean = BuildTask.create "Clean" [] { + !! "src/**/bin" + ++ "src/**/obj" + ++ "tests/**/bin" + ++ "tests/**/obj" + ++ "pkg" + |> Shell.cleanDirs +} + + +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 build = BuildTask.create "Build" [clean] { + solutionFile + |> DotNet.build (fun p -> + {p with MSBuildParams = { p.MSBuildParams with DisableInternalBinLog = true }} + ) +} + diff --git a/build/Build.fs b/build/Build.fs new file mode 100644 index 0000000..b0150e6 --- /dev/null +++ b/build/Build.fs @@ -0,0 +1,46 @@ +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 DocumentationTasks +open ReleaseTasks + +/// Full release of nuget package, git tag, and documentation for the stable version. +let _release = + BuildTask.createEmpty + "Release" + [clean; build; runTests; pack; buildDocs; createTag; publishNuget; releaseDocs] + +/// Full release of nuget package, git tag, and documentation for the prerelease version. +let _preRelease = + BuildTask.createEmpty + "PreRelease" + [setPrereleaseTag; clean; build; runTests; packPrerelease; buildDocsPrerelease; createPrereleaseTag; publishNugetPrerelease; prereleaseDocs] + +/// Full release of nuget package for the prerelease version. +let _releaseNoDocs = + BuildTask.createEmpty + "ReleaseNoDocs" + [clean; build; runTests; pack; createTag; publishNuget;] + +/// Full release of nuget package for the prerelease version. +let _preReleaseNoDocs = + BuildTask.createEmpty + "PreReleaseNoDocs" + [setPrereleaseTag; clean; build; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease] + +[] +let main args = + runOrDefault build args diff --git a/build/DocumentationTasks.fs b/build/DocumentationTasks.fs new file mode 100644 index 0000000..e85fa1e --- /dev/null +++ b/build/DocumentationTasks.fs @@ -0,0 +1,36 @@ +module DocumentationTasks + +open Helpers +open ProjectInfo +open BasicTasks + +open BlackFox.Fake + + +let buildDocs = BuildTask.create "BuildDocs" [build] { + printfn "building docs with stable version %s" stableVersionTag + runDotNet + (sprintf "fsdocs build --eval --clean --properties Configuration=Release --parameters fsdocs-package-version %s" stableVersionTag) + "Content" +} + +let buildDocsPrerelease = BuildTask.create "BuildDocsPrerelease" [setPrereleaseTag; build] { + printfn "building docs with prerelease version %s" prereleaseTag + runDotNet + (sprintf "fsdocs build --eval --clean --properties Configuration=Release --parameters fsdocs-package-version %s" prereleaseTag) + "Content" +} + +let watchDocs = BuildTask.create "WatchDocs" [build] { + printfn "watching docs with stable version %s" stableVersionTag + runDotNet + (sprintf "fsdocs watch --eval --clean --properties Configuration=Release --parameters fsdocs-package-version %s" stableVersionTag) + "Content" +} + +let watchDocsPrerelease = BuildTask.create "WatchDocsPrerelease" [setPrereleaseTag; build] { + printfn "watching docs with prerelease version %s" prereleaseTag + runDotNet + (sprintf "fsdocs watch --eval --clean --properties Configuration=Release --parameters fsdocs-package-version %s" prereleaseTag) + "Content" +} 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..25a41c3 --- /dev/null +++ b/build/PackageTasks.fs @@ -0,0 +1,65 @@ +module PackageTasks + +open ProjectInfo + +open MessagePrompts +open BasicTasks +open TestTasks + +open BlackFox.Fake +open Fake.Core +open Fake.DotNet +open Fake.IO.Globbing.Operators + +open System.Text.RegularExpressions + +/// https://github.com/Freymaurer/Fake.Extensions.Release#release-notes-in-nuget +let private replaceCommitLink input = + let commitLinkPattern = @"\[\[#[a-z0-9]*\]\(.*\)\] " + Regex.Replace(input,commitLinkPattern,"") + +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 |> List.map replaceCommitLink |> 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 |> List.map replaceCommitLink |> String.toLines ) + ] @ p.MSBuildParams.Properties) + } + { + p with + VersionSuffix = Some prereleaseSuffix + OutputPath = Some pkgDir + MSBuildParams = msBuildParams + } + )) + else + failwith "aborted" +} diff --git a/build/ProjectInfo.fs b/build/ProjectInfo.fs new file mode 100644 index 0000000..d5a44b4 --- /dev/null +++ b/build/ProjectInfo.fs @@ -0,0 +1,40 @@ +module ProjectInfo + +open Fake.Core + + +let project = "docs-template" + +let testProjects = + [ + // add relative paths (from project root) to your testprojects here + ] + +let solutionFile = $"{project}.sln" + +let configuration = "Release" + +let gitOwner = "fslaborg" + +let gitHome = $"https://github.com/{gitOwner}" + +let projectRepo = $"https://github.com/{gitOwner}/{project}" + +let pkgDir = "pkg" + + +// Create RELEASE_NOTES.md if not existing. Or "release" would throw an error. +Fake.Extensions.Release.ReleaseNotes.ensure() + +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 + diff --git a/build/ReleaseNotesTasks.fs b/build/ReleaseNotesTasks.fs new file mode 100644 index 0000000..8b67175 --- /dev/null +++ b/build/ReleaseNotesTasks.fs @@ -0,0 +1,31 @@ +module ReleaseNotesTasks + + +open Fake.Extensions.Release +open BlackFox.Fake + +/// This might not be necessary, mostly useful for apps which want to display current version as it creates an accessible F# version script from RELEASE_NOTES.md +let createAssemblyVersion = BuildTask.create "createvfs" [] { + AssemblyVersion.create ProjectInfo.project +} + +// https://github.com/Freymaurer/Fake.Extensions.Release#releaseupdate +let updateReleaseNotes = BuildTask.createFn "ReleaseNotes" [] (fun config -> + ReleaseNotes.update(ProjectInfo.gitOwner, ProjectInfo.project, config) +) + + +// https://github.com/Freymaurer/Fake.Extensions.Release#githubdraft +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 + ) +) + diff --git a/build/ReleaseTasks.fs b/build/ReleaseTasks.fs new file mode 100644 index 0000000..6dcccbb --- /dev/null +++ b/build/ReleaseTasks.fs @@ -0,0 +1,87 @@ +module ReleaseTasks + +open MessagePrompts +open ProjectInfo +open BasicTasks +open TestTasks +open PackageTasks +open DocumentationTasks + +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" +} + +let releaseDocs = BuildTask.create "ReleaseDocs" [buildDocs] { + let msg = + sprintf "release docs for version %s?" + stableVersionTag + if promptYesNo msg then + Shell.cleanDir "temp" + Git.CommandHelper.runSimpleGitCommand "." (sprintf "clone %s temp/gh-pages --depth 1 -b gh-pages" projectRepo) |> ignore + Shell.copyRecursive "output" "temp/gh-pages" true |> printfn "%A" + Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" "add ." |> printfn "%s" + let cmd = sprintf """commit -a -m "Update generated documentation for version %s""" stableVersionTag + Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" cmd |> printfn "%s" + Git.Branches.push "temp/gh-pages" + else failwith "aborted" +} + +let prereleaseDocs = BuildTask.create "PrereleaseDocs" [buildDocsPrerelease] { + let msg = sprintf "release docs for version %s?" prereleaseTag + if promptYesNo msg then + Shell.cleanDir "temp" + Git.CommandHelper.runSimpleGitCommand "." (sprintf "clone %s temp/gh-pages --depth 1 -b gh-pages" projectRepo) |> ignore + Shell.copyRecursive "output" "temp/gh-pages" true |> printfn "%A" + Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" "add ." |> printfn "%s" + let cmd = sprintf """commit -a -m "Update generated documentation for version %s""" prereleaseTag + Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" cmd |> printfn "%s" + Git.Branches.push "temp/gh-pages" + else failwith "aborted" +} diff --git a/build/TestTasks.fs b/build/TestTasks.fs new file mode 100644 index 0000000..dcdd19b --- /dev/null +++ b/build/TestTasks.fs @@ -0,0 +1,23 @@ +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 + ) +} + diff --git a/build/build.fsproj b/build/build.fsproj new file mode 100644 index 0000000..f7ed9a6 --- /dev/null +++ b/build/build.fsproj @@ -0,0 +1,34 @@ + + + + net8.0 + Exe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs-template.sln b/docs-template.sln new file mode 100644 index 0000000..874a0fd --- /dev/null +++ b/docs-template.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "docs-template", "Content\docs-template.fsproj", "{C4449189-76C5-4637-ACF7-6BB16C40337F}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "build", "build\build.fsproj", "{FC960823-1B42-43EB-B71C-8B5ACA5DFAA5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C4449189-76C5-4637-ACF7-6BB16C40337F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4449189-76C5-4637-ACF7-6BB16C40337F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4449189-76C5-4637-ACF7-6BB16C40337F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4449189-76C5-4637-ACF7-6BB16C40337F}.Release|Any CPU.Build.0 = Release|Any CPU + {FC960823-1B42-43EB-B71C-8B5ACA5DFAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC960823-1B42-43EB-B71C-8B5ACA5DFAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC960823-1B42-43EB-B71C-8B5ACA5DFAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC960823-1B42-43EB-B71C-8B5ACA5DFAA5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal