Commit b68567b0 authored by RawKStar77's avatar RawKStar77

Create renderInlineMath() to handle edge cases

Splits up math and markdown rendering into 2 functions:

renderMathAndMarkdown handles blockmath, and renderInlineMath handles inline math. Multiline math like matrices is not supported with inline math, but this is ok because it wouldn't look right anyway.
parent ff23ee93
...@@ -100,9 +100,9 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc ...@@ -100,9 +100,9 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc
end = (text.before + text.selection).length - 2 end = (text.before + text.selection).length - 2
insertMarkup(newtext, start, end) insertMarkup(newtext, start, end)
return return
newtext = text.before + "\\(" + "LaTex" + "\\)" + text.after newtext = text.before + "\\(" + "LaTex or MathML" + "\\)" + text.after
start = text.before.length + 2 start = text.before.length + 2
end = (text.before + "LaTex").length + 2 end = (text.before + "LaTex or MathML").length + 2
insertMarkup(newtext, start, end) insertMarkup(newtext, start, end)
scope.insertMath = -> scope.insertMath = ->
...@@ -110,16 +110,16 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc ...@@ -110,16 +110,16 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc
index = text.before.length index = text.before.length
if index == 0 if index == 0
# The selection takes place at the very start of the input # The selection takes place at the very start of the input
applyInlineMarkup("$$", "LaTex") applyInlineMarkup("$$", "LaTex or MathML")
else if text.selection != "" else if text.selection != ""
if input.value.substring(index - 1).charAt(0) == "\n" if input.value.substring(index - 1).charAt(0) == "\n"
# Look to see if the selection falls at the beginning of a new line. # Look to see if the selection falls at the beginning of a new line.
applyInlineMarkup("$$", "LaTex") applyInlineMarkup("$$", "LaTex or MathML")
else else
inlineMath(text) inlineMath(text)
else if input.value.substring((text.start - 1 ), text.start) == "\n" else if input.value.substring((text.start - 1 ), text.start) == "\n"
# Edge case, no selection, the cursor is on a new line. # Edge case, no selection, the cursor is on a new line.
applyInlineMarkup("$$", "LaTex") applyInlineMarkup("$$", "LaTex or MathML")
else else
# No selection, cursor is not on new line. # No selection, cursor is not on new line.
inlineMath(text) inlineMath(text)
...@@ -299,81 +299,66 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc ...@@ -299,81 +299,66 @@ markdown = ['$filter', '$sanitize', '$sce', '$timeout', ($filter, $sanitize, $sc
input.style.height = output.style.height input.style.height = output.style.height
$timeout -> inputEl.focus() $timeout -> inputEl.focus()
MathJaxFallback = false mathJaxFallback = false
# Re-render the markdown when the view needs updating. renderMathAndMarkdown = (textToCheck) ->
ctrl.$render = ->
if !scope.readonly and !scope.preview
inputEl.val (ctrl.$viewValue or '')
value = ctrl.$viewValue or ''
convert = $filter('converter') convert = $filter('converter')
re = /(?:\$\$)|(?:\\?\\\(|\\?\\\))/g re = /\$\$/g
htmlElement = /<[a-z]+>/
startMath = 0 startMath = 0
endMath = 0 endMath = 0
i = 0
parts = []
indexes = (match while match = re.exec(value))
indexes.push(value.length)
###
XXX Hacky stuff: Our markdown converter removes backslashes causing problems for certain
types of math. To address this we split the input up on math delimiters, and now don't
run the math through our markdown converter. This works great for blockmath but inline math
causes some difficulties. While the code below works for most things, there are a few edge
cases such as use of math within block quotes or lists that cause the output to look weird.
This is because the input to the markdown convert is getting split up in ways that do not
reflect how the text should actually be rendered.
For example: indexes = (match.index while match = re.exec(textToCheck))
* We can use inline math like this \(1+1=2\) see! indexes.push(textToCheck.length)
Renders as: parts = for index in indexes
<ul>
<li>We can use inline math like this </li>
<span class="katex">MATH</span>see!<p></p></ul>
###
for match in indexes
if startMath > endMath if startMath > endMath
endMath = match.index + match.toString().length endMath = index + 2
try try
parts.push katex.renderToString($sanitize value.substring(startMath, match.index)) katex.renderToString($sanitize textToCheck.substring(startMath, index))
catch catch
loadMathJax() loadMathJax()
MathJaxFallback = true mathJaxFallback = true
parts.push $sanitize value.substring(startMath, match.index) $sanitize textToCheck.substring(startMath, index)
else else
startMath = match.index + match.toString().length startMath = index + 2
# Inline math needs to fall inline, which can be tricky considering the markdown $sanitize convert renderInlineMath textToCheck.substring(endMath, index)
# converter will take the part that comes before a peice of math and surround it
# with markup: <p>Here is some inline math: </p>\(2 + 2 = 4\) return parts.join('')
# Here we look for various cases.
if match[0] == "\\(" renderInlineMath = (textToCheck) ->
# Text falls between two instances of inline math, we must remove the opening and re = /\\?\\\(|\\?\\\)/g
# closing <p> tags since this is meant to be one paragraph. startMath = null
if i - 1 >= 0 and indexes[i - 1].toString() == "\\)" endMath = null
markdown = $sanitize convert value.substring(endMath, match.index) match = undefined
tagLength = htmlElement.exec(markdown)[0].length indexes = []
parts.push markdown.substring(tagLength, markdown.length - (tagLength + 1)) while match = re.exec(textToCheck)
# Text preceeds a case of inline math. We must remove the ending </p> tag indexes.push [
# so that the math is inline. match.index
]
for index in indexes
if startMath == null
startMath = index[0] + 2
else else
markdown = $sanitize convert value.substring(endMath, match.index) endMath = index[0]
tagLength = htmlElement.exec(markdown)[0].length if startMath != null and endMath != null
parts.push markdown.substring(0, markdown.length - (tagLength + 1)) math = katex.renderToString(textToCheck.substring(startMath, endMath))
# Text follows a case of inline math, we must remove opening <p> tag. textToCheck = (
else if i - 1 >= 0 and indexes[i - 1].toString() == "\\)" textToCheck.substring(0, (startMath - 2)) + math +
markdown = $sanitize convert value.substring(endMath, match.index) textToCheck.substring((endMath + 2))
tagLength = htmlElement.exec(markdown)[0].length )
parts.push markdown.substring(tagLength, markdown.length) startMath = null
else # Block Math or no math. endMath = null
parts.push $sanitize convert value.substring(endMath, match.index) return renderInlineMath(textToCheck)
i++ return textToCheck
scope.rendered = $sce.trustAsHtml parts.join('') # Re-render the markdown when the view needs updating.
if MathJaxFallback ctrl.$render = ->
if !scope.readonly and !scope.preview
inputEl.val (ctrl.$viewValue or '')
value = ctrl.$viewValue or ''
rendered = renderMathAndMarkdown value
scope.rendered = $sce.trustAsHtml rendered
if mathJaxFallback
$timeout (-> MathJax?.Hub.Queue ['Typeset', MathJax.Hub, output]), 0, false $timeout (-> MathJax?.Hub.Queue ['Typeset', MathJax.Hub, output]), 0, false
# React to the changes to the input # React to the changes to the input
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment