/// <summary> /// Appends the opening MathML <math> tag to the specified StringBuilder instance. /// </summary> /// <param name="bld">The StringBuilder instance.</param> /// <param name="altText">The alternative text.</param> /// <param name="inline">Indicates whether the math block is inline.</param> public static void AppendMathProlog(StringBuilder bld, string altText, bool inline, LatexToMathMLConverter customization) { bld.Append("\n<math xmlns=\"http://www.w3.org/1998/Math/MathML\" alttext=\""); bld.Append(altText); bld.Append("\" "); bld.Append(inline ? "display=\"inline\"" : "display=\"block\""); bld.Append(" class=\"" + customization.GetCurrentCssStyle() + "\""); bld.Append(">\n<mstyle displaystyle=\"true\" />"); }
public static string ConvertOutline(IList<LatexExpression> outline, LatexToMathMLConverter customization) { var bld = new StringBuilder(); var backupTextSize = customization.CurrentTextSize; var backupTextStyle = customization.CurrentTextStyle; foreach (var child in outline) { bld.Append(child.Convert()); } customization.CurrentTextSize = backupTextSize; customization.CurrentTextStyle = backupTextStyle; return bld.ToString(); }
/// <summary> /// Initializes a new instance of the BibtexItem class. /// </summary> /// <param name="type">the Bibtex type of the item.</param> /// <param name="name">The name of the item.</param> /// <param name="number">The cite number of the item.</param> /// <param name="values">The data associated with the item.</param> /// <param name="customization"></param> public BibtexItem(string type, string name, int number, Dictionary<string, string> values, LatexToMathMLConverter customization) { Type = type; Name = name; Number = number; _values = new Dictionary<string, List<LatexExpression>>(values.Count); foreach (var pair in values) { var root = LatexExpression.CreateRoot(new StringReader(pair.Value), customization); _values.Add(pair.Key, root.Expressions[0]); } }
static void Main(string[] args) { #if MONO LatexToMathMLConverter.GhostScriptBinaryPath = "gs"; #else LatexToMathMLConverter.GhostScriptBinaryPath = @"C:\\Program Files (x86)\\gs\\gs8.64\\bin\\gswin32c.exe"; #endif var lmm = new LatexToMathMLConverter( "E:\\source.txt", Encoding.GetEncoding(1251), "E:\\source.xml"); lmm.ValidateResult = true; lmm.Convert(); }
private static string HandleStr(string str) { string latexBegin = "\\documentclass{article} \\begin{document}"; string latexEnd = "\\end{document}"; string oxmlText = "<w:p><w:r><w:t>{0}</w:t></w:r></w:p>"; StringBuilder result = new StringBuilder("<w:p>"); if (str.IndexOf(@"\(") > 0 || str.IndexOf(@"\)") > 0) { var mathArray = str.Split(new string[] { @"\(" }, str.Length, StringSplitOptions.None); for (int i = 0; i < mathArray.Length; i++) { var mstr = mathArray[i]; if (mstr.IndexOf(@"\)") > 0) { var mathArray1 = mstr.Split(new string[] { @"\)" }, mstr.Length, StringSplitOptions.None); if (mathArray1.Length > 0) { var latexxml = latexBegin + "$" + mathArray1[0] + "$" + latexEnd; var lmm = new LatexToMathMLConverter(latexxml); var mathxml = lmm.ConvertToText(); var omml = OpenXmlWord.ConvertMathMl2OMML(mathxml); result.Append(omml); } if (mathArray1.Length > 1) { result.AppendFormat("<w:r><w:t>{0}</w:t></w:r>", mathArray1[1]); } } else { result.AppendFormat("<w:r><w:t>{0}</w:t></w:r>", mstr); } } } else { result.AppendFormat("<w:r><w:t>{0}</w:t></w:r>", str); } result.Append("</w:p>"); return result.ToString(); }
static void Main(string[] args) { Console.WriteLine("Graphics can be automatically converted from eps/pdf to png. The path to GhostScript must be set to provide that.\n"); Console.WriteLine("For now, it is hard-coded: d:\\Program Files\\GhostScript\\gs9.00\\bin\\gswin32c.exe"); if (args.Length != 2) { Console.WriteLine("Usage: ltx2mml doc.tex doc.xhtml"); return; } #if MONO LatexToMathMLConverter.GhostScriptBinaryPath = "gs"; #else LatexToMathMLConverter.GhostScriptBinaryPath = @"d:\Program Files\GhostScript\gs9.00\bin\gswin32c.exe"; #endif var lmm = new LatexToMathMLConverter( args[0], Encoding.GetEncoding(1251), args[1]); lmm.ValidateResult = true; lmm.Convert(); }
/// <summary> /// Builds a new LatexExpression instance (front). /// </summary> /// <param name="parent">The parent of the builded expression.</param> /// <param name="parentChildNumber">Index of the parent child outline.</param> /// <param name="indexInParentChild">Index in the parent child outline.</param> /// <param name="verbatimMode">True if verbatim mode is on; otherwise, false.</param> /// <param name="beginning">The beginning string.</param> /// <param name="rdr">The reader to read ahead.</param> /// <param name="end">The stub of the unparsed part.</param> /// <param name="mathMode">The math mode switch.</param> /// <param name="whitespaceBefore">Indicates whether there was at least one whitespace char before the returned result.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> /// <returns></returns> private static LatexExpression ReadFromTextReader(LatexExpression parent, int parentChildNumber, ref int indexInParentChild, ref bool verbatimMode, bool mathMode, LatexToMathMLConverter customization, string beginning, TextReader rdr, out string end, ref bool whitespaceBefore) { if (beginning == null && rdr == null) { end = null; return null; } return ReadFromTextReaderInner(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, mathMode, customization, beginning ?? rdr.ReadLine(), rdr, out end, ref whitespaceBefore); }
/// <summary> /// Parses the document and builds the document object tree. /// </summary> /// <param name="rdr">The reader to read the document from.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> /// <returns>The root of the document object tree.</returns> public static LatexExpression CreateRoot(TextReader rdr, LatexToMathMLConverter customization) { bool verbatimMode = false; int rootIndex = 0; var root = new LatexExpression(null, 0, ref rootIndex, ref verbatimMode, ExpressionType.Root, false, customization, null, null, null) { Expressions = new List<List<LatexExpression>>(1) }; var children = new List<LatexExpression>(); string beginning = null; string end; LatexExpression cmd; rootIndex = 0; bool mathMode = false; bool whitespaceBefore = false; while ((cmd = ReadFromTextReader(root, 0, ref rootIndex, ref verbatimMode, mathMode, customization, beginning, rdr, out end, ref whitespaceBefore)) != null) { CheckMathMode(cmd, ref mathMode); beginning = end; children.Add(cmd); } root.Expressions.Add(children); return root; }
/// <summary> /// Initializes a new instance of the LatexExpression class. /// </summary> /// <param name="parent">The parent of the builded expression.</param> /// <param name="parentChildNumber">Index of the parent child outline.</param> /// <param name="indexInParentChild">Index in the parent child outline.</param> /// <param name="verbatimMode">True if verbatim mode is on; otherwise, false.</param> /// <param name="type">The expression type.</param> /// <param name="mathMode">The math mode switch.</param> /// <param name="name">The expression name.</param> /// <param name="options">The options of the expression.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> /// <param name="values">The child outlines of the expression.</param> private LatexExpression(LatexExpression parent, int parentChildNumber, ref int indexInParentChild, ref bool verbatimMode, ExpressionType type, bool mathMode, LatexToMathMLConverter customization, string name, string options, params string[] values) { Parent = parent; ParentChildNumber = parentChildNumber; IndexInParentChild = indexInParentChild++; Customization = customization; Name = name; ExprType = type; MathMode = mathMode; #region Switch verbatim mode on/off if (type == ExpressionType.Verbatim) { verbatimMode = false; } if (Expressions != null && Name == "begin" && Expressions[0][0].Name == "verbatim" && Expressions.Count == 1) { verbatimMode = true; } #endregion ParseOptions(options); if (values != null) { ParseExpressions(values); } #region If a math block, add the alternative text if (type == ExpressionType.InlineMath || type == ExpressionType.BlockMath) { // ReSharper disable PossibleNullReferenceException Expressions.Add(new List<LatexExpression>()); int index = 0; Expressions[1].Add(new LatexExpression(this, 1, ref index, ref verbatimMode, ExpressionType.PlainText, false, Customization, values[0], null, null)); // ReSharper restore PossibleNullReferenceException } #endregion #region Post-parse plain text if in math mode if (ExprType == ExpressionType.PlainText && mathMode && Name.Length > 1 && (Parent.ExprType != ExpressionType.Block || Parent.Name != "PlainText") && (Parent.ExprType != ExpressionType.Command || Parent.Name != "begin" && Parent.Name != "end")) { ExprType = ExpressionType.Block; Name = "PlainText"; #region Parse var list = new List<string>(); var buf = "" + name[0]; for (int pos = 1; pos < name.Length; pos++) { var chrPre = name[pos - 1]; var chr = name[pos]; if (char.IsWhiteSpace(chr)) { list.Add(buf); buf = ""; continue; } if (char.IsDigit(chr)) { #region Digit if (char.IsDigit(chrPre)) { buf += chr; continue; } if (char.IsLetter(chr) || chr == '(') { list.Add("InvisibleTimes"); } list.Add(buf); buf = "" + chr; continue; #endregion } if (char.IsLetter(chr)) { #region Letter if (char.IsLetter(chrPre)) { buf += chr; continue; } if (char.IsDigit(chr) || chr == '(') { list.Add("InvisibleTimes"); } list.Add(buf); buf = "" + chr; continue; #endregion } #region >=, <= if (chr == '=') { if (chrPre == '>' || chrPre == '<') { buf += chr; } } #endregion list.Add(buf); buf = "" + chr; } list.Add(buf); #endregion Expressions = new List<List<LatexExpression>>(list.Count) {new List<LatexExpression>()}; int i; for (i = 0; i < list.Count;) { if (list[i].Trim() != "") { Expressions[0].Add(new LatexExpression(this, 0, ref i, ref verbatimMode, ExpressionType.PlainText, true, customization, list[i].Trim(), null, null)); } else { i++; } } } #endregion }
/// <summary> /// Initializes a new instance of the LatexExpression class of type ExpressionType.Block. /// </summary> /// <param name="name">The name of the block.</param> /// <param name="parent">The parent of the builded expression.</param> /// <param name="parentChildNumber">Index of the parent child outline.</param> /// <param name="indexInParentChild">Index in the parent child outline.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> public LatexExpression(string name, LatexExpression parent, int parentChildNumber, int indexInParentChild, LatexToMathMLConverter customization) { Name = name; Customization = customization; ExprType = ExpressionType.Block; MathMode = parent.MathMode | parent.ExprType == ExpressionType.BlockMath | parent.ExprType == ExpressionType.InlineMath; Parent = parent; ParentChildNumber = parentChildNumber; IndexInParentChild = indexInParentChild; Expressions = new List<List<LatexExpression>> {new List<LatexExpression>()}; }
/// <summary> /// Builds the document object tree. /// </summary> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> /// <remarks>The parsing procedure consists of stand-alone passes, so that it resembles a compiler pipeline.</remarks> public void Parse(LatexToMathMLConverter customization) { // Replace \begin{equation} and \end{equation} with $$. Do better later. _source = _source.Replace("\\begin{equation}", "\n$$"); _source = _source.Replace("\\end{equation}", "$$\n"); foreach (var rule in PreformatRules) { _source = _source.Replace(rule[0], rule[1]); } var rdr = new StringReader(_source); const byte PASS_COUNT = 14; byte step = 1; // Build the tree LogInfo("CreateRoot"); _root = LatexExpression.CreateRoot(rdr, customization); OnProgressEvent(step++, PASS_COUNT); // PJ: Wrap inside \begin{document} and \end{document} if these are missing AddDocument(_root); // Include the \input files LogInfo("IncludeImports"); IncludeImports(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Rebuild tree with custom commands _customCommands = new Dictionary<string, LatexExpression>(); LogInfo("RecursiveParseCustomCommands"); RecursiveParseCustomCommands(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Ensure that commands like \title are out of the document scope LogInfo("MoveCommandsOutOfDocument"); MoveCommandsOutOfDocument(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Incapsulate fragments between \begin and \end LogInfo("IncapsulateCommands"); IncapsulateCommands(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Post-parse arrays and tabular LogInfo("PostParseTables"); PostParseTables(Root.Expressions[0], customization); OnProgressEvent(step++, PASS_COUNT); // Build super- and subscripts LogInfo("BuildScripts"); BuildScripts(Root.Expressions[0], customization); OnProgressEvent(step++, PASS_COUNT); // Build lists LogInfo("BuildLists"); BuildLists(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Build paragraph blocks LogInfo("BuildParagraphs"); BuildParagraphs(Root.FindDocument().Expressions[0], customization); OnProgressEvent(step++, PASS_COUNT); // Simplify math blocks that begin with baseless scripts LogInfo("SimplifyScripts"); //SimplifyBaselessScripts(Root.Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Numerate blocks (needed for the next step) LogInfo("NumerateBlocks"); NumerateBlocks(Root.FindDocument().Expressions[0]); Root.Customization.Counters.Add("document", 0); OnProgressEvent(step++, PASS_COUNT); // Simplify math blocks that begin with baseless scripts LogInfo("PreProcessLabels"); PreprocessLabels(Root.FindDocument().Expressions[0]); Root.Customization.Counters.Clear(); OnProgressEvent(step++, PASS_COUNT); // Deal with algorithmic blocks LogInfo("PreprocessAlgorithms"); PreprocessAlgorithms(Root.FindDocument().Expressions[0]); OnProgressEvent(step++, PASS_COUNT); // Attach the bibliography LogInfo("AttachBibliography"); AttachBibliography(); OnProgressEvent(step++, PASS_COUNT); LogInfo("Finished"); }
public void UpdatePlugg(Plugg p, PluggContent pc) { //For restore if something goes wrong Plugg oldP = GetPlugg(p.PluggId); IEnumerable<PluggContent> oldPCs = GetAllContentInPlugg(p.PluggId); rep.UpdatePlugg(p); //No repair necessary if this fails //For now, remove all PluggContent and recreate in all languages from pc. Fix this when we can deal with translations try { foreach (PluggContent pcDelete in oldPCs) { rep.DeletePluggContent(pcDelete); } pc.PluggId = p.PluggId; if (pc.LatexText != null) { LatexToMathMLConverter myConverter = new LatexToMathMLConverter(pc.LatexText); myConverter.Convert(); pc.LatexTextInHtml = myConverter.HTMLOutput; } LocaleController lc = new LocaleController(); var locales = lc.GetLocales(PortalID); foreach (var locale in locales) { pc.CultureCode = locale.Key; rep.CreatePluggContent(pc); } } catch (Exception) { //recreate old Plugg/PluggContent before rethrow var pcs = GetAllContentInPlugg(p.PluggId); foreach (PluggContent pcDelete in pcs) { rep.DeletePluggContent(pcDelete); } rep.DeletePlugg(p); rep.CreatePlugg(oldP); foreach (PluggContent oldPC in oldPCs) rep.CreatePluggContent(oldPC); throw; } }
/// <summary> /// Post-parses arrays and tabular. /// </summary> /// <param name="outline">The outline of a LatexExpression instance.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> private static void PostParseTables(IList<LatexExpression> outline, LatexToMathMLConverter customization) { for (int i = 0; i < outline.Count; i++) { if (outline[i].ExprType == ExpressionType.Block && (TableLikeBlockNames.Contains(outline[i].Name))) { int parentChildNumber = outline[i].Expressions.Count == 1? 0 : 1; var main = outline[i].Expressions[parentChildNumber]; var table = new List<List<List<LatexExpression>>>(3) {new List<List<LatexExpression>>(3)}; #region Build table int rowIndex = 0; for (int j = 0; ; j++) { var cell = new List<LatexExpression>(2); for (; j < main.Count && !(main[j].Name == "\\" && main[j].ExprType == ExpressionType.Command) && !(main[j].Name == "&" && main[j].ExprType == ExpressionType.PlainText) ; j++) { // \hline won't do the same in XHTML if (main[j].ExprType == ExpressionType.Command && main[j].Name == "hline") continue; if (main[j].ExprType == ExpressionType.Comment) continue; cell.Add(main[j]); } if (cell.Count > 0) { table[rowIndex].Add(cell); } if (j == main.Count) { break; } if (main[j].Name == "\\") { rowIndex++; table.Add(new List<List<LatexExpression>>(3)); } } if (table[rowIndex].Count == 0) { table.RemoveAt(rowIndex); } #endregion #region Link table main = new List<LatexExpression>(table.Count); for (int j = 0; j < table.Count; j++) { // Add row main.Add(new LatexExpression("", outline[i], parentChildNumber, j, customization)); for (int k = 0; k < table[j].Count; k++) { // Add column cell main[j].Expressions[0].Add(new LatexExpression("", main[j], 0, k, customization)); for (int m = 0; m < table[j][k].Count; m++) { table[j][k][m].Parent = main[j].Expressions[0][k]; table[j][k][m].ParentChildNumber = 0; table[j][k][m].IndexInParentChild = m; // Add cell atom main[j].Expressions[0][k].Expressions[0].Add(table[j][k][m]); } } } outline[i].Expressions[parentChildNumber] = main; #endregion } } for (int i = 0; i < outline.Count; i++) { if (outline[i].Expressions != null) { foreach (var subTree in outline[i].Expressions) { PostParseTables(subTree, customization); } } } }
/// <summary> /// Performs the conversion procedure of math blocks. /// </summary> /// <param name="outline">The sequence of expressions to convert.</param> /// <param name="altText">The alternative text.</param> /// <param name="inline">Indicates whether the math block is inline.</param> /// <returns>The converted XML string.</returns> private static string CommonConvert(IList<LatexExpression> outline, string altText, bool inline, LatexToMathMLConverter customization) { if (outline.Count == 0) return ""; var bld = new StringBuilder(); AppendMathProlog(bld, altText, inline, customization); bld.Append("<mrow>\n"); bld.Append(SequenceConverter.ConvertOutline(outline, customization)); bld.Append("\n</mrow>\n"); AppendMathEpilog(bld); return bld.ToString(); }
/// <summary> /// Initializes a new instance of the BibtexParser class. /// </summary> /// <param name="rdr"></param> public BibtexParser(StringReader rdr, LatexToMathMLConverter customization) { _rdr = rdr; _customization = customization; }
private bool HandleStr(string str, Paragraph p) { try { string latexBegin = "\\documentclass{article} \\begin{document}"; string latexEnd = "\\end{document}"; var run1 = new Run(); if (!string.IsNullOrEmpty(str) && (str.IndexOf(@"\(") > 0 || str.IndexOf(@"\)") > 0)) { var mathArray = str.Split(new string[] { @"\(" }, str.Length, StringSplitOptions.None); for (int i = 0; i < mathArray.Length; i++) { var mstr = mathArray[i]; if (mstr.IndexOf(@"\)") > 0) { var mathArray1 = mstr.Split(new string[] { @"\)" }, mstr.Length, StringSplitOptions.None); if (mathArray1.Length > 0) { var latexxml = latexBegin + "$" + mathArray1[0] + "$" + latexEnd; var lmm = new LatexToMathMLConverter(latexxml); var mathxml = lmm.ConvertToText(); var omml = ConvertMathMl2OMML(mathxml); run1 = new Run(); WritOfficeMathMLToWord(omml, run1); p.Append(run1); } if (mathArray1.Length > 1) { run1 = new Run(); run1.Append(new Text(mathArray1[1])); p.Append(run1); } } else { run1 = new Run(); run1.Append(new Text(mstr)); p.Append(run1); } } } else { run1 = new Run(); run1.Append(new Text(str)); p.Append(run1); } } catch (Exception ex) { throw ex; } return true; }
/// <summary> /// Recursively build paragragh structure. /// </summary> /// <param name="list">The outline of a LatexExpression instance.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> private static void BuildParagraphs(List<LatexExpression> list, LatexToMathMLConverter customization) { for (int i = 0; i < list.Count; i++) { if (list[i].Expressions != null) { foreach (var subTree in list[i].Expressions) { BuildParagraphs(subTree, customization); } } bool isParagraph = list[i].ExprType == ExpressionType.Command && list[i].Name.IndexOf("paragraph") > -1 && !list[i].MathMode; bool isLikeParagraph = !list[i].MathMode && (list[i].ExprType == ExpressionType.Command && list[i].Name.IndexOf("section") > -1 || list[i].ExprType == ExpressionType.BlockMath || list[i].ExprType == ExpressionType.Block && list[i].Name != "" || list[i].ExprType == ExpressionType.Verbatim); if (isParagraph || isLikeParagraph) { int j; #region Set j to the paragraph breaker expression index bool found = false; for (j = i + 1; j < list.Count; j++) { if (list[j].ExprType == ExpressionType.Command && (list[j].Name.IndexOf("paragraph") > -1 || list[j].Name.IndexOf("section") > -1) || list[j].ExprType == ExpressionType.Block && list[j].Name != "" || list[j].ExprType == ExpressionType.BlockMath || list[j].ExprType == ExpressionType.Verbatim) { found = true; break; } } if (!found) { j = list.Count; } #endregion if (isParagraph) { #region Create and link the block var block = new List<LatexExpression>(j - i - 1); List<LatexExpression> paragraphTitle = null; if (list[i].Expressions != null) { paragraphTitle = list[i].Expressions[0]; } list[i] = new LatexExpression(list[i].Name, list[i].Parent, list[i].ParentChildNumber, i, customization); int parentChildNumber = 0; if (paragraphTitle != null) { list[i].Expressions[0] = paragraphTitle; list[i].Expressions.Add(new List<LatexExpression>()); parentChildNumber = 1; } for (int k = i + 1; k < j; k++) { list[k].Parent = list[i]; list[k].ParentChildNumber = parentChildNumber; list[k].IndexInParentChild = k - i - 1; block.Add(new LatexExpression(list[k])); } list[i].Expressions[parentChildNumber] = block; #endregion if (j - i - 1 > 0) { list.RemoveRange(i + 1, j - i - 1); #region Update indices after the block int delta = j - i - 1; for (int k = i + 1; k < list.Count; k++) { list[k].IndexInParentChild -= delta; } #endregion } } if (isLikeParagraph && j - i > 1) { #region Create and link the new block var expr = new LatexExpression("paragraph", list[i + 1].Parent, list[i + 1].ParentChildNumber, i + 1, customization); for (int k = i + 1; k < j; k++) { list[k].Parent = expr; list[k].ParentChildNumber = 0; list[k].IndexInParentChild = k - i - 1; expr.Expressions[0].Add(new LatexExpression(list[k])); } list[i + 1] = expr; #endregion if (j - i - 1 > 1) { list.RemoveRange(i + 2, j - i - 2); #region Update indices after the block int delta = j - i - 2; for (int k = i + 2; k < list.Count; k++) { list[k].IndexInParentChild -= delta; } #endregion } } } } }
/// <summary> /// Initializes a new instance of the LatexParser class. /// </summary> /// <param name="source">The source string to build the tree from.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> public LatexParser(string source, LatexToMathMLConverter customization) { if (String.IsNullOrEmpty(source)) { throw new ArgumentException("The parameter can not be null or empty.", "source"); } _source = source; _customization = customization; }
/// <summary> /// Builds a new LatexExpression instance (main). /// </summary> /// <param name="parent">The parent of the builded expression.</param> /// <param name="parentChildNumber">Index of the parent child outline.</param> /// <param name="indexInParentChild">Index in the parent child outline.</param> /// <param name="verbatimMode">True if verbatim mode is on; otherwise, false.</param> /// <param name="beginning">The beginning string.</param> /// <param name="rdr">The reader to read ahead.</param> /// <param name="mathMode">The math mode switch.</param> /// <param name="end">The stub of the unparsed part.</param> /// <param name="whitespaceBefore">Indicates whether there was at least one whitespace char before the returned result.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> /// <returns>The parsed LatexExpression instance.</returns> private static LatexExpression ReadFromTextReaderInner(LatexExpression parent, int parentChildNumber, ref int indexInParentChild, ref bool verbatimMode, bool mathMode, LatexToMathMLConverter customization, string beginning, TextReader rdr, out string end, ref bool whitespaceBefore) { string name; #region Verbatim if (verbatimMode) { name = ReadToVerbatimEnd(beginning, rdr, out end); return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.Verbatim, false, customization, name, null, null); } #endregion bool whitespaceBeforeGuard; string str = ReadToNotEmptyString(beginning, rdr, out whitespaceBeforeGuard); whitespaceBefore |= whitespaceBeforeGuard; if (str == null) { end = null; return null; } string value; switch (str[0]) { case '\\': #region Command string options; string[] values; name = Regex.Match(str.Substring(1), @"^[a-zA-Z]+\*?").Value; if (String.IsNullOrEmpty(name)) { name = "" + str[1]; options = null; if (name != "[") { values = null; end = str.Substring(2); } else // Math { value = ParseBraces(ref str, rdr, "\\[", "\\]", out whitespaceBefore); end = str; return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.BlockMath, mathMode, customization, name, null, value); } } else { ParseCommandOptionsAndValues( str.Substring(name.Length + 1), rdr, out end, out options, out values, out whitespaceBefore); } return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.Command, mathMode, customization, name, options, values); #endregion case '$': #region Math ExpressionType type; if (str[1] == '$') { name = "$$"; value = ParseBraces(ref str, rdr, "$$", "$$", out whitespaceBefore); type = ExpressionType.BlockMath; } else { name = "$"; value = ParseBraces(ref str, rdr, "$", "$", out whitespaceBefore); type = ExpressionType.InlineMath; } end = str; return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, type, false, customization, name, null, value); #endregion case '%': #region Comment end = null; return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.Comment, false, customization, str.Substring(1), null, null); #endregion case '{': #region Block value = ParseBraces(ref str, rdr, "{", "}", out whitespaceBefore); end = str; return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.Block, mathMode, customization, "{}", null, value); #endregion case '&': #region Table cell end = str.Substring(1); return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.PlainText, mathMode, customization, "&", null, null); #endregion case '^': case '_': #region Block for sub and sup if (mathMode) { name = "" + str[0]; str = ReadToNotEmptyString(str.Substring(1), rdr, out whitespaceBefore); switch (str[0]) { case '{': value = ParseBraces(ref str, rdr, "{", "}", out whitespaceBefore); end = str; break; case '\\': var cmdName = Regex.Match(str.Substring(1), @"^[a-zA-Z]+\*?").Value; ParseCommandOptionsAndValues( str.Substring(cmdName.Length + 1), rdr, out end, out options, out values, out whitespaceBefore); value = "\\" + cmdName + options; if (values != null) { for (int i = 0; i < values.Length; i++) { value += "{" + values[i] + "}"; } } break; default: value = "" + str[0]; if (char.IsDigit(str[0])) { value = Regex.Match(str, @"\d+").Value; } if (char.IsLetter(str[0])) { value = Regex.Match(str, @"[a-zA-Z]+").Value; } end = str.Substring(value.Length); break; } return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.Block, true, customization, name, null, value); } goto default; #endregion default: #region Plain text block name = ""; var stopChars = mathMode ? new[] { '\\', '$', '{', '%', '&', '^', '_' } : new[] { '\\', '$', '{', '%', '&' }; int stopPos; while ((stopPos = GetStopPos(str, stopChars)) == -1) { if (rdr != null) { name += str + " "; str = rdr.ReadLine(); if (str == null) // End of the document { name = name.Substring(0, name.Length - 1); break; } if (str.Trim() == "") { str = "\\paragraph"; stopPos = 0; break; } } else { stopPos = str.Length; break; } } if (str == null) // End of the document? { end = null; } else { name += str.Substring(0, stopPos); if (stopPos < str.Length && (str[stopPos] == '^' || str[stopPos] == '_')) { var match = Regex.Match(name, @"[a-zA-Z]+\s*\Z"); var chunk = match.Value; if (chunk.Trim() == "") { match = Regex.Match(name, @"\d+\s*\Z"); chunk = match.Value; if (chunk.Trim() == "") { match = Regex.Match(name, @"\S\s*\Z"); chunk = match.Value.Trim(); } } if (name != chunk) { end = name.Substring(match.Index) + str.Substring(stopPos); name = name.Substring(0, match.Index); } else { end = str.Substring(stopPos); } } else { end = str.Substring(stopPos); } } return new LatexExpression(parent, parentChildNumber, ref indexInParentChild, ref verbatimMode, ExpressionType.PlainText, mathMode, customization, (whitespaceBefore? " " : "") + SmartTextTrim(name), null, null); #endregion } }
public void SavePlugg(PluggContainer p) { try { bool isNew = p.ThePlugg.PluggId == 0; //Temporary - remove soon p.ThePlugg.Title = "Title no longer here"; p.ThePlugg.CreatedByUserId = 1; p.ThePlugg.ModifiedByUserId = 1; if (isNew) rep.CreatePlugg(p.ThePlugg); else rep.UpdatePlugg(p.ThePlugg); //Todo: Update.. p.TheTitle.ItemId = p.ThePlugg.PluggId; p.TheTitle.ItemType = ETextItemType.PluggTitle; p.TheTitle.CcStatus = ECCStatus.InCreationLanguage; p.TheTitle.CreatedByUserId = p.ThePlugg.CreatedByUserId; p.TheTitle.ModifiedByUserId = p.ThePlugg.ModifiedByUserId; SavePhText(p.TheTitle); //Todo: Update.. if (p.TheHtmlText != null) { p.TheHtmlText.ItemId = p.ThePlugg.PluggId; p.TheHtmlText.ItemType = ETextItemType.PluggHtml; p.TheHtmlText.CcStatus = ECCStatus.InCreationLanguage; p.TheHtmlText.CreatedByUserId = p.ThePlugg.CreatedByUserId; p.TheHtmlText.ModifiedByUserId = p.ThePlugg.ModifiedByUserId; SavePhText(p.TheHtmlText); } //Todo: Update.. if (p.TheLatex != null) { p.TheLatex.ItemId = p.ThePlugg.PluggId; p.TheLatex.ItemType = ELatexType.Plugg; p.TheLatex.CcStatus = ECCStatus.InCreationLanguage; p.TheLatex.CreatedByUserId = p.ThePlugg.CreatedByUserId; p.TheLatex.ModifiedByUserId = p.ThePlugg.ModifiedByUserId; LatexToMathMLConverter myConverter = new LatexToMathMLConverter(p.TheLatex.Text); myConverter.Convert(); p.TheLatex.HtmlText = myConverter.HTMLOutput; SaveLatexText(p.TheLatex); } LocaleController lc = new LocaleController(); var locales = lc.GetLocales(PortalID); foreach (var locale in locales) { if (locale.Key != p.ThePlugg.CreatedInCultureCode) { GoogleTranslate(p.TheTitle, locale.Key); if (p.TheHtmlText != null) GoogleTranslate(p.TheHtmlText, locale.Key); if (p.TheLatex != null) GoogleTranslate(p.TheLatex, locale.Key); } } //Create PluggPage DNNHelper d = new DNNHelper(); string pageUrl = p.ThePlugg.PluggId.ToString(); string pageName = pageUrl + ": " + p.TheTitle.Text; TabInfo newTab = d.AddPluggPage(pageName, pageUrl); p.ThePlugg.TabId = newTab.TabID; rep.UpdatePlugg(p.ThePlugg); } catch (Exception) { //Todo: Update DeletePlugg(p.ThePlugg); throw; } }
/// <summary> /// Must set Text, ItemId, ItemType, CultureCode, CultureCodeStatus and CreatedByUserId or it will not save anything /// If text is versioned, it creates a new version /// If text is not versioned, it creates new text or updates text depending on TextId. /// </summary> /// <param name="t"></param> public void SaveLatexText(PHLatex t) { if (t.Text == null || t.ItemId == 0 || t.ItemType == ELatexItemType.NotSet || t.CultureCode == null || t.CultureCodeStatus == ECultureCodeStatus.NotSet || t.CreatedByUserId == 0) return; //Nothing to save if (t.ModifiedByUserId == 0) t.ModifiedByUserId = t.CreatedByUserId; t.ModifiedOnDate = DateTime.Now; t.CurrentVersion = true; if (t.HtmlText==null || t.HtmlText == "") { LatexToMathMLConverter myConverter = new LatexToMathMLConverter(t.Text); myConverter.Convert(); t.HtmlText = myConverter.HTMLOutput; } bool isVersioned = (t.ItemType == ELatexItemType.PluggComponentLatex || t.ItemType == ELatexItemType.CourseLatexText); if (isVersioned) { var prevText = rep.GetCurrentVersionLatexText(t.CultureCode, t.ItemId, t.ItemType); if (prevText == null) { t.Version = 1; } else { t.Version = prevText.Version++; prevText.CurrentVersion = false; rep.UpdateLatexText(prevText); } t.CreatedOnDate = DateTime.Now; rep.CreateLatexText(t); } else { t.Version = 0; if (t.LatexId == 0) { t.CreatedOnDate = DateTime.Now; rep.CreateLatexText(t); } else rep.UpdateLatexText(t); } }
/// <summary> /// Recursively build scripts (for msup, munder, etc.) /// </summary> /// <param name="list">The outline of a LatexExpression instance.</param> /// <param name="customization">The LatexToMathMLConverter class instance to customize the conversion result.</param> private static void BuildScripts(List<LatexExpression> list, LatexToMathMLConverter customization) { for (int i = 0; i < list.Count; i++) { if (list[i].Expressions != null) { foreach (var subTree in list[i].Expressions) { BuildScripts(subTree, customization); } } if (list[i].ExprType == ExpressionType.Block && (list[i].Name == "^" || list[i].Name == "_") && i > 0) { if (list[i - 1].ExprType == ExpressionType.Command && list[i - 1].Name == "limits") { list[i - 1].EraseFromParent(); i--; } #region Place the previous expression to the script block if (i < list.Count - 1 && list[i + 1].ExprType == ExpressionType.Block && (list[i + 1].Name == "^" || list[i + 1].Name == "_")) { var block = new LatexExpression("script" + list[i].Name + list[i + 1].Name, list[i].Parent, list[i].ParentChildNumber, i - 1, customization); block.MathMode = list[i].MathMode; block.Expressions[0].Add(new LatexExpression(list[i - 1])); block.Expressions[0].Add(new LatexExpression(list[i])); block.Expressions[0].Add(new LatexExpression(list[i + 1])); block.Expressions[0][0].Parent = block; block.Expressions[0][0].ParentChildNumber = 0; block.Expressions[0][0].IndexInParentChild = 0; block.Expressions[0][0].MathMode = block.MathMode; block.Expressions[0][1].Parent = block; block.Expressions[0][1].ParentChildNumber = 0; block.Expressions[0][1].IndexInParentChild = 1; block.Expressions[0][1].MathMode = block.MathMode; block.Expressions[0][2].Parent = block; block.Expressions[0][2].ParentChildNumber = 0; block.Expressions[0][2].IndexInParentChild = 2; block.Expressions[0][2].MathMode = block.MathMode; list[i - 1] = block; list[i].EraseFromParent(); list[i].EraseFromParent(); } else { var block = new LatexExpression("script" + list[i].Name, list[i].Parent, list[i].ParentChildNumber, i - 1, customization); block.MathMode = list[i].MathMode; block.Expressions[0].Add(new LatexExpression(list[i - 1])); block.Expressions[0].Add(new LatexExpression(list[i])); block.Expressions[0][0].Parent = block; block.Expressions[0][0].ParentChildNumber = 0; block.Expressions[0][0].IndexInParentChild = 0; block.Expressions[0][0].MathMode = block.MathMode; block.Expressions[0][1].Parent = block; block.Expressions[0][1].ParentChildNumber = 0; block.Expressions[0][1].IndexInParentChild = 1; block.Expressions[0][1].MathMode = block.MathMode; list[i - 1] = block; list[i].EraseFromParent(); } i--; #endregion } } }