flannel 0.1.5 → 0.2.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.
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :minor: 1
3
- :patch: 5
2
+ :minor: 2
3
+ :patch: 1
4
4
  :major: 0
5
5
  :build:
data/flannel.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{flannel}
8
- s.version = "0.1.5"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jamal Hansen"]
12
- s.date = %q{2010-01-10}
12
+ s.date = %q{2010-01-14}
13
13
  s.email = %q{jamal.hansen@gmail.com}
14
14
  s.executables = ["quilt-it~", "quilt-it"]
15
15
  s.extra_rdoc_files = [
@@ -50,14 +50,17 @@ Gem::Specification.new do |s|
50
50
  "features/wiki_links.feature",
51
51
  "flannel.gemspec",
52
52
  "lib/flannel.rb",
53
+ "lib/flannel/cache_location_does_not_exist_error.rb",
53
54
  "lib/flannel/cutting_board.rb",
54
55
  "lib/flannel/feed_parser.rb",
56
+ "lib/flannel/file_cache.rb",
55
57
  "lib/flannel/shears.rb",
56
58
  "lib/flannel/square.rb",
57
59
  "lib/flannel/stripe.rb",
58
60
  "lib/flannel/wrappable.rb",
59
61
  "test/cutting_board_test.rb",
60
62
  "test/feed_parser_test.rb",
63
+ "test/file_cache_test.rb",
61
64
  "test/flannel_test.rb",
62
65
  "test/shears_test.rb",
63
66
  "test/square_test.rb",
@@ -72,6 +75,7 @@ Gem::Specification.new do |s|
72
75
  s.summary = %q{A soft comfortable worn in markup language for Ruby}
73
76
  s.test_files = [
74
77
  "test/test_helper.rb",
78
+ "test/file_cache_test.rb",
75
79
  "test/stripe_test.rb",
76
80
  "test/cutting_board_test.rb",
77
81
  "test/feed_parser_test.rb",
data/lib/flannel.rb CHANGED
@@ -4,6 +4,7 @@ require 'flannel/square'
4
4
  require 'flannel/shears'
5
5
  require 'flannel/stripe'
6
6
  require 'flannel/feed_parser'
7
+ require 'flannel/file_cache'
7
8
 
8
9
  module Flannel
9
10
  def self.quilt markup, params={}
@@ -0,0 +1,4 @@
1
+ module Flannel
2
+ class Flannel::CacheLocationDoesNotExistError < RuntimeError
3
+ end
4
+ end
@@ -1,14 +1,12 @@
1
- #require 'shears'
2
-
3
1
 
4
2
  module Flannel
5
3
  class CuttingBoard
6
4
  def initialize params={}
7
- @wiki_link= params[:wiki_link]
5
+ @params = params
8
6
  end
9
7
 
10
8
  def cut markup
11
- shears = Flannel::Shears.new
9
+ shears = Flannel::Shears.new @params
12
10
  squares = shears.cut markup
13
11
  squares.map { |square| square.to_h }.join("\n\n")
14
12
  end
@@ -3,6 +3,10 @@ require 'open-uri'
3
3
 
4
4
  module Flannel
5
5
  class FeedParser
6
+ def initialize params={}
7
+ @cache = params[:cache] if params.has_key?(:cache)
8
+ end
9
+
6
10
  def sub_feeds(url)
7
11
  url = format_url(url)
8
12
  get_news(url)
@@ -15,7 +19,10 @@ module Flannel
15
19
  end
16
20
 
17
21
  def get_document url
18
- open(url)
22
+ doc = @cache.retrieve(url) if @cache
23
+ doc = open(url) unless doc
24
+ @cache.save url, doc if @cache
25
+ doc
19
26
  end
20
27
 
21
28
  def format_item(link, title)
@@ -24,19 +31,16 @@ module Flannel
24
31
 
25
32
  def get_news url
26
33
  item_string = ""
27
- #begin
28
- doc = Hpricot.XML(get_document(url))
29
34
 
30
- (doc/"item").each do |item|
31
- link = (item/"link").inner_html
32
- title = (item/"title").inner_html
33
- item_string << format_item(link, title)
34
- end
35
-
36
- item_string
37
- #rescue
38
- # "Error retrieving data."
39
- #end
35
+ doc = Hpricot.XML(get_document(url))
36
+
37
+ (doc/"item").each do |item|
38
+ link = (item/"link").inner_html
39
+ title = (item/"title").inner_html
40
+ item_string << format_item(link, title)
41
+ end
42
+
43
+ item_string
40
44
  end
41
45
  end
42
46
  end
@@ -0,0 +1,52 @@
1
+ require 'flannel/cache_location_does_not_exist_error'
2
+ require 'digest/md5'
3
+
4
+ module Flannel
5
+ class FileCache
6
+ attr_reader :seconds_till_expiration
7
+
8
+ def initialize cache_location, seconds_till_expiration=3600
9
+ unless File.exists?(cache_location) && File.directory?(cache_location)
10
+ raise CacheLocationDoesNotExistError
11
+ end
12
+
13
+ @cache_location = cache_location
14
+ @seconds_till_expiration = seconds_till_expiration
15
+ end
16
+
17
+ def save url, data
18
+ key = generate_key url
19
+ File.open(File.join(@cache_location, key), 'w') {|f| f.write(data) }
20
+ end
21
+
22
+ def retrieve url
23
+ key = generate_key url
24
+ file = File.join(@cache_location, key)
25
+
26
+ return nil unless File.exists?(file)
27
+
28
+ saved_at = File.mtime(file)
29
+ expires_at = saved_at + @seconds_till_expiration
30
+
31
+ if Time.now >= expires_at
32
+ File.delete(file)
33
+ return nil
34
+ end
35
+
36
+ read file
37
+ end
38
+
39
+ private
40
+ def generate_key url
41
+ Digest::MD5.hexdigest(url)
42
+ end
43
+
44
+ def read file
45
+ data = ''
46
+ File.open(file, "r") { |f|
47
+ data = f.read
48
+ }
49
+ data
50
+ end
51
+ end
52
+ end
@@ -3,6 +3,10 @@
3
3
 
4
4
  module Flannel
5
5
  class Shears
6
+ def initialize params={}
7
+ @params = params
8
+ end
9
+
6
10
  def cut markup
7
11
  @squares = []
8
12
  @square = Flannel::Square.new
@@ -23,7 +27,7 @@ module Flannel
23
27
 
24
28
  def shift_square
25
29
  @squares << @square unless @square.blank?
26
- @square = Flannel::Square.new
30
+ @square = Flannel::Square.new @params
27
31
  end
28
32
 
29
33
  def need_new_square? line
@@ -9,11 +9,13 @@ module Flannel
9
9
  @tags ={:preformatted => "pre", :feed => "ul", :list => "ul", :header_1 => "h1", :header_2 => "h2", :header_3 => "h3", :header_4 => "h4", :header_5 => "h5", :header_6 => "h6"}
10
10
  @stripes = []
11
11
  @style = :paragraph
12
+ @params = params
12
13
  end
13
14
 
14
15
  def << text
15
16
  text = text.strip unless @style == :preformatted
16
- @stripes << Flannel::Stripe.stitch(text, :style=>@style)
17
+ @params[:style] = @style
18
+ @stripes << Flannel::Stripe.stitch(text, @params.dup)
17
19
  end
18
20
 
19
21
  def to_s
@@ -1,5 +1,3 @@
1
- #require 'wrappable'
2
- #require 'feed_parser'
3
1
 
4
2
  module Flannel
5
3
  class Stripe
@@ -12,22 +10,19 @@ module Flannel
12
10
 
13
11
  def initialize weave="", params={}
14
12
  @weave = weave
15
- @wiki_link = params[:wiki_link]
16
- @style = params[:style]
13
+ @params = params
17
14
  end
18
15
 
19
16
  def wiki_link topic
20
- if @wiki_link
21
- @wiki_link.call(permalink topic)
17
+ if @params[:wiki_link]
18
+ @params[:wiki_link].call(permalink topic)
22
19
  else
23
20
  permalink topic[1..-2]
24
21
  end
25
22
  end
26
23
 
27
24
  def permalink topic
28
- require 'iconv'
29
- # thanks to ismasan http://snippets.dzone.com/posts/show/4457
30
- (Iconv.new('US-ASCII//TRANSLIT', 'utf-8').iconv topic).gsub(/[^\w\s\-]/,'').gsub(/[^\w]|[\_]/,' ').split.join('-').downcase
25
+ topic.gsub(%r{[^/\w\s\-]},'').gsub(%r{[^\w/]|[\_]},' ').split.join('-').downcase
31
26
  end
32
27
 
33
28
  def empty?
@@ -36,12 +31,17 @@ module Flannel
36
31
 
37
32
  def build_wiki_links
38
33
  return @weave if preformatted
39
- @weave.gsub(/-\w(.*?)\w>/) { |match| %{<a href="#{wiki_link match}">#{match[1..-2]}</a>}}
34
+ @weave.gsub(/-\w(.*?)\w>/) { |match| %{<a href="#{wiki_link match}">#{format_link_display(match)}</a>}}
35
+ end
36
+
37
+ def format_link_display text
38
+ text[1..-2].split("/").last
40
39
  end
41
40
 
42
41
  def to_h
42
+
43
43
  if feed
44
- parser = Flannel::FeedParser.new
44
+ parser = Flannel::FeedParser.new @params
45
45
  parser.sub_feeds @weave
46
46
  else
47
47
  text = build_wiki_links
@@ -50,15 +50,15 @@ module Flannel
50
50
  end
51
51
 
52
52
  def preformatted
53
- @style == :preformatted
53
+ @params[:style] == :preformatted
54
54
  end
55
55
 
56
56
  def list
57
- @style == :list
57
+ @params[:style] == :list
58
58
  end
59
59
 
60
60
  def feed
61
- @style == :feed
61
+ @params[:style] == :feed
62
62
  end
63
63
 
64
64
  def markup text
@@ -2,6 +2,20 @@ require 'test_helper'
2
2
  require 'mocha'
3
3
 
4
4
  class FeedTest < Test::Unit::TestCase
5
+ context "wiring" do
6
+ setup do
7
+ @rubyyot = File.read(File.join(File.dirname(__FILE__), "..", "features", "fixtures", "rubyyot.rss"))
8
+ @expected_rubyyot = "<ul><li>\n <a href='http://blog.rubyyot"
9
+ end
10
+
11
+ should "be set up for feeds" do
12
+ feed = "http://blog.rubyyot.com/tag/rubyyot/feed/rss"
13
+ body = Flannel.quilt "& #{feed}"
14
+
15
+ assert_equal(@expected_rubyyot, body[0..40])
16
+ end
17
+ end
18
+
5
19
  context "bootstrapping test" do
6
20
  setup do
7
21
  @devlicious = File.read(File.join(File.dirname(__FILE__), "..", "features", "fixtures", "devlicious.rss"))
@@ -0,0 +1,114 @@
1
+ require 'test_helper'
2
+ require 'mocha'
3
+
4
+ class FileCacheTest < Test::Unit::TestCase
5
+ context "Creating File cache" do
6
+ should "require a location" do
7
+ begin
8
+ cache = Flannel::FileCache.new
9
+ assert_fail "should have raised ArgumentError"
10
+ rescue ArgumentError => e
11
+ assert true
12
+ end
13
+ end
14
+
15
+ should "require a valid location" do
16
+ begin
17
+ cache = Flannel::FileCache.new "foo/bar"
18
+ assert_fail "should have raised Flannel::CacheLocationDoesNotExistError"
19
+ rescue Flannel::CacheLocationDoesNotExistError => e
20
+ assert true
21
+ end
22
+ end
23
+ end
24
+
25
+ context "Generating a key" do
26
+ setup do
27
+ @cache = Flannel::FileCache.new "tmp"
28
+ end
29
+
30
+ should "be private" do
31
+ begin
32
+ key = @cache.generate_key "http://example.com"
33
+ assert_fail "generate_key should be private"
34
+ rescue NoMethodError => e
35
+ assert true
36
+ end
37
+ end
38
+
39
+ should "make MD5 hash" do
40
+ url = "http://example.com"
41
+ key = @cache.send :generate_key, url
42
+ assert_equal(Digest::MD5.hexdigest(url), key)
43
+ end
44
+ end
45
+
46
+ context "saving a file" do
47
+ setup do
48
+ clear_dir "tmp"
49
+ @url = "http://example.com"
50
+ @cache_location = "tmp"
51
+ @cache = Flannel::FileCache.new @cache_location
52
+ @key = @cache.send :generate_key, @url
53
+ end
54
+
55
+ should "save data to a file" do
56
+ @cache.save @url, "some data"
57
+ assert File.exists?(File.join(@cache_location, @key)), "cache did not save data"
58
+ end
59
+ end
60
+
61
+ context "retrieving data" do
62
+ setup do
63
+ clear_dir "tmp"
64
+ @url = "http://example.com"
65
+ @cache_location = "tmp"
66
+ @data = "this is some data"
67
+ @cache = Flannel::FileCache.new @cache_location
68
+ @key = @cache.send :generate_key, @url
69
+ end
70
+
71
+ should "should return the saved data" do
72
+ @cache.save @url, @data
73
+ data = @cache.retrieve @url
74
+ assert_equal @data, data
75
+ end
76
+
77
+ should "should return nil if there is no data" do
78
+ data = @cache.retrieve @url
79
+ assert_nil data
80
+ end
81
+ end
82
+
83
+ context "expiration" do
84
+ setup do
85
+ clear_dir "tmp"
86
+ @url = "http://example.com"
87
+ @cache_location = "tmp"
88
+ @data = "this is some data"
89
+ end
90
+
91
+ should "accept an expiration time" do
92
+ cache = Flannel::FileCache.new @cache_location, 1
93
+ assert_equal 1, cache.seconds_till_expiration
94
+ end
95
+
96
+ should "default expiration to 1 hour" do
97
+ cache = Flannel::FileCache.new @cache_location
98
+ assert_equal 3600, cache.seconds_till_expiration
99
+ end
100
+
101
+ should "miss when content is expired" do
102
+ cache = Flannel::FileCache.new @cache_location, 1
103
+ cache.save @url, @data
104
+ sleep 1
105
+ assert_nil(cache.retrieve(@url))
106
+ end
107
+
108
+ should "hit when content is not expired" do
109
+ cache = Flannel::FileCache.new @cache_location, 2
110
+ cache.save @url, @data
111
+ assert_equal(@data, cache.retrieve(@url))
112
+ end
113
+ end
114
+ end
data/test/square_test.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'stripe'
3
2
 
4
3
  class SquareTest < Test::Unit::TestCase
5
4
  context "basic behavior" do
data/test/stripe_test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'test_helper'
2
- #require 'stripe'
2
+ require 'flannel/stripe'
3
3
 
4
4
  class StripeTest < Test::Unit::TestCase
5
5
  context "basic operations" do
@@ -23,13 +23,12 @@ class StripeTest < Test::Unit::TestCase
23
23
  context "building wiki links" do
24
24
  setup do
25
25
  wiki_link = lambda { |keyword| "http://www.example.com/foo/#{keyword}"}
26
- @stripe = Flannel::Stripe.stitch "the -roof is on fire>", :wiki_link =>
27
- wiki_link
26
+ @stripe = Flannel::Stripe.stitch "the -roof is on fire>", :wiki_link => wiki_link
28
27
  end
29
28
 
30
29
  should "build wiki links based on a lambda" do
31
30
  assert_equal "http://www.example.com/foo/cheese",
32
- @stripe.wiki_link("cheese")
31
+ @stripe.wiki_link("-cheese>")
33
32
  end
34
33
 
35
34
  should "find and replace wiki link markup" do
@@ -39,13 +38,26 @@ wiki_link
39
38
 
40
39
  should "permalink topics when making wiki links" do
41
40
  assert_equal "http://www.example.com/foo/cheese-tastes-good",
42
- @stripe.wiki_link("cheese tastes good")
41
+ @stripe.wiki_link("-cheese tastes good>")
43
42
  end
44
43
 
45
44
  should "not be greedy in matching" do
46
45
  stripe = Flannel::Stripe.stitch("a -foo> and a -bar>.")
47
- assert_equal 'a <a href="foo">foo</a> and a <a href="bar">bar</a>.',
48
- stripe.build_wiki_links
46
+ assert_equal 'a <a href="foo">foo</a> and a <a href="bar">bar</a>.', stripe.build_wiki_links
47
+ end
48
+ end
49
+
50
+ context "subdirectories" do
51
+ setup do
52
+ @stripe = Flannel::Stripe.stitch "I think it -cheese/tastes good>."
53
+ end
54
+
55
+ should "handle subdirectories" do
56
+ assert_equal "cheese/tastes-good", @stripe.wiki_link("-cheese/tastes good>")
57
+ end
58
+
59
+ should "not display directory info" do
60
+ assert_equal 'I think it <a href="cheese/tastes-good">tastes good</a>.', @stripe.build_wiki_links
49
61
  end
50
62
  end
51
63
 
data/test/test_helper.rb CHANGED
@@ -1,10 +1,27 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'shoulda'
4
+ require 'fileutils'
4
5
 
5
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
7
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
8
  require 'flannel'
8
9
 
9
10
  class Test::Unit::TestCase
11
+ def assert_fail message
12
+ assert false, message
13
+ end
14
+
15
+ def clear_dir dirname
16
+ Dir.foreach(dirname) do |f|
17
+ path = File.join(dirname, f)
18
+ if f == '.' or f == '..' then
19
+ next
20
+ elsif
21
+ File.directory?(path) then FileUtils.rm_rf(path)
22
+ else
23
+ FileUtils.rm( path )
24
+ end
25
+ end
26
+ end
10
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flannel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamal Hansen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-10 00:00:00 -06:00
12
+ date: 2010-01-14 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -76,14 +76,17 @@ files:
76
76
  - features/wiki_links.feature
77
77
  - flannel.gemspec
78
78
  - lib/flannel.rb
79
+ - lib/flannel/cache_location_does_not_exist_error.rb
79
80
  - lib/flannel/cutting_board.rb
80
81
  - lib/flannel/feed_parser.rb
82
+ - lib/flannel/file_cache.rb
81
83
  - lib/flannel/shears.rb
82
84
  - lib/flannel/square.rb
83
85
  - lib/flannel/stripe.rb
84
86
  - lib/flannel/wrappable.rb
85
87
  - test/cutting_board_test.rb
86
88
  - test/feed_parser_test.rb
89
+ - test/file_cache_test.rb
87
90
  - test/flannel_test.rb
88
91
  - test/shears_test.rb
89
92
  - test/square_test.rb
@@ -119,6 +122,7 @@ specification_version: 3
119
122
  summary: A soft comfortable worn in markup language for Ruby
120
123
  test_files:
121
124
  - test/test_helper.rb
125
+ - test/file_cache_test.rb
122
126
  - test/stripe_test.rb
123
127
  - test/cutting_board_test.rb
124
128
  - test/feed_parser_test.rb