Module: Coradoc::Pipeline

Defined in:
lib/coradoc/pipeline.rb

Overview

Parse / serialize / convert pipeline. Single source of truth for the document transformation flow, extracted from the top-level Coradoc façade so pipeline logic has its own home and its own spec surface. Public API on Coradoc delegates here.

Class Method Summary collapse

Class Method Details

.buildObject



75
76
77
# File 'lib/coradoc/pipeline.rb', line 75

def build(&)
  CoreModel::DocumentElement.build(children: [], &)
end

.convert(text, from:, to:) ⇒ Object



49
50
51
52
# File 'lib/coradoc/pipeline.rb', line 49

def convert(text, from:, to:, **)
  core = parse(text, format: from)
  serialize(core, to: to, **)
end

.convert_file(path, to:, from: nil) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/coradoc/pipeline.rb', line 101

def convert_file(path, to:, from: nil, **)
  source_format = from || FormatCatalog.detect_format(path)
  raise UnsupportedFormatError, "Could not detect format for: #{path}" unless source_format

  core = parse_file(path, format: source_format)
  serialize(core, to: to, **)
end

.parse(text, format:) ⇒ Object

Parse text to a document model. Graph mode: include:: directives survive as CoreModel::Include link nodes — no file I/O happens during parse. Splicing included content is a separate, explicit step (see Coradoc.resolve_includes).



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/coradoc/pipeline.rb', line 14

def parse(text, format:)
  format_module = FormatCatalog.get_format(format)
  unless format_module
    raise UnsupportedFormatError.new(format,
                                     available: FormatCatalog.registered_formats)
  end

  text = Hooks.invoke(:before_parse, text, format: format)
  result = format_module.parse_to_core(text)
  Hooks.invoke(:after_parse, result, format: format)
end

.parse_file(path, format: nil) ⇒ Object

Raises:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/coradoc/pipeline.rb', line 79

def parse_file(path, format: nil)
  raise FileNotFoundError, path unless File.exist?(path)

  source_format = format || FormatCatalog.detect_format(path)
  raise UnsupportedFormatError, "Could not detect format for: #{path}" unless source_format

  format_module = FormatCatalog.get_format(source_format)
  unless format_module
    raise UnsupportedFormatError.new(source_format,
                                     available: FormatCatalog.registered_formats)
  end

  if FormatCatalog.binary_format?(source_format)
    format_module.parse_to_core(path)
  else
    content = File.read(path)
    content = Hooks.invoke(:before_parse, content, format: source_format)
    result = format_module.parse_file_to_core(path, content)
    Hooks.invoke(:after_parse, result, format: source_format)
  end
end

.resolve_includes(document, base_dir:, missing_include: :error, max_depth: Coradoc::ResolveIncludes::DEFAULT_MAX_DEPTH, allow_unsafe: false, resolver: nil) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/coradoc/pipeline.rb', line 26

def resolve_includes(document, base_dir:,
                     missing_include: :error,
                     max_depth: Coradoc::ResolveIncludes::DEFAULT_MAX_DEPTH,
                     allow_unsafe: false,
                     resolver: nil)
  resolver = Coradoc::IncludeResolver.coerce(
    resolver,
    base_dir: base_dir,
    allow_unsafe: allow_unsafe
  )
  Coradoc::ResolveIncludes.call(
    document,
    resolver: resolver,
    base_dir: base_dir,
    missing_include: missing_include,
    max_depth: max_depth
  )
end


45
46
47
# File 'lib/coradoc/pipeline.rb', line 45

def rewrite_links(document, rewriter: nil, &)
  Coradoc::LinkRewriter.rewrite(document, rewriter: rewriter, &)
end

.serialize(model, to:) ⇒ Object



66
67
68
69
70
71
72
73
# File 'lib/coradoc/pipeline.rb', line 66

def serialize(model, to:, **)
  format_module = FormatCatalog.get_format(to)
  raise UnsupportedFormatError.new(to, available: FormatCatalog.registered_formats) unless format_module

  model = Hooks.invoke(:before_serialize, model, format: to)
  result = format_module.serialize(model, **)
  Hooks.invoke(:after_serialize, result, format: to)
end

.to_core(model) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/coradoc/pipeline.rb', line 54

def to_core(model)
  return model if model.is_a?(CoreModel::Base)

  FormatCatalog.registry.each_value do |format_module|
    next unless format_module.handles_model?(model)

    return format_module.to_core(model)
  end

  raise TransformationError, "No transformer found for #{model.class}"
end