lib/metanorma/generic.rb
require "metanorma/generic/processor"
require "metanorma/generic/version"
require "forwardable"
require "yaml"
module Metanorma
module Generic # rubocop:disable Style/MutableConstant
ORGANIZATION_NAME_SHORT = "Acme"
ORGANIZATION_NAME_LONG = "Acme Corp."
DOCUMENT_NAMESPACE = "https://www.metanorma.org/ns/generic"
YAML_CONFIG_FILE = "metanorma.yml"
class DummyProcessor < ::Metanorma::Processor
def initialize; end # rubocop:disable Lint/MissingSuper
end
class Configuration
CONFIG_ATTRS = %i[
organization_name_short
organization_name_long
bibliography_titles
boilerplate
committees
document_namespace
docid_template
doctypes
default_doctype
fonts_manifest
i18nyaml
logo_path
logo_paths
header
htmlcoverpage
htmlintropage
htmlstylesheet
html_bodyfont
html_headerfont
html_monospacefont
html_normalfontsize
html_monospacefontsize
html_smallerfontsize
html_footnotefontsize
metadata_extensions
metanorma_name
normref_titles
published_stages
relations
default_stage
stage_abbreviations
scripts
scripts_pdf
standardstylesheet
symbols_titles
termsdefs_titles
validate_rng_file
webfont
wordcoverpage
wordintropage
wordstylesheet
word_bodyfont
word_headerfont
word_monospacefont
word_normalfontsize
word_monospacefontsize
word_smallerfontsize
word_footnotefontsize
xml_root_tag
pdf_stylesheet
formats
].freeze
def filepath_attrs
%i[i18nyaml boilerplate logo_path logo_paths header boilerplate
htmlcoverpage htmlintropage htmlstylesheet scripts scripts_pdf
standardstylesheet validate_rng_file wordcoverpage wordintropage
wordstylesheet pdf_stylesheet]
end
attr_accessor(*CONFIG_ATTRS)
class << self
attr_accessor :_file
end
def self.inherited(klass) # rubocop:disable Lint/MissingSuper
klass._file = caller_locations(1..1).first.absolute_path
end
def initialize(*args)
super
# Try to set config values from yaml file in current directory
@yaml = File.join(File.dirname(self.class::_file || __FILE__), "..",
"..", YAML_CONFIG_FILE)
set_default_values_from_yaml_file(@yaml)
end
# may be invoked multiple times, needs to not overwrite
def postprocess_defaults
default_org
default_formats
default_titles
end
def default_org
self.organization_name_short ||= ORGANIZATION_NAME_SHORT
self.organization_name_long ||= ORGANIZATION_NAME_LONG
self.document_namespace ||= DOCUMENT_NAMESPACE
end
# convert array to hash; if already is hash (no override in customize),
# don't reconvert
def default_formats
formats.is_a?(Hash) and return
self.formats ||= %w(html doc)
self.formats = self.formats.each_with_object({}) do |k, m|
m[k.to_sym] = k
end
self.formats.merge! DummyProcessor.new.output_formats
end
def default_titles
self.termsdefs_titles ||=
["Terms and definitions", "Terms, definitions, symbols and abbreviated terms",
"Terms, definitions, symbols and abbreviations", "Terms, definitions and symbols",
"Terms, definitions and abbreviations", "Terms, definitions and abbreviated terms"]
self.symbols_titles ||=
["Symbols and abbreviated terms", "Symbols", "Abbreviated terms",
"Abbreviations"]
self.normref_titles ||=
["Normative references"]
self.bibliography_titles ||= ["Bibliography"]
end
def set_default_values_from_yaml_file(config_file)
if File.file?(config_file)
root_path, default_config_options =
set_default_values_from_yaml_file_prep(config_file)
CONFIG_ATTRS.each do |attr|
set_default_value_from_yaml_file(attr, root_path,
default_config_options)
end
end
postprocess_defaults
end
def set_default_value_from_yaml_file(attr, root_path, default_options)
value = default_options[attr.to_s]
value && filepath_attrs.include?(attr) and
value = absolute_path(value, root_path)
instance_variable_set("@#{attr}", value)
end
def set_default_values_from_yaml_file_prep(config_file)
root_path = File.dirname(config_file)
default_config_options =
YAML.safe_load(File.read(config_file, encoding: "UTF-8"))
default_config_options["doctypes"].is_a? Array and
default_config_options["doctypes"] =
default_config_options["doctypes"].each_with_object({}) do |k, m|
m[k] = nil
end
[root_path, default_config_options]
end
def blank?(val)
val.nil? || (val.respond_to?(:empty?) && val.empty?)
end
def absolute_path(value, root_path)
case value
when Hash then absolute_path1(value, root_path)
when Array then absolute_path1_array(value, root_path)
when String
if !value.empty? && !Pathname.new(value).absolute?
Pathname.new(File.join(root_path, value)).cleanpath.to_s
else value
end
else value
end
end
def absolute_path1(hash, pref)
hash.reject { |_k, v| blank?(v) }.transform_values do |v|
absolute_path(v, pref)
end
end
def absolute_path1_array(value, pref)
value.reject { |a| blank?(a) }.each_with_object([]) do |v1, g|
g << absolute_path(v1, pref)
end
end
end
class << self
extend Forwardable
attr_accessor :configuration
Configuration::CONFIG_ATTRS.each do |attr_name|
def_delegator :@configuration, attr_name
end
def configure
self.configuration ||= Configuration.new
yield(configuration)
end
end
configure {}
end
end