jekyll-og-image 1.0.4 → 1.1.0

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: eeccdc0ae99d37ef260733506fbad4ebf5c60f925cdb2514acb91dcb346d1673
4
- data.tar.gz: b8b291f97eddc6a0be9dc080d2f999be0bb027224bf5bf2953f941a89491b63a
3
+ metadata.gz: b61ed8f290ff7d539d5797f7e176821c7467cf1e5c2405e54960909663271ef5
4
+ data.tar.gz: 300123301cf7fc2dc403cc8254181772983f036cb8a06e7e23374fda7861d62c
5
5
  SHA512:
6
- metadata.gz: b15a8205247be628cf982c6efb8f9127cd0ba2eb1d2421e7f7f702802e4960a14317612cfffa010d41972e1b2ba2671eae82f19092552f93b71003995096a21a
7
- data.tar.gz: 47b2a2845a7e6bd2a25ef2f249af3fcd1e78adf9179366680e173fc0228aaa5e564be2f5935a0752b3c2c5dd8061b6b17959d7f592fa50ca08d54006baca272c
6
+ metadata.gz: 6a29185631359c3b89faddc2b54187bbfd663b762c6533eb5909270e78320c04f313193ddd4c3e33652946865ef486b7bfaefbb941637a965d8fc02f8f6560b4
7
+ data.tar.gz: 83fa74112ac6747aa11a402913b6cd736c828f318b8a08ddf342d7aac8212a367b9c7028378fe681dbb8725dd44a6fcfe3ec379beb9e999e9e105cc6d52adb61
data/.rspec_status CHANGED
@@ -1,5 +1,5 @@
1
1
  example_id | status | run_time |
2
2
  ----------------------------------- | ------ | --------------- |
3
- ./spec/jekyll_og_image_spec.rb[1:1] | passed | 0.01883 seconds |
4
- ./spec/jekyll_og_image_spec.rb[1:2] | passed | 0.31382 seconds |
5
- ./spec/jekyll_og_image_spec.rb[1:3] | passed | 0.07861 seconds |
3
+ ./spec/jekyll_og_image_spec.rb[1:1] | passed | 0.01708 seconds |
4
+ ./spec/jekyll_og_image_spec.rb[1:2] | passed | 0.27293 seconds |
5
+ ./spec/jekyll_og_image_spec.rb[1:3] | passed | 0.06846 seconds |
data/README.md CHANGED
@@ -61,6 +61,31 @@ og_image:
61
61
 
62
62
  ![Example 1](examples/1.png)
63
63
 
64
+ ### Background Color and Text Colors
65
+
66
+ ```yaml
67
+ og_image:
68
+ output_dir: "/assets/og"
69
+ image: "/assets/images/igor.jpeg"
70
+ canvas:
71
+ background_color: "#F9E065"
72
+ header:
73
+ font_family: "Roboto, Bold"
74
+ color: "#333333"
75
+ content:
76
+ font_family: "Roboto, Regular"
77
+ color: "#333333"
78
+ force: false
79
+ domain: "igor.works"
80
+ border_bottom:
81
+ width: 20
82
+ fill:
83
+ - "#002B7F"
84
+ - "#FCD116"
85
+ - "#CE1126"
86
+ ```
87
+
88
+ ![Example 3](examples/3.png)
64
89
 
65
90
 
66
91
  ## Contributing
data/examples/1.png CHANGED
Binary file
data/examples/2.png CHANGED
Binary file
data/examples/3.png ADDED
Binary file
@@ -5,6 +5,18 @@ require "anyway_config"
5
5
  class JekyllOgImage::Config < Anyway::Config
6
6
  attr_config output_dir: "assets/images/og"
7
7
  attr_config force: false
8
+ attr_config verbose: false
9
+ attr_config canvas: {
10
+ background_color: "#FFFFFF"
11
+ }
12
+ attr_config header: {
13
+ font_family: "Helvetica, Bold",
14
+ color: "#2f313d"
15
+ }
16
+ attr_config content: {
17
+ font_family: "Helvetica, Regular",
18
+ color: "#535358"
19
+ }
8
20
  attr_config :image
9
21
  attr_config :domain
10
22
  attr_config border_bottom: {
@@ -12,6 +24,20 @@ class JekyllOgImage::Config < Anyway::Config
12
24
  fill: [ "#211F1F", "#F4CBB2", "#AD5C51", "#9CDAF1", "#7DBBE6" ]
13
25
  }
14
26
 
27
+ coerce_types canvas: {
28
+ background_color: { type: :string }
29
+ }
30
+
31
+ coerce_types header: {
32
+ font_family: { type: :string },
33
+ color: { type: :string }
34
+ }
35
+
36
+ coerce_types content: {
37
+ font_family: { type: :string },
38
+ color: { type: :string }
39
+ }
40
+
15
41
  coerce_types image: { type: :string }
16
42
 
17
43
  coerce_types border_bottom: {
@@ -21,4 +21,20 @@ class JekyllOgImage::Element::Base
21
21
  raise ArgumentError, "Invalid gravity: #{@gravity.inspect}"
22
22
  end
23
23
  end
24
+
25
+ def composite_with_gravity(canvas, overlay, x, y)
26
+ if gravity_nw?
27
+ canvas.composite(overlay, :over, x: [ x ], y: [ y ]).flatten
28
+ elsif gravity_ne?
29
+ x = canvas.width - overlay.width - x
30
+ canvas.composite(overlay, :over, x: [ x ], y: [ y ]).flatten
31
+ elsif gravity_sw?
32
+ y = canvas.height - overlay.height - y
33
+ canvas.composite(overlay, :over, x: [ x ], y: [ y ]).flatten
34
+ elsif gravity_se?
35
+ x = canvas.width - overlay.width - x
36
+ y = canvas.height - overlay.height - y
37
+ canvas.composite(overlay, :over, x: [ x ], y: [ y ]).flatten
38
+ end
39
+ end
24
40
  end
@@ -4,43 +4,57 @@ class JekyllOgImage::Element::Border < JekyllOgImage::Element::Base
4
4
  class Part < Data.define(:rgb, :width, :height, :offset)
5
5
  end
6
6
 
7
- def initialize(canvas, size, position: :bottom, fill: "#000000")
8
- @canvas = canvas
7
+ def initialize(size, position: :bottom, fill: "#000000")
9
8
  @size = size
10
9
  @position = position
11
10
  @fill = fill
12
11
 
13
12
  validate_position!
13
+ end
14
14
 
15
- @border = Vips::Image.black(*dimensions)
15
+ def apply_to(canvas, &block)
16
+ border = Vips::Image.black(*dimensions(canvas))
16
17
 
17
- parts.each.with_index do |part, index|
18
- border = Vips::Image.black(part.width, part.height).ifthenelse([ 0, 0, 0 ], part.rgb)
18
+ parts(canvas).each.with_index do |part, index|
19
+ image = Vips::Image.black(part.width, part.height).ifthenelse([ 0, 0, 0 ], part.rgb)
19
20
 
20
21
  if vertical?
21
- @border = @border.composite(border, :over, x: [ 0 ], y: [ part.offset ]).flatten
22
+ border = border.composite(image, :over, x: [ 0 ], y: [ part.offset ]).flatten
22
23
  else
23
- @border = @border.composite(border, :over, x: [ part.offset ], y: [ 0 ]).flatten
24
+ border = border.composite(image, :over, x: [ part.offset ], y: [ 0 ]).flatten
24
25
  end
25
26
  end
26
- end
27
27
 
28
- def apply(&block)
29
- result = block.call(@canvas, @border) if block_given?
28
+ result = block.call(canvas, border) if block_given?
29
+
30
30
  x, y = result ? [ result.fetch(:x, 0), result.fetch(:y, 0) ] : [ 0, 0 ]
31
31
 
32
32
  if vertical?
33
- x = @position == :left ? x : @canvas.width - @size - x
34
- @canvas.composite(@border, :over, x: [ x ], y: [ 0 ]).flatten
33
+ x = @position == :left ? x : canvas.width - @size - x
34
+ canvas.composite(border, :over, x: [ x ], y: [ 0 ]).flatten
35
35
  else
36
- y = @position == :top ? y : @canvas.height - @size - y
37
- @canvas.composite(@border, :over, x: [ 0 ], y: [ y ]).flatten
36
+ y = @position == :top ? y : canvas.height - @size - y
37
+ canvas.composite(border, :over, x: [ 0 ], y: [ y ]).flatten
38
38
  end
39
39
  end
40
40
 
41
- def parts
41
+ private
42
+
43
+ def hex_to_rgb(hex)
44
+ hex.match(/#(..)(..)(..)/)[1..3].map { |x| x.hex }
45
+ end
46
+
47
+ def dimensions(canvas)
48
+ if vertical?
49
+ [ @size, canvas.height ]
50
+ else
51
+ [ canvas.width, @size ]
52
+ end
53
+ end
54
+
55
+ def parts(canvas)
42
56
  if @fill.is_a?(Array)
43
- width, height = vertical? ? [ @size, (@canvas.height / @fill.size) ] : [ (@canvas.width / @fill.size), @size ]
57
+ width, height = vertical? ? [ @size, (canvas.height / @fill.size) ] : [ (canvas.width / @fill.size), @size ]
44
58
 
45
59
  @fill.map.with_index do |item, index|
46
60
  Part.new(
@@ -51,26 +65,12 @@ class JekyllOgImage::Element::Border < JekyllOgImage::Element::Base
51
65
  )
52
66
  end
53
67
  else
54
- length = vertical? ? @canvas.height : @canvas.width
68
+ length = vertical? ? canvas.height : canvas.width
55
69
 
56
70
  [ Part.new(rgb: hex_to_rgb(@fill), length: length, offset: 0) ]
57
71
  end
58
72
  end
59
73
 
60
- private
61
-
62
- def hex_to_rgb(hex)
63
- hex.match(/#(..)(..)(..)/)[1..3].map { |x| x.hex }
64
- end
65
-
66
- def dimensions
67
- if vertical?
68
- [ @size, @canvas.height ]
69
- else
70
- [ @canvas.width, @size ]
71
- end
72
- end
73
-
74
74
  def vertical?
75
75
  @position == :left || @position == :right
76
76
  end
@@ -8,31 +8,22 @@ class JekyllOgImage::Element::Canvas < JekyllOgImage::Element::Base
8
8
  end
9
9
 
10
10
  def image(source, **opts, &block)
11
- image = JekyllOgImage::Element::Image.new(
12
- @canvas, source, **opts
13
- )
14
-
15
- @canvas = image.apply(&block)
11
+ image = JekyllOgImage::Element::Image.new(source, **opts)
12
+ @canvas = image.apply_to(@canvas, &block)
16
13
 
17
14
  self
18
15
  end
19
16
 
20
17
  def text(message, **opts, &block)
21
- text = JekyllOgImage::Element::Text.new(
22
- @canvas, message, **opts
23
- )
24
-
25
- @canvas = text.apply(&block)
18
+ text = JekyllOgImage::Element::Text.new(message, **opts)
19
+ @canvas = text.apply_to(@canvas, &block)
26
20
 
27
21
  self
28
22
  end
29
23
 
30
- def border(width, position: :bottom, fill: "#000000")
31
- @canvas = JekyllOgImage::Element::Border.new(
32
- @canvas, width,
33
- position: position,
34
- fill: fill
35
- ).apply
24
+ def border(width, **opts, &block)
25
+ border = JekyllOgImage::Element::Border.new(width, **opts)
26
+ @canvas = border.apply_to(@canvas, &block)
36
27
 
37
28
  self
38
29
  end
@@ -1,19 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JekyllOgImage::Element::Image < JekyllOgImage::Element::Base
4
- def initialize(canvas, source, gravity: :nw, width:, height:)
5
- @canvas = canvas
4
+ def initialize(source, gravity: :nw, width:, height:, radius:)
6
5
  @gravity = gravity
7
6
  @source = source
8
7
  @width = width
9
8
  @height = height
9
+ @radius = radius
10
10
 
11
11
  validate_gravity!
12
12
  end
13
13
 
14
- def apply(&block)
14
+ def apply_to(canvas, &block)
15
15
  image = Vips::Image.new_from_buffer(@source, "")
16
- result = block.call(@canvas, image) if block_given?
16
+ image = round_corners(image) if @radius
17
+
18
+ result = block.call(canvas, image) if block_given?
17
19
 
18
20
  if @width && @height
19
21
  ratio = calculate_ratio(image, @width, @height, :min)
@@ -22,19 +24,7 @@ class JekyllOgImage::Element::Image < JekyllOgImage::Element::Base
22
24
 
23
25
  x, y = result ? [ result.fetch(:x, 0), result.fetch(:y, 0) ] : [ 0, 0 ]
24
26
 
25
- if gravity_nw?
26
- @canvas.composite(image, :over, x: [ x ], y: [ y ]).flatten
27
- elsif gravity_ne?
28
- x = @canvas.width - image.width - x
29
- @canvas.composite(image, :over, x: [ x ], y: [ y ]).flatten
30
- elsif gravity_sw?
31
- y = @canvas.height - image.height - y
32
- @canvas.composite(image, :over, x: [ x ], y: [ y ]).flatten
33
- elsif gravity_se?
34
- x = @canvas.width - image.width - x
35
- y = @canvas.height - image.height - y
36
- @canvas.composite(image, :over, x: [ x ], y: [ y ]).flatten
37
- end
27
+ composite_with_gravity(canvas, image, x, y)
38
28
  end
39
29
 
40
30
  private
@@ -45,6 +35,25 @@ class JekyllOgImage::Element::Image < JekyllOgImage::Element::Base
45
35
  end
46
36
  end
47
37
 
38
+ def round_corners(image)
39
+ mask = %(
40
+ <svg viewBox="0 0 #{image.width} #{image.height}">
41
+ <rect
42
+ rx="#{@radius}"
43
+ ry="#{@radius}"
44
+ x="0"
45
+ y="0"
46
+ width="#{image.width}"
47
+ height="#{image.height}"
48
+ fill="#fff"
49
+ />
50
+ </svg>
51
+ )
52
+
53
+ mask = Vips::Image.new_from_buffer(mask, "")
54
+ image.bandjoin mask[3]
55
+ end
56
+
48
57
  def calculate_ratio(image, width, height, mode)
49
58
  if mode == :min
50
59
  [ width.to_f / image.width, height.to_f / image.height ].min
@@ -1,43 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JekyllOgImage::Element::Text < JekyllOgImage::Element::Base
4
- def initialize(canvas, message, gravity: :nw, width: nil, dpi: nil, color: "#000000", font: nil)
5
- @canvas = canvas
4
+ def initialize(message, gravity: :nw, width: nil, dpi: nil, color: "#000000", font: nil)
5
+ @message = message
6
6
  @gravity = gravity
7
+ @width = width
8
+ @dpi = dpi
9
+ @color = color
10
+ @font = font
7
11
 
8
12
  validate_gravity!
13
+ end
9
14
 
10
- text = Vips::Image.text(message,
11
- font: font,
12
- width: width,
13
- dpi: dpi,
15
+ def apply_to(canvas, &block)
16
+ text = Vips::Image.text(@message,
17
+ font: @font,
18
+ width: @width,
19
+ dpi: @dpi,
14
20
  wrap: :word,
15
21
  align: :low
16
22
  )
17
23
 
18
- @text = text
19
- .new_from_image(hex_to_rgb(color))
24
+ text = text
25
+ .new_from_image(hex_to_rgb(@color))
20
26
  .copy(interpretation: :srgb)
21
27
  .bandjoin(text)
22
- end
23
28
 
24
- def apply(&block)
25
- result = block.call(@canvas, @text) if block_given?
29
+ result = block.call(canvas, text) if block_given?
30
+
26
31
  x, y = result ? [ result.fetch(:x, 0), result.fetch(:y, 0) ] : [ 0, 0 ]
27
32
 
28
- if gravity_nw?
29
- @canvas.composite(@text, :over, x: [ x ], y: [ y ]).flatten
30
- elsif gravity_ne?
31
- x = @canvas.width - @text.width - x
32
- @canvas.composite(@text, :over, x: [ x ], y: [ y ]).flatten
33
- elsif gravity_sw?
34
- y = @canvas.height - @text.height - y
35
- @canvas.composite(@text, :over, x: [ x ], y: [ y ]).flatten
36
- elsif gravity_se?
37
- x = @canvas.width - @text.width - x
38
- y = @canvas.height - @text.height - y
39
- @canvas.composite(@text, :over, x: [ x ], y: [ y ]).flatten
40
- end
33
+ composite_with_gravity(canvas, text, x, y)
41
34
  end
42
35
 
43
36
  private
@@ -15,10 +15,10 @@ class JekyllOgImage::Generator < Jekyll::Generator
15
15
  path = File.join(site.config["source"], base_path, "#{post.data['slug']}.png")
16
16
 
17
17
  if !File.exist?(path) || JekyllOgImage.config.force?
18
- Jekyll.logger.info "Jekyll Og Image:", "Generating image #{path}"
18
+ Jekyll.logger.info "Jekyll Og Image:", "Generating image #{path}" if JekyllOgImage.config.verbose?
19
19
  generate_image_for_post(site, post, path)
20
20
  else
21
- Jekyll.logger.info "Jekyll Og Image:", "Skipping image generation #{path} as it already exists."
21
+ Jekyll.logger.info "Jekyll Og Image:", "Skipping image generation #{path} as it already exists." if JekyllOgImage.config.verbose?
22
22
  end
23
23
 
24
24
  post.data["image"] ||= {
@@ -35,7 +35,9 @@ class JekyllOgImage::Generator < Jekyll::Generator
35
35
  def generate_image_for_post(site, post, path)
36
36
  date = post.date.strftime("%B %d, %Y")
37
37
 
38
- canvas = JekyllOgImage::Element::Canvas.new(1200, 600)
38
+ canvas = JekyllOgImage::Element::Canvas.new(1200, 600,
39
+ color: JekyllOgImage.config.canvas["background_color"]
40
+ )
39
41
  .border(JekyllOgImage.config.border_bottom["width"],
40
42
  position: :bottom,
41
43
  fill: JekyllOgImage.config.border_bottom["fill"]
@@ -46,22 +48,23 @@ class JekyllOgImage::Generator < Jekyll::Generator
46
48
  File.read(File.join(site.config["source"], JekyllOgImage.config.image)),
47
49
  gravity: :ne,
48
50
  width: 150,
49
- height: 150
51
+ height: 150,
52
+ radius: 50
50
53
  ) { |_canvas, _text| { x: 80, y: 100 } }
51
54
  end
52
55
 
53
56
  canvas = canvas.text(post.data["title"],
54
57
  width: JekyllOgImage.config.image ? 870 : 1040,
55
- color: "#2f313d",
58
+ color: JekyllOgImage.config.header["color"],
56
59
  dpi: 400,
57
- font: "Helvetica, Bold"
60
+ font: JekyllOgImage.config.header["font_family"]
58
61
  ) { |_canvas, _text| { x: 80, y: 100 } }
59
62
 
60
63
  canvas = canvas.text(date,
61
64
  gravity: :sw,
62
- color: "#535358",
65
+ color: JekyllOgImage.config.content["color"],
63
66
  dpi: 150,
64
- font: "Helvetica, Regular"
67
+ font: JekyllOgImage.config.content["font_family"]
65
68
  ) { |_canvas, _text| { x: 80, y: post.data["tags"].any? ? 150 : 100 } }
66
69
 
67
70
  if post.data["tags"].any?
@@ -69,14 +72,19 @@ class JekyllOgImage::Generator < Jekyll::Generator
69
72
 
70
73
  canvas = canvas.text(tags,
71
74
  gravity: :sw,
72
- color: "#535358",
75
+ color: JekyllOgImage.config.content["color"],
73
76
  dpi: 150,
74
- font: "Helvetica, Regular"
77
+ font: JekyllOgImage.config.content["font_family"]
75
78
  ) { |_canvas, _text| { x: 80, y: 100 } }
76
79
  end
77
80
 
78
81
  if JekyllOgImage.config.domain
79
- canvas = canvas.text(JekyllOgImage.config.domain, gravity: :se, color: "#535358", dpi: 150, font: "Helvetica, Regular") do |_canvas, _text|
82
+ canvas = canvas.text(JekyllOgImage.config.domain,
83
+ gravity: :se,
84
+ color: JekyllOgImage.config.content["color"],
85
+ dpi: 150,
86
+ font: JekyllOgImage.config.content["font_family"]
87
+ ) do |_canvas, _text|
80
88
  {
81
89
  x: 80,
82
90
  y: post.data["tags"].any? ? 150 : 100
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllOgImage
4
- VERSION = "1.0.4"
4
+ VERSION = "1.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-og-image
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Alexandrov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-05 00:00:00.000000000 Z
11
+ date: 2024-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll-seo-tag
@@ -86,7 +86,7 @@ dependencies:
86
86
  - - "<"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '5.0'
89
- description:
89
+ description:
90
90
  email:
91
91
  - igor.alexandrov@gmail.com
92
92
  executables: []
@@ -102,7 +102,7 @@ files:
102
102
  - Rakefile
103
103
  - examples/1.png
104
104
  - examples/2.png
105
- - jekyll-og-image.gemspec
105
+ - examples/3.png
106
106
  - lib/jekyll-og-image.rb
107
107
  - lib/jekyll_og_image.rb
108
108
  - lib/jekyll_og_image/config.rb
@@ -118,7 +118,7 @@ licenses:
118
118
  - MIT
119
119
  metadata:
120
120
  homepage_uri: https://github.com/igor-alexandrov/jekyll-og-image
121
- post_install_message:
121
+ post_install_message:
122
122
  rdoc_options: []
123
123
  require_paths:
124
124
  - lib
@@ -133,8 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
133
  - !ruby/object:Gem::Version
134
134
  version: '0'
135
135
  requirements: []
136
- rubygems_version: 3.5.4
137
- signing_key:
136
+ rubygems_version: 3.5.3
137
+ signing_key:
138
138
  specification_version: 4
139
139
  summary: Jekyll plugin to generate GitHub-style open graph images
140
140
  test_files: []
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/jekyll_og_image/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "jekyll-og-image"
7
- spec.version = JekyllOgImage::VERSION
8
- spec.authors = [ "Igor Alexandrov" ]
9
- spec.email = [ "igor.alexandrov@gmail.com" ]
10
-
11
- spec.summary = "Jekyll plugin to generate GitHub-style open graph images"
12
- spec.homepage = "https://github.com/igor-alexandrov/jekyll-og-image"
13
- spec.license = "MIT"
14
- spec.required_ruby_version = ">= 3.2.0"
15
-
16
- spec.metadata["homepage_uri"] = spec.homepage
17
-
18
- # Specify which files should be added to the gem when it is released.
19
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
- spec.files = Dir.chdir(__dir__) do
21
- `git ls-files -z`.split("\x0").reject do |f|
22
- (File.expand_path(f) == __FILE__) ||
23
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
24
- end
25
- end
26
-
27
- spec.require_paths = [ "lib" ]
28
-
29
- spec.add_dependency "jekyll-seo-tag", "~> 2.8"
30
- spec.add_dependency "zeitwerk", "~> 2.6"
31
- spec.add_dependency "anyway_config", "~> 2.6"
32
- spec.add_dependency "ruby-vips", "~> 2.2.0"
33
- spec.add_runtime_dependency "jekyll", ">= 3.4", "< 5.0"
34
- end