SteelGolem icon

transcluding wikitext templates

SteelGolem | PRO | 04/30/15 11:39:15 AM UTC | 0 ⭐ | 616 👁️ | Never ⏰ | []
C# |

5.44 KB

|

None

|

0 👍

/

0 👎

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