sevgi-showcase 0.95.0 → 0.98.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -0
  3. data/README.md +9 -17
  4. data/lib/sevgi/showcase/dark.rb +4 -0
  5. data/lib/sevgi/showcase/minitest/script.rb +59 -57
  6. data/lib/sevgi/showcase/minitest/shell.rb +132 -128
  7. data/lib/sevgi/showcase/minitest/suite.rb +48 -46
  8. data/lib/sevgi/showcase/minitest.rb +6 -0
  9. data/lib/sevgi/showcase/version.rb +1 -1
  10. data/lib/sevgi/showcase.rb +0 -3
  11. data/srv/checkers.sevgi +79 -0
  12. data/srv/checkers.svg +117 -0
  13. data/srv/clover.sevgi +19 -0
  14. data/srv/clover.svg +11 -0
  15. data/srv/clover.yml +3 -0
  16. data/srv/copperplate.sevgi +50 -0
  17. data/srv/copperplate.svg +99 -0
  18. data/srv/copperplate.yml +5 -0
  19. data/srv/{gear-wheel.sevgi → gear.sevgi} +7 -9
  20. data/srv/gear.svg +11 -0
  21. data/srv/gear.yml +2 -0
  22. data/srv/{grid-cells.sevgi → grid.sevgi} +9 -9
  23. data/srv/{grid-cells.svg → grid.svg} +13 -1
  24. data/srv/heart.sevgi +17 -0
  25. data/srv/{heart-mask.svg → heart.svg} +3 -3
  26. data/srv/heart.yml +3 -0
  27. data/srv/logo.sevgi +39 -0
  28. data/srv/logo.svg +29 -0
  29. data/srv/logo.yml +4 -0
  30. data/srv/logos.sevgi +34 -0
  31. data/srv/logos.svg +38 -0
  32. data/srv/logos.yml +4 -0
  33. data/srv/{meter-face.sevgi → meter.sevgi} +6 -6
  34. data/srv/meter.svg +18 -0
  35. data/srv/pacman.sevgi +18 -0
  36. data/srv/pacman.svg +15 -0
  37. data/srv/pokey.sevgi +14 -0
  38. data/srv/pokey.svg +6 -0
  39. data/srv/{ruler-line.sevgi → ruler-.sevgi} +7 -7
  40. data/srv/ruler.sevgi +61 -0
  41. data/srv/ruler.svg +445 -0
  42. data/srv/{snow-flake.sevgi → snowflake.sevgi} +2 -2
  43. data/srv/{snow-flake.svg → snowflake.svg} +1 -1
  44. data/srv/snowflake.yml +2 -0
  45. data/srv/squared.sevgi +42 -0
  46. data/srv/squared.svg +71 -0
  47. data/srv/squared.yml +4 -0
  48. data/srv/stars.sevgi +19 -0
  49. data/srv/stars.svg +30 -0
  50. data/srv/stars.yml +3 -0
  51. data/srv/tulips.sevgi +27 -0
  52. data/srv/tulips.svg +19 -0
  53. data/srv/tulips.yml +3 -0
  54. metadata +57 -36
  55. data/srv/checker-board.sevgi +0 -96
  56. data/srv/checker-board.svg +0 -117
  57. data/srv/gear-wheel.svg +0 -12
  58. data/srv/gear-wheel.yml +0 -3
  59. data/srv/heart-mask.sevgi +0 -17
  60. data/srv/heart-mask.yml +0 -3
  61. data/srv/meter-face.svg +0 -13
  62. data/srv/pacman-pokey.sevgi +0 -17
  63. data/srv/pacman-pokey.svg +0 -9
  64. data/srv/pacman-single.sevgi +0 -17
  65. data/srv/pacman-single.svg +0 -14
  66. data/srv/ruler-hline.sevgi +0 -55
  67. data/srv/ruler-hline.svg +0 -443
  68. data/srv/snow-flake.yml +0 -1
  69. /data/srv/{checker-board.yml → checkers.yml} +0 -0
  70. /data/srv/{grid-cells.yml → grid.yml} +0 -0
  71. /data/srv/{meter-face.yml → meter.yml} +0 -0
  72. /data/srv/{pacman-pokey.yml → pacman.yml} +0 -0
  73. /data/srv/{pacman-single.yml → pokey.yml} +0 -0
  74. /data/srv/{ruler-line.svg → ruler-.svg} +0 -0
  75. /data/srv/{ruler-hline.yml → ruler-.yml} +0 -0
  76. /data/srv/{ruler-line.yml → ruler.yml} +0 -0
@@ -1,53 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sevgi
4
- # Minitest helpers used by the showcase component.
5
- # @api private
6
- module Test
7
- # Showcase script suite collection.
4
+ module Showcase
5
+ # Minitest helpers used by the showcase component.
8
6
  # @api private
9
- class Suite
10
- # Creates a suite from a showcase root directory.
11
- # @param rootdir [String] showcase root directory
12
- # @return [void]
13
- def initialize(rootdir)
14
- @scripts = load(rootdir)
15
- end
16
-
17
- # Returns scripts belonging to a suite.
18
- # @param suite [String, Symbol] suite name
19
- # @return [Array<Sevgi::Test::Script>]
20
- def [](suite)
21
- (@cache ||= {})[suite] ||= @scripts.select { |script| script.suite == suite.to_s }
22
- end
23
-
24
- # Returns all suite names.
25
- # @return [Array<String>]
26
- def suites
27
- @suites ||= @scripts.map(&:suite).uniq
28
- end
29
-
30
- # Suite names that are expected to be invalid examples.
31
- NON_VALIDS = ["gotcha"].freeze
32
-
33
- # Returns scripts expected to be invalid.
34
- # @return [Array<Sevgi::Test::Script>]
35
- def non_valids
36
- NON_VALIDS.map { self[it] }.flatten
37
- end
38
-
39
- # Returns scripts expected to render successfully.
40
- # @return [Array<Sevgi::Test::Script>]
41
- def valids
42
- suites.reject { NON_VALIDS.include?(it) }.map { self[it] }.flatten
43
- end
44
-
45
- alias to_a valids
46
-
47
- private
48
-
49
- def load(rootdir)
50
- ::Dir["#{rootdir}/**/*.sevgi"].grep_v(%r{(/_|/lib/|/library/)}).map { Script.new(it) }
7
+ module Test
8
+ # Showcase script suite collection.
9
+ # @api private
10
+ class Suite
11
+ # Creates a suite from a showcase root directory.
12
+ # @param rootdir [String] showcase root directory
13
+ # @return [void]
14
+ def initialize(rootdir)
15
+ @scripts = load(rootdir)
16
+ end
17
+
18
+ # Returns scripts belonging to a suite.
19
+ # @param suite [String, Symbol] suite name
20
+ # @return [Array<Sevgi::Showcase::Test::Script>]
21
+ def [](suite)
22
+ (@cache ||= {})[suite] ||= @scripts.select { |script| script.suite == suite.to_s }
23
+ end
24
+
25
+ # Returns all suite names.
26
+ # @return [Array<String>]
27
+ def suites
28
+ @suites ||= @scripts.map(&:suite).uniq
29
+ end
30
+
31
+ # Suite names that are expected to be invalid examples.
32
+ NON_VALIDS = ["gotcha"].freeze
33
+
34
+ # Returns scripts expected to be invalid.
35
+ # @return [Array<Sevgi::Showcase::Test::Script>]
36
+ def non_valids
37
+ NON_VALIDS.map { self[it] }.flatten
38
+ end
39
+
40
+ # Returns scripts expected to render successfully.
41
+ # @return [Array<Sevgi::Showcase::Test::Script>]
42
+ def valids
43
+ suites.reject { NON_VALIDS.include?(it) }.map { self[it] }.flatten
44
+ end
45
+
46
+ alias to_a valids
47
+
48
+ private
49
+
50
+ def load(rootdir)
51
+ ::Dir["#{rootdir}/**/*.sevgi"].grep_v(%r{(/_|/lib/|/library/)}).map { Script.new(it) }
52
+ end
51
53
  end
52
54
  end
53
55
  end
@@ -3,3 +3,9 @@
3
3
  require_relative "minitest/script"
4
4
  require_relative "minitest/shell"
5
5
  require_relative "minitest/suite"
6
+
7
+ module Sevgi
8
+ module Showcase
9
+ private_constant :Test
10
+ end
11
+ end
@@ -4,6 +4,6 @@ module Sevgi
4
4
  # Showcase component namespace.
5
5
  module Showcase
6
6
  # Current showcase component version.
7
- VERSION = "0.95.0"
7
+ VERSION = "0.98.2"
8
8
  end
9
9
  end
@@ -2,7 +2,4 @@
2
2
 
3
3
  require "sevgi"
4
4
 
5
- require_relative "showcase/dark"
6
- require_relative "showcase/minitest"
7
-
8
5
  require_relative "showcase/version"
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env -S ruby -S sevgi
2
+ # frozen_string_literal: true
3
+
4
+ module CheckerBoard
5
+ extend SVG::Module
6
+
7
+ BOARD_MARGIN = 50
8
+ CELL_SIZE = 100
9
+ PIECE_SIZE = 80
10
+ SIZE = (CELL_SIZE * 8) + (BOARD_MARGIN * 2)
11
+
12
+ STYLE = {
13
+ ".board-frame" => { fill: "#d1bfa7", stroke: "#6a3f2b" },
14
+ ".inner-frame" => {
15
+ fill: "#6a3f2b",
16
+ stroke: "#6a3f2b",
17
+ "stroke-width": (BOARD_MARGIN * 0.7).round
18
+ },
19
+ ".cell" => { stroke: "white", "stroke-width": 1 },
20
+ ".light.cell" => { fill: "#d4a76f" },
21
+ ".dark.cell" => { fill: "#6a3f2b" },
22
+ ".piece" => {
23
+ filter: "drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5))",
24
+ stroke: "none"
25
+ },
26
+ ".light.piece" => { fill: "#f5f5f5" },
27
+ ".dark.piece" => { fill: "#333" }
28
+ }.freeze
29
+
30
+ base do # Draw the board.
31
+ css STYLE
32
+
33
+ square class: "board-frame", length: SIZE
34
+ square class: "inner-frame", x: BOARD_MARGIN, y: BOARD_MARGIN,
35
+ length: SIZE - (BOARD_MARGIN * 2)
36
+
37
+ 8.times do |row|
38
+ 8.times do |col|
39
+ square class: "#{(row + col).even? ? "dark" : "light"} cell",
40
+ x: (col * CELL_SIZE) + BOARD_MARGIN,
41
+ y: (row * CELL_SIZE) + BOARD_MARGIN,
42
+ length: CELL_SIZE
43
+ end
44
+ end
45
+ end
46
+
47
+ def call(placement)
48
+ center = BOARD_MARGIN + (CELL_SIZE / 2)
49
+
50
+ placement.each do |tone, rows|
51
+ rows.each do |row, cols|
52
+ cols.each do |col|
53
+ circle class: "#{tone} piece",
54
+ cx: (col * CELL_SIZE) + center,
55
+ cy: (row * CELL_SIZE) + center,
56
+ r: PIECE_SIZE / 2
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ placement = {
64
+ dark: {
65
+ 0 => [1, 3, 5, 7],
66
+ 1 => [0, 2, 4, 6]
67
+ },
68
+ light: {
69
+ 6 => [1, 3, 5, 7],
70
+ 7 => [0, 2, 4, 6]
71
+ }
72
+ }
73
+
74
+ SVG :minimal,
75
+ width: CheckerBoard::SIZE,
76
+ height: CheckerBoard::SIZE,
77
+ viewBox: "0 0 #{CheckerBoard::SIZE} #{CheckerBoard::SIZE}" do
78
+ Call CheckerBoard, placement
79
+ end.Save
data/srv/checkers.svg ADDED
@@ -0,0 +1,117 @@
1
+ <svg width="900" height="900" viewBox="0 0 900 900">
2
+ <style type="text/css">
3
+ <![CDATA[
4
+ .board-frame {
5
+ fill: #d1bfa7;
6
+ stroke: #6a3f2b;
7
+ }
8
+ .inner-frame {
9
+ fill: #6a3f2b;
10
+ stroke: #6a3f2b;
11
+ stroke-width: 35;
12
+ }
13
+ .cell {
14
+ stroke: white;
15
+ stroke-width: 1;
16
+ }
17
+ .light.cell {
18
+ fill: #d4a76f;
19
+ }
20
+ .dark.cell {
21
+ fill: #6a3f2b;
22
+ }
23
+ .piece {
24
+ filter: drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5));
25
+ stroke: none;
26
+ }
27
+ .light.piece {
28
+ fill: #f5f5f5;
29
+ }
30
+ .dark.piece {
31
+ fill: #333;
32
+ }
33
+ ]]>
34
+ </style>
35
+ <rect width="900" height="900" class="board-frame"/>
36
+ <rect width="800" height="800" class="inner-frame" x="50" y="50"/>
37
+ <rect width="100" height="100" class="dark cell" x="50" y="50"/>
38
+ <rect width="100" height="100" class="light cell" x="150" y="50"/>
39
+ <rect width="100" height="100" class="dark cell" x="250" y="50"/>
40
+ <rect width="100" height="100" class="light cell" x="350" y="50"/>
41
+ <rect width="100" height="100" class="dark cell" x="450" y="50"/>
42
+ <rect width="100" height="100" class="light cell" x="550" y="50"/>
43
+ <rect width="100" height="100" class="dark cell" x="650" y="50"/>
44
+ <rect width="100" height="100" class="light cell" x="750" y="50"/>
45
+ <rect width="100" height="100" class="light cell" x="50" y="150"/>
46
+ <rect width="100" height="100" class="dark cell" x="150" y="150"/>
47
+ <rect width="100" height="100" class="light cell" x="250" y="150"/>
48
+ <rect width="100" height="100" class="dark cell" x="350" y="150"/>
49
+ <rect width="100" height="100" class="light cell" x="450" y="150"/>
50
+ <rect width="100" height="100" class="dark cell" x="550" y="150"/>
51
+ <rect width="100" height="100" class="light cell" x="650" y="150"/>
52
+ <rect width="100" height="100" class="dark cell" x="750" y="150"/>
53
+ <rect width="100" height="100" class="dark cell" x="50" y="250"/>
54
+ <rect width="100" height="100" class="light cell" x="150" y="250"/>
55
+ <rect width="100" height="100" class="dark cell" x="250" y="250"/>
56
+ <rect width="100" height="100" class="light cell" x="350" y="250"/>
57
+ <rect width="100" height="100" class="dark cell" x="450" y="250"/>
58
+ <rect width="100" height="100" class="light cell" x="550" y="250"/>
59
+ <rect width="100" height="100" class="dark cell" x="650" y="250"/>
60
+ <rect width="100" height="100" class="light cell" x="750" y="250"/>
61
+ <rect width="100" height="100" class="light cell" x="50" y="350"/>
62
+ <rect width="100" height="100" class="dark cell" x="150" y="350"/>
63
+ <rect width="100" height="100" class="light cell" x="250" y="350"/>
64
+ <rect width="100" height="100" class="dark cell" x="350" y="350"/>
65
+ <rect width="100" height="100" class="light cell" x="450" y="350"/>
66
+ <rect width="100" height="100" class="dark cell" x="550" y="350"/>
67
+ <rect width="100" height="100" class="light cell" x="650" y="350"/>
68
+ <rect width="100" height="100" class="dark cell" x="750" y="350"/>
69
+ <rect width="100" height="100" class="dark cell" x="50" y="450"/>
70
+ <rect width="100" height="100" class="light cell" x="150" y="450"/>
71
+ <rect width="100" height="100" class="dark cell" x="250" y="450"/>
72
+ <rect width="100" height="100" class="light cell" x="350" y="450"/>
73
+ <rect width="100" height="100" class="dark cell" x="450" y="450"/>
74
+ <rect width="100" height="100" class="light cell" x="550" y="450"/>
75
+ <rect width="100" height="100" class="dark cell" x="650" y="450"/>
76
+ <rect width="100" height="100" class="light cell" x="750" y="450"/>
77
+ <rect width="100" height="100" class="light cell" x="50" y="550"/>
78
+ <rect width="100" height="100" class="dark cell" x="150" y="550"/>
79
+ <rect width="100" height="100" class="light cell" x="250" y="550"/>
80
+ <rect width="100" height="100" class="dark cell" x="350" y="550"/>
81
+ <rect width="100" height="100" class="light cell" x="450" y="550"/>
82
+ <rect width="100" height="100" class="dark cell" x="550" y="550"/>
83
+ <rect width="100" height="100" class="light cell" x="650" y="550"/>
84
+ <rect width="100" height="100" class="dark cell" x="750" y="550"/>
85
+ <rect width="100" height="100" class="dark cell" x="50" y="650"/>
86
+ <rect width="100" height="100" class="light cell" x="150" y="650"/>
87
+ <rect width="100" height="100" class="dark cell" x="250" y="650"/>
88
+ <rect width="100" height="100" class="light cell" x="350" y="650"/>
89
+ <rect width="100" height="100" class="dark cell" x="450" y="650"/>
90
+ <rect width="100" height="100" class="light cell" x="550" y="650"/>
91
+ <rect width="100" height="100" class="dark cell" x="650" y="650"/>
92
+ <rect width="100" height="100" class="light cell" x="750" y="650"/>
93
+ <rect width="100" height="100" class="light cell" x="50" y="750"/>
94
+ <rect width="100" height="100" class="dark cell" x="150" y="750"/>
95
+ <rect width="100" height="100" class="light cell" x="250" y="750"/>
96
+ <rect width="100" height="100" class="dark cell" x="350" y="750"/>
97
+ <rect width="100" height="100" class="light cell" x="450" y="750"/>
98
+ <rect width="100" height="100" class="dark cell" x="550" y="750"/>
99
+ <rect width="100" height="100" class="light cell" x="650" y="750"/>
100
+ <rect width="100" height="100" class="dark cell" x="750" y="750"/>
101
+ <circle class="dark piece" cx="200" cy="100" r="40"/>
102
+ <circle class="dark piece" cx="400" cy="100" r="40"/>
103
+ <circle class="dark piece" cx="600" cy="100" r="40"/>
104
+ <circle class="dark piece" cx="800" cy="100" r="40"/>
105
+ <circle class="dark piece" cx="100" cy="200" r="40"/>
106
+ <circle class="dark piece" cx="300" cy="200" r="40"/>
107
+ <circle class="dark piece" cx="500" cy="200" r="40"/>
108
+ <circle class="dark piece" cx="700" cy="200" r="40"/>
109
+ <circle class="light piece" cx="200" cy="700" r="40"/>
110
+ <circle class="light piece" cx="400" cy="700" r="40"/>
111
+ <circle class="light piece" cx="600" cy="700" r="40"/>
112
+ <circle class="light piece" cx="800" cy="700" r="40"/>
113
+ <circle class="light piece" cx="100" cy="800" r="40"/>
114
+ <circle class="light piece" cx="300" cy="800" r="40"/>
115
+ <circle class="light piece" cx="500" cy="800" r="40"/>
116
+ <circle class="light piece" cx="700" cy="800" r="40"/>
117
+ </svg>
data/srv/clover.sevgi ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env -S ruby -S sevgi
2
+ # frozen_string_literal: true
3
+
4
+ CLOVER = <<~PATH
5
+ m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
6
+ PATH
7
+
8
+ CENTER = 13
9
+ SIZE = 26
10
+
11
+ SVG :minimal, width: SIZE, height: SIZE do
12
+ rect width: SIZE, height: SIZE, rx: 0.75, fill: "white"
13
+ defs { path id: "Clover", d: CLOVER, fill: "purple" }
14
+
15
+ 4.times do |quarter|
16
+ leaf = use href: "#Clover", x: CENTER, y: CENTER - 10
17
+ leaf.Rotate quarter * 90, CENTER, CENTER
18
+ end
19
+ end.Save
data/srv/clover.svg ADDED
@@ -0,0 +1,11 @@
1
+ <svg width="26" height="26">
2
+ <rect width="26" height="26" rx="0.75" fill="white"/>
3
+ <defs>
4
+ <path id="Clover" d="m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
5
+ " fill="purple"/>
6
+ </defs>
7
+ <use href="#Clover" x="13" y="3"/>
8
+ <use href="#Clover" x="13" y="3" transform="rotate(90, 13, 13)"/>
9
+ <use href="#Clover" x="13" y="3" transform="rotate(180, 13, 13)"/>
10
+ <use href="#Clover" x="13" y="3" transform="rotate(270, 13, 13)"/>
11
+ </svg>
data/srv/clover.yml ADDED
@@ -0,0 +1,3 @@
1
+ dark:
2
+ purple: "#e5c39c"
3
+ white: "#222222"
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env -S ruby -S sevgi
2
+ # frozen_string_literal: true
3
+
4
+ COLS = 15
5
+ MULTIPLE = 5
6
+ ROWS = 10
7
+ SLANT = 55
8
+ UNIT = 6
9
+
10
+ canvas = SVG.Canvas width: COLS * UNIT, height: ROWS * UNIT
11
+ grid = Grid canvas, unit: UNIT, multiple: MULTIPLE
12
+
13
+ module Guidesheet
14
+ extend SVG::Module
15
+
16
+ FRAME = 0.6
17
+
18
+ STYLE = {
19
+ ".angle" => { fill: "none", stroke: "green", "stroke-width": 0.12 },
20
+ ".frame" => { fill: "none", stroke: "blue", "stroke-width": FRAME },
21
+ ".major" => { fill: "none", stroke: "blue", "stroke-width": 0.4 },
22
+ ".minor" => { fill: "none", stroke: "magenta", "stroke-width": 0.12 }
23
+ }.freeze
24
+
25
+ base { css STYLE }
26
+
27
+ def call(grid)
28
+ layer id: "Slants" do
29
+ TileY "slant-row", n: grid.y.n, d: grid.y.u do
30
+ Hatch grid.rowbox, angle: -SLANT, step: grid.x.su, class: %w[angle slant]
31
+ end
32
+ end
33
+
34
+ layer id: "Squares" do
35
+ Draw grid.x.minor.lines, class: %w[rule minor horizontal]
36
+ Draw grid.y.minor.lines, class: %w[rule minor vertical]
37
+ Draw grid.x.major.lines, class: %w[rule major horizontal]
38
+ Draw grid.y.major.lines, class: %w[rule major vertical]
39
+ end
40
+
41
+ rect x: FRAME / 2, y: FRAME / 2,
42
+ width: grid.width - FRAME, height: grid.height - FRAME,
43
+ class: %w[frame rule]
44
+ end
45
+ end
46
+
47
+ SVG :inkscape, canvas, "shape-rendering": "geometricPrecision" do
48
+ rect width: "100%", height: "100%", fill: "white"
49
+ Layer! Guidesheet, grid, attributes: { id: "Guides" }
50
+ end.Save
@@ -0,0 +1,99 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ xmlns:_="http://sevgi.roktas.dev"
5
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
6
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
7
+ shape-rendering="geometricPrecision"
8
+ width="90.0mm"
9
+ height="60.0mm"
10
+ viewBox="0 0 90 60"
11
+ >
12
+ <rect width="100%" height="100%" fill="white"/>
13
+ <g id="Guides" inkscape:groupmode="layer" sodipodi:insensitive="true">
14
+ <style type="text/css">
15
+ <![CDATA[
16
+ .angle {
17
+ fill: none;
18
+ stroke: green;
19
+ stroke-width: 0.12;
20
+ }
21
+ .frame {
22
+ fill: none;
23
+ stroke: blue;
24
+ stroke-width: 0.6;
25
+ }
26
+ .major {
27
+ fill: none;
28
+ stroke: blue;
29
+ stroke-width: 0.4;
30
+ }
31
+ .minor {
32
+ fill: none;
33
+ stroke: magenta;
34
+ stroke-width: 0.12;
35
+ }
36
+ ]]>
37
+ </style>
38
+ <g id="Slants" inkscape:groupmode="layer">
39
+ <defs>
40
+ <g id="slant-row">
41
+ <path d="M 90 28.376891 L 88.863487 30" class="angle slant"/>
42
+ <path d="M 90 17.91621 L 81.538839 30" class="angle slant"/>
43
+ <path d="M 90 7.455529 L 74.214192 30" class="angle slant"/>
44
+ <path d="M 87.89577 0 L 66.889544 30" class="angle slant"/>
45
+ <path d="M 80.571123 0 L 59.564897 30" class="angle slant"/>
46
+ <path d="M 73.246475 0 L 52.240249 30" class="angle slant"/>
47
+ <path d="M 65.921828 0 L 44.915602 30" class="angle slant"/>
48
+ <path d="M 58.59718 0 L 37.590954 30" class="angle slant"/>
49
+ <path d="M 51.272533 0 L 30.266307 30" class="angle slant"/>
50
+ <path d="M 43.947885 0 L 22.941659 30" class="angle slant"/>
51
+ <path d="M 36.623238 0 L 15.617012 30" class="angle slant"/>
52
+ <path d="M 29.29859 0 L 8.292364 30" class="angle slant"/>
53
+ <path d="M 21.973943 0 L 0.967716 30" class="angle slant"/>
54
+ <path d="M 14.649295 0 L 0 20.921362" class="angle slant"/>
55
+ <path d="M 7.324648 0 L 0 10.460681" class="angle slant"/>
56
+ </g>
57
+ </defs>
58
+ <use id="slant-row-1" href="#slant-row" class="tile-row-1 tile-row-first"/>
59
+ <use id="slant-row-2" href="#slant-row" class="tile-row-2 tile-row-last" y="30"/>
60
+ </g>
61
+ <g id="Squares" inkscape:groupmode="layer">
62
+ <path d="M 0 0 L 90 0" class="rule minor horizontal"/>
63
+ <path d="M 0 6 L 90 6" class="rule minor horizontal"/>
64
+ <path d="M 0 12 L 90 12" class="rule minor horizontal"/>
65
+ <path d="M 0 18 L 90 18" class="rule minor horizontal"/>
66
+ <path d="M 0 24 L 90 24" class="rule minor horizontal"/>
67
+ <path d="M 0 30 L 90 30" class="rule minor horizontal"/>
68
+ <path d="M 0 36 L 90 36" class="rule minor horizontal"/>
69
+ <path d="M 0 42 L 90 42" class="rule minor horizontal"/>
70
+ <path d="M 0 48 L 90 48" class="rule minor horizontal"/>
71
+ <path d="M 0 54 L 90 54" class="rule minor horizontal"/>
72
+ <path d="M 0 60 L 90 60" class="rule minor horizontal"/>
73
+ <path d="M 0 0 L 0 60" class="rule minor vertical"/>
74
+ <path d="M 6 0 L 6 60" class="rule minor vertical"/>
75
+ <path d="M 12 0 L 12 60" class="rule minor vertical"/>
76
+ <path d="M 18 0 L 18 60" class="rule minor vertical"/>
77
+ <path d="M 24 0 L 24 60" class="rule minor vertical"/>
78
+ <path d="M 30 0 L 30 60" class="rule minor vertical"/>
79
+ <path d="M 36 0 L 36 60" class="rule minor vertical"/>
80
+ <path d="M 42 0 L 42 60" class="rule minor vertical"/>
81
+ <path d="M 48 0 L 48 60" class="rule minor vertical"/>
82
+ <path d="M 54 0 L 54 60" class="rule minor vertical"/>
83
+ <path d="M 60 0 L 60 60" class="rule minor vertical"/>
84
+ <path d="M 66 0 L 66 60" class="rule minor vertical"/>
85
+ <path d="M 72 0 L 72 60" class="rule minor vertical"/>
86
+ <path d="M 78 0 L 78 60" class="rule minor vertical"/>
87
+ <path d="M 84 0 L 84 60" class="rule minor vertical"/>
88
+ <path d="M 90 0 L 90 60" class="rule minor vertical"/>
89
+ <path d="M 0 0 L 90 0" class="rule major horizontal"/>
90
+ <path d="M 0 30 L 90 30" class="rule major horizontal"/>
91
+ <path d="M 0 60 L 90 60" class="rule major horizontal"/>
92
+ <path d="M 0 0 L 0 60" class="rule major vertical"/>
93
+ <path d="M 30 0 L 30 60" class="rule major vertical"/>
94
+ <path d="M 60 0 L 60 60" class="rule major vertical"/>
95
+ <path d="M 90 0 L 90 60" class="rule major vertical"/>
96
+ </g>
97
+ <rect x="0.3" y="0.3" width="89.4" height="59.4" class="frame rule"/>
98
+ </g>
99
+ </svg>
@@ -0,0 +1,5 @@
1
+ dark:
2
+ blue: "#60a5fa"
3
+ green: "#4ade80"
4
+ magenta: "#f472b6"
5
+ white: "#222222"
@@ -1,27 +1,25 @@
1
1
  #!/usr/bin/env -S ruby -S sevgi
2
2
  # frozen_string_literal: true
3
3
 
4
- GEAR_STYLE = {
5
- fill: "#333",
4
+ STYLE = {
5
+ fill: "purple",
6
+ mask: "url(#hole)",
6
7
  stroke: "none"
7
8
  }.freeze
8
9
 
9
10
  SVG :minimal, width: 100, height: 100, viewBox: "0 0 100 100" do
10
- rect x: 0, y: 0, width: 100, height: 100, fill: "lightgreen"
11
-
12
11
  mask id: "hole",
13
12
  maskUnits: "userSpaceOnUse",
14
13
  maskContentUnits: "userSpaceOnUse",
15
14
  x: 0, y: 0, width: 100, height: 100 do
16
- rect x: 0, y: 0, width: 100, height: 100, fill: "white"
15
+ square length: 100, fill: "white"
17
16
  circle cx: 50, cy: 50, r: 15, fill: "black"
18
17
  end
19
18
 
20
- circle cx: 50, cy: 50, r: 30, mask: "url(#hole)", **GEAR_STYLE
19
+ circle cx: 50, cy: 50, r: 30, **STYLE
21
20
 
22
21
  [0, 45, 90, 135].each do |angle|
23
- rect x: 45, y: 10, width: 10, height: 80,
24
- mask: "url(#hole)", transform: "rotate(#{angle} 50 50)",
25
- **GEAR_STYLE
22
+ tooth = rect x: 45, y: 10, width: 10, height: 80, **STYLE
23
+ tooth.Rotate angle, 50, 50
26
24
  end
27
25
  end.Save
data/srv/gear.svg ADDED
@@ -0,0 +1,11 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100">
2
+ <mask id="hole" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
3
+ <rect width="100" height="100" fill="white"/>
4
+ <circle cx="50" cy="50" r="15" fill="black"/>
5
+ </mask>
6
+ <circle cx="50" cy="50" r="30" fill="purple" mask="url(#hole)" stroke="none"/>
7
+ <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none"/>
8
+ <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(45, 50, 50)"/>
9
+ <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(90, 50, 50)"/>
10
+ <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(135, 50, 50)"/>
11
+ </svg>
data/srv/gear.yml ADDED
@@ -0,0 +1,2 @@
1
+ dark:
2
+ purple: "#e5c39c"
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env -S ruby -S sevgi
2
2
  # frozen_string_literal: true
3
3
 
4
- CELL_SIZE = 20
4
+ SIZE = 20
5
5
  COLORS = %w[#FF6961 #77DD77 #FFD700].freeze
6
- COLS = 8
7
- ROWS = 3
6
+ COLS = 9
7
+ ROWS = 4
8
8
 
9
9
  SVG :minimal,
10
- width: COLS * CELL_SIZE,
11
- height: ROWS * CELL_SIZE,
12
- viewBox: "0 0 #{COLS * CELL_SIZE} #{ROWS * CELL_SIZE}" do
10
+ width: COLS * SIZE,
11
+ height: ROWS * SIZE,
12
+ viewBox: "0 0 #{COLS * SIZE} #{ROWS * SIZE}" do
13
13
  css ".cell" => { stroke: "white" }
14
14
 
15
15
  COLS.times do |col|
16
16
  ROWS.times do |row|
17
17
  rect class: "cell",
18
- x: col * CELL_SIZE, y: row * CELL_SIZE,
19
- width: CELL_SIZE, height: CELL_SIZE,
20
- rx: (CELL_SIZE * 0.1).round,
18
+ x: col * SIZE, y: row * SIZE,
19
+ width: SIZE, height: SIZE,
20
+ rx: (SIZE * 0.1).round,
21
21
  fill: COLORS[(col + row) % COLORS.length]
22
22
  end
23
23
  end