inkscape_merge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.0"
12
+ gem "rcov", ">= 0"
13
+ end
@@ -0,0 +1,20 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.0)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.9.2)
10
+ rcov (0.9.9)
11
+ shoulda (2.11.3)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (~> 1.0.0)
18
+ jeweler (~> 1.6.0)
19
+ rcov
20
+ shoulda
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Laas Toom
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,66 @@
1
+ = inkscape_merge
2
+
3
+ Script to merge SVG files with CSV data-files using Inkscape, to produce
4
+ one outputfile (e.g. PDF) per data-row.
5
+
6
+ Script inspired by and based on Aurélio A. Heckert excellent
7
+ InkscapeGenerator (http://wiki.colivre.net/Aurium/InkscapeGenerator)
8
+
9
+ Heckert's original script unfortunately broke for me several times and
10
+ I took the opportunity to rewrite it and make it more extendable for future.
11
+
12
+ = Requirements
13
+
14
+ * Inkscape (preferably in PATH)
15
+
16
+ = USAGE
17
+
18
+ == Install the gem
19
+
20
+ gem install inkscape_merge
21
+
22
+ == Create files
23
+
24
+ Create CSV data file with first row as a header. The values from this row are
25
+ used as keys in the SVG file substitution.
26
+
27
+ Create SVG file that contains some variables in the form:
28
+
29
+ %VAR_name%
30
+
31
+ Where `name` is the name of a column in the CSV file created previously.
32
+ These variables can be anywhere inside the SVG, from plain text nodes to color values.
33
+ This script just brute-forcedly `gsubs` these values as text w/o any thought.
34
+
35
+ == Run the script
36
+
37
+ The script requires at least three arguments:
38
+ * the input SVG file
39
+ * the input CSV file
40
+ * and the output file `pattern`
41
+
42
+ Note: output pattern undergoes the same substitutions as the SVG file, so to create easily unique file names.
43
+ Additionally the output pattern can contain `%d` which is replaced with current row number.
44
+
45
+ Example:
46
+ inkscape_merge -f postcard.svg -d names.csv -o postcards/card_%d.pdf
47
+
48
+ This produces files like:
49
+ * postcards/
50
+ * card_1.pdf
51
+ * card_2.pdf
52
+
53
+ == Contributing to inkscape_merge
54
+
55
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
56
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
57
+ * Fork the project
58
+ * Start a feature/bugfix branch
59
+ * Commit and push until you are happy with your contribution
60
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
61
+
62
+ == Copyright
63
+
64
+ Copyright (c) 2011 Laas Toom. See LICENSE.txt for
65
+ further details.
66
+
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "inkscape_merge"
18
+ gem.homepage = "http://github.com/borgand/inkscape_merge"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Merge SVG files with CSV file using Inkscape}
21
+ gem.description = %Q{Script to merge SVG files with CSV data-files using Inkscape, to produce
22
+ one outputfile (e.g. PDF) per data-row.}
23
+ gem.email = "laas.toom@gmail.com"
24
+ gem.authors = ["Laas Toom"]
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/test_*.rb'
40
+ test.verbose = true
41
+ test.rcov_opts << '--exclude "gems/*"'
42
+ end
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "inkscape_merge #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'inkscape_merge'
4
+ require 'optparse'
5
+
6
+
7
+ processor = Inkscape::Merge::Processor.new
8
+ options = processor.options
9
+
10
+ # Parse command line arguments
11
+ OptionParser.new do |opts|
12
+ opts.banner = "Usage: inkscape_csv_merge.rb [options]"
13
+ opts.separator ""
14
+ opts.separator "REQUIRED options"
15
+ opts.on("-d", "--data-file [DATA_FILE]", "Data-file to take values from.") {|d| options.data_file = d}
16
+ opts.on("-f", "--svg-file [SVG_FILE]", "SVG file to be used as template. Default: none") {|f| options.svg_file = f}
17
+ opts.on('-o', '--output_pattern PAT', 'Pattern to produce output file names. Undergoes the same substitutions as the SVG file and additionally %d can be used for current row number. Default: none') {|p|
18
+ options.output = p
19
+ }
20
+
21
+ opts.separator ""
22
+ opts.separator "Optional"
23
+ opts.on('-i', '--inkscape INKSCAPE_BIN', "Where Inkscape binary can be found") {|i| options.inkscape = i}
24
+ opts.on('--format FMT', "Output format. Must be supported export format of Inkscape. Default: #{options.format}"){|f| options.format = f}
25
+ opts.on("--dpi DPI", Integer, "Specify output DPI. Default: #{options.dpi}") {|d| options.dpi = d}
26
+ opts.on("-v", "--[no-]verbose", "Run verbosely") {|v| options.verbose = v}
27
+ opts.on("-l", "--limit [LIMIT]", Integer, "Only process LIMIT rows. 0 means no limit. Default: #{options.limit}") {|l|
28
+ options.limit = l
29
+ }
30
+
31
+ opts.separator ""
32
+ opts.separator "CSV parser options"
33
+ opts.on("--csv_col_sep SEP", "CSV column separator. Default: #{options.csv_options[:col_sep]}") {|v| opts.csv_options[:col_sep] = v}
34
+ opts.on("--csv_encoding ENC", "CSV file encoding. Default: #{options.csv_options[:encoding]}") {|e| opts.csv_options[:encoding] = e}
35
+
36
+ opts.separator ""
37
+
38
+ opts.on_tail("-h", "--help", "Show this help") { puts opts; exit }
39
+ end.parse!
40
+
41
+ # Run the processor
42
+ begin
43
+ processor.run
44
+ rescue => e
45
+ $stderr.puts "ERROR: #{e}"
46
+ exit 1
47
+ end
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{inkscape_merge}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Laas Toom"]
12
+ s.date = %q{2011-08-10}
13
+ s.default_executable = %q{inkscape_merge}
14
+ s.description = %q{Script to merge SVG files with CSV data-files using Inkscape, to produce
15
+ one outputfile (e.g. PDF) per data-row.}
16
+ s.email = %q{laas.toom@gmail.com}
17
+ s.executables = ["inkscape_merge"]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE.txt",
20
+ "README.rdoc"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE.txt",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "bin/inkscape_merge",
31
+ "inkscape_merge.gemspec",
32
+ "lib/inkscape_merge.rb",
33
+ "lib/inkscape_merge/data_parsers.rb",
34
+ "lib/inkscape_merge/processor.rb",
35
+ "test/helper.rb",
36
+ "test/test_inkscape_merge.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/borgand/inkscape_merge}
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.7}
42
+ s.summary = %q{Merge SVG files with CSV file using Inkscape}
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
52
+ s.add_development_dependency(%q<rcov>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<shoulda>, [">= 0"])
55
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
57
+ s.add_dependency(%q<rcov>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<shoulda>, [">= 0"])
61
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
62
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
63
+ s.add_dependency(%q<rcov>, [">= 0"])
64
+ end
65
+ end
66
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'inkscape_merge/processor'
3
+
4
+
@@ -0,0 +1,41 @@
1
+ require 'csv'
2
+
3
+
4
+ # Module to detect and wrap data-files
5
+ module Inkscape # :nodoc:
6
+ module Merge # :nodoc:
7
+ module DataParser
8
+
9
+ # Detect, which parser to use for given input file
10
+ def self.detect(options)
11
+ case options.data_file
12
+ when /.csv$/i
13
+ return ::Inkscape::Merge::DataParser::CSV.new(options.data_file, options.csv_options)
14
+ end
15
+ end
16
+
17
+ # CSV file parser
18
+ # Though Ruby's CSV would suffice, we explicitly wrap it in an API
19
+ # Other parsers must comply to this API
20
+ class CSV
21
+ include Enumerable
22
+
23
+ # Read file into memory
24
+ def initialize(data_file, csv_options)
25
+ opts = csv_options
26
+ @data = ::CSV.read data_file, opts
27
+ end
28
+
29
+ # Return headers as an array
30
+ def headers
31
+ @data.headers
32
+ end
33
+
34
+ # Wraps CSV#each for enumerable support
35
+ def each(&block)
36
+ @data.each &block
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,113 @@
1
+ require 'ostruct'
2
+ require 'tempfile'
3
+ require 'fileutils'
4
+ require 'inkscape_merge/data_parsers'
5
+
6
+ module Inkscape # :nodoc:
7
+ module Merge # :nodoc:
8
+ # Main class to initialize processing
9
+ class Processor
10
+ attr_reader :options
11
+
12
+ # Initialize the processor, setting files and options
13
+ def initialize
14
+ @options = OpenStruct.new
15
+ # Default options
16
+ @options.format = "pdf"
17
+ @options.csv_options = {:headers => true, :col_sep => ',', :encoding => 'utf-8'}
18
+ @options.limit = 0
19
+ @options.dpi = 300
20
+ @options.inkscape = %x(which inkscape)
21
+ # If no Inkscape in PATH, try to guess from platform
22
+ if options.inkscape.empty?
23
+ options.inkscape = case RUBY_PLATFORM
24
+ when /darwin/
25
+ "/Applications/Inkscape.app/Contents/Resources/bin/inkscape"
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ # Iterate over all data rows and generate output files
32
+ # Optionally stop when LIMIT is reached
33
+ def run
34
+ validate_options
35
+
36
+ # Open the files
37
+ @svg = File.read options.svg_file
38
+ @data_file = DataParser.detect(options)
39
+
40
+ count = 0
41
+ headers = @data_file.headers
42
+ pattern = /%VAR_(#{headers.map(&:to_s).join("|")})%/
43
+ @data_file.each{|row|
44
+ break if @options.limit > 0 && count >= @options.limit
45
+ count += 1
46
+ puts "Row: #{count}"
47
+ tmp_file = Tempfile.new('inkscape_merge')
48
+ begin
49
+ (outfile,merged_svg) = [@options.output,@svg].map{|s|
50
+ s.gsub(pattern){|m|
51
+ puts $1 if @options.verbose
52
+ # return corresponding value from current row
53
+ row[$1]
54
+ }
55
+ }
56
+
57
+ # Write merged SVG out
58
+ tmp_file.puts merged_svg
59
+ tmp_file.close
60
+
61
+ # Sprintf outfile with current row number
62
+ outfile %= count
63
+
64
+ # Generate output path
65
+ FileUtils.mkdir_p(File.dirname outfile)
66
+
67
+ # Generate the file itself
68
+ ink_generate tmp_file.path, outfile, @options.format, @options.dpi
69
+ rescue => e
70
+ $stderr.puts "ERROR: #{e}"
71
+ $stderr.puts e.backtrace if @options.verbose
72
+ ensure
73
+ tmp_file.unlink
74
+ end
75
+ }
76
+ end
77
+
78
+ private
79
+
80
+ # Validate options and give error if something is missing
81
+ def validate_options
82
+ # TODO: replace with
83
+
84
+ # If inkscape can not be found or run, bail out
85
+ unless File.executable? @options.inkscape
86
+ raise ArgumentError, "Inkscape not found or not executable"
87
+ end
88
+
89
+ unless @options.svg_file
90
+ raise ArgumentError, "SVG file must be given"
91
+ end
92
+
93
+ unless @options.data_file
94
+ raise ArgumentError, "Data-file must be given"
95
+ end
96
+
97
+ unless @options.output
98
+ raise ArgumentError, "Output pattern must be given"
99
+ end
100
+ end
101
+
102
+ # Run Inkscape to generate files
103
+ def ink_generate(in_file, out_file, format='pdf', dpi="300")
104
+ cmd = %(#{@options.inkscape} --without-gui --export-#{format}=#{out_file} --export-dpi=#{dpi} #{in_file})
105
+ puts "INKSCAPE CMD: #{cmd}" if @options.verbose
106
+ ink_error = `#{cmd} 2>&1`
107
+ unless $?.success?
108
+ $stderr.puts "Inkscape ERROR (#{$?}): #{ink_error}"
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'inkscape_merge'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestInkscapeMerge < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inkscape_merge
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Laas Toom
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-08-10 00:00:00 +03:00
18
+ default_executable: inkscape_merge
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 0
43
+ - 0
44
+ version: 1.0.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 6
58
+ - 0
59
+ version: 1.6.0
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rcov
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ prerelease: false
75
+ version_requirements: *id004
76
+ description: |-
77
+ Script to merge SVG files with CSV data-files using Inkscape, to produce
78
+ one outputfile (e.g. PDF) per data-row.
79
+ email: laas.toom@gmail.com
80
+ executables:
81
+ - inkscape_merge
82
+ extensions: []
83
+
84
+ extra_rdoc_files:
85
+ - LICENSE.txt
86
+ - README.rdoc
87
+ files:
88
+ - .document
89
+ - Gemfile
90
+ - Gemfile.lock
91
+ - LICENSE.txt
92
+ - README.rdoc
93
+ - Rakefile
94
+ - VERSION
95
+ - bin/inkscape_merge
96
+ - inkscape_merge.gemspec
97
+ - lib/inkscape_merge.rb
98
+ - lib/inkscape_merge/data_parsers.rb
99
+ - lib/inkscape_merge/processor.rb
100
+ - test/helper.rb
101
+ - test/test_inkscape_merge.rb
102
+ has_rdoc: true
103
+ homepage: http://github.com/borgand/inkscape_merge
104
+ licenses:
105
+ - MIT
106
+ post_install_message:
107
+ rdoc_options: []
108
+
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 4265623212388845729
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 0
127
+ version: "0"
128
+ requirements: []
129
+
130
+ rubyforge_project:
131
+ rubygems_version: 1.3.7
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: Merge SVG files with CSV file using Inkscape
135
+ test_files: []
136
+