Skip to content

Commit

Permalink
Merge pull request #8799 from ckeditor/i/8435-empty-embed-preview
Browse files Browse the repository at this point in the history
Other (html-embed): A placeholder should be displayed if the HTML snippet is not previewable or empty. Closes #8435.
  • Loading branch information
oleq authored Jan 18, 2021
2 parents d97206c + 8e0dbc5 commit a35881b
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 21 deletions.
4 changes: 3 additions & 1 deletion packages/ckeditor5-html-embed/lang/contexts.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"HTML snippet": "The HTML snippet.",
"Paste raw HTML here...": "A placeholder that will be displayed in the raw HTML textarea field.",
"Edit source": "A label of a button that switches the HTML embed to the source editing mode.",
"Save changes": "A label of a button that saves the HTML embed content and navigates back to the preview."
"Save changes": "A label of a button that saves the HTML embed content and navigates back to the preview.",
"No preview available": "An information displayed in the HTML embed preview if the content is not previewable.",
"Empty snippet content": "An information displayed in the HTML embed preview if the HTML snippet has no content."
}
22 changes: 18 additions & 4 deletions packages/ckeditor5-html-embed/src/htmlembedediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,27 @@ export default class HtmlEmbedEditing extends Plugin {
}

function createPreviewContainer( { domDocument, state, props, editor } ) {
const domPreviewContainer = createElement( domDocument, 'div', {
class: 'raw-html-embed__preview',
const sanitizedOutput = props.sanitizeHtml( state.getRawHtmlValue() );
const placeholderText = state.getRawHtmlValue().length > 0 ?
t( 'No preview available' ) :
t( 'Empty snippet content' );

const domPreviewPlaceholder = createElement( domDocument, 'div', {
class: 'ck ck-reset_all raw-html-embed__preview-placeholder'
}, placeholderText );

const domPreviewContent = createElement( domDocument, 'div', {
class: 'raw-html-embed__preview-content',
dir: editor.locale.contentLanguageDirection
} );

const sanitizeOutput = props.sanitizeHtml( state.getRawHtmlValue() );
domPreviewContainer.innerHTML = sanitizeOutput.html;
domPreviewContent.innerHTML = sanitizedOutput.html;

const domPreviewContainer = createElement( domDocument, 'div', {
class: 'raw-html-embed__preview'
}, [
domPreviewPlaceholder, domPreviewContent
] );

return domPreviewContainer;
}
Expand Down
45 changes: 40 additions & 5 deletions packages/ckeditor5-html-embed/tests/htmlembedediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -695,16 +695,20 @@ describe( 'HtmlEmbedEditing', () => {
} );
} );

it( 'renders a div with a preview', () => {
it( 'should render a div with a preview and placeholder', () => {
setModelData( model, '<rawHtml value="foo"></rawHtml>' );
const widget = viewDocument.getRoot().getChild( 0 );
const contentWrapper = widget.getChild( 1 );
const domContentWrapper = editor.editing.view.domConverter.mapViewToDom( contentWrapper );

expect( domContentWrapper.querySelector( 'div.raw-html-embed__preview' ).innerHTML ).to.equal( 'foo' );
expect( domContentWrapper.querySelector( 'div.raw-html-embed__preview-content' ).innerHTML )
.to.equal( 'foo' );

expect( domContentWrapper.querySelector( 'div.raw-html-embed__preview-placeholder' ) )
.to.not.equal( null );
} );

it( 'updates the preview once the model changes', () => {
it( 'should update the preview once the model changes', () => {
setModelData( model, '<rawHtml value="foo"></rawHtml>' );

editor.model.change( writer => writer.setAttribute( 'value', 'bar', editor.model.document.getRoot().getChild( 0 ) ) );
Expand All @@ -713,7 +717,38 @@ describe( 'HtmlEmbedEditing', () => {
const contentWrapper = widget.getChild( 1 );
const domContentWrapper = editor.editing.view.domConverter.mapViewToDom( contentWrapper );

expect( domContentWrapper.querySelector( 'div.raw-html-embed__preview' ).innerHTML ).to.equal( 'bar' );
expect( domContentWrapper.querySelector( 'div.raw-html-embed__preview-content' ).innerHTML ).to.equal( 'bar' );
} );

describe( 'placeholder', () => {
function getPlaceholder() {
const widget = viewDocument.getRoot().getChild( 0 );
const contentWrapper = widget.getChild( 1 );
const domContentWrapper = editor.editing.view.domConverter.mapViewToDom( contentWrapper );

return domContentWrapper.querySelector( 'div.raw-html-embed__preview-placeholder' );
}

it( 'should inherit the styles from the editor', () => {
setModelData( model, '<rawHtml value=""></rawHtml>' );
const placeholder = getPlaceholder();

expect( placeholder.classList.value ).to.contain( 'ck ck-reset_all' );
} );

it( 'should display the proper information if the snippet is empty', () => {
setModelData( model, '<rawHtml value=""></rawHtml>' );
const placeholder = getPlaceholder();

expect( placeholder.innerHTML ).to.equal( 'Empty snippet content' );
} );

it( 'should display the proper information if the snippet is not empty', () => {
setModelData( model, '<rawHtml value="foo"></rawHtml>' );
const placeholder = getPlaceholder();

expect( placeholder.innerHTML ).to.equal( 'No preview available' );
} );
} );

describe( 'different setting of ui and content language', () => {
Expand Down Expand Up @@ -769,7 +804,7 @@ describe( 'HtmlEmbedEditing', () => {
const contentWrapper = widget.getChild( 1 );
const domContentWrapper = editor.editing.view.domConverter.mapViewToDom( contentWrapper );

return domContentWrapper.querySelector( 'div.raw-html-embed__preview' );
return domContentWrapper.querySelector( 'div.raw-html-embed__preview-content' );
}
} );
} );
Expand Down
8 changes: 8 additions & 0 deletions packages/ckeditor5-html-embed/tests/manual/htmlembed.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,12 @@ <h3>HTML comments in HTML snippet</h3>
<div id="aaaa">fooo</div>
<!-- end -->
</div>

<h3>Not previewable content in HTML snippet</h3>
<div class="raw-html-embed">
<!-- Example comment, should not be displayed -->
</div>

<h3>Empty HTML snippet</h3>
<div class="raw-html-embed"></div>
</div>
11 changes: 8 additions & 3 deletions packages/ckeditor5-html-embed/tests/manual/htmlembed.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@

---

After the editor initialization, it should contain 5 widgets with embedded HTML:
After the editor initialization, it should contain 8 widgets with embedded HTML:

- `video`
- `audio`
- `picture` (resize the window to see other images, limits: 1200px, 650px)
- `iframe`
- `table`
- `text with comment`
- `comment`
- `empty`

All resources are provided by the ["Sample Files for Development"](http://techslides.com/sample-files-for-development) article. Thanks!
Resources are provided by the ["Sample Files for Development"](http://techslides.com/sample-files-for-development) article. Thanks!

By default, the "previews in view" mode is enabled. It means that previews should be visible.
By default, the "previews in view" mode is enabled. It means that previews should be visible.
* If no preview is available (e.g. the only content of HTML snippet is a comment or script), the text "No preview available" should be displayed.
* If the HTML snippet is empty, the text "Empty content" should be displayed.

We use the [`sanitize-html`](https://www.npmjs.com/package/sanitize-html) package to clean up the input HTML. It means that some of the
elements or attributes may be not rendered in the editing view. However, they still will be returned in the editor's data.
Expand Down
29 changes: 29 additions & 0 deletions packages/ckeditor5-html-embed/theme/htmlembed.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,35 @@
display: flex;
flex-direction: column;
}

& .raw-html-embed__preview {
position: relative;
overflow: hidden;
display: flex;
}

& .raw-html-embed__preview-content {
width: 100%;
position: relative;
margin: auto;

/* Gives spacing to the small renderable elements, so they always cover the placeholder. */
display: table;
border-collapse: separate;
border-spacing: 7px;
}

& .raw-html-embed__preview-placeholder {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;

display: flex;
align-items: center;
justify-content: center;
}
}

.ck-content .raw-html-embed {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,27 @@

/* The preview data container. */
& .raw-html-embed__preview {
overflow: hidden;
box-sizing: border-box;
width: var(--ck-html-embed-content-width);
min-height: var(--ck-html-embed-content-min-height);
width: var(--ck-html-embed-content-width);

/* Disable all mouse interaction as long as the editor is not read–only. */
@nest .ck-editor__editable:not(.ck-read-only) & {
pointer-events: none;
}
}

& .raw-html-embed__preview-content {
box-sizing: border-box;
text-align: center;
background-color: var(--ck-color-base-foreground);

& > table {
& > * {
margin-left: auto;
margin-right: auto;
}
}

/* Disable all mouse interaction as long as the editor is not read–only. */
@nest .ck-editor__editable:not(.ck-read-only) & {
pointer-events: none;
}
& .raw-html-embed__preview-placeholder {
color: var(--ck-html-embed-source-disabled-color)
}
}

0 comments on commit a35881b

Please sign in to comment.