Skip to content

Commit

Permalink
Merge pull request #31 from philips-software/chore/refactor-settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Brend-Smits authored Apr 13, 2023
2 parents 58291fa + 7d9e157 commit f66a194
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 61 deletions.
96 changes: 48 additions & 48 deletions Action/Domain/Settings.cs
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
using System.Collections.Generic;
using CommandLine;

namespace PostMediumGitHubAction.Domain
namespace PostMediumGitHubAction.Domain;

public class Settings
{
public class Settings
{
[Option('e', "title", Required = true, HelpText = "The post's title.")]
public string Title { get; set; }
[Option('e', "title", Required = false, HelpText = "The post's title.")]
public string Title { get; set; }

[Option('a', "tags", Required = true, HelpText = "The post’s tags.", Separator = ',')]
public IEnumerable<string> Tags { get; set; }
[Option('a', "tags", Required = false, HelpText = "The post’s tags.", Separator = ',')]
public IEnumerable<string> Tags { get; set; }

[Option('u', "canonical-url", Required = false, HelpText = "The canonical URL of the post. " +
"If canonicalUrl was not specified in the creation of the post, this field will not be present.")]
public string CanonicalUrl { get; set; }
[Option('u', "canonical-url", Required = false, HelpText = "The canonical URL of the post. " +
"If canonicalUrl was not specified in the creation of the post, this field will not be present.")]
public string CanonicalUrl { get; set; }

[Option('s', "publish-status", Required = false,
HelpText = "The publish status of the post. Valid values are: Draft, Public or Unlisted")]
public string PublishStatus { get; set; } = "draft";
[Option('s', "publish-status", Required = false,
HelpText = "The publish status of the post. Valid values are: Draft, Public or Unlisted")]
public string PublishStatus { get; set; }


[Option('l', "license", Required = false, HelpText =
"The license of the post. Valid values are all-rights-reserved, " +
"cc-40-by, cc-40-by-sa, cc-40-by-nd, cc-40-by-nc, cc-40-by-nc-nd, cc-40-by-nc-sa, cc-40-zero, public-domain.")]
public string License { get; set; } = "all-rights-reserved";
[Option('l', "license", Required = false, HelpText =
"The license of the post. Valid values are all-rights-reserved, " +
"cc-40-by, cc-40-by-sa, cc-40-by-nd, cc-40-by-nc, cc-40-by-nc-nd, cc-40-by-nc-sa, cc-40-zero, public-domain.")]
public string License { get; set; }

[Option('p', "publication-id", Required = false,
HelpText =
"The id of the publication the post is being created under. If you do not know the Id, use PublicationName")]
public string PublicationId { get; set; }
[Option('p', "publication-id", Required = false,
HelpText =
"The id of the publication the post is being created under. If you do not know the Id, use PublicationName")]
public string PublicationId { get; set; }

[Option('n', "publication-name", Required = false,
HelpText =
"The name of the publication the post is being created under. Either PublicationName of PublicationId should be set.")]
public string PublicationName { get; set; }
[Option('n', "publication-name", Required = false,
HelpText =
"The name of the publication the post is being created under. Either PublicationName of PublicationId should be set.")]
public string PublicationName { get; set; }

[Option('f', "notify-followers", Required = false,
HelpText = "Whether to notify followers that the user has published.")]
public bool NotifyFollowers { get; set; } = false;
[Option('f', "notify-followers", Required = false,
HelpText = "Whether to notify followers that the user has published.")]
public bool NotifyFollowers { get; set; }

[Option('o', "content-format", Required = true,
HelpText = "The format of the \"content\" field. There are two valid values, \"html\", and \"markdown\"")]
public string ContentFormat { get; set; }
[Option('o', "content-format", Required = true,
HelpText = "The format of the \"content\" field. There are two valid values, \"html\", and \"markdown\"")]
public string ContentFormat { get; set; }

[Option('c', "content", Required = false, HelpText =
"The body of the post, in a valid, semantic, HTML fragment, or Markdown. " +
"Further markups may be supported in the future. " +
"If you want your title to appear on the post page, you must also include it as part of the post content.")]
public string Content { get; set; }
[Option('c', "content", Required = false, HelpText =
"The body of the post, in a valid, semantic, HTML fragment, or Markdown. " +
"Further markups may be supported in the future. " +
"If you want your title to appear on the post page, you must also include it as part of the post content.")]
public string Content { get; set; }

[Option('i', "file", Required = false,
HelpText =
"Path to the file that should be read and used as content. If this is set, this will overrule the Content property.")]
public string File { get; set; }
[Option('i', "file", Required = false,
HelpText =
"Path to the file that should be read and used as content. If this is set, this will overrule the Content property.")]
public string File { get; set; }

[Option('t', "integration-token", Required = true,
HelpText =
"The token that should be used to authenticate in the API. Token can be retrieved at https://medium.com/me/settings under \"Integration Token\"")]
public string IntegrationToken { get; set; }
[Option('t', "integration-token", Required = true,
HelpText =
"The token that should be used to authenticate in the API. Token can be retrieved at https://medium.com/me/settings under \"Integration Token\"")]
public string IntegrationToken { get; set; }

[Option('m', "parse-frontmatter", Required = false,
HelpText = "Should the action read and delete frontmatter in a markdown file. Frontmatter should start with --- and end with ---. Should be on the top of the page. When parsing frontmatter, only markdown is supported and settings will be overwritten if specified in the frontmatter.")]
public bool ParseFrontmatter { get; set; } = false;
}
[Option('m', "parse-frontmatter", Required = false,
HelpText =
"Should the action read and delete frontmatter in a markdown file. Frontmatter should start with --- and end with ---. Should be on the top of the page. When parsing frontmatter, only markdown is supported and settings will be overwritten if specified in the frontmatter.")]
public bool ParseFrontmatter { get; set; }
}
28 changes: 16 additions & 12 deletions Action/Services/MediumService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public async Task<MediumCreatedPost> SubmitNewContentAsync()
/// </summary>
/// <param name="content">Content in markdown</param>
/// <returns></returns>
private async Task ParseFrontmatter(string content)
public async Task ParseFrontmatter(string content)
{
MarkdownPipeline pipeline = new MarkdownPipelineBuilder()
.UseYamlFrontMatter()
Expand All @@ -91,22 +91,26 @@ private async Task ParseFrontmatter(string content)
{
string yaml = yamlBlock.Lines.ToString();

try
// Define a list of naming conventions to support
INamingConvention[] supportedNamingConventions = new INamingConvention[]
{
// deserialize the yaml block into a custom type
IDeserializer deserializer = new DeserializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
Settings metadata = deserializer.Deserialize<Settings>(yaml);
_settings = _configureService.OverrideSettings(_settings, metadata);
}
catch (YamlException)
PascalCaseNamingConvention.Instance,
UnderscoredNamingConvention.Instance,
CamelCaseNamingConvention.Instance,
NullNamingConvention.Instance,
HyphenatedNamingConvention.Instance
};

foreach (INamingConvention namingConvention in supportedNamingConventions)
{
// Deserialize YAML with the current naming convention
IDeserializer deserializer = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.WithNamingConvention(namingConvention)
.IgnoreUnmatchedProperties()
.Build();
Settings metadata = deserializer.Deserialize<Settings>(yaml);

// Override settings with the deserialized metadata
_settings = _configureService.OverrideSettings(_settings, metadata);
}

Expand Down
26 changes: 25 additions & 1 deletion Tests/MediumServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
Expand Down Expand Up @@ -255,7 +256,7 @@ public async Task
IConfigureService configureService = new ConfigureService();
string[] args =
{
"-t", "validToken", "-e", "some-title", "-a", "tag", "-o", "markdown", "-n",
"-t", "validToken", "-o", "markdown", "-n",
"Philips Experience Design Blog", "--file", "test-with-unused-frontmatter.md", "--parse-frontmatter", "true"
};
Settings configuredSettings = configureService.ConfigureApplication(args);
Expand All @@ -280,6 +281,29 @@ public async Task
Assert.AreEqual("some-content", post.Title);
}

[Test]
public async Task
SubmitNewContentAsync_WithVariousNamingConventionsInFrontmatter_ShouldHaveProperSettingsAndCreatePostAsPublication()
{
IConfigureService configureService = new ConfigureService();
string[] args =
{
"-t", "validToken", "-o", "markdown", "-n",
"Philips Experience Design Blog", "--file", "test-with-various-naming-conventions.md",
"--parse-frontmatter", "true"
};
Settings configuredSettings = configureService.ConfigureApplication(args);
configuredSettings.Content =
"---\nTitle: \"Hello World\"\ndate: 2023-03-05T16:44:36+08:00\npublishdate: 2023-03-20T04:44:36+08:00\ncanonical_url: 'https://some-url.com'\nPublishStatus: 'unlisted'\ntags: ['helloworld']\ncomments: true\ndraft: true\n---\nHello world";
MediumService service = new(configuredSettings, new HttpClient());

Assert.DoesNotThrowAsync(async () => await service.ParseFrontmatter(configuredSettings.Content));
Assert.AreEqual("Hello World", configuredSettings.Title);
Assert.AreEqual("https://some-url.com", configuredSettings.CanonicalUrl);
Assert.AreEqual("unlisted", configuredSettings.PublishStatus);
Assert.AreEqual("helloworld", configuredSettings.Tags.First());
}

[Test]
public void SetWorkflowOutputs_WithMediumPost_ShouldSetOutputs()
{
Expand Down

0 comments on commit f66a194

Please sign in to comment.