diff --git a/AeroNovelTool/src/AtxtProject.cs b/AeroNovelTool/src/AtxtProject.cs index 9d1e2d2..787cac3 100644 --- a/AeroNovelTool/src/AtxtProject.cs +++ b/AeroNovelTool/src/AtxtProject.cs @@ -6,246 +6,261 @@ public class AtxtProject { - public ProjectConfig config; - public string dir; - public List srcs = new List(); + public ProjectConfig config; + public string dir; + public List srcs = new List(); - public List src_paths = new List(); - public AtxtProject(string dir) - { - this.dir = dir; - if (File.Exists(Path.Combine(dir, "config.txt"))) - { - config = new ProjectConfig(File.ReadAllLines(Path.Combine(dir, "config.txt"))); - Log.Info("Read config.txt"); - } - } - public void CollectSource() - { - string[] files = Directory.GetFiles(dir); - foreach (string f in files) - { - Match m = Regex.Match(Path.GetFileName(f), AeroNovel.regStr_filename); - if (!m.Success) - { - m = Regex.Match(Path.GetFileName(f), AeroNovel.regStr_filename_xhtml); - if (!m.Success) { continue; } - } - src_paths.Add(f); - } - src_paths.Sort(); + public List src_paths = new List(); + public AtxtProject(string dir) + { + this.dir = dir; + if (File.Exists(Path.Combine(dir, "config.txt"))) + { + config = new ProjectConfig(File.ReadAllLines(Path.Combine(dir, "config.txt"))); + Log.Info("Read config.txt"); + } + } + public void CollectSource() + { + string[] files = Directory.GetFiles(dir); + foreach (string f in files) + { + Match m = Regex.Match(Path.GetFileName(f), AeroNovel.regStr_filename); + if (!m.Success) + { + m = Regex.Match(Path.GetFileName(f), AeroNovel.regStr_filename_xhtml); + if (!m.Success) { continue; } + } + src_paths.Add(f); + } + src_paths.Sort(); - foreach (string txt_path in src_paths) - { - var src = new AtxtSource(txt_path); - srcs.Add(src); - } - if (config != null && config.joinCommands.Count > 0) - { - Log.Info("Combine Source. Join blank lines: " + config.joinBlankLine); - foreach (var cmbcmd in config.joinCommands) - { - Log.Info($"{cmbcmd}"); - int startIndex = srcs.FindIndex(0, s => s.no.CompareTo(cmbcmd.start) == 0); - int endIndex = srcs.FindIndex(0, s => s.no.CompareTo(cmbcmd.end) == 0); - if (startIndex < 0 || endIndex < 0) - { - Log.Error("Failure: " + cmbcmd.ToString()); - continue; - } - string blankLines = new string('\n', config.joinBlankLine); - var contentToJoin = srcs.GetRange(startIndex, endIndex - startIndex + 1).Select(s => s.content); - string content = string.Join(blankLines, contentToJoin); - AtxtSource combined = new AtxtSource($"{cmbcmd.start}.atxt", cmbcmd.start, cmbcmd.title, content); - srcs.RemoveRange(startIndex, endIndex - startIndex + 1); - srcs.Insert(startIndex, combined); - } - } - } + foreach (string txt_path in src_paths) + { + var src = new AtxtSource(txt_path); + srcs.Add(src); + } + if (config != null && config.joinCommands.Count > 0) + { + Log.Info("Combine Source. Join blank lines: " + config.joinBlankLine); + foreach (var cmbcmd in config.joinCommands) + { + Log.Info($"{cmbcmd}"); + int startIndex = srcs.FindIndex(0, s => s.no.CompareTo(cmbcmd.start) == 0); + int endIndex = srcs.FindIndex(0, s => s.no.CompareTo(cmbcmd.end) == 0); + if (startIndex < 0 || endIndex < 0) + { + Log.Error("Failure: " + cmbcmd.ToString()); + continue; + } + string blankLines = new string('\n', config.joinBlankLine); + var contentToJoin = srcs.GetRange(startIndex, endIndex - startIndex + 1).Select(s => s.content); + string content = string.Join(blankLines, contentToJoin); + AtxtSource combined = new AtxtSource($"{cmbcmd.start}.atxt", cmbcmd.start, cmbcmd.title, content); + srcs.RemoveRange(startIndex, endIndex - startIndex + 1); + srcs.Insert(startIndex, combined); + } + } + } + public enum MacroMode + { + Epub, + Bbcode, + InlineHTML + } - public Dictionary macros; - public void LoadMacro() - { - if (File.Exists(Path.Combine(dir, "macros.txt"))) - { - Log.Info("Read macros.txt"); - string[] macros_raw = File.ReadAllLines(Path.Combine(dir, "macros.txt")); - macros = new Dictionary(); - foreach (string macro in macros_raw) - { - string[] s = macro.Split('\t'); - if (s.Length < 2) - { - Log.Warn("Macro defination is not complete. Use tab to separate: " + macro); - } - else if (s.Length == 2) - { - macros.Add(s[0], s[1]); - } - else//length>2 - { - macros.Add(s[0], s[2]); - } - } - } - } + public Dictionary macros; + public void LoadMacro(MacroMode mode) + { + int replacement = 1; + switch (mode) + { + case MacroMode.Bbcode: replacement = 2; break; + case MacroMode.InlineHTML: replacement = 3; break; + } + if (File.Exists(Path.Combine(dir, "macros.txt"))) + { + Log.Info("Read macros.txt"); + string[] macros_raw = File.ReadAllLines(Path.Combine(dir, "macros.txt")); + macros = new Dictionary(); + foreach (string macro in macros_raw) + { + string[] s = macro.Split('\t'); + if (s.Length < 2) + { + Log.Warn("Macro defination is not complete. Use tab to separate: " + macro); + } + else + { + if (s.Length <= replacement) + { + macros.Add(s[0], s[1]);//fallback to epub mode + } + else + { + macros.Add(s[0], s[replacement]); + } + } + } + } + } - public Dictionary web_images; - public void LoadWebImages() - { - web_images = new Dictionary(); - string path = Path.Combine(dir, "web_images"); - if (File.Exists(path + ".md")) - { - Log.Note("图床链接配置文档读取成功:" + path + ".md"); - string[] a = File.ReadAllLines(path + ".md"); - Regex md_img = new Regex("\\[(.+?)\\]\\((.+?)\\)"); - foreach (var x in a) - { - var b = md_img.Match(x); - if (b.Success) - { - web_images.Add(b.Groups[1].Value, b.Groups[2].Value); - } - } - } - if (File.Exists(path + ".txt")) - { - Log.Note("图床链接配置文档读取成功:" + path + ".txt"); - string[] a = File.ReadAllLines(path + ".txt"); - foreach (var x in a) - { - var b = x.Split(' '); - if (b.Length > 1) - { - web_images.Add(b[0], b[1]); - } - } - } + public Dictionary web_images; + public void LoadWebImages() + { + web_images = new Dictionary(); + string path = Path.Combine(dir, "web_images"); + if (File.Exists(path + ".md")) + { + Log.Note("图床链接配置文档读取成功:" + path + ".md"); + string[] a = File.ReadAllLines(path + ".md"); + Regex md_img = new Regex("\\[(.+?)\\]\\((.+?)\\)"); + foreach (var x in a) + { + var b = md_img.Match(x); + if (b.Success) + { + web_images.Add(b.Groups[1].Value, b.Groups[2].Value); + } + } + } + if (File.Exists(path + ".txt")) + { + Log.Note("图床链接配置文档读取成功:" + path + ".txt"); + string[] a = File.ReadAllLines(path + ".txt"); + foreach (var x in a) + { + var b = x.Split(' '); + if (b.Length > 1) + { + web_images.Add(b[0], b[1]); + } + } + } - } + } } public class AtxtSource { - public string content, path; - public string no, title, ext, xhtmlName; - public string[] lines - { - get - { - return content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); - } - } - public AtxtSource(string path) - { - this.path = path; - Match m = Regex.Match(Path.GetFileNameWithoutExtension(path), AeroNovel.regStr_filename_noext); - ext = Path.GetExtension(path); - no = m.Groups[1].Value; - title = Util.UrlDecode(m.Groups[2].Value); - xhtmlName = MapFileName(no, title); - content = File.ReadAllText(path); - } - public AtxtSource(string dummy_path, string no, string title, string content) - { - this.path = dummy_path; - ext = ".atxt"; - this.no = no; - this.title = Util.UrlDecode(title); - xhtmlName = MapFileName(no, title); - this.content = content; - } - public override string ToString() - { - return $"{no}{title}{ext}"; - } - string MapFileName(string no, string readableName) - { - string lowered = readableName; - string numberMap = "1①Ⅰ"; - foreach (char c in numberMap) - { - int block = (int)c - 1; - for (int i = 0; i <= 9; i++) - { - char numberChar = Convert.ToChar(block + i); - lowered = lowered.Replace(numberChar, (char)('0' + i)); - } - } - string trimmed = lowered.Replace(" ", ""); - //Name dic start - Dictionary name_dic = new Dictionary - { - {"序章","prologue"}, - {"终章","epilogue"}, - {"終章","epilogue"}, - {"序幕","prologue"}, - {"尾声","epilogue"}, - {"简介","summary"}, - {"簡介","summary"}, - {"後記","postscript"}, - {"后记","postscript"}, - {"目錄","toc"}, - {"目录","toc"}, - {"间章","interlude"}, - {"幕间","interlude"} - }; + public string content, path; + public string no, title, ext, xhtmlName; + public string[] lines + { + get + { + return content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + } + } + public AtxtSource(string path) + { + this.path = path; + Match m = Regex.Match(Path.GetFileNameWithoutExtension(path), AeroNovel.regStr_filename_noext); + ext = Path.GetExtension(path); + no = m.Groups[1].Value; + title = Util.UrlDecode(m.Groups[2].Value); + xhtmlName = MapFileName(no, title); + content = File.ReadAllText(path); + } + public AtxtSource(string dummy_path, string no, string title, string content) + { + this.path = dummy_path; + ext = ".atxt"; + this.no = no; + this.title = Util.UrlDecode(title); + xhtmlName = MapFileName(no, title); + this.content = content; + } + public override string ToString() + { + return $"{no}{title}{ext}"; + } + string MapFileName(string no, string readableName) + { + string lowered = readableName; + string numberMap = "1①Ⅰ"; + foreach (char c in numberMap) + { + int block = (int)c - 1; + for (int i = 0; i <= 9; i++) + { + char numberChar = Convert.ToChar(block + i); + lowered = lowered.Replace(numberChar, (char)('0' + i)); + } + } + string trimmed = lowered.Replace(" ", ""); + //Name dic start + Dictionary name_dic = new Dictionary + { + {"序章","prologue"}, + {"终章","epilogue"}, + {"終章","epilogue"}, + {"序幕","prologue"}, + {"尾声","epilogue"}, + {"简介","summary"}, + {"簡介","summary"}, + {"後記","postscript"}, + {"后记","postscript"}, + {"目錄","toc"}, + {"目录","toc"}, + {"间章","interlude"}, + {"幕间","interlude"} + }; - foreach (var k in name_dic) - { - if (trimmed.Contains(k.Key)) - { - return "atxt" + no + "_" + k.Value + ".xhtml"; + foreach (var k in name_dic) + { + if (trimmed.Contains(k.Key)) + { + return "atxt" + no + "_" + k.Value + ".xhtml"; - } - } - //name dic end + } + } + //name dic end - //chapter number - { - string t = trimmed; - string[] chapterNumberPatterns = new string[]{ - "^第([一二三四五六七八九十百零\\d]{1,10})", - "([一二三四五六七八九十百零\\d]{1,10})\\s", - "([一二三四五六七八九十百零\\d]{1,10})章" - }; - foreach (string pattern in chapterNumberPatterns) - { - var m_num = Regex.Match(t, pattern); - if (m_num.Success) - { - string chapterNumber = m_num.Groups[1].Value; - if (!char.IsDigit(chapterNumber[0])) chapterNumber = "" + Util.FromChineseNumber(chapterNumber); + //chapter number + { + string t = trimmed; + string[] chapterNumberPatterns = new string[]{ + "^第([一二三四五六七八九十百零\\d]{1,10})", + "([一二三四五六七八九十百零\\d]{1,10})\\s", + "([一二三四五六七八九十百零\\d]{1,10})章" + }; + foreach (string pattern in chapterNumberPatterns) + { + var m_num = Regex.Match(t, pattern); + if (m_num.Success) + { + string chapterNumber = m_num.Groups[1].Value; + if (!char.IsDigit(chapterNumber[0])) chapterNumber = "" + Util.FromChineseNumber(chapterNumber); - return "atxt" + no + "_chapter" + chapterNumber + ".xhtml"; - } - } - } - //chapter numder end + return "atxt" + no + "_chapter" + chapterNumber + ".xhtml"; + } + } + } + //chapter numder end - //just keep ascii - { - string t = lowered; - string name = "_"; - for (int i = 0; i < t.Length; i++) - { - if (t[i] < 128) - { - if (t[i] == ' ') - { - if (i == t.Length - 1) continue; - if (name.EndsWith('_')) continue; - name += '_'; continue; - } - if (t[i] == '_' && name.EndsWith('_')) continue; - name += t[i]; - } - } - if (name.EndsWith('_')) name = name.Substring(0, name.Length - 1); - return "atxt" + no + name + ".xhtml"; - } - } + //just keep ascii + { + string t = lowered; + string name = "_"; + for (int i = 0; i < t.Length; i++) + { + if (t[i] < 128) + { + if (t[i] == ' ') + { + if (i == t.Length - 1) continue; + if (name.EndsWith('_')) continue; + name += '_'; continue; + } + if (t[i] == '_' && name.EndsWith('_')) continue; + name += t[i]; + } + } + if (name.EndsWith('_')) name = name.Substring(0, name.Length - 1); + return "atxt" + no + name + ".xhtml"; + } + } } @@ -253,82 +268,82 @@ string MapFileName(string no, string readableName) public enum ConfigValue { - unset = 0, - active = 1, - disable = 2 + unset = 0, + active = 1, + disable = 2 } public class ProjectConfig { - public List joinCommands = new List(); - public int joinBlankLine = 0; - public ConfigValue indentAdjust; - public ConfigValue addInfo; + public List joinCommands = new List(); + public int joinBlankLine = 0; + public ConfigValue indentAdjust; + public ConfigValue addInfo; - public ProjectConfig(string[] content) - { - foreach (var line in content) - { - var sep = line.IndexOf(':'); - if (sep < 0) continue; - var cmd = line.Substring(0, sep); - var arg = line.Substring(sep + 1); - switch (cmd) - { - case "join": - joinCommands.Add(new JoinCommand(arg)); - break; - case "join_blank_line": - int.TryParse(arg, out joinBlankLine); - break; - case "indent_adjust": - indentAdjust = GetConfigValue(arg); break; - case "add_info": - addInfo = GetConfigValue(arg); break; - } - } - joinCommands.Sort((c1, c2) => c1.start.CompareTo(c2.start)); - } - ConfigValue GetConfigValue(string s) - { - s = s.ToLower(); - switch (s) - { - case "true": - case "yes": - case "1": - case "active": - case "enable": - return ConfigValue.active; - case "false": - case "no": - case "0": - case "disable": - return ConfigValue.disable; - default: - return ConfigValue.unset; + public ProjectConfig(string[] content) + { + foreach (var line in content) + { + var sep = line.IndexOf(':'); + if (sep < 0) continue; + var cmd = line.Substring(0, sep); + var arg = line.Substring(sep + 1); + switch (cmd) + { + case "join": + joinCommands.Add(new JoinCommand(arg)); + break; + case "join_blank_line": + int.TryParse(arg, out joinBlankLine); + break; + case "indent_adjust": + indentAdjust = GetConfigValue(arg); break; + case "add_info": + addInfo = GetConfigValue(arg); break; + } + } + joinCommands.Sort((c1, c2) => c1.start.CompareTo(c2.start)); + } + ConfigValue GetConfigValue(string s) + { + s = s.ToLower(); + switch (s) + { + case "true": + case "yes": + case "1": + case "active": + case "enable": + return ConfigValue.active; + case "false": + case "no": + case "0": + case "disable": + return ConfigValue.disable; + default: + return ConfigValue.unset; - } - } + } + } } public class JoinCommand { - public string start, end; - public bool used = false; - public string title; - static Regex regex = new Regex("([0-9]{2})-([0-9]{2})(.*)"); + public string start, end; + public bool used = false; + public string title; + static Regex regex = new Regex("([0-9]{2})-([0-9]{2})(.*)"); - public JoinCommand(string cmd) - { - var r = regex.Match(cmd); - if (!r.Success) throw new Exception("Join Command Fail: " + cmd); - start = r.Groups[1].Value; - end = r.Groups[2].Value; - title = r.Groups[3].Value; - } + public JoinCommand(string cmd) + { + var r = regex.Match(cmd); + if (!r.Success) throw new Exception("Join Command Fail: " + cmd); + start = r.Groups[1].Value; + end = r.Groups[2].Value; + title = r.Groups[3].Value; + } - public override string ToString() - { - return $"JoinCommand: {start}-{end} {title}"; - } + public override string ToString() + { + return $"JoinCommand: {start}-{end} {title}"; + } } \ No newline at end of file diff --git a/AeroNovelTool/src/func/GenBBcode.cs b/AeroNovelTool/src/func/GenBBcode.cs index 226c228..59848a9 100644 --- a/AeroNovelTool/src/func/GenBBcode.cs +++ b/AeroNovelTool/src/func/GenBBcode.cs @@ -13,7 +13,7 @@ class GenBbcode public GenBbcode(string dir) { project = new AtxtProject(dir); - project.LoadMacro(); + project.LoadMacro(AtxtProject.MacroMode.Bbcode); project.LoadWebImages(); project.CollectSource(); } @@ -71,10 +71,12 @@ string GenBody(string[] txt) const string reg_imgchar = "\\[imgchar\\]((?!http).*?)\\[\\/imgchar\\]"; const string reg_class = "\\[class=(.*?)\\](.*?)\\[\\/class\\]"; const string reg_chapter = "\\[chapter=(.*?)\\](.*?)\\[\\/chapter\\]"; - Dictionary reg_dic = new Dictionary - { + Dictionary reg_dic_comment = new Dictionary{ {"/\\*.*?\\*/",""}, {"///.*",""}, + }; + Dictionary reg_dic = new Dictionary + { //{"\\[align=(.*?)\\](.*?)\\[\\/align\\]","

$2

"}, {"^\\[center\\](.*?)\\[\\/center\\]$","[align=center]$1[/align]"}, {"^\\[right\\](.*?)\\[\\/right\\]$","[align=right]$1[/align]"}, @@ -118,11 +120,26 @@ string GenBody(string[] txt) string r = line; Match m = Regex.Match("", "1"); + do + { + foreach (var pair in reg_dic_comment) + { + m = Regex.Match(r, pair.Key); + if (m.Success) + { + Regex reg = new Regex(pair.Key); + r = reg.Replace(r, pair.Value); + break; + } + } + } while (m.Success); //macros if (project.macros != null) { + int executionCount = 0; do { + string safeCheck = r; foreach (var pair in project.macros) { m = Regex.Match(r, pair.Key); @@ -130,9 +147,18 @@ string GenBody(string[] txt) { Regex reg = new Regex(pair.Key); r = reg.Replace(r, pair.Value); + executionCount++; + if (r == safeCheck) continue; break; } } + if (r == safeCheck) break; + if (executionCount > 100) + { + Log.Error("Macro: Max count"); + Log.Error(r); + break; + } } while (m.Success); } if (r.StartsWith("##")) continue; diff --git a/AeroNovelTool/src/func/GenEPUB.cs b/AeroNovelTool/src/func/GenEPUB.cs index 875b6f5..1cf5d76 100644 --- a/AeroNovelTool/src/func/GenEPUB.cs +++ b/AeroNovelTool/src/func/GenEPUB.cs @@ -28,6 +28,10 @@ public string img_path { get { return Path.Combine(dir, "Images"); } } + public string fnt_path + { + get { return Path.Combine(dir, "Fonts"); } + } public List img_names = new List(); public ChineseConvertOption cc_option; public ConfigValue indentAdjust = 0; @@ -105,6 +109,7 @@ public EpubFile Gen(string dir) CollectSource(); GenContent(); GetImage(); + GetFont(); GetCss(); TextEpubItemFile toc = epub.GetFile("OEBPS/toc.ncx"); @@ -314,6 +319,31 @@ void GetImage() } + } + void GetFont() + { + if (Directory.Exists(fnt_path)) + { + Dictionary fnttype = new Dictionary + { + {".otf","application/font-sfnt"}, + }; + foreach (var f in Directory.GetFiles(fnt_path)) + { + string ext = Path.GetExtension(f.ToLower()); + string fn = Path.GetFileName(f); + if (fnttype.ContainsKey(ext)) + { + EpubItemFile i = new EpubItemFile("OEBPS/Fonts/" + fn, File.ReadAllBytes(f)); + epub.items.Add(i); + string properties = ""; + items += $" \n"; + Log.Info("Add font: " + fn); + } + + } + } + } void GetCss() { diff --git a/AeroNovelTool/src/func/GenHTML.cs b/AeroNovelTool/src/func/GenHTML.cs index 3d73ffd..bfcb87c 100644 --- a/AeroNovelTool/src/func/GenHTML.cs +++ b/AeroNovelTool/src/func/GenHTML.cs @@ -24,6 +24,10 @@ public string Gen(string[] txt) const string reg_imgchar = "\\[imgchar\\](.*?)\\[\\/imgchar\\]"; const string reg_class = "\\[class=(.*?)\\](.*?)\\[\\/class\\]"; const string reg_chapter = "\\[chapter=(.*?)\\](.*?)\\[\\/chapter\\]"; + Dictionary reg_dic_comment = new Dictionary{ + {"/\\*.*?\\*/",""}, + {"///.*",""}, + }; Dictionary reg_dic = new Dictionary { {"^\\[align=(.*?)\\](.*?)\\[\\/align\\]$","

$2

"}, @@ -39,10 +43,6 @@ public string Gen(string[] txt) {"^\\[h5\\](.*?)\\[\\/h5\\]$","
$1
"}, {"^\\[h6\\](.*?)\\[\\/h6\\]$","
$1
"}, ///以上做旧版兼容,找个时机扫进垃圾堆 - - ///优先去除注释 - {"/\\*.*?\\*/",""}, - {"///.*",""}, {"^#center:(.*)","

$1

"}, {"^#right:(.*)","

$1

"}, @@ -56,7 +56,7 @@ public string Gen(string[] txt) {reg_chapter,""}, {"\\[b\\](.*?)\\[\\/b\\]","$1"}, {"^#title:(.*)","

$1

"}, - {"\\[ruby=(.*?)\\](.*?)\\[\\/ruby\\]","$2$1"}, + {"\\[ruby=(.*?)\\](.*?)\\[\\/ruby\\]","$2($1)"}, {"^\\[pagebreak\\]$","


"}, {"\\[emphasis\\](.*?)\\[\\/emphasis\\]","$1"}, {"\\[s\\](.*?)\\[\\/s\\]","$1"}, @@ -79,7 +79,6 @@ public string Gen(string[] txt) {"(?)(?$0"} }; - string html = ""; foreach (string line in txt) { @@ -87,11 +86,26 @@ public string Gen(string[] txt) string r = EncodeHTML(line); Match m = Regex.Match("", "1"); + do + { + foreach (var pair in reg_dic_comment) + { + m = Regex.Match(r, pair.Key); + if (m.Success) + { + Regex reg = new Regex(pair.Key); + r = reg.Replace(r, pair.Value); + break; + } + } + } while (m.Success); if (context != null & context.macros != null) { + int executionCount = 0; do { + string safeCheck = r; foreach (var pair in context.macros) { m = Regex.Match(r, pair.Key); @@ -99,9 +113,18 @@ public string Gen(string[] txt) { Regex reg = new Regex(pair.Key); r = reg.Replace(r, pair.Value); + executionCount++; + if (r == safeCheck) continue; break; } } + if (r == safeCheck) break; + if (executionCount > 100) + { + Log.Error("Macro: Max count"); + Log.Error(r); + break; + } } while (m.Success); } diff --git a/AeroNovelTool/src/func/GenInlineHTML.cs b/AeroNovelTool/src/func/GenInlineHTML.cs index 19d36cc..d3b568e 100644 --- a/AeroNovelTool/src/func/GenInlineHTML.cs +++ b/AeroNovelTool/src/func/GenInlineHTML.cs @@ -9,7 +9,7 @@ class GenInlineHTML public GenInlineHTML(string dir) { project = new AtxtProject(dir); - project.LoadMacro(); + project.LoadMacro(AtxtProject.MacroMode.InlineHTML); project.LoadWebImages(); project.CollectSource(); } @@ -50,13 +50,12 @@ public string GenBody(string[] txt) const string reg_imgchar = "\\[imgchar\\](.*?)\\[\\/imgchar\\]"; const string reg_class = "\\[class=(.*?)\\](.*?)\\[\\/class\\]"; const string reg_chapter = "\\[chapter=(.*?)\\](.*?)\\[\\/chapter\\]"; - Dictionary reg_dic = new Dictionary - { - - ///优先去除注释 + Dictionary reg_dic_comment = new Dictionary{ {"/\\*.*?\\*/",""}, {"///.*",""}, - + }; + Dictionary reg_dic = new Dictionary + { {"^#center:(.*)","

$1

"}, {"^#right:(.*)","

$1

"}, {"^#left:(.*)","

$1

"}, @@ -69,7 +68,7 @@ public string GenBody(string[] txt) {reg_chapter,"$2"}, {"\\[b\\](.*?)\\[\\/b\\]","$1"}, {"^#title:(.*)","

$1

"}, - {"\\[ruby=(.*?)\\](.*?)\\[\\/ruby\\]","$2$1"}, + {"\\[ruby=(.*?)\\](.*?)\\[\\/ruby\\]","$2($1)"}, {"^\\[pagebreak\\]$","


"}, {"\\[em\\](.*?)\\[\\/em\\]","$1"}, {"\\[s\\](.*?)\\[\\/s\\]","$1"}, @@ -82,7 +81,7 @@ public string GenBody(string[] txt) {"^#h4:(.*)","

$1

"}, {"^#h5:(.*)","
$1
"}, {"^#h6:(.*)","
$1
"}, - {"^#class:(.*)","
"}, + {"^#class:(.*)","
"}, {"^#/class","
"}, {"\\[font\\](.*?)\\[\\/font\\]","$1"}, {"\\[url=(.*?)\\](.*?)\\[\\/url\\]","$2"}, @@ -99,12 +98,28 @@ public string GenBody(string[] txt) if (line.StartsWith("##")) continue; string r = EncodeHTML(line); + Match m = Regex.Match("", "1"); + do + { + foreach (var pair in reg_dic_comment) + { + m = Regex.Match(r, pair.Key); + if (m.Success) + { + Regex reg = new Regex(pair.Key); + r = reg.Replace(r, pair.Value); + break; + } + } + } while (m.Success); if (project.macros != null) { + int executionCount = 0; do { + string safeCheck = r; foreach (var pair in project.macros) { m = Regex.Match(r, pair.Key); @@ -112,9 +127,18 @@ public string GenBody(string[] txt) { Regex reg = new Regex(pair.Key); r = reg.Replace(r, pair.Value); + executionCount++; + if (r == safeCheck) continue; break; } } + if (r == safeCheck) break; + if (executionCount > 100) + { + Log.Error("Macro: Max count"); + Log.Error(r); + break; + } } while (m.Success); } diff --git a/AeroNovelTool/src/func/GlossaryImportation.cs b/AeroNovelTool/src/func/GlossaryImportation.cs index d7cf5d6..0368284 100644 --- a/AeroNovelTool/src/func/GlossaryImportation.cs +++ b/AeroNovelTool/src/func/GlossaryImportation.cs @@ -74,10 +74,11 @@ string TranslateLine(string line) if (t1 != null) { temp[i] = t1; } else { - if (!string.IsNullOrEmpty(temp[i].output)) + string tryGetOutput = GetOutput(temp[i]); + if (!string.IsNullOrEmpty(tryGetOutput)) { - TryAddSpace(ref result, temp[i].output); - result += temp[i].output; + TryAddSpace(ref result, tryGetOutput); + result += tryGetOutput; temp.Clear(); break; } @@ -108,6 +109,19 @@ CharNode FindNodeByChar(List nodes, char c) return null; } + string GetOutput(CharNode node) + { + do + { + if (!string.IsNullOrEmpty(node.output)) + { + return node.output; + } + node = node.parent; + } while (node.parent != null); + return null; + } + void TryAddSpace(ref string result, string added) { if (result != "") @@ -139,13 +153,16 @@ bool isBracket(char c) private class CharNode { public char v; + public CharNode parent = null; public CharNode(char c) { v = c; } public CharNode AddChild(char c) { CharNode child = new CharNode(c); + child.parent = this; children.Add(child); return child; } + public List children = new List(); public string output = ""; diff --git a/AeroNovelTool/src/version.cs b/AeroNovelTool/src/version.cs index 6a68896..8d7242e 100644 --- a/AeroNovelTool/src/version.cs +++ b/AeroNovelTool/src/version.cs @@ -1,4 +1,4 @@ class Version { - public static string date = "20211201"; + public static string date = "20211226"; } \ No newline at end of file diff --git a/AeroNovelTool/template/OEBPS/Styles/Style.css b/AeroNovelTool/template/OEBPS/Styles/Style.css index cd0145c..8f28df3 100644 --- a/AeroNovelTool/template/OEBPS/Styles/Style.css +++ b/AeroNovelTool/template/OEBPS/Styles/Style.css @@ -51,7 +51,7 @@ p { .atxt_illu { width: 100%; - height: 100vh; + height: 99vh; page-break-inside: avoid; display: flex; align-items: center;