raml_ruby 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +71 -0
  7. data/Rakefile +1 -0
  8. data/fixtures/include_1.raml +7 -0
  9. data/fixtures/schemas/canonicalSchemas.raml +3 -0
  10. data/fixtures/schemas/filesystem/file.json +1 -0
  11. data/fixtures/schemas/filesystem/files.json +1 -0
  12. data/fixtures/schemas/filesystem/fileupdate.json +1 -0
  13. data/fixtures/schemas/filesystem/relative/test.json +1 -0
  14. data/lib/raml.rb +104 -0
  15. data/lib/raml/exceptions.rb +27 -0
  16. data/lib/raml/mixin/bodies.rb +32 -0
  17. data/lib/raml/mixin/documentable.rb +32 -0
  18. data/lib/raml/mixin/global.rb +20 -0
  19. data/lib/raml/mixin/headers.rb +22 -0
  20. data/lib/raml/mixin/merge.rb +24 -0
  21. data/lib/raml/mixin/parent.rb +54 -0
  22. data/lib/raml/mixin/validation.rb +49 -0
  23. data/lib/raml/node.rb +219 -0
  24. data/lib/raml/node/abstract_method.rb +61 -0
  25. data/lib/raml/node/abstract_resource.rb +165 -0
  26. data/lib/raml/node/abstract_resource_circular.rb +5 -0
  27. data/lib/raml/node/body.rb +94 -0
  28. data/lib/raml/node/documentation.rb +28 -0
  29. data/lib/raml/node/header.rb +4 -0
  30. data/lib/raml/node/method.rb +106 -0
  31. data/lib/raml/node/parameter/abstract_parameter.rb +251 -0
  32. data/lib/raml/node/parameter/base_uri_parameter.rb +6 -0
  33. data/lib/raml/node/parameter/form_parameter.rb +6 -0
  34. data/lib/raml/node/parameter/query_parameter.rb +6 -0
  35. data/lib/raml/node/parameter/uri_parameter.rb +7 -0
  36. data/lib/raml/node/parametized_reference.rb +15 -0
  37. data/lib/raml/node/reference.rb +4 -0
  38. data/lib/raml/node/resource.rb +26 -0
  39. data/lib/raml/node/resource_type.rb +20 -0
  40. data/lib/raml/node/resource_type_reference.rb +5 -0
  41. data/lib/raml/node/response.rb +32 -0
  42. data/lib/raml/node/root.rb +246 -0
  43. data/lib/raml/node/schema.rb +41 -0
  44. data/lib/raml/node/schema_reference.rb +5 -0
  45. data/lib/raml/node/template.rb +55 -0
  46. data/lib/raml/node/trait.rb +18 -0
  47. data/lib/raml/node/trait_reference.rb +5 -0
  48. data/lib/raml/parser.rb +57 -0
  49. data/lib/raml/parser/include.rb +25 -0
  50. data/lib/raml/patch/hash.rb +6 -0
  51. data/lib/raml/patch/module.rb +12 -0
  52. data/lib/raml/version.rb +3 -0
  53. data/raml_ruby.gemspec +35 -0
  54. data/raml_spec_reqs.md +276 -0
  55. data/templates/abstract_parameter.slim +68 -0
  56. data/templates/body.slim +15 -0
  57. data/templates/collapse.slim +10 -0
  58. data/templates/documentation.slim +2 -0
  59. data/templates/method.slim +38 -0
  60. data/templates/resource.slim +33 -0
  61. data/templates/response.slim +13 -0
  62. data/templates/root.slim +39 -0
  63. data/templates/style.sass +119 -0
  64. data/test/apis/box-api.raml +4224 -0
  65. data/test/apis/instagram-api.raml +3378 -0
  66. data/test/apis/stripe-api.raml +12227 -0
  67. data/test/apis/twilio-rest-api.raml +6618 -0
  68. data/test/apis/twitter-rest-api.raml +34284 -0
  69. data/test/raml/body_spec.rb +268 -0
  70. data/test/raml/documentation_spec.rb +49 -0
  71. data/test/raml/header_spec.rb +17 -0
  72. data/test/raml/include_spec.rb +40 -0
  73. data/test/raml/method_spec.rb +701 -0
  74. data/test/raml/parameter/abstract_parameter_spec.rb +564 -0
  75. data/test/raml/parameter/form_parameter_spec.rb +17 -0
  76. data/test/raml/parameter/query_parameter_spec.rb +33 -0
  77. data/test/raml/parameter/uri_parameter_spec.rb +44 -0
  78. data/test/raml/parser_spec.rb +53 -0
  79. data/test/raml/raml_spec.rb +32 -0
  80. data/test/raml/resource_spec.rb +440 -0
  81. data/test/raml/resource_type_spec.rb +51 -0
  82. data/test/raml/response_spec.rb +251 -0
  83. data/test/raml/root_spec.rb +655 -0
  84. data/test/raml/schema_spec.rb +110 -0
  85. data/test/raml/spec_helper.rb +11 -0
  86. data/test/raml/template_spec.rb +98 -0
  87. data/test/raml/trait_spec.rb +31 -0
  88. metadata +337 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d5b2c3c690054638bb3cdf5dd0ea4fe0cf6e5763
4
+ data.tar.gz: 913d89301e7cb20ff0e6c73deb7b5104b93b4e47
5
+ SHA512:
6
+ metadata.gz: a2c78f5010254baab46d008805a257e78a0793486f0e339607a514d2622685c6d991550f53b463ed91b1ff03aead6ff3d5ee5077ba44880dc2c2483900b3d033
7
+ data.tar.gz: 1206b2996083539351d5ece371ee8451658c7994b7c9630ae99db5019b30bdd42933f673722ad28092dbc3be34da5aad19c5e63c681317d61747267db80d82ee
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rvmrc
7
+ *.sublime*
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.1.2"
5
+ - jruby-19mode
6
+ script: bundle exec rspec test
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in raml_ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014-2015 kgorin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # RAML ruby
2
+
3
+ [![Build Status](https://travis-ci.org/eliaslevy/raml_ruby.svg?branch=master)](https://travis-ci.org/eliaslevy/raml_ruby)
4
+
5
+ Implementation of a RAML parser in Ruby. It uses the stdlib YAML parser
6
+ (Psych). It can also generate HTML documentation.
7
+
8
+
9
+ <!---
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'raml_ruby'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install raml_ruby
23
+ -->
24
+
25
+ ## Usage
26
+
27
+ Clone this repository:
28
+
29
+ git clone git@github.com:coub/raml_ruby.git
30
+
31
+ Require:
32
+
33
+ require 'lib/raml'
34
+
35
+ or
36
+
37
+ pry -r ./lib/raml.rb
38
+
39
+ To parse the file:
40
+
41
+ Raml.parse_file("path/to/your/file.raml")
42
+
43
+ To generate HTML documentation:
44
+
45
+ # write to file
46
+ Raml.document("/path/to/your/file.raml", "path/to/output/file.html")
47
+
48
+ # or just on screen
49
+ Raml.document("/path/to/your/file.raml")
50
+
51
+ ## To Do
52
+
53
+ - Align mergin strategy of conflicting properties of resource types and traits with official Javascript and Java parsers.
54
+ - Security schemes
55
+ - Publish to Rubygems
56
+
57
+ More a more detailed analysis of the spec requirements and which ones are finishes see the [RAML requirements document](raml_spec_reqs.md).
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
66
+
67
+ ## License
68
+
69
+ See [LICENSE](https://github.com/coub/raml_ruby/blob/master/LICENSE.txt).
70
+
71
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #%RAML 0.8
2
+ baseUri: https://api.example.com
3
+ title: Filesystem API
4
+ version: 0.1
5
+ schemas:
6
+ - !include schemas/canonicalSchemas.raml
7
+ - File: !include schemas/filesystem/file.json
@@ -0,0 +1,3 @@
1
+ FileUpdate: !include filesystem/fileupdate.json
2
+ Files: !include filesystem/files.json
3
+ Test: !include filesystem/relative/test.json
@@ -0,0 +1 @@
1
+ file_schema
@@ -0,0 +1 @@
1
+ files_schema
@@ -0,0 +1 @@
1
+ file_update_schema
@@ -0,0 +1 @@
1
+ test_schema
data/lib/raml.rb ADDED
@@ -0,0 +1,104 @@
1
+ require_relative 'raml/version'
2
+
3
+ require_relative 'raml/patch/module'
4
+ require_relative 'raml/patch/hash'
5
+
6
+ require_relative 'raml/exceptions'
7
+
8
+ require_relative 'raml/parser'
9
+ require_relative 'raml/parser/include'
10
+
11
+ require_relative 'raml/mixin/bodies'
12
+ require_relative 'raml/mixin/documentable'
13
+ require_relative 'raml/mixin/global'
14
+ require_relative 'raml/mixin/headers'
15
+ require_relative 'raml/mixin/merge'
16
+ require_relative 'raml/mixin/parent'
17
+ require_relative 'raml/mixin/validation'
18
+
19
+ require_relative 'raml/node'
20
+ require_relative 'raml/node/reference'
21
+ require_relative 'raml/node/parametized_reference'
22
+
23
+ require_relative 'raml/node/parameter/abstract_parameter'
24
+ require_relative 'raml/node/parameter/form_parameter'
25
+ require_relative 'raml/node/parameter/query_parameter'
26
+ require_relative 'raml/node/parameter/uri_parameter'
27
+ require_relative 'raml/node/parameter/base_uri_parameter'
28
+
29
+ require_relative 'raml/node/schema'
30
+ require_relative 'raml/node/schema_reference'
31
+
32
+ require_relative 'raml/node/header'
33
+ require_relative 'raml/node/body'
34
+ require_relative 'raml/node/response'
35
+
36
+ require_relative 'raml/node/trait_reference'
37
+ require_relative 'raml/node/resource_type_reference'
38
+
39
+ require_relative 'raml/node/template'
40
+
41
+ require_relative 'raml/node/abstract_method'
42
+ require_relative 'raml/node/trait'
43
+ require_relative 'raml/node/method'
44
+
45
+ require_relative 'raml/node/abstract_resource'
46
+ require_relative 'raml/node/resource_type'
47
+ require_relative 'raml/node/resource'
48
+ require_relative 'raml/node/abstract_resource_circular'
49
+
50
+ require_relative 'raml/node/documentation'
51
+
52
+ require_relative 'raml/node/root'
53
+
54
+ module Raml
55
+ # Parses RAML from a string.
56
+ #
57
+ # @param raml [String] the string containing RAML.
58
+ # @return [Raml::Root] the RAML root node.
59
+ # @raise [RamlError] if the RAML is invalid.
60
+ def self.parse(raml)
61
+ Raml::Parser.parse raml
62
+ end
63
+
64
+ # Parses RAML from a file.
65
+ #
66
+ # @param filepath [String] the file path of the file containing RAML.
67
+ # @return [Raml::Root] the RAML root node.
68
+ # @raise [Errno::ENOENT] if the file can't be found.
69
+ # @raise [Errno::EACCES] if the file can't be read.
70
+ # @raise [RamlError] if the RAML is invalid.
71
+ def self.parse_file(filepath)
72
+ file = File.new filepath
73
+ raise UnsupportedRamlVersion unless file.readline =~ /\A#%RAML 0.8\s*\z/
74
+
75
+ path = File.dirname filepath
76
+ path = nil if path == ''
77
+
78
+ Raml::Parser.parse file.read, path
79
+ end
80
+
81
+ # Parses RAML from a file and generates API documentation in HTML. If no
82
+ # output filename argument is given, the HTML is returned as a string. If
83
+ # an output filename argument is given, the HTML is stored to a file at
84
+ # that location.
85
+ #
86
+ # @param filepath [String] the file path of the file containing RAML.
87
+ # @param out_file [String] the file path of the file to write the documentation to. Defaults to nil.
88
+ # @return [String] the HTML documentation, if out_file is nil.
89
+ # @raise [Errno::ENOENT] if the file can't be found.
90
+ # @raise [Errno::EACCES] if the files can't be read or written.
91
+ # @raise [RamlError] if the RAML is invalid.
92
+ def self.document(filepath, out_file=nil)
93
+ root = parse_file filepath
94
+ root.expand
95
+
96
+ if out_file
97
+ File.open(out_file, 'w') do |file|
98
+ file.write root.document
99
+ end
100
+ else
101
+ root.document
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,27 @@
1
+ module Raml
2
+ class RamlError < StandardError; end
3
+
4
+ class UnsupportedRamlVersion < RamlError; end
5
+ class CantIncludeFile < RamlError; end
6
+
7
+ class RequiredPropertyMissing < RamlError; end
8
+ class InvalidProperty < RamlError; end
9
+ class UnknownProperty < RamlError; end
10
+
11
+ class InvalidParent < RamlError; end
12
+ class InvalidSchema < RamlError; end
13
+
14
+ class InvalidMethod < RamlError; end
15
+
16
+ class InvalidParameterType < RamlError; end
17
+ class InapplicableParameterAttribute < RamlError; end
18
+ class InvalidParameterAttribute < RamlError; end
19
+
20
+ class InvalidMediaType < RamlError; end
21
+
22
+ class UnknownTraitReference < RamlError; end
23
+ class UnknownResourceTypeReference < RamlError; end
24
+ class MergeError < RamlError; end
25
+ class UnknownTypeOrTraitParameter < RamlError; end
26
+ class UnknownTypeOrTraitParamFunction < RamlError; end
27
+ end
@@ -0,0 +1,32 @@
1
+ module Raml
2
+ module Bodies
3
+ # @!attribute [r] bodies
4
+ # @return [Hash<String, Raml::Body>] the bodies, keyed by their media type.
5
+
6
+ # XXX - need this line here to trigger Yard to generate docs for the above attribute.
7
+
8
+ private
9
+
10
+ def self.included(base)
11
+ base.instance_eval do
12
+ non_scalar_property :body
13
+ children_by :bodies, :media_type , Body
14
+ end
15
+ end
16
+
17
+ def parse_body(value)
18
+ if value.is_a? Hash and value.keys.all? {|k| k.is_a? String and k =~ /.+\/.+/ }
19
+ # If all keys looks like media types, its not a default media type body.
20
+ validate_hash 'body', value, String, Hash
21
+ value.map { |b_name, b_data| Body.new b_name, b_data, self }
22
+
23
+ else
24
+ # Its a default media type body.
25
+ validate_hash 'body', value, String
26
+ media_type = default_media_type
27
+ raise InvalidMediaType, 'Body with no media type, but default media type has not been declared.' unless media_type
28
+ Body.new media_type, value, self
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require 'kramdown'
2
+
3
+ module Raml
4
+ module Documentable
5
+ # @!attribute [rw] display_name
6
+ # @return [String, nil] the node's display name.
7
+
8
+ # @!attribute [rw] description
9
+ # @return [String, nil] the node's description.
10
+
11
+ # @private
12
+ def html_description
13
+ Kramdown::Document.new(description, input: :GFM).to_html
14
+ end
15
+
16
+ private
17
+
18
+ def self.included(base)
19
+ base.instance_eval do
20
+ scalar_property :display_name, :description
21
+ end
22
+ end
23
+
24
+ def validate_display_name
25
+ raise InvalidProperty, "displayName property mus be a string." unless display_name.is_a? String
26
+ end
27
+
28
+ def validate_description
29
+ raise InvalidProperty, "description property mus be a string." unless description.is_a? String
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ module Raml
2
+ # @private
3
+ module Global
4
+ def default_media_type
5
+ @parent.default_media_type
6
+ end
7
+
8
+ def trait_declarations
9
+ @parent.trait_declarations
10
+ end
11
+
12
+ def resource_type_declarations
13
+ @parent.resource_type_declarations
14
+ end
15
+
16
+ def schema_declarations
17
+ @parent.schema_declarations
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Raml
2
+ module Headers
3
+ # @!attribute [r] headers
4
+ # @return [Hash<String, Raml::Header>] the headers, keyed by the header name.
5
+
6
+ # XXX - need this line here to trigger Yard to generate docs for the above attribute.
7
+
8
+ private
9
+
10
+ def self.included(base)
11
+ base.instance_eval do
12
+ non_scalar_property :headers
13
+ children_by :headers, :name, Header
14
+ end
15
+ end
16
+
17
+ def parse_headers(value)
18
+ validate_hash 'headers', value, String, Hash
19
+ value.map { |h_name, h_data| Header.new h_name, h_data, self }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module Raml
2
+ # @private
3
+ module Merge
4
+ def merge(other)
5
+ other.scalar_properties.each do |prop|
6
+ prop_var = "@#{prop}"
7
+ prop_val = other.instance_variable_get prop_var
8
+ instance_variable_set prop_var, prop_val unless prop_val.nil?
9
+ end
10
+ end
11
+
12
+ def merge_properties(other, type)
13
+ match, no_match = other.send(type).values.partition { |param| self.send(type).has_key? param.name }
14
+
15
+ match.each { |param| self.send(type)[param.name].merge param }
16
+
17
+ # if its an optional property, and there is no match in self, don't merge it.
18
+ no_match.reject! { |node| node.optional }
19
+ no_match.map! { |node| node.clone }
20
+ no_match.each { |node| node.parent = self }
21
+ @children += no_match
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ module Raml
2
+ module Parent
3
+ # @!attribute [rw] children
4
+ # @return [Array<Raml::Node>] children nodes.
5
+ attr_accessor :children
6
+
7
+ private
8
+
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ # @private
14
+ module ClassMethods
15
+ def child_of(name, type)
16
+ type = [ type ] unless type.is_a? Array
17
+
18
+ self.instance_eval do
19
+ define_method name do
20
+ @children.select { |child| type.include? child.class }.first
21
+ end
22
+ end
23
+ end
24
+
25
+ def children_of(name, type)
26
+ type = [ type ] unless type.is_a? Array
27
+
28
+ self.instance_eval do
29
+ define_method name do
30
+ @children.select { |child| type.include? child.class }
31
+ end
32
+ end
33
+ end
34
+
35
+ def children_by(name, key, type, merge_parents=false)
36
+ self.instance_eval do
37
+ define_method name do
38
+ result = Hash[
39
+ @children.
40
+ select { |child| child.is_a? type }.
41
+ map { |child| [ child.send(key.to_sym), child ] }
42
+ ]
43
+
44
+ if merge_parents and parent and parent.respond_to? name
45
+ result = parent.send(name).merge result
46
+ end
47
+
48
+ result
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end