smartdown 0.1.0 → 0.1.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,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