Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: backport triple colon extension updates #9000

Merged
merged 2 commits into from
Jul 22, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ namespace Docfx.MarkdigEngine.Extensions;
public class ChromelessFormExtension : ITripleColonExtensionInfo
{
public string Name => "form";

public bool SelfClosing => true;

public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, out IDictionary<string, string> renderProperties, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
public bool IsInline => false;

public bool IsBlock => true;

public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
{
htmlAttributes = null;
renderProperties = new Dictionary<string, string>();
var model = string.Empty;
var action = string.Empty;
var submitText = string.Empty;
var model = "";
var action = "";
var submitText = "";
foreach (var attribute in attributes)
{
var name = attribute.Key;
Expand All @@ -33,46 +37,44 @@ public bool TryProcessAttributes(IDictionary<string, string> attributes, out Htm
action = value;
break;
case "submittext":
submitText = WebUtility.HtmlEncode(value);
submitText = value;
break;
default:
logError($"Unexpected attribute \"{name}\".");
return false;
}
}

if (action == string.Empty)
if (string.IsNullOrEmpty(action))
{
logError("Form action must be specified.");
return false;
}
if (submitText == string.Empty)
if (string.IsNullOrEmpty(submitText))
{
logError("Submit text must be specified.");
return false;
}

htmlAttributes = new HtmlAttributes();
if (model != string.Empty)
if (!string.IsNullOrEmpty(model))
{
htmlAttributes.AddProperty("data-model", model);
}
htmlAttributes.AddProperty("data-action", action);
htmlAttributes.AddClass("chromeless-form");

renderProperties.Add(new KeyValuePair<string, string>("submitText", submitText));

return true;
}

public bool Render(HtmlRenderer renderer, MarkdownObject markdownObject, Action<string> logWarning)
{
var block = (TripleColonBlock)markdownObject;
block.RenderProperties.TryGetValue("submitText", out var buttonText);
block.Attributes.TryGetValue("submitText", out var submitText);

renderer.Write("<form").WriteAttributes(block).WriteLine(">");
renderer.WriteLine("<div></div>");
renderer.WriteLine($"<button class=\"button is-primary\" disabled=\"disabled\" type=\"submit\">{buttonText}</button>");
renderer.WriteLine($"<button class=\"button is-primary\" disabled=\"disabled\" type=\"submit\">{WebUtility.HtmlEncode(submitText)}</button>");
renderer.WriteLine("</form>");

return true;
Expand All @@ -82,4 +84,4 @@ public bool TryValidateAncestry(ContainerBlock container, Action<string> logErro
{
return true;
}
}
}
68 changes: 39 additions & 29 deletions src/Docfx.MarkdigEngine.Extensions/TripleColon/CodeExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,50 @@ namespace Docfx.MarkdigEngine.Extensions;
public class CodeExtension : ITripleColonExtensionInfo
{
public string Name => "code";

public bool SelfClosing => true;
public bool EndingTripleColons => false;

public static bool EndingTripleColons => false;

public bool IsInline => false;

public bool IsBlock => true;

private readonly MarkdownContext _context;
private readonly HtmlCodeSnippetRenderer _codeSnippetRenderer;

public CodeExtension(MarkdownContext context)
{
_context = context;
_codeSnippetRenderer = new(_context);
}

public bool Render(HtmlRenderer renderer, MarkdownObject markdownObject, Action<string> logWarning)
{
var block = (TripleColonBlock)markdownObject;
block.Attributes.TryGetValue("id", out var currentId); //it's okay if this is null
block.Attributes.TryGetValue("range", out var currentRange); //it's okay if this is null
block.Attributes.TryGetValue("source", out var currentSource); //source has already been checked above
block.Attributes.TryGetValue("id", out var currentId); // it's okay if this is null
block.Attributes.TryGetValue("range", out var currentRange); // it's okay if this is null
block.Attributes.TryGetValue("source", out var currentSource); // source has already been checked above
var (code, codePath) = _context.ReadFile(currentSource, block);
if (string.IsNullOrEmpty(code))
{
logWarning($"The code snippet \"{currentSource}\" could not be found.");
return false;
}

//var updatedCode = GetCodeSnippet(currentRange, currentId, code, logError).TrimEnd();
var htmlCodeSnippetRenderer = new HtmlCodeSnippetRenderer(_context);
var snippet = new CodeSnippet(null);
snippet.CodePath = currentSource;
snippet.TagName = currentId;

HtmlCodeSnippetRenderer.TryGetLineRanges(currentRange, out var ranges);
snippet.CodeRanges = ranges;
var updatedCode = htmlCodeSnippetRenderer.GetContent(code, snippet);

var snippet = new CodeSnippet(null)
{
CodePath = currentSource,
TagName = currentId,
CodeRanges = ranges,
};

var updatedCode = _codeSnippetRenderer.GetContent(code, snippet);
updatedCode = ExtensionsHelper.Escape(updatedCode).TrimEnd();

if (updatedCode == string.Empty)
if (string.IsNullOrEmpty(updatedCode))
{
logWarning($"It looks like your code snippet was not rendered. Try range instead.");
return false;
Expand All @@ -57,17 +66,15 @@ public bool Render(HtmlRenderer renderer, MarkdownObject markdownObject, Action<
return true;
}

public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, out IDictionary<string, string> renderProperties, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
{

htmlAttributes = null;
renderProperties = new Dictionary<string, string>();
var source = string.Empty;
var range = string.Empty;
var id = string.Empty;
var highlight = string.Empty;
var language = string.Empty;
var interactive = string.Empty;
var source = "";
var range = "";
var id = "";
var highlight = "";
var language = "";
var interactive = "";

foreach (var attribute in attributes)
{
Expand Down Expand Up @@ -117,12 +124,20 @@ public bool TryProcessAttributes(IDictionary<string, string> attributes, out Htm
htmlAttributes.AddProperty("data-interactive", language);
htmlAttributes.AddProperty("data-interactive-mode", interactive);
}
if (!string.IsNullOrEmpty(highlight)) htmlAttributes.AddProperty("highlight-lines", highlight);
if (!string.IsNullOrEmpty(highlight))
{
htmlAttributes.AddProperty("highlight-lines", highlight);
}

return true;
}

private string InferLanguageFromFile(string source, Action<string> logError)
public bool TryValidateAncestry(ContainerBlock container, Action<string> logError)
{
return true;
}

private static string InferLanguageFromFile(string source, Action<string> logError)
{
var fileExtension = Path.GetExtension(source);
if (fileExtension == null)
Expand All @@ -136,9 +151,4 @@ private string InferLanguageFromFile(string source, Action<string> logError)
}
return language;
}

public bool TryValidateAncestry(ContainerBlock container, Action<string> logError)
{
return true;
}
}
90 changes: 46 additions & 44 deletions src/Docfx.MarkdigEngine.Extensions/TripleColon/ImageExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,24 @@ public class ImageExtension : ITripleColonExtensionInfo
private readonly MarkdownContext _context;

public string Name => "image";

public bool SelfClosing => true;

public bool IsInline => true;

public bool IsBlock => true;

public ImageExtension(MarkdownContext context)
{
_context = context;
}

public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, out IDictionary<string, string> renderProperties, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
public bool TryProcessAttributes(IDictionary<string, string> attributes, out HtmlAttributes htmlAttributes, Action<string> logError, Action<string> logWarning, MarkdownObject markdownObject)
{
htmlAttributes = null;
renderProperties = new Dictionary<string, string>();
var src = string.Empty;
var alt = string.Empty;
var type = string.Empty;
var loc_scope = string.Empty;
var src = "";
var alt = "";
var type = "";
foreach (var attribute in attributes)
{
var name = attribute.Key;
Expand All @@ -41,7 +44,7 @@ public bool TryProcessAttributes(IDictionary<string, string> attributes, out Htm
type = value;
break;
case "loc-scope":
loc_scope = value;
var loc_scope = value;
break;
case "source":
src = value;
Expand Down Expand Up @@ -73,29 +76,10 @@ public bool TryProcessAttributes(IDictionary<string, string> attributes, out Htm
}

// add loc scope missing/invalid validation here

if ((string.IsNullOrEmpty(alt) && type != "icon") || string.IsNullOrEmpty(src))
{
return false;
}
htmlAttributes = new HtmlAttributes();

// alt is allowed to be empty for icon type image
if (string.IsNullOrEmpty(alt) && type == "icon")
htmlAttributes.AddProperty("src", _context.GetLink(src, markdownObject));
else
htmlAttributes.AddProperty("src", _context.GetImageLink(src, markdownObject, alt));

if (type == "icon")
{
htmlAttributes.AddProperty("role", "presentation");
}
else
{
htmlAttributes.AddProperty("alt", alt);
}
var id = GetHtmlId(markdownObject);
if (type == "complex") htmlAttributes.AddProperty("aria-describedby", id);

return true;
}
Expand All @@ -108,19 +92,33 @@ public bool Render(HtmlRenderer renderer, MarkdownObject obj, Action<string> log
{
currentType = "content";
}
tripleColonObj.Attributes.TryGetValue("lightbox", out var currentLightbox); //it's okay if this is null
tripleColonObj.Attributes.TryGetValue("border", out var currentBorderStr); //it's okay if this is null
tripleColonObj.Attributes.TryGetValue("link", out var currentLink); //it's okay if this is null
if (!bool.TryParse(currentBorderStr, out var currentBorder))
tripleColonObj.Attributes.TryGetValue("lightbox", out var currentLightbox); // it's okay if this is null
tripleColonObj.Attributes.TryGetValue("border", out var currentBorderStr); // it's okay if this is null
tripleColonObj.Attributes.TryGetValue("link", out var currentLink); // it's okay if this is null
tripleColonObj.Attributes.TryGetValue("alt-text", out var alt); // it's okay if this is null
tripleColonObj.Attributes.TryGetValue("source", out var src); // it's okay if this is null

var htmlAttributes = new HtmlAttributes();

htmlAttributes.AddProperty("src", _context.GetImageLink(src, obj, alt));

if (currentType == "icon")
{
if (currentType == "icon")
{
currentBorder = false;
htmlAttributes.AddProperty("role", "presentation");
}
else
{
currentBorder = true;
htmlAttributes.AddProperty("alt", alt);
}
var htmlId = GetHtmlId(obj);
if (currentType == "complex")
{
htmlAttributes.AddProperty("aria-describedby", htmlId);
}

if (!bool.TryParse(currentBorderStr, out var currentBorder))
{
currentBorder = currentType != "icon";
}

if (currentBorder)
Expand All @@ -133,11 +131,13 @@ public bool Render(HtmlRenderer renderer, MarkdownObject obj, Action<string> log
{
renderer.WriteLine("<span class=\"mx-imgBorder\">");
}

}
else
{
if (tripleColonObj is Block) renderer.WriteLine("<p>");
if (tripleColonObj is Block)
{
renderer.WriteLine("<p>");
}
}
if (!string.IsNullOrEmpty(currentLink))
{
Expand All @@ -156,15 +156,14 @@ public bool Render(HtmlRenderer renderer, MarkdownObject obj, Action<string> log
}
if (currentType != "complex")
{
renderer.Write("<img").WriteAttributes(obj).WriteLine(">");
renderer.Write("<img").WriteAttributes(htmlAttributes).WriteLine(">");

if (tripleColonObj is ContainerBlock
&& (tripleColonObj as ContainerBlock).LastChild != null)
{
var inline = ((tripleColonObj as ContainerBlock).LastChild as ParagraphBlock).Inline;
renderer.WriteChildren(inline);
}

}
else
{
Expand All @@ -173,11 +172,10 @@ public bool Render(HtmlRenderer renderer, MarkdownObject obj, Action<string> log
logWarning("If type is \"complex\", then descriptive content is required. Please make sure you have descriptive content.");
return false;
}
var htmlId = GetHtmlId(obj);
renderer.Write("<img").WriteAttributes(obj).WriteLine(">");
renderer.WriteLine($"<div id=\"{htmlId}\" class=\"visually-hidden\">");
renderer.WriteChildren(tripleColonObj as ContainerBlock);
renderer.WriteLine("</div>");
renderer.Write("<img").WriteAttributes(htmlAttributes).WriteLine(">");
renderer.WriteLine($"<div id=\"{htmlId}\" class=\"visually-hidden\"><p>");
renderer.Write(tripleColonObj.Body);
renderer.WriteLine("</p></div>");
}
if (!string.IsNullOrEmpty(currentLightbox) || !string.IsNullOrEmpty(currentLink))
{
Expand All @@ -189,7 +187,11 @@ public bool Render(HtmlRenderer renderer, MarkdownObject obj, Action<string> log
}
else
{
if (currentBorder) renderer.WriteLine("</span>");
if (currentBorder)
{
renderer.WriteLine("</span>");
}

renderer.WriteChildren(tripleColonObj as ContainerInline);
}
return true;
Expand Down
Loading