xdan / jodit

Jodit - Best WYSIWYG Editor for You
https://xdsoft.net/jodit/
MIT License
1.62k stars 342 forks source link

Editor inserts plain html/xml without linebreaks "paste Insert as Text" or removes everything and only keeps text "paste -> keep" #1093

Open Orgoth opened 4 months ago

Orgoth commented 4 months ago

Jodit Version: 4.0.18

Browser: Chrome/IE/Safary/FF OS: Linux Is React App: False

Code

<ruleset name="pcsg-generated-ruleset">
  <description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/</description>
  <rule ref="Generic.Classes.DuplicateClassName"/>
  <rule ref="Generic.CodeAnalysis.EmptyStatement"/>
  <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
  <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
  <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
  <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
  <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
  <rule ref="Generic.ControlStructures.InlineControlStructure"/>
  <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
  <rule ref="Generic.Formatting.MultipleStatementAlignment"/>
</ruleset>

Expected behavior:

Auswahl_817

If the HTML/XML is copied from a page with extra styles, then these are not copied either, instead it is converted and the content is inserted as if the option "Insert only text" had been selected.

Auswahl_818

Actual behavior: https://xdsoft.net/jodit/

Keep Auswahl_819

Insert as Text Auswahl_820

This is what ckeditor created when pasting "ctrl+v"

<pre style="-webkit-text-stroke-width:0px;background-color:silver;border-radius:5px;border-width:0px;box-shadow:rgb(51, 51, 51) 0px 0px 5px;color:rgb(0, 0, 0);font-family:inherit;font-feature-settings:inherit;font-kerning:inherit;font-optical-sizing:inherit;font-size:medium;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;height:208px;letter-spacing:normal;line-height:inherit;margin:25px;orphans:2;overflow:auto;padding:20px;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;vertical-align:baseline;widows:2;width:1728px;word-spacing:0px;" data-placeholder="Type or paste your content here!">&lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ruleset</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">name</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"pcsg-generated-ruleset"</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">description</span></span>&gt;Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/&lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">/description</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.Classes.DuplicateClassName"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.EmptyStatement"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.UnconditionalIfStatement"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.UnnecessaryFinalModifier"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.UnusedFunctionParameter"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.CodeAnalysis.UselessOverridingMethod"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.ControlStructures.InlineControlStructure"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.Formatting.DisallowMultipleStatements"/</span></span>&gt;
  &lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">rule</span></span> <span style="color:red;"><span class="tagAttribute" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">ref</span></span>=<span style="color:blue;"><span class="tagValue" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">"Generic.Formatting.MultipleStatementAlignment"/</span></span>&gt;
&lt;<span style="color:purple;"><span class="tagName" style="border-width:0px;font:inherit;margin:0px;padding:0px;vertical-align:baseline;">/ruleset</span></span>&gt;</pre>
Orgoth commented 4 months ago

If I disable the pasteStore and paste the xml as text "ctrl + shift + v" only the text is getting inserted.

Auswahl_823

If I disable __insertByType within defaultPasteProcess, the HTML/XML is getting pasted more or less how I would expect it. "ctrl + shift + v"

Auswahl_824

Orgoth commented 4 months ago

This is the result, which thunderbird creates, when pasting the xml/html. "ctrl + shift + v"

<p>&lt;ruleset name="pcsg-generated-ruleset"&gt;<br>
      &nbsp; &lt;description&gt;Created with the PHP Coding Standard Generator.<a class="moz-txt-link-freetext" href="http://edorian.github.com/php-coding-standard-generator/" id="ext-element-59" target="_blank">http://edorian.github.com/php-coding-standard-generator/</a>&lt;/description&gt;<br>
      &nbsp; &lt;rule ref="Generic.Classes.DuplicateClassName"/&gt;<br>
      &nbsp; &lt;rule ref="Generic.CodeAnalysis.EmptyStatement"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.CodeAnalysis.UnconditionalIfStatement"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/&gt;<br>
      &nbsp; &lt;rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/&gt;<br>
      &nbsp; &lt;rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.ControlStructures.InlineControlStructure"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.Formatting.DisallowMultipleStatements"/&gt;<br>
      &nbsp; &lt;rule      ref="Generic.Formatting.MultipleStatementAlignment"/&gt;<br>
      &lt;/ruleset&gt;<br>    </p>
Orgoth commented 4 months ago

I have now dealt with the ClipboardEvent and I think that it can be distinguished well via the types. If Types only contains text/plain, then it should always be inserted with the specialchar treatment. I think that it would also make sense if the "beforePasteInsert" event is also passed the ClipboardEvent so that the developer has the option of evaluating it and specifying his logic.

const result = editor.e.fire('beforePasteInsert', html);
const result = editor.e.fire('beforePasteInsert', html, e);

Example:

        me.messageEditor.events.on('beforePasteInsert',function(html,e){
            let clipBoard = e.clipboardData;
            if( !clipBoard.getData('text/html') && clipBoard.getData('text/plain') ){
                html = html.replaceAll(/<br\s*\/?>/gmi,"\n");
                html = me.htmlspecialchars(html);
                html = html.replaceAll(/\n/gm,"<br>");
                html = html.replaceAll(/ /gm,"&nbsp;");
            }
            console.log(html);
            return html;
        });