目录
内容简介
园子里面很多博主都会为自己的博文创建目录,方便大家浏览。我很好奇大家是怎么做的,是不是有自动生成目录的工具可以推荐一下(我知道word可以,但是直接贴word文档会生成很多多余的html tag)。
前几天写前端网页最佳实践目录项实在有点多,手动加起来太麻烦了,我尝试搜了下没有找到,于是写了几行代码来完成这工作。拿出来分享给有同样需要的朋友。
工具代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | using System; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace HtmlIndexGenerator { class Program { const string HeaderPattern = @"<h(?<level>[1-6])[\s\S]*?>[\s\S]*?</h([1-6])>" ; const string TagPattern = @"<[\s\S]*?>" ; const string IdPattern = "(id|name)=\"(?<id>[\\s\\S]*?)\"" ; const int MaxHeaderLimit = 6; const string H1Style = @"font-weight:bold" ; const string H2Style = @"" ; const string H3Style = @"" ; const string H4Style = @"" ; const string H5Style = @"" ; const string H6Style = @"font-size:10px;" ; static string [] HeaderStyles = new string []{ H1Style, H2Style, H3Style, H4Style, H5Style, H6Style }; static void Main( string [] args) { string fileName; int limit; ParseParameter(args, out fileName, out limit); string html = GetHtml(fileName); if ( string .IsNullOrEmpty(html)) return ; string index = GenerateIndex(html, limit); string outputFile = "index.htm" ; File.WriteAllText(outputFile, index, Encoding.UTF8); Console.WriteLine( "{0} generated." , outputFile); } /// <summary> /// Prints help document. /// </summary> private static void PrintHelp() { Console.WriteLine( "Usage: IndexGen.exe [filename] [-l] level" ); Console.WriteLine( "-l: header level limit, -l 3 limit the output to <h3>" ); Console.WriteLine( "Example: IndexGen.exe page.htm" ); } /// <summary> /// Parses command line paramters. /// </summary> /// <param name="args">Input parameters</param> /// <param name="fileName">Output parameter for parsed file name. Null if parse failed.</param> /// <param name="limit">Output parameter for header level limit.</param> private static void ParseParameter( string [] args, out string fileName, out int limit) { fileName = null ; limit = MaxHeaderLimit; for ( int i = 0; i < args.Length; i++) { if (args[i].Equals( "-l" , StringComparison.InvariantCultureIgnoreCase)) { if (i + 1 >= args.Length || ! int .TryParse(args[i + 1], out limit)) { Console.WriteLine( "Invalid parameter for -l" ); PrintHelp(); return ; } } } if (args.Length > 0) { fileName = args[args.Length - 1]; } } /// <summary> /// Reads html content according to specified file name. /// </summary> /// <param name="fileName">File name</param> /// <returns>Html content of the specific file.</returns> private static string GetHtml( string fileName) { string html = null ; if ( string .IsNullOrEmpty(fileName)) { Console.WriteLine( "Specify a file name" ); PrintHelp(); return html; } if (!File.Exists(fileName)) { Console.WriteLine( "File {0} dose not exist" , fileName); PrintHelp(); return html; } // Auto defect file encoding. using (StreamReader reader = new StreamReader(fileName, detectEncodingFromByteOrderMarks: true )) { Encoding encoding = reader.CurrentEncoding; html = File.ReadAllText(fileName, encoding); } return html; } /// <summary> /// Generates the index html. /// </summary> /// <param name="html">Html content of specified file.</param> /// <param name="limit">Header limit</param> /// <returns>Generated index html</returns> private static string GenerateIndex( string html, int limit) { Regex regex = new Regex(HeaderPattern, RegexOptions.IgnoreCase); Regex regexId = new Regex(IdPattern, RegexOptions.IgnoreCase); MatchCollection headerMatches = regex.Matches(html); int previousLevel = 1; StringBuilder indexBuilder = new StringBuilder(); indexBuilder.Append( "<div id=\"doc-index\">" ); indexBuilder.Append( "<ul>" ); foreach (Match headerMatch in headerMatches) { int currentLevel = int .Parse(headerMatch.Groups[ "level" ].Value); string header = Regex.Replace(headerMatch.Value, TagPattern, string .Empty); Match idMatch = regexId.Match(headerMatch.Value); string id = idMatch.Success ? idMatch.Groups[ "id" ].Value : null ; string link = string .IsNullOrEmpty(id) ? header : string .Format( "<a href=\"#{0}\">{1}</a>" , id, header); if (currentLevel == previousLevel) { indexBuilder.AppendFormat( "<li style=\"{1}\">{0}</li>" , link, HeaderStyles[currentLevel - 1]); } else if (currentLevel > previousLevel && currentLevel <= limit) { indexBuilder.AppendFormat( "<ul><li style=\"{1}\">{0}</li>" , link, HeaderStyles[currentLevel - 1]); previousLevel = currentLevel; } else if (currentLevel < previousLevel) { indexBuilder.AppendFormat( "</ul><li style=\"{1}\">{0}</li>" , link, HeaderStyles[currentLevel - 1]); previousLevel = currentLevel; } } indexBuilder.Append( "</ul></div>" ); return indexBuilder.ToString(); } } } |
使用方法
将程序编译成执行文件,把博文存成本地文件,注意要存成unicode或utf-8,通过命令行运行。一个名叫index.htm的文件会生成在相同目录下。
如果你只希望限制生成目录的级数,可以用 -l 参数指定,-l 3代表只生成<h1> 到<h3>的目录。
双击打开后是这个样子,
接下来需要做的是将生成的内容复制粘贴到博文你想放目录的地方。简单的目录就生成了,参看本文目录。
如果你想更改样式,可以直接修改代码中对不同的header的样式定义。
工具改进
这只是个小工具,肯定有很多让小伙伴们惊呆的不足,
- 首先不应该用正则表达式解析html,具体原因可以看这里,如果真的要分析html,.net推荐使用htmlagilitypack,python推荐使用beautifulsoup,我这里不想再引入外部库,所以假设我们解析的html都是标准格式。
- 另外我没写代码去生成标题的id属性,因为很多朋友希望id是有意义的名字而不简单的header1、lable2之类的,所以id还是需要你自己添加,不然超链接出不来。 <h1 id="intro"></h1>
- 也尝试把这段代码转换成powershell脚本省了大家编译,这里有介绍如何做的方法,可惜插件也有硬伤,有些语法还不支持,比如using, out 参数等。
另外如果大家有好的工具也请推荐下,这里抛砖引玉了。
分类:
技术分享 - 工具使用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探