brief 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +71 -55
  4. data/README.md +149 -48
  5. data/Rakefile +15 -5
  6. data/bin/brief +15 -28
  7. data/brief.gemspec +17 -11
  8. data/examples/blog/brief.rb +54 -0
  9. data/examples/blog/docs/an-intro-to-brief.html.md +9 -0
  10. data/lib/.DS_Store +0 -0
  11. data/lib/brief/briefcase.rb +78 -0
  12. data/lib/brief/cli/change.rb +14 -0
  13. data/lib/brief/cli/init.rb +66 -0
  14. data/{spec/fixtures/generated/project_overview.json → lib/brief/cli/publish.rb} +0 -0
  15. data/lib/brief/cli/write.rb +0 -0
  16. data/lib/brief/configuration.rb +19 -115
  17. data/lib/brief/core_ext.rb +11 -0
  18. data/lib/brief/document/content_extractor.rb +33 -0
  19. data/lib/brief/document/front_matter.rb +20 -0
  20. data/lib/brief/document/rendering.rb +37 -0
  21. data/lib/brief/document.rb +43 -38
  22. data/lib/brief/document_mapper.rb +158 -0
  23. data/lib/brief/dsl.rb +42 -0
  24. data/lib/brief/model/definition.rb +117 -0
  25. data/lib/brief/model.rb +177 -0
  26. data/lib/brief/repository.rb +57 -0
  27. data/lib/brief/version.rb +1 -7
  28. data/lib/brief.rb +35 -40
  29. data/spec/fixtures/example/brief.rb +27 -0
  30. data/spec/fixtures/example/docs/concept.html.md +5 -0
  31. data/spec/fixtures/example/docs/epic.html.md +19 -0
  32. data/spec/fixtures/example/docs/persona.html.md +5 -0
  33. data/spec/fixtures/example/docs/release.html.md +7 -0
  34. data/spec/fixtures/example/docs/resource.html.md +5 -0
  35. data/spec/fixtures/example/docs/user_story.html.md +24 -0
  36. data/spec/fixtures/example/docs/wireframe.html.md +5 -0
  37. data/spec/fixtures/example/models/epic.rb +16 -0
  38. data/spec/lib/brief/briefcase_spec.rb +27 -0
  39. data/spec/lib/brief/document_spec.rb +14 -22
  40. data/spec/lib/brief/dsl_spec.rb +4 -15
  41. data/spec/lib/brief/model_spec.rb +84 -0
  42. data/spec/lib/brief/repository_spec.rb +60 -0
  43. data/spec/spec_helper.rb +12 -14
  44. data/spec/support/test_helpers.rb +0 -0
  45. data/tasks/brief/release.rake +0 -0
  46. metadata +120 -110
  47. data/.gitignore +0 -1
  48. data/Guardfile +0 -5
  49. data/examples/project_overview.md +0 -23
  50. data/lib/brief/cli/commands/config.rb +0 -40
  51. data/lib/brief/cli/commands/publish.rb +0 -27
  52. data/lib/brief/cli/commands/write.rb +0 -27
  53. data/lib/brief/formatters/base.rb +0 -12
  54. data/lib/brief/formatters/github_milestone_rollup.rb +0 -52
  55. data/lib/brief/git.rb +0 -19
  56. data/lib/brief/github/wiki.rb +0 -9
  57. data/lib/brief/github.rb +0 -141
  58. data/lib/brief/github_client/authentication.rb +0 -32
  59. data/lib/brief/github_client/client.rb +0 -86
  60. data/lib/brief/github_client/commands.rb +0 -5
  61. data/lib/brief/github_client/issue_labels.rb +0 -65
  62. data/lib/brief/github_client/issues.rb +0 -22
  63. data/lib/brief/github_client/milestone_issues.rb +0 -13
  64. data/lib/brief/github_client/organization_activity.rb +0 -9
  65. data/lib/brief/github_client/organization_issues.rb +0 -13
  66. data/lib/brief/github_client/organization_repositories.rb +0 -20
  67. data/lib/brief/github_client/organization_users.rb +0 -9
  68. data/lib/brief/github_client/repository_events.rb +0 -8
  69. data/lib/brief/github_client/repository_issue_events.rb +0 -9
  70. data/lib/brief/github_client/repository_issues.rb +0 -8
  71. data/lib/brief/github_client/repository_labels.rb +0 -18
  72. data/lib/brief/github_client/repository_milestones.rb +0 -9
  73. data/lib/brief/github_client/request.rb +0 -181
  74. data/lib/brief/github_client/request_wrapper.rb +0 -121
  75. data/lib/brief/github_client/response_object.rb +0 -50
  76. data/lib/brief/github_client/single_repository.rb +0 -9
  77. data/lib/brief/github_client/user_activity.rb +0 -16
  78. data/lib/brief/github_client/user_gists.rb +0 -9
  79. data/lib/brief/github_client/user_info.rb +0 -9
  80. data/lib/brief/github_client/user_issues.rb +0 -13
  81. data/lib/brief/github_client/user_organizations.rb +0 -9
  82. data/lib/brief/github_client/user_repositories.rb +0 -9
  83. data/lib/brief/github_client.rb +0 -43
  84. data/lib/brief/handlers/base.rb +0 -62
  85. data/lib/brief/handlers/github_issue.rb +0 -41
  86. data/lib/brief/handlers/github_milestone.rb +0 -37
  87. data/lib/brief/handlers/github_wiki.rb +0 -11
  88. data/lib/brief/line.rb +0 -69
  89. data/lib/brief/parser.rb +0 -354
  90. data/lib/brief/publisher/handler_manager.rb +0 -47
  91. data/lib/brief/publisher.rb +0 -142
  92. data/lib/brief/tree.rb +0 -43
  93. data/lib/core_ext.rb +0 -37
  94. data/spec/fixtures/front_end_tutorial.md +0 -33
  95. data/spec/fixtures/generator_dsl_example.rb +0 -22
  96. data/spec/fixtures/project_overview.md +0 -48
  97. data/spec/fixtures/sample.md +0 -19
  98. data/spec/lib/brief/line_spec.rb +0 -11
  99. data/spec/lib/brief/parser_spec.rb +0 -12
@@ -1,181 +0,0 @@
1
- require 'rubygems'
2
- require 'escape_utils'
3
- require 'uri_template'
4
-
5
- class Brief::GithubClient::Request
6
-
7
- MissingArguments = Class.new(Exception)
8
-
9
- attr_accessor :options, :user, :org, :repo, :params, :headers, :github_token
10
-
11
- class << self
12
- attr_accessor :_required_arguments
13
- end
14
-
15
- def self.requires *args
16
- (self._required_arguments = args).uniq!
17
- end
18
-
19
- def self.required_arguments
20
- Array(self._required_arguments).uniq
21
- end
22
-
23
- def initialize(options={}, &block)
24
- @options = options.with_indifferent_access.dup
25
- @client, @user, @org, @repo, @github_token = options.values_at(:client, :user,:org,:repo,:github_token)
26
- @params = options[:params] || {}
27
- @headers = options[:headers] || {}
28
-
29
- instance_eval(&blk) if block_given?
30
-
31
- assert_valid_arguments!
32
- end
33
-
34
- def required_arguments
35
- Array(self.class._required_arguments)
36
- end
37
-
38
- def with_valid_arguments &blk
39
- instance_eval(&blk) if block_given?
40
- assert_valid_arguments!
41
- self
42
- end
43
-
44
- def assert_valid_arguments!
45
- return true if required_arguments.length > 0
46
-
47
- valid = required_arguments.all? do |arg|
48
- test = false
49
- test = true if !!self.send(arg).present?
50
- test = true if options.has_key?(arg)
51
-
52
- test
53
- end
54
-
55
- raise MissingArguments unless valid
56
- end
57
-
58
- def to_object
59
- req = self
60
-
61
- response_wrapper = lambda do |r|
62
- Brief::GithubClient::ResponseObject.new(r).with_request_object(req)
63
- end
64
-
65
- return object.map(&response_wrapper) if object.is_a?(Array)
66
-
67
- response_wrapper.call(object)
68
- end
69
-
70
- def object
71
- records
72
- end
73
-
74
- def refresh
75
- @request = nil
76
- self
77
- end
78
-
79
- def all
80
- to_object
81
- end
82
-
83
- def create params={}
84
- client.post_request(request_endpoint, params).request.run
85
- end
86
-
87
- def create_object params={}
88
- resp = create(params)
89
- Hashie::Mash.new(JSON.parse(resp.body))
90
- end
91
-
92
- def update record_id, params={}
93
- client.update_request("#{ request_endpoint }/#{ record_id }", params).request.run
94
- end
95
-
96
- def update_object record_id, params={}
97
- resp = update(record_id, params)
98
- Hashie::Mash.new(JSON.parse(resp.body))
99
- end
100
-
101
- def destroy record_id, params={}
102
- client.delete_request("#{ request_endpoint }/#{ record_id }").request.run
103
- end
104
-
105
- def show record_id, params={}
106
- client.get_request("#{ request_endpoint }/#{ record_id }", params).to_object
107
- end
108
-
109
- def client
110
- return @client if @client
111
-
112
- if impersonate_user.present?
113
- @client = Brief::GithubClient::Client.new(user: impersonate_user, headers: headers, github_token: github_token)
114
- end
115
-
116
- @client = Brief.github_client
117
- end
118
-
119
- def records
120
- @records = request.records
121
- end
122
-
123
- def results
124
- records
125
- end
126
-
127
- def result
128
- records
129
- end
130
-
131
- def request_endpoint
132
- options.fetch(:endpoint, endpoint)
133
- end
134
-
135
- def request refresh=false
136
- @request = nil if refresh
137
- @request ||= client.get_request(request_endpoint, params)
138
- end
139
-
140
- def organization_or_user
141
- supplied_org || user
142
- end
143
-
144
- def user_or_organization
145
- supplied_user || supplied_org
146
- end
147
-
148
- def org
149
- organization_or_user
150
- end
151
-
152
- # The idea of 'supplied' means it was provided to the object
153
- # and not calculated in any way. This is used when determining
154
- # the value for the endpoint, in the context of a github user vs github organization
155
- def supplied_org
156
- @org
157
- end
158
-
159
- def supplied_user
160
- @user
161
- end
162
-
163
- def supplied_repo
164
- @repo
165
- end
166
-
167
- protected
168
- def github_token
169
- @github_token || impersonate_user.try(:github_token) || Brief.config.github_token
170
- end
171
-
172
- def endpoint
173
- "users/#{ user }"
174
- end
175
-
176
- def impersonate_user
177
- if defined?(::User) && ::User.respond_to?(:find_by_github_nickname)
178
- @impersonate_user ||= ::User.find_by_github_nickname(user)
179
- end
180
- end
181
- end
@@ -1,121 +0,0 @@
1
- module Brief::GithubClient
2
-
3
- class RequestWrapper
4
- attr_accessor :request,:headers,:params,:type, :method
5
-
6
- class << self
7
- attr_accessor :request_cache, :response_cache
8
- end
9
-
10
- self.request_cache ||= Brief::GithubClient.request_cache
11
- self.response_cache ||= Brief::GithubClient.response_cache
12
-
13
- def initialize(type,params,headers)
14
- @type = type
15
- @params = params
16
- @headers = headers
17
- @method = :get
18
-
19
- @cache_key = Digest::MD5.hexdigest([params.to_json, type].to_json)
20
- end
21
-
22
- def url
23
- "https://api.github.com/#{ type }"
24
- end
25
-
26
- def request
27
- if method == :get
28
- @request = Typhoeus::Request.new url,
29
- method: method,
30
- headers: request_headers,
31
- params: params
32
- else
33
- @request = Typhoeus::Request.new url,
34
- method: method,
35
- headers: request_headers,
36
- body: JSON.generate(params)
37
- end
38
- end
39
-
40
- def get
41
- @method = :get
42
- self
43
- end
44
-
45
- def update
46
- @method = :patch
47
- self
48
- end
49
-
50
- def post
51
- @method = :post
52
- self
53
- end
54
-
55
- def create
56
- @method = :post
57
- self
58
- end
59
-
60
- def delete
61
- @method = :delete
62
- self
63
- end
64
-
65
- def request_headers
66
- if method == :get && cached_etag.present? && cached_etag.length > 1
67
- if Brief::GithubClient.enable_caching
68
- @headers["If-None-Match"] = cached_etag.split('|').first
69
- @headers["If-Modified-Since"] = cached_etag.split('|').last
70
- end
71
- end
72
-
73
- @headers
74
- end
75
-
76
- def cached_etag
77
- Brief::GithubClient.enable_caching ? self.class.request_cache[cache_key] : nil
78
- end
79
-
80
- def cache_key
81
- @cache_key
82
- end
83
-
84
- def cached?
85
- response.headers.try(:[],"Status") == "304 Not Modified"
86
- end
87
-
88
- def response
89
- return @response if @response
90
-
91
- @response = request.run
92
-
93
- if Brief::GithubClient.enable_caching && response.headers.try(:[],"Status") == "200 OK"
94
- self.class.request_cache[cache_key] = "#{response.headers.try(:[],"Etag")}|#{ response.headers.try(:[],"Last-Modified") }"
95
- self.class.response_cache[cache_key] = response.body
96
- end
97
-
98
- @response
99
- end
100
-
101
- def result
102
- @result ||= JSON.parse(response_body)
103
- end
104
-
105
- def response_body
106
- return response.body unless Brief::GithubClient.enable_caching
107
-
108
- self.class.response_cache.fetch(cache_key) do
109
- response.body
110
- end
111
- end
112
-
113
- def records
114
- result
115
- end
116
-
117
- def to_object
118
- Hashie::Mash.new(result)
119
- end
120
- end
121
- end
@@ -1,50 +0,0 @@
1
- module Brief::GithubClient
2
- class ResponseObject < Hashie::Mash
3
-
4
- def url_fields
5
- keys.grep(/_url/).inject({}) do |memo,field|
6
- memo[field] = self.send(field)
7
- memo
8
- end
9
- end
10
-
11
- def with_request_class obj
12
- @request_class = obj if obj
13
- self
14
- end
15
-
16
- def with_request_object obj
17
- @request_object = obj if obj
18
- self
19
- end
20
-
21
- def request_object
22
- @request_object
23
- end
24
-
25
- def request_class
26
- @request_class || Brief::GithubClient::Request
27
- end
28
-
29
- def fetch(relationship, params={})
30
- if endpoint_for(relationship)
31
- endpoint_url = endpoint_for(relationship)
32
- tmpl = URITemplate.new(endpoint_url)
33
- request_class.new(client: request_object.client, endpoint: tmpl.expand(params))
34
- end
35
- end
36
-
37
- def endpoint_for(relationship)
38
- url = url_for(relationship)
39
- url && url.gsub(%r{https://api.github.com/},'')
40
- end
41
-
42
- def url_for(relationship)
43
- field ="#{ relationship }_url"
44
-
45
- if has_key?(field)
46
- send(field)
47
- end
48
- end
49
- end
50
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class SingleRepository < Request
3
- requires :org, :repo
4
-
5
- def endpoint
6
- "repos/#{ org }/#{ repo }"
7
- end
8
- end
9
- end
@@ -1,16 +0,0 @@
1
- module Brief::GithubClient
2
- class UserActivity < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{user}/events"
7
- end
8
-
9
- def organization_repos
10
- all.select do |item|
11
- item.repo && item.repo.name.try(:match,org) rescue false
12
- end
13
- end
14
-
15
- end
16
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class UserGists < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{ user }/gists"
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class UserInfo < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{ user }"
7
- end
8
- end
9
- end
@@ -1,13 +0,0 @@
1
- module Brief::GithubClient
2
- class UserIssues < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{ user }/issues"
7
- end
8
-
9
- def params
10
- @params.merge(sort:"updated")
11
- end
12
- end
13
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class UserOrganizations < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{ user }/orgs"
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class UserRepositories < Request
3
- requires :user
4
-
5
- def endpoint
6
- "users/#{ user }/repos"
7
- end
8
- end
9
- end
@@ -1,43 +0,0 @@
1
- module Brief::GithubClient
2
- def self.default_organization
3
- Brief.profile.github_organization
4
- end
5
-
6
- def self.default_github_token
7
- Brief.profile.github_token
8
- end
9
-
10
- # Brief.github_client is useful for backend apps where there is a Brief configuration profile
11
- Brief.define_singleton_method(:github_client) do
12
- Brief::GithubClient::Client.new(github_token: Brief.profile.github_token)
13
- end
14
-
15
- class << self
16
- attr_accessor :request_cache,
17
- :response_cache,
18
- :enable_caching
19
- end
20
-
21
- self.request_cache ||= {}
22
- self.response_cache ||= {}
23
- self.enable_caching = false
24
-
25
- def self.clear_caches!
26
- self.request_cache = {}
27
- self.response_cache = {}
28
- end
29
- end
30
-
31
- require 'brief/github_client/authentication'
32
- require 'brief/github_client/client'
33
- require 'brief/github_client/request'
34
- require 'brief/github_client/request_wrapper'
35
- require 'brief/github_client/response_object'
36
- require 'brief/github_client/commands'
37
- require 'brief/github_client/issues'
38
- require 'brief/github_client/issue_labels'
39
- require 'brief/github_client/repository_issues'
40
- require 'brief/github_client/repository_milestones'
41
- require 'brief/github_client/repository_labels'
42
- require 'brief/github_client/milestone_issues'
43
- require 'brief/github_client/user_issues'
@@ -1,62 +0,0 @@
1
- module Brief
2
- module Handlers
3
- class Base
4
- attr_accessor :element, :prepared
5
-
6
- def initialize(element)
7
- @element = element
8
- end
9
-
10
- def method_missing meth, *args, &block
11
- if element.respond_to?(meth)
12
- return element.send(meth, *args, &block)
13
- end
14
-
15
- super
16
- end
17
-
18
- def content
19
- element.content
20
- end
21
-
22
- def document
23
- get_manager.try :document
24
- end
25
-
26
- def document_settings
27
- document.try(:settings)
28
- end
29
-
30
- def get_manager &block
31
- if block_given?
32
- @get_manager = block
33
- end
34
-
35
- @get_manager && @get_manager.call()
36
- end
37
-
38
- def parent &block
39
- if block_given?
40
- @find_parent_block = block
41
- end
42
-
43
- @find_parent_block && @find_parent_block.call(element.parent_id)
44
- end
45
-
46
- # Your handler should implement this method, the goal is to transform the
47
- # element we are passed into an object that is suitable for whatever integration
48
- # you have planned for it. For example, preparing the necessary attributes for
49
- # a submission to github issues or milestones
50
- def prepare!
51
- @prepared ||= begin
52
- element
53
- end
54
- end
55
-
56
- # Do whatever you want to do with the prepared element
57
- def handle!
58
- prepare!
59
- end
60
- end
61
- end
62
- end
@@ -1,41 +0,0 @@
1
- module Brief
2
- module Handlers
3
- class GithubIssue < Base
4
- def prepare!
5
- @prepared ||= begin
6
- if github_api_issue.present?
7
- element.issue_url = github_api_issue.url
8
- element.issue_number = github_api_issue.number
9
- else
10
- element.issue_url = create_in_github_api.url
11
- element.issue_number = github_api_issue.number
12
- end
13
-
14
- element
15
- end
16
- end
17
-
18
- def create_in_github_api
19
- issues_api.create_object(body: body, title: title, milestone: milestone)
20
- end
21
-
22
- def body
23
- element.content
24
- end
25
-
26
- def milestone
27
- parent && parent.milestone_number
28
- end
29
-
30
- def issues_api refresh=false
31
- Brief.repository_issues.tap do |api|
32
- refresh ? api.refresh : api
33
- end
34
- end
35
-
36
- def github_api_issue
37
- issues_api(true).all.detect {|issue| issue.title == title }
38
- end
39
- end
40
- end
41
- end
@@ -1,37 +0,0 @@
1
- module Brief
2
- module Handlers
3
- class GithubMilestone < Base
4
- def prepare!
5
- @prepared ||= begin
6
- if github_api_milestone.present?
7
- element.milestone_url = github_api_milestone.url
8
- element.milestone_number = github_api_milestone.number
9
- else
10
- element.milestone_url = create_in_github_api.url
11
- element.milestone_number = github_api_milestone.number
12
- end
13
-
14
- element
15
- end
16
- end
17
-
18
- def create_in_github_api
19
- @github_api_milestone ||= milestones_api.create_object(body: body, title: title)
20
- end
21
-
22
- def body
23
- document.parser.content_lines_under(title).reject(&:blank?).join("\n")
24
- end
25
-
26
- def milestones_api refresh=false
27
- Brief.repository_milestones.tap do |api|
28
- refresh ? api.refresh : api
29
- end
30
- end
31
-
32
- def github_api_milestone
33
- @github_api_milestone ||= milestones_api(true).all.detect {|milestone| milestone.title == element.title }
34
- end
35
- end
36
- end
37
- end
@@ -1,11 +0,0 @@
1
- module Brief
2
- module Handlers
3
- class GithubWiki < Base
4
- def prepare!
5
- @prepared ||= begin
6
- element
7
- end
8
- end
9
- end
10
- end
11
- end
data/lib/brief/line.rb DELETED
@@ -1,69 +0,0 @@
1
- module Brief
2
- class Line
3
- attr_reader :_content,
4
- :number,
5
- :code
6
-
7
- attr_accessor :raw
8
-
9
- HeadingRegex = /^#+\s*/
10
- CodeBlockRegex = /^\s*```/
11
-
12
- def initialize(content, number, code=false)
13
- @_content = content
14
- @number = number + 1
15
- @code = code
16
- end
17
-
18
- def to_s
19
- content
20
- end
21
-
22
- def type
23
- case
24
- when code?
25
- "content"
26
- when _content.match(HeadingRegex)
27
- "heading"
28
- when _content.match(CodeBlockRegex)
29
- "code_block_marker"
30
- else
31
- "content"
32
- end
33
- end
34
-
35
- def content
36
- _content.gsub(HeadingRegex, '')
37
- end
38
-
39
- def raw
40
- @raw || _content
41
- end
42
-
43
- def heading?
44
- !code? && type == "heading"
45
- end
46
-
47
- def level
48
- _content.match(HeadingRegex).to_s.count('#')
49
- end
50
-
51
- def sort_index
52
- [level, number]
53
- end
54
-
55
- def line_number
56
- number
57
- end
58
-
59
- def content?
60
- type == "content" || type == "code_block_marker"
61
- end
62
-
63
- def code?
64
- !!@code
65
- end
66
-
67
- end
68
- end
69
-