diff --git a/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue b/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue index 99ba8c519489cae3a87a18e3679201614bb61e32..b7f419d58400ee232b691c531ba321449ec197e4 100644 --- a/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue +++ b/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue @@ -14,10 +14,6 @@ export default { return { toggleId: uniqueId('dropdown-toggle-btn-'), items: [ - { - text: __('Comment'), - action: () => this.insert('comment'), - }, { text: __('Code block'), action: () => this.insert('codeBlock'), diff --git a/app/assets/javascripts/content_editor/extensions/comment.js b/app/assets/javascripts/content_editor/extensions/comment.js deleted file mode 100644 index 8e247e552a39718d2260a481a8aa7752055b5a68..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/content_editor/extensions/comment.js +++ /dev/null @@ -1,49 +0,0 @@ -import { Node, textblockTypeInputRule } from '@tiptap/core'; - -export const commentInputRegex = /^<!--[\s\n]$/; - -export default Node.create({ - name: 'comment', - content: 'text*', - marks: '', - group: 'block', - code: true, - isolating: true, - defining: true, - - parseHTML() { - return [ - { - tag: 'comment', - preserveWhitespace: 'full', - getContent(element, schema) { - const node = schema.node('paragraph', {}, [ - schema.text( - element.textContent.replace(/&#x([0-9A-F]{2,4});/gi, (_, code) => - String.fromCharCode(parseInt(code, 16)), - ) || ' ', - ), - ]); - return node.content; - }, - }, - ]; - }, - - renderHTML() { - return [ - 'pre', - { class: 'gl-p-0 gl-border-0 gl-bg-transparent gl-text-gray-300' }, - ['span', { class: 'content-editor-comment' }, 0], - ]; - }, - - addInputRules() { - return [ - textblockTypeInputRule({ - find: commentInputRegex, - type: this.type, - }), - ]; - }, -}); diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js index ee1f706ec7e335df4cc25aab9e3e82caafa190a8..ebed2038f87c13aeb0dcfea06d404ae697f6fd47 100644 --- a/app/assets/javascripts/content_editor/services/create_content_editor.js +++ b/app/assets/javascripts/content_editor/services/create_content_editor.js @@ -10,7 +10,6 @@ import BulletList from '../extensions/bullet_list'; import Code from '../extensions/code'; import CodeBlockHighlight from '../extensions/code_block_highlight'; import ColorChip from '../extensions/color_chip'; -import Comment from '../extensions/comment'; import DescriptionItem from '../extensions/description_item'; import DescriptionList from '../extensions/description_list'; import Details from '../extensions/details'; @@ -112,7 +111,6 @@ export const createContentEditor = ({ BulletList, Code, ColorChip, - Comment, CodeBlockHighlight, DescriptionItem, DescriptionList, diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js index 4dbafd1632d6f781fd6dc12d9a6fbc84bd7952c6..51eff4d870875c64151a2be37df98052134e4335 100644 --- a/app/assets/javascripts/content_editor/services/markdown_serializer.js +++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js @@ -13,7 +13,6 @@ import DescriptionList from '../extensions/description_list'; import Details from '../extensions/details'; import DetailsContent from '../extensions/details_content'; import DrawioDiagram from '../extensions/drawio_diagram'; -import Comment from '../extensions/comment'; import Diagram from '../extensions/diagram'; import Emoji from '../extensions/emoji'; import Figure from '../extensions/figure'; @@ -52,7 +51,6 @@ import Text from '../extensions/text'; import Video from '../extensions/video'; import WordBreak from '../extensions/word_break'; import { - renderComment, renderCodeBlock, renderHardBreak, renderTable, @@ -134,7 +132,6 @@ const defaultSerializerConfig = { }), [BulletList.name]: preserveUnchanged(renderBulletList), [CodeBlockHighlight.name]: preserveUnchanged(renderCodeBlock), - [Comment.name]: renderComment, [Diagram.name]: preserveUnchanged(renderCodeBlock), [DrawioDiagram.name]: preserveUnchanged({ render: renderImage, diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js index b2cbc9c3fed8558506d2ed74e6434f3deb368c6e..17e650644b375425db23e5a7d7a00454393e0030 100644 --- a/app/assets/javascripts/content_editor/services/serialization_helpers.js +++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js @@ -365,13 +365,6 @@ export function renderPlayable(state, node) { renderImage(state, node); } -export function renderComment(state, node) { - state.write('<!--'); - state.write(node.textContent); - state.write('-->'); - state.closeBlock(node); -} - export function renderCodeBlock(state, node) { state.write( `\`\`\`${ diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index a7655efe7a932486480afba41d24e3b8951d617b..7f1b961e92a87f369a554dd4ab2f60a56020e825 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -48,9 +48,7 @@ def markdown_context_params end.merge( requested_path: params[:path], ref: params[:ref], - # Disable comments in markdown for IE browsers because comments in IE - # could allow script execution. - allow_comments: !browser.ie? + allow_comments: false ) end diff --git a/glfm_specification/output_example_snapshots/html.yml b/glfm_specification/output_example_snapshots/html.yml index 199512ef6e6d1e45555a44539634afd7817c4dd3..a301ab48fc0029f913fd853fe95f7f205a24495c 100644 --- a/glfm_specification/output_example_snapshots/html.yml +++ b/glfm_specification/output_example_snapshots/html.yml @@ -1908,7 +1908,7 @@ <!-- foo -->*bar* <p><em>baz</em></p> static: |- - <!-- foo -->*bar* + *bar* <p data-sourcepos="2:1-2:5" dir="auto"><em>baz</em></p> wysiwyg: |- <p dir="auto">*bar* @@ -1930,11 +1930,8 @@ bar baz --> <p>okay</p> - static: |- - <!-- Foo + static: |2- - bar - baz --> <p data-sourcepos="5:1-5:4" dir="auto">okay</p> wysiwyg: |- <p dir="auto">okay</p> @@ -1988,12 +1985,10 @@ <!-- foo --> <pre><code><!-- foo --> </code></pre> - static: |2- - <!-- foo --> - <div class="gl-relative markdown-code-block js-markdown-code"> - <pre data-sourcepos="3:5-3:16" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><!-- foo --></span></code></pre> - <copy-code></copy-code> - </div> + static: " \n<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre + data-sourcepos=\"3:5-3:16\" class=\"code highlight js-syntax-highlight language-plaintext\" + lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\"><!-- + foo --></span></code></pre>\n<copy-code></copy-code>\n</div>" wysiwyg: |- <pre dir="auto" class="content-editor-code-block undefined code highlight"><code><!-- foo --></code></pre> 04_06_00__leaf_blocks__html_blocks__036: @@ -4313,7 +4308,7 @@ <li data-sourcepos="1:1-1:5">foo</li> <li data-sourcepos="2:1-3:0">bar</li> </ul> - <!-- --> + <ul data-sourcepos="6:1-7:5" dir="auto"> <li data-sourcepos="6:1-6:5">baz</li> <li data-sourcepos="7:1-7:5">bim</li> @@ -4345,7 +4340,7 @@ <p data-sourcepos="5:5-5:7">foo</p> </li> </ul> - <!-- --> + <div class="gl-relative markdown-code-block js-markdown-code"> <pre data-sourcepos="9:5-9:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre> <copy-code></copy-code> @@ -7384,15 +7379,14 @@ <p>foo <!-- this is a comment - with hyphen --></p> static: |- - <p data-sourcepos="1:1-2:25" dir="auto">foo <!-- this is a - comment - with hyphen --></p> + <p data-sourcepos="1:1-2:25" dir="auto">foo </p> wysiwyg: |- <p dir="auto">foo </p> 06_11_00__inlines__raw_html__014: canonical: | <p>foo <!-- not a comment -- two hyphens --></p> static: |- - <p data-sourcepos="1:1-1:41" dir="auto">foo <!-- not a comment -- two hyphens --></p> + <p data-sourcepos="1:1-1:41" dir="auto">foo </p> wysiwyg: |- <p dir="auto">foo <!-- not a comment -- two hyphens --></p> 06_11_00__inlines__raw_html__015: @@ -7400,7 +7394,7 @@ <p>foo <!--> foo --></p> <p>foo <!-- foo---></p> static: |- - <p data-sourcepos="1:1-1:17" dir="auto">foo <!----> foo --></p> + <p data-sourcepos="1:1-1:17" dir="auto">foo foo --></p> <p data-sourcepos="3:1-3:16" dir="auto">foo <!-- foo---></p> wysiwyg: |- <p dir="auto">foo <!--> foo --></p> diff --git a/glfm_specification/output_spec/spec.html b/glfm_specification/output_spec/spec.html index 4ec7f6831242a38fc737d4e1481ed506ae353ea3..6ede9858af17dfef5424da1f715d01becc73c1ea 100644 --- a/glfm_specification/output_spec/spec.html +++ b/glfm_specification/output_spec/spec.html @@ -267,7 +267,7 @@ for a complete list of all examples, which are a superset of examples from:</p> <li data-sourcepos="23:1-23:88">GitLab Flavored Markdown Official Specification (the same ones from this specifiation)</li> <li data-sourcepos="24:1-25:0">GitLab Flavored Markdown Internal Extensions.</li> </ul> -<!-- BEGIN TESTS --> + <h1 data-sourcepos="27:1-27:40" dir="auto"> <a id="user-content-gitlab-official-specification-markdown" class="anchor" href="#gitlab-official-specification-markdown" aria-hidden="true"></a>GitLab Official Specification Markdown</h1> <p data-sourcepos="29:1-31:104" dir="auto">Note: This specification is a work in progress. Only some of the official GLFM extensions @@ -563,7 +563,7 @@ line.</p> <copy-code></copy-code> </div> </div> -<!-- END TESTS --> + </body> </html> diff --git a/lib/api/markdown.rb b/lib/api/markdown.rb index 5ef60ab0b9413fbc22812a4b4952eb27b3b7c9d1..08b172cd608f1008f2074a48093cc54fcb9db274 100644 --- a/lib/api/markdown.rb +++ b/lib/api/markdown.rb @@ -40,10 +40,7 @@ class Markdown < ::API::Base context[:skip_project_check] = true end - # Disable comments in markdown for IE browsers because comments in IE - # could allow script execution. - browser = Browser.new(headers['User-Agent']) - context[:allow_comments] = !browser.ie? + context[:allow_comments] = false present({ html: Banzai.render_and_post_process(params[:text], context) }, with: Entities::Markdown) end diff --git a/spec/frontend/content_editor/extensions/comment_spec.js b/spec/frontend/content_editor/extensions/comment_spec.js deleted file mode 100644 index 7d8ff28e4d7d7190b75b9f79e127797e69b144d3..0000000000000000000000000000000000000000 --- a/spec/frontend/content_editor/extensions/comment_spec.js +++ /dev/null @@ -1,30 +0,0 @@ -import Comment from '~/content_editor/extensions/comment'; -import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils'; - -describe('content_editor/extensions/comment', () => { - let tiptapEditor; - let doc; - let comment; - - beforeEach(() => { - tiptapEditor = createTestEditor({ extensions: [Comment] }); - ({ - builders: { doc, comment }, - } = createDocBuilder({ - tiptapEditor, - names: { - comment: { nodeType: Comment.name }, - }, - })); - }); - - describe('when typing the comment input rule', () => { - it('inserts a comment node', () => { - const expectedDoc = doc(comment()); - - triggerNodeInputRule({ tiptapEditor, inputRuleText: '<!-- ' }); - - expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON()); - }); - }); -}); diff --git a/spec/frontend/content_editor/services/gl_api_markdown_deserializer_spec.js b/spec/frontend/content_editor/services/gl_api_markdown_deserializer_spec.js index a9960918e624c0b2702b9c3dfd2e4898604e490f..1f7b56ef7623a5305a0e05693cc0f3489cf67108 100644 --- a/spec/frontend/content_editor/services/gl_api_markdown_deserializer_spec.js +++ b/spec/frontend/content_editor/services/gl_api_markdown_deserializer_spec.js @@ -1,6 +1,5 @@ import createMarkdownDeserializer from '~/content_editor/services/gl_api_markdown_deserializer'; import Bold from '~/content_editor/extensions/bold'; -import Comment from '~/content_editor/extensions/comment'; import { createTestEditor, createDocBuilder } from '../test_utils'; describe('content_editor/services/gl_api_markdown_deserializer', () => { @@ -8,21 +7,19 @@ describe('content_editor/services/gl_api_markdown_deserializer', () => { let doc; let p; let bold; - let comment; let tiptapEditor; beforeEach(() => { tiptapEditor = createTestEditor({ - extensions: [Bold, Comment], + extensions: [Bold], }); ({ - builders: { doc, p, bold, comment }, + builders: { doc, p, bold }, } = createDocBuilder({ tiptapEditor, names: { bold: { markType: Bold.name }, - comment: { nodeType: Comment.name }, }, })); renderMarkdown = jest.fn(); @@ -35,16 +32,16 @@ describe('content_editor/services/gl_api_markdown_deserializer', () => { beforeEach(async () => { const deserializer = createMarkdownDeserializer({ render: renderMarkdown }); - renderMarkdown.mockResolvedValueOnce(`<p><strong>${text}</strong></p><!-- some comment -->`); + renderMarkdown.mockResolvedValueOnce(`<p><strong>${text}</strong></p>`); result = await deserializer.deserialize({ - markdown: '**Bold text**\n<!-- some comment -->', + markdown: '**Bold text**', schema: tiptapEditor.schema, }); }); it('transforms HTML returned by render function to a ProseMirror document', () => { - const document = doc(p(bold(text)), comment(' some comment ')); + const document = doc(p(bold(text))); expect(result.document.toJSON()).toEqual(document.toJSON()); }); diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js index 4521822042ceb364d09de98594619c6e95095e7f..7be8114902aab4b11336a097ac6a19045040fdca 100644 --- a/spec/frontend/content_editor/services/markdown_serializer_spec.js +++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js @@ -3,7 +3,6 @@ import Bold from '~/content_editor/extensions/bold'; import BulletList from '~/content_editor/extensions/bullet_list'; import Code from '~/content_editor/extensions/code'; import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight'; -import Comment from '~/content_editor/extensions/comment'; import DescriptionItem from '~/content_editor/extensions/description_item'; import DescriptionList from '~/content_editor/extensions/description_list'; import Details from '~/content_editor/extensions/details'; @@ -56,7 +55,6 @@ const { bulletList, code, codeBlock, - comment, details, detailsContent, div, @@ -99,7 +97,6 @@ const { bulletList: { nodeType: BulletList.name }, code: { markType: Code.name }, codeBlock: { nodeType: CodeBlockHighlight.name }, - comment: { nodeType: Comment.name }, details: { nodeType: Details.name }, detailsContent: { nodeType: DetailsContent.name }, descriptionItem: { nodeType: DescriptionItem.name }, @@ -187,30 +184,6 @@ describe('markdownSerializer', () => { ); }); - it('correctly serializes a comment node', () => { - expect(serialize(paragraph('hi'), comment(' this is a\ncomment '))).toBe( - ` -hi - -<!-- this is a -comment --> - `.trim(), - ); - }); - - it('correctly renders a comment with markdown in it without adding any slashes', () => { - expect(serialize(paragraph('hi'), comment('this is a list\n- a\n- b\n- c'))).toBe( - ` -hi - -<!--this is a list -- a -- b -- c--> - `.trim(), - ); - }); - it('escapes < and > in a paragraph', () => { expect( serialize(paragraph(text("some prose: <this> and </this> looks like code, but isn't"))), diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js index 00aee32753b29bfdaa26da710ed63315e5214a42..2192f75ac7499d6bd71f9b9be96af2861cd26d54 100644 --- a/spec/frontend/content_editor/test_utils.js +++ b/spec/frontend/content_editor/test_utils.js @@ -9,7 +9,6 @@ import Bold from '~/content_editor/extensions/bold'; import BulletList from '~/content_editor/extensions/bullet_list'; import Code from '~/content_editor/extensions/code'; import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight'; -import Comment from '~/content_editor/extensions/comment'; import DescriptionItem from '~/content_editor/extensions/description_item'; import DescriptionList from '~/content_editor/extensions/description_list'; import Details from '~/content_editor/extensions/details';