Class: Uniword::DocumentWriter

Inherits:
Object
  • Object
show all
Defined in:
lib/uniword/document_writer.rb

Overview

Writer for saving Document instances to files.

Responsibility: Handle document persistence operations. Follows Single Responsibility Principle - writing logic separated from Document class itself.

Examples:

Save document

writer = Uniword::DocumentWriter.new(document)
writer.save("output.docx")

Save with specific format

writer.save("output.mhtml", format: :mhtml)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document) ⇒ DocumentWriter

Initialize a new DocumentWriter.

Examples:

Create writer

writer = DocumentWriter.new(document)

Parameters:

Raises:

  • (ArgumentError)

    if document is invalid



27
28
29
30
# File 'lib/uniword/document_writer.rb', line 27

def initialize(document)
  validate_document(document)
  @document = document
end

Instance Attribute Details

#documentWordprocessingml::DocumentRoot (readonly)

Returns The document to write.

Returns:



18
19
20
# File 'lib/uniword/document_writer.rb', line 18

def document
  @document
end

Instance Method Details

#infer_format(path) ⇒ Symbol

Infer the format from file extension.

Examples:

Infer format

format = writer.infer_format("output.docx")
# => :docx

Parameters:

  • path (String)

    The file path

Returns:

  • (Symbol)

    The inferred format (:docx, :mhtml)

Raises:

  • (ArgumentError)

    if format cannot be inferred



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/uniword/document_writer.rb', line 72

def infer_format(path)
  extension = File.extname(path).downcase

  case extension
  when ".docx"
    :docx
  when ".docm"
    :docm
  when ".dotx"
    :dotx
  when ".dotm"
    :dotm
  when ".mhtml", ".mht"
    :mhtml
  when ".doc"
    # .doc can be MHTML saved with Word (not binary old Word format)
    # We don't support binary .doc output, but MHTML .doc is valid
    :mhtml
  else
    raise ArgumentError,
          "Cannot infer format from extension: #{extension}. " \
          "Supported extensions: .docx, .docm, .dotx, .dotm, .mhtml, .mht"
  end
end

#save(path, format: :auto, profile: nil) ⇒ void

This method returns an undefined value.

Save the document to a file.

Examples:

Save as DOCX

writer.save("output.docx")

Save with explicit format

writer.save("output.mht", format: :mhtml)

Parameters:

  • path (String)

    The output file path

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

    The format (:auto, :docx, :mhtml)

Raises:

  • (ArgumentError)

    if path is invalid

  • (ArgumentError)

    if format is not supported



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/uniword/document_writer.rb', line 45

def save(path, format: :auto, profile: nil)
  validate_path(path)

  format = infer_format(path) if format == :auto

  case format
  when :docx, :docm
    Docx::Package.to_file(document, path, profile: profile)
  when :dotx, :dotm
    Ooxml::DotxPackage.to_file(document, path, profile: profile)
  when :mhtml
    Mhtml::MhtmlPackage.to_file(document, path)
  else
    raise ArgumentError,
          "No handler registered for format: #{format.inspect}"
  end
end

#write_to_stream(stream, format: :docx) ⇒ void

This method returns an undefined value.

Write the document to a stream (StringIO). Compatible with docx gem API

Examples:

Write to StringIO

io = StringIO.new
writer.write_to_stream(io)
io.rewind
content = io.read

Parameters:

  • stream (IO, StringIO)

    The output stream

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

    The format (:docx, :mhtml)



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/uniword/document_writer.rb', line 109

def write_to_stream(stream, format: :docx)
  require "tempfile"

  # Use a temporary file to generate the document
  temp_file = Tempfile.new(["uniword_stream", ".#{format}"], binmode: true)
  begin
    # Save to temp file
    save(temp_file.path, format: format)

    # Read and write to stream in binary mode
    temp_file.rewind
    content = File.binread(temp_file.path)
    stream.write(content)
  ensure
    temp_file.close
    temp_file.unlink
  end
end