Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom SVG attributes #113

Merged
merged 1 commit into from May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Expand Up @@ -90,14 +90,16 @@ module_size - The Pixel size of each module
(defaults 11)
shape_rendering - SVG Attribute: auto | optimizeSpeed | crispEdges | geometricPrecision
(defaults crispEdges)
standalone - whether to make this a full SVG file, or only an svg to embed in other svg
standalone - Whether to make this a full SVG file, or only an svg to embed in other svg
(default true)
use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
and quality. This will become the default in future versions.
(default false)
viewbox - replace the `svg.width` and `svg.height` attribute with `svg.viewBox` to
viewbox - Replace the `svg.width` and `svg.height` attribute with `svg.viewBox` to
allow CSS scaling
(default false)
svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
(default {})
```
Example
```ruby
Expand All @@ -111,7 +113,10 @@ svg = qrcode.as_svg(
shape_rendering: 'crispEdges',
module_size: 11,
standalone: true,
use_path: true
use_path: true,
svg_attributes: {
id: "myUniqueId"
}
)
```

Expand Down
17 changes: 16 additions & 1 deletion lib/rqrcode/export/svg.rb
Expand Up @@ -115,6 +115,13 @@ def end_y
end
end

DEFAULT_SVG_ATTRIBUTES = [
%(version="1.1"),
%(xmlns="http://www.w3.org/2000/svg"),
%(xmlns:xlink="http://www.w3.org/1999/xlink"),
%(xmlns:ev="http://www.w3.org/2001/xml-events")
]

SVG_PATH_COMMANDS = {
move: "M",
up: "v-",
Expand Down Expand Up @@ -145,6 +152,8 @@ def end_y
# (default false)
# viewbox - replace `width` and `height` in <svg> with a viewBox, allows CSS scaling
# (default false)
# svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
# (default {})
#
def as_svg(options = {})
fill = options[:fill]
Expand All @@ -155,14 +164,20 @@ def as_svg(options = {})
module_size = options[:module_size] || 11
standalone = options[:standalone].nil? ? true : options[:standalone]
viewbox = options[:viewbox].nil? ? false : options[:viewbox]
svg_attributes = options[:svg_attributes] || {}

# height and width dependent on offset and QR complexity
dimension = (@qrcode.module_count * module_size) + (2 * offset)
# use dimensions differently if we are using a viewBox
dimensions_attr = viewbox ? %(viewBox="0 0 #{dimension} #{dimension}") : %(width="#{dimension}" height="#{dimension}")

svg_tag_attributes = (DEFAULT_SVG_ATTRIBUTES + [
dimensions_attr,
%(shape-rendering="#{shape_rendering}")
] + svg_attributes.map { |k, v| %(#{k}="#{v}") }).join(" ")

xml_tag = %(<?xml version="1.0" standalone="yes"?>)
open_tag = %(<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" #{dimensions_attr} shape-rendering="#{shape_rendering}">)
open_tag = %(<svg #{svg_tag_attributes}>)
close_tag = "</svg>"

output_tag = (use_path ? Path : Rect).new(@qrcode)
Expand Down
4 changes: 4 additions & 0 deletions spec/rqrcode/data.rb
Expand Up @@ -22,6 +22,10 @@
<?xml version="1.0" standalone="yes"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" viewBox="0 0 319 319" shape-rendering="crispEdges"><path d="M0 0h7v7h-7zM8 0h7v2h-1v1h1v1h-2v-2h-1v-1h-2v2h-2v-1h1v-1h-1zM17 0h3v2h1v5h-1v-2h-1v2h-1v-3h-2v-1h2v1h1v-2h-1v-1h-1zM22 0h7v7h-7zM1 1v5h5v-5zM23 1v5h5v-5zM2 2h3v3h-3zM11 2h1v1h-1zM24 2h3v3h-3zM8 4h1v1h-1zM10 4h1v1h1v1h-1v1h-1v-1h-1v-1h1zM13 5h1v1h-1zM15 5h2v2h-1v-1h-1zM8 6h1v1h1v1h2v-2h1v1h1v-1h1v1h-1v1h-2v1h-3v-1h-1zM15 7h1v1h1v1h-1v3h1v-1h1v-1h1v1h-1v2h-1v1h1v1h-2v-2h-1v-1h-1v1h-1v-2h1v-1h1v-1h-1v-1h1zM5 8h2v1h-1v1h2v1h-2v1h1v1h-1v1h-2v-1h1v-2h-1v-1h-1v4h-1v-2h-1v1h-1v-3h1v-1h4zM18 8h3v1h1v-1h1v2h1v-2h1v2h1v-2h1v1h1v-1h1v1h-1v1h-1v1h-1v3h-2v-1h1v-1h-1v-1h-1v3h1v1h-2v-2h-1v-1h1v-1h-2v-2h-2zM12 9h1v1h-1zM1 10v1h1v-1zM10 10h2v2h-1v2h1v1h1v-1h1v-1h1v1h-1v1h1v1h1v2h2v-1h1v-2h1v-1h-1v-2h1v1h1v3h-1v1h-1v2h-3v1h2v1h-3v-1h-1v-2h-1v1h-1v-3h-2v1h-1v-1h-1v1h-2v1h3v1h1v1h-1v1h1v1h2v-2h-1v-1h1v1h1v1h1v1h-1v1h1v-1h1v1h1v1h-1v1h-3v-1h-1v-1h-1v2h1v1h2v2h-1v-1h-2v-1h-1v-2h-1v-1h1v-1h-1v-2h-1v-1h-2v-1h-1v-1h1v-2h1v-1h1v-1h1v-2h1v1h1zM27 12h1v1h-1zM9 13v1h1v-1zM28 13h1v1h-1zM0 14h2v1h1v-1h1v2h-1v1h-1v1h1v1h2v1h-2v1h-1v-2h-1v2h-1zM7 14v1h-1v1h1v-1h1v-1zM24 15h3v3h-2v-1h-1zM22 16h1v1h-1zM28 16h1v3h-1zM14 17v1h1v-1zM20 17h1v2h2v-2h1v3h1v-1h1v1h-1v1h1v-1h2v1h-1v1h-2v1h1v1h-1v1h-1v1h1v-1h3v2h-1v-1h-1v1h-1v2h-1v-2h-1v1h-1v-1h-1v1h-2v-1h-1v-1h-3v-1h1v-1h1v-1h2v-1h-1v-1h1v-2h1zM5 20h2v1h-2zM19 21v1h1v-1zM21 21v3h3v-3zM0 22h7v7h-7zM22 22h1v1h-1zM27 22h1v1h-1zM1 23v5h5v-5zM28 23h1v1h-1zM2 24h3v3h-3zM17 24v1h1v-1zM21 25v1h2v-1zM14 26h1v1h1v1h1v1h-3zM9 27h1v1h-1zM26 27h1v1h-1zM28 27h1v1h-1z" style="fill:#000" transform="translate(0,0) scale(11)"/></svg>
SVG

AS_SVG5 = <<~SVG.chomp
<?xml version="1.0" standalone="yes"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="231" height="231" shape-rendering="crispEdges" id="myUniqueId" class="myClass"><path d="M0 0h7v7h-7zM8 0h1v1h-1zM10 0h1v1h-1zM12 0h1v3h-2v-2h1zM14 0h7v7h-7zM1 1v5h5v-5zM15 1v5h5v-5zM2 2h3v3h-3zM8 2h1v1h-1zM16 2h3v3h-3zM9 3h1v1h1v1h-1v1h-1v-1h-1v-1h1zM11 5h1v1h-1zM8 6h1v1h1v-1h1v1h1v-1h1v4h-1v1h2v-3h1v6h1v1h1v-1h1v-1h-1v-1h-1v-4h1v3h2v-1h-1v-2h1v1h1v-1h1v1h-1v3h1v2h-1v1h-1v-1h-1v1h1v1h-4v-1h-1v-1h-3v-2h-1v-1h-2v-1h2v-1h-1v-1h-1zM5 8h2v1h-2zM10 8v1h1v-1zM0 9h1v2h-1zM2 9h1v1h-1zM4 9h1v1h-1zM6 10h1v1h-1zM10 10v1h1v-1zM2 11h1v1h1v-1h2v1h-1v1h-3zM7 11h1v1h-1zM6 12h1v1h-1zM8 12h2v1h-1v1h-1zM12 12v1h1v-1zM18 12v1h1v-1zM0 14h7v7h-7zM9 14h1v1h2v1h2v1h-1v1h-1v1h-2v-1h1v-1h-2v-1h-1v-1h1zM1 15v5h5v-5zM2 16h3v3h-3zM19 16h1v1h-1zM14 17h1v1h-1zM16 17h2v1h-1v1h-1zM13 18h1v1h-1zM19 18h2v1h-2zM17 19h2v1h-2zM10 20h2v1h-2zM19 20h1v1h-1z" style="fill:#000" transform="translate(0,0) scale(11)"/></svg>
SVG

AS_BASIC = <<~STR
XXXXXXXOOOXOXOOXXXOOOOXXXXXXX
XOOOOOXOOXXXXXOOXOXOOOXOOOOOX
Expand Down
12 changes: 12 additions & 0 deletions spec/rqrcode/export_svg_spec.rb
Expand Up @@ -49,4 +49,16 @@
)).to eq(AS_SVG4)
end
end

context "svg_attributes" do
it "renders `svg_attributes` when provided " do
expect(RQRCode::QRCode.new("qrcode").as_svg(
use_path: true,
svg_attributes: {
id: "myUniqueId",
class: "myClass"
}
)).to eq(AS_SVG5)
end
end
end