Class: Kotoshu::Documents::MarkdownDocument
- Defined in:
- lib/kotoshu/documents/markdown_document.rb
Overview
Markdown document implementation.
Handles Markdown files with AST parsing for structured navigation.
Constant Summary
Constants inherited from Document
Instance Attribute Summary
Attributes inherited from Document
#content, #format, #language_code
Instance Method Summary collapse
-
#apply(corrections) ⇒ MarkdownDocument
Apply corrections and return new document.
-
#context_for(location, window: 2) ⇒ Models::Context
Get context around a location.
-
#get_node(path) ⇒ Object?
Get node at a specific path in the AST.
-
#initialize(content, format: :markdown, language_code: 'en') ⇒ MarkdownDocument
constructor
Create a new markdown document.
-
#name ⇒ String
Document name for display.
-
#parse ⇒ Hash
Parse the markdown document into an AST.
-
#replace_node(location, new_text) ⇒ Object
Replace text at a specific location.
-
#text_nodes ⇒ Array<TextNode>
Get all text nodes for spell checking.
Methods inherited from Document
detect_format, detect_language_from_path, from_file, from_string, #line_count, #word_count
Constructor Details
#initialize(content, format: :markdown, language_code: 'en') ⇒ MarkdownDocument
Create a new markdown document.
23 24 25 26 27 28 29 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 23 def initialize(content, format: :markdown, language_code: 'en') raise ArgumentError, "Format must be :markdown" unless format == :markdown super(content, format: format, language_code: language_code) @parsed = false @ast = nil end |
Instance Method Details
#apply(corrections) ⇒ MarkdownDocument
Apply corrections and return new document.
139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 139 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 markdown, navigates the AST to find surrounding context.
76 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 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 76 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| s[:type] == 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.
63 64 65 66 67 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 63 def get_node(path) parse unless @parsed navigate_ast(@ast, path) end |
#name ⇒ String
Document name for display.
155 156 157 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 155 def name "markdown" end |
#parse ⇒ Hash
Parse the markdown document into an AST.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 34 def parse return @ast if @parsed begin require 'kramdown' rescue LoadError raise "Kramdown gem not available. Add 'kramdown' to Gemfile" end kd = Kramdown::Document.new(content) @ast = kd.to_hash @parsed = true @ast end |
#replace_node(location, new_text) ⇒ Object
Replace text at a specific location.
Navigates the AST to find the text node and replaces it, then regenerates markdown.
return [MarkdownDocument] New document with replacement
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 118 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 markdown from modified AST begin require 'kramdown' new_content = Kramdown::Converter.new(modified_ast).to_kramdown rescue LoadError raise "Kramdown gem not available. Add 'kramdown' to Gemfile" end MarkdownDocument.new(new_content, @format, @language_code) end |
#text_nodes ⇒ Array<TextNode>
Get all text nodes for spell checking.
Extracts text from the AST, skipping code blocks.
55 56 57 |
# File 'lib/kotoshu/documents/markdown_document.rb', line 55 def text_nodes extract_text_nodes end |