Closed raymondtri closed 2 years ago
There is another machine we have here locally that is exhibiting similar issues and I will be posting more information from it tomorrow morning. The delete / recreate block fixed it for me for now, but that can really be a pain on larger sites.
These errors occur on page load:
[Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'mutations' of undefined"
found in
---> <A17Wysiwyg> at frontend/js/components/Wysiwyg.vue
<A17Locale> at frontend/js/components/LocaleField.vue
<A17BlockCustomPageContent> at frontend/js/components/blocks/customs/BlockCustom_Page_Content.vue
<A17Block> at frontend/js/components/blocks/Block.vue
<TransitionGroup>
<Draggable>
<A17Content> at frontend/js/components/Content.vue
<A17Fieldset> at frontend/js/components/Fieldset.vue
<Root>
TypeError: Cannot read property 'mutations' of undefined
at mark (quill.js?9339:7166)
at eval (quill.js?9339:7204)
at LinkedList.forEach (quill.js?9339:7048)
at eval (quill.js?9339:7203)
at NodeList.forEach (<anonymous>)
at eval (quill.js?9339:7199)
at Array.forEach (<anonymous>)
at ScrollBlot.optimize (quill.js?9339:7192)
at Scroll.optimize (quill.js?9339:4307)
at Scroll.batchEnd (quill.js?9339:4180)
This error occurs after making a change in wysiwig:
Uncaught Error: diff() called with non-document
at eval (quill.js?9339:492)
at Array.map (<anonymous>)
at Delta.map (quill.js?9339:386)
at eval (quill.js?9339:487)
at Array.map (<anonymous>)
at Delta.diff (quill.js?9339:486)
at History.record (quill.js?9339:6522)
at Emitter.eval (quill.js?9339:6481)
at Emitter.emit (quill.js?9339:8598)
at Emitter.emit (quill.js?9339:1893)
I'm now getting this problem on multiple clients installs.
It seems that some really simple html can cause this problem.
Just edit a wysiwyg field directly in your db editor and set the fields content to <em><br>def</em>
. That will cause the JS error I believe. Whereas <em>abc<br>def</em>
will work without issue.
It seems that editing in Quill allows for this kind of html to be generated, so you can easily end up with a document that has such an issue. What's so frustrating is that Twill doesn't acknowledge any problem occured, so a user can update the doc and think it was saved without issue as the normal yellow success msg appears.
This is really causing me serious grief.... Is there no solution @ifox ?
@raymondtri @arkid did you guys fix this issue? I'm currently having it with our wysiwygs
@dacastro4 no fix :(
facing the same issue
@ifox Do you know what is going on here ? I'm getting this on various installs and its a total pain as it stops twill functioning for me in the most fundamental of ways - ie changes to wysiwyg fields dont save on an update (even though twill thinks everything went ok and reports success ).
Is there a work around at least ?
Hi @arkid, what's going on is that the database column for your wysiwyg field contains non printable chars that make Quill crash on page load. It really became an issue for a single instance out of many on our side and what we ended up doing was creating a command and post-save action that was replacing offending characters from the html string in database. I will create a gist later today to share the approach here. Hope that helps, I know it can be a very annoying issue.
Ah ok understood, thanks @ifox that would be amazing! :)
Managed to reproduce, but going to leave this open until quill 2.x is released and hope it will be fixed by then.
I have (I think) implemented a fix here: https://github.com/area17/twill/pull/1680
If you want you can give this a try by applying the pr as a patch (https://github.com/area17/twill/pull/1680.patch) and run php artisan twill:build
.
@ifox or anyone else, is there a strategy on cleaning up html tags that may reside in existing documents? Is there anything I can write to run over my records and clean it up ?
Hello @adam-jones-net , we had to use "ezyang/htmlpurifier" to constantly clean in up, because our clients are pasting Word documents in Quill, so on some of our repositories we added this:
public function update($id, $fields)
{
parent::update($id, $fields);
$this->fixHtmls($id);
}
protected function fixHtmls($id)
{
$this->model
->findOrFail($id)
->blocks->each(
fn($block) => app(BlockRepository::class)->fixBlockHtmls(
$block,
),
);
}
And this is our BlockRepository
<?php
namespace App\Repositories;
use A17\Twill\Models\Block;
use App\Services\Html\Service;
class BlockRepository
{
/**
* @var \Illuminate\Contracts\Foundation\Application|mixed
*/
private $htmlService;
public function __construct()
{
$this->htmlService = app(Service::class);
}
private function fixAllHtmlItems($content)
{
if (is_string($content)) {
return $this->fixHtmlString($content);
}
if (is_array($content)) {
foreach ($content as $key => $value) {
$content[$key] = $this->fixAllHtmlItems($value);
}
}
return $content;
}
/**
* @param \A17\Twill\Models\Block $block
*/
public function fixBlockHtmls(Block $block): void
{
$block['content'] = $this->fixAllHtmlItems($block['content']);
$block->save();
}
public function fixHtml()
{
foreach (Block::all() as $block) {
$this->fixBlockHtmls($block);
}
}
private function fixHtmlString(string $content)
{
if (is_html($content)) {
return $this->htmlService->purify(
$this->removeNonPrintableChars($content),
);
}
return $content;
}
private function removeNonPrintableChars(string $string)
{
$string = str_replace(
['<br>', '<br />', '<br/>', "\n", "\r", '\n', '\r'],
'',
$string,
);
return preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
}
}
And our HTML Service
<?php
namespace App\Services\Html;
use HTMLPurifier;
use HTMLPurifier_Config;
use Gajus\Dindent\Indenter;
use Illuminate\Support\Str;
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
class Service
{
private function listWrongTags($html)
{
preg_match_all('#(<\s?\\\/.{1,5}>)#', $html, $matches);
$tags = [];
foreach ($matches[0] as $tag) {
$newTag = str_replace('<\/', '</', $tag);
$newTag = str_replace('< \/', '</', $newTag);
$tags[$tag] = $newTag;
}
return $tags;
}
private function removeBrokenHtmlTags($html)
{
foreach ($this->listWrongTags($html) as $tag => $newTag) {
$html = str_replace($tag, $newTag, $html);
}
return str_replace(['\n\r', '\r\n'], ['', ''], $html);
}
public function indent(string $html)
{
return app(Indenter::class)->indent($html);
}
public function inlineCss($html)
{
$cssInliner = new CssToInlineStyles();
$html = Str::of($html);
$css = $html->between('<style>', '</style>');
$html = $html->before('<style>') . $html->after('</style>');
$html = Str::of($cssInliner->convert($html, $css));
return $html->before($table = '<table class="email"') .
sprintf('<style>%s</style>%s', $css, $table) .
$html->after($table);
}
public function inlineCssAndIndent($html)
{
return $this->indent($this->inlineCss($html));
}
public function purify($html)
{
if (!is_html($html)) {
return $html;
}
$pure = $this->removeBrokenHtmlTags($html);
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
$config->set('HTML.SafeIframe', true);
$config->set('HTML.Trusted', true);
$config->set(
'URI.SafeIframeRegexp',
'%^(http://|https://|//)(www.youtube.com/embed/|player.vimeo.com/video/|vernissage.fondationlouisvuitton.eventmaker.io/|player.freecaster.com/|api.soundcloud.com/tracks/|w.soundcloud.com/player/)%',
);
$pure = (new HTMLPurifier($config))->purify($pure);
return $this->removeHtmlentitiedTags($html, $pure);
}
private function removeHtmlentitiedTags($html, string $newHtml)
{
foreach ($this->listWrongTags($html) as $tag => $newTag) {
$newHtml = str_replace(
[htmlentities($tag), htmlentities($newTag)],
['', ''],
$newHtml,
);
}
return $newHtml;
}
}
It does more than you probably need, like also fixing indentation, but I just pasted here the whole thing unedited.
There is a strange issue I'm running into with the Quill WYSIWYG. I believe it is related to this topic:
https://github.com/quilljs/quill/issues/2312
I wish I could provide a better bug report, but I can't figure out a replicatable set of circumstances for this. I'll be keeping an eye out for this, and I will be adding more information as it is found.
The effects of this bug are that once it affects a wysiwyg form field, that field can no longer be edited without needing to be completely deleted and recreated.