` as placeholder for legacy
+ placeholder: stripTags(i18nRegistry.translate(placeholder))
+ };
+ });
+
return config;
};
diff --git a/packages/neos-ui-ckeditor5-bindings/src/placeholder.vanilla-css b/packages/neos-ui-ckeditor5-bindings/src/placeholder.vanilla-css
new file mode 100644
index 0000000000..7249952164
--- /dev/null
+++ b/packages/neos-ui-ckeditor5-bindings/src/placeholder.vanilla-css
@@ -0,0 +1,8 @@
+.ck.ck-placeholder:before, .ck .ck-placeholder:before {
+ content: attr(data-placeholder);
+
+ /* See ckeditor/ckeditor5#469. */
+ pointer-events: none;
+
+ color: #999;
+}
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.js
deleted file mode 100644
index fd73888a19..0000000000
--- a/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-import {stripTags} from '@neos-project/utils-helpers';
-import styles from './neosPlaceholder.vanilla-css'; // eslint-disable-line no-unused-vars
-
-// If the data is "empty" (BR, P) or the placeholder then return an empty string.
-// Otherwise return the original data
-const htmlIsEmptyish = data => {
- if (!data) {
- return true;
- }
-
- if (data.length > 50) {
- return false;
- }
- const value = data.replace(/[\n|\t|\u200b]*/g, '').toLowerCase().trim();
- const a = (
- !value ||
- value === ' ' ||
- value === '' ||
- value === '' ||
- value === '
' ||
- value === '
' ||
- value === '
' ||
- value === ' ' ||
- value === ' ' ||
- value === ' ' ||
- value.match(/^<([a-z0-9]+)> <\/\1>$/)
- );
- return a;
-};
-
-export default class NeosPlaceholder extends Plugin {
- static get pluginName() {
- return 'NeosPlaceholder';
- }
-
- getPlaceholder() {
- return stripTags(this.editor.config.get('neosPlaceholder'));
- }
-
- addPlaceholder() {
- this.editor.editing.view.change(writer => {
- writer.setAttribute('data-neos-placeholder', this.getPlaceholder(), this.editor.editing.view.document.getRoot());
- });
- }
-
- removePlaceholder() {
- this.editor.editing.view.change(writer => {
- writer.removeAttribute('data-neos-placeholder', this.editor.editing.view.document.getRoot());
- });
- }
-
- updatePlaceholder() {
- if (htmlIsEmptyish(this.editor.getData({trim: 'none'})) && !this.editor.ui.focusTracker.isFocused) {
- this.addPlaceholder();
- } else {
- this.removePlaceholder();
- }
- }
-
- init() {
- if (this.editor.config.get('neosPlaceholder')) {
- this.updatePlaceholder();
-
- const model = this.editor.data.model;
-
- model.on('applyOperation', () => {
- this.updatePlaceholder();
- return true;
- });
- this.editor.ui.focusTracker.on('change:isFocused', () => {
- this.updatePlaceholder();
- });
- }
- }
-}
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.vanilla-css b/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.vanilla-css
deleted file mode 100644
index a70a2b13ef..0000000000
--- a/packages/neos-ui-ckeditor5-bindings/src/plugins/neosPlaceholder.vanilla-css
+++ /dev/null
@@ -1,5 +0,0 @@
-[data-neos-placeholder]:before {
- color: #999;
- content: attr(data-neos-placeholder);
- cursor: text;
-}
diff --git a/packages/neos-ui-ckeditor5-bindings/tests/manual/index.html b/packages/neos-ui-ckeditor5-bindings/tests/manual/index.html
index 2f9831bb83..1f2bf8b006 100644
--- a/packages/neos-ui-ckeditor5-bindings/tests/manual/index.html
+++ b/packages/neos-ui-ckeditor5-bindings/tests/manual/index.html
@@ -3,6 +3,7 @@
+
CKEditor Manual Test
From 1234d9a0dc07239f66d833b1c6cd5d8329fd535d Mon Sep 17 00:00:00 2001
From: mhsdesign <85400359+mhsdesign@users.noreply.github.com>
Date: Mon, 3 Jul 2023 12:32:40 +0200
Subject: [PATCH 3/4] BUGFIX: ckeditor `editor.getData` contains
``
---
.../src/cleanupContentBeforeCommit.js | 23 +-----------
.../src/cleanupContentBeforeCommit.spec.js | 26 -------------
.../src/plugins/inlineMode.js | 37 ++++++++++++++++++-
.../src/plugins/inlineMode.spec.js | 31 ++++++++++++++++
4 files changed, 68 insertions(+), 49 deletions(-)
create mode 100644 packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js
diff --git a/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.js b/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.js
index 4efa9cb2f6..a9b6d0c3f7 100644
--- a/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.js
+++ b/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.js
@@ -1,28 +1,9 @@
-// We remove opening and closing span tags that are produced by the inlineMode plugin
+
+// TODO: remove when this is fixed: https://github.com/ckeditor/ckeditor5/issues/401
/** @param {String} content */
export const cleanupContentBeforeCommit = content => {
- // TODO: remove when this is fixed: https://github.com/ckeditor/ckeditor5/issues/401
if (content.match(/^<([a-z][a-z0-9]*)\b[^>]*> <\/\1>$/)) {
return '';
}
-
- if (content.includes('')) {
- let contentWithoutOuterInlineWrapper = content;
-
- if (content.startsWith('') && content.endsWith('')) {
- contentWithoutOuterInlineWrapper = content
- .replace(/^/, '')
- .replace(/<\/neos-inline-wrapper>$/, '');
- }
-
- if (contentWithoutOuterInlineWrapper.includes('')) {
- // in the case, multiple root paragraph elements were inserted into the ckeditor (wich is currently not prevented if the html is modified from outside)
- // we have multiple root elements of type . We will convert all of them into spans.
- return content
- .replace(//g, '')
- .replace(/<\/neos-inline-wrapper>/g, '');
- }
- return contentWithoutOuterInlineWrapper;
- }
return content;
};
diff --git a/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.spec.js b/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.spec.js
index 08ab6aad9e..8fcc51b1d0 100644
--- a/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.spec.js
+++ b/packages/neos-ui-ckeditor5-bindings/src/cleanupContentBeforeCommit.spec.js
@@ -8,29 +8,3 @@ test('remove empty nbsp', () => {
assertCleanedUpContent('
', '');
assertCleanedUpContent('', '');
})
-
-describe('ckeditor inline mode hack, cleanup ', () => {
- test('noop', () => {
- assertCleanedUpContent('', '');
-
- assertCleanedUpContent('', '');
- })
-
- test('cleanup single ', () => {
- assertCleanedUpContent('', '');
- assertCleanedUpContent('foo', 'foo');
-
- assertCleanedUpContent('foo', 'foo');
- })
-
- test('cleanup multiple ', () => {
- assertCleanedUpContent('foobar', 'foobar');
-
- assertCleanedUpContent('foobar', 'foobar');
- })
-
- test('cleanup after other root', () => {
- // in the case you had multiple paragraphs and a headline and switched to autoparagrahp: false
- assertCleanedUpContent('
foo
bar', '
foo
bar');
- })
-})
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
index 54540cb393..096b9afb7e 100644
--- a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
+++ b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
@@ -14,8 +14,7 @@ export default class InlineMode extends Plugin {
// we map paragraph model into plain element in edit mode
editor.conversion.for('editingDowncast').elementToElement({model: 'paragraph', view: 'span', converterPriority: 'high'});
- // to avoid having a wrapping "span" tag, we will convert the outmost 'paragraph' and strip the custom tag 'neos-inline-wrapper'
- // in a hacky cleanup in cleanupContentBeforeCommit
+ // to avoid having a wrapping "span" tag, we will convert the outmost 'paragraph' ...
// see https://neos-project.slack.com/archives/C07QEQ1U2/p1687952441254759 - i could find a better solution
editor.conversion.for('dataDowncast').elementToElement({model: 'paragraph', view: ( modelElement, viewWriter ) => {
const parentIsRoot = modelElement.parent.is('$root');
@@ -26,6 +25,12 @@ export default class InlineMode extends Plugin {
return viewWriter.createContainerElement('neos-inline-wrapper');
}, converterPriority: 'high'});
+ // ... and strip the custom tag 'neos-inline-wrapper' in a hacky cleanup in cleanupData
+ editor.data.decorate('get');
+ editor.data.on('get', (event) => {
+ event.return = cleanupNeosInlineWrapper(event.return)
+ });
+
// we redefine enter key to create soft breaks ( ) instead of new paragraphs
editor.editing.view.document.on('enter', (evt, data) => {
editor.execute('shiftEnter');
@@ -35,3 +40,31 @@ export default class InlineMode extends Plugin {
}, {priority: 'high'});
}
}
+
+/**
+ * We remove opening and closing span tags that are produced by the inlineMode plugin
+ *
+ * @private only exported for testing
+ * @param {String} content
+ */
+export const cleanupNeosInlineWrapper = content => {
+ if (content.includes('')) {
+ let contentWithoutOuterInlineWrapper = content;
+
+ if (content.startsWith('') && content.endsWith('')) {
+ contentWithoutOuterInlineWrapper = content
+ .replace(/^/, '')
+ .replace(/<\/neos-inline-wrapper>$/, '');
+ }
+
+ if (contentWithoutOuterInlineWrapper.includes('')) {
+ // in the case, multiple root paragraph elements were inserted into the ckeditor (wich is currently not prevented if the html is modified from outside)
+ // we have multiple root elements of type . We will convert all of them into spans.
+ return content
+ .replace(//g, '')
+ .replace(/<\/neos-inline-wrapper>/g, '');
+ }
+ return contentWithoutOuterInlineWrapper;
+ }
+ return content;
+};
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js
new file mode 100644
index 0000000000..f48739226c
--- /dev/null
+++ b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js
@@ -0,0 +1,31 @@
+import {cleanupNeosInlineWrapper} from './inlineMode'
+
+const assertCleanedUpContent = (input, expected) => {
+ expect(cleanupNeosInlineWrapper(input)).toBe(expected);
+}
+
+describe('ckeditor inline mode hack, cleanup ', () => {
+ test('noop', () => {
+ assertCleanedUpContent('', '');
+
+ assertCleanedUpContent('', '');
+ })
+
+ test('cleanup single ', () => {
+ assertCleanedUpContent('', '');
+ assertCleanedUpContent('foo', 'foo');
+
+ assertCleanedUpContent('foo', 'foo');
+ })
+
+ test('cleanup multiple ', () => {
+ assertCleanedUpContent('foobar', 'foobar');
+
+ assertCleanedUpContent('foobar', 'foobar');
+ })
+
+ test('cleanup after other root', () => {
+ // in the case you had multiple paragraphs and a headline and switched to autoparagrahp: false
+ assertCleanedUpContent('
` as placeholder for legacy
- placeholder: stripTags(i18nRegistry.translate(placeholder))
- };
- });
-
return config;
};
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.js
new file mode 100644
index 0000000000..24498ce2d1
--- /dev/null
+++ b/packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.js
@@ -0,0 +1,27 @@
+/**
+ * We remove opening and closing span tags that are produced by the inlineMode plugin
+ *
+ * @private only exported for testing
+ * @param {String} content
+ */
+export const cleanupNeosInlineWrapper = content => {
+ if (content.includes('')) {
+ let contentWithoutOuterInlineWrapper = content;
+
+ if (content.startsWith('') && content.endsWith('')) {
+ contentWithoutOuterInlineWrapper = content
+ .replace(/^/, '')
+ .replace(/<\/neos-inline-wrapper>$/, '');
+ }
+
+ if (contentWithoutOuterInlineWrapper.includes('')) {
+ // in the case, multiple root paragraph elements were inserted into the ckeditor (wich is currently not prevented if the html is modified from outside)
+ // we have multiple root elements of type . We will convert all of them into spans.
+ return content
+ .replace(//g, '')
+ .replace(/<\/neos-inline-wrapper>/g, '');
+ }
+ return contentWithoutOuterInlineWrapper;
+ }
+ return content;
+};
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.spec.js
similarity index 95%
rename from packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js
rename to packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.spec.js
index f48739226c..4aa01d60c0 100644
--- a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.spec.js
+++ b/packages/neos-ui-ckeditor5-bindings/src/plugins/cleanupNeosInlineWrapper.spec.js
@@ -1,4 +1,4 @@
-import {cleanupNeosInlineWrapper} from './inlineMode'
+import {cleanupNeosInlineWrapper} from './cleanupNeosInlineWrapper';
const assertCleanedUpContent = (input, expected) => {
expect(cleanupNeosInlineWrapper(input)).toBe(expected);
diff --git a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
index 096b9afb7e..17b749d0d5 100644
--- a/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
+++ b/packages/neos-ui-ckeditor5-bindings/src/plugins/inlineMode.js
@@ -1,4 +1,5 @@
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import {cleanupNeosInlineWrapper} from './cleanupNeosInlineWrapper';
/**
* HACK, since there is yet no native support
@@ -40,31 +41,3 @@ export default class InlineMode extends Plugin {
}, {priority: 'high'});
}
}
-
-/**
- * We remove opening and closing span tags that are produced by the inlineMode plugin
- *
- * @private only exported for testing
- * @param {String} content
- */
-export const cleanupNeosInlineWrapper = content => {
- if (content.includes('')) {
- let contentWithoutOuterInlineWrapper = content;
-
- if (content.startsWith('') && content.endsWith('')) {
- contentWithoutOuterInlineWrapper = content
- .replace(/^/, '')
- .replace(/<\/neos-inline-wrapper>$/, '');
- }
-
- if (contentWithoutOuterInlineWrapper.includes('')) {
- // in the case, multiple root paragraph elements were inserted into the ckeditor (wich is currently not prevented if the html is modified from outside)
- // we have multiple root elements of type . We will convert all of them into spans.
- return content
- .replace(//g, '')
- .replace(/<\/neos-inline-wrapper>/g, '');
- }
- return contentWithoutOuterInlineWrapper;
- }
- return content;
-};