6 Commits

Author SHA1 Message Date
kor-elf d4ae9e0e43 Merge pull request 'Версия 0.6.0' (#9) from develop into main
Reviewed-on: #9
2026-06-21 00:37:21 +05:00
kor-elf 859187bafa Update image version to 0.6.0 in production configuration 2026-06-21 00:17:32 +05:00
kor-elf 9e6e699db0 Add "Do not translate" functionality to TinyMCE editor
- Add a custom TinyMCE plugin to mark content with `translate="no"`.
- Update WYSIWYG editor to support the "Do not translate" toggle button and menu item.
- Highlight non-translatable content with custom styles in the editor.
- Localize plugin strings for English and Russian.
2026-06-20 23:54:25 +05:00
kor-elf 993350073c Cast description input to string with default value in StoreUpdateRequest. 2026-06-20 23:13:59 +05:00
kor-elf 9a6604a40b Replace InterventionImage::read with InterventionImage::decodePath for image processing 2026-06-20 22:18:51 +05:00
kor-elf 85a4361d0c UpUpdated Laravel to version 13. 2026-06-20 22:18:21 +05:00
8 changed files with 2389 additions and 3970 deletions
@@ -34,7 +34,7 @@ final class StoreUpdateRequest extends FormRequest implements FormRequestDto
{ {
return new StoreUpdate( return new StoreUpdate(
title: $this->input('title'), title: $this->input('title'),
description: $this->input('description'), description: (string) $this->input('description', ''),
storages: $this->storages(), storages: $this->storages(),
isTranslateAutomatically: (bool) $this->input('translate-automatically', false), isTranslateAutomatically: (bool) $this->input('translate-automatically', false),
); );
@@ -9,7 +9,7 @@ final readonly class ResizeCommandHandler
{ {
public function resize(Storage $storage, int $width, int $height): Storage public function resize(Storage $storage, int $width, int $height): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->width() < $width && $image->height() < $height) { if ($image->width() < $width && $image->height() < $height) {
return $storage; return $storage;
} }
@@ -23,7 +23,7 @@ final readonly class ResizeCommandHandler
public function width(Storage $storage, int $width): Storage public function width(Storage $storage, int $width): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->width() < $width) { if ($image->width() < $width) {
return $storage; return $storage;
} }
@@ -37,7 +37,7 @@ final readonly class ResizeCommandHandler
public function height(Storage $storage, int $height): Storage public function height(Storage $storage, int $height): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->height() < $height) { if ($image->height() < $height) {
return $storage; return $storage;
} }
+31 -12
View File
@@ -1,4 +1,5 @@
{ {
"$schema": "https://getcomposer.org/schema.json",
"name": "laravel/laravel", "name": "laravel/laravel",
"type": "project", "type": "project",
"description": "The skeleton application for the Laravel framework.", "description": "The skeleton application for the Laravel framework.",
@@ -6,23 +7,22 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.3", "php": "^8.3",
"intervention/image-laravel": "^1.2", "intervention/image-laravel": "^4.0",
"kor-elf/captcha-rule-for-laravel": "^1.0", "kor-elf/captcha-rule-for-laravel": "^1.0",
"kor-elf/translate-laravel": "1.3.0", "kor-elf/translate-laravel": "^2.0",
"laravel/framework": "^11.0", "laravel/framework": "^13.8",
"laravel/tinker": "^2.9", "laravel/tinker": "^3.0",
"staudenmeir/laravel-adjacency-list": "^1.0" "staudenmeir/laravel-adjacency-list": "^1.26"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.13", "barryvdh/laravel-debugbar": "^4.3",
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
"laravel-lang/common": "^6.2", "laravel/pail": "^1.2.5",
"laravel/pint": "^1.13", "laravel/pao": "^1.0.6",
"laravel/sail": "^1.26", "laravel/pint": "^1.27",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.0", "nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^12.5.12"
"spatie/laravel-ignition": "^2.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -37,6 +37,22 @@
} }
}, },
"scripts": { "scripts": {
"setup": [
"composer install",
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
"@php artisan key:generate",
"@php artisan migrate --force",
"npm install --ignore-scripts",
"npm run build"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1 --timeout=0\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
],
"test": [
"@php artisan config:clear --ansi @no_additional_args",
"@php artisan test"
],
"post-autoload-dump": [ "post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi" "@php artisan package:discover --ansi"
@@ -51,6 +67,9 @@
"@php artisan key:generate --ansi", "@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"", "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi" "@php artisan migrate --graceful --ansi"
],
"pre-package-uninstall": [
"Illuminate\\Foundation\\ComposerScripts::prePackageUninstall"
] ]
}, },
"extra": { "extra": {
+2252 -3946
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
<?php declare(strict_types=1);
return [
'Do not translate' => 'Do not translate',
'Mark as not to translate' => 'Mark as not to translate',
];
+6
View File
@@ -0,0 +1,6 @@
<?php declare(strict_types=1);
return [
'Do not translate' => 'Не переводить',
'Mark as not to translate' => 'Пометить как не переводить',
];
@@ -95,14 +95,96 @@
xhr.send(formData); xhr.send(formData);
}); });
@endif @endif
tinymce.PluginManager.add('translateNo', (editor) => {
const ATTR = 'translate';
const VALUE = 'no';
const isTranslateNo = (node) =>
node && node.nodeType === 1 && node.getAttribute(ATTR) === VALUE;
const toggleTranslateNo = () => {
const selectedNode = editor.selection.getNode();
if (isTranslateNo(selectedNode)) {
// Remove translate="no", expand span
if (selectedNode.tagName === 'SPAN') {
editor.dom.remove(selectedNode, true); // true = сохранить детей
} else {
editor.dom.setAttrib(selectedNode, ATTR, null);
}
return;
}
// If inside translate="no", remove the mark
const wrapper = editor.dom.getParent(selectedNode, `[${ATTR}="${VALUE}"]`);
if (wrapper) {
if (wrapper.tagName === 'SPAN') {
editor.dom.remove(wrapper, true);
} else {
editor.dom.setAttrib(wrapper, ATTR, null);
}
return;
}
// Otherwise, wrap the selection
editor.formatter.register('translateNo', {
inline: 'span',
attributes: { [ATTR]: VALUE },
remove: 'all'
});
editor.formatter.apply('translateNo');
};
editor.ui.registry.addToggleButton('translateNo', {
icon: 'translate',
tooltip: '{{ __('editor.Do not translate') }}',
onAction: toggleTranslateNo,
onSetup: (api) => {
const setActive = () => {
const node = editor.selection.getNode();
api.setActive(
isTranslateNo(node) ||
!!editor.dom.getParent(node, `[${ATTR}="${VALUE}"]`)
);
};
editor.on('NodeChange', setActive);
return () => editor.off('NodeChange', setActive);
}
});
editor.ui.registry.addMenuItem('translateNo', {
text: '{{ __('editor.Mark as not to translate') }}',
icon: 'translate',
onAction: toggleTranslateNo
});
});
tinymce.init({ tinymce.init({
content_style: `
span[translate="no"] {
background: rgba(255, 215, 0, 0.35);
outline: 1px dashed #e0a800;
position: relative;
}
span[translate="no"]:hover::before {
position: absolute;
content: "{{ __('editor.Do not translate') }}";
left: 0;
bottom: 100%;
background: #e0a800;
white-space: nowrap;
padding: 0.25rem;
border: 1px solid #ddd;
}
`,
selector: '#{{ $tinyId }}', selector: '#{{ $tinyId }}',
@if(in_array(app()->getLocale(), ['ru'], true)) @if(in_array(app()->getLocale(), ['ru'], true))
language: '{{ app()->getLocale() }}', language: '{{ app()->getLocale() }}',
@endif @endif
license_key: '{{ $tinymceLicenseKey }}', license_key: '{{ $tinymceLicenseKey }}',
plugins: 'advlist code emoticons link lists table codesample media my-image', plugins: 'advlist code emoticons link lists table codesample media my-image translateNo',
toolbar: 'bold italic | bullist numlist | link image emoticons media codesample', toolbar: 'bold italic | bullist numlist | link image emoticons media codesample translateNo',
referrer_policy: 'origin', referrer_policy: 'origin',
@if($storageUpload !== null) @if($storageUpload !== null)
images_upload_handler: imageUpload, images_upload_handler: imageUpload,
+6 -6
View File
@@ -1,8 +1,8 @@
#version: '3.7' #version: '3.7'
services: services:
app: app:
# image: korelf/my-projects-website:0.5.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db
@@ -20,8 +20,8 @@ services:
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json # - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
queue: queue:
# image: korelf/my-projects-website:0.5.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db
@@ -35,8 +35,8 @@ services:
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json # - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
scheduler: scheduler:
# image: korelf/my-projects-website:0.5.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.5.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db