]> BookStack Code Mirror - bookstack/commitdiff
Input WYSIWYG: Added compontent and rough logic to book form
authorDan Brown <redacted>
Sat, 16 Dec 2023 14:48:35 +0000 (14:48 +0000)
committerDan Brown <redacted>
Sat, 16 Dec 2023 14:48:35 +0000 (14:48 +0000)
Just as a draft for prototyping and playing around to get things
started.

resources/js/components/index.js
resources/js/components/wysiwyg-editor.js
resources/js/components/wysiwyg-input.js [new file with mode: 0644]
resources/js/wysiwyg/config.js
resources/views/books/parts/form.blade.php
resources/views/form/editor-translations.blade.php [moved from resources/views/pages/parts/editor-translations.blade.php with 100% similarity]
resources/views/pages/parts/wysiwyg-editor.blade.php

index a56f18a5aff728f7f7aba88aeb9b6f42c645ad9a..3a66079d7f8345d81cf4cd543fe55ef5c5745472 100644 (file)
@@ -58,3 +58,4 @@ export {TriLayout} from './tri-layout';
 export {UserSelect} from './user-select';
 export {WebhookEvents} from './webhook-events';
 export {WysiwygEditor} from './wysiwyg-editor';
+export {WysiwygInput} from './wysiwyg-input';
index 21db207e6705451daf45d7a241210b63c1aa00be..82f60827d7af668637d3624d7bbd38c5658ce311 100644 (file)
@@ -1,4 +1,4 @@
-import {build as buildEditorConfig} from '../wysiwyg/config';
+import {buildForEditor as buildEditorConfig} from '../wysiwyg/config';
 import {Component} from './component';
 
 export class WysiwygEditor extends Component {
@@ -6,17 +6,13 @@ export class WysiwygEditor extends Component {
     setup() {
         this.elem = this.$el;
 
-        this.pageId = this.$opts.pageId;
-        this.textDirection = this.$opts.textDirection;
-        this.isDarkMode = document.documentElement.classList.contains('dark-mode');
-
         this.tinyMceConfig = buildEditorConfig({
             language: this.$opts.language,
             containerElement: this.elem,
-            darkMode: this.isDarkMode,
-            textDirection: this.textDirection,
+            darkMode: document.documentElement.classList.contains('dark-mode'),
+            textDirection: this.$opts.textDirection,
             drawioUrl: this.getDrawIoUrl(),
-            pageId: Number(this.pageId),
+            pageId: Number(this.$opts.pageId),
             translations: {
                 imageUploadErrorText: this.$opts.imageUploadErrorText,
                 serverUploadLimitText: this.$opts.serverUploadLimitText,
diff --git a/resources/js/components/wysiwyg-input.js b/resources/js/components/wysiwyg-input.js
new file mode 100644 (file)
index 0000000..88c06a3
--- /dev/null
@@ -0,0 +1,26 @@
+import {Component} from './component';
+import {buildForInput} from '../wysiwyg/config';
+
+export class WysiwygInput extends Component {
+
+    setup() {
+        this.elem = this.$el;
+
+        const config = buildForInput({
+            language: this.$opts.language,
+            containerElement: this.elem,
+            darkMode: document.documentElement.classList.contains('dark-mode'),
+            textDirection: this.textDirection,
+            translations: {
+                imageUploadErrorText: this.$opts.imageUploadErrorText,
+                serverUploadLimitText: this.$opts.serverUploadLimitText,
+            },
+            translationMap: window.editor_translations,
+        });
+
+        window.tinymce.init(config).then(editors => {
+            this.editor = editors[0];
+        });
+    }
+
+}
index 6973db8c86d606aab1cb628d8d3f1f36ca951f81..d7c6bba729559047daa432d3ddadf22308b83cbc 100644 (file)
@@ -217,7 +217,7 @@ body {
  * @param {WysiwygConfigOptions} options
  * @return {Object}
  */
-export function build(options) {
+export function buildForEditor(options) {
     // Set language
     window.tinymce.addI18n(options.language, options.translationMap);
 
@@ -290,6 +290,54 @@ export function build(options) {
     };
 }
 
+/**
+ * @param {WysiwygConfigOptions} options
+ * @return {RawEditorOptions}
+ */
+export function buildForInput(options) {
+    // Set language
+    window.tinymce.addI18n(options.language, options.translationMap);
+
+    // BookStack Version
+    const version = document.querySelector('script[src*="/dist/app.js"]').getAttribute('src').split('?version=')[1];
+
+    // Return config object
+    return {
+        width: '100%',
+        height: '300px',
+        target: options.containerElement,
+        cache_suffix: `?version=${version}`,
+        content_css: [
+            window.baseUrl('/dist/styles.css'),
+        ],
+        branding: false,
+        skin: options.darkMode ? 'tinymce-5-dark' : 'tinymce-5',
+        body_class: 'page-content',
+        browser_spellcheck: true,
+        relative_urls: false,
+        language: options.language,
+        directionality: options.textDirection,
+        remove_script_host: false,
+        document_base_url: window.baseUrl('/'),
+        end_container_on_empty_block: true,
+        remove_trailing_brs: false,
+        statusbar: false,
+        menubar: false,
+        plugins: 'link autolink',
+        contextmenu: false,
+        toolbar: 'bold italic underline link',
+        content_style: getContentStyle(options),
+        color_map: colorMap,
+        init_instance_callback(editor) {
+            const head = editor.getDoc().querySelector('head');
+            head.innerHTML += fetchCustomHeadContent();
+        },
+        setup(editor) {
+            //
+        },
+    };
+}
+
 /**
  * @typedef {Object} WysiwygConfigOptions
  * @property {Element} containerElement
index e22be619d66dd107eb54fd6b529ce292e1fb1af7..3a2e30da60d930326715f46a100b29a6ad99341d 100644 (file)
@@ -1,3 +1,6 @@
+@push('head')
+    <script src="{{ versioned_asset('libs/tinymce/tinymce.min.js') }}" nonce="{{ $cspNonce }}"></script>
+@endpush
 
 {{ csrf_field() }}
 <div class="form-group title-input">
@@ -8,6 +11,15 @@
 <div class="form-group description-input">
     <label for="description">{{ trans('common.description') }}</label>
     @include('form.textarea', ['name' => 'description'])
+
+    <textarea component="wysiwyg-input"
+              option:wysiwyg-input:language="{{ $locale->htmlLang() }}"
+              option:wysiwyg-input:text-direction="{{ $locale->htmlDirection() }}"
+              id="description_html" name="description_html" rows="5"
+              @if($errors->has('description_html')) class="text-neg" @endif>@if(isset($model) || old('description_html')){{ old('description_html') ? old($name) : $model->description_html}}@endif</textarea>
+    @if($errors->has('description_html'))
+        <div class="text-neg text-small">{{ $errors->first('description_html') }}</div>
+    @endif
 </div>
 
 <div class="form-group collapsible" component="collapsible" id="logo-control">
@@ -62,4 +74,5 @@
     <button type="submit" class="button">{{ trans('entities.books_save') }}</button>
 </div>
 
-@include('entities.selector-popup', ['entityTypes' => 'page', 'selectorEndpoint' => '/search/entity-selector-templates'])
\ No newline at end of file
+@include('entities.selector-popup', ['entityTypes' => 'page', 'selectorEndpoint' => '/search/entity-selector-templates'])
+@include('form.editor-translations')
\ No newline at end of file
index ca6b6da8a2809f74ea32060fb5d29fceee6225ab..84a267b681b9b6a257d664eaaf460669d383ec93 100644 (file)
@@ -18,4 +18,4 @@
     <div class="text-neg text-small">{{ $errors->first('html') }}</div>
 @endif
 
-@include('pages.parts.editor-translations')
\ No newline at end of file
+@include('form.editor-translations')
\ No newline at end of file