svgr 0.1.0 → 0.1.3

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.
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"