Skip to content

Commit

Permalink
Add custom SVG attributes
Browse files Browse the repository at this point in the history
Thanks to @mjy and #99 for the initial work
  • Loading branch information
whomwah committed Apr 22, 2021
1 parent f913e0a commit f1a6a9e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -90,8 +90,10 @@ 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)
svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
(default {})
```
Example
```ruby
Expand Down
17 changes: 16 additions & 1 deletion lib/rqrcode/export/svg.rb
Expand Up @@ -5,6 +5,12 @@
module RQRCode
module Export
module SVG
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")
]
#
# Render the SVG from the Qrcode.
#
Expand All @@ -16,19 +22,28 @@ module SVG
# shape_rendering - Defaults to crispEdges
# standalone - wether to make this a full SVG file, or only svg to embed
# in other svg.
# svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain
#
def as_svg(options = {})
# parse options
offset = options[:offset].to_i || 0
color = options[:color] || "000"
shape_rendering = options[:shape_rendering] || "crispEdges"
module_size = options[:module_size] || 11
standalone = options[:standalone].nil? ? true : options[:standalone]
svg_attributes = options[:svg_attributes] || {}

# height and width dependent on offset and QR complexity
dimension = (@qrcode.module_count * module_size) + (2 * offset)

svg_tag_attributes = (DEFAULT_SVG_ATTRIBUTES + [
%(width="#{dimension}"),
%(height="#{dimension}"),
%(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" width="#{dimension}" height="#{dimension}" shape-rendering="#{shape_rendering}">)
open_tag = %(<svg #{svg_tag_attributes}>)
close_tag = "</svg>"

result = []
Expand Down
16 changes: 16 additions & 0 deletions spec/rqrcode/export_svg_spec.rb
Expand Up @@ -30,5 +30,21 @@
expect(doc).not_to match(%r{<svg.*>})
expect(doc).not_to match(%r{</svg>})
end

it "renders id when `svg_attributes[:id]` is provided " do
doc = RQRCode::QRCode.new("qrcode").as_svg(svg_attributes: {id: "123"})
# For now we do very naive pattern matching. The alternative is to
# include a librariry for parsing XML, like nokogiri. That is a big
# change for such a small test, though.
expect(doc).to match(%r{<svg.*\sid="123".*>})
end

it "renders class when `svg_attributes[:class]` is provided " do
doc = RQRCode::QRCode.new("qrcode").as_svg(svg_attributes: {class: "foo"})
# For now we do very naive pattern matching. The alternative is to
# include a librariry for parsing XML, like nokogiri. That is a big
# change for such a small test, though.
expect(doc).to match(%r{<svg.*\sclass="foo".*>})
end
end
end

0 comments on commit f1a6a9e

Please sign in to comment.