/// <summary><!-- sort_files {{{1 --> /// - function to specify the order of the source files. /// </summary> public static List <string> sort_files(List <string> seq) { var ret1 = new SortedDictionary <int, string>(); var ret2 = new List <string>(); foreach (var fname in seq) { var n = extract_order_from_file(fname); if (!n.HasValue) { ret2.Add(fname); continue; } var n2 = n.Value * 10000; while (ret1.ContainsKey(n2)) { Log.warn("order {1} was already specified for {0}, " + "re-order it...", ret1[n2], n.Value); n2 += 1; } ret1.Add(n2, fname); } var ret3 = ret1.Values.ToList().Concat(ret2).ToList(); return(ret3); }
/// <summary><!-- extract_order_from_file --> /// - function to extract the orders of the source files. /// </summary> private static int?extract_order_from_file(string fname) { String txt; try { txt = System.IO.File.ReadAllText(fname); } catch (Exception) { return(null); } var n = txt.IndexOf("<" + "page>"); if (n == -1) { return(null); } Log.debg("page-order: page-tag detected: {0} in {1}", n, fname); txt = txt.Substring(n + 6); n = txt.IndexOf("<" + "/page>"); if (n == -1) { return(null); } txt = txt.Substring(0, n); Log.debg("page-order: /page detected: at {0} => {1}", n, txt); if (!Int32.TryParse(txt, out n)) { Log.eror("page-order: can't parse number: {0} in {1}, check it", txt, fname); return(null); } Log.info("page-order: extracted {0} for {1}.", n, fname); return(n); }
/// <summary> <!-- leave_tag {{{1 --> part of parse XML. /// the callback from XmlParser when parser found end of tags. /// </summary> public void leave_tag(string tagname) { if (tagname == "file") { if (tagname == this.tag_f) { this.tag_f = ""; } return; } if (tagname == "block") { Log.warn("XML:leave block: " + this.block_name); this.tag = ""; this.flash_output(); this.block_info.Clear(); return; } if (tagname != this.tag) { return; } if (cfg.tags_output.Contains(tagname)) { this.tag = ""; return; } if (cfg.tags_article.Contains(tagname)) { this.tag = ""; return; } }
/// <summary> <!-- flash_output {{{1 --> part of parse XML. /// append the cached block text into the markdown file. /// </summary> public void flash_output() { var blk = this.block; Log.debg("flash: {0}", blk.Count); if (blk.Count < 1) { Log.eror("block is empty(1): " + this.block_name); blk.Clear(); return; } var ret = strip_indent(blk); if (is_empty(ret)) { Log.eror("block is empty(2): " + this.block_name); if (!cfg.f_output_empty_block) { blk.Clear(); return; } } this.block_info.Add("name", this.block_name); var s = cfg.format_block_head(this.block_info); if (s.Length > 0) { TextFile.print(s); } TextFile.print(ret); blk.Clear(); }
/// <summary> <!-- chardata {{{1 --> parse XML /// the callback from XmlParser when parser found data block. /// </summary> /// <param name="data">data block contents as string</param> public void chardata(String data) { Log.debg("XML:chardata: {0}", data); if (this.tag.Length > 0) { this.block.Add(data); } }
/// <summary> <!-- strip_indent {{{1 --> part of parse XML, /// strip indent from content block. /// </summary> public string strip_indent(List <string> block) { var src = String.Join("", block); var lines = src.Split('\n'); var lin1 = ""; foreach (var line in lines) { lin1 = strip_comment(line); if (lin1.Trim().Length > 0) { break; } lin1 = ""; } var ind = 0; // can"t determine, reserve all text. if (lin1.Length > 0) { int n = -1; foreach (var ch in lin1) { n += 1; if (ch != ' ') { ind = n; break; } } } Log.eror("indent: {0}", ind); var ret = ""; foreach (var line in lines) { if (ret.Length < 1 && line.Length < 1) { continue; } if (line.Length < ind) { ret += line; } else { ret += line.Substring(ind); } ret += "\n"; } return(ret); }
/// <summary> <!-- enter_tag {{{1 --> part of parse XML. /// the callback from XmlParser when parser found begining of tags. /// </summary> /// <param name="tagname">begining tag name</param> /// <param name="attrs">attributes of the tag</param> public void enter_tag(string tagname, Dictionary <String, String> attrs ) { Log.debg("enter {0}", tagname); if (tagname == "block") { this.block_name = !attrs.ContainsKey("name") ? "": attrs["name"]; } if (cfg.tags_article.Contains(tagname) && attrs.ContainsKey(cfg.attr_article)) { Log.debg("detect tag-a {0}", tagname); if (this.block_info.ContainsKey(tagname)) { Log.eror("already detected {0}", tagname); } else { this.block_info.Add(tagname, "1"); } this.tag = tagname; } if (cfg.tags_output.Contains(tagname)) { Log.debg("detect tag-n {0}", tagname); if (this.block_info.ContainsKey(tagname)) { Log.eror("already detected {0}", tagname); } else { this.block_info.Add(tagname, "1"); } this.tag = tagname; } if (tagname == "file") { this.tag_f = tagname; var name = attrs.ContainsKey("name") ? attrs["name"]: ""; name = filename_relative(name); name = cfg.format_file_name(name); if (name.Length > 0) { TextFile.print(name); } } }
/// <summary> <!-- extract_plain_and_xml_output {{{1 --> parse_source /// - python version: can handle multi-encodings of documents. /// - C# version: did not handle multi-encodings, /// you must choose single encoding. /// </summary> /// <remarks> /// - strip triple slash lines from source `///` /// by `extract_plain_and_xml_text()` . /// </remarks> public static IEnumerable <string> extract_plain_and_xml_text( string fname ) { yield return("<file name=\"" + fname + "\">\n"); Log.debg("parse {0}...", fname); var block = new List <String>(); foreach (var line in System.IO.File.ReadAllLines(fname)) { /* try { // multi-encodings * lin = line.decode(cfg.enc); * } catch (UnicodeDecodeError) { * lin = line.decode(cfg.encs[1]); } */ var src = line.Trim(); var f = !src.StartsWith("///"); if (f && block.Count > 0) { var name = determine_function_name(line); name = SecurityElement.Escape(name); name = name.Length < 1 ? "<block>": String.Format("<block name=\"{0}\">", name); yield return(name + "\n"); foreach (var i in block) { var j = strip_comment(i); yield return(j + "\n"); } yield return("</block>\n"); block.Clear(); continue; } else if (f) { continue; } Log.debg("src:extracted: " + line); block.Add(line); } yield return("</file>\n"); }
/// <summary> <!-- filename_relative {{{1 --> utility, /// strip the directory of a root from path string. /// </summary> public string filename_relative(string path) { var droot = System.IO.Path.GetFullPath(this.dname_root); // var droot = System.IO.Path.GetDirectoryName( // System.Reflection.Assembly.GetEntryAssembly().Location); // droot = System.IO.Path.GetDirectoryName(droot); // .. // droot = System.IO.Path.GetDirectory(droot); // .. Log.debg("relative: directory root: {0}", droot); var _path = System.IO.Path.GetFullPath(path); Log.debg("relative: file-name : {0}", _path); if (_path.StartsWith(droot)) { _path = _path.Substring(droot.Length); } if (_path.StartsWith("/")) { _path = _path.Substring(1); } return(_path); }