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

.build(&block) ⇒ Object



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

def build(&block)
  CoreModel::DocumentElement.build(children: [], &block)
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, &block)
  Coradoc::LinkRewriter.rewrite(document, rewriter: rewriter, &block)
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