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<string, string> argumentLookup = new Dictionary<string, string>();
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
*/
Comments