ckeditor / ckeditor5

Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.
https://ckeditor.com/ckeditor-5
Other
8.71k stars 3.63k forks source link

Support for details and summary elements #8457

Open castroCrea opened 3 years ago

castroCrea commented 3 years ago

šŸ“ Provide a description of the new feature

What is the expected behavior of the proposed feature?

Someone ever try to do a details/summary element

image

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details

I tried with no success

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import Command from '@ckeditor/ckeditor5-core/src/command';

export default class DetailSummary extends Plugin {
    static get requires() {
        return [DetailSummaryEditing];
    }
}

class DetailSummaryEditing extends Plugin {
    init() {
        this._defineSchema();
        this._defineConverters();
        this.editor.commands.add(
            'insertDetailSummary',
            new InsertDetailSummaryCommand(this.editor)
        );
    }

    _defineSchema() {
        // ADDED
        const schema = this.editor.model.schema;
        schema.register('detailSummary', {
            // Behaves like a self-contained object (e.g. an image).
            isObject: true,

            // Allow in places where other blocks are allowed (e.g. directly in the root).
            allowWhere: '$block',
            allowAttributes: ['data-uuid']
        });

        schema.register('summary', {
            // Cannot be split or left by the caret.
            isLimit: true,

            allowIn: 'detailSummary',

            // Allow content which is allowed in blocks (i.e. text with attributes).
            allowContentOf: '$block'
        });

        schema.register('detailContent', {
            // Cannot be split or left by the caret.
            isLimit: true,

            allowIn: 'detailSummary',

            // Allow content which is allowed in the root (e.g. paragraphs).
            allowContentOf: '$root'
        });

        schema.addChildCheck((context, childDefinition) => {
            if (
                context.endsWith('detailSummary') &&
                childDefinition.name == 'detailSummary'
            ) {
                return false;
            }
        });
    }

    _defineConverters() {
        const conversion = this.editor.conversion;
        conversion.for('upcast').elementToElement({
            model: "detailSummary",
            view: {
                name: 'details',
                classes: 'detail_summary'
            },
        });

        conversion.for('downcast').elementToElement({
            model: 'detailSummary',
            view: {
                name: 'details',
                classes: 'detail_summary'
            }
        });

        // <summary> converters
        conversion.for('upcast').elementToElement({
            model: 'summary',
            view: {
                name: 'summary',
                classes: 'summary'
            }
        });
        conversion.for('downcast').elementToElement({
            model: 'summary',
            view: {
                name: 'h1',
                classes: 'summary'
            }
        });

        // <div> converters detailContent
        conversion.for('upcast').elementToElement({
            model: 'detailContent',
            view: {
                name: 'div',
                classes: 'detail_content'
            }
        });
        conversion.for('downcast').elementToElement({
            model: 'detailContent',
            view: {
                name: 'div',
                classes: 'detail_content'
            }
        });

    }
}

class InsertDetailSummaryCommand extends Command {
    execute(options = {}) {
        this.editor.model.change(writer => {
            this.editor.model.insertContent(createDetailSummary(writer));
        });
    }

    refresh() {
        const model = this.editor.model;
        const selection = model.document.selection;
        const allowedIn = model.schema.findAllowedParent(
            selection.getFirstPosition(),
            'detailSummary'
        );

        this.isEnabled = allowedIn !== null;
    }
}

function createDetailSummary(writer) {
    const detailSummary = writer.createElement('detailSummary');
    const summary = writer.createElement('summary');
    const detailContent = writer.createElement('detailContent');

    writer.append(summary, detailSummary);
    writer.append(detailContent, detailSummary);

    writer.appendElement('paragraph', detailContent);

    return detailSummary;
}

If you'd like to see this feature implemented, add a šŸ‘ reaction to this post.

Mgsy commented 3 years ago

Hi, thanks for the report. I confirm it as a valid feature request.

castroCrea commented 3 years ago

any news on this ?

finzzz commented 2 years ago

Hello, please implement this feature, especially for bullet list...

CKEditorBot commented 9 months ago

There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may still be relevant, so if you're interested in the solution, leave a comment or reaction under this issue.

heinrich-ulbricht commented 9 months ago

Need this in SharePoint Online, where CKEditor is used to power modern text web parts.

bonnepioche commented 5 months ago

Hi! I would love to see this feature implemented! Thx!

Witoso commented 5 months ago

+23 :+1: from #11068

sudheerb commented 1 month ago

Hi @Witoso , CKEditor 5 team, I see that details tag is working in CKEditor 5 now. But 'summary' tag still doesn't work and CKEditor 5 strips off (deletes) the summary tag within the details tag. Any idea when this will be fixed ?

Details: Input HTML:

<details class="list">
    <summary class="list">
        <h2>Click here</h2>
    </summary>
<div>
    THIS IS DIV CONTENT
</div>
</details>

gets modified by CKEditor5 to

<details class="list">
    <h2>
        Click here
    </h2>
    <div>
        THIS IS DIV CONTENT
    </div>
</details> 

Note that this is a valid HTML as reported in MDN Documentation as seen here.