nexmo-oas-renderer 2.2.0 → 2.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a463231ba72ba74bc9a6555449eb2d2cba6155c32a2506235b04b8bf332678b
4
- data.tar.gz: 9c8ed923712ff7e677c6f36b532e77fb41ef6120057d52635f7b1a892102aacc
3
+ metadata.gz: 329535118b6e5e736d931e461902f10a14a96379a68898eb767f028e3144cd60
4
+ data.tar.gz: ad0abd7f6ca82cd40851972514e2891facc7c3d71a037b3b3a600c90076a2731
5
5
  SHA512:
6
- metadata.gz: b3e4c30d89a5cc22fd66491751235b49d4b56a5a63ce8e9a3d303e8c4989f5e3a47cc8964c5d78b6cc4f1d33467e1ca83065a00e399fcfc076607a81633b7c3e
7
- data.tar.gz: df6590d1e2de8eb3771dcec2c0cf3617a7453e81e83a34318989d2f42d0513032dfd5c4a35ea3f991a8d1785f6871f6b800e5fb79a863f4c8890ebff89cd2754
6
+ metadata.gz: 5957e08812155be2c049151b14bfe784987ec5738569dcedd30d5464f9f597176e5afeb80dd545421fa684790e941accd4dff8f5bc23993074102351129d435c
7
+ data.tar.gz: a42ed3a17078f74e6b6d5ebe97b161f14c05e25d95758bb6d81c55686d1e2a8dc18dfd8133c8bd5ca27cc777eb571de6ada3923316b1eff2161b5741f273a40c
@@ -0,0 +1,28 @@
1
+
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [ master ]
7
+ pull_request:
8
+ branches: [ master ]
9
+
10
+ jobs:
11
+ test:
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest]
15
+ ruby: [2.5, 2.6, 2.7]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby }}
23
+ - name: Install dependencies
24
+ run: bundle install
25
+ - name: Run tests
26
+ run: bundle exec rspec
27
+ - name: Run rubocop
28
+ run: bundle exec rubocop
@@ -0,0 +1,14 @@
1
+ name: Review App
2
+ on:
3
+ pull_request_target:
4
+ types: [opened, reopened, synchronize, labeled, closed]
5
+ jobs:
6
+ create-review-app:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - name: Create Review App
10
+ uses: mheap/github-action-pr-heroku-review-app@v1
11
+ env:
12
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13
+ HEROKU_PIPELINE_ID: ${{ secrets.HEROKU_PIPELINE_ID }}
14
+ HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:2.6
1
+ FROM ruby:2.7.2
2
2
  COPY . /
3
3
  RUN gem install bundler
4
4
  RUN bundle install
@@ -1,16 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nexmo-oas-renderer (2.2.0)
4
+ nexmo-oas-renderer (2.6.0)
5
5
  activemodel (~> 6.0)
6
6
  activesupport (~> 6.0)
7
7
  banzai (~> 0.1.2)
8
8
  dotenv (~> 2.7)
9
9
  neatjson (~> 0.8)
10
- nexmo_markdown_renderer (~> 0.3)
10
+ nexmo_markdown_renderer (~> 0.8)
11
11
  oas_parser (~> 0.25.1)
12
- octicons_helper (~> 8.2)
13
- redcarpet (= 3.4.0)
12
+ redcarpet (= 3.5.1)
14
13
  sass (~> 3.1)
15
14
  shotgun (~> 0.9)
16
15
  sinatra (~> 2.0)
@@ -18,56 +17,56 @@ PATH
18
17
  GEM
19
18
  remote: https://rubygems.org/
20
19
  specs:
21
- actioncable (6.0.3.2)
22
- actionpack (= 6.0.3.2)
20
+ actioncable (6.0.3.4)
21
+ actionpack (= 6.0.3.4)
23
22
  nio4r (~> 2.0)
24
23
  websocket-driver (>= 0.6.1)
25
- actionmailbox (6.0.3.2)
26
- actionpack (= 6.0.3.2)
27
- activejob (= 6.0.3.2)
28
- activerecord (= 6.0.3.2)
29
- activestorage (= 6.0.3.2)
30
- activesupport (= 6.0.3.2)
24
+ actionmailbox (6.0.3.4)
25
+ actionpack (= 6.0.3.4)
26
+ activejob (= 6.0.3.4)
27
+ activerecord (= 6.0.3.4)
28
+ activestorage (= 6.0.3.4)
29
+ activesupport (= 6.0.3.4)
31
30
  mail (>= 2.7.1)
32
- actionmailer (6.0.3.2)
33
- actionpack (= 6.0.3.2)
34
- actionview (= 6.0.3.2)
35
- activejob (= 6.0.3.2)
31
+ actionmailer (6.0.3.4)
32
+ actionpack (= 6.0.3.4)
33
+ actionview (= 6.0.3.4)
34
+ activejob (= 6.0.3.4)
36
35
  mail (~> 2.5, >= 2.5.4)
37
36
  rails-dom-testing (~> 2.0)
38
- actionpack (6.0.3.2)
39
- actionview (= 6.0.3.2)
40
- activesupport (= 6.0.3.2)
37
+ actionpack (6.0.3.4)
38
+ actionview (= 6.0.3.4)
39
+ activesupport (= 6.0.3.4)
41
40
  rack (~> 2.0, >= 2.0.8)
42
41
  rack-test (>= 0.6.3)
43
42
  rails-dom-testing (~> 2.0)
44
43
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
45
- actiontext (6.0.3.2)
46
- actionpack (= 6.0.3.2)
47
- activerecord (= 6.0.3.2)
48
- activestorage (= 6.0.3.2)
49
- activesupport (= 6.0.3.2)
44
+ actiontext (6.0.3.4)
45
+ actionpack (= 6.0.3.4)
46
+ activerecord (= 6.0.3.4)
47
+ activestorage (= 6.0.3.4)
48
+ activesupport (= 6.0.3.4)
50
49
  nokogiri (>= 1.8.5)
51
- actionview (6.0.3.2)
52
- activesupport (= 6.0.3.2)
50
+ actionview (6.0.3.4)
51
+ activesupport (= 6.0.3.4)
53
52
  builder (~> 3.1)
54
53
  erubi (~> 1.4)
55
54
  rails-dom-testing (~> 2.0)
56
55
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
57
- activejob (6.0.3.2)
58
- activesupport (= 6.0.3.2)
56
+ activejob (6.0.3.4)
57
+ activesupport (= 6.0.3.4)
59
58
  globalid (>= 0.3.6)
60
- activemodel (6.0.3.2)
61
- activesupport (= 6.0.3.2)
62
- activerecord (6.0.3.2)
63
- activemodel (= 6.0.3.2)
64
- activesupport (= 6.0.3.2)
65
- activestorage (6.0.3.2)
66
- actionpack (= 6.0.3.2)
67
- activejob (= 6.0.3.2)
68
- activerecord (= 6.0.3.2)
59
+ activemodel (6.0.3.4)
60
+ activesupport (= 6.0.3.4)
61
+ activerecord (6.0.3.4)
62
+ activemodel (= 6.0.3.4)
63
+ activesupport (= 6.0.3.4)
64
+ activestorage (6.0.3.4)
65
+ actionpack (= 6.0.3.4)
66
+ activejob (= 6.0.3.4)
67
+ activerecord (= 6.0.3.4)
69
68
  marcel (~> 0.3.1)
70
- activesupport (6.0.3.2)
69
+ activesupport (6.0.3.4)
71
70
  concurrent-ruby (~> 1.0, >= 1.0.2)
72
71
  i18n (>= 0.7, < 2)
73
72
  minitest (~> 5.1)
@@ -78,20 +77,20 @@ GEM
78
77
  ast (2.4.1)
79
78
  banzai (0.1.3)
80
79
  builder (3.2.4)
81
- concurrent-ruby (1.1.6)
80
+ concurrent-ruby (1.1.7)
82
81
  crass (1.0.6)
83
82
  deep_merge (1.2.1)
84
83
  diff-lcs (1.4.2)
85
84
  dotenv (2.7.6)
86
85
  erubi (1.9.0)
87
- ffi (1.13.1)
86
+ ffi (1.14.2)
88
87
  globalid (0.4.2)
89
88
  activesupport (>= 4.2.0)
90
89
  hansi (0.2.0)
91
90
  hash-deep-merge (0.1.1)
92
- i18n (1.8.3)
91
+ i18n (1.8.5)
93
92
  concurrent-ruby (~> 1.0)
94
- loofah (2.6.0)
93
+ loofah (2.7.0)
95
94
  crass (~> 1.0.2)
96
95
  nokogiri (>= 1.5.9)
97
96
  mail (2.7.1)
@@ -101,25 +100,26 @@ GEM
101
100
  method_source (1.0.0)
102
101
  mimemagic (0.3.5)
103
102
  mini_mime (1.0.2)
104
- mini_portile2 (2.4.0)
105
- minitest (5.14.1)
103
+ mini_portile2 (2.5.0)
104
+ minitest (5.14.2)
106
105
  mustermann (1.1.1)
107
106
  ruby2_keywords (~> 0.0.1)
108
107
  mustermann-contrib (1.1.1)
109
108
  hansi (~> 0.2.0)
110
109
  mustermann (= 1.1.1)
111
110
  neatjson (0.9)
112
- nexmo_markdown_renderer (0.4.1)
111
+ nexmo_markdown_renderer (0.8.0)
112
+ actionview (~> 6.0)
113
113
  activemodel (~> 6.0)
114
114
  banzai (~> 0.1.2)
115
115
  i18n (~> 1.7)
116
116
  nokogiri (~> 1.10)
117
- octicons_helper (~> 8.2)
118
117
  redcarpet (~> 3.4)
119
118
  rouge (~> 2.0.7)
120
- nio4r (2.5.2)
121
- nokogiri (1.10.9)
122
- mini_portile2 (~> 2.4.0)
119
+ nio4r (2.5.4)
120
+ nokogiri (1.11.1)
121
+ mini_portile2 (~> 2.5.0)
122
+ racc (~> 1.4)
123
123
  oas_parser (0.25.1)
124
124
  activesupport (>= 4.0.0)
125
125
  addressable (~> 2.3)
@@ -128,43 +128,39 @@ GEM
128
128
  hash-deep-merge
129
129
  mustermann-contrib (~> 1.1.1)
130
130
  nokogiri
131
- octicons (8.5.0)
132
- nokogiri (>= 1.6.3.1)
133
- octicons_helper (8.5.0)
134
- octicons (= 8.5.0)
135
- rails
136
131
  parallel (1.19.2)
137
132
  parser (2.7.1.4)
138
133
  ast (~> 2.4.1)
139
134
  public_suffix (4.0.6)
135
+ racc (1.5.2)
140
136
  rack (2.2.3)
141
137
  rack-protection (2.1.0)
142
138
  rack
143
139
  rack-test (1.1.0)
144
140
  rack (>= 1.0, < 3)
145
- rails (6.0.3.2)
146
- actioncable (= 6.0.3.2)
147
- actionmailbox (= 6.0.3.2)
148
- actionmailer (= 6.0.3.2)
149
- actionpack (= 6.0.3.2)
150
- actiontext (= 6.0.3.2)
151
- actionview (= 6.0.3.2)
152
- activejob (= 6.0.3.2)
153
- activemodel (= 6.0.3.2)
154
- activerecord (= 6.0.3.2)
155
- activestorage (= 6.0.3.2)
156
- activesupport (= 6.0.3.2)
141
+ rails (6.0.3.4)
142
+ actioncable (= 6.0.3.4)
143
+ actionmailbox (= 6.0.3.4)
144
+ actionmailer (= 6.0.3.4)
145
+ actionpack (= 6.0.3.4)
146
+ actiontext (= 6.0.3.4)
147
+ actionview (= 6.0.3.4)
148
+ activejob (= 6.0.3.4)
149
+ activemodel (= 6.0.3.4)
150
+ activerecord (= 6.0.3.4)
151
+ activestorage (= 6.0.3.4)
152
+ activesupport (= 6.0.3.4)
157
153
  bundler (>= 1.3.0)
158
- railties (= 6.0.3.2)
154
+ railties (= 6.0.3.4)
159
155
  sprockets-rails (>= 2.0.0)
160
156
  rails-dom-testing (2.0.3)
161
157
  activesupport (>= 4.2.0)
162
158
  nokogiri (>= 1.6)
163
159
  rails-html-sanitizer (1.3.0)
164
160
  loofah (~> 2.3)
165
- railties (6.0.3.2)
166
- actionpack (= 6.0.3.2)
167
- activesupport (= 6.0.3.2)
161
+ railties (6.0.3.4)
162
+ actionpack (= 6.0.3.4)
163
+ activesupport (= 6.0.3.4)
168
164
  method_source
169
165
  rake (>= 0.8.7)
170
166
  thor (>= 0.20.3, < 2.0)
@@ -173,7 +169,7 @@ GEM
173
169
  rb-fsevent (0.10.4)
174
170
  rb-inotify (0.10.1)
175
171
  ffi (~> 1.0)
176
- redcarpet (3.4.0)
172
+ redcarpet (3.5.1)
177
173
  regexp_parser (1.7.1)
178
174
  rexml (3.2.4)
179
175
  rouge (2.0.7)
@@ -218,7 +214,7 @@ GEM
218
214
  sprockets (4.0.2)
219
215
  concurrent-ruby (~> 1.0)
220
216
  rack (> 1, < 3)
221
- sprockets-rails (3.2.1)
217
+ sprockets-rails (3.2.2)
222
218
  actionpack (>= 4.0)
223
219
  activesupport (>= 4.0)
224
220
  sprockets (>= 3.0.0)
@@ -228,10 +224,10 @@ GEM
228
224
  tzinfo (1.2.7)
229
225
  thread_safe (~> 0.1)
230
226
  unicode-display_width (1.7.0)
231
- websocket-driver (0.7.2)
227
+ websocket-driver (0.7.3)
232
228
  websocket-extensions (>= 0.1.0)
233
229
  websocket-extensions (0.1.5)
234
- zeitwerk (2.3.1)
230
+ zeitwerk (2.4.1)
235
231
 
236
232
  PLATFORMS
237
233
  ruby
@@ -0,0 +1 @@
1
+ web: bundle exec ./exe/nexmo-oas-renderer
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
1
  # Nexmo OAS Renderer
2
+
3
+ ![Build Status](https://github.com/Nexmo/nexmo-oas-renderer/workflows/CI/badge.svg)
4
+ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.txt)
5
+
2
6
  Sinatra application that provides a preview of how the OAS documents will be rendered within [Nexmo Developer](https://developer.nexmo.com/).
3
7
 
4
8
  * [Dependencies](#requirements)
@@ -0,0 +1,15 @@
1
+ {
2
+ "buildpacks": [{ "url": "heroku/ruby" }],
3
+ "env": {
4
+ "RACK_ENV": "production",
5
+ "RAILS_ENV": "production",
6
+ "OAS_PATH": "samples"
7
+ },
8
+ "stack": "heroku-18",
9
+ "formation": {
10
+ "web": {
11
+ "quantity": 1,
12
+ "size": "free"
13
+ }
14
+ }
15
+ }
@@ -13,6 +13,7 @@ require_relative './presenters/open_api_specification'
13
13
  require_relative './presenters/navigation'
14
14
  require_relative './presenters/request_body_raw'
15
15
  require_relative './presenters/response_tabs'
16
+ require_relative './presenters/content_switcher'
16
17
  require_relative './helpers/render'
17
18
  require_relative './helpers/navigation'
18
19
  require_relative './helpers/summary'
@@ -15,7 +15,7 @@ module Nexmo
15
15
  if args.length > 2
16
16
  super
17
17
  else
18
- ApplicationController.renderer.render(*args)
18
+ ApplicationController.renderer.new(request.env).render(*args)
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ module OAS
5
+ module Renderer
6
+ module Presenters
7
+ class ContentSwitcher
8
+ attr_reader :panels
9
+
10
+ def initialize(format:, label: nil, theme_light:, force_type: nil)
11
+ @format = format
12
+ @panels = []
13
+ @label = label
14
+ @force_type = force_type
15
+ @theme_light = theme_light
16
+ end
17
+
18
+ def add_content(title:, content:, tab_id:, active:)
19
+ @panels.push({
20
+ 'title' => title,
21
+ 'content' => content,
22
+ 'x-tab-id' => tab_id,
23
+ 'active' => active,
24
+ })
25
+ end
26
+
27
+ def render
28
+ type = 'tabs'
29
+ type = 'dropdown' if @panels.length >= 8
30
+
31
+ type = @force_type if @force_type
32
+
33
+ [:"open_api/content_switcher/_#{type}", locals: {
34
+ panels: @panels,
35
+ format: @format,
36
+ label: @label,
37
+ switcher: self,
38
+ theme_light: @theme_light,
39
+ }]
40
+ end
41
+
42
+ def id
43
+ @id ||= "s-#{SecureRandom.hex}"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -24,6 +24,10 @@ module Nexmo
24
24
  end
25
25
 
26
26
  def content
27
+ if @content.is_a?(Nexmo::OAS::Renderer::Presenters::ContentSwitcher)
28
+ return @content.render
29
+ end
30
+
27
31
  if @content == :responses
28
32
  Nexmo::OAS::Renderer::ResponseParserDecorator
29
33
  .new(@schema)
@@ -8,7 +8,7 @@ module Nexmo
8
8
  module Renderer
9
9
  module Presenters
10
10
  class ResponseTabs
11
- attr_reader :format
11
+ attr_reader :format, :switcher
12
12
 
13
13
  def initialize(format, response, content, endpoint, theme_light: nil)
14
14
  @format = format
@@ -16,6 +16,7 @@ module Nexmo
16
16
  @content = content
17
17
  @endpoint = endpoint
18
18
  @theme_light = theme_light
19
+ @switcher ||= @response.schema(@format)['x-switcher']
19
20
  end
20
21
 
21
22
  def tab_links
@@ -31,17 +32,50 @@ module Nexmo
31
32
  def tab_panels
32
33
  @tab_panels ||= @response.split_schemas(@format).map.with_index do |schema, index|
33
34
  schema = handle_all_of(schema)
35
+ examples = examples_for_schema(schema)
34
36
  ResponseTab::Panel.new(
35
37
  schema: schema,
36
38
  index: index,
37
39
  format: @format,
38
- content: @content,
40
+ content: examples || @content,
39
41
  endpoint: @endpoint,
40
42
  theme_light: @theme_light
41
43
  )
42
44
  end
43
45
  end
44
46
 
47
+ def examples_for_schema(schema)
48
+ # If there are any examples, show them
49
+ examples = @response.raw.dig('content', @format, 'examples')
50
+ return nil unless @content == :responses && @format == 'application/json' && examples
51
+
52
+ example_switcher = Nexmo::OAS::Renderer::Presenters::ContentSwitcher.new(format: format, force_type: 'dropdown', theme_light: @theme_light)
53
+
54
+ has_visible_panel = false
55
+ examples.each_with_index do |v, _k|
56
+ # Only if the example key is listed in x-examples in the schema
57
+ next unless schema['x-examples']&.include?(v[0])
58
+
59
+ response = JSON.neat_generate(v[1], {
60
+ wrap: true,
61
+ after_colon: 1,
62
+ })
63
+
64
+ content = <<~HEREDOC
65
+ <pre class="pre-wrap language-json #{@theme_light ? 'Vlt-prism--dark' : ''} Vlt-prism--copy-disabled"><code>#{response}</code></pre>
66
+ HEREDOC
67
+
68
+ example_switcher.add_content(
69
+ title: v[0].titleize,
70
+ content: content,
71
+ tab_id: v[0],
72
+ active: !has_visible_panel
73
+ )
74
+ has_visible_panel = true
75
+ end
76
+ return example_switcher if example_switcher.panels.size.positive?
77
+ end
78
+
45
79
  def handle_all_of(schema)
46
80
  if schema['allOf']
47
81
  schema['allOf'].each do |p|
@@ -20,6 +20,14 @@ document.addEventListener("DOMContentLoaded", function() {
20
20
  var matchingTabs = document.querySelectorAll('[data-tab-link="' + link + '"]');
21
21
  Array.from(matchingTabs).forEach(function (element) {
22
22
  element.dispatchEvent(new Event('toggle'));
23
+
24
+ // Switch anything that's in a dropdown
25
+ if (element.parentNode.className.indexOf("Vlt-dropdown__panel__content") !== -1) {
26
+ // This is *very* structure dependent, but also the most compatible way to handle it
27
+ var panel = element.parentNode.parentNode;
28
+ var titleNodes = Array.from(panel.previousSibling.previousSibling.firstChild.childNodes);
29
+ titleNodes[1].textContent = element.textContent;
30
+ }
23
31
  });
24
32
  });
25
33
  });
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Copyright (c) 2001-present, Vonage.
3
+ *
4
+ * Dropdowns (requires core)
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ Volta.dropdown = function () {
10
+ var _class = {
11
+ wrapper: 'Vlt-dropdown',
12
+ block: 'Vlt-dropdown__block',
13
+ btn: 'Vlt-dropdown__trigger',
14
+ btnLegacy: 'Vlt-dropdown__btn',
15
+ dismissed: 'Vlt-callout--dismissed',
16
+ expanded: 'Vlt-dropdown--expanded',
17
+ label: 'Vlt-dropdown__label',
18
+ link: 'Vlt-dropdown__link',
19
+ noCloseLink: 'Vlt-dropdown__link--noclose',
20
+ noCloseBlock: 'Vlt-dropdown__block--noclose',
21
+ panel: 'Vlt-dropdown__panel',
22
+ panelContent: 'Vlt-dropdown__panel__content',
23
+ selection: 'Vlt-dropdown__selection',
24
+ switch: 'Vlt-switch',
25
+ switchSlider: 'Vlt-switch__slider'
26
+ }
27
+
28
+ function Dropdown() {}
29
+
30
+ Dropdown.prototype = {
31
+ init: function(element, supressClickHandler) {
32
+ this.dropdown = element;
33
+ this.selection = this.dropdown.querySelector('.' + _class.selection);
34
+ this.isSelectionVisible = !!this.selection;
35
+ this.btn = this.dropdown.querySelector('.' + _class.btn) || this.dropdown.querySelector('.' + _class.btnLegacy);
36
+ this._suppress = supressClickHandler;
37
+
38
+ if(!this._suppress) {
39
+ this._addEventListener();
40
+ }
41
+ },
42
+ _addEventListener: function(){
43
+ var openHandler = this.open.bind(this);
44
+ this.dropdown.addEventListener('click', openHandler, { once: true })
45
+ },
46
+ close: function(text) {
47
+ if(text) {
48
+ this._setDropdownSelectionText(text);
49
+ }
50
+ this.dropdown.classList.remove(_class.expanded);
51
+
52
+ if(!this._suppress){
53
+ this._addEventListener();
54
+ }
55
+
56
+ },
57
+ _closeEventHandler: undefined,
58
+ _closeEvent: function(e) {
59
+ var targetIsPanel = Volta._hasClass(e.target, _class.panel);
60
+ var parentIsPanel = Volta._closest(e.target, '.' + _class.panelContent, _class.panel) !== null;
61
+ var parentLink = Volta._closest(e.target, '.' + _class.link, _class.wrapper);
62
+ var parentIsLink = parentLink && parentLink.length === 1;
63
+ var isSwitchSlider = Volta._hasClass(e.target, _class.switchSlider);
64
+ var isParentSwitch = Volta._closest(e.target,'.' + _class.switch, _class.link);
65
+ var isNoClose = Volta._hasClass(e.target, _class.noCloseLink) || Volta._hasClass(e.target, _class.noCloseBlock);
66
+ var isNoCloseParent = Volta._closest(e.target,'.' + _class.noCloseLink, _class.link) || Volta._closest(e.target,'.' + _class.noCloseBlock, _class.noCloseBlock);
67
+ var isInput = e.target instanceof HTMLInputElement;
68
+
69
+ if(!targetIsPanel && !parentIsPanel && !parentIsLink && !isNoClose && !isInput && !isNoCloseParent) {
70
+ e.preventDefault();
71
+ e.stopPropagation();
72
+ }
73
+
74
+ if(isSwitchSlider || isParentSwitch || isNoClose || isInput || isNoCloseParent) {
75
+ return null;
76
+ }
77
+
78
+ var text;
79
+ if(parentIsPanel && Volta._hasClass(e.target, _class.label)) {
80
+ text = e.target.innerHTML;
81
+ } else if (parentIsPanel) {
82
+ var label = e.target.querySelector('.' + _class.label);
83
+ if(label) {
84
+ text = label.innerHTML;
85
+ }
86
+ }
87
+
88
+ this.close(text);
89
+
90
+ document.querySelector('body').removeEventListener('click', this._closeEventHandler );
91
+ },
92
+ open: function(event) {
93
+ if(event) {
94
+ event.preventDefault();
95
+ event.stopPropagation();
96
+ }
97
+
98
+ this.dropdown.classList.add(_class.expanded);
99
+
100
+ if(!this._suppress){
101
+ this._closeEventHandler = this._closeEvent.bind(this);
102
+ document.querySelector('body').addEventListener('click', this._closeEventHandler );
103
+ }
104
+ },
105
+ _setDropdownSelectionText: function(text) {
106
+ if(this.isSelectionVisible) {
107
+ this.selection.innerText = text;
108
+ } else {
109
+ this.btn.innerText = text;
110
+ this.btn.value = text;
111
+ }
112
+ },
113
+ _suppress: false
114
+ }
115
+
116
+ return {
117
+ create: create,
118
+ init: attachDropdownHandlers
119
+ }
120
+
121
+ /**
122
+ * @public
123
+ *
124
+ * @description Attach a listeners to dropdowns
125
+ */
126
+ function attachDropdownHandlers() {
127
+ document.querySelectorAll('.' + _class.wrapper).forEach(attachHandler);
128
+
129
+ function attachHandler(dropdown) {
130
+ create(dropdown);
131
+ }
132
+ }
133
+
134
+ /**
135
+ * @private
136
+ *
137
+ * @description Create a dropdown element
138
+ * @param {HTMLElement} element
139
+ */
140
+ function create(element){
141
+ var dropdown = Object.create(Dropdown.prototype, {})
142
+ dropdown.init(element);
143
+ return dropdown;
144
+ }
145
+ }();
@@ -53,6 +53,7 @@
53
53
  .oas-wrapper .oas-parameter-description {
54
54
  margin-left: 16px; }
55
55
  .oas-wrapper .oas-parameter-meta {
56
+ padding-bottom: 2px;
56
57
  border-bottom: 1px solid #ccc;
57
58
  margin-bottom: 4px; }
58
59
  .oas-wrapper .oas-parameter-nested {
@@ -3,7 +3,7 @@
3
3
  module Nexmo
4
4
  module OAS
5
5
  module Renderer
6
- VERSION = '2.2.0'
6
+ VERSION = '2.6.0'
7
7
  end
8
8
  end
9
9
  end
@@ -5,10 +5,11 @@
5
5
  <script src="/assets/javascripts/volta.accordion.js"></script>
6
6
  <script src="/assets/javascripts/volta.tabs.js"></script>
7
7
  <script src="/assets/javascripts/volta.modal.js"></script>
8
+ <script src="/assets/javascripts/volta.dropdown.js"></script>
8
9
  <script src="/assets/javascripts/volta.tooltip.js"></script>
9
10
  <script src="/assets/javascripts/nexmo-oas-renderer.js?a=1"></script>
10
11
  <script src="/assets/javascripts/components/format.js"></script>
11
12
  <script type="text/javascript">
12
- Volta.init(["accordion", "tab", "modal", "tooltip"]);
13
+ Volta.init(["accordion", "tab", "modal", "tooltip", "dropdown"]);
13
14
  new Format
14
15
  </script>
@@ -1,6 +1,6 @@
1
1
  <div class="Vlt-grid">
2
2
  <div class="Vlt-col oas-left-panel header-row" style="padding-top:20px;">
3
- <a href="<%= @theme_link %>" class="Vlt-switch Vlt-switch--secondary" style="float:right;">
3
+ <a href="<%= @theme_link %>" class="Vlt-switch Vlt-switch--secondary" style="float:right;" title="colour theme switcher">
4
4
  <span class="Vlt-switch__slider"></span>
5
5
  </a>
6
6
 
@@ -39,6 +39,20 @@
39
39
  </div>
40
40
  </div>
41
41
 
42
+
43
+ <% if @specification.groups.size > 1 %>
44
+ <h4>Jump to:</h4>
45
+ <div style="margin-bottom: 30px; padding: 8px;">
46
+ <% @specification.groups.each do |name, endpoints| %>
47
+ <% if name %>
48
+ <% group = definition.raw['tags'].detect { |tag| tag['name'].capitalize == name.capitalize } %>
49
+ <p><a href="#<%= group['name'].parameterize %>"><%= group['name'] %> &raquo;</a></p>
50
+ <p class="Vlt-grey-darker"><%= group['description']&.render_markdown %></p>
51
+ <% end %>
52
+ <% end %>
53
+ </div>
54
+ <% end %>
55
+
42
56
  <%
43
57
  # If there's only one group, everything is untagged
44
58
  if @specification.groups.size === 1
@@ -39,9 +39,10 @@
39
39
 
40
40
  <%
41
41
  # This can likely be better done as a presenter, but it works for now
42
- schema = endpoint.request_body.content[format]['schema']['oneOf']
42
+ request = endpoint.request_body.content[format]['schema']
43
+ schema = request['oneOf']
43
44
  %>
44
- <%= erb :'open_api/_tabbed_parameters', locals: { body: endpoint.request_body, schema: schema, format: format, callback: callback } %>
45
+ <%= erb :'open_api/_tabbed_parameters', locals: { body: endpoint.request_body, request: request, schema: schema, format: format, callback: callback } %>
45
46
  <%
46
47
  end
47
48
  end
@@ -58,13 +58,21 @@
58
58
  <% if parameter.required %>
59
59
  <span class="constraint">Required</span>
60
60
  <% end %>
61
-
62
61
  <% if parameter.minimum || parameter.raw['minLength'] %>
63
62
  | <span class="constraint">Min:</span> <%= parameter.minimum || parameter.raw['minLength'] %>
64
63
  <% end %>
65
64
  <% if parameter.maximum || parameter.raw['maxLength'] %>
66
65
  | <span class="constraint">Max:</span> <%= parameter.maximum || parameter.raw['maxLength'] %>
67
66
  <% end %>
67
+ <% if parameter.default || parameter.raw['default'] %>
68
+ | <span class="constraint">Default:</span> <%= parameter.default || parameter.raw['default'] %>
69
+ <% end %>
70
+ <% if parameter.raw['deprecated'] %>
71
+ | <span class="constraint">DEPRECATED</span> <span>: This field has been deprecated. </span>
72
+ <% end %>
73
+ <% if parameter.raw['x-replace-with']%>
74
+ <span> <%= 'Please use ' + '<code>'+ parameter.raw['x-replace-with'] + '</code>' + ' instead.' %> </span>
75
+ <% end %>
68
76
  </div>
69
77
 
70
78
  <%= (parameter.description || parameter.schema['description'] || '').render_markdown %>
@@ -1,18 +1,16 @@
1
- <% tabs = Nexmo::OAS::Renderer::Presenters::ResponseTabs.new(format, response, content, endpoint, theme_light: @theme_light) %>
1
+ <%
2
+ tabs = Nexmo::OAS::Renderer::Presenters::ResponseTabs.new(format, response, content, endpoint, theme_light: @theme_light)
2
3
 
3
- <div class='Vlt-tabs js-format' data-format='<%= tabs.format %>'>
4
- <div class='Vlt-tabs__header' role='tablist' aria-label='Responses'>
5
- <% tabs.tab_links.each do |link| %>
6
- <div role='tab' class='<%= link.css_classes %>' <% if link.data_tab_link %>data-tab-link="<%= link.data_tab_link %>"<% end %>>
7
- <%= link.content %>
8
- </div>
9
- <% end %>
10
- </div>
11
- <div class='Vlt-tabs__content'>
12
- <% tabs.tab_panels.each do |panel| %>
13
- <div class='<%= panel.css_classes %>'>
14
- <%= erb *panel.content %>
15
- </div>
16
- <% end %>
17
- </div>
18
- </div>
4
+ switcher = Nexmo::OAS::Renderer::Presenters::ContentSwitcher.new(label: "Response Example", format: format, force_type: tabs.switcher, theme_light: @theme_light)
5
+
6
+ tabs.tab_links.each_with_index do |v,k|
7
+ switcher.add_content(
8
+ title: v.content,
9
+ content: (erb *tabs.tab_panels[k].content),
10
+ tab_id: v.data_tab_link,
11
+ active: k == 0
12
+ )
13
+ end
14
+ %>
15
+
16
+ <%= erb *switcher.render %>
@@ -12,8 +12,7 @@
12
12
  s
13
13
  end
14
14
 
15
-
16
- panels = []
15
+ switcher = Nexmo::OAS::Renderer::Presenters::ContentSwitcher.new(label: "Request Details", format: format, force_type: request['x-switcher'], theme_light: @theme_light)
17
16
 
18
17
  schemas.each_with_index do |schema, index|
19
18
  if schema['properties']
@@ -25,40 +24,21 @@
25
24
  end
26
25
  end
27
26
 
28
- panels.push({
29
- 'description' => schema['title'] || schema['description'],
30
- 'parameters' => schema['properties'],
31
- 'oneOf' => schema['oneOf'],
32
- 'x-tab-id' => schema['x-tab-id'] || schema['title'].parameterize,
33
- 'active' => index == 0
34
- })
27
+
28
+ if schema['oneOf']
29
+ content = (erb :'open_api/_tabbed_parameters', locals: { body: body, request: schema, schema: schema['oneOf'], format: format, callback: callback })
30
+ else
31
+ content = (erb :'open_api/_parameters', locals: { parameters: schema['properties'], callback: callback })
32
+ end
33
+
34
+ switcher.add_content(
35
+ title: schema['title'] || schema['description'],
36
+ content: content,
37
+ tab_id: schema['x-tab-id'],
38
+ active: index == 0
39
+ )
35
40
  end
36
41
  %>
37
42
 
38
- <div class="Vlt-tabs js-format" data-format="<%= format %>">
39
- <div class="Vlt-tabs__header" role="tablist" aria-label="Responses">
40
- <% panels.each do |panel| %>
41
- <div role="tab" data-tab-link="<%= panel['x-tab-id'] %>" class="Vlt-tabs__link <%= panel['active'] ? 'Vlt-tabs__link_active' : '' %>">
42
- <%= panel['description'] %>
43
- </div>
44
- <% end %>
45
- </div>
46
- <div class="Vlt-tabs__content">
47
- <% panels.each do |panel| %>
48
- <div class="Vlt-tabs__panel <%= panel['active'] ? 'Vlt-tabs__panel_active' : '' %>">
49
- <%
50
- # Nested oneOf?
51
- if panel['oneOf']
52
- %>
53
- <%= erb :'open_api/_tabbed_parameters', locals: { body: body, schema: panel['oneOf'], format: format, callback: callback } %>
54
- <%
55
- else
56
- %>
57
-
58
- <%= erb :'open_api/_parameters', locals: { parameters: panel['parameters'], callback: callback } %>
59
- <% end %>
60
- </div>
61
- <% end %>
62
- </div>
63
- </div>
43
+ <%= erb *switcher.render %>
64
44
 
@@ -0,0 +1,24 @@
1
+ <div class="Vlt-dropdown Vlt-dropdown--full-width">
2
+ <div class="Vlt-dropdown__trigger Vlt-dropdown__trigger--btn"><button class="Vlt-btn Vlt-btn--<%= (theme_light ? "secondary" : "tertiary") %>">
3
+ <%= label ? "#{label}: " : ""%><span class="Vlt-dropdown__selection"><%= panels[0]['title'] %></span>
4
+ </button></div>
5
+ <div class="Vlt-dropdown__panel">
6
+ <div data-tab-content="<%= switcher.id %>" class="Vlt-dropdown__panel__content">
7
+ <% panels.each do |panel| %>
8
+ <div role="tab" data-tab-link="<%= panel['x-tab-id'] || panel['title'].parameterize %>" class="Vlt-dropdown__link Vlt-dropdown__label Vlt-js-tabs__link"><%= panel['title'] %></div>
9
+ <% end %>
10
+ </div>
11
+ </div>
12
+ </div>
13
+
14
+
15
+ <div class="js-format" data-format="<%= format %>">
16
+ <div id="<%= switcher.id %>" class="Vlt-js-tabs__content">
17
+ <% panels.each do |panel| %>
18
+ <div class="Vlt-js-tabs__panel <%= panel['active'] ? 'Vlt-js-tabs__panel_active' : '' %>">
19
+ <%= panel['content'] %>
20
+ </div>
21
+ <% end %>
22
+ </div>
23
+ </div>
24
+
@@ -0,0 +1,18 @@
1
+ <div class="Vlt-tabs js-format" data-format="<%= format %>">
2
+ <div class="Vlt-tabs__header" role="tablist" aria-label="<%= label %>">
3
+ <% panels.each do |panel| %>
4
+ <div role="tab" data-tab-link="<%= panel['x-tab-id'] || panel['title'].parameterize %>" class="Vlt-tabs__link <%= panel['active'] ? 'Vlt-tabs__link_active' : '' %>">
5
+ <%= panel['title'] %>
6
+ </div>
7
+ <% end %>
8
+ </div>
9
+ <div class="Vlt-tabs__content">
10
+ <% panels.each do |panel| %>
11
+ <div class="Vlt-tabs__panel <%= panel['active'] ? 'Vlt-tabs__panel_active' : '' %>">
12
+ <%= panel['content'] %>
13
+ </div>
14
+ <% end %>
15
+ </div>
16
+ </div>
17
+
18
+
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  # Specify which files should be added to the gem when it is released.
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|samples)/}) }
29
29
  end
30
30
  spec.bindir = 'exe'
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -36,10 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency 'banzai', '~> 0.1.2'
37
37
  spec.add_runtime_dependency 'dotenv', '~> 2.7'
38
38
  spec.add_runtime_dependency 'neatjson', '~> 0.8'
39
- spec.add_runtime_dependency 'nexmo_markdown_renderer', '~> 0.3'
39
+ spec.add_runtime_dependency 'nexmo_markdown_renderer', '~> 0.8'
40
40
  spec.add_runtime_dependency 'oas_parser', '~> 0.25.1'
41
- spec.add_runtime_dependency 'octicons_helper', '~> 8.2'
42
- spec.add_runtime_dependency 'redcarpet', '3.4.0'
41
+ spec.add_runtime_dependency 'redcarpet', '3.5.1'
43
42
  spec.add_runtime_dependency 'sass', '~> 3.1'
44
43
  spec.add_runtime_dependency 'shotgun', '~> 0.9'
45
44
  spec.add_runtime_dependency 'sinatra', '~> 2.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexmo-oas-renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabian Rodriguez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-30 00:00:00.000000000 Z
11
+ date: 2021-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.3'
89
+ version: '0.8'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.3'
96
+ version: '0.8'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: oas_parser
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -108,34 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.25.1
111
- - !ruby/object:Gem::Dependency
112
- name: octicons_helper
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '8.2'
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '8.2'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: redcarpet
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - '='
130
116
  - !ruby/object:Gem::Version
131
- version: 3.4.0
117
+ version: 3.5.1
132
118
  type: :runtime
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
122
  - - '='
137
123
  - !ruby/object:Gem::Version
138
- version: 3.4.0
124
+ version: 3.5.1
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: sass
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -243,19 +229,22 @@ extensions: []
243
229
  extra_rdoc_files: []
244
230
  files:
245
231
  - ".env.example"
232
+ - ".github/workflows/ci.yml"
233
+ - ".github/workflows/pull_request-review.yml"
246
234
  - ".github/workflows/push-docker-publish.yml"
247
235
  - ".gitignore"
248
236
  - ".rspec"
249
237
  - ".rubocop.yml"
250
- - ".travis.yml"
251
238
  - CHANGELOG.md
252
239
  - CONTRIBUTING.md
253
240
  - Dockerfile
254
241
  - Gemfile
255
242
  - Gemfile.lock
256
243
  - LICENSE.txt
244
+ - Procfile
257
245
  - README.md
258
246
  - Rakefile
247
+ - app.json
259
248
  - bin/console
260
249
  - bin/setup
261
250
  - exe/nexmo-oas-renderer
@@ -271,6 +260,7 @@ files:
271
260
  - lib/nexmo/oas/renderer/helpers/summary.rb
272
261
  - lib/nexmo/oas/renderer/helpers/url.rb
273
262
  - lib/nexmo/oas/renderer/presenters/api_specification.rb
263
+ - lib/nexmo/oas/renderer/presenters/content_switcher.rb
274
264
  - lib/nexmo/oas/renderer/presenters/endpoint.rb
275
265
  - lib/nexmo/oas/renderer/presenters/groups.rb
276
266
  - lib/nexmo/oas/renderer/presenters/navigation.rb
@@ -300,6 +290,7 @@ files:
300
290
  - lib/nexmo/oas/renderer/public/assets/javascripts/tooltip.min.js
301
291
  - lib/nexmo/oas/renderer/public/assets/javascripts/volta.accordion.js
302
292
  - lib/nexmo/oas/renderer/public/assets/javascripts/volta.core.js
293
+ - lib/nexmo/oas/renderer/public/assets/javascripts/volta.dropdown.js
303
294
  - lib/nexmo/oas/renderer/public/assets/javascripts/volta.modal.js
304
295
  - lib/nexmo/oas/renderer/public/assets/javascripts/volta.tabs.js
305
296
  - lib/nexmo/oas/renderer/public/assets/javascripts/volta.tooltip.js
@@ -366,6 +357,8 @@ files:
366
357
  - lib/nexmo/oas/renderer/views/open_api/_tabbed_parameters.erb
367
358
  - lib/nexmo/oas/renderer/views/open_api/_tabbed_single_parameter.erb
368
359
  - lib/nexmo/oas/renderer/views/open_api/_webhooks.erb
360
+ - lib/nexmo/oas/renderer/views/open_api/content_switcher/_dropdown.erb
361
+ - lib/nexmo/oas/renderer/views/open_api/content_switcher/_tabs.erb
369
362
  - lib/nexmo/oas/renderer/views/open_api/show.erb
370
363
  - lib/nexmo/oas/renderer/views/static/404.erb
371
364
  - nexmo-oas-renderer.gemspec
@@ -1,9 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- rvm:
4
- - 2.5
5
- - 2.6
6
- - 2.7
7
- script:
8
- - bundle exec rspec
9
- - bundle exec rubocop