using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace sg_wiki_with_templates_testing { class Program { static void Main(string[] args) { // TODO: should be using args[0] string arg = "wiki entry 1.txt"; string output = LoadWikiFile(arg); StreamWriter writer = new StreamWriter("output.txt"); writer.Write(output); writer.Flush(); writer.Close(); } private static string LoadWikiFile(string filename) { StreamReader reader = new StreamReader(filename); string input = reader.ReadToEnd(); reader.Close(); string mangledInput = input; while (mangledInput.Contains("}}")) { // find and copy innermost nested template string int end = mangledInput.IndexOf("}}"); int start = end; end += "}}".Length; while (mangledInput.Substring(start, 2) != "{{") start--; string textToReplace = mangledInput.Substring(start, end - start); string templateFilename = ""; // break template string into arguments lookup string innerText = textToReplace.Substring("{{".Length, textToReplace.Length - "{{}}".Length); string[] argumentValues = innerText.Split(new char[] { '|' }); Dictionary argumentLookup = new Dictionary(); for (int a = 0; a < argumentValues.Length; a++) { string[] argumentTokens = argumentValues[a].Split(new char[] { '=' }); string argumentName = argumentTokens[0].Trim(); string argumentValue = (argumentTokens.Length > 1) ? argumentTokens[1].Trim() : ""; argumentLookup.Add(argumentName, argumentValue); argumentValues[a] = argumentValue; // used for indexed variable lookups later if (a == 0) templateFilename = argumentName + ".txt"; } // read the template file if (!File.Exists(templateFilename)) throw new FileNotFoundException("Could not find template '" + templateFilename + "'. Requested from wikitext '" + filename + "'."); reader = new StreamReader(templateFilename); string template = reader.ReadToEnd(); reader.Close(); // block recursion for now // TODO: recursion is dangerous, but will it be useful? if (template.Contains(textToReplace)) // TODO: is this how we should handle this? throw new Exception("Template '" + templateFilename + "' contains a reference to itself; recursion is currently being blocked."); // replace arguments with values string mangledTemplate = template; // NOTE: we don't need to worry about nested arguments while (mangledTemplate.Contains("{{{")) { // find next argument start = mangledTemplate.IndexOf("{{{"); end = mangledTemplate.IndexOf("}}}", start) + "}}}".Length; string argTextToReplace = mangledTemplate.Substring(start, end - start); string argInnerText = argTextToReplace.Substring("{{{".Length, argTextToReplace.Length - "{{{}}}".Length).Trim(); // TODO: "magic words" string replaceArgWith = ""; // see if it's an indexed variable, eg: {{{1}}} int argIndex = -1; if (int.TryParse(argInnerText, out argIndex)) { if (argIndex > 0 && argIndex < argumentLookup.Keys.Count) replaceArgWith = argumentValues[argIndex]; } else // it's a named variable, eg: {{{n}}} { if (argumentLookup.ContainsKey(argInnerText)) replaceArgWith = argumentLookup[argInnerText]; } // replace the argument string with the result mangledTemplate = mangledTemplate.Replace(argTextToReplace, replaceArgWith); } // finish transcluding with processed template mangledInput = mangledInput.Replace(textToReplace, mangledTemplate); } return mangledInput; } } } /* * wiki entry 1.txt * some text before template {{wiki template 1 | arg1 = foo | arg2 = bar | arg3 }} some text after template */ /* * wiki template 1.txt * start of template 1 text 1: {{{1}}} 2: {{{2}}} 3: {{{3}}} arg1: {{{arg1}}} arg2: {{{arg2}}} arg3: {{{arg3}}} end of template 1 text */ /* * output.txt * some text before template start of template 1 text 1: foo 2: bar 3: arg1: foo arg2: bar arg3: end of template 1 text some text after template */