Commit d3377fa7 authored by Luke Duncalfe's avatar Luke Duncalfe

Add Wiki support for AsciiDoc include directive

GitLab added support for the AsciiDoc `include` directive in 3f5d7c7e.
The content of a file could be included if the file was part of the same
repository.

The Wiki `show` view was missing the expected variables needed for the
included file to be found in the repository. An AsciiDoc `include`
directive would instead cause a 500 error to be raised.

https://gitlab.com/gitlab-org/gitlab/issues/195625
parent ee4bfa00
......@@ -39,6 +39,10 @@ class Projects::WikisController < Projects::ApplicationController
if @page
set_encoding_error unless valid_encoding?
# Assign vars expected by MarkupHelper
@ref = params[:version_id]
@path = @page.path
render 'show'
elsif file_blob
send_blob(@project_wiki.repository, file_blob)
......
......@@ -132,6 +132,7 @@ module MarkupHelper
pipeline: :wiki,
project: @project,
project_wiki: @project_wiki,
repository: @project_wiki.repository,
page_slug: wiki_page.slug,
issuable_state_filter_enabled: true
)
......
......@@ -13,7 +13,7 @@ module Gitlab
super(logger: Gitlab::AppLogger)
@context = context
@repository = context[:project].try(:repository)
@repository = context[:repository] || context[:project].try(:repository)
# Note: Asciidoctor calls #freeze on extensions, so we can't set new
# instance variables after initialization.
......@@ -111,7 +111,7 @@ module Gitlab
end
def ref
context[:ref] || context[:project].default_branch
context[:ref] || repository&.root_ref
end
def requested_path
......
# frozen_string_literal: true
require 'spec_helper'
describe 'User views AsciiDoc page with includes', :js do
let_it_be(:user) { create(:user) }
let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' }
let(:project) { create(:project, :public, :wiki_repo) }
let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')}
let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") }
def create_wiki_page(title, content:)
attrs = {
title: title,
content: content,
format: :asciidoc
}
create(:wiki_page, wiki: project.wiki, attrs: attrs)
end
before do
sign_in(user)
end
context 'when the file being included exists' do
it 'includes the file contents' do
visit(project_wiki_path(project, wiki_page))
page.within(:css, wiki_content_selector) do
expect(page).to have_content('Content from the main page. Content from the included page')
end
end
context 'when there are multiple versions of the wiki pages' do
before do
included_wiki_page.update(message: 'updated included file', content: 'Updated content from the included page')
wiki_page.update(message: 'updated wiki page', content: "Updated content from the main page.\ninclude::included_page.asciidoc[]")
end
let(:latest_version_id) { wiki_page.versions.first.id }
let(:oldest_version_id) { wiki_page.versions.last.id }
context 'viewing the latest version' do
it 'includes the latest content' do
visit(project_wiki_path(project, wiki_page, version_id: latest_version_id))
page.within(:css, wiki_content_selector) do
expect(page).to have_content('Updated content from the main page. Updated content from the included page')
end
end
end
context 'viewing the original version' do
it 'includes the content from the original version' do
visit(project_wiki_path(project, wiki_page, version_id: oldest_version_id))
page.within(:css, wiki_content_selector) do
expect(page).to have_content('Content from the main page. Content from the included page')
end
end
end
end
end
context 'when the file being included does not exist' do
before do
included_wiki_page.delete
end
it 'outputs an error' do
visit(project_wiki_path(project, wiki_page))
page.within(:css, wiki_content_selector) do
expect(page).to have_content('Content from the main page. [ERROR: include::included_page.asciidoc[] - unresolved directive]')
end
end
end
end
......@@ -273,16 +273,19 @@ describe MarkupHelper do
describe '#render_wiki_content' do
let(:wiki) { double('WikiPage', path: "file.#{extension}") }
let(:wiki_repository) { double('Repository') }
let(:context) do
{
pipeline: :wiki, project: project, project_wiki: wiki,
page_slug: 'nested/page', issuable_state_filter_enabled: true
page_slug: 'nested/page', issuable_state_filter_enabled: true,
repository: wiki_repository
}
end
before do
expect(wiki).to receive(:content).and_return('wiki content')
expect(wiki).to receive(:slug).and_return('nested/page')
expect(wiki).to receive(:repository).and_return(wiki_repository)
helper.instance_variable_set(:@project_wiki, wiki)
end
......
......@@ -518,6 +518,28 @@ module Gitlab
end
end
context 'when repository is passed into the context' do
let(:wiki_repo) { project.wiki.repository }
let(:include_path) { 'wiki_file.adoc' }
before do
project.create_wiki
context.merge!(repository: wiki_repo)
end
context 'when the file exists' do
before do
create_file(include_path, 'Content from wiki', repository: wiki_repo)
end
it { is_expected.to include('<p>Content from wiki</p>') }
end
context 'when the file does not exist' do
it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]")}
end
end
context 'recursive includes with relative paths' do
let(:input) do
<<~ADOC
......@@ -562,8 +584,8 @@ module Gitlab
end
end
def create_file(path, content)
project.repository.create_file(project.creator, path, content,
def create_file(path, content, repository: project.repository)
repository.create_file(project.creator, path, content,
message: "Add #{path}", branch_name: 'asciidoc')
end
end
......
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