diff --git a/lib/main.js b/lib/main.js index 01fe4d7e..c3f61bec 100644 --- a/lib/main.js +++ b/lib/main.js @@ -742,12 +742,18 @@ function GetState(state) { MathJax.OutputJax.CommonHTML.ID = 0; } - // Clear any existing user defined macros + // Clear any existing user defined macros, then load macros from state Object.keys(TEX.Definitions.macros).forEach(function(macroName){ if (TEX.Definitions.macros[macroName].isUser) { delete TEX.Definitions.macros[macroName]; } }); + if (state && state.macros) { + for (var macroName in state.macros) { + TEX.Definitions.macros[macroName] = state.macros[macroName]; + TEX.Definitions.macros[macroName].isUser = true; + } + } } // @@ -772,6 +778,7 @@ function ReturnResult(result) { if (state) { var AMS = MathJax.Extension["TeX/AMSmath"]; var GLYPH = MathJax.OutputJax.SVG.BBOX.GLYPH; + var TEX = MathJax.InputJax.TeX; state.AMS.startNumber = AMS.startNumber; state.AMS.labels = AMS.labels; state.AMS.IDs = AMS.IDs; @@ -780,6 +787,13 @@ function ReturnResult(result) { state.defs = GLYPH.defs; state.n = GLYPH.n; state.ID = ID; + state.macros = {}; + for (var macroName in TEX.Definitions.macros) { + var macro = TEX.Definitions.macros[macroName]; + if (macro.isUser) { + state.macros[macroName] = macro; + } + } } serverState = STATE.READY; callback(result, originalData); diff --git a/test/macro-state.js b/test/macro-state.js index 23af5db7..e2007bb7 100644 --- a/test/macro-state.js +++ b/test/macro-state.js @@ -21,3 +21,40 @@ tape('macros should be cleared from global state', function(t) { t.true(data.errors, '\\mymacro should no longer be defined'); }); }); + +tape('macros can be persisted using state option', function(t) { + t.plan(4); + mjAPI.start(); + + var state = {}; + + mjAPI.typeset({ + math: "\\def\\mymacro{2\\pi} \\mymacro", + format: "TeX", + mml: true, + state: state + }, function(data) { + t.false(data.errors, 'Defined and used macro'); + t.equal(Object.keys(state.macros).length, 1, 'Only stores the user defined macro in state'); + + // Ensure state contains only serializable data + state = JSON.parse(JSON.stringify(state)); + + mjAPI.typeset({ + math: "\\mymacro", + format: "TeX", + mml: true, + state: state + }, function(data) { + t.false(data.errors, '\\mymacro was not persisted in state'); + }); + + mjAPI.typeset({ + math: "\\mymacro", + format: "TeX", + mml: true, + }, function(data) { + t.true(data.errors, '\\mymacro should no longer be defined if state is not provided'); + }); + }); +});