diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
new file mode 100644
index 0000000..6a501d4
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
@@ -0,0 +1,34 @@
+#
+
+
+
+## Issue
+
+This PR addresses Issue #.
+
+
+
+## Check list
+
+### Required
+
+- [ ] I have updated `release-notes/wip-release-notes.md` file
+- [ ] I have addressed style warnings given by Visual Studio/ReSharper/Rider
+- [ ] I have checked that all tests pass.
+
+### Optional
+
+
+
+- [ ] I have updated the `readme.md` file
+- [ ] I have bumped the version number in the `version.txt`
+- [ ] I have added or updated any necessary tests.
+- [ ] I have ensured that any new code is covered by tests where reasonably possible.
diff --git a/.github/workflows/build-gedcom-package.yml b/.github/workflows/build-gedcom-package.yml
index 7e7a9d2..06e3206 100644
--- a/.github/workflows/build-gedcom-package.yml
+++ b/.github/workflows/build-gedcom-package.yml
@@ -6,15 +6,27 @@ on:
- main
paths-ignore:
- 'README.md'
+ - 'Example/**'
- '.vscode/**'
- '.gitignore'
+ - 'contributors.md'
+ - 'release-notes/**'
+ - '.github/PULL_REQUEST_TEMPLATE/**'
+ - 'src/.idea/**'
+ - 'docs/**'
pull_request:
types: [assigned, opened, synchronize, reopened]
paths-ignore:
- 'README.md'
+ - 'Example/**'
- '.vscode/**'
- '.gitignore'
+ - 'contributors.md'
+ - 'release-notes/**'
+ - '.github/PULL_REQUEST_TEMPLATE/**'
+ - 'src/.idea/**'
+ - 'docs/**'
workflow_dispatch:
inputs:
@@ -33,12 +45,14 @@ jobs:
runs-on: ubuntu-latest
env:
STRAVAIG_SOLUTION: ./src/Gedcom.sln
- STRAVAIG_UNIT_TESTS: ./src/Stravaig.Gedcom.UnitTests
- STRAVAIG_PACKAGE_PROJECT: src/Stravaig.Gedcom/Stravaig.Gedcom.csproj
+ STRAVAIG_TESTS: ./src/Stravaig.Gedcom.UnitTests
+ STRAVAIG_PROJECT: Stravaig.Gedcom
steps:
- uses: actions/checkout@v2
name: Checking out the source code
+ with:
+ fetch-depth: 0
- name: Set version number
shell: pwsh
@@ -46,33 +60,100 @@ jobs:
- name: Display workflow state
run: |
- echo "Solution: $STRAVAIG_SOLUTION"
- echo "Unit tests: $STRAVAIG_UNIT_TESTS"
- echo "Package project: $STRAVAIG_PACKAGE_PROJECT"
- echo "Package version: $STRAVAIG_PACKAGE_VERSION"
- echo "Version Suffix: $STRAVAIG_PACKAGE_VERSION_SUFFIX"
- echo "Publish To NuGet: $STRAVAIG_PUBLISH_TO_NUGET"
- echo "Solution: $STRAVAIG_SOLUTION"
+ echo "STRAVAIG_SOLUTION: $STRAVAIG_SOLUTION"
+ echo "STRAVAIG_PROJECT: $STRAVAIG_PROJECT"
+ echo "STRAVAIG_TESTS: $STRAVAIG_TESTS"
+ echo "STRAVAIG_PACKAGE_VERSION: $STRAVAIG_PACKAGE_VERSION"
+ echo "STRAVAIG_PACKAGE_VERSION_SUFFIX: $STRAVAIG_PACKAGE_VERSION_SUFFIX"
+ echo "STRAVAIG_PACKAGE_FULL_VERSION: $STRAVAIG_PACKAGE_FULL_VERSION"
+ echo "STRAVAIG_PUBLISH_TO_NUGET: $STRAVAIG_PUBLISH_TO_NUGET"
+ echo "STRAVAIG_IS_PREVIEW: $STRAVAIG_IS_PREVIEW"
+ echo "STRAVAIG_IS_STABLE: $STRAVAIG_IS_STABLE"
- uses: actions/setup-dotnet@v1
name: Setup .NET Core
with:
- dotnet-version: 3.1.402
+ dotnet-version: 3.1.x
- name: Build Solution
run: dotnet build ${{ env.STRAVAIG_SOLUTION }} --configuration Release
- name: Test solution
- run: dotnet test ${{ env.STRAVAIG_UNIT_TESTS }} --configuration Release
+ run: dotnet test ${{ env.STRAVAIG_TESTS }} --configuration Release
- name: Package Preview Release
- if: ${{ env.STRAVAIG_PACKAGE_VERSION_SUFFIX != '~' }}
- run: dotnet pack ${{ env.STRAVAIG_PACKAGE_PROJECT }} --configuration Release --output ./out --include-symbols --include-source /p:VersionPrefix="$STRAVAIG_PACKAGE_VERSION" --version-suffix "$STRAVAIG_PACKAGE_VERSION_SUFFIX" -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
+ if: ${{ env.STRAVAIG_IS_PREVIEW == 'true' }}
+ run: dotnet pack ./src/$STRAVAIG_PROJECT/$STRAVAIG_PROJECT.csproj --configuration Release --output ./out --include-symbols --include-source /p:VersionPrefix="$STRAVAIG_PACKAGE_VERSION" --version-suffix "$STRAVAIG_PACKAGE_VERSION_SUFFIX" -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
- name: Package Stable Release
- if: ${{ env.STRAVAIG_PACKAGE_VERSION_SUFFIX == '~' }}
- run: dotnet pack ${{ env.STRAVAIG_PACKAGE_PROJECT }} --configuration Release --output ./out --include-symbols --include-source /p:VersionPrefix="$STRAVAIG_PACKAGE_VERSION" -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
+ if: ${{ env.STRAVAIG_IS_STABLE == 'true' }}
+ run: dotnet pack ./src/$STRAVAIG_PROJECT/$STRAVAIG_PROJECT.csproj --configuration Release --output ./out --include-symbols --include-source /p:VersionPrefix="$STRAVAIG_PACKAGE_VERSION" -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
- name: Push package to NuGet
if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' }}
run: dotnet nuget push ./out/*.nupkg --api-key ${{ secrets.STRAVAIG_NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
+
+ - name: List Contributors
+ shell: pwsh
+ run: ./list-contributors.ps1
+
+ - name: Build Release Notes
+ shell: pwsh
+ run: ./build-release-notes.ps1
+
+ - name: Archive Simulated Release Notes
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'false' }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: simulated-release-information
+ path: |
+ contributors.md
+ release-notes/full-release-notes.md
+ release-notes/release-notes-${{ env.STRAVAIG_PACKAGE_FULL_VERSION }}.md
+ retention-days: 7
+
+ - name: Archive Release Notes
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: release-information
+ path: |
+ contributors.md
+ release-notes/full-release-notes.md
+ release-notes/release-notes-${{ env.STRAVAIG_PACKAGE_FULL_VERSION }}.md
+
+ - name: Mark Release
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' }}
+ uses: ncipollo/release-action@v1
+ with:
+ artifacts: "./out/*.nupkg,./out/*.snupkg,LICENSE,contributors.md,readme.md,./release-notes/release-notes-${{ env.STRAVAIG_PACKAGE_FULL_VERSION }}.md"
+ token: ${{ secrets.GITHUB_TOKEN }}
+ bodyFile: "release-body.md"
+ prerelease: ${{ env.STRAVAIG_IS_PREVIEW }}
+ commit: ${{ env.GITHUB_SHA }}
+ tag: v${{ env.STRAVAIG_PACKAGE_FULL_VERSION }}
+ draft: false
+
+ - name: Bump version
+ #IF Publishing & Stable release
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' && env.STRAVAIG_IS_STABLE == 'true' }}
+ shell: pwsh
+ run: ./Bump-Version.ps1 -BumpPatch
+
+ - name: Reset WIP release notes
+ #IF Publishing & Stable release
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' && env.STRAVAIG_IS_STABLE == 'true' }}
+ shell: pwsh
+ run: ./Reset-WipReleaseNotes.ps1
+
+ - name: Commit post release updates
+ #IF Publishing & Stable release
+ if: ${{ env.STRAVAIG_PUBLISH_TO_NUGET == 'true' && env.STRAVAIG_IS_STABLE == 'true' }}
+ uses: EndBug/add-and-commit@v5
+ with:
+ add: ./contributors.md ./release-notes/** ./version.txt
+ author_name: StravaigBot
+ author_email: stravaig@colinmackay.scot
+ message: "[bot] Bump Version & Post v${{ env.STRAVAIG_PACKAGE_FULL_VERSION }} Release updates."
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index bf975bc..8031be7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -350,3 +350,84 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+
+
+# Sphinx/Read-the-Docs build folders
+
+docs/build/
+docs/_build/
+docs/source/_build
+
+# Below this line take from: https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
+# -----------------------------------------------------------------------------
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+**/.idea/**/workspace.xml
+**/.idea/**/tasks.xml
+**/.idea/**/usage.statistics.xml
+**/.idea/**/dictionaries
+**/.idea/**/shelf
+
+# Generated files
+**/.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+**/.idea/**/dataSources/
+**/.idea/**/dataSources.ids
+**/.idea/**/dataSources.local.xml
+**/.idea/**/sqlDataSources.xml
+**/.idea/**/dynamic.xml
+**/.idea/**/uiDesigner.xml
+**/.idea/**/dbnavigator.xml
+
+# Gradle
+**/.idea/**/gradle.xml
+**/.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+**/.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+**/.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+**/.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+**/.idea/caches/build_file_checksums.ser
\ No newline at end of file
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000..25aadbd
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,26 @@
+# .readthedocs.yml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+ builder: html
+ fail_on_warning: true
+
+# Build documentation with MkDocs
+#mkdocs:
+# configuration: mkdocs.yml
+
+# Optionally build your docs in additional formats such as PDF
+# formats:
+# - pdf
+
+# Optionally set the version of Python and requirements required to build your docs
+# python:
+# version: 3.7
+# install:
+# - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..a5a1469
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,10 @@
+{
+ "cSpell.words": [
+ "Gedcom",
+ "Stravaig",
+ "nuget",
+ "nupkg",
+ "pwsh",
+ "snupkg"
+ ]
+}
\ No newline at end of file
diff --git a/Bump-Version.ps1 b/Bump-Version.ps1
new file mode 100644
index 0000000..0725980
--- /dev/null
+++ b/Bump-Version.ps1
@@ -0,0 +1,53 @@
+[CmdletBinding()]
+param (
+ [Switch]
+ $BumpMajor,
+
+ [Switch]
+ $BumpMinor,
+
+ [Switch]
+ $BumpPatch
+)
+
+$VersionFile = "$PSScriptRoot/version.txt";
+$currentVersion = Get-Content $VersionFile -ErrorAction Stop
+if ($null -eq $currentVersion)
+{
+ Write-Error "The $VersionFile file is empty"
+ Exit 1
+}
+if ($currentVersion.GetType().BaseType.Name -eq "Array")
+{
+ $currentVersion = $currentVersion[0]
+ Write-Warning "$VersionFile contains more than one line of text. Using the first line."
+}
+if ($currentVersion -notmatch "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$")
+{
+ Write-Error "The contents of $VersionFile (`"$nextVersion`") not recognised as a valid version number."
+ Exit 2
+}
+
+$parts = $currentVersion.Split('.');
+[int]$major = $parts[0]
+[int]$minor = $parts[1]
+[int]$patch = $parts[2]
+
+if ($BumpMajor)
+{
+ $major += 1;
+}
+
+if ($BumpMinor)
+{
+ $minor += 1;
+}
+
+if ($BumpPatch)
+{
+ $patch += 1;
+}
+
+$newVersion = "$major.$minor.$patch";
+
+Set-Content $VersionFile $newVersion -Encoding UTF8 -Force
\ No newline at end of file
diff --git a/Reset-WipReleaseNotes.ps1 b/Reset-WipReleaseNotes.ps1
new file mode 100644
index 0000000..b298ff2
--- /dev/null
+++ b/Reset-WipReleaseNotes.ps1
@@ -0,0 +1,16 @@
+$content = @(
+"# Release Notes",
+"",
+"## Version X",
+"",
+"Date: ???",
+""
+"### Bugs"
+"",
+"### Features",
+"",
+"### Miscellaneous",
+""
+)
+
+Set-Content "$PSScriptRoot/release-notes/wip-release-notes.md" $content -Encoding UTF8 -Force
\ No newline at end of file
diff --git a/Set-Version.ps1 b/Set-Version.ps1
index 3cb2a4b..ac8ce67 100644
--- a/Set-Version.ps1
+++ b/Set-Version.ps1
@@ -1,62 +1,70 @@
-[CmdletBinding()]
-param (
- [Parameter(Mandatory=$false)]
- [string]
- $IsPreview = $true,
-
- [Parameter(Mandatory=$false)]
- [string]
- $IsPublicRelease = "false"
-)
-
-function ConvertTo-Boolean([string]$Value, [bool]$EmptyDefault)
-{
- if ([string]::IsNullOrWhiteSpace($value)) { return $EmptyDefault; }
- if ($Value -like "true") { return $true; }
- if ($Value -like "false") { return $false; }
- throw "Don't know how to convert `"$Value`" into a Boolean."
-}
-
-[bool]$IsPreview = ConvertTo-Boolean -Value $IsPreview -EmptyDefault $true;
-[bool]$IsPublicRelease = ConvertTo-Boolean -Value $IsPublicRelease -EmptyDefault $false;
-
-$VersionFile = "$PSScriptRoot/version.txt";
-
-Get-ChildItem Env:
-
-# Work out the version number
-$nextVersion = Get-Content $VersionFile -ErrorAction Stop
-if ($null -eq $nextVersion)
-{
- Write-Error "The $VersionFile file is empty"
- Exit 1
-}
-if ($nextVersion.GetType().BaseType.Name -eq "Array")
-{
- $nextVersion = $nextVersion[0]
- Write-Warning "$VersionFile contains more than one line of text. Using the first line."
-}
-if ($nextVersion -notmatch "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$")
-{
- Write-Error "The contents of $VersionFile (`"$nextVersion`") not recognised as a valid version number."
- Exit 2
-}
-"STRAVAIG_PACKAGE_VERSION=$nextVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
-
-# Work out the suffix (~ = no suffix)
-$suffix = "~"
-if ($IsPreview)
-{
- $suffix = "preview."
- $suffix += $Env:GITHUB_RUN_NUMBER
-}
-"STRAVAIG_PACKAGE_VERSION_SUFFIX=$suffix" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
-
-if ($IsPublicRelease)
-{
- "STRAVAIG_PUBLISH_TO_NUGET=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
-}
-else
-{
- "STRAVAIG_PUBLISH_TO_NUGET=false" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
-}
+[CmdletBinding()]
+param (
+ [Parameter(Mandatory=$false)]
+ [string]
+ $IsPreview = $true,
+
+ [Parameter(Mandatory=$false)]
+ [string]
+ $IsPublicRelease = "false"
+)
+
+function ConvertTo-Boolean([string]$Value, [bool]$EmptyDefault)
+{
+ if ([string]::IsNullOrWhiteSpace($value)) { return $EmptyDefault; }
+ if ($Value -like "true") { return $true; }
+ if ($Value -like "false") { return $false; }
+ throw "Don't know how to convert `"$Value`" into a Boolean."
+}
+
+[bool]$IsPreview = ConvertTo-Boolean -Value $IsPreview -EmptyDefault $true;
+[bool]$IsPublicRelease = ConvertTo-Boolean -Value $IsPublicRelease -EmptyDefault $false;
+
+$VersionFile = "$PSScriptRoot/version.txt";
+
+# Work out the version number
+$nextVersion = Get-Content $VersionFile -ErrorAction Stop
+if ($null -eq $nextVersion)
+{
+ Write-Error "The $VersionFile file is empty"
+ Exit 1
+}
+if ($nextVersion.GetType().BaseType.Name -eq "Array")
+{
+ $nextVersion = $nextVersion[0]
+ Write-Warning "$VersionFile contains more than one line of text. Using the first line."
+}
+if ($nextVersion -notmatch "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$")
+{
+ Write-Error "The contents of $VersionFile (`"$nextVersion`") not recognised as a valid version number."
+ Exit 2
+}
+"STRAVAIG_PACKAGE_VERSION=$nextVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+$fullVersion = $nextVersion;
+
+# Work out the suffix (~ = no suffix)
+$suffix = "~"
+if ($IsPreview)
+{
+ $suffix = "preview."
+ $suffix += $Env:GITHUB_RUN_NUMBER
+ $fullVersion += "-"+$suffix;
+ "STRAVAIG_IS_STABLE=false" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+ "STRAVAIG_IS_PREVIEW=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+}
+else
+{
+ "STRAVAIG_IS_STABLE=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+ "STRAVAIG_IS_PREVIEW=false" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+}
+"STRAVAIG_PACKAGE_VERSION_SUFFIX=$suffix" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+"STRAVAIG_PACKAGE_FULL_VERSION=$fullVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+
+if ($IsPublicRelease)
+{
+ "STRAVAIG_PUBLISH_TO_NUGET=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+}
+else
+{
+ "STRAVAIG_PUBLISH_TO_NUGET=false" | Out-File -FilePath $Env:GITHUB_ENV -Encoding UTF8 -Append
+}
diff --git a/build-release-notes.ps1 b/build-release-notes.ps1
new file mode 100644
index 0000000..28d1ccb
--- /dev/null
+++ b/build-release-notes.ps1
@@ -0,0 +1,40 @@
+$fullVersion = $Env:STRAVAIG_PACKAGE_FULL_VERSION
+
+$currentReleaseNotes = Get-Content "$PSScriptRoot/release-notes/wip-release-notes.md";
+
+for($i = 0; $i -lt $currentReleaseNotes.Length; $i++)
+{
+ $line = $currentReleaseNotes[$i];
+ if ($line -eq "## Version X")
+ {
+ $line = "## Version $fullVersion"
+ $currentReleaseNotes[$i] = $line;
+ }
+
+ if ($line -eq "Date: ???")
+ {
+ $line = "Date: "+(Get-Date).ToString("dddd, d MMMM, yyyy 'at' HH:mm:ss zzzz")
+ $currentReleaseNotes[$i] = $line;
+ }
+}
+
+Set-Content "$PSScriptRoot/release-notes/release-notes-$fullVersion.md" $currentReleaseNotes -Encoding UTF8 -Force
+
+$fullReleaseNotes = Get-Content "$PSScriptRoot/release-notes/full-release-notes.md";
+
+$preamble = $fullReleaseNotes[0..1];
+
+$currentReleaseNotesExtractLength = $currentReleaseNotes.Length - 1;
+$currentReleaseNotesExtract = $currentReleaseNotes[2..$currentReleaseNotesExtractLength]
+
+$existingLength = $fullReleaseNotes.Length - 1;
+$existing = $fullReleaseNotes[2..$existingLength];
+
+$fullReleaseNotes = $preamble + $currentReleaseNotesExtract + $existing
+
+Set-Content "$PSScriptRoot/release-notes/full-release-notes.md" $fullReleaseNotes -Encoding UTF8 -Force
+
+$contributors = Get-Content "$PSScriptRoot/contributors.md";
+$releaseBody = $currentReleaseNotes + @("", "---", "") + $contributors
+Set-Content "$PSScriptRoot/release-body.md" $releaseBody -Encoding UTF8 -Force
+
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..d4bb2cb
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..3dc595b
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,63 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'Stravaig Gedcom'
+copyright = '2021, Stravaig Projects'
+author = 'Stravaig Projects'
+
+# The full version, including alpha/beta/rc tags
+release = '0.2.0'
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx_rtd_theme'
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = [
+ '_templates'
+]
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = [
+ '_build',
+ 'Thumbs.db',
+ '.DS_Store'
+]
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_rtd_theme'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+# html_static_path = ['_static']
+html_static_path = []
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..c541527
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,27 @@
+.. Stravaig Configuration Diagnostics documentation master file, created by
+ sphinx-quickstart on Tue Jan 5 16:04:48 2021.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Stravaig Projects: Gedcom documentation
+=======================================
+
+The GEDCOM file format is the defacto standard for transmission of genealogy or family-tree data. It has been around since the mid-eighties and was devised by the Church of Latter Day Saints.
+
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Introduction:
+
+
+.. toctree::
+ :maxdepth: 2
+ :caption: advanced
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..2340437
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,47 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ echo Cannot find environment variable for the Sphinx Build.
+ echo Setting to 'sphinx-build'
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+REM python /home/docs/checkouts/readthedocs.org/user_builds/stravaigextensionsconfigurationdiagnostics/envs/latest/bin/sphinx-build
+REM -T -E -W --keep-going -b readthedocs -d _build/doctrees-readthedocs -D language=en . _build/html
+echo %SPHINXBUILD% -T -E -W --keep-going -b %1 -d _build/doctrees-readthedocs -D language=en %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+%SPHINXBUILD% -T -E -W --keep-going -b %1 -d _build/doctrees-readthedocs -D language=en %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+if errorlevel 0 (
+ echo.
+ echo Done!
+) else (
+ echo.
+ echo FAILED!
+)
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/readme.md b/docs/readme.md
new file mode 100644
index 0000000..d764e67
--- /dev/null
+++ b/docs/readme.md
@@ -0,0 +1,34 @@
+# Installing the doc generation tools
+
+## Install Python
+
+This is currently using Python 3.9. You can get it here: https://www.python.org/downloads/
+
+## Install Sphinx
+
+From a command/PowerShell prompt:
+* `pip install sphinx`
+* `python -m pip install --upgrade pip`
+
+## Install the theme
+
+* `pip install sphinx-rtd-theme`
+
+
+# Building the documentation
+
+Navigate to the `docs` folder and run:
+```powershell
+./make html
+```
+
+## Running a HTTP server
+
+In a separate terminal, navigate to the newly created `docs/_build/html` folder, and run:
+```powershell
+python -m http.server 8000
+```
+
+## More information
+
+For more information see: https://www.sphinx-doc.org/en/1.5.1/tutorial.html
\ No newline at end of file
diff --git a/list-contributors.ps1 b/list-contributors.ps1
new file mode 100644
index 0000000..a16f501
--- /dev/null
+++ b/list-contributors.ps1
@@ -0,0 +1,389 @@
+# This script is licenced under an MIT licence. Licence details can be found at
+# https://github.com/Stravaig-Projects/Repo-Contributor-List/blob/master/LICENSE
+# Please keep this licence notice link intact.
+#
+# Full details of this script can be found at:
+# https://github.com/Stravaig-Projects/Repo-Contributor-List
+
+param
+(
+ [parameter(Mandatory=$false)]
+ [string]$OutputFile = "contributors.md",
+
+ [parameter(Mandatory=$false)]
+ [string]$DateTimeFormat = "dddd, d MMMM, yyyy @ HH:mm:ss zzz",
+
+ [parameter(Mandatory=$false)]
+ [string]$TimeFormat = "HH:mm:ss zzz",
+
+ [parameter(Mandatory=$false)]
+ [ValidateSet("Name", "FirstCommit", "LastCommit", "CommitCount")]
+ [string]$SortOrder = "Name",
+
+ [parameter(Mandatory=$false)]
+ [ValidateSet("Ascending", "Descending")]
+ [string]$SortDirection = "Ascending",
+
+ [parameter(Mandatory=$false)]
+ [System.IO.FileInfo]$AkaFilePath,
+
+ [parameter(Mandatory=$false)]
+ [System.IO.FileInfo]$IgnoredNamesPath,
+
+ [parameter(Mandatory=$false)]
+ [System.IO.FileInfo]$IgnoredEmailsPath
+)
+
+function Test-StringEquality($A, $B)
+{
+ return [string]::Compare($A, $B, $true) -eq 0
+}
+
+function Test-Name($contributor, $committerName)
+{
+ return $null -ne $contributor.Names.Where({ Test-StringEquality $_ $committerName }, "First", 1)[0];
+}
+
+function Test-Email($contributor, $committerEmail)
+{
+ return $null -ne $contributor.Emails.Where({ Test-StringEquality $_ $committerEmail }, "First", 1)[0];
+}
+
+function Test-IgnoredItem($Item, $IgnoredItemsList)
+{
+ return $null -ne $IgnoredItemsList.Where({ Test-StringEquality $_ $Item }, "First", 1)[0];
+}
+function Test-Contributor($contributor, $commit)
+{
+ $nameMatch = Test-Name -Contributor $contributor -Commit $commit.Name;
+ if ($nameMatch) {
+ return $true;
+ }
+
+ $emailMatch = Test-Email -Contributor $contributor -Commit $commit.Email;
+ return $emailMatch;
+}
+
+function Get-ConfigFilePath($configFilePath, $defaultConfigFilePath, $friendlyName)
+{
+ $configFileMustExist = $true;
+ if ($null -eq $configFilePath)
+ {
+ $configFileMustExist = $false;
+ $configFilePath = $defaultConfigFilePath;
+ }
+
+ $pathExists = Test-Path -Path $configFilePath;
+
+ if (-not $pathExists)
+ {
+ if ($configFileMustExist)
+ {
+ throw "The `"$friendlyName`" file at $configFilePath does not exist.";
+ }
+ else
+ {
+ return $null;
+ }
+ }
+ return $configFilePath;
+}
+
+function Get-IgnoredNamesList($IgnoredNamesPath, $AkaContributors)
+{
+ $result = @();
+ foreach($contributor in $AkaContributors)
+ {
+ foreach($name in $contributor.names)
+ {
+ $result += $name;
+ Write-Verbose "Ignoring name `"$name`"";
+ }
+ }
+
+ $IgnoredNamesPath = Get-ConfigFilePath -configFilePath $IgnoredNamesPath -defaultConfigFilePath "$PSScriptRoot/.stravaig/list-contributor-ignore-names.txt" -friendlyName "list of ignored names";
+ if ($null -ne $IgnoredNamesPath)
+ {
+ $ignoredNames = Get-Content -Path $IgnoredNamesPath;
+ foreach($name in $ignoredNames)
+ {
+ $result += $name;
+ Write-Verbose "Ignoring name `"$name`"";
+ }
+ }
+ $result = $result | Select-Object -Unique;
+ return (,$result);
+}
+
+function Get-IgnoredEmailsList($IgnoredEmailsPath, $AkaContributors)
+{
+ $result = @();
+ foreach($contributor in $AkaContributors)
+ {
+ foreach($email in $contributor.emails)
+ {
+ $result += $email;
+ Write-Verbose "Ignoring email `"$email`"";
+ }
+ }
+
+ $IgnoredEmailsPath = Get-ConfigFilePath -configFilePath $IgnoredEmailsPath -defaultConfigFilePath "$PSScriptRoot/.stravaig/list-contributor-ignore-emails.txt" -friendlyName "list of ignored email addresses";
+ if ($null -ne $IgnoredEmailsPath)
+ {
+ $ignoredEmails = Get-Content -Path $IgnoredEmailsPath;
+ foreach($email in $ignoredEmails)
+ {
+ $result += $email;
+ Write-Verbose "Ignoring email `"$email`"";
+ }
+ }
+ $result = $result | Select-Object -Unique;
+ return (,$result);
+}
+
+function Get-InitialContributors($AkaFilePath)
+{
+ $result = @();
+ $akaFilePath = Get-ConfigFilePath -configFilePath $akaFilePath -defaultConfigFilePath "$PSScriptRoot/.stravaig/list-contributor-akas.json" -friendlyName "AKA (Also Known As)";
+ if ($null -eq $akaFilePath)
+ {
+ return (,$result);
+ }
+
+ try
+ {
+ $akaDetails = Get-Content -Raw -Path $akaFilePath | ConvertFrom-Json -ErrorAction Stop
+ }
+ catch
+ {
+ # For some reason it isn't stopping the script when erroring with
+ # -ErrorAction Stop in the ConvertFrom-Json
+ throw $_
+ }
+
+ foreach($person in $akaDetails)
+ {
+ if ($null -eq $person.primaryName)
+ {
+ $fragment = $person | ConvertTo-Json;
+ throw "Each entry must have a `"primaryPerson`" element.`n$fragment";
+ }
+
+ if ($null -eq $person.emails)
+ {
+ $fragment = $person | ConvertTo-Json;
+ throw "Each entry must have a `"emails`" element. If there are no emails supply an empty array.`n$fragment";
+ }
+
+ if ($null -eq $person.akas)
+ {
+ $fragment = $person | ConvertTo-Json;
+ throw "Each entry must have a `"akas`" element. If there are no AKAs supply an empty array.`n$fragment";
+ }
+
+ $contributor = New-Object -TypeName PSObject -Property @{
+ Names=@($person.primaryName);
+ PrimaryName = $person.primaryName;
+ Emails=@();
+ FirstCommit=[DateTime]::MaxValue;
+ LastCommit=[DateTime]::MinValue;
+ CommitCount=0
+ };
+ Write-Verbose "Adding name `"$($contributor.PrimaryName)`" as primary name from $akaFilePath.";
+
+ foreach($email in $person.emails)
+ {
+ if (-not (Test-Email -Contributor $contributor -CommitterEmail $email))
+ {
+ $contributor.Emails += $email;
+ Write-Verbose "Adding email `"$email`" to $($contributor.PrimaryName) from $akaFilePath."
+ }
+ }
+
+ foreach($name in $person.akas)
+ {
+ if (-not (Test-Name -Contributor $contributor -CommitterName $name))
+ {
+ $contributor.Names += $name;
+ Write-Verbose "Adding name `"$name`" to $($contributor.PrimaryName) from $akaFilePath."
+ }
+ }
+
+ $result += $contributor;
+ }
+
+ return (,$result);
+}
+
+$contributors = Get-InitialContributors -AkaFilePath $AkaFilePath;
+$ignoredNamesList = Get-IgnoredNamesList -IgnoredNamesPath $IgnoredNamesPath -AkaContributors $contributors
+$ignoredEmailsList = Get-IgnoredEmailsList -IgnoredEmailsPath $IgnoredEmailsPath -AkaContributors $contributors
+& git log --format="\`"%ai\`",\`"%an\`",\`"%ae\`",\`"%H\`"" > raw-contributors.csv
+$commits = Import-Csv raw-contributors.csv -Header Time,Name,Email,Hash | Sort-Object Time;
+Remove-Item .\raw-contributors.csv
+
+$commitsPerPercentPoint = [Math]::Ceiling($commits.Length / 100)
+$totalCommits = $commits.Length;
+for($i = 0; $i -lt $totalCommits; $i++)
+{
+ $nextCommit = $commits[$i];
+ $commitTime = [DateTime]::ParseExact($nextCommit.Time, "yyyy-MM-dd HH:mm:ss zzz", [CultureInfo]::InvariantCulture);
+
+ if ($i % $commitsPerPercentPoint -eq 0)
+ {
+ $percent = [Math]::Floor($i / $totalCommits * 100);
+ Write-Progress -Activity "Processing" -CurrentOperation "Commit $i of $totalCommits" -PercentComplete $percent
+ }
+
+ $contributor = $contributors.Where({Test-Contributor -Contributor $_ -Commit $nextCommit}, "First", 1)[0]
+ if ($null -eq $contributor)
+ {
+ $contributor = New-Object -TypeName PSObject -Property @{
+ Names=@($nextCommit.Name);
+ PrimaryName = $nextCommit.Name;
+ Emails=@($nextCommit.Email);
+ FirstCommit=$commitTime;
+ LastCommit=$commitTime;
+ CommitCount=1
+ };
+ $contributors += $contributor;
+ Write-Verbose "Adding name `"$($nextCommit.Name)`" as primary name from commit $($nextCommit.Hash).";
+ Write-Verbose "Adding email `"$($nextCommit.Email)`" to $($contributor.PrimaryName) from commit $($nextCommit.Hash)."
+ }
+ else
+ {
+ if ((-not(Test-IgnoredItem -Item $nextCommit.Email -IgnoredItemsList $ignoredEmailsList)) -and
+ (-not (Test-Email -Contributor $contributor -CommitterEmail $nextCommit.Email)))
+ {
+ Write-Verbose "Adding email `"$($nextCommit.Email)`" to $($contributor.PrimaryName) from commit $($nextCommit.Hash)."
+ $contributor.Emails += $nextCommit.Email;
+ }
+ if ((-not(Test-IgnoredItem -Item $nextCommit.Name -IgnoredItemsList $ignoredNamesList)) -and
+ (-not (Test-Name -Contributor $contributor -CommitterName $nextCommit.Name)))
+ {
+ Write-Verbose "Adding name `"$($nextCommit.Name)`" to $($contributor.PrimaryName) from commit $($nextCommit.Hash)."
+ $contributor.Names += $nextCommit.Name;
+ }
+ if ($commitTime -lt $contributor.FirstCommit)
+ {
+ $contributor.FirstCommit = $commitTime;
+ }
+ if ($commitTime -gt $contributor.LastCommit)
+ {
+ $contributor.LastCommit = $commitTime
+ }
+ $contributor.CommitCount += 1;
+ }
+}
+Write-Progress -Activity "Processing" -PercentComplete 100 -Completed
+
+$contributors = $contributors | Where-Object CommitCount -gt 0
+
+$isDescending = $SortDirection -eq "Descending";
+Switch($SortOrder)
+{
+ "Name" {
+ $contributors = $contributors | Sort-Object PrimaryName -Descending:$isDescending;
+ $textOrderBy = "contributor name";
+ }
+ "FirstCommit" {
+ $contributors = $contributors | Sort-Object FirstCommit -Descending:$isDescending;
+ $textOrderBy = "first commit date";
+ }
+ "LastCommit" {
+ $contributors = $contributors | Sort-Object LastCommit -Descending:$isDescending;
+ $textOrderBy = "last commit date";
+ }
+ "CommitCount" {
+ $contributors = $contributors | Sort-Object CommitCount -Descending:$isDescending;
+ $textOrderBy = "number of commits";
+ }
+}
+
+
+"# Contributors" | Out-File $OutputFile -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+$line = "This is a list of all the contributors to this repository in "
+$line += $SortDirection.ToLower();
+"$line order by the $textOrderBy." | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+foreach($contributor in $contributors)
+{
+ $name = $contributor.PrimaryName;
+ $aka = ""
+ if ($contributor.Names.Length -gt 1)
+ {
+ $aka = " (AKA ";
+ $isFirst = $true;
+ for($i = 1; $i -lt $contributor.Names.Length; $i++)
+ {
+ if (-not $isFirst) { $aka += ", " }
+ $aka += "*"+$contributor.Names[$i]+"*";
+ $isFirst = $false
+ }
+ $aka += ")"
+ }
+ $numCommits = $contributor.CommitCount
+ $commitMsg = "commit"; if ($numCommits -gt 1) { $commitMsg += "s" }
+ $start = $contributor.FirstCommit.ToString($DateTimeFormat);
+ if ($contributor.FirstCommit.Date -eq $contributor.LastCommit.Date)
+ {
+ $end = $contributor.LastCommit.ToString($TimeFormat);
+ }
+ else {
+ $end = $contributor.LastCommit.ToString($DateTimeFormat);
+ }
+ "**$name**$aka contributed $numCommits $commitMsg" | Out-File $OutputFile -Append -Encoding utf8 -NoNewline
+ if ($numCommits -eq 1)
+ {
+ " on $start." | Out-File $OutputFile -Append -Encoding utf8
+ }
+ else
+ {
+ " from $start to $end." | Out-File $OutputFile -Append -Encoding utf8
+ }
+ "" | Out-File $OutputFile -Append -Encoding utf8
+}
+"## Summary" | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+
+$firstCommit = $commits[0];
+$firstCommitMsg = [DateTime]::ParseExact($firstCommit.Time, "yyyy-MM-dd HH:mm:ss zzz", [CultureInfo]::InvariantCulture).ToString($DateTimeFormat);
+$lastCommit = $commits[$totalCommits - 1];
+$lastCommitMsg = [DateTime]::ParseExact($lastCommit.Time, "yyyy-MM-dd HH:mm:ss zzz", [CultureInfo]::InvariantCulture).ToString($DateTimeFormat);
+
+":octocat: $totalCommits commits in total." | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+":date: From $firstCommitMsg." | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+":date: Until $lastCommitMsg." | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+
+$topCommitters = ($contributors | Sort-Object CommitCount -Descending);
+$topCommitter = $topCommitters[0];
+$name = $topCommitter.PrimaryName;
+$commitCount = $topCommitter.CommitCount;
+$percentage = $topCommitter.CommitCount / $totalCommits;
+
+":1st_place_medal: Gold medal to $name with $commitCount commits which represents "+("{0:P2}" -f $percentage)+" of all commits." | Out-File $OutputFile -Append -Encoding utf8
+"" | Out-File $OutputFile -Append -Encoding utf8
+
+$topCommitter = $topCommitters[1];
+if ($null -ne $topCommitter)
+{
+ $name = $topCommitter.PrimaryName;
+ $commitCount = $topCommitter.CommitCount;
+ $percentage = $topCommitter.CommitCount / $totalCommits;
+ ":2nd_place_medal: Silver medal to $name with $commitCount commits which represents "+("{0:P2}" -f $percentage)+" of all commits." | Out-File $OutputFile -Append -Encoding utf8
+ "" | Out-File $OutputFile -Append -Encoding utf8
+}
+
+$topCommitter = $topCommitters[2];
+if ($null -ne $topCommitter)
+{
+ $name = $topCommitter.PrimaryName;
+ $commitCount = $topCommitter.CommitCount;
+ $percentage = $topCommitter.CommitCount / $totalCommits;
+ ":3rd_place_medal: Bronze medal to $name with $commitCount commits which represents "+("{0:P2}" -f $percentage)+" of all commits." | Out-File $OutputFile -Append -Encoding utf8
+ "" | Out-File $OutputFile -Append -Encoding utf8
+}
diff --git a/release-notes/full-release-notes.md b/release-notes/full-release-notes.md
new file mode 100644
index 0000000..6a876a2
--- /dev/null
+++ b/release-notes/full-release-notes.md
@@ -0,0 +1,4 @@
+# Full Release Notes
+
+
+
diff --git a/release-notes/wip-release-notes.md b/release-notes/wip-release-notes.md
new file mode 100644
index 0000000..d984e01
--- /dev/null
+++ b/release-notes/wip-release-notes.md
@@ -0,0 +1,13 @@
+# Release Notes
+
+## Version X
+
+Date: ???
+
+### Bugs
+
+### Features
+
+### Miscellaneous
+
+* #60: Make build and release process consistent with other Stravaig Projects.
\ No newline at end of file
diff --git a/src/.idea/.idea.Gedcom/.idea/contentModel.xml b/src/.idea/.idea.Gedcom/.idea/contentModel.xml
index 40aa673..dce9273 100644
--- a/src/.idea/.idea.Gedcom/.idea/contentModel.xml
+++ b/src/.idea/.idea.Gedcom/.idea/contentModel.xml
@@ -489,17 +489,18 @@
-
+
-
-
+
+
+
-
-
+
+
\ No newline at end of file
diff --git a/src/.idea/.idea.Gedcom/.idea/modules.xml b/src/.idea/.idea.Gedcom/.idea/modules.xml
index af928f2..dd8bc26 100644
--- a/src/.idea/.idea.Gedcom/.idea/modules.xml
+++ b/src/.idea/.idea.Gedcom/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/src/.idea/.idea.Gedcom/.idea/riderModule.iml b/src/.idea/.idea.Gedcom/.idea/riderModule.iml
new file mode 100644
index 0000000..7435797
--- /dev/null
+++ b/src/.idea/.idea.Gedcom/.idea/riderModule.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Stravaig.FamilyTreeGenerator/Requests/Handlers/RenderIndividualAsMarkdownHandler.cs b/src/Stravaig.FamilyTreeGenerator/Requests/Handlers/RenderIndividualAsMarkdownHandler.cs
index 643bf45..3c68078 100644
--- a/src/Stravaig.FamilyTreeGenerator/Requests/Handlers/RenderIndividualAsMarkdownHandler.cs
+++ b/src/Stravaig.FamilyTreeGenerator/Requests/Handlers/RenderIndividualAsMarkdownHandler.cs
@@ -30,7 +30,6 @@ public class RenderIndividualAsMarkdownHandler : RequestHandler logger,
@@ -54,7 +53,6 @@ public RenderIndividualAsMarkdownHandler(
_relationshipRenderer = relationshipRenderer;
_residenceRenderer = residenceRenderer;
_occupationRenderer = occupationRenderer;
- _hasSources = false;
}
public override RenderIndividual Handle(RenderIndividual command)
@@ -81,7 +79,6 @@ private void InitHandler(RenderIndividual command)
{
void AddSource(GedcomSourceRecord record, GedcomIndividualRecord individualRecord)
{
- _hasSources = true;
command.AddSource(record, individualRecord);
}