svgr 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d224bf9a5fc726732a3fc41025e5e427b854e64af0e98b885dfa07463b8f3163
4
- data.tar.gz: 50ab5833da2e78c564b801297d366807e28bd158029bc311753cf54efde76245
3
+ metadata.gz: '0005479337446fbe607007a85e09bb6328ab3c1933a21197fa50875229f4cc82'
4
+ data.tar.gz: 36c5b92d7bc1507d05c5ee4c3ad4fc588f70cdc7ecf4a3d93e17657038542c17
5
5
  SHA512:
6
- metadata.gz: 90ff675a77946193b6065b75346748f7b12fde67753ef4d516e8cfc152c20a198a04ac9cd54b07cf62f9dc86f1e0e8e3a70d033844d15bceed36884da57697bb
7
- data.tar.gz: cda5463648daf778a6e1dc9e2f11bf2b993f3ea96c63fdfbff6c0ea013d0f953fc4a6e1642ee50c491e4cde42a5798c2487d9ff1d3632798552714b0c5156940
6
+ metadata.gz: 68a6c31b1841c307b0df5742cb254495764b66deb446b774aa83bb9def6f46083e7dfc700751a9e9530736686013b47bd787e987bdff4964388f94e7ae34e13a
7
+ data.tar.gz: bc660eb66946fd9e33aa8d2e63435a11335852dfcfe4612d2e2c1c2fb6c12c90a28b47792322a4ed9f94439b75cfbeed26ff061c23d5b7b433bf5d80a06ab512
data/bin/svgr CHANGED
@@ -1,15 +1,50 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require_relative '../lib/svgr'
4
-
5
- # The first command-line argument will be the subcommand (e.g., "combine")
6
- subcommand = ARGV.shift
7
-
8
- case subcommand
9
- when 'combine'
10
- Svgr::CombineSvgs.start(ARGV)
11
- else
12
- puts "Unknown subcommand: #{subcommand}"
13
- puts "Usage: svgr combine <source_directory> <output_file> <rows> <columns> [options]"
14
- exit(1)
15
- end
3
+ require "optparse"
4
+ require_relative "../lib/svgr/arrange/grid"
5
+ require_relative "../lib/svgr/document/resize"
6
+
7
+ module Svgr
8
+ def self.start(argv)
9
+ global_opts = {}
10
+
11
+ subcommands = {
12
+ "arrange:grid" => ->(args) { Svgr::Arrange::Grid.start(args) },
13
+ "document:resize" => ->(args) { Svgr::Document::Resize.start(args) },
14
+ }
15
+
16
+ opt_parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: svgr [options] <subcommand>"
18
+
19
+ opts.separator ""
20
+ opts.separator "Subcommands:"
21
+ subcommands.each do |name, _|
22
+ opts.separator " #{name}"
23
+ end
24
+
25
+ opts.separator ""
26
+ opts.separator "Global options:"
27
+
28
+ opts.on("-h", "--help", "Prints this help") do
29
+ puts opts
30
+ exit
31
+ end
32
+ end
33
+
34
+ opt_parser.order!(argv)
35
+
36
+ if argv.empty?
37
+ puts opt_parser
38
+ exit(1)
39
+ end
40
+
41
+ subcommand = argv.shift
42
+ subcommands.fetch(subcommand).call(argv)
43
+ rescue KeyError
44
+ puts "Error: Unknown subcommand '#{subcommand}'"
45
+ puts opt_parser
46
+ exit(1)
47
+ end
48
+ end
49
+
50
+ Svgr.start(ARGV)
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ require "optparse"
5
+
6
+ module Svgr
7
+ module Arrange
8
+ class Grid
9
+ class << self
10
+ def start(argv)
11
+ options = {
12
+ scaling_factor: 1,
13
+ margin_top: 0,
14
+ margin_left: 0,
15
+ }
16
+
17
+ opt_parser =
18
+ OptionParser.new do |opts|
19
+ opts.banner =
20
+ "Usage: svgr arrange:grid [options] <file_paths> <rows> <columns>"
21
+
22
+ opts.on(
23
+ "-s",
24
+ "--scaling-factor FACTOR",
25
+ Float,
26
+ "Scaling factor for the SVG elements",
27
+ ) { |s| options[:scaling_factor] = s }
28
+
29
+ opts.on(
30
+ "-t",
31
+ "--margin-top MARGIN",
32
+ Integer,
33
+ "Top margin between the SVG elements",
34
+ ) { |t| options[:margin_top] = t }
35
+
36
+ opts.on(
37
+ "-l",
38
+ "--margin-left MARGIN",
39
+ Integer,
40
+ "Left margin between the SVG elements",
41
+ ) { |l| options[:margin_left] = l }
42
+
43
+ opts.on("-h", "--help", "Prints this help") do
44
+ puts opts
45
+ exit
46
+ end
47
+ end
48
+ opt_parser.parse!(argv)
49
+
50
+ if argv.length < 3
51
+ puts opt_parser.help
52
+ exit(1)
53
+ end
54
+
55
+ file_paths, rows, columns = argv.shift(3)
56
+ rows = rows.to_i
57
+ columns = columns.to_i
58
+ svg_files = file_paths.split(",")[0...rows * columns]
59
+
60
+ combined_elements =
61
+ svg_files.flat_map do |file|
62
+ content = read_svg_file(file)
63
+ extract_svg_elements(content)
64
+ end
65
+
66
+ combined_svg = create_combined_svg(
67
+ combined_elements,
68
+ rows,
69
+ columns,
70
+ options[:scaling_factor],
71
+ margin: { top: options[:margin_top], left: options[:margin_left] },
72
+ )
73
+
74
+ write_svg(combined_svg)
75
+ end
76
+
77
+ def read_svg_file(file)
78
+ File.read(file)
79
+ end
80
+
81
+ def extract_svg_elements(svg_content)
82
+ doc = Nokogiri.XML(svg_content)
83
+ doc.remove_namespaces!
84
+ top_level_groups = doc.xpath("//svg/g")
85
+
86
+ if top_level_groups.empty?
87
+ # Wrap all child elements of the SVG document in a group
88
+ svg_element = doc.at_xpath("//svg")
89
+ new_group = Nokogiri::XML::Node.new("g", doc)
90
+
91
+ svg_element.children.each { |child| new_group.add_child(child) }
92
+
93
+ svg_element.add_child(new_group)
94
+ top_level_groups = [new_group]
95
+ end
96
+
97
+ top_level_groups
98
+ end
99
+
100
+ def create_combined_svg(
101
+ elements,
102
+ rows,
103
+ columns,
104
+ scaling_factor,
105
+ margin: {}
106
+ )
107
+ margin_top = margin.fetch(:top, 0)
108
+ margin_left = margin.fetch(:left, 0)
109
+
110
+ width =
111
+ columns * 100 * scaling_factor +
112
+ (columns - 1) * margin_left * scaling_factor
113
+ height =
114
+ rows * 100 * scaling_factor + (rows - 1) * margin_top * scaling_factor
115
+
116
+ combined_svg =
117
+ Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
118
+ xml.svg(
119
+ xmlns: "http://www.w3.org/2000/svg",
120
+ width: width,
121
+ height: height,
122
+ ) do
123
+ elements.each_with_index do |element, index|
124
+ row = index / columns
125
+ col = index % columns
126
+
127
+ # Adjust the 'transform' attribute to position and scale the element in the grid
128
+ x =
129
+ col * (100 * scaling_factor + margin_left * scaling_factor) +
130
+ (width - 100 * scaling_factor) / 2
131
+ y = row * (100 * scaling_factor + margin_top * scaling_factor)
132
+
133
+ # Offset by half the size of the element vertically and horizontally
134
+ x += 50 * scaling_factor
135
+ y += 50 * scaling_factor
136
+
137
+ transform = "translate(#{x}, #{y}) scale(#{scaling_factor})"
138
+ element["transform"] = transform
139
+ xml.parent << element
140
+ end
141
+ end
142
+ end
143
+
144
+ combined_svg.to_xml
145
+ end
146
+
147
+ def write_svg(svg)
148
+ puts svg
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ require "optparse"
5
+
6
+ module Svgr
7
+ module Document
8
+ class Resize
9
+ class << self
10
+ def start(argv)
11
+ parser = OptionParser.new do |opts|
12
+ opts.banner = "Usage: svgr document:resize <width> <height>"
13
+
14
+ opts.on("-h", "--help", "Prints this help") do
15
+ puts opts
16
+ exit
17
+ end
18
+ end
19
+ parser.parse!(argv)
20
+
21
+ if argv.size < 2
22
+ puts parser.help
23
+ exit(1)
24
+ end
25
+
26
+ width = argv[0].to_f
27
+ height = argv[1].to_f
28
+
29
+ svg_content = $stdin.read
30
+
31
+ resized_svg = resize(svg_content, width, height)
32
+
33
+ # Write the output
34
+ output = resized_svg.to_xml
35
+ puts output
36
+ end
37
+
38
+ def resize(content, width, height)
39
+ doc = Nokogiri.XML(content)
40
+ doc.remove_namespaces!
41
+ svg_element = doc.at_xpath("/svg")
42
+
43
+ # Get the original SVG width and height
44
+ svg_width = svg_element["width"].to_i
45
+ svg_height = svg_element["height"].to_i
46
+
47
+ # Calculate width and height in pixels using a DPI of 96
48
+ width_px = (width * 96 / 25.4).round
49
+ height_px = (height * 96 / 25.4).round
50
+
51
+ # Calculate the difference between the new width and height and the original width and height
52
+ width_diff = (width_px - svg_width) / 2
53
+ height_diff = (height_px - svg_height) / 2
54
+
55
+ # Update the width and height attributes of the SVG element
56
+ svg_element["width"] = width_px
57
+ svg_element["height"] = height_px
58
+
59
+ # Create a new group element to wrap all the existing elements and apply the translation
60
+ new_group = Nokogiri::XML::Node.new("g", doc)
61
+ new_group["transform"] = "translate(#{width_diff}, #{height_diff})"
62
+ svg_element.children.each do |child|
63
+ new_group.add_child(child)
64
+ end
65
+ svg_element.add_child(new_group)
66
+
67
+ doc
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
metadata CHANGED
@@ -1,29 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svgr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nassredean Nasseri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-05 00:00:00.000000000 Z
11
+ date: 2023-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-shopify
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2'
13
69
  - !ruby/object:Gem::Dependency
14
70
  name: nokogiri
15
71
  requirement: !ruby/object:Gem::Requirement
16
72
  requirements:
17
73
  - - "~>"
18
74
  - !ruby/object:Gem::Version
19
- version: '1.12'
75
+ version: '1'
20
76
  type: :runtime
21
77
  prerelease: false
22
78
  version_requirements: !ruby/object:Gem::Requirement
23
79
  requirements:
24
80
  - - "~>"
25
81
  - !ruby/object:Gem::Version
26
- version: '1.12'
82
+ version: '1'
27
83
  description: A Ruby gem that provides a command-line interface for various SVG utilities
28
84
  email:
29
85
  executables:
@@ -32,10 +88,8 @@ extensions: []
32
88
  extra_rdoc_files: []
33
89
  files:
34
90
  - bin/svgr
35
- - lib/svgr.rb
36
- - lib/svgr/combine_svgs.rb
37
- - lib/svgr/count_files_by_type.rb
38
- - lib/svgr/delete_files_by_type.rb
91
+ - lib/svgr/arrange/grid.rb
92
+ - lib/svgr/document/resize.rb
39
93
  homepage: https://github.com/nassredean/svgr
40
94
  licenses:
41
95
  - MIT
@@ -1,132 +0,0 @@
1
- require "nokogiri"
2
- require "optparse"
3
-
4
- module Svgr
5
- class CombineSvgs
6
- def self.start(argv)
7
- options = {
8
- scaling_factor: 1,
9
- margin_top: 0,
10
- margin_left: 0,
11
- sort: "default"
12
- }
13
-
14
- OptionParser
15
- .new do |opts|
16
- opts.banner =
17
- "Usage: svgr combine [options] <source_directory> <output_file> <rows> <columns>"
18
-
19
- opts.on(
20
- "-s",
21
- "--scaling-factor FACTOR",
22
- Float,
23
- "Scaling factor for the SVG elements"
24
- ) { |s| options[:scaling_factor] = s }
25
-
26
- opts.on(
27
- "-t",
28
- "--margin-top MARGIN",
29
- Integer,
30
- "Top margin between the SVG elements"
31
- ) { |t| options[:margin_top] = t }
32
-
33
- opts.on(
34
- "-l",
35
- "--margin-left MARGIN",
36
- Integer,
37
- "Left margin between the SVG elements"
38
- ) { |l| options[:margin_left] = l }
39
-
40
- opts.on(
41
- "--sort SORT",
42
- %w[default random],
43
- "Sorting option for the SVG files (default, random)"
44
- ) { |sort| options[:sort] = sort }
45
- end
46
- .parse!(argv)
47
-
48
- if argv.length < 4
49
- puts "Usage: svgr combine [options] <source_directory> <output_file> <rows> <columns>"
50
- exit(1)
51
- end
52
-
53
- source_directory, output_file, rows, columns = argv.shift(4)
54
- rows = rows.to_i
55
- columns = columns.to_i
56
- svg_files =
57
- list_svg_files(source_directory, options[:sort])[0...rows * columns]
58
-
59
- combined_elements =
60
- svg_files.flat_map do |file|
61
- content = read_svg_file(file)
62
- extract_svg_elements(content)
63
- end
64
-
65
- combined_svg =
66
- create_combined_svg(
67
- combined_elements,
68
- rows,
69
- columns,
70
- options[:scaling_factor],
71
- options[:margin_top],
72
- options[:margin_left]
73
- )
74
-
75
- save_svg_to_file(combined_svg, output_file)
76
- end
77
-
78
- def self.list_svg_files(directory, sort_option)
79
- svg_files = Dir.glob(File.join(directory, "*.svg"))
80
-
81
- case sort_option
82
- when "default"
83
- svg_files.sort_by { |file| File.basename(file, ".svg").to_i }
84
- when "random"
85
- svg_files.shuffle
86
- else
87
- puts "Invalid sorting option. Allowed options: default, random"
88
- exit(1)
89
- end
90
- end
91
-
92
- def self.read_svg_file(file)
93
- File.read(file)
94
- end
95
-
96
- def self.extract_svg_elements(svg_content)
97
- doc = Nokogiri.XML(svg_content)
98
- doc.remove_namespaces!
99
- doc.xpath("//svg/g")
100
- end
101
-
102
- def self.create_combined_svg(
103
- elements,
104
- rows,
105
- columns,
106
- scaling_factor,
107
- margin_top,
108
- margin_left
109
- )
110
- combined_svg =
111
- Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
112
- xml.svg(xmlns: "http://www.w3.org/2000/svg") do
113
- elements.each_with_index do |element, index|
114
- row = index / columns
115
- col = index % columns
116
-
117
- # Adjust the 'transform' attribute to position and scale the element in the grid
118
- transform =
119
- "translate(#{col * (100 + margin_left) * scaling_factor}, #{row * (100 + margin_top) * scaling_factor}) scale(#{scaling_factor})"
120
- element["transform"] = transform
121
- xml << element.to_xml
122
- end
123
- end
124
- end
125
- combined_svg.to_xml
126
- end
127
-
128
- def self.save_svg_to_file(svg, file)
129
- File.write(file, svg)
130
- end
131
- end
132
- end
@@ -1,14 +0,0 @@
1
- def count_files_by_type(directory, file_extension)
2
- Dir.glob(File.join(directory, "*.#{file_extension}")).count
3
- end
4
-
5
- if ARGV.length != 2
6
- puts "Usage: ruby count_files_by_type.rb <source_directory> <file_extension>"
7
- exit(1)
8
- end
9
-
10
- source_directory = ARGV[0]
11
- file_extension = ARGV[1]
12
- file_count = count_files_by_type(source_directory, file_extension)
13
-
14
- puts "Number of #{file_extension.upcase} files in #{source_directory}: #{file_count}"
@@ -1,32 +0,0 @@
1
- require "fileutils"
2
-
3
- def get_files_by_type(directory, file_extension)
4
- Dir
5
- .glob(File.join(directory, "*.#{file_extension}"))
6
- .sort_by { |f| File.basename(f).to_i }
7
- end
8
-
9
- def delete_file(file)
10
- File.delete(file)
11
- end
12
-
13
- if ARGV.length != 2
14
- puts "Usage: ruby delete_files_by_type.rb <source_directory> <file_extension>"
15
- exit(1)
16
- end
17
-
18
- source_directory = ARGV[0]
19
- file_extension = ARGV[1]
20
-
21
- files = get_files_by_type(source_directory, file_extension)
22
-
23
- files.each do |file|
24
- puts "File: #{file}"
25
- print "Do you want to delete this file? [y/N]: "
26
- answer = STDIN.gets.chomp.downcase
27
-
28
- if answer == "y"
29
- delete_file(file)
30
- puts "Deleted #{file}"
31
- end
32
- end
data/lib/svgr.rb DELETED
@@ -1 +0,0 @@
1
- require_relative "svgr/combine_svgs"