Replace Gutenberg with GrapesJS for pages

I simply can not use Gutenberg without having it choking in its own
over-engineered architecture: using it inside a form, submits it when
clicking the button to change a paragraph’s text size; and using the
custom text size in pixels causes the paragraph component to fail.

The issue with paragraph’s custom text size is that block-editor’s
typography hook expects the font size to be a string, such as '12px' or
'1em', to call startsWith on it, but the paragraph sets an integer,
always assuming that the units are pixels.  Integers do not have a
startsWith method.

Looking at the Gutenberg distributed with the current version of
WordPress, 6.3, seems that now paragraph has a selector for the units,
therefore never sets just the integer.  That made me think that the
components used by the Isolated Block Editor are “mismatched”: maybe in
a previous version of block-editor it was always passed as an integer
too?

I downloaded the source code of the Isolated Block Editor and tried to
update @wordpress/block-library from version 8.14.0 to the current
version, 8.16.0, but fails with an error saying that 'core/paragraph' is
not registered, when, as far as i could check, it was.  Seems that
something changed in @wordpress/blocks between version 12.14.0 and
12.16.0, so i tried to upgrade that module as well; it did not work
because @wordpress/data was not updated —do not remember the actual
error message—.  Upgrading to @wordpress/data from 9.7.0 to 9.9.0 made
the registration of the 'isolated/editor' subregistry to be apparently
ignored, because the posterior select('isolated/editor') within a
withSelect hook returns undefined.

At this point, i gave up: it is obvious that the people that shit
JavaScript for Gutenberg do not care for semantic versioning, and there
are a lot of moving parts to fix just to be able to use a simple
paragraph block!

It seems, however, that there are not many open-source, block-based
_layout_ editors out there: mainly GrapesJS and Craft.JS.  Craft.JS,
however, has no way to output HTML[0], requiring hacks such as using
React to generate the HTML and then pasted that shit onto the page;
totally useless for me.

I am not a fan of GrapesJS either: it seems that the “text block” is
a content-editable div, and semantic HTML can go fuck itself,
apparently.  Typical webshit mentality. By strapping another huge
dependency like CKEditor, but only up to the already out-of-support
version 4, i can write headers, paragraphs and list.  That’s
something, i guess.

[0]: https://github.com/prevwong/craft.js/issues/42

Part of #33.
This commit is contained in:
jordi fita mas 2023-08-11 02:38:49 +02:00
parent c0f532df4e
commit c010b1adba
8 changed files with 51 additions and 13 deletions

View File

@ -53,6 +53,9 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
"CSRFInput": func() template.HTML {
return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s">`, auth.CSRFTokenField, user.CSRFToken))
},
"raw": func(s string) template.HTML {
return template.HTML(s)
},
})
if _, err := t.ParseFiles(templateFile(layout), templateFile("form.gohtml"), templateFile(filename)); err != nil {
panic(err)

View File

@ -75,17 +75,39 @@ ready(function () {
ready(function () {
const textareas = document.querySelectorAll('textarea.html');
for (const textarea of textareas) {
wp.attachEditor(textarea, {
iso: {
sidebar: {
inspector: true,
inserter: true,
},
toolbar: {
inspector: true,
navigation: true,
const canvas = document.createElement('div');
textarea.parentNode.insertBefore(canvas, textarea.nextSibling);
textarea.style.display = 'none';
const textareaStorage = (editor) => {
editor.Storage.add('textarea', {
load() {
editor.setComponents(textarea.value);
},
store(data) {
const component = editor.Pages.getSelected().getMainComponent();
textarea.value = component.getInnerHTML();
},
});
}
const editor = grapesjs.init({
container: canvas,
height: '500px',
width: 'auto',
plugins: [
textareaStorage,
'gjs-blocks-basic',
'grapesjs-plugin-ckeditor',
'grapesjs-preset-webpage',
],
storageManager: {
type: 'textarea',
autosave: true,
autoload: true,
stepsBeforeSave: 1,
},
});
}
})

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
/*! grapesjs-plugin-ckeditor - 1.0.1 */
!function(e,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports["grapesjs-plugin-ckeditor"]=t():e["grapesjs-plugin-ckeditor"]=t()}('undefined'!=typeof globalThis?globalThis:'undefined'!=typeof window?window:this,(()=>(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})}},t={};e.r(t),e.d(t,{default:()=>i});var n=void 0&&(void 0).__assign||function(){return n=Object.assign||function(e){for(var t,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e},n.apply(this,arguments)},o=function(e,t){[].forEach.call(e,t)},r=function(e){return e.stopPropagation()};const i=function(e,t){void 0===t&&(t={});var i,a,c,l=n({options:{},customRte:{},position:'left',ckeditor:'https://cdn.ckeditor.com/4.21.0/standard-all/ckeditor.js',onToolbar:function(){}},t),u=l.ckeditor,s='undefined'!=typeof window,d=!1;u?'string'==typeof u?s&&(d=!0,(a=u,(c=document.createElement('script')).src=a,document.head.appendChild(c),c).onload=function(){i=window.CKEDITOR}):u.inline&&(i=u):s&&(i=window.CKEDITOR);var f=function(){return setTimeout((function(){return e.refresh()}),0)},p=function(){e.log('CKEDITOR instance not found',{level:'error'})};if(!i&&!d)return p();var g=function(e,t){var n;(null===(n=null==t?void 0:t.focusManager)||void 0===n?void 0:n.hasFocus)||(e.contentEditable='true',null==t||t.focus(),f())};e.setCustomRte(n({getContent:function(e,t){return t.getData()},enable:function(t,a){if(a&&'destroyed'!=a.status)return g(t,a),a;if(i){var c=e.RichTextEditor.getToolbarEl();o(c.children,(function(e){e.style.display='none'}));var u=n({},l.options),s='sharedspace';return u.extraPlugins?'string'==typeof u.extraPlugins?u.extraPlugins+=",".concat(s):Array.isArray(u.extraPlugins)&&u.extraPlugins.push(s):u.extraPlugins=s,u.sharedSpaces||(u.sharedSpaces={top:c}),(a=i.inline(t,u)).on('contentDom',(function(){var e=a.editable();e.attachListener(e,'click',(function(){return t.click()}))})),a.on('instanceReady',(function(){var t=c.querySelector("#cke_".concat(a.name));t&&(t.style.display='block',l.onToolbar(t)),e.refresh(),f()})),a.on('dialogShow',(function(){var e=document.querySelectorAll('.cke_dialog_background_cover, .cke_dialog_container');o(e,(function(e){e.removeEventListener('mousedown',r),e.addEventListener('mousedown',r)}))})),a.on('key',(function(e){13===e.data.keyCode&&f()})),g(t,a),a}p()},disable:function(e,t){var n;e.contentEditable='false',null===(n=null==t?void 0:t.focusManager)||void 0===n||n.blur(!0)}},l.customRte)),e.on('rteToolbarPosUpdate',(function(e){var t=e.elRect;switch(l.position){case'center':e.left=t.width/2-e.targetWidth/2;break;case'right':e.left='',e.right=0}}))};return t})()));
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

1
web/static/grapesjs@0.21.4.min.css vendored Normal file

File diff suppressed because one or more lines are too long

3
web/static/grapesjs@0.21.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,11 +3,11 @@
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "head" -}}
<link rel="stylesheet" media="screen" href="/static/isolated-block-editor@2.26.0.css"/>
<link rel="stylesheet" media="screen" href="/static/isolated-block-editor-core@2.26.0.css"/>
<script src="/static/react@18.2.0.min.js"></script>
<script src="/static/react-dom@18.2.0.min.js"></script>
<script src="/static/isolated-block-editor@2.26.0.min.js"></script>
<link rel="stylesheet" media="screen" href="/static/grapesjs@0.21.4.min.css">
<script src="/static/grapesjs@0.21.4.min.js"></script>
<script src="/static/grapesjs-plugin-ckeditor@1.0.1.min.js"></script>
<script src="/static/grapesjs-blocks-basic@1.0.2.min.js"></script>
<script src="/static/grapesjs-preset-webpage@1.0.3.min.js"></script>
{{- end }}
{{ define "title" -}}