Class: Ace::Support::Markdown::Organisms::DocumentEditor

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/support/markdown/organisms/document_editor.rb

Overview

Main API for document editing with fluent interface Provides safe editing with state management and validation

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_path) ⇒ DocumentEditor

Create a new DocumentEditor

Parameters:

  • file_path (String)

    Path to the markdown file

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
22
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 14

def initialize(file_path)
  raise ArgumentError, "File path cannot be nil" if file_path.nil?
  raise FileOperationError, "File not found: #{file_path}" unless File.exist?(file_path)

  @file_path = file_path
  @original_content = File.read(file_path)
  @document = Models::MarkdownDocument.parse(@original_content, file_path: file_path)
  @backup_path = nil
end

Instance Attribute Details

#documentObject (readonly)

Returns the value of attribute document.



10
11
12
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 10

def document
  @document
end

#file_pathObject (readonly)

Returns the value of attribute file_path.



10
11
12
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 10

def file_path
  @file_path
end

#original_contentObject (readonly)

Returns the value of attribute original_content.



10
11
12
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 10

def original_content
  @original_content
end

Class Method Details

.from_content(content, file_path: nil) ⇒ DocumentEditor

Create a DocumentEditor from content string

Parameters:

  • content (String)

    The markdown content

  • file_path (String, nil) (defaults to: nil)

    Optional file path for context

Returns:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 172

def self.from_content(content, file_path: nil)
  # Create a temporary file if needed
  if file_path.nil?
    require "tempfile"
    temp = Tempfile.new(["markdown", ".md"])
    temp.write(content)
    temp.close
    file_path = temp.path
  else
    File.write(file_path, content)
  end

  new(file_path)
end

Instance Method Details

#add_section(heading, content, level: 2) ⇒ DocumentEditor

Add a new section

Parameters:

  • heading (String)

    The section heading

  • content (String)

    The section content

  • level (Integer) (defaults to: 2)

    The heading level (default: 2)

Returns:



72
73
74
75
76
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 72

def add_section(heading, content, level: 2)
  section = Models::Section.new(heading: heading, content: content, level: level)
  @document = Molecules::SectionEditor.add_section(@document, section)
  self
end

#append_to_section(heading, content) ⇒ DocumentEditor

Append to a section

Parameters:

  • heading (String)

    The section heading

  • content (String)

    Content to append

Returns:



54
55
56
57
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 54

def append_to_section(heading, content)
  @document = Molecules::SectionEditor.append_to_section(@document, heading, content)
  self
end

#delete_section(heading) ⇒ DocumentEditor

Delete a section

Parameters:

  • heading (String)

    The section heading

Returns:



62
63
64
65
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 62

def delete_section(heading)
  @document = Molecules::SectionEditor.delete_section(@document, heading)
  self
end

#modified?Boolean

Check if document has been modified

Returns:

  • (Boolean)


158
159
160
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 158

def modified?
  @document.to_markdown != @original_content
end

#replace_section(heading, new_content) ⇒ DocumentEditor

Replace a section’s content

Parameters:

  • heading (String)

    The section heading

  • new_content (String)

    The new content

Returns:



45
46
47
48
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 45

def replace_section(heading, new_content)
  @document = Molecules::SectionEditor.replace_section(@document, heading, new_content)
  self
end

#rollbackHash

Rollback to original content

Returns:

  • (Hash)

    Result with :success, :errors



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 131

def rollback
  if @backup_path && File.exist?(@backup_path)
    begin
      File.write(@file_path, File.read(@backup_path))
      File.delete(@backup_path)
      @backup_path = nil

      # Reload document
      @document = Models::MarkdownDocument.parse(@original_content, file_path: @file_path)

      {success: true, errors: []}
    rescue => e
      {success: false, errors: ["Rollback failed: #{e.message}"]}
    end
  else
    {success: false, errors: ["No backup available for rollback"]}
  end
end

#save!(backup: true, validate_before: true, rules: {}) ⇒ Hash

Save the document to file

Parameters:

  • backup (Boolean) (defaults to: true)

    Create backup before writing (default: true)

  • validate_before (Boolean) (defaults to: true)

    Validate before writing (default: true)

  • rules (Hash) (defaults to: {})

    Optional validation rules

Returns:

  • (Hash)

    Result with :success, :backup_path, :errors



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 98

def save!(backup: true, validate_before: true, rules: {})
  # Validate before save
  if validate_before
    validation = validate(rules: rules)
    unless validation[:valid]
      return {
        success: false,
        backup_path: nil,
        errors: validation[:errors]
      }
    end
  end

  # Generate new content
  new_content = @document.to_markdown

  # Use SafeFileWriter for atomic write with backup
  result = SafeFileWriter.write(
    @file_path,
    new_content,
    backup: backup
  )

  if result[:success]
    @backup_path = result[:backup_path]
    @original_content = new_content
  end

  result
end

#set_field(key, value) ⇒ DocumentEditor

Update a single frontmatter field

Parameters:

  • key (String)

    The field key

  • value (Object)

    The field value

Returns:



36
37
38
39
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 36

def set_field(key, value)
  @document = Molecules::FrontmatterEditor.update_field(@document, key, value)
  self
end

#statsHash

Get document statistics

Returns:

  • (Hash)


164
165
166
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 164

def stats
  @document.stats
end

#to_markdownString

Get current document content as string

Returns:

  • (String)


152
153
154
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 152

def to_markdown
  @document.to_markdown
end

#update_frontmatter(updates) ⇒ DocumentEditor

Update frontmatter fields

Parameters:

  • updates (Hash)

    Fields to update

Returns:



27
28
29
30
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 27

def update_frontmatter(updates)
  @document = Molecules::FrontmatterEditor.update(@document, updates)
  self
end

#valid?(rules: {}) ⇒ Boolean

Check if document is valid

Parameters:

  • rules (Hash) (defaults to: {})

    Optional validation rules

Returns:

  • (Boolean)


89
90
91
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 89

def valid?(rules: {})
  validate(rules: rules)[:valid]
end

#validate(rules: {}) ⇒ Hash

Validate the current document state

Parameters:

  • rules (Hash) (defaults to: {})

    Optional validation rules

Returns:

  • (Hash)

    Result with :valid, :errors, :warnings



81
82
83
84
# File 'lib/ace/support/markdown/organisms/document_editor.rb', line 81

def validate(rules: {})
  content = @document.to_markdown
  Atoms::DocumentValidator.validate(content, rules: rules)
end