praxis 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +15 -2
  4. data/CHANGELOG.md +54 -1
  5. data/bin/praxis +49 -2
  6. data/lib/api_browser/Gruntfile.js +247 -90
  7. data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +19 -0
  8. data/lib/api_browser/app/bower_components/angular-mocks/README.md +57 -0
  9. data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +2193 -0
  10. data/lib/api_browser/app/bower_components/angular-mocks/bower.json +9 -0
  11. data/lib/api_browser/app/bower_components/angular-mocks/package.json +27 -0
  12. data/lib/api_browser/app/bower_components/angular/.bower.json +6 -5
  13. data/lib/api_browser/app/bower_components/angular/README.md +23 -4
  14. data/lib/api_browser/app/bower_components/angular/angular-csp.css +6 -0
  15. data/lib/api_browser/app/bower_components/angular/angular.js +2287 -1597
  16. data/lib/api_browser/app/bower_components/angular/angular.min.js +212 -205
  17. data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
  18. data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
  19. data/lib/api_browser/app/bower_components/angular/bower.json +2 -1
  20. data/lib/api_browser/app/bower_components/angular/package.json +25 -0
  21. data/lib/api_browser/app/bower_components/showdown/.bower.json +39 -0
  22. data/lib/api_browser/app/bower_components/showdown/.jshintignore +2 -0
  23. data/lib/api_browser/app/bower_components/showdown/.travis.yml +8 -0
  24. data/lib/api_browser/app/bower_components/showdown/Gruntfile.js +100 -0
  25. data/lib/api_browser/app/bower_components/showdown/README.md +317 -0
  26. data/lib/api_browser/app/bower_components/showdown/bower.json +26 -0
  27. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js +1606 -0
  28. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js.map +1 -0
  29. data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.min.js +2 -0
  30. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js +2 -0
  31. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js.map +1 -0
  32. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js +2 -0
  33. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js.map +1 -0
  34. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js +2 -0
  35. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js.map +1 -0
  36. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js +2 -0
  37. data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js.map +1 -0
  38. data/lib/api_browser/app/bower_components/showdown/license.txt +34 -0
  39. data/lib/api_browser/app/bower_components/showdown/package.json +47 -0
  40. data/lib/api_browser/app/bower_components/showdown/src/extensions/github.js +25 -0
  41. data/lib/api_browser/app/bower_components/showdown/src/extensions/prettify.js +29 -0
  42. data/lib/api_browser/app/bower_components/showdown/src/extensions/table.js +106 -0
  43. data/lib/api_browser/app/bower_components/showdown/src/extensions/twitter.js +42 -0
  44. data/lib/api_browser/app/bower_components/showdown/src/ng-showdown.js +150 -0
  45. data/lib/api_browser/app/bower_components/showdown/src/showdown.js +1454 -0
  46. data/lib/api_browser/app/index.html +6 -4
  47. data/lib/api_browser/app/js/app.js +1 -2
  48. data/lib/api_browser/app/js/controllers/action.js +4 -4
  49. data/lib/api_browser/app/js/controllers/controller.js +1 -1
  50. data/lib/api_browser/app/js/controllers/menu.js +5 -3
  51. data/lib/api_browser/app/js/controllers/type.js +5 -5
  52. data/lib/api_browser/app/js/directives/attribute_description.js +5 -5
  53. data/lib/api_browser/app/js/directives/attribute_table.js +1 -1
  54. data/lib/api_browser/app/js/directives/attribute_table_row.js +2 -2
  55. data/lib/api_browser/app/js/directives/no_container.js +1 -1
  56. data/lib/api_browser/app/js/directives/request_body.js +5 -5
  57. data/lib/api_browser/app/js/directives/request_headers.js +3 -6
  58. data/lib/api_browser/app/js/directives/request_parameters.js +3 -6
  59. data/lib/api_browser/app/js/directives/type_label.js +4 -5
  60. data/lib/api_browser/app/js/factories/Documentation.js +4 -4
  61. data/lib/api_browser/app/js/factories/PayloadTemplates.js +2 -2
  62. data/lib/api_browser/app/js/factories/TypeTemplates.js +3 -3
  63. data/lib/api_browser/app/js/filters/markdown.js +6 -0
  64. data/lib/api_browser/app/js/filters/resource_name.js +2 -2
  65. data/lib/api_browser/app/sass/modules/_header.scss +2 -7
  66. data/lib/api_browser/app/sass/{main.scss → praxis.scss} +0 -0
  67. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +370 -367
  68. data/lib/api_browser/app/views/action.html +2 -2
  69. data/lib/api_browser/app/views/controller.html +2 -2
  70. data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
  71. data/lib/api_browser/app/views/layout.html +2 -11
  72. data/lib/api_browser/app/views/navbar.html +9 -0
  73. data/lib/api_browser/app/views/resource/_actions.html +1 -1
  74. data/lib/api_browser/app/views/type.html +2 -2
  75. data/lib/api_browser/app/views/type/_details.html +2 -1
  76. data/lib/api_browser/bower.json +5 -0
  77. data/lib/api_browser/package.json +18 -7
  78. data/lib/praxis.rb +8 -3
  79. data/lib/praxis/action_definition.rb +28 -6
  80. data/lib/praxis/api_definition.rb +30 -2
  81. data/lib/praxis/api_general_info.rb +36 -0
  82. data/lib/praxis/bootloader.rb +1 -0
  83. data/lib/praxis/collection.rb +34 -0
  84. data/lib/praxis/controller.rb +7 -0
  85. data/lib/praxis/dispatcher.rb +3 -0
  86. data/lib/praxis/links.rb +2 -8
  87. data/lib/praxis/media_type.rb +6 -24
  88. data/lib/praxis/media_type_collection.rb +6 -2
  89. data/lib/praxis/plugin_concern.rb +2 -1
  90. data/lib/praxis/request.rb +24 -15
  91. data/lib/praxis/request_stages/request_stage.rb +19 -4
  92. data/lib/praxis/request_stages/validate_params_and_headers.rb +1 -1
  93. data/lib/praxis/request_stages/validate_payload.rb +1 -1
  94. data/lib/praxis/resource_definition.rb +45 -10
  95. data/lib/praxis/response_definition.rb +46 -27
  96. data/lib/praxis/restful_doc_generator.rb +94 -7
  97. data/lib/praxis/simple_media_type.rb +2 -9
  98. data/lib/praxis/stage.rb +1 -4
  99. data/lib/praxis/tasks/api_docs.rb +51 -19
  100. data/lib/praxis/tasks/routes.rb +19 -15
  101. data/lib/praxis/types/media_type_common.rb +31 -0
  102. data/lib/praxis/types/multipart.rb +4 -4
  103. data/lib/praxis/version.rb +1 -1
  104. data/praxis.gemspec +2 -2
  105. data/spec/api_browser/factories/documentation_spec.js +50 -0
  106. data/spec/api_browser/filters/attribute_name_spec.js +23 -0
  107. data/spec/functional_spec.rb +62 -10
  108. data/spec/praxis/action_definition_spec.rb +12 -4
  109. data/spec/praxis/api_definition_spec.rb +159 -0
  110. data/spec/praxis/api_general_info_spec.rb +36 -0
  111. data/spec/praxis/bootloader_spec.rb +10 -1
  112. data/spec/praxis/media_type_collection_spec.rb +46 -53
  113. data/spec/praxis/media_type_spec.rb +6 -6
  114. data/spec/praxis/request_stage_spec.rb +7 -2
  115. data/spec/praxis/request_stages_validate_spec.rb +12 -7
  116. data/spec/praxis/resource_definition_spec.rb +62 -0
  117. data/spec/praxis/response_definition_spec.rb +26 -16
  118. data/spec/praxis/stage_spec.rb +4 -8
  119. data/spec/praxis/types/collection_spec.rb +144 -0
  120. data/spec/spec_app/app/controllers/instances.rb +8 -2
  121. data/spec/spec_app/design/api.rb +11 -0
  122. data/spec/spec_app/design/media_types/instance.rb +12 -0
  123. data/spec/spec_app/design/media_types/volume.rb +9 -2
  124. data/spec/spec_app/design/media_types/volume_snapshot.rb +9 -6
  125. data/spec/spec_app/design/resources/instances.rb +25 -10
  126. data/spec/support/spec_media_types.rb +1 -1
  127. data/spec/support/spec_resource_definitions.rb +2 -0
  128. data/tasks/thor/app.rb +15 -10
  129. data/tasks/thor/example.rb +115 -115
  130. data/tasks/thor/templates/generator/empty_app/.gitignore +2 -0
  131. data/tasks/thor/templates/generator/empty_app/docs/app.js +1 -0
  132. data/tasks/thor/templates/generator/empty_app/docs/styles.scss +3 -0
  133. metadata +50 -9
  134. data/lib/api_browser/app/css/main.css +0 -4511
  135. data/lib/praxis/types/collection.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4684312c88071162f3525b9ee7c88c9f9a7587d2
4
- data.tar.gz: fcf53c832ebc5f430dc37b9944ccc334b7ec3678
3
+ metadata.gz: 969f34805663e8986a5ac60e86216c3139324d98
4
+ data.tar.gz: 8fb76988854889627663ff66874ecb1a8f4549b0
5
5
  SHA512:
6
- metadata.gz: a600f9e9857b338f87c3dbec975e016a7f3bee940b0a9c590cfc241e7b05e81825877a92a6b49049089ef76ecabcf127ef978d3d545d828b8d7ce197a0b792d8
7
- data.tar.gz: 115db171ee75c4569beab2277e4c917bcd768e444e264b769862373936365a54cff1eaa154c21cf7543b59816756e45aafddbc0dd0c95714afdc392f95cae006
6
+ metadata.gz: 228bc86fd20fef3ad70b282519266378b6f90333e36438923b5a5ed8c416ccacf7d5ac4444bab3d675a2bdd210a3cb89a62090d3ce780d2a5c62cc9c848216d1
7
+ data.tar.gz: b355e2bd55fe51389ba695d8348303560208d960694f8832d74ebf59942b3e9088cf757c48ae37109b975d6dac238815f15528457c32655c2baa3c3c9b7cf290
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.1.5
data/.travis.yml CHANGED
@@ -1,5 +1,18 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - "2.1.2"
5
- script: bundle exec rspec spec
4
+ - "2.1.5"
5
+ node_js:
6
+ - "0.10"
7
+ branches:
8
+ only:
9
+ - master
10
+ before_install:
11
+ - cd lib/api_browser
12
+ - npm install
13
+ - cd ../..
14
+ script:
15
+ - bundle exec rspec spec
16
+ - cd lib/api_browser
17
+ - npm test
18
+ - cd ../..
data/CHANGELOG.md CHANGED
@@ -2,8 +2,60 @@
2
2
 
3
3
  ## next
4
4
 
5
- ## 0.13.0
5
+ ## 0.14.0
6
+
7
+ * Adds features for customizing and exporting the Doc browser, namely the following changes:
8
+ 1. All doc browser stuff is now centralised under the `praxis:docs` namespace.
9
+ 2. The doc browser requires node.js. (TODO: add this to the docs PR)
10
+ 3. `rake praxis:docs:generate` generates the JSON schema files. `rake praxis:api_docs` is now an alias of this with the idea that `rake praxis:api_docs` will be deprecated.
11
+ 4. `rake praxis:docs:preview` will open a browser window with the doc browser. It will refresh automatically when the design files change as well as when any customisations change.
12
+ 5. `rake praxis:docs:build` will generate a fully built static version of the app in `docs/output`. This can then be put on S3 or GH pages and should work.
13
+ 6. The default app generator will now generate a docs directory with some files to get you started.
14
+ 7. Any `.js` file in the `docs` directory will be included in the doc browser. Angular's dependency injection allows users to override any service or controller as needed.
15
+ 8. The default `docs/styles.scss` simply `@import 'praxis'`. However this means the user can override any of bootstraps variables allowing for easy theme customisation. Rules etc. can now also be overridden.
16
+ 9. Any templates defined in `docs/views` take precedence over those defined in the doc browser. This means the user can easily customise parts of the app, while leaving the rest up to us.
17
+ 10. Any changes to the above customisations will be automatically reloaded on save.
18
+ * First pass at describing (and doc-generating) API global information
19
+ * Inside a `Praxis::ApiDefinition.define` block one can now specify a few things about the API by using:
20
+ * info("1.0") `<block>` - Which will apply to a particular version only
21
+ * info `<block>` - Which will be inherited by any existing API version
22
+ * The current pieces of information that can be defined in the block are: `name`, `title`, `description` and `basepath`. See [this](https://github.com/rightscale/praxis/blob/master/spec/spec_app/design/api.rb) for details
23
+ * NOTE: This information is output to the JSON files, BUT not used in the doc browser yet.
24
+ * Changed the doc generation and browser to use "ids" instead of "names" for routes and generated files.
25
+ * Currently, "ids" are generated using dashes instead of double colons (instead of random ids). This closes issue #31.
26
+ * Added the definition and handling of canonical urls for API resources
27
+ * One can now specify which action URL should be considered as the canonical resource href:
28
+ * by using `canonical_path <action_name>` at the top of the resource definition class
29
+ * See the [instances](https://github.com/rightscale/praxis/blob/master/spec/spec_app/design/resources/instances.rb) resource definition for an example.
30
+ * With a canonical href defined, one can then both generate and parse them by using:
31
+ * `.to_href(<named arguments hash>) => <href String>`
32
+ * `.parse_href( <href String> ) => < named arguments hash >`. Note: The returned arguments are properly typed-coerced.
33
+ * These helpers can be accessed from:
34
+ * the `definition` object in the controller instance (i.e., `self.definition.to_href(id: 1). )
35
+ * or through the class-level methods in the resource definition (i.e. `MyApiResource.parse_href("/my_resource/1")` )
36
+ * Hooked up rake tasks into the `praxis` binary for convenience. In particular
37
+ * praxis routes [json]
38
+ * praxis docs [browser]
39
+ * praxis console
40
+ * Added `MediaTypeCommon` module, which contains the `identifier`, `description`, and `describe` methods formerly found in `MediaType`. This is now the module used for checking whether a given class should be included in generated documentation, or is valid for use in a `ResponseDefinition`
41
+ * Improved `Praxis::Collection.of` when used with MediaTypes
42
+ * It will now define an inner `<media_type>::Collection` type that is an `Attributor::Collection` of the MediaType that also will include the `MediaTypeCommon` module.
43
+ * By default, Praxis will take the identifier of the parent `MediaType` and append a `collection=true` suffix to it.
44
+ * Fixed `ResponseDefinition` Content-Type validation to properly handle parameters (i.e., "application/json;collection=true").
45
+ * Note: For "index" type actions, this now means Praxis will properly validate any 'collection=true' parameter specified in the `ResponseDefintion` and set by the controller.
46
+ * Deprecated `MediaTypeCollection`. Please define separate classes and attributes for "collection" and "summary" uses.
47
+ * Improved code for stages
48
+ * `setup!` is no longer called within the `run` default code of a stage
49
+ * removed unnecessary raise error when substages are empty (while not common it can be possible, and totally valid)
50
+ * Add `Response` to supported classes in `PluginConcern`
51
+ * Fix doc generation to use `ids` for top-level types (rather than names) so they are correctly linkable.
52
+ * Doc Browser: Added support for Markdown rendering of descriptions (for resources, media_types, attributes, etc...)
53
+ * Added test framework for the doc browser. Run the tests with `grunt test` from lib/api_browser.
54
+ * Enhanced the `praxis:docs:preview` rake task with an optional port parameter
55
+ * Fixed praxis:routes rake task to support actions that do not have routes defined
56
+ * Added `:source` to `ActionDefinition` parameter descriptions with the value of either 'url' or 'query' to denote where the parameter is (typically) extracted from. Note: not currently shown in doc browser.
6
57
 
58
+ ## 0.13.0
7
59
  * Added `nodoc!` method to `ActionDefinition`, `ResourceDefinition` to hide actions and resources from the generated documentation.
8
60
  * Default HTTP responses:
9
61
  * Added descriptions
@@ -24,6 +76,7 @@
24
76
  * This is not compatible if it also wants to use the `links` DSL.
25
77
 
26
78
 
79
+
27
80
  ## 0.11.2
28
81
 
29
82
  * The Doc Browser will now not change the menu when refreshing.
data/bin/praxis CHANGED
@@ -2,12 +2,59 @@
2
2
 
3
3
  require 'bundler'
4
4
 
5
+ Bundler.setup :default, :test
6
+ Bundler.require :default, :test
7
+
8
+
9
+ if ["routes","docs","console"].include? ARGV[0]
10
+ require 'rake'
11
+ require 'praxis'
12
+ require 'praxis/tasks'
13
+
14
+ case ARGV[0]
15
+ when "routes"
16
+ Rake::Task['praxis:routes'].invoke(ARGV[1])
17
+ when "docs"
18
+ task_name = case ARGV[1]
19
+ when nil,'browser'
20
+ 'praxis:docs:preview'
21
+ when 'generate'
22
+ 'praxis:docs:generate'
23
+ when 'package'
24
+ 'praxis:docs:build'
25
+ end
26
+ # task_name = ARGV[1] == 'browser' ? 'praxis:doc_browser' : 'praxis:api_docs'
27
+ Rake::Task[task_name].invoke
28
+ when "console"
29
+ Rake::Task['praxis:console'].invoke
30
+ end
31
+ exit 0
32
+ end
33
+ # Thor tasks
5
34
  path_to_praxis = File.expand_path(File.dirname(File.dirname(__FILE__)))
6
35
  path_to_loader = '%s/tasks/loader.thor' % path_to_praxis
7
36
 
8
37
  load path_to_loader
9
38
 
10
39
  class PraxisGenerator < Thor
40
+
41
+ # Include a few fake thor action descriptions (for the rake tasks above) so they can show up in the same usage messages
42
+ desc "routes [json]", "Prints the route table of the application. Defaults to table format, but can produce json"
43
+ def routes
44
+ end
45
+
46
+ desc "docs [generate|browser|package]", <<-EOF
47
+ Generates API documentation and a Web App to inspect it
48
+ generate - Generates the JSON docs
49
+ browser - (default) Generates JSON docs, and automatically starts a Web app to browse them.
50
+ package - Generates JSON docs, and neatly packages all the necessary static files ready for exporting the browsing app.
51
+ EOF
52
+ def docs
53
+ end
54
+
55
+ desc "console", "Open a console to the application, with its environment loaded"
56
+ def console
57
+ end
11
58
 
12
59
  # Simple helper to go get the existing description for the real action
13
60
  # Usage must still be provided rather than retrieved (since it is not a
@@ -33,7 +80,7 @@ class PraxisGenerator < Thor
33
80
  def generate(app_name)
34
81
  warn "This is a deprecated method.\nTo generate a hello world example, please use:\n praxis example #{app_name} "
35
82
  end
83
+
36
84
  end
37
-
38
-
85
+
39
86
  PraxisGenerator.start(ARGV)
@@ -3,13 +3,24 @@ module.exports = function(grunt) {
3
3
  require('load-grunt-tasks')(grunt);
4
4
 
5
5
  // Time how long tasks take. Can help when optimizing build times
6
- require('time-grunt')(grunt);
6
+ try {
7
+ require('time-grunt')(grunt);
8
+ } catch(e) {
9
+
10
+ }
11
+
12
+ var userDocsPath = process.env.USER_DOCS_PATH,
13
+ buildPath = userDocsPath + '/output',
14
+ browserPort = process.env.DOC_PORT || '9090';
15
+
16
+ var cssOutput = {};
17
+ cssOutput[buildPath + '/css/main.css'] = userDocsPath + '/styles.scss';
7
18
 
8
19
  grunt.initConfig({
9
20
  // web server for development
10
21
  connect: {
11
22
  options: {
12
- port: '9090',
23
+ port: browserPort,
13
24
  hostname: '0.0.0.0'
14
25
  },
15
26
  livereload: {
@@ -17,6 +28,7 @@ module.exports = function(grunt) {
17
28
  livereload: 9091,
18
29
  open: true,
19
30
  base: [
31
+ userDocsPath,
20
32
  '.tmp',
21
33
  '.data',
22
34
  'app'
@@ -25,77 +37,38 @@ module.exports = function(grunt) {
25
37
  },
26
38
  dist: {
27
39
  options: {
28
- base: ['.data', 'dist']
40
+ base: ['.data', buildPath]
29
41
  }
30
42
  }
31
43
  },
32
44
 
33
45
  clean: {
34
- dist: {
46
+ serve: {
35
47
  files: [{
36
48
  dot: true,
37
49
  src: [
38
- '.tmp',
39
- 'dist/*',
40
- '!dist/.git*'
50
+ '.tmp'
41
51
  ]
42
52
  }]
43
- }
44
- },
45
-
46
- // Watches files for changes
47
- watch: {
48
- // Reload stuff when the grunt file changes
49
- config: {
50
- files: ['Gruntfile.js'],
51
- tasks: 'prep',
52
- options: {
53
- reload: true
54
- }
55
- },
56
-
57
- // Updates index.html for any file added or removed
58
- scripts: {
59
- files: ['app/js/**/*.js'],
60
- tasks: 'fileblocks:scripts',
61
- options: { livereload: 9091 }
62
- },
63
-
64
- // Updates index.html for any bower component added or removed
65
- bowerComponents: {
66
- files: ['app/bower_components/**/*'],
67
- tasks: 'wiredep',
68
- options: { livereload: 9091 }
69
53
  },
70
-
71
- // Rebuild the stylesheets for any SASS file changed
72
- sass: {
73
- files: [
74
- 'app/sass/**/*.scss',
75
- 'app/bower_components/**/*.scss'
76
- ],
77
- tasks: 'sass',
78
- options: { livereload: 9091 }
79
- },
80
-
81
- // Watches files that don't need processing
82
- other: {
83
- files: [
84
- 'app/css/*.css',
85
- "app/index.html",
86
- "app/views/**/*.html"
87
- ],
54
+ dist: {
88
55
  options: {
89
- livereload: 9091
90
- }
56
+ force: true,
57
+ },
58
+ files: [{
59
+ dot: true,
60
+ src: [
61
+ '.tmp',
62
+ buildPath
63
+ ]
64
+ }]
91
65
  }
92
66
  },
93
-
94
67
  // Automatically inject Bower components into the app
95
68
  wiredep: {
96
69
  app: {
97
- src: 'app/index.html',
98
- ignorePath: 'app/',
70
+ src: '.tmp/index.html',
71
+ ignorePath: /(..\/)?app\//,
99
72
  // We do not use bootstrap's JS code, also the SASS styles are included by our style sheet
100
73
  exclude: [/bootstrap-sass/]
101
74
  }
@@ -104,13 +77,34 @@ module.exports = function(grunt) {
104
77
  // Automatically inject the JS files into the app
105
78
  fileblocks: {
106
79
  options: { removeFiles: true },
107
- scripts: {
80
+ dist: {
81
+ src: 'app/index.html',
82
+ dest: '.tmp/index.html',
83
+ blocks: {
84
+ scripts: {
85
+ cwd: 'app',
86
+ // This ensures app.js comes first so the angular module is declared
87
+ src: ['js/app.js', 'js/**/*.js']
88
+ },
89
+ userscripts: {
90
+ // cwd: userDocsPath,
91
+ src: [userDocsPath + '/app.js', userDocsPath + '/**/*.js', '!' + userDocsPath + '/output/**/*.js']
92
+ }
93
+ }
94
+ },
95
+
96
+ serve: {
108
97
  src: 'app/index.html',
98
+ dest: '.tmp/index.html',
109
99
  blocks: {
110
100
  scripts: {
111
101
  cwd: 'app',
112
102
  // This ensures app.js comes first so the angular module is declared
113
103
  src: ['js/app.js', 'js/**/*.js']
104
+ },
105
+ userscripts: {
106
+ cwd: userDocsPath,
107
+ src: ['app.js', '**/*.js', '!output/**/*.js']
114
108
  }
115
109
  }
116
110
  }
@@ -121,29 +115,28 @@ module.exports = function(grunt) {
121
115
  server: {
122
116
  options: {
123
117
  sourceComments: 'map',
124
- sourceMap: 'app/css/main.css.map'
118
+ sourceMap: __dirname + '/.tmp/css/main.css.map',
119
+ includePaths: ['app/sass']
125
120
  },
126
121
  files: {
127
- 'app/css/main.css': 'app/sass/main.scss'
122
+ '.tmp/css/main.css': userDocsPath + '/styles.scss'
128
123
  }
129
124
  },
130
125
  dist: {
131
126
  options: {
132
- sourceComments: 'none'
127
+ sourceComments: 'none',
128
+ includePaths: ['app/sass']
133
129
  },
134
- files: {
135
- 'dist/css/main.css': 'app/sass/main.scss'
136
- }
130
+ files: cssOutput
137
131
  }
138
132
  },
139
133
 
140
134
  cssmin: {
141
135
  dist: {
142
- files: {
143
- 'dist/css/main.css': [
144
- 'dist/css/main.css'
145
- ]
146
- }
136
+ files: [{
137
+ src: buildPath + '/css/main.css',
138
+ dest: buildPath + '/css/main.css'
139
+ }]
147
140
  }
148
141
  },
149
142
 
@@ -152,7 +145,7 @@ module.exports = function(grunt) {
152
145
  files: [{
153
146
  expand: true,
154
147
  cwd: '.tmp/concat/scripts',
155
- src: 'scripts.js',
148
+ src: '*.js',
156
149
  dest: '.tmp/concat/scripts'
157
150
  }]
158
151
  }
@@ -161,8 +154,8 @@ module.exports = function(grunt) {
161
154
  filerev: {
162
155
  dist: {
163
156
  src: [
164
- 'dist/scripts/*.js',
165
- 'dist/css/*.css'
157
+ buildPath + '/scripts/*.js',
158
+ buildPath + '/css/*.css'
166
159
  ]
167
160
  }
168
161
  },
@@ -179,16 +172,27 @@ module.exports = function(grunt) {
179
172
  removeScriptTypeAttributes: true,
180
173
  removeStyleLinkTypeAttributes: true
181
174
  },
182
- module: 'docBrowser',
183
175
  bootstrap: function(module, script) {
184
176
  return 'angular.module("' + module + '").run(function($templateCache){' + script + '});';
185
177
  },
186
- usemin: 'dist/scripts/scripts.js'
187
178
  },
188
179
  dist: {
189
180
  cwd: 'app',
190
181
  src: 'views/**/*.html',
191
- dest: '.tmp/templates.js'
182
+ dest: '.tmp/templates.js',
183
+ options: {
184
+ usemin: buildPath + '/scripts/praxis.js',
185
+ module: 'PraxisDocBrowser',
186
+ }
187
+ },
188
+ userScripts: {
189
+ cwd: userDocsPath,
190
+ src: 'views/**/*.html',
191
+ dest: '.tmp/usertemplates.js',
192
+ options: {
193
+ usemin: buildPath + '/scripts/docs.js',
194
+ module: 'DocBrowser',
195
+ }
192
196
  }
193
197
  },
194
198
 
@@ -198,10 +202,25 @@ module.exports = function(grunt) {
198
202
  expand: true,
199
203
  dot: true,
200
204
  cwd: 'app',
201
- dest: 'dist',
205
+ dest: buildPath,
206
+ src: [
207
+ '*.{ico,png,txt}'
208
+ ]
209
+ }, {
210
+ expand: true,
211
+ dot: true,
212
+ cwd: '.tmp',
213
+ dest: buildPath,
202
214
  src: [
203
- '*.{ico,png,txt}',
204
- 'index.html',
215
+ 'index.html'
216
+ ]
217
+ }, {
218
+ expand: true,
219
+ dot: true,
220
+ cwd: userDocsPath,
221
+ dest: buildPath,
222
+ src: [
223
+ 'api/**'
205
224
  ]
206
225
  }]
207
226
  }
@@ -211,36 +230,146 @@ module.exports = function(grunt) {
211
230
  // concat, minify and revision files. Creates configurations in memory so
212
231
  // additional tasks can operate on them
213
232
  useminPrepare: {
214
- html: 'app/index.html',
233
+ html: '.tmp/index.html',
215
234
  options: {
216
- dest: 'dist'
235
+ dest: buildPath
217
236
  }
218
237
  },
219
238
 
220
239
  // Performs rewrites based on rev and the useminPrepare configuration
221
240
  usemin: {
222
- html: ['dist/{,*/}*.html'],
223
- css: ['dist/css/{,*/}*.css'],
241
+ html: [buildPath + '/index.html'],
242
+ css: [buildPath + '/css/{,*/}*.css'],
243
+ options: {
244
+ assetsDirs: [buildPath]
245
+ }
246
+ },
247
+
248
+ karma: {
224
249
  options: {
225
- assetsDirs: ['dist']
250
+ files: [
251
+ 'node_modules/quick_check/dist/jasmine-quick-check.js',
252
+ 'app/bower_components/jquery/dist/jquery.js',
253
+ 'app/bower_components/angular/angular.js',
254
+ 'app/bower_components/lodash/dist/lodash.compat.js',
255
+ 'app/bower_components/angular-ui-router/release/angular-ui-router.js',
256
+ 'app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js',
257
+ 'app/bower_components/angular-sanitize/angular-sanitize.js',
258
+ 'app/bower_components/angular-mocks/angular-mocks.js',
259
+ 'app/js/app.js', 'app/js/**/*.js', '.tmp/templates.js', '../../spec/api_browser/**/*.js'
260
+ ],
261
+ frameworks: ['jasmine'],
262
+ reporters: ['dots'],
263
+ },
264
+ unit: {
265
+ browsers: ['PhantomJS'],
266
+ singleRun: true
267
+ }
268
+ },
269
+
270
+ jshint: {
271
+ src: ['app/js/**/*.js', '../../spec/api_browser/**/*.js'],
272
+ options: {
273
+ bitwise: true,
274
+ immed: true,
275
+ newcap: false,
276
+ noarg: true,
277
+ noempty: true,
278
+ nonew: true,
279
+ trailing: true,
280
+ boss: true,
281
+ eqnull: true,
282
+ expr: true,
283
+ laxbreak: true,
284
+ loopfunc: true,
285
+ sub: true,
286
+ undef: true,
287
+ unused: true,
288
+ browser: true,
289
+ quotmark: true,
290
+ indent: 2,
291
+ jasmine: true,
292
+ globals: {
293
+ "angular": false,
294
+ "app": true,
295
+ "_": false,
296
+ "$": false,
297
+ "jQuery": false,
298
+ "Showdown": false,
299
+ "inject": false,
300
+ "qc": false
301
+ }
226
302
  }
227
303
  }
228
304
  });
229
305
 
230
- // Prepares the assets (used by watch:config)
231
- grunt.registerTask('prep', [
232
- 'fileblocks',
233
- 'wiredep',
234
- 'sass'
235
- ]);
306
+ grunt.registerTask('runGenerator', function() {
307
+ var exec = require('child_process').exec;
308
+ var done = this.async();
309
+ exec('bundle exec rake praxis:docs:generate', {cwd: userDocsPath + '/../'}, done);
310
+ });
236
311
 
237
312
  grunt.registerTask('serve', function(target) {
238
313
  if (target === 'dist') {
239
314
  return grunt.task.run(['build', 'connect:dist:keepalive']);
240
315
  }
241
316
 
317
+ grunt.config.merge({
318
+ watch: {
319
+ // Updates index.html for any file added or removed
320
+ scripts: {
321
+ files: ['app/js/**/*.js', userDocsPath + '/**/*.js'],
322
+ tasks: 'fileblocks:serve',
323
+ options: { livereload: 9091 }
324
+ },
325
+
326
+ // Updates index.html for any bower component added or removed
327
+ bowerComponents: {
328
+ files: ['app/bower_components/**/*', userDocsPath + '/bower_components/**/*'],
329
+ tasks: 'wiredep',
330
+ options: { livereload: 9091 }
331
+ },
332
+
333
+ // Rebuild the stylesheets for any SASS file changed
334
+ sass: {
335
+ files: [
336
+ 'app/sass/**/*.scss',
337
+ 'app/bower_components/**/*.scss',
338
+ userDocsPath + '/**/*.scss'
339
+ ],
340
+ tasks: 'sass',
341
+ options: { livereload: 9091 }
342
+ },
343
+
344
+ data: {
345
+ files: [
346
+ userDocsPath + '/../design/**/*.rb'
347
+ ],
348
+ tasks: 'runGenerator',
349
+ options: { livereload: 9091 }
350
+ },
351
+
352
+ // Watches files that don't need processing
353
+ other: {
354
+ files: [
355
+ 'app/css/*.css',
356
+ "app/index.html",
357
+ "app/views/**/*.html",
358
+ userDocsPath + '/views/**/*.html'
359
+ ],
360
+ options: {
361
+ livereload: 9091
362
+ }
363
+ }
364
+ }
365
+ });
366
+
367
+
242
368
  grunt.task.run([
243
- 'prep',
369
+ 'clean:serve',
370
+ 'fileblocks:serve',
371
+ 'wiredep',
372
+ 'sass:server',
244
373
  'connect:livereload',
245
374
  'watch'
246
375
  ]);
@@ -248,7 +377,9 @@ module.exports = function(grunt) {
248
377
 
249
378
  grunt.registerTask('build', [
250
379
  'clean:dist',
251
- 'prep',
380
+ 'fileblocks:dist',
381
+ 'wiredep',
382
+ 'sass:dist',
252
383
  'useminPrepare',
253
384
  'ngtemplates',
254
385
  'concat',
@@ -260,5 +391,31 @@ module.exports = function(grunt) {
260
391
  'usemin'
261
392
  ]);
262
393
 
394
+ grunt.registerTask('test', function() {
395
+ grunt.config.set('watch', {
396
+ tests: {
397
+ files: [
398
+ 'app/js/**',
399
+ '../../spec/api_browser/**'
400
+ ],
401
+ tasks: ['jshint:src', 'karma:unit'],
402
+ options: {
403
+ atBegin: true
404
+ }
405
+ }
406
+ });
407
+
408
+ grunt.task.run([
409
+ 'ngtemplates:dist',
410
+ 'watch:tests'
411
+ ]);
412
+ });
413
+
414
+ grunt.registerTask('ci', [
415
+ 'ngtemplates:dist',
416
+ 'jshint:src',
417
+ 'karma:unit'
418
+ ]);
419
+
263
420
  grunt.registerTask("default", ["serve"]);
264
421
  };