diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb index c606ccf4a07e7bd3306df1801d1f6a9f333c370d..f8c3e125c3beca145dcb724dd6dbbb6b4f0c23cc 100644 --- a/app/controllers/concerns/wiki_actions.rb +++ b/app/controllers/concerns/wiki_actions.rb @@ -246,7 +246,7 @@ def load_sidebar @sidebar_page = wiki.find_sidebar(params[:version_id]) unless @sidebar_page # Fallback to default sidebar - @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries + @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries(load_content: Feature.enabled?(:wiki_front_matter_title, container)) end rescue ::Gitlab::Git::CommandTimedOut => e @sidebar_error = e @@ -326,7 +326,9 @@ def send_wiki_file_blob(wiki, file_blob) end def load_content? - return false if %w[history destroy diff show].include?(params[:action]) + skip_actions = Feature.enabled?(:wiki_front_matter_title, container) ? %w[history destroy diff] : %w[history destroy diff show] + + return false if skip_actions.include?(params[:action]) true end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 2eed693ca760b105d2d30cd487762829e4e0824f..3dd8f334a68b70fe1a998df0248681b18fd5719e 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -80,6 +80,7 @@ def slug alias_method :to_param, :slug def human_title + return front_matter_title if Feature.enabled?(:wiki_front_matter_title, container) && front_matter_title.present? return 'Home' if title == Wiki::HOMEPAGE title @@ -95,6 +96,10 @@ def title=(new_title) attributes[:title] = new_title end + def front_matter_title + front_matter[:title] + end + def raw_content attributes[:content] ||= page&.text_data end @@ -320,7 +325,7 @@ def diffs(diff_options = {}) def serialize_front_matter(hash) return '' unless hash.present? - YAML.dump(hash.transform_keys(&:to_s)) + "---\n" + YAML.dump(hash.to_h.transform_keys(&:to_s)) + "---\n" end def update_front_matter(attrs) diff --git a/config/feature_flags/development/wiki_front_matter.yml b/config/feature_flags/development/wiki_front_matter.yml index 39196440d176e50657c6c5616840317bb7824444..20316142c41e5da5ab29d414ae2509d990d620de 100644 --- a/config/feature_flags/development/wiki_front_matter.yml +++ b/config/feature_flags/development/wiki_front_matter.yml @@ -1,7 +1,7 @@ --- name: wiki_front_matter introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27706 -rollout_issue_url: +rollout_issue_url: milestone: '12.10' type: development group: group::editor diff --git a/config/feature_flags/development/wiki_front_matter_title.yml b/config/feature_flags/development/wiki_front_matter_title.yml new file mode 100644 index 0000000000000000000000000000000000000000..381bb2e1154e3dfbf51788cf6c3240e3e333f3db --- /dev/null +++ b/config/feature_flags/development/wiki_front_matter_title.yml @@ -0,0 +1,8 @@ +--- +name: wiki_front_matter_title +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133521 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/428259 +milestone: '16.6' +type: development +group: group::knowledge +default_enabled: false diff --git a/ee/spec/requests/api/wikis_spec.rb b/ee/spec/requests/api/wikis_spec.rb index c44da5f53be07cfe63bc7f0b8bef088289be225b..39fd18d01ebb7b8c2de6422ed20ea8ac6fcc3811 100644 --- a/ee/spec/requests/api/wikis_spec.rb +++ b/ee/spec/requests/api/wikis_spec.rb @@ -21,7 +21,7 @@ let(:group) { create(:group, :internal, :wiki_repo) } let(:wiki) { create(:group_wiki, container: group, user: user) } let(:payload) { { content: 'content', format: 'rdoc', title: 'title' } } - let(:expected_keys_with_content) { %w[content format slug title encoding] } + let(:expected_keys_with_content) { %w[content format slug title encoding front_matter] } let(:expected_keys_without_content) { %w[format slug title] } before do diff --git a/lib/api/entities/wiki_page.rb b/lib/api/entities/wiki_page.rb index 0f3fdd586a350bfa6c60b23a1282119d567d7b66..8b2c951ecf25d5553103086233618e131d03c294 100644 --- a/lib/api/entities/wiki_page.rb +++ b/lib/api/entities/wiki_page.rb @@ -22,6 +22,10 @@ class WikiPage < WikiPageBasic expose :encoding, documentation: { type: 'string', example: 'UTF-8' } do |wiki_page| wiki_page.content.encoding.name end + + expose :front_matter, documentation: { type: 'Hash', example: { title: "deploy" } }, if: ->(wiki_page) { + ::Feature.enabled?(:wiki_front_matter_title, wiki_page.container) + } end end end diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb index 2058f5de7065302fa530578a1c78f2c36a893cd4..a7408512102078e7d1dbe00f8a8e7b47312aa2e3 100644 --- a/lib/api/wikis.rb +++ b/lib/api/wikis.rb @@ -85,6 +85,9 @@ class Wikis < ::API::Base end params do requires :title, type: String, desc: 'Title of a wiki page' + optional :front_matter, type: Hash do + optional :title, type: String, desc: 'Front matter title of a wiki page' + end requires :content, type: String, desc: 'Content of a wiki page' use :common_wiki_page_params end @@ -112,6 +115,9 @@ class Wikis < ::API::Base end params do optional :title, type: String, desc: 'Title of a wiki page' + optional :front_matter, type: Hash do + optional :title, type: String, desc: 'Front matter title of a wiki page' + end optional :content, type: String, desc: 'Content of a wiki page' use :common_wiki_page_params at_least_one_of :content, :title, :format diff --git a/spec/lib/api/entities/wiki_page_spec.rb b/spec/lib/api/entities/wiki_page_spec.rb index a3566293c5c778628d24583e72e9ef9c4cf51722..da75ade997bf536d006ae318520b36fbe1e35723 100644 --- a/spec/lib/api/entities/wiki_page_spec.rb +++ b/spec/lib/api/entities/wiki_page_spec.rb @@ -24,7 +24,7 @@ context "with front matter content" do let(:wiki_page) { create(:wiki_page) } - let(:content_with_front_matter) { "---\nxxx: abc\n---\nHome Page" } + let(:content_with_front_matter) { "---\ntitle: abc\n---\nHome Page" } before do wiki_page.update(content: content_with_front_matter) # rubocop:disable Rails/SaveBang @@ -33,6 +33,10 @@ it 'returns the raw wiki page content' do expect(subject[:content]).to eq content_with_front_matter end + + it 'return the front matter title' do + expect(subject[:front_matter]).to eq({ title: "abc" }) + end end context 'when render_html param is passed' do diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 2e1cb9d3d9b653b2483c5d652a7ca37819b2b02c..f3cf8966b9a1d38884d5578d08784412c55c6898 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -58,6 +58,7 @@ def force_wiki_change_branch let(:front_matter) { { title: 'Foo', slugs: %w[slug_a slug_b] } } it { expect(wiki_page.front_matter).to eq(front_matter) } + it { expect(wiki_page.front_matter_title).to eq(front_matter[:title]) } end context 'the wiki page has front matter' do @@ -1054,4 +1055,28 @@ def force_wiki_change_branch ) end end + + describe "#human_title" do + context "with front matter title" do + let(:front_matter_title) { "abc" } + let(:content_with_front_matter_title) { "---\ntitle: #{front_matter_title}\n---\nHome Page" } + let(:wiki_page) { create(:wiki_page, container: container, content: content_with_front_matter_title) } + + context "when wiki_front_matter_title enabled" do + it 'returns the front matter title' do + expect(wiki_page.human_title).to eq front_matter_title + end + end + + context "when wiki_front_matter_title disabled" do + before do + stub_feature_flags(wiki_front_matter_title: false) + end + + it 'returns the page title' do + expect(wiki_page.human_title).to eq wiki_page.title + end + end + end + end end diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb index 00e38a5bb7e0eaf4dfef4ac4a21e42c0423283c6..95ebe9ae5a86ea68fec1063853504a9c8f872555 100644 --- a/spec/requests/api/wikis_spec.rb +++ b/spec/requests/api/wikis_spec.rb @@ -31,7 +31,7 @@ let(:project_wiki) { create(:project_wiki, project: project, user: user) } let(:payload) { { content: 'content', format: 'rdoc', title: 'title' } } - let(:expected_keys_with_content) { %w(content format slug title encoding) } + let(:expected_keys_with_content) { %w(content format slug title encoding front_matter) } let(:expected_keys_without_content) { %w(format slug title) } let(:wiki) { project_wiki } @@ -354,6 +354,18 @@ end include_examples 'wikis API creates wiki page' + + context "with front matter title" do + let(:payload) { { title: 'title', front_matter: { "title" => "title in front matter" }, content: 'content' } } + + it "save front matter" do + post(api(url, user), params: payload) + + expect(response).to have_gitlab_http_status(:created) + expect(json_response['front_matter']).to eq(payload[:front_matter]) + expect(json_response['content']).to include(payload[:front_matter]["title"]) + end + end end context 'when user is maintainer' do @@ -478,6 +490,20 @@ include_examples 'wiki API 404 Wiki Page Not Found' end + + context "with front matter title" do + let(:payload) do + { title: 'new title', front_matter: { "title" => "title in front matter" }, content: 'new content' } + end + + it "save front matter" do + put(api(url, user), params: payload) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['front_matter']).to eq(payload[:front_matter]) + expect(json_response['content']).to include(payload[:front_matter]["title"]) + end + end end context 'when user is maintainer' do diff --git a/spec/support/shared_examples/lib/wikis_api_examples.rb b/spec/support/shared_examples/lib/wikis_api_examples.rb index c57ac328a60a52bd3b9ab59cfe12a5f62e777156..162a2b8ea49d2cbe15c1a7eb581b6017e80cda60 100644 --- a/spec/support/shared_examples/lib/wikis_api_examples.rb +++ b/spec/support/shared_examples/lib/wikis_api_examples.rb @@ -53,7 +53,7 @@ specify do expect(response).to have_gitlab_http_status(:ok) - expect(json_response.size).to eq(5) + expect(json_response.size).to eq(6) expect(json_response.keys).to match_array(expected_keys_with_content) expect(json_response['content']).to eq(expected_content) expect(json_response['slug']).to eq(page.slug) @@ -118,7 +118,7 @@ post(api(url, user), params: payload) expect(response).to have_gitlab_http_status(:created) - expect(json_response.size).to eq(5) + expect(json_response.size).to eq(6) expect(json_response.keys).to match_array(expected_keys_with_content) expect(json_response['content']).to eq(payload[:content]) expect(json_response['slug']).to eq(payload[:title].tr(' ', '-')) @@ -145,7 +145,7 @@ put(api(url, user), params: payload) expect(response).to have_gitlab_http_status(:ok) - expect(json_response.size).to eq(5) + expect(json_response.size).to eq(6) expect(json_response.keys).to match_array(expected_keys_with_content) expect(json_response['content']).to eq(payload[:content]) expect(json_response['slug']).to eq(payload[:title].tr(' ', '-'))