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