{"简介": {"Path": "index"},"快速使用": {"Path": "quick"},"高级": {"Children": {"内容A": {"Path": "advanced/content1"},"内容B": {"Path": "advanced/content2"}}}}
导航文件的内容将被解析生成树形结构展示于页面 。
节点名称$.{name}
属性名称将作为导航目录的树形节点名 。属性值为对象 , 不能为空 。可以存在多个节点 。
节点路径$.{name}.Path
属性作为该节点对应的文档路径 , 路径为相对路径 。属性可以不存在 。不存在或为空时 , 只作为可折叠节点 , 点击不会导航至其它页面 。
节点子项$.{name}.Children
属性作为该节点的子项容器 , 里面包含了该节点下的所有子节点内容 。属性可以不存在 。
可以组合多层树形导航目录 。
{"一级目录1": {"Path": "c1"},"一级目录2": {"Path": "c2"},"一级目录3": {"Children": {"二级目录1": {"Path": "c3/c1"},"二级目录2": {"Children": {"三级目录1": {"Path": "c3/c2/c1"},"三级目录2": {"Path": "c3/c2/c2"}}}}}}
文档路径规则基于配置 , DocMarkdown会将网站的路径映射至目标文档 。例如/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++;}});}
经验总结扩展阅读
- 客厅隔断材质都有哪些 客厅隔断设计要点是什么
- 矮的拼音怎么写 矮的解释是什么
- 毒五月的九毒日是哪几天
- 安装电视机挂架方法 这几点一定要注意到
- 空调加氟收费标准 如何判断空调是否需要加氟
- 痛风的症状以及治疗方法
- 2023年广州毕业生创业补贴怎么申请 广州毕业生创业补贴社保要求吗
- 夏普和三星电视哪个好 好质量要会选
- 如何选购电视机 选购电视时要注意什么
- 噫的拼音怎么写 噫的解释是什么