-
Notifications
You must be signed in to change notification settings - Fork 867
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support to configure markdig extension by configuration.
- Loading branch information
Showing
16 changed files
with
902 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
src/Docfx.MarkdigEngine.Extensions/MarkdigExtensionSetting.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Diagnostics; | ||
using System.Text.Json; | ||
using System.Text.Json.Nodes; | ||
using System.Text.Json.Serialization; | ||
|
||
#nullable enable | ||
|
||
namespace Docfx.MarkdigEngine.Extensions; | ||
|
||
/// <summary> | ||
/// Markdig extension setting. | ||
/// </summary> | ||
[DebuggerDisplay(@"Name = {Name}")] | ||
[Newtonsoft.Json.JsonConverter(typeof(MarkdigExtensionSettingConverter))] | ||
public class MarkdigExtensionSetting | ||
{ | ||
private static readonly JsonSerializerOptions DefaultSerializerOptions = new() | ||
{ | ||
AllowTrailingCommas = true, | ||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||
Converters = { | ||
new JsonStringEnumConverter() | ||
}, | ||
}; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="MarkdigExtensionSetting"/> class. | ||
/// </summary> | ||
public MarkdigExtensionSetting(string name, JsonObject? options = null) | ||
{ | ||
Name = name; | ||
if (options != null) | ||
{ | ||
Options = options.Deserialize<JsonElement>(); | ||
} | ||
else | ||
{ | ||
Options = null; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Name of markdig extension | ||
/// </summary> | ||
public string Name { get; init; } | ||
|
||
/// <summary> | ||
/// Options of markdig extension. | ||
/// This option is storead as immutable JsonElement object. | ||
/// </summary> | ||
public JsonElement? Options { get; init; } | ||
|
||
/// <summary> | ||
/// Gets markdig extension options as specified class object. | ||
/// </summary> | ||
public T GetOptions<T>(T fallbackValue) | ||
{ | ||
if (Options == null) | ||
{ | ||
return fallbackValue; | ||
} | ||
|
||
var jsonObject = JsonSerializer.SerializeToNode(Options)?.AsObject(); | ||
|
||
if (jsonObject != null | ||
&& jsonObject.TryGetPropertyValue("options", out var optionsNode) | ||
&& optionsNode != null) | ||
{ | ||
return optionsNode.Deserialize<T>(DefaultSerializerOptions)!; | ||
} | ||
else | ||
{ | ||
return fallbackValue; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets markdig extension options as specified class object. | ||
/// </summary> | ||
public T GetOptionsValue<T>(string key, T fallbackValue) | ||
{ | ||
if (Options == null) | ||
{ | ||
return fallbackValue; | ||
} | ||
|
||
var jsonNode = JsonSerializer.SerializeToNode(Options)?.AsObject(); | ||
|
||
// Try to read options property that have specified key. | ||
if (jsonNode != null | ||
&& jsonNode.TryGetPropertyValue("options", out var optionsNode) | ||
&& optionsNode != null | ||
&& optionsNode.AsObject().TryGetPropertyValue(key, out var valueNode)) | ||
{ | ||
return valueNode!.GetValue<T>()!; | ||
} | ||
else | ||
{ | ||
return fallbackValue; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Allow implicit cast from markdig extension name. | ||
/// </summary> | ||
public static implicit operator MarkdigExtensionSetting(string name) | ||
{ | ||
return new MarkdigExtensionSetting(name); | ||
} | ||
} |
96 changes: 96 additions & 0 deletions
96
src/Docfx.MarkdigEngine.Extensions/MarkdigExtensionSettingConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using Newtonsoft.Json.Linq; | ||
using Newtonsoft.Json; | ||
|
||
namespace Docfx.MarkdigEngine.Extensions; | ||
|
||
internal class MarkdigExtensionSettingConverter : Newtonsoft.Json.JsonConverter | ||
{ | ||
// JsonSerializerOptions that used to deserialize MarkdigExtension options. | ||
internal static readonly System.Text.Json.JsonSerializerOptions DefaultSerializerOptions = new() | ||
{ | ||
IncludeFields = true, | ||
AllowTrailingCommas = true, | ||
DictionaryKeyPolicy = System.Text.Json.JsonNamingPolicy.CamelCase, | ||
PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase, | ||
PropertyNameCaseInsensitive = true, | ||
Converters = { | ||
new System.Text.Json.Serialization.JsonStringEnumConverter() | ||
}, | ||
WriteIndented = false, | ||
}; | ||
|
||
/// <inheritdoc/> | ||
public override bool CanConvert(Type objectType) | ||
{ | ||
return objectType == typeof(MarkdigExtensionSetting); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||
{ | ||
// var value = reader.Value; | ||
switch (reader.TokenType) | ||
{ | ||
case JsonToken.String: | ||
{ | ||
var name = (string)reader.Value; | ||
return new MarkdigExtensionSetting(name); | ||
} | ||
case JsonToken.StartObject: | ||
{ | ||
var jObj = JObject.Load(reader); | ||
|
||
var props = jObj.Properties().ToArray(); | ||
|
||
// Object key must be the name of markdig extension. | ||
if (props.Length != 1) | ||
return null; | ||
|
||
var prop = props[0]; | ||
var name = prop.Name; | ||
|
||
var options = prop.Value; | ||
if (options.Count() == 0) | ||
{ | ||
return new MarkdigExtensionSetting(name); | ||
} | ||
|
||
// Serialize options to JsonElement. | ||
var jsonElement = System.Text.Json.JsonSerializer.SerializeToElement(options, DefaultSerializerOptions); | ||
|
||
return new MarkdigExtensionSetting(name) | ||
{ | ||
Options = jsonElement, | ||
}; | ||
} | ||
|
||
default: | ||
return null; | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||
{ | ||
if (value == null) | ||
return; | ||
|
||
var model = (MarkdigExtensionSetting)value; | ||
|
||
if (model.Options == null || !model.Options.HasValue) | ||
{ | ||
writer.WriteValue(model.Name); | ||
} | ||
else | ||
{ | ||
writer.WriteStartObject(); | ||
writer.WritePropertyName(model.Name); | ||
var json = model.Options.ToString(); | ||
writer.WriteRawValue(json); | ||
writer.WriteEndObject(); | ||
} | ||
} | ||
} |
Oops, something went wrong.