brief 1.8.6 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -3
  3. data/.travis.yml +8 -0
  4. data/Gemfile.lock +9 -8
  5. data/Rakefile +19 -15
  6. data/apps/blueprint/models/page.rb +1 -1
  7. data/apps/blueprint/models/roadmap.rb +14 -0
  8. data/apps/blueprint/templates/epic.md.erb +0 -0
  9. data/apps/blueprint/templates/milestone.md.erb +0 -0
  10. data/apps/blueprint/templates/page.md.erb +0 -0
  11. data/apps/blueprint/templates/persona.md.erb +0 -0
  12. data/apps/blueprint/templates/user_story.md.erb +0 -0
  13. data/bin/brief +3 -3
  14. data/brief.gemspec +9 -3
  15. data/examples/blog/brief.rb +13 -18
  16. data/examples/blog/docs/posts/this-is-my-first-post.md +12 -0
  17. data/lib/brief.rb +10 -4
  18. data/lib/brief/apps.rb +1 -1
  19. data/lib/brief/briefcase.rb +13 -8
  20. data/lib/brief/briefcase/initializer.rb +64 -0
  21. data/lib/brief/cli/all.rb +69 -0
  22. data/lib/brief/cli/export.rb +21 -10
  23. data/lib/brief/cli/parse.rb +1 -1
  24. data/lib/brief/cli/render.rb +1 -1
  25. data/lib/brief/data.rb +1 -1
  26. data/lib/brief/document.rb +18 -15
  27. data/lib/brief/document/rendering.rb +18 -33
  28. data/lib/brief/document_mapper.rb +1 -1
  29. data/lib/brief/model/serializers.rb +2 -2
  30. data/lib/brief/version.rb +1 -1
  31. data/packaging/wrapper.sh +32 -0
  32. data/spec/fixtures/example/docs/epics/epic.html.md +25 -0
  33. data/spec/fixtures/example/docs/index.md +15 -0
  34. data/spec/fixtures/example/docs/page.html.md +14 -0
  35. data/spec/fixtures/example/docs/persona.html.md +5 -0
  36. data/spec/fixtures/example/docs/release.html.md +9 -0
  37. data/spec/fixtures/example/docs/resource.html.md +5 -0
  38. data/spec/fixtures/example/docs/user_story.html.md +24 -0
  39. data/spec/fixtures/example/docs/wireframe.html.md +5 -0
  40. data/spec/fixtures/example/models/page.rb +2 -1
  41. data/spec/lib/brief/serializers_spec.rb +1 -1
  42. data/tasks/distribution/configuration.rb +15 -0
  43. data/tasks/distribution/executable.rb +28 -0
  44. data/tasks/distribution/package.rb +85 -0
  45. data/tasks/distribution/package_helpers.rb +12 -0
  46. data/tasks/distribution/release.rb +49 -0
  47. data/tasks/distribution/release_notes.erb +14 -0
  48. data/tasks/distribution/release_notes.rb +62 -0
  49. data/tasks/distribution/tarball.rb +47 -0
  50. data/tasks/distribution/travelling_ruby.rb +87 -0
  51. data/tasks/package.rake +41 -0
  52. data/tasks/styles.rake +47 -0
  53. data/tasks/upload.rake +40 -0
  54. metadata +51 -18
  55. data/clients/package.json +0 -11
  56. data/examples/blog/docs/an-intro-to-brief.html.md +0 -9
  57. data/lib/.DS_Store +0 -0
  58. data/lib/brief/cli/change.rb +0 -14
  59. data/lib/brief/cli/init.rb +0 -65
@@ -1,21 +1,32 @@
1
1
  command 'export' do |c|
2
- c.syntax= 'brief export [OPTIONS]'
3
- c.description = 'Export a parsed version of the document collection'
2
+ c.syntax = 'brief export PATH [OPTIONS]'
3
+ c.description = 'export the briefcase found in PATH'
4
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'
5
+ c.option '--output PATH', String, 'Save the output to the specified path'
6
+ c.option '--app APP', String, 'Use the specified app to get our models etc'
7
+ c.option '--config PATH', String, 'Use the specified config file'
8
8
 
9
9
  c.action do |args, options|
10
- options.default :config_path => Pathname(Dir.pwd).join('brief.rb')
10
+ root = Pathname(args.first || Brief.pwd)
11
11
 
12
+ o = {
13
+ root: root
14
+ }
12
15
 
13
- briefcase = Brief::Briefcase.new(config_path: Pathname(options.config_path))
16
+ o[:app] = options.app if options.app
17
+ o[:config_path] = options.config if options.config
14
18
 
15
- dump = briefcase.as_full_export()
19
+ briefcase = Brief::Briefcase.new(o)
16
20
 
17
- output = args.first || "#{ briefcase.cache_key }.json"
21
+ export = briefcase.as_full_export.to_json
18
22
 
19
- Pathname(Dir.pwd).join(output).open("w+") {|fh| fh.write(dump.to_json) }
23
+ if options.output
24
+ output = Pathname(options.output)
25
+ output = output.join(briefcase.slug + ".json") if output.directory?
26
+ output.open("w+") {|fh| fh.write(export) }
27
+ else
28
+ puts export
29
+ end
20
30
  end
21
31
  end
32
+
@@ -9,7 +9,7 @@ command 'parse' do |c|
9
9
  c.option '--type TYPE', String, 'Valid options: hash, array; Output as a hash keyed by path, or an array. Defaults to array.'
10
10
 
11
11
  c.action do |args, options|
12
- options.default(root: Pathname(Dir.pwd), type: "array")
12
+ options.default(root: Pathname(Brief.pwd), type: "array")
13
13
 
14
14
  o = {
15
15
  root: options.root
@@ -9,7 +9,7 @@ command 'render' do |c|
9
9
  c.option '--include-raw', nil, 'Whether or not to include the raw content'
10
10
 
11
11
  c.action do |args, options|
12
- options.default(root: Pathname(Dir.pwd))
12
+ options.default(root: Pathname(Brief.pwd))
13
13
 
14
14
  o = {
15
15
  root: options.root
@@ -19,7 +19,7 @@ module Brief
19
19
  attr_accessor :sources, :root
20
20
 
21
21
  def initialize(options={})
22
- @root = options.fetch(:root) { Pathname(Dir.pwd).join('data') }
22
+ @root = options.fetch(:root) { Pathname(Brief.pwd).join('data') }
23
23
  @sources = {}.to_mash
24
24
 
25
25
  load_files.each do |source, data|
@@ -4,23 +4,10 @@ module Brief
4
4
  include Brief::Document::FrontMatter
5
5
  include Brief::Document::Templating
6
6
 
7
- attr_accessor :path, :content, :frontmatter, :raw_content, :options
8
-
9
- def document
10
- self
11
- end
12
-
13
- def to_s
14
- "#{ model_class }.at_path(#{relative_path})"
7
+ def self.from_contents(content, frontmatter, &block)
15
8
  end
16
9
 
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
10
+ attr_accessor :path, :content, :frontmatter, :raw_content, :options
24
11
 
25
12
  def initialize(path, options = {})
26
13
  if path.respond_to?(:key?) && options.empty?
@@ -39,6 +26,22 @@ module Brief
39
26
  end
40
27
  end
41
28
 
29
+ def document
30
+ self
31
+ end
32
+
33
+ def to_s
34
+ "#{ model_class }.at_path(#{relative_path})"
35
+ end
36
+
37
+ def inspect
38
+ "#{ model_class }.at_path(#{relative_path})"
39
+ end
40
+
41
+ def relative_path
42
+ briefcase.present? ? path.relative_path_from(briefcase.docs_path) : path
43
+ end
44
+
42
45
  def content_hash
43
46
  Digest::MD5.hexdigest(@content.to_s)
44
47
  end
@@ -1,38 +1,23 @@
1
- module Brief
2
- class Document
3
- module Rendering
4
- extend ActiveSupport::Concern
1
+ module GitHub
2
+ class Markdown
5
3
 
6
- # Uses a custom Redcarpet::Render::HTML subclass
7
- # which simply inserts data attributes on each heading element
8
- # so that they can be queried with CSS more deliberately.
9
- class HeadingWrapper < ::Redcarpet::Render::HTML
10
- def header(text, level)
11
- "<h#{level} data-level='#{level}' data-heading='#{ text }'>#{text}</h#{level}>"
12
- end
13
- end
4
+ def self.render_gfm(content)
5
+ html = self.to_html(content, :gfm)
6
+ html = add_level_and_heading(html)
7
+ html
8
+ end
14
9
 
15
- module ClassMethods
16
- def renderer_class
17
- HeadingWrapper
18
- end
10
+ def self.add_level_and_heading(html)
11
+ html.gsub(/<h([1-6])>(.+?)<\/h\1>/,"<h\\1 data-level='\\1' data-heading='\\2'>\\2<\/h\\1>")
12
+ end
19
13
 
20
- def renderer
21
- @renderer ||= begin
22
- r = renderer_class.new(tables: true,
23
- autolink: true,
24
- gh_blockcode: true,
25
- fenced_code_blocks: true,
26
- footnotes: true)
14
+ end
15
+ end
27
16
 
28
- ::Redcarpet::Markdown.new(r, :tables => true,
29
- :autolink => true,
30
- :gh_blockcode => true,
31
- :fenced_code_blocks => true,
32
- :footnotes => true)
33
- end
34
- end
35
- end
17
+ module Brief
18
+ class Document
19
+ module Rendering
20
+ extend ActiveSupport::Concern
36
21
 
37
22
  def script_preamble
38
23
  <<-EOF
@@ -78,11 +63,11 @@ module Brief
78
63
  protected
79
64
 
80
65
  def to_raw_html
81
- renderer.render(content)
66
+ renderer.render_gfm(content)
82
67
  end
83
68
 
84
69
  def renderer
85
- @renderer ||= self.class.renderer
70
+ @renderer ||= GitHub::Markdown
86
71
  end
87
72
 
88
73
  attr_writer :renderer
@@ -71,7 +71,7 @@ module Brief::DocumentMapper
71
71
 
72
72
  def run_query
73
73
  if query_is_empty?
74
- select
74
+ model.to_a
75
75
  else
76
76
  model.select do |obj|
77
77
  match = true
@@ -19,8 +19,8 @@ module Brief::Model::Serializers
19
19
  title: document_title,
20
20
  actions: self.class.defined_actions,
21
21
  updated_at: File.mtime(path).to_i,
22
- id: (doc_id = file_hash),
23
- hash: doc_id,
22
+ id: Digest::MD5.hexdigest(path.to_s),
23
+ hash: file_hash,
24
24
  urls: {
25
25
  view_content_url: "/view/content/#{ doc_path }",
26
26
  view_rendered_url: "/view/rendered/#{ doc_path }",
@@ -1,3 +1,3 @@
1
1
  module Brief
2
- VERSION = '1.8.6'
2
+ VERSION = '1.8.8'
3
3
  end
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+
3
+ export BRIEF_PWD=$PWD
4
+ set -e
5
+
6
+ TARGET_FILE=$0
7
+
8
+ cd `dirname $TARGET_FILE`
9
+ TARGET_FILE=`basename $TARGET_FILE`
10
+
11
+ # Iterate down a (possible) chain of symlinks
12
+ while [ -L "$TARGET_FILE" ]
13
+ do
14
+ TARGET_FILE=`readlink $TARGET_FILE`
15
+ cd `dirname $TARGET_FILE`
16
+ TARGET_FILE=`basename $TARGET_FILE`
17
+ done
18
+
19
+ # Compute the canonicalized name by finding the physical path
20
+ # for the directory we're in and appending the target file.
21
+ PHYS_DIR=`pwd -P`
22
+ RESULT=$PHYS_DIR/$TARGET_FILE
23
+
24
+ # Figure out where this script is located.
25
+ SELFDIR=$(dirname "$RESULT")
26
+
27
+ # Tell Bundler where the Gemfile and gems are.
28
+ export BUNDLE_GEMFILE="$SELFDIR/lib/app/Gemfile"
29
+ unset BUNDLE_IGNORE_CONFIG
30
+
31
+ # Run the actual app using the bundled Ruby interpreter.
32
+ exec "$SELFDIR/lib/ruby/bin/ruby" -rbundler/setup "$SELFDIR/lib/app/bin/brief" "$@"
@@ -0,0 +1,25 @@
1
+ ---
2
+ type: epic
3
+ title: Blueprint Epic Example
4
+ subheading: An example of an Epic
5
+ state: active
6
+ ---
7
+
8
+ # Blueprint Epic Example
9
+
10
+ This is an example of an Epic Document. An Epic is a single document
11
+ which contains user stories and such.
12
+
13
+ # User Stories
14
+
15
+ ## A user wants to write epics
16
+
17
+ As a **User** I want to **write epics** so that I can **write a bunch of user stories in one file**
18
+
19
+ ## A user wants to annotate wireframes
20
+
21
+ As a **User** I want to **annotate wireframes** so that I can **augment diagrams with targeted explanations**
22
+
23
+ ## A user wants to provide details about domain concepts
24
+
25
+ As a **User** I want to **provide some detailed explanations of domain concepts** so that I can **augment diagrams with targeted explanations**
@@ -0,0 +1,15 @@
1
+ ---
2
+ type: outline
3
+ ---
4
+
5
+ # Table of contents
6
+
7
+ ## Personas
8
+ ## Epics
9
+ ## Wireframes
10
+ ## Concepts
11
+
12
+ ```yaml
13
+ option: one
14
+ other: two
15
+ ```
@@ -0,0 +1,14 @@
1
+ ---
2
+ type: page
3
+ title: Summary
4
+ ---
5
+
6
+ # Summary
7
+
8
+ The Blueprint by Architects.io is a functional specifications and requirements document that joins together various materials produced by Software Architects, Domain Modelers, Researchers, UX and UI Designers, Engineers, and Product Managers. The overall purpose is to communicate design intent, vision, and goals, along with the strategy and logistics of implementation.
9
+
10
+ Our aim is to reduce the overall communication effort required to deliver products whose results more closely match the intent and goals. This requires more effective communication tools, a more effortless feedback loop, and a methodology for validating and refining the goals themselves as everyone's understanding develops.
11
+
12
+ ```yaml
13
+ nested: structure
14
+ ```
@@ -0,0 +1,5 @@
1
+ ---
2
+ type: persona
3
+ title: Blueprint Persona Example
4
+ subheading: A description of a typical user of the software
5
+ ---
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: release
3
+ title: Blueprint Release Example
4
+ subheading: A release milestone for the software
5
+ status: Planned
6
+ date: 2018-12-18
7
+ ---
8
+
9
+ This is a release it is a simple file with no real structure.
@@ -0,0 +1,5 @@
1
+ ---
2
+ type: resource
3
+ title: Blueprint Example Resource
4
+ subheading: An example API Resource document
5
+ ---
@@ -0,0 +1,24 @@
1
+ ---
2
+ type: user_story
3
+ title: Blueprint User Story Example
4
+ subheading: A way of describing desired behavior of the software, from the perspective of a persona who has a goal
5
+ epic: Blueprint Epic Example
6
+ release: Blueprint Release Example
7
+ state: active
8
+ title: A Blueprint Persona Example wants this behavior
9
+ ---
10
+
11
+ As a **Blueprint Persona Example** I would like to **do this certain thing in the software** so that I can **accomplish this goal**
12
+
13
+ #### Wireframes
14
+
15
+ - Blueprint Wireframe Example
16
+
17
+ #### Concepts
18
+
19
+ - Blueprint Concept Example
20
+
21
+ #### Resources
22
+
23
+ - Blueprint Example Resource
24
+
@@ -0,0 +1,5 @@
1
+ ---
2
+ type: wireframe
3
+ title: Blueprint Wireframe Example
4
+ subheading: A key concept to the domain model
5
+ ---
@@ -8,6 +8,7 @@ class Brief::Page
8
8
  content do
9
9
  title "h1:first-of-type"
10
10
  paragraph "p:first-of-type"
11
- yaml_data "code.yaml:first-of-type", :serialize => :yaml
11
+ yaml_data "pre[lang='yaml'] code", :serialize => :yaml
12
+ yaml "pre[lang='yaml'] code", :serialize => :yaml
12
13
  end
13
14
  end
@@ -6,6 +6,6 @@ describe "Serializing From Docs" do
6
6
  }
7
7
 
8
8
  it "should serialize the yaml" do
9
- expect(page.yaml_data.nested).to eq("structure")
9
+ expect(page.yaml.nested).to eq("structure")
10
10
  end
11
11
  end
@@ -0,0 +1,15 @@
1
+ module Distribution
2
+ class << self
3
+ attr_accessor :configuration
4
+ end
5
+
6
+ def self.configure
7
+ self.configuration ||= Configuration.new
8
+ yield configuration
9
+ end
10
+
11
+ class Configuration
12
+ attr_accessor :package_name, :packaging_dir, :version, :rb_version,
13
+ :native_extensions
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ Dir[File.join(Dir.pwd, 'tasks', '**', '*.rb')].each { |f| require f }
2
+
3
+ module Distribution
4
+ class Executable
5
+ include PackageHelpers
6
+ extend Forwardable
7
+
8
+ attr_reader :package
9
+
10
+ def_delegators :@package, :dir, :package_name
11
+
12
+ def initialize(package)
13
+ @package = package
14
+ end
15
+
16
+ def self.create(package)
17
+ executable = new(package)
18
+ executable.copy_wrapper
19
+ executable
20
+ end
21
+
22
+ def copy_wrapper
23
+ print_to_console 'Creating exexutable...'
24
+
25
+ FileUtils.cp 'packaging/wrapper.sh', "#{dir}/#{package_name}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,85 @@
1
+ require 'fileutils'
2
+ require 'forwardable'
3
+
4
+ Dir[File.join(Dir.pwd, 'tasks', '**', '*.rb')].each { |f| require f }
5
+
6
+ module Distribution
7
+ class Package
8
+ extend Forwardable
9
+ include PackageHelpers
10
+
11
+ attr_reader :config, :dir, :tarball, :package, :arch, :root
12
+
13
+ def_delegators :@config, :version, :rb_version, :package_name,
14
+ :packaging_dir, :native_extensions
15
+
16
+ def initialize(arch)
17
+ abort 'Ruby 2.1.x required' if RUBY_VERSION !~ /^2\.1\./
18
+
19
+ @arch = arch
20
+ @config = ::Distribution.configuration
21
+ @dir = "#{package_name}-#{version}-#{arch}"
22
+ @package = self
23
+ @root = File.expand_path '.'
24
+ end
25
+
26
+ def self.create(args)
27
+ new(*args).build
28
+ end
29
+
30
+ def build
31
+ initialize_install_dir
32
+ copy_brief
33
+ install_ruby_and_gems
34
+ create_executable
35
+ post_cleanup
36
+ @tarball = create_tarball
37
+ clean_dir
38
+ end
39
+
40
+ private
41
+
42
+ def clean_dir
43
+ FileUtils.cd root do
44
+ FileUtils.remove_dir(dir, true) if Dir.exist? dir
45
+ end
46
+ end
47
+
48
+ def post_cleanup
49
+ print_to_console 'Cleaning up...'
50
+
51
+ files = ["#{packaging_dir}/traveling-ruby-#{rb_version}-#{arch}.tar.gz"]
52
+
53
+ files.each { |file| FileUtils.rm file if File.exist? file }
54
+ end
55
+
56
+ def create_tarball
57
+ Tarball.new self
58
+ end
59
+
60
+ def create_executable
61
+ Executable.create self
62
+ end
63
+
64
+ def install_ruby_and_gems
65
+ TravellingRuby.install self
66
+ end
67
+
68
+ def initialize_install_dir
69
+ clean_dir
70
+
71
+ FileUtils.cd root do
72
+ FileUtils.mkdir_p "#{dir}/lib/app"
73
+ end
74
+ end
75
+
76
+ def copy_brief
77
+ print_to_console 'Copying brief...'
78
+
79
+ %w(brief.gemspec Gemfile Gemfile.lock lib assets apps bin)
80
+ .each do |folder|
81
+ FileUtils.cp_r File.join(root, folder), "#{dir}/lib/app"
82
+ end
83
+ end
84
+ end
85
+ end