require "asciidoctor/extensions"
require "fileutils"
require "uuidtools"
require "yaml"
require_relative "./macros_plantuml.rb"
require_relative "./datamodel/attributes_table_preprocessor.rb"
require_relative "./datamodel/diagram_preprocessor.rb"
require "metanorma-plugin-datastruct"
require "metanorma-plugin-lutaml"
module Asciidoctor
module Standoc
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 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 InheritInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :inherit
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 ConceptInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :concept
name_positional_attributes "id", "word", "term"
# match %r{concept:(?[^\[]*)\[(?|.*?[^\\])\]$}
match /\{\{(?|.*?[^\\])\}\}/
using_format :short
# deal with locality attrs and their disruption of positional attrs
def preprocess_attrs(attrs)
attrs.delete("term") if attrs["term"] && !attrs["word"]
attrs.delete(3) if attrs[3] == attrs["term"]
a = attrs.keys.reject { |k| k.is_a?(String) || [1, 2].include?(k) }
attrs["word"] ||= attrs[a[0]] if !a.empty?
attrs["term"] ||= attrs[a[1]] if a.length > 1
attrs
end
def process(parent, _target, attr)
attr = preprocess_attrs(attr)
localities = attr.keys.reject { |k| %w(id word term).include? k }.
reject { |k| k.is_a? Numeric }.
map { |k| "#{k}=#{attr[k]}" }.join(",")
text = [localities, attr["word"]].reject{ |k| k.nil? || k.empty? }.
join(",")
out = Asciidoctor::Inline.new(parent, :quoted, text).convert
%{#{out}}
end
end
class PseudocodeBlockMacro < Asciidoctor::Extensions::BlockProcessor
use_dsl
named :pseudocode
on_context :example, :sourcecode
def init_indent(s)
/^(?[ \t]*)(?.*)$/ =~ s
prefix = prefix.gsub(/\t/, "\u00a0\u00a0\u00a0\u00a0")
.gsub(/ /, "\u00a0")
prefix + suffix
end
def supply_br(lines)
ignore = false
lines.each_with_index do |l, i|
/^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|\`\`\`\`+|____\+)$/.match(l) &&
(ignore = !ignore)
next if l.empty? || l.match(/ \+$/)
next if /^\[.*\]$/.match(l)
next if ignore
next if i == lines.size - 1 || i < lines.size - 1 && lines[i + 1].empty?
lines[i] += " +"
end
lines
end
def process(parent, reader, attrs)
attrs["role"] = "pseudocode"
lines = reader.lines.map { |m| init_indent(m) }
ret = create_block(parent, :example, supply_br(lines),
attrs, content_model: :compound)
ret
end
end
class HTML5RubyMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :ruby
parse_content_as :text
option :pos_attrs, %w(rpbegin rt rpend)
def process(_parent, target, attributes)
rpbegin = "("
rpend = ")"
if (attributes.size == 1) && attributes.key?("text")
rt = attributes["text"]
elsif (attributes.size == 2) && attributes.key?(1) &&
attributes.key?("rpbegin")
# for example, html5ruby:楽聖少女[がくせいしょうじょ]
rt = attributes[1] || ""
else
rpbegin = attributes["rpbegin"]
rt = attributes["rt"]
rpend = attributes["rpend"]
end
"#{target}"\
""
end
end
class ToDoAdmonitionBlock < Extensions::BlockProcessor
use_dsl
named :TODO
on_contexts :example, :paragraph
def process(parent, reader, attrs)
attrs["name"] = "todo"
attrs["caption"] = "TODO"
create_block parent, :admonition, reader.lines, attrs,
content_model: :compound
end
end
class ToDoInlineAdmonitionBlock < Extensions::Treeprocessor
def process(document)
(document.find_by context: :paragraph).each do |para|
next unless /^TODO: /.match para.lines[0]
parent = para.parent
para.set_attr("name", "todo")
para.set_attr("caption", "TODO")
para.lines[0].sub!(/^TODO: /, "")
todo = Block.new parent, :admonition, attributes: para.attributes,
source: para.lines, content_model: :compound
parent.blocks[parent.blocks.index(para)] = todo
end
end
end
class AutonumberInlineMacro < Extensions::InlineMacroProcessor
use_dsl
named :autonumber
parse_content_as :text
def process(parent, target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
%{#{out}}
end
end
class VariantInlineMacro < Extensions::InlineMacroProcessor
use_dsl
named :lang
parse_content_as :text
def process(parent, target, attrs)
/^(?[^-]*)(-(?