opal/browser/cookies.rb in opal-browser-0.3.1 vs opal/browser/cookies.rb in opal-browser-0.3.2

- old
+ new

@@ -1,19 +1,26 @@ -require 'stringio' - module Browser # Allows manipulation of browser cookies. # # @see https://developer.mozilla.org/en-US/docs/Web/API/document.cookie # # Usage: # -# cookies = Browser::Cookies.new(`document`) +# cookies = $document.cookies # cookies["my-cookie"] = "monster" # cookies.delete("my-cookie") # +# By default, cookies are stored JSON-encoded. You can supply a `raw:` option +# whenever you need to access/write the cookies in a raw way, eg. +# +# cookies["my-other-cookie", raw: true] = 123 +# +# You can also set this option while referencing $document.cookies, eg. +# +# cookies = $document.cookies(raw: true) +# cookies["my-other-cookie"] = 123 class Cookies # Default cookie options. DEFAULT = { expires: Time.now + 60 * 60 * 24, secure: false @@ -24,119 +31,141 @@ attr_reader :options # Create a new {Cookies} wrapper. # # @param document [native] the native document object - def initialize(document) + # @param options [Hash] the default cookie options + def initialize(document, options = {}) @document = document - @options = DEFAULT.dup + @options = DEFAULT.merge(options) end # Access the cookie with the given name. # # @param name [String] the name of the cookie + # @param options [Hash] the options for the cookie # + # @option options [Boolean] :raw get a raw cookie value, don't encode it with JSON + # # @return [Object] - def [](name) + def [](name, options = {}) + options = @options.merge(options) + matches = `#@document.cookie`.scan(/#{Regexp.escape(FormData.encode(name))}=([^;]*)/) return if matches.empty? - result = matches.flatten.map {|value| - JSON.parse(FormData.decode(value)) - } + result = matches.flatten.map do |value| + if options[:raw] + FormData.decode(value) + else + JSON.parse(FormData.decode(value)) + end + end result.length == 1 ? result.first : result end # Set a cookie. # # @param name [String] the name of the cookie # @param value [Object] the data to set # @param options [Hash] the options for the cookie # + # @option options [Boolean] :raw don't encode a value with JSON # @option options [Integer] :max_age the max age of the cookie in seconds # @option options [Time] :expires the expire date # @option options [String] :path the path the cookie is valid on # @option options [String] :domain the domain the cookie is valid on # @option options [Boolean] :secure whether the cookie is secure or not - def []=(name, value, options = {}) - string = value.is_a?(String) ? value : JSON.dump(value) - encoded_value = encode(name, string, @options.merge(options)) + def []=(name, options = {}, value) + options = @options.merge(options) + if options[:raw] + string = value.to_s + else + string = JSON.dump(value) + end + encoded_value = encode(name, string, options) `#@document.cookie = #{encoded_value}` end # Delete a cookie. # # @param name [String] the name of the cookie - def delete(name) + def delete(name, _options = {}) `#@document.cookie = #{encode name, '', expires: Time.now}` end # @!attribute [r] keys # @return [Array<String>] all the cookie names - def keys - Array(`#@document.cookie.split(/; /)`).map {|cookie| + def keys(_options = {}) + Array(`#@document.cookie.split(/; /)`).map do |cookie| cookie.split(/\s*=\s*/).first - } + end end # @!attribute [r] values # @return [Array] all the cookie values - def values - keys.map {|key| - self[key] - } + def values(options = {}) + options = @options.merge(options) + keys.map do |key| + self[key, options] + end end # Enumerate the cookies. # # @yieldparam key [String] the name of the cookie # @yieldparam value [String] the value of the cookie # + # @param options [Hash] the options for the cookie + # + # @option options [Boolean] :raw don't encode a value with JSON + # # @return [self] - def each(&block) - return enum_for :each unless block + def each(options = {}, &block) + return enum_for :each, options unless block + options = @options.merge(options) - keys.each {|key| - yield key, self[key] - } + keys.each do |key| + yield key, self[key, options] + end self end # Delete all the cookies # # @return [self] - def clear - keys.each {|key| + def clear(_options = {}) + keys.each do |key| delete key - } + end self end protected def encode(key, value, options = {}) - io = StringIO.new + io = [] io << FormData.encode(key) << ?= << FormData.encode(value) << '; ' io << 'max-age=' << options[:max_age] << '; ' if options[:max_age] io << 'expires=' << options[:expires].utc << '; ' if options[:expires] io << 'path=' << options[:path] << '; ' if options[:path] io << 'domain=' << options[:domain] << '; ' if options[:domain] io << 'secure' if options[:secure] - io.string + io.join end end class DOM::Document < DOM::Element # @!attribute [r] cookies # @return [Cookies] the cookies for the document - def cookies - Cookies.new(@native) if defined?(`#@native.cookie`) + def cookies(options = {}) + Cookies.new(@native, options) if defined?(`#@native.cookie`) end end end