diff --git a/app/Config/app.php b/app/Config/app.php index 24ed5799b..7297048b4 100755 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -124,6 +124,7 @@ return [ BookStack\Providers\EventServiceProvider::class, BookStack\Providers\RouteServiceProvider::class, BookStack\Providers\CustomFacadeProvider::class, + BookStack\Providers\CustomValidationServiceProvider::class, ], /* diff --git a/app/Entities/Repos/BookRepo.php b/app/Entities/Repos/BookRepo.php index 008a9080c..f32dd8582 100644 --- a/app/Entities/Repos/BookRepo.php +++ b/app/Entities/Repos/BookRepo.php @@ -6,11 +6,9 @@ use BookStack\Entities\Book; use BookStack\Entities\Managers\TrashCan; use BookStack\Exceptions\ImageUploadException; use BookStack\Exceptions\NotFoundException; -use BookStack\Exceptions\NotifyException; use BookStack\Facades\Activity; use BookStack\Uploads\ImageRepo; use Exception; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Http\UploadedFile; use Illuminate\Support\Collection; @@ -24,7 +22,6 @@ class BookRepo /** * BookRepo constructor. - * @param $tagRepo */ public function __construct(BaseRepo $baseRepo, TagRepo $tagRepo, ImageRepo $imageRepo) { diff --git a/app/Entities/Repos/BookshelfRepo.php b/app/Entities/Repos/BookshelfRepo.php index 7cd333ff3..039278228 100644 --- a/app/Entities/Repos/BookshelfRepo.php +++ b/app/Entities/Repos/BookshelfRepo.php @@ -18,7 +18,6 @@ class BookshelfRepo /** * BookshelfRepo constructor. - * @param $baseRepo */ public function __construct(BaseRepo $baseRepo) { diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index 6b593d85e..0e5b48482 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -11,7 +11,6 @@ use BookStack\Entities\Page; use BookStack\Entities\PageRevision; use BookStack\Exceptions\MoveOperationException; use BookStack\Exceptions\NotFoundException; -use BookStack\Exceptions\NotifyException; use BookStack\Exceptions\PermissionsException; use BookStack\Facades\Activity; use Exception; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index f41815399..c9bf4f36b 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -13,7 +13,6 @@ use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Schema; use URL; -use Validator; class AppServiceProvider extends ServiceProvider { @@ -32,37 +31,11 @@ class AppServiceProvider extends ServiceProvider URL::forceScheme($isHttps ? 'https' : 'http'); } - // Custom validation methods - Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) { - $validImageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp']; - return in_array(strtolower($value->getClientOriginalExtension()), $validImageExtensions); - }); - - Validator::extend('no_double_extension', function ($attribute, $value, $parameters, $validator) { - $uploadName = $value->getClientOriginalName(); - return substr_count($uploadName, '.') < 2; - }); - - Validator::extend('safe_url', function ($attribute, $value, $parameters, $validator) { - $cleanLinkName = strtolower(trim($value)); - $isJs = strpos($cleanLinkName, 'javascript:') === 0; - $isData = strpos($cleanLinkName, 'data:') === 0; - return !$isJs && !$isData; - }); - // Custom blade view directives Blade::directive('icon', function ($expression) { return "<?php echo icon($expression); ?>"; }); - Blade::directive('exposeTranslations', function ($expression) { - return "<?php \$__env->startPush('translations'); ?>" . - "<?php foreach({$expression} as \$key): ?>" . - '<meta name="translation" key="<?php echo e($key); ?>" value="<?php echo e(trans($key)); ?>">' . "\n" . - "<?php endforeach; ?>" . - '<?php $__env->stopPush(); ?>'; - }); - // Allow longer string lengths after upgrade to utf8mb4 Schema::defaultStringLength(191); diff --git a/app/Providers/CustomValidationServiceProvider.php b/app/Providers/CustomValidationServiceProvider.php new file mode 100644 index 000000000..4a5272b40 --- /dev/null +++ b/app/Providers/CustomValidationServiceProvider.php @@ -0,0 +1,33 @@ +<?php + +namespace BookStack\Providers; + +use Illuminate\Support\Facades\Validator; +use Illuminate\Support\ServiceProvider; + +class CustomValidationServiceProvider extends ServiceProvider +{ + + /** + * Register our custom validation rules when the application boots. + */ + public function boot(): void + { + Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) { + $validImageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp']; + return in_array(strtolower($value->getClientOriginalExtension()), $validImageExtensions); + }); + + Validator::extend('no_double_extension', function ($attribute, $value, $parameters, $validator) { + $uploadName = $value->getClientOriginalName(); + return substr_count($uploadName, '.') < 2; + }); + + Validator::extend('safe_url', function ($attribute, $value, $parameters, $validator) { + $cleanLinkName = strtolower(trim($value)); + $isJs = strpos($cleanLinkName, 'javascript:') === 0; + $isData = strpos($cleanLinkName, 'data:') === 0; + return !$isJs && !$isData; + }); + } +} diff --git a/resources/js/components/markdown-editor.js b/resources/js/components/markdown-editor.js index 19d26d4a9..bd107f2bf 100644 --- a/resources/js/components/markdown-editor.js +++ b/resources/js/components/markdown-editor.js @@ -13,6 +13,7 @@ class MarkdownEditor { this.pageId = this.$opts.pageId; this.textDirection = this.$opts.textDirection; + this.imageUploadErrorText = this.$opts.imageUploadErrorText; this.markdown = new MarkdownIt({html: true}); this.markdown.use(mdTasksLists, {label: true}); @@ -373,7 +374,7 @@ class MarkdownEditor { const newContent = `[](${resp.data.url})`; replaceContent(placeHolderText, newContent); }).catch(err => { - window.$events.emit('error', trans('errors.image_upload_error')); + window.$events.emit('error', context.imageUploadErrorText); replaceContent(placeHolderText, selectedText); console.log(err); }); @@ -492,7 +493,7 @@ class MarkdownEditor { this.cm.focus(); DrawIO.close(); }).catch(err => { - window.$events.emit('error', trans('errors.image_upload_error')); + window.$events.emit('error', this.imageUploadErrorText); console.log(err); }); }); diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js index a32e78161..bae70ad14 100644 --- a/resources/js/components/wysiwyg-editor.js +++ b/resources/js/components/wysiwyg-editor.js @@ -38,7 +38,7 @@ function editorPaste(event, editor, wysiwygComponent) { editor.dom.replace(newEl, id); }).catch(err => { editor.dom.remove(id); - window.$events.emit('error', trans('errors.image_upload_error')); + window.$events.emit('error', wysiwygComponent.imageUploadErrorText); console.log(err); }); }, 10); @@ -236,7 +236,7 @@ function codePlugin() { }); } -function drawIoPlugin(drawioUrl, isDarkMode, pageId) { +function drawIoPlugin(drawioUrl, isDarkMode, pageId, wysiwygComponent) { let pageEditor = null; let currentNode = null; @@ -280,7 +280,7 @@ function drawIoPlugin(drawioUrl, isDarkMode, pageId) { pageEditor.dom.setAttrib(imgElem, 'src', img.url); pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id); } catch (err) { - window.$events.emit('error', trans('errors.image_upload_error')); + window.$events.emit('error', wysiwygComponent.imageUploadErrorText); console.log(err); } return; @@ -295,7 +295,7 @@ function drawIoPlugin(drawioUrl, isDarkMode, pageId) { pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id); } catch (err) { pageEditor.dom.remove(id); - window.$events.emit('error', trans('errors.image_upload_error')); + window.$events.emit('error', wysiwygComponent.imageUploadErrorText); console.log(err); } }, 5); @@ -414,12 +414,12 @@ function listenForBookStackEditorEvents(editor) { class WysiwygEditor { - setup() { this.elem = this.$el; this.pageId = this.$opts.pageId; this.textDirection = this.$opts.textDirection; + this.imageUploadErrorText = this.$opts.imageUploadErrorText; this.isDarkMode = document.documentElement.classList.contains('dark-mode'); this.plugins = "image table textcolor paste link autolink fullscreen code customhr autosave lists codeeditor media"; @@ -437,7 +437,7 @@ class WysiwygEditor { const drawioUrlElem = document.querySelector('[drawio-url]'); if (drawioUrlElem) { const url = drawioUrlElem.getAttribute('drawio-url'); - drawIoPlugin(url, this.isDarkMode, this.pageId); + drawIoPlugin(url, this.isDarkMode, this.pageId, this); this.plugins += ' drawio'; } diff --git a/resources/views/pages/markdown-editor.blade.php b/resources/views/pages/markdown-editor.blade.php index 6c1437ec1..a9d1f1174 100644 --- a/resources/views/pages/markdown-editor.blade.php +++ b/resources/views/pages/markdown-editor.blade.php @@ -1,10 +1,8 @@ <div id="markdown-editor" component="markdown-editor" option:markdown-editor:page-id="{{ $model->id ?? 0 }}" option:markdown-editor:text-direction="{{ config('app.rtl') ? 'rtl' : 'ltr' }}" + option:markdown-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}" class="flex-fill flex code-fill"> - @exposeTranslations([ - 'errors.image_upload_error', - ]) <div class="markdown-editor-wrap active"> <div class="editor-toolbar"> diff --git a/resources/views/pages/wysiwyg-editor.blade.php b/resources/views/pages/wysiwyg-editor.blade.php index 3bc85caa9..d8b8b1c35 100644 --- a/resources/views/pages/wysiwyg-editor.blade.php +++ b/resources/views/pages/wysiwyg-editor.blade.php @@ -1,12 +1,9 @@ <div component="wysiwyg-editor" option:wysiwyg-editor:page-id="{{ $model->id ?? 0 }}" option:wysiwyg-editor:text-direction="{{ config('app.rtl') ? 'rtl' : 'ltr' }}" + option:wysiwyg-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}" class="flex-fill flex"> - @exposeTranslations([ - 'errors.image_upload_error', - ]) - <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> </div>