From 4844016577d53e317acf779a432368d221ac92dd Mon Sep 17 00:00:00 2001 From: Volker Killesreiter Date: Thu, 18 Apr 2024 10:46:25 +0200 Subject: [PATCH] fix add in between --- .eslintignore | 2 + js/build/split_paragraph.js | 2 +- js/ckeditor5_plugins/.eslintrc | 57 +++++++++++++++++++ .../split_paragraph/src/index.js | 16 ++++-- .../ParagraphsFeaturesSplitTextTest.php | 17 +++--- 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 js/ckeditor5_plugins/.eslintrc diff --git a/.eslintignore b/.eslintignore index b04a2fd..93e907e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,3 +7,5 @@ sites/**/libraries/**/* profiles/**/libraries/**/* **/js_test_files/**/* js/build/* +js/ckeditor5_plugins/**/* +webpack.config.js diff --git a/js/build/split_paragraph.js b/js/build/split_paragraph.js index 703530d..3ccd4b3 100644 --- a/js/build/split_paragraph.js +++ b/js/build/split_paragraph.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.split_paragraph=e())}(self,(function(){return function(){var t={"ckeditor5/src/core.js":function(t,e,r){t.exports=r("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":function(t,e,r){t.exports=r("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":function(t){"use strict";t.exports=CKEditor5.dll}},e={};function r(o){var a=e[o];if(void 0!==a)return a.exports;var s=e[o]={exports:{}};return t[o](s,s.exports,r),s.exports}r.d=function(t,e){for(var o in e)r.o(e,o)&&!r.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};var o={};return function(){"use strict";r.d(o,{default:function(){return i}});var t=r("ckeditor5/src/core.js"),e=r("ckeditor5/src/ui.js");class a extends t.Command{execute(){const{model:t,sourceElement:e}=this.editor,r=Drupal.t("[Splitting in progress... ⌛]"),o=this.editor.getData();t.change((e=>{e.insertText(r,t.document.selection.getFirstPosition())}));const s=(new DOMParser).parseFromString(this.editor.getData(),"text/html").body,[i,d,n]=a.splitNode(s,r);if(!n||!i||!d)return void this.editor.setData(o);const l=e.closest(".paragraphs-subform").closest("tr.draggable"),p=l.querySelector("[data-paragraphs-split-text-type]").dataset.paragraphsSplitTextType,c=[...l.parentNode.children].filter((t=>t.querySelector(".paragraphs-actions"))).indexOf(l)+1;window._splitParagraph={data:{first:i.outerHTML,second:d.outerHTML},selector:e.dataset.drupalSelector};const u=e.closest(".field--widget-paragraphs").querySelector("input.paragraph-type-add-delta.modal");u.value=c;const h=u.getAttribute("data-drupal-selector").substr(5).replace(/-add-more-add-more-delta$/,"-"+p+"-add-more").replace(/_/g,"-");e.closest(".field--widget-paragraphs").querySelector('[data-drupal-selector^="'+h+'"]').dispatchEvent(new Event("mousedown"))}refresh(){this.isEnabled=!!this.editor.sourceElement.closest(".field--widget-paragraphs")?.querySelector("input.paragraph-type-add-delta.modal")}static splitNode(t,e){const r=t=>{if(t.nodeType===Node.TEXT_NODE){const r=t.data.indexOf(e);if(r>=0){const o=t.data.substring(0,r),a=t.data.substring(r+e.length);return[o?document.createTextNode(o):null,a?document.createTextNode(a):null,!0]}return[t,null,!1]}const o=[],a=[];let s=!1;if(t.childNodes.forEach((t=>{if(s)a.push(t);else{const[e,i,d]=r(t);s=d,e&&o.push(e),i&&a.push(i)}})),!s)return[t,null,!1];const i=t.cloneNode(),d=t.cloneNode();return o.forEach((t=>{i.appendChild(t)})),a.forEach((t=>{d.appendChild(t)})),[i.childNodes.length>0?i:null,d.childNodes.length>0?d:null,s]};return r(t)}}class s extends t.Plugin{init(){this.editor.ui.componentFactory.add("splitParagraph",(t=>{const r=this.editor.commands.get("splitParagraph"),o=new e.ButtonView(t);return o.set({label:this.editor.t("Split Paragraph"),icon:'\r\n\r\n\r\n\x3c!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --\x3e\r\n\r\n\t\r\n',tooltip:!0}),o.bind("isOn","isEnabled").to(r,"value","isEnabled"),this.listenTo(o,"execute",(()=>this.editor.execute("splitParagraph"))),o})),this.editor.commands.add("splitParagraph",new a(this.editor))}afterInit(){if(window._splitParagraph){if(console.log(this.editor.sourceElement.dataset.drupalSelector),console.log(this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/,"-[0-9]+-"))),"string"==typeof window._splitParagraph.data.second){const t=this.editor.sourceElement.closest("tr.draggable"),e=t?.previousElementSibling;e&&this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/,"-[0-9]+-"))&&setTimeout((()=>{this.editor.setData(window._splitParagraph.data.second),window._splitParagraph.data.second=null}),0)}"string"==typeof window._splitParagraph.data.first&&this.editor.sourceElement.dataset.drupalSelector===window._splitParagraph.selector&&setTimeout((()=>{this.editor.setData(window._splitParagraph.data.first),window._splitParagraph.data.first=null}),0)}}}var i={SplitParagraph:s}}(),o=o.default}()})); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.split_paragraph=e())}(self,(function(){return function(){var t={"ckeditor5/src/core.js":function(t,e,r){t.exports=r("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":function(t,e,r){t.exports=r("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":function(t){"use strict";t.exports=CKEditor5.dll}},e={};function r(o){var a=e[o];if(void 0!==a)return a.exports;var s=e[o]={exports:{}};return t[o](s,s.exports,r),s.exports}r.d=function(t,e){for(var o in e)r.o(e,o)&&!r.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};var o={};return function(){"use strict";r.d(o,{default:function(){return i}});var t=r("ckeditor5/src/core.js"),e=r("ckeditor5/src/ui.js");class a extends t.Command{execute(){const{model:t,sourceElement:e}=this.editor,r=Drupal.t("[Splitting in progress... ⌛]"),o=this.editor.getData();t.change((e=>{e.insertText(r,t.document.selection.getFirstPosition())}));const s=(new DOMParser).parseFromString(this.editor.getData(),"text/html").body,[i,n,d]=a.splitNode(s,r);if(!d||!i||!n)return void this.editor.setData(o);const l=e.closest(".paragraphs-subform").closest("tr.draggable"),p=l.querySelector("[data-paragraphs-split-text-type]").dataset.paragraphsSplitTextType,c=[...l.parentNode.children].filter((t=>t.querySelector(".paragraphs-actions"))).indexOf(l)+1;window._splitParagraph={data:{first:i.outerHTML,second:n.outerHTML},selector:e.dataset.drupalSelector};const u=e.closest(".field--widget-paragraphs").querySelector("input.paragraph-type-add-delta.modal");u.value=c;const h=u.getAttribute("data-drupal-selector").substr(5).replace(/-add-more-add-more-delta$/,"-"+p+"-add-more").replace(/_/g,"-");e.closest(".field--widget-paragraphs").querySelector('[data-drupal-selector^="'+h+'"]').dispatchEvent(new Event("mousedown"))}refresh(){this.isEnabled=!!this.editor.sourceElement.closest(".field--widget-paragraphs")?.querySelector("input.paragraph-type-add-delta.modal")}static splitNode(t,e){const r=t=>{if(t.nodeType===Node.TEXT_NODE){const r=t.data.indexOf(e);if(r>=0){const o=t.data.substring(0,r),a=t.data.substring(r+e.length);return[o?document.createTextNode(o):null,a?document.createTextNode(a):null,!0]}return[t,null,!1]}const o=[],a=[];let s=!1;if(t.childNodes.forEach((t=>{if(s)a.push(t);else{const[e,i,n]=r(t);s=n,e&&o.push(e),i&&a.push(i)}})),!s)return[t,null,!1];const i=t.cloneNode(),n=t.cloneNode();return o.forEach((t=>{i.appendChild(t)})),a.forEach((t=>{n.appendChild(t)})),[i.childNodes.length>0?i:null,n.childNodes.length>0?n:null,s]};return r(t)}}class s extends t.Plugin{init(){this.editor.ui.componentFactory.add("splitParagraph",(t=>{const r=this.editor.commands.get("splitParagraph"),o=new e.ButtonView(t);return o.set({label:this.editor.t("Split Paragraph"),icon:'\r\n\r\n\r\n\x3c!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --\x3e\r\n\r\n\t\r\n',tooltip:!0}),o.bind("isOn","isEnabled").to(r,"value","isEnabled"),this.listenTo(o,"execute",(()=>this.editor.execute("splitParagraph"))),o})),this.editor.commands.add("splitParagraph",new a(this.editor))}afterInit(){if(window._splitParagraph){if("string"==typeof window._splitParagraph.data.second){const t=this.editor.sourceElement.closest("tr.draggable");let e=t?.previousElementSibling;for(;e&&!e.matches("tr.draggable");)e=e.previousElementSibling;e&&this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/,"-[0-9]+-"))&&setTimeout((()=>{this.editor.setData(window._splitParagraph.data.second),window._splitParagraph.data.second=null}),0)}"string"==typeof window._splitParagraph.data.first&&this.editor.sourceElement.dataset.drupalSelector===window._splitParagraph.selector&&setTimeout((()=>{this.editor.setData(window._splitParagraph.data.first),window._splitParagraph.data.first=null}),0)}}}var i={SplitParagraph:s}}(),o=o.default}()})); \ No newline at end of file diff --git a/js/ckeditor5_plugins/.eslintrc b/js/ckeditor5_plugins/.eslintrc new file mode 100644 index 0000000..0cf118f --- /dev/null +++ b/js/ckeditor5_plugins/.eslintrc @@ -0,0 +1,57 @@ +{ + "extends": [ + "airbnb-base", + "plugin:prettier/recommended", + "plugin:yml/recommended" + ], + "root": true, + "env": { + "browser": true, + "es6": true, + "node": true + }, + "parserOptions": { + "ecmaVersion": 2020 + }, + "globals": { + "Drupal": true, + "drupalSettings": true, + "drupalTranslations": true, + "jQuery": true, + "_": true, + "Cookies": true, + "Backbone": true, + "Modernizr": true, + "loadjs": true, + "Shepherd": true, + "Sortable": true, + "once": true, + "CKEditor5": true, + "tabbable": true, + "slugify": true, + "bodyScrollLock" : true + }, + "rules": { + "prettier/prettier": "error", + "consistent-return": ["off"], + "no-underscore-dangle": ["off"], + "max-nested-callbacks": ["warn", 3], + "import/no-mutable-exports": ["warn"], + "no-plusplus": ["warn", { + "allowForLoopAfterthoughts": true + }], + "no-param-reassign": ["off"], + "no-prototype-builtins": ["off"], + "valid-jsdoc": ["warn", { + "prefer": { + "returns": "return", + "property": "prop" + }, + "requireReturn": false + }], + "no-unused-vars": ["warn"], + "operator-linebreak": ["error", "after", { "overrides": { "?": "ignore", ":": "ignore" } }], + "yml/indent": ["error", 2], + "max-len": ["error", { "code": 120 }] + } +} diff --git a/js/ckeditor5_plugins/split_paragraph/src/index.js b/js/ckeditor5_plugins/split_paragraph/src/index.js index 8a4c98c..6525d18 100644 --- a/js/ckeditor5_plugins/split_paragraph/src/index.js +++ b/js/ckeditor5_plugins/split_paragraph/src/index.js @@ -39,14 +39,18 @@ class SplitParagraph extends Plugin { afterInit() { // Set value of the new paragraph. if (window._splitParagraph) { - console.log(this.editor.sourceElement.dataset.drupalSelector); - console.log(this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/, '-[0-9]+-'))); if (typeof window._splitParagraph.data.second === 'string') { const paragraph = this.editor.sourceElement.closest('tr.draggable'); - // this.editor.sourceElement. - // closest('.field--widget-paragraphs').querySelector('tr'); - const previousParagraph = paragraph?.previousElementSibling; - if (previousParagraph && this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/, '-[0-9]+-'))) { + let previousParagraph = paragraph?.previousElementSibling; + + while (previousParagraph) { + if (previousParagraph.matches("tr.draggable")) break; + previousParagraph = previousParagraph.previousElementSibling; + } + + if ( + previousParagraph && + this.editor.sourceElement.dataset.drupalSelector.match(window._splitParagraph.selector.replace(/-[0-9]+-?/, '-[0-9]+-'))) { // Defer to wait until init is complete. setTimeout(() => { this.editor.setData(window._splitParagraph.data.second); diff --git a/tests/src/FunctionalJavascript/ParagraphsFeaturesSplitTextTest.php b/tests/src/FunctionalJavascript/ParagraphsFeaturesSplitTextTest.php index 1deff94..401721d 100644 --- a/tests/src/FunctionalJavascript/ParagraphsFeaturesSplitTextTest.php +++ b/tests/src/FunctionalJavascript/ParagraphsFeaturesSplitTextTest.php @@ -364,7 +364,6 @@ public function testSplitTextFeature() { $script = << { let newPosition; const selection = writer.createSelection(editor.model.document.getRoot(), 'in'); @@ -452,7 +451,6 @@ public function testSplitTextFeature() { $script = << { let newPosition; const selection = writer.createSelection(editor.model.document.getRoot(), 'in'); @@ -499,6 +497,16 @@ public function testSplitTextFeature() { $page->checkField('fields[field_paragraphs][settings_edit_form][third_party_settings][paragraphs_features][add_in_between]'); $this->assertEquals(TRUE, $session->evaluateScript("document.querySelector('.paragraphs-features__add-in-between__option').checked"), 'Checkbox should be checked.'); + // Disable auto-collapse. + $page->selectFieldOption('fields[field_paragraphs][settings_edit_form][settings][autocollapse]', 'none'); + $session->executeScript("jQuery('[name=\"fields[field_paragraphs][settings_edit_form][settings][autocollapse]\"]').trigger('change');"); + $this->assertSession()->assertWaitOnAjaxRequest(); + + // Set edit mode to open. + $page->selectFieldOption('fields[field_paragraphs][settings_edit_form][settings][edit_mode]', 'open'); + $session->executeScript("jQuery('[name=\"fields[field_paragraphs][settings_edit_form][settings][edit_mode]\"]').trigger('change');"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->submitForm([], 'Update'); $this->assertSession()->assertWaitOnAjaxRequest(); $this->submitForm([], 'Save'); @@ -520,7 +528,6 @@ public function testSplitTextFeature() { $script = << { let newPosition; const selection = writer.createSelection(editor.model.document.getRoot(), 'in'); @@ -546,10 +553,6 @@ public function testSplitTextFeature() { $driver->evaluateScript("Drupal.CKEditor5Instances.get('$ck_editor_id_1').getData();") ); - // And then original collapsed paragraph. - $this->scrollClick('css', '[name=field_paragraphs_0_edit]'); - $this->assertSession()->assertWaitOnAjaxRequest(); - $ck_editor_id_0 = $this->getCkEditorId(0); static::assertEquals( $paragraph_content_0,