yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ica[Docs] Fix dead links when subsection title have underscore (#5662)0586e5ab4

master
8.6 KiB235 linesraw
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Text;
6namespace toc
7{
8    public class Builder
9    {
10        public static string getAnchorId(string title)
11        {
12            StringBuilder sb = new StringBuilder();
13            title = title.Trim().ToLower();
14
15            foreach (var ch in title)
16            {
17                if (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9'
18                    || ch == '-'|| ch =='_')
19                    sb.Append(ch);
20                else if (ch == ' ' )
21                    sb.Append('-');
22            }
23            return sb.ToString();
24        }
25
26        public class Node
27        {
28            public List<string> fileNamePrefix = new List<string>();
29            public string title;
30            public string shortTitle;
31            public string fileID;
32            public List<string> sections = new List<string>();
33            public List<string> sectionShortTitles = new List<string>();
34            public List<Node> children = new List<Node>();
35        }
36
37        public static void buildTOC(StringBuilder sb, Node n)
38        {
39            sb.AppendFormat("<li data-link=\"{0}\"><span>{1}</span>\n", n.fileID, n.shortTitle);
40            if (n.children.Count != 0)
41            {
42                sb.AppendLine("<ul class=\"toc_list\">");
43                foreach(var c in n.children)
44                    buildTOC(sb, c);
45                sb.AppendLine("</ul>");
46            }
47            else if (n.sections.Count != 0)
48            {
49                sb.AppendLine("<ul class=\"toc_list\">");
50                for (int i = 0; i < n.sections.Count; i++)
51                {
52                    var s = n.sections[i];
53                    var shortTitle = n.sectionShortTitles[i];
54                    sb.AppendFormat("<li data-link=\"{0}#{1}\"><span>{2}</span></li>\n", n.fileID, getAnchorId(s), shortTitle);
55                }
56                sb.AppendLine("</ul>");
57            }
58            sb.AppendLine("</li>");
59        }
60        public static string buildTOC(Node n)
61        {
62            StringBuilder sb = new StringBuilder();
63            sb.Append(@"<ul class=""toc_root_list"">");
64            buildTOC(sb, n);
65            sb.Append(@"</ul>");
66            return sb.ToString();
67        }
68
69        public static bool isChild(Node parent, Node child)
70        {
71            if (parent.fileNamePrefix.Count < child.fileNamePrefix.Count)
72            {
73                bool equal = true;
74                for (int k = 0; k < parent.fileNamePrefix.Count; k++)
75                {
76                    if (parent.fileNamePrefix[k] != child.fileNamePrefix[k])
77                    {
78                        equal = false;
79                        break;
80                    }
81                }
82                return equal;
83            }
84            return false;
85        }
86
87        public static string getNextNonEmptyLine(string[] lines, int i)
88        {
89            i++;
90            while (i < lines.Length)
91            {
92                if (lines[i].Trim().Length != 0)
93                    return lines[i];
94                i++;
95            }
96            return "";
97        }
98        const string shortTitlePrefix = "[//]: # (ShortTitle: ";
99
100        public static string maybeGetShortTitleImpl(string originalTitle, string[] lines, int line)
101        {
102            string nextLine = getNextNonEmptyLine(lines, line);
103            if (nextLine.StartsWith(shortTitlePrefix))
104            {
105                return nextLine.Substring(shortTitlePrefix.Length, nextLine.Length - shortTitlePrefix.Length - 1).Trim();
106            }
107            return originalTitle;
108        }
109
110        public static string escapeString(string input)
111        {
112            StringBuilder sb = new StringBuilder();
113            foreach (var ch in input)
114            {
115                if (ch == '<')
116                    sb.Append("&lt;");
117                else if (ch == '>')
118                    sb.Append("&gt;");
119                else
120                    sb.Append(ch);
121            }
122            return sb.ToString();
123        }
124        public static string maybeGetShortTitle(string originalTitle, string[] lines, int line)
125        {
126            string title = maybeGetShortTitleImpl(originalTitle, lines, line);
127            return escapeString(title);
128        }
129        public static string Run(string path)
130        {
131            StringBuilder outputSB = new StringBuilder();
132            outputSB.AppendFormat("Building table of contents from {0}...\n", path);
133            var files = System.IO.Directory.EnumerateFiles(path, "*.md").OrderBy(f => System.IO.Path.GetFileName(f));
134            List<Node> nodes = new List<Node>();
135            foreach (var f in files)
136            {
137                var content = File.ReadAllLines(f);
138                Node node = new Node();
139                node.fileID = Path.GetFileNameWithoutExtension(f);
140                outputSB.AppendFormat("  {0}.md\n", node.fileID);
141                bool mainTitleFound = false;
142                for (int i = 1; i < content.Length; i++)
143                {
144                    if (content[i].StartsWith("==="))
145                    {
146                        mainTitleFound = true;
147                        node.title = content[i-1];
148                        node.shortTitle = maybeGetShortTitle(node.title, content, i);
149                    }
150                    if (content[i].StartsWith("---"))
151                    {
152                        if (!mainTitleFound) continue;
153                        node.sections.Add(content[i-1]);
154                        node.sectionShortTitles.Add(maybeGetShortTitle(content[i - 1], content, i));
155                    }
156                    if (content[i].StartsWith("#") && !content[i].StartsWith("##") && node.title == null)
157                    {
158                        mainTitleFound = true;
159                        node.title = content[i].Substring(1, content[i].Length - 1).Trim();
160                        node.shortTitle = maybeGetShortTitle(node.title, content, i);
161                    }
162                    if (content[i].StartsWith("##") && !content[i].StartsWith("###"))
163                    {
164                        if (!mainTitleFound) continue;
165                        var sectionStr = content[i].Substring(2, content[i].Length - 2).Trim();
166                        node.sections.Add(sectionStr);
167                        node.sectionShortTitles.Add(maybeGetShortTitle(sectionStr, content, i));
168                    }
169                    if (content[i].StartsWith("permalink:"))
170                    {
171                        var prefixLength = ("permalink:").Length;
172                        var permaPath = content[i].Substring(prefixLength, content[i].Length - prefixLength).Trim();
173                        node.fileID = Path.GetFileName(permaPath);
174                    }
175                }
176                if (node.title == null)
177                {
178                    outputSB.AppendFormat("Error: {0} does not define a title.", f);
179                    node.title = "Untitiled";
180                }
181                var titleSecs = Path.GetFileName(f).Split('-');
182                foreach (var s in titleSecs)
183                {
184                    if (s.Length == 2 && s[1]>='0' && s[1] <= '9')
185                    {
186                        node.fileNamePrefix.Add(s);
187                    }
188                    else
189                    {
190                        break;
191                    }
192                }
193                // Find parent node.
194                Node parent=null;
195                for (int l = nodes.Count-1; l>=0; l--)
196                {
197                    var n = nodes[l];
198                    if (isChild(n, node))
199                    {
200                       parent = n;
201                       break;
202                    }
203                }
204                if (parent != null)
205                    parent.children.Add(node);
206                else
207                {
208                    // find child
209                    foreach (var other in nodes)
210                    {
211                        if (isChild(node, other))
212                        {
213                            node.children.Add(other);
214                        }
215                    }
216                    foreach (var c in node.children)
217                    {
218                        nodes.Remove(c);
219
220                    }
221                    nodes.Add(node);
222                }
223            }
224            var root = nodes.Find(x=>x.fileID=="index");
225            if (root != null)
226            {
227                var html = buildTOC(root);
228                var outPath = Path.Combine(path, "toc.html");
229                File.WriteAllText(outPath, html);
230                outputSB.AppendFormat("Output written to: {0}\n", outPath);
231            }
232            return outputSB.ToString();
233        }
234    }
235}