Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion cleanrepo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,76 @@ static async Task Main(string[] args)
builder.Configuration.GetSection(nameof(Options))
.Bind(options);

options.ExcludeOrphanedIncludeFiles = ParseStringListOption(
builder.Configuration,
nameof(Options.ExcludeOrphanedIncludeFiles),
options.ExcludeOrphanedIncludeFiles);

await RunOptions(options);
}

private static List<string>? ParseStringListOption(
IConfigurationRoot configuration,
string optionName,
List<string>? currentValue)
{
string key = $"{nameof(Options)}:{optionName}";

foreach (IConfigurationProvider provider in configuration.Providers.Reverse())
{
if (provider.TryGet(key, out string? rawValue))
{
return ParseStringListValue(rawValue);
}

List<string> children = [.. provider.GetChildKeys([], key)];
if (children.Count == 0)
continue;

List<string> values = [.. children
.OrderBy(child => int.TryParse(child, out int index) ? index : int.MaxValue)
.ThenBy(child => child, StringComparer.InvariantCultureIgnoreCase)
.Select(child =>
{
provider.TryGet($"{key}:{child}", out string? value);
return value?.Trim();
})
.Where(value => !string.IsNullOrWhiteSpace(value))
.Select(value => value!.Trim('"'))
.Distinct(StringComparer.InvariantCultureIgnoreCase)];

return values;
}

return currentValue;
}

private static List<string> ParseStringListValue(string? rawValue)
{
if (string.IsNullOrWhiteSpace(rawValue))
return [];

rawValue = rawValue.Trim();

if (rawValue.StartsWith('[') && rawValue.EndsWith(']'))
{
try
{
return JsonSerializer.Deserialize<List<string>>(rawValue) ?? [];
}
catch (JsonException ex)
{
throw new ArgumentException($"Option must be a valid JSON array of strings.", ex);
}
}

return [.. rawValue
.Split([',', ';', '\n', '\r'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(value => value.Trim('"'))
.Where(value => !string.IsNullOrWhiteSpace(value))
.Distinct(StringComparer.InvariantCultureIgnoreCase)];
}

static async Task RunOptions(Options options)
{
if (string.IsNullOrEmpty(options.Function))
Expand Down Expand Up @@ -237,7 +304,7 @@ static async Task RunOptions(Options options)
$"in the '{options.TargetDirectory}' directory...\n");

// Extract hash keys from the dictionary.
List<string> mediaFilesList = docFxRepo._imageRefs.Keys.ToList();
List<string> mediaFilesList = [.. docFxRepo._imageRefs.Keys];

if (mediaFilesList.Count == 0)
{
Expand Down
7 changes: 6 additions & 1 deletion cleanrepo/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ branding:
color: 'purple'
inputs:
function:
description: 'The function you want to run: FindOrphanedArticles, FindOrphanedImages, FindOrphanedIncludes, FindOrphanedSnippets, CatalogImages, CatalogImagesWithText, FilterImagesForText, ReplaceRedirectTargets, ReplaceWithRelativeLinks, or RemoveRedirectHops.'
description: 'The function you want to run: FindOrphanedArticles, FindOrphanedImages, FindOrphanedIncludes, FindOrphanedSnippets, ReplaceRedirectTargets, ReplaceWithRelativeLinks, or RemoveRedirectHops.'
required: true
docfx_directory:
description: 'The directory that contains the docfx.json file for the docset.'
Expand All @@ -18,6 +18,9 @@ inputs:
url_base_path:
description: 'The URL base path for your docset, for example, /dotnet or /windows/uwp.'
required: true
exclude_include_files:
description: 'A list of file names or paths that should never be considered orphaned.'
default: '[]'
runs:
using: docker
image: ../cleanrepo.Dockerfile
Expand All @@ -30,3 +33,5 @@ runs:
- ${{ inputs.target_directory }}
- '/Options:UrlBasePath'
- ${{ inputs.url_base_path }}
- '/Options:ExcludeOrphanedIncludeFiles'
- ${{ inputs.exclude_include_files }}
Loading