1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

Merge branch 'development' into release

This commit is contained in:
Dan Brown
2025-06-17 15:29:46 +01:00
51 changed files with 511 additions and 300 deletions

View File

@@ -487,3 +487,5 @@ jellium :: French
Qxlkdr :: Swedish Qxlkdr :: Swedish
Hari (muhhari) :: Indonesian Hari (muhhari) :: Indonesian
仙君御 (xjy) :: Chinese Simplified 仙君御 (xjy) :: Chinese Simplified
TapioM :: Finnish
lingb58 :: Chinese Traditional

View File

@@ -160,7 +160,9 @@ class SearchIndex
/** @var DOMNode $child */ /** @var DOMNode $child */
foreach ($doc->getBodyChildren() as $child) { foreach ($doc->getBodyChildren() as $child) {
$nodeName = $child->nodeName; $nodeName = $child->nodeName;
$termCounts = $this->textToTermCountMap(trim($child->textContent)); $text = trim($child->textContent);
$text = str_replace("\u{00A0}", ' ', $text);
$termCounts = $this->textToTermCountMap($text);
foreach ($termCounts as $term => $count) { foreach ($termCounts as $term => $count) {
$scoreChange = $count * ($elementScoreAdjustmentMap[$nodeName] ?? 1); $scoreChange = $count * ($elementScoreAdjustmentMap[$nodeName] ?? 1);
$scoresByTerm[$term] = ($scoresByTerm[$term] ?? 0) + $scoreChange; $scoresByTerm[$term] = ($scoresByTerm[$term] ?? 0) + $scoreChange;

192
composer.lock generated
View File

@@ -62,16 +62,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.343.22", "version": "3.344.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "174cc187df3bde52c21e9c00a4e99610a08732a3" "reference": "eb0bc621472592545539329499961a15a3f9f6dc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/174cc187df3bde52c21e9c00a4e99610a08732a3", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eb0bc621472592545539329499961a15a3f9f6dc",
"reference": "174cc187df3bde52c21e9c00a4e99610a08732a3", "reference": "eb0bc621472592545539329499961a15a3f9f6dc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -153,9 +153,9 @@
"support": { "support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions", "forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.343.22" "source": "https://github.com/aws/aws-sdk-php/tree/3.344.6"
}, },
"time": "2025-05-30T18:11:02+00:00" "time": "2025-06-12T18:03:59+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@@ -1740,16 +1740,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v11.45.0", "version": "v11.45.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "d0730deb427632004d24801be7ca1ed2c10fbc4e" "reference": "b09ba32795b8e71df10856a2694706663984a239"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/d0730deb427632004d24801be7ca1ed2c10fbc4e", "url": "https://api.github.com/repos/laravel/framework/zipball/b09ba32795b8e71df10856a2694706663984a239",
"reference": "d0730deb427632004d24801be7ca1ed2c10fbc4e", "reference": "b09ba32795b8e71df10856a2694706663984a239",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1951,7 +1951,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2025-05-20T15:15:58+00:00" "time": "2025-06-03T14:01:40+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
@@ -3285,16 +3285,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "3.9.1", "version": "3.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/CarbonPHP/carbon.git", "url": "https://github.com/CarbonPHP/carbon.git",
"reference": "ced71f79398ece168e24f7f7710462f462310d4d" "reference": "c1397390dd0a7e0f11660f0ae20f753d88c1f3d9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/c1397390dd0a7e0f11660f0ae20f753d88c1f3d9",
"reference": "ced71f79398ece168e24f7f7710462f462310d4d", "reference": "c1397390dd0a7e0f11660f0ae20f753d88c1f3d9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3302,7 +3302,7 @@
"ext-json": "*", "ext-json": "*",
"php": "^8.1", "php": "^8.1",
"psr/clock": "^1.0", "psr/clock": "^1.0",
"symfony/clock": "^6.3 || ^7.0", "symfony/clock": "^6.3.12 || ^7.0",
"symfony/polyfill-mbstring": "^1.0", "symfony/polyfill-mbstring": "^1.0",
"symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0"
}, },
@@ -3312,14 +3312,13 @@
"require-dev": { "require-dev": {
"doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/dbal": "^3.6.3 || ^4.0",
"doctrine/orm": "^2.15.2 || ^3.0", "doctrine/orm": "^2.15.2 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.57.2", "friendsofphp/php-cs-fixer": "^3.75.0",
"kylekatarnls/multi-tester": "^2.5.3", "kylekatarnls/multi-tester": "^2.5.3",
"ondrejmirtes/better-reflection": "^6.25.0.4",
"phpmd/phpmd": "^2.15.0", "phpmd/phpmd": "^2.15.0",
"phpstan/extension-installer": "^1.3.1", "phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^1.11.2", "phpstan/phpstan": "^2.1.17",
"phpunit/phpunit": "^10.5.20", "phpunit/phpunit": "^10.5.46",
"squizlabs/php_codesniffer": "^3.9.0" "squizlabs/php_codesniffer": "^3.13.0"
}, },
"bin": [ "bin": [
"bin/carbon" "bin/carbon"
@@ -3387,7 +3386,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-01T19:51:51+00:00" "time": "2025-06-12T10:24:28+00:00"
}, },
{ {
"name": "nette/schema", "name": "nette/schema",
@@ -3453,16 +3452,16 @@
}, },
{ {
"name": "nette/utils", "name": "nette/utils",
"version": "v4.0.6", "version": "v4.0.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nette/utils.git", "url": "https://github.com/nette/utils.git",
"reference": "ce708655043c7050eb050df361c5e313cf708309" "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309", "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2",
"reference": "ce708655043c7050eb050df361c5e313cf708309", "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3533,9 +3532,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nette/utils/issues", "issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v4.0.6" "source": "https://github.com/nette/utils/tree/v4.0.7"
}, },
"time": "2025-03-30T21:06:30+00:00" "time": "2025-06-03T04:55:08+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
@@ -4775,20 +4774,20 @@
}, },
{ {
"name": "ramsey/uuid", "name": "ramsey/uuid",
"version": "4.7.6", "version": "4.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ramsey/uuid.git", "url": "https://github.com/ramsey/uuid.git",
"reference": "91039bc1faa45ba123c4328958e620d382ec7088" "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
"reference": "91039bc1faa45ba123c4328958e620d382ec7088", "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
"ext-json": "*", "ext-json": "*",
"php": "^8.0", "php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0" "ramsey/collection": "^1.2 || ^2.0"
@@ -4797,26 +4796,23 @@
"rhumsaa/uuid": "self.version" "rhumsaa/uuid": "self.version"
}, },
"require-dev": { "require-dev": {
"captainhook/captainhook": "^5.10", "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3", "captainhook/plugin-composer": "^5.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"doctrine/annotations": "^1.8", "ergebnis/composer-normalize": "^2.47",
"ergebnis/composer-normalize": "^2.15", "mockery/mockery": "^1.6",
"mockery/mockery": "^1.3",
"paragonie/random-lib": "^2", "paragonie/random-lib": "^2",
"php-mock/php-mock": "^2.2", "php-mock/php-mock": "^2.6",
"php-mock/php-mock-mockery": "^1.3", "php-mock/php-mock-mockery": "^1.5",
"php-parallel-lint/php-parallel-lint": "^1.1", "php-parallel-lint/php-parallel-lint": "^1.4.0",
"phpbench/phpbench": "^1.0", "phpbench/phpbench": "^1.2.14",
"phpstan/extension-installer": "^1.1", "phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^1.8", "phpstan/phpstan": "^2.1",
"phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-mockery": "^2.0",
"phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^8.5 || ^9", "phpunit/phpunit": "^9.6",
"ramsey/composer-repl": "^1.4", "slevomat/coding-standard": "^8.18",
"slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.13"
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.9"
}, },
"suggest": { "suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
@@ -4851,19 +4847,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/ramsey/uuid/issues", "issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.7.6" "source": "https://github.com/ramsey/uuid/tree/4.8.1"
}, },
"funding": [ "time": "2025-06-01T06:28:46+00:00"
{
"url": "https://github.com/ramsey",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
"type": "tidelift"
}
],
"time": "2024-04-27T21:32:50+00:00"
}, },
{ {
"name": "robrichards/xmlseclibs", "name": "robrichards/xmlseclibs",
@@ -7906,16 +7892,16 @@
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.18.0", "version": "2.18.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/filp/whoops.git", "url": "https://github.com/filp/whoops.git",
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e" "reference": "89dabca1490bc77dbcab41c2b20968c7e44bf7c3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", "url": "https://api.github.com/repos/filp/whoops/zipball/89dabca1490bc77dbcab41c2b20968c7e44bf7c3",
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", "reference": "89dabca1490bc77dbcab41c2b20968c7e44bf7c3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7965,7 +7951,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/filp/whoops/issues", "issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.18.0" "source": "https://github.com/filp/whoops/tree/2.18.2"
}, },
"funding": [ "funding": [
{ {
@@ -7973,7 +7959,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-03-15T12:00:00+00:00" "time": "2025-06-11T20:42:19+00:00"
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",
@@ -8145,16 +8131,16 @@
}, },
{ {
"name": "larastan/larastan", "name": "larastan/larastan",
"version": "v3.4.0", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/larastan/larastan.git", "url": "https://github.com/larastan/larastan.git",
"reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222" "reference": "36706736a0c51d3337478fab9c919d78d2e03404"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/1042fa0c2ee490bb6da7381f3323f7292ad68222", "url": "https://api.github.com/repos/larastan/larastan/zipball/36706736a0c51d3337478fab9c919d78d2e03404",
"reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222", "reference": "36706736a0c51d3337478fab9c919d78d2e03404",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -8222,7 +8208,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/larastan/larastan/issues", "issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.4.0" "source": "https://github.com/larastan/larastan/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -8230,7 +8216,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-04-22T09:44:59+00:00" "time": "2025-06-10T09:34:58+00:00"
}, },
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
@@ -8377,23 +8363,23 @@
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
"version": "v8.8.0", "version": "v8.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nunomaduro/collision.git", "url": "https://github.com/nunomaduro/collision.git",
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", "url": "https://api.github.com/repos/nunomaduro/collision/zipball/44ccb82e3e21efb5446748d2a3c81a030ac22bd5",
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"filp/whoops": "^2.18.0", "filp/whoops": "^2.18.1",
"nunomaduro/termwind": "^2.3.0", "nunomaduro/termwind": "^2.3.1",
"php": "^8.2.0", "php": "^8.2.0",
"symfony/console": "^7.2.5" "symfony/console": "^7.3.0"
}, },
"conflict": { "conflict": {
"laravel/framework": "<11.44.2 || >=13.0.0", "laravel/framework": "<11.44.2 || >=13.0.0",
@@ -8401,15 +8387,15 @@
}, },
"require-dev": { "require-dev": {
"brianium/paratest": "^7.8.3", "brianium/paratest": "^7.8.3",
"larastan/larastan": "^3.2", "larastan/larastan": "^3.4.2",
"laravel/framework": "^11.44.2 || ^12.6", "laravel/framework": "^11.44.2 || ^12.18",
"laravel/pint": "^1.21.2", "laravel/pint": "^1.22.1",
"laravel/sail": "^1.41.0", "laravel/sail": "^1.43.1",
"laravel/sanctum": "^4.0.8", "laravel/sanctum": "^4.1.1",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"orchestra/testbench-core": "^9.12.0 || ^10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4",
"pestphp/pest": "^3.8.0", "pestphp/pest": "^3.8.2",
"sebastian/environment": "^7.2.0 || ^8.0" "sebastian/environment": "^7.2.1 || ^8.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -8472,7 +8458,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2025-04-03T14:33:09+00:00" "time": "2025-06-11T01:04:21+00:00"
}, },
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",
@@ -8975,16 +8961,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "11.5.21", "version": "11.5.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289" "reference": "86ebcd8a3dbcd1857d88505109b2a2b376501cde"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d565e2cdc21a7db9dc6c399c1fc2083b8010f289", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/86ebcd8a3dbcd1857d88505109b2a2b376501cde",
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289", "reference": "86ebcd8a3dbcd1857d88505109b2a2b376501cde",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -9056,7 +9042,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.21" "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.23"
}, },
"funding": [ "funding": [
{ {
@@ -9080,7 +9066,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-21T12:35:00+00:00" "time": "2025-06-13T05:47:49+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@@ -10022,16 +10008,16 @@
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
"version": "3.13.0", "version": "3.13.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
"reference": "65ff2489553b83b4597e89c3b8b721487011d186" "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186", "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1b71b4dd7e7ef651ac749cea67e513c0c832f4bd",
"reference": "65ff2489553b83b4597e89c3b8b721487011d186", "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10102,7 +10088,7 @@
"type": "thanks_dev" "type": "thanks_dev"
} }
], ],
"time": "2025-05-11T03:36:00+00:00" "time": "2025-06-12T15:04:34+00:00"
}, },
{ {
"name": "ssddanbrown/asserthtml", "name": "ssddanbrown/asserthtml",

View File

@@ -486,7 +486,7 @@ Link: https://github.com/ramsey/collection.git
ramsey/uuid ramsey/uuid
License: MIT License: MIT
License File: vendor/ramsey/uuid/LICENSE License File: vendor/ramsey/uuid/LICENSE
Copyright: Copyright (c) 2012-2023 Ben Ramsey <***@*********.***> Copyright: Copyright (c) 2012-2025 Ben Ramsey <***@*********.***>
Source: https://github.com/ramsey/uuid.git Source: https://github.com/ramsey/uuid.git
Link: https://github.com/ramsey/uuid.git Link: https://github.com/ramsey/uuid.git
----------- -----------

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Vytvořit', 'create' => 'Vytvořit',
'update' => 'Aktualizovat', 'update' => 'Aktualizovat',
'edit' => 'Upravit', 'edit' => 'Upravit',
'archive' => 'Archive', 'archive' => 'Archivovat',
'unarchive' => 'Un-Archive', 'unarchive' => 'Od-Archivovat',
'sort' => 'Seřadit', 'sort' => 'Seřadit',
'move' => 'Přesunout', 'move' => 'Přesunout',
'copy' => 'Kopírovat', 'copy' => 'Kopírovat',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Stabilní obsah)', 'pages_edit_switch_to_markdown_stable' => '(Stabilní obsah)',
'pages_edit_switch_to_wysiwyg' => 'Přepnout na WYSIWYG Editor', 'pages_edit_switch_to_wysiwyg' => 'Přepnout na WYSIWYG Editor',
'pages_edit_switch_to_new_wysiwyg' => 'Přepnout na nový WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Přepnout na nový WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(V beta testování)',
'pages_edit_set_changelog' => 'Nastavit protokol změn', 'pages_edit_set_changelog' => 'Nastavit protokol změn',
'pages_edit_enter_changelog_desc' => 'Zadejte stručný popis změn, které jste provedli', 'pages_edit_enter_changelog_desc' => 'Zadejte stručný popis změn, které jste provedli',
'pages_edit_enter_changelog' => 'Zadejte protokol změn', 'pages_edit_enter_changelog' => 'Zadejte protokol změn',
@@ -392,11 +392,11 @@ return [
'comment' => 'Komentář', 'comment' => 'Komentář',
'comments' => 'Komentáře', 'comments' => 'Komentáře',
'comment_add' => 'Přidat komentář', 'comment_add' => 'Přidat komentář',
'comment_none' => 'No comments to display', 'comment_none' => 'Žádné komentáře k zobrazení',
'comment_placeholder' => 'Zde zadejte komentář', 'comment_placeholder' => 'Zde zadejte komentář',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count vlákno komentáře|:count vláken komentářů',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count archivováno',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Archivovaná vlákna',
'comment_save' => 'Uložit komentář', 'comment_save' => 'Uložit komentář',
'comment_new' => 'Nový komentář', 'comment_new' => 'Nový komentář',
'comment_created' => 'komentováno :createDiff', 'comment_created' => 'komentováno :createDiff',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Komentář odstraněn', 'comment_deleted_success' => 'Komentář odstraněn',
'comment_created_success' => 'Komentář přidán', 'comment_created_success' => 'Komentář přidán',
'comment_updated_success' => 'Komentář aktualizován', 'comment_updated_success' => 'Komentář aktualizován',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Komentář archivován',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Komentář od-archivován',
'comment_view' => 'View comment', 'comment_view' => 'Zobrazit komentář',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Přejít na vlákno',
'comment_delete_confirm' => 'Opravdu chcete odstranit tento komentář?', 'comment_delete_confirm' => 'Opravdu chcete odstranit tento komentář?',
'comment_in_reply_to' => 'Odpověď na :commentId', 'comment_in_reply_to' => 'Odpověď na :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Odkaz',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Zastaralý)',
'comment_editor_explain' => 'Zde jsou komentáře, které zůstaly na této stránce. Komentáře lze přidat a spravovat při prohlížení uložené stránky.', 'comment_editor_explain' => 'Zde jsou komentáře, které zůstaly na této stránce. Komentáře lze přidat a spravovat při prohlížení uložené stránky.',
// Revision // Revision

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Erstellen', 'create' => 'Erstellen',
'update' => 'Aktualisieren', 'update' => 'Aktualisieren',
'edit' => 'Bearbeiten', 'edit' => 'Bearbeiten',
'archive' => 'Archive', 'archive' => 'Archivieren',
'unarchive' => 'Un-Archive', 'unarchive' => 'Nicht mehr archivieren',
'sort' => 'Sortieren', 'sort' => 'Sortieren',
'move' => 'Verschieben', 'move' => 'Verschieben',
'copy' => 'Kopieren', 'copy' => 'Kopieren',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Stabiler Inhalt)', 'pages_edit_switch_to_markdown_stable' => '(Stabiler Inhalt)',
'pages_edit_switch_to_wysiwyg' => 'Zum WYSIWYG-Editor wechseln', 'pages_edit_switch_to_wysiwyg' => 'Zum WYSIWYG-Editor wechseln',
'pages_edit_switch_to_new_wysiwyg' => 'Zum neuen WYSIWYG wechseln', 'pages_edit_switch_to_new_wysiwyg' => 'Zum neuen WYSIWYG wechseln',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(Im Beta-Test)',
'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen', 'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen',
'pages_edit_enter_changelog_desc' => 'Bitte geben Sie eine kurze Zusammenfassung Ihrer Änderungen ein', 'pages_edit_enter_changelog_desc' => 'Bitte geben Sie eine kurze Zusammenfassung Ihrer Änderungen ein',
'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben', 'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben',
@@ -392,11 +392,11 @@ return [
'comment' => 'Kommentar', 'comment' => 'Kommentar',
'comments' => 'Kommentare', 'comments' => 'Kommentare',
'comment_add' => 'Kommentieren', 'comment_add' => 'Kommentieren',
'comment_none' => 'No comments to display', 'comment_none' => 'Keine Kommentare vorhanden',
'comment_placeholder' => 'Geben Sie hier Ihre Kommentare ein', 'comment_placeholder' => 'Geben Sie hier Ihre Kommentare ein',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count Thema|:count Themen',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count archiviert',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Archivierte Themen',
'comment_save' => 'Kommentar speichern', 'comment_save' => 'Kommentar speichern',
'comment_new' => 'Neuer Kommentar', 'comment_new' => 'Neuer Kommentar',
'comment_created' => ':createDiff kommentiert', 'comment_created' => ':createDiff kommentiert',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Kommentar gelöscht', 'comment_deleted_success' => 'Kommentar gelöscht',
'comment_created_success' => 'Kommentar hinzugefügt', 'comment_created_success' => 'Kommentar hinzugefügt',
'comment_updated_success' => 'Kommentar aktualisiert', 'comment_updated_success' => 'Kommentar aktualisiert',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Kommentar archiviert',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Kommentar nicht mehr archiviert',
'comment_view' => 'View comment', 'comment_view' => 'Kommentar ansehen',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Zum Thema springen',
'comment_delete_confirm' => 'Möchten Sie diesen Kommentar wirklich löschen?', 'comment_delete_confirm' => 'Möchten Sie diesen Kommentar wirklich löschen?',
'comment_in_reply_to' => 'Antwort auf :commentId', 'comment_in_reply_to' => 'Antwort auf :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Referenz',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Veraltet)',
'comment_editor_explain' => 'Hier sind die Kommentare, die auf dieser Seite hinterlassen wurden. Kommentare können hinzugefügt und verwaltet werden, wenn die gespeicherte Seite angezeigt wird.', 'comment_editor_explain' => 'Hier sind die Kommentare, die auf dieser Seite hinterlassen wurden. Kommentare können hinzugefügt und verwaltet werden, wenn die gespeicherte Seite angezeigt wird.',
// Revision // Revision

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Anlegen', 'create' => 'Anlegen',
'update' => 'Aktualisieren', 'update' => 'Aktualisieren',
'edit' => 'Bearbeiten', 'edit' => 'Bearbeiten',
'archive' => 'Archive', 'archive' => 'Archivieren',
'unarchive' => 'Un-Archive', 'unarchive' => 'Nicht mehr archivieren',
'sort' => 'Sortieren', 'sort' => 'Sortieren',
'move' => 'Verschieben', 'move' => 'Verschieben',
'copy' => 'Kopieren', 'copy' => 'Kopieren',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Stabiler Inhalt)', 'pages_edit_switch_to_markdown_stable' => '(Stabiler Inhalt)',
'pages_edit_switch_to_wysiwyg' => 'Zum WYSIWYG-Editor wechseln', 'pages_edit_switch_to_wysiwyg' => 'Zum WYSIWYG-Editor wechseln',
'pages_edit_switch_to_new_wysiwyg' => 'Zum neuen WYSIWYG wechseln', 'pages_edit_switch_to_new_wysiwyg' => 'Zum neuen WYSIWYG wechseln',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(Im Beta-Test)',
'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen', 'pages_edit_set_changelog' => 'Änderungsprotokoll hinzufügen',
'pages_edit_enter_changelog_desc' => 'Bitte gib eine kurze Zusammenfassung deiner Änderungen ein', 'pages_edit_enter_changelog_desc' => 'Bitte gib eine kurze Zusammenfassung deiner Änderungen ein',
'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben', 'pages_edit_enter_changelog' => 'Änderungsprotokoll eingeben',
@@ -392,11 +392,11 @@ return [
'comment' => 'Kommentar', 'comment' => 'Kommentar',
'comments' => 'Kommentare', 'comments' => 'Kommentare',
'comment_add' => 'Kommentieren', 'comment_add' => 'Kommentieren',
'comment_none' => 'No comments to display', 'comment_none' => 'Keine Kommentare vorhanden',
'comment_placeholder' => 'Gib hier deine Kommentare ein', 'comment_placeholder' => 'Gib hier deine Kommentare ein',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count Thema|:count Themen',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count archiviert',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Archivierte Themen',
'comment_save' => 'Kommentar speichern', 'comment_save' => 'Kommentar speichern',
'comment_new' => 'Neuer Kommentar', 'comment_new' => 'Neuer Kommentar',
'comment_created' => ':createDiff kommentiert', 'comment_created' => ':createDiff kommentiert',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Kommentar gelöscht', 'comment_deleted_success' => 'Kommentar gelöscht',
'comment_created_success' => 'Kommentar hinzugefügt', 'comment_created_success' => 'Kommentar hinzugefügt',
'comment_updated_success' => 'Kommentar aktualisiert', 'comment_updated_success' => 'Kommentar aktualisiert',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Kommentar archiviert',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Kommentar nicht mehr archiviert',
'comment_view' => 'View comment', 'comment_view' => 'Kommentar ansehen',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Zum Thema springen',
'comment_delete_confirm' => 'Möchtst du diesen Kommentar wirklich löschen?', 'comment_delete_confirm' => 'Möchtst du diesen Kommentar wirklich löschen?',
'comment_in_reply_to' => 'Antwort auf :commentId', 'comment_in_reply_to' => 'Antwort auf :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Referenz',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Veraltet)',
'comment_editor_explain' => 'Hier sind die Kommentare, die auf dieser Seite hinterlassen wurden. Kommentare können hinzugefügt und verwaltet werden, wenn die gespeicherte Seite angezeigt wird.', 'comment_editor_explain' => 'Hier sind die Kommentare, die auf dieser Seite hinterlassen wurden. Kommentare können hinzugefügt und verwaltet werden, wenn die gespeicherte Seite angezeigt wird.',
// Revision // Revision

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Crear', 'create' => 'Crear',
'update' => 'Actualizar', 'update' => 'Actualizar',
'edit' => 'Editar', 'edit' => 'Editar',
'archive' => 'Archive', 'archive' => 'Archivar',
'unarchive' => 'Un-Archive', 'unarchive' => 'Desarchivar',
'sort' => 'Ordenar', 'sort' => 'Ordenar',
'move' => 'Mover', 'move' => 'Mover',
'copy' => 'Copiar', 'copy' => 'Copiar',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Contenido Estable)', 'pages_edit_switch_to_markdown_stable' => '(Contenido Estable)',
'pages_edit_switch_to_wysiwyg' => 'Cambiar a Editor WYSIWYG', 'pages_edit_switch_to_wysiwyg' => 'Cambiar a Editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg' => 'Cambiar a nuevo editor WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Cambiar a nuevo editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(En prueba beta)',
'pages_edit_set_changelog' => 'Ajustar Log de cambios', 'pages_edit_set_changelog' => 'Ajustar Log de cambios',
'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado', 'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado',
'pages_edit_enter_changelog' => 'Entrar al Log de cambios', 'pages_edit_enter_changelog' => 'Entrar al Log de cambios',
@@ -392,11 +392,11 @@ return [
'comment' => 'Comentario', 'comment' => 'Comentario',
'comments' => 'Comentarios', 'comments' => 'Comentarios',
'comment_add' => 'Añadir Comentario', 'comment_add' => 'Añadir Comentario',
'comment_none' => 'No comments to display', 'comment_none' => 'No hay comentarios para mostrar',
'comment_placeholder' => 'Introduzca su comentario aquí', 'comment_placeholder' => 'Introduzca su comentario aquí',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count hilo de comentarios|:count hilos de comentarios',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count Archivados',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Hilos archivados',
'comment_save' => 'Guardar comentario', 'comment_save' => 'Guardar comentario',
'comment_new' => 'Nuevo Comentario', 'comment_new' => 'Nuevo Comentario',
'comment_created' => 'comentado :createDiff', 'comment_created' => 'comentado :createDiff',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Comentario borrado', 'comment_deleted_success' => 'Comentario borrado',
'comment_created_success' => 'Comentario añadido', 'comment_created_success' => 'Comentario añadido',
'comment_updated_success' => 'Comentario actualizado', 'comment_updated_success' => 'Comentario actualizado',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Comentario archivado',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Comentario desarchivado',
'comment_view' => 'View comment', 'comment_view' => 'Ver comentario',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Ir al hilo',
'comment_delete_confirm' => '¿Está seguro de que quiere borrar este comentario?', 'comment_delete_confirm' => '¿Está seguro de que quiere borrar este comentario?',
'comment_in_reply_to' => 'En respuesta a :commentId', 'comment_in_reply_to' => 'En respuesta a :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Referencia',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(obsoleto)',
'comment_editor_explain' => 'Estos son los comentarios que se han escrito en esta página. Los comentarios se pueden añadir y administrar cuando se ve la página guardada.', 'comment_editor_explain' => 'Estos son los comentarios que se han escrito en esta página. Los comentarios se pueden añadir y administrar cuando se ve la página guardada.',
// Revision // Revision

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Contenido Estable)', 'pages_edit_switch_to_markdown_stable' => '(Contenido Estable)',
'pages_edit_switch_to_wysiwyg' => 'Cambiar a Editor WYSIWYG', 'pages_edit_switch_to_wysiwyg' => 'Cambiar a Editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg' => 'Cambiar a nuevo editor WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Cambiar a nuevo editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(En prueba beta)',
'pages_edit_set_changelog' => 'Establecer cambios de registro', 'pages_edit_set_changelog' => 'Establecer cambios de registro',
'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado', 'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado',
'pages_edit_enter_changelog' => 'Entrar en cambio de registro', 'pages_edit_enter_changelog' => 'Entrar en cambio de registro',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Stabiilne sisu)', 'pages_edit_switch_to_markdown_stable' => '(Stabiilne sisu)',
'pages_edit_switch_to_wysiwyg' => 'Kasuta WYSIWYG redaktorit', 'pages_edit_switch_to_wysiwyg' => 'Kasuta WYSIWYG redaktorit',
'pages_edit_switch_to_new_wysiwyg' => 'Kasuta uut tekstiredaktorit', 'pages_edit_switch_to_new_wysiwyg' => 'Kasuta uut tekstiredaktorit',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(beetatestimisel)',
'pages_edit_set_changelog' => 'Muudatuste logi', 'pages_edit_set_changelog' => 'Muudatuste logi',
'pages_edit_enter_changelog_desc' => 'Sisesta tehtud muudatuste lühikirjeldus', 'pages_edit_enter_changelog_desc' => 'Sisesta tehtud muudatuste lühikirjeldus',
'pages_edit_enter_changelog' => 'Salvesta muudatuste logi', 'pages_edit_enter_changelog' => 'Salvesta muudatuste logi',

View File

@@ -10,7 +10,7 @@ return [
// Auth // Auth
'error_user_exists_different_creds' => 'Sähköpostiosoite :email on jo käytössä toisessa käyttäjätunnuksessa.', 'error_user_exists_different_creds' => 'Sähköpostiosoite :email on jo käytössä toisessa käyttäjätunnuksessa.',
'auth_pre_register_theme_prevention' => 'User account could not be registered for the provided details', 'auth_pre_register_theme_prevention' => 'Käyttäjätiliä ei voitu rekisteröidä annetuille tiedoille',
'email_already_confirmed' => 'Sähköposti on jo vahvistettu, yritä kirjautua sisään.', 'email_already_confirmed' => 'Sähköposti on jo vahvistettu, yritä kirjautua sisään.',
'email_confirmation_invalid' => 'Tämä vahvistuslinkki ei ole voimassa tai sitä on jo käytetty, yritä rekisteröityä uudelleen.', 'email_confirmation_invalid' => 'Tämä vahvistuslinkki ei ole voimassa tai sitä on jo käytetty, yritä rekisteröityä uudelleen.',
'email_confirmation_expired' => 'Vahvistuslinkki on vanhentunut, uusi vahvistussähköposti on lähetetty.', 'email_confirmation_expired' => 'Vahvistuslinkki on vanhentunut, uusi vahvistussähköposti on lähetetty.',
@@ -38,7 +38,7 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa
'social_driver_not_found' => 'Sosiaalisen median tilin ajuria ei löytynyt', 'social_driver_not_found' => 'Sosiaalisen median tilin ajuria ei löytynyt',
'social_driver_not_configured' => ':socialAccount-tilin asetuksia ei ole määritetty oikein.', 'social_driver_not_configured' => ':socialAccount-tilin asetuksia ei ole määritetty oikein.',
'invite_token_expired' => 'Tämä kutsulinkki on vanhentunut. Voit sen sijaan yrittää palauttaa tilisi salasanan.', 'invite_token_expired' => 'Tämä kutsulinkki on vanhentunut. Voit sen sijaan yrittää palauttaa tilisi salasanan.',
'login_user_not_found' => 'A user for this action could not be found.', 'login_user_not_found' => 'Käyttäjää tälle toiminnolle ei löytynyt.',
// System // System
'path_not_writable' => 'Tiedostopolkuun :filePath ei voitu ladata tiedostoa. Tarkista polun kirjoitusoikeudet.', 'path_not_writable' => 'Tiedostopolkuun :filePath ei voitu ladata tiedostoa. Tarkista polun kirjoitusoikeudet.',
@@ -79,7 +79,7 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa
// Users // Users
'users_cannot_delete_only_admin' => 'Ainoaa ylläpitäjää ei voi poistaa', 'users_cannot_delete_only_admin' => 'Ainoaa ylläpitäjää ei voi poistaa',
'users_cannot_delete_guest' => 'Vieraskäyttäjää ei voi poistaa', 'users_cannot_delete_guest' => 'Vieraskäyttäjää ei voi poistaa',
'users_could_not_send_invite' => 'Could not create user since invite email failed to send', 'users_could_not_send_invite' => 'Käyttäjää ei voitu luoda kutsun lähettämisen jälkeen',
// Roles // Roles
'role_cannot_be_edited' => 'Tätä roolia ei voi muokata', 'role_cannot_be_edited' => 'Tätä roolia ei voi muokata',
@@ -107,16 +107,16 @@ Sovellus ei tunnista ulkoisen todennuspalvelun pyyntöä. Ongelman voi aiheuttaa
'back_soon' => 'Se palautetaan pian.', 'back_soon' => 'Se palautetaan pian.',
// Import // Import
'import_zip_cant_read' => 'Could not read ZIP file.', 'import_zip_cant_read' => 'ZIP-tiedostoa ei voitu lukea.',
'import_zip_cant_decode_data' => 'Could not find and decode ZIP data.json content.', 'import_zip_cant_decode_data' => 'ZIP-tiedoston data.json sisältöä ei löydy eikä sitä voitu purkaa.',
'import_zip_no_data' => 'ZIP file data has no expected book, chapter or page content.', 'import_zip_no_data' => 'ZIP-tiedostoilla ei ole odotettua kirjaa, lukua tai sivun sisältöä.',
'import_validation_failed' => 'Import ZIP failed to validate with errors:', 'import_validation_failed' => 'Tuonti ZIP epäonnistui virheiden kanssa:',
'import_zip_failed_notification' => 'Failed to import ZIP file.', 'import_zip_failed_notification' => 'ZIP-tiedoston tuominen epäonnistui.',
'import_perms_books' => 'You are lacking the required permissions to create books.', 'import_perms_books' => 'Sinulla ei ole tarvittavia oikeuksia luoda kirjoja.',
'import_perms_chapters' => 'You are lacking the required permissions to create chapters.', 'import_perms_chapters' => 'Sinulla ei ole tarvittavia oikeuksia luoda kappaleita.',
'import_perms_pages' => 'You are lacking the required permissions to create pages.', 'import_perms_pages' => 'Sinulla ei ole tarvittavia oikeuksia luoda sivuja.',
'import_perms_images' => 'You are lacking the required permissions to create images.', 'import_perms_images' => 'Sinulla ei ole tarvittavia oikeuksia luoda kuvia.',
'import_perms_attachments' => 'You are lacking the required permission to create attachments.', 'import_perms_attachments' => 'Sinulla ei ole tarvittavaa lupaa luoda liitteitä.',
// API errors // API errors
'api_no_authorization_found' => 'Pyynnöstä ei löytynyt valtuutuskoodia', 'api_no_authorization_found' => 'Pyynnöstä ei löytynyt valtuutuskoodia',

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Crea', 'create' => 'Crea',
'update' => 'Aggiorna', 'update' => 'Aggiorna',
'edit' => 'Modifica', 'edit' => 'Modifica',
'archive' => 'Archive', 'archive' => 'Archivia',
'unarchive' => 'Un-Archive', 'unarchive' => 'Ripristina',
'sort' => 'Ordina', 'sort' => 'Ordina',
'move' => 'Sposta', 'move' => 'Sposta',
'copy' => 'Copia', 'copy' => 'Copia',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Contenuto stabile)', 'pages_edit_switch_to_markdown_stable' => '(Contenuto stabile)',
'pages_edit_switch_to_wysiwyg' => 'Passa all\'editor WYSIWYG', 'pages_edit_switch_to_wysiwyg' => 'Passa all\'editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg' => 'Passa al nuovo WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Passa al nuovo WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Test)',
'pages_edit_set_changelog' => 'Imposta changelog', 'pages_edit_set_changelog' => 'Imposta changelog',
'pages_edit_enter_changelog_desc' => 'Inserisci una breve descrizione dei cambiamenti che hai apportato', 'pages_edit_enter_changelog_desc' => 'Inserisci una breve descrizione dei cambiamenti che hai apportato',
'pages_edit_enter_changelog' => 'Inserisci changelog', 'pages_edit_enter_changelog' => 'Inserisci changelog',
@@ -392,11 +392,11 @@ return [
'comment' => 'Commento', 'comment' => 'Commento',
'comments' => 'Commenti', 'comments' => 'Commenti',
'comment_add' => 'Aggiungi commento', 'comment_add' => 'Aggiungi commento',
'comment_none' => 'No comments to display', 'comment_none' => 'Nessun commento da visualizzare',
'comment_placeholder' => 'Scrivi un commento', 'comment_placeholder' => 'Scrivi un commento',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count Comment Thread|:count Comment Threads',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count Archiviato',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Discussioni Archiviate',
'comment_save' => 'Salva commento', 'comment_save' => 'Salva commento',
'comment_new' => 'Nuovo commento', 'comment_new' => 'Nuovo commento',
'comment_created' => 'ha commentato :createDiff', 'comment_created' => 'ha commentato :createDiff',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Commento eliminato', 'comment_deleted_success' => 'Commento eliminato',
'comment_created_success' => 'Commento aggiunto', 'comment_created_success' => 'Commento aggiunto',
'comment_updated_success' => 'Commento aggiornato', 'comment_updated_success' => 'Commento aggiornato',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Commento archiviato',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Commento ripristinato',
'comment_view' => 'View comment', 'comment_view' => 'Visualizza commento',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Vai al thread',
'comment_delete_confirm' => 'Sei sicuro di voler eliminare questo commento?', 'comment_delete_confirm' => 'Sei sicuro di voler eliminare questo commento?',
'comment_in_reply_to' => 'In risposta a :commentId', 'comment_in_reply_to' => 'In risposta a :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Riferimento',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Obsoleto)',
'comment_editor_explain' => 'Ecco i commenti che sono stati lasciati in questa pagina. I commenti possono essere aggiunti e gestiti quando si visualizza la pagina salvata.', 'comment_editor_explain' => 'Ecco i commenti che sono stati lasciati in questa pagina. I commenti possono essere aggiunti e gestiti quando si visualizza la pagina salvata.',
// Revision // Revision

View File

@@ -30,8 +30,8 @@ return [
'create' => '作成', 'create' => '作成',
'update' => '更新', 'update' => '更新',
'edit' => '編集', 'edit' => '編集',
'archive' => 'Archive', 'archive' => 'アーカイブ',
'unarchive' => 'Un-Archive', 'unarchive' => 'アーカイブ解除',
'sort' => '並び順', 'sort' => '並び順',
'move' => '移動', 'move' => '移動',
'copy' => 'コピー', 'copy' => 'コピー',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(安定したコンテンツ)', 'pages_edit_switch_to_markdown_stable' => '(安定したコンテンツ)',
'pages_edit_switch_to_wysiwyg' => 'WYSIWYGエディタに切り替え', 'pages_edit_switch_to_wysiwyg' => 'WYSIWYGエディタに切り替え',
'pages_edit_switch_to_new_wysiwyg' => '新しいWYSIWYGエディタに切り替える', 'pages_edit_switch_to_new_wysiwyg' => '新しいWYSIWYGエディタに切り替える',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(ベータテスト版)',
'pages_edit_set_changelog' => '編集内容についての説明', 'pages_edit_set_changelog' => '編集内容についての説明',
'pages_edit_enter_changelog_desc' => 'どのような変更を行ったのかを記録してください', 'pages_edit_enter_changelog_desc' => 'どのような変更を行ったのかを記録してください',
'pages_edit_enter_changelog' => '編集内容を入力', 'pages_edit_enter_changelog' => '編集内容を入力',
@@ -393,11 +393,11 @@ return [
'comment' => 'コメント', 'comment' => 'コメント',
'comments' => 'コメント', 'comments' => 'コメント',
'comment_add' => 'コメント追加', 'comment_add' => 'コメント追加',
'comment_none' => 'No comments to display', 'comment_none' => '表示するコメントがありません',
'comment_placeholder' => 'コメントを記入してください', 'comment_placeholder' => 'コメントを記入してください',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count 個のコメントスレッド|:count 個のコメントスレッド',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count 個のアーカイブ',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'アーカイブされたスレッド',
'comment_save' => 'コメントを保存', 'comment_save' => 'コメントを保存',
'comment_new' => '新規コメント作成', 'comment_new' => '新規コメント作成',
'comment_created' => 'コメントを作成しました :createDiff', 'comment_created' => 'コメントを作成しました :createDiff',
@@ -406,14 +406,14 @@ return [
'comment_deleted_success' => 'コメントを削除しました', 'comment_deleted_success' => 'コメントを削除しました',
'comment_created_success' => 'コメントを追加しました', 'comment_created_success' => 'コメントを追加しました',
'comment_updated_success' => 'コメントを更新しました', 'comment_updated_success' => 'コメントを更新しました',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'コメントをアーカイブしました',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'コメントのアーカイブを解除しました',
'comment_view' => 'View comment', 'comment_view' => 'コメントを表示',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'スレッドにジャンプ',
'comment_delete_confirm' => '本当にこのコメントを削除しますか?', 'comment_delete_confirm' => '本当にこのコメントを削除しますか?',
'comment_in_reply_to' => ':commentIdへ返信', 'comment_in_reply_to' => ':commentIdへ返信',
'comment_reference' => 'Reference', 'comment_reference' => '参照箇所',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(以前の記述)',
'comment_editor_explain' => 'ここにはページに付けられたコメントを表示します。 コメントの追加と管理は保存されたページの表示時に行うことができます。', 'comment_editor_explain' => 'ここにはページに付けられたコメントを表示します。 コメントの追加と管理は保存されたページの表示時に行うことができます。',
// Revision // Revision

View File

@@ -30,8 +30,8 @@ return [
'create' => 'Aanmaken', 'create' => 'Aanmaken',
'update' => 'Bijwerken', 'update' => 'Bijwerken',
'edit' => 'Bewerk', 'edit' => 'Bewerk',
'archive' => 'Archive', 'archive' => 'Archiveer',
'unarchive' => 'Un-Archive', 'unarchive' => 'Terughalen',
'sort' => 'Sorteer', 'sort' => 'Sorteer',
'move' => 'Verplaats', 'move' => 'Verplaats',
'copy' => 'Kopieer', 'copy' => 'Kopieer',

View File

@@ -23,7 +23,7 @@ return [
'meta_updated' => 'Bijgewerkt: :timeLength', 'meta_updated' => 'Bijgewerkt: :timeLength',
'meta_updated_name' => 'Bijgewerkt: :timeLength door :user', 'meta_updated_name' => 'Bijgewerkt: :timeLength door :user',
'meta_owned_name' => 'Eigendom van :user', 'meta_owned_name' => 'Eigendom van :user',
'meta_reference_count' => 'Gerefereerd door :count item|Gerefereerd door :count items', 'meta_reference_count' => 'Verwijzing in :count item|Verwijzing in :count items',
'entity_select' => 'Entiteit selecteren', 'entity_select' => 'Entiteit selecteren',
'entity_select_lack_permission' => 'Je hebt niet de vereiste machtiging om dit item te selecteren', 'entity_select_lack_permission' => 'Je hebt niet de vereiste machtiging om dit item te selecteren',
'images' => 'Afbeeldingen', 'images' => 'Afbeeldingen',
@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Stabiele Inhoud)', 'pages_edit_switch_to_markdown_stable' => '(Stabiele Inhoud)',
'pages_edit_switch_to_wysiwyg' => 'Schakel naar de WYSIWYG Bewerker', 'pages_edit_switch_to_wysiwyg' => 'Schakel naar de WYSIWYG Bewerker',
'pages_edit_switch_to_new_wysiwyg' => 'Schakel naar de nieuwe WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Schakel naar de nieuwe WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta-testfase)',
'pages_edit_set_changelog' => 'Logboek instellen', 'pages_edit_set_changelog' => 'Logboek instellen',
'pages_edit_enter_changelog_desc' => 'Geef een korte omschrijving van de wijzigingen die je gemaakt hebt', 'pages_edit_enter_changelog_desc' => 'Geef een korte omschrijving van de wijzigingen die je gemaakt hebt',
'pages_edit_enter_changelog' => 'Voeg toe aan logboek', 'pages_edit_enter_changelog' => 'Voeg toe aan logboek',
@@ -392,11 +392,11 @@ return [
'comment' => 'Reactie', 'comment' => 'Reactie',
'comments' => 'Reacties', 'comments' => 'Reacties',
'comment_add' => 'Reactie toevoegen', 'comment_add' => 'Reactie toevoegen',
'comment_none' => 'No comments to display', 'comment_none' => 'Geen opmerkingen om weer te geven',
'comment_placeholder' => 'Laat hier een reactie achter', 'comment_placeholder' => 'Laat hier een reactie achter',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count Reactie Thread|:count Reactie Threads',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count Gearchiveerd',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Gearchiveerde Threads',
'comment_save' => 'Sla reactie op', 'comment_save' => 'Sla reactie op',
'comment_new' => 'Nieuwe reactie', 'comment_new' => 'Nieuwe reactie',
'comment_created' => 'reactie gegeven :createDiff', 'comment_created' => 'reactie gegeven :createDiff',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Reactie verwijderd', 'comment_deleted_success' => 'Reactie verwijderd',
'comment_created_success' => 'Reactie toegevoegd', 'comment_created_success' => 'Reactie toegevoegd',
'comment_updated_success' => 'Reactie bijgewerkt', 'comment_updated_success' => 'Reactie bijgewerkt',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Opmerking gearchiveerd',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Opmerking teruggehaald',
'comment_view' => 'View comment', 'comment_view' => 'Opmerking weergeven',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Ga naar thread',
'comment_delete_confirm' => 'Weet je zeker dat je deze reactie wilt verwijderen?', 'comment_delete_confirm' => 'Weet je zeker dat je deze reactie wilt verwijderen?',
'comment_in_reply_to' => 'Als antwoord op :commentId', 'comment_in_reply_to' => 'Als antwoord op :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Verwijzing',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Verouderd)',
'comment_editor_explain' => 'Hier zijn de opmerkingen die zijn achtergelaten op deze pagina. Opmerkingen kunnen worden toegevoegd en beheerd wanneer u de opgeslagen pagina bekijkt.', 'comment_editor_explain' => 'Hier zijn de opmerkingen die zijn achtergelaten op deze pagina. Opmerkingen kunnen worden toegevoegd en beheerd wanneer u de opgeslagen pagina bekijkt.',
// Revision // Revision

View File

@@ -35,8 +35,8 @@ return [
'create' => 'Criar', 'create' => 'Criar',
'update' => 'Atualizar', 'update' => 'Atualizar',
'edit' => 'Editar', 'edit' => 'Editar',
'archive' => 'Archive', 'archive' => 'Arquivar',
'unarchive' => 'Un-Archive', 'unarchive' => 'Desarquivar',
'sort' => 'Ordenar', 'sort' => 'Ordenar',
'move' => 'Mover', 'move' => 'Mover',
'copy' => 'Copiar', 'copy' => 'Copiar',

View File

@@ -248,7 +248,7 @@ return [
'pages_edit_switch_to_markdown_stable' => '(Conteúdo Estável)', 'pages_edit_switch_to_markdown_stable' => '(Conteúdo Estável)',
'pages_edit_switch_to_wysiwyg' => 'Alternar para o Editor WYSIWYG', 'pages_edit_switch_to_wysiwyg' => 'Alternar para o Editor WYSIWYG',
'pages_edit_switch_to_new_wysiwyg' => 'Mudar para o novo WYSIWYG', 'pages_edit_switch_to_new_wysiwyg' => 'Mudar para o novo WYSIWYG',
'pages_edit_switch_to_new_wysiwyg_desc' => '(In Beta Testing)', 'pages_edit_switch_to_new_wysiwyg_desc' => '(Em teste beta)',
'pages_edit_set_changelog' => 'Relatar Alterações', 'pages_edit_set_changelog' => 'Relatar Alterações',
'pages_edit_enter_changelog_desc' => 'Digite uma breve descrição das alterações efetuadas por você', 'pages_edit_enter_changelog_desc' => 'Digite uma breve descrição das alterações efetuadas por você',
'pages_edit_enter_changelog' => 'Insira Alterações', 'pages_edit_enter_changelog' => 'Insira Alterações',
@@ -392,11 +392,11 @@ return [
'comment' => 'Comentário', 'comment' => 'Comentário',
'comments' => 'Comentários', 'comments' => 'Comentários',
'comment_add' => 'Adicionar Comentário', 'comment_add' => 'Adicionar Comentário',
'comment_none' => 'No comments to display', 'comment_none' => 'Nenhum comentário para exibir',
'comment_placeholder' => 'Digite seus comentários aqui', 'comment_placeholder' => 'Digite seus comentários aqui',
'comment_thread_count' => ':count Comment Thread|:count Comment Threads', 'comment_thread_count' => ':count Tópico de Comentário|:count Tópicos de Comentários',
'comment_archived_count' => ':count Archived', 'comment_archived_count' => ':count Arquivado',
'comment_archived_threads' => 'Archived Threads', 'comment_archived_threads' => 'Tópicos Arquivados',
'comment_save' => 'Salvar comentário', 'comment_save' => 'Salvar comentário',
'comment_new' => 'Novo Comentário', 'comment_new' => 'Novo Comentário',
'comment_created' => 'comentado :createDiff', 'comment_created' => 'comentado :createDiff',
@@ -405,14 +405,14 @@ return [
'comment_deleted_success' => 'Comentário removido', 'comment_deleted_success' => 'Comentário removido',
'comment_created_success' => 'Comentário adicionado', 'comment_created_success' => 'Comentário adicionado',
'comment_updated_success' => 'Comentário editado', 'comment_updated_success' => 'Comentário editado',
'comment_archive_success' => 'Comment archived', 'comment_archive_success' => 'Comentário arquivado',
'comment_unarchive_success' => 'Comment un-archived', 'comment_unarchive_success' => 'Comentário desarquivado',
'comment_view' => 'View comment', 'comment_view' => 'Ver comentário',
'comment_jump_to_thread' => 'Jump to thread', 'comment_jump_to_thread' => 'Ir para o tópico',
'comment_delete_confirm' => 'Você tem certeza de que deseja excluir este comentário?', 'comment_delete_confirm' => 'Você tem certeza de que deseja excluir este comentário?',
'comment_in_reply_to' => 'Em resposta à :commentId', 'comment_in_reply_to' => 'Em resposta à :commentId',
'comment_reference' => 'Reference', 'comment_reference' => 'Referência',
'comment_reference_outdated' => '(Outdated)', 'comment_reference_outdated' => '(Desatualizado)',
'comment_editor_explain' => 'Aqui estão os comentários que foram deixados nesta página. Comentários podem ser adicionados e gerenciados ao visualizar a página salva.', 'comment_editor_explain' => 'Aqui estão os comentários que foram deixados nesta página. Comentários podem ser adicionados e gerenciados ao visualizar a página salva.',
// Revision // Revision

View File

@@ -47,7 +47,7 @@ return [
'bookshelf_update' => '更新書棧', 'bookshelf_update' => '更新書棧',
'bookshelf_update_notification' => '書棧已更新', 'bookshelf_update_notification' => '書棧已更新',
'bookshelf_delete' => '刪除書棧', 'bookshelf_delete' => '刪除書棧',
'bookshelf_delete_notification' => '書已刪除', 'bookshelf_delete_notification' => '書已刪除',
// Revisions // Revisions
'revision_restore' => '還原的版本', 'revision_restore' => '還原的版本',

View File

@@ -67,7 +67,7 @@ return [
// Entities // Entities
'entity_not_found' => '找不到實體', 'entity_not_found' => '找不到實體',
'bookshelf_not_found' => '未找到書', 'bookshelf_not_found' => '未找到書',
'book_not_found' => '找不到書本', 'book_not_found' => '找不到書本',
'page_not_found' => '找不到頁面', 'page_not_found' => '找不到頁面',
'chapter_not_found' => '找不到章節', 'chapter_not_found' => '找不到章節',

View File

@@ -40,7 +40,7 @@ export class PageComment extends Component {
this.commentId = this.$opts.commentId; this.commentId = this.$opts.commentId;
this.commentLocalId = this.$opts.commentLocalId; this.commentLocalId = this.$opts.commentLocalId;
this.deletedText = this.$opts.deletedText; this.deletedText = this.$opts.deletedText;
this.deletedText = this.$opts.deletedText; this.updatedText = this.$opts.updatedText;
this.archiveText = this.$opts.archiveText; this.archiveText = this.$opts.archiveText;
// Editor reference and text options // Editor reference and text options

View File

@@ -84,7 +84,7 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
// @ts-ignore // @ts-ignore
window.debugEditorState = () => { window.debugEditorState = () => {
console.log(editor.getEditorState().toJSON()); return editor.getEditorState().toJSON();
}; };
registerCommonNodeMutationListeners(context); registerCommonNodeMutationListeners(context);

View File

@@ -355,6 +355,7 @@ function onSelectionChange(
lastNode instanceof ParagraphNode && lastNode instanceof ParagraphNode &&
lastNode.getChildrenSize() === 0 lastNode.getChildrenSize() === 0
) { ) {
selection.format = lastNode.getTextFormat();
selection.style = lastNode.getTextStyle(); selection.style = lastNode.getTextStyle();
} else { } else {
selection.format = 0; selection.format = 0;

View File

@@ -1069,6 +1069,7 @@ describe('LexicalEditor tests', () => {
__prev: null, __prev: null,
__size: 1, __size: 1,
__style: '', __style: '',
__textFormat: 0,
__textStyle: '', __textStyle: '',
__type: 'paragraph', __type: 'paragraph',
}); });
@@ -1149,6 +1150,7 @@ describe('LexicalEditor tests', () => {
__prev: null, __prev: null,
__size: 1, __size: 1,
__style: '', __style: '',
__textFormat: 0,
__textStyle: '', __textStyle: '',
__type: 'paragraph', __type: 'paragraph',
}); });

View File

@@ -76,6 +76,7 @@ describe('LexicalEditorState tests', () => {
__prev: null, __prev: null,
__size: 1, __size: 1,
__style: '', __style: '',
__textFormat: 0,
__textStyle: '', __textStyle: '',
__type: 'paragraph', __type: 'paragraph',
}); });
@@ -111,7 +112,7 @@ describe('LexicalEditorState tests', () => {
}); });
expect(JSON.stringify(editor.getEditorState().toJSON())).toEqual( expect(JSON.stringify(editor.getEditorState().toJSON())).toEqual(
`{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Hello world","type":"text","version":1}],"direction":null,"type":"paragraph","version":1,"id":"","alignment":"","inset":0,"textStyle":""}],"direction":null,"type":"root","version":1}}`, `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Hello world","type":"text","version":1}],"direction":null,"type":"paragraph","version":1,"id":"","alignment":"","inset":0,"textFormat":0,"textStyle":""}],"direction":null,"type":"root","version":1}}`,
); );
}); });

File diff suppressed because one or more lines are too long

View File

@@ -38,6 +38,7 @@ import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
import {EditorUiContext} from "../../../../ui/framework/core"; import {EditorUiContext} from "../../../../ui/framework/core";
import {EditorUIManager} from "../../../../ui/framework/manager"; import {EditorUIManager} from "../../../../ui/framework/manager";
import {ImageNode} from "@lexical/rich-text/LexicalImageNode"; import {ImageNode} from "@lexical/rich-text/LexicalImageNode";
import {MediaNode} from "@lexical/rich-text/LexicalMediaNode";
type TestEnv = { type TestEnv = {
readonly container: HTMLDivElement; readonly container: HTMLDivElement;
@@ -487,6 +488,7 @@ export function createTestContext(): EditorUiContext {
theme: {}, theme: {},
nodes: [ nodes: [
ImageNode, ImageNode,
MediaNode,
] ]
}); });

View File

@@ -19,7 +19,7 @@ import type {
LexicalNode, LexicalNode,
NodeKey, NodeKey,
} from '../LexicalNode'; } from '../LexicalNode';
import type {RangeSelection} from 'lexical'; import {RangeSelection, TEXT_TYPE_TO_FORMAT, TextFormatType} from 'lexical';
import { import {
$applyNodeReplacement, $applyNodeReplacement,
@@ -36,6 +36,7 @@ import {CommonBlockNode, copyCommonBlockProperties, SerializedCommonBlockNode} f
export type SerializedParagraphNode = Spread< export type SerializedParagraphNode = Spread<
{ {
textFormat: number;
textStyle: string; textStyle: string;
}, },
SerializedCommonBlockNode SerializedCommonBlockNode
@@ -45,10 +46,12 @@ export type SerializedParagraphNode = Spread<
export class ParagraphNode extends CommonBlockNode { export class ParagraphNode extends CommonBlockNode {
['constructor']!: KlassConstructor<typeof ParagraphNode>; ['constructor']!: KlassConstructor<typeof ParagraphNode>;
/** @internal */ /** @internal */
__textFormat: number;
__textStyle: string; __textStyle: string;
constructor(key?: NodeKey) { constructor(key?: NodeKey) {
super(key); super(key);
this.__textFormat = 0;
this.__textStyle = ''; this.__textStyle = '';
} }
@@ -56,6 +59,22 @@ export class ParagraphNode extends CommonBlockNode {
return 'paragraph'; return 'paragraph';
} }
getTextFormat(): number {
const self = this.getLatest();
return self.__textFormat;
}
setTextFormat(type: number): this {
const self = this.getWritable();
self.__textFormat = type;
return self;
}
hasTextFormat(type: TextFormatType): boolean {
const formatFlag = TEXT_TYPE_TO_FORMAT[type];
return (this.getTextFormat() & formatFlag) !== 0;
}
getTextStyle(): string { getTextStyle(): string {
const self = this.getLatest(); const self = this.getLatest();
return self.__textStyle; return self.__textStyle;
@@ -73,6 +92,7 @@ export class ParagraphNode extends CommonBlockNode {
afterCloneFrom(prevNode: this) { afterCloneFrom(prevNode: this) {
super.afterCloneFrom(prevNode); super.afterCloneFrom(prevNode);
this.__textFormat = prevNode.__textFormat;
this.__textStyle = prevNode.__textStyle; this.__textStyle = prevNode.__textStyle;
copyCommonBlockProperties(prevNode, this); copyCommonBlockProperties(prevNode, this);
} }
@@ -125,12 +145,14 @@ export class ParagraphNode extends CommonBlockNode {
static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode { static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode {
const node = $createParagraphNode(); const node = $createParagraphNode();
deserializeCommonBlockNode(serializedNode, node); deserializeCommonBlockNode(serializedNode, node);
node.setTextFormat(serializedNode.textFormat);
return node; return node;
} }
exportJSON(): SerializedParagraphNode { exportJSON(): SerializedParagraphNode {
return { return {
...super.exportJSON(), ...super.exportJSON(),
textFormat: this.getTextFormat(),
textStyle: this.getTextStyle(), textStyle: this.getTextStyle(),
type: 'paragraph', type: 'paragraph',
version: 1, version: 1,
@@ -144,6 +166,7 @@ export class ParagraphNode extends CommonBlockNode {
restoreSelection: boolean, restoreSelection: boolean,
): ParagraphNode { ): ParagraphNode {
const newElement = $createParagraphNode(); const newElement = $createParagraphNode();
newElement.setTextFormat(rangeSelection.format);
newElement.setTextStyle(rangeSelection.style); newElement.setTextStyle(rangeSelection.style);
const direction = this.getDirection(); const direction = this.getDirection();
newElement.setDirection(direction); newElement.setDirection(direction);

View File

@@ -620,6 +620,7 @@ export class TextNode extends LexicalNode {
// HTML content and not have the ability to use CSS classes. // HTML content and not have the ability to use CSS classes.
exportDOM(editor: LexicalEditor): DOMExportOutput { exportDOM(editor: LexicalEditor): DOMExportOutput {
let {element} = super.exportDOM(editor); let {element} = super.exportDOM(editor);
const originalElementName = (element?.nodeName || '').toLowerCase()
invariant( invariant(
element !== null && isHTMLElement(element), element !== null && isHTMLElement(element),
'Expected TextNode createDOM to always return a HTMLElement', 'Expected TextNode createDOM to always return a HTMLElement',
@@ -649,8 +650,8 @@ export class TextNode extends LexicalNode {
// This is the only way to properly add support for most clients, // This is the only way to properly add support for most clients,
// even if it's semantically incorrect to have to resort to using // even if it's semantically incorrect to have to resort to using
// <b>, <u>, <s>, <i> elements. // <b>, <u>, <s>, <i> elements.
if (this.hasFormat('bold')) { if (this.hasFormat('bold') && originalElementName !== 'strong') {
element = wrapElementWith(element, 'b'); element = wrapElementWith(element, 'strong');
} }
if (this.hasFormat('italic')) { if (this.hasFormat('italic')) {
element = wrapElementWith(element, 'em'); element = wrapElementWith(element, 'em');

View File

@@ -53,6 +53,7 @@ describe('LexicalParagraphNode tests', () => {
direction: null, direction: null,
id: '', id: '',
inset: 0, inset: 0,
textFormat: 0,
textStyle: '', textStyle: '',
type: 'paragraph', type: 'paragraph',
version: 1, version: 1,

View File

@@ -839,7 +839,7 @@ describe('LexicalTextNode tests', () => {
paragraph.append(textNode); paragraph.append(textNode);
const html = $generateHtmlFromNodes($getEditor(), null); const html = $generateHtmlFromNodes($getEditor(), null);
expect(html).toBe('<p><u><em><b><code spellcheck="false"><strong>hello</strong></code></b></em></u></p>'); expect(html).toBe('<p><u><em><strong><code spellcheck="false"><strong>hello</strong></code></strong></em></u></p>');
}); });
}); });

View File

@@ -8,13 +8,12 @@ import {
} from 'lexical'; } from 'lexical';
import type {EditorConfig} from "lexical/LexicalEditor"; import type {EditorConfig} from "lexical/LexicalEditor";
import {el, setOrRemoveAttribute, sizeToPixels} from "../../utils/dom"; import {el, setOrRemoveAttribute, sizeToPixels, styleMapToStyleString, styleStringToStyleMap} from "../../utils/dom";
import { import {
CommonBlockAlignment, deserializeCommonBlockNode, CommonBlockAlignment, deserializeCommonBlockNode,
setCommonBlockPropsFromElement, setCommonBlockPropsFromElement,
updateElementWithCommonBlockProps updateElementWithCommonBlockProps
} from "lexical/nodes/common"; } from "lexical/nodes/common";
import {$selectSingleNode} from "../../utils/selection";
import {SerializedCommonBlockNode} from "lexical/nodes/CommonBlockNode"; import {SerializedCommonBlockNode} from "lexical/nodes/CommonBlockNode";
export type MediaNodeTag = 'iframe' | 'embed' | 'object' | 'video' | 'audio'; export type MediaNodeTag = 'iframe' | 'embed' | 'object' | 'video' | 'audio';
@@ -46,6 +45,19 @@ function filterAttributes(attributes: Record<string, string>): Record<string, st
return filtered; return filtered;
} }
function removeStyleFromAttributes(attributes: Record<string, string>, styleName: string): Record<string, string> {
const attrCopy = Object.assign({}, attributes);
if (!attributes.style) {
return attrCopy;
}
const map = styleStringToStyleMap(attributes.style);
map.delete(styleName);
attrCopy.style = styleMapToStyleString(map);
return attrCopy;
}
function domElementToNode(tag: MediaNodeTag, element: HTMLElement): MediaNode { function domElementToNode(tag: MediaNodeTag, element: HTMLElement): MediaNode {
const node = $createMediaNode(tag); const node = $createMediaNode(tag);
@@ -118,7 +130,7 @@ export class MediaNode extends ElementNode {
getAttributes(): Record<string, string> { getAttributes(): Record<string, string> {
const self = this.getLatest(); const self = this.getLatest();
return self.__attributes; return Object.assign({}, self.__attributes);
} }
setSources(sources: MediaNodeSource[]) { setSources(sources: MediaNodeSource[]) {
@@ -128,25 +140,37 @@ export class MediaNode extends ElementNode {
getSources(): MediaNodeSource[] { getSources(): MediaNodeSource[] {
const self = this.getLatest(); const self = this.getLatest();
return self.__sources; return self.__sources.map(s => Object.assign({}, s))
} }
setSrc(src: string): void { setSrc(src: string): void {
const attrs = Object.assign({}, this.getAttributes()); const attrs = this.getAttributes();
const sources = this.getSources();
if (this.__tag ==='object') { if (this.__tag ==='object') {
attrs.data = src; attrs.data = src;
} if (this.__tag === 'video' && sources.length > 0) {
sources[0].src = src;
delete attrs.src;
if (sources.length > 1) {
sources.splice(1, sources.length - 1);
}
this.setSources(sources);
} else { } else {
attrs.src = src; attrs.src = src;
} }
this.setAttributes(attrs); this.setAttributes(attrs);
} }
setWidthAndHeight(width: string, height: string): void { setWidthAndHeight(width: string, height: string): void {
const attrs = Object.assign( let attrs: Record<string, string> = Object.assign(
{},
this.getAttributes(), this.getAttributes(),
{width, height}, {width, height},
); );
attrs = removeStyleFromAttributes(attrs, 'width');
attrs = removeStyleFromAttributes(attrs, 'height');
this.setAttributes(attrs); this.setAttributes(attrs);
} }
@@ -185,8 +209,8 @@ export class MediaNode extends ElementNode {
return; return;
} }
const attrs = Object.assign({}, this.getAttributes(), {height}); const attrs = Object.assign(this.getAttributes(), {height});
this.setAttributes(attrs); this.setAttributes(removeStyleFromAttributes(attrs, 'height'));
} }
getHeight(): number { getHeight(): number {
@@ -195,8 +219,9 @@ export class MediaNode extends ElementNode {
} }
setWidth(width: number): void { setWidth(width: number): void {
const attrs = Object.assign({}, this.getAttributes(), {width}); const existingAttrs = this.getAttributes();
this.setAttributes(attrs); const attrs: Record<string, string> = Object.assign(existingAttrs, {width});
this.setAttributes(removeStyleFromAttributes(attrs, 'width'));
} }
getWidth(): number { getWidth(): number {
@@ -222,15 +247,9 @@ export class MediaNode extends ElementNode {
createDOM(_config: EditorConfig, _editor: LexicalEditor) { createDOM(_config: EditorConfig, _editor: LexicalEditor) {
const media = this.createInnerDOM(); const media = this.createInnerDOM();
const wrap = el('span', { return el('span', {
class: media.className + ' editor-media-wrap', class: media.className + ' editor-media-wrap',
}, [media]); }, [media]);
wrap.addEventListener('click', e => {
_editor.update(() => $selectSingleNode(this));
});
return wrap;
} }
updateDOM(prevNode: MediaNode, dom: HTMLElement): boolean { updateDOM(prevNode: MediaNode, dom: HTMLElement): boolean {

View File

@@ -0,0 +1,46 @@
import {createTestContext} from "lexical/__tests__/utils";
import {$createMediaNode} from "@lexical/rich-text/LexicalMediaNode";
describe('LexicalMediaNode', () => {
test('setWidth/setHeight/setWidthAndHeight functions remove relevant styles', () => {
const {editor} = createTestContext();
editor.updateAndCommit(() => {
const mediaMode = $createMediaNode('video');
const defaultStyles = {style: 'width:20px;height:40px;color:red'};
mediaMode.setAttributes(defaultStyles);
mediaMode.setWidth(60);
expect(mediaMode.getWidth()).toBe(60);
expect(mediaMode.getAttributes().style).toBe('height:40px;color:red');
mediaMode.setAttributes(defaultStyles);
mediaMode.setHeight(77);
expect(mediaMode.getHeight()).toBe(77);
expect(mediaMode.getAttributes().style).toBe('width:20px;color:red');
mediaMode.setAttributes(defaultStyles);
mediaMode.setWidthAndHeight('6', '7');
expect(mediaMode.getWidth()).toBe(6);
expect(mediaMode.getHeight()).toBe(7);
expect(mediaMode.getAttributes().style).toBe('color:red');
});
});
test('setSrc on video uses sources if existing', () => {
const {editor} = createTestContext();
editor.updateAndCommit(() => {
const mediaMode = $createMediaNode('video');
mediaMode.setAttributes({src: 'z'});
mediaMode.setSources([{src: 'a', type: 'video'}, {src: 'b', type: 'video'}]);
mediaMode.setSrc('c');
expect(mediaMode.getAttributes().src).toBeUndefined();
expect(mediaMode.getSources()).toHaveLength(1);
expect(mediaMode.getSources()[0].src).toBe('c');
});
});
});

View File

@@ -123,6 +123,7 @@ describe('table selection', () => {
__prev: null, __prev: null,
__size: 1, __size: 1,
__style: '', __style: '',
__textFormat: 0,
__textStyle: '', __textStyle: '',
__type: 'paragraph', __type: 'paragraph',
}); });

View File

@@ -92,6 +92,7 @@ export const image: EditorButtonDefinition = {
context.editor.update(() => { context.editor.update(() => {
const link = $createLinkedImageNodeFromImageData(image); const link = $createLinkedImageNodeFromImageData(image);
$insertNodes([link]); $insertNodes([link]);
link.select();
}); });
}) })
}); });

View File

@@ -192,11 +192,17 @@ export function $showMediaForm(media: MediaNode|null, context: EditorUiContext):
let formDefaults = {}; let formDefaults = {};
if (media) { if (media) {
const nodeAttrs = media.getAttributes(); const nodeAttrs = media.getAttributes();
const nodeDOM = media.exportDOM(context.editor).element;
const nodeHtml = (nodeDOM instanceof HTMLElement) ? nodeDOM.outerHTML : '';
formDefaults = { formDefaults = {
src: nodeAttrs.src || nodeAttrs.data || '', src: nodeAttrs.src || nodeAttrs.data || media.getSources()[0]?.src || '',
width: nodeAttrs.width, width: nodeAttrs.width,
height: nodeAttrs.height, height: nodeAttrs.height,
embed: '', embed: nodeHtml,
// This is used so we can check for edits against the embed field on submit
embed_check: nodeHtml,
} }
} }
@@ -214,7 +220,8 @@ export const media: EditorFormDefinition = {
})); }));
const embedCode = (formData.get('embed') || '').toString().trim(); const embedCode = (formData.get('embed') || '').toString().trim();
if (embedCode) { const embedCheck = (formData.get('embed_check') || '').toString().trim();
if (embedCode && embedCode !== embedCheck) {
context.editor.update(() => { context.editor.update(() => {
const node = $createMediaNodeFromHtml(embedCode); const node = $createMediaNodeFromHtml(embedCode);
if (selectedNode && node) { if (selectedNode && node) {
@@ -236,6 +243,7 @@ export const media: EditorFormDefinition = {
if (selectedNode) { if (selectedNode) {
selectedNode.setSrc(src); selectedNode.setSrc(src);
selectedNode.setWidthAndHeight(width, height); selectedNode.setWidthAndHeight(width, height);
context.manager.triggerFutureStateRefresh();
return; return;
} }
@@ -281,6 +289,11 @@ export const media: EditorFormDefinition = {
name: 'embed', name: 'embed',
type: 'textarea', type: 'textarea',
}, },
{
label: '',
name: 'embed_check',
type: 'hidden',
},
], ],
} }
]) ])

View File

@@ -224,6 +224,10 @@ export function getImageToolbarContent(): EditorUiElement[] {
return [new EditorButton(image)]; return [new EditorButton(image)];
} }
export function getMediaToolbarContent(): EditorUiElement[] {
return [new EditorButton(media)];
}
export function getLinkToolbarContent(): EditorUiElement[] { export function getLinkToolbarContent(): EditorUiElement[] {
return [ return [
new EditorButton(link), new EditorButton(link),

View File

@@ -11,7 +11,7 @@ import {el} from "../../utils/dom";
export interface EditorFormFieldDefinition { export interface EditorFormFieldDefinition {
label: string; label: string;
name: string; name: string;
type: 'text' | 'select' | 'textarea' | 'checkbox'; type: 'text' | 'select' | 'textarea' | 'checkbox' | 'hidden';
} }
export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition { export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition {
@@ -67,6 +67,9 @@ export class EditorFormField extends EditorUiElement {
input = el('textarea', {id, name: this.definition.name, class: 'editor-form-field-input'}); input = el('textarea', {id, name: this.definition.name, class: 'editor-form-field-input'});
} else if (this.definition.type === 'checkbox') { } else if (this.definition.type === 'checkbox') {
input = el('input', {id, name: this.definition.name, type: 'checkbox', class: 'editor-form-field-input-checkbox', value: 'true'}); input = el('input', {id, name: this.definition.name, type: 'checkbox', class: 'editor-form-field-input-checkbox', value: 'true'});
} else if (this.definition.type === 'hidden') {
input = el('input', {id, name: this.definition.name, type: 'hidden'});
return el('div', {hidden: 'true'}, [input]);
} else { } else {
input = el('input', {id, name: this.definition.name, class: 'editor-form-field-input'}); input = el('input', {id, name: this.definition.name, class: 'editor-form-field-input'});
} }

View File

@@ -12,17 +12,21 @@ function isNodeWithSize(node: LexicalNode): node is NodeHasSize&LexicalNode {
class NodeResizer { class NodeResizer {
protected context: EditorUiContext; protected context: EditorUiContext;
protected dom: HTMLElement|null = null; protected resizerDOM: HTMLElement|null = null;
protected targetNode: LexicalNode|null = null;
protected scrollContainer: HTMLElement; protected scrollContainer: HTMLElement;
protected mouseTracker: MouseDragTracker|null = null; protected mouseTracker: MouseDragTracker|null = null;
protected activeSelection: string = ''; protected activeSelection: string = '';
protected loadAbortController = new AbortController();
constructor(context: EditorUiContext) { constructor(context: EditorUiContext) {
this.context = context; this.context = context;
this.scrollContainer = context.scrollDOM; this.scrollContainer = context.scrollDOM;
this.onSelectionChange = this.onSelectionChange.bind(this); this.onSelectionChange = this.onSelectionChange.bind(this);
this.onTargetDOMLoad = this.onTargetDOMLoad.bind(this);
context.manager.onSelectionChange(this.onSelectionChange); context.manager.onSelectionChange(this.onSelectionChange);
} }
@@ -34,12 +38,7 @@ class NodeResizer {
if (nodes.length === 1 && isNodeWithSize(nodes[0])) { if (nodes.length === 1 && isNodeWithSize(nodes[0])) {
const node = nodes[0]; const node = nodes[0];
const nodeKey = node.getKey(); let nodeDOM = this.getTargetDOM(node)
let nodeDOM = this.context.editor.getElementByKey(nodeKey);
if (nodeDOM && nodeDOM.nodeName === 'SPAN') {
nodeDOM = nodeDOM.firstElementChild as HTMLElement;
}
if (nodeDOM) { if (nodeDOM) {
this.showForNode(node, nodeDOM); this.showForNode(node, nodeDOM);
@@ -47,56 +46,81 @@ class NodeResizer {
} }
} }
protected getTargetDOM(targetNode: LexicalNode|null): HTMLElement|null {
if (targetNode == null) {
return null;
}
let nodeDOM = this.context.editor.getElementByKey(targetNode.__key)
if (nodeDOM && nodeDOM.nodeName === 'SPAN') {
nodeDOM = nodeDOM.firstElementChild as HTMLElement;
}
return nodeDOM;
}
protected onTargetDOMLoad(): void {
this.updateResizerPosition();
}
teardown() { teardown() {
this.context.manager.offSelectionChange(this.onSelectionChange); this.context.manager.offSelectionChange(this.onSelectionChange);
this.hide(); this.hide();
} }
protected showForNode(node: NodeHasSize&LexicalNode, dom: HTMLElement) { protected showForNode(node: NodeHasSize&LexicalNode, targetDOM: HTMLElement) {
this.dom = this.buildDOM(); this.resizerDOM = this.buildDOM();
this.targetNode = node;
let ghost = el('span', {class: 'editor-node-resizer-ghost'}); let ghost = el('span', {class: 'editor-node-resizer-ghost'});
if ($isImageNode(node)) { if ($isImageNode(node)) {
ghost = el('img', {src: dom.getAttribute('src'), class: 'editor-node-resizer-ghost'}); ghost = el('img', {src: targetDOM.getAttribute('src'), class: 'editor-node-resizer-ghost'});
} }
this.dom.append(ghost); this.resizerDOM.append(ghost);
this.context.scrollDOM.append(this.dom); this.context.scrollDOM.append(this.resizerDOM);
this.updateDOMPosition(dom); this.updateResizerPosition();
this.mouseTracker = this.setupTracker(this.dom, node, dom); this.mouseTracker = this.setupTracker(this.resizerDOM, node, targetDOM);
this.activeSelection = node.getKey(); this.activeSelection = node.getKey();
if (targetDOM.matches('img, embed, iframe, object')) {
this.loadAbortController = new AbortController();
targetDOM.addEventListener('load', this.onTargetDOMLoad, { signal: this.loadAbortController.signal });
}
} }
protected updateDOMPosition(nodeDOM: HTMLElement) { protected updateResizerPosition() {
if (!this.dom) { const targetDOM = this.getTargetDOM(this.targetNode);
if (!this.resizerDOM || !targetDOM) {
return; return;
} }
const scrollAreaRect = this.scrollContainer.getBoundingClientRect(); const scrollAreaRect = this.scrollContainer.getBoundingClientRect();
const nodeRect = nodeDOM.getBoundingClientRect(); const nodeRect = targetDOM.getBoundingClientRect();
const top = nodeRect.top - (scrollAreaRect.top - this.scrollContainer.scrollTop); const top = nodeRect.top - (scrollAreaRect.top - this.scrollContainer.scrollTop);
const left = nodeRect.left - scrollAreaRect.left; const left = nodeRect.left - scrollAreaRect.left;
this.dom.style.top = `${top}px`; this.resizerDOM.style.top = `${top}px`;
this.dom.style.left = `${left}px`; this.resizerDOM.style.left = `${left}px`;
this.dom.style.width = nodeRect.width + 'px'; this.resizerDOM.style.width = nodeRect.width + 'px';
this.dom.style.height = nodeRect.height + 'px'; this.resizerDOM.style.height = nodeRect.height + 'px';
} }
protected updateDOMSize(width: number, height: number): void { protected updateDOMSize(width: number, height: number): void {
if (!this.dom) { if (!this.resizerDOM) {
return; return;
} }
this.dom.style.width = width + 'px'; this.resizerDOM.style.width = width + 'px';
this.dom.style.height = height + 'px'; this.resizerDOM.style.height = height + 'px';
} }
protected hide() { protected hide() {
this.mouseTracker?.teardown(); this.mouseTracker?.teardown();
this.dom?.remove(); this.resizerDOM?.remove();
this.targetNode = null;
this.activeSelection = ''; this.activeSelection = '';
this.loadAbortController.abort();
} }
protected buildDOM() { protected buildDOM() {
@@ -110,7 +134,7 @@ class NodeResizer {
}, handleElems); }, handleElems);
} }
setupTracker(container: HTMLElement, node: NodeHasSize, nodeDOM: HTMLElement): MouseDragTracker { setupTracker(container: HTMLElement, node: NodeHasSize&LexicalNode, nodeDOM: HTMLElement): MouseDragTracker {
let startingWidth: number = 0; let startingWidth: number = 0;
let startingHeight: number = 0; let startingHeight: number = 0;
let startingRatio: number = 0; let startingRatio: number = 0;
@@ -140,7 +164,7 @@ class NodeResizer {
return new MouseDragTracker(container, '.editor-node-resizer-handle', { return new MouseDragTracker(container, '.editor-node-resizer-handle', {
down(event: MouseEvent, handle: HTMLElement) { down(event: MouseEvent, handle: HTMLElement) {
_this.dom?.classList.add('active'); _this.resizerDOM?.classList.add('active');
_this.context.editor.getEditorState().read(() => { _this.context.editor.getEditorState().read(() => {
const domRect = nodeDOM.getBoundingClientRect(); const domRect = nodeDOM.getBoundingClientRect();
startingWidth = node.getWidth() || domRect.width; startingWidth = node.getWidth() || domRect.width;
@@ -163,12 +187,15 @@ class NodeResizer {
_this.context.editor.update(() => { _this.context.editor.update(() => {
node.setWidth(size.width); node.setWidth(size.width);
node.setHeight(hasHeight ? size.height : 0); node.setHeight(hasHeight ? size.height : 0);
_this.context.manager.triggerLayoutUpdate(); }, {
onUpdate: () => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
_this.updateDOMPosition(nodeDOM); _this.context.manager.triggerLayoutUpdate();
}) _this.updateResizerPosition();
}); });
_this.dom?.classList.remove('active'); }
});
_this.resizerDOM?.classList.remove('active');
} }
}); });
} }

View File

@@ -15,6 +15,7 @@ class TableResizer {
protected targetCell: HTMLElement|null = null; protected targetCell: HTMLElement|null = null;
protected xMarkerAtStart : boolean = false; protected xMarkerAtStart : boolean = false;
protected yMarkerAtStart : boolean = false; protected yMarkerAtStart : boolean = false;
protected activeInTable: boolean = false;
constructor(editor: LexicalEditor, editScrollContainer: HTMLElement) { constructor(editor: LexicalEditor, editScrollContainer: HTMLElement) {
this.editor = editor; this.editor = editor;
@@ -33,9 +34,10 @@ class TableResizer {
} }
protected setupListeners() { protected setupListeners() {
this.onTableMouseOver = this.onTableMouseOver.bind(this);
this.onCellMouseMove = this.onCellMouseMove.bind(this); this.onCellMouseMove = this.onCellMouseMove.bind(this);
this.onScrollOrResize = this.onScrollOrResize.bind(this); this.onScrollOrResize = this.onScrollOrResize.bind(this);
this.editScrollContainer.addEventListener('mousemove', this.onCellMouseMove); this.editScrollContainer.addEventListener('mouseover', this.onTableMouseOver, { passive: true });
window.addEventListener('scroll', this.onScrollOrResize, {capture: true, passive: true}); window.addEventListener('scroll', this.onScrollOrResize, {capture: true, passive: true});
window.addEventListener('resize', this.onScrollOrResize, {passive: true}); window.addEventListener('resize', this.onScrollOrResize, {passive: true});
} }
@@ -44,8 +46,26 @@ class TableResizer {
this.updateCurrentMarkerTargetPosition(); this.updateCurrentMarkerTargetPosition();
} }
protected onTableMouseOver(event: MouseEvent): void {
if (this.dragging) {
return;
}
const table = (event.target as HTMLElement).closest('table') as HTMLElement|null;
if (table && !this.activeInTable) {
this.editScrollContainer.addEventListener('mousemove', this.onCellMouseMove, { passive: true });
this.onCellMouseMove(event);
this.activeInTable = true;
} else if (!table && this.activeInTable) {
this.editScrollContainer.removeEventListener('mousemove', this.onCellMouseMove);
this.hideMarkers();
this.activeInTable = false;
}
}
protected onCellMouseMove(event: MouseEvent) { protected onCellMouseMove(event: MouseEvent) {
const cell = (event.target as HTMLElement).closest('td,th') as HTMLElement; const cell = (event.target as HTMLElement).closest('td,th') as HTMLElement|null;
if (!cell || this.dragging) { if (!cell || this.dragging) {
return; return;
} }
@@ -66,10 +86,16 @@ class TableResizer {
protected updateMarkersTo(cell: HTMLElement, xPos: number, yPos: number) { protected updateMarkersTo(cell: HTMLElement, xPos: number, yPos: number) {
const markers: MarkerDomRecord = this.getMarkers(); const markers: MarkerDomRecord = this.getMarkers();
const table = cell.closest('table') as HTMLElement; const table = cell.closest('table') as HTMLElement;
const caption: HTMLTableCaptionElement|null = table.querySelector('caption');
const tableRect = table.getBoundingClientRect(); const tableRect = table.getBoundingClientRect();
const editBounds = this.editScrollContainer.getBoundingClientRect(); const editBounds = this.editScrollContainer.getBoundingClientRect();
const maxTop = Math.max(tableRect.top, editBounds.top); let tableTop = tableRect.top;
if (caption) {
tableTop = caption.getBoundingClientRect().bottom;
}
const maxTop = Math.max(tableTop, editBounds.top);
const maxBottom = Math.min(tableRect.bottom, editBounds.bottom); const maxBottom = Math.min(tableRect.bottom, editBounds.bottom);
const maxHeight = maxBottom - maxTop; const maxHeight = maxBottom - maxTop;
markers.x.style.left = xPos + 'px'; markers.x.style.left = xPos + 'px';
@@ -85,6 +111,13 @@ class TableResizer {
markers.x.hidden = tableRect.top > editBounds.bottom || tableRect.bottom < editBounds.top; markers.x.hidden = tableRect.top > editBounds.bottom || tableRect.bottom < editBounds.top;
} }
protected hideMarkers(): void {
if (this.markerDom) {
this.markerDom.x.hidden = true;
this.markerDom.y.hidden = true;
}
}
protected updateCurrentMarkerTargetPosition(): void { protected updateCurrentMarkerTargetPosition(): void {
if (!this.targetCell) { if (!this.targetCell) {
return; return;

View File

@@ -34,7 +34,11 @@ export class EditorContextToolbar extends EditorContainerUiElement {
dom.hidden = !showing; dom.hidden = !showing;
if (!showing) { if (!this.target.isConnected) {
// If our target is no longer in the DOM, tell the manager an update is needed.
this.getContext().manager.triggerFutureStateRefresh();
return;
} else if (!showing) {
return; return;
} }

View File

@@ -3,7 +3,7 @@ import {
getCodeToolbarContent, getDetailsToolbarContent, getCodeToolbarContent, getDetailsToolbarContent,
getImageToolbarContent, getImageToolbarContent,
getLinkToolbarContent, getLinkToolbarContent,
getMainEditorFullToolbar, getTableToolbarContent getMainEditorFullToolbar, getMediaToolbarContent, getTableToolbarContent
} from "./defaults/toolbars"; } from "./defaults/toolbars";
import {EditorUIManager} from "./framework/manager"; import {EditorUIManager} from "./framework/manager";
import {EditorUiContext} from "./framework/core"; import {EditorUiContext} from "./framework/core";
@@ -44,6 +44,10 @@ export function buildEditorUI(container: HTMLElement, element: HTMLElement, scro
selector: 'img:not([drawio-diagram] img)', selector: 'img:not([drawio-diagram] img)',
content: getImageToolbarContent(), content: getImageToolbarContent(),
}); });
manager.registerContextToolbar('media', {
selector: '.editor-media-wrap',
content: getMediaToolbarContent(),
});
manager.registerContextToolbar('link', { manager.registerContextToolbar('link', {
selector: 'a', selector: 'a',
content: getLinkToolbarContent(), content: getLinkToolbarContent(),

View File

@@ -52,12 +52,19 @@ export type StyleMap = Map<string, string>;
/** /**
* Creates a map from an element's styles. * Creates a map from an element's styles.
* Uses direct attribute value string handling since attempting to iterate * Uses direct attribute value string handling since attempting to iterate
* over .style will expand out any shorthand properties (like 'padding') making * over .style will expand out any shorthand properties (like 'padding')
* rather than being representative of the actual properties set. * rather than being representative of the actual properties set.
*/ */
export function extractStyleMapFromElement(element: HTMLElement): StyleMap { export function extractStyleMapFromElement(element: HTMLElement): StyleMap {
const map: StyleMap = new Map();
const styleText= element.getAttribute('style') || ''; const styleText= element.getAttribute('style') || '';
return styleStringToStyleMap(styleText);
}
/**
* Convert string-formatted styles into a StyleMap.
*/
export function styleStringToStyleMap(styleText: string): StyleMap {
const map: StyleMap = new Map();
const rules = styleText.split(';'); const rules = styleText.split(';');
for (const rule of rules) { for (const rule of rules) {
@@ -72,6 +79,17 @@ export function extractStyleMapFromElement(element: HTMLElement): StyleMap {
return map; return map;
} }
/**
* Convert a StyleMap into inline string style text.
*/
export function styleMapToStyleString(map: StyleMap): string {
const parts = [];
for (const [style, value] of map.entries()) {
parts.push(`${style}:${value}`);
}
return parts.join(';');
}
export function setOrRemoveAttribute(element: HTMLElement, name: string, value: string|null|undefined) { export function setOrRemoveAttribute(element: HTMLElement, name: string, value: string|null|undefined) {
if (value) { if (value) {
element.setAttribute(name, value); element.setAttribute(name, value);

View File

@@ -3,7 +3,7 @@ import {
$createParagraphNode, $createRangeSelection, $createParagraphNode, $createRangeSelection,
$getRoot, $getRoot,
$getSelection, $isBlockElementNode, $isDecoratorNode, $getSelection, $isBlockElementNode, $isDecoratorNode,
$isElementNode, $isElementNode, $isParagraphNode,
$isTextNode, $isTextNode,
$setSelection, $setSelection,
BaseSelection, DecoratorNode, BaseSelection, DecoratorNode,
@@ -60,12 +60,19 @@ export function $selectionContainsTextFormat(selection: BaseSelection | null, fo
return false; return false;
} }
for (const node of selection.getNodes()) { // Check text nodes
const nodes = selection.getNodes();
for (const node of nodes) {
if ($isTextNode(node) && node.hasFormat(format)) { if ($isTextNode(node) && node.hasFormat(format)) {
return true; return true;
} }
} }
// If we're in an empty paragraph, check the paragraph format
if (nodes.length === 1 && $isParagraphNode(nodes[0]) && nodes[0].hasTextFormat(format)) {
return true;
}
return false; return false;
} }

View File

@@ -454,7 +454,7 @@ body.editor-is-fullscreen {
.editor-media-wrap { .editor-media-wrap {
display: inline-block; display: inline-block;
cursor: not-allowed; cursor: not-allowed;
iframe { iframe, video {
pointer-events: none; pointer-events: none;
} }
&.align-left { &.align-left {

View File

@@ -106,4 +106,14 @@ class SearchIndexingTest extends TestCase
$this->assertNull($scoreByTerm->get($term), "Failed asserting that \"$term\" is not indexed"); $this->assertNull($scoreByTerm->get($term), "Failed asserting that \"$term\" is not indexed");
} }
} }
public function test_non_breaking_spaces_handled_as_spaces()
{
$page = $this->entities->newPage(['html' => '<p>a&nbsp;tigerbadger is a dangerous&nbsp;animal</p>']);
$scoreByTerm = $page->searchTerms()->pluck('score', 'term');
$this->assertNotNull($scoreByTerm->get('tigerbadger'));
$this->assertNotNull($scoreByTerm->get('dangerous'));
$this->assertNotNull($scoreByTerm->get('animal'));
}
} }