/grpc/
。当以/
结尾或为空值时,自动添加index
。然后得到路径/grpc/index
。
如果存在多语言
,则于路径末尾添加.{lang}
, {lang}
为当前语言值
。最后于末尾添加.md
扩展名 。得到路径/grpc/index.zh-cn.md
。
如果存在路径地址,则于路径前添加/{path}
路径地址
。得到路径/docs/grpc/index.zh-cn.md
。
如果存在多版本
, 则于路径前添加/{version}
,{version}
为版本路径
。得到路径/main/docs/grpc/index.zh-cn.md
最后于路径前添加{baseUrl}
基础地址
。得到路径https://raw.githubusercontent.com/who/project/main/docs/grpc/index.zh-cn.md
。
DocMarkdown将请求该地址以获取Markdown文档内容并解析生成Html内容展现出来 。
解析与渲染markdig
能解析Markdown
内容并返回一系列不同类型的对象,根据这些对象的类型,我们可以生成想要的内容对应的Razor组件
定义一个MarkdownRenderer
用于解析对应类型的对象
public abstract class MarkdownRenderer{public abstract bool CanRender(MarkdownObject markdown);public abstract object Render(IMarkdownRenderContext context, MarkdownObject markdown);}public abstract class MarkdownRenderer<T> : MarkdownRendererwhere T : MarkdownObject{public override bool CanRender(MarkdownObject markdown){return markdown is T;}public override object Render(IMarkdownRenderContext context, MarkdownObject markdown){return Render(context, (T)markdown);}protected abstract object Render(IMarkdownRenderContext context, T markdown);}
为什么返回object类型?这是由于Markdown
里支持HTML
内容,而markdig
返回行内HTML
内容时,会将一个元素拆成两个IarkdownRender
。一个是开头,例如<span>
,一个是结尾,例如</span>
。
渲染Block和Inline
public RenderFragment RenderBlock(ContainerBlock containerBlock){return new RenderFragment(builder =>{int i = 0;foreach (var block in containerBlock){var obj = Render(block);if (obj is RenderFragment fragment)builder.AddContent(i, fragment);else if (obj is MarkupString markup)builder.AddContent(i, markup);else if (obj is HtmlElement html){if (html.IsEnd)builder.CloseComponent();else{builder.OpenElement(i, html.Tag);i++;if (html.Attributes != null){foreach (var attr in html.Attributes){if (attr.Value =https://www.huyubaike.com/biancheng/= null)builder.AddAttribute(i, attr.Key);elsebuilder.AddAttribute(i, attr.Key, attr.Value);i++;}}if (html.IsSelfClose)builder.CloseElement();}}elsebuilder.AddContent(i, obj);i++;}});}public RenderFragment RenderInline(ContainerInline containerInline){return new RenderFragment(content =>{var inline = containerInline.FirstChild;int i = 0;while (inline != null){var obj = Render(inline);if (obj is RenderFragment fragment)content.AddContent(i, fragment);else if (obj is MarkupString markup)content.AddContent(i, markup);else if (obj is HtmlElement html){if (html.IsEnd)content.CloseComponent();else{content.OpenElement(i, html.Tag);i++;if (html.Attributes != null){foreach (var attr in html.Attributes){if (attr.Value == null)content.AddAttribute(i, attr.Key);elsecontent.AddAttribute(i, attr.Key, attr.Value);i++;}}if (html.IsSelfClose)content.CloseElement();}}elsecontent.AddContent(i, obj);inline = inline.NextSibling;i++;}});}
渲染整个Markdown
文档
private void RenderMarkdown(RenderHandle renderHandle, MarkdownDocument document){var content = RenderBlock(document);renderHandle.Render(builder =>{builder.OpenComponent<LayoutView>(0);builder.AddAttribute(1, nameof(LayoutView.Layout), typeof(MainLayout));builder.AddAttribute(2, nameof(LayoutView.ChildContent), (RenderFragment)(child =>{child.OpenComponent<Index>(0);child.AddAttribute(1, "Content", content);child.CloseComponent();}));builder.CloseComponent();});}
加载为了加快加载速度,按照官方文档,改为加载Brotli
压缩后的文件并增加加载进度动画
<div id="app"><div class="position-fixed" style="bottom: 0; top: 0; left: 0; right: 0;"><div class="d-flex flex-column justify-content-center align-items-center h-100"><div style="width: 64px; height: 64px;"><svg viewBox="0 0 21 24"><path fill="transparent" d="M4.5,19.5A1.5,1.5,0,0,0,6,21H18.08V18H6A1.51,1.51,0,0,0,4.5,19.5Z" transform="translate(-1.5)" /><path fill="#1296db" d="M21.39,18a1.12,1.12,0,0,0,1.12-1.12V1.13A1.13,1.13,0,0,0,21.38,0H6A4.5,4.5,0,0,0,1.5,4.5v15A4.5,4.5,0,0,0,6,24H21.38a1.13,1.13,0,0,0,1.13-1.13v-.76A1.12,1.12,0,0,0,21.39,21h-.3V18Zm-4.14-4.54-2.93-4h1.79V5h2.3V9.42h1.79ZM13.29,5v8.52H11V8.91L8.94,11.54,6.89,8.91v4.64H4.59V5H6.95l2,3.22,2-3.22Zm4.79,16H6a1.5,1.5,0,0,1,0-3H18.08Z" transform="translate(-1.5)" /></svg></div><div class="w-50"><div class="progress" style="margin-top: 32px;"><div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">0%</div></div></div></div></div></div>
推荐阅读
- 如何破解压缩包的密码从网盘里面下载了一个压缩包,解压的时候需要输入密码,不知道密码是什么,该怎么
- 一 我要涨知识 —— TypeScript 常见面试题
- 克妻的男人面相特点有哪些,这4类男人千万不要嫁
- e笔画怎么写-E的正确笔顺怎么写?
- DNF怎么打红字(dnf武器有必要打红字么)
- 原神珊瑚宫心海突破材料需要哪些
- 原神钟离突破材料需要哪些
- 设计得什么填词语|设计写出搭配合适的词语
- 想开发DAYU200,我教你
- 这是你需要的初级钢琴教程汇总 练习曲篇