Quiz math fixup bug fixes

closes LS-1685
flag=none

test plan:
  - when a quiz is fixed-up, the tooltips on equation answers should
    be reasonable.
  - if we find inline latex burried in the sea of html-ish text
    it's extracted and turned into an equation image. Sadly
    I don't remember what quiz+question I discovered this on
    (though it was near the top of peyton's course)
  - when fixup generates equation images, the title has its closing
    quote, so the tooltip looks correct.

Change-Id: I21201b094c46ee057d1a6f779d120db303e31bca
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254544
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Nate Armstrong <narmstrong@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
Ed Schiebel 2020-12-07 17:11:54 -05:00
parent eed550ce62
commit 567512cf47
2 changed files with 36 additions and 16 deletions

View File

@ -25,7 +25,7 @@ module QuizMathDataFixup
else else
questions = quiz_or_bank.quiz_questions questions = quiz_or_bank.quiz_questions
end end
questions = questions.where("updated_at>?", check_date) if check_date questions = questions.where('updated_at>?', check_date) if check_date
questions.find_each do |quiz_question| questions.find_each do |quiz_question|
begin begin
old_data = quiz_question.question_data.to_hash old_data = quiz_question.question_data.to_hash
@ -63,13 +63,21 @@ module QuizMathDataFixup
end end
def fixup_question_data(data) def fixup_question_data(data)
%i(neutral_comments_html correct_comments_html incorrect_comments_html).each do |key| %i[neutral_comments_html correct_comments_html incorrect_comments_html].each do |key|
if data[key].present? data[key] = fixup_html(data[key]) if data[key].present?
data[key] = fixup_html(data[key])
end
end end
data[:answers].each_with_index do |answer, index| data[:answers].each_with_index do |answer, index|
%i(html comments_html).each { |key| answer[key] = fixup_html(answer[key]) if answer[key].present? } %i[html comments_html].each do |key|
# if there's html, the text field is used as the title attribute/tooltip
# clear it out if we updated the html because it's probably hosed.
if answer[key].present?
answer[key] = fixup_html(answer[key])
text_key = key.to_s.sub(/html/, 'text')
answer[text_key] = '' if answer[text_key].present?
end
end
data[:answers][index] = answer data[:answers][index] = answer
end end
data data
@ -78,17 +86,28 @@ module QuizMathDataFixup
def fixup_html(html) def fixup_html(html)
return html unless html return html unless html
html = Nokogiri::HTML::DocumentFragment.parse(html) html = Nokogiri::HTML::DocumentFragment.parse(html)
html.search('[id^="MathJax"]').each(&:remove)
if html.children.length == 1 && html.children[0].node_type == Nokogiri::XML::Node::TEXT_NODE if html.children.length == 1 && html.children[0].node_type == Nokogiri::XML::Node::TEXT_NODE
# look for an equation_images URL in the text and extract the latex
m = %r{equation_images\/([^\s]+)}.match(html.content) m = %r{equation_images\/([^\s]+)}.match(html.content)
if m && m[1]
code = URI.unescape(URI.unescape(m[1]))
html =
"<img class='equation_image' src='/equation_images/#{m[1]}' alt='LaTeX: #{code}' title='#{
code
}' data-equation-content='#{code}'/>"
else
# look for \(inline latex\) and extract it
m = html.content.match(/\\\(((?!\\\)).+)\\\)/)
if m && m[1] if m && m[1]
code = URI.unescape(URI.unescape(m[1])) code = URI.unescape(URI.unescape(m[1]))
html = html =
"<img class='equation_image' src='/equation_images/#{m[1]}' alt='LaTeX: #{ "<img class='equation_image' src='/equation_images/#{m[1]}' alt='LaTeX: #{
code code
}' title='#{code} data-equation-content='#{code}>" }' title='#{code}' data-equation-content='#{code}'/>"
end end
return html end
html.search('[id^="MathJax"]').each(&:remove)
return html.to_s
end end
html.search('.math_equation_latex').each do |latex| html.search('.math_equation_latex').each do |latex|
# find MathJax generated children, extract the eq's mathml # find MathJax generated children, extract the eq's mathml
@ -107,17 +126,16 @@ module QuizMathDataFixup
latex.replace( latex.replace(
"<img class='equation_image' src='/equation_images/#{escaped}' alt='LaTeX: #{ "<img class='equation_image' src='/equation_images/#{escaped}' alt='LaTeX: #{
code code
}' title='#{code}>" }' title='#{code}' data-equation-content='#{code}'/>"
) )
elsif mml elsif mml
latex.replace( latex.replace(
"<math xmlns='http://www.w3.org/1998/Math/MathML' class='math_equation_mml'>#{ "<math xmlns='http://www.w3.org/1998/Math/MathML' class='math_equation_mml'>#{mml}</math>"
mml
}</math>"
) )
end end
end end
html.search('[id^="MathJax"]').each(&:remove)
html.search('span.hidden-readable').each(&:remove) html.search('span.hidden-readable').each(&:remove)
html.to_s html.to_s
@ -128,6 +146,8 @@ module QuizMathDataFixup
end end
def check_or_fix_question_banks(batch_of_ids) def check_or_fix_question_banks(batch_of_ids)
AssessmentQuestionBank.where(id: batch_of_ids).find_each { |q| fixup_quiz_questions_with_bad_math(q, question_bank: true) } AssessmentQuestionBank.where(id: batch_of_ids).find_each do |q|
fixup_quiz_questions_with_bad_math(q, question_bank: true)
end
end end
end end

View File

@ -67,7 +67,7 @@ module UserContent
# inadvertently saved the hidden-readable span, causing # inadvertently saved the hidden-readable span, causing
# them to multiply everytime the entity is edited. # them to multiply everytime the entity is edited.
# Strip the ones that shouldn't be there before adding a new one # Strip the ones that shouldn't be there before adding a new one
node.next.remove while node.next && node.next['class'] == 'hidden-readable' node.next_element.remove while node.next_element && node.next_element['class'] == 'hidden-readable'
if !use_updated_math_rendering if !use_updated_math_rendering
mathml = UserContent.latex_to_mathml(equation) mathml = UserContent.latex_to_mathml(equation)