Module: MarkdownComposer

Defined in:
lib/markdown_composer.rb,
lib/markdown_composer/plan.rb,
lib/markdown_composer/take.rb,
lib/markdown_composer/where.rb,
lib/markdown_composer/result.rb,
lib/markdown_composer/source.rb,
lib/markdown_composer/version.rb,
lib/markdown_composer/executor.rb,
lib/markdown_composer/data_path.rb,
lib/markdown_composer/validator.rb,
lib/markdown_composer/registries.rb,
lib/markdown_composer/diagnostics.rb,
lib/markdown_composer/capabilities.rb,
lib/markdown_composer/plan_builder.rb,
lib/markdown_composer/value_object.rb,
lib/markdown_composer/document_index.rb,
lib/markdown_composer/transform_runner.rb,
lib/markdown_composer/markdown_renderer.rb,
lib/markdown_composer/transform_options.rb,
lib/markdown_composer/composition_buffer.rb,
lib/markdown_composer/selection_resolver.rb,
lib/markdown_composer/registries/registry.rb,
lib/markdown_composer/source_list_builder.rb,
lib/markdown_composer/transforms/registry.rb,
lib/markdown_composer/registries/take_entries.rb,
lib/markdown_composer/registries/take_registry.rb,
lib/markdown_composer/registries/action_entries.rb,
lib/markdown_composer/registries/source_entries.rb,
lib/markdown_composer/registries/support_values.rb,
lib/markdown_composer/registries/target_entries.rb,
lib/markdown_composer/registries/where_registry.rb,
lib/markdown_composer/document_index/html_parser.rb,
lib/markdown_composer/transforms/default_entries.rb,
lib/markdown_composer/registries/condition_entries.rb,
lib/markdown_composer/registries/unit_token_entries.rb,
lib/markdown_composer/document_index/markdown_parser.rb,
lib/markdown_composer/transform_runner/scope_resolver.rb,
lib/markdown_composer/transform_runner/content_placement.rb,
lib/markdown_composer/transform_runner/heading_numbering.rb,
lib/markdown_composer/transform_runner/field_interpolator.rb

Defined Under Namespace

Modules: ActionRegistryEntries, Capabilities, DataPath, DefaultTransformEntries, MarkdownRenderer, RegistrySupportValues, SourceRegistryEntries, Take, TakeRegistryEntries, TargetRegistryEntries, TransformOptions, Transforms, UnitTokenRegistryEntries, Where, WhereRegistryEntries Classes: CompositionBuffer, Diagnostics, DocumentIndex, Executor, Plan, PlanBuilder, Registries, Registry, Result, SelectionResolver, Source, SourceListBuilder, TransformRunner, Validator, WhereRegistry

Constant Summary collapse

VERSION =
"0.7.0"
Diagnostic =
MarkdownComposer.value_object(:severity, :code, :message, :path, :details) do
  def to_h
    {
      severity: severity,
      code: code,
      message: message,
      path: path,
      details: details
    }.compact
  end
end
ComposerNode =
MarkdownComposer.value_object(:id, :source_key, :type, :source_position, :level, :text, :attributes, :children, :raw, :start_line, :end_line) do
  def heading?
    type.start_with?("heading_")
  end

  def to_h
    {
      id: id,
      source_key: source_key,
      type: type,
      source_position: source_position,
      level: level,
      text: text,
      attributes: attributes,
      children: children.map(&:to_h),
      raw: raw,
      start_line: start_line,
      end_line: end_line
    }
  end
end
ComposerSection =
MarkdownComposer.value_object(:id, :source_key, :heading_node, :level, :title_text, :body_nodes, :child_sections, :all_nodes, :source_position, :parent_section_id, :start_line, :end_line) do
  def text
    [ title_text, *all_nodes.map(&:text) ].compact.join("\n")
  end

  def raw
    [ heading_node, *all_nodes.reject { |node| node.attributes["derived"] } ].compact.uniq(&:id).sort_by(&:source_position).map(&:raw).join
  end

  def to_h
    {
      id: id,
      source_key: source_key,
      heading_node: heading_node&.to_h,
      level: level,
      title_text: title_text,
      body_nodes: body_nodes.map(&:to_h),
      child_sections: child_sections.map(&:id),
      all_nodes: all_nodes.map(&:id),
      source_position: source_position,
      parent_section_id: parent_section_id,
      start_line: start_line,
      end_line: end_line
    }
  end
end
RegistryEntry =
MarkdownComposer.value_object(:token, :aliases, :label, :tooltip, :meaning, :row_sentence, :support, :source_formats, :condition_fields) do
  def supports?(consumer, options = {})
    value = support.fetch(consumer.to_sym, :disabled).to_sym
    return true if %i[normal advanced output_only include_only].include?(value)
    return options.fetch(:optional_tokens, false) if value == :optional
    return options.fetch(:adapter_policy_tokens, false) if value == :adapter_policy

    false
  end

  def to_h
    {
      token: token,
      aliases: aliases,
      label: label,
      tooltip: tooltip,
      meaning: meaning,
      row_sentence: row_sentence,
      support: support,
      source_formats: source_formats,
      condition_fields: condition_fields
    }
  end
end
TakeRegistryEntry =
MarkdownComposer.value_object(:token, :aliases, :label, :tooltip, :meaning, :support, :value_type, :deterministic) do
  def to_h
    {
      token: token,
      aliases: aliases,
      label: label,
      tooltip: tooltip,
      meaning: meaning,
      support: support,
      value_type: value_type,
      deterministic: deterministic
    }
  end
end
ConditionFieldRegistryEntry =
MarkdownComposer.value_object(:token, :aliases, :label, :tooltip, :meaning, :predicates, :applies_to, :source_formats, :field_take) do
  def to_h
    {
      token: token,
      aliases: aliases,
      label: label,
      tooltip: tooltip,
      meaning: meaning,
      predicates: predicates,
      applies_to: applies_to,
      source_formats: source_formats,
      field_take: field_take
    }
  end
end
PredicateRegistryEntry =
MarkdownComposer.value_object(:token, :aliases, :label, :tooltip, :meaning, :value_type, :support) do
  def to_h
    {
      token: token,
      aliases: aliases,
      label: label,
      tooltip: tooltip,
      meaning: meaning,
      value_type: value_type,
      support: support
    }
  end
end
WhereGroupRegistryEntry =
MarkdownComposer.value_object(:token, :aliases, :label, :tooltip, :meaning, :arity) do
  def to_h
    {
      token: token,
      aliases: aliases,
      label: label,
      tooltip: tooltip,
      meaning: meaning,
      arity: arity
    }
  end
end

Class Method Summary collapse

Class Method Details

.capabilities(options: {}) ⇒ Object



63
64
65
# File 'lib/markdown_composer.rb', line 63

def capabilities(options: {})
  Capabilities.build(options)
end

.compose(sources:, config: nil, plan: nil, options: {}) ⇒ Object

Raises:

  • (ArgumentError)


31
32
33
34
35
36
37
# File 'lib/markdown_composer.rb', line 31

def compose(sources:, config: nil, plan: nil, options: {})
  plan ||= config
  raise ArgumentError, "provide config: or plan:" unless plan

  plan = plan.is_a?(Plan) ? plan : Plan.new(plan)
  Executor.new(sources: sources, plan: plan, options: options).call
end

.normalise(config_or_rows) ⇒ Object Also known as: normalize



39
40
41
42
43
44
45
46
47
48
# File 'lib/markdown_composer.rb', line 39

def normalise(config_or_rows)
  plan = if config_or_rows.is_a?(Plan)
    config_or_rows
  elsif config_or_rows.is_a?(Array)
    Plan.from_rows(config_or_rows)
  else
    Plan.new(config_or_rows)
  end
  plan.to_h
end

.parse_json(json_string) ⇒ Object



85
86
87
88
89
# File 'lib/markdown_composer.rb', line 85

def parse_json(json_string)
  Plan.new(JSON.parse(json_string))
rescue JSON::ParserError => e
  Plan.invalid("json.syntax", e.message)
end

.parse_rows(row_hashes) ⇒ Object



101
102
103
# File 'lib/markdown_composer.rb', line 101

def parse_rows(row_hashes)
  Plan.from_rows(row_hashes)
end

.parse_yaml(yaml_string) ⇒ Object



79
80
81
82
83
# File 'lib/markdown_composer.rb', line 79

def parse_yaml(yaml_string)
  Plan.new(YAML.safe_load(yaml_string, permitted_classes: [ Symbol ], aliases: false) || {})
rescue Psych::SyntaxError => e
  Plan.invalid("yaml.syntax", e.message)
end

.plan(&block) ⇒ Object



67
68
69
70
71
# File 'lib/markdown_composer.rb', line 67

def plan(&block)
  builder = PlanBuilder.new
  builder.instance_eval(&block) if block
  builder.to_plan
end

.registriesObject



110
111
112
# File 'lib/markdown_composer.rb', line 110

def registries
  Registries.default
end

.source_list(&block) ⇒ Object



73
74
75
76
77
# File 'lib/markdown_composer.rb', line 73

def source_list(&block)
  builder = SourceListBuilder.new
  builder.instance_eval(&block) if block
  builder.to_a
end

.to_json(plan, pretty: true) ⇒ Object



96
97
98
99
# File 'lib/markdown_composer.rb', line 96

def to_json(plan, pretty: true)
  plan = Plan.new(plan) unless plan.is_a?(Plan)
  pretty ? JSON.pretty_generate(plan.to_h) : JSON.generate(plan.to_h)
end

.to_rows(plan) ⇒ Object



105
106
107
108
# File 'lib/markdown_composer.rb', line 105

def to_rows(plan)
  plan = Plan.new(plan) unless plan.is_a?(Plan)
  plan.steps
end

.to_yaml(plan) ⇒ Object



91
92
93
94
# File 'lib/markdown_composer.rb', line 91

def to_yaml(plan)
  plan = Plan.new(plan) unless plan.is_a?(Plan)
  YAML.dump(plan.to_h)
end

.validate(config:, sources: [], options: {}) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/markdown_composer.rb', line 51

def validate(config:, sources: [], options: {})
  plan = config.is_a?(Plan) ? config : Plan.new(config)
  normalized_sources = Array(sources).map { |source| Source.build(source) }
  diagnostics = Validator.new(plan, sources: normalized_sources, options: options).call
  {
    valid: !diagnostics.any_errors?,
    plan: plan.to_h,
    diagnostics: diagnostics.as_json,
    errors: diagnostics.errors.map(&:to_h)
  }
end

.value_object(*members, &block) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
# File 'lib/markdown_composer/value_object.rb', line 4

def self.value_object(*members, &block)
  Struct.new(*members, keyword_init: true) do
    def with(attributes)
      values = {}
      each_pair { |name, value| values[name] = value }
      self.class.new(**values.merge(attributes))
    end

    class_eval(&block) if block
  end
end