icalendar 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.txt +4 -0
- data/README.md +44 -1
- data/Rakefile +8 -0
- data/lib/icalendar/base.rb +1 -1
- data/lib/icalendar/calendar.rb +35 -52
- data/lib/icalendar/component.rb +63 -82
- data/lib/icalendar/component/event.rb +1 -1
- data/lib/icalendar/component/freebusy.rb +1 -1
- data/lib/icalendar/component/journal.rb +1 -1
- data/lib/icalendar/component/timezone.rb +0 -13
- data/lib/icalendar/component/todo.rb +1 -1
- data/lib/icalendar/parser.rb +13 -0
- data/test/test_calendar.rb +44 -1
- data/test/test_parameter.rb +4 -2
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 44c08a1f244a35efd4affc4705028dfe9798f707
         | 
| 4 | 
            +
              data.tar.gz: f67a4772936897ed6fed5efd4d3d6d8f6c564ac9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 336fc24e516f61e887be407e55c5670475c965770a13e42be3b97fc1843cb02f5a21f40cba4aa76887f868c51637c0d9510548748f4dce34d8ff0d62579d0529
         | 
| 7 | 
            +
              data.tar.gz: aeb52da8e30cea70b4faaa2b931b827e19952837f85c2403959859702fa2b80213a0ef4d05d0c7d45ac0ab99bc90b7fa6f96e36e5bc7d1c163d1f6ac4dca06ee
         | 
    
        data/History.txt
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -6,6 +6,24 @@ iCalendar -- Internet calendaring, Ruby style | |
| 6 6 |  | 
| 7 7 | 
             
            <http://github.com/icalendar/icalendar>
         | 
| 8 8 |  | 
| 9 | 
            +
            2.x Status
         | 
| 10 | 
            +
            ---
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            iCalendar 2.0 is under active development, and can be followed in the
         | 
| 13 | 
            +
            [2.0beta branch](https://github.com/icalendar/icalendar/tree/2.0beta).
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            iCalendar 1.x (currently the master branch) will still survive for a
         | 
| 16 | 
            +
            while, but will only be accepting bug fixes from this point forward
         | 
| 17 | 
            +
            unless someone else wants to take over more active maintainership of
         | 
| 18 | 
            +
            the 1.x series.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            ### 2.0 Goals ###
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            * Implements [RFC 5545](http://tools.ietf.org/html/rfc5545)
         | 
| 23 | 
            +
            * More obvious access to parameters and values
         | 
| 24 | 
            +
            * Cleaner & easier timezone support
         | 
| 25 | 
            +
             | 
| 26 | 
            +
             | 
| 9 27 | 
             
            DESCRIPTION
         | 
| 10 28 | 
             
            ---
         | 
| 11 29 |  | 
| @@ -92,7 +110,7 @@ ALARMS | |
| 92 110 |  | 
| 93 111 | 
             
            ### Within an event ###
         | 
| 94 112 |  | 
| 95 | 
            -
                cal.event | 
| 113 | 
            +
                cal.event do
         | 
| 96 114 | 
             
                  # ...other event properties
         | 
| 97 115 | 
             
                  alarm do
         | 
| 98 116 | 
             
                    action        "EMAIL"
         | 
| @@ -186,6 +204,31 @@ TIMEZONES | |
| 186 204 | 
             
                # END:STANDARD
         | 
| 187 205 | 
             
                # END:VTIMEZONE
         | 
| 188 206 |  | 
| 207 | 
            +
            iCalendar has some basic support for creating VTIMEZONE blocks from timezone information pulled from `tzinfo`. You must require `tzinfo` support manually to take advantage, and iCalendar only supports `tzinfo` with versions `~> 0.3`
         | 
| 208 | 
            +
             | 
| 209 | 
            +
            #### Example ####
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                require 'tzinfo'
         | 
| 212 | 
            +
                require 'icalendar/tzinfo'
         | 
| 213 | 
            +
                
         | 
| 214 | 
            +
                cal = Calendar.new
         | 
| 215 | 
            +
                
         | 
| 216 | 
            +
                event_start = DateTime.new 2008, 12, 29, 8, 0, 0
         | 
| 217 | 
            +
                event_end = DateTime.new 2008, 12, 29, 11, 0, 0
         | 
| 218 | 
            +
                
         | 
| 219 | 
            +
                tzid = "America/Chicago"
         | 
| 220 | 
            +
                tz = TZInfo::Timezone.get tzid
         | 
| 221 | 
            +
                timezone = tz.ical_timezone event_start
         | 
| 222 | 
            +
                cal.add timezone
         | 
| 223 | 
            +
              
         | 
| 224 | 
            +
                cal.event do
         | 
| 225 | 
            +
                    dtstart     event_start.tap { |d| d.ical_params = {'TZID' => tzid} }
         | 
| 226 | 
            +
                    dtend       event_end.tap { |d| d.ical_params = {'TZID' => tzid} }
         | 
| 227 | 
            +
                    summary     "Meeting with the man."
         | 
| 228 | 
            +
                    description "Have a long lunch meeting and decide nothing..."
         | 
| 229 | 
            +
                end
         | 
| 230 | 
            +
             | 
| 231 | 
            +
             | 
| 189 232 | 
             
            Unicode
         | 
| 190 233 | 
             
            ---
         | 
| 191 234 |  | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/icalendar/base.rb
    CHANGED
    
    
    
        data/lib/icalendar/calendar.rb
    CHANGED
    
    | @@ -25,88 +25,60 @@ module Icalendar | |
| 25 25 | 
             
                  self.version = "2.0" # Version of the specification
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 | 
            -
                def  | 
| 29 | 
            -
                  " | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
                  # Then the properties
         | 
| 33 | 
            -
                  print_properties(@properties.select { |k,v| k != 'version' }) +
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  # sub components
         | 
| 36 | 
            -
                  yield +
         | 
| 28 | 
            +
                def print_headers
         | 
| 29 | 
            +
                  "VERSION:#{version}\r\n"
         | 
| 30 | 
            +
                end
         | 
| 37 31 |  | 
| 38 | 
            -
             | 
| 39 | 
            -
                   | 
| 32 | 
            +
                def properties_to_print
         | 
| 33 | 
            +
                  @properties.select { |k,v| k != 'version' }
         | 
| 40 34 | 
             
                end
         | 
| 41 35 |  | 
| 42 36 | 
             
                def event(&block)
         | 
| 43 | 
            -
                   | 
| 44 | 
            -
                   | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                       | 
| 37 | 
            +
                  calendar_tzid = timezone_id
         | 
| 38 | 
            +
                  build_component Event.new do
         | 
| 39 | 
            +
                    # Note: I'm not sure this is the best way to pass this down, but it works
         | 
| 40 | 
            +
                    self.tzid = calendar_tzid
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    if block
         | 
| 43 | 
            +
                      instance_eval(&block)
         | 
| 44 | 
            +
                      if tzid
         | 
| 45 | 
            +
                        dtstart.ical_params = { "TZID" => e.tzid }
         | 
| 46 | 
            +
                        dtend.ical_params = { "TZID" => e.tzid } unless dtend.nil?
         | 
| 47 | 
            +
                      end
         | 
| 54 48 | 
             
                    end
         | 
| 55 49 | 
             
                  end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  e
         | 
| 58 50 | 
             
                end
         | 
| 59 51 |  | 
| 60 52 | 
             
                def find_event(uid)
         | 
| 61 | 
            -
                   | 
| 53 | 
            +
                  events.find {|e| e.uid == uid}
         | 
| 62 54 | 
             
                end
         | 
| 63 55 |  | 
| 64 56 | 
             
                def todo(&block)
         | 
| 65 | 
            -
                   | 
| 66 | 
            -
                  self.add_component e
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                  e.instance_eval(&block) if block
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  e
         | 
| 57 | 
            +
                  build_component Todo.new, &block
         | 
| 71 58 | 
             
                end
         | 
| 72 59 |  | 
| 73 60 | 
             
                def find_todo(uid)
         | 
| 74 | 
            -
                   | 
| 61 | 
            +
                  todos.find {|t| t.uid == uid}
         | 
| 75 62 | 
             
                end
         | 
| 76 63 |  | 
| 77 64 | 
             
                def journal(&block)
         | 
| 78 | 
            -
                   | 
| 79 | 
            -
                  self.add_component e
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  e.instance_eval(&block) if block
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                  e
         | 
| 65 | 
            +
                  build_component Journal.new, &block
         | 
| 84 66 | 
             
                end
         | 
| 85 67 |  | 
| 86 68 | 
             
                def find_journal(uid)
         | 
| 87 | 
            -
                   | 
| 69 | 
            +
                  journals.find {|j| j.uid == uid}
         | 
| 88 70 | 
             
                end
         | 
| 89 71 |  | 
| 90 72 | 
             
                def freebusy(&block)
         | 
| 91 | 
            -
                   | 
| 92 | 
            -
                  self.add_component e
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                  e.instance_eval(&block) if block
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                  e
         | 
| 73 | 
            +
                  build_component Freebusy.new, &block
         | 
| 97 74 | 
             
                end
         | 
| 98 75 |  | 
| 99 76 | 
             
                def find_freebusy(uid)
         | 
| 100 | 
            -
                   | 
| 77 | 
            +
                  freebusys.find {|f| f.uid == uid}
         | 
| 101 78 | 
             
                end
         | 
| 102 79 |  | 
| 103 80 | 
             
                def timezone(&block)
         | 
| 104 | 
            -
                   | 
| 105 | 
            -
                  self.add_component e
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                  e.instance_eval(&block) if block
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  e
         | 
| 81 | 
            +
                  build_component Timezone.new, &block
         | 
| 110 82 | 
             
                end
         | 
| 111 83 |  | 
| 112 84 | 
             
                # The "PUBLISH" method in a "VEVENT" calendar component is an
         | 
| @@ -122,6 +94,17 @@ module Icalendar | |
| 122 94 | 
             
                  self.ip_method = "PUBLISH"
         | 
| 123 95 | 
             
                end
         | 
| 124 96 |  | 
| 97 | 
            +
                private
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  def build_component(component, &block)
         | 
| 100 | 
            +
                    add_component component
         | 
| 101 | 
            +
                    component.instance_eval(&block) if block
         | 
| 102 | 
            +
                    component
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  def timezone_id
         | 
| 106 | 
            +
                    timezones[0].tzid if timezones.length > 0
         | 
| 107 | 
            +
                  end
         | 
| 125 108 | 
             
              end # class Calendar
         | 
| 126 109 |  | 
| 127 110 | 
             
            end # module Icalendar
         | 
    
        data/lib/icalendar/component.rb
    CHANGED
    
    | @@ -49,7 +49,7 @@ module Icalendar | |
| 49 49 |  | 
| 50 50 | 
             
                def initialize(name)
         | 
| 51 51 | 
             
                  @name = name
         | 
| 52 | 
            -
                  @components = Hash.new | 
| 52 | 
            +
                  @components = Hash.new { |h, k| h[k] = [] }
         | 
| 53 53 | 
             
                  @properties = {}
         | 
| 54 54 |  | 
| 55 55 | 
             
                  @@logger.info("New #{@name[1,@name.size].capitalize}...")
         | 
| @@ -57,13 +57,7 @@ module Icalendar | |
| 57 57 |  | 
| 58 58 | 
             
                # Add a sub-component to the current component object.
         | 
| 59 59 | 
             
                def add_component(component)
         | 
| 60 | 
            -
                   | 
| 61 | 
            -
             | 
| 62 | 
            -
                  unless @components.has_key? key
         | 
| 63 | 
            -
                    @components[key] = []
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                  @components[key] << component
         | 
| 60 | 
            +
                  @components[component.key_name] << component
         | 
| 67 61 | 
             
                end
         | 
| 68 62 |  | 
| 69 63 | 
             
                # Add a component to the calendar.
         | 
| @@ -79,11 +73,7 @@ module Icalendar | |
| 79 73 | 
             
                alias add_journal add_component
         | 
| 80 74 |  | 
| 81 75 | 
             
                def remove_component(component)
         | 
| 82 | 
            -
                   | 
| 83 | 
            -
             | 
| 84 | 
            -
                  if @components.has_key? key
         | 
| 85 | 
            -
                    @components[key].delete(component)
         | 
| 86 | 
            -
                  end
         | 
| 76 | 
            +
                  @components[component.key_name].delete(component)
         | 
| 87 77 | 
             
                end
         | 
| 88 78 |  | 
| 89 79 | 
             
                # Remove a component from the calendar.
         | 
| @@ -105,95 +95,82 @@ module Icalendar | |
| 105 95 |  | 
| 106 96 | 
             
                # Output in the icalendar format
         | 
| 107 97 | 
             
                def to_ical
         | 
| 108 | 
            -
                   | 
| 109 | 
            -
                     | 
| 110 | 
            -
             | 
| 111 | 
            -
                       | 
| 112 | 
            -
                    end
         | 
| 113 | 
            -
                    s
         | 
| 98 | 
            +
                  printer do
         | 
| 99 | 
            +
                    [print_headers,
         | 
| 100 | 
            +
                      print_properties,
         | 
| 101 | 
            +
                      print_subcomponents].join
         | 
| 114 102 | 
             
                  end
         | 
| 115 103 | 
             
                end
         | 
| 116 104 |  | 
| 117 105 | 
             
                # Print this icalendar component
         | 
| 118 106 | 
             
                def print_component
         | 
| 119 | 
            -
                   | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
                  # Then the properties
         | 
| 123 | 
            -
                  print_properties +
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                  # sub components
         | 
| 126 | 
            -
                  yield +
         | 
| 107 | 
            +
                  to_ical
         | 
| 108 | 
            +
                end
         | 
| 127 109 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
                   | 
| 110 | 
            +
                def print_subcomponents
         | 
| 111 | 
            +
                  @components.values.map do |component_parts|
         | 
| 112 | 
            +
                    Array(component_parts).map &:to_ical
         | 
| 113 | 
            +
                  end.join
         | 
| 130 114 | 
             
                end
         | 
| 131 115 |  | 
| 132 | 
            -
                def  | 
| 133 | 
            -
                   | 
| 116 | 
            +
                def printer
         | 
| 117 | 
            +
                  ["BEGIN:#{@name.upcase}\r\n",
         | 
| 118 | 
            +
                  yield,
         | 
| 119 | 
            +
                  "END:#{@name.upcase}\r\n"].join
         | 
| 120 | 
            +
                end
         | 
| 134 121 |  | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                     | 
| 139 | 
            -
             | 
| 122 | 
            +
                def print_properties(properties = properties_to_print)
         | 
| 123 | 
            +
                  excludes = %w(geo rrule categories exdate)
         | 
| 124 | 
            +
                  properties.sort.map do |key, val|
         | 
| 125 | 
            +
                    property = fix_conflict_with_built_in(key)
         | 
| 126 | 
            +
                    prelude = property.gsub(/_/, '-').upcase
         | 
| 127 | 
            +
                    params = print_parameters(val)
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                    value = ":#{val.to_ical}"
         | 
| 130 | 
            +
                    multiline = multiline_property?(property)
         | 
| 131 | 
            +
                    if multiline || (!multiline && !excludes.include?(property))
         | 
| 132 | 
            +
                      value = escape_chars(value)
         | 
| 140 133 | 
             
                    end
         | 
| 141 134 |  | 
| 142 | 
            -
                     | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
                    else
         | 
| 151 | 
            -
                      prelude = "#{key.gsub(/_/, '-').upcase}"
         | 
| 152 | 
            -
                      val.each do |v|
         | 
| 153 | 
            -
                        params = print_parameters(v)
         | 
| 154 | 
            -
                        value = ":#{v.to_ical}"
         | 
| 155 | 
            -
                        value = escape_chars(value)
         | 
| 156 | 
            -
                        add_sliced_text(s, prelude + params + value)
         | 
| 157 | 
            -
                      end
         | 
| 158 | 
            -
                    end
         | 
| 159 | 
            -
                  end
         | 
| 160 | 
            -
                  s
         | 
| 135 | 
            +
                    chunk_lines(prelude + params + value)
         | 
| 136 | 
            +
                  end.join
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                # Take out underscore for property names that conflicted
         | 
| 140 | 
            +
                # with built-in words.
         | 
| 141 | 
            +
                def fix_conflict_with_built_in(key)
         | 
| 142 | 
            +
                  key.sub(/\Aip_/, '')
         | 
| 161 143 | 
             
                end
         | 
| 162 144 |  | 
| 163 145 | 
             
                def escape_chars(value)
         | 
| 164 | 
            -
                   | 
| 165 | 
            -
                  return v
         | 
| 166 | 
            -
                   # return value
         | 
| 146 | 
            +
                  value.gsub("\\", "\\\\").gsub("\r\n", "\n").gsub("\r", "\n").gsub("\n", "\\n").gsub(",", "\\,").gsub(";", "\\;")
         | 
| 167 147 | 
             
                end
         | 
| 168 148 |  | 
| 169 | 
            -
                def  | 
| 170 | 
            -
                   | 
| 171 | 
            -
                   | 
| 172 | 
            -
                   | 
| 149 | 
            +
                def chunk_lines(str, length = MAX_LINE_LENGTH, separator = "\r\n ")
         | 
| 150 | 
            +
                  chunks = str.scan(/.{1,#{length}}/)
         | 
| 151 | 
            +
                  lines = chunks.join(separator) << separator
         | 
| 152 | 
            +
                  lines.gsub(/ *$/, '')
         | 
| 173 153 | 
             
                end
         | 
| 174 154 |  | 
| 175 155 | 
             
                # Print the parameters for a specific property.
         | 
| 176 156 | 
             
                def print_parameters(value)
         | 
| 177 | 
            -
                   | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
                     | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
                     | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
                    end
         | 
| 195 | 
            -
                  end
         | 
| 196 | 
            -
                  s
         | 
| 157 | 
            +
                  return "" unless value.respond_to?(:ical_params)
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                  Array(value.ical_params).map do |key, val|
         | 
| 160 | 
            +
                    val = Array(val)
         | 
| 161 | 
            +
                    next if val.empty?
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                    escaped = val.map { |v| Parser.escape(v.to_ical) }.join(',')
         | 
| 164 | 
            +
                    ";#{key}=" << escaped
         | 
| 165 | 
            +
                  end.join
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                def properties_to_print
         | 
| 169 | 
            +
                  @properties # subclasses can exclude properties
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                def print_headers
         | 
| 173 | 
            +
                  "" # subclasses can specify headers
         | 
| 197 174 | 
             
                end
         | 
| 198 175 |  | 
| 199 176 | 
             
                # TODO: Look into the x-property, x-param stuff...
         | 
| @@ -214,6 +191,10 @@ module Icalendar | |
| 214 191 | 
             
                # Make it protected so we can monitor usage...
         | 
| 215 192 | 
             
                protected
         | 
| 216 193 |  | 
| 194 | 
            +
                def key_name
         | 
| 195 | 
            +
                  (self.class.to_s.downcase + 's').gsub('icalendar::', '').to_sym
         | 
| 196 | 
            +
                end
         | 
| 197 | 
            +
             | 
| 217 198 | 
             
                def self.ical_component(*syms)
         | 
| 218 199 | 
             
                  hash_accessor :@components, *syms
         | 
| 219 200 | 
             
                end
         | 
| @@ -45,19 +45,6 @@ module Icalendar | |
| 45 45 | 
             
                  @components[key] = component
         | 
| 46 46 | 
             
                end
         | 
| 47 47 |  | 
| 48 | 
            -
                # Also need a custom to_ical because typically it iterates over an array
         | 
| 49 | 
            -
                # of components.
         | 
| 50 | 
            -
                def to_ical
         | 
| 51 | 
            -
                  print_component do
         | 
| 52 | 
            -
                  s = ""
         | 
| 53 | 
            -
                    @components.each_value do |comp|
         | 
| 54 | 
            -
                      s << comp.to_ical
         | 
| 55 | 
            -
                    end
         | 
| 56 | 
            -
                  s
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 48 | 
             
                def initialize(name = "VTIMEZONE")
         | 
| 62 49 | 
             
                  super(name)
         | 
| 63 50 | 
             
                end
         | 
    
        data/lib/icalendar/parser.rb
    CHANGED
    
    | @@ -65,6 +65,19 @@ module Icalendar | |
| 65 65 | 
             
                  @@logger.debug("New Calendar Parser: #{@file.inspect}")
         | 
| 66 66 | 
             
                end
         | 
| 67 67 |  | 
| 68 | 
            +
                def self.escape(value)
         | 
| 69 | 
            +
                  if value =~ %r{\A#{Parser::QSTR}\z|\A#{Parser::PTEXT}\z}
         | 
| 70 | 
            +
                    value
         | 
| 71 | 
            +
                  else
         | 
| 72 | 
            +
                    stripped = value.gsub '"', "'"
         | 
| 73 | 
            +
                    if stripped =~ /\A#{Parser::PTEXT}\z/
         | 
| 74 | 
            +
                      stripped
         | 
| 75 | 
            +
                    else
         | 
| 76 | 
            +
                      %|"#{stripped}"|
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 68 81 | 
             
                # Define next line for an IO object.
         | 
| 69 82 | 
             
                # Works for strings now with StringIO
         | 
| 70 83 | 
             
                def next_line
         | 
    
        data/test/test_calendar.rb
    CHANGED
    
    | @@ -45,6 +45,7 @@ class TestCalendar < Test::Unit::TestCase | |
| 45 45 |  | 
| 46 46 | 
             
               def test_create_multiple_event_calendar
         | 
| 47 47 | 
             
                   # Create a fresh calendar
         | 
| 48 | 
            +
                   Timecop.freeze DateTime.new(2013, 12, 26, 5, 0, 0, '+0000')
         | 
| 48 49 | 
             
                   cal = Calendar.new
         | 
| 49 50 | 
             
                   [1,2,3].each do |t|
         | 
| 50 51 | 
             
                       cal.event do
         | 
| @@ -57,7 +58,49 @@ class TestCalendar < Test::Unit::TestCase | |
| 57 58 | 
             
                           self.summary = "test #{t} todo"
         | 
| 58 59 | 
             
                       end
         | 
| 59 60 | 
             
                   end
         | 
| 60 | 
            -
                    | 
| 61 | 
            +
                   expected_no_uid = <<-EXPECTED.gsub("\n", "\r\n")
         | 
| 62 | 
            +
            BEGIN:VCALENDAR
         | 
| 63 | 
            +
            VERSION:2.0
         | 
| 64 | 
            +
            CALSCALE:GREGORIAN
         | 
| 65 | 
            +
            PRODID:iCalendar-Ruby
         | 
| 66 | 
            +
            BEGIN:VEVENT
         | 
| 67 | 
            +
            DTEND:19970901T190000Z
         | 
| 68 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 69 | 
            +
            SEQUENCE:0
         | 
| 70 | 
            +
            SUMMARY:This is summary 1
         | 
| 71 | 
            +
            END:VEVENT
         | 
| 72 | 
            +
            BEGIN:VEVENT
         | 
| 73 | 
            +
            DTEND:19970902T190000Z
         | 
| 74 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 75 | 
            +
            SEQUENCE:0
         | 
| 76 | 
            +
            SUMMARY:This is summary 2
         | 
| 77 | 
            +
            END:VEVENT
         | 
| 78 | 
            +
            BEGIN:VEVENT
         | 
| 79 | 
            +
            DTEND:19970903T190000Z
         | 
| 80 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 81 | 
            +
            SEQUENCE:0
         | 
| 82 | 
            +
            SUMMARY:This is summary 3
         | 
| 83 | 
            +
            END:VEVENT
         | 
| 84 | 
            +
            BEGIN:VTODO
         | 
| 85 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 86 | 
            +
            SEQUENCE:0
         | 
| 87 | 
            +
            SUMMARY:test 1 todo
         | 
| 88 | 
            +
            END:VTODO
         | 
| 89 | 
            +
            BEGIN:VTODO
         | 
| 90 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 91 | 
            +
            SEQUENCE:0
         | 
| 92 | 
            +
            SUMMARY:test 2 todo
         | 
| 93 | 
            +
            END:VTODO
         | 
| 94 | 
            +
            BEGIN:VTODO
         | 
| 95 | 
            +
            DTSTAMP:20131226T050000Z
         | 
| 96 | 
            +
            SEQUENCE:0
         | 
| 97 | 
            +
            SUMMARY:test 3 todo
         | 
| 98 | 
            +
            END:VTODO
         | 
| 99 | 
            +
            END:VCALENDAR
         | 
| 100 | 
            +
                   EXPECTED
         | 
| 101 | 
            +
                   actual_no_uid = cal.to_ical.gsub /^UID:.*\r\n(?: .*\r\n)*/, ''
         | 
| 102 | 
            +
                   Timecop.return
         | 
| 103 | 
            +
                   assert_equal expected_no_uid, actual_no_uid
         | 
| 61 104 | 
             
               end
         | 
| 62 105 |  | 
| 63 106 | 
             
               def test_find
         | 
    
        data/test/test_parameter.rb
    CHANGED
    
    | @@ -40,9 +40,11 @@ class TestParameter < Test::Unit::TestCase | |
| 40 40 |  | 
| 41 41 | 
             
              def test_unquoted_property_parameters
         | 
| 42 42 | 
             
                params = {'ALTREP' => ['"http://my.language.net"'],
         | 
| 43 | 
            -
                          'LANGUAGE' => ['SPANISH:CATILLAN'] | 
| 43 | 
            +
                          'LANGUAGE' => ['SPANISH:CATILLAN'],
         | 
| 44 | 
            +
                          'CN' => ['Joe "The Man" Tester']}
         | 
| 44 45 | 
             
                expected_params = {'ALTREP' => ['"http://my.language.net"'],
         | 
| 45 | 
            -
                                   'LANGUAGE' => ['"SPANISH:CATILLAN"'] | 
| 46 | 
            +
                                   'LANGUAGE' => ['"SPANISH:CATILLAN"'],
         | 
| 47 | 
            +
                                   'CN' => ["Joe 'The Man' Tester"]}
         | 
| 46 48 | 
             
                @event.summary('This is a test summary.', params)
         | 
| 47 49 |  | 
| 48 50 | 
             
                assert_equal params, @event.summary.ical_params
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: icalendar
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.5. | 
| 4 | 
            +
              version: 1.5.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ryan Ahearn
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2014-02-28 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rake
         |