From 6a434e7f3e051ac68b6791d73defeea122e80ac7 Mon Sep 17 00:00:00 2001 From: LeFnord Date: Wed, 11 Jan 2017 20:00:47 +0100 Subject: [PATCH] issue#566: removes markdown - updates README - updates UPGRADING --- README.md | 90 +----------------- UPGRADING.md | 6 ++ lib/grape-swagger.rb | 3 - lib/grape-swagger/doc_methods.rb | 4 +- lib/grape-swagger/endpoint.rb | 11 +-- lib/grape-swagger/errors.rb | 13 +-- .../markdown/kramdown_adapter.rb | 37 -------- .../markdown/redcarpet_adapter.rb | 92 ------------------- spec/markdown/kramdown_adapter_spec.rb | 31 ------- spec/markdown/redcarpet_adapter_spec.rb | 66 ------------- spec/swagger_v2/api_swagger_v2_detail_spec.rb | 78 +--------------- .../swagger_v2/description_not_initialized.rb | 2 +- 12 files changed, 28 insertions(+), 405 deletions(-) delete mode 100644 lib/grape-swagger/markdown/kramdown_adapter.rb delete mode 100644 lib/grape-swagger/markdown/redcarpet_adapter.rb delete mode 100644 spec/markdown/kramdown_adapter_spec.rb delete mode 100644 spec/markdown/redcarpet_adapter_spec.rb diff --git a/README.md b/README.md index 5f31c445..1e93bbcf 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ * [Routes Configuration](#routes) * [Using Grape Entities](#grape-entity) * [Securing the Swagger UI](#oauth) -* [Markdown](#md_usage) +* [Markdown (deprecated)](#md_usage) * [Example](#example) * [Rake Tasks](#rake) @@ -196,7 +196,6 @@ end * [add_base_path](#add_base_path) * [add_version](#add_version) * [doc_version](#doc_version) -* [markdown](#markdown) * [endpoint_auth_wrapper](#endpoint_auth_wrapper) * [swagger_endpoint_guard](#swagger_endpoint_guard) * [token_owner](#token_owner) @@ -268,18 +267,8 @@ add_swagger_documentation \ ``` -#### markdown: -Allow markdown in `detail`, default is `false`. (disabled) See [below](#md_usage) for details. - -```ruby -add_swagger_documentation \ - markdown: GrapeSwagger::Markdown::KramdownAdapter.new -``` -or alternative -```ruby -add_swagger_documentation \ - markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new -``` +#### markdown: (deprecated) +OAPI accepts GFM for descriptions #### endpoint_auth_wrapper: @@ -1087,77 +1076,8 @@ The lambda is checking whether the user is authenticated (if not, the token_owne role - only admins can see this endpoint. -## Markdown in Detail - -The grape-swagger gem allows you to add an explanation in markdown in the detail field. Which would result in proper formatted markdown in Swagger UI. -Grape-swagger uses adapters for several markdown formatters. It includes adapters for [kramdown](http://kramdown.rubyforge.org) (kramdown [syntax](http://kramdown.rubyforge.org/syntax.html)) and [redcarpet](https://github.com/vmg/redcarpet). -The adapters are packed in the GrapeSwagger::Markdown modules. We do not include the markdown gems in our gemfile, so be sure to include or install the depended gems. - -To use it, add a new instance of the adapter to the markdown options of `add_swagger_documentation`, such as: -```ruby -add_swagger_documentation \ - markdown: GrapeSwagger::Markdown::KramdownAdapter.new(options) -``` -and write your route details in GFM, examples could be find in [details spec](blob/master/spec/swagger_v2/api_swagger_v2_detail_spec.rb) - - -#### Kramdown -If you want to use kramdown as markdown formatter, you need to add kramdown to your gemfile. - -```ruby -gem 'kramdown' -``` - -Configure your api documentation route with: -```ruby -add_swagger_documentation \ - markdown: GrapeSwagger::Markdown::KramdownAdapter.new(options) -``` - - -#### Redcarpet -As alternative you can use [redcarpet](https://github.com/vmg/redcarpet) as formatter, you need to include redcarpet in your gemspec. If you also want to use [rouge](https://github.com/jneen/rouge) as syntax highlighter you also need to include it. - -```ruby -gem 'redcarpet' -gem 'rouge' -``` - -Configure your api documentation route with: - -```ruby -add_swagger_documentation( - markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new(render_options: { highlighter: :rouge }) -) -``` - -Alternatively you can disable rouge by adding `:none` as highlighter option. You can add redcarpet extensions and render options trough the `extenstions:` and `render_options:` parameters. - - -#### Custom markdown formatter - -You can also add your custom adapter for your favourite markdown formatter, as long it responds to the method `markdown(text)` and it formats the given text. - - -```ruby -module API - - class FancyAdapter - attr_reader :adapter - - def initialize(options) - require 'superbmarkdownformatter' - @adapter = SuperbMarkdownFormatter.new options - end - - def markdown(text) - @adapter.render_supreme(text) - end - end - - add_swagger_documentation markdown: FancyAdapter.new(no_links: true) -end -``` +## Markdown in Detail (deprecated) +OAPI accepts GFM for descriptions diff --git a/UPGRADING.md b/UPGRADING.md index 25049080..0cf8cc94 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,11 @@ ## Upgrading Grape-swagger +### Upgrading to >= 0.26.0 + +Usage of option `markdown` won't no longer be supported, +cause OAPI accepts [GFM](https://help.github.com/articles/github-flavored-markdown) and plain text. +(see: [description of `Info`](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/2.0.md#info-object)) + ### Upgrading to >= 0.25.2 Avoids ambiguous documentation of array parameters, diff --git a/lib/grape-swagger.rb b/lib/grape-swagger.rb index 5cf69769..8f2b8928 100644 --- a/lib/grape-swagger.rb +++ b/lib/grape-swagger.rb @@ -7,9 +7,6 @@ require 'grape-swagger/doc_methods' require 'grape-swagger/model_parsers' -require 'grape-swagger/markdown/kramdown_adapter' -require 'grape-swagger/markdown/redcarpet_adapter' - module GrapeSwagger class << self def model_parsers diff --git a/lib/grape-swagger/doc_methods.rb b/lib/grape-swagger/doc_methods.rb index 4361f64f..1b147068 100644 --- a/lib/grape-swagger/doc_methods.rb +++ b/lib/grape-swagger/doc_methods.rb @@ -27,6 +27,9 @@ def mount_path end def setup(options) + # FIXME: move out after next minor is released + GrapeSwagger::Errors::SwaggerSpecDeprecated.tell!(options[:markdown]) if options.key?(:markdown) + options = defaults.merge(options) # options could be set on #add_swagger_documentation call, @@ -93,7 +96,6 @@ def defaults base_path: nil, add_base_path: false, add_version: true, - markdown: false, hide_documentation_path: true, format: :json, authorizations: nil, diff --git a/lib/grape-swagger/endpoint.rb b/lib/grape-swagger/endpoint.rb index 90aa3600..83737538 100644 --- a/lib/grape-swagger/endpoint.rb +++ b/lib/grape-swagger/endpoint.rb @@ -105,12 +105,12 @@ def path_item(routes, options) def method_object(route, options, path) method = {} method[:summary] = summary_object(route) - method[:description] = description_object(route, options[:markdown]) + method[:description] = description_object(route) method[:produces] = produces_object(route, options[:produces] || options[:format]) method[:consumes] = consumes_object(route, options[:format]) method[:parameters] = params_object(route) method[:security] = security_object(route) - method[:responses] = response_object(route, options[:markdown]) + method[:responses] = response_object(route) method[:tags] = route.options.fetch(:tags, tag_object(route)) method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route, path) method.delete_if { |_, value| value.blank? } @@ -130,10 +130,9 @@ def summary_object(route) summary end - def description_object(route, markdown) + def description_object(route) description = route.description if route.description.present? description = route.options[:detail] if route.options.key?(:detail) - description = markdown.markdown(description.to_s).chomp if markdown description end @@ -178,7 +177,7 @@ def params_object(route) parameters end - def response_object(route, markdown) + def response_object(route) codes = (route.http_codes || route.options[:failure] || []) codes = apply_success_codes(route) + codes @@ -199,7 +198,7 @@ def response_object(route, markdown) next unless !response_model.start_with?('Swagger_doc') && ((@definitions[response_model] && value[:code].to_s.start_with?('2')) || value[:model]) - @definitions[response_model][:description] = description_object(route, markdown) + @definitions[response_model][:description] = description_object(route) # TODO: proof that the definition exist, if model isn't specified reference = { '$ref' => "#/definitions/#{response_model}" } memo[value[:code]][:schema] = if route.options[:is_array] diff --git a/lib/grape-swagger/errors.rb b/lib/grape-swagger/errors.rb index 243e47b0..c0953af0 100644 --- a/lib/grape-swagger/errors.rb +++ b/lib/grape-swagger/errors.rb @@ -1,12 +1,13 @@ module GrapeSwagger module Errors - class MarkdownDependencyMissingError < StandardError - def initialize(missing_gem) - super("Missing required dependency: #{missing_gem}") - end - end - class UnregisteredParser < StandardError; end class SwaggerSpec < StandardError; end + class SwaggerSpecDeprecated < SwaggerSpec + class << self + def tell!(what) + warn "[GrapeSwagger] usage of #{what} is deprecated" + end + end + end end end diff --git a/lib/grape-swagger/markdown/kramdown_adapter.rb b/lib/grape-swagger/markdown/kramdown_adapter.rb deleted file mode 100644 index ca07f9fc..00000000 --- a/lib/grape-swagger/markdown/kramdown_adapter.rb +++ /dev/null @@ -1,37 +0,0 @@ -module GrapeSwagger - class Markdown - class KramdownAdapter - attr_reader :options - - ### - # Initializes the kramdown adapter with options. - # See kramdown documentation what options can be passed. - # Default it uses Github flavoured markup as input and won't use coderay as converter for syntax highlighting. - # config: an hash of configuration options to be passed to the kramdown. - # usage: - # Add the kramdown gem to your gemfile or run: - # $ (sudo) gem install kramdown - # - # Then pass a new instance of GrapeSwagger::Markdown::KramdownAdapter as markdown option. - ### - def initialize(config = {}) - require 'kramdown' - defaults = { - input: 'GFM', - enable_coderay: false - } - @options = defaults.merge(config) - rescue LoadError - raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'kramdown' - end - - ### - # marks down the given text to html format. - # text: The text to be formatted. - ### - def markdown(text) - Kramdown::Document.new(text, @options).to_html - end - end - end -end diff --git a/lib/grape-swagger/markdown/redcarpet_adapter.rb b/lib/grape-swagger/markdown/redcarpet_adapter.rb deleted file mode 100644 index 111d6fea..00000000 --- a/lib/grape-swagger/markdown/redcarpet_adapter.rb +++ /dev/null @@ -1,92 +0,0 @@ -module GrapeSwagger - class Markdown - class RedcarpetAdapter - module RenderWithoutSyntaxHighlighter - require 'cgi' - - def block_code(code, language) - language ||= 'text' - "
-
#{CGI.escapeHTML(code)}
-
" - end - end - - attr_reader :extension_options - - attr_reader :render_options - - ### - # Initializes the redcarpet adapter with markup options. - # See redcarpet documentation what options can be passed. - # Default it uses fenced_code_blocks, autolinks and rouge as syntax highlighter. - # To configure an highlighter add {highlighter: :value} to the extentions hash. - # Currently supported highlighters: - # :rouge - # - # extensions: an hash of configuration options to be passed to markdown. - # render_options: an hash of configuration options to be passed to renderer. - # - # usage: - # Add the redcarpet gem to your gemfile or run: - # $ (sudo) gem install redcarpet - # when you want to have rouge as syntax highlighter add rouge to the gemfile or run: - # $ (sudo) gem install rouge - # - # GrapeSwagger::Markdown::RedcarpetAdapter.new({highlighter: :none},{no_links: true}) - # will use no syntax highlighter and won't render links. - ### - def initialize(options = {}) - require 'redcarpet' - extentions_defaults = { - fenced_code_blocks: true, - autolink: true - } - render_defaults = { highlighter: :rouge } - @extension_options = extentions_defaults.merge(options.fetch(:extensions, {})) - @render_options = render_defaults.merge(options.fetch(:render_options, {})) - @renderer = new_redcarpet_renderer(@render_options.delete(:highlighter)).new(@render_options) - @markdown = Redcarpet::Markdown.new(@renderer, @extension_options) - rescue LoadError - raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'redcarpet' - end - - ### - # Marks down the given text to html format. - ### - def markdown(text) - @markdown.render(text) - end - - private - - ### - # Creates a new redcarpet renderer based on the highlighter given. - # - # render_options: options passed to the renderer. - # - # usage: - # new_redcarpet_renderer(:rouge) # uses rouge as highlighter. - # new_redcarpet_renderer # no highlight plugin - ### - def new_redcarpet_renderer(syntax_highlighter = nil) - case syntax_highlighter - when :rouge - begin - Class.new(Redcarpet::Render::HTML) do - require 'rouge' - require 'rouge/plugins/redcarpet' - include Rouge::Plugins::Redcarpet - end - rescue LoadError - raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'rouge' - end - else - Class.new(Redcarpet::Render::HTML) do - include RenderWithoutSyntaxHighlighter - end - end - end - end - end -end diff --git a/spec/markdown/kramdown_adapter_spec.rb b/spec/markdown/kramdown_adapter_spec.rb deleted file mode 100644 index e6f9390f..00000000 --- a/spec/markdown/kramdown_adapter_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'spec_helper' - -describe GrapeSwagger::Markdown::KramdownAdapter do - context 'initialization' do - it 'uses GFM as default input and disable coderay' do - adapter = GrapeSwagger::Markdown::KramdownAdapter.new - - expect(adapter.options).to eq(input: 'GFM', enable_coderay: false) - end - - it 'overrides default values' do - options = { input: 'kramdown', enable_coderay: true } - - adapter = GrapeSwagger::Markdown::KramdownAdapter.new options - - expect(adapter.options).to eq(options) - end - end - - context 'markdown' do - it 'marks down with the configured options' do - text = '# hello world' - options = { input: 'GFM', enable_coderay: true, auto_ids: false, hard_wrap: true } - expect(GrapeSwagger::Markdown::KramdownAdapter).to receive(:new).with(options).and_call_original - - output = GrapeSwagger::Markdown::KramdownAdapter.new(options).markdown(text) - - expect(output).to include('

hello world

') - end - end -end diff --git a/spec/markdown/redcarpet_adapter_spec.rb b/spec/markdown/redcarpet_adapter_spec.rb deleted file mode 100644 index 6c1bd1e0..00000000 --- a/spec/markdown/redcarpet_adapter_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'spec_helper' - -describe GrapeSwagger::Markdown::RedcarpetAdapter, unless: RUBY_PLATFORM.eql?('java') || RUBY_ENGINE.eql?('rbx') do - context 'initialization' do - context 'initialization' do - it 'uses fenced_code_blocks, auto_links and rouge as default.' do - expect_any_instance_of(GrapeSwagger::Markdown::RedcarpetAdapter).to receive(:new_redcarpet_renderer).with(:rouge).and_call_original - - adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new - - expect(adapter.extension_options).to eq(fenced_code_blocks: true, autolink: true) - expect(adapter.render_options).to eq({}) - end - - it 'initializes with no highlighter.' do - expect_any_instance_of(GrapeSwagger::Markdown::RedcarpetAdapter).to receive(:new_redcarpet_renderer).with(:none).and_call_original - - adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new render_options: { highlighter: :none } - - expect(adapter.extension_options).to eq(fenced_code_blocks: true, autolink: true) - expect(adapter.render_options).to eq({}) - end - - it 'overrides default values' do - extensions = { fenced_code_blocks: true, autolink: true } - render_options = { highlighter: :none, no_links: true } - - adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new extensions: extensions, render_options: render_options - - expect(adapter.extension_options).to eq(extensions) - expect(adapter.render_options).to eq(no_links: true) - end - end - - context 'markdown' do - it 'marks down with the configured options' do - text = '# hello world #' - extensions = { fenced_code_blocks: true, autolink: true } - render_options = { highlighter: :none, no_links: true } - expect_any_instance_of(Redcarpet::Markdown).to receive(:render).with(text).and_call_original - - output = GrapeSwagger::Markdown::RedcarpetAdapter.new(extensions: extensions, render_options: render_options).markdown(text) - - expect(output).to include('

hello world

') - end - end - - context 'new_redcarpet_renderer' do - it 'returns a rouge syntax highlighter' do - adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new - renderer = adapter.send(:new_redcarpet_renderer, :rouge) - - expect(renderer).to include(Rouge::Plugins::Redcarpet) - expect(renderer.superclass).to be(Redcarpet::Render::HTML) - end - - it 'returns a default syntax highlighter' do - adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new - renderer = adapter.send(:new_redcarpet_renderer, :none) - - expect(renderer).to include(GrapeSwagger::Markdown::RedcarpetAdapter::RenderWithoutSyntaxHighlighter) - expect(renderer.superclass).to be(Redcarpet::Render::HTML) - end - end - end -end diff --git a/spec/swagger_v2/api_swagger_v2_detail_spec.rb b/spec/swagger_v2/api_swagger_v2_detail_spec.rb index ad375609..74d9bc71 100644 --- a/spec/swagger_v2/api_swagger_v2_detail_spec.rb +++ b/spec/swagger_v2/api_swagger_v2_detail_spec.rb @@ -46,7 +46,7 @@ class DetailApi < Grape::API { 'declared_params' => declared(params) } end - add_swagger_documentation + add_swagger_documentation markdown: 'foo' end end end @@ -74,80 +74,4 @@ def app expect(subject['paths']['/use_detail_block']['get']['description']).to eql 'detailed description of the route inside the `desc` block' end end - - describe 'details, convert markdown with kramdown' do - include_context "#{MODEL_PARSER} swagger example" - - before :all do - module TheApi - class GfmDetailApi < Grape::API - format :json - - desc 'This returns something', - detail: details, - entity: Entities::UseResponse, - failure: [{ code: 400, model: Entities::ApiError }] - get '/use_gfm_detail' do - { 'declared_params' => declared(params) } - end - - add_swagger_documentation markdown: GrapeSwagger::Markdown::KramdownAdapter.new - end - end - end - - def app - TheApi::GfmDetailApi - end - - subject do - get '/swagger_doc' - JSON.parse(last_response.body) - end - - specify do - expect(subject['paths']['/use_gfm_detail']['get']).to include('description') - expect(subject['paths']['/use_gfm_detail']['get']['description']).to eql( - "

Burgers in Heaven

\n\n
\n

A burger doesn’t come for free

\n
\n\n

If you want to reserve a burger in heaven, you have to do
\nsome crazy stuff on earth.

\n\n
def do_good\nputs 'help people'\nend\n
\n\n
    \n
  • Will go to Heaven: Probably
  • \n
  • Will go to Hell: Probably not
  • \n
" - ) - end - end - - describe 'details, convert markdown with redcarpet', unless: RUBY_PLATFORM.eql?('java') do - include_context "#{MODEL_PARSER} swagger example" - - before :all do - module TheApi - class GfmRcDetailApi < Grape::API - format :json - - desc 'This returns something', - detail: details, - entity: Entities::UseResponse, - failure: [{ code: 400, model: Entities::ApiError }] - get '/use_gfm_rc_detail' do - { 'declared_params' => declared(params) } - end - - add_swagger_documentation markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new - end - end - end - - def app - TheApi::GfmRcDetailApi - end - - subject do - get '/swagger_doc' - JSON.parse(last_response.body) - end - - specify do - expect(subject['paths']['/use_gfm_rc_detail']['get']).to include('description') - expect(subject['paths']['/use_gfm_rc_detail']['get']['description']).to eql( - "

Burgers in Heaven

\n\n
\n

A burger doesn't come for free

\n
\n\n

If you want to reserve a burger in heaven, you have to do\nsome crazy stuff on earth.

\n
def do_good\nputs 'help people'\nend\n
\n
    \n
  • Will go to Heaven: Probably
  • \n
  • Will go to Hell: Probably not
  • \n
" - ) - end - end end diff --git a/spec/swagger_v2/description_not_initialized.rb b/spec/swagger_v2/description_not_initialized.rb index 3f15d088..a8e3e7e6 100644 --- a/spec/swagger_v2/description_not_initialized.rb +++ b/spec/swagger_v2/description_not_initialized.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'details' do - describe 'details, pass markdown with redcarpet even with nil description and detail', unless: RUBY_PLATFORM.eql?('java') do + describe 'has no description, if details or description are nil' do before :all do module TheApi class GfmRcDetailApi < Grape::API