Commit 33a87eea authored by Ethan Urie's avatar Ethan Urie

Merge branch '336792-fj-add-render-capabilities-to-wiki-api' into 'master'

Add wiki page render option to wiki API

See merge request gitlab-org/gitlab!81134
parents c882d3ed be93a263
...@@ -127,7 +127,7 @@ module MarkupHelper ...@@ -127,7 +127,7 @@ module MarkupHelper
text = wiki_page.content text = wiki_page.content
return '' unless text.present? return '' unless text.present?
context = render_wiki_content_context(@wiki, wiki_page, context) context = render_wiki_content_context(wiki_page.wiki, wiki_page, context)
html = markup_unsafe(wiki_page.path, text, context) html = markup_unsafe(wiki_page.path, text, context)
prepare_for_rendering(html, context) prepare_for_rendering(html, context)
......
...@@ -9,6 +9,7 @@ type: reference, api ...@@ -9,6 +9,7 @@ type: reference, api
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212199) in GitLab 13.5. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212199) in GitLab 13.5.
> - The `encoding` field was [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81150) in GitLab 14.9. > - The `encoding` field was [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81150) in GitLab 14.9.
> - The `render_html` attribute was [added](https://gitlab.com/gitlab-org/gitlab/-/issues/336792) in GitLab 14.9.
The [group wikis](../user/project/wiki/group.md) API is available only in APIv4. The [group wikis](../user/project/wiki/group.md) API is available only in APIv4.
An API for [project wikis](wikis.md) is also available. An API for [project wikis](wikis.md) is also available.
...@@ -69,6 +70,7 @@ GET /groups/:id/wikis/:slug ...@@ -69,6 +70,7 @@ GET /groups/:id/wikis/:slug
| --------- | ------- | -------- | --------------------- | | --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` | | `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
| `render_html` | boolean | no | Return the rendered HTML of the wiki page |
```shell ```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/wikis/home" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/wikis/home"
......
...@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w ...@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Project wikis API **(FREE)** # Project wikis API **(FREE)**
> The `encoding` field was [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81150) in GitLab 14.9. > - The `encoding` field was [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81150) in GitLab 14.9.
> - The `render_html` attribute was [added](https://gitlab.com/gitlab-org/gitlab/-/issues/336792) in GitLab 14.9.
The project [wikis](../user/project/wiki/index.md) API is available only in APIv4. The project [wikis](../user/project/wiki/index.md) API is available only in APIv4.
An API for [group wikis](group_wikis.md) is also available. An API for [group wikis](group_wikis.md) is also available.
...@@ -67,6 +68,7 @@ GET /projects/:id/wikis/:slug ...@@ -67,6 +68,7 @@ GET /projects/:id/wikis/:slug
| --------- | ------- | -------- | --------------------- | | --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `slug` | string | yes | URLencoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` | | `slug` | string | yes | URLencoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
| `render_html` | boolean | no | Return the rendered HTML of the wiki page |
```shell ```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/home" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/home"
......
...@@ -128,6 +128,7 @@ RSpec.describe API::Wikis do ...@@ -128,6 +128,7 @@ RSpec.describe API::Wikis do
describe 'GET /groups/:id/wikis/:slug' do describe 'GET /groups/:id/wikis/:slug' do
let(:page) { create(:wiki_page, wiki: wiki) } let(:page) { create(:wiki_page, wiki: wiki) }
let(:url) { "/groups/#{group.id}/wikis/#{page.slug}" } let(:url) { "/groups/#{group.id}/wikis/#{page.slug}" }
let(:params) { {} }
context 'when wiki is disabled' do context 'when wiki is disabled' do
before do before do
...@@ -178,7 +179,8 @@ RSpec.describe API::Wikis do ...@@ -178,7 +179,8 @@ RSpec.describe API::Wikis do
context 'when user is developer' do context 'when user is developer' do
before do before do
group.add_developer(user) group.add_developer(user)
get api(url, user)
get api(url, user), params: params
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -194,7 +196,7 @@ RSpec.describe API::Wikis do ...@@ -194,7 +196,7 @@ RSpec.describe API::Wikis do
before do before do
group.add_maintainer(user) group.add_maintainer(user)
get api(url, user) get api(url, user), params: params
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -220,7 +222,7 @@ RSpec.describe API::Wikis do ...@@ -220,7 +222,7 @@ RSpec.describe API::Wikis do
before do before do
group.add_developer(user) group.add_developer(user)
get api(url, user) get api(url, user), params: params
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -236,7 +238,7 @@ RSpec.describe API::Wikis do ...@@ -236,7 +238,7 @@ RSpec.describe API::Wikis do
before do before do
group.add_maintainer(user) group.add_maintainer(user)
get api(url, user) get api(url, user), params: params
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
......
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
module API module API
module Entities module Entities
class WikiPage < WikiPageBasic class WikiPage < WikiPageBasic
expose :content include ::MarkupHelper
expose :content do |wiki_page, options|
options[:render_html] ? render_wiki_content(wiki_page) : wiki_page.content
end
expose :encoding do |wiki_page| expose :encoding do |wiki_page|
wiki_page.content.encoding.name wiki_page.content.encoding.name
......
...@@ -45,11 +45,12 @@ module API ...@@ -45,11 +45,12 @@ module API
end end
params do params do
requires :slug, type: String, desc: 'The slug of a wiki page' requires :slug, type: String, desc: 'The slug of a wiki page'
optional :render_html, type: Boolean, default: false, desc: 'Render content to HTML'
end end
get ':id/wikis/:slug' do get ':id/wikis/:slug' do
authorize! :read_wiki, container authorize! :read_wiki, container
present wiki_page, with: Entities::WikiPage present wiki_page, with: Entities::WikiPage, render_html: params[:render_html]
end end
desc 'Create a wiki page' do desc 'Create a wiki page' do
......
...@@ -315,33 +315,26 @@ RSpec.describe MarkupHelper do ...@@ -315,33 +315,26 @@ RSpec.describe MarkupHelper do
end end
describe '#render_wiki_content' do describe '#render_wiki_content' do
let(:wiki) { double('WikiPage', path: "file.#{extension}") } let(:wiki) { build(:wiki, container: project) }
let(:wiki_repository) { double('Repository') }
let(:content) { 'wiki content' } let(:content) { 'wiki content' }
let(:slug) { 'nested/page' }
let(:wiki_page) { double('WikiPage', path: "file.#{extension}", content: content, slug: slug, wiki: wiki) }
let(:context) do let(:context) do
{ {
pipeline: :wiki, project: project, wiki: wiki, pipeline: :wiki, project: project, wiki: wiki,
page_slug: 'nested/page', issuable_reference_expansion_enabled: true, page_slug: slug, issuable_reference_expansion_enabled: true,
repository: wiki_repository repository: wiki.repository
} }
end end
before do
expect(wiki).to receive(:content).and_return(content)
expect(wiki).to receive(:slug).and_return('nested/page')
expect(wiki).to receive(:repository).and_return(wiki_repository)
allow(wiki).to receive(:container).and_return(project)
helper.instance_variable_set(:@wiki, wiki)
end
context 'when file is Markdown' do context 'when file is Markdown' do
let(:extension) { 'md' } let(:extension) { 'md' }
it 'renders using #markdown_unsafe helper method' do it 'renders using #markdown_unsafe helper method' do
expect(helper).to receive(:markdown_unsafe).with('wiki content', context) expect(helper).to receive(:markdown_unsafe).with('wiki content', context)
helper.render_wiki_content(wiki) helper.render_wiki_content(wiki_page)
end end
context 'when context has labels' do context 'when context has labels' do
...@@ -350,7 +343,7 @@ RSpec.describe MarkupHelper do ...@@ -350,7 +343,7 @@ RSpec.describe MarkupHelper do
let(:content) { '~Bug' } let(:content) { '~Bug' }
it 'renders label' do it 'renders label' do
result = helper.render_wiki_content(wiki) result = helper.render_wiki_content(wiki_page)
doc = Nokogiri::HTML.parse(result) doc = Nokogiri::HTML.parse(result)
expect(doc.css('.gl-label-link')).not_to be_empty expect(doc.css('.gl-label-link')).not_to be_empty
...@@ -366,7 +359,7 @@ RSpec.describe MarkupHelper do ...@@ -366,7 +359,7 @@ RSpec.describe MarkupHelper do
end end
it 'renders uploads relative to project' do it 'renders uploads relative to project' do
result = helper.render_wiki_content(wiki) result = helper.render_wiki_content(wiki_page)
expect(result).to include("#{project.full_path}#{upload_link}") expect(result).to include("#{project.full_path}#{upload_link}")
end end
...@@ -379,7 +372,7 @@ RSpec.describe MarkupHelper do ...@@ -379,7 +372,7 @@ RSpec.describe MarkupHelper do
it 'renders using Gitlab::Asciidoc' do it 'renders using Gitlab::Asciidoc' do
expect(Gitlab::Asciidoc).to receive(:render) expect(Gitlab::Asciidoc).to receive(:render)
helper.render_wiki_content(wiki) helper.render_wiki_content(wiki_page)
end end
end end
...@@ -398,7 +391,7 @@ FooBar ...@@ -398,7 +391,7 @@ FooBar
it 'renders using #markdown_unsafe helper method' do it 'renders using #markdown_unsafe helper method' do
expect(helper).to receive(:markdown_unsafe).with(content, context) expect(helper).to receive(:markdown_unsafe).with(content, context)
result = helper.render_wiki_content(wiki) result = helper.render_wiki_content(wiki_page)
expect(result).to be_empty expect(result).to be_empty
end end
...@@ -410,7 +403,7 @@ FooBar ...@@ -410,7 +403,7 @@ FooBar
it 'renders all other formats using Gitlab::OtherMarkup' do it 'renders all other formats using Gitlab::OtherMarkup' do
expect(Gitlab::OtherMarkup).to receive(:render) expect(Gitlab::OtherMarkup).to receive(:render)
helper.render_wiki_content(wiki) helper.render_wiki_content(wiki_page)
end end
end end
end end
......
...@@ -5,7 +5,10 @@ require 'spec_helper' ...@@ -5,7 +5,10 @@ require 'spec_helper'
RSpec.describe API::Entities::WikiPage do RSpec.describe API::Entities::WikiPage do
let_it_be_with_reload(:wiki_page) { create(:wiki_page) } let_it_be_with_reload(:wiki_page) { create(:wiki_page) }
let(:entity) { described_class.new(wiki_page) } let(:params) { {} }
let(:entity) { described_class.new(wiki_page, params) }
subject { entity.as_json }
it 'returns the proper encoding for the wiki page content' do it 'returns the proper encoding for the wiki page content' do
expect(entity.as_json[:encoding]).to eq 'UTF-8' expect(entity.as_json[:encoding]).to eq 'UTF-8'
...@@ -14,4 +17,26 @@ RSpec.describe API::Entities::WikiPage do ...@@ -14,4 +17,26 @@ RSpec.describe API::Entities::WikiPage do
expect(entity.as_json[:encoding]).to eq 'ISO-8859-1' expect(entity.as_json[:encoding]).to eq 'ISO-8859-1'
end end
it 'returns the raw wiki page content' do
expect(subject[:content]).to eq wiki_page.content
end
context 'when render_html param is passed' do
context 'when it is true' do
let(:params) { { render_html: true } }
it 'returns the wiki page content rendered' do
expect(subject[:content]).to eq "<p data-sourcepos=\"1:1-1:#{wiki_page.content.size}\" dir=\"auto\">#{wiki_page.content}</p>"
end
end
context 'when it is false' do
let(:params) { { render_html: false } }
it 'returns the raw wiki page content' do
expect(subject[:content]).to eq wiki_page.content
end
end
end
end end
...@@ -130,41 +130,42 @@ RSpec.describe API::Wikis do ...@@ -130,41 +130,42 @@ RSpec.describe API::Wikis do
describe 'GET /projects/:id/wikis/:slug' do describe 'GET /projects/:id/wikis/:slug' do
let(:page) { create(:wiki_page, wiki: project.wiki) } let(:page) { create(:wiki_page, wiki: project.wiki) }
let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" } let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" }
let(:params) { {} }
subject(:request) { get api(url, user), params: params }
context 'when wiki is disabled' do context 'when wiki is disabled' do
let(:project) { project_wiki_disabled } let(:project) { project_wiki_disabled }
before do
request
end
context 'when user is guest' do context 'when user is guest' do
before do let(:user) { nil }
get api(url)
end
include_examples 'wiki API 404 Project Not Found' include_examples 'wiki API 404 Project Not Found'
end end
context 'when user is developer' do context 'when user is developer' do
before do let(:user) { developer }
get api(url, developer)
end
include_examples 'wiki API 403 Forbidden' include_examples 'wiki API 403 Forbidden'
end end
context 'when user is maintainer' do context 'when user is maintainer' do
before do let(:user) { maintainer }
get api(url, maintainer)
end
include_examples 'wiki API 403 Forbidden' include_examples 'wiki API 403 Forbidden'
end end
end end
context 'when wiki is available only for team members' do context 'when wiki is available only for team members' do
let(:project) { create(:project, :wiki_repo, :wiki_private) } let_it_be_with_reload(:project) { create(:project, :wiki_repo, :wiki_private) }
context 'when user is guest' do context 'when user is guest' do
before do before do
get api(url) request
end end
include_examples 'wiki API 404 Project Not Found' include_examples 'wiki API 404 Project Not Found'
...@@ -173,7 +174,8 @@ RSpec.describe API::Wikis do ...@@ -173,7 +174,8 @@ RSpec.describe API::Wikis do
context 'when user is developer' do context 'when user is developer' do
before do before do
project.add_developer(user) project.add_developer(user)
get api(url, user)
request
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -189,7 +191,7 @@ RSpec.describe API::Wikis do ...@@ -189,7 +191,7 @@ RSpec.describe API::Wikis do
before do before do
project.add_maintainer(user) project.add_maintainer(user)
get api(url, user) request
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -203,11 +205,13 @@ RSpec.describe API::Wikis do ...@@ -203,11 +205,13 @@ RSpec.describe API::Wikis do
end end
context 'when wiki is available for everyone with access' do context 'when wiki is available for everyone with access' do
let(:project) { create(:project, :wiki_repo) } let_it_be_with_reload(:project) { create(:project, :wiki_repo) }
context 'when user is guest' do context 'when user is guest' do
let(:user) { nil }
before do before do
get api(url) request
end end
include_examples 'wiki API 404 Project Not Found' include_examples 'wiki API 404 Project Not Found'
...@@ -217,7 +221,7 @@ RSpec.describe API::Wikis do ...@@ -217,7 +221,7 @@ RSpec.describe API::Wikis do
before do before do
project.add_developer(user) project.add_developer(user)
get api(url, user) request
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
...@@ -233,7 +237,7 @@ RSpec.describe API::Wikis do ...@@ -233,7 +237,7 @@ RSpec.describe API::Wikis do
before do before do
project.add_maintainer(user) project.add_maintainer(user)
get api(url, user) request
end end
include_examples 'wikis API returns wiki page' include_examples 'wikis API returns wiki page'
......
...@@ -44,14 +44,32 @@ RSpec.shared_examples_for 'wikis API returns list of wiki pages' do ...@@ -44,14 +44,32 @@ RSpec.shared_examples_for 'wikis API returns list of wiki pages' do
end end
RSpec.shared_examples_for 'wikis API returns wiki page' do RSpec.shared_examples_for 'wikis API returns wiki page' do
it 'returns the wiki page' do shared_examples 'returns wiki page' do
expect(response).to have_gitlab_http_status(:ok) specify do
expect(json_response.size).to eq(5) expect(response).to have_gitlab_http_status(:ok)
expect(json_response.keys).to match_array(expected_keys_with_content) expect(json_response.size).to eq(5)
expect(json_response['content']).to eq(page.content) expect(json_response.keys).to match_array(expected_keys_with_content)
expect(json_response['slug']).to eq(page.slug) expect(json_response['content']).to eq(expected_content)
expect(json_response['title']).to eq(page.title) expect(json_response['slug']).to eq(page.slug)
expect(json_response['encoding']).to eq('UTF-8') expect(json_response['title']).to eq(page.title)
end
end
let(:expected_content) { page.content }
it_behaves_like 'returns wiki page'
context 'when render param is false' do
let(:params) { { render_html: false } }
it_behaves_like 'returns wiki page'
end
context 'when render param is true' do
let(:params) { { render_html: true } }
let(:expected_content) { '<p data-sourcepos="1:1-1:21" dir="auto">Content for wiki page</p>' }
it_behaves_like 'returns wiki page'
end end
end end
......
...@@ -31,7 +31,7 @@ RSpec.describe 'shared/wikis/_sidebar.html.haml' do ...@@ -31,7 +31,7 @@ RSpec.describe 'shared/wikis/_sidebar.html.haml' do
context 'The sidebar comes from a custom page' do context 'The sidebar comes from a custom page' do
before do before do
assign(:sidebar_page, double('WikiPage', path: 'sidebar.md', slug: 'sidebar', content: 'Some sidebar content')) assign(:sidebar_page, double('WikiPage', path: 'sidebar.md', slug: 'sidebar', content: 'Some sidebar content', wiki: wiki))
end end
it 'does not show an alert' do it 'does not show an alert' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment