From 9ebbf7ce94e0547e803d63e311b921252ad1dc5c Mon Sep 17 00:00:00 2001 From: Dan Brown <ssddanbrown@googlemail.com> Date: Mon, 1 Jul 2024 15:10:22 +0100 Subject: [PATCH] Lexical: Started loading real content, Improved html loading Added more styling/layout for buttons and main content area --- resources/js/components/wysiwyg-editor.js | 4 +- resources/js/wysiwyg/actions.ts | 19 +++++++- resources/js/wysiwyg/index.ts | 6 ++- resources/js/wysiwyg/ui/framework/buttons.ts | 2 +- resources/sass/_editor.scss | 20 ++++++-- .../pages/parts/wysiwyg-editor.blade.php | 47 ++----------------- 6 files changed, 45 insertions(+), 53 deletions(-) diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index bdcdd5c51..2f0e660b1 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -5,10 +5,10 @@ export class WysiwygEditor extends Component { setup() { this.elem = this.$el; this.editContainer = this.$refs.editContainer; - this.editContent = this.$refs.editContent; + this.input = this.$refs.input; window.importVersioned('wysiwyg').then(wysiwyg => { - const editorContent = this.editContent.textContent; + const editorContent = this.input.value; wysiwyg.createPageEditorInstance(this.editContainer, editorContent); }); } diff --git a/resources/js/wysiwyg/actions.ts b/resources/js/wysiwyg/actions.ts index bca31e51b..3a32b82d8 100644 --- a/resources/js/wysiwyg/actions.ts +++ b/resources/js/wysiwyg/actions.ts @@ -1,17 +1,32 @@ -import {$getRoot, LexicalEditor} from "lexical"; +import {$createParagraphNode, $getRoot, $isTextNode, LexicalEditor} from "lexical"; import {$generateHtmlFromNodes, $generateNodesFromDOM} from "@lexical/html"; +import {$createCustomParagraphNode} from "./nodes/custom-paragraph"; export function setEditorContentFromHtml(editor: LexicalEditor, html: string) { const parser = new DOMParser(); const dom = parser.parseFromString(html, 'text/html'); + console.log(html); editor.update(() => { - const nodes = $generateNodesFromDOM(editor, dom); + // Empty existing const root = $getRoot(); for (const child of root.getChildren()) { child.remove(true); } + + const nodes = $generateNodesFromDOM(editor, dom); + + // Wrap top-level text nodes + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if ($isTextNode(node)) { + const paragraph = $createCustomParagraphNode(); + paragraph.append(node); + nodes[i] = paragraph; + } + } + root.append(...nodes); }); } diff --git a/resources/js/wysiwyg/index.ts b/resources/js/wysiwyg/index.ts index 3ca01835f..b0ff896c7 100644 --- a/resources/js/wysiwyg/index.ts +++ b/resources/js/wysiwyg/index.ts @@ -29,8 +29,12 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st const editArea = el('div', { contenteditable: 'true', + class: 'editor-content-area page-content', }); - container.append(editArea); + const editWrap = el('div', { + class: 'editor-content-wrap', + }, [editArea]); + container.append(editWrap); container.classList.add('editor-container'); const editor = createEditor(config); diff --git a/resources/js/wysiwyg/ui/framework/buttons.ts b/resources/js/wysiwyg/ui/framework/buttons.ts index f74201ff7..4418be623 100644 --- a/resources/js/wysiwyg/ui/framework/buttons.ts +++ b/resources/js/wysiwyg/ui/framework/buttons.ts @@ -51,7 +51,7 @@ export class EditorButton extends EditorUiElement { const label = this.getLabel(); let child: string|HTMLElement = label; if (this.definition.icon) { - child = el('span', {class: 'editor-button-icon'}); + child = el('div', {class: 'editor-button-icon'}); child.innerHTML = this.definition.icon; } diff --git a/resources/sass/_editor.scss b/resources/sass/_editor.scss index 79cbc73e8..753038263 100644 --- a/resources/sass/_editor.scss +++ b/resources/sass/_editor.scss @@ -14,6 +14,9 @@ .editor-toolbar-main { display: flex; flex-wrap: wrap; + justify-content: center; + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; } body.editor-is-fullscreen { @@ -22,13 +25,24 @@ body.editor-is-fullscreen { z-index: 20; } } +.editor-content-area { + &:focus { + outline: 0; + } +} +.editor-content-wrap { + overflow-y: scroll; +} // Buttons .editor-button { - border: 1px solid #DDD; font-size: 12px; padding: 4px 6px; color: #444; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; } .editor-button:hover { background-color: #EEE; @@ -38,7 +52,6 @@ body.editor-is-fullscreen { .editor-button[disabled] { pointer-events: none; cursor: not-allowed; - background-color: #EEE; opacity: .6; } .editor-button-active, .editor-button-active:hover { @@ -52,7 +65,8 @@ body.editor-is-fullscreen { .editor-button-icon svg { width: 24px; height: 24px; - fill: #000; + color: inherit; + fill: currentColor; } // Containers diff --git a/resources/views/pages/parts/wysiwyg-editor.blade.php b/resources/views/pages/parts/wysiwyg-editor.blade.php index 8fc0dc55a..ee5a2e19b 100644 --- a/resources/views/pages/parts/wysiwyg-editor.blade.php +++ b/resources/views/pages/parts/wysiwyg-editor.blade.php @@ -4,55 +4,14 @@ option:wysiwyg-editor:text-direction="{{ $locale->htmlDirection() }}" option:wysiwyg-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}" option:wysiwyg-editor:server-upload-limit-text="{{ trans('errors.server_upload_limit') }}" - class=""> + class="flex-container-column flex-fill"> - <div class="editor-container" refs="wysiwyg-editor@edit-container"> + <div class="editor-container flex-container-column flex-fill" refs="wysiwyg-editor@edit-container"> </div> - <script type="text/html" refs="wysiwyg-editor@edit-content"> - <p id="Content!">Some <strong>content</strong> here</p> - <p>Content with image in, before text. <img src="https://bookstack.local/bookstack/uploads/images/gallery/2022-03/scaled-1680-/cats-image-2400x1000-2.jpg" width="200" alt="Sleepy meow"> After text.</p> - <p>This has a <a href="https://example.com" target="_blank" title="Link to example">link</a> in it</p> - <h2>List below this h2 header</h2> - <ul> - <li>Hello</li> - </ul> - - <details> - <summary>Collapsible details/summary block</summary> - <p>Inner text here</p> - <h4>Inner Header</h4> - <p>More text <strong>with bold in</strong> it</p> - </details> - - <p class="callout info"> - Hello there, this is an info callout - </p> - - <h3>Table</h3> - - <table> - <thead> - <tr> - <th>Cell A</th> - <th>Cell B</th> - <th>Cell C</th> - </tr> - </thead> - <tbody> - <tr> - <td>Cell D</td> - <td>Cell E</td> - <td>Cell F</td> - </tr> - </tbody> - </table> - </script> - <div id="lexical-debug" style="white-space: pre-wrap; font-size: 12px; height: 200px; overflow-y: scroll; background-color: #000; padding: 1rem; border-radius: 4px; color: #FFF;"></div> -{{-- <textarea id="html-editor" name="html" rows="5"--}} -{{-- @if($errors->has('html')) class="text-neg" @endif>@if(isset($model) || old('html')){{ old('html') ? old('html') : $model->html }}@endif</textarea>--}} + <textarea refs="wysiwyg-editor@input" id="html-editor" hidden="hidden" name="html" rows="5">{{ old('html') ?? $model->html ?? '' }}</textarea> </div> @if($errors->has('html'))