Commit 730625f0 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'patch/fix-markdown-preview-wikis' into 'master'

Wiki preview URL converting problem [via Markdown]

Current implementation when rendering the preview, thinks relative links are for project repository files.

We are creating a new preview route that will define correct context data to render for wikis instead.

Fixes #2380, #1184

See merge request !3461
parents 7c6c933c 1575a95b
...@@ -88,6 +88,20 @@ class Projects::WikisController < Projects::ApplicationController ...@@ -88,6 +88,20 @@ class Projects::WikisController < Projects::ApplicationController
) )
end end
def markdown_preview
text = params[:text]
ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
ext.analyze(text)
render json: {
body: view_context.markdown(text, pipeline: :wiki, project_wiki: @project_wiki),
references: {
users: ext.users.map(&:username)
}
}
end
def git_access def git_access
end end
......
...@@ -5,10 +5,14 @@ ...@@ -5,10 +5,14 @@
- content_for :scripts_body_top do - content_for :scripts_body_top do
- project = @target_project || @project - project = @target_project || @project
- if @project_wiki
- markdown_preview_path = namespace_project_wikis_markdown_preview_path(project.namespace, project)
- else
- markdown_preview_path = markdown_preview_namespace_project_path(project.namespace, project)
- if current_user - if current_user
:javascript :javascript
window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}"; window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}";
window.markdown_preview_path = "#{markdown_preview_namespace_project_path(project.namespace, project)}"; window.markdown_preview_path = "#{markdown_preview_path}";
- content_for :scripts_body do - content_for :scripts_body do
= render "layouts/init_auto_complete" if current_user = render "layouts/init_auto_complete" if current_user
......
...@@ -575,6 +575,7 @@ Rails.application.routes.draw do ...@@ -575,6 +575,7 @@ Rails.application.routes.draw do
# Order matters to give priority to these matches # Order matters to give priority to these matches
get '/wikis/git_access', to: 'wikis#git_access' get '/wikis/git_access', to: 'wikis#git_access'
get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages'
post '/wikis/markdown_preview', to:'wikis#markdown_preview'
post '/wikis', to: 'wikis#create' post '/wikis', to: 'wikis#create'
get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID
......
...@@ -118,7 +118,7 @@ module Banzai ...@@ -118,7 +118,7 @@ module Banzai
end end
if path if path
content_tag(:img, nil, src: path) content_tag(:img, nil, src: path, class: 'gfm')
end end
end end
...@@ -144,12 +144,18 @@ module Banzai ...@@ -144,12 +144,18 @@ module Banzai
# if it is not. # if it is not.
def process_page_link_tag(parts) def process_page_link_tag(parts)
if parts.size == 1 if parts.size == 1
url = parts[0].strip reference = parts[0].strip
else else
name, url = *parts.compact.map(&:strip) name, reference = *parts.compact.map(&:strip)
end end
content_tag(:a, name || url, href: url) if url?(reference)
href = reference
else
href = ::File.join(project_wiki_base_path, reference)
end
content_tag(:a, name || reference, href: href, class: 'gfm')
end end
def project_wiki def project_wiki
......
require 'uri'
module Banzai
module Filter
# HTML filter that "fixes" relative links to files in a repository.
#
# Context options:
# :project_wiki
class WikiLinkFilter < HTML::Pipeline::Filter
def call
return doc unless project_wiki?
doc.search('a:not(.gfm)').each do |el|
process_link_attr el.attribute('href')
end
doc
end
protected
def project_wiki?
!context[:project_wiki].nil?
end
def process_link_attr(html_attr)
return if html_attr.blank? || file_reference?(html_attr)
uri = URI(html_attr.value)
if uri.relative? && uri.path.present?
html_attr.value = rebuild_wiki_uri(uri).to_s
end
rescue URI::Error
# noop
end
def rebuild_wiki_uri(uri)
uri.path = ::File.join(project_wiki_base_path, uri.path)
uri
end
def file_reference?(html_attr)
!File.extname(html_attr.value).blank?
end
def project_wiki
context[:project_wiki]
end
def project_wiki_base_path
project_wiki && project_wiki.wiki_base_path
end
end
end
end
...@@ -2,8 +2,10 @@ module Banzai ...@@ -2,8 +2,10 @@ module Banzai
module Pipeline module Pipeline
class WikiPipeline < FullPipeline class WikiPipeline < FullPipeline
def self.filters def self.filters
@filters ||= super.insert_after(Filter::TableOfContentsFilter, @filters ||= begin
Filter::GollumTagsFilter) super.insert_after(Filter::TableOfContentsFilter, Filter::GollumTagsFilter)
.insert_before(Filter::TaskListFilter, Filter::WikiLinkFilter)
end
end end
end end
end end
......
...@@ -39,7 +39,7 @@ describe 'GitLab Markdown', feature: true do ...@@ -39,7 +39,7 @@ describe 'GitLab Markdown', feature: true do
end end
def doc(html = @html) def doc(html = @html)
Nokogiri::HTML::DocumentFragment.parse(html) @doc ||= Nokogiri::HTML::DocumentFragment.parse(html)
end end
# Shared behavior that all pipelines should exhibit # Shared behavior that all pipelines should exhibit
...@@ -230,6 +230,7 @@ describe 'GitLab Markdown', feature: true do ...@@ -230,6 +230,7 @@ describe 'GitLab Markdown', feature: true do
file = Gollum::File.new(@project_wiki.wiki) file = Gollum::File.new(@project_wiki.wiki)
expect(file).to receive(:path).and_return('images/example.jpg') expect(file).to receive(:path).and_return('images/example.jpg')
expect(@project_wiki).to receive(:find_file).with('images/example.jpg').and_return(file) expect(@project_wiki).to receive(:find_file).with('images/example.jpg').and_return(file)
allow(@project_wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
@html = markdown(@feat.raw_markdown, { pipeline: :wiki, project_wiki: @project_wiki }) @html = markdown(@feat.raw_markdown, { pipeline: :wiki, project_wiki: @project_wiki })
end end
......
...@@ -70,20 +70,22 @@ describe Banzai::Filter::GollumTagsFilter, lib: true do ...@@ -70,20 +70,22 @@ describe Banzai::Filter::GollumTagsFilter, lib: true do
end end
context 'linking internal resources' do context 'linking internal resources' do
it "the created link's text will be equal to the resource's text" do it "the created link's text includes the resource's text and wiki base path" do
tag = '[[wiki-slug]]' tag = '[[wiki-slug]]'
doc = filter("See #{tag}", project_wiki: project_wiki) doc = filter("See #{tag}", project_wiki: project_wiki)
expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug')
expect(doc.at_css('a').text).to eq 'wiki-slug' expect(doc.at_css('a').text).to eq 'wiki-slug'
expect(doc.at_css('a')['href']).to eq 'wiki-slug' expect(doc.at_css('a')['href']).to eq expected_path
end end
it "the created link's text will be link-text" do it "the created link's text will be link-text" do
tag = '[[link-text|wiki-slug]]' tag = '[[link-text|wiki-slug]]'
doc = filter("See #{tag}", project_wiki: project_wiki) doc = filter("See #{tag}", project_wiki: project_wiki)
expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug')
expect(doc.at_css('a').text).to eq 'link-text' expect(doc.at_css('a').text).to eq 'link-text'
expect(doc.at_css('a')['href']).to eq 'wiki-slug' expect(doc.at_css('a')['href']).to eq expected_path
end end
end end
......
...@@ -11,7 +11,7 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -11,7 +11,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo Foo
MD MD
result = described_class.call(markdown, project: spy, project_wiki: double) result = described_class.call(markdown, project: spy, project_wiki: spy)
aggregate_failures do aggregate_failures do
expect(result[:output].text).not_to include '[[' expect(result[:output].text).not_to include '[['
...@@ -29,7 +29,7 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -29,7 +29,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo Foo
MD MD
output = described_class.to_html(markdown, project: spy, project_wiki: double) output = described_class.to_html(markdown, project: spy, project_wiki: spy)
expect(output).to include('[[<em>toc</em>]]') expect(output).to include('[[<em>toc</em>]]')
end end
...@@ -42,7 +42,7 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -42,7 +42,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo Foo
MD MD
output = described_class.to_html(markdown, project: spy, project_wiki: double) output = described_class.to_html(markdown, project: spy, project_wiki: spy)
aggregate_failures do aggregate_failures do
expect(output).not_to include('<ul>') expect(output).not_to include('<ul>')
......
...@@ -13,7 +13,7 @@ module MarkdownMatchers ...@@ -13,7 +13,7 @@ module MarkdownMatchers
set_default_markdown_messages set_default_markdown_messages
match do |actual| match do |actual|
link = actual.at_css('a:contains("Relative Link")') link = actual.at_css('a:contains("Relative Link")')
image = actual.at_css('img[alt="Relative Image"]') image = actual.at_css('img[alt="Relative Image"]')
expect(link['href']).to end_with('master/doc/README.md') expect(link['href']).to end_with('master/doc/README.md')
...@@ -72,14 +72,15 @@ module MarkdownMatchers ...@@ -72,14 +72,15 @@ module MarkdownMatchers
have_css("img[src$='#{src}']") have_css("img[src$='#{src}']")
end end
prefix = '/namespace1/gitlabhq/wikis'
set_default_markdown_messages set_default_markdown_messages
match do |actual| match do |actual|
expect(actual).to have_link('linked-resource', href: 'linked-resource') expect(actual).to have_link('linked-resource', href: "#{prefix}/linked-resource")
expect(actual).to have_link('link-text', href: 'linked-resource') expect(actual).to have_link('link-text', href: "#{prefix}/linked-resource")
expect(actual).to have_link('http://example.com', href: 'http://example.com') expect(actual).to have_link('http://example.com', href: 'http://example.com')
expect(actual).to have_link('link-text', href: 'http://example.com/pdfs/gollum.pdf') expect(actual).to have_link('link-text', href: 'http://example.com/pdfs/gollum.pdf')
expect(actual).to have_image('/gitlabhq/wikis/images/example.jpg') expect(actual).to have_image("#{prefix}/images/example.jpg")
expect(actual).to have_image('http://example.com/images/example.jpg') expect(actual).to have_image('http://example.com/images/example.jpg')
end end
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