pdf-storycards 0.0.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.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2007-12-27
2
+
3
+ * Initial release
4
+
@@ -0,0 +1,17 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/stories2cards
6
+ lib/pdf/storycards.rb
7
+ lib/pdf/storycards/scenario.rb
8
+ lib/pdf/storycards/story.rb
9
+ lib/pdf/storycards/story_capturing_mediator.rb
10
+ lib/pdf/storycards/writer.rb
11
+ spec/addition
12
+ spec/calculator_stories
13
+ spec/pdf/storycards/story_capturing_mediator_spec.rb
14
+ spec/pdf/storycards/story_spec.rb
15
+ spec/pdf/storycards/writer_spec.rb
16
+ spec/rspec_suite.rb
17
+ spec/spec_helper.rb
@@ -0,0 +1,55 @@
1
+ PDF StoryCards
2
+ by Luke Melia
3
+ http://www.lukemelia.com/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Provides a script and library to parses stories saved in the RSpec
8
+ plain text story format and saves a PDF file with printable 3"x5"
9
+ index cards suitable for using in agile planning and prioritization.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * Create a PDF with each page as a 3x5 sheet, or as 4 cards per 8.5 x 11 sheet
14
+ * Currently reads stories from a single file.
15
+ * TODO: Take a directory and find all stories in it
16
+ * TODO: Take stories via STDIN
17
+ * TODO: Improve test coverage
18
+
19
+ == SYNOPSIS:
20
+
21
+ StorycardPdfWriter.make_pdf("/tmp/stories.txt", "/tmp/storycards.pdf", :style => :card_1up)
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * RSpec (for parsing stories)
26
+ * PDF::Writer (for creating PDFs)
27
+
28
+ == INSTALL:
29
+
30
+ sudo gem install storycards
31
+
32
+ == LICENSE:
33
+
34
+ (The MIT License)
35
+
36
+ Copyright (c) 2007 Luke Melia
37
+
38
+ Permission is hereby granted, free of charge, to any person obtaining
39
+ a copy of this software and associated documentation files (the
40
+ 'Software'), to deal in the Software without restriction, including
41
+ without limitation the rights to use, copy, modify, merge, publish,
42
+ distribute, sublicense, and/or sell copies of the Software, and to
43
+ permit persons to whom the Software is furnished to do so, subject to
44
+ the following conditions:
45
+
46
+ The above copyright notice and this permission notice shall be
47
+ included in all copies or substantial portions of the Software.
48
+
49
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
50
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
53
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
54
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
55
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ dir = File.dirname(__FILE__)
6
+ lib_path = File.expand_path("#{dir}/lib")
7
+ $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
8
+ require 'pdf/storycards'
9
+ ENV["VERSION"] = PDF::Storycards::VERSION
10
+
11
+ Hoe.new('pdf-storycards', PDF::Storycards::VERSION) do |p|
12
+ p.rubyforge_name = 'pdf-storycards'
13
+ p.author = 'Luke Melia'
14
+ p.email = 'luke@lukemelia.com'
15
+ p.summary = 'Utilities for generating printable story cards for agile planning and measurement'
16
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
17
+ # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
18
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
19
+ p.extra_deps << ['pdf-writer', '>= 1.1.7']
20
+ p.extra_deps << ['rspec', '>= 1.1.1']
21
+ end
22
+
23
+ # vim: syntax=Ruby
@@ -0,0 +1,129 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # == Synopsis
4
+ # stories2cards parses stories saved in the RSpec plain text story
5
+ # format and saves a PDF file with printable 3"x5"" index cards
6
+ # suitable for using in agile planning and prioritization.
7
+ #
8
+ # == Examples
9
+ # This command outputs a PDF consisting of one card for each story and
10
+ # narrative defined in stories.txt and saves it as stories.pdf
11
+ #
12
+ # stories2cards stories.txt
13
+ #
14
+ # Other examples
15
+ #
16
+ # stories2cards stories.txt -o /tmp/cards.pdf
17
+ # stories2cards stories.txt --style=4up
18
+ #
19
+ # == Usage
20
+ # stories2cards [options] text_file_with_stories
21
+ #
22
+ # For help use stories2cards -h
23
+ #
24
+ # == Options
25
+ # -h, --help Displays help message
26
+ # -v, --version Display the version, then exit
27
+ # -o, --output=PATH Specify the path to the PDF file
28
+ # to be created, defaults to storycards.pdf
29
+ # -s, --style=1up|4up Defaults to 1up
30
+ # -b, --[no-]borders Print borders (only has effect with 4up style
31
+ #
32
+ # == Author
33
+ # Luke Melia
34
+ #
35
+ # == Copyright
36
+ # Copyright (c) 2007 Luke Melia. Licensed under the MIT License
37
+ # http://www.opensource.org/licenses/mit-license.php
38
+
39
+ require 'optparse'
40
+ require 'rdoc/usage'
41
+ require 'ostruct'
42
+
43
+ begin
44
+ require 'pdf/storycards'
45
+ rescue LoadError => le
46
+ if le.message =~ %r{pdf/storycards$}
47
+ root = File.dirname(File.dirname(File.expand_path(__FILE__)))
48
+ $LOAD_PATH.unshift(File.join(root, "lib"))
49
+ require 'pdf/storycards'
50
+ else
51
+ raise
52
+ end
53
+ end
54
+
55
+ class App
56
+
57
+ attr_reader :options
58
+
59
+ def initialize(arguments, stdin)
60
+ @arguments = arguments
61
+ @stdin = stdin
62
+
63
+ # Set defaults
64
+ @options = OpenStruct.new
65
+ @options.output = "storycards.pdf"
66
+ @options.style = :"1up"
67
+ end
68
+
69
+ # Parse options, check arguments, then process the command
70
+ def run
71
+ if parsed_options? && arguments_valid?
72
+ process_arguments
73
+ process_command
74
+ else
75
+ output_usage
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def parsed_options?
82
+
83
+ # Specify options
84
+ opts = OptionParser.new
85
+ opts.on('-v', '--version') { output_version ; exit 0 }
86
+ opts.on('-h', '--help') { output_help }
87
+ opts.on('-o', '--output [PATH]') { |path| @options.output = path }
88
+ opts.on('-s', '--style [STYLE]', [:"1up", :"4up"]) { |style| @options.style = style }
89
+ opts.on("-b", "--[no-]borders", "Print borders") { |b| options.borders = b }
90
+ opts.parse!(@arguments) rescue return false
91
+
92
+ true
93
+ end
94
+
95
+ # True if required arguments were provided
96
+ def arguments_valid?
97
+ return false unless @arguments.length == 1
98
+ return false unless File.exists?(@arguments[0])
99
+ return true
100
+ end
101
+
102
+ # Setup the arguments
103
+ def process_arguments
104
+ @source_file = @arguments[0]
105
+ end
106
+
107
+ def output_help
108
+ output_version
109
+ RDoc::usage() #exits app
110
+ end
111
+
112
+ def output_usage
113
+ RDoc::usage('usage') # gets usage from comments above
114
+ end
115
+
116
+ def output_version
117
+ puts "#{File.basename(__FILE__)} version #{PDF::Storycards::VERSION}"
118
+ end
119
+
120
+ def process_command
121
+ style = :card_1up if @options.style == :"1up"
122
+ style = :letter_4up if @options.style == :"4up"
123
+ PDF::Storycards::Writer.make_pdf(@source_file, @options.output, :style => style)
124
+ end
125
+ end
126
+
127
+ # Create and run the application
128
+ app = App.new(ARGV, STDIN)
129
+ app.run
@@ -0,0 +1,10 @@
1
+ module PDF
2
+ module Storycards
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
6
+
7
+ require 'pdf/storycards/scenario'
8
+ require 'pdf/storycards/story'
9
+ require 'pdf/storycards/story_capturing_mediator'
10
+ require 'pdf/storycards/writer'
@@ -0,0 +1,21 @@
1
+ module PDF
2
+ module Storycards
3
+ class Scenario
4
+ def initialize(name)
5
+ @name = name
6
+ @steps = []
7
+ end
8
+
9
+ def add_step(step)
10
+ @steps << step
11
+ end
12
+ end
13
+
14
+ class Step
15
+ def initialize(type, name)
16
+ @type = type
17
+ @name = name
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module PDF
2
+ module Storycards
3
+ class Story
4
+ def initialize(title, narrative)
5
+ @title = title
6
+ @narrative = narrative
7
+ def @narrative.to_sentence
8
+ self.sub(/^\s*I want/, ", I want").gsub(/^\s*So that/, ", so that").split($/).join(" ").gsub(' ,',',').squeeze(" ")
9
+ end
10
+ @scenarios = []
11
+ end
12
+
13
+ attr_accessor :title, :narrative
14
+
15
+ def add_scenario(scenario)
16
+ @scenarios << scenario
17
+ end
18
+
19
+ def current_scenario
20
+ @scenarios.last
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,52 @@
1
+ # RSpec's story parser needs to be constructed with a Mediator. The mediator defined in the class
2
+ # below simply collects stories and exposes the collection as StoryCapturingMediator#stories.
3
+ #
4
+ # It also sprinkles in a magic method on Story#narrative called to_sentence, which formats the
5
+ # story narrative as a single sentence without newlines.
6
+ module PDF
7
+ module Storycards
8
+
9
+ class StoryCapturingMediator
10
+
11
+ def initialize
12
+ @stories = []
13
+ end
14
+
15
+ attr_reader :stories
16
+
17
+ def create_story(title, narrative)
18
+ @stories << Story.new(title, narrative)
19
+ end
20
+
21
+ def create_scenario(title)
22
+ current_story.add_scenario Scenario.new(title)
23
+ end
24
+
25
+ def create_given(name)
26
+ current_scenario.add_step Step.new('Given', name)
27
+ end
28
+
29
+ def create_given_scenario(name)
30
+ current_scenario.add_step Step.new('GivenScenario', name)
31
+ end
32
+
33
+ def create_when(name)
34
+ current_scenario.add_step Step.new('When', name)
35
+ end
36
+
37
+ def create_then(name)
38
+ current_scenario.add_step Step.new('Then', name)
39
+ end
40
+
41
+ private
42
+ def current_story
43
+ @stories.last
44
+ end
45
+
46
+ def current_scenario
47
+ current_story.current_scenario
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,91 @@
1
+ require 'pdf/writer'
2
+ require 'spec/story/runner/story_parser.rb'
3
+
4
+ module PDF
5
+ module Storycards
6
+ class Writer
7
+
8
+ def self.make_pdf( path, output_path = 'storycards.pdf', opts = {} )
9
+ output_path = 'storycards.pdf' if output_path.nil?
10
+ opts[:style] = :card_1up unless opts[:style]
11
+ opts[:border] = false unless opts[:border]
12
+
13
+ stories = self.parse_stories(path)
14
+
15
+ if opts[:style] == :card_1up
16
+ pdf = PDF::Writer.new(:paper => [7.62, 12.7], :orientation => :landscape) #3x5 card
17
+ pdf.margins_mm 8
18
+ pdf.move_pointer(-60)
19
+
20
+ stories.each_with_index do |story, index|
21
+ pdf.y = 0 if index > 0
22
+ print_card_text(pdf, story)
23
+ end
24
+
25
+ pdf.save_as(output_path)
26
+ return output_path
27
+
28
+ elsif opts[:style] == :letter_4up
29
+
30
+ pdf = PDF::Writer.new(:paper => "LETTER", :orientation => :landscape)
31
+ card_width = PDF::Writer.in2pts(5)
32
+ card_height = PDF::Writer.in2pts(3)
33
+ margin = PDF::Writer.in2pts(0.33)
34
+ gutter = margin
35
+ padding = 10
36
+
37
+ pdf.start_columns(2, gutter)
38
+ stories.each_with_index do |story, index|
39
+
40
+ is_laying_out_left_hand_column = (index < 2)
41
+ if is_laying_out_left_hand_column
42
+ rect_x = margin
43
+ else
44
+ rect_x = pdf.page_width - margin - card_width
45
+ end
46
+
47
+ is_laying_out_top_row = (index % 2 == 0)
48
+ if is_laying_out_top_row
49
+ pdf.start_new_page unless index == 0
50
+ pdf.y = pdf.page_height - margin - padding
51
+ rect_y = pdf.page_height - margin - card_height
52
+ else
53
+ rect_y = margin
54
+ pdf.y = margin + card_height - padding
55
+ end
56
+
57
+ print_border(pdf, rect_x, rect_y, card_width, card_height) if opts[:border]
58
+ print_card_text(pdf, story, padding)
59
+ end
60
+
61
+ pdf.save_as(output_path)
62
+ return output_path
63
+
64
+ end
65
+ end
66
+ private
67
+
68
+ def self.print_border(pdf, x, y, width, height)
69
+ pdf.stroke_color(Color::RGB::Black)
70
+ pdf.stroke_style(PDF::Writer::StrokeStyle.new(1))
71
+ pdf.rectangle(rect_x, rect_y, card_width, card_height).close_stroke
72
+ end
73
+
74
+ def self.parse_stories(path)
75
+ story_mediator = StoryCapturingMediator.new
76
+ story_parser = Spec::Story::Runner::StoryParser.new(story_mediator)
77
+ story_text = File.read(path)
78
+ story_parser.parse(story_text.split("\n"))
79
+ return story_mediator.stories
80
+ end
81
+
82
+ def self.print_card_text(pdf, story, padding = 0)
83
+ pdf.text "<b>#{story.title}</b>", :font_size => 18, :justification => :center,
84
+ :left => padding, :right => padding
85
+ pdf.move_pointer(12)
86
+ pdf.text story.narrative.to_sentence, :justification => :left, :font_size => 14,
87
+ :left => padding, :right => padding
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,34 @@
1
+ This is a story about a calculator. The text up here above the Story: declaration
2
+ won't be processed, so you can write whatever you wish!
3
+
4
+ Story: simple addition
5
+
6
+ As an accountant
7
+ I want to add numbers
8
+ So that I can count beans
9
+
10
+ Scenario: add one plus one
11
+ Given an addend of 1
12
+ And an addend of 1
13
+
14
+ When the addends are addeds
15
+
16
+ Then the sum should be 3
17
+ And the corks should be popped
18
+
19
+ Scenario: add two plus five
20
+ Given an addend of 2
21
+ And an addend of 5
22
+
23
+ When the addends are added
24
+
25
+ Then the sum should be 7
26
+ Then it should snow
27
+
28
+ Scenario: add three more
29
+ GivenScenario add two plus five
30
+ And an addend of 3
31
+
32
+ When the addends are added
33
+
34
+ Then the sum should be 10
@@ -0,0 +1,66 @@
1
+ This is a story about a calculator. The text up here above the Story: declaration
2
+ won't be processed, so you can write whatever you wish!
3
+
4
+ Story: simple addition
5
+
6
+ As an accountant
7
+ I want to add numbers
8
+ So that I can count beans
9
+
10
+ Scenario: add one plus one
11
+ Given an addend of 1
12
+ And an addend of 1
13
+
14
+ When the addends are addeds
15
+
16
+ Then the sum should be 3
17
+ And the corks should be popped
18
+
19
+ Scenario: add two plus five
20
+ Given an addend of 2
21
+ And an addend of 5
22
+
23
+ When the addends are added
24
+
25
+ Then the sum should be 7
26
+ Then it should snow
27
+
28
+ Scenario: add three more
29
+ GivenScenario add two plus five
30
+ And an addend of 3
31
+
32
+ When the addends are added
33
+
34
+ Then the sum should be 10
35
+
36
+ Story: simple subtraction
37
+
38
+ As an accountant
39
+ I want to subtract numbers
40
+ So that I can count beans
41
+
42
+ Scenario: subtract one minus one
43
+ Given an argument of 1
44
+ And an argument of 1
45
+
46
+ When the second argument is subtracted from the first argument
47
+
48
+ Then the different should be 0
49
+ And the corks should be popped
50
+
51
+ Scenario: subtract two from five
52
+ Given an argument of 5
53
+ And an argument of 2
54
+
55
+ When the second argument is subtracted from the first argument
56
+
57
+ Then the difference should be 3
58
+ Then it should snow
59
+
60
+ Scenario: subtract two more
61
+ GivenScenario subtract two from five
62
+ And an argument of 2
63
+
64
+ When the result is reduced by the argument
65
+
66
+ Then the result should be 1
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe PDF::Storycards::StoryCapturingMediator do
4
+
5
+ before(:each) do
6
+ @mediator = PDF::Storycards::StoryCapturingMediator.new
7
+ end
8
+
9
+ describe "initial state" do
10
+ it "should have an empty list of stories" do
11
+ @mediator.stories.should == []
12
+ end
13
+ end
14
+
15
+ it "should add stories when sent :create_story" do
16
+ @mediator.create_story('my title', 'my narrative')
17
+ @mediator.stories.length.should == 1
18
+ @mediator.stories.first.should be_an_instance_of(PDF::Storycards::Story)
19
+ end
20
+
21
+ describe "after having a story added" do
22
+ before(:each) do
23
+ @mediator.create_story('User joins a Group',
24
+ "As a user
25
+ I want to be able to join a group
26
+ So that I can connect to members with similar interests")
27
+ end
28
+
29
+ it "should have a story with the specified title" do
30
+ @mediator.stories.first.title.should == 'User joins a Group'
31
+ end
32
+
33
+ it "should have a story with the specified narrative" do
34
+ @mediator.stories.first.narrative.should =~ /As a user\s+I want to be able to join a group\s+So that I can connect to members with similar interests/
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe PDF::Storycards::Story do
4
+ before(:each) do
5
+ @story = PDF::Storycards::Story.new('User joins a Group',
6
+ "As a user
7
+ I want to be able to join a group
8
+ So that I can connect to members with similar interests")
9
+ end
10
+
11
+ it "should have the specified title" do
12
+ @story.title.should == 'User joins a Group'
13
+ end
14
+
15
+ it "should have the specified narrative" do
16
+ @story.narrative.should =~ /As a user\s+I want to be able to join a group\s+So that I can connect to members with similar interests/
17
+ end
18
+
19
+ it "should have a narrative that can be converted to a sentence without newlines" do
20
+ @story.narrative.to_sentence.should == 'As a user, I want to be able to join a group, so that I can connect to members with similar interests'
21
+ end
22
+
23
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ module PDF
4
+ class Writer
5
+ def save_as(path)
6
+ #no op
7
+ end
8
+ end
9
+ end
10
+
11
+ describe PDF::Storycards::Writer do
12
+
13
+ before(:all) do
14
+ @single_story_path = File.dirname(__FILE__) + '/../../addition'
15
+ @multiple_stories_path = File.dirname(__FILE__) + '/../../calculator_stories'
16
+ end
17
+
18
+ it "should parse an example plain text story file and create a new story" do
19
+ stories = PDF::Storycards::Writer.send(:parse_stories, @single_story_path)
20
+ stories.first.title.should == 'simple addition'
21
+ stories.first.narrative.should == "As an accountant\nI want to add numbers\nSo that I can count beans"
22
+ end
23
+
24
+ it "should not print border when printing 1-up" do
25
+ PDF::Storycards::Writer.should_not_receive(:print_border)
26
+ PDF::Storycards::Writer.make_pdf(@multiple_stories_path, 'storycards.pdf', :style => :card_1up)
27
+ end
28
+
29
+ it "should not print border when printing 4-up with default options" do
30
+ PDF::Storycards::Writer.should_not_receive(:print_border)
31
+ PDF::Storycards::Writer.make_pdf(@multiple_stories_path, 'storycards.pdf', :style => :letter_4up)
32
+ end
33
+
34
+ it "should print border when printing 4-up with border option set to true" do
35
+ PDF::Storycards::Writer.should_receive(:print_border).twice
36
+ PDF::Storycards::Writer.make_pdf(@multiple_stories_path, 'storycards.pdf', :style => :letter_4up, :border => true)
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ if __FILE__ == $0
5
+ dir = File.dirname(__FILE__)
6
+ Dir["#{dir}/**/*_spec.rb"].each do |file|
7
+ # puts "require '#{file}'"
8
+ require file
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'stringio'
2
+ require 'spec'
3
+ require 'spec/mocks'
4
+
5
+ dir = File.dirname(__FILE__)
6
+ lib_path = File.expand_path("#{dir}/../lib")
7
+ $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
8
+
9
+ require 'pdf/storycards'
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdf-storycards
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Luke Melia
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2007-12-29 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: pdf-writer
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.7
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: rspec
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.1.1
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.4.0
41
+ version:
42
+ description: "== FEATURES/PROBLEMS: * Create a PDF with each page as a 3x5 sheet, or as 4 cards per 8.5 x 11 sheet * Currently reads stories from a single file. * TODO: Take a directory and find all stories in it * TODO: Take stories via STDIN * TODO: Improve test coverage == SYNOPSIS: StorycardPdfWriter.make_pdf(\"/tmp/stories.txt\", \"/tmp/storycards.pdf\", :style => :card_1up) == REQUIREMENTS:"
43
+ email: luke@lukemelia.com
44
+ executables:
45
+ - stories2cards
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - History.txt
50
+ - Manifest.txt
51
+ - README.txt
52
+ files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - README.txt
56
+ - Rakefile
57
+ - bin/stories2cards
58
+ - lib/pdf/storycards.rb
59
+ - lib/pdf/storycards/scenario.rb
60
+ - lib/pdf/storycards/story.rb
61
+ - lib/pdf/storycards/story_capturing_mediator.rb
62
+ - lib/pdf/storycards/writer.rb
63
+ - spec/addition
64
+ - spec/calculator_stories
65
+ - spec/pdf/storycards/story_capturing_mediator_spec.rb
66
+ - spec/pdf/storycards/story_spec.rb
67
+ - spec/pdf/storycards/writer_spec.rb
68
+ - spec/rspec_suite.rb
69
+ - spec/spec_helper.rb
70
+ has_rdoc: true
71
+ homepage: http://www.zenspider.com/ZSS/Products/pdf-storycards/
72
+ post_install_message:
73
+ rdoc_options:
74
+ - --main
75
+ - README.txt
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ requirements: []
91
+
92
+ rubyforge_project: pdf-storycards
93
+ rubygems_version: 1.0.1
94
+ signing_key:
95
+ specification_version: 2
96
+ summary: Utilities for generating printable story cards for agile planning and measurement
97
+ test_files: []
98
+