@zzish/math-rich-input 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,12 @@
1
1
  # MathRichInput
2
2
 
3
- This project is a math rich input component that allows users to edit a "text area" with the following key features:
4
-
5
- 1. Ability to render, insert and edit equations in the input field
6
- 2. A toolbar that appears on focus:
7
- - Buttons for bold, italic, underline, subscript and superscript
8
- - Button for accents
9
- - Button for inserting equations
3
+ This project is a `MathRichInput` component that allows users to edit a "text area" with the following key features:
10
4
 
5
+ 1. Ability to render, insert and edit mathematical equations in the input field
6
+ 2. A toolbar that appears on focus with:
7
+ - Five buttons for bold, italic, underline, subscript and superscript
8
+ - A button for accents and other special characters
9
+ - A button to bring up a WYSIWIG equation editor and insert equations
11
10
 
12
11
  ## Usage
13
12
 
@@ -71,6 +70,21 @@ export default class App extends Component {
71
70
  />
72
71
  }
73
72
  ```
73
+ ### Legacy usage
74
+
75
+ By default the `MathRichInput` will output content in html via the `onChange` callback method. You can force it to output tex and plain text instead using the `outputTex` and `outputPlainText` properties as follows:
76
+
77
+ ```js
78
+ <MathRichInput
79
+ outputTex={true}
80
+ outputPlainText={true}
81
+ value={this.state.value}
82
+ mimeType={this.state.mimeType}
83
+ options={this.state.options}
84
+ onChange={this.handleInputChange}
85
+ />
86
+ ```
87
+
74
88
 
75
89
  ### Rendering content created using MathRichInput with MathRichArea
76
90
 
@@ -82,91 +96,106 @@ export default class App extends Component {
82
96
 
83
97
  See the section on MathRichArea below for more information and alternative ways to render.
84
98
 
85
- #### Mime type
99
+ ## Mime types
86
100
 
87
- In basic usage, the MathRichInput will attempt to work out the appropriate mime type for the inital value property if supplied. However, it is good practice to explicitly set the initial mime type when it is known. For normal usage you can simply set the mime type to application/x-zzish-html-math. You only need to read further if you have preexisting content in application/x-tex format.
101
+ In basic usage, the `MathRichInput` will attempt to work out the appropriate mime type for the inital value property if not supplied. However, it is good practice to explicitly set the initial mime type when it is known. For normal usage of `MathRichInput` using default settings, you can simply set the mime type to `application/x-zzish-html-math`. You only need to read further if you have preexisting content in `text/plain` or `application/x-tex` mime types.
88
102
 
89
103
  The four supported mime types are:
90
104
 
91
- 1. text/plain
92
- 2. text/html
93
- 3. application/x-zzish-html-math
94
- 4. application/x-tex
105
+ 1. `text/plain`
106
+ 2. `application/x-tex`
107
+ 3. `text/html`
108
+ 4. `application/x-zzish-html-math`
109
+
110
+ 2 and 4 support math equations.
111
+
112
+ Content in the `application/x-tex` mime type contains maths in tex equation format between a pair of $ symbols, or pairs of escaped round or square brackets, `\( \)` or `\[ \]`.
113
+
114
+ Content in the `application/x-zzish-html-math` contains maths in tex equation format between a pair of `<math></math>` tags.
95
115
 
96
- The latter two mime types support math equations. Content in the application/x-tex mime type contains maths in tex equation format between a pair of $ symbols. Content in the application/x-zzish-html-math contains maths in tex equation format between a pair of `<math></math>` tags. Here are examples of the two types:
116
+ Here are examples of content in the two types:
97
117
 
98
118
  * "Find all solutions for $x$ when $x^2 + 4x - 2 = \sqrt{9}$"
99
119
  * "Find `<b>`all`</b>` solutions for `<math>`x`</math>` when `<math>`x^2 + 4x - 2 = \sqrt{9}`</math>`"
100
120
 
101
- Note that the application/x-zzish-html-math mime type allows for text with full html formatting richness including `<p></p>`,`<b></b>`,`<i></i>`,`<u></u>`,`<sup></sup>` and `<sub></sub>` tags.
121
+ Note that the `application/x-zzish-html-math` mime type allows for text with full html formatting richness including `<p></p>`,`<b></b>`,`<i></i>`,`<u></u>`,`<sup></sup>` and `<sub></sub>` tags.
102
122
 
103
- The MathRichInput supports the four mime types above, but the key consideration for developers is choosing witheter to set the mime-type initially to one of application/x-tex or application/x-zzish-html-math.
123
+ The MathRichInput supports the four mime types above, but the key consideration for developers is choosing witheter to set the mime-type initially to one of `plain/text`, `application/x-tex` or `application/x-zzish-html-math`.
104
124
 
105
- If your content is only ever created using this MathRichInput component, then you can safely always set the mimeType to application/x-zzish-html-math. This is because, by default, the component will only ever output content in one of the first three mime types and the application/x-zzish-html-math mime type is a superset of the text/plain and text/html formats.
125
+ If your content is only ever created using this `MathRichInput` component with default settings, then you can safely always set the mimeType to `application/x-zzish-html-math`. This is because, by default, the component will only ever output content as `text/html` or `application/x-zzish-html-math` and the `application/x-zzish-html-math` mime type is a superset of the `text/html` mime type.
106
126
 
107
- If, however, you have some legacy content in tex/latex format, you should set the mimeType to application/x-tex when the legacy content is known to be in tex/latex format. If you are unsure whether the content is tex or not, then you can not set a mime type and the MathRichInput will determine the best mime-type. 99% of the time the MathRichInput will choose the correct mime type.
127
+ If, however, you have some legacy content in plain text or tex/latex format, you should ideally set the mimeType as appropriate. If you are unsure as to the type of your content, then you can leave the mime type unset and the `MathRichInput` will choose the best mime-type automatically. It will generally make good choices, but it will make the wrong choice on plain text such as the following:
108
128
 
109
- Whatever the value and mime type of any initial content provided, the input field will always return the content in one of the first three mime types by default (via the onChange callback method):
129
+ * "To bold text in html you should put the text betweeen `<b>` and `<\b>` tags"
110
130
 
111
- 1. text/plain
112
- 2. text/html
113
- 3. application/x-zzish-html-math
131
+ In this example, the automatic detection will assume this is html, as it will identify the bold html tags. It will thus bold the word 'and'. It is not possible for the automatic detection to determine that this was in fact plain text.
114
132
 
115
- These mime types should ideally be stored along with the value and supplied to the MathRichInput and MathRichArea in future.
133
+ Whatever the value and mime type of any initial content provided, the input field will always return the content in one of the two html mime types by default (via the onChange callback method):
116
134
 
117
- If you desire the output to be in tex\latex, then pass the parameter outputTex={true}. When you choose to output in tex, font styling (eg. bold) and multiline are disabled for users. Unless you have a good reason to output in tex, you should not use this settting.
135
+ 1. `text/html`
136
+ 3. `application/x-zzish-html-math`
118
137
 
119
- #### Options
138
+ These mime types should ideally be stored along with the value and supplied back to the `MathRichInput` and `MathRichArea` in future.
139
+
140
+ If you desire the output to be `tex\latex`, then pass the parameter `outputTex={true}`. When you choose to output in tex, font styling (eg. bold) and multiline are disabled for users.
141
+
142
+ By default, any output content that does not contain multiple lines (i.e. `<p></p>` tags), any html font styling (e.g. `<b></b>`), or any math elements will still be returned as `text\html` and any special html characters will be converted to their html codings (for example `<` will be converted to `&gt;`). If required you can choose to have content that does not need any html or math formatting returned as plain text using `outputPlainText={true}`.
143
+
144
+ In general, unless you have a *very* good reason to, you should not set `outputTex={true}` or `outputPlainText={true}` and you should have your content returned as html (`text/html`) or html math (`application/x-zzish-html-math`) as happens with the default settings.
145
+
146
+ ## Options
120
147
 
121
148
  The options property is used to return the current state of the equation editor so that if the user closes and reopens the equation editor, the state is remembered. In particular it allows you to store whether the user:
122
149
 
123
150
  * Is using the equation editor in expert mode
124
- * Has selected a specific synbols tab
151
+ * Has selected a specific symbols tab
125
152
 
126
153
  Note that normally options should be a global object with the same options used across all input fields. This is so that the user does not need to reselect expert mode and/or select the same tab each time they reopen the equation editor.
127
154
 
128
- The options property can be initialed to null rather than set explicitly as above. The options can be saved against the users persistent settings if desired.
155
+ The options property can be initialised to null rather than set explicitly as above. The options can be saved against the user's persistent user settings if desired.
129
156
 
130
157
  #### Other properties
131
158
 
132
159
  ##### enableFontStyling
133
160
 
134
- (not yet implemented)
135
-
136
- Set enableFontStyling={false} to:
161
+ Set `enableFontStyling={false}` to:
137
162
 
138
163
  * Disable the bold, italic, underline, subscript and superscript buttons on the toolbar
139
164
  * Disalbe CTRL-B and other font styling hot keys
140
165
 
141
166
  ##### enableMultiline
142
167
 
143
- (not yet implemented)
144
-
145
- Set enableMultiline={false} to:
168
+ Set `enableMultiline={false}` to:
146
169
 
147
170
  * Disable new lines being entered by pressing the return key
148
171
 
149
172
  ##### enableMath
150
173
 
151
- Set enableMath={false} to:
174
+ Set `enableMath={false}` to:
152
175
 
153
176
  * Disable the equation editor button on the toolbar
154
177
 
155
178
  ##### outputTex
156
179
 
157
- (not yet implemented)
158
-
159
- Set outputTex={true} to:
180
+ Set `outputTex={true}` to:
160
181
 
161
182
  * Force output to be in tex (math equations are enclosed in a pair of $ symbols)
162
183
 
163
- As a side effect, this also implicitly sets enableMultiline and enableFontStyling to false (see above).
184
+ As a side effect, this also implicitly sets `enableMultiline` and `enableFontStyling` to false (see above).
185
+
186
+ ##### outputPlainText
187
+
188
+ Set `outputPlainText={true}` to:
189
+
190
+ * Force output to be in plain text when the input text contains no html and no maths
191
+
192
+ Note that this does not disable multiline or font styling
164
193
 
165
194
  ##### editable
166
195
 
167
196
  (not yet implemented)
168
197
 
169
- Set editable={false} to purely render the value and not allow it to be edited by the user. Note that normally you would use the non-editable MathRichArea component to purely render values (it is a much lighter component).
198
+ Set `editable={false}` to purely render the value and not allow it to be edited by the user. Note that normally you would use the non-editable MathRichArea component to purely render values (it is a much lighter component).
170
199
 
171
200
  ## MathRichArea
172
201
 
@@ -187,7 +216,7 @@ For example, assuming that you had a page containing some content:
187
216
  <div className="question">{this.state.questionText}</div>
188
217
  <div className="answer">{this.state.answerText}</div>
189
218
  ```
190
- where the question and answer text was simple text in the legacy codebase, but is not the content.value returned from a MathRichInput (and thus may - or may not - contain html or maths).
219
+ where the question and answer text was simple text in any one of the four supported mime types.
191
220
 
192
221
  Simply add the following code:
193
222
 
package/dist/index.js CHANGED
@@ -20466,6 +20466,8 @@ function isTextLatexMath(text) {
20466
20466
  // We need at least two dollar signs to be latex
20467
20467
  var i = text.indexOf("$");
20468
20468
  if (i < 0) return false;
20469
+ var j = text.indexOf("\\$");
20470
+ if (j >= 0) return true;
20469
20471
  i = text.indexOf("$", i + 1);
20470
20472
  if (i < 0) return false; // Lets try and extract the potentially latex nodes
20471
20473
 
@@ -20528,15 +20530,15 @@ function isTextLatexMath(text) {
20528
20530
  var allWords = true;
20529
20531
  var longWord = false;
20530
20532
 
20531
- for (var j = 0; j < words.length; j++) {
20533
+ for (var _j = 0; _j < words.length; _j++) {
20532
20534
  // console.log(j+":"+words[j])
20533
- if (words[j].length > 0 && WORDS_REG_EXP.test(words[j]) === false) {
20535
+ if (words[_j].length > 0 && WORDS_REG_EXP.test(words[_j]) === false) {
20534
20536
  // console.log("Not: "+words[j])
20535
20537
  allWords = false;
20536
20538
  break;
20537
20539
  }
20538
20540
 
20539
- if (words[j].length >= 3) longWord = true;
20541
+ if (words[_j].length >= 3) longWord = true;
20540
20542
  }
20541
20543
 
20542
20544
  if (allWords && longWord) return false;
@@ -20619,18 +20621,25 @@ function determineMimeType(text) {
20619
20621
  {this.test("$a bcd> e$", "application/x-tex")}
20620
20622
  */
20621
20623
 
20622
- var RAW_TEXT_MATH_START_TAG_TEX = "$";
20623
- var RAW_TEXT_MATH_END_TAG_TEX = "$";
20624
+ var RAW_TEXT_MATH_START_TAG_TEX = "\\[";
20625
+ var RAW_TEXT_MATH_END_TAG_TEX = "\\]";
20624
20626
  var RAW_TEXT_MATH_START_TAG_HTML_MATH = "<math>";
20625
20627
  var RAW_TEXT_MATH_END_TAG_HTML_MATH = "</math>";
20626
20628
  var INLINE_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]|\\\([\s\S]+?\\\)|\$[^$\\]*(?:\\.[^$\\]*)*\$/g;
20627
- var BLOCK_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]/g; // const HTML_MATH_REG_EXP = /<math>.*?<\/math>/gi;
20629
+ var BLOCK_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]/g; // const INLINE_TEX_REG_EXP = /(?<!\\)\$[\s\S]+?(?<!\\)\$/g
20630
+ // In general, (?<!Y)X matches an X that is not preceded by a Y. so (?<!\\)\$
20631
+ // const INLINE_TEX_REG_EXP = /(?<!\\)(?:((?<!\$)\${1,2}(?!\$))|(\\\()|(\\\[)|(\\begin\{equation\}))(?(1)(.*?)(?<!\\)(?<!\$)\1(?!\$)|(?:(.*(?R)?.*)(?<!\\)(?:(?(2)\\\)|(?(3)\\\]|\\end\{equation\})))))/
20632
+ // const HTML_MATH_REG_EXP = /<math>.*?<\/math>/gi;
20628
20633
 
20629
20634
  var HTML_MATH_REG_EXP = /<math>[\s\S]*?<\/math>/gi;
20630
20635
  var SPAN_OPEN_BASE = "<span class=\"base\">";
20631
20636
  var SPAN_CLOSE = "</span>";
20632
- var MARK$1 = "_M_A_R_K_";
20637
+ var MARK$1 = String.fromCharCode(0); // const MARK = "_M_A_R_K_"
20638
+
20633
20639
  var MARK_REG_EXP$1 = new RegExp(MARK$1, "g");
20640
+ var TEMP_CHAR = String.fromCharCode(1);
20641
+ var TEMP_CHAR_REG_EXP = new RegExp(TEMP_CHAR, "g");
20642
+ var DOLLAR_SLASH_REG_EXP = /\\\$/g;
20634
20643
  var SMALL_SPACE_CHAR_CODE$1 = 8203;
20635
20644
  var SMALL_SPACE$1 = String.fromCharCode(SMALL_SPACE_CHAR_CODE$1);
20636
20645
  var SMALL_SPACE_REG_EXP = new RegExp(SMALL_SPACE$1, "g");
@@ -20772,7 +20781,6 @@ function getLatex(node) {
20772
20781
  // <annotation encoding="application/x-tex">L' = {L}{\sqrt{1-\frac{v^2}{c^2}}}</annotation>
20773
20782
  var annotation = getFirstDescendentByTagName(node, "annotation");
20774
20783
  var latex = annotation.childNodes[0].nodeValue;
20775
- latex = decodeLatex(latex);
20776
20784
  return latex;
20777
20785
  } catch (error) {
20778
20786
  console.error(error);
@@ -20822,41 +20830,60 @@ var decodeFromHtml = function () {
20822
20830
  // Note we don't need to encode it so do nothing here
20823
20831
 
20824
20832
 
20825
- function encodeLatex(text) {
20833
+ function encodeToLatex(text) {
20826
20834
  // console.log("Pre-encoded: "+text)
20827
- // console.log("Post-encoded: "+text)
20835
+ text = text.replace(/\$/g, "\\$"); // console.log("Post-encoded: "+text)
20836
+
20828
20837
  return text;
20829
20838
  } // Note we don't need to decode it so do nothing here
20830
20839
 
20831
20840
 
20832
- function decodeLatex(text) {
20841
+ function decodeFromLatex(text) {
20833
20842
  // console.log("Pre-decoded: "+text)
20834
- // console.log("Post-decoded: "+text)
20843
+ text = text.replace(/\\\$/g, "$"); // console.log("Post-decoded: "+text)
20844
+
20835
20845
  return text;
20836
20846
  }
20837
20847
 
20848
+ function removeEncodingIfPlainText(text, mimeType, useHtmlMath) {
20849
+ if (mimeType !== MIME_TYPE_PLAIN_TEXT$1) return text;
20850
+ if (useHtmlMath) return decodeFromHtml(text);else return decodeFromLatex(text);
20851
+ }
20852
+
20838
20853
  function addText(arrayOfText, text, mark, offset) {
20854
+ var useHtmlMath = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
20855
+
20839
20856
  // console.log("Mark: "+mark)
20840
20857
  if (offset === 0) {
20841
20858
  if (mark) {
20842
- arrayOfText.push(MARK$1); // arrayOfText.push(" ")
20843
-
20859
+ arrayOfText.push(MARK$1);
20844
20860
  arrayOfText.push(MARK$1);
20845
20861
  }
20846
20862
 
20847
20863
  arrayOfText.push(text);
20848
20864
  } else {
20849
- var decoded = decodeFromHtml(text); // console.log("Decoded: "+decoded)
20865
+ if (useHtmlMath) {
20866
+ var decoded = decodeFromHtml(text);
20867
+ arrayOfText.push(encodeToHtml(decoded.substring(0, offset)));
20850
20868
 
20851
- arrayOfText.push(encodeToHtml(decoded.substring(0, offset)));
20869
+ if (mark) {
20870
+ arrayOfText.push(MARK$1);
20871
+ arrayOfText.push(MARK$1);
20872
+ }
20852
20873
 
20853
- if (mark) {
20854
- arrayOfText.push(MARK$1); // arrayOfText.push(" ")
20874
+ arrayOfText.push(encodeToHtml(decoded.substring(offset)));
20875
+ } else {
20876
+ var _decoded = decodeFromLatex(text);
20855
20877
 
20856
- arrayOfText.push(MARK$1);
20857
- }
20878
+ arrayOfText.push(encodeToLatex(_decoded.substring(0, offset)));
20858
20879
 
20859
- arrayOfText.push(encodeToHtml(decoded.substring(offset)));
20880
+ if (mark) {
20881
+ arrayOfText.push(MARK$1);
20882
+ arrayOfText.push(MARK$1);
20883
+ }
20884
+
20885
+ arrayOfText.push(encodeToLatex(_decoded.substring(offset)));
20886
+ }
20860
20887
  }
20861
20888
  }
20862
20889
 
@@ -20869,7 +20896,7 @@ function addTextForNode(node, arrayOfText) {
20869
20896
 
20870
20897
  try {
20871
20898
  if (isTextNode(node)) {
20872
- addText(arrayOfText, useHtmlMath ? encodeToHtml(node.nodeValue) : node.nodeValue, mark, offset, useHtmlMath);
20899
+ addText(arrayOfText, useHtmlMath ? encodeToHtml(node.nodeValue) : encodeToLatex(node.nodeValue), mark, offset, useHtmlMath);
20873
20900
  } else if (isBrNode(node)) {
20874
20901
  useHtmlMath && arrayOfText.push("<br>");
20875
20902
  } else if (isBIUNode(node)) {
@@ -20883,7 +20910,7 @@ function addTextForNode(node, arrayOfText) {
20883
20910
  } else if (isKatexNode(node)) {
20884
20911
  if (mark) arrayOfText.push(MARK$1);
20885
20912
  arrayOfText.push(useHtmlMath ? RAW_TEXT_MATH_START_TAG_HTML_MATH : RAW_TEXT_MATH_START_TAG_TEX);
20886
- arrayOfText.push(encodeLatex(getLatex(node)));
20913
+ arrayOfText.push(getLatex(node));
20887
20914
  arrayOfText.push(useHtmlMath ? RAW_TEXT_MATH_END_TAG_HTML_MATH : RAW_TEXT_MATH_END_TAG_TEX);
20888
20915
  if (mark) arrayOfText.push(MARK$1);
20889
20916
  } else {
@@ -20930,6 +20957,7 @@ function elementToMarkedRawText(element) {
20930
20957
  var raw_text = result.join(""); // remove any zero-width spaces we added to the html
20931
20958
 
20932
20959
  raw_text = raw_text.replace(SMALL_SPACE_REG_EXP, '');
20960
+ console.log("Marked raw text: " + raw_text);
20933
20961
  return raw_text;
20934
20962
  }
20935
20963
  function replaceMarksWithMath(markedRawText, latex) {
@@ -21009,22 +21037,29 @@ function renderLatexString(katex, s, t) {
21009
21037
  function rawTextToHtml(katex, string, mimeType) {
21010
21038
  if (string === "") return "";
21011
21039
  if (mimeType === null || mimeType === undefined || mimeType === "") mimeType = determineMimeType(string);
21012
- if (mimeType === MIME_TYPE_PLAIN_TEXT$1) return string;
21013
- var parseAsTex = false;
21014
- if (mimeType === MIME_TYPE_TEX$1 || mimeType === MIME_TYPE_LATEX) parseAsTex = true;
21015
-
21016
- if (!parseAsTex && mimeType !== MIME_TYPE_HTML$1 && mimeType !== MIME_TYPE_ZZISH_HTML_MATH$1) {
21040
+ if (mimeType === MIME_TYPE_PLAIN_TEXT$1) return encodeToHtml(string);
21041
+ var parseAsTex;
21042
+ if (mimeType === MIME_TYPE_TEX$1 || mimeType === MIME_TYPE_LATEX) parseAsTex = true;else if (mimeType === MIME_TYPE_HTML$1 || mimeType === MIME_TYPE_ZZISH_HTML_MATH$1) parseAsTex = false;else {
21043
+ parseAsTex = false;
21017
21044
  console.error("Unknown mime type: " + mimeType);
21018
- }
21045
+ } // console.log("Original string: "+string)
21046
+
21047
+ if (parseAsTex) string = string.replace(DOLLAR_SLASH_REG_EXP, TEMP_CHAR); // console.log("Modded string: "+string)
21019
21048
 
21020
21049
  var stringElements = string.split(parseAsTex ? INLINE_TEX_REG_EXP : HTML_MATH_REG_EXP); // Insert small space at start of first element if it is an empty element
21021
21050
 
21022
21051
  if (stringElements[0] === "") // This means the original string stars with latex
21023
- stringElements[0] = "&#" + SMALL_SPACE$1.charCodeAt(0); // Insert small space at end of <p></p> elements so that empty lines get rendered
21052
+ stringElements[0] = "&#" + SMALL_SPACE$1.charCodeAt(0);
21024
21053
 
21025
- if (mimeType === MIME_TYPE_ZZISH_HTML_MATH$1 || mimeType === MIME_TYPE_HTML$1) {
21054
+ if (parseAsTex) {
21026
21055
  for (var i = 0; i < stringElements.length; i++) {
21027
- stringElements[i] = stringElements[i].replace(P_TAG_REG_EXP, P_ELEMENT_SMALL_SPACE);
21056
+ stringElements[i] = stringElements[i].replace(TEMP_CHAR_REG_EXP, "$");
21057
+ stringElements[i] = encodeToHtml(stringElements[i]);
21058
+ }
21059
+ } else {
21060
+ // Insert small space at end of <p></p> elements so that empty lines get rendered
21061
+ for (var _i = 0; _i < stringElements.length; _i++) {
21062
+ stringElements[_i] = stringElements[_i].replace(P_TAG_REG_EXP, P_ELEMENT_SMALL_SPACE);
21028
21063
  }
21029
21064
  }
21030
21065
 
@@ -21032,13 +21067,22 @@ function rawTextToHtml(katex, string, mimeType) {
21032
21067
  var latexElements = string.match(parseAsTex ? INLINE_TEX_REG_EXP : HTML_MATH_REG_EXP);
21033
21068
  var result = [];
21034
21069
 
21035
- for (var _i = 0; _i < stringElements.length; _i++) {
21036
- result.push(stringElements[_i]);
21070
+ for (var _i2 = 0; _i2 < stringElements.length; _i2++) {
21071
+ result.push(stringElements[_i2]);
21072
+
21073
+ if (latexElements[_i2]) {
21074
+ var element = latexElements[_i2];
21075
+ var type = void 0;
21076
+
21077
+ if (parseAsTex) {
21078
+ type = getDisplayType(element);
21079
+ element = stripDollars(element);
21080
+ element = element.replace(TEMP_CHAR_REG_EXP, "\\$");
21081
+ } else {
21082
+ type = "inline";
21083
+ element = stripTags(element);
21084
+ }
21037
21085
 
21038
- if (latexElements[_i]) {
21039
- var element = latexElements[_i];
21040
- var type = parseAsTex ? getDisplayType(element) : "inline";
21041
- element = parseAsTex ? stripDollars(element) : stripTags(element);
21042
21086
  var renderedElement = renderLatexString(katex, element, type);
21043
21087
  renderedElement = renderedElement + "&#" + SMALL_SPACE$1.charCodeAt(0);
21044
21088
  result.push(renderedElement);
@@ -21545,6 +21589,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
21545
21589
 
21546
21590
  var mimeType = _this2.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0);
21547
21591
 
21592
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, _this2.enableHtml());
21593
+
21548
21594
  _this2.applyChangesToComponent(raw_text, mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab); // Consume the event
21549
21595
 
21550
21596
 
@@ -21810,6 +21856,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
21810
21856
 
21811
21857
  var mimeType = _this2.getMimeType(nodeCounts.html > 0, true);
21812
21858
 
21859
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, _this2.enableHtml());
21860
+
21813
21861
  _this2.applyChangesToComponent(raw_text, mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
21814
21862
  } catch (error) {
21815
21863
  console.error(error);
@@ -22114,6 +22162,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22114
22162
 
22115
22163
  var mimeType = _this2.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0);
22116
22164
 
22165
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, _this2.enableHtml());
22166
+
22117
22167
  _this2.applyChangesToComponent(raw_text, mimeType, params, _this2.props.useExpertMode, _this2.props.selectedTab);
22118
22168
  } catch (error) {
22119
22169
  console.error(error);
@@ -22394,6 +22444,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22394
22444
 
22395
22445
  var _mimeType = null;
22396
22446
  if (_this2.editingExistingEquation) _mimeType = _this2.getMimeType(_nodeCounts.html > 0, _nodeCounts.katex > 1);else _mimeType = _this2.getMimeType(_nodeCounts.html > 0, _nodeCounts.katex > 0);
22447
+ _new_raw_text = removeEncodingIfPlainText(_new_raw_text, _mimeType, _this2.enableHtml());
22397
22448
 
22398
22449
  _this2.applyChangesToComponent(_new_raw_text, _mimeType, _new_rangeParams6, _this2.props.useExpertMode, _this2.props.selectedTab);
22399
22450
 
@@ -22442,6 +22493,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22442
22493
 
22443
22494
  var mimeType = _this2.getMimeType(nodeCounts.html > 0, true);
22444
22495
 
22496
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, _this2.enableHtml());
22497
+
22445
22498
  _this2.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22446
22499
 
22447
22500
  _this2.setState({
@@ -22526,6 +22579,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22526
22579
  new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, new_text));
22527
22580
  if (rangeParams.startNodeIndex === rangeParams.endNodeIndex && rangeParams.startOffset === rangeParams.endOffset) new_rangeParams.startOffset = new_rangeParams.startOffset + new_text.length;
22528
22581
  new_rangeParams.endOffset = new_rangeParams.endOffset + new_text.length;
22582
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.state.mimeType, _this2.enableHtml());
22529
22583
 
22530
22584
  _this2.applyChangesToComponent(new_raw_text, _this2.state.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22531
22585
  } catch (error) {
@@ -22557,6 +22611,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22557
22611
  console.log(new_rangeParams);
22558
22612
  console.log("Old nodes");
22559
22613
  console.log(_this2.editableDiv.childNodes);
22614
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.state.mimeType, _this2.enableHtml());
22560
22615
 
22561
22616
  _this2.applyChangesToComponent(new_raw_text, _this2.state.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22562
22617
  } catch (error) {
@@ -22593,6 +22648,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22593
22648
  console.log(new_rangeParams);
22594
22649
  console.log("Old nodes");
22595
22650
  console.log(_this2.editableDiv.childNodes);
22651
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.state.mimeType, _this2.enableHtml());
22596
22652
 
22597
22653
  _this2.applyChangesToComponent(new_raw_text, _this2.state.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22598
22654
  } catch (error) {
@@ -22618,6 +22674,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22618
22674
  new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, new_char));
22619
22675
  if (rangeParams.startNodeIndex === rangeParams.endNodeIndex && rangeParams.startOffset === rangeParams.endOffset) new_rangeParams.startOffset = new_rangeParams.startOffset + new_char.length + 1;
22620
22676
  new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length + 1;
22677
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.state.mimeType, _this2.enableHtml());
22621
22678
 
22622
22679
  _this2.applyChangesToComponent(new_raw_text, _this2.state.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22623
22680
  } catch (error) {
@@ -22643,6 +22700,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22643
22700
  new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length;
22644
22701
  } else new_raw_text = removeMarks(replaceCharacterBeforeMarks(raw_text, new_char));
22645
22702
 
22703
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.state.mimeType, _this2.enableHtml());
22704
+
22646
22705
  _this2.applyChangesToComponent(new_raw_text, _this2.state.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22647
22706
  } catch (error) {
22648
22707
  console.error(error);
@@ -22768,12 +22827,19 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22768
22827
 
22769
22828
  }, {
22770
22829
  key: "getMimeType",
22771
- value: function getMimeType(isHtml, hasMath) {
22772
- if (isHtml) {
22773
- if (hasMath) return MIME_TYPE_ZZISH_HTML_MATH;else return MIME_TYPE_HTML;
22774
- } else {
22775
- if (hasMath) return MIME_TYPE_TEX;else return MIME_TYPE_PLAIN_TEXT;
22830
+ value: function getMimeType(hasHtml, hasMath) {
22831
+ var _this$props$outputTex2, _this$props$outputPla;
22832
+
22833
+ var outputTex = (_this$props$outputTex2 = this.props.outputTex) !== null && _this$props$outputTex2 !== void 0 ? _this$props$outputTex2 : false;
22834
+ var outputPlainText = (_this$props$outputPla = this.props.outputPlainText) !== null && _this$props$outputPla !== void 0 ? _this$props$outputPla : false;
22835
+
22836
+ if (outputTex) {
22837
+ if (hasMath || !outputPlainText) return MIME_TYPE_TEX;else return MIME_TYPE_PLAIN_TEXT;
22776
22838
  }
22839
+
22840
+ if (hasMath) return MIME_TYPE_ZZISH_HTML_MATH;
22841
+ if (hasHtml || !outputPlainText) return MIME_TYPE_HTML;
22842
+ return MIME_TYPE_PLAIN_TEXT;
22777
22843
  }
22778
22844
  }, {
22779
22845
  key: "setOldRangeParams",
@@ -23019,7 +23085,9 @@ var MathRichArea = /*#__PURE__*/function (_React$Component) {
23019
23085
  }, {
23020
23086
  key: "render",
23021
23087
  value: function render() {
23022
- var html = rawTextToHtml(katex$1, this.props.children, this.props.mime_type);
23088
+ // console.log("Mime type: "+this.props.mimeType)
23089
+ var html = rawTextToHtml(katex$1, this.props.children, this.props.mimeType); // console.log("html: "+html)
23090
+
23023
23091
  return /*#__PURE__*/React.createElement("span", {
23024
23092
  dangerouslySetInnerHTML: {
23025
23093
  __html: html
@@ -23031,6 +23099,4 @@ var MathRichArea = /*#__PURE__*/function (_React$Component) {
23031
23099
  return MathRichArea;
23032
23100
  }(React.Component);
23033
23101
 
23034
- console.log("hello charles");
23035
-
23036
23102
  export { MathRichArea, MathRichInput, renderMathInNode };
@@ -61,148 +61,6 @@
61
61
  margin: 0px 2px 0px 2px;
62
62
  }
63
63
 
64
- /* Note that the top left position of the toolbar is set programatically in componentDidMount */
65
-
66
- .Toolbar {
67
- position: fixed;
68
- z-index: 1;
69
- /* width:270px; */
70
- height:42px;
71
- background-color: white;
72
- border: 1px solid #d0d0d0;
73
- border-radius: 5px;
74
- box-shadow: 1px 1px 5px #a0a0a0;
75
- animation: 0.5s fadeIn1;
76
- animation-fill-mode: forwards;
77
- top: 0px;
78
- left: 0px; /* important to set this so that toolbar initially renders full width */
79
- }
80
-
81
- @keyframes fadeIn1 {
82
- 0% {
83
- opacity: 0;
84
- }
85
- 100% {
86
- opacity: 1.0;
87
- }
88
- }
89
-
90
- .Toolbar-button {
91
- font-family:sans-serif;
92
- font-size: 16px;
93
- width:40px;
94
- height: 36px;
95
- background-color: white;
96
- border-radius: 5px;
97
- border: 0px;
98
- padding: 1px;
99
- margin: 2px;
100
- }
101
-
102
-
103
- .Toolbar-button:hover {
104
- color: white;
105
- background: #663676;
106
- cursor: pointer;
107
- }
108
-
109
- .Toolbar-button:active {
110
- background: #808080;
111
- color: white;
112
- cursor: pointer;
113
- }
114
-
115
- .TB-narrow {
116
- width:30px;
117
- }
118
-
119
- .TB-wide {
120
- width:46px;
121
- }
122
-
123
- .TB-up4 {
124
- position: relative;
125
- top:-4px;
126
- }
127
-
128
- .TB-selected {
129
- background: #D0D0D0;
130
- color: black;
131
- cursor: pointer;
132
- animation: 0.2s TB-fadeIn;
133
- animation-fill-mode: forwards;
134
- }
135
-
136
- .TB-selected:hover {
137
- color: white;
138
- background: #663676;
139
- cursor: pointer;
140
- }
141
-
142
- @keyframes TB-fadeIn {
143
- 00% {
144
- background: white;
145
- }
146
- 100% {
147
- background: #D0D0D0;
148
- }
149
- }
150
-
151
-
152
- /* Tooltip text */
153
- .Toolbar-button .tooltiptext {
154
- font-weight: normal;
155
- visibility: hidden;
156
- width: 100px;
157
- background-color: #222;
158
- color: #fff;
159
- /*font-weight: bold;*/
160
- font-size: 12px;
161
- text-align: center;
162
- padding: 4px 10px;
163
- border-radius: 6px;
164
-
165
- /* Position the tooltip text - see examples below! */
166
- position: absolute;
167
- z-index: 2;
168
- top: -90%; /* Must leave a small gap between tooltip and button */
169
- left: 50px;
170
-
171
- /* transform: translate (50%,0%); */
172
- }
173
-
174
- /* Show the tooltip text when you mouse over the tooltip container */
175
- .Toolbar-button:hover .tooltiptext {
176
- animation: 0.8s fadeIn2;
177
- animation-fill-mode: forwards;
178
- visibility: visible;
179
- /* width: 100px; */
180
- /* top: -90%; */ /* Must leave a small gap between tooltip and button */
181
- /* left: 20%; */
182
- /* margin-left: -50px; */
183
- }
184
-
185
- @keyframes fadeIn2 {
186
- 00% {
187
- opacity: 0;
188
- }
189
- 70% {
190
- opacity: 0;
191
- }
192
- 100% {
193
- visibility: visible;
194
- opacity: 0.9;
195
- }
196
- }
197
-
198
- /* .tooltip {
199
- position: relative;
200
- display: inline-block;
201
- border-bottom: 1px dotted black; /* If you want dots under the hoverable text
202
- } */
203
-
204
-
205
-
206
64
 
207
65
  .EquationEditorModal-background {
208
66
  position: fixed;
@@ -366,7 +224,149 @@ input:checked + .slider:before {
366
224
 
367
225
  .slider.round:before {
368
226
  border-radius: 50%;
227
+ }/* Note that the top left position of the toolbar is set programatically in componentDidMount */
228
+
229
+ .Toolbar {
230
+ position: fixed;
231
+ z-index: 1;
232
+ /* width:270px; */
233
+ height:42px;
234
+ background-color: white;
235
+ border: 1px solid #d0d0d0;
236
+ border-radius: 5px;
237
+ box-shadow: 1px 1px 5px #a0a0a0;
238
+ animation: 0.5s fadeIn1;
239
+ animation-fill-mode: forwards;
240
+ top: 0px;
241
+ left: 0px; /* important to set this so that toolbar initially renders full width */
242
+ }
243
+
244
+ @keyframes fadeIn1 {
245
+ 0% {
246
+ opacity: 0;
247
+ }
248
+ 100% {
249
+ opacity: 1.0;
250
+ }
251
+ }
252
+
253
+ .Toolbar-button {
254
+ font-family:sans-serif;
255
+ font-size: 16px;
256
+ width:40px;
257
+ height: 36px;
258
+ background-color: white;
259
+ border-radius: 5px;
260
+ border: 0px;
261
+ padding: 1px;
262
+ margin: 2px;
369
263
  }
264
+
265
+
266
+ .Toolbar-button:hover {
267
+ color: white;
268
+ background: #663676;
269
+ cursor: pointer;
270
+ }
271
+
272
+ .Toolbar-button:active {
273
+ background: #808080;
274
+ color: white;
275
+ cursor: pointer;
276
+ }
277
+
278
+ .TB-narrow {
279
+ width:30px;
280
+ }
281
+
282
+ .TB-wide {
283
+ width:46px;
284
+ }
285
+
286
+ .TB-up4 {
287
+ position: relative;
288
+ top:-4px;
289
+ }
290
+
291
+ .TB-selected {
292
+ background: #D0D0D0;
293
+ color: black;
294
+ cursor: pointer;
295
+ animation: 0.2s TB-fadeIn;
296
+ animation-fill-mode: forwards;
297
+ }
298
+
299
+ .TB-selected:hover {
300
+ color: white;
301
+ background: #663676;
302
+ cursor: pointer;
303
+ }
304
+
305
+ @keyframes TB-fadeIn {
306
+ 00% {
307
+ background: white;
308
+ }
309
+ 100% {
310
+ background: #D0D0D0;
311
+ }
312
+ }
313
+
314
+
315
+ /* Tooltip text */
316
+ .Toolbar-button .tooltiptext {
317
+ font-weight: normal;
318
+ visibility: hidden;
319
+ width: 100px;
320
+ background-color: #222;
321
+ color: #fff;
322
+ /*font-weight: bold;*/
323
+ font-size: 12px;
324
+ text-align: center;
325
+ padding: 4px 10px;
326
+ border-radius: 6px;
327
+
328
+ /* Position the tooltip text - see examples below! */
329
+ position: absolute;
330
+ z-index: 2;
331
+ top: -90%; /* Must leave a small gap between tooltip and button */
332
+ left: 50px;
333
+
334
+ /* transform: translate (50%,0%); */
335
+ }
336
+
337
+ /* Show the tooltip text when you mouse over the tooltip container */
338
+ .Toolbar-button:hover .tooltiptext {
339
+ animation: 0.8s fadeIn2;
340
+ animation-fill-mode: forwards;
341
+ visibility: visible;
342
+ /* width: 100px; */
343
+ /* top: -90%; */ /* Must leave a small gap between tooltip and button */
344
+ /* left: 20%; */
345
+ /* margin-left: -50px; */
346
+ }
347
+
348
+ @keyframes fadeIn2 {
349
+ 00% {
350
+ opacity: 0;
351
+ }
352
+ 70% {
353
+ opacity: 0;
354
+ }
355
+ 100% {
356
+ visibility: visible;
357
+ opacity: 0.9;
358
+ }
359
+ }
360
+
361
+ /* .tooltip {
362
+ position: relative;
363
+ display: inline-block;
364
+ border-bottom: 1px dotted black; /* If you want dots under the hoverable text
365
+ } */
366
+
367
+
368
+
369
+
370
370
  /* Note that the top left position of the accent bar is set programatically in componentDidMount */
371
371
 
372
372
  .AccentBar {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zzish/math-rich-input",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React component for user to enter rich text with embedded math equations.",
5
5
  "repository": {
6
6
  "type": "git",
package/rollup.config.js CHANGED
@@ -9,7 +9,7 @@ export default {
9
9
  input: "src/index.js",
10
10
  output: {
11
11
  file: "dist/index.js",
12
- // format: "cjs",
12
+ format: "cjs",
13
13
  },
14
14
  plugins: [
15
15
  nodeResolve({ main: true }),
@@ -3,7 +3,7 @@ import React from 'react'
3
3
  import katex from "katex";
4
4
  import {setupKatex} from "./katexHelper"
5
5
  import {rawTextToHtml} from './mathRichInputHelper'
6
- import {MIME_TYPE_TEX, MIME_TYPE_HTML, MIME_TYPE_ZZISH_HTML_MATH,
6
+ import {MIME_TYPE_TEX, MIME_TYPE_HTML, MIME_TYPE_ZZISH_HTML_MATH,
7
7
  isTextLatexMath, isTextHtml, isTextHtmlMath} from './mimeTypeHelper'
8
8
 
9
9
 
@@ -96,8 +96,13 @@ export default class MathRichArea extends React.Component {
96
96
  }
97
97
 
98
98
  render() {
99
- let html = rawTextToHtml(katex, this.props.children, this.props.mime_type)
99
+ // console.log("Mime type: "+this.props.mimeType)
100
+ let html = rawTextToHtml(katex, this.props.children, this.props.mimeType)
101
+ // console.log("html: "+html)
100
102
 
101
103
  return <span dangerouslySetInnerHTML={{__html: html}}></span>
102
104
  }
103
- }
105
+ }
106
+
107
+
108
+
@@ -9,6 +9,7 @@ import Toolbar from './Toolbar'
9
9
  import {
10
10
  isKatexNode,
11
11
  elementToMarkedRawText,
12
+ removeEncodingIfPlainText,
12
13
  rawTextToHtml,
13
14
  getLatex,
14
15
  setRangeParams,
@@ -147,18 +148,23 @@ export default class MathRichInput extends React.Component {
147
148
  // /<\s*sub[^>]*>(.*?)<\s*\/\s*sub\s*>/i.test(text)
148
149
  // }
149
150
 
150
- getMimeType(isHtml, hasMath) {
151
- if (isHtml) {
152
- if (hasMath)
153
- return MIME_TYPE_ZZISH_HTML_MATH
154
- else
155
- return MIME_TYPE_HTML
156
- } else {
157
- if (hasMath)
151
+ getMimeType(hasHtml, hasMath) {
152
+ let outputTex = this.props.outputTex ?? false
153
+ let outputPlainText = this.props.outputPlainText ?? false
154
+
155
+ if (outputTex) {
156
+ if (hasMath || !outputPlainText)
158
157
  return MIME_TYPE_TEX
159
158
  else
160
159
  return MIME_TYPE_PLAIN_TEXT
161
- }
160
+ }
161
+
162
+ if (hasMath)
163
+ return MIME_TYPE_ZZISH_HTML_MATH
164
+ if (hasHtml || !outputPlainText)
165
+ return MIME_TYPE_HTML
166
+
167
+ return MIME_TYPE_PLAIN_TEXT
162
168
  }
163
169
 
164
170
  _countNodeTypes = () => {
@@ -420,6 +426,7 @@ export default class MathRichInput extends React.Component {
420
426
 
421
427
  let nodeCounts = this._countNodeTypes()
422
428
  let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0)
429
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
423
430
 
424
431
  this.applyChangesToComponent(raw_text, mimeType, new_rangeParams,
425
432
  this.props.useExpertMode, this.props.selectedTab)
@@ -697,6 +704,7 @@ export default class MathRichInput extends React.Component {
697
704
 
698
705
  let nodeCounts = this._countNodeTypes()
699
706
  let mimeType = this.getMimeType(nodeCounts.html > 0, true)
707
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
700
708
 
701
709
  this.applyChangesToComponent(raw_text,
702
710
  mimeType,
@@ -991,7 +999,7 @@ export default class MathRichInput extends React.Component {
991
999
  handleInput = (event) => {
992
1000
  try {
993
1001
  // console.log("handleInput")
994
- const raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml())
1002
+ let raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml())
995
1003
  const params = this._getRangeParams()
996
1004
  if (params === null || params === undefined)
997
1005
  console.error("Could not get range params from input field")
@@ -1004,6 +1012,8 @@ export default class MathRichInput extends React.Component {
1004
1012
 
1005
1013
  let nodeCounts = this._countNodeTypes()
1006
1014
  let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0)
1015
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
1016
+
1007
1017
  this.applyChangesToComponent(raw_text, mimeType, params,
1008
1018
  this.props.useExpertMode, this.props.selectedTab)
1009
1019
  } catch (error) {
@@ -1305,6 +1315,7 @@ export default class MathRichInput extends React.Component {
1305
1315
  mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.katex > 1)
1306
1316
  else
1307
1317
  mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.katex > 0)
1318
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, this.enableHtml())
1308
1319
 
1309
1320
  this.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams,
1310
1321
  this.props.useExpertMode, this.props.selectedTab)
@@ -1346,6 +1357,7 @@ export default class MathRichInput extends React.Component {
1346
1357
 
1347
1358
  let nodeCounts = this._countNodeTypes()
1348
1359
  let mimeType = this.getMimeType(nodeCounts.html > 0, true)
1360
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, this.enableHtml())
1349
1361
 
1350
1362
  this.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams,
1351
1363
  this.props.useExpertMode, this.props.selectedTab)
@@ -1430,6 +1442,8 @@ export default class MathRichInput extends React.Component {
1430
1442
  new_rangeParams.startOffset = new_rangeParams.startOffset + new_text.length
1431
1443
  new_rangeParams.endOffset = new_rangeParams.endOffset + new_text.length
1432
1444
 
1445
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1446
+
1433
1447
  this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1434
1448
  this.props.useExpertMode, this.props.selectedTab)
1435
1449
  } catch (error) {
@@ -1460,6 +1474,8 @@ export default class MathRichInput extends React.Component {
1460
1474
  console.log("Old nodes")
1461
1475
  console.log(this.editableDiv.childNodes)
1462
1476
 
1477
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1478
+
1463
1479
  this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1464
1480
  this.props.useExpertMode, this.props.selectedTab)
1465
1481
  } catch (error) {
@@ -1498,6 +1514,8 @@ export default class MathRichInput extends React.Component {
1498
1514
  console.log("Old nodes")
1499
1515
  console.log(this.editableDiv.childNodes)
1500
1516
 
1517
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1518
+
1501
1519
  this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1502
1520
  this.props.useExpertMode, this.props.selectedTab)
1503
1521
  } catch (error) {
@@ -1521,6 +1539,7 @@ export default class MathRichInput extends React.Component {
1521
1539
  new_rangeParams.startOffset = new_rangeParams.startOffset + new_char.length + 1
1522
1540
  new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length + 1
1523
1541
 
1542
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1524
1543
  this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1525
1544
  this.props.useExpertMode, this.props.selectedTab)
1526
1545
  } catch (error) {
@@ -1547,6 +1566,7 @@ export default class MathRichInput extends React.Component {
1547
1566
  else
1548
1567
  new_raw_text = removeMarks(replaceCharacterBeforeMarks(raw_text, new_char))
1549
1568
 
1569
+ new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1550
1570
  this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1551
1571
  this.props.useExpertMode, this.props.selectedTab)
1552
1572
  } catch (error) {
@@ -1,22 +1,34 @@
1
1
  import { determineMimeType } from './mimeTypeHelper'
2
2
 
3
- export const RAW_TEXT_MATH_START_TAG_TEX = "$"
4
- export const RAW_TEXT_MATH_END_TAG_TEX = "$"
3
+ export const RAW_TEXT_MATH_START_TAG_TEX = "\\["
4
+ export const RAW_TEXT_MATH_END_TAG_TEX = "\\]"
5
5
  export const RAW_TEXT_MATH_START_TAG_HTML_MATH = "<math>"
6
6
  export const RAW_TEXT_MATH_END_TAG_HTML_MATH = "</math>"
7
7
 
8
8
  const INLINE_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]|\\\([\s\S]+?\\\)|\$[^$\\]*(?:\\.[^$\\]*)*\$/g;
9
9
  const BLOCK_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]/g;
10
10
 
11
+ // const INLINE_TEX_REG_EXP = /(?<!\\)\$[\s\S]+?(?<!\\)\$/g
12
+
13
+ // In general, (?<!Y)X matches an X that is not preceded by a Y. so (?<!\\)\$
14
+
15
+ // const INLINE_TEX_REG_EXP = /(?<!\\)(?:((?<!\$)\${1,2}(?!\$))|(\\\()|(\\\[)|(\\begin\{equation\}))(?(1)(.*?)(?<!\\)(?<!\$)\1(?!\$)|(?:(.*(?R)?.*)(?<!\\)(?:(?(2)\\\)|(?(3)\\\]|\\end\{equation\})))))/
16
+
17
+
11
18
  // const HTML_MATH_REG_EXP = /<math>.*?<\/math>/gi;
12
19
  const HTML_MATH_REG_EXP = /<math>[\s\S]*?<\/math>/gi;
13
20
 
14
21
  const SPAN_OPEN_BASE = "<span class=\"base\">"
15
22
  const SPAN_CLOSE = "</span>"
16
23
 
17
- const MARK = "_M_A_R_K_"
24
+ const MARK = String.fromCharCode(0)
25
+ // const MARK = "_M_A_R_K_"
18
26
  const MARK_REG_EXP = new RegExp(MARK, "g")
19
27
 
28
+ const TEMP_CHAR = String.fromCharCode(1)
29
+ const TEMP_CHAR_REG_EXP = new RegExp(TEMP_CHAR, "g")
30
+ const DOLLAR_SLASH_REG_EXP = /\\\$/g
31
+
20
32
  const SMALL_SPACE_CHAR_CODE = 8203
21
33
  const SMALL_SPACE = String.fromCharCode(SMALL_SPACE_CHAR_CODE)
22
34
  const SMALL_SPACE_REG_EXP = new RegExp(SMALL_SPACE, "g")
@@ -195,7 +207,6 @@ export function getLatex(node) {
195
207
  // <annotation encoding="application/x-tex">L' = {L}{\sqrt{1-\frac{v^2}{c^2}}}</annotation>
196
208
  let annotation = getFirstDescendentByTagName(node, "annotation")
197
209
  let latex = annotation.childNodes[0].nodeValue
198
- latex = decodeLatex(latex)
199
210
  return latex
200
211
  } catch (error) {
201
212
  console.error(error)
@@ -211,7 +222,7 @@ function encodeToHtml(text) {
211
222
  text = text.replace(/</g,"&lt;")
212
223
  text = text.replace(/'/g,"&apos;")
213
224
  text = text.replace(/"/g,"&quot;")
214
- text = text.replace(/\$/g,"&#36;")
225
+ text = text.replace(/\$/g,"&#36;")
215
226
  return text
216
227
  }
217
228
 
@@ -247,38 +258,57 @@ var decodeFromHtml = (function() {
247
258
  // }
248
259
 
249
260
  // Note we don't need to encode it so do nothing here
250
- function encodeLatex(text) {
261
+ function encodeToLatex(text) {
251
262
  // console.log("Pre-encoded: "+text)
263
+ text = text.replace(/\$/g,"\\$")
252
264
  // console.log("Post-encoded: "+text)
253
265
  return text
254
266
  }
255
267
 
256
268
  // Note we don't need to decode it so do nothing here
257
- function decodeLatex(text) {
269
+ function decodeFromLatex(text) {
258
270
  // console.log("Pre-decoded: "+text)
271
+ text = text.replace(/\\\$/g,"$")
259
272
  // console.log("Post-decoded: "+text)
260
273
  return text
261
274
  }
262
275
 
263
- function addText(arrayOfText, text, mark, offset) {
276
+ export function removeEncodingIfPlainText(text, mimeType, useHtmlMath) {
277
+ if (mimeType !== MIME_TYPE_PLAIN_TEXT)
278
+ return text
279
+
280
+ if (useHtmlMath)
281
+ return decodeFromHtml(text)
282
+ else
283
+ return decodeFromLatex(text)
284
+ }
285
+
286
+ function addText(arrayOfText, text, mark, offset, useHtmlMath=true) {
264
287
  // console.log("Mark: "+mark)
265
288
  if (offset === 0) {
266
289
  if (mark) {
267
290
  arrayOfText.push(MARK)
268
- // arrayOfText.push(" ")
269
291
  arrayOfText.push(MARK)
270
292
  }
271
293
  arrayOfText.push(text)
272
294
  } else {
273
- let decoded = decodeFromHtml(text)
274
- // console.log("Decoded: "+decoded)
275
- arrayOfText.push(encodeToHtml(decoded.substring(0,offset)))
276
- if (mark) {
277
- arrayOfText.push(MARK)
278
- // arrayOfText.push(" ")
279
- arrayOfText.push(MARK)
295
+ if (useHtmlMath) {
296
+ let decoded = decodeFromHtml(text)
297
+ arrayOfText.push(encodeToHtml(decoded.substring(0,offset)))
298
+ if (mark) {
299
+ arrayOfText.push(MARK)
300
+ arrayOfText.push(MARK)
301
+ }
302
+ arrayOfText.push(encodeToHtml(decoded.substring(offset)))
303
+ } else {
304
+ let decoded = decodeFromLatex(text)
305
+ arrayOfText.push(encodeToLatex(decoded.substring(0,offset)))
306
+ if (mark) {
307
+ arrayOfText.push(MARK)
308
+ arrayOfText.push(MARK)
309
+ }
310
+ arrayOfText.push(encodeToLatex(decoded.substring(offset)))
280
311
  }
281
- arrayOfText.push(encodeToHtml(decoded.substring(offset)))
282
312
  }
283
313
  }
284
314
 
@@ -291,7 +321,7 @@ function addTextForNode(node, arrayOfText, nodeToMark=null, offset=0, useHtmlMat
291
321
  try {
292
322
  if (isTextNode(node)) {
293
323
  addText(arrayOfText,
294
- useHtmlMath ? encodeToHtml(node.nodeValue) : node.nodeValue,
324
+ useHtmlMath ? encodeToHtml(node.nodeValue) : encodeToLatex(node.nodeValue),
295
325
  mark, offset, useHtmlMath)
296
326
  } else if (isBrNode(node)) {
297
327
  useHtmlMath && arrayOfText.push("<br>")
@@ -305,7 +335,7 @@ function addTextForNode(node, arrayOfText, nodeToMark=null, offset=0, useHtmlMat
305
335
  if (mark)
306
336
  arrayOfText.push(MARK)
307
337
  arrayOfText.push(useHtmlMath ? RAW_TEXT_MATH_START_TAG_HTML_MATH : RAW_TEXT_MATH_START_TAG_TEX)
308
- arrayOfText.push(encodeLatex(getLatex(node)))
338
+ arrayOfText.push(getLatex(node))
309
339
  arrayOfText.push(useHtmlMath ? RAW_TEXT_MATH_END_TAG_HTML_MATH : RAW_TEXT_MATH_END_TAG_TEX)
310
340
  if (mark)
311
341
  arrayOfText.push(MARK)
@@ -350,7 +380,9 @@ export function elementToMarkedRawText(element, nodeToMark=null, offset=0, useHt
350
380
 
351
381
  // remove any zero-width spaces we added to the html
352
382
  raw_text = raw_text.replace(SMALL_SPACE_REG_EXP,'')
353
-
383
+
384
+ console.log("Marked raw text: " + raw_text)
385
+
354
386
  return raw_text
355
387
  }
356
388
 
@@ -444,23 +476,38 @@ export function rawTextToHtml(katex, string, mimeType) {
444
476
  mimeType = determineMimeType(string)
445
477
 
446
478
  if (mimeType === MIME_TYPE_PLAIN_TEXT)
447
- return string
479
+ return encodeToHtml(string)
448
480
 
449
- let parseAsTex = false
450
- if (mimeType === MIME_TYPE_TEX || mimeType === MIME_TYPE_LATEX)
481
+ let parseAsTex
482
+ if (mimeType === MIME_TYPE_TEX ||
483
+ mimeType === MIME_TYPE_LATEX)
451
484
  parseAsTex = true
452
- if (!parseAsTex && (mimeType !== MIME_TYPE_HTML && mimeType !== MIME_TYPE_ZZISH_HTML_MATH)) {
485
+ else if (mimeType === MIME_TYPE_HTML ||
486
+ mimeType === MIME_TYPE_ZZISH_HTML_MATH)
487
+ parseAsTex = false
488
+ else {
489
+ parseAsTex = false
453
490
  console.error("Unknown mime type: "+mimeType)
454
491
  }
455
492
 
493
+ // console.log("Original string: "+string)
494
+ if (parseAsTex)
495
+ string = string.replace(DOLLAR_SLASH_REG_EXP, TEMP_CHAR)
496
+ // console.log("Modded string: "+string)
497
+
456
498
  const stringElements = string.split(parseAsTex ? INLINE_TEX_REG_EXP : HTML_MATH_REG_EXP);
457
499
 
458
500
  // Insert small space at start of first element if it is an empty element
459
501
  if (stringElements[0] === "") // This means the original string stars with latex
460
502
  stringElements[0] = "&#" + SMALL_SPACE.charCodeAt(0)
461
503
 
462
- // Insert small space at end of <p></p> elements so that empty lines get rendered
463
- if (mimeType === MIME_TYPE_ZZISH_HTML_MATH || mimeType === MIME_TYPE_HTML) {
504
+ if (parseAsTex) {
505
+ for (let i = 0; i <stringElements.length; i++) {
506
+ stringElements[i] = stringElements[i].replace(TEMP_CHAR_REG_EXP, "$")
507
+ stringElements[i] = encodeToHtml(stringElements[i])
508
+ }
509
+ } else {
510
+ // Insert small space at end of <p></p> elements so that empty lines get rendered
464
511
  for (let i = 0; i <stringElements.length; i++)
465
512
  stringElements[i] = stringElements[i].replace(P_TAG_REG_EXP, P_ELEMENT_SMALL_SPACE)
466
513
  }
@@ -476,8 +523,15 @@ export function rawTextToHtml(katex, string, mimeType) {
476
523
 
477
524
  if (latexElements[i]) {
478
525
  let element = latexElements[i]
479
- const type = parseAsTex ? getDisplayType(element) : "inline"
480
- element = parseAsTex ? stripDollars(element) : stripTags(element)
526
+ let type
527
+ if (parseAsTex) {
528
+ type = getDisplayType(element)
529
+ element = stripDollars(element)
530
+ element = element.replace(TEMP_CHAR_REG_EXP, "\\$")
531
+ } else {
532
+ type = "inline"
533
+ element = stripTags(element)
534
+ }
481
535
 
482
536
  let renderedElement = renderLatexString(katex, element, type)
483
537
  renderedElement = renderedElement + "&#"+SMALL_SPACE.charCodeAt(0)
@@ -25,6 +25,9 @@ export function isTextLatexMath(text) {
25
25
  let i = text.indexOf("$")
26
26
  if (i < 0)
27
27
  return false
28
+ let j = text.indexOf("\\$")
29
+ if (j >=0)
30
+ return true
28
31
  i = text.indexOf("$",i+1)
29
32
  if (i < 0)
30
33
  return false