Last active
June 9, 2016 15:04
-
-
Save noniq/50083b746a5eb80a618e43e35a1c2c98 to your computer and use it in GitHub Desktop.
Zip file generator in ruby, suitable for templating OOXML documents (DOCX, XLSX, …)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a simple example which uses rubyzip to recursively generate a zip file from the contents of a specified directory. The | |
# directory itself is not included in the archive, rather just its contents. | |
# | |
# The generator has been extended to support ERB templates: Files with an extension ending in `.erb` will be processed by ERB | |
# before they are added to the archive (the filename in the archive will have `.erb` stripped). | |
# | |
# Suitable for templating OOXML documents (eg. DOCX or AXSLX): Just create the template document in the office application of your | |
# choice, rename the extension to ".zip" and unzip the file. Now add ERB code to individual files as needed (for DOCX you’ll most | |
# likely want to edit `word/document.xml`). Don't forget to also add an additonial `.erb` extension to those files! Then run | |
# ErbZipGenerator on the top level directory and with a suitable output filename – done! | |
# | |
# Usage: | |
# directoryToZip = "/tmp/input/document" | |
# outputFile = "/tmp/document.docx" | |
# zf = ZipFileGenerator.new(directoryToZip, outputFile, binding) | |
# zf.write() | |
# | |
# Based on https://github.com/rubyzip/rubyzip/blob/05916bf89181e1955118fd3ea059f18acac28cc8/samples/example_recursive.rb | |
require 'zip' | |
class ErbZipFileGenerator | |
# Initialize with the directory to zip and the location of the output archive. | |
def initialize(input_dir, output_file, erb_binding) | |
@input_dir = input_dir | |
@output_file = output_file | |
@erb_binding = erb_binding | |
end | |
# Zip the input directory. | |
def write | |
entries = Dir.entries(@input_dir) - %w(. ..) | |
::Zip::File.open(@output_file, ::Zip::File::CREATE) do |io| | |
write_entries entries, '', io | |
end | |
end | |
private | |
# A helper method to make the recursion work. | |
def write_entries(entries, path, io) | |
entries.each do |e| | |
zip_file_path = path == '' ? e : File.join(path, e) | |
disk_file_path = File.join(@input_dir, zip_file_path) | |
if File.directory? disk_file_path | |
recursively_deflate_directory(disk_file_path, io, zip_file_path) | |
else | |
put_into_archive(disk_file_path, io, zip_file_path) | |
end | |
end | |
end | |
def recursively_deflate_directory(disk_file_path, io, zip_file_path) | |
io.mkdir zip_file_path | |
subdir = Dir.entries(disk_file_path) - %w(. ..) | |
write_entries subdir, zip_file_path, io | |
end | |
def put_into_archive(disk_file_path, io, zip_file_path) | |
io.get_output_stream(zip_file_path.sub(/\.erb$/, '')) do |f| | |
contents = if disk_file_path.end_with?('.erb') | |
ERB.new(File.read(disk_file_path)).result(@erb_binding) | |
else | |
File.open(disk_file_path, 'rb').read | |
end | |
f.puts(contents) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment