Class: Kotoshu::Documents::AsciidocDocument

Inherits:
Document
  • Object
show all
Defined in:
lib/kotoshu/documents/asciidoc_document.rb

Overview

AsciiDoc document implementation.

Handles AsciiDoc files with AST parsing for structured navigation.

Examples:

Creating an asciidoc document

doc = AsciidocDocument.new("= Title\n\nParagraph text")
doc.text_nodes.each { |node| puts node.text }

Constant Summary

Constants inherited from Document

Document::FORMATS

Instance Attribute Summary

Attributes inherited from Document

#content, #format, #language_code

Instance Method Summary collapse

Methods inherited from Document

detect_format, detect_language_from_path, from_file, from_string, #line_count, #word_count

Constructor Details

#initialize(content, format: :asciidoc, language_code: 'en') ⇒ AsciidocDocument

Create a new asciidoc document.

Parameters:

  • content (String)

    The document content

  • format (Symbol) (defaults to: :asciidoc)

    Document format (must be :asciidoc)

  • language_code (String) (defaults to: 'en')

    Language code

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 23

def initialize(content, format: :asciidoc, language_code: 'en')
  raise ArgumentError, "Format must be :asciidoc" unless format == :asciidoc

  super(content, format: format, language_code: language_code)
  @parsed = false
  @ast = nil
end

Instance Method Details

#apply(corrections) ⇒ AsciidocDocument

Apply corrections and return new document.

Parameters:

Returns:



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 140

def apply(corrections)
  return self if corrections.empty?

  # Apply corrections one by one
  result = self
  corrections.each do |error|
    suggestion = error.recommended_suggestion
    result = result.replace_node(error.location, suggestion.word)
  end

  result
end

#context_for(location, window: 2) ⇒ Models::Context

Get context around a location.

For asciidoc, navigates the AST to find surrounding context.

Parameters:

  • location (Location)

    The error location

  • window (Integer) (defaults to: 2)

    Number of sibling elements before/after

Returns:



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 77

def context_for(location, window: 2)
  return plain_text_context(location, window: 5) if location.line_column?

  parse unless @parsed

  # For node-based locations, find parent and siblings
  parent_path = location.node_path[0..-2]
  current_type = location.node_path.last

  parent = navigate_ast(@ast, parent_path)
  return Models::Context.new(before: "", current: "", after: "", location: location, window: window) unless parent

  # Find siblings around current element
  siblings = extract_siblings(parent)
  current_idx = siblings.find_index { |s| node_type(s) == current_type }

  return Models::Context.new(before: "", current: "", after: "", location: location, window: window) unless current_idx

  before_sibs = siblings[[0, current_idx - window].max..current_idx - 1]
  after_sibs = siblings[(current_idx + 1)..(current_idx + window)]

  before = before_sibs.map { |s| text_from_node(s) }.join("\n")
  current = text_from_node(parent)
  after = after_sibs.map { |s| text_from_node(s) }.join("\n")

  Models::Context.new(
    before: before,
    current: current,
    after: after,
    location: location,
    window: window
  )
end

#get_node(path) ⇒ Object?

Get node at a specific path in the AST.

Parameters:

  • path (Array)

    Node path (e.g., [:section, 0, :paragraph, 2])

Returns:

  • (Object, nil)

    The node or nil



64
65
66
67
68
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 64

def get_node(path)
  parse unless @parsed

  navigate_ast(@ast, path)
end

#nameString

Document name for display.

Returns:

  • (String)

    Document name



156
157
158
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 156

def name
  "asciidoc"
end

#parseArray<Asciidoctor::AbstractBlock>

Parse the asciidoc document into an AST.

Returns:

  • (Array<Asciidoctor::AbstractBlock>)

    The parsed AST



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 34

def parse
  return @ast if @parsed

  begin
    require 'asciidoctor'
  rescue LoadError
    raise "Asciidoctor gem not available. Add 'asciidoctor' to Gemfile"
  end

  # Parse with Asciidoctor
  doc = Asciidoctor.load(content, parse: false, header_footer: false)
  @ast = doc.blocks
  @parsed = true

  @ast
end

#replace_node(location, new_text) ⇒ AsciidocDocument

Replace text at a specific location.

Navigates the AST to find the text node and replaces it, then regenerates asciidoc.

Parameters:

  • location (Location)

    The location to replace

  • new_text (String)

    The new text

Returns:



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 119

def replace_node(location, new_text)
  parse unless @parsed

  # Navigate to the node and replace its text
  modified_ast = replace_in_ast(@ast, location.node_path, new_text)

  # Regenerate asciidoc from modified AST
  begin
    require 'asciidoctor'
    new_content = convert_ast_to_asciidoc(modified_ast)
  rescue LoadError
    raise "Asciidoctor gem not available. Add 'asciidoctor' to Gemfile"
  end

  AsciidocDocument.new(new_content, @format, @language_code)
end

#text_nodesArray<TextNode>

Get all text nodes for spell checking.

Extracts text from the AST, skipping code blocks and source listings.

Returns:

  • (Array<TextNode>)

    Text nodes in the document



56
57
58
# File 'lib/kotoshu/documents/asciidoc_document.rb', line 56

def text_nodes
  extract_text_nodes
end