summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beckmann <king-jan1999@hotmail.de>2018-06-27 08:47:29 +0000
committerPhil Hughes <me@iamphill.com>2018-06-27 08:47:29 +0000
commit351d5f3e36c9bb3bb187d838c68ede33f6f80b14 (patch)
treee1afe970af23c6217259193774e25812d9fc99cd
parent87f7597a4fb7852fc81f830158cdfd5fdec8fac4 (diff)
downloadgitlab-ce-351d5f3e36c9bb3bb187d838c68ede33f6f80b14.tar.gz
Resolve "Copying ordered list to new comment becomes unordered"
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js15
-rw-r--r--changelogs/unreleased/40484-ordered-lists-copy-gfm.yml5
-rw-r--r--spec/javascripts/behaviors/copy_as_gfm_spec.js55
3 files changed, 74 insertions, 1 deletions
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 5c249f3068e..6b7550efff8 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -189,12 +189,25 @@ export const getParameterByName = (name, urlToParse) => {
return decodeURIComponent(results[2].replace(/\+/g, ' '));
};
+const handleSelectedRange = (range) => {
+ const container = range.commonAncestorContainer;
+ // add context to fragment if needed
+ if (container.tagName === 'OL') {
+ const parentContainer = document.createElement(container.tagName);
+ parentContainer.appendChild(range.cloneContents());
+ return parentContainer;
+ }
+ return range.cloneContents();
+};
+
export const getSelectedFragment = () => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
const documentFragment = document.createDocumentFragment();
+
for (let i = 0; i < selection.rangeCount; i += 1) {
- documentFragment.appendChild(selection.getRangeAt(i).cloneContents());
+ const range = selection.getRangeAt(i);
+ documentFragment.appendChild(handleSelectedRange(range));
}
if (documentFragment.textContent.length === 0) return null;
diff --git a/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml b/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml
new file mode 100644
index 00000000000..f4b34909ae9
--- /dev/null
+++ b/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml
@@ -0,0 +1,5 @@
+---
+title: Keep lists ordered when copying only list items
+merge_request: 18522
+author: Jan Beckmann
+type: fixed
diff --git a/spec/javascripts/behaviors/copy_as_gfm_spec.js b/spec/javascripts/behaviors/copy_as_gfm_spec.js
index efbe09a10a2..c2db81c6ce4 100644
--- a/spec/javascripts/behaviors/copy_as_gfm_spec.js
+++ b/spec/javascripts/behaviors/copy_as_gfm_spec.js
@@ -44,4 +44,59 @@ describe('CopyAsGFM', () => {
callPasteGFM();
});
});
+
+ describe('CopyAsGFM.copyGFM', () => {
+ // Stub getSelection to return a purpose-built object.
+ const stubSelection = (html, parentNode) => ({
+ getRangeAt: () => ({
+ commonAncestorContainer: { tagName: parentNode },
+ cloneContents: () => {
+ const fragment = document.createDocumentFragment();
+ const node = document.createElement('div');
+ node.innerHTML = html;
+ Array.from(node.childNodes).forEach((item) => fragment.appendChild(item));
+ return fragment;
+ },
+ }),
+ rangeCount: 1,
+ });
+
+ const clipboardData = {
+ setData() {},
+ };
+
+ const simulateCopy = () => {
+ const e = {
+ originalEvent: {
+ clipboardData,
+ },
+ preventDefault() {},
+ stopPropagation() {},
+ };
+ CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection);
+ return clipboardData;
+ };
+
+ beforeEach(() => spyOn(clipboardData, 'setData'));
+
+ describe('list handling', () => {
+ it('uses correct gfm for unordered lists', () => {
+ const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
+ spyOn(window, 'getSelection').and.returnValue(selection);
+ simulateCopy();
+
+ const expectedGFM = '- List Item1\n- List Item2';
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ });
+
+ it('uses correct gfm for ordered lists', () => {
+ const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
+ spyOn(window, 'getSelection').and.returnValue(selection);
+ simulateCopy();
+
+ const expectedGFM = '1. List Item1\n1. List Item2';
+ expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
+ });
+ });
+ });
});