Commit 05e0f504 authored by Toon Claes's avatar Toon Claes

Cache the rendered README, but post-process on show

Because the post-processing of the rendered README is dependent on the
context (i.e. the current user), do the post-processing when the
README is being displayed.
parent ef4d4446
...@@ -60,12 +60,17 @@ module MarkupHelper ...@@ -60,12 +60,17 @@ module MarkupHelper
end end
def markdown(text, context = {}) def markdown(text, context = {})
html = markdown_render(text, context)
markup_postprocess(html, context)
end
def markdown_render(text, context = {})
return "" unless text.present? return "" unless text.present?
context[:project] ||= @project context[:project] ||= @project
html = Banzai.render(text, context) Banzai.render(text, context)
banzai_postprocess(html, context)
end end
def markdown_field(object, field) def markdown_field(object, field)
...@@ -76,7 +81,7 @@ module MarkupHelper ...@@ -76,7 +81,7 @@ module MarkupHelper
banzai_postprocess(html, object.banzai_render_context(field)) banzai_postprocess(html, object.banzai_render_context(field))
end end
def asciidoc(text) def asciidoc_render(text)
Gitlab::Asciidoc.render( Gitlab::Asciidoc.render(
text, text,
project: @project, project: @project,
...@@ -90,7 +95,7 @@ module MarkupHelper ...@@ -90,7 +95,7 @@ module MarkupHelper
) )
end end
def other_markup(file_name, text) def other_markup_render(file_name, text)
Gitlab::OtherMarkup.render( Gitlab::OtherMarkup.render(
file_name, file_name,
text, text,
...@@ -105,6 +110,14 @@ module MarkupHelper ...@@ -105,6 +110,14 @@ module MarkupHelper
) )
end end
def markup_postprocess(html, context = {})
return "" unless html.present?
context[:project] ||= @project
banzai_postprocess(html, context)
end
# Return the first line of +text+, up to +max_chars+, after parsing the line # Return the first line of +text+, up to +max_chars+, after parsing the line
# as Markdown. HTML tags in the parsed output are not counted toward the # as Markdown. HTML tags in the parsed output are not counted toward the
# +max_chars+ limit. If the length limit falls within a tag's contents, then # +max_chars+ limit. If the length limit falls within a tag's contents, then
...@@ -116,27 +129,34 @@ module MarkupHelper ...@@ -116,27 +129,34 @@ module MarkupHelper
end end
def render_wiki_content(wiki_page) def render_wiki_content(wiki_page)
context = { pipeline: :wiki, project_wiki: @project_wiki, page_slug: wiki_page.slug }
case wiki_page.format case wiki_page.format
when :markdown when :markdown
markdown(wiki_page.content, pipeline: :wiki, project_wiki: @project_wiki, page_slug: wiki_page.slug) html = markdown_render(wiki_page.content, context)
when :asciidoc when :asciidoc
asciidoc(wiki_page.content) html = asciidoc_render(wiki_page.content)
else else
wiki_page.formatted_content.html_safe return wiki_page.formatted_content.html_safe
end end
markup_postprocess(html, context)
end end
def render_markup(file_name, file_content) def render_markup(file_name, file_content)
html = markup_render(file_name, file_content)
markup_postprocess(html)
end
def markup_render(file_name, file_content)
if gitlab_markdown?(file_name) if gitlab_markdown?(file_name)
Hamlit::RailsHelpers.preserve(markdown(file_content)) Hamlit::RailsHelpers.preserve(markdown_render(file_content))
elsif asciidoc?(file_name) elsif asciidoc?(file_name)
asciidoc(file_content) asciidoc_render(file_content)
elsif plain?(file_name) elsif plain?(file_name)
content_tag :pre, class: 'plain-readme' do content_tag :pre, class: 'plain-readme' do
file_content file_content
end end
else else
other_markup(file_name, file_content) other_markup_render(file_name, file_content)
end end
rescue RuntimeError rescue RuntimeError
simple_format(file_content) simple_format(file_content)
......
...@@ -12,10 +12,6 @@ module TreeHelper ...@@ -12,10 +12,6 @@ module TreeHelper
tree.html_safe tree.html_safe
end end
def render_readme(readme)
render_markup(readme.name, readme.data)
end
# Return an image icon depending on the file type and mode # Return an image icon depending on the file type and mode
# #
# type - String type of the tree item; either 'folder' or 'file' # type - String type of the tree item; either 'folder' or 'file'
......
require 'securerandom' require 'securerandom'
class Repository class Repository
include MarkupHelper
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
include RepositoryMirroring include RepositoryMirroring
...@@ -17,9 +18,9 @@ class Repository ...@@ -17,9 +18,9 @@ class Repository
# same name. The cache key used by those methods must also match method's # same name. The cache key used by those methods must also match method's
# name. # name.
# #
# For example, for entry `:readme` there's a method called `readme` which # For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `readme` cache key. # stores its data in the `commit_count` cache key.
CACHED_METHODS = %i(size commit_count readme contribution_guide CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide
changelog license_blob license_key gitignore koding_yml changelog license_blob license_key gitignore koding_yml
gitlab_ci_yml branch_names tag_names branch_count gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? empty? root_ref).freeze tag_count avatar exists? empty? root_ref).freeze
...@@ -28,7 +29,7 @@ class Repository ...@@ -28,7 +29,7 @@ class Repository
# changed. This Hash maps file types (as returned by Gitlab::FileDetector) to # changed. This Hash maps file types (as returned by Gitlab::FileDetector) to
# the corresponding methods to call for refreshing caches. # the corresponding methods to call for refreshing caches.
METHOD_CACHES_FOR_FILE_TYPES = { METHOD_CACHES_FOR_FILE_TYPES = {
readme: :readme, readme: :rendered_readme,
changelog: :changelog, changelog: :changelog,
license: %i(license_blob license_key), license: %i(license_blob license_key),
contributing: :contribution_guide, contributing: :contribution_guide,
...@@ -527,7 +528,11 @@ class Repository ...@@ -527,7 +528,11 @@ class Repository
head.readme head.readme
end end
end end
cache_method :readme
def rendered_readme
markup_render(readme.name, readme.data) if readme
end
cache_method :rendered_readme
def contribution_guide def contribution_guide
file_on_head(:contributing) file_on_head(:contributing)
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
- if can?(current_user, :push_code, @project) - if can?(current_user, :push_code, @project)
= link_to icon('pencil'), namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light edit-project-readme' = link_to icon('pencil'), namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light edit-project-readme'
.file-content.wiki .file-content.wiki
= cache(readme_cache_key) do = markup_postprocess(@repository.rendered_readme)
= render_readme(readme)
- else - else
.row-content-block.second-block.center .row-content-block.second-block.center
%h3.page-title %h3.page-title
......
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
%strong %strong
= readme.name = readme.name
.file-content.wiki .file-content.wiki
= render_readme(readme) = render_markup(readme.name, readme.data)
---
title: 'Remove view fragment caching for project READMEs'
merge_request: 8838
author:
...@@ -34,8 +34,6 @@ module Gitlab ...@@ -34,8 +34,6 @@ module Gitlab
html = ::Asciidoctor.convert(input, asciidoc_opts) html = ::Asciidoctor.convert(input, asciidoc_opts)
html = Banzai.post_process(html, context)
filter = Banzai::Filter::SanitizationFilter.new(html) filter = Banzai::Filter::SanitizationFilter.new(html)
html = filter.call.to_s html = filter.call.to_s
......
...@@ -15,8 +15,6 @@ module Gitlab ...@@ -15,8 +15,6 @@ module Gitlab
html = GitHub::Markup.render(file_name, input). html = GitHub::Markup.render(file_name, input).
force_encoding(input.encoding) force_encoding(input.encoding)
html = Banzai.post_process(html, context)
filter = Banzai::Filter::SanitizationFilter.new(html) filter = Banzai::Filter::SanitizationFilter.new(html)
html = filter.call.to_s html = filter.call.to_s
......
...@@ -239,33 +239,6 @@ describe ApplicationHelper do ...@@ -239,33 +239,6 @@ describe ApplicationHelper do
end end
end end
describe 'render_markup' do
let(:content) { 'Noël' }
let(:user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
it 'preserves encoding' do
expect(content.encoding.name).to eq('UTF-8')
expect(helper.render_markup('foo.rst', content).encoding.name).to eq('UTF-8')
end
it "delegates to #markdown when file name corresponds to Markdown" do
expect(helper).to receive(:gitlab_markdown?).with('foo.md').and_return(true)
expect(helper).to receive(:markdown).and_return('NOEL')
expect(helper.render_markup('foo.md', content)).to eq('NOEL')
end
it "delegates to #asciidoc when file name corresponds to AsciiDoc" do
expect(helper).to receive(:asciidoc?).with('foo.adoc').and_return(true)
expect(helper).to receive(:asciidoc).and_return('NOEL')
expect(helper.render_markup('foo.adoc', content)).to eq('NOEL')
end
end
describe '#active_when' do describe '#active_when' do
it { expect(helper.active_when(true)).to eq('active') } it { expect(helper.active_when(true)).to eq('active') }
it { expect(helper.active_when(false)).to eq(nil) } it { expect(helper.active_when(false)).to eq(nil) }
......
...@@ -126,15 +126,16 @@ describe MarkupHelper do ...@@ -126,15 +126,16 @@ describe MarkupHelper do
it "uses Wiki pipeline for markdown files" do it "uses Wiki pipeline for markdown files" do
allow(@wiki).to receive(:format).and_return(:markdown) allow(@wiki).to receive(:format).and_return(:markdown)
expect(helper).to receive(:markdown).with('wiki content', pipeline: :wiki, project_wiki: @wiki, page_slug: "nested/page") expect(helper).to receive(:markdown_render).with('wiki content', pipeline: :wiki, project_wiki: @wiki, page_slug: "nested/page")
helper.render_wiki_content(@wiki) helper.render_wiki_content(@wiki)
end end
it "uses Asciidoctor for asciidoc files" do it "uses Asciidoctor for asciidoc files" do
allow_any_instance_of(ApplicationSetting).to receive(:current).and_return(::ApplicationSetting.create_from_defaults)
allow(@wiki).to receive(:format).and_return(:asciidoc) allow(@wiki).to receive(:format).and_return(:asciidoc)
expect(helper).to receive(:asciidoc).with('wiki content') expect(helper).to receive(:asciidoc_render).with('wiki content')
helper.render_wiki_content(@wiki) helper.render_wiki_content(@wiki)
end end
...@@ -149,6 +150,29 @@ describe MarkupHelper do ...@@ -149,6 +150,29 @@ describe MarkupHelper do
end end
end end
describe 'render_markup' do
let(:content) { 'Noël' }
it 'preserves encoding' do
expect(content.encoding.name).to eq('UTF-8')
expect(helper.render_markup('foo.rst', content).encoding.name).to eq('UTF-8')
end
it "delegates to #markdown_render when file name corresponds to Markdown" do
expect(helper).to receive(:gitlab_markdown?).with('foo.md').and_return(true)
expect(helper).to receive(:markdown_render).and_return('NOEL')
expect(helper.render_markup('foo.md', content)).to eq('NOEL')
end
it "delegates to #asciidoc_render when file name corresponds to AsciiDoc" do
expect(helper).to receive(:asciidoc?).with('foo.adoc').and_return(true)
expect(helper).to receive(:asciidoc_render).and_return('NOEL')
expect(helper.render_markup('foo.adoc', content)).to eq('NOEL')
end
end
describe '#first_line_in_markdown' do describe '#first_line_in_markdown' do
it 'truncates Markdown properly' do it 'truncates Markdown properly' do
text = "@#{user.username}, can you look at this?\nHello world\n" text = "@#{user.username}, can you look at this?\nHello world\n"
......
...@@ -1803,9 +1803,9 @@ describe Repository, models: true do ...@@ -1803,9 +1803,9 @@ describe Repository, models: true do
describe '#refresh_method_caches' do describe '#refresh_method_caches' do
it 'refreshes the caches of the given types' do it 'refreshes the caches of the given types' do
expect(repository).to receive(:expire_method_caches). expect(repository).to receive(:expire_method_caches).
with(%i(readme license_blob license_key)) with(%i(rendered_readme license_blob license_key))
expect(repository).to receive(:readme) expect(repository).to receive(:rendered_readme)
expect(repository).to receive(:license_blob) expect(repository).to receive(:license_blob)
expect(repository).to receive(:license_key) expect(repository).to receive(:license_key)
......
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