svgr 0.1.1 → 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 +4 -4
- data/bin/svgr +4 -4
- data/lib/svgr/arrange/grid.rb +153 -0
- data/lib/svgr/document/resize.rb +72 -0
- metadata +4 -4
- data/lib/svgr/arrange_grid.rb +0 -180
- data/lib/svgr/document_resize.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0005479337446fbe607007a85e09bb6328ab3c1933a21197fa50875229f4cc82'
|
4
|
+
data.tar.gz: 36c5b92d7bc1507d05c5ee4c3ad4fc588f70cdc7ecf4a3d93e17657038542c17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68a6c31b1841c307b0df5742cb254495764b66deb446b774aa83bb9def6f46083e7dfc700751a9e9530736686013b47bd787e987bdff4964388f94e7ae34e13a
|
7
|
+
data.tar.gz: bc660eb66946fd9e33aa8d2e63435a11335852dfcfe4612d2e2c1c2fb6c12c90a28b47792322a4ed9f94439b75cfbeed26ff061c23d5b7b433bf5d80a06ab512
|
data/bin/svgr
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "optparse"
|
4
|
-
require_relative "../lib/svgr/
|
5
|
-
require_relative "../lib/svgr/
|
4
|
+
require_relative "../lib/svgr/arrange/grid"
|
5
|
+
require_relative "../lib/svgr/document/resize"
|
6
6
|
|
7
7
|
module Svgr
|
8
8
|
def self.start(argv)
|
9
9
|
global_opts = {}
|
10
10
|
|
11
11
|
subcommands = {
|
12
|
-
"arrange:grid" => ->(args) { Svgr::
|
13
|
-
"document:resize" => ->(args) { Svgr::
|
12
|
+
"arrange:grid" => ->(args) { Svgr::Arrange::Grid.start(args) },
|
13
|
+
"document:resize" => ->(args) { Svgr::Document::Resize.start(args) },
|
14
14
|
}
|
15
15
|
|
16
16
|
opt_parser = OptionParser.new do |opts|
|
@@ -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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: svgr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
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-
|
11
|
+
date: 2023-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -88,8 +88,8 @@ extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
90
|
- bin/svgr
|
91
|
-
- lib/svgr/
|
92
|
-
- lib/svgr/
|
91
|
+
- lib/svgr/arrange/grid.rb
|
92
|
+
- lib/svgr/document/resize.rb
|
93
93
|
homepage: https://github.com/nassredean/svgr
|
94
94
|
licenses:
|
95
95
|
- MIT
|
data/lib/svgr/arrange_grid.rb
DELETED
@@ -1,180 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "nokogiri"
|
4
|
-
require "optparse"
|
5
|
-
|
6
|
-
module Svgr
|
7
|
-
class ArrangeGrid
|
8
|
-
class << self
|
9
|
-
def start(argv)
|
10
|
-
options = {
|
11
|
-
scaling_factor: 1,
|
12
|
-
margin_top: 0,
|
13
|
-
margin_left: 0,
|
14
|
-
sort: "default",
|
15
|
-
}
|
16
|
-
|
17
|
-
opt_parser =
|
18
|
-
OptionParser.new do |opts|
|
19
|
-
opts.banner =
|
20
|
-
"Usage: svgr arrange:grid [options] <source_directory> <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(
|
44
|
-
"--sort SORT",
|
45
|
-
["default", "random"],
|
46
|
-
"Sorting option for the SVG files (default, random)",
|
47
|
-
) { |sort| options[:sort] = sort }
|
48
|
-
|
49
|
-
opts.on("--out FILE", "Specify an output file path") do |file|
|
50
|
-
options[:out] = file
|
51
|
-
end
|
52
|
-
|
53
|
-
opts.on("-h", "--help", "Prints this help") do
|
54
|
-
puts opts
|
55
|
-
exit
|
56
|
-
end
|
57
|
-
end
|
58
|
-
opt_parser.parse!(argv)
|
59
|
-
|
60
|
-
if argv.length < 3
|
61
|
-
puts opt_parser.help
|
62
|
-
exit(1)
|
63
|
-
end
|
64
|
-
|
65
|
-
source_directory, rows, columns = argv.shift(3)
|
66
|
-
rows = rows.to_i
|
67
|
-
columns = columns.to_i
|
68
|
-
svg_files =
|
69
|
-
list_svg_files(source_directory, options[:sort])[0...rows * columns]
|
70
|
-
|
71
|
-
combined_elements =
|
72
|
-
svg_files.flat_map do |file|
|
73
|
-
content = read_svg_file(file)
|
74
|
-
extract_svg_elements(content)
|
75
|
-
end
|
76
|
-
|
77
|
-
combined_svg = create_combined_svg(
|
78
|
-
combined_elements,
|
79
|
-
rows,
|
80
|
-
columns,
|
81
|
-
options[:scaling_factor],
|
82
|
-
margin: { top: options[:margin_top], left: options[:margin_left] },
|
83
|
-
)
|
84
|
-
|
85
|
-
write_svg(combined_svg, options[:out])
|
86
|
-
end
|
87
|
-
|
88
|
-
def list_svg_files(directory, sort_option)
|
89
|
-
svg_files = Dir.glob(File.join(directory, "*.svg"))
|
90
|
-
|
91
|
-
case sort_option
|
92
|
-
when "default"
|
93
|
-
svg_files.sort_by { |file| File.basename(file, ".svg").to_i }
|
94
|
-
when "random"
|
95
|
-
svg_files.shuffle
|
96
|
-
else
|
97
|
-
puts "Invalid sorting option. Allowed options: default, random"
|
98
|
-
exit(1)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def read_svg_file(file)
|
103
|
-
File.read(file)
|
104
|
-
end
|
105
|
-
|
106
|
-
def extract_svg_elements(svg_content)
|
107
|
-
doc = Nokogiri.XML(svg_content)
|
108
|
-
doc.remove_namespaces!
|
109
|
-
top_level_groups = doc.xpath("//svg/g")
|
110
|
-
|
111
|
-
if top_level_groups.empty?
|
112
|
-
# Wrap all child elements of the SVG document in a group
|
113
|
-
svg_element = doc.at_xpath("//svg")
|
114
|
-
new_group = Nokogiri::XML::Node.new("g", doc)
|
115
|
-
|
116
|
-
svg_element.children.each { |child| new_group.add_child(child) }
|
117
|
-
|
118
|
-
svg_element.add_child(new_group)
|
119
|
-
top_level_groups = [new_group]
|
120
|
-
end
|
121
|
-
|
122
|
-
top_level_groups
|
123
|
-
end
|
124
|
-
|
125
|
-
def create_combined_svg(
|
126
|
-
elements,
|
127
|
-
rows,
|
128
|
-
columns,
|
129
|
-
scaling_factor,
|
130
|
-
margin: {}
|
131
|
-
)
|
132
|
-
margin_top = margin.fetch(:top, 0)
|
133
|
-
margin_left = margin.fetch(:left, 0)
|
134
|
-
|
135
|
-
width =
|
136
|
-
columns * 100 * scaling_factor +
|
137
|
-
(columns - 1) * margin_left * scaling_factor
|
138
|
-
height =
|
139
|
-
rows * 100 * scaling_factor + (rows - 1) * margin_top * scaling_factor
|
140
|
-
|
141
|
-
combined_svg =
|
142
|
-
Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
143
|
-
xml.svg(
|
144
|
-
xmlns: "http://www.w3.org/2000/svg",
|
145
|
-
width: width,
|
146
|
-
height: height,
|
147
|
-
) do
|
148
|
-
elements.each_with_index do |element, index|
|
149
|
-
row = index / columns
|
150
|
-
col = index % columns
|
151
|
-
|
152
|
-
# Adjust the 'transform' attribute to position and scale the element in the grid
|
153
|
-
x =
|
154
|
-
col * (100 * scaling_factor + margin_left * scaling_factor) +
|
155
|
-
(width - 100 * scaling_factor) / 2
|
156
|
-
y = row * (100 * scaling_factor + margin_top * scaling_factor)
|
157
|
-
|
158
|
-
# Offset by half the size of the element vertically and horizontally
|
159
|
-
x += 50 * scaling_factor
|
160
|
-
y += 50 * scaling_factor
|
161
|
-
|
162
|
-
transform = "translate(#{x}, #{y}) scale(#{scaling_factor})"
|
163
|
-
element["transform"] = transform
|
164
|
-
xml << element.to_xml
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
combined_svg.to_xml
|
169
|
-
end
|
170
|
-
|
171
|
-
def write_svg(svg, output_file = nil)
|
172
|
-
if output_file
|
173
|
-
File.write(output_file, svg)
|
174
|
-
else
|
175
|
-
puts svg
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
data/lib/svgr/document_resize.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "nokogiri"
|
4
|
-
require "optparse"
|
5
|
-
|
6
|
-
module Svgr
|
7
|
-
class DocumentResize
|
8
|
-
class << self
|
9
|
-
def start(argv)
|
10
|
-
options = {}
|
11
|
-
parser = OptionParser.new do |opts|
|
12
|
-
opts.banner = "Usage: svgr document:resize <width> <height> [--in INPUT_FILE] [--out OUTPUT_FILE]"
|
13
|
-
|
14
|
-
opts.on("--in INPUT_FILE", "Specify the input file path") do |input_file|
|
15
|
-
options[:input_file] = input_file
|
16
|
-
end
|
17
|
-
|
18
|
-
opts.on("--out OUTPUT_FILE", "Specify the output file path") do |output_file|
|
19
|
-
options[:output_file] = output_file
|
20
|
-
end
|
21
|
-
|
22
|
-
opts.on("-h", "--help", "Prints this help") do
|
23
|
-
puts opts
|
24
|
-
exit
|
25
|
-
end
|
26
|
-
end
|
27
|
-
parser.parse!(argv)
|
28
|
-
|
29
|
-
if argv.size < 2
|
30
|
-
puts parser.help
|
31
|
-
exit(1)
|
32
|
-
end
|
33
|
-
|
34
|
-
width = argv[0].to_f
|
35
|
-
height = argv[1].to_f
|
36
|
-
|
37
|
-
input_file = options[:input_file]
|
38
|
-
output_file = options[:output_file]
|
39
|
-
|
40
|
-
svg_content = if input_file
|
41
|
-
File.read(input_file)
|
42
|
-
else
|
43
|
-
$stdin.read
|
44
|
-
end
|
45
|
-
|
46
|
-
resized_svg = resize(svg_content, width, height, input_file, output_file)
|
47
|
-
|
48
|
-
# Write the output
|
49
|
-
output = resized_svg.to_xml
|
50
|
-
if output_file
|
51
|
-
File.write(output_file, output)
|
52
|
-
else
|
53
|
-
puts output
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def resize(content, width, height, input_file, output_file)
|
58
|
-
doc = Nokogiri.XML(content)
|
59
|
-
doc.remove_namespaces!
|
60
|
-
svg_element = doc.at_xpath("/svg")
|
61
|
-
|
62
|
-
# Get the original SVG width and height
|
63
|
-
svg_width = svg_element["width"].to_i
|
64
|
-
svg_height = svg_element["height"].to_i
|
65
|
-
|
66
|
-
# Calculate width and height in pixels using a DPI of 96
|
67
|
-
width_px = (width * 96 / 25.4).round
|
68
|
-
height_px = (height * 96 / 25.4).round
|
69
|
-
|
70
|
-
# Calculate the difference between the new width and height and the original width and height
|
71
|
-
width_diff = (width_px - svg_width) / 2
|
72
|
-
height_diff = (height_px - svg_height) / 2
|
73
|
-
|
74
|
-
# Update the width and height attributes of the SVG element
|
75
|
-
svg_element["width"] = width_px
|
76
|
-
svg_element["height"] = height_px
|
77
|
-
|
78
|
-
# Create a new group element to wrap all the existing elements and apply the translation
|
79
|
-
new_group = Nokogiri::XML::Node.new("g", doc)
|
80
|
-
new_group["transform"] = "translate(#{width_diff}, #{height_diff})"
|
81
|
-
svg_element.children.each do |child|
|
82
|
-
new_group.add_child(child)
|
83
|
-
end
|
84
|
-
svg_element.add_child(new_group)
|
85
|
-
|
86
|
-
doc
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|