require "csv"
module Metanorma
module Standoc
class PreferredTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :preferred
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
%{#{out}}
end
end
class AltTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :alt
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted,
attrs["text"]).convert
%{#{out}}
end
end
class AdmittedTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :admitted
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted,
attrs["text"]).convert
%{#{out}}
end
end
class DeprecatedTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :deprecated
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted,
attrs["text"]).convert
%{#{out}}
end
end
class DomainTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :domain
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted,
attrs["text"]).convert
%{#{out}}
end
end
class TermRefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :term
name_positional_attributes "name", "termxref"
using_format :short
def process(_parent, _target, attrs)
termref = attrs["termxref"] || attrs["name"]
"#{attrs['name']}" \
"#{termref}"
end
end
class SymbolRefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :symbol
name_positional_attributes "name", "termxref"
using_format :short
def process(_parent, _target, attrs)
termref = attrs["termxref"] || attrs["name"]
"#{attrs['name']}" \
"#{termref}"
end
end
# Possibilities:
# {{<>, term}}
# {{<>, term, text}}
# {{<>, term}}
# {{<>, term, text}}
# {{term}} equivalent to term:[term]
# {{term, text}} equivalent to term:[term, text]
# text may optionally be followed by crossreference-rendering, options=""
class ConceptInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :concept
match /\{\{(?|.*?[^\\])\}\}/m
using_format :short
def preprocess_attrs(target)
m = /^(?<<.+?>>)?(?.*)$/m.match(target)
ret = { id: m[:id]&.sub(/^<</, "")&.sub(/>>$/, "") }
if m2 = /^(?.*?)(?,opt(?:ion)?s=.+)$/m
.match(m[:rest].sub(/^,/, ""))
ret[:opt] = CSV.parse_line(m2[:opt].sub(/^,opt(ion)?s=/, "")
.sub(/^"(.+)"$/m, "\\1").sub(/^'(.+)'$/m, "\\1"))
attrs = preprocess_attrs_csv(m2[:rest])
else attrs = preprocess_attrs_csv(m[:rest])
end
attrs.map! { |x| x.gsub(/\s+/, " ") }
ret.merge(term: attrs[0], word: attrs[1] || attrs[0],
render: attrs[2])
end
def preprocess_attrs_csv(line)
CSV.parse_line(line.sub(/^,/, "")) || []
rescue StandardError
raise "error processing #{line} as CSV"
end
def generate_attrs(opts)
ret = ""
%w(ital bold ref linkmention linkref).each do |x|
opts.include?("no#{x}") and ret += " #{x}='false'"
opts.include?(x) and ret += " #{x}='true'"
end
ret
end
def process(parent, target, _attrs)
attrs = preprocess_attrs(target)
term, word, render = %i(term word render).each_with_object([]) do |x, m|
m << Asciidoctor::Inline.new(parent, :quoted, attrs[x]).convert
end
opt = generate_attrs(attrs[:opt] || [])
if attrs[:id] then "" \
"#{term}#{word}" \
"#{render}"
else "#{term}" \
"#{word}#{render}"
end
rescue StandardError => e
raise("processing {{#{target}}}: #{e.message}")
end
end
# Possibilities:
# related:relation[<>, term]
# related:relation[<>, term]
# related:relation[term] equivalent to a crossreference to term:[term]
class RelatedTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :related
parse_content_as :text
def preprocess_attrs(target)
m = /^(?<<.+?>>, ?)?(?.*)$/.match(target)
{ id: m[:id]&.sub(/^<</, "")&.sub(/>>, ?$/, ""),
term: m[:rest] }
end
def process(parent, target, attrs)
out = preprocess_attrs(attrs["text"])
term = Asciidoctor::Inline.new(parent, :quoted,
out[:term]).convert
if out[:id] then "" \
"#{term}"
else "#{term}" \
"#{term}"
end
rescue StandardError => e
raise("processing related:#{target}[#{attrs['text']}]: #{e.message}")
end
end
end
end