raml_ruby 0.1.1

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.
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