victor-cli 0.2.0 → 0.3.2
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/README.md +32 -25
- data/bin/victor +1 -0
- data/lib/victor/cli/command_line.rb +4 -5
- data/lib/victor/cli/commands/{generate_ruby.rb → convert.rb} +17 -8
- data/lib/victor/cli/commands/init.rb +71 -0
- data/lib/victor/cli/commands/render.rb +73 -0
- data/lib/victor/cli/css_data.rb +27 -0
- data/lib/victor/cli/refinements/rendering.rb +46 -0
- data/lib/victor/cli/{ruby_code.rb → ruby_source.rb} +9 -4
- data/lib/victor/cli/svg_node.rb +141 -0
- data/lib/victor/cli/templates/init/cli.rb +15 -0
- data/lib/victor/cli/templates/init/dsl.rb +19 -0
- data/lib/victor/cli/templates/init/standalone.rb +19 -0
- data/lib/victor/cli/templates/nodes/css.erb +7 -0
- data/lib/victor/cli/templates/nodes/element.erb +18 -0
- data/lib/victor/cli/templates/nodes/root_cli.erb +12 -0
- data/lib/victor/cli/templates/nodes/root_dsl.erb +17 -0
- data/lib/victor/cli/templates/nodes/root_standalone.erb +14 -0
- data/lib/victor/cli/templates/nodes/text.erb +2 -0
- data/lib/victor/cli/version.rb +1 -1
- data/lib/victor/cli.rb +9 -4
- metadata +77 -27
- data/lib/victor/cli/code_generator.rb +0 -81
- data/lib/victor/cli/commands/generate_svg.rb +0 -39
- data/lib/victor/cli/parser.rb +0 -64
- data/lib/victor/cli/templates/cli.rb +0 -8
- data/lib/victor/cli/templates/dsl.rb +0 -12
- data/lib/victor/cli/templates/standalone.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82fc02c3ba2a1713203ac34aa76bd025ae9fb4cf04139c74b7e9dadb055d8005
|
4
|
+
data.tar.gz: 9204eb4ce2e142b989266e7079942f70d13f0051bdeee1618715ef8608eec8c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c01a4894fa0830e67d55ef0d90d4a67163765896993d52637d31a26f16eb15215c0ac40797be6bd65958f8a52a1019a343c95551f38a7d2abbf01a222b35963
|
7
|
+
data.tar.gz: 4430b1433977028919dcc33c67225746cf23f08f8ec5520af821dc7997adcaf3f3a793e19ec79fa289ff39b06457015207fde16f2fabe21cec8aec3bf83df991
|
data/README.md
CHANGED
@@ -16,35 +16,15 @@ Command line interface for [Victor][victor], the SVG Library.
|
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
19
|
-
###
|
19
|
+
### `init`: Create a sample Ruby file
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
```xml
|
24
|
-
<!-- example.svg -->
|
25
|
-
<svg width="140" height="100">
|
26
|
-
<circle cx="50" cy="50" r="30" fill="yellow"/>
|
27
|
-
</svg>
|
28
|
-
```
|
29
|
-
|
30
|
-
Run this command:
|
21
|
+
Run this command to create an initial sample file:
|
31
22
|
|
32
23
|
```shell
|
33
|
-
$ victor
|
34
|
-
```
|
35
|
-
|
36
|
-
To generate this Ruby code:
|
37
|
-
|
38
|
-
```ruby
|
39
|
-
setup width: "140", height: "100"
|
40
|
-
|
41
|
-
build do
|
42
|
-
circle cx: "50", cy: "50", r: "30", fill: "yellow"
|
43
|
-
end
|
44
|
-
|
24
|
+
$ victor init example
|
45
25
|
```
|
46
26
|
|
47
|
-
###
|
27
|
+
### `render`: Render Ruby to SVG
|
48
28
|
|
49
29
|
Given this Ruby code:
|
50
30
|
|
@@ -59,7 +39,7 @@ end
|
|
59
39
|
|
60
40
|
Run this command:
|
61
41
|
```shell
|
62
|
-
$ victor
|
42
|
+
$ victor render example.rb --template minimal
|
63
43
|
```
|
64
44
|
|
65
45
|
To generate this code:
|
@@ -70,6 +50,33 @@ To generate this code:
|
|
70
50
|
</svg>
|
71
51
|
```
|
72
52
|
|
53
|
+
### `convert`: Convert SVG to Ruby
|
54
|
+
|
55
|
+
Given this SVG file:
|
56
|
+
|
57
|
+
```xml
|
58
|
+
<!-- example.svg -->
|
59
|
+
<svg width="140" height="100">
|
60
|
+
<circle cx="50" cy="50" r="30" fill="yellow"/>
|
61
|
+
</svg>
|
62
|
+
```
|
63
|
+
|
64
|
+
Run this command:
|
65
|
+
|
66
|
+
```shell
|
67
|
+
$ victor convert example.svg
|
68
|
+
```
|
69
|
+
|
70
|
+
To generate this Ruby code:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
setup width: 140, height: 100
|
74
|
+
|
75
|
+
build do
|
76
|
+
circle cx: 50, cy: 50, r: 30, fill: "yellow"
|
77
|
+
end
|
78
|
+
|
79
|
+
```
|
73
80
|
---
|
74
81
|
|
75
82
|
[victor]: https://github.com/DannyBen/victor
|
data/bin/victor
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'mister_bin'
|
2
|
-
|
3
|
-
require_relative 'commands/generate_ruby'
|
4
|
-
require_relative 'commands/generate_svg'
|
2
|
+
requires 'commands/base', 'commands'
|
5
3
|
|
6
4
|
module Victor
|
7
5
|
module CLI
|
@@ -10,8 +8,9 @@ module Victor
|
|
10
8
|
router = MisterBin::Runner.new version: VERSION,
|
11
9
|
header: "Victor SVG Utilities"
|
12
10
|
|
13
|
-
router.route '
|
14
|
-
router.route '
|
11
|
+
router.route 'init', to: Commands::Init
|
12
|
+
router.route 'convert', to: Commands::Convert
|
13
|
+
router.route 'render', to: Commands::Render
|
15
14
|
|
16
15
|
router
|
17
16
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Victor
|
2
2
|
module CLI
|
3
3
|
module Commands
|
4
|
-
class
|
4
|
+
class Convert < Base
|
5
5
|
summary "Convert SVG to Ruby code"
|
6
6
|
|
7
|
-
usage "victor
|
8
|
-
usage "victor
|
7
|
+
usage "victor convert SVG_FILE [RUBY_FILE --template NAME]"
|
8
|
+
usage "victor convert (-h|--help)"
|
9
9
|
|
10
10
|
option "-t, --template NAME", "Name of the Ruby template to use. Can be:\n" +
|
11
11
|
" standalone a full standalone Ruby script\n" +
|
@@ -15,14 +15,16 @@ module Victor
|
|
15
15
|
param "SVG_FILE", "Input SVG file"
|
16
16
|
param "RUBY_FILE", "Output Ruby file. Leave empty to write to stdout"
|
17
17
|
|
18
|
-
example "victor
|
18
|
+
example "victor convert example.svg example.rb"
|
19
19
|
|
20
20
|
def run
|
21
|
-
svg_file =
|
22
|
-
|
23
|
-
|
21
|
+
svg_file = args["SVG_FILE"]
|
22
|
+
template = args['--template']
|
23
|
+
svg_node = SVGNode.load_file svg_file, layout: template
|
24
24
|
|
25
|
-
|
25
|
+
validate_template template if template
|
26
|
+
|
27
|
+
code = svg_node.render
|
26
28
|
ruby_file = args["RUBY_FILE"]
|
27
29
|
|
28
30
|
if ruby_file
|
@@ -32,6 +34,13 @@ module Victor
|
|
32
34
|
puts code
|
33
35
|
end
|
34
36
|
end
|
37
|
+
|
38
|
+
def validate_template(template)
|
39
|
+
allowed = %w[cli dsl standalone]
|
40
|
+
unless allowed.include? template
|
41
|
+
raise "Template not found #{template}\nAvailable templates: #{allowed.join ', '}"
|
42
|
+
end
|
43
|
+
end
|
35
44
|
end
|
36
45
|
end
|
37
46
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Victor
|
2
|
+
module CLI
|
3
|
+
module Commands
|
4
|
+
class Init < Base
|
5
|
+
summary "Create a sample Victor Ruby script"
|
6
|
+
|
7
|
+
usage "victor init RUBY_FILE [--template TEMPLATE]"
|
8
|
+
usage "victor init (-h|--help)"
|
9
|
+
|
10
|
+
option "-t, --template NAME", "Name of the Ruby template to use. Can be:\n" +
|
11
|
+
" standalone a full standalone Ruby script\n" +
|
12
|
+
" dsl a Victor DSL script\n" +
|
13
|
+
" cli a Victor CLI compatible DSL script (default)"
|
14
|
+
|
15
|
+
param "RUBY_FILE", "Output Ruby file"
|
16
|
+
|
17
|
+
example "victor init ghost.rb"
|
18
|
+
example "victor init ghost.rb --template standalone"
|
19
|
+
|
20
|
+
def run
|
21
|
+
raise "File already exists #{filename}" if File.exist? filename
|
22
|
+
|
23
|
+
basename = File.basename filename, '.rb'
|
24
|
+
vars = { filename: filename, basename: basename }
|
25
|
+
content = template_content(template) % vars
|
26
|
+
|
27
|
+
File.write filename, content
|
28
|
+
say "Saved #{filename}"
|
29
|
+
|
30
|
+
if template == 'cli'
|
31
|
+
say %Q[Run !txtblu!victor render "#{filename}"!txtrst! to render]
|
32
|
+
else
|
33
|
+
say %Q[Run !txtblu!ruby "#{filename}"!txtrst! to render]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def filename
|
40
|
+
@filename ||= if args["RUBY_FILE"].end_with? '.rb'
|
41
|
+
args["RUBY_FILE"]
|
42
|
+
else
|
43
|
+
args['RUBY_FILE'] + ".rb"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def template
|
48
|
+
@template ||= args['--template'] || 'cli'
|
49
|
+
end
|
50
|
+
|
51
|
+
def template_content(name)
|
52
|
+
filename = File.join templates_path, "#{name}.rb"
|
53
|
+
|
54
|
+
unless available_templates.include? name
|
55
|
+
raise "Invalid template #{name}\nAvailable templates: #{available_templates.join ', '}"
|
56
|
+
end
|
57
|
+
|
58
|
+
File.read filename
|
59
|
+
end
|
60
|
+
|
61
|
+
def templates_path
|
62
|
+
@templates_path ||= File.expand_path "../templates/init", __dir__
|
63
|
+
end
|
64
|
+
|
65
|
+
def available_templates
|
66
|
+
['cli', 'dsl', 'standalone']
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'filewatcher'
|
2
|
+
|
3
|
+
module Victor
|
4
|
+
module CLI
|
5
|
+
module Commands
|
6
|
+
class Render < Base
|
7
|
+
summary "Render Ruby code to SVG"
|
8
|
+
|
9
|
+
usage "victor render RUBY_FILE [SVG_FILE] [options]"
|
10
|
+
usage "victor render (-h|--help)"
|
11
|
+
|
12
|
+
option '-t, --template TEMPLATE', "Set SVG template\n"+
|
13
|
+
"Can be: default, html, minimal, or a file path"
|
14
|
+
|
15
|
+
option '-w, --watch', 'Watch the source file and regenerate on change'
|
16
|
+
|
17
|
+
param "RUBY_FILE", "Input Ruby file"
|
18
|
+
param "SVG_FILE", "Output SVG file. Leave empty to write to stdout"
|
19
|
+
|
20
|
+
example "victor render input.rb output.svg"
|
21
|
+
example "victor render input.rb --template minimal"
|
22
|
+
|
23
|
+
def run
|
24
|
+
if args['--watch']
|
25
|
+
watch { generate }
|
26
|
+
else
|
27
|
+
generate
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def generate
|
34
|
+
code = File.read ruby_file
|
35
|
+
|
36
|
+
ruby_source = RubySource.new code, ruby_file
|
37
|
+
ruby_source.evaluate
|
38
|
+
ruby_source.template template if template
|
39
|
+
|
40
|
+
if svg_file
|
41
|
+
ruby_source.svg.save svg_file
|
42
|
+
say "Saved #{svg_file}"
|
43
|
+
else
|
44
|
+
puts ruby_source.svg.render
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def watch
|
49
|
+
say "Watching #{ruby_file} for changes"
|
50
|
+
file_watcher.watch do |file, event|
|
51
|
+
yield unless event == :deleted
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def file_watcher
|
56
|
+
@file_watcher ||= Filewatcher.new(ruby_file, immediate: true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def ruby_file
|
60
|
+
args["RUBY_FILE"]
|
61
|
+
end
|
62
|
+
|
63
|
+
def svg_file
|
64
|
+
args["SVG_FILE"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def template
|
68
|
+
args['--template']
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "css_parser"
|
2
|
+
|
3
|
+
module Victor
|
4
|
+
module CLI
|
5
|
+
class CSSData
|
6
|
+
attr_reader :css_string
|
7
|
+
|
8
|
+
def initialize(css_string)
|
9
|
+
@css_string = css_string
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_h
|
13
|
+
parser.load_string! css_string
|
14
|
+
parser.to_h['all']
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parser
|
20
|
+
@parser ||= CssParser::Parser.new
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Victor
|
2
|
+
module CLI
|
3
|
+
module Rendering
|
4
|
+
refine Hash do
|
5
|
+
def render
|
6
|
+
# TODO: Reduce cognitive complexity
|
7
|
+
map do |key, value|
|
8
|
+
key = key.to_key if key.is_a? String
|
9
|
+
|
10
|
+
if key == "style"
|
11
|
+
value = "{ #{value.style_to_hash.render} }"
|
12
|
+
elsif value.is_a? String
|
13
|
+
value = value.to_value
|
14
|
+
end
|
15
|
+
|
16
|
+
"#{key}: #{value}"
|
17
|
+
end.join ", "
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
refine String do
|
23
|
+
def to_key
|
24
|
+
gsub('-', '_').to_sym.inspect[1..-1]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_value
|
28
|
+
if to_f.to_s == self or to_i.to_s == self
|
29
|
+
self
|
30
|
+
else
|
31
|
+
%Q["#{self}"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Transforms the valus of a style attribute to a hash
|
36
|
+
# Example: "color: black; top: 10" => { color: black, top: 10 }
|
37
|
+
def style_to_hash
|
38
|
+
parser = CssParser::Parser.new
|
39
|
+
parser.load_string! "victor { #{self} }"
|
40
|
+
parser.to_h["all"]["victor"]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,15 +1,20 @@
|
|
1
1
|
module Victor
|
2
2
|
module CLI
|
3
|
-
class
|
3
|
+
class RubySource
|
4
4
|
include Victor::DSL
|
5
|
-
attr_reader :code
|
5
|
+
attr_reader :code, :filename
|
6
6
|
|
7
|
-
def initialize(code)
|
7
|
+
def initialize(code, filename = nil)
|
8
8
|
@code = code
|
9
|
+
@filename = filename
|
9
10
|
end
|
10
11
|
|
11
12
|
def evaluate
|
12
|
-
|
13
|
+
if filename
|
14
|
+
instance_eval code, filename
|
15
|
+
else
|
16
|
+
instance_eval code
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def template(template)
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'erb'
|
3
|
+
require 'rufo'
|
4
|
+
|
5
|
+
module Victor
|
6
|
+
module CLI
|
7
|
+
class SVGNode
|
8
|
+
using Rendering
|
9
|
+
attr_reader :node, :layout
|
10
|
+
|
11
|
+
# Returns a new instance from an SVG file
|
12
|
+
def self.load_file(path, layout: nil)
|
13
|
+
load File.read(path), layout: layout
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns a new instance from raw SVG string
|
17
|
+
def self.load(svg_string, layout: nil)
|
18
|
+
doc = Nokogiri::XML svg_string
|
19
|
+
root = doc.children.last
|
20
|
+
new root, layout: layout
|
21
|
+
end
|
22
|
+
|
23
|
+
# Initializes with a Nokogiri XML node
|
24
|
+
def initialize(node, layout: nil)
|
25
|
+
@node = node
|
26
|
+
@layout = layout || :cli
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns formatted Ruby code
|
30
|
+
def render
|
31
|
+
Rufo::Formatter.format ruby_code
|
32
|
+
rescue Rufo::SyntaxError => e
|
33
|
+
raise ruby_code
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
"#<#{self.class} name=#{name}, type=#{type}>"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the tag name
|
41
|
+
def name
|
42
|
+
node.name
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns one of our internal types (symbol)
|
46
|
+
def type
|
47
|
+
@type ||= type!
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a hash of attributes
|
51
|
+
def attributes
|
52
|
+
@attributes ||= attributes!
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the content (body) of the lement
|
56
|
+
def content
|
57
|
+
@content ||= content!
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns an array of children elements (SVGNode)
|
61
|
+
def children
|
62
|
+
@children ||= children!
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the ruby code, unformatted
|
66
|
+
def ruby_code
|
67
|
+
erb erb_template
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# Returns true if the element should be ignored
|
73
|
+
def rejected?
|
74
|
+
(node.text? and node.text.strip.empty?) or type == :junk
|
75
|
+
end
|
76
|
+
|
77
|
+
# Renders ERB code
|
78
|
+
def erb(code)
|
79
|
+
ERB.new(code, trim_mode: '%-').result(binding)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the content of the appropriate ERB tempalte, based on type
|
83
|
+
def erb_template
|
84
|
+
@erb_template ||= File.read(erb_template_file)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the path to the appropriate ERB template, based on type
|
88
|
+
def erb_template_file
|
89
|
+
file = type == :root ? "root_#{layout}" : type
|
90
|
+
path = File.expand_path "templates/nodes/#{file}.erb", __dir__
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the internal element type
|
94
|
+
def type!
|
95
|
+
if node.text?
|
96
|
+
:text
|
97
|
+
elsif node.comment?
|
98
|
+
:junk
|
99
|
+
elsif node.name == 'style'
|
100
|
+
:css
|
101
|
+
elsif node.name == 'svg'
|
102
|
+
:root
|
103
|
+
else
|
104
|
+
:element
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns a filtered list of SVGNode children
|
109
|
+
def children!
|
110
|
+
node.children.map do |child|
|
111
|
+
SVGNode.new child
|
112
|
+
end.reject(&:rejected?)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns a hash of attributes
|
116
|
+
def attributes!
|
117
|
+
node.attribute_nodes.map do |attr|
|
118
|
+
name = attr.name
|
119
|
+
value = attr.value
|
120
|
+
key = attr.respond_to?(:prefix) ? "#{attr.prefix}:#{name}" : name
|
121
|
+
|
122
|
+
[key, value]
|
123
|
+
end.to_h
|
124
|
+
end
|
125
|
+
|
126
|
+
def content!
|
127
|
+
if type == :css
|
128
|
+
CSSData.new(node.content).to_h
|
129
|
+
elsif node.content.is_a? String
|
130
|
+
node.content.strip
|
131
|
+
else
|
132
|
+
# TODO: do we need this?
|
133
|
+
# :nocov:
|
134
|
+
node.content
|
135
|
+
# :nocov:
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Render this by running:
|
2
|
+
# victor render "%{filename}"
|
3
|
+
|
4
|
+
setup viewBox: "0 0 100 100"
|
5
|
+
|
6
|
+
build do
|
7
|
+
circle cx: 50, cy: 50, r: 40, fill: 'yellow'
|
8
|
+
rect x: 10, y: 50, width: 80, height: 50, fill: 'yellow'
|
9
|
+
|
10
|
+
[25, 50].each do |x|
|
11
|
+
circle cx: x, cy: 40, r: 8, fill: 'white'
|
12
|
+
end
|
13
|
+
|
14
|
+
path d: "M11 100 l13 -15 l13 15 l13 -15 l13 15 l13 -15 l13 15 Z", fill: 'white'
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Render this by running
|
2
|
+
# ruby "%{filename}"
|
3
|
+
require 'victor/script'
|
4
|
+
|
5
|
+
setup viewBox: "0 0 100 100"
|
6
|
+
|
7
|
+
build do
|
8
|
+
circle cx: 50, cy: 50, r: 40, fill: 'yellow'
|
9
|
+
rect x: 10, y: 50, width: 80, height: 50, fill: 'yellow'
|
10
|
+
|
11
|
+
[25, 50].each do |x|
|
12
|
+
circle cx: x, cy: 40, r: 8, fill: 'white'
|
13
|
+
end
|
14
|
+
|
15
|
+
path d: "M11 100 l13 -15 l13 15 l13 -15 l13 15 l13 -15 l13 15 Z", fill: 'white'
|
16
|
+
end
|
17
|
+
|
18
|
+
puts render
|
19
|
+
save "%{basename}"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Render this by running
|
2
|
+
# ruby "%{filename}"
|
3
|
+
require 'victor'
|
4
|
+
|
5
|
+
svg = Victor::SVG.new viewBox: "0 0 100 100"
|
6
|
+
|
7
|
+
svg.build do
|
8
|
+
circle cx: 50, cy: 50, r: 40, fill: 'yellow'
|
9
|
+
rect x: 10, y: 50, width: 80, height: 50, fill: 'yellow'
|
10
|
+
|
11
|
+
[25, 50].each do |x|
|
12
|
+
circle cx: x, cy: 40, r: 8, fill: 'white'
|
13
|
+
end
|
14
|
+
|
15
|
+
path d: "M11 100 l13 -15 l13 15 l13 -15 l13 15 l13 -15 l13 15 Z", fill: 'white'
|
16
|
+
end
|
17
|
+
|
18
|
+
puts svg.render
|
19
|
+
svg.save "%{basename}"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= "# :element" if ENV['DEBUG'] -%>
|
2
|
+
<%- if children.any? -%>
|
3
|
+
<%- if children.count == 1 and children.first.node.text? -%>
|
4
|
+
<%- if attributes.any? -%>
|
5
|
+
<%= name %> "<%= content %>", <%= attributes.render %>
|
6
|
+
<%- else -%>
|
7
|
+
<%= name %> "<%= content %>"
|
8
|
+
<%- end -%>
|
9
|
+
<%- else -%>
|
10
|
+
<%= name %> <%= attributes.render %> do
|
11
|
+
<%- children.each do |child| -%>
|
12
|
+
<%= child.render %>
|
13
|
+
<%- end -%>
|
14
|
+
end
|
15
|
+
<%- end -%>
|
16
|
+
<%- else -%>
|
17
|
+
<%= name %> <%= attributes.render %>
|
18
|
+
<%- end -%>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= "# :root" if ENV['DEBUG'] -%>
|
2
|
+
# Render this template by running 'victor render FILE'
|
3
|
+
|
4
|
+
<%- if attributes.any? -%>
|
5
|
+
setup <%= attributes.render %>
|
6
|
+
<%- end -%>
|
7
|
+
|
8
|
+
build do
|
9
|
+
<%- children.each do |child| -%>
|
10
|
+
<%= child.render %>
|
11
|
+
<%- end -%>
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= "# :root" if ENV['DEBUG'] -%>
|
2
|
+
# Render this template by running 'ruby FILE' or 'victor render FILE'
|
3
|
+
|
4
|
+
require 'victor/script'
|
5
|
+
|
6
|
+
<%- if attributes.any? -%>
|
7
|
+
setup <%= attributes.render %>
|
8
|
+
<%- end -%>
|
9
|
+
|
10
|
+
build do
|
11
|
+
<%- children.each do |child| -%>
|
12
|
+
<%= child.render %>
|
13
|
+
<%- end -%>
|
14
|
+
end
|
15
|
+
|
16
|
+
puts render
|
17
|
+
save 'output'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%= "# :root" if ENV['DEBUG'] -%>
|
2
|
+
# Render this template by running 'ruby FILE' or 'victor render FILE'
|
3
|
+
|
4
|
+
require "victor"
|
5
|
+
|
6
|
+
svg = Victor::SVG.new <%= attributes.render %>
|
7
|
+
|
8
|
+
svg.build do
|
9
|
+
<%- children.each do |child| -%>
|
10
|
+
<%= child.render %>
|
11
|
+
<%- end -%>
|
12
|
+
end
|
13
|
+
|
14
|
+
svg.save "result"
|
data/lib/victor/cli/version.rb
CHANGED
data/lib/victor/cli.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
require 'victor'
|
2
|
-
|
3
|
-
|
4
|
-
require_relative 'cli/
|
2
|
+
require 'requires'
|
3
|
+
requires 'cli/refinements'
|
4
|
+
require_relative 'cli/ruby_source'
|
5
|
+
require_relative 'cli/css_data'
|
5
6
|
require_relative 'cli/command_line'
|
7
|
+
require_relative 'cli/svg_node'
|
6
8
|
|
7
|
-
|
9
|
+
if ENV['BYEBUG']
|
10
|
+
require 'byebug'
|
11
|
+
require 'lp'
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: victor-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
@@ -9,64 +9,64 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: filewatcher
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '1.1'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '1.1'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: nokogiri
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '1.10'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '1.10'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: pretty_trace
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 0.2.5
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
55
|
+
version: 0.2.5
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
57
|
+
name: requires
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '0.2'
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '0.2'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rufo
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,19 +82,61 @@ dependencies:
|
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0.12'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
85
|
+
name: colsole
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '0.
|
90
|
+
version: '0.7'
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '0.
|
97
|
+
version: '0.7'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: css_parser
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '1.7'
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '1.7'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: mister_bin
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0.7'
|
119
|
+
type: :runtime
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.7'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: victor
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.3'
|
133
|
+
type: :runtime
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.3'
|
98
140
|
description: CLI for Victor, the SVG Library
|
99
141
|
email: db@dannyben.com
|
100
142
|
executables:
|
@@ -105,16 +147,24 @@ files:
|
|
105
147
|
- README.md
|
106
148
|
- bin/victor
|
107
149
|
- lib/victor/cli.rb
|
108
|
-
- lib/victor/cli/code_generator.rb
|
109
150
|
- lib/victor/cli/command_line.rb
|
110
151
|
- lib/victor/cli/commands/base.rb
|
111
|
-
- lib/victor/cli/commands/
|
112
|
-
- lib/victor/cli/commands/
|
113
|
-
- lib/victor/cli/
|
114
|
-
- lib/victor/cli/
|
115
|
-
- lib/victor/cli/
|
116
|
-
- lib/victor/cli/
|
117
|
-
- lib/victor/cli/
|
152
|
+
- lib/victor/cli/commands/convert.rb
|
153
|
+
- lib/victor/cli/commands/init.rb
|
154
|
+
- lib/victor/cli/commands/render.rb
|
155
|
+
- lib/victor/cli/css_data.rb
|
156
|
+
- lib/victor/cli/refinements/rendering.rb
|
157
|
+
- lib/victor/cli/ruby_source.rb
|
158
|
+
- lib/victor/cli/svg_node.rb
|
159
|
+
- lib/victor/cli/templates/init/cli.rb
|
160
|
+
- lib/victor/cli/templates/init/dsl.rb
|
161
|
+
- lib/victor/cli/templates/init/standalone.rb
|
162
|
+
- lib/victor/cli/templates/nodes/css.erb
|
163
|
+
- lib/victor/cli/templates/nodes/element.erb
|
164
|
+
- lib/victor/cli/templates/nodes/root_cli.erb
|
165
|
+
- lib/victor/cli/templates/nodes/root_dsl.erb
|
166
|
+
- lib/victor/cli/templates/nodes/root_standalone.erb
|
167
|
+
- lib/victor/cli/templates/nodes/text.erb
|
118
168
|
- lib/victor/cli/version.rb
|
119
169
|
homepage: https://github.com/dannyben/victor-cli
|
120
170
|
licenses:
|
@@ -128,14 +178,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
178
|
requirements:
|
129
179
|
- - ">="
|
130
180
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
181
|
+
version: 2.7.0
|
132
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
183
|
requirements:
|
134
184
|
- - ">="
|
135
185
|
- !ruby/object:Gem::Version
|
136
186
|
version: '0'
|
137
187
|
requirements: []
|
138
|
-
rubygems_version: 3.
|
188
|
+
rubygems_version: 3.3.14
|
139
189
|
signing_key:
|
140
190
|
specification_version: 4
|
141
191
|
summary: CLI for Victor, the SVG Library
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require "rufo"
|
2
|
-
|
3
|
-
module Victor
|
4
|
-
module CLI
|
5
|
-
class CodeGenerator
|
6
|
-
attr_reader :svg_tree, :template
|
7
|
-
|
8
|
-
def initialize(svg_tree, template: nil)
|
9
|
-
@svg_tree = svg_tree
|
10
|
-
@template = template || :cli
|
11
|
-
end
|
12
|
-
|
13
|
-
def generate
|
14
|
-
Rufo::Formatter.format(code_for_node(svg_tree))
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def code_for_node(node)
|
20
|
-
case node.first
|
21
|
-
when "svg"
|
22
|
-
root_to_ruby node
|
23
|
-
else
|
24
|
-
node_to_ruby node
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def node_to_ruby(node)
|
29
|
-
name, attrs, children = node
|
30
|
-
code = "#{name} #{attrs_to_ruby(attrs)} "
|
31
|
-
unless children.empty?
|
32
|
-
code << " do\n"
|
33
|
-
code << nodes_to_ruby(children)
|
34
|
-
code << "\nend\n"
|
35
|
-
end
|
36
|
-
code
|
37
|
-
end
|
38
|
-
|
39
|
-
def nodes_to_ruby(nodes)
|
40
|
-
nodes.map(&method(:code_for_node)).join("\n")
|
41
|
-
end
|
42
|
-
|
43
|
-
def attrs_to_ruby(attrs)
|
44
|
-
attrs.reduce([]) do |acc, (k, v)|
|
45
|
-
acc << "#{k.to_sym.inspect[1..-1]}: #{v.inspect}"
|
46
|
-
acc
|
47
|
-
end.join(",")
|
48
|
-
end
|
49
|
-
|
50
|
-
def root_to_ruby(node)
|
51
|
-
_, attrs, children = node
|
52
|
-
values = {
|
53
|
-
attributes: attrs_to_ruby(attrs),
|
54
|
-
nodes: nodes_to_ruby(children)
|
55
|
-
}
|
56
|
-
|
57
|
-
template_content(template) % values
|
58
|
-
end
|
59
|
-
|
60
|
-
def template_content(name)
|
61
|
-
filename = File.join templates_path, "#{name}.rb"
|
62
|
-
|
63
|
-
unless File.exist? filename
|
64
|
-
raise "Template not found #{name}\nAvailable templates: #{available_templates.join ', '}"
|
65
|
-
end
|
66
|
-
|
67
|
-
File.read filename
|
68
|
-
end
|
69
|
-
|
70
|
-
def templates_path
|
71
|
-
@templates_path ||= File.expand_path "templates", __dir__
|
72
|
-
end
|
73
|
-
|
74
|
-
def available_templates
|
75
|
-
@available_templates ||= Dir["#{templates_path}/*.rb"].map do |path|
|
76
|
-
File.basename path, '.rb'
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Victor
|
2
|
-
module CLI
|
3
|
-
module Commands
|
4
|
-
class GenerateSVG < Base
|
5
|
-
summary "Convert Ruby code to SVG"
|
6
|
-
|
7
|
-
usage "victor to-svg RUBY_FILE [SVG_FILE --template TEMPLATE]"
|
8
|
-
usage "victor to-svg (-h|--help)"
|
9
|
-
|
10
|
-
option '-t, --template TEMPLATE', "Set SVG template\n"+
|
11
|
-
"Can be: default, html, minimal, or a file path"
|
12
|
-
|
13
|
-
param "RUBY_FILE", "Input Ruby file"
|
14
|
-
param "SVG_FILE", "Output SVG file. Leave empty to write to stdout"
|
15
|
-
|
16
|
-
example "victor to-svg input.rb output.svg"
|
17
|
-
example "victor to-svg input.rb --template minimal"
|
18
|
-
|
19
|
-
def run
|
20
|
-
ruby_file = args["RUBY_FILE"]
|
21
|
-
svg_file = args["SVG_FILE"]
|
22
|
-
template = args['--template']
|
23
|
-
code = File.read ruby_file
|
24
|
-
|
25
|
-
ruby_code = RubyCode.new code
|
26
|
-
ruby_code.evaluate
|
27
|
-
ruby_code.template template if template
|
28
|
-
|
29
|
-
if svg_file
|
30
|
-
ruby_code.svg.save svg_file
|
31
|
-
say "Saved #{svg_file}"
|
32
|
-
else
|
33
|
-
puts ruby_code.svg.render
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/victor/cli/parser.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require "nokogiri"
|
2
|
-
|
3
|
-
module Victor
|
4
|
-
module CLI
|
5
|
-
class Parser
|
6
|
-
attr_reader :raw_svg
|
7
|
-
|
8
|
-
def initialize(raw_svg)
|
9
|
-
@raw_svg = raw_svg
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse
|
13
|
-
parse_node svg_root
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
|
19
|
-
def parse_node(node)
|
20
|
-
case node
|
21
|
-
when Nokogiri::XML::Comment
|
22
|
-
nil
|
23
|
-
when Nokogiri::XML::Text
|
24
|
-
parse_text node
|
25
|
-
else
|
26
|
-
parse_normal_node node
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def parse_text(node)
|
31
|
-
inner_text = node.text
|
32
|
-
cleaned_text = inner_text.strip
|
33
|
-
return nil unless cleaned_text.length > 0
|
34
|
-
return ["_", {}, cleaned_text]
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse_normal_node(node)
|
38
|
-
[
|
39
|
-
node.name,
|
40
|
-
node_attrs(node),
|
41
|
-
node.children.map(&method(:parse_node)).compact,
|
42
|
-
]
|
43
|
-
end
|
44
|
-
|
45
|
-
def node_attrs(node)
|
46
|
-
node.attributes.values.reduce({}) do |acc, attr|
|
47
|
-
name = attr.name
|
48
|
-
value = attr.value
|
49
|
-
key = attr.respond_to?(:prefix) ? "#{attr.prefix}:#{name}" : name
|
50
|
-
acc[key] = value
|
51
|
-
acc
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def xml_doc
|
56
|
-
Nokogiri::XML raw_svg
|
57
|
-
end
|
58
|
-
|
59
|
-
def svg_root
|
60
|
-
xml_doc.children.last
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|