brief 1.6.1 → 1.7.0
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/Gemfile.lock +1 -1
- data/apps/blueprint/config.rb +5 -2
- data/apps/blueprint/models/epic.rb +3 -0
- data/apps/blueprint/models/page.rb +3 -3
- data/clients/package.json +11 -0
- data/lib/brief/briefcase.rb +1 -1
- data/lib/brief/cli/export.rb +21 -0
- data/lib/brief/core_ext.rb +6 -0
- data/lib/brief/document/content_extractor.rb +59 -31
- data/lib/brief/document.rb +35 -3
- data/lib/brief/model/serializers.rb +2 -2
- data/lib/brief/model.rb +12 -0
- data/lib/brief/repository.rb +8 -1
- data/lib/brief/version.rb +1 -1
- data/spec/fixtures/example/docs/concept.html.md +6 -4
- data/spec/lib/brief/hashing_spec.rb +26 -0
- data/spec/lib/brief/repository_spec.rb +12 -1
- data/spec/spec_helper.rb +7 -2
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5994d22ccc22af64d2a24fb82f2cbc687eba9dad
|
4
|
+
data.tar.gz: 238e456cc9f8f35cf0b58e6d8963f857935b28ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6923156ac95ba428b498b98290ca2e2a03fcee5ddd28da8f90029e6ec4c5fb5c144de04e87929b7923065f43ada6df779cdf2e025e498a3abc063dbcbad358b
|
7
|
+
data.tar.gz: 2e09b44afca6169797fe7cc31d9bbdf396b824279112dc59d480019abe245029c7e8c3f1c0c7663551eefe85e7de01218f43716ddb565af4513b5c0a023fa907
|
data/.gitignore
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
# the test suite writes to this
|
2
|
-
spec/fixtures/example/docs
|
3
|
-
spec/fixtures/example/docs
|
2
|
+
spec/fixtures/example/docs
|
3
|
+
spec/fixtures/example/docs
|
data/Gemfile.lock
CHANGED
data/apps/blueprint/config.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
view(:summary) do |
|
1
|
+
view(:summary) do |*args|
|
2
|
+
params = args.extract_options!
|
3
|
+
briefcase = args.first
|
4
|
+
|
2
5
|
briefcase.present(:default, params).tap do |hash|
|
3
|
-
if summary =
|
6
|
+
if summary = briefcase.pages.find {|p| p.title == "Summary" }
|
4
7
|
hash.merge!(summary: summary.to_model.as_json(:rendered=>true, :content=>true))
|
5
8
|
end
|
6
9
|
end
|
@@ -35,6 +35,9 @@ As a **User** I would like to **Do this** so that I can **succeed**
|
|
35
35
|
|
36
36
|
content do
|
37
37
|
title "h1:first-of-type"
|
38
|
+
paragraph "p:first-of-type"
|
39
|
+
paragraphs "p"
|
40
|
+
|
38
41
|
define_section "User Stories" do
|
39
42
|
each("h2").has(:title => "h2",
|
40
43
|
:paragraph => "p:first-of-type",
|
@@ -8,9 +8,9 @@ class Brief::Apps::Blueprint::Page
|
|
8
8
|
end
|
9
9
|
|
10
10
|
content do
|
11
|
-
title "h1:first-of-type"
|
12
|
-
tagline "h2:first-of-type"
|
13
11
|
paragraph "p:first-of-type"
|
14
|
-
|
12
|
+
title "h1:first-of-type", :hide => true
|
13
|
+
tagline "h2:first-of-type", :hide => true
|
14
|
+
yaml_data "code.yaml:first-of-type", :serialize => :yaml, :hide => true
|
15
15
|
end
|
16
16
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
{
|
2
|
+
"name": "brief-client",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"description": "a client for the brief markdown as a database service",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
8
|
+
},
|
9
|
+
"author": "",
|
10
|
+
"license": "ISC"
|
11
|
+
}
|
data/lib/brief/briefcase.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
command 'export' do |c|
|
2
|
+
c.syntax= 'brief export [OPTIONS]'
|
3
|
+
c.description = 'Export a parsed version of the document collection'
|
4
|
+
|
5
|
+
c.option '--include-content', nil, 'whether to include the unparsed content'
|
6
|
+
c.option '--include-rendered', nil, 'whether to include the rendered content'
|
7
|
+
c.option '--config-path PATH', String, 'Path to the config file'
|
8
|
+
|
9
|
+
c.action do |args, options|
|
10
|
+
options.default :config_path => Pathname(Dir.pwd).join('brief.rb')
|
11
|
+
|
12
|
+
|
13
|
+
briefcase = Brief::Briefcase.new(config_path: Pathname(options.config_path))
|
14
|
+
|
15
|
+
json = briefcase.present("default", content: !!options.include_content, rendered: !!options.include_rendered)
|
16
|
+
|
17
|
+
output = args.first || "briefcase.json"
|
18
|
+
|
19
|
+
Pathname(Dir.pwd).join(output).open("w+") {|fh| fh.write(json.to_json) }
|
20
|
+
end
|
21
|
+
end
|
data/lib/brief/core_ext.rb
CHANGED
@@ -12,7 +12,7 @@ module Brief
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def content_schema_attributes
|
15
|
-
model_class.definition.content_schema.attributes
|
15
|
+
model_class.definition.content_schema.attributes.symbolize_keys!
|
16
16
|
end
|
17
17
|
|
18
18
|
def extracted_content_data
|
@@ -25,39 +25,67 @@ module Brief
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def respond_to?(meth)
|
28
|
-
|
28
|
+
supports_extraction?(meth) || super
|
29
|
+
end
|
30
|
+
|
31
|
+
def extraction_rule_for(attribute)
|
32
|
+
content_schema_attributes.fetch(attribute.to_sym, nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
def selector_for(attribute)
|
36
|
+
extraction_rule_for(attribute).first
|
37
|
+
end
|
38
|
+
|
39
|
+
def supports_extraction?(attribute)
|
40
|
+
content_schema_attributes.key?(attribute.to_sym)
|
29
41
|
end
|
30
42
|
|
31
43
|
def method_missing(meth, *_args, &_block)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
44
|
+
return super unless supports_extraction?(meth)
|
45
|
+
rule = ExtractionRule.new(extraction_rule_for(meth))
|
46
|
+
rule.apply_to(document)
|
47
|
+
end
|
48
|
+
|
49
|
+
class ExtractionRule
|
50
|
+
attr_reader :rule, :args
|
51
|
+
|
52
|
+
def initialize(rule)
|
53
|
+
@rule = rule
|
54
|
+
@args = rule.args
|
55
|
+
end
|
56
|
+
|
57
|
+
def options
|
58
|
+
args[1] || {}.to_mash
|
59
|
+
end
|
60
|
+
|
61
|
+
def deserialize?
|
62
|
+
!!(options.serialize.present? && options.serialize)
|
63
|
+
end
|
64
|
+
|
65
|
+
def format
|
66
|
+
options.serialize.to_sym
|
67
|
+
end
|
68
|
+
|
69
|
+
def selector
|
70
|
+
args.first if args.first.is_a?(String)
|
71
|
+
end
|
72
|
+
|
73
|
+
def apply_to(document)
|
74
|
+
raise 'Must specify a selector' unless selector
|
75
|
+
|
76
|
+
extracted = document.css(selector)
|
77
|
+
|
78
|
+
return nil if extracted.length == 0
|
79
|
+
|
80
|
+
case
|
81
|
+
when deserialize? && format == :json
|
82
|
+
(JSON.parse(extracted.text.to_s) rescue {}).to_mash
|
83
|
+
when deserialize? && format == :yaml
|
84
|
+
(YAML.load(extracted.text.to_s) rescue {}).to_mash
|
85
|
+
when selector.match(/first-of-type/) && extracted.length > 0
|
86
|
+
extracted.first.text
|
87
|
+
else
|
88
|
+
extracted.map(&:text)
|
61
89
|
end
|
62
90
|
end
|
63
91
|
end
|
data/lib/brief/document.rb
CHANGED
@@ -10,6 +10,18 @@ module Brief
|
|
10
10
|
self
|
11
11
|
end
|
12
12
|
|
13
|
+
def to_s
|
14
|
+
"#{ model_class }.at_path(#{relative_path})"
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
"#{ model_class }.at_path(#{relative_path})"
|
19
|
+
end
|
20
|
+
|
21
|
+
def relative_path
|
22
|
+
briefcase.present? ? path.relative_path_from(briefcase.docs_path) : path
|
23
|
+
end
|
24
|
+
|
13
25
|
def initialize(path, options = {})
|
14
26
|
if path.respond_to?(:key?) && options.empty?
|
15
27
|
@frontmatter = path.to_mash
|
@@ -27,6 +39,18 @@ module Brief
|
|
27
39
|
end
|
28
40
|
end
|
29
41
|
|
42
|
+
def content_hash
|
43
|
+
Digest::MD5.hexdigest(@content.to_s)
|
44
|
+
end
|
45
|
+
|
46
|
+
def file_hash
|
47
|
+
Digest::MD5.hexdigest(path.read.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
def content_stale?
|
51
|
+
content_hash != file_hash
|
52
|
+
end
|
53
|
+
|
30
54
|
def raw= val
|
31
55
|
@raw_set = true
|
32
56
|
@raw_content = val
|
@@ -55,6 +79,7 @@ module Brief
|
|
55
79
|
@frontmatter = nil
|
56
80
|
@raw_frontmatter = nil
|
57
81
|
@refreshing = true
|
82
|
+
@content_hash = nil
|
58
83
|
load_frontmatter
|
59
84
|
true
|
60
85
|
end
|
@@ -106,9 +131,10 @@ module Brief
|
|
106
131
|
end
|
107
132
|
|
108
133
|
def content
|
109
|
-
if @content.nil?
|
110
|
-
|
134
|
+
if @content.nil? && path && path.exist?
|
135
|
+
@content = path.read
|
111
136
|
end
|
137
|
+
|
112
138
|
@content || generate_content
|
113
139
|
end
|
114
140
|
|
@@ -153,8 +179,14 @@ module Brief
|
|
153
179
|
path.extname
|
154
180
|
end
|
155
181
|
|
182
|
+
def model_attributes
|
183
|
+
(data || {}).to_hash
|
184
|
+
.merge(path: path, document: self)
|
185
|
+
.reverse_merge(type: document_type)
|
186
|
+
end
|
187
|
+
|
156
188
|
def to_model
|
157
|
-
model_class.
|
189
|
+
model_class.try(:new, model_attributes)
|
158
190
|
end
|
159
191
|
|
160
192
|
def exist?
|
@@ -7,7 +7,7 @@ module Brief::Model::Serializers
|
|
7
7
|
doc_path = path.relative_path_from(docs_path).to_s
|
8
8
|
|
9
9
|
# TEMP
|
10
|
-
title = data.try(:[], :title) ||
|
10
|
+
title = data.try(:[], :title) || extracted_content_data.try(:title) || (send(:title) rescue nil) || path.basename.to_s.gsub(/\.html.md/,'')
|
11
11
|
title = title.to_s.gsub(/\.md/,'')
|
12
12
|
|
13
13
|
{
|
@@ -16,7 +16,7 @@ module Brief::Model::Serializers
|
|
16
16
|
path: path.to_s,
|
17
17
|
type: type,
|
18
18
|
group: type.to_s.pluralize,
|
19
|
-
title:
|
19
|
+
title: document_title,
|
20
20
|
actions: self.class.defined_actions,
|
21
21
|
urls: {
|
22
22
|
view_content_url: "/view/content/#{ doc_path }",
|
data/lib/brief/model.rb
CHANGED
@@ -29,6 +29,14 @@ module Brief
|
|
29
29
|
end
|
30
30
|
|
31
31
|
module AccessorMethods
|
32
|
+
def document_title
|
33
|
+
data.try(:[], :title) ||
|
34
|
+
extracted_content_data.try(:title) ||
|
35
|
+
path.basename.to_s
|
36
|
+
.gsub(/\.html.md/,'')
|
37
|
+
.gsub(/\.md/,'')
|
38
|
+
end
|
39
|
+
|
32
40
|
def data
|
33
41
|
document.data || {}.to_mash
|
34
42
|
end
|
@@ -112,6 +120,10 @@ module Brief
|
|
112
120
|
type_alias && type_alias == other.type_alias
|
113
121
|
end
|
114
122
|
|
123
|
+
def accessor_property_names
|
124
|
+
(definition.content_schema.attributes.keys + definition.metadata_schema.keys).uniq
|
125
|
+
end
|
126
|
+
|
115
127
|
def to_schema
|
116
128
|
{
|
117
129
|
schema: {
|
data/lib/brief/repository.rb
CHANGED
@@ -21,8 +21,15 @@ module Brief
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def method_missing(meth, *args, &block)
|
24
|
-
|
24
|
+
in_model_group = model_groups.include?(meth.to_s)
|
25
|
+
|
26
|
+
if in_model_group && args.empty?
|
25
27
|
find_models_by_type(meth)
|
28
|
+
elsif in_model_group && !args.empty?
|
29
|
+
group = find_models_by_type(meth)
|
30
|
+
Brief::DocumentMapper::Query.new(group).send(:where, *args)
|
31
|
+
else
|
32
|
+
super
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
data/lib/brief/version.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
---
|
2
2
|
type: concept
|
3
|
-
|
4
|
-
subheading: A key concept to the domain model
|
5
|
-
needle: cbw5astzg5gh0ui3op68054s9sm39me6vjvc
|
3
|
+
|
6
4
|
---
|
7
5
|
|
8
|
-
# Modified Content
|
6
|
+
# Modified Content 38inom7nxjlo9z3neuhognu1y75csd79i1ec
|
7
|
+
|
8
|
+
1
|
9
|
+
|
10
|
+
1
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Hashing" do
|
4
|
+
let(:doc) { Brief.concept_document }
|
5
|
+
|
6
|
+
it "has a content hash" do
|
7
|
+
expect(doc.content_hash).not_to be_empty
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has a file system hash" do
|
11
|
+
expect(doc.file_hash).not_to be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it "detects when it is stale" do
|
15
|
+
new_content = doc.content += "\n\n1";
|
16
|
+
doc.path.open("w+") {|fh| fh.write("---\ntype: concept\n\n---\n\n#{new_content}") }
|
17
|
+
expect(doc).to be_content_stale
|
18
|
+
end
|
19
|
+
|
20
|
+
it "refreshes itself if stale" do
|
21
|
+
new_content = doc.content += "\n\n1";
|
22
|
+
doc.path.open("w+") {|fh| fh.write("---\ntype: concept\n\n---\n\n#{new_content}") }
|
23
|
+
expect(doc).to be_content_stale
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -9,11 +9,22 @@ describe "The Brief Document Repository" do
|
|
9
9
|
|
10
10
|
it "gives me the document models for paths" do
|
11
11
|
paths = ["./concept.html.md", "wireframe.html.md", "epics/epic.html.md", Brief.example_document.path.realpath]
|
12
|
-
|
13
12
|
docs = repository.documents_at(*paths)
|
13
|
+
expect(docs).not_to be_empty
|
14
14
|
end
|
15
15
|
|
16
16
|
context "querying api" do
|
17
|
+
it "lets me query the model groups with params" do
|
18
|
+
items = Brief.testcase.epics(title:"No Bueno").all
|
19
|
+
expect(items).to be_empty
|
20
|
+
end
|
21
|
+
|
22
|
+
it "lets me query the model group with params" do
|
23
|
+
items = Brief.testcase.epics(title:"Blueprint Epic Example").all
|
24
|
+
expect(items).not_to be_empty
|
25
|
+
expect(items.map(&:title).uniq).to include("Blueprint Epic Example")
|
26
|
+
end
|
27
|
+
|
17
28
|
it "finds the first document matching a query" do
|
18
29
|
query = repository.where(state:"active")
|
19
30
|
expect(query.first.type).to eq("epic")
|
data/spec/spec_helper.rb
CHANGED
@@ -13,14 +13,19 @@ module Brief
|
|
13
13
|
testcase.root
|
14
14
|
end
|
15
15
|
|
16
|
+
def self.concept_document
|
17
|
+
path = Brief.example_path.join("docs","concept.html.md")
|
18
|
+
testcase.document_at(path)
|
19
|
+
end
|
20
|
+
|
16
21
|
def self.page_document
|
17
22
|
path = Brief.example_path.join("docs","page.html.md")
|
18
|
-
|
23
|
+
testcase.document_at(path)
|
19
24
|
end
|
20
25
|
|
21
26
|
def self.example_document
|
22
27
|
path = Brief.example_path.join("docs","epics","epic.html.md")
|
23
|
-
|
28
|
+
testcase.document_at(path)
|
24
29
|
end
|
25
30
|
|
26
31
|
def self.testcase
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brief
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Soeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- apps/blueprint/models/wireframe.rb
|
246
246
|
- bin/brief
|
247
247
|
- brief.gemspec
|
248
|
+
- clients/package.json
|
248
249
|
- examples/blog/brief.rb
|
249
250
|
- examples/blog/docs/an-intro-to-brief.html.md
|
250
251
|
- lib/.DS_Store
|
@@ -253,6 +254,7 @@ files:
|
|
253
254
|
- lib/brief/apps.rb
|
254
255
|
- lib/brief/briefcase.rb
|
255
256
|
- lib/brief/cli/change.rb
|
257
|
+
- lib/brief/cli/export.rb
|
256
258
|
- lib/brief/cli/init.rb
|
257
259
|
- lib/brief/cli/write.rb
|
258
260
|
- lib/brief/configuration.rb
|
@@ -312,6 +314,7 @@ files:
|
|
312
314
|
- spec/lib/brief/briefcase_spec.rb
|
313
315
|
- spec/lib/brief/document_spec.rb
|
314
316
|
- spec/lib/brief/dsl_spec.rb
|
317
|
+
- spec/lib/brief/hashing_spec.rb
|
315
318
|
- spec/lib/brief/model_spec.rb
|
316
319
|
- spec/lib/brief/models/page_spec.rb
|
317
320
|
- spec/lib/brief/persistence_spec.rb
|
@@ -378,6 +381,7 @@ test_files:
|
|
378
381
|
- spec/lib/brief/briefcase_spec.rb
|
379
382
|
- spec/lib/brief/document_spec.rb
|
380
383
|
- spec/lib/brief/dsl_spec.rb
|
384
|
+
- spec/lib/brief/hashing_spec.rb
|
381
385
|
- spec/lib/brief/model_spec.rb
|
382
386
|
- spec/lib/brief/models/page_spec.rb
|
383
387
|
- spec/lib/brief/persistence_spec.rb
|