smartdown 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ require 'smartdown/api/node'
2
+ module Smartdown
3
+ module Api
4
+ class Coversheet < Node
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'smartdown/parser/directory_input'
2
+
3
+ module Smartdown
4
+ module Api
5
+ class DirectoryInput < Smartdown::Parser::DirectoryInput
6
+ def initialize(coversheet_path)
7
+ super(coversheet_path)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,119 @@
1
+ require 'smartdown'
2
+ require 'smartdown/engine'
3
+ require 'smartdown/api/state'
4
+ require 'smartdown/api/coversheet'
5
+ require 'smartdown/api/question_page'
6
+ require 'smartdown/api/outcome'
7
+
8
+ module Smartdown
9
+ module Api
10
+ class Flow
11
+
12
+ def initialize(smartdown_input)
13
+ @smartdown_flow = Smartdown::Parser::FlowInterpreter.new(smartdown_input).interpret
14
+ @engine = Smartdown::Engine.new(@smartdown_flow)
15
+ end
16
+
17
+ def state(started, responses)
18
+ state = smartdown_state(started, responses)
19
+ State.new(transform_node(node_by_name(state.get(:current_node))),
20
+ previous_question_nodes_for(state),
21
+ responses
22
+ )
23
+ end
24
+
25
+ def name
26
+ @smartdown_flow.name
27
+ end
28
+
29
+ def title
30
+ coversheet.title
31
+ end
32
+
33
+ def meta_description
34
+ front_matter.meta_description
35
+ end
36
+
37
+ def need_id
38
+ front_matter.satisfies_need
39
+ end
40
+
41
+ def status
42
+ front_matter.status
43
+ end
44
+
45
+ def draft?
46
+ status == 'draft'
47
+ end
48
+
49
+ def transition?
50
+ status == 'transition'
51
+ end
52
+
53
+ def published?
54
+ status == 'published'
55
+ end
56
+
57
+ def nodes
58
+ @smartdown_flow.nodes.map{ |node| transform_node(node) }
59
+ .select{ |node| (node.is_a? Smartdown::Api::QuestionPage) ||
60
+ (node.is_a? Smartdown::Api::Outcome)
61
+ }
62
+ end
63
+
64
+ def question_pages
65
+ nodes.select{ |node| node.is_a? Smartdown::Api::QuestionPage }
66
+ end
67
+
68
+ def outcomes
69
+ nodes.select{ |node| node.is_a? Smartdown::Api::Outcome}
70
+ end
71
+
72
+ private
73
+
74
+ def transform_node(node)
75
+ if node.elements.any?{|element| element.is_a? Smartdown::Model::Element::StartButton}
76
+ Smartdown::Api::Coversheet.new(node)
77
+ elsif node.elements.any?{|element| element.is_a? Smartdown::Model::NextNodeRules}
78
+ if node.elements.any?{|element| element.is_a? Smartdown::Model::Element::MultipleChoice}
79
+ Smartdown::Api::QuestionPage.new(node)
80
+ else
81
+ #TODO: support other types of questions
82
+ end
83
+ else
84
+ Smartdown::Api::Outcome.new(node)
85
+ end
86
+ end
87
+
88
+ def coversheet
89
+ @coversheet ||= Smartdown::Api::Coversheet.new(@smartdown_flow.coversheet)
90
+ end
91
+
92
+ def front_matter
93
+ @front_matter ||= coversheet.front_matter
94
+ end
95
+
96
+ def smartdown_state(started, responses)
97
+ smartdown_responses = responses.clone
98
+ if started
99
+ smartdown_responses.unshift('y')
100
+ end
101
+ @engine.process(smartdown_responses)
102
+ end
103
+
104
+ def node_by_name(node_name)
105
+ @smartdown_flow.node(node_name)
106
+ end
107
+
108
+ def previous_question_nodes_for(state)
109
+ node_path = state.get('path')
110
+ return [] if node_path.empty?
111
+
112
+ node_path[1..-1].map do |node_name|
113
+ node_by_name(node_name)
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,25 @@
1
+ require 'smartdown/api/question'
2
+
3
+ module Smartdown
4
+ module Api
5
+ class MultipleChoice < Question
6
+ def options
7
+ question = elements.find{|element| element.is_a? Smartdown::Model::Element::MultipleChoice}
8
+ question.choices.map do |choice|
9
+ OpenStruct.new(:label => choice[1], :value => choice[0])
10
+ end
11
+ end
12
+
13
+ def name
14
+ question = elements.find{|element| element.is_a? Smartdown::Model::Element::MultipleChoice}
15
+ question.name
16
+ end
17
+
18
+ #TODO: move to presenters in smart-answer app
19
+ def partial_template_name
20
+ "multiple_choice_question"
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,67 @@
1
+ module Smartdown
2
+ module Api
3
+ class Node
4
+
5
+ attr_reader :title ,:elements, :front_matter, :name
6
+
7
+ def initialize(node)
8
+ node_elements = node.elements.clone
9
+ headings = node_elements.select {
10
+ |element| element.is_a? Smartdown::Model::Element::MarkdownHeading
11
+ }
12
+ @title = headings.first.content.to_s if headings.first
13
+ node_elements.delete(headings.first) #Remove page title
14
+ @elements = node_elements
15
+ @front_matter = node.front_matter
16
+ @name = node.name
17
+ end
18
+
19
+ def has_title?
20
+ !!title
21
+ end
22
+
23
+ def body
24
+ elements_before_smartdown = elements.take_while{|element| !smartdown_element?(element)}
25
+ build_govspeak(elements_before_smartdown)
26
+ end
27
+
28
+ def has_body?
29
+ !!body
30
+ end
31
+
32
+ def has_devolved_body?
33
+ !!devolved_body
34
+ end
35
+
36
+ def devolved_body
37
+ elements_after_smartdown = elements.drop_while{|element| !smartdown_element?(element)}
38
+ build_govspeak(elements_after_smartdown)
39
+ end
40
+
41
+ def next_nodes
42
+ elements.select{ |element| element.is_a? Smartdown::Model::NextNodeRules }
43
+ end
44
+
45
+ def permitted_next_nodes
46
+ next_nodes
47
+ end
48
+
49
+ private
50
+
51
+ def markdown_element?(element)
52
+ (element.is_a? Smartdown::Model::Element::MarkdownParagraph) || (element.is_a? Smartdown::Model::Element::MarkdownHeading)
53
+ end
54
+
55
+ def smartdown_element?(element)
56
+ !markdown_element?(element)
57
+ end
58
+
59
+ def build_govspeak(elements)
60
+ markdown_elements = elements.select do |element|
61
+ markdown_element?(element)
62
+ end
63
+ GovspeakPresenter.new(markdown_elements.map(&:content).join("\n")).html
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,16 @@
1
+ module Smartdown
2
+ module Api
3
+ class Outcome < Node
4
+
5
+ def has_next_steps?
6
+ !!next_steps
7
+ end
8
+
9
+ def next_steps
10
+ next_step_element = elements.find{|element| element.is_a? Smartdown::Model::Element::NextSteps}
11
+ GovspeakPresenter.new(next_step_element.content).html if next_step_element
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ module Smartdown
2
+ module Api
3
+ class PreviousQuestion
4
+
5
+ attr_reader :response, :title
6
+
7
+ def initialize(title, question_element, response, modifiable)
8
+ @title = title
9
+ @question_element = question_element
10
+ @response = response
11
+ @modifiable = modifiable
12
+ end
13
+
14
+ #TODO: remove need for this method by impleemnting modification properly
15
+ def modifiable?
16
+ @modifiable
17
+ end
18
+
19
+ #TODO: to be moved to presenter
20
+ def multiple_responses?
21
+ false
22
+ end
23
+
24
+ #TODO: move to presenter, this object API should only expose question_element.choices
25
+ def response_label(value=response)
26
+ @question_element.choices.fetch(value)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,76 @@
1
+ module Smartdown
2
+ module Api
3
+ class Question
4
+
5
+ attr_reader :number
6
+
7
+ def initialize(elements, number=nil)
8
+ @elements = elements
9
+ @number = number
10
+ end
11
+
12
+ #TODO: this assumes the title is the first element
13
+ def title
14
+ elements.first.content
15
+ end
16
+
17
+ def has_body?
18
+ !!body
19
+ end
20
+
21
+ def body
22
+ elements_before_smartdown = elements[1..-1].take_while{|element| !smartdown_element?(element)}
23
+ build_govspeak(elements_before_smartdown)
24
+ end
25
+
26
+ def has_hint?
27
+ !!hint
28
+ end
29
+
30
+ #TODO: confirm we can delete this
31
+ # Usage TBC, most hints should actually be `body`s, semi-deprecated
32
+ # As we transition content we should better define it, or remove it
33
+ def hint
34
+ end
35
+
36
+ def prefix
37
+ "todo prefix"
38
+ end
39
+
40
+ def suffix
41
+ "todo suffix"
42
+ end
43
+
44
+ def subtitle
45
+ "todo subtitle"
46
+ end
47
+
48
+ #TODO
49
+ def error
50
+ end
51
+
52
+ #TODO: should not be needed
53
+ def responses
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :elements
59
+
60
+ def markdown_element?(element)
61
+ (element.is_a? Smartdown::Model::Element::MarkdownParagraph) || (element.is_a? Smartdown::Model::Element::MarkdownHeading)
62
+ end
63
+
64
+ def smartdown_element?(element)
65
+ !markdown_element?(element)
66
+ end
67
+
68
+ def build_govspeak(elements)
69
+ markdown_elements = elements.select do |element|
70
+ markdown_element?(element)
71
+ end
72
+ GovspeakPresenter.new(markdown_elements.map(&:content).join("\n")).html
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,15 @@
1
+ require 'smartdown/api/multiple_choice'
2
+
3
+ module Smartdown
4
+ module Api
5
+ class QuestionPage < Node
6
+ def questions
7
+ elements.slice_before do |element|
8
+ element.is_a? Smartdown::Model::Element::MarkdownHeading
9
+ end.each_with_index.map do |question_element_group, index|
10
+ Smartdown::Api::MultipleChoice.new(question_element_group, index+1)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,58 @@
1
+ require 'smartdown/api/previous_question'
2
+
3
+ module Smartdown
4
+ module Api
5
+ class State
6
+
7
+ attr_reader :responses, :current_node
8
+
9
+ def initialize(current_node, previous_questionpage_smartdown_nodes, responses)
10
+ @current_node = current_node
11
+ @previous_question_page_nodes = previous_questionpage_smartdown_nodes
12
+ @responses = responses
13
+ end
14
+
15
+ def started?
16
+ !current_node.is_a? Smartdown::Api::Coversheet
17
+ end
18
+
19
+ def finished?
20
+ current_node.is_a? Smartdown::Api::Outcome
21
+ end
22
+
23
+ #TODO: refactor this :-O
24
+ def previous_questions
25
+ response_index = 0
26
+ previous_question_nodes.map.each_with_index do |previous_questions, node_index|
27
+ previous_questions.map.each_with_index do |previous_question, index|
28
+ previous_question = Smartdown::Api::PreviousQuestion.new(
29
+ previous_question_title_nodes[node_index][index].content,
30
+ previous_question,
31
+ responses[response_index],
32
+ index == 0
33
+ )
34
+ response_index+=1
35
+ previous_question
36
+ end
37
+ end.flatten
38
+ end
39
+
40
+ def previous_question_nodes
41
+ @previous_question_page_nodes.map(&:questions)
42
+ end
43
+
44
+ def previous_question_title_nodes
45
+ @previous_question_page_nodes.map(&:question_titles)
46
+ end
47
+
48
+ def current_question_number
49
+ responses.count + 1
50
+ end
51
+
52
+ private
53
+
54
+ attr_reader :smartdown_state, :previous_question_page_nodes
55
+
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Smartdown
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2014-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parslet
16
- requirement: &10785560 !ruby/object:Gem::Requirement
16
+ requirement: &20994400 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.6.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *10785560
24
+ version_requirements: *20994400
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &10784820 !ruby/object:Gem::Requirement
27
+ requirement: &20993600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *10784820
35
+ version_requirements: *20993600
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &10784240 !ruby/object:Gem::Requirement
38
+ requirement: &20993000 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *10784240
46
+ version_requirements: *20993000
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: gem_publisher
49
- requirement: &10783580 !ruby/object:Gem::Requirement
49
+ requirement: &20992380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *10783580
57
+ version_requirements: *20992380
58
58
  description:
59
59
  email: david.heath@digital.cabinet-office.gov.uk
60
60
  executables:
@@ -79,6 +79,16 @@ files:
79
79
  - lib/smartdown/parser/element/next_steps.rb
80
80
  - lib/smartdown/parser/element/markdown_heading.rb
81
81
  - lib/smartdown/parser/flow_interpreter.rb
82
+ - lib/smartdown/api/coversheet.rb
83
+ - lib/smartdown/api/question.rb
84
+ - lib/smartdown/api/flow.rb
85
+ - lib/smartdown/api/question_page.rb
86
+ - lib/smartdown/api/state.rb
87
+ - lib/smartdown/api/node.rb
88
+ - lib/smartdown/api/directory_input.rb
89
+ - lib/smartdown/api/previous_question.rb
90
+ - lib/smartdown/api/outcome.rb
91
+ - lib/smartdown/api/multiple_choice.rb
82
92
  - lib/smartdown/version.rb
83
93
  - lib/smartdown/engine/node_presenter.rb
84
94
  - lib/smartdown/engine/state.rb
@@ -157,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
167
  version: '0'
158
168
  segments:
159
169
  - 0
160
- hash: -476092451501996578
170
+ hash: 3595553799676610551
161
171
  required_rubygems_version: !ruby/object:Gem::Requirement
162
172
  none: false
163
173
  requirements:
@@ -166,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
176
  version: '0'
167
177
  segments:
168
178
  - 0
169
- hash: -476092451501996578
179
+ hash: 3595553799676610551
170
180
  requirements: []
171
181
  rubyforge_project:
172
182
  rubygems_version: 1.8.11