mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-02-06 09:09:38 +03:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf0ba9f756 | ||
|
|
05f8034439 | ||
|
|
1d1186c901 | ||
|
|
641a26cdf7 | ||
|
|
5fd8e7e0e9 | ||
|
|
d926ca5f71 | ||
|
|
b69722c3b5 | ||
|
|
c9aa1c979f | ||
|
|
49498cfaf9 | ||
|
|
3a4aa81115 | ||
|
|
f021823287 | ||
|
|
3a8a476906 | ||
|
|
328bc88f02 | ||
|
|
2a99e23e6d | ||
|
|
b855bbaaea | ||
|
|
96436839f1 | ||
|
|
b4f29a85ab | ||
|
|
4a2a044f3d | ||
|
|
ca09ed916f | ||
|
|
dbefda055f |
10
.github/ISSUE_TEMPLATE/config.yml
vendored
10
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,9 +1,13 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord chat support
|
||||
- name: Discord Chat Support
|
||||
url: https://discord.gg/ztkBqR2
|
||||
about: Realtime support / chat with the community and the team.
|
||||
about: Realtime support & chat with the BookStack community and the team.
|
||||
|
||||
- name: Debugging & Common Issues
|
||||
url: https://www.bookstackapp.com/docs/admin/debugging/
|
||||
about: Find details on how to debug issues and view common issues with thier resolutions.
|
||||
about: Find details on how to debug issues and view common issues with their resolutions.
|
||||
|
||||
- name: Official Support Plans
|
||||
url: https://www.bookstackapp.com/support/
|
||||
about: View our official support plans that offer assured support for business.
|
||||
1
.github/translators.txt
vendored
1
.github/translators.txt
vendored
@@ -242,3 +242,4 @@ sgenc :: Turkish
|
||||
Shukrullo (vodiylik) :: Uzbek
|
||||
William W. (Nevnt) :: Chinese Traditional
|
||||
eamaro :: Portuguese
|
||||
Ypsilon-dev :: Arabic
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -5,10 +5,10 @@ Homestead.yaml
|
||||
.idea
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
/public/dist/*.map
|
||||
/public/dist
|
||||
/public/plugins
|
||||
/public/css/*.map
|
||||
/public/js/*.map
|
||||
/public/css
|
||||
/public/js
|
||||
/public/bower
|
||||
/public/build/
|
||||
/storage/images
|
||||
|
||||
@@ -28,10 +28,10 @@ class TagRepo
|
||||
'name',
|
||||
($searchTerm || $nameFilter) ? 'value' : DB::raw('COUNT(distinct value) as `values`'),
|
||||
DB::raw('COUNT(id) as usages'),
|
||||
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Page\', 1, 0)) as page_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Chapter\', 1, 0)) as chapter_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Book\', 1, 0)) as book_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'BookStack\\\\BookShelf\', 1, 0)) as shelf_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'page\', 1, 0)) as page_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'chapter\', 1, 0)) as chapter_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'book\', 1, 0)) as book_count'),
|
||||
DB::raw('SUM(IF(entity_type = \'bookshelf\', 1, 0)) as shelf_count'),
|
||||
])
|
||||
->orderBy($nameFilter ? 'value' : 'name');
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ return [
|
||||
// to the server if the browser has a HTTPS connection. This will keep
|
||||
// the cookie from being sent to you if it can not be done securely.
|
||||
'secure' => env('SESSION_SECURE_COOKIE', null)
|
||||
?? Str::startsWith(env('APP_URL'), 'https:'),
|
||||
?? Str::startsWith(env('APP_URL', ''), 'https:'),
|
||||
|
||||
// HTTP Access Only
|
||||
// Setting this value to true will prevent JavaScript from accessing the
|
||||
|
||||
@@ -215,14 +215,16 @@ class ExportFormatter
|
||||
*/
|
||||
protected function containHtml(string $htmlContent): string
|
||||
{
|
||||
$imageTagsOutput = [];
|
||||
preg_match_all("/\<img.*?src\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $imageTagsOutput);
|
||||
// Replace embed tags with images
|
||||
$htmlContent = preg_replace("/<embed (.*?)>/i", '<img $1>', $htmlContent);
|
||||
|
||||
// Replace image src with base64 encoded image strings
|
||||
// Replace image & embed src attributes with base64 encoded data strings
|
||||
$imageTagsOutput = [];
|
||||
preg_match_all("/<img .*?src=['\"](.*?)['\"].*?>/i", $htmlContent, $imageTagsOutput);
|
||||
if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) {
|
||||
foreach ($imageTagsOutput[0] as $index => $imgMatch) {
|
||||
$oldImgTagString = $imgMatch;
|
||||
$srcString = $imageTagsOutput[2][$index];
|
||||
$srcString = $imageTagsOutput[1][$index];
|
||||
$imageEncoded = $this->imageService->imageUriToBase64($srcString);
|
||||
if ($imageEncoded === null) {
|
||||
$imageEncoded = $srcString;
|
||||
@@ -232,14 +234,13 @@ class ExportFormatter
|
||||
}
|
||||
}
|
||||
|
||||
// Replace any relative links with full system URL
|
||||
$linksOutput = [];
|
||||
preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $linksOutput);
|
||||
|
||||
// Replace image src with base64 encoded image strings
|
||||
preg_match_all("/<a .*href=['\"](.*?)['\"].*?>/i", $htmlContent, $linksOutput);
|
||||
if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) {
|
||||
foreach ($linksOutput[0] as $index => $linkMatch) {
|
||||
$oldLinkString = $linkMatch;
|
||||
$srcString = $linksOutput[2][$index];
|
||||
$srcString = $linksOutput[1][$index];
|
||||
if (strpos(trim($srcString), 'http') !== 0) {
|
||||
$newSrcString = url($srcString);
|
||||
$newLinkString = str_replace($srcString, $newSrcString, $oldLinkString);
|
||||
@@ -248,7 +249,6 @@ class ExportFormatter
|
||||
}
|
||||
}
|
||||
|
||||
// Replace any relative links with system domain
|
||||
return $htmlContent;
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ class SearchRunner
|
||||
/** @var Connection $connection */
|
||||
$connection = $query->getConnection();
|
||||
$tagValue = (float) trim($connection->getPdo()->quote($tagValue), "'");
|
||||
$query->whereRaw("value ${tagOperator} ${tagValue}");
|
||||
$query->whereRaw("value {$tagOperator} {$tagValue}");
|
||||
} else {
|
||||
$query->where('value', $tagOperator, $tagValue);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@ class JsonDebugException extends Exception
|
||||
}
|
||||
|
||||
/**
|
||||
* Covert this exception into a response.
|
||||
* Convert this exception into a response.
|
||||
* We add a manual data conversion to UTF8 to ensure any binary data is presentable as a JSON string.
|
||||
*/
|
||||
public function render(): JsonResponse
|
||||
{
|
||||
return response()->json($this->data);
|
||||
$cleaned = mb_convert_encoding($this->data, 'UTF-8');
|
||||
|
||||
return response()->json($cleaned);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,9 +127,11 @@ abstract class Controller extends BaseController
|
||||
protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse
|
||||
{
|
||||
return response()->stream(function () use ($stream) {
|
||||
// End & flush the output buffer otherwise we still seem to use memory.
|
||||
|
||||
// End & flush the output buffer, if we're in one, otherwise we still use memory.
|
||||
// Output buffer may or may not exist depending on PHP `output_buffering` setting.
|
||||
// Ignore in testing since output buffers are used to gather a response.
|
||||
if (!app()->runningUnitTests()) {
|
||||
if (!empty(ob_get_status()) && !app()->runningUnitTests()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
@@ -217,6 +219,6 @@ abstract class Controller extends BaseController
|
||||
*/
|
||||
protected function getImageValidationRules(): array
|
||||
{
|
||||
return ['image_extension', 'mimes:jpeg,png,gif,webp', 'max:' . (config('app.upload_limit') * 1000)];
|
||||
return ['image_extension', 'mimes:jpeg,png,gif,webp,svg', 'max:' . (config('app.upload_limit') * 1000)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,11 @@ class DrawioImageController extends Controller
|
||||
return $this->jsonError('Image data could not be found');
|
||||
}
|
||||
|
||||
$isSvg = strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'svg';
|
||||
$uriPrefix = $isSvg ? 'data:image/svg+xml;base64,' : 'data:image/png;base64,';
|
||||
|
||||
return response()->json([
|
||||
'content' => base64_encode($imageData),
|
||||
'content' => $uriPrefix . base64_encode($imageData),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class SettingController extends Controller
|
||||
$this->logActivity(ActivityType::SETTINGS_UPDATE, $category);
|
||||
$this->showSuccessNotification(trans('settings.settings_save_success'));
|
||||
|
||||
return redirect("/settings/${category}");
|
||||
return redirect("/settings/{$category}");
|
||||
}
|
||||
|
||||
protected function ensureCategoryExists(string $category): void
|
||||
|
||||
@@ -11,7 +11,7 @@ class Localization
|
||||
/**
|
||||
* Array of right-to-left locales.
|
||||
*/
|
||||
protected $rtlLocales = ['ar', 'he'];
|
||||
protected $rtlLocales = ['ar', 'fa', 'he'];
|
||||
|
||||
/**
|
||||
* Map of BookStack locale names to best-estimate system locale names.
|
||||
@@ -30,6 +30,7 @@ class Localization
|
||||
'es_AR' => 'es_AR',
|
||||
'et' => 'et_EE',
|
||||
'eu' => 'eu_ES',
|
||||
'fa' => 'fa_IR',
|
||||
'fr' => 'fr_FR',
|
||||
'he' => 'he_IL',
|
||||
'hr' => 'hr_HR',
|
||||
|
||||
@@ -148,7 +148,8 @@ class ImageRepo
|
||||
*/
|
||||
public function saveDrawing(string $base64Uri, int $uploadedTo): Image
|
||||
{
|
||||
$name = 'Drawing-' . user()->id . '-' . time() . '.png';
|
||||
$isSvg = strpos($base64Uri, 'data:image/svg+xml;') === 0;
|
||||
$name = 'Drawing-' . user()->id . '-' . time() . ($isSvg ? '.svg' : '.png');
|
||||
|
||||
return $this->imageService->saveNewFromBase64Uri($base64Uri, $name, 'drawio', $uploadedTo);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class ImageService
|
||||
protected $image;
|
||||
protected $fileSystem;
|
||||
|
||||
protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'];
|
||||
|
||||
/**
|
||||
* ImageService constructor.
|
||||
@@ -230,6 +230,14 @@ class ImageService
|
||||
return strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'gif';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given image is an SVG image file.
|
||||
*/
|
||||
protected function isSvg(Image $image): bool
|
||||
{
|
||||
return strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'svg';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given image and image data is apng.
|
||||
*/
|
||||
@@ -255,8 +263,8 @@ class ImageService
|
||||
*/
|
||||
public function getThumbnail(Image $image, ?int $width, ?int $height, bool $keepRatio = false): string
|
||||
{
|
||||
// Do not resize GIF images where we're not cropping
|
||||
if ($keepRatio && $this->isGif($image)) {
|
||||
// Do not resize GIF images where we're not cropping or SVG images.
|
||||
if (($keepRatio && $this->isGif($image)) || $this->isSvg($image)) {
|
||||
return $this->getPublicUrl($image->path);
|
||||
}
|
||||
|
||||
|
||||
107
composer.lock
generated
107
composer.lock
generated
@@ -58,16 +58,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.222.1",
|
||||
"version": "3.222.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "632621d97180e82d3adc1245a7b272774c30dbf5"
|
||||
"reference": "03d35eef5c509798d2c08587cfd9a7c33afe2260"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/632621d97180e82d3adc1245a7b272774c30dbf5",
|
||||
"reference": "632621d97180e82d3adc1245a7b272774c30dbf5",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/03d35eef5c509798d2c08587cfd9a7c33afe2260",
|
||||
"reference": "03d35eef5c509798d2c08587cfd9a7c33afe2260",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -143,9 +143,9 @@
|
||||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.222.1"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.222.7"
|
||||
},
|
||||
"time": "2022-04-28T18:17:24+00:00"
|
||||
"time": "2022-05-06T18:16:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -563,22 +563,22 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "3.3.5",
|
||||
"version": "3.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/dbal.git",
|
||||
"reference": "719663b15983278227669c8595151586a2ff3327"
|
||||
"reference": "9e7f76dd1cde81c62574fdffa5a9c655c847ad21"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/719663b15983278227669c8595151586a2ff3327",
|
||||
"reference": "719663b15983278227669c8595151586a2ff3327",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/9e7f76dd1cde81c62574fdffa5a9c655c847ad21",
|
||||
"reference": "9e7f76dd1cde81c62574fdffa5a9c655c847ad21",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2",
|
||||
"doctrine/cache": "^1.11|^2.0",
|
||||
"doctrine/deprecations": "^0.5.3",
|
||||
"doctrine/deprecations": "^0.5.3|^1",
|
||||
"doctrine/event-manager": "^1.0",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"psr/cache": "^1|^2|^3",
|
||||
@@ -586,15 +586,15 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "9.0.0",
|
||||
"jetbrains/phpstorm-stubs": "2021.1",
|
||||
"phpstan/phpstan": "1.5.3",
|
||||
"phpstan/phpstan-strict-rules": "^1.1",
|
||||
"phpunit/phpunit": "9.5.16",
|
||||
"jetbrains/phpstorm-stubs": "2022.1",
|
||||
"phpstan/phpstan": "1.6.3",
|
||||
"phpstan/phpstan-strict-rules": "^1.2",
|
||||
"phpunit/phpunit": "9.5.20",
|
||||
"psalm/plugin-phpunit": "0.16.1",
|
||||
"squizlabs/php_codesniffer": "3.6.2",
|
||||
"symfony/cache": "^5.2|^6.0",
|
||||
"symfony/console": "^2.7|^3.0|^4.0|^5.0|^6.0",
|
||||
"vimeo/psalm": "4.22.0"
|
||||
"vimeo/psalm": "4.23.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
||||
@@ -654,7 +654,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/dbal/issues",
|
||||
"source": "https://github.com/doctrine/dbal/tree/3.3.5"
|
||||
"source": "https://github.com/doctrine/dbal/tree/3.3.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -670,29 +670,29 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-05T09:50:18+00:00"
|
||||
"time": "2022-05-02T17:21:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"version": "v0.5.3",
|
||||
"version": "v1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/deprecations.git",
|
||||
"reference": "9504165960a1f83cc1480e2be1dd0a0478561314"
|
||||
"reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/9504165960a1f83cc1480e2be1dd0a0478561314",
|
||||
"reference": "9504165960a1f83cc1480e2be1dd0a0478561314",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
|
||||
"reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0|^7.0|^8.0",
|
||||
"phpunit/phpunit": "^7.0|^8.0|^9.0",
|
||||
"psr/log": "^1.0"
|
||||
"doctrine/coding-standard": "^9",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.5",
|
||||
"psr/log": "^1|^2|^3"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
|
||||
@@ -711,9 +711,9 @@
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/deprecations/issues",
|
||||
"source": "https://github.com/doctrine/deprecations/tree/v0.5.3"
|
||||
"source": "https://github.com/doctrine/deprecations/tree/v1.0.0"
|
||||
},
|
||||
"time": "2021-03-21T12:59:47+00:00"
|
||||
"time": "2022-05-02T15:47:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/event-manager",
|
||||
@@ -1790,16 +1790,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v8.83.10",
|
||||
"version": "v8.83.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "148ae59b7da6c3db6736374d357c5aaef9506fb7"
|
||||
"reference": "d85c34179f209977043502441f9e44ca432a14b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/148ae59b7da6c3db6736374d357c5aaef9506fb7",
|
||||
"reference": "148ae59b7da6c3db6736374d357c5aaef9506fb7",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/d85c34179f209977043502441f9e44ca432a14b4",
|
||||
"reference": "d85c34179f209977043502441f9e44ca432a14b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1959,7 +1959,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2022-04-27T14:07:37+00:00"
|
||||
"time": "2022-05-03T14:47:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
@@ -2909,16 +2909,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "2.57.0",
|
||||
"version": "2.58.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78"
|
||||
"reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4a54375c21eea4811dbd1149fe6b246517554e78",
|
||||
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/97a34af22bde8d0ac20ab34b29d7bfe360902055",
|
||||
"reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2936,7 +2936,8 @@
|
||||
"phpmd/phpmd": "^2.9",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12.54 || ^1.0",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
|
||||
"phpunit/php-file-iterator": "^2.0.5",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.23",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"bin": [
|
||||
@@ -3001,7 +3002,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-02-13T18:13:33+00:00"
|
||||
"time": "2022-04-25T19:31:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
@@ -4095,16 +4096,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psy/psysh",
|
||||
"version": "v0.11.2",
|
||||
"version": "v0.11.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bobthecow/psysh.git",
|
||||
"reference": "7f7da640d68b9c9fec819caae7c744a213df6514"
|
||||
"reference": "05c544b339b112226ad14803e1e5b09a61957454"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/7f7da640d68b9c9fec819caae7c744a213df6514",
|
||||
"reference": "7f7da640d68b9c9fec819caae7c744a213df6514",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/05c544b339b112226ad14803e1e5b09a61957454",
|
||||
"reference": "05c544b339b112226ad14803e1e5b09a61957454",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4119,15 +4120,13 @@
|
||||
"symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.2",
|
||||
"hoa/console": "3.17.05.02"
|
||||
"bamarni/composer-bin-plugin": "^1.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)",
|
||||
"ext-pdo-sqlite": "The doc command requires SQLite to work.",
|
||||
"ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.",
|
||||
"ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.",
|
||||
"hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit."
|
||||
"ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history."
|
||||
},
|
||||
"bin": [
|
||||
"bin/psysh"
|
||||
@@ -4167,9 +4166,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bobthecow/psysh/issues",
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.11.2"
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.11.4"
|
||||
},
|
||||
"time": "2022-02-28T15:28:54+00:00"
|
||||
"time": "2022-05-06T12:49:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
@@ -9005,16 +9004,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.6.3",
|
||||
"version": "1.6.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "6128620b98292e0b69ea6d799871d77163681c8e"
|
||||
"reference": "d41c39cb2e487663bce9bbd97c660e244b73abad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6128620b98292e0b69ea6d799871d77163681c8e",
|
||||
"reference": "6128620b98292e0b69ea6d799871d77163681c8e",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d41c39cb2e487663bce9bbd97c660e244b73abad",
|
||||
"reference": "d41c39cb2e487663bce9bbd97c660e244b73abad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9040,7 +9039,7 @@
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.6.3"
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.6.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9060,7 +9059,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-28T11:27:53+00:00"
|
||||
"time": "2022-05-04T22:55:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
62
public/dist/app.js
vendored
62
public/dist/app.js
vendored
File diff suppressed because one or more lines are too long
33
public/dist/code.js
vendored
33
public/dist/code.js
vendored
File diff suppressed because one or more lines are too long
1
public/dist/export-styles.css
vendored
1
public/dist/export-styles.css
vendored
File diff suppressed because one or more lines are too long
1
public/dist/print-styles.css
vendored
1
public/dist/print-styles.css
vendored
@@ -1 +0,0 @@
|
||||
:root{--color-primary: #206ea7;--color-primary-light: rgba(32,110,167,0.15);--color-page: #206ea7;--color-page-draft: #7e50b1;--color-chapter: #af4d0d;--color-book: #077b70;--color-bookshelf: #a94747}header{display:none}html,body{font-size:12px;background-color:#fff}.page-content{margin:0 auto}.print-hidden{display:none !important}.tri-layout-container{grid-template-columns:1fr;grid-template-areas:"b";margin-inline-start:0;margin-inline-end:0;display:block}.card{box-shadow:none}.content-wrap.card{padding-inline-start:0;padding-inline-end:0}/*# sourceMappingURL=print-styles.css.map */
|
||||
1
public/dist/styles.css
vendored
1
public/dist/styles.css
vendored
File diff suppressed because one or more lines are too long
@@ -18,10 +18,8 @@ class MarkdownEditor {
|
||||
this.markdown = new MarkdownIt({html: true});
|
||||
this.markdown.use(mdTasksLists, {label: true});
|
||||
|
||||
this.display = this.elem.querySelector('.markdown-display');
|
||||
|
||||
this.displayStylesLoaded = false;
|
||||
this.input = this.elem.querySelector('textarea');
|
||||
this.display = this.$refs.display;
|
||||
this.input = this.$refs.input;
|
||||
|
||||
this.cm = null;
|
||||
this.Code = null;
|
||||
@@ -32,23 +30,13 @@ class MarkdownEditor {
|
||||
});
|
||||
|
||||
this.onMarkdownScroll = this.onMarkdownScroll.bind(this);
|
||||
|
||||
const displayLoad = () => {
|
||||
this.displayDoc = this.display.contentDocument;
|
||||
this.init(cmLoadPromise);
|
||||
};
|
||||
|
||||
if (this.display.contentDocument.readyState === 'complete') {
|
||||
displayLoad();
|
||||
} else {
|
||||
this.display.addEventListener('load', displayLoad.bind(this));
|
||||
}
|
||||
|
||||
window.$events.emitPublic(this.elem, 'editor-markdown::setup', {
|
||||
markdownIt: this.markdown,
|
||||
displayEl: this.display,
|
||||
codeMirrorInstance: this.cm,
|
||||
});
|
||||
|
||||
this.init(cmLoadPromise);
|
||||
}
|
||||
|
||||
init(cmLoadPromise) {
|
||||
@@ -56,17 +44,17 @@ class MarkdownEditor {
|
||||
let lastClick = 0;
|
||||
|
||||
// Prevent markdown display link click redirect
|
||||
this.displayDoc.addEventListener('click', event => {
|
||||
let isDblClick = Date.now() - lastClick < 300;
|
||||
this.display.addEventListener('click', event => {
|
||||
const isDblClick = Date.now() - lastClick < 300;
|
||||
|
||||
let link = event.target.closest('a');
|
||||
const link = event.target.closest('a');
|
||||
if (link !== null) {
|
||||
event.preventDefault();
|
||||
window.open(link.getAttribute('href'));
|
||||
return;
|
||||
}
|
||||
|
||||
let drawing = event.target.closest('[drawio-diagram]');
|
||||
const drawing = event.target.closest('[drawio-diagram]');
|
||||
if (drawing !== null && isDblClick) {
|
||||
this.actionEditDrawing(drawing);
|
||||
return;
|
||||
@@ -77,10 +65,10 @@ class MarkdownEditor {
|
||||
|
||||
// Button actions
|
||||
this.elem.addEventListener('click', event => {
|
||||
let button = event.target.closest('button[data-action]');
|
||||
const button = event.target.closest('button[data-action]');
|
||||
if (button === null) return;
|
||||
|
||||
let action = button.getAttribute('data-action');
|
||||
const action = button.getAttribute('data-action');
|
||||
if (action === 'insertImage') this.actionInsertImage();
|
||||
if (action === 'insertLink') this.actionShowLinkSelector();
|
||||
if (action === 'insertDrawing' && (event.ctrlKey || event.metaKey)) {
|
||||
@@ -132,35 +120,11 @@ class MarkdownEditor {
|
||||
window.$events.emit('editor-markdown-change', content);
|
||||
|
||||
// Set body content
|
||||
this.displayDoc.body.className = 'page-content';
|
||||
this.displayDoc.body.innerHTML = html;
|
||||
|
||||
// Copy styles from page head and set custom styles for editor
|
||||
this.loadStylesIntoDisplay();
|
||||
}
|
||||
|
||||
loadStylesIntoDisplay() {
|
||||
if (this.displayStylesLoaded) return;
|
||||
this.displayDoc.documentElement.classList.add('markdown-editor-display');
|
||||
// Set display to be dark mode if parent is
|
||||
|
||||
if (document.documentElement.classList.contains('dark-mode')) {
|
||||
this.displayDoc.documentElement.style.backgroundColor = '#222';
|
||||
this.displayDoc.documentElement.classList.add('dark-mode');
|
||||
}
|
||||
|
||||
this.displayDoc.head.innerHTML = '';
|
||||
const styles = document.head.querySelectorAll('style,link[rel=stylesheet]');
|
||||
for (let style of styles) {
|
||||
const copy = style.cloneNode(true);
|
||||
this.displayDoc.head.appendChild(copy);
|
||||
}
|
||||
|
||||
this.displayStylesLoaded = true;
|
||||
this.display.innerHTML = html;
|
||||
}
|
||||
|
||||
onMarkdownScroll(lineCount) {
|
||||
const elems = this.displayDoc.body.children;
|
||||
const elems = this.display.children;
|
||||
if (elems.length <= lineCount) return;
|
||||
|
||||
const topElem = (lineCount === -1) ? elems[elems.length-1] : elems[lineCount];
|
||||
@@ -317,7 +281,7 @@ class MarkdownEditor {
|
||||
let cursor = cm.getCursor();
|
||||
let lineContent = cm.getLine(cursor.line);
|
||||
let lineLen = lineContent.length;
|
||||
let newLineContent = lineContent;
|
||||
let newLineContent;
|
||||
|
||||
if (lineContent.indexOf(start) === 0 && lineContent.slice(-end.length) === end) {
|
||||
newLineContent = lineContent.slice(start.length, lineContent.length - end.length);
|
||||
@@ -333,9 +297,9 @@ class MarkdownEditor {
|
||||
let selection = cm.getSelection();
|
||||
if (selection === '') return wrapLine(start, end);
|
||||
|
||||
let newSelection = selection;
|
||||
let newSelection;
|
||||
let frontDiff = 0;
|
||||
let endDiff = 0;
|
||||
let endDiff;
|
||||
|
||||
if (selection.indexOf(start) === 0 && selection.slice(-end.length) === end) {
|
||||
newSelection = selection.slice(start.length, selection.length - end.length);
|
||||
@@ -445,10 +409,10 @@ class MarkdownEditor {
|
||||
|
||||
DrawIO.show(url,() => {
|
||||
return Promise.resolve('');
|
||||
}, (pngData) => {
|
||||
}, (drawingData) => {
|
||||
|
||||
const data = {
|
||||
image: pngData,
|
||||
image: drawingData,
|
||||
uploaded_to: Number(this.pageId),
|
||||
};
|
||||
|
||||
@@ -462,7 +426,7 @@ class MarkdownEditor {
|
||||
}
|
||||
|
||||
insertDrawing(image, originalCursor) {
|
||||
const newText = `<div drawio-diagram="${image.id}"><img src="${image.url}"></div>`;
|
||||
const newText = DrawIO.buildDrawingContentHtml(image);
|
||||
this.cm.focus();
|
||||
this.cm.replaceSelection(newText);
|
||||
this.cm.setCursor(originalCursor.line, originalCursor.ch + newText.length);
|
||||
@@ -480,21 +444,22 @@ class MarkdownEditor {
|
||||
|
||||
DrawIO.show(drawioUrl, () => {
|
||||
return DrawIO.load(drawingId);
|
||||
}, (pngData) => {
|
||||
}, (drawingData) => {
|
||||
|
||||
let data = {
|
||||
image: pngData,
|
||||
image: drawingData,
|
||||
uploaded_to: Number(this.pageId),
|
||||
};
|
||||
|
||||
window.$http.post("/images/drawio", data).then(resp => {
|
||||
let newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
|
||||
let newContent = this.cm.getValue().split('\n').map(line => {
|
||||
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {
|
||||
return newText;
|
||||
}
|
||||
return line;
|
||||
const image = resp.data;
|
||||
const newText = DrawIO.buildDrawingContentHtml(image);
|
||||
|
||||
const newContent = this.cm.getValue().split('\n').map(line => {
|
||||
const isDrawing = line.includes(`drawio-diagram="${drawingId}"`);
|
||||
return isDrawing ? newText : line;
|
||||
}).join('\n');
|
||||
|
||||
this.cm.setValue(newContent);
|
||||
this.cm.setCursor(cursorPos);
|
||||
this.cm.focus();
|
||||
|
||||
@@ -24,7 +24,7 @@ class PageEditor {
|
||||
this.draftDisplayIcon = this.$refs.draftDisplayIcon;
|
||||
this.changelogInput = this.$refs.changelogInput;
|
||||
this.changelogDisplay = this.$refs.changelogDisplay;
|
||||
this.changeEditorButtons = this.$manyRefs.changeEditor;
|
||||
this.changeEditorButtons = this.$manyRefs.changeEditor || [];
|
||||
this.switchDialogContainer = this.$refs.switchDialog;
|
||||
|
||||
// Translations
|
||||
|
||||
@@ -55,7 +55,7 @@ function drawEventExport(message) {
|
||||
}
|
||||
|
||||
function drawEventSave(message) {
|
||||
drawPostMessage({action: 'export', format: 'xmlpng', xml: message.xml, spin: 'Updating drawing'});
|
||||
drawPostMessage({action: 'export', format: 'xmlsvg', xml: message.xml, spin: 'Updating drawing'});
|
||||
}
|
||||
|
||||
function drawEventInit() {
|
||||
@@ -96,7 +96,21 @@ async function upload(imageData, pageUploadedToId) {
|
||||
*/
|
||||
async function load(drawingId) {
|
||||
const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
|
||||
return `data:image/png;base64,${resp.data.content}`;
|
||||
return resp.data.content;
|
||||
}
|
||||
|
||||
export default {show, close, upload, load};
|
||||
|
||||
function buildDrawingContentHtml(drawing) {
|
||||
const isSvg = drawing.url.split('.').pop().toLowerCase() === 'svg';
|
||||
const image = `<img src="${drawing.url}">`;
|
||||
const embed = `<embed src="${drawing.url}" type="image/svg+xml">`;
|
||||
return `<div drawio-diagram="${drawing.id}">${isSvg ? embed : image}</div>`
|
||||
}
|
||||
|
||||
function buildDrawingContentNode(drawing) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = buildDrawingContentHtml(drawing);
|
||||
return div.children[0];
|
||||
}
|
||||
|
||||
export default {show, close, upload, load, buildDrawingContentHtml, buildDrawingContentNode};
|
||||
@@ -1,4 +1,5 @@
|
||||
import DrawIO from "../services/drawio";
|
||||
import {build} from "./config";
|
||||
|
||||
let pageEditor = null;
|
||||
let currentNode = null;
|
||||
@@ -15,15 +16,14 @@ function isDrawing(node) {
|
||||
function showDrawingManager(mceEditor, selectedNode = null) {
|
||||
pageEditor = mceEditor;
|
||||
currentNode = selectedNode;
|
||||
|
||||
// Show image manager
|
||||
window.ImageManager.show(function (image) {
|
||||
if (selectedNode) {
|
||||
let imgElem = selectedNode.querySelector('img');
|
||||
pageEditor.dom.setAttrib(imgElem, 'src', image.url);
|
||||
pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
|
||||
pageEditor.dom.replace(buildDrawingNode(image), selectedNode);
|
||||
} else {
|
||||
let imgHTML = `<div drawio-diagram="${image.id}" contenteditable="false"><img src="${image.url}"></div>`;
|
||||
pageEditor.insertContent(imgHTML);
|
||||
const drawingHtml = DrawIO.buildDrawingContentHtml(image);
|
||||
pageEditor.insertContent(drawingHtml);
|
||||
}
|
||||
}, 'drawio');
|
||||
}
|
||||
@@ -34,7 +34,14 @@ function showDrawingEditor(mceEditor, selectedNode = null) {
|
||||
DrawIO.show(options.drawioUrl, drawingInit, updateContent);
|
||||
}
|
||||
|
||||
async function updateContent(pngData) {
|
||||
function buildDrawingNode(drawing) {
|
||||
const drawingEl = DrawIO.buildDrawingContentNode(drawing);
|
||||
drawingEl.setAttribute('contenteditable', 'false');
|
||||
drawingEl.setAttribute('data-ephox-embed-iri', 'true');
|
||||
return drawingEl;
|
||||
}
|
||||
|
||||
async function updateContent(drawingData) {
|
||||
const id = "image-" + Math.random().toString(16).slice(2);
|
||||
const loadingImage = window.baseUrl('/loading.gif');
|
||||
|
||||
@@ -50,11 +57,9 @@ async function updateContent(pngData) {
|
||||
// Handle updating an existing image
|
||||
if (currentNode) {
|
||||
DrawIO.close();
|
||||
let imgElem = currentNode.querySelector('img');
|
||||
try {
|
||||
const img = await DrawIO.upload(pngData, options.pageId);
|
||||
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
|
||||
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
|
||||
const img = await DrawIO.upload(drawingData, options.pageId);
|
||||
pageEditor.dom.replace(buildDrawingNode(img), currentNode);
|
||||
} catch (err) {
|
||||
handleUploadError(err);
|
||||
}
|
||||
@@ -62,12 +67,11 @@ async function updateContent(pngData) {
|
||||
}
|
||||
|
||||
setTimeout(async () => {
|
||||
pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" id="${id}"></div>`);
|
||||
pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" alt="Loading" id="${id}"></div>`);
|
||||
DrawIO.close();
|
||||
try {
|
||||
const img = await DrawIO.upload(pngData, options.pageId);
|
||||
pageEditor.dom.setAttrib(id, 'src', img.url);
|
||||
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
|
||||
const img = await DrawIO.upload(drawingData, options.pageId);
|
||||
pageEditor.dom.replace(buildDrawingNode(img), pageEditor.dom.get(id).parentNode);
|
||||
} catch (err) {
|
||||
pageEditor.dom.remove(id);
|
||||
handleUploadError(err);
|
||||
@@ -86,7 +90,6 @@ function drawingInit() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {WysiwygConfigOptions} providedOptions
|
||||
* @return {function(Editor, string)}
|
||||
*/
|
||||
@@ -130,14 +133,28 @@ export function getPlugin(providedOptions) {
|
||||
showDrawingEditor(editor, selectedNode);
|
||||
});
|
||||
|
||||
editor.on('SetContent', function () {
|
||||
const drawings = editor.$('body > div[drawio-diagram]');
|
||||
if (!drawings.length) return;
|
||||
editor.on('PreInit', () => {
|
||||
editor.parser.addNodeFilter('div', function(nodes) {
|
||||
for (const node of nodes) {
|
||||
if (node.attr('drawio-diagram')) {
|
||||
// Set content editable to be false to prevent direct editing of child content.
|
||||
node.attr('contenteditable', 'false');
|
||||
// Set this attribute to prevent drawing contents being parsed as media embeds
|
||||
// to avoid contents being replaced with placeholder images.
|
||||
// TinyMCE embed plugin sources looks for this attribute in its logic.
|
||||
node.attr('data-ephox-embed-iri', 'true');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
editor.undoManager.transact(function () {
|
||||
drawings.each((index, elem) => {
|
||||
elem.setAttribute('contenteditable', 'false');
|
||||
});
|
||||
editor.serializer.addNodeFilter('div', function(nodes) {
|
||||
for (const node of nodes) {
|
||||
// Clean up content attributes
|
||||
if (node.attr('drawio-diagram')) {
|
||||
node.attr('contenteditable', null);
|
||||
node.attr('data-ephox-embed-iri', null);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -7,61 +7,61 @@ return [
|
||||
|
||||
// Pages
|
||||
'page_create' => 'تم إنشاء صفحة',
|
||||
'page_create_notification' => 'Page successfully created',
|
||||
'page_create_notification' => 'تم إنشاء الصفحة بنجاح',
|
||||
'page_update' => 'تم تحديث الصفحة',
|
||||
'page_update_notification' => 'Page successfully updated',
|
||||
'page_update_notification' => 'تم تحديث الصفحة بنجاح',
|
||||
'page_delete' => 'تم حذف الصفحة',
|
||||
'page_delete_notification' => 'Page successfully deleted',
|
||||
'page_delete_notification' => 'تم حذف الصفحة بنجاح',
|
||||
'page_restore' => 'تمت استعادة الصفحة',
|
||||
'page_restore_notification' => 'Page successfully restored',
|
||||
'page_restore_notification' => 'تمت استعادة الصفحة بنجاح',
|
||||
'page_move' => 'تم نقل الصفحة',
|
||||
|
||||
// Chapters
|
||||
'chapter_create' => 'تم إنشاء فصل',
|
||||
'chapter_create_notification' => 'Chapter successfully created',
|
||||
'chapter_create_notification' => 'تم إنشاء الفصل بنجاح',
|
||||
'chapter_update' => 'تم تحديث الفصل',
|
||||
'chapter_update_notification' => 'Chapter successfully updated',
|
||||
'chapter_update_notification' => 'تم تحديث الفصل بنجاح',
|
||||
'chapter_delete' => 'تم حذف الفصل',
|
||||
'chapter_delete_notification' => 'Chapter successfully deleted',
|
||||
'chapter_delete_notification' => 'تم حذف الفصل بنجاح',
|
||||
'chapter_move' => 'تم نقل الفصل',
|
||||
|
||||
// Books
|
||||
'book_create' => 'تم إنشاء كتاب',
|
||||
'book_create_notification' => 'Book successfully created',
|
||||
'book_create_notification' => 'تم إنشاء الكتاب بنجاح',
|
||||
'book_update' => 'تم تحديث الكتاب',
|
||||
'book_update_notification' => 'Book successfully updated',
|
||||
'book_update_notification' => 'تم تحديث الكتاب بنجاح',
|
||||
'book_delete' => 'تم حذف الكتاب',
|
||||
'book_delete_notification' => 'Book successfully deleted',
|
||||
'book_delete_notification' => 'تم حذف الكتاب بنجاح',
|
||||
'book_sort' => 'تم سرد الكتاب',
|
||||
'book_sort_notification' => 'Book successfully re-sorted',
|
||||
'book_sort_notification' => 'تم إعادة فرز الكتاب بنجاح',
|
||||
|
||||
// Bookshelves
|
||||
'bookshelf_create' => 'created bookshelf',
|
||||
'bookshelf_create_notification' => 'Bookshelf successfully created',
|
||||
'bookshelf_create' => 'تم إنشاء رف كتب',
|
||||
'bookshelf_create_notification' => 'تم إنشاء الرف بنجاح',
|
||||
'bookshelf_update' => 'تم تحديث الرف',
|
||||
'bookshelf_update_notification' => 'Bookshelf successfully updated',
|
||||
'bookshelf_update_notification' => 'تم تحديث الرف بنجاح',
|
||||
'bookshelf_delete' => 'تم تحديث الرف',
|
||||
'bookshelf_delete_notification' => 'Bookshelf successfully deleted',
|
||||
'bookshelf_delete_notification' => 'تم حذف الرف بنجاح',
|
||||
|
||||
// Favourites
|
||||
'favourite_add_notification' => '":name" has been added to your favourites',
|
||||
'favourite_remove_notification' => '":name" has been removed from your favourites',
|
||||
'favourite_add_notification' => 'تم إضافة ":name" إلى المفضلة لديك',
|
||||
'favourite_remove_notification' => 'تم إزالة ":name" من المفضلة لديك',
|
||||
|
||||
// MFA
|
||||
'mfa_setup_method_notification' => 'Multi-factor method successfully configured',
|
||||
'mfa_remove_method_notification' => 'Multi-factor method successfully removed',
|
||||
'mfa_setup_method_notification' => 'تم تكوين طريقة متعددة العوامل بنجاح',
|
||||
'mfa_remove_method_notification' => 'تمت إزالة طريقة متعددة العوامل بنجاح',
|
||||
|
||||
// Webhooks
|
||||
'webhook_create' => 'created webhook',
|
||||
'webhook_create_notification' => 'Webhook successfully created',
|
||||
'webhook_update' => 'updated webhook',
|
||||
'webhook_update_notification' => 'Webhook successfully updated',
|
||||
'webhook_delete' => 'deleted webhook',
|
||||
'webhook_delete_notification' => 'Webhook successfully deleted',
|
||||
'webhook_create' => 'تم إنشاء webhook',
|
||||
'webhook_create_notification' => 'تم إنشاء Webhook بنجاح',
|
||||
'webhook_update' => 'تم تحديث webhook',
|
||||
'webhook_update_notification' => 'تم تحديث Webhook بنجاح',
|
||||
'webhook_delete' => 'حذف webhook',
|
||||
'webhook_delete_notification' => 'تم حذف Webhook بنجاح',
|
||||
|
||||
// Users
|
||||
'user_update_notification' => 'User successfully updated',
|
||||
'user_delete_notification' => 'User successfully removed',
|
||||
'user_update_notification' => 'تم تحديث المستخدم بنجاح',
|
||||
'user_delete_notification' => 'تم إزالة المستخدم بنجاح',
|
||||
|
||||
// Other
|
||||
'commented_on' => 'تم التعليق',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'Hebraisk',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -282,6 +282,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung
|
||||
'es_AR' => 'Spanisch Argentinisch',
|
||||
'et' => 'Estnisch',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Französisch',
|
||||
'he' => 'Hebräisch',
|
||||
'hr' => 'Kroatisch',
|
||||
|
||||
@@ -282,6 +282,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung
|
||||
'es_AR' => 'Spanisch Argentinisch',
|
||||
'et' => 'Estnisch',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Französisch',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Kroatisch',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Francés',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Croata',
|
||||
|
||||
@@ -280,6 +280,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Francés',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Croata',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina (Argentiina hispaania keel)',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français (prantsuse keel)',
|
||||
'he' => 'עברית (heebrea keel)',
|
||||
'hr' => 'Hrvatski (horvaadi keel)',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Espagnol (Argentine)',
|
||||
'et' => 'Estonien',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'Hébreu',
|
||||
'hr' => 'Croate',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Spagnolo d\'Argentina',
|
||||
'et' => 'Estone',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Francese',
|
||||
'he' => 'Ebraico',
|
||||
'hr' => 'Croato',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => '히브리어',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -7,164 +7,164 @@
|
||||
*/
|
||||
return [
|
||||
// General editor terms
|
||||
'general' => 'General',
|
||||
'advanced' => 'Advanced',
|
||||
'none' => 'None',
|
||||
'general' => 'Vispārīgi',
|
||||
'advanced' => 'Papildu iespējas',
|
||||
'none' => 'Neviens',
|
||||
'cancel' => 'Atcelt',
|
||||
'save' => 'Saglabāt',
|
||||
'close' => 'Aizvērt',
|
||||
'undo' => 'Undo',
|
||||
'redo' => 'Redo',
|
||||
'left' => 'Left',
|
||||
'center' => 'Center',
|
||||
'right' => 'Right',
|
||||
'top' => 'Top',
|
||||
'middle' => 'Middle',
|
||||
'bottom' => 'Bottom',
|
||||
'undo' => 'Atsaukt',
|
||||
'redo' => 'Atcelt atsaukšanu',
|
||||
'left' => 'Pa kreisi',
|
||||
'center' => 'Centrā',
|
||||
'right' => 'Pa labi',
|
||||
'top' => 'Augšā',
|
||||
'middle' => 'Vidū',
|
||||
'bottom' => 'Apakšā',
|
||||
'width' => 'Platums',
|
||||
'height' => 'Augstums',
|
||||
'More' => 'Vairāk',
|
||||
'select' => 'Select...',
|
||||
'select' => 'Atlasīt...',
|
||||
|
||||
// Toolbar
|
||||
'formats' => 'Formāti',
|
||||
'header_large' => 'Large Header',
|
||||
'header_medium' => 'Medium Header',
|
||||
'header_small' => 'Small Header',
|
||||
'header_tiny' => 'Tiny Header',
|
||||
'header_large' => 'Liels virsraksts',
|
||||
'header_medium' => 'Vidējs virsraksts',
|
||||
'header_small' => 'Mazs virsraksts',
|
||||
'header_tiny' => 'Ļoti mazs virsraksts',
|
||||
'paragraph' => 'Rindkopa',
|
||||
'blockquote' => 'Blockquote',
|
||||
'inline_code' => 'Inline code',
|
||||
'blockquote' => 'Citāts',
|
||||
'inline_code' => 'Kods iekļauts rindā',
|
||||
'callouts' => 'Norādes',
|
||||
'callout_information' => 'Informācija',
|
||||
'callout_success' => 'Success',
|
||||
'callout_success' => 'Veiksmīgi',
|
||||
'callout_warning' => 'Brīdinājums',
|
||||
'callout_danger' => 'Danger',
|
||||
'bold' => 'Bold',
|
||||
'italic' => 'Italic',
|
||||
'underline' => 'Underline',
|
||||
'strikethrough' => 'Strikethrough',
|
||||
'superscript' => 'Superscript',
|
||||
'subscript' => 'Subscript',
|
||||
'callout_danger' => 'Bīstami',
|
||||
'bold' => 'Treknraksts',
|
||||
'italic' => 'Slīpraksts',
|
||||
'underline' => 'Pasvītrojums',
|
||||
'strikethrough' => 'Pārsvītrojums',
|
||||
'superscript' => 'Augšraksts',
|
||||
'subscript' => 'Apakšraksts',
|
||||
'text_color' => 'Teksta krāsa',
|
||||
'custom_color' => 'Custom color',
|
||||
'remove_color' => 'Remove color',
|
||||
'custom_color' => 'Pielāgot krāsu',
|
||||
'remove_color' => 'Noņemt krāsu',
|
||||
'background_color' => 'Fona krāsa',
|
||||
'align_left' => 'Align left',
|
||||
'align_center' => 'Align center',
|
||||
'align_right' => 'Align right',
|
||||
'align_justify' => 'Justify',
|
||||
'list_bullet' => 'Bullet list',
|
||||
'align_left' => 'Līdzināt pa kreisi',
|
||||
'align_center' => 'Līdzināt pa vidu',
|
||||
'align_right' => 'Līdzināt pa labi',
|
||||
'align_justify' => 'Līdzināt gar abām malām',
|
||||
'list_bullet' => 'Nenumurēts saraksts',
|
||||
'list_numbered' => 'Numurēts saraksts',
|
||||
'list_task' => 'Task list',
|
||||
'list_task' => 'Uzdevumu saraksts',
|
||||
'indent_increase' => 'Palielināt atkāpi',
|
||||
'indent_decrease' => 'Samazināt atkāpi',
|
||||
'table' => 'Tabula',
|
||||
'insert_image' => 'Ievietot attēlu',
|
||||
'insert_image_title' => 'Insert/Edit Image',
|
||||
'insert_link' => 'Insert/edit link',
|
||||
'insert_link_title' => 'Insert/Edit Link',
|
||||
'insert_horizontal_line' => 'Insert horizontal line',
|
||||
'insert_code_block' => 'Insert code block',
|
||||
'insert_drawing' => 'Insert/edit drawing',
|
||||
'drawing_manager' => 'Drawing manager',
|
||||
'insert_media' => 'Insert/edit media',
|
||||
'insert_media_title' => 'Insert/Edit Media',
|
||||
'clear_formatting' => 'Clear formatting',
|
||||
'source_code' => 'Source code',
|
||||
'source_code_title' => 'Source Code',
|
||||
'fullscreen' => 'Fullscreen',
|
||||
'image_options' => 'Image options',
|
||||
'insert_image_title' => 'Ievietot/rediģēt attēlu',
|
||||
'insert_link' => 'Ievietot/rediģēt saiti',
|
||||
'insert_link_title' => 'Ievietot/rediģēt saiti',
|
||||
'insert_horizontal_line' => 'Ievietot horizontālu līniju',
|
||||
'insert_code_block' => 'Ievietot koda bloku',
|
||||
'insert_drawing' => 'Ievietot/rediģēt zīmējumu',
|
||||
'drawing_manager' => 'Zīmēšanas pārvaldnieks',
|
||||
'insert_media' => 'Ievietot/rediģēt mediju',
|
||||
'insert_media_title' => 'Ievietot/rediģēt mediju',
|
||||
'clear_formatting' => 'Notīrīt noformējumu',
|
||||
'source_code' => 'Pirmkods',
|
||||
'source_code_title' => 'Pirmkods',
|
||||
'fullscreen' => 'Pilnekrāns',
|
||||
'image_options' => 'Attēla uzstādījumu',
|
||||
|
||||
// Tables
|
||||
'table_properties' => 'Table properties',
|
||||
'table_properties_title' => 'Table Properties',
|
||||
'delete_table' => 'Delete table',
|
||||
'insert_row_before' => 'Insert row before',
|
||||
'insert_row_after' => 'Insert row after',
|
||||
'delete_row' => 'Delete row',
|
||||
'insert_column_before' => 'Insert column before',
|
||||
'insert_column_after' => 'Insert column after',
|
||||
'delete_column' => 'Delete column',
|
||||
'table_properties' => 'Tabulas īpašības',
|
||||
'table_properties_title' => 'Tabulas īpašības',
|
||||
'delete_table' => 'Dzēst tabulu',
|
||||
'insert_row_before' => 'Ievietot rindu augstāk',
|
||||
'insert_row_after' => 'Ievietot rindu zemāk',
|
||||
'delete_row' => 'Dzēst rindu',
|
||||
'insert_column_before' => 'Ievietot kolonnu pirms',
|
||||
'insert_column_after' => 'Ievietot kolonnu pēc',
|
||||
'delete_column' => 'Dzēst kolonnu',
|
||||
'table_cell' => 'Šūna',
|
||||
'table_row' => 'Rinda',
|
||||
'table_column' => 'Kolonna',
|
||||
'cell_properties' => 'Cell properties',
|
||||
'cell_properties_title' => 'Cell Properties',
|
||||
'cell_type' => 'Cell type',
|
||||
'cell_properties' => 'Šūnas īpašības',
|
||||
'cell_properties_title' => 'Šūnas īpašības',
|
||||
'cell_type' => 'Šūnas tips',
|
||||
'cell_type_cell' => 'Šūna',
|
||||
'cell_scope' => 'Scope',
|
||||
'cell_type_header' => 'Header cell',
|
||||
'merge_cells' => 'Merge cells',
|
||||
'split_cell' => 'Split cell',
|
||||
'table_row_group' => 'Row Group',
|
||||
'table_column_group' => 'Column Group',
|
||||
'horizontal_align' => 'Horizontal align',
|
||||
'vertical_align' => 'Vertical align',
|
||||
'border_width' => 'Border width',
|
||||
'border_style' => 'Border style',
|
||||
'border_color' => 'Border color',
|
||||
'row_properties' => 'Row properties',
|
||||
'row_properties_title' => 'Row Properties',
|
||||
'cut_row' => 'Cut row',
|
||||
'copy_row' => 'Copy row',
|
||||
'paste_row_before' => 'Paste row before',
|
||||
'paste_row_after' => 'Paste row after',
|
||||
'row_type' => 'Row type',
|
||||
'row_type_header' => 'Header',
|
||||
'row_type_body' => 'Body',
|
||||
'row_type_footer' => 'Footer',
|
||||
'alignment' => 'Alignment',
|
||||
'cut_column' => 'Cut column',
|
||||
'copy_column' => 'Copy column',
|
||||
'paste_column_before' => 'Paste column before',
|
||||
'paste_column_after' => 'Paste column after',
|
||||
'cell_padding' => 'Cell padding',
|
||||
'cell_spacing' => 'Cell spacing',
|
||||
'caption' => 'Caption',
|
||||
'show_caption' => 'Show caption',
|
||||
'constrain' => 'Constrain proportions',
|
||||
'cell_border_solid' => 'Solid',
|
||||
'cell_border_dotted' => 'Dotted',
|
||||
'cell_border_dashed' => 'Dashed',
|
||||
'cell_border_double' => 'Double',
|
||||
'cell_border_groove' => 'Groove',
|
||||
'cell_border_ridge' => 'Ridge',
|
||||
'cell_border_inset' => 'Inset',
|
||||
'cell_border_outset' => 'Outset',
|
||||
'cell_border_none' => 'None',
|
||||
'cell_border_hidden' => 'Hidden',
|
||||
'cell_scope' => 'Darbības lauks',
|
||||
'cell_type_header' => 'Galvenes šūna',
|
||||
'merge_cells' => 'Sapludināt šūnas',
|
||||
'split_cell' => 'Sadalīt šūnas',
|
||||
'table_row_group' => 'Rindu grupa',
|
||||
'table_column_group' => 'Kolonnu grupa',
|
||||
'horizontal_align' => 'Horizontāls novietojums',
|
||||
'vertical_align' => 'Vertikāls novietojums',
|
||||
'border_width' => 'Apmales platums',
|
||||
'border_style' => 'Apmales veids',
|
||||
'border_color' => 'Apmales krāsa',
|
||||
'row_properties' => 'Rindas īpašības',
|
||||
'row_properties_title' => 'Rindas īpašības',
|
||||
'cut_row' => 'Izgriezt rindu',
|
||||
'copy_row' => 'Kopēt rindu',
|
||||
'paste_row_before' => 'Ielīmēt rindu augstāk',
|
||||
'paste_row_after' => 'Ielīmēt rindu zemāk',
|
||||
'row_type' => 'Rindas tips',
|
||||
'row_type_header' => 'Galvene',
|
||||
'row_type_body' => 'Pamata saturs',
|
||||
'row_type_footer' => 'Kājene',
|
||||
'alignment' => 'Līdzināšana',
|
||||
'cut_column' => 'Izgriezt kolonnu',
|
||||
'copy_column' => 'Kopēt kolonnu',
|
||||
'paste_column_before' => 'Ielīmēt kolonnu pirms',
|
||||
'paste_column_after' => 'Ielīmēt kolonnu pēc',
|
||||
'cell_padding' => 'Šūnu iekšējais attālums',
|
||||
'cell_spacing' => 'Šūnu attālums',
|
||||
'caption' => 'Virsraksts',
|
||||
'show_caption' => 'Parādīt virsrakstu',
|
||||
'constrain' => 'Saglabāt proporcijas',
|
||||
'cell_border_solid' => 'Pilna',
|
||||
'cell_border_dotted' => 'Punktēta',
|
||||
'cell_border_dashed' => 'Raustīta līnija',
|
||||
'cell_border_double' => 'Dubulta',
|
||||
'cell_border_groove' => 'Iedoba',
|
||||
'cell_border_ridge' => 'Izcelta',
|
||||
'cell_border_inset' => 'Iespiesta',
|
||||
'cell_border_outset' => 'Pacelta',
|
||||
'cell_border_none' => 'Nekas',
|
||||
'cell_border_hidden' => 'Paslēpts',
|
||||
|
||||
// Images, links, details/summary & embed
|
||||
'source' => 'Source',
|
||||
'alt_desc' => 'Alternative description',
|
||||
'embed' => 'Embed',
|
||||
'paste_embed' => 'Paste your embed code below:',
|
||||
'source' => 'Avots',
|
||||
'alt_desc' => 'Alternatīvais apraksts',
|
||||
'embed' => 'Iekļaut',
|
||||
'paste_embed' => 'Iekopējiet savu iekļaušanas kodu zemāk:',
|
||||
'url' => 'URL',
|
||||
'text_to_display' => 'Text to display',
|
||||
'text_to_display' => 'Attēlojamais teksts',
|
||||
'title' => 'Nosaukums',
|
||||
'open_link' => 'Open link in...',
|
||||
'open_link_current' => 'Current window',
|
||||
'open_link_new' => 'New window',
|
||||
'insert_collapsible' => 'Insert collapsible block',
|
||||
'collapsible_unwrap' => 'Unwrap',
|
||||
'edit_label' => 'Edit label',
|
||||
'toggle_open_closed' => 'Toggle open/closed',
|
||||
'collapsible_edit' => 'Edit collapsible block',
|
||||
'toggle_label' => 'Toggle label',
|
||||
'open_link' => 'Atvērt saiti...',
|
||||
'open_link_current' => 'Šis logs',
|
||||
'open_link_new' => 'Jauns logs',
|
||||
'insert_collapsible' => 'Ievietot sakļaujamu bloku',
|
||||
'collapsible_unwrap' => 'Attīt',
|
||||
'edit_label' => 'Rediģēt marķējumu',
|
||||
'toggle_open_closed' => 'Pārslēgt atvērts/aizvērts',
|
||||
'collapsible_edit' => 'Rediģēt sakļaujamu bloku',
|
||||
'toggle_label' => 'Pārslēgt marķējumu',
|
||||
|
||||
// About view
|
||||
'about' => 'About the editor',
|
||||
'about_title' => 'About the WYSIWYG Editor',
|
||||
'editor_license' => 'Editor License & Copyright',
|
||||
'editor_tiny_license' => 'This editor is built using :tinyLink which is provided under an LGPL v2.1 license.',
|
||||
'editor_tiny_license_link' => 'The copyright and license details of TinyMCE can be found here.',
|
||||
'save_continue' => 'Save Page & Continue',
|
||||
'callouts_cycle' => '(Keep pressing to toggle through types)',
|
||||
'link_selector' => 'Link to content',
|
||||
'about' => 'Par redaktoru',
|
||||
'about_title' => 'Par WYSIWYG redaktoru',
|
||||
'editor_license' => 'Redaktora licence un autortiesības',
|
||||
'editor_tiny_license' => 'Šis redaktors ir izveidots, izmantojot :tinyLink, kas ir publicēts ar LGPL v2.1 licenci.',
|
||||
'editor_tiny_license_link' => 'TinyMCE autortiesības un licences detaļas var atrast šeit.',
|
||||
'save_continue' => 'Saglabāt lapu un turpināt',
|
||||
'callouts_cycle' => '(Turpiniet spiest, lai pārslēgtu tipus)',
|
||||
'link_selector' => 'Saite uz saturu',
|
||||
'shortcuts' => 'Saīsnes',
|
||||
'shortcut' => 'Saīsne',
|
||||
'shortcuts_intro' => 'The following shortcuts are available in the editor:',
|
||||
'shortcuts_intro' => 'Šajā redaktorā pieejamas šādas saīsnes:',
|
||||
'windows_linux' => '(Windows/Linux)',
|
||||
'mac' => '(Mac)',
|
||||
'description' => 'Apraksts',
|
||||
|
||||
@@ -196,19 +196,19 @@ return [
|
||||
'pages_edit_draft_save_at' => 'Melnraksts saglabāts ',
|
||||
'pages_edit_delete_draft' => 'Dzēst melnrakstu',
|
||||
'pages_edit_discard_draft' => 'Atmest malnrakstu',
|
||||
'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
|
||||
'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
|
||||
'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
|
||||
'pages_edit_switch_to_markdown' => 'Pārslēgties uz Markdown redaktoru',
|
||||
'pages_edit_switch_to_markdown_clean' => '(Iztīrītais saturs)',
|
||||
'pages_edit_switch_to_markdown_stable' => '(Stabilais saturs)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'Pārslēgties uz WYSIWYG redaktoru',
|
||||
'pages_edit_set_changelog' => 'Pievienot izmaiņu aprakstu',
|
||||
'pages_edit_enter_changelog_desc' => 'Ievadi nelielu aprakstu par vaiktajām izmaiņām',
|
||||
'pages_edit_enter_changelog' => 'Izmaiņu apraksts',
|
||||
'pages_editor_switch_title' => 'Switch Editor',
|
||||
'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
|
||||
'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
|
||||
'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
|
||||
'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.',
|
||||
'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.',
|
||||
'pages_editor_switch_title' => 'Pārslēgt redaktoru',
|
||||
'pages_editor_switch_are_you_sure' => 'Vai tiešām vēlaties pārslēgt šai lapai lietojamo redaktoru?',
|
||||
'pages_editor_switch_consider_following' => 'Pārslēdzot redaktorus, ņemiet vērā:',
|
||||
'pages_editor_switch_consideration_a' => 'Pēc saglabāšanas jaunā redaktora izvēle tiks izmantota nākotnē visiem lietotājiem, tai skaitā tiem, kam var nebūt tiesības pašiem mainīt redaktora veidu.',
|
||||
'pages_editor_switch_consideration_b' => 'Tas var noteiktos apstākļos novest pie iespējamiem noformējuma un sintakses zudumiem.',
|
||||
'pages_editor_switch_consideration_c' => 'Birku vai izmaiņu saraksta ieraksti, kas veikti kopš pēdējās saglabāšanas, nesaglabāsies kopā ar šīm izmaiņām.',
|
||||
'pages_save' => 'Saglabāt lapu',
|
||||
'pages_title' => 'Lapas virsraksts',
|
||||
'pages_name' => 'Lapas nosaukums',
|
||||
@@ -235,7 +235,7 @@ return [
|
||||
'pages_revisions_number' => '#',
|
||||
'pages_revisions_numbered' => 'Revīzija #:id',
|
||||
'pages_revisions_numbered_changes' => 'Revīzijas #:id izmaiņas',
|
||||
'pages_revisions_editor' => 'Editor Type',
|
||||
'pages_revisions_editor' => 'Redaktora veids',
|
||||
'pages_revisions_changelog' => 'Izmaiņu žurnāls',
|
||||
'pages_revisions_changes' => 'Izmaiņas',
|
||||
'pages_revisions_current' => 'Pašreizējā versija',
|
||||
|
||||
@@ -10,8 +10,8 @@ return [
|
||||
'settings' => 'Iestatījumi',
|
||||
'settings_save' => 'Saglabāt iestatījumus',
|
||||
'settings_save_success' => 'Iestatījumi saglabāti',
|
||||
'system_version' => 'System Version',
|
||||
'categories' => 'Categories',
|
||||
'system_version' => 'Sistēmas versija',
|
||||
'categories' => 'Kategorijas',
|
||||
|
||||
// App Settings
|
||||
'app_customization' => 'Pielāgojumi',
|
||||
@@ -27,8 +27,8 @@ return [
|
||||
'app_secure_images' => 'Paaugstinātas drošības attēlu ielāde',
|
||||
'app_secure_images_toggle' => 'Ieslēgt paaugstinātas drošības attēlu ielādi',
|
||||
'app_secure_images_desc' => 'Ātrdarbības nolūkos attēli ir publiski pieejami. Šī opcija pievieno nejaušu grūti uzminamu teksta virkni attēlu adresēs. Pārliecinieties kā ir izslēgta direktoriju pārlūkošana, lai nepieļautu vieglu piekļuvi šiem failiem.',
|
||||
'app_default_editor' => 'Default Page Editor',
|
||||
'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
|
||||
'app_default_editor' => 'Noklusētais lapu redaktors',
|
||||
'app_default_editor_desc' => 'Izvēlieties noklusēto redaktoru jaunu lapu rediģēšanai. To iespējams norādīt arī lapu līmenī, ja piekļuves tiesības to atļauj.',
|
||||
'app_custom_html' => 'Pielāgot HTML head saturu',
|
||||
'app_custom_html_desc' => 'Šis saturs tiks pievienots <head> sadaļas apakšā visām lapām. Tas ir noderīgi papildinot CSS stilus vai pievienojot analītikas kodu.',
|
||||
'app_custom_html_disabled_notice' => 'Pielāgots HTML head saturs ir izslēgts šajā uzstādījumu lapā, lai nodrošinātu, ka iespējams atcelt jebkādas kritiskas izmaiņas.',
|
||||
@@ -152,7 +152,7 @@ return [
|
||||
'role_access_api' => 'Piekļūt sistēmas API',
|
||||
'role_manage_settings' => 'Pārvaldīt iestatījumus',
|
||||
'role_export_content' => 'Eksportēt saturu',
|
||||
'role_editor_change' => 'Change page editor',
|
||||
'role_editor_change' => 'Mainīt lapu redaktoru',
|
||||
'role_asset' => 'Resursa piekļuves tiesības',
|
||||
'roles_system_warning' => 'Jebkuras no trīs augstāk redzamajām atļaujām dod iespēju lietotājam mainīt savas un citu lietotāju sistēmas atļaujas. Pievieno šīs grupu atļaujas tikai tiem lietotājiem, kuriem uzticies.',
|
||||
'role_asset_desc' => 'Šīs piekļuves tiesības kontrolē noklusēto piekļuvi sistēmas resursiem. Grāmatām, nodaļām un lapām norādītās tiesības būs pārākas par šīm.',
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Igauņu',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina (Argentijns Spaans)',
|
||||
'et' => 'Eesti keel (Estisch)',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français (Frans)',
|
||||
'he' => 'עברית (Hebreeuws)',
|
||||
'hr' => 'Hrvatski (Kroatisch)',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Estoński',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -280,6 +280,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'İbranice',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -24,7 +24,7 @@ return [
|
||||
'width' => 'Ширина',
|
||||
'height' => 'Висота',
|
||||
'More' => 'Більше',
|
||||
'select' => 'Select...',
|
||||
'select' => 'Вибрати…',
|
||||
|
||||
// Toolbar
|
||||
'formats' => 'Формати',
|
||||
@@ -53,10 +53,10 @@ return [
|
||||
'align_left' => 'Вирівняти по лівому краю',
|
||||
'align_center' => 'Вирівняти по центру',
|
||||
'align_right' => 'Вирівнювання по правому краю',
|
||||
'align_justify' => 'Justify',
|
||||
'align_justify' => 'За шириною',
|
||||
'list_bullet' => 'Маркований список',
|
||||
'list_numbered' => 'Нумерований список',
|
||||
'list_task' => 'Task list',
|
||||
'list_task' => 'Список завдань',
|
||||
'indent_increase' => 'Збільшити відступ',
|
||||
'indent_decrease' => 'Зменшити відступ',
|
||||
'table' => 'Таблиця',
|
||||
@@ -95,8 +95,8 @@ return [
|
||||
'cell_type_cell' => 'Комірка',
|
||||
'cell_scope' => 'Scope',
|
||||
'cell_type_header' => 'Комірка заголовка',
|
||||
'merge_cells' => 'Merge cells',
|
||||
'split_cell' => 'Split cell',
|
||||
'merge_cells' => 'Об\'єднати комірки',
|
||||
'split_cell' => 'Роз\'єднати комірку',
|
||||
'table_row_group' => 'Група рядків',
|
||||
'table_column_group' => 'Група стовпців',
|
||||
'horizontal_align' => 'Горизонтальне вирівнювання',
|
||||
@@ -154,7 +154,7 @@ return [
|
||||
'toggle_label' => 'Перемкнути ярлики',
|
||||
|
||||
// About view
|
||||
'about' => 'About the editor',
|
||||
'about' => 'Про редактор',
|
||||
'about_title' => 'Про WYSIWYG редактор',
|
||||
'editor_license' => 'Ліцензія редактора і авторські права',
|
||||
'editor_tiny_license' => 'Цей редактор побудований за допомогою :tinyLink що забезпечується під ліцензією LGPL v2.1.',
|
||||
|
||||
@@ -196,14 +196,14 @@ return [
|
||||
'pages_edit_draft_save_at' => 'Чернетка збережена о ',
|
||||
'pages_edit_delete_draft' => 'Видалити чернетку',
|
||||
'pages_edit_discard_draft' => 'Відхилити чернетку',
|
||||
'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor',
|
||||
'pages_edit_switch_to_markdown_clean' => '(Clean Content)',
|
||||
'pages_edit_switch_to_markdown_stable' => '(Stable Content)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor',
|
||||
'pages_edit_switch_to_markdown' => 'Змінити редактор на Markdown',
|
||||
'pages_edit_switch_to_markdown_clean' => '(Очистити вміст)',
|
||||
'pages_edit_switch_to_markdown_stable' => '(Стабілізувати вміст)',
|
||||
'pages_edit_switch_to_wysiwyg' => 'Змінити редактор на WYSIWYG',
|
||||
'pages_edit_set_changelog' => 'Встановити журнал змін',
|
||||
'pages_edit_enter_changelog_desc' => 'Введіть короткий опис внесених вами змін',
|
||||
'pages_edit_enter_changelog' => 'Введіть список змін',
|
||||
'pages_editor_switch_title' => 'Switch Editor',
|
||||
'pages_editor_switch_title' => 'Змінити редактор',
|
||||
'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?',
|
||||
'pages_editor_switch_consider_following' => 'Consider the following when changing editors:',
|
||||
'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.',
|
||||
|
||||
@@ -10,8 +10,8 @@ return [
|
||||
'settings' => 'Налаштування',
|
||||
'settings_save' => 'Зберегти налаштування',
|
||||
'settings_save_success' => 'Налаштування збережено',
|
||||
'system_version' => 'System Version',
|
||||
'categories' => 'Categories',
|
||||
'system_version' => 'Версія',
|
||||
'categories' => 'Категорії',
|
||||
|
||||
// App Settings
|
||||
'app_customization' => 'Налаштування',
|
||||
@@ -27,8 +27,8 @@ return [
|
||||
'app_secure_images' => 'Вищі налаштування безпеки для зображень',
|
||||
'app_secure_images_toggle' => 'Увімкунти вищі налаштування безпеки для завантаження зображень',
|
||||
'app_secure_images_desc' => 'З міркувань продуктивності всі зображення є загальнодоступними. Цей параметр додає випадковий, важко передбачуваний рядок перед URL-адресами зображень. Переконайтеся, що індексація каталогів не активована, щоб запобігти легкому доступу.',
|
||||
'app_default_editor' => 'Default Page Editor',
|
||||
'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.',
|
||||
'app_default_editor' => 'Стандартний редактор сторінок',
|
||||
'app_default_editor_desc' => 'Виберіть, який редактор буде використовуватися за замовчуванням під час редагування нових сторінок. Це можна перевизначити на рівні дозволів сторінки.',
|
||||
'app_custom_html' => 'Користувацький вміст HTML-заголовку',
|
||||
'app_custom_html_desc' => 'Будь-який доданий тут вміст буде вставлено в нижню частину розділу <head> кожної сторінки. Це зручно для перевизначення стилів, або додавання коду аналітики.',
|
||||
'app_custom_html_disabled_notice' => 'На цій сторінці налаштувань відключений користувацький вміст заголовка HTML, щоб гарантувати, що будь-які невдалі зміни можна буде відновити.',
|
||||
@@ -152,7 +152,7 @@ return [
|
||||
'role_access_api' => 'Доступ до системного API',
|
||||
'role_manage_settings' => 'Керування налаштуваннями програми',
|
||||
'role_export_content' => 'Вміст експорту',
|
||||
'role_editor_change' => 'Change page editor',
|
||||
'role_editor_change' => 'Змінити редактор сторінок',
|
||||
'role_asset' => 'Дозволи',
|
||||
'roles_system_warning' => 'Майте на увазі, що доступ до будь-якого з вищезазначених трьох дозволів може дозволити користувачеві змінювати власні привілеї або привілеї інших в системі. Ролі з цими дозволами призначайте лише довіреним користувачам.',
|
||||
'role_asset_desc' => 'Ці дозволи контролюють стандартні доступи всередині системи. Права на книги, розділи та сторінки перевизначать ці дозволи.',
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => 'עברית',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -279,6 +279,7 @@ return [
|
||||
'es_AR' => 'Español Argentina',
|
||||
'et' => 'Eesti keel',
|
||||
'eu' => 'Euskara',
|
||||
'fa' => 'فارسی',
|
||||
'fr' => 'Français',
|
||||
'he' => '希伯來語',
|
||||
'hr' => 'Hrvatski',
|
||||
|
||||
@@ -114,26 +114,20 @@
|
||||
|
||||
.markdown-display {
|
||||
margin-inline-start: -1px;
|
||||
}
|
||||
|
||||
.markdown-editor-display {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
body {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
padding-inline-start: 16px;
|
||||
padding-inline-end: 16px;
|
||||
}
|
||||
padding: $-m;
|
||||
overflow-y: scroll;
|
||||
[drawio-diagram]:hover {
|
||||
outline: 2px solid var(--color-primary);
|
||||
}
|
||||
[drawio-diagram] embed {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
html.markdown-editor-display.dark-mode {
|
||||
.dark-mode .markdown-display {
|
||||
background-color: #222;
|
||||
body {
|
||||
background-color: #222;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
|
||||
@@ -48,6 +48,11 @@ body.page-content.mce-content-body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Prevent interaction with embed contents
|
||||
.page-content.mce-content-body embed {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Details/summary editor usability
|
||||
.page-content.mce-content-body details summary {
|
||||
pointer-events: none;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<div class="mb-xs"><a href="#request-format">Request Format</a></div>
|
||||
<div class="mb-xs"><a href="#listing-endpoints">Listing Endpoints</a></div>
|
||||
<div class="mb-xs"><a href="#error-handling">Error Handling</a></div>
|
||||
<div class="mb-xs"><a href="#rate-limits">Rate Limits</a></div>
|
||||
</div>
|
||||
|
||||
@foreach($docs as $model => $endpoints)
|
||||
|
||||
@@ -160,4 +160,23 @@
|
||||
"message": "No authorization token found on the request"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</code></pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h5 id="rate-limits" class="text-mono mb-m">Rate Limits</h5>
|
||||
<p>
|
||||
The API has built-in per-user rate-limiting to prevent potential abuse using the API.
|
||||
By default, this is set to 180 requests per minute but this can be changed by an administrator
|
||||
by setting an "API_REQUESTS_PER_MIN" .env option like so:
|
||||
</p>
|
||||
|
||||
<pre><code class="language-bash"># The number of API requests that can be made per minute by a single user.
|
||||
API_REQUESTS_PER_MIN=180</code></pre>
|
||||
|
||||
<p>
|
||||
When the limit is reached you will receive a 429 "Too Many Attempts." error response.
|
||||
It's generally good practice to limit requests made from your API client, where possible, to avoid
|
||||
affecting normal use of the system caused by over-consuming system resources.
|
||||
Keep in mind there may be other rate-limiting factors such as web-server & firewall controls.
|
||||
</p>
|
||||
@@ -17,13 +17,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="{{ $cspNonce }}">
|
||||
setTimeout(async () => {
|
||||
const result = await window.components["confirm-dialog"][0].show();
|
||||
console.log({result});
|
||||
}, 1000);
|
||||
</script>
|
||||
|
||||
<div class="container" id="home-default">
|
||||
<div class="grid third gap-xxl no-row-gap" >
|
||||
<div>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
<div markdown-input class="flex flex-fill">
|
||||
<textarea id="markdown-editor-input"
|
||||
refs="markdown-editor@input"
|
||||
@if($errors->has('markdown')) class="text-neg" @endif
|
||||
name="markdown"
|
||||
rows="5">@if(isset($model) || old('markdown')){{ old('markdown') ?? ($model->markdown === '' ? $model->html : $model->markdown) }}@endif</textarea>
|
||||
@@ -34,7 +35,10 @@
|
||||
<div class="editor-toolbar">
|
||||
<div class="editor-toolbar-label">{{ trans('entities.pages_md_preview') }}</div>
|
||||
</div>
|
||||
<iframe src="about:blank" class="markdown-display" sandbox="allow-same-origin"></iframe>
|
||||
<div class="markdown-display">
|
||||
<div refs="markdown-editor@display"
|
||||
class="page-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -615,7 +615,7 @@ class LdapTest extends TestCase
|
||||
|
||||
public function test_dump_user_details_option_works()
|
||||
{
|
||||
config()->set(['services.ldap.dump_user_details' => true]);
|
||||
config()->set(['services.ldap.dump_user_details' => true, 'services.ldap.thumbnail_attribute' => 'jpegphoto']);
|
||||
|
||||
$this->commonLdapMocks(1, 1, 1, 1, 1);
|
||||
$this->mockLdap->shouldReceive('searchAndGetEntries')->times(1)
|
||||
@@ -623,7 +623,9 @@ class LdapTest extends TestCase
|
||||
->andReturn(['count' => 1, 0 => [
|
||||
'uid' => [$this->mockUser->name],
|
||||
'cn' => [$this->mockUser->name],
|
||||
'dn' => ['dc=test' . config('services.ldap.base_dn')],
|
||||
// Test dumping binary data for avatar responses
|
||||
'jpegphoto' => base64_decode('/9j/4AAQSkZJRg=='),
|
||||
'dn' => ['dc=test' . config('services.ldap.base_dn')],
|
||||
]]);
|
||||
|
||||
$resp = $this->post('/login', [
|
||||
|
||||
@@ -258,6 +258,24 @@ class ExportTest extends TestCase
|
||||
unlink($testFilePath);
|
||||
}
|
||||
|
||||
public function test_page_export_contained_html_embed_elements_are_converted_to_images_with_srcs_inlined()
|
||||
{
|
||||
$page = Page::query()->first();
|
||||
$page->html = '<embed src="http://localhost/uploads/images/gallery/svg_test.svg"/>';
|
||||
$page->save();
|
||||
|
||||
$storageDisk = Storage::disk('local');
|
||||
$storageDisk->makeDirectory('uploads/images/gallery');
|
||||
$storageDisk->put('uploads/images/gallery/svg_test.svg', '<svg>good</svg>');
|
||||
|
||||
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
|
||||
|
||||
$storageDisk->delete('uploads/images/gallery/svg_test.svg');
|
||||
|
||||
$resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg', false);
|
||||
$resp->assertSee('<img src="data:image/svg+xml;base64,PHN2Zz5nb29kPC9zdmc+">', false);
|
||||
}
|
||||
|
||||
public function test_exports_removes_scripts_from_custom_head()
|
||||
{
|
||||
$entities = [
|
||||
|
||||
@@ -111,7 +111,7 @@ class TestResponse extends BaseTestResponse
|
||||
|
||||
foreach ($elements as $element) {
|
||||
$element = new Crawler($element);
|
||||
if (preg_match("/$pattern/i", $element->html())) {
|
||||
if (preg_match("/$pattern/i", $element->text())) {
|
||||
$matched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class DrawioTest extends TestCase
|
||||
{
|
||||
use UsesImages;
|
||||
|
||||
public function test_get_image_as_base64()
|
||||
public function test_get_image_as_base64_with_png_content()
|
||||
{
|
||||
$page = Page::first();
|
||||
$this->asAdmin();
|
||||
@@ -23,11 +23,27 @@ class DrawioTest extends TestCase
|
||||
|
||||
$imageGet = $this->getJson("/images/drawio/base64/{$image->id}");
|
||||
$imageGet->assertJson([
|
||||
'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=',
|
||||
'content' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_drawing_base64_upload()
|
||||
public function test_get_image_as_base64_with_svg_content()
|
||||
{
|
||||
$page = Page::first();
|
||||
$this->asAdmin();
|
||||
|
||||
$this->uploadImage('my-drawing.svg', $page->id, 'image/svg+xml', 'diagram.svg');
|
||||
$image = Image::first();
|
||||
$image->type = 'drawio';
|
||||
$image->save();
|
||||
|
||||
$imageGet = $this->getJson("/images/drawio/base64/{$image->id}");
|
||||
$imageGet->assertJson([
|
||||
'content' => 'data:image/svg+xml;base64,' . base64_encode(file_get_contents($this->getTestImageFilePath('diagram.svg'))),
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_drawing_base64_upload_with_png()
|
||||
{
|
||||
$page = Page::first();
|
||||
$editor = $this->getEditor();
|
||||
@@ -35,7 +51,7 @@ class DrawioTest extends TestCase
|
||||
|
||||
$upload = $this->postJson('images/drawio', [
|
||||
'uploaded_to' => $page->id,
|
||||
'image' => 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=',
|
||||
'image' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII=',
|
||||
]);
|
||||
|
||||
$upload->assertStatus(200);
|
||||
@@ -54,6 +70,34 @@ class DrawioTest extends TestCase
|
||||
$this->assertTrue($testImageData === $uploadedImageData, 'Uploaded image file data does not match our test image as expected');
|
||||
}
|
||||
|
||||
public function test_drawing_base64_upload_with_svg()
|
||||
{
|
||||
$page = Page::first();
|
||||
$editor = $this->getEditor();
|
||||
$this->actingAs($editor);
|
||||
|
||||
$upload = $this->postJson('images/drawio', [
|
||||
'uploaded_to' => $page->id,
|
||||
'image' => 'data:image/svg+xml;base64,' . base64_encode(file_get_contents($this->getTestImageFilePath('diagram.svg'))),
|
||||
]);
|
||||
|
||||
$upload->assertStatus(200);
|
||||
$upload->assertJson([
|
||||
'type' => 'drawio',
|
||||
'uploaded_to' => $page->id,
|
||||
'created_by' => $editor->id,
|
||||
'updated_by' => $editor->id,
|
||||
]);
|
||||
|
||||
$image = Image::where('type', '=', 'drawio')->first();
|
||||
$this->assertStringEndsWith('.svg', $image->path);
|
||||
$this->assertTrue(file_exists(public_path($image->path)), 'Uploaded image not found at path: ' . public_path($image->path));
|
||||
|
||||
$testImageData = file_get_contents($this->getTestImageFilePath('diagram.svg'));
|
||||
$uploadedImageData = file_get_contents(public_path($image->path));
|
||||
$this->assertTrue($testImageData === $uploadedImageData, 'Uploaded image file data does not match our test image as expected');
|
||||
}
|
||||
|
||||
public function test_drawio_url_can_be_configured()
|
||||
{
|
||||
config()->set('services.drawio', 'http://cats.com?dog=tree');
|
||||
|
||||
@@ -74,6 +74,23 @@ class ImageTest extends TestCase
|
||||
$this->assertStringNotContainsString('thumbs-', $imgDetails['response']->thumbs->display);
|
||||
}
|
||||
|
||||
public function test_svg_upload()
|
||||
{
|
||||
/** @var Page $page */
|
||||
$page = Page::query()->first();
|
||||
$admin = $this->getAdmin();
|
||||
$this->actingAs($admin);
|
||||
|
||||
$imgDetails = $this->uploadGalleryImage($page, 'diagram.svg', 'image/svg+xml');
|
||||
$this->assertFileExists(public_path($imgDetails['path']));
|
||||
$this->assertTrue(
|
||||
$imgDetails['response']->url === $imgDetails['response']->thumbs->gallery
|
||||
&& $imgDetails['response']->url === $imgDetails['response']->thumbs->display,
|
||||
);
|
||||
|
||||
$this->deleteImage($imgDetails['path']);
|
||||
}
|
||||
|
||||
public function test_image_edit()
|
||||
{
|
||||
$editor = $this->getEditor();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Tests\Uploads;
|
||||
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Uploads\Image;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use stdClass;
|
||||
|
||||
@@ -39,9 +40,9 @@ trait UsesImages
|
||||
/**
|
||||
* Get a test image that can be uploaded.
|
||||
*/
|
||||
protected function getTestImage(string $fileName, ?string $testDataFileName = null): UploadedFile
|
||||
protected function getTestImage(string $fileName, ?string $testDataFileName = null, $mimeType = 'image/png'): UploadedFile
|
||||
{
|
||||
return new UploadedFile($this->getTestImageFilePath($testDataFileName), $fileName, 'image/png', null, true);
|
||||
return new UploadedFile($this->getTestImageFilePath($testDataFileName), $fileName, $mimeType, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +74,7 @@ trait UsesImages
|
||||
*/
|
||||
protected function uploadImage($name, $uploadedTo = 0, $contentType = 'image/png', ?string $testDataFileName = null)
|
||||
{
|
||||
$file = $this->getTestImage($name, $testDataFileName);
|
||||
$file = $this->getTestImage($name, $testDataFileName, $contentType);
|
||||
|
||||
return $this->withHeader('Content-Type', $contentType)
|
||||
->call('POST', '/images/gallery', ['uploaded_to' => $uploadedTo], [], ['file' => $file], []);
|
||||
@@ -84,11 +85,9 @@ trait UsesImages
|
||||
* Returns the image name.
|
||||
* Can provide a page to relate the image to.
|
||||
*
|
||||
* @param Page|null $page
|
||||
*
|
||||
* @return array{name: string, path: string, page: Page, response: stdClass}
|
||||
*/
|
||||
protected function uploadGalleryImage(Page $page = null, ?string $testDataFileName = null)
|
||||
protected function uploadGalleryImage(Page $page = null, string $testDataFileName = null, string $contentType = 'image/png')
|
||||
{
|
||||
if ($page === null) {
|
||||
$page = Page::query()->first();
|
||||
@@ -98,7 +97,7 @@ trait UsesImages
|
||||
$relPath = $this->getTestImagePath('gallery', $imageName);
|
||||
$this->deleteImage($relPath);
|
||||
|
||||
$upload = $this->uploadImage($imageName, $page->id, 'image/png', $testDataFileName);
|
||||
$upload = $this->uploadImage($imageName, $page->id, $contentType, $testDataFileName);
|
||||
$upload->assertStatus(200);
|
||||
|
||||
return [
|
||||
|
||||
3
tests/test-data/diagram.svg
Normal file
3
tests/test-data/diagram.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="121px" height="141px" viewBox="-0.5 -0.5 121 141"><defs/><g><ellipse cx="25" cy="87.5" rx="7.5" ry="7.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 25 95 L 25 120 M 25 100 L 10 100 M 25 100 L 40 100 M 25 120 L 10 140 M 25 120 L 40 140" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 0 L 120 0 L 120 50 L 80 50 L 60 80 L 60 50 L 0 50 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 25px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Hello!</div></div></div></foreignObject><text x="60" y="29" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Hello!</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
Reference in New Issue
Block a user