svgeez 2.0.0 → 4.0.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
- SHA1:
3
- metadata.gz: ffc434b8172b66099c912055ef13b35c80e77c81
4
- data.tar.gz: 8fcc4b68c1524106727b9763eb72c857ede85571
2
+ SHA256:
3
+ metadata.gz: ca924e5f0fad11f4fdecab5e808ac801088f2f3a2f5d5399d1dd896e9d833f87
4
+ data.tar.gz: c9983ad74b3c812fe5b47cb9a1b5de73bf4bea64a8fcab6f53cd38791c9795c3
5
5
  SHA512:
6
- metadata.gz: b50e59f7247e21a0312e82dd6382b7eb0bd452825007569173c6d68826a4cf6bf06185222c63c66793c07a12fc2ffbf605e3d15158be13e0ee54fe48f7f66aaf
7
- data.tar.gz: a80f431e5289595e059dd8e11a7cd73508d204b45f1513690911301ac24494157825ffea391fd3b6c0a359aabaf119d937f0f6aa40343280fb2a550a7c2ec49d
6
+ metadata.gz: 845e9150fe2d51c6431ad1a9659a9ef90383675f11cfe2f1245568f271f8588402b112183c88f56e95b2e0c9342956b42ac92f1ead7e1993177cb143039279e5
7
+ data.tar.gz: 21bc1821b63b4e3ed9d4b53c88e6d3e8db2dec382a3f3c2fd73bd1f47c5fd95ff5fce8ecd8981bab85baf5c596ba122a328b06b121f103885b4879285aa7e218
@@ -0,0 +1,47 @@
1
+ version: 2.1
2
+
3
+ orbs:
4
+ ruby: circleci/ruby@1.1.2
5
+
6
+ jobs:
7
+ test:
8
+ parameters:
9
+ version:
10
+ type: string
11
+ executor:
12
+ name: ruby/default
13
+ tag: << parameters.version >>
14
+ steps:
15
+ - checkout
16
+ - run:
17
+ name: Generate Gemfile.lock
18
+ command: bundle lock
19
+ - ruby/install-deps
20
+ - run:
21
+ name: Install SVGO
22
+ command: sudo npm install -g svgo@1.3.2
23
+ - run:
24
+ name: Install CodeClimate test reporter
25
+ command: |
26
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
27
+ chmod +x ./cc-test-reporter
28
+ ./cc-test-reporter before-build
29
+ - run:
30
+ name: Run CI script
31
+ command: bin/ci
32
+ - run:
33
+ name: Upload coverage report to CodeClimate
34
+ command: ./cc-test-reporter after-build
35
+
36
+ workflows:
37
+ version: 2
38
+ default:
39
+ jobs:
40
+ - test:
41
+ matrix:
42
+ parameters:
43
+ version:
44
+ - "2.5-node"
45
+ - "2.6-node"
46
+ - "2.7-node"
47
+ - "3.0-node"
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "bundler"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ assignees:
8
+ - "jgarber623"
data/.reek.yml ADDED
@@ -0,0 +1,16 @@
1
+ detectors:
2
+ DuplicateMethodCall:
3
+ max_calls: 2
4
+ IrresponsibleModule:
5
+ enabled: false
6
+ TooManyStatements:
7
+ exclude:
8
+ - Svgeez::Builder#build
9
+ - Svgeez::Builder#initialize
10
+ - Svgeez::Commands::Watch#process
11
+ UtilityFunction:
12
+ exclude:
13
+ - Svgeez::Elements::SymbolElement#element_contents
14
+
15
+ exclude_paths:
16
+ - vendor/
data/.rubocop.yml CHANGED
@@ -1,24 +1,32 @@
1
1
  require:
2
+ - rubocop-performance
3
+ - rubocop-rake
2
4
  - rubocop-rspec
3
5
 
4
- Metrics/BlockLength:
5
- Exclude:
6
- - "spec/**/*"
6
+ AllCops:
7
+ NewCops: disable
7
8
 
8
- Metrics/LineLength:
9
+ Layout/LineLength:
9
10
  Enabled: false
10
11
 
11
- RSpec/AnyInstance:
12
- Enabled: false
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - spec/**/*
13
15
 
14
- RSpec/MessageSpies:
15
- EnforcedStyle: receive
16
+ Naming/RescuedExceptionsVariableName:
17
+ PreferredName: exception
16
18
 
17
19
  RSpec/MultipleExpectations:
18
20
  Max: 2
19
21
 
22
+ RSpec/MultipleMemoizedHelpers:
23
+ Max: 10
24
+
20
25
  Style/Documentation:
21
26
  Enabled: false
22
27
 
23
28
  Style/FrozenStringLiteralComment:
24
29
  Enabled: false
30
+
31
+ Style/SymbolArray:
32
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.4
1
+ 2.5.9
data/.simplecov CHANGED
@@ -1,10 +1,16 @@
1
+ require 'simplecov_json_formatter'
1
2
  require 'simplecov-console'
2
3
 
3
- formatters = [SimpleCov::Formatter::HTMLFormatter]
4
+ formatters = [
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ SimpleCov::Formatter::JSONFormatter
7
+ ]
4
8
 
9
+ # rubocop:disable Style/IfUnlessModifier
5
10
  if RSpec.configuration.files_to_run.length > 1
6
11
  formatters << SimpleCov::Formatter::Console
7
12
  end
13
+ # rubocop:enable Style/IfUnlessModifier
8
14
 
9
15
  SimpleCov.start do
10
16
  formatter SimpleCov::Formatter::MultiFormatter.new(formatters)
data/CHANGELOG.md CHANGED
@@ -1,11 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.0 / 2021-07-12
4
+
5
+ - **Breaking Change:** Require SVGO version 1.3.2 (c108320)
6
+ - Add Ruby 3 support (af4772d)
7
+ - **Breaking Change:** Remove Ruby 2.4 support (3ec6ea3)
8
+ - Update `listen` dependency constraint (e05a61b)
9
+ - Remove development gem dependency constraints (2911fae)
10
+ - Update development Ruby version to 2.5.9 (1e61b0b)
11
+ - Replace `bin/*` scripts with `bin/ci`
12
+ - Migrate from Travis CI to Circle CI
13
+
14
+ ## 3.2.0 / 2020-08-11
15
+
16
+ - Add `--prefix` option (#79 and #80)
17
+ - Update development Ruby version to 2.4.10 (8d517c1)
18
+
19
+ ## 3.1.0 / 2020-01-20
20
+
21
+ - Expand supported Ruby versions to include 2.7 (bcc23b5)
22
+
23
+ ## 3.0.0 / 2019-08-02
24
+
25
+ ### Breaking Changes
26
+
27
+ - Bump required minimum SVGO version to 1.3.0 (afa24c6)
28
+
29
+ ### Additional Enhancements
30
+
31
+ - Refactor command classes (02f420c)
32
+ - Refactor specs ()
33
+ - Update development dependencies
34
+
35
+ ## 2.0.1 / 2019-01-03
36
+
37
+ - Expand supported Ruby versions to include 2.6 (0facfd0)
38
+
3
39
  ## 2.0.0 / 2018-12-04
4
40
 
5
- - Refactor classes to use `attr_reader`s ([c62780f](https://github.com/jgarber623/svgeez/commit/c62780f))
6
- - Change required Ruby versions and liberalize dependency constraints ([35fcadb](https://github.com/jgarber623/svgeez/commit/35fcadb))
7
- - Change project Ruby version to 2.4.4 ([301d341](https://github.com/jgarber623/svgeez/commit/301d341))
8
- - Bump required SVGO version to 1.1.1 ([28741fc](https://github.com/jgarber623/svgeez/commit/28741fc))
41
+ - Refactor classes to use `attr_reader`s (c62780f)
42
+ - Change required Ruby versions and liberalize dependency constraints (35fcadb)
43
+ - Change project Ruby version to 2.4.9 (301d341)
44
+ - Bump required SVGO version to 1.1.1 (28741fc)
9
45
 
10
46
  ## Previous Releases
11
47
 
data/CONTRIBUTING.md CHANGED
@@ -8,9 +8,9 @@ There are a couple ways you can help improve svgeez:
8
8
 
9
9
  ## Getting Started
10
10
 
11
- svgeez is developed using Ruby 2.4.4 and is additionally tested against Ruby 2.5.3 using [Travis CI](https://travis-ci.org/jgarber623/svgeez).
11
+ svgeez is developed using Ruby 2.5.9 and is additionally tested against Ruby 2.6, 2.7, and 3.0 using [CircleCI](https://app.circleci.com/pipelines/github/jgarber623/svgeez).
12
12
 
13
- Before making changes to svgeez, you'll want to install Ruby 2.4.4. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm). Once you've installed Ruby 2.4.4 using your method of choice, install the project's gems by running:
13
+ Before making changes to svgeez, you'll want to install Ruby 2.5.9. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm). Once you've installed Ruby 2.5.9 using your method of choice, install the project's gems by running:
14
14
 
15
15
  ```sh
16
16
  bundle install
@@ -30,8 +30,8 @@ npm install -g svgo
30
30
  1. Install development dependencies as outlined above.
31
31
  1. Create a feature branch for the code changes you're looking to make: `git checkout -b my-new-feature`.
32
32
  1. _Write some code!_
33
- 1. Build (`bin/rake build`) and install (`bin/rake install`) your updated code.
34
- 1. If your changes would benefit from testing, add the necessary tests and verify everything passes by running `bin/rake`.
33
+ 1. Build (`bundle exec rake build`) and install (`bundle exec rake install`) your updated code.
34
+ 1. If your changes would benefit from testing, add the necessary tests and verify everything passes by running `bin/ci`.
35
35
  1. Commit your changes: `git commit -am 'Add some new feature or fix some issue'`. _(See [this excellent article](https://chris.beams.io/posts/git-commit/) for tips on writing useful Git commit messages.)_
36
36
  1. Push the branch to your fork: `git push -u origin my-new-feature`.
37
37
  1. Create a new [pull request][pulls] and we'll review your changes.
@@ -40,8 +40,6 @@ npm install -g svgo
40
40
 
41
41
  Code formatting conventions are defined in the `.editorconfig` file which uses the [EditorConfig](http://editorconfig.org) syntax. There are [plugins for a variety of editors](http://editorconfig.org/#download) that utilize the settings in the `.editorconfig` file. We recommended you install the EditorConfig plugin for your editor of choice.
42
42
 
43
- Additionally, [Rubocop](https://github.com/bbatsov/rubocop) can be used to help identify possible trouble areas in your code. Run `bin/rubocop` to generate Rubocop's static code analysis report.
44
-
45
43
  Your bug fix or feature addition won't be rejected if it runs afoul of any (or all) of these guidelines, but following the guidelines will definitely make everyone's lives a little easier.
46
44
 
47
45
  [issues]: https://github.com/jgarber623/svgeez/issues
data/Gemfile CHANGED
@@ -2,3 +2,14 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in svgeez.gemspec
4
4
  gemspec
5
+
6
+ gem 'pry-byebug'
7
+ gem 'rake'
8
+ gem 'reek'
9
+ gem 'rspec'
10
+ gem 'rubocop'
11
+ gem 'rubocop-performance'
12
+ gem 'rubocop-rake'
13
+ gem 'rubocop-rspec'
14
+ gem 'simplecov'
15
+ gem 'simplecov-console'
data/README.md CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  **A Ruby gem for automatically generating an SVG sprite from a folder of SVG icons.**
4
4
 
5
- [![Gem](https://img.shields.io/gem/v/svgeez.svg?style=for-the-badge)](https://rubygems.org/gems/svgeez)
6
- [![Downloads](https://img.shields.io/gem/dt/svgeez.svg?style=for-the-badge)](https://rubygems.org/gems/svgeez)
7
- [![Build](https://img.shields.io/travis/jgarber623/svgeez/master.svg?style=for-the-badge)](https://travis-ci.org/jgarber623/svgeez)
8
- [![Dependencies](https://img.shields.io/depfu/jgarber623/svgeez.svg?style=for-the-badge)](https://depfu.com/github/jgarber623/svgeez)
9
- [![Maintainability](https://img.shields.io/codeclimate/maintainability/jgarber623/svgeez.svg?style=for-the-badge)](https://codeclimate.com/github/jgarber623/svgeez)
10
- [![Coverage](https://img.shields.io/codeclimate/c/jgarber623/svgeez.svg?style=for-the-badge)](https://codeclimate.com/github/jgarber623/svgeez/code)
5
+ [![Gem](https://img.shields.io/gem/v/svgeez.svg?logo=rubygems&style=for-the-badge)](https://rubygems.org/gems/svgeez)
6
+ [![Downloads](https://img.shields.io/gem/dt/svgeez.svg?logo=rubygems&style=for-the-badge)](https://rubygems.org/gems/svgeez)
7
+ [![Build](https://img.shields.io/circleci/build/github/jgarber623/svgeez?logo=circleci&style=for-the-badge)](https://app.circleci.com/pipelines/github/jgarber623/svgeez)
8
+ [![Maintainability](https://img.shields.io/codeclimate/maintainability/jgarber623/svgeez.svg?logo=code-climate&style=for-the-badge)](https://codeclimate.com/github/jgarber623/svgeez)
9
+ [![Coverage](https://img.shields.io/codeclimate/c/jgarber623/svgeez.svg?logo=code-climate&style=for-the-badge)](https://codeclimate.com/github/jgarber623/svgeez/code)
11
10
 
12
11
  If you're using an [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) icon system in your Web projects, svgeez can help speed up your workflow by automating the SVG sprite generation process. Run svgeez alongside your existing project (or integrate it into your current build system); add, edit, or delete SVG files from a folder; and marvel as svgeez generates a single SVG sprite file ready for inclusion in your user interface.
13
12
 
@@ -21,7 +20,7 @@ _For more on why SVG sprites are the bee's knees as far as icon systems go, give
21
20
 
22
21
  ## Getting Started
23
22
 
24
- Before installing and using svgeez, you'll want to have Ruby 2.4 (or newer) installed on your computer. There are plenty of ways to go about this, but my preference is [rbenv](https://github.com/sstephenson/rbenv). svgeez is developed using Ruby 2.4.4 and automatically tested against 2.4.4 and 2.5.3 by [Travis CI](https://travis-ci.org/jgarber623/svgeez).
23
+ Before installing and using svgeez, you'll want to have Ruby 2.5 (or newer) installed on your computer. There are plenty of ways to go about this, but my preference is [rbenv](https://github.com/sstephenson/rbenv). svgeez is developed using Ruby 2.5.9 and is additionally tested against Ruby 2.6, 2.7, and 3.0 using [CircleCI](https://app.circleci.com/pipelines/github/jgarber623/svgeez).
25
24
 
26
25
  ## Installation
27
26
 
@@ -30,19 +29,19 @@ If you're using [Bundler](http://bundler.io), add svgeez to your project's Gemfi
30
29
  ```rb
31
30
  source 'https://rubygems.org'
32
31
 
33
- gem 'svgeez', '~> 2.0'
32
+ gem 'svgeez', '~> 3.0'
34
33
  ```
35
34
 
36
35
  …and hop over to your command prompt and run…
37
36
 
38
37
  ```sh
39
- $ bundle install
38
+ bundle install
40
39
  ```
41
40
 
42
41
  You may also install svgeez directly by issuing the following command:
43
42
 
44
43
  ```sh
45
- $ gem install svgeez
44
+ gem install svgeez
46
45
  ```
47
46
 
48
47
  ## Usage
@@ -56,18 +55,19 @@ You can manually generate an SVG sprite from a folder of SVGs with the `build` c
56
55
  A basic example:
57
56
 
58
57
  ```sh
59
- $ svgeez build --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg
58
+ svgeez build --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg
60
59
  ```
61
60
 
62
61
  The above example will combine all SVG files in `~/Sites/sixtwothree.org/images/icons` into a single SVG sprite file (`icons.svg`) in `~/Sites/sixtwothree.org/images`.
63
62
 
64
63
  #### Options and Defaults
65
64
 
66
- |Option|Description|
67
- |---|---|
68
- |`-s`<br>`--source`|Path to the folder of source SVGs (defaults to `./_svgeez`).|
69
- |`-d`<br>`--destination`|Path to the destination file or folder (defaults to `./svgeez.svg`)|
70
- |`--with-svgo`|Optimize SVG sprite file with [SVGO](https://github.com/svg/svgo)|
65
+ | Option | Description |
66
+ |:----------------------|:------------------------------------------------------------------|
67
+ | `-s`, `--source` | Path to folder of source SVGs (defaults to `./_svgeez`). |
68
+ | `-d`, `--destination` | Path to destination file or folder (defaults to `./svgeez.svg`) |
69
+ | `-p`, `--prefix` | Optional prefix to append to generated `id` attribute values |
70
+ | `--with-svgo` | Optimize SVG sprite file with [SVGO](https://github.com/svg/svgo) |
71
71
 
72
72
  ### The `watch` command
73
73
 
@@ -76,7 +76,7 @@ The `watch` command takes the same arguments as the `build` command but uses the
76
76
  Tweaking the example from above:
77
77
 
78
78
  ```sh
79
- $ svgeez watch --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg
79
+ svgeez watch --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg
80
80
  ```
81
81
 
82
82
  svgeez will remaing running, watching for new, removed, or updated SVG files in the provided source folder. As SVG files are added, deleted, or modified in the source folder, svgeez will pump out updated SVG sprite files to the destination folder.
@@ -91,8 +91,10 @@ The first section of Jayden Seric's post, [How to optimize SVG](http://jaydenser
91
91
 
92
92
  If you have the excellent [SVGO](https://github.com/svg/svgo) utility installed on your system (and the `svgo` command is available in your `PATH`), you can use the `--with-svgo` option and optimize the generated sprite file.
93
93
 
94
+ **Note:** If using SVGO with svgeez, you must use SVGO version 1.3.2. Future releases of svgeez will update to use SVGO version 2.x.x.
95
+
94
96
  ```sh
95
- $ svgeez build --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg --with-svgo
97
+ svgeez build --source ~/Sites/sixtwothree.org/images/icons --destination ~/Sites/sixtwothree.org/images/icons.svg --with-svgo
96
98
  ```
97
99
 
98
100
  Depending on the number of individual SVG files in the source folder, using the `--with-svgo` option can add considerable time to SVG sprite generation.
@@ -197,7 +199,7 @@ button svg {
197
199
 
198
200
  ## Improving svgeez
199
201
 
200
- You want to help make svgeez better? Hell yeah! I like your enthusiasm. For more on how you can help, check out [CONTRIBUTING.md](https://github.com/jgarber623/svgeez/blob/master/CONTRIBUTING.md).
202
+ You want to help make svgeez better? Hell yeah! I like your enthusiasm. For more on how you can help, check out [CONTRIBUTING.md](https://github.com/jgarber623/svgeez/blob/main/CONTRIBUTING.md).
201
203
 
202
204
  ### Donations
203
205
 
@@ -223,10 +225,12 @@ svgeez is written and maintained by [Jason Garber](https://sixtwothree.org).
223
225
 
224
226
  ### Additional Contributors
225
227
 
228
+ - [Abhinav Mishra](https://github.com/abhinavmsra)
226
229
  - [Brett Wilkins](https://github.com/bwilkins)
227
230
  - [danny](https://github.com/f96q)
228
231
  - [Denis Hovart](https://github.com/dhovart)
229
232
  - [Desmond Sadler](https://github.com/dezman)
233
+ - [motoroller95](https://github.com/motoroller95)
230
234
 
231
235
  ## License
232
236
 
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bundler/gem_tasks'
2
+
2
3
  require 'rspec/core/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new
data/lib/svgeez.rb CHANGED
@@ -1,26 +1,28 @@
1
1
  require 'fileutils'
2
- require 'listen'
3
2
  require 'logger'
4
- require 'mercenary'
5
3
  require 'mkmf'
6
4
  require 'securerandom'
7
5
 
6
+ require 'listen'
7
+ require 'mercenary'
8
+
8
9
  require 'svgeez/version'
9
10
 
10
11
  require 'svgeez/command'
11
12
  require 'svgeez/commands/build'
12
13
  require 'svgeez/commands/watch'
13
14
 
15
+ require 'svgeez/elements/svg_element'
16
+ require 'svgeez/elements/symbol_element'
17
+
14
18
  require 'svgeez/builder'
15
19
  require 'svgeez/destination'
16
20
  require 'svgeez/optimizer'
17
21
  require 'svgeez/source'
18
- require 'svgeez/svg_element'
19
- require 'svgeez/symbol_element'
20
22
 
21
23
  module Svgeez
22
24
  def self.logger
23
- @logger ||= Logger.new(STDOUT)
25
+ @logger ||= Logger.new($stdout)
24
26
  end
25
27
 
26
28
  logger.formatter = proc { |_, _, _, msg| "#{msg}\n" }
@@ -1,44 +1,69 @@
1
1
  module Svgeez
2
2
  class Builder
3
3
  SOURCE_IS_DESTINATION_MESSAGE = "Setting `source` and `destination` to the same path isn't allowed!".freeze
4
+ SOURCE_DOES_NOT_EXIST = 'Provided `source` folder does not exist.'.freeze
4
5
  NO_SVGS_IN_SOURCE_MESSAGE = 'No SVGs were found in `source` folder.'.freeze
5
6
 
6
- attr_reader :source, :destination
7
+ attr_reader :source, :destination, :prefix
7
8
 
8
9
  def initialize(options = {})
9
10
  @source = Source.new(options)
10
11
  @destination = Destination.new(options)
11
12
  @svgo = options.fetch('svgo', false)
13
+ @prefix = options.fetch('prefix', @destination.file_id)
14
+
15
+ raise SOURCE_IS_DESTINATION_MESSAGE if source_is_destination?
16
+ raise SOURCE_DOES_NOT_EXIST unless source_exists?
17
+ rescue RuntimeError => exception
18
+ logger.error exception.message
19
+ exit
12
20
  end
13
21
 
14
22
  # rubocop:disable Metrics/AbcSize
15
23
  def build
16
- return Svgeez.logger.error(SOURCE_IS_DESTINATION_MESSAGE) if source_is_destination?
17
- return Svgeez.logger.warn(NO_SVGS_IN_SOURCE_MESSAGE) if source_is_empty?
24
+ raise NO_SVGS_IN_SOURCE_MESSAGE if source_is_empty?
18
25
 
19
- Svgeez.logger.info "Generating sprite at `#{destination.file_path}` from #{source.file_paths.length} SVG#{'s' if source.file_paths.length > 1}..."
26
+ logger.info "Generating sprite at `#{destination_file_path}` from #{source_files_count} SVG#{'s' if source_files_count > 1}..."
20
27
 
21
28
  # Make destination folder
22
29
  FileUtils.mkdir_p(destination.folder_path)
23
30
 
24
31
  # Write the file
25
- File.open(destination.file_path, 'w') do |f|
26
- f.write destination_file_contents
32
+ File.open(destination_file_path, 'w') do |file|
33
+ file.write destination_file_contents
27
34
  end
28
35
 
29
- Svgeez.logger.info "Successfully generated sprite at `#{destination.file_path}`."
36
+ logger.info "Successfully generated sprite at `#{destination_file_path}`."
37
+ rescue RuntimeError => exception
38
+ logger.warn exception.message
30
39
  end
31
40
  # rubocop:enable Metrics/AbcSize
32
41
 
33
42
  private
34
43
 
35
44
  def destination_file_contents
36
- file_contents = SvgElement.new(source, destination).build
45
+ file_contents = Elements::SvgElement.new(source, destination, prefix).build
37
46
  file_contents = Optimizer.new.optimize(file_contents) if @svgo
38
47
 
39
48
  file_contents.insert(4, ' style="display: none;"')
40
49
  end
41
50
 
51
+ def destination_file_path
52
+ @destination_file_path ||= destination.file_path
53
+ end
54
+
55
+ def logger
56
+ @logger ||= Svgeez.logger
57
+ end
58
+
59
+ def source_exists?
60
+ File.directory?(source.folder_path)
61
+ end
62
+
63
+ def source_files_count
64
+ source.file_paths.length
65
+ end
66
+
42
67
  def source_is_destination?
43
68
  /\A#{source.folder_path}/ =~ destination.folder_path
44
69
  end
@@ -1,18 +1,39 @@
1
1
  module Svgeez
2
2
  class Command
3
- def self.subclasses
4
- @subclasses ||= []
5
- end
3
+ class << self
4
+ def subclasses
5
+ @subclasses ||= []
6
+ end
6
7
 
7
- def self.inherited(base)
8
- subclasses << base
9
- super(base)
10
- end
8
+ def inherited(base)
9
+ subclasses << base
10
+ super(base)
11
+ end
12
+
13
+ def init_with_program(program)
14
+ program.command(name.split('::').last.downcase.to_sym) do |command|
15
+ command.description command_description
16
+ command.syntax command_syntax
17
+
18
+ add_actions(command)
19
+ add_options(command)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def add_actions(command)
26
+ command.action do |_, options|
27
+ command_action(options)
28
+ end
29
+ end
11
30
 
12
- def self.add_build_options(command)
13
- command.option 'source', '-s', '--source [FOLDER]', 'Source folder (defaults to ./_svgeez)'
14
- command.option 'destination', '-d', '--destination [OUTPUT]', 'Destination file or folder (defaults to ./svgeez.svg)'
15
- command.option 'svgo', '--with-svgo', 'Optimize source SVGs with SVGO before sprite generation (non-destructive)'
31
+ def add_options(command)
32
+ command.option 'source', '-s', '--source [FOLDER]', 'Source folder (defaults to ./_svgeez)'
33
+ command.option 'destination', '-d', '--destination [OUTPUT]', 'Destination file or folder (defaults to ./svgeez.svg)'
34
+ command.option 'prefix', '-p', '--prefix [PREFIX]', 'Custom Prefix for icon id (defaults to destination filename)'
35
+ command.option 'svgo', '--with-svgo', 'Optimize source SVGs with SVGO before sprite generation (non-destructive)'
36
+ end
16
37
  end
17
38
  end
18
39
  end
@@ -1,21 +1,24 @@
1
1
  module Svgeez
2
2
  module Commands
3
3
  class Build < Command
4
- def self.init_with_program(program)
5
- program.command(:build) do |command|
6
- command.description 'Builds an SVG sprite from a folder of SVG icons'
7
- command.syntax 'build [options]'
4
+ class << self
5
+ def process(options)
6
+ Svgeez::Builder.new(options).build
7
+ end
8
8
 
9
- add_build_options(command)
9
+ private
10
10
 
11
- command.action do |_, options|
12
- Build.process(options)
13
- end
11
+ def command_action(options)
12
+ Build.process(options)
14
13
  end
15
- end
16
14
 
17
- def self.process(options)
18
- Svgeez::Builder.new(options).build
15
+ def command_description
16
+ 'Builds an SVG sprite from a folder of SVG icons'
17
+ end
18
+
19
+ def command_syntax
20
+ 'build [options]'
21
+ end
19
22
  end
20
23
  end
21
24
  end
@@ -1,33 +1,33 @@
1
1
  module Svgeez
2
2
  module Commands
3
3
  class Watch < Command
4
- def self.init_with_program(program)
5
- program.command(:watch) do |command|
6
- command.description 'Watches a folder of SVG icons for changes'
7
- command.syntax 'watch [options]'
4
+ class << self
5
+ def process(options)
6
+ builder = Svgeez::Builder.new(options)
7
+ folder_path = builder.source.folder_path
8
8
 
9
- add_build_options(command)
9
+ Svgeez.logger.info "Watching `#{folder_path}` for changes... Press ctrl-c to stop."
10
10
 
11
- command.action do |_, options|
12
- Build.process(options)
13
- Watch.process(options)
14
- end
11
+ Listen.to(folder_path, only: /\.svg\z/) { builder.build }.start
12
+ sleep
13
+ rescue Interrupt
14
+ Svgeez.logger.info 'Quitting svgeez...'
15
15
  end
16
- end
17
16
 
18
- def self.process(options)
19
- builder = Svgeez::Builder.new(options)
17
+ private
20
18
 
21
- listener = Listen.to(builder.source.folder_path, only: /\.svg\z/) do
22
- builder.build
19
+ def command_action(options)
20
+ Build.process(options)
21
+ Watch.process(options)
23
22
  end
24
23
 
25
- Svgeez.logger.info "Watching `#{builder.source.folder_path}` for changes... Press ctrl-c to stop."
24
+ def command_description
25
+ 'Watches a folder of SVG icons for changes'
26
+ end
26
27
 
27
- listener.start
28
- sleep
29
- rescue Interrupt
30
- Svgeez.logger.info 'Quitting svgeez...'
28
+ def command_syntax
29
+ 'watch [options]'
30
+ end
31
31
  end
32
32
  end
33
33
  end
@@ -0,0 +1,23 @@
1
+ module Svgeez
2
+ module Elements
3
+ class SvgElement
4
+ def initialize(source, destination, prefix)
5
+ @source = source
6
+ @destination = destination
7
+ @prefix = prefix
8
+ end
9
+
10
+ def build
11
+ %(<svg id="#{@destination.file_id}" xmlns="http://www.w3.org/2000/svg">#{symbol_elements.join}</svg>)
12
+ end
13
+
14
+ private
15
+
16
+ def symbol_elements
17
+ @source.file_paths.map do |file_path|
18
+ SymbolElement.new(file_path, @prefix).build
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module Svgeez
2
+ module Elements
3
+ class SymbolElement
4
+ def initialize(file_path, file_id)
5
+ @file_path = file_path
6
+ @file_id = file_id
7
+ end
8
+
9
+ def build
10
+ IO.read(@file_path).match(%r{^<svg\s*?(?<attributes>.*?)>(?<content>.*?)</svg>}m) do |matches|
11
+ %(<symbol #{element_attributes(matches[:attributes]).sort.join(' ')}>#{element_contents(matches[:content])}</symbol>)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def element_attributes(attributes)
18
+ attrs = attributes.scan(/(?:viewBox|xmlns:.+?)=".*?"/m)
19
+ id_prefix = @file_id
20
+ id_suffix = File.basename(@file_path, '.svg').gsub(/['"\s]/, '-')
21
+ id_attribute = [id_prefix, id_suffix].reject(&:empty?).join('-')
22
+
23
+ attrs << %(id="#{id_attribute}")
24
+ end
25
+
26
+ def element_contents(content)
27
+ content.scan(/\sid="(.+?)"/).flatten.each do |value|
28
+ uuid = SecureRandom.uuid
29
+
30
+ content.gsub!(/\s(id|xlink:href)="(#?#{value})"/m, %( \\1="\\2-#{uuid}"))
31
+ content.gsub!(/\s(clip-path|fill|filter|marker-end|marker-mid|marker-start|mask|stroke)="url\((##{value})\)"/m, %( \\1="url(\\2-#{uuid})"))
32
+ end
33
+
34
+ content
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,14 +1,16 @@
1
1
  module Svgeez
2
2
  class Optimizer
3
- SVGO_MINIMUM_VERSION = '1.1.1'.freeze
4
- SVGO_MINIMUM_VERSION_MESSAGE = "svgeez relies on SVGO #{SVGO_MINIMUM_VERSION} or newer. Continuing with standard sprite generation...".freeze
3
+ SVGO_VERSION = '1.3.2'.freeze
4
+ SVGO_VERSION_MESSAGE = "svgeez relies on SVGO #{SVGO_VERSION}. Continuing with standard sprite generation...".freeze
5
5
  SVGO_NOT_INSTALLED = 'Unable to find `svgo` in your PATH. Continuing with standard sprite generation...'.freeze
6
6
 
7
7
  def optimize(file_contents)
8
- return Svgeez.logger.warn(SVGO_NOT_INSTALLED) unless installed?
9
- return Svgeez.logger.warn(SVGO_MINIMUM_VERSION_MESSAGE) unless supported?
8
+ raise SVGO_NOT_INSTALLED unless installed?
9
+ raise SVGO_VERSION_MESSAGE unless supported?
10
10
 
11
- `cat <<EOF | svgo --disable=cleanupIDs --disable=removeViewBox -i - -o -\n#{file_contents}\nEOF`
11
+ `cat <<EOF | svgo --disable=cleanupIDs --disable=removeHiddenElems --disable=removeViewBox -i - -o -\n#{file_contents}\nEOF`
12
+ rescue RuntimeError => exception
13
+ logger.warn exception.message
12
14
  end
13
15
 
14
16
  private
@@ -17,8 +19,12 @@ module Svgeez
17
19
  @installed ||= find_executable0('svgo')
18
20
  end
19
21
 
22
+ def logger
23
+ @logger ||= Svgeez.logger
24
+ end
25
+
20
26
  def supported?
21
- @supported ||= Gem::Version.new(`svgo -v`.strip) >= Gem::Version.new(SVGO_MINIMUM_VERSION)
27
+ @supported ||= `svgo -v`.strip == SVGO_VERSION
22
28
  end
23
29
  end
24
30
  end
@@ -1,3 +1,3 @@
1
1
  module Svgeez
2
- VERSION = '2.0.0'.freeze
2
+ VERSION = '4.0.0'.freeze
3
3
  end
data/svgeez.gemspec CHANGED
@@ -1,10 +1,7 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
- require 'svgeez/version'
1
+ require_relative 'lib/svgeez/version'
5
2
 
6
3
  Gem::Specification.new do |spec|
7
- spec.required_ruby_version = ['>= 2.4', '< 2.6']
4
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 3.1')
8
5
 
9
6
  spec.name = 'svgeez'
10
7
  spec.version = Svgeez::VERSION
@@ -16,20 +13,17 @@ Gem::Specification.new do |spec|
16
13
  spec.homepage = 'https://github.com/jgarber623/svgeez'
17
14
  spec.license = 'MIT'
18
15
 
19
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin|spec)/}) }
16
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin|spec)/}) }
18
+ end
20
19
 
21
20
  spec.bindir = 'exe'
22
21
  spec.executables = ['svgeez']
23
22
  spec.require_paths = ['lib']
24
23
 
25
- spec.add_development_dependency 'bundler', '~> 1.17'
26
- spec.add_development_dependency 'rake', '~> 12.3'
27
- spec.add_development_dependency 'rspec', '~> 3.8'
28
- spec.add_development_dependency 'rubocop', '~> 0.60.0'
29
- spec.add_development_dependency 'rubocop-rspec', '~> 1.30'
30
- spec.add_development_dependency 'simplecov', '~> 0.16.1'
31
- spec.add_development_dependency 'simplecov-console', '~> 0.4.2'
24
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
25
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
32
26
 
33
- spec.add_runtime_dependency 'listen', '~> 3.1'
34
- spec.add_runtime_dependency 'mercenary', '~> 0.3.6'
27
+ spec.add_runtime_dependency 'listen', '~> 3.5'
28
+ spec.add_runtime_dependency 'mercenary', '~> 0.4.0'
35
29
  end
metadata CHANGED
@@ -1,141 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svgeez
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Garber
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2021-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.17'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.17'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '12.3'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '12.3'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '3.8'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '3.8'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.60.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.60.0
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.30'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.30'
83
- - !ruby/object:Gem::Dependency
84
- name: simplecov
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.16.1
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.16.1
97
- - !ruby/object:Gem::Dependency
98
- name: simplecov-console
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 0.4.2
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: 0.4.2
111
13
  - !ruby/object:Gem::Dependency
112
14
  name: listen
113
15
  requirement: !ruby/object:Gem::Requirement
114
16
  requirements:
115
17
  - - "~>"
116
18
  - !ruby/object:Gem::Version
117
- version: '3.1'
19
+ version: '3.5'
118
20
  type: :runtime
119
21
  prerelease: false
120
22
  version_requirements: !ruby/object:Gem::Requirement
121
23
  requirements:
122
24
  - - "~>"
123
25
  - !ruby/object:Gem::Version
124
- version: '3.1'
26
+ version: '3.5'
125
27
  - !ruby/object:Gem::Dependency
126
28
  name: mercenary
127
29
  requirement: !ruby/object:Gem::Requirement
128
30
  requirements:
129
31
  - - "~>"
130
32
  - !ruby/object:Gem::Version
131
- version: 0.3.6
33
+ version: 0.4.0
132
34
  type: :runtime
133
35
  prerelease: false
134
36
  version_requirements: !ruby/object:Gem::Requirement
135
37
  requirements:
136
38
  - - "~>"
137
39
  - !ruby/object:Gem::Version
138
- version: 0.3.6
40
+ version: 0.4.0
139
41
  description: Automatically generate an SVG sprite from a folder of SVG icons.
140
42
  email:
141
43
  - jason@sixtwothree.org
@@ -144,14 +46,16 @@ executables:
144
46
  extensions: []
145
47
  extra_rdoc_files: []
146
48
  files:
49
+ - ".circleci/config.yml"
147
50
  - ".editorconfig"
51
+ - ".github/dependabot.yml"
148
52
  - ".gitignore"
53
+ - ".reek.yml"
149
54
  - ".rspec"
150
55
  - ".rubocop"
151
56
  - ".rubocop.yml"
152
57
  - ".ruby-version"
153
58
  - ".simplecov"
154
- - ".travis.yml"
155
59
  - CHANGELOG.md
156
60
  - CODE_OF_CONDUCT.md
157
61
  - CONTRIBUTING.md
@@ -166,17 +70,19 @@ files:
166
70
  - lib/svgeez/commands/build.rb
167
71
  - lib/svgeez/commands/watch.rb
168
72
  - lib/svgeez/destination.rb
73
+ - lib/svgeez/elements/svg_element.rb
74
+ - lib/svgeez/elements/symbol_element.rb
169
75
  - lib/svgeez/optimizer.rb
170
76
  - lib/svgeez/source.rb
171
- - lib/svgeez/svg_element.rb
172
- - lib/svgeez/symbol_element.rb
173
77
  - lib/svgeez/version.rb
174
78
  - svgeez.gemspec
175
79
  homepage: https://github.com/jgarber623/svgeez
176
80
  licenses:
177
81
  - MIT
178
- metadata: {}
179
- post_install_message:
82
+ metadata:
83
+ bug_tracker_uri: https://github.com/jgarber623/svgeez/issues
84
+ changelog_uri: https://github.com/jgarber623/svgeez/blob/v4.0.0/CHANGELOG.md
85
+ post_install_message:
180
86
  rdoc_options: []
181
87
  require_paths:
182
88
  - lib
@@ -184,19 +90,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
90
  requirements:
185
91
  - - ">="
186
92
  - !ruby/object:Gem::Version
187
- version: '2.4'
93
+ version: '2.5'
188
94
  - - "<"
189
95
  - !ruby/object:Gem::Version
190
- version: '2.6'
96
+ version: '3.1'
191
97
  required_rubygems_version: !ruby/object:Gem::Requirement
192
98
  requirements:
193
99
  - - ">="
194
100
  - !ruby/object:Gem::Version
195
101
  version: '0'
196
102
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.6.14.1
199
- signing_key:
103
+ rubygems_version: 3.2.16
104
+ signing_key:
200
105
  specification_version: 4
201
106
  summary: Automatically generate an SVG sprite from a folder of SVG icons.
202
107
  test_files: []
data/.travis.yml DELETED
@@ -1,24 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4.4
4
- - 2.5.3
5
- cache:
6
- - bundler
7
- before_install:
8
- - gem install bundler
9
- - nvm install node
10
- - npm install -g svgo
11
- before_script:
12
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
13
- - chmod +x ./cc-test-reporter
14
- - ./cc-test-reporter before-build
15
- script:
16
- - bundle exec rubocop
17
- - bundle exec rake
18
- after_script:
19
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
20
- notifications:
21
- email: false
22
- slack:
23
- rooms:
24
- secure: nA0yP2h64kUBM4bs1PrLBfoMvj/u8S1g/Yc0BICCJWpcahUnZiX4Kd87+zprfg0r1nX1Eu+5ileM9U4Z9CeOfNHVma/o5PISliRMgWe3k9na+I66oEybj1u4+a3wA+upXsZQ+RpnJh1aE3A99EdA8plGhAjts3cmdYzcEknDM5wLRxj0V4H7lVzYGHBC4wKWTJ3dEq3uSnYvymxuJI29a8H1bgrlTsTutzwLmEiyDfiXEjUUfoUIE3EVjJdEswJUXmjUPGKB7a/O63ExZj1vtmPAFITw9MeTChbV+5suG0Ibv7dOwqACidqj868HGYHQ7I/G+SwRvJvwWyzmbbFzclupJqudDLPWLKOT8SeUDrezdi9cGg6NI4domRcKRlSSqX1uBDrI7yvhtPeAsB5GFSBCbZVobvVcc1oDitM0KXsQ1kzAKSxnoT0w+egVMfD15ga656agu2qVjiivBBscfSyoNIsQD90j+xGdKBysXGUFE1SxVJ3WtJ6X22PVpDRvjmFmdeT2vnpdA0YB00zvBibGvT+WFP2Iw45YBpXzc3bXj5zRlni79CsehWs44aUfQxNMaPi5G7Dzp+0C/cxDA7DgdU/aVjg6lkXgkuuKE0uybYrTQvWSQ43c8k3eExEMmy3/vFgG82rwGA6STfXf0EUmZ2N6MRI8E1eIU5M78OE=
@@ -1,20 +0,0 @@
1
- module Svgeez
2
- class SvgElement
3
- def initialize(source, destination)
4
- @source = source
5
- @destination = destination
6
- end
7
-
8
- def build
9
- %(<svg id="#{@destination.file_id}" xmlns="http://www.w3.org/2000/svg">#{symbol_elements.join}</svg>)
10
- end
11
-
12
- private
13
-
14
- def symbol_elements
15
- @source.file_paths.map do |file_path|
16
- SymbolElement.new(file_path, @destination.file_id).build
17
- end
18
- end
19
- end
20
- end
@@ -1,30 +0,0 @@
1
- module Svgeez
2
- class SymbolElement
3
- def initialize(file_path, file_id)
4
- @file_path = file_path
5
- @file_id = file_id
6
- end
7
-
8
- def build
9
- IO.read(@file_path).match(%r{^<svg\s*?(?<attributes>.*?)>(?<content>.*?)</svg>}m) do |matches|
10
- %(<symbol #{element_attributes(matches[:attributes]).sort.join(' ')}>#{element_contents(matches[:content])}</symbol>)
11
- end
12
- end
13
-
14
- private
15
-
16
- def element_attributes(attributes)
17
- attrs = attributes.scan(/(?:viewBox|xmlns:.+?)=".*?"/m)
18
-
19
- attrs << %(id="#{@file_id}-#{File.basename(@file_path, '.svg').gsub(/['"\s]/, '-')}")
20
- end
21
-
22
- def element_contents(content)
23
- content.scan(/\sid="(.+?)"/).flatten.each do |value|
24
- content.gsub!(/\s(id|xlink:href)="(#?#{value})"/m, %( \\1="\\2-#{SecureRandom.uuid}"))
25
- end
26
-
27
- content
28
- end
29
- end
30
- end