diff --git a/app/assets/javascripts/content_editor/extensions/image.js b/app/assets/javascripts/content_editor/extensions/image.js index 65849ec4d0d9f2dc5d219c364430c2c540073643..fc4c108b773d787077c8a9e1919fc9aa208c76d4 100644 --- a/app/assets/javascripts/content_editor/extensions/image.js +++ b/app/assets/javascripts/content_editor/extensions/image.js @@ -52,6 +52,22 @@ export default Image.extend({ return img.getAttribute('title'); }, }, + width: { + default: null, + parseHTML: (element) => { + const img = resolveImageEl(element); + + return img.getAttribute('width'); + }, + }, + height: { + default: null, + parseHTML: (element) => { + const img = resolveImageEl(element); + + return img.getAttribute('height'); + }, + }, isReference: { default: false, renderHTML: () => '', @@ -76,6 +92,8 @@ export default Image.extend({ src: HTMLAttributes.src, alt: HTMLAttributes.alt, title: HTMLAttributes.title, + width: HTMLAttributes.width, + height: HTMLAttributes.height, }, ]; }, diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js index 5ee9d66def1666899596226866a0e7c193706717..98f8ce518fe29b6c1a74f7e74c543424f7440da7 100644 --- a/app/assets/javascripts/content_editor/services/serialization_helpers.js +++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js @@ -308,7 +308,7 @@ export function renderHardBreak(state, node, parent, index) { } export function renderImage(state, node) { - const { alt, canonicalSrc, src, title, isReference } = node.attrs; + const { alt, canonicalSrc, src, title, width, height, isReference } = node.attrs; if (isString(src) || isString(canonicalSrc)) { const quotedTitle = title ? ` ${state.quote(title)}` : ''; @@ -316,7 +316,17 @@ export function renderImage(state, node) { ? `[${canonicalSrc}]` : `(${state.esc(canonicalSrc || src)}${quotedTitle})`; - state.write(`![${state.esc(alt || '')}]${sourceExpression}`); + const sizeAttributes = []; + if (width) { + sizeAttributes.push(`width=${JSON.stringify(width)}`); + } + if (height) { + sizeAttributes.push(`height=${JSON.stringify(height)}`); + } + + const attributes = sizeAttributes.length ? `{${sizeAttributes.join(' ')}}` : ''; + + state.write(`![${state.esc(alt || '')}]${sourceExpression}${attributes}`); } } diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml index e986f5309e876b8b4d6ba77d119f945139c27ab7..501d06692ea19eb6b0bb2935fdcbe15084165f1f 100644 --- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml +++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml @@ -78,3 +78,33 @@ skip_running_conformance_wysiwyg_tests: Example currently fails. See https://gitlab.com/gitlab-org/gitlab/-/issues/383866 skip_running_snapshot_wysiwyg_html_tests: Example currently fails. See https://gitlab.com/gitlab-org/gitlab/-/issues/383866 skip_running_snapshot_prosemirror_json_tests: Example currently fails. See https://gitlab.com/gitlab-org/gitlab/-/issues/383866 +08_05_00__gitlab_internal_extension_markdown__image_attributes__001: + skip_update_example_snapshot_html_wysiwyg: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_update_example_snapshot_prosemirror_json: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_conformance_wysiwyg_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_wysiwyg_html_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_prosemirror_json_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 +08_05_00__gitlab_internal_extension_markdown__image_attributes__002: + skip_update_example_snapshot_html_wysiwyg: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_update_example_snapshot_prosemirror_json: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_conformance_wysiwyg_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_wysiwyg_html_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_prosemirror_json_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 +08_05_00__gitlab_internal_extension_markdown__image_attributes__003: + skip_update_example_snapshot_html_wysiwyg: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_update_example_snapshot_prosemirror_json: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_conformance_wysiwyg_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_wysiwyg_html_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_prosemirror_json_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 +08_05_00__gitlab_internal_extension_markdown__image_attributes__004: + skip_update_example_snapshot_html_wysiwyg: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_update_example_snapshot_prosemirror_json: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_conformance_wysiwyg_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_wysiwyg_html_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_prosemirror_json_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 +08_05_00__gitlab_internal_extension_markdown__image_attributes__005: + skip_update_example_snapshot_html_wysiwyg: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_update_example_snapshot_prosemirror_json: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_conformance_wysiwyg_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_wysiwyg_html_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 + skip_running_snapshot_prosemirror_json_tests: WYSYWIG and prosemirror examples not generated correctly. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106733#note_1206201340 diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md b/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md index 4d5b16b7ec070f2882a5648dd6404739118df326..63518a93f71f5d165a8122d3adc68e0ab2ab9d21 100644 --- a/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md +++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md @@ -696,4 +696,54 @@ Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz . TODO: Write canonical HTML for this example ```````````````````````````````` + +## Image Attributes + +See +[Change the image dimensions](https://docs.gitlab.com/ee/user/markdown.html#change-the-image-dimensions) +in the GitLab Flavored Markdown documentation. + +The `width` and `height` attributes for an image can be specified directly after +the image markdown. + +General syntax conforms to the +[commonmark-hs attribute syntax](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/attributes.md) +where it makes sense. + +```````````````````````````````` example gitlab +{width="100" height="100"} +. +<p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> +```````````````````````````````` + +`%` and `px` units may also be specified. + +```````````````````````````````` example gitlab +{width="100%"} +. +<p><img src="https://gitlab.com/logo.png" width="100%"></p> +```````````````````````````````` + +```````````````````````````````` example gitlab +{height="100px"} +. +<p><img src="https://gitlab.com/logo.png" height="100px"></p> +```````````````````````````````` + +Whitespace is tolerated around the delimiters: + +```````````````````````````````` example gitlab +{ width="100" height="100" } +. +<p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> +```````````````````````````````` + +Attributes must immediately follow the image markdown. + +```````````````````````````````` example gitlab + {width="100" height="100"} +. +<p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p> +```````````````````````````````` + <!-- END TESTS --> diff --git a/glfm_specification/output_example_snapshots/examples_index.yml b/glfm_specification/output_example_snapshots/examples_index.yml index 934be77ebd56dd1b2f9695de4585741a13c5506a..d08f16c7313029fb75c2af67a8e232298bd47b56 100644 --- a/glfm_specification/output_example_snapshots/examples_index.yml +++ b/glfm_specification/output_example_snapshots/examples_index.yml @@ -2240,3 +2240,18 @@ 08_04_52__gitlab_internal_extension_markdown__migrated_golden_master_examples__word_break__001: spec_example_position: 749 source_specification: gitlab +08_05_00__gitlab_internal_extension_markdown__image_attributes__001: + spec_example_position: 750 + source_specification: gitlab +08_05_00__gitlab_internal_extension_markdown__image_attributes__002: + spec_example_position: 751 + source_specification: gitlab +08_05_00__gitlab_internal_extension_markdown__image_attributes__003: + spec_example_position: 752 + source_specification: gitlab +08_05_00__gitlab_internal_extension_markdown__image_attributes__004: + spec_example_position: 753 + source_specification: gitlab +08_05_00__gitlab_internal_extension_markdown__image_attributes__005: + spec_example_position: 754 + source_specification: gitlab diff --git a/glfm_specification/output_example_snapshots/html.yml b/glfm_specification/output_example_snapshots/html.yml index c724f670bb516bfa01068a7e472e2b8b019ccc78..06e88ce4b817716ac4aff1120e7fb8cfa93e2aab 100644 --- a/glfm_specification/output_example_snapshots/html.yml +++ b/glfm_specification/output_example_snapshots/html.yml @@ -8625,3 +8625,28 @@ <p data-sourcepos="1:1-1:60" dir="auto">Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz</wbr></wbr></wbr></wbr></p> wysiwyg: |- <p>Fernstraßenbauprivatfinanzierungsgesetz</p> +08_05_00__gitlab_internal_extension_markdown__image_attributes__001: + canonical: | + <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> + static: |- + <p data-sourcepos="1:1-1:58" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" width="100" height="100" decoding="async" class="lazy" data-src="https://gitlab.com/logo.png"></a></p> +08_05_00__gitlab_internal_extension_markdown__image_attributes__002: + canonical: | + <p><img src="https://gitlab.com/logo.png" width="100%"></p> + static: |- + <p data-sourcepos="1:1-1:46" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" width="100%" decoding="async" class="lazy" data-src="https://gitlab.com/logo.png"></a></p> +08_05_00__gitlab_internal_extension_markdown__image_attributes__003: + canonical: | + <p><img src="https://gitlab.com/logo.png" height="100px"></p> + static: |- + <p data-sourcepos="1:1-1:48" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" height="100px" decoding="async" class="lazy" data-src="https://gitlab.com/logo.png"></a></p> +08_05_00__gitlab_internal_extension_markdown__image_attributes__004: + canonical: | + <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> + static: |- + <p data-sourcepos="1:1-1:60" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" width="100" height="100" decoding="async" class="lazy" data-src="https://gitlab.com/logo.png"></a></p> +08_05_00__gitlab_internal_extension_markdown__image_attributes__005: + canonical: | + <p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p> + static: |- + <p data-sourcepos="1:1-1:59" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" decoding="async" class="lazy" data-src="https://gitlab.com/logo.png"></a> {width="100" height="100"}</p> diff --git a/glfm_specification/output_example_snapshots/markdown.yml b/glfm_specification/output_example_snapshots/markdown.yml index 29fce0bccfb3bfe318873487566730ab9210ff29..c5145803088ba4b2f3d614ba252342ccc07c08f5 100644 --- a/glfm_specification/output_example_snapshots/markdown.yml +++ b/glfm_specification/output_example_snapshots/markdown.yml @@ -2547,3 +2547,13 @@  08_04_52__gitlab_internal_extension_markdown__migrated_golden_master_examples__word_break__001: | Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz +08_05_00__gitlab_internal_extension_markdown__image_attributes__001: | + {width="100" height="100"} +08_05_00__gitlab_internal_extension_markdown__image_attributes__002: | + {width="100%"} +08_05_00__gitlab_internal_extension_markdown__image_attributes__003: | + {height="100px"} +08_05_00__gitlab_internal_extension_markdown__image_attributes__004: | + { width="100" height="100" } +08_05_00__gitlab_internal_extension_markdown__image_attributes__005: | +  {width="100" height="100"} diff --git a/glfm_specification/output_example_snapshots/prosemirror_json.yml b/glfm_specification/output_example_snapshots/prosemirror_json.yml index a654cacfca61396c59b7eda427ad735784f3dc07..db5c14dcf985cc99836b10c37f7b983c0900fd01 100644 --- a/glfm_specification/output_example_snapshots/prosemirror_json.yml +++ b/glfm_specification/output_example_snapshots/prosemirror_json.yml @@ -14577,6 +14577,8 @@ "title": "*", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": false } } @@ -15723,6 +15725,8 @@ "title": null, "uploading": false, "canonicalSrc": "moon.jpg", + "width": null, + "height": null, "isReference": false }, "marks": [ @@ -15851,6 +15855,8 @@ "title": null, "uploading": false, "canonicalSrc": "uri3", + "width": null, + "height": null, "isReference": false } } @@ -16265,6 +16271,8 @@ "title": null, "uploading": false, "canonicalSrc": "moon.jpg", + "width": null, + "height": null, "isReference": false }, "marks": [ @@ -18112,6 +18120,8 @@ "title": "title", "uploading": false, "canonicalSrc": "/url", + "width": null, + "height": null, "isReference": false } } @@ -18134,6 +18144,8 @@ "title": "train & tracks", "uploading": false, "canonicalSrc": "foo *bar*", + "width": null, + "height": null, "isReference": true } } @@ -18170,6 +18182,8 @@ "title": null, "uploading": false, "canonicalSrc": "/url2", + "width": null, + "height": null, "isReference": false } } @@ -18192,6 +18206,8 @@ "title": null, "uploading": false, "canonicalSrc": "/url2", + "width": null, + "height": null, "isReference": false } } @@ -18214,6 +18230,8 @@ "title": "train & tracks", "uploading": false, "canonicalSrc": "foo *bar*", + "width": null, + "height": null, "isReference": true } } @@ -18250,6 +18268,8 @@ "title": "train & tracks", "uploading": false, "canonicalSrc": "foobar", + "width": null, + "height": null, "isReference": true } } @@ -18286,6 +18306,8 @@ "title": null, "uploading": false, "canonicalSrc": "train.jpg", + "width": null, + "height": null, "isReference": false } } @@ -18312,6 +18334,8 @@ "title": "title", "uploading": false, "canonicalSrc": "/path/to/train.jpg", + "width": null, + "height": null, "isReference": false } } @@ -18334,6 +18358,8 @@ "title": null, "uploading": false, "canonicalSrc": "url", + "width": null, + "height": null, "isReference": false } } @@ -18356,6 +18382,8 @@ "title": null, "uploading": false, "canonicalSrc": "/url", + "width": null, + "height": null, "isReference": false } } @@ -18378,6 +18406,8 @@ "title": null, "uploading": false, "canonicalSrc": "bar", + "width": null, + "height": null, "isReference": true } } @@ -18414,6 +18444,8 @@ "title": null, "uploading": false, "canonicalSrc": "bar", + "width": null, + "height": null, "isReference": true } } @@ -18450,6 +18482,8 @@ "title": "title", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": true } } @@ -18486,6 +18520,8 @@ "title": "title", "uploading": false, "canonicalSrc": "*foo* bar", + "width": null, + "height": null, "isReference": true } } @@ -18522,6 +18558,8 @@ "title": "title", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": true } } @@ -18558,6 +18596,8 @@ "title": "title", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": true } }, @@ -18598,6 +18638,8 @@ "title": "title", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": true } } @@ -18634,6 +18676,8 @@ "title": "title", "uploading": false, "canonicalSrc": "*foo* bar", + "width": null, + "height": null, "isReference": true } } @@ -18694,6 +18738,8 @@ "title": "title", "uploading": false, "canonicalSrc": "foo", + "width": null, + "height": null, "isReference": true } } @@ -21025,6 +21071,8 @@ "title": null, "uploading": false, "canonicalSrc": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png", + "width": null, + "height": null, "isReference": false } } @@ -21047,6 +21095,8 @@ "title": null, "uploading": false, "canonicalSrc": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png", + "width": null, + "height": null, "isReference": false } } @@ -21069,6 +21119,8 @@ "title": null, "uploading": false, "canonicalSrc": "test-file.png", + "width": null, + "height": null, "isReference": false } } @@ -22751,6 +22803,8 @@ "title": null, "uploading": false, "canonicalSrc": "https://gitlab.com/logo.png", + "width": null, + "height": null, "isReference": false } } diff --git a/glfm_specification/output_example_snapshots/snapshot_spec.html b/glfm_specification/output_example_snapshots/snapshot_spec.html index 8e18c768c7d1dc8735d3aa401d1fffe5f785049a..080712d1b4ebcc832b8c0794564d6490dec69e5d 100644 --- a/glfm_specification/output_example_snapshots/snapshot_spec.html +++ b/glfm_specification/output_example_snapshots/snapshot_spec.html @@ -363,6 +363,7 @@ <li><a href="#word_break">word_break</a></li> </ul> </li> +<li><a href="#image-attributes">Image Attributes</a></li> </ul> </li> </ul> @@ -13477,6 +13478,74 @@ also requires an EE license enabling the <code>group_wikis</code> feature:</p> <copy-code></copy-code> </div> </div> +<h2 data-sourcepos="15072:1-15072:19" dir="auto"> +<a id="user-content-image-attributes" class="anchor" href="#image-attributes" aria-hidden="true"></a>Image Attributes</h2> +<p data-sourcepos="15074:1-15076:46" dir="auto">See +<a href="https://docs.gitlab.com/ee/user/markdown.html#change-the-image-dimensions" rel="nofollow noreferrer noopener" target="_blank">Change the image dimensions</a> +in the GitLab Flavored Markdown documentation.</p> +<p data-sourcepos="15078:1-15079:19" dir="auto">The <code>width</code> and <code>height</code> attributes for an image can be specified directly after +the image markdown.</p> +<p data-sourcepos="15081:1-15083:21" dir="auto">General syntax conforms to the +<a href="https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/attributes.md" rel="nofollow noreferrer noopener" target="_blank">commonmark-hs attribute syntax</a> +where it makes sense.</p> +<div> +<div><a href="#example-750">Example 750</a></div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15088:1-15090:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">{width="100" height="100"}</span></code></pre> +<copy-code></copy-code> +</div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15092:1-15094:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><p><img src="https://gitlab.com/logo.png" width="100" height="100"></p></span></code></pre> +<copy-code></copy-code> +</div> +</div> +<p data-sourcepos="15097:1-15097:41" dir="auto"><code>%</code> and <code>px</code> units may also be specified.</p> +<div> +<div><a href="#example-751">Example 751</a></div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15102:1-15104:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">{width="100%"}</span></code></pre> +<copy-code></copy-code> +</div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15106:1-15108:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><p><img src="https://gitlab.com/logo.png" width="100%"></p></span></code></pre> +<copy-code></copy-code> +</div> +</div> +<div> +<div><a href="#example-752">Example 752</a></div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15114:1-15116:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">{height="100px"}</span></code></pre> +<copy-code></copy-code> +</div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15118:1-15120:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><p><img src="https://gitlab.com/logo.png" height="100px"></p></span></code></pre> +<copy-code></copy-code> +</div> +</div> +<p data-sourcepos="15123:1-15123:46" dir="auto">Whitespace is tolerated around the delimiters:</p> +<div> +<div><a href="#example-753">Example 753</a></div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15128:1-15130:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">{ width="100" height="100" }</span></code></pre> +<copy-code></copy-code> +</div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15132:1-15134:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><p><img src="https://gitlab.com/logo.png" width="100" height="100"></p></span></code></pre> +<copy-code></copy-code> +</div> +</div> +<p data-sourcepos="15137:1-15137:54" dir="auto">Attributes must immediately follow the image markdown.</p> +<div> +<div><a href="#example-754">Example 754</a></div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15142:1-15144:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> {width="100" height="100"}</span></code></pre> +<copy-code></copy-code> +</div> +<div class="gl-relative markdown-code-block js-markdown-code"> +<pre data-sourcepos="15146:1-15148:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"><p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p></span></code></pre> +<copy-code></copy-code> +</div> +</div> </body> </html> diff --git a/glfm_specification/output_example_snapshots/snapshot_spec.md b/glfm_specification/output_example_snapshots/snapshot_spec.md index 8898857ba45ddab6d9174658dab52244e37a73c4..ccee9c1707e6a72cccb38427d7fc9762c63f5253 100644 --- a/glfm_specification/output_example_snapshots/snapshot_spec.md +++ b/glfm_specification/output_example_snapshots/snapshot_spec.md @@ -10576,3 +10576,53 @@ Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz . TODO: Write canonical HTML for this example ```````````````````````````````` + +## Image Attributes + +See +[Change the image dimensions](https://docs.gitlab.com/ee/user/markdown.html#change-the-image-dimensions) +in the GitLab Flavored Markdown documentation. + +The `width` and `height` attributes for an image can be specified directly after +the image markdown. + +General syntax conforms to the +[commonmark-hs attribute syntax](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/attributes.md) +where it makes sense. + +```````````````````````````````` example gitlab +{width="100" height="100"} +. +<p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> +```````````````````````````````` + +`%` and `px` units may also be specified. + +```````````````````````````````` example gitlab +{width="100%"} +. +<p><img src="https://gitlab.com/logo.png" width="100%"></p> +```````````````````````````````` + +```````````````````````````````` example gitlab +{height="100px"} +. +<p><img src="https://gitlab.com/logo.png" height="100px"></p> +```````````````````````````````` + +Whitespace is tolerated around the delimiters: + +```````````````````````````````` example gitlab +{ width="100" height="100" } +. +<p><img src="https://gitlab.com/logo.png" width="100" height="100"></p> +```````````````````````````````` + +Attributes must immediately follow the image markdown. + +```````````````````````````````` example gitlab + {width="100" height="100"} +. +<p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p> +```````````````````````````````` + diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js index a29678ff1bcf4a762277dec0194339199ac5cd52..90551065ee43914ca79d7d285e6ab1be9485cbd7 100644 --- a/spec/frontend/content_editor/services/markdown_serializer_spec.js +++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js @@ -380,6 +380,26 @@ this is not really json but just trying out whether this case works or not ); }); + it.each` + width | height | outputAttributes + ${300} | ${undefined} | ${'width=300'} + ${undefined} | ${300} | ${'height=300'} + ${300} | ${300} | ${'width=300 height=300'} + ${'300%'} | ${'300px'} | ${'width="300%" height="300px"'} + `( + 'correctly serializes an image with width and height attributes', + ({ width, height, outputAttributes }) => { + const imageAttrs = { src: 'img.jpg', alt: 'foo bar' }; + + if (width) imageAttrs.width = width; + if (height) imageAttrs.height = height; + + expect(serialize(paragraph(image(imageAttrs)))).toBe( + `{${outputAttributes}}`, + ); + }, + ); + it('does not serialize an image when src and canonicalSrc are empty', () => { expect(serialize(paragraph(image({})))).toBe(''); });