Class: Metanorma::Processor

Inherits:
Object
  • Object
show all
Defined in:
lib/metanorma/processor/processor.rb

Overview

Abstract base class for Metanorma flavor processors. Each flavor gem (metanorma-iso, metanorma-itu, etc.) defines a subclass and registers it with Registry; the registry then dispatches input documents to the appropriate processor based on the document's declared flavor / class.

Subclasses MUST set @short, @input_format, and (if Asciidoctor is the input parser) @asciidoctor_backend in their initialize, and MAY override #output_formats, #use_presentation_xml, #options_preprocess, and #output to customise their output pipeline.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProcessor

Returns a new instance of Processor.

Raises:

  • (RuntimeError)

    always — concrete flavors must override.



30
31
32
# File 'lib/metanorma/processor/processor.rb', line 30

def initialize
  raise "This is an abstract class!"
end

Instance Attribute Details

#asciidoctor_backendSymbol? (readonly)

Returns Asciidoctor backend symbol used when the processor's input is Asciidoc (e.g. :iso, :standoc); nil for non-Asciidoc inputs.

Returns:

  • (Symbol, nil)

    Asciidoctor backend symbol used when the processor's input is Asciidoc (e.g. :iso, :standoc); nil for non-Asciidoc inputs.



27
28
29
# File 'lib/metanorma/processor/processor.rb', line 27

def asciidoctor_backend
  @asciidoctor_backend
end

#input_formatSymbol (readonly)

Returns input parser identifier (typically :asciidoc).

Returns:

  • (Symbol)

    input parser identifier (typically :asciidoc).



22
23
24
# File 'lib/metanorma/processor/processor.rb', line 22

def input_format
  @input_format
end

#shortSymbol (readonly)

Returns short name registered with the Registry (e.g. :iso, :itu).

Returns:

  • (Symbol)

    short name registered with the Registry (e.g. :iso, :itu).



19
20
21
# File 'lib/metanorma/processor/processor.rb', line 19

def short
  @short
end

Instance Method Details

#document_transformersHash{Symbol => Hash}

Per-format "document model" publishing specs. Override in a flavor to register injected reader + transformer classes for a document-model output leg (Presentation/Semantic XML -> reader -> transformer -> XML), so the flavor declares two classes rather than re-implementing the read/transform/serialise chain in #output. The classes need not live in the Metanorma:: tree.

Each value is a Hash with keys:

:reader                  - responds to +.from_xml(String)+ -> model
                         (required)
:transformer             - responds to +.new(model, options)+; the
                         instance responds to +#transform+ -> target,
                         and the target responds to +#to_xml+
                         (required)
:to_xml_options          - Hash splatted into +target.to_xml(**opts)+
                         (default +{}+)
:strip_default_namespace - strip +xmlns="..."+ before +from_xml+
                         (default +false+)
:post_process            - callable +(xml, transformer, options)+
                         -> xml (default identity)

Returns:

  • (Hash{Symbol => Hash})

    format symbol -> spec. Empty by default, so flavors that do not use this leg are unaffected.



69
70
71
# File 'lib/metanorma/processor/processor.rb', line 69

def document_transformers
  {}
end

#extract_metanorma_options(file) ⇒ Hash

Read metanorma-specific options from the input file's header via Input::Asciidoc#extract_metanorma_options.

Parameters:

  • file (String)

    raw input contents.

Returns:

  • (Hash)

    metanorma-specific options (+:type+, :extensions, :relaton, :asciimath, :novalid).



204
205
206
# File 'lib/metanorma/processor/processor.rb', line 204

def extract_metanorma_options(file)
  Metanorma::Input::Asciidoc.new.extract_metanorma_options(file)
end

#extract_options(file) ⇒ Hash

Read processor-relevant options from the input file's header via Input::Asciidoc#extract_options, merging in this processor's output_formats for downstream stages.

Parameters:

  • file (String)

    raw input contents.

Returns:

  • (Hash)

    extracted options.



193
194
195
196
# File 'lib/metanorma/processor/processor.rb', line 193

def extract_options(file)
  Metanorma::Input::Asciidoc.new.extract_options(file)
    .merge(output_formats: output_formats)
end

#input_to_isodoc(file, filename, options = {}) ⇒ String

Convert an input file to Metanorma semantic XML by routing it through the Input::Asciidoc processor with this processor's Asciidoctor backend. Override for non-Asciidoc inputs.

Parameters:

  • file (String)

    the raw input contents.

  • filename (String)

    the source filename (used for relative path resolution in includes).

  • options (Hash) (defaults to: {})

    passthrough options for the input processor; see Input::Asciidoc#process.

Returns:

  • (String)

    Metanorma semantic XML.



84
85
86
87
# File 'lib/metanorma/processor/processor.rb', line 84

def input_to_isodoc(file, filename, options = {})
  Metanorma::Input::Asciidoc.new.process(file, filename,
                                         @asciidoctor_backend, options)
end

#options_preprocess(options) ⇒ Hash

Mutate options in place to ensure :output_formats is set. Override to add other flavor-specific defaults.

Parameters:

  • options (Hash)

    processor options.

Returns:

  • (Hash)

    options with :output_formats defaulted.



113
114
115
# File 'lib/metanorma/processor/processor.rb', line 113

def options_preprocess(options)
  options[:output_formats] ||= output_formats
end

#output(isodoc_node, inname, outname, format, options = {}) ⇒ Object

Default output-writer. If format is registered in #document_transformers, render it through the document-model leg (#render_via_document_model); otherwise dump the rendered output string to a UTF-8 file. Flavors override this for binary formats (Word, PDF) that need different post-processing, calling super for the document-model and passthrough cases.

Parameters:

  • isodoc_node (String, nil)

    rendered output content, or the semantic XML string on the document-model semantic leg.

  • inname (String)

    source filename.

  • outname (String)

    destination path.

  • format (Symbol)

    output format.

  • options (Hash) (defaults to: {})

    processor options.

Returns:

  • (Object)

    bytes written (passthrough) or the serialised XML string (document-model leg).



132
133
134
135
136
137
138
139
140
# File 'lib/metanorma/processor/processor.rb', line 132

def output(isodoc_node, inname, outname, format, options = {})
  options_preprocess(options)
  if document_transformers.key?(format)
    render_via_document_model(isodoc_node, inname, outname, format,
                              options)
  else
    File.open(outname, "w:UTF-8") { |f| f.write(isodoc_node) }
  end
end

#output_formatsHash{Symbol => String}

Mapping of output-format name to file extension. Subclasses typically extend this with HTML / Word / PDF entries.

Returns:

  • (Hash{Symbol => String})

    format symbol -> file extension.



38
39
40
41
42
43
44
# File 'lib/metanorma/processor/processor.rb', line 38

def output_formats
  {
    xml: "xml",
    presentation: "presentation.xml",
    rxl: "rxl",
  }
end

#render_via_document_model(isodoc_node, inname, outname, format, options) ⇒ String

Render a document-model output leg: read the input XML into a model via the registered reader, transform it, serialise, optionally post-process, and write. The input XML comes from isodoc_node (semantic leg) or, when that is nil, from reading inname (presentation leg) — so both #use_presentation_xml settings are supported transparently. The driver is duck-typed: it never names a concrete reader/transformer/target-model gem, keeping those out of metanorma-core's dependencies.

Parameters:

  • isodoc_node (String, nil)

    semantic XML string, or nil on the presentation leg.

  • inname (String)

    input filename (read on the presentation leg).

  • outname (String, nil)

    destination path; written when non-nil.

  • format (Symbol)

    output-format symbol; must be a key of #document_transformers.

  • options (Hash)

    processor options, passed to the transformer and post-processor.

Returns:

  • (String)

    the serialised (and post-processed) output XML.



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/metanorma/processor/processor.rb', line 159

def render_via_document_model(isodoc_node, inname, outname, format, options)
  spec = document_transformers.fetch(format)
  xml = document_model_input_xml(isodoc_node, inname)
  xml = xml.gsub(/\sxmlns="[^"]*"/, "") if spec[:strip_default_namespace]
  transformer = spec.fetch(:transformer)
    .new(spec.fetch(:reader).from_xml(xml), options)
  out = transformer.transform.to_xml(**(spec[:to_xml_options] || {}))
  if (post = spec[:post_process])
    out = post.call(out, transformer, options)
  end
  File.open(outname, "w:UTF-8") { |f| f.write(out) } if outname
  out
end

#use_presentation_xml(ext) ⇒ Boolean

Whether the given output extension is downstream of the presentation XML stage (and therefore needs presentation XML generated first). Defaults to true for HTML/Word/PDF. Other formats such as RFC and STS are generated directly from semantic XML

Parameters:

  • ext (Symbol)

    output-format symbol.

Returns:

  • (Boolean)


100
101
102
103
104
105
106
# File 'lib/metanorma/processor/processor.rb', line 100

def use_presentation_xml(ext)
  case ext
  when :html, :doc, :pdf then true
  else
    false
  end
end