diff options
Diffstat (limited to 'app')
26 files changed, 122 insertions, 25 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index b6364318537..ad928484952 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -108,6 +108,11 @@ type: String, required: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, projectPath: { type: String, required: true, @@ -282,6 +287,7 @@ :issuable-templates="issuableTemplates" :markdown-docs-path="markdownDocsPath" :markdown-preview-path="markdownPreviewPath" + :markdown-version="markdownVersion" :project-path="projectPath" :project-namespace="projectNamespace" :show-delete-button="showDeleteButton" diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue index 5f58f671c73..97acc5ba385 100644 --- a/app/assets/javascripts/issue_show/components/fields/description.vue +++ b/app/assets/javascripts/issue_show/components/fields/description.vue @@ -20,6 +20,11 @@ type: String, required: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, canAttachFile: { type: Boolean, required: false, @@ -47,6 +52,7 @@ <markdown-field :markdown-preview-path="markdownPreviewPath" :markdown-docs-path="markdownDocsPath" + :markdown-version="markdownVersion" :can-attach-file="canAttachFile" :enable-autocomplete="enableAutocomplete" > diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index 5bfc072e3da..e509bb52f7d 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -35,6 +35,11 @@ type: String, required: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, projectPath: { type: String, required: true, @@ -97,6 +102,7 @@ :form-state="formState" :markdown-preview-path="markdownPreviewPath" :markdown-docs-path="markdownDocsPath" + :markdown-version="markdownVersion" :can-attach-file="canAttachFile" :enable-autocomplete="enableAutocomplete" /> diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 48cda28a1ae..8124ae6201f 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1251,13 +1251,15 @@ export default class Notes { var postUrl = $originalContentEl.data('postUrl'); var targetId = $originalContentEl.data('targetId'); var targetType = $originalContentEl.data('targetType'); + var markdownVersion = $originalContentEl.data('markdownVersion'); this.glForm = new GLForm($editForm.find('form'), this.enableGFM); $editForm .find('form') .attr('action', `${postUrl}?html=true`) - .attr('data-remote', 'true'); + .attr('data-remote', 'true') + .attr('data-markdown-version', markdownVersion); $editForm.find('.js-form-target-id').val(targetId); $editForm.find('.js-form-target-type').val(targetType); $editForm diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index c6a524f68cb..6612bc44e0b 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -34,6 +34,11 @@ export default { type: String, required: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, }, data() { return { @@ -344,6 +349,7 @@ Please check your network connection and try again.`; :markdown-preview-path="markdownPreviewPath" :markdown-docs-path="markdownDocsPath" :quick-actions-docs-path="quickActionsDocsPath" + :markdown-version="markdownVersion" :add-spacing-classes="false"> <textarea id="note-body" diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index d2db68df98e..6f4a0709825 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -92,6 +92,7 @@ export default { :is-editing="isEditing" :note-body="noteBody" :note-id="note.id" + :markdown-version="note.cached_markdown_version" @handleFormUpdate="handleFormUpdate" @cancelForm="formCancelHandler" /> diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index a4e3faa5d75..963e3a37b39 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -24,6 +24,11 @@ export default { required: false, default: 0, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, saveButtonTitle: { type: String, required: false, @@ -156,6 +161,7 @@ export default { <markdown-field :markdown-preview-path="markdownPreviewPath" :markdown-docs-path="markdownDocsPath" + :markdown-version="markdownVersion" :quick-actions-docs-path="quickActionsDocsPath" :add-spacing-classes="false"> <textarea diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index a8995021699..9b8713b40fb 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -43,6 +43,11 @@ export default { required: false, default: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, }, data() { return { @@ -192,6 +197,7 @@ export default { <comment-form :noteable-type="noteableType" + :markdown-version="markdownVersion" /> </div> </template> diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js index eed3a82854d..6dd4c9d66ac 100644 --- a/app/assets/javascripts/notes/index.js +++ b/app/assets/javascripts/notes/index.js @@ -15,6 +15,7 @@ document.addEventListener('DOMContentLoaded', () => { const notesDataset = document.getElementById('js-vue-notes').dataset; const parsedUserData = JSON.parse(notesDataset.currentUserData); const noteableData = JSON.parse(notesDataset.noteableData); + const { markdownVersion } = notesDataset; let currentUserData = {}; noteableData.noteableType = notesDataset.noteableType; @@ -33,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => { return { noteableData, currentUserData, + markdownVersion, notesData: JSON.parse(notesDataset.notesData), }; }, @@ -42,6 +44,7 @@ document.addEventListener('DOMContentLoaded', () => { noteableData: this.noteableData, notesData: this.notesData, userData: this.currentUserData, + markdownVersion: this.markdownVersion, }, }); }, diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/preview_markdown.js index 0e973cab4d2..0964baf8954 100644 --- a/app/assets/javascripts/preview_markdown.js +++ b/app/assets/javascripts/preview_markdown.js @@ -28,12 +28,16 @@ MarkdownPreview.prototype.ajaxCache = {}; MarkdownPreview.prototype.showPreview = function ($form) { var mdText; + var markdownVersion; + var url; var preview = $form.find('.js-md-preview'); - var url = preview.data('url'); if (preview.hasClass('md-preview-loading')) { return; } + mdText = $form.find('textarea.markdown-area').val(); + markdownVersion = $form.attr('data-markdown-version'); + url = this.versionedPreviewPath(preview.data('url'), markdownVersion); if (mdText.trim().length === 0) { preview.text(this.emptyMessage); @@ -59,6 +63,14 @@ MarkdownPreview.prototype.showPreview = function ($form) { } }; +MarkdownPreview.prototype.versionedPreviewPath = function (markdownPreviewPath, markdownVersion) { + if (typeof markdownVersion === 'undefined') { + return markdownPreviewPath; + } + + return `${markdownPreviewPath}${markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'}markdown_version=${markdownVersion}`; +}; + MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) { if (!url) { return; diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 298971a36b2..d62537021ca 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -1,5 +1,6 @@ <script> import $ from 'jquery'; + import { s__ } from '~/locale'; import Flash from '../../../flash'; import GLForm from '../../../gl_form'; import markdownHeader from './header.vue'; @@ -22,6 +23,11 @@ type: String, required: true, }, + markdownVersion: { + type: Number, + required: false, + default: 0, + }, addSpacingClasses: { type: Boolean, required: false, @@ -92,10 +98,11 @@ if (text) { this.markdownPreviewLoading = true; - this.$http.post(this.markdownPreviewPath, { text }) - .then(resp => resp.json()) - .then(data => this.renderMarkdown(data)) - .catch(() => new Flash('Error loading markdown preview')); + this.$http + .post(this.versionedPreviewPath(), { text }) + .then(resp => resp.json()) + .then(data => this.renderMarkdown(data)) + .catch(() => new Flash(s__('Error loading markdown preview'))); } else { this.renderMarkdown(); } @@ -119,6 +126,13 @@ $(this.$refs['markdown-preview']).renderGFM(); }); }, + + versionedPreviewPath() { + const { markdownPreviewPath, markdownVersion } = this; + return `${markdownPreviewPath}${ + markdownPreviewPath.indexOf('?') === -1 ? '?' : '&' + }markdown_version=${markdownVersion}`; + }, }, }; </script> diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index 7ac63c914fa..99123fcb3b0 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -14,6 +14,8 @@ module PreviewMarkdown else {} end + markdown_params[:markdown_engine] = result[:markdown_engine] + render json: { body: view_context.markdown(result[:text], markdown_params), references: { diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 353479776b8..7bbdc798ddd 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -249,6 +249,7 @@ module IssuablesHelper issuableRef: issuable.to_reference, markdownPreviewPath: preview_markdown_path(parent), markdownDocsPath: help_page_path('user/markdown'), + markdownVersion: issuable.cached_markdown_version, issuableTemplates: issuable_templates(issuable), initialTitleHtml: markdown_field(issuable, :title), initialTitleText: issuable.title, diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb index 39e7a7fd396..cbb971cf8b7 100644 --- a/app/helpers/markup_helper.rb +++ b/app/helpers/markup_helper.rb @@ -107,6 +107,7 @@ module MarkupHelper def markup(file_name, text, context = {}) context[:project] ||= @project + context[:markdown_engine] ||= :redcarpet html = context.delete(:rendered) || markup_unsafe(file_name, text, context) prepare_for_rendering(html, context) end @@ -120,7 +121,8 @@ module MarkupHelper project: @project, project_wiki: @project_wiki, page_slug: wiki_page.slug, - issuable_state_filter_enabled: true + issuable_state_filter_enabled: true, + markdown_engine: :redcarpet } html = diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 3fa2e5452c8..5404ead44f3 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -169,6 +169,7 @@ module NotesHelper registerPath: new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'), newSessionPath: new_session_path(:user, redirect_to_referer: 'yes'), markdownDocsPath: help_page_path('user/markdown'), + markdownVersion: issuable.cached_markdown_version, quickActionsDocsPath: help_page_path('user/project/quick_actions'), closePath: close_issuable_path(issuable), reopenPath: reopen_issuable_path(issuable), diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb index 9f6358cecbe..b05bf909058 100644 --- a/app/models/concerns/cache_markdown_field.rb +++ b/app/models/concerns/cache_markdown_field.rb @@ -40,6 +40,18 @@ module CacheMarkdownField end end + class MarkdownEngine + def self.from_version(version = nil) + return :common_mark if version.nil? || version == 0 + + if version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START + :redcarpet + else + :common_mark + end + end + end + def skip_project_check? false end @@ -57,7 +69,7 @@ module CacheMarkdownField # Banzai is less strict about authors, so don't always have an author key context[:author] = self.author if self.respond_to?(:author) - context[:markdown_engine] = markdown_engine + context[:markdown_engine] = MarkdownEngine.from_version(latest_cached_markdown_version) context end @@ -123,14 +135,6 @@ module CacheMarkdownField end end - def markdown_engine - if latest_cached_markdown_version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START - :redcarpet - else - :common_mark - end - end - included do cattr_reader :cached_markdown_fields do FieldData.new diff --git a/app/models/repository.rb b/app/models/repository.rb index 22a4b73b4b0..7cd600fec5b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -564,7 +564,7 @@ class Repository end def rendered_readme - MarkupHelper.markup_unsafe(readme.name, readme.data, project: project) if readme + MarkupHelper.markup_unsafe(readme.name, readme.data, project: project, markdown_engine: :redcarpet) if readme end cache_method :rendered_readme diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb index ce0c31b5806..0e1f94a9f61 100644 --- a/app/serializers/note_entity.rb +++ b/app/serializers/note_entity.rb @@ -62,6 +62,8 @@ class NoteEntity < API::Entities::Note expose :attachment, using: NoteAttachmentEntity, if: -> (note, _) { note.attachment? } + expose :cached_markdown_version + private def current_user diff --git a/app/services/preview_markdown_service.rb b/app/services/preview_markdown_service.rb index 4ee2c1796bd..6da4d9523cf 100644 --- a/app/services/preview_markdown_service.rb +++ b/app/services/preview_markdown_service.rb @@ -6,7 +6,8 @@ class PreviewMarkdownService < BaseService success( text: text, users: users, - commands: commands.join(' ') + commands: commands.join(' '), + markdown_engine: markdown_engine ) end @@ -42,4 +43,8 @@ class PreviewMarkdownService < BaseService def commands_target_id params[:quick_actions_target_id] end + + def markdown_engine + CacheMarkdownField::MarkdownEngine.from_version(params[:markdown_version].to_i) + end end diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 2c5ffd85372..1e4e9450ffa 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -1,2 +1,4 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'issue-form common-note-form js-quick-submit js-requires-input' } do |f| += form_for [@project.namespace.becomes(Namespace), @project, @issue], + html: { class: 'issue-form common-note-form js-quick-submit js-requires-input' }, + data: { markdown_version: @issue.cached_markdown_version } do |f| = render 'shared/issuable/form', f: f, issuable: @issue diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 179c1fcc684..5a59f956cb5 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -1,2 +1,4 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f| += form_for [@project.namespace.becomes(Namespace), @project, @merge_request], + html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' }, + data: { markdown_version: @merge_request.cached_markdown_version } do |f| = render 'shared/issuable/form', f: f, issuable: @merge_request diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 4cc59718715..ace094a671a 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -1,4 +1,6 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'milestone-form common-note-form js-quick-submit js-requires-input'} do |f| += form_for [@project.namespace.becomes(Namespace), @project, @milestone], + html: {class: 'milestone-form common-note-form js-quick-submit js-requires-input'}, + data: { markdown_version: @milestone.cached_markdown_version } do |f| = form_errors(@milestone) .row .col-md-6 diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index d6f758608a0..8093cc2c2d7 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -11,7 +11,9 @@ %strong= @tag.name - = form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name), html: { class: 'common-note-form release-form js-quick-submit' }) do |f| + = form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name), + html: { class: 'common-note-form release-form js-quick-submit' }, + data: { markdown_version: @release.cached_markdown_version }) do |f| = render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do = render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files hereā¦" = render 'shared/notes/hints' diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 26fe1de31fe..de692466fe5 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -1,7 +1,9 @@ - commit_message = @page.persisted? ? s_("WikiPageEdit|Update %{page_title}") : s_("WikiPageCreate|Create %{page_title}") - commit_message = commit_message % { page_title: @page.title } -= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'wiki-form common-note-form prepend-top-default js-quick-submit' } do |f| += form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, + html: { class: 'wiki-form common-note-form prepend-top-default js-quick-submit' }, + data: { markdown_version: CacheMarkdownField::CACHE_REDCARPET_VERSION } do |f| = form_errors(@page) - if @page.persisted? diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml index d4e8f30e458..f5464058bc0 100644 --- a/app/views/shared/notes/_note.html.haml +++ b/app/views/shared/notes/_note.html.haml @@ -52,7 +52,7 @@ .note-text.md = markdown_field(note, :note) = edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago') - .original-note-content.hidden{ data: { post_url: note_url(note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore } } + .original-note-content.hidden{ data: { post_url: note_url(note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore, markdown_version: note.cached_markdown_version } } #{note.note} - if note_editable = render 'shared/notes/edit', note: note diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml index 858adc8be37..5e5c050d5c3 100644 --- a/app/views/shared/snippets/_form.html.haml +++ b/app/views/shared/snippets/_form.html.haml @@ -2,7 +2,9 @@ = page_specific_javascript_tag('lib/ace.js') .snippet-form-holder - = form_for @snippet, url: url, html: { class: "snippet-form js-requires-input js-quick-submit common-note-form" } do |f| + = form_for @snippet, url: url, + html: { class: "snippet-form js-requires-input js-quick-submit common-note-form" }, + data: { markdown_version: @snippet.cached_markdown_version } do |f| = form_errors(@snippet) .form-group.row |