diff --git a/Action/.env-example b/Action/.env-example
index 843e666..99bec81 100644
--- a/Action/.env-example
+++ b/Action/.env-example
@@ -9,4 +9,5 @@ License=all-rights-reserved
PublicationId=123456789
PublicationName=Philips Tech Blog
NotifyFollowers=true
-File=
\ No newline at end of file
+File=
+ParseFrontmatter=false
\ No newline at end of file
diff --git a/Action/PostMediumGitHubAction.csproj b/Action/PostMediumGitHubAction.csproj
index 3ccf70a..46dd07a 100644
--- a/Action/PostMediumGitHubAction.csproj
+++ b/Action/PostMediumGitHubAction.csproj
@@ -11,7 +11,9 @@
+
+
\ No newline at end of file
diff --git a/Action/Properties/launchSettings.json b/Action/Properties/launchSettings.json
index 90a8416..66ada68 100644
--- a/Action/Properties/launchSettings.json
+++ b/Action/Properties/launchSettings.json
@@ -1,6 +1,6 @@
{
"profiles": {
- "PostMediumGitHubAction2": {
+ "PostMediumGitHubAction": {
"commandName": "Project"
},
"Docker": {
diff --git a/Action/Services/ConfigureService.cs b/Action/Services/ConfigureService.cs
index 44b8059..0a07d74 100644
--- a/Action/Services/ConfigureService.cs
+++ b/Action/Services/ConfigureService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using CommandLine;
@@ -7,6 +8,9 @@ namespace PostMediumGitHubAction.Services
{
internal class ConfigureService
{
+ public ConfigureService()
+ {
+ }
public ConfigureService(string[] args)
{
ConfigureApplication(args);
@@ -31,6 +35,7 @@ private void ConfigureApplication(string[] args)
Program.Settings.PublicationName =
Environment.GetEnvironmentVariable(nameof(Program.Settings.PublicationName));
Program.Settings.PublishStatus = Environment.GetEnvironmentVariable(nameof(Program.Settings.PublishStatus));
+ Program.Settings.ParseFrontmatter = Convert.ToBoolean(Environment.GetEnvironmentVariable(nameof(Program.Settings.ParseFrontmatter)));
Program.Settings.Tags = Environment.GetEnvironmentVariable(nameof(Program.Settings.Tags))?.Split(',');
Program.Settings.Title = Environment.GetEnvironmentVariable(nameof(Program.Settings.Title));
@@ -53,6 +58,42 @@ private void ConfigureApplication(string[] args)
Program.Settings.ContentFormat = Program.Settings.ContentFormat?.ToLower();
}
+ ///
+ /// Override Program Settings with values from parameter if they are not null.
+ ///
+ /// Settings to replace Program settings with
+ public void OverrideSettings(Settings settingsToReplace)
+ {
+ if (settingsToReplace.CanonicalUrl != null)
+ {
+ Program.Settings.CanonicalUrl = settingsToReplace.CanonicalUrl;
+ }
+
+ if (settingsToReplace.ContentFormat != null)
+ {
+ Program.Settings.ContentFormat = settingsToReplace.ContentFormat;
+ }
+
+ if (settingsToReplace.Tags.Any())
+ {
+ Program.Settings.Tags = settingsToReplace.Tags;
+ }
+
+ if (settingsToReplace.License != null)
+ {
+ Program.Settings.License = settingsToReplace.License;
+ }
+
+ if (settingsToReplace.PublishStatus != null)
+ {
+ Program.Settings.PublishStatus = settingsToReplace.PublishStatus;
+ }
+
+ if (settingsToReplace.Title != null)
+ {
+ Program.Settings.Title = settingsToReplace.Title;
+ }
+ }
///
/// Checks if settings are filled in correctly.
///
diff --git a/Action/Services/MediumService.cs b/Action/Services/MediumService.cs
index 5306ebb..2cb2c44 100644
--- a/Action/Services/MediumService.cs
+++ b/Action/Services/MediumService.cs
@@ -5,12 +5,19 @@
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
+using Markdig;
+using Markdig.Extensions.Yaml;
+using Markdig.Renderers;
+using Markdig.Syntax;
using PostMediumGitHubAction.Domain;
+using YamlDotNet.Serialization;
+using YamlDotNet.Serialization.NamingConventions;
namespace PostMediumGitHubAction.Services
{
public class MediumService
{
+ private ConfigureService _configureService = new ConfigureService();
public async Task SubmitNewContentAsync()
{
User user = await GetCurrentMediumUserAsync();
@@ -20,11 +27,56 @@ public async Task SubmitNewContentAsync()
if (!string.IsNullOrEmpty(Program.Settings.File))
Program.Settings.Content = await ReadFileFromPath(Program.Settings.File);
+ if (Program.Settings.ContentFormat == "markdown" && Program.Settings.ParseFrontmatter)
+ {
+ await ParseFrontmatter(Program.Settings.Content);
+ }
MediumCreatedPost post = await CreateNewPostUnderPublicationAsync(pub.Id);
SetWorkflowOutputs(post);
}
+ ///
+ /// Parse markdown content and look for frontmatter.
+ /// Convert the markdown into HTML to remove the frontmatter.
+ ///
+ /// Content in markdown
+ ///
+ private async Task ParseFrontmatter(string content)
+ {
+ MarkdownPipeline pipeline = new MarkdownPipelineBuilder()
+ .UseYamlFrontMatter()
+ .Build();
+
+ StringWriter writer = new StringWriter();
+ HtmlRenderer renderer = new HtmlRenderer(writer);
+ pipeline.Setup(renderer);
+
+ MarkdownDocument document = Markdown.Parse(content, pipeline);
+
+ // extract the front matter from markdown document
+ YamlFrontMatterBlock yamlBlock = document.Descendants().FirstOrDefault();
+
+ if (yamlBlock != null)
+ {
+ string yaml = yamlBlock.Lines.ToString();
+
+ // deserialize the yaml block into a custom type
+ IDeserializer deserializer = new DeserializerBuilder()
+ .WithNamingConvention(PascalCaseNamingConvention.Instance)
+ .Build();
+
+ Settings metadata = deserializer.Deserialize(yaml);
+ _configureService.OverrideSettings(metadata);
+ // finally we can render the markdown content as html if necessary
+ renderer.Render(document);
+ await writer.FlushAsync();
+ string html = writer.ToString();
+ Program.Settings.Content = html;
+ Program.Settings.ContentFormat = "html";
+ }
+ }
+
///
/// Retrieves current authenticated user
///
@@ -79,7 +131,7 @@ public async Task CreateNewPostUnderPublicationAsync(string p
Content = Program.Settings.Content,
ContentFormat = Program.Settings.ContentFormat,
PublishStatus = Program.Settings.PublishStatus,
- Tags = (string[])Program.Settings.Tags,
+ Tags = Program.Settings.Tags as string[],
Title = Program.Settings.Title
};
HttpResponseMessage response = await Program.Client.PostAsync($"publications/{publicationId}/posts",
diff --git a/Action/Settings.cs b/Action/Settings.cs
index 78fc2a3..4b5de87 100644
--- a/Action/Settings.cs
+++ b/Action/Settings.cs
@@ -58,5 +58,9 @@ public class Settings
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;
}
}
\ No newline at end of file
diff --git a/README.md b/README.md
index a5e57cb..5f75941 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
(back to top)
## State
-> Functional, but work in progress. Use at your own risk.
+> Functional
## Usage
@@ -34,14 +34,14 @@ The easiest way to use this action is to add the following into your workflow fi
1. Add the following part in your workflow file:
- ```yaml
+ ```
jobs:
post-to-medium:
name: Post to Medium
runs-on: ubuntu-latest
steps:
- name: Create Medium Post
- uses: philips-software/post-to-medium-action@v0.2
+ uses: philips-software/post-to-medium-action@v0.3
with:
integration_token: "${{ secrets.INTEGRATION_TOKEN }}"
content: "content here"
@@ -69,6 +69,7 @@ The easiest way to use this action is to add the following into your workflow fi
| canonical_url | The canonical URL of the post. If canonicalUrl was not specified in the creation of the post, this field will not be present. | `false` | |
| tags | The post’s tags. Provide a comma separated string without spaces. | `true` | |
| title | The post's title. | `true` | |
+| parse_frontmatter | 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. | `true` | false |
## Outputs
diff --git a/action.yaml b/action.yaml
index 0afbae5..f279bb6 100644
--- a/action.yaml
+++ b/action.yaml
@@ -47,6 +47,10 @@ inputs:
description: "The post's title."
required: true
default: ""
+ parse_frontmatter:
+ description: "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."
+ required: false
+ default: "false"
outputs:
id:
@@ -98,6 +102,8 @@ runs:
- ${{ inputs.content }}
- '--file'
- ${{ inputs.file }}
+ - '--parse-frontmatter'
+ - ${{ inputs.parse_frontmatter }}
branding: