require "asciidoctor/extensions"
require "htmlentities"
require "unicode2latex"
require "mime/types"
require "base64"
require "English"
require "latexmath"
module Metanorma
module Standoc
module Inline
def refid?(ref)
@refids.include? ref
end
def inline_anchor(node)
case node.type
when :ref then inline_anchor_ref node
when :xref then inline_anchor_xref node
when :link then inline_anchor_link node
when :bibref then inline_anchor_bibref node
end
end
def inline_anchor_ref(node)
noko do |xml|
xml.bookmark nil, **attr_code(id: node.id)
end.join
end
def inline_anchor_xref(node)
noko do |xml|
attrs = inline_anchor_xref_attrs(node)
c = attrs[:text]
attrs.delete(:text) unless c.nil?
xml.xref **attr_code(attrs) do |x|
x << c
end
end.join
end
def inline_anchor_xref_attrs(node)
m = inline_anchor_xref_match(node)
t = node.target.gsub(/^#/, "").gsub(%r{(\.xml|\.adoc)(#.*$)}, "\\2")
m.nil? and return { target: t, type: "inline", text: node.text }
{ target: t, type: m[:fn].nil? ? "inline" : "footnote",
case: m[:case]&.sub(/%$/, ""),
droploc: m[:drop].nil? && m[:drop2].nil? ? nil : true,
text: inline_anchor_xref_text(m, node),
hidden: m[:hidden] }
end
def inline_anchor_xref_match(node)
/^(?:hidden%(?[^,]+),?)?
(?droploc%)?(?capital%|lowercase%)?(?droploc%)?
(?fn:?\s*)?(?.*)$/x.match node.text
end
def inline_anchor_xref_text(match, node)
if %i[case fn drop drop2 hidden].any? do |x|
!match[x].nil?
end
match[:text]
else node.text
end
end
def inline_anchor_link(node)
contents = node.text
contents = "" if node.target.gsub(%r{^mailto:}, "") == node.text
attributes = { target: node.target, alt: node.attr("title"),
"update-type": node.attr("updatetype") ||
node.attr("update-type") }
noko do |xml|
xml.link **attr_code(attributes) do |l|
l << contents
end
end.join
end
def inline_anchor_bibref(node)
eref_contents = HTMLEntities.new
.decode(node.text || node.target || node.id)
&.sub(/^\[?([^\[\]]+?)\]?$/, "[\\1]")
@refids << (node.target || node.id)
noko do |xml|
xml.ref **attr_code(id: node.target || node.id) do |r|
r << eref_contents
end
end.join
end
def inline_callout(node)
noko do |xml|
xml.callout node.text
end.join
end
def inline_footnote(node)
@fn_number ||= 0
noko do |xml|
@fn_number += 1
xml.fn **{ reference: @fn_number } do |fn|
fn.p { |p| p << node.text }
end
end.join
end
def inline_break(node)
noko do |xml|
xml << node.text
xml.br
end.join
end
def page_break(node)
attrs = {}
node.option?("landscape") and attrs[:orientation] = "landscape"
node.option?("portrait") and attrs[:orientation] = "portrait"
noko { |xml| xml.pagebreak **attr_code(attrs) }.join
end
def thematic_break(_node)
noko { |xml| xml.hr }.join
end
def xml_encode(text)
HTMLEntities.new.encode(text, :basic, :hexadecimal)
.gsub(/>/, ">").gsub(/</, "<").gsub(/&/, "&")
.gsub(/>/, ">").gsub(/</, "<").gsub(/&/, "&")
.gsub(/"/, '"').gsub(/
/, "\n").gsub(/&#/, "")
end
def latex_parse1(text)
lxm_input = Unicode2LaTeX.unicode2latex(HTMLEntities.new.decode(text))
results = Latexmath.parse(lxm_input).to_mathml
results.nil? and
@log.add("Math", nil,
"latexmlmath failed to process equation:\n#{lxm_input}")
results&.sub(%r{