diff --git a/.github/workflows/release_documentation.yml b/.github/workflows/release_documentation.yml index f379948ef..a2ded3b44 100644 --- a/.github/workflows/release_documentation.yml +++ b/.github/workflows/release_documentation.yml @@ -12,22 +12,22 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 9.0.x + dotnet-version: | + 9.0.x + 8.0.x - - name: Setup Ruby for documentation build - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.2' - bundler-cache: true + - name: Setup docfx + run: dotnet tool install -g docfx - name: Build documentation - run: dotnet run --project 'build/build.fsproj' -- -t Documentation + run: docfx build + working-directory: ./docs - name: Upload documentation uses: actions/upload-artifact@v4 with: name: docs path: | - bin/Release/nsubstitute.github.com/ + ./docs/_site retention-days: 7 compression-level: 9 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3829d7356..6f73355dc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,15 +46,8 @@ jobs: 9.0.x 8.0.x - # used for documentation - - name: Setup Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.2' - bundler-cache: true - - name: Build documentation - run: build\build.cmd --target Documentation + run: dotnet run --project 'build/build.fsproj' format-verify: runs-on: ubuntu-latest diff --git a/build/build.cmd b/build/build.cmd deleted file mode 100644 index c20b4544e..000000000 --- a/build/build.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -cls -set encoding=utf-8 - -SET SCRIPT_DIR=%~dp0 -dotnet run --project "%SCRIPT_DIR%/build.fsproj" -- %* diff --git a/build/build.fs b/build/build.fs index e7c4b15fa..3a819ba06 100644 --- a/build/build.fs +++ b/build/build.fs @@ -1,9 +1,6 @@ -open System -open System.Diagnostics open System.IO open Fake.Core -open Fake.Core.TargetOperators open Fake.DotNet open Fake.IO open Fake.IO.Globbing.Operators @@ -54,18 +51,18 @@ let initTargets() = let outputCodePath = output "CodeFromDocs" Directory.create outputCodePath // generate samples from docs - ExamplesToCode.Convert [ root "docs/"; root "docs/help/_posts/"; root ] outputCodePath + ExamplesToCode.Convert [ root "docs/"; root "docs/docs"; root ] outputCodePath // compile code samples let csproj = """ - net6.0;net462 + net8.0;net462 latest - + - + @@ -78,41 +75,6 @@ let initTargets() = DotNet.build (fun p -> p) projPath DotNet.test (fun p -> p) projPath - let tryFindFileOnPath (file : string) : string option = - Environment.GetEnvironmentVariable("PATH").Split([| Path.PathSeparator |]) - |> Seq.append ["."] - |> fun path -> ProcessUtils.tryFindFile path file - - Target.description("Build documentation website. Requires Ruby, bundler and jekyll.") - Target.create "Documentation" <| fun _ -> - Trace.log "Building site..." - let exe = [ "bundle.bat"; "bundle" ] - |> Seq.map tryFindFileOnPath - |> Seq.collect (Option.toList) - |> Seq.tryFind (fun _ -> true) - |> function | Some x -> Trace.log ("using " + x); x - | None -> Trace.log ("count not find exe"); "bundle" - - let workingDir = root "docs/" - let docOutputRelativeToWorkingDir = ".." output "nsubstitute.github.com" - - // TODO migrate the following to FAKE API: CreateProcess.ofStartInfo(p) - // https://fake.build/apidocs/v5/fake-core-createprocess.html - // that doesn't work for some reason - let p = ProcessStartInfo( - UseShellExecute = false, - CreateNoWindow = true, - FileName = exe, - WorkingDirectory = workingDir, - Arguments = "exec jekyll build -d \"" + docOutputRelativeToWorkingDir + "\"") - let proc = Process.Start(p) - proc.WaitForExit() - let result = proc.ExitCode - if result = 0 then - "Site built in " + docOutputRelativeToWorkingDir |> Trace.log - else - "failed to build site" |> failwith - Target.description("List targets, similar to `rake -T`. For more details, run `--listTargets` instead.") Target.create "-T" <| fun _ -> printfn "Optional config options:" @@ -121,8 +83,6 @@ let initTargets() = printfn "" Target.listAvailable() - "Documentation" <== [ "TestCodeFromDocs" ] - [] let main argv = argv diff --git a/build/build.fsproj b/build/build.fsproj index f46710b07..abb45da83 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -7,8 +7,6 @@ - - diff --git a/build/build.sh b/build/build.sh deleted file mode 100755 index c141bbddf..000000000 --- a/build/build.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -set -eu -set -o pipefail - -SCRIPT_PATH="${BASH_SOURCE[0]}"; -if ([ -h "${SCRIPT_PATH}" ]) then - while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done -fi - -# A trick to resolve the script directory -pushd . > /dev/null -cd `dirname ${SCRIPT_PATH}` > /dev/null -SCRIPT_PATH=`pwd`; -popd > /dev/null - -dotnet run --project "${SCRIPT_PATH}/build.fsproj" -- "$@" diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index b83a1e380..000000000 --- a/docs/_config.yml +++ /dev/null @@ -1,9 +0,0 @@ -highlighter: rouge -permalink: /:categories/:title/ -lsi: false -markdown: KramdownPlus -repo: https://github.com/nsubstitute/NSubstitute - -kramdown: - input: GFM - syntax_highlighter: rouge diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html deleted file mode 100644 index 0118f13af..000000000 --- a/docs/_layouts/default.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - NSubstitute: {{ page.title }} - - - - - - - -
- {{ content }} -
- - - - - diff --git a/docs/_layouts/post.html b/docs/_layouts/post.html deleted file mode 100644 index efb7177f4..000000000 --- a/docs/_layouts/post.html +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: default ---- - -
-
-
    - {% for post in site.categories.help reversed %} -
  • {{ post.title }}
  • - {% endfor %} -
-
- -
-

{{ page.title }}

- {{ content }} - -
- Edit this page -
- -
-
- diff --git a/docs/_plugins/kramdownplus.rb b/docs/_plugins/kramdownplus.rb deleted file mode 100644 index c75c91ad2..000000000 --- a/docs/_plugins/kramdownplus.rb +++ /dev/null @@ -1,17 +0,0 @@ -# Use Kramdown, but add anchors with underscores for compatibility with older versions -class Jekyll::Converters::Markdown::KramdownPlus - def initialize(config) - require 'kramdown' - @config = config['kramdown'] || {} - rescue LoadError - raise FatalException.new("Missing dependency: kramdown") - end - - def convert(content) - Kramdown::Document.new(content, @config) - .to_html - .gsub(/.+<\/h\d>/) { |full_match| - "\n#{full_match}" - } - end -end diff --git a/docs/css/style.css b/docs/css/style.css deleted file mode 100644 index 20b43d193..000000000 --- a/docs/css/style.css +++ /dev/null @@ -1,299 +0,0 @@ -html { font-family: "helvetica", Helvetica, Arial } -body { - margin: 0; - padding: 0; - border: 0; - width: 100%; - min-width: 600px; -} - -p { - font-size: 1.0em; - line-height: 1.6; -} - -ul { - font-size: 1.0em; - line-height: 1.6; -} - -h1{font-size: 2.5em} -h2{font-size: 2.0em} -h3{font-size: 1.5em} - -a:link { color: #365f91; text-decoration: none;} -a:visited { color: #365f91; text-decoration: none;} -a:hover { color: #365f91;text-decoration: underline;} -a:active { color: #000000; text-decoration: underline;} - -#header { padding-top: 1.5em; } -#header h1 { - font-size: 3em; - color:#0A2D44; -} - -#header a { - text-decoration:none; - color:#000000; -} - -#header img { - border:0; -} - -#nav { - clear: both; - margin-top: 2em; - font-weight: bold; -} - -#nav a { - margin: 0.7em; -} - -#footer { font-size: xx-small; text-align: center; padding: 15px; clear: both; } -#post { - position:relative; - clear:both; - float:left; - width:100%; -} - -#content { - clear: both; -} -#post-index { - float: left; - line-height: 1.7em; - position: relative; - width:21%; - top:5em; - background-color: #ECF0F5; - -webkit-border-top-right-radius: 20px; - -webkit-border-bottom-right-radius: 20px; - -moz-border-radius-topright: 20px; - -moz-border-radius-bottomright: 20px; - border-top-right-radius: 20px; - border-bottom-right-radius: 20px; -} - -#post-content { - float: left; - position: relative; - width: 71%; - padding-left: 10px; -} - -#page-navigation { - padding-top: 2em; - padding-bottom: 2em; -} -#page-navigation > .next { - float: right; -} - -#page-navigation > .previous { - float: left; -} - -#features { - float: left; - position: relative; - width:60%; - padding: 2em; - padding-top: 0em; -} - -.sidebar { - float: right; - position: relative; - width:25%; - padding: 2em; - padding-right: 1em; - - background-color: #ECF0F5; - -webkit-border-top-left-radius: 20px; - -webkit-border-bottom-left-radius: 20px; - -moz-border-radius-topleft: 20px; - -moz-border-radius-bottomleft: 20px; - border-top-left-radius: 20px; - border-bottom-left-radius: 20px; -} - -.sidebar h3 { - margin: 0px; -} - -#downloads ul { - margin: 0; - padding: 5px; -} - -.download { - margin-bottom: 2em; - padding-top: 0; - padding-bottom: 1em; -} - -.download a { - display: block; - padding-top: 1em; - color: black; - text-decoration: underline; -} - -li.github { list-style-image: url(/images/github-16x16.png); } -li.nsubstitute { list-style-image: url(/images/nsubstitute-16x16.png); } -li.nuget { list-style-image: url(/images/nuget-16x16.png); } -li.teamcity { list-style-image: url(/images/teamcity-16x16.png); } - -div.highlight { - border: 1px solid #AAAAAA; - padding: 5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - overflow: auto; -} - -div.feature-title { - font-size: 1.5em; -} - -div.feature-detail { -} - -div.feature { - clear:both; -} - -code { - font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; -} - -.highlight { - box-sizing: content-box !important; - line-height: 1.1em !important; - font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; - font-weight: normal !important; - font-style: normal !important; - font-size: 1em !important; - min-height: inherit !important; -} - -h1 { - margin-top: 0.5em; - margin-bottom: 0.2em; -} - -h2 { - position: relative; - margin-top: 0.5em; - margin-bottom: 0.2em; -} - -h3 { - position: relative; - margin-top: 0.5em; - margin-bottom: 0.2em; -} - -.tooltip { - visibility: visible; - color: #365f91; - background-color: #ECF0F5; - position: absolute; - z-index: 1; - white-space: nowrap; - font-size: 0.4em; - padding: 0.6em; - margin: 0.4em auto auto 0.6em; - border-radius: 30px; -} - -.tooltip-hidden { - visibility: hidden; -} - -.tooltip:hover { - cursor: pointer; -} - -.edit-link { - display: inline-block; - margin-top: 10px; -} -.edit-text { - padding-left: 18px; -} -.pencil { - width: 5px; - height: 12px; - background: #365f91; - margin-right: 12px; - position: relative; - left: 2px; - top: 15px; - transform: rotate(30deg); -} -.pencil::before { - content: ""; - position: absolute; - width: 5px; - height: 5px; - background: #365f91; - top: -6px ; -} -.pencil::after { - content: "" ; - position: absolute; - width: 3.5px; - height: 3.5px; - background: #365f91; - left: 0.75px; - bottom: -2px; - transform: rotate(45deg); -} - -/* Pygments vs style, as generated by: - * https://github.com/richleland/pygments-css/blob/master/vs.css - */ -.highlight .hll { background-color: #ffffcc } -.highlight { background: #ffffff; } -.highlight .c { color: #008000 } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #0000ff } /* Keyword */ -.highlight .ch { color: #008000 } /* Comment.Hashbang */ -.highlight .cm { color: #008000 } /* Comment.Multiline */ -.highlight .cp { color: #0000ff } /* Comment.Preproc */ -.highlight .cpf { color: #008000 } /* Comment.PreprocFile */ -.highlight .c1 { color: #008000 } /* Comment.Single */ -.highlight .cs { color: #008000 } /* Comment.Special */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gh { font-weight: bold } /* Generic.Heading */ -.highlight .gp { font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { font-weight: bold } /* Generic.Subheading */ -.highlight .kc { color: #0000ff } /* Keyword.Constant */ -.highlight .kd { color: #0000ff } /* Keyword.Declaration */ -.highlight .kn { color: #0000ff } /* Keyword.Namespace */ -.highlight .kp { color: #0000ff } /* Keyword.Pseudo */ -.highlight .kr { color: #0000ff } /* Keyword.Reserved */ -.highlight .kt { color: #2b91af } /* Keyword.Type */ -.highlight .s { color: #a31515 } /* Literal.String */ -.highlight .nc { color: #2b91af } /* Name.Class */ -.highlight .ow { color: #0000ff } /* Operator.Word */ -.highlight .sa { color: #a31515 } /* Literal.String.Affix */ -.highlight .sb { color: #a31515 } /* Literal.String.Backtick */ -.highlight .sc { color: #a31515 } /* Literal.String.Char */ -.highlight .dl { color: #a31515 } /* Literal.String.Delimiter */ -.highlight .sd { color: #a31515 } /* Literal.String.Doc */ -.highlight .s2 { color: #a31515 } /* Literal.String.Double */ -.highlight .se { color: #a31515 } /* Literal.String.Escape */ -.highlight .sh { color: #a31515 } /* Literal.String.Heredoc */ -.highlight .si { color: #a31515 } /* Literal.String.Interpol */ -.highlight .sx { color: #a31515 } /* Literal.String.Other */ -.highlight .sr { color: #a31515 } /* Literal.String.Regex */ -.highlight .s1 { color: #a31515 } /* Literal.String.Single */ -.highlight .ss { color: #a31515 } /* Literal.String.Symbol */ -/* End pygments vs style */ \ No newline at end of file diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 000000000..5e61ed22a --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json", + "metadata": [ + { + "src": [ + { + "src": "../src", + "files": [ + "**/*.csproj" + ] + } + ], + "dest": "api" + } + ], + "build": { + "content": [ + { + "files": [ + "**/*.{md,yml}" + ], + "exclude": [ + "_site/**" + ] + } + ], + "resource": [ + { + "files": [ + "images/**", + "favicon.ico" + ] + } + ], + "output": "_site", + "template": [ + "default", + "modern" + ], + "globalMetadata": { + "_appName": "NSubstitute", + "_appTitle": "NSubstitute", + "_appLogoPath": "images/nsubstitute-32x32.png", + "_enableSearch": true, + "pdf": true, + "repo": "https://github.com/nsubstitute/NSubstitute" + } + } +} \ No newline at end of file diff --git a/docs/help/_posts/2010-01-01-getting-started.markdown b/docs/docs/2010-01-01-getting-started.md similarity index 97% rename from docs/help/_posts/2010-01-01-getting-started.markdown rename to docs/docs/2010-01-01-getting-started.md index fe4eb0ec6..454db1c0b 100644 --- a/docs/help/_posts/2010-01-01-getting-started.markdown +++ b/docs/docs/2010-01-01-getting-started.md @@ -1,9 +1,8 @@ --- title: Getting started -layout: post --- -## Adding NSubstitute to your test project +## Adding NSubstitute to your test project First add the [NSubstitute NuGet package](https://nuget.org/List/Packages/NSubstitute) to your test project using [NuGet](https://docs.microsoft.com/en-us/nuget/quickstart/use-a-package) (either the command line executable, or via the package manager in your IDE). @@ -20,9 +19,9 @@ It is optional but recommended to also install [NSubstitute.Analyzers.CSharp](ht ``` ## Using NSubstitute in a test fixture -So now you are staring at a blank test fixture (created with your favourite unit testing framework; for these examples we're using [NUnit](https://nunit.org/)), and are wondering where to start. +So now you are staring at a blank test fixture (created with your favourite unit testing framework; for these examples we're using [NUnit](https://nunit.org/)), and are wondering where to start. -First, add `using NSubstitute;` to your current C# file. This will give you everything you need to start substituting. +First, add `using NSubstitute;` to your current C# file. This will give you everything you need to start substituting. Now let's say we have a basic calculator interface: diff --git a/docs/help/_posts/2010-01-02-creating-a-substitute.markdown b/docs/docs/2010-01-02-creating-a-substitute.md similarity index 99% rename from docs/help/_posts/2010-01-02-creating-a-substitute.markdown rename to docs/docs/2010-01-02-creating-a-substitute.md index 6b856cf9c..f15d80779 100644 --- a/docs/help/_posts/2010-01-02-creating-a-substitute.markdown +++ b/docs/docs/2010-01-02-creating-a-substitute.md @@ -1,6 +1,5 @@ --- title: Creating a substitute -layout: post --- The basic syntax for creating a substitute is: diff --git a/docs/help/_posts/2010-02-01-set-return-value.markdown b/docs/docs/2010-02-01-set-return-value.md similarity index 99% rename from docs/help/_posts/2010-02-01-set-return-value.markdown rename to docs/docs/2010-02-01-set-return-value.md index b8894f13f..4e5b5723b 100644 --- a/docs/help/_posts/2010-02-01-set-return-value.markdown +++ b/docs/docs/2010-02-01-set-return-value.md @@ -1,6 +1,5 @@ --- title: Setting a return value -layout: post --- The following examples relate to substituting for the following interface: diff --git a/docs/help/_posts/2010-02-02-return-for-args.markdown b/docs/docs/2010-02-02-return-for-args.md similarity index 98% rename from docs/help/_posts/2010-02-02-return-for-args.markdown rename to docs/docs/2010-02-02-return-for-args.md index d1abf6362..b4e156681 100644 --- a/docs/help/_posts/2010-02-02-return-for-args.markdown +++ b/docs/docs/2010-02-02-return-for-args.md @@ -1,6 +1,5 @@ --- title: Return for specific args -layout: post --- @@ -87,7 +86,7 @@ As of NSubstitute 4.0 argument matchers can no longer be used in expression tree > CS8153: An expression tree lambda may not contain a call to a method, property, or indexer that returns by reference -The `Arg.Compat` matchers can be used to work around this issue. They do not return by reference so they are fine to use in expression trees. +The `Arg.Compat` matchers can be used to work around this issue. They do not return by reference so they are fine to use in expression trees.