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
- .build ⇒ Object
- .convert(text, from:, to:) ⇒ Object
- .convert_file(path, to:, from: nil) ⇒ Object
-
.parse(text, format:) ⇒ Object
Parse text to a document model.
- .parse_file(path, format: nil) ⇒ Object
- .resolve_includes(document, base_dir:, missing_include: :error, max_depth: Coradoc::ResolveIncludes::DEFAULT_MAX_DEPTH, allow_unsafe: false, resolver: nil) ⇒ Object
-
.resolve_references(document, catalog:, presentation:, resolver: nil, missing: :warn, ambiguous: :disambiguate, materialize: false, format: nil) ⇒ CoreModel::Base
Resolve every reference (xref, citation, link, include, image, footnote) in a parsed document using a unified content-graph model.
- .rewrite_links(document, rewriter: nil) ⇒ Object
- .serialize(model, to:, allow_unresolved_includes: false) ⇒ Object
- .to_core(model) ⇒ Object
Class Method Details
.build ⇒ Object
134 135 136 |
# File 'lib/coradoc/pipeline.rb', line 134 def build(&) CoreModel::DocumentElement.build(children: [], &) end |
.convert(text, from:, to:) ⇒ Object
106 107 108 109 |
# File 'lib/coradoc/pipeline.rb', line 106 def convert(text, from:, to:, **) core = parse(text, format: from) serialize(core, to: to, **) end |
.convert_file(path, to:, from: nil) ⇒ Object
160 161 162 163 164 165 166 |
# File 'lib/coradoc/pipeline.rb', line 160 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
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/coradoc/pipeline.rb', line 138 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 |
.resolve_references(document, catalog:, presentation:, resolver: nil, missing: :warn, ambiguous: :disambiguate, materialize: false, format: nil) ⇒ CoreModel::Base
Resolve every reference (xref, citation, link, include, image,
footnote) in a parsed document using a unified content-graph
model. Mirrors resolve_includes in shape: two-step, immutable.
Step one always runs: every Edge is resolved through the
Resolver and the +missing+/+ambiguous+ policies are enforced
(raise or warn). Step two is opt-in: with materialize: true
the tree is rebuilt with each Edge replaced by the output of
the Materializer registered for its
[kind, presentation, format] tuple.
The input document is never mutated. With materialize: false
the input document itself is returned; with materialize: true
a new document is returned that structurally shares untouched
subtrees with the input (treat both as immutable). Nodes whose
kind has no registered materializer are preserved unchanged.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/coradoc/pipeline.rb', line 89 def resolve_references(document, catalog:, presentation:, resolver: nil, missing: :warn, ambiguous: :disambiguate, materialize: false, format: nil) Coradoc::Reference::Resolution.new( catalog: catalog, presentation: presentation, resolver: resolver, missing: missing, ambiguous: ambiguous, materialize: materialize, format: format ).call(document) end |
.rewrite_links(document, rewriter: nil) ⇒ Object
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:, allow_unresolved_includes: false) ⇒ Object
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/coradoc/pipeline.rb', line 123 def serialize(model, to:, allow_unresolved_includes: false, **) format_module = FormatCatalog.get_format(to) raise UnsupportedFormatError.new(to, available: FormatCatalog.registered_formats) unless format_module Coradoc::Validation.guard_unresolved_includes!(model, format_module) unless allow_unresolved_includes 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
111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/coradoc/pipeline.rb', line 111 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 |