From c76d12d1ded72b5bf74a51fdb1647f87bb935edc Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Fri, 15 Dec 2023 10:58:20 -0700 Subject: [PATCH 01/59] Oidc: Properly query the UserInfo Endpoint BooksStack's OIDC Client requests the 'profile' and 'email' scope values in order to have access to the 'name', 'email', and other claims. It looks for these claims in the ID Token that is returned along with the Access Token. However, the OIDC-core specification section 5.4 [1] only requires that the Provider include those claims in the ID Token *if* an Access Token is not also issued. If an Access Token is issued, the Provider can leave out those claims from the ID Token, and the Client is supposed to obtain them by submitting the Access Token to the UserInfo Endpoint. So I suppose it's just good luck that the OIDC Providers that BookStack has been tested with just so happen to also stick those claims in the ID Token even though they don't have to. But others (in particular: https://login.infomaniak.com) don't do so, and require fetching the UserInfo Endpoint.) A workaround is currently possible by having the user write a theme with a ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook that fetches the UserInfo Endpoint. This workaround isn't great, for a few reasons: 1. Asking the user to implement core parts of the OIDC protocol is silly. 2. The user either needs to re-fetch the .well-known/openid-configuration file to discover the endpoint (adding yet another round-trip to each login) or hard-code the endpoint, which is fragile. 3. The hook doesn't receive the HTTP client configuration. So, have BookStack's OidcService fetch the UserInfo Endpoint and inject those claims into the ID Token, if a UserInfo Endpoint is defined. Two points about this: - Injecting them into the ID Token's claims is the most obvious approach given the current code structure; though I'm not sure it is the best approach, perhaps it should instead fetch the user info in processAuthorizationResponse() and pass that as an argument to processAccessTokenCallback() which would then need a bit of restructuring. But this made sense because it's also how the ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook works. - OIDC *requires* that a UserInfo Endpoint exists, so why bother with that "if a UserInfo Endpoint is defined" bit? Simply out of an abundance of caution that there's an existing BookStack user that is relying on it not fetching the UserInfo Endpoint in order to work with a non-compliant OIDC Provider. [1]: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims --- .env.example.complete | 1 + app/Access/Oidc/OidcProviderSettings.php | 7 ++++- app/Access/Oidc/OidcService.php | 12 ++++++++ app/Config/oidc.php | 1 + tests/Auth/OidcTest.php | 38 ++++++++++++++++++++++-- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index e8520a24c..124296818 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -267,6 +267,7 @@ OIDC_ISSUER_DISCOVER=false OIDC_PUBLIC_KEY=null OIDC_AUTH_ENDPOINT=null OIDC_TOKEN_ENDPOINT=null +OIDC_USERINFO_ENDPOINT=null OIDC_ADDITIONAL_SCOPES=null OIDC_DUMP_USER_DETAILS=false OIDC_USER_TO_GROUPS=false diff --git a/app/Access/Oidc/OidcProviderSettings.php b/app/Access/Oidc/OidcProviderSettings.php index bea6a523e..49ccab6f0 100644 --- a/app/Access/Oidc/OidcProviderSettings.php +++ b/app/Access/Oidc/OidcProviderSettings.php @@ -22,6 +22,7 @@ class OidcProviderSettings public ?string $authorizationEndpoint; public ?string $tokenEndpoint; public ?string $endSessionEndpoint; + public ?string $userinfoEndpoint; /** * @var string[]|array[] @@ -128,6 +129,10 @@ class OidcProviderSettings $discoveredSettings['tokenEndpoint'] = $result['token_endpoint']; } + if (!empty($result['userinfo_endpoint'])) { + $discoveredSettings['userinfoEndpoint'] = $result['userinfo_endpoint']; + } + if (!empty($result['jwks_uri'])) { $keys = $this->loadKeysFromUri($result['jwks_uri'], $httpClient); $discoveredSettings['keys'] = $this->filterKeys($keys); @@ -177,7 +182,7 @@ class OidcProviderSettings */ public function arrayForProvider(): array { - $settingKeys = ['clientId', 'clientSecret', 'redirectUri', 'authorizationEndpoint', 'tokenEndpoint']; + $settingKeys = ['clientId', 'clientSecret', 'redirectUri', 'authorizationEndpoint', 'tokenEndpoint', 'userinfoEndpoint']; $settings = []; foreach ($settingKeys as $setting) { $settings[$setting] = $this->$setting; diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index f1e5b25af..244957991 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -85,6 +85,7 @@ class OidcService 'authorizationEndpoint' => $config['authorization_endpoint'], 'tokenEndpoint' => $config['token_endpoint'], 'endSessionEndpoint' => is_string($config['end_session_endpoint']) ? $config['end_session_endpoint'] : null, + 'userinfoEndpoint' => $config['userinfo_endpoint'], ]); // Use keys if configured @@ -228,6 +229,17 @@ class OidcService session()->put("oidc_id_token", $idTokenText); + if (!empty($settings->userinfoEndpoint)) { + $provider = $this->getProvider($settings); + $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); + $response = $provider->getParsedResponse($request); + $claims = $idToken->getAllClaims(); + foreach ($response as $key => $value) { + $claims[$key] = $value; + } + $idToken->replaceClaims($claims); + } + $returnClaims = Theme::dispatch(ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE, $idToken->getAllClaims(), [ 'access_token' => $accessToken->getToken(), 'expires_in' => $accessToken->getExpires(), diff --git a/app/Config/oidc.php b/app/Config/oidc.php index 7f8f40d41..8b5470931 100644 --- a/app/Config/oidc.php +++ b/app/Config/oidc.php @@ -35,6 +35,7 @@ return [ // OAuth2 endpoints. 'authorization_endpoint' => env('OIDC_AUTH_ENDPOINT', null), 'token_endpoint' => env('OIDC_TOKEN_ENDPOINT', null), + 'userinfo_endpoint' => env('OIDC_USERINFO_ENDPOINT', null), // OIDC RP-Initiated Logout endpoint URL. // A false value force-disables RP-Initiated Logout. diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index dbf26f1bd..f47a20100 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -668,11 +668,44 @@ class OidcTest extends TestCase protected function runLogin($claimOverrides = []): TestResponse { + // These two variables should perhaps be arguments instead of + // assuming that they're tied to whether discovery is enabled, + // but that's how the tests are written for now. + $claimsInIdToken = !config('oidc.discover'); + $tokenEndpoint = config('oidc.discover') + ? OidcJwtHelper::defaultIssuer() . '/oidc/token' + : 'https://oidc.local/token'; + $this->post('/oidc/login'); $state = session()->get('oidc_state'); - $this->mockHttpClient([$this->getMockAuthorizationResponse($claimOverrides)]); - return $this->get('/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=' . $state); + $providerResponses = [$this->getMockAuthorizationResponse($claimsInIdToken ? $claimOverrides : [])]; + if (!$claimsInIdToken) { + $providerResponses[] = new Response(200, [ + 'Content-Type' => 'application/json', + 'Cache-Control' => 'no-cache, no-store', + 'Pragma' => 'no-cache', + ], json_encode($claimOverrides)); + } + + $transactions = $this->mockHttpClient($providerResponses); + + $response = $this->get('/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=' . $state); + + if (auth()->check()) { + $this->assertEquals($claimsInIdToken ? 1 : 2, $transactions->requestCount()); + $tokenRequest = $transactions->requestAt(0); + $this->assertEquals($tokenEndpoint, (string) $tokenRequest->getUri()); + $this->assertEquals('POST', $tokenRequest->getMethod()); + if (!$claimsInIdToken) { + $userinfoRequest = $transactions->requestAt(1); + $this->assertEquals(OidcJwtHelper::defaultIssuer() . '/oidc/userinfo', (string) $userinfoRequest->getUri()); + $this->assertEquals('GET', $userinfoRequest->getMethod()); + $this->assertEquals('Bearer abc123', $userinfoRequest->getHeader('Authorization')[0]); + } + } + + return $response; } protected function getAutoDiscoveryResponse($responseOverrides = []): Response @@ -684,6 +717,7 @@ class OidcTest extends TestCase ], json_encode(array_merge([ 'token_endpoint' => OidcJwtHelper::defaultIssuer() . '/oidc/token', 'authorization_endpoint' => OidcJwtHelper::defaultIssuer() . '/oidc/authorize', + 'userinfo_endpoint' => OidcJwtHelper::defaultIssuer() . '/oidc/userinfo', 'jwks_uri' => OidcJwtHelper::defaultIssuer() . '/oidc/keys', 'issuer' => OidcJwtHelper::defaultIssuer(), 'end_session_endpoint' => OidcJwtHelper::defaultIssuer() . '/oidc/logout', From 2ed931aeed9c6d633c391fff01637e68e35b75a2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Mar 2024 11:29:51 +0000 Subject: [PATCH 02/59] Updated minimum PHP version from 8.0 to 8.1 For #4893 --- .github/workflows/test-migrations.yml | 2 +- .github/workflows/test-php.yml | 2 +- composer.json | 4 +- composer.lock | 952 +++++++++++++------------- phpstan.neon.dist | 2 +- 5 files changed, 478 insertions(+), 484 deletions(-) diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index 63f52a295..9b13787f7 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - php: ['8.0', '8.1', '8.2', '8.3'] + php: ['8.1', '8.2', '8.3'] steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml index 89ebf0dec..53087a82f 100644 --- a/.github/workflows/test-php.yml +++ b/.github/workflows/test-php.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - php: ['8.0', '8.1', '8.2', '8.3'] + php: ['8.1', '8.2', '8.3'] steps: - uses: actions/checkout@v1 diff --git a/composer.json b/composer.json index 85bb3cbae..74fbcf8f2 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "license": "MIT", "type": "project", "require": { - "php": "^8.0.2", + "php": "^8.1.0", "ext-curl": "*", "ext-dom": "*", "ext-fileinfo": "*", @@ -99,7 +99,7 @@ "preferred-install": "dist", "sort-packages": true, "platform": { - "php": "8.0.2" + "php": "8.1.0" } }, "extra": { diff --git a/composer.lock b/composer.lock index e1033b5b2..1b58e55ac 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7c64775f79832d552a2ef40e11f79c40", + "content-hash": "54d735153e12b120d9dd41ab847e3032", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.300.6", + "version": "3.300.15", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "957ccef631684d612d01ced2fa3b0506f2ec78c3" + "reference": "0cd194438b84588615121a93d0bc46bf55ca678b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/957ccef631684d612d01ced2fa3b0506f2ec78c3", - "reference": "957ccef631684d612d01ced2fa3b0506f2ec78c3", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0cd194438b84588615121a93d0bc46bf55ca678b", + "reference": "0cd194438b84588615121a93d0bc46bf55ca678b", "shasum": "" }, "require": { @@ -151,9 +151,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.300.6" + "source": "https://github.com/aws/aws-sdk-php/tree/3.300.15" }, - "time": "2024-02-27T19:05:27+00:00" + "time": "2024-03-11T18:33:13+00:00" }, { "name": "bacon/bacon-qr-code", @@ -211,27 +211,27 @@ }, { "name": "barryvdh/laravel-dompdf", - "version": "v2.0.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "9843d2be423670fb434f4c978b3c0f4dd92c87a6" + "reference": "c8b8a8490e5f7348cf99054821fb248f103e7d24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/9843d2be423670fb434f4c978b3c0f4dd92c87a6", - "reference": "9843d2be423670fb434f4c978b3c0f4dd92c87a6", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/c8b8a8490e5f7348cf99054821fb248f103e7d24", + "reference": "c8b8a8490e5f7348cf99054821fb248f103e7d24", "shasum": "" }, "require": { - "dompdf/dompdf": "^2.0.1", - "illuminate/support": "^6|^7|^8|^9|^10", + "dompdf/dompdf": "^2.0.3", + "illuminate/support": "^6|^7|^8|^9|^10|^11", "php": "^7.2 || ^8.0" }, "require-dev": { - "nunomaduro/larastan": "^1|^2", - "orchestra/testbench": "^4|^5|^6|^7|^8", - "phpro/grumphp": "^1", + "larastan/larastan": "^1.0|^2.7.0", + "orchestra/testbench": "^4|^5|^6|^7|^8|^9", + "phpro/grumphp": "^1 || ^2.5", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -272,7 +272,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.0.1" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.0" }, "funding": [ { @@ -284,30 +284,30 @@ "type": "github" } ], - "time": "2023-01-12T15:12:49+00:00" + "time": "2024-03-04T08:18:20+00:00" }, { "name": "barryvdh/laravel-snappy", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-snappy.git", - "reference": "940eec2d99b89cbc9bea2f493cf068382962a485" + "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/940eec2d99b89cbc9bea2f493cf068382962a485", - "reference": "940eec2d99b89cbc9bea2f493cf068382962a485", + "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/716dcb6db24de4ce8e6ae5941cfab152af337ea0", + "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0", "shasum": "" }, "require": { - "illuminate/filesystem": "^9|^10", - "illuminate/support": "^9|^10", - "knplabs/knp-snappy": "^1.4", + "illuminate/filesystem": "^9|^10|^11.0", + "illuminate/support": "^9|^10|^11.0", + "knplabs/knp-snappy": "^1.4.4", "php": ">=7.2" }, "require-dev": { - "orchestra/testbench": "^7|^8" + "orchestra/testbench": "^7|^8|^9.0" }, "type": "library", "extra": { @@ -350,7 +350,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-snappy/issues", - "source": "https://github.com/barryvdh/laravel-snappy/tree/v1.0.2" + "source": "https://github.com/barryvdh/laravel-snappy/tree/v1.0.3" }, "funding": [ { @@ -362,7 +362,7 @@ "type": "github" } ], - "time": "2023-04-07T10:38:54+00:00" + "time": "2024-03-09T19:20:39+00:00" }, { "name": "brick/math", @@ -708,16 +708,16 @@ }, { "name": "doctrine/dbal", - "version": "3.8.2", + "version": "3.8.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "a19a1d05ca211f41089dffcc387733a6875196cb" + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/a19a1d05ca211f41089dffcc387733a6875196cb", - "reference": "a19a1d05ca211f41089dffcc387733a6875196cb", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c", + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c", "shasum": "" }, "require": { @@ -733,12 +733,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.57", + "phpstan/phpstan": "1.10.58", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.16", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.8.1", + "squizlabs/php_codesniffer": "3.9.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -801,7 +801,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.2" + "source": "https://github.com/doctrine/dbal/tree/3.8.3" }, "funding": [ { @@ -817,7 +817,7 @@ "type": "tidelift" } ], - "time": "2024-02-12T18:36:36+00:00" + "time": "2024-03-03T15:55:06+00:00" }, { "name": "doctrine/deprecations", @@ -868,30 +868,29 @@ }, { "name": "doctrine/event-manager", - "version": "1.2.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "conflict": { "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.8", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.24" + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" }, "type": "library", "autoload": { @@ -940,7 +939,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" }, "funding": [ { @@ -956,7 +955,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:51:15+00:00" + "time": "2022-10-12T20:59:15+00:00" }, { "name": "doctrine/inflector", @@ -1051,28 +1050,27 @@ }, { "name": "doctrine/lexer", - "version": "2.1.1", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", - "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.21" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -1109,7 +1107,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.1" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -1125,7 +1123,7 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:35:39+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "dompdf/dompdf", @@ -1252,26 +1250,26 @@ }, { "name": "egulias/email-validator", - "version": "3.2.6", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7" + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", - "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", "shasum": "" }, "require": { - "doctrine/lexer": "^1.2|^2", - "php": ">=7.2", - "symfony/polyfill-intl-idn": "^1.15" + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^8.5.8|^9.3.3", - "vimeo/psalm": "^4" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -1279,7 +1277,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -1307,7 +1305,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/3.2.6" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" }, "funding": [ { @@ -1315,7 +1313,7 @@ "type": "github" } ], - "time": "2023-06-01T07:04:22+00:00" + "time": "2023-10-06T06:47:41+00:00" }, { "name": "fruitcake/php-cors", @@ -1947,36 +1945,29 @@ }, { "name": "knplabs/knp-snappy", - "version": "v1.4.4", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/KnpLabs/snappy.git", - "reference": "3db13fe45d12a7bccb2b83f622e5a90f7e40b111" + "reference": "98468898b50c09f26d56d905b79b0f52a2215da6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/3db13fe45d12a7bccb2b83f622e5a90f7e40b111", - "reference": "3db13fe45d12a7bccb2b83f622e5a90f7e40b111", + "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/98468898b50c09f26d56d905b79b0f52a2215da6", + "reference": "98468898b50c09f26d56d905b79b0f52a2215da6", "shasum": "" }, "require": { - "php": ">=7.1", - "psr/log": "^1.0||^2.0||^3.0", - "symfony/process": "~3.4||~4.3||~5.0||~6.0" + "php": ">=8.1", + "psr/log": "^2.0||^3.0", + "symfony/process": "^5.0||^6.0||^7.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16||^3.0", + "friendsofphp/php-cs-fixer": "^3.0", "pedrotroller/php-cs-custom-fixer": "^2.19", "phpstan/phpstan": "^1.0.0", "phpstan/phpstan-phpunit": "^1.0.0", - "phpunit/phpunit": "~7.4||~8.5" - }, - "suggest": { - "h4cc/wkhtmltoimage-amd64": "Provides wkhtmltoimage-amd64 binary for Linux-compatible machines, use version `~0.12` as dependency", - "h4cc/wkhtmltoimage-i386": "Provides wkhtmltoimage-i386 binary for Linux-compatible machines, use version `~0.12` as dependency", - "h4cc/wkhtmltopdf-amd64": "Provides wkhtmltopdf-amd64 binary for Linux-compatible machines, use version `~0.12` as dependency", - "h4cc/wkhtmltopdf-i386": "Provides wkhtmltopdf-i386 binary for Linux-compatible machines, use version `~0.12` as dependency", - "wemersonjanuario/wkhtmltopdf-windows": "Provides wkhtmltopdf executable for Windows, use version `~0.12` as dependency" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -2015,9 +2006,9 @@ ], "support": { "issues": "https://github.com/KnpLabs/snappy/issues", - "source": "https://github.com/KnpLabs/snappy/tree/v1.4.4" + "source": "https://github.com/KnpLabs/snappy/tree/v1.5.0" }, - "time": "2023-09-13T12:18:19+00:00" + "time": "2023-12-18T09:12:11+00:00" }, { "name": "laravel/framework", @@ -2603,16 +2594,16 @@ }, { "name": "league/flysystem", - "version": "3.24.0", + "version": "3.25.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "b25a361508c407563b34fac6f64a8a17a8819675" + "reference": "4c44347133618cccd9b3df1729647a1577b4ad99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b25a361508c407563b34fac6f64a8a17a8819675", - "reference": "b25a361508c407563b34fac6f64a8a17a8819675", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4c44347133618cccd9b3df1729647a1577b4ad99", + "reference": "4c44347133618cccd9b3df1729647a1577b4ad99", "shasum": "" }, "require": { @@ -2640,7 +2631,7 @@ "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "microsoft/azure-storage-blob": "^1.1", - "phpseclib/phpseclib": "^3.0.34", + "phpseclib/phpseclib": "^3.0.36", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", "sabre/dav": "^4.6.0" @@ -2677,7 +2668,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.24.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.25.0" }, "funding": [ { @@ -2689,7 +2680,7 @@ "type": "github" } ], - "time": "2024-02-04T12:10:17+00:00" + "time": "2024-03-09T17:06:45+00:00" }, { "name": "league/flysystem-aws-s3-v3", @@ -3451,31 +3442,31 @@ }, { "name": "nette/schema", - "version": "v1.2.5", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", + "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", "shasum": "" }, "require": { - "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", - "php": "7.1 - 8.3" + "nette/utils": "^4.0", + "php": "8.1 - 8.3" }, "require-dev": { - "nette/tester": "^2.3 || ^2.4", + "nette/tester": "^2.4", "phpstan/phpstan-nette": "^1.0", - "tracy/tracy": "^2.7" + "tracy/tracy": "^2.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -3507,9 +3498,9 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.5" + "source": "https://github.com/nette/schema/tree/v1.3.0" }, - "time": "2023-10-05T20:37:59+00:00" + "time": "2023-12-11T11:54:22+00:00" }, { "name": "nette/utils", @@ -3599,16 +3590,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.1", + "version": "v5.0.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", - "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", "shasum": "" }, "require": { @@ -3651,9 +3642,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" }, - "time": "2024-02-21T19:24:10+00:00" + "time": "2024-03-05T20:51:40+00:00" }, { "name": "nunomaduro/termwind", @@ -4081,16 +4072,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.36", + "version": "3.0.37", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "c2fb5136162d4be18fdd4da9980696f3aee96d7b" + "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c2fb5136162d4be18fdd4da9980696f3aee96d7b", - "reference": "c2fb5136162d4be18fdd4da9980696f3aee96d7b", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8", + "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8", "shasum": "" }, "require": { @@ -4171,7 +4162,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.36" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.37" }, "funding": [ { @@ -4187,7 +4178,7 @@ "type": "tidelift" } ], - "time": "2024-02-26T05:13:14+00:00" + "time": "2024-03-03T02:14:58+00:00" }, { "name": "pragmarx/google2fa", @@ -4888,21 +4879,20 @@ }, { "name": "ramsey/collection", - "version": "1.3.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "symfony/polyfill-php81": "^1.23" + "php": "^8.1" }, "require-dev": { "captainhook/plugin-composer": "^5.3", @@ -4962,7 +4952,7 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.3.0" + "source": "https://github.com/ramsey/collection/tree/2.0.0" }, "funding": [ { @@ -4974,7 +4964,7 @@ "type": "tidelift" } ], - "time": "2022-12-27T19:12:24+00:00" + "time": "2022-12-31T21:50:55+00:00" }, { "name": "ramsey/uuid", @@ -5605,23 +5595,24 @@ }, { "name": "symfony/console", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -5635,18 +5626,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5675,12 +5664,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.19" + "source": "https://github.com/symfony/console/tree/v6.4.4" }, "funding": [ { @@ -5696,24 +5685,24 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-22T20:27:10+00:00" }, { "name": "symfony/css-selector", - "version": "v6.0.19", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1" + "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f1d00bddb83a4cb2138564b2150001cb6ce272b1", - "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229", + "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -5745,7 +5734,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.0.19" + "source": "https://github.com/symfony/css-selector/tree/v6.4.3" }, "funding": [ { @@ -5761,29 +5750,29 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.2", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -5812,7 +5801,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -5828,31 +5817,35 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/error-handler", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c7df52182f43a68522756ac31a532dd5b1e6db67" + "reference": "c725219bdf2afc59423c32793d5019d2a904e13a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c7df52182f43a68522756ac31a532dd5b1e6db67", - "reference": "c7df52182f43a68522756ac31a532dd5b1e6db67", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c725219bdf2afc59423c32793d5019d2a904e13a", + "reference": "c725219bdf2afc59423c32793d5019d2a904e13a", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -5883,7 +5876,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.0.19" + "source": "https://github.com/symfony/error-handler/tree/v6.4.4" }, "funding": [ { @@ -5899,28 +5892,29 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-22T20:27:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.0.19", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a" + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", - "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae9d3a6f3003a6caf56acd7466d8d52378d44fef", + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/event-dispatcher-contracts": "^2|^3" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -5928,17 +5922,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^5.4|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5966,7 +5956,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.19" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.3" }, "funding": [ { @@ -5982,33 +5972,30 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.2", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6045,7 +6032,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" }, "funding": [ { @@ -6061,24 +6048,27 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/finder", - "version": "v6.0.19", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11" + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11", - "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", "autoload": { @@ -6106,7 +6096,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.0.19" + "source": "https://github.com/symfony/finder/tree/v6.4.0" }, "funding": [ { @@ -6122,38 +6112,40 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2023-10-31T17:30:12+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.0.20", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6" + "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e16b2676a4b3b1fa12378a20b29c364feda2a8d6", - "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ebc713bc6e6f4b53f46539fc158be85dfcd77304", + "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "symfony/cache": "<6.3" }, "require-dev": { - "predis/predis": "~1.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^5.4|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest": { - "symfony/mime": "To use the file extension guesser" + "doctrine/dbal": "^2.13.1|^3|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6181,7 +6173,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.0.20" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.4" }, "funding": [ { @@ -6197,44 +6189,48 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:41:07+00:00" + "time": "2024-02-08T15:01:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.20", + "version": "v6.4.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6dc70833fd0ef5e861e17c7854c12d7d86679349" + "reference": "f6947cb939d8efee137797382cb4db1af653ef75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6dc70833fd0ef5e861e17c7854c12d7d86679349", - "reference": "6dc70833fd0ef5e861e17c7854c12d7d86679349", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6947cb939d8efee137797382cb4db1af653ef75", + "reference": "f6947cb939d8efee137797382cb4db1af653ef75", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/error-handler": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/browser-kit": "<5.4", "symfony/cache": "<5.4", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/mailer": "<5.4", "symfony/messenger": "<5.4", "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, "provide": { @@ -6242,28 +6238,28 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, "type": "library", "autoload": { "psr-4": { @@ -6290,7 +6286,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.0.20" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.5" }, "funding": [ { @@ -6306,24 +6302,25 @@ "type": "tidelift" } ], - "time": "2023-02-01T08:22:55+00:00" + "time": "2024-03-04T21:00:47+00:00" }, { "name": "symfony/mime", - "version": "v6.0.19", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "d7052547a0070cbeadd474e172b527a00d657301" + "reference": "5017e0a9398c77090b7694be46f20eb796262a34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/d7052547a0070cbeadd474e172b527a00d657301", - "reference": "d7052547a0070cbeadd474e172b527a00d657301", + "url": "https://api.github.com/repos/symfony/mime/zipball/5017e0a9398c77090b7694be46f20eb796262a34", + "reference": "5017e0a9398c77090b7694be46f20eb796262a34", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -6332,15 +6329,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + "symfony/serializer": "<6.3.2" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3.2|^7.0" }, "type": "library", "autoload": { @@ -6372,7 +6370,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.0.19" + "source": "https://github.com/symfony/mime/tree/v6.4.3" }, "funding": [ { @@ -6388,7 +6386,7 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2024-01-30T08:32:12+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6946,21 +6944,22 @@ "time": "2024-01-29T20:11:03+00:00" }, { - "name": "symfony/polyfill-php81", + "name": "symfony/polyfill-php83", "version": "v1.29.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d", - "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" }, "type": "library", "extra": { @@ -6974,7 +6973,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php83\\": "" }, "classmap": [ "Resources/stubs" @@ -6994,7 +6993,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -7003,7 +7002,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" }, "funding": [ { @@ -7102,20 +7101,20 @@ }, { "name": "symfony/process", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "2114fd60f26a296cc403a7939ab91478475a33d4" + "reference": "710e27879e9be3395de2b98da3f52a946039f297" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2114fd60f26a296cc403a7939ab91478475a33d4", - "reference": "2114fd60f26a296cc403a7939ab91478475a33d4", + "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297", + "reference": "710e27879e9be3395de2b98da3f52a946039f297", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -7143,7 +7142,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.19" + "source": "https://github.com/symfony/process/tree/v6.4.4" }, "funding": [ { @@ -7159,45 +7158,40 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-20T12:31:00+00:00" }, { "name": "symfony/routing", - "version": "v6.0.19", + "version": "v6.4.5", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e56ca9b41c1ec447193474cd86ad7c0b547755ac" + "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e56ca9b41c1ec447193474cd86ad7c0b547755ac", - "reference": "e56ca9b41c1ec447193474cd86ad7c0b547755ac", + "url": "https://api.github.com/repos/symfony/routing/zipball/7fe30068e207d9c31c0138501ab40358eb2d49a4", + "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "doctrine/annotations": "<1.12", - "symfony/config": "<5.4", + "symfony/config": "<6.2", "symfony/dependency-injection": "<5.4", "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7231,7 +7225,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.19" + "source": "https://github.com/symfony/routing/tree/v6.4.5" }, "funding": [ { @@ -7247,36 +7241,33 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-27T12:33:30+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.0.2", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { - "php": ">=8.0.2", - "psr/container": "^2.0" + "php": ">=8.1", + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7286,7 +7277,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7313,7 +7307,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -7329,37 +7323,38 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:58+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7398,7 +7393,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.19" + "source": "https://github.com/symfony/string/tree/v6.4.4" }, "funding": [ { @@ -7414,32 +7409,35 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-01T13:16:41+00:00" }, { "name": "symfony/translation", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e", + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "symfony/config": "<5.4", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", "symfony/twig-bundle": "<5.4", "symfony/yaml": "<5.4" }, @@ -7447,22 +7445,19 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7493,7 +7488,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.19" + "source": "https://github.com/symfony/translation/tree/v6.4.4" }, "funding": [ { @@ -7509,32 +7504,29 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-02-20T13:16:58+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.0.2", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { - "php": ">=8.0.2" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7544,7 +7536,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7571,7 +7566,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -7587,28 +7582,28 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/uid", - "version": "v6.0.19", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d" + "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", - "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", + "url": "https://api.github.com/repos/symfony/uid/zipball/1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", + "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7645,7 +7640,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.0.19" + "source": "https://github.com/symfony/uid/tree/v6.4.3" }, "funding": [ { @@ -7661,42 +7656,39 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "eb980457fa6899840fe1687e8627a03a7d8a3d52" + "reference": "b439823f04c98b84d4366c79507e9da6230944b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eb980457fa6899840fe1687e8627a03a7d8a3d52", - "reference": "eb980457fa6899840fe1687e8627a03a7d8a3d52", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b439823f04c98b84d4366c79507e9da6230944b1", + "reference": "b439823f04c98b84d4366c79507e9da6230944b1", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "phpunit/phpunit": "<5.4.3", "symfony/console": "<5.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, "bin": [ "Resources/bin/var-dump-server" ], @@ -7733,7 +7725,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.19" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.4" }, "funding": [ { @@ -7749,7 +7741,7 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-02-15T11:23:52+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -8024,30 +8016,30 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -8074,7 +8066,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -8090,7 +8082,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "fakerphp/faker", @@ -8354,16 +8346,16 @@ }, { "name": "larastan/larastan", - "version": "v2.9.1", + "version": "v2.9.2", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "467113c58d110ad617cf9e07ff49b0948d1c03cc" + "reference": "a79b46b96060504b400890674b83f66aa7f5db6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/467113c58d110ad617cf9e07ff49b0948d1c03cc", - "reference": "467113c58d110ad617cf9e07ff49b0948d1c03cc", + "url": "https://api.github.com/repos/larastan/larastan/zipball/a79b46b96060504b400890674b83f66aa7f5db6d", + "reference": "a79b46b96060504b400890674b83f66aa7f5db6d", "shasum": "" }, "require": { @@ -8380,6 +8372,7 @@ "phpstan/phpstan": "^1.10.50" }, "require-dev": { + "doctrine/coding-standard": "^12.0", "nikic/php-parser": "^4.17.1", "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.0", "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.0", @@ -8431,7 +8424,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.1" + "source": "https://github.com/larastan/larastan/tree/v2.9.2" }, "funding": [ { @@ -8451,7 +8444,7 @@ "type": "patreon" } ], - "time": "2024-02-26T14:10:20+00:00" + "time": "2024-02-27T03:16:03+00:00" }, { "name": "mockery/mockery", @@ -8685,20 +8678,21 @@ }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -8739,9 +8733,15 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -8884,16 +8884,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.59", + "version": "1.10.60", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e607609388d3a6d418a50a49f7940e8086798281" + "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e607609388d3a6d418a50a49f7940e8086798281", - "reference": "e607609388d3a6d418a50a49f7940e8086798281", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe", "shasum": "" }, "require": { @@ -8942,20 +8942,20 @@ "type": "tidelift" } ], - "time": "2024-02-20T13:59:13+00:00" + "time": "2024-03-07T13:30:19+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "9.2.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", "shasum": "" }, "require": { @@ -9012,7 +9012,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" }, "funding": [ { @@ -9020,7 +9020,7 @@ "type": "github" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2024-03-02T06:37:42+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9368,16 +9368,16 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -9412,7 +9412,7 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -9420,7 +9420,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -9666,16 +9666,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -9720,7 +9720,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -9728,7 +9728,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -9795,16 +9795,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -9860,7 +9860,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -9868,20 +9868,20 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -9924,7 +9924,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -9932,7 +9932,7 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", @@ -10468,32 +10468,26 @@ }, { "name": "symfony/dom-crawler", - "version": "v6.0.19", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "622578ff158318b1b49d95068bd6b66c713601e9" + "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/622578ff158318b1b49d95068bd6b66c713601e9", - "reference": "622578ff158318b1b49d95068bd6b66c713601e9", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", + "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", "shasum": "" }, "require": { - "php": ">=8.0.2", + "masterminds/html5": "^2.6", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, - "conflict": { - "masterminds/html5": "<2.6" - }, "require-dev": { - "masterminds/html5": "^2.6", - "symfony/css-selector": "^5.4|^6.0" - }, - "suggest": { - "symfony/css-selector": "" + "symfony/css-selector": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -10521,7 +10515,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.0.19" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.4" }, "funding": [ { @@ -10537,20 +10531,20 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-02-07T09:17:57+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -10579,7 +10573,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -10587,7 +10581,7 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], @@ -10598,7 +10592,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.0.2", + "php": "^8.1.0", "ext-curl": "*", "ext-dom": "*", "ext-fileinfo": "*", @@ -10609,7 +10603,7 @@ }, "platform-dev": [], "platform-overrides": { - "php": "8.0.2" + "php": "8.1.0" }, "plugin-api-version": "2.3.0" } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 5fec36c2f..15a519e20 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,7 +9,7 @@ parameters: # The level 8 is the highest level level: 1 - phpVersion: 80002 + phpVersion: 80200 bootstrapFiles: - bootstrap/phpstan.php From 07761524af8277699d75fca09f35341420a6c619 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Mar 2024 12:08:26 +0000 Subject: [PATCH 03/59] Dev: Fixed flaky OIDC test, updated dev version --- tests/Auth/OidcTest.php | 10 ++++++++-- version | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index 345d1dc78..228c75e9e 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -594,10 +594,16 @@ class OidcTest extends TestCase { config()->set(['oidc.end_session_endpoint' => 'https://example.com/logout']); - $this->runLogin(); + // Fix times so our token is predictable + $claimOverrides = [ + 'iat' => time(), + 'exp' => time() + 720, + 'auth_time' => time() + ]; + $this->runLogin($claimOverrides); $resp = $this->asEditor()->post('/oidc/logout'); - $query = 'id_token_hint=' . urlencode(OidcJwtHelper::idToken()) . '&post_logout_redirect_uri=' . urlencode(url('/')); + $query = 'id_token_hint=' . urlencode(OidcJwtHelper::idToken($claimOverrides)) . '&post_logout_redirect_uri=' . urlencode(url('/')); $resp->assertRedirect('https://example.com/logout?' . $query); } diff --git a/version b/version index 05edb56cc..522220af0 100644 --- a/version +++ b/version @@ -1 +1 @@ -v23.09-dev +v24.03-dev From 70479df5dccc2910fa5a0e6821b304fdd989bd38 Mon Sep 17 00:00:00 2001 From: Martin Rys Date: Tue, 12 Mar 2024 14:04:33 +0100 Subject: [PATCH 04/59] Dockerfile: Don't cache 50MB of lists and use a single layer, make it pretty --- dev/docker/Dockerfile | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/dev/docker/Dockerfile b/dev/docker/Dockerfile index 349e315d2..fe497e9e6 100644 --- a/dev/docker/Dockerfile +++ b/dev/docker/Dockerfile @@ -3,23 +3,32 @@ FROM php:8.1-apache ENV APACHE_DOCUMENT_ROOT /app/public WORKDIR /app -# Install additional dependacnies and configure apache -RUN apt-get update -y \ - && apt-get install -y git zip unzip libpng-dev libldap2-dev libzip-dev wait-for-it \ - && docker-php-ext-configure ldap --with-libdir="lib/$(gcc -dumpmachine)" \ - && docker-php-ext-install pdo_mysql gd ldap zip \ - && pecl install xdebug \ - && docker-php-ext-enable xdebug \ - && a2enmod rewrite \ - && sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \ - && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf +RUN < Date: Sat, 16 Mar 2024 15:12:14 +0000 Subject: [PATCH 05/59] Framework: Upgrade from Laravel 9 to 10 Following Laravel guidance and GitHub diff. Not yet in tested state with app-specific changes made. --- app/App/Providers/AppServiceProvider.php | 32 +- app/App/Providers/AuthServiceProvider.php | 8 +- app/App/Providers/EventServiceProvider.php | 8 +- app/App/Providers/RouteServiceProvider.php | 16 +- app/App/Providers/ThemeServiceProvider.php | 8 +- .../Providers/TranslationServiceProvider.php | 8 +- .../Providers/ViewTweaksServiceProvider.php | 4 +- app/Config/app.php | 45 +-- app/Config/cache.php | 3 +- app/Config/hashing.php | 3 +- app/Config/logging.php | 8 + app/Config/queue.php | 6 + app/Config/session.php | 7 + app/Http/Kernel.php | 4 +- .../Middleware/RedirectIfAuthenticated.php | 9 +- app/Http/Middleware/ThrottleApiRequests.php | 2 +- app/Http/Middleware/TrustHosts.php | 4 +- composer.json | 4 +- composer.lock | 293 +++++++++++------- tests/CreatesApplication.php | 5 +- 20 files changed, 253 insertions(+), 224 deletions(-) diff --git a/app/App/Providers/AppServiceProvider.php b/app/App/Providers/AppServiceProvider.php index 0f4dc55dd..9012a07eb 100644 --- a/app/App/Providers/AppServiceProvider.php +++ b/app/App/Providers/AppServiceProvider.php @@ -25,7 +25,7 @@ class AppServiceProvider extends ServiceProvider * Custom container bindings to register. * @var string[] */ - public $bindings = [ + public array $bindings = [ ExceptionRenderer::class => BookStackExceptionHandlerPage::class, ]; @@ -33,7 +33,7 @@ class AppServiceProvider extends ServiceProvider * Custom singleton bindings to register. * @var string[] */ - public $singletons = [ + public array $singletons = [ 'activity' => ActivityLogger::class, SettingService::class => SettingService::class, SocialDriverManager::class => SocialDriverManager::class, @@ -42,11 +42,19 @@ class AppServiceProvider extends ServiceProvider ]; /** - * Bootstrap any application services. - * - * @return void + * Register any application services. */ - public function boot() + public function register(): void + { + $this->app->singleton(PermissionApplicator::class, function ($app) { + return new PermissionApplicator(null); + }); + } + + /** + * Bootstrap any application services. + */ + public function boot(): void { // Set root URL $appUrl = config('app.url'); @@ -67,16 +75,4 @@ class AppServiceProvider extends ServiceProvider 'page' => Page::class, ]); } - - /** - * Register any application services. - * - * @return void - */ - public function register() - { - $this->app->singleton(PermissionApplicator::class, function ($app) { - return new PermissionApplicator(null); - }); - } } diff --git a/app/App/Providers/AuthServiceProvider.php b/app/App/Providers/AuthServiceProvider.php index 26d180310..23c339079 100644 --- a/app/App/Providers/AuthServiceProvider.php +++ b/app/App/Providers/AuthServiceProvider.php @@ -18,10 +18,8 @@ class AuthServiceProvider extends ServiceProvider { /** * Bootstrap the application services. - * - * @return void */ - public function boot() + public function boot(): void { // Password Configuration // Changes here must be reflected in ApiDocsGenerate@getValidationAsString. @@ -58,10 +56,8 @@ class AuthServiceProvider extends ServiceProvider /** * Register the application services. - * - * @return void */ - public function register() + public function register(): void { Auth::provider('external-users', function ($app, array $config) { return new ExternalBaseUserProvider($config['model']); diff --git a/app/App/Providers/EventServiceProvider.php b/app/App/Providers/EventServiceProvider.php index 4ec9facdf..4cd527ba4 100644 --- a/app/App/Providers/EventServiceProvider.php +++ b/app/App/Providers/EventServiceProvider.php @@ -29,20 +29,16 @@ class EventServiceProvider extends ServiceProvider /** * Register any events for your application. - * - * @return void */ - public function boot() + public function boot(): void { // } /** * Determine if events and listeners should be automatically discovered. - * - * @return bool */ - public function shouldDiscoverEvents() + public function shouldDiscoverEvents(): bool { return false; } diff --git a/app/App/Providers/RouteServiceProvider.php b/app/App/Providers/RouteServiceProvider.php index abd556244..3a155920e 100644 --- a/app/App/Providers/RouteServiceProvider.php +++ b/app/App/Providers/RouteServiceProvider.php @@ -24,10 +24,8 @@ class RouteServiceProvider extends ServiceProvider /** * Define your route model bindings, pattern filters, etc. - * - * @return void */ - public function boot() + public function boot(): void { $this->configureRateLimiting(); @@ -41,10 +39,8 @@ class RouteServiceProvider extends ServiceProvider * Define the "web" routes for the application. * * These routes all receive session state, CSRF protection, etc. - * - * @return void */ - protected function mapWebRoutes() + protected function mapWebRoutes(): void { Route::group([ 'middleware' => 'web', @@ -65,10 +61,8 @@ class RouteServiceProvider extends ServiceProvider * Define the "api" routes for the application. * * These routes are typically stateless. - * - * @return void */ - protected function mapApiRoutes() + protected function mapApiRoutes(): void { Route::group([ 'middleware' => 'api', @@ -81,10 +75,8 @@ class RouteServiceProvider extends ServiceProvider /** * Configure the rate limiters for the application. - * - * @return void */ - protected function configureRateLimiting() + protected function configureRateLimiting(): void { RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); diff --git a/app/App/Providers/ThemeServiceProvider.php b/app/App/Providers/ThemeServiceProvider.php index 4c657d912..2cf581d38 100644 --- a/app/App/Providers/ThemeServiceProvider.php +++ b/app/App/Providers/ThemeServiceProvider.php @@ -10,10 +10,8 @@ class ThemeServiceProvider extends ServiceProvider { /** * Register services. - * - * @return void */ - public function register() + public function register(): void { // Register the ThemeService as a singleton $this->app->singleton(ThemeService::class, fn ($app) => new ThemeService()); @@ -21,10 +19,8 @@ class ThemeServiceProvider extends ServiceProvider /** * Bootstrap services. - * - * @return void */ - public function boot() + public function boot(): void { // Boot up the theme system $themeService = $this->app->make(ThemeService::class); diff --git a/app/App/Providers/TranslationServiceProvider.php b/app/App/Providers/TranslationServiceProvider.php index c1752f38e..b838129a6 100644 --- a/app/App/Providers/TranslationServiceProvider.php +++ b/app/App/Providers/TranslationServiceProvider.php @@ -11,10 +11,8 @@ class TranslationServiceProvider extends BaseProvider { /** * Register the service provider. - * - * @return void */ - public function register() + public function register(): void { $this->registerLoader(); @@ -41,10 +39,8 @@ class TranslationServiceProvider extends BaseProvider /** * Register the translation line loader. * Overrides the default register action from Laravel so a custom loader can be used. - * - * @return void */ - protected function registerLoader() + protected function registerLoader(): void { $this->app->singleton('translation.loader', function ($app) { return new FileLoader($app['files'], $app['path.lang']); diff --git a/app/App/Providers/ViewTweaksServiceProvider.php b/app/App/Providers/ViewTweaksServiceProvider.php index 10593ac8b..7115dcb51 100644 --- a/app/App/Providers/ViewTweaksServiceProvider.php +++ b/app/App/Providers/ViewTweaksServiceProvider.php @@ -12,10 +12,8 @@ class ViewTweaksServiceProvider extends ServiceProvider { /** * Bootstrap services. - * - * @return void */ - public function boot() + public function boot(): void { // Set paginator to use bootstrap-style pagination Paginator::useBootstrap(); diff --git a/app/Config/app.php b/app/Config/app.php index fc913eb8f..dda787f3f 100644 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -9,6 +9,7 @@ */ use Illuminate\Support\Facades\Facade; +use Illuminate\Support\ServiceProvider; return [ @@ -113,46 +114,22 @@ return [ ], // Application Service Providers - 'providers' => [ - - // Laravel Framework Service Providers... - Illuminate\Auth\AuthServiceProvider::class, - Illuminate\Broadcasting\BroadcastServiceProvider::class, - Illuminate\Bus\BusServiceProvider::class, - Illuminate\Cache\CacheServiceProvider::class, - Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, - Illuminate\Cookie\CookieServiceProvider::class, - Illuminate\Database\DatabaseServiceProvider::class, - Illuminate\Encryption\EncryptionServiceProvider::class, - Illuminate\Filesystem\FilesystemServiceProvider::class, - Illuminate\Foundation\Providers\FoundationServiceProvider::class, - Illuminate\Hashing\HashServiceProvider::class, - Illuminate\Mail\MailServiceProvider::class, - Illuminate\Notifications\NotificationServiceProvider::class, - Illuminate\Pagination\PaginationServiceProvider::class, - Illuminate\Pipeline\PipelineServiceProvider::class, - Illuminate\Queue\QueueServiceProvider::class, - Illuminate\Redis\RedisServiceProvider::class, - Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, - Illuminate\Session\SessionServiceProvider::class, - Illuminate\Validation\ValidationServiceProvider::class, - Illuminate\View\ViewServiceProvider::class, - + 'providers' => ServiceProvider::defaultProviders()->merge([ // Third party service providers Barryvdh\DomPDF\ServiceProvider::class, Barryvdh\Snappy\ServiceProvider::class, SocialiteProviders\Manager\ServiceProvider::class, // BookStack custom service providers - \BookStack\App\Providers\ThemeServiceProvider::class, - \BookStack\App\Providers\AppServiceProvider::class, - \BookStack\App\Providers\AuthServiceProvider::class, - \BookStack\App\Providers\EventServiceProvider::class, - \BookStack\App\Providers\RouteServiceProvider::class, - \BookStack\App\Providers\TranslationServiceProvider::class, - \BookStack\App\Providers\ValidationRuleServiceProvider::class, - \BookStack\App\Providers\ViewTweaksServiceProvider::class, - ], + BookStack\App\Providers\ThemeServiceProvider::class, + BookStack\App\Providers\AppServiceProvider::class, + BookStack\App\Providers\AuthServiceProvider::class, + BookStack\App\Providers\EventServiceProvider::class, + BookStack\App\Providers\RouteServiceProvider::class, + BookStack\App\Providers\TranslationServiceProvider::class, + BookStack\App\Providers\ValidationRuleServiceProvider::class, + BookStack\App\Providers\ViewTweaksServiceProvider::class, + ])->toArray(), // Class Aliases // This array of class aliases to be registered on application start. diff --git a/app/Config/cache.php b/app/Config/cache.php index d1d47ab16..2ba16059a 100644 --- a/app/Config/cache.php +++ b/app/Config/cache.php @@ -53,7 +53,8 @@ return [ 'file' => [ 'driver' => 'file', - 'path' => storage_path('framework/cache'), + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), ], 'memcached' => [ diff --git a/app/Config/hashing.php b/app/Config/hashing.php index 585ee094c..91d0db16b 100644 --- a/app/Config/hashing.php +++ b/app/Config/hashing.php @@ -21,7 +21,8 @@ return [ // passwords are hashed using the Bcrypt algorithm. This will allow you // to control the amount of time it takes to hash the given password. 'bcrypt' => [ - 'rounds' => env('BCRYPT_ROUNDS', 10), + 'rounds' => env('BCRYPT_ROUNDS', 12), + 'verify' => true, ], // Argon Options diff --git a/app/Config/logging.php b/app/Config/logging.php index d49cd727d..f5cbd5ffc 100644 --- a/app/Config/logging.php +++ b/app/Config/logging.php @@ -4,6 +4,7 @@ use Monolog\Formatter\LineFormatter; use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; +use Monolog\Processor\PsrLogMessageProcessor; /** * Logging configuration options. @@ -49,6 +50,7 @@ return [ 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'days' => 14, + 'replace_placeholders' => true, ], 'daily' => [ @@ -56,6 +58,7 @@ return [ 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'days' => 7, + 'replace_placeholders' => true, ], 'stderr' => [ @@ -65,16 +68,20 @@ return [ 'with' => [ 'stream' => 'php://stderr', ], + 'processors' => [PsrLogMessageProcessor::class], ], 'syslog' => [ 'driver' => 'syslog', 'level' => 'debug', + 'facility' => LOG_USER, + 'replace_placeholders' => true, ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => 'debug', + 'replace_placeholders' => true, ], // Custom errorlog implementation that logs out a plain, @@ -88,6 +95,7 @@ return [ 'formatter_with' => [ 'format' => '%message%', ], + 'replace_placeholders' => true, ], 'null' => [ diff --git a/app/Config/queue.php b/app/Config/queue.php index a14799f35..795a79325 100644 --- a/app/Config/queue.php +++ b/app/Config/queue.php @@ -40,6 +40,12 @@ return [ ], + // Job batching + 'batching' => [ + 'database' => 'mysql', + 'table' => 'job_batches', + ], + // Failed queue job logging 'failed' => [ 'driver' => 'database-uuids', diff --git a/app/Config/session.php b/app/Config/session.php index a00d75807..f2ec2509f 100644 --- a/app/Config/session.php +++ b/app/Config/session.php @@ -85,4 +85,11 @@ return [ // do not enable this as other CSRF protection services are in place. // Options: lax, strict, none 'same_site' => 'lax', + + + // Partitioned Cookies + // Setting this value to true will tie the cookie to the top-level site for + // a cross-site context. Partitioned cookies are accepted by the browser + // when flagged "secure" and the Same-Site attribute is set to "none". + 'partitioned' => false, ]; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index d23f56a2c..30714e2ac 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -45,11 +45,11 @@ class Kernel extends HttpKernel ]; /** - * The application's route middleware. + * The application's middleware aliases. * * @var array */ - protected $routeMiddleware = [ + protected $middlewareAliases = [ 'auth' => \BookStack\Http\Middleware\Authenticate::class, 'can' => \BookStack\Http\Middleware\CheckUserHasPermission::class, 'guest' => \BookStack\Http\Middleware\RedirectIfAuthenticated::class, diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 069973a95..745f7196d 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -6,19 +6,16 @@ use BookStack\App\Providers\RouteServiceProvider; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Symfony\Component\HttpFoundation\Response; class RedirectIfAuthenticated { /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null ...$guards - * - * @return mixed + * @param Closure(Request): (Response) $next */ - public function handle(Request $request, Closure $next, ...$guards) + public function handle(Request $request, Closure $next, string ...$guards): Response { $guards = empty($guards) ? [null] : $guards; diff --git a/app/Http/Middleware/ThrottleApiRequests.php b/app/Http/Middleware/ThrottleApiRequests.php index c63d0c603..cef2d3906 100644 --- a/app/Http/Middleware/ThrottleApiRequests.php +++ b/app/Http/Middleware/ThrottleApiRequests.php @@ -9,7 +9,7 @@ class ThrottleApiRequests extends Middleware /** * Resolve the number of attempts if the user is authenticated or not. */ - protected function resolveMaxAttempts($request, $maxAttempts) + protected function resolveMaxAttempts($request, $maxAttempts): int { return (int) config('api.requests_per_minute'); } diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php index 7bd89ee51..c13d631fe 100644 --- a/app/Http/Middleware/TrustHosts.php +++ b/app/Http/Middleware/TrustHosts.php @@ -9,9 +9,9 @@ class TrustHosts extends Middleware /** * Get the host patterns that should be trusted. * - * @return array + * @return array */ - public function hosts() + public function hosts(): array { return [ $this->allSubdomainsOfApplicationUrl(), diff --git a/composer.json b/composer.json index 74fbcf8f2..f58c2c9dd 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,9 @@ "doctrine/dbal": "^3.5", "guzzlehttp/guzzle": "^7.4", "intervention/image": "^2.7", - "laravel/framework": "^9.0", + "laravel/framework": "^10.10", "laravel/socialite": "^5.10", - "laravel/tinker": "^2.6", + "laravel/tinker": "^2.8", "league/commonmark": "^2.3", "league/flysystem-aws-s3-v3": "^3.0", "league/html-to-markdown": "^5.0.0", diff --git a/composer.lock b/composer.lock index 1b58e55ac..0edbd79bd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "54d735153e12b120d9dd41ab847e3032", + "content-hash": "df0a9795e5dd228d680cabf1f34d3aa6", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.300.15", + "version": "3.301.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "0cd194438b84588615121a93d0bc46bf55ca678b" + "reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0cd194438b84588615121a93d0bc46bf55ca678b", - "reference": "0cd194438b84588615121a93d0bc46bf55ca678b", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0a910d2b35e7087337cdf3569dc9b6ce232aafba", + "reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba", "shasum": "" }, "require": { @@ -151,9 +151,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.300.15" + "source": "https://github.com/aws/aws-sdk-php/tree/3.301.1" }, - "time": "2024-03-11T18:33:13+00:00" + "time": "2024-03-15T18:14:42+00:00" }, { "name": "bacon/bacon-qr-code", @@ -211,16 +211,16 @@ }, { "name": "barryvdh/laravel-dompdf", - "version": "v2.1.0", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "c8b8a8490e5f7348cf99054821fb248f103e7d24" + "reference": "cb37868365f9b937039d316727a1fced1e87b31c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/c8b8a8490e5f7348cf99054821fb248f103e7d24", - "reference": "c8b8a8490e5f7348cf99054821fb248f103e7d24", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/cb37868365f9b937039d316727a1fced1e87b31c", + "reference": "cb37868365f9b937039d316727a1fced1e87b31c", "shasum": "" }, "require": { @@ -272,7 +272,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.0" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.1" }, "funding": [ { @@ -284,7 +284,7 @@ "type": "github" } ], - "time": "2024-03-04T08:18:20+00:00" + "time": "2024-03-15T12:48:39+00:00" }, { "name": "barryvdh/laravel-snappy", @@ -2012,20 +2012,21 @@ }, { "name": "laravel/framework", - "version": "v9.52.16", + "version": "v10.48.3", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "082345d76fc6a55b649572efe10b11b03e279d24" + "reference": "5791c052b41c6b593556adc687076bfbdd13c501" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/082345d76fc6a55b649572efe10b11b03e279d24", - "reference": "082345d76fc6a55b649572efe10b11b03e279d24", + "url": "https://api.github.com/repos/laravel/framework/zipball/5791c052b41c6b593556adc687076bfbdd13c501", + "reference": "5791c052b41c6b593556adc687076bfbdd13c501", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.3.2", "egulias/email-validator": "^3.2.1|^4.0", @@ -2038,33 +2039,38 @@ "ext-tokenizer": "*", "fruitcake/php-cors": "^1.2", "guzzlehttp/uri-template": "^1.0", - "laravel/serializable-closure": "^1.2.2", + "laravel/prompts": "^0.1.9", + "laravel/serializable-closure": "^1.3", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", - "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.62.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.67", "nunomaduro/termwind": "^1.13", - "php": "^8.0.2", + "php": "^8.1", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^6.0.9", - "symfony/error-handler": "^6.0", - "symfony/finder": "^6.0", - "symfony/http-foundation": "^6.0", - "symfony/http-kernel": "^6.0", - "symfony/mailer": "^6.0", - "symfony/mime": "^6.0", - "symfony/process": "^6.0", - "symfony/routing": "^6.0", - "symfony/uid": "^6.0", - "symfony/var-dumper": "^6.0", + "symfony/console": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/finder": "^6.2", + "symfony/http-foundation": "^6.4", + "symfony/http-kernel": "^6.2", + "symfony/mailer": "^6.2", + "symfony/mime": "^6.2", + "symfony/process": "^6.2", + "symfony/routing": "^6.2", + "symfony/uid": "^6.2", + "symfony/var-dumper": "^6.2", "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.4.1", "voku/portable-ascii": "^2.0" }, "conflict": { + "carbonphp/carbon-doctrine-types": ">=3.0", + "doctrine/dbal": ">=4.0", + "mockery/mockery": "1.6.8", + "phpunit/phpunit": ">=11.0.0", "tightenco/collect": "<5.5.33" }, "provide": { @@ -2095,6 +2101,7 @@ "illuminate/notifications": "self.version", "illuminate/pagination": "self.version", "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", "illuminate/routing": "self.version", @@ -2108,7 +2115,7 @@ "require-dev": { "ably/ably-php": "^1.0", "aws/aws-sdk-php": "^3.235.5", - "doctrine/dbal": "^2.13.3|^3.1.4", + "doctrine/dbal": "^3.5.1", "ext-gmp": "*", "fakerphp/faker": "^1.21", "guzzlehttp/guzzle": "^7.5", @@ -2118,20 +2125,21 @@ "league/flysystem-read-only": "^3.3", "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^7.24", + "nyholm/psr7": "^1.2", + "orchestra/testbench-core": "^8.18", "pda/pheanstalk": "^4.0", - "phpstan/phpdoc-parser": "^1.15", "phpstan/phpstan": "^1.4.7", - "phpunit/phpunit": "^9.5.8", - "predis/predis": "^1.1.9|^2.0.2", - "symfony/cache": "^6.0", - "symfony/http-client": "^6.0" + "phpunit/phpunit": "^10.0.7", + "predis/predis": "^2.0.2", + "symfony/cache": "^6.2", + "symfony/http-client": "^6.2.4", + "symfony/psr-http-message-bridge": "^2.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", "brianium/paratest": "Required to run tests in parallel (^6.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", @@ -2153,27 +2161,28 @@ "mockery/mockery": "Required to use mocking (^1.5.1).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8).", - "predis/predis": "Required to use the predis connector (^1.1.9|^2.0.2).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", + "predis/predis": "Required to use the predis connector (^2.0.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^6.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^6.0).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.0).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "9.x-dev" + "dev-master": "10.x-dev" } }, "autoload": { "files": [ "src/Illuminate/Collections/helpers.php", "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" ], @@ -2206,7 +2215,64 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-10-03T13:02:30+00:00" + "time": "2024-03-15T10:17:07+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.1.16", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "ca6872ab6aec3ab61db3a61f83a6caf764ec7781" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/ca6872ab6aec3ab61db3a61f83a6caf764ec7781", + "reference": "ca6872ab6aec3ab61db3a61f83a6caf764ec7781", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/collections": "^10.0|^11.0", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.1.16" + }, + "time": "2024-02-21T19:25:27+00:00" }, { "name": "laravel/serializable-closure", @@ -2594,16 +2660,16 @@ }, { "name": "league/flysystem", - "version": "3.25.0", + "version": "3.25.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "4c44347133618cccd9b3df1729647a1577b4ad99" + "reference": "abbd664eb4381102c559d358420989f835208f18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4c44347133618cccd9b3df1729647a1577b4ad99", - "reference": "4c44347133618cccd9b3df1729647a1577b4ad99", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/abbd664eb4381102c559d358420989f835208f18", + "reference": "abbd664eb4381102c559d358420989f835208f18", "shasum": "" }, "require": { @@ -2668,7 +2734,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.25.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.25.1" }, "funding": [ { @@ -2680,20 +2746,20 @@ "type": "github" } ], - "time": "2024-03-09T17:06:45+00:00" + "time": "2024-03-16T12:53:19+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.24.0", + "version": "3.25.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "809474e37b7fb1d1f8bcc0f8a98bc1cae99aa513" + "reference": "6a5be0e6d6a93574e80805c9cc108a4b63c824d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/809474e37b7fb1d1f8bcc0f8a98bc1cae99aa513", - "reference": "809474e37b7fb1d1f8bcc0f8a98bc1cae99aa513", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/6a5be0e6d6a93574e80805c9cc108a4b63c824d8", + "reference": "6a5be0e6d6a93574e80805c9cc108a4b63c824d8", "shasum": "" }, "require": { @@ -2733,7 +2799,7 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.24.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.25.1" }, "funding": [ { @@ -2745,20 +2811,20 @@ "type": "github" } ], - "time": "2024-01-26T18:43:21+00:00" + "time": "2024-03-15T19:58:44+00:00" }, { "name": "league/flysystem-local", - "version": "3.23.1", + "version": "3.25.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "b884d2bf9b53bb4804a56d2df4902bb51e253f00" + "reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/b884d2bf9b53bb4804a56d2df4902bb51e253f00", - "reference": "b884d2bf9b53bb4804a56d2df4902bb51e253f00", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/61a6a90d6e999e4ddd9ce5adb356de0939060b92", + "reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92", "shasum": "" }, "require": { @@ -2792,8 +2858,7 @@ "local" ], "support": { - "issues": "https://github.com/thephpleague/flysystem-local/issues", - "source": "https://github.com/thephpleague/flysystem-local/tree/3.23.1" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.25.1" }, "funding": [ { @@ -2805,7 +2870,7 @@ "type": "github" } ], - "time": "2024-01-26T18:25:23+00:00" + "time": "2024-03-15T19:58:44+00:00" }, { "name": "league/html-to-markdown", @@ -3167,42 +3232,41 @@ }, { "name": "monolog/monolog", - "version": "2.9.2", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f" + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", - "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + "psr/log-implementation": "3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "aws/aws-sdk-php": "^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", - "guzzlehttp/guzzle": "^7.4", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^0.12.91", - "phpunit/phpunit": "^8.5.14", - "predis/predis": "^1.1 || ^2.0", - "rollbar/rollbar": "^1.3 || ^2 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^10.1", + "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", - "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -3225,7 +3289,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -3253,7 +3317,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.9.2" + "source": "https://github.com/Seldaek/monolog/tree/3.5.0" }, "funding": [ { @@ -3265,7 +3329,7 @@ "type": "tidelift" } ], - "time": "2023-10-27T15:25:26+00:00" + "time": "2023-10-27T15:32:31+00:00" }, { "name": "mtdowling/jmespath.php", @@ -3951,16 +4015,16 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.5.2", + "version": "0.5.3", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa" + "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/732faa9fb4309221e2bd9b2fda5de44f947133aa", - "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/0e46722c154726a5f9ac218197ccc28adba16fcf", + "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf", "shasum": "" }, "require": { @@ -3979,7 +4043,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-3.0-or-later" ], "authors": [ { @@ -3991,9 +4055,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.2" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.3" }, - "time": "2024-02-07T12:49:40+00:00" + "time": "2024-02-23T20:39:24+00:00" }, { "name": "phpoption/phpoption", @@ -4756,16 +4820,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.0", + "version": "v0.12.1", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "750bf031a48fd07c673dbe3f11f72362ea306d0d" + "reference": "39621c73e0754328252f032c6997b983afc50431" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/750bf031a48fd07c673dbe3f11f72362ea306d0d", - "reference": "750bf031a48fd07c673dbe3f11f72362ea306d0d", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/39621c73e0754328252f032c6997b983afc50431", + "reference": "39621c73e0754328252f032c6997b983afc50431", "shasum": "" }, "require": { @@ -4829,9 +4893,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.0" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.1" }, - "time": "2023-12-20T15:28:09+00:00" + "time": "2024-03-15T03:22:57+00:00" }, { "name": "ralouphie/getallheaders", @@ -8448,7 +8512,7 @@ }, { "name": "mockery/mockery", - "version": "1.6.7", + "version": "1.6.9", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", @@ -8884,16 +8948,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.60", + "version": "1.10.62", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe" + "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe", - "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9", + "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9", "shasum": "" }, "require": { @@ -8942,7 +9006,7 @@ "type": "tidelift" } ], - "time": "2024-03-07T13:30:19+00:00" + "time": "2024-03-13T12:27:20+00:00" }, { "name": "phpunit/php-code-coverage", @@ -10168,16 +10232,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -10189,7 +10253,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -10210,8 +10274,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -10219,7 +10282,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php index b1cefbb65..3258d05bc 100644 --- a/tests/CreatesApplication.php +++ b/tests/CreatesApplication.php @@ -3,15 +3,14 @@ namespace Tests; use Illuminate\Contracts\Console\Kernel; +use Illuminate\Foundation\Application; trait CreatesApplication { /** * Creates the application. - * - * @return \Illuminate\Foundation\Application */ - public function createApplication() + public function createApplication(): Application { $app = require __DIR__ . '/../bootstrap/app.php'; $app->make(Kernel::class)->bootstrap(); From d6b77179856420b21a4d428d070b7d784c90b468 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Mar 2024 15:26:34 +0000 Subject: [PATCH 06/59] Framework: Fixed issues breaking tests For #4903 --- app/Translation/FileLoader.php | 12 +++++++++--- tests/Auth/ResetPasswordTest.php | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/Translation/FileLoader.php b/app/Translation/FileLoader.php index de1124046..1fec4d18b 100644 --- a/app/Translation/FileLoader.php +++ b/app/Translation/FileLoader.php @@ -8,16 +8,22 @@ class FileLoader extends BaseLoader { /** * Load the messages for the given locale. + * * Extends Laravel's translation FileLoader to look in multiple directories * so that we can load in translation overrides from the theme file if wanted. * + * Note: As of using Laravel 10, this may now be redundant since Laravel's + * file loader supports multiple paths. This needs further testing though + * to confirm if Laravel works how we expect, since we specifically need + * the theme folder to be able to partially override core lang files. + * * @param string $locale * @param string $group * @param string|null $namespace * * @return array */ - public function load($locale, $group, $namespace = null) + public function load($locale, $group, $namespace = null): array { if ($group === '*' && $namespace === '*') { return $this->loadJsonPaths($locale); @@ -25,8 +31,8 @@ class FileLoader extends BaseLoader if (is_null($namespace) || $namespace === '*') { $themePath = theme_path('lang'); - $themeTranslations = $themePath ? $this->loadPath($themePath, $locale, $group) : []; - $originalTranslations = $this->loadPath($this->path, $locale, $group); + $themeTranslations = $themePath ? $this->loadPaths([$themePath], $locale, $group) : []; + $originalTranslations = $this->loadPaths($this->paths, $locale, $group); return array_merge($originalTranslations, $themeTranslations); } diff --git a/tests/Auth/ResetPasswordTest.php b/tests/Auth/ResetPasswordTest.php index e60ac5643..d2af17b9c 100644 --- a/tests/Auth/ResetPasswordTest.php +++ b/tests/Auth/ResetPasswordTest.php @@ -95,7 +95,7 @@ class ResetPasswordTest extends TestCase $resp = $this->followingRedirects()->post('/password/email', [ 'email' => $editor->email, ]); - Notification::assertTimesSent(1, ResetPasswordNotification::class); + Notification::assertSentTimes(ResetPasswordNotification::class, 1); $resp->assertSee('A password reset link will be sent to ' . $editor->email . ' if that email address is found in the system.'); } } From 45d52f27ae578e00b8d45d6848ffcefede6015d6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Mar 2024 15:29:09 +0000 Subject: [PATCH 07/59] Migrations: Updated with type hints instead of php doc Also updated code to properly import used facades. For #4903 --- .../2014_10_12_000000_create_users_table.php | 15 +++++---- ...12_100000_create_password_resets_table.php | 9 ++---- .../2015_07_12_114933_create_books_table.php | 9 ++---- .../2015_07_12_190027_create_pages_table.php | 9 ++---- .../2015_07_13_172121_create_images_table.php | 9 ++---- ...015_07_27_172342_create_chapters_table.php | 9 ++---- ...015_08_08_200447_add_users_to_entities.php | 9 ++---- ..._09_093534_create_page_revisions_table.php | 9 ++---- ...5_08_16_142133_create_activities_table.php | 9 ++---- ...08_29_105422_add_roles_and_permissions.php | 31 +++++++++---------- ...015_08_30_125859_create_settings_table.php | 9 ++---- .../2015_08_31_175240_add_search_indexes.php | 7 ++--- ...04_165821_create_social_accounts_table.php | 9 ++---- ...05_164707_add_email_confirmation_table.php | 9 ++---- .../2015_11_21_145609_create_views_table.php | 9 ++---- .../2015_11_26_221857_add_entity_indexes.php | 9 ++---- .../2015_12_05_145049_fulltext_weighting.php | 7 ++--- ...15_12_07_195238_add_image_upload_types.php | 9 ++---- .../2015_12_09_195748_add_user_avatars.php | 9 ++---- ...1_11_210908_add_external_auth_to_users.php | 9 ++---- ...016_02_25_184030_add_slug_to_revisions.php | 9 ++---- ...27_120329_update_permissions_and_roles.php | 26 +++++++--------- ...2_28_084200_add_entity_access_controls.php | 9 ++---- ...6_03_09_203143_add_page_revision_types.php | 9 ++---- .../2016_03_13_082138_add_page_drafts.php | 9 ++---- ...2016_03_25_123157_add_markdown_support.php | 9 ++---- ...9_100730_add_view_permissions_to_roles.php | 14 ++++----- ..._192649_create_joint_permissions_table.php | 15 +++++---- .../2016_05_06_185215_create_tags_table.php | 9 ++---- ...7_181521_add_summary_to_page_revisions.php | 9 ++---- .../2016_09_29_101449_remove_hidden_roles.php | 14 ++++----- ..._10_09_142037_create_attachments_table.php | 14 ++++----- .../2017_01_21_163556_create_cache_table.php | 8 ++--- ...017_01_21_163602_create_sessions_table.php | 8 ++--- ...03_19_091553_create_search_index_table.php | 8 ++--- .../2017_04_20_185112_add_revision_counts.php | 9 ++---- ...02_152834_update_db_encoding_to_ut8mb4.php | 4 --- ...017_08_01_130541_create_comments_table.php | 14 ++++----- ...7_08_29_102650_add_cover_image_display.php | 8 ++--- ...07_15_173514_add_role_external_auth_id.php | 8 ++--- ..._08_04_115700_create_bookshelves_table.php | 13 +++----- ...2019_07_07_112515_add_template_support.php | 9 ++---- ...19_08_17_140214_add_user_invites_table.php | 8 ++--- .../2019_12_29_120917_add_api_auth.php | 9 ++---- ...08_04_111754_drop_joint_permissions_id.php | 8 ++--- ...20_08_04_131052_remove_role_name_field.php | 8 ++--- ...2020_09_19_094251_add_activity_indexes.php | 8 ++--- ...0_09_27_210059_add_entity_soft_deletes.php | 8 ++--- ...20_09_27_210528_create_deletions_table.php | 8 ++--- ...11_07_232321_simplify_activities_table.php | 8 ++--- ..._173528_add_owned_by_field_to_entities.php | 8 ++--- ..._01_30_225441_add_settings_type_column.php | 8 ++--- .../2021_03_08_215138_add_user_slug.php | 9 ++---- ...1_05_15_173110_create_favourites_table.php | 8 ++--- ...1_06_30_173111_create_mfa_values_table.php | 8 ++--- ...085038_add_mfa_enforced_to_roles_table.php | 8 ++--- ...8_28_161743_add_export_role_permission.php | 8 ++--- ..._09_26_044614_add_activities_ip_column.php | 8 ++--- ...021_11_26_070438_add_index_for_user_ip.php | 8 ++--- ...021_12_07_111343_create_webhooks_table.php | 8 ++--- .../2021_12_13_152024_create_jobs_table.php | 8 ++--- ..._12_13_152120_create_failed_jobs_table.php | 8 ++--- ...041_add_webhooks_timeout_error_columns.php | 8 ++--- ...add_editor_change_field_and_permission.php | 8 ++--- ..._04_25_140741_update_polymorphic_types.php | 8 ++--- ...7_16_170051_drop_joint_permission_type.php | 8 ++--- ...2_08_17_092941_create_references_table.php | 8 ++--- ..._02_082910_fix_shelf_cover_image_types.php | 8 ++--- ...91406_flatten_entity_permissions_table.php | 8 ++--- ...08_104202_drop_entity_restricted_field.php | 8 ++--- ...625_refactor_joint_permissions_storage.php | 8 ++--- ...1230_copy_color_settings_for_dark_mode.php | 8 ++--- ...93655_increase_attachments_path_length.php | 8 ++--- ...3_200227_add_updated_at_index_to_pages.php | 8 ++--- ...1823_remove_guest_user_secondary_roles.php | 6 +--- ...ve_bookshelf_create_entity_permissions.php | 4 --- ...receive_notifications_role_permissions.php | 9 ++---- ...2023_07_31_104430_create_watches_table.php | 8 ++--- .../2023_08_21_174248_increase_cache_size.php | 8 ++--- ...2_104541_add_default_template_to_books.php | 8 ++--- ...40913_add_description_html_to_entities.php | 8 ++--- ...04542_add_default_template_to_chapters.php | 8 ++--- ...4_02_04_141358_add_views_updated_index.php | 8 ++--- 83 files changed, 241 insertions(+), 523 deletions(-) diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 61b73b7f2..638394df6 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -1,16 +1,17 @@ increments('id'); @@ -26,17 +27,15 @@ return new class extends Migration 'name' => 'Admin', 'email' => 'admin@admin.com', 'password' => bcrypt('password'), - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); } /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('users'); } diff --git a/database/migrations/2014_10_12_100000_create_password_resets_table.php b/database/migrations/2014_10_12_100000_create_password_resets_table.php index f29aff42b..f53370009 100644 --- a/database/migrations/2014_10_12_100000_create_password_resets_table.php +++ b/database/migrations/2014_10_12_100000_create_password_resets_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('password_resets', function (Blueprint $table) { $table->string('email')->index(); @@ -21,10 +20,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('password_resets'); } diff --git a/database/migrations/2015_07_12_114933_create_books_table.php b/database/migrations/2015_07_12_114933_create_books_table.php index 959169458..98d043365 100644 --- a/database/migrations/2015_07_12_114933_create_books_table.php +++ b/database/migrations/2015_07_12_114933_create_books_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('books', function (Blueprint $table) { $table->increments('id'); @@ -23,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('books'); } diff --git a/database/migrations/2015_07_12_190027_create_pages_table.php b/database/migrations/2015_07_12_190027_create_pages_table.php index d9b266813..8ef5fc971 100644 --- a/database/migrations/2015_07_12_190027_create_pages_table.php +++ b/database/migrations/2015_07_12_190027_create_pages_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('pages', function (Blueprint $table) { $table->increments('id'); @@ -27,10 +26,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('pages'); } diff --git a/database/migrations/2015_07_13_172121_create_images_table.php b/database/migrations/2015_07_13_172121_create_images_table.php index 8814d079e..ae57fc80d 100644 --- a/database/migrations/2015_07_13_172121_create_images_table.php +++ b/database/migrations/2015_07_13_172121_create_images_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('images', function (Blueprint $table) { $table->increments('id'); @@ -22,10 +21,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('images'); } diff --git a/database/migrations/2015_07_27_172342_create_chapters_table.php b/database/migrations/2015_07_27_172342_create_chapters_table.php index bfccd6fac..fca92429c 100644 --- a/database/migrations/2015_07_27_172342_create_chapters_table.php +++ b/database/migrations/2015_07_27_172342_create_chapters_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('chapters', function (Blueprint $table) { $table->increments('id'); @@ -25,10 +24,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('chapters'); } diff --git a/database/migrations/2015_08_08_200447_add_users_to_entities.php b/database/migrations/2015_08_08_200447_add_users_to_entities.php index 8acfd360a..51dfafc6a 100644 --- a/database/migrations/2015_08_08_200447_add_users_to_entities.php +++ b/database/migrations/2015_08_08_200447_add_users_to_entities.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->integer('created_by'); @@ -32,10 +31,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropColumn('created_by'); diff --git a/database/migrations/2015_08_09_093534_create_page_revisions_table.php b/database/migrations/2015_08_09_093534_create_page_revisions_table.php index b8264fd29..af9104edc 100644 --- a/database/migrations/2015_08_09_093534_create_page_revisions_table.php +++ b/database/migrations/2015_08_09_093534_create_page_revisions_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('page_revisions', function (Blueprint $table) { $table->increments('id'); @@ -25,10 +24,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('page_revisions'); } diff --git a/database/migrations/2015_08_16_142133_create_activities_table.php b/database/migrations/2015_08_16_142133_create_activities_table.php index 742a4a40d..316d52ced 100644 --- a/database/migrations/2015_08_16_142133_create_activities_table.php +++ b/database/migrations/2015_08_16_142133_create_activities_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('activities', function (Blueprint $table) { $table->increments('id'); @@ -26,10 +25,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('activities'); } diff --git a/database/migrations/2015_08_29_105422_add_roles_and_permissions.php b/database/migrations/2015_08_29_105422_add_roles_and_permissions.php index 517cfaf43..a2a8ae9d6 100644 --- a/database/migrations/2015_08_29_105422_add_roles_and_permissions.php +++ b/database/migrations/2015_08_29_105422_add_roles_and_permissions.php @@ -10,17 +10,18 @@ * @url https://github.com/Zizaco/entrust */ +use Carbon\Carbon; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Create table for storing roles Schema::create('roles', function (Blueprint $table) { @@ -71,22 +72,22 @@ return new class extends Migration 'name' => 'admin', 'display_name' => 'Admin', 'description' => 'Administrator of the whole application', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); $editorId = DB::table('roles')->insertGetId([ 'name' => 'editor', 'display_name' => 'Editor', 'description' => 'User can edit Books, Chapters & Pages', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); $viewerId = DB::table('roles')->insertGetId([ 'name' => 'viewer', 'display_name' => 'Viewer', 'description' => 'User can view books & their content behind authentication', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); // Create default CRUD permissions and allocate to admins and editors @@ -97,8 +98,8 @@ return new class extends Migration $newPermId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower($op), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ ['permission_id' => $newPermId, 'role_id' => $adminId], @@ -115,8 +116,8 @@ return new class extends Migration $newPermId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower($op), 'display_name' => $op . ' ' . $entity, - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'permission_id' => $newPermId, @@ -138,10 +139,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('permission_role'); Schema::drop('permissions'); diff --git a/database/migrations/2015_08_30_125859_create_settings_table.php b/database/migrations/2015_08_30_125859_create_settings_table.php index 45c9c08b3..d1273bf09 100644 --- a/database/migrations/2015_08_30_125859_create_settings_table.php +++ b/database/migrations/2015_08_30_125859_create_settings_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('settings', function (Blueprint $table) { $table->string('setting_key')->primary()->indexed(); @@ -21,10 +20,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('settings'); } diff --git a/database/migrations/2015_08_31_175240_add_search_indexes.php b/database/migrations/2015_08_31_175240_add_search_indexes.php index 6097fd13e..4e0421e9e 100644 --- a/database/migrations/2015_08_31_175240_add_search_indexes.php +++ b/database/migrations/2015_08_31_175240_add_search_indexes.php @@ -2,13 +2,12 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -23,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); $pages = $sm->listTableDetails('pages'); diff --git a/database/migrations/2015_09_04_165821_create_social_accounts_table.php b/database/migrations/2015_09_04_165821_create_social_accounts_table.php index bea901136..7a9b1a496 100644 --- a/database/migrations/2015_09_04_165821_create_social_accounts_table.php +++ b/database/migrations/2015_09_04_165821_create_social_accounts_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('social_accounts', function (Blueprint $table) { $table->increments('id'); @@ -24,10 +23,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('social_accounts'); } diff --git a/database/migrations/2015_09_05_164707_add_email_confirmation_table.php b/database/migrations/2015_09_05_164707_add_email_confirmation_table.php index a28a5728e..9e58493c7 100644 --- a/database/migrations/2015_09_05_164707_add_email_confirmation_table.php +++ b/database/migrations/2015_09_05_164707_add_email_confirmation_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('users', function (Blueprint $table) { $table->boolean('email_confirmed')->default(true); @@ -26,10 +25,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('email_confirmed'); diff --git a/database/migrations/2015_11_21_145609_create_views_table.php b/database/migrations/2015_11_21_145609_create_views_table.php index bb8c373d8..00ccc7ac3 100644 --- a/database/migrations/2015_11_21_145609_create_views_table.php +++ b/database/migrations/2015_11_21_145609_create_views_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('views', function (Blueprint $table) { $table->increments('id'); @@ -24,10 +23,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('views'); } diff --git a/database/migrations/2015_11_26_221857_add_entity_indexes.php b/database/migrations/2015_11_26_221857_add_entity_indexes.php index 3203eb8a7..3f1882447 100644 --- a/database/migrations/2015_11_26_221857_add_entity_indexes.php +++ b/database/migrations/2015_11_26_221857_add_entity_indexes.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('books', function (Blueprint $table) { $table->index('slug'); @@ -48,10 +47,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('books', function (Blueprint $table) { $table->dropIndex('books_slug_index'); diff --git a/database/migrations/2015_12_05_145049_fulltext_weighting.php b/database/migrations/2015_12_05_145049_fulltext_weighting.php index a18508c45..7f9d2373c 100644 --- a/database/migrations/2015_12_05_145049_fulltext_weighting.php +++ b/database/migrations/2015_12_05_145049_fulltext_weighting.php @@ -2,13 +2,12 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -23,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); $pages = $sm->listTableDetails('pages'); diff --git a/database/migrations/2015_12_07_195238_add_image_upload_types.php b/database/migrations/2015_12_07_195238_add_image_upload_types.php index c9f9675c7..ce6e5d6b6 100644 --- a/database/migrations/2015_12_07_195238_add_image_upload_types.php +++ b/database/migrations/2015_12_07_195238_add_image_upload_types.php @@ -3,15 +3,14 @@ use BookStack\Uploads\Image; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('images', function (Blueprint $table) { $table->string('path', 400); @@ -27,10 +26,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('images', function (Blueprint $table) { $table->dropColumn('type'); diff --git a/database/migrations/2015_12_09_195748_add_user_avatars.php b/database/migrations/2015_12_09_195748_add_user_avatars.php index 950526ddc..dd8bcf0b4 100644 --- a/database/migrations/2015_12_09_195748_add_user_avatars.php +++ b/database/migrations/2015_12_09_195748_add_user_avatars.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('users', function (Blueprint $table) { $table->integer('image_id')->default(0); @@ -19,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('image_id'); diff --git a/database/migrations/2016_01_11_210908_add_external_auth_to_users.php b/database/migrations/2016_01_11_210908_add_external_auth_to_users.php index ff889d867..413a8a29d 100644 --- a/database/migrations/2016_01_11_210908_add_external_auth_to_users.php +++ b/database/migrations/2016_01_11_210908_add_external_auth_to_users.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('external_auth_id')->index(); @@ -19,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('external_auth_id'); diff --git a/database/migrations/2016_02_25_184030_add_slug_to_revisions.php b/database/migrations/2016_02_25_184030_add_slug_to_revisions.php index a083e10b5..86a08f2c8 100644 --- a/database/migrations/2016_02_25_184030_add_slug_to_revisions.php +++ b/database/migrations/2016_02_25_184030_add_slug_to_revisions.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('page_revisions', function (Blueprint $table) { $table->string('slug'); @@ -22,10 +21,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('page_revisions', function (Blueprint $table) { $table->dropColumn('slug'); diff --git a/database/migrations/2016_02_27_120329_update_permissions_and_roles.php b/database/migrations/2016_02_27_120329_update_permissions_and_roles.php index dd62301d6..c0d86086d 100644 --- a/database/migrations/2016_02_27_120329_update_permissions_and_roles.php +++ b/database/migrations/2016_02_27_120329_update_permissions_and_roles.php @@ -1,15 +1,15 @@ where('name', '=', 'admin')->first()->id; @@ -30,8 +30,8 @@ return new class extends Migration $permissionId = DB::table('permissions')->insertGetId([ 'name' => $name, 'display_name' => $displayName, - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, @@ -47,8 +47,8 @@ return new class extends Migration $permissionId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, @@ -66,10 +66,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Get roles with permissions we need to change $adminRoleId = DB::table('roles')->where('name', '=', 'admin')->first()->id; @@ -85,8 +83,8 @@ return new class extends Migration $permissionId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower($op), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, @@ -103,8 +101,8 @@ return new class extends Migration $permissionId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower($op), 'display_name' => $op . ' ' . $entity, - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, diff --git a/database/migrations/2016_02_28_084200_add_entity_access_controls.php b/database/migrations/2016_02_28_084200_add_entity_access_controls.php index 7a796e728..cf8ba5f30 100644 --- a/database/migrations/2016_02_28_084200_add_entity_access_controls.php +++ b/database/migrations/2016_02_28_084200_add_entity_access_controls.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('images', function (Blueprint $table) { $table->integer('uploaded_to')->default(0); @@ -46,10 +45,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('images', function (Blueprint $table) { $table->dropColumn('uploaded_to'); diff --git a/database/migrations/2016_03_09_203143_add_page_revision_types.php b/database/migrations/2016_03_09_203143_add_page_revision_types.php index 2fc630437..566f2fdeb 100644 --- a/database/migrations/2016_03_09_203143_add_page_revision_types.php +++ b/database/migrations/2016_03_09_203143_add_page_revision_types.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('page_revisions', function (Blueprint $table) { $table->string('type')->default('version'); @@ -20,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('page_revisions', function (Blueprint $table) { $table->dropColumn('type'); diff --git a/database/migrations/2016_03_13_082138_add_page_drafts.php b/database/migrations/2016_03_13_082138_add_page_drafts.php index ce5979632..a8690513f 100644 --- a/database/migrations/2016_03_13_082138_add_page_drafts.php +++ b/database/migrations/2016_03_13_082138_add_page_drafts.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->boolean('draft')->default(false); @@ -20,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropColumn('draft'); diff --git a/database/migrations/2016_03_25_123157_add_markdown_support.php b/database/migrations/2016_03_25_123157_add_markdown_support.php index a89fc273d..f0b42b645 100644 --- a/database/migrations/2016_03_25_123157_add_markdown_support.php +++ b/database/migrations/2016_03_25_123157_add_markdown_support.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->longText('markdown')->default(''); @@ -23,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropColumn('markdown'); diff --git a/database/migrations/2016_04_09_100730_add_view_permissions_to_roles.php b/database/migrations/2016_04_09_100730_add_view_permissions_to_roles.php index 411c24007..481ac785f 100644 --- a/database/migrations/2016_04_09_100730_add_view_permissions_to_roles.php +++ b/database/migrations/2016_04_09_100730_add_view_permissions_to_roles.php @@ -1,15 +1,15 @@ get(); @@ -21,8 +21,8 @@ return new class extends Migration $permId = DB::table('permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); // Assign view permission to all current roles foreach ($currentRoles as $role) { @@ -37,10 +37,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Delete the new view permission $entities = ['Book', 'Page', 'Chapter']; diff --git a/database/migrations/2016_04_20_192649_create_joint_permissions_table.php b/database/migrations/2016_04_20_192649_create_joint_permissions_table.php index 745e156bc..ba9f615e4 100644 --- a/database/migrations/2016_04_20_192649_create_joint_permissions_table.php +++ b/database/migrations/2016_04_20_192649_create_joint_permissions_table.php @@ -1,17 +1,18 @@ increments('id'); @@ -48,8 +49,8 @@ return new class extends Migration 'description' => 'The role given to public visitors if allowed', 'system_name' => 'public', 'hidden' => true, - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]; // Ensure unique name @@ -79,10 +80,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('joint_permissions'); diff --git a/database/migrations/2016_05_06_185215_create_tags_table.php b/database/migrations/2016_05_06_185215_create_tags_table.php index b065a052f..1be9a389f 100644 --- a/database/migrations/2016_05_06_185215_create_tags_table.php +++ b/database/migrations/2016_05_06_185215_create_tags_table.php @@ -2,15 +2,14 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('tags', function (Blueprint $table) { $table->increments('id'); @@ -30,10 +29,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('tags'); } diff --git a/database/migrations/2016_07_07_181521_add_summary_to_page_revisions.php b/database/migrations/2016_07_07_181521_add_summary_to_page_revisions.php index 03942b17a..562e6415f 100644 --- a/database/migrations/2016_07_07_181521_add_summary_to_page_revisions.php +++ b/database/migrations/2016_07_07_181521_add_summary_to_page_revisions.php @@ -1,15 +1,14 @@ string('summary')->nullable(); @@ -18,10 +17,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('page_revisions', function ($table) { $table->dropColumn('summary'); diff --git a/database/migrations/2016_09_29_101449_remove_hidden_roles.php b/database/migrations/2016_09_29_101449_remove_hidden_roles.php index 2f729673f..fa0a5fe92 100644 --- a/database/migrations/2016_09_29_101449_remove_hidden_roles.php +++ b/database/migrations/2016_09_29_101449_remove_hidden_roles.php @@ -1,17 +1,17 @@ 'Guest', 'system_name' => 'public', 'email_confirmed' => true, - 'created_at' => \Carbon\Carbon::now(), - 'updated_at' => \Carbon\Carbon::now(), + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now(), ]); // Get the public role @@ -45,10 +45,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('roles', function (Blueprint $table) { $table->boolean('hidden')->default(false); diff --git a/database/migrations/2016_10_09_142037_create_attachments_table.php b/database/migrations/2016_10_09_142037_create_attachments_table.php index 41db5723d..278051c8b 100644 --- a/database/migrations/2016_10_09_142037_create_attachments_table.php +++ b/database/migrations/2016_10_09_142037_create_attachments_table.php @@ -1,17 +1,17 @@ increments('id'); @@ -40,8 +40,8 @@ return new class extends Migration $permissionId = DB::table('role_permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, @@ -52,10 +52,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('attachments'); diff --git a/database/migrations/2017_01_21_163556_create_cache_table.php b/database/migrations/2017_01_21_163556_create_cache_table.php index abff912f2..7c07c0cb8 100644 --- a/database/migrations/2017_01_21_163556_create_cache_table.php +++ b/database/migrations/2017_01_21_163556_create_cache_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('cache', function (Blueprint $table) { $table->string('key')->unique(); @@ -22,10 +20,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('cache'); } diff --git a/database/migrations/2017_01_21_163602_create_sessions_table.php b/database/migrations/2017_01_21_163602_create_sessions_table.php index c32838a8c..3f52752c2 100644 --- a/database/migrations/2017_01_21_163602_create_sessions_table.php +++ b/database/migrations/2017_01_21_163602_create_sessions_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('sessions', function (Blueprint $table) { $table->string('id')->unique(); @@ -25,10 +23,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('sessions'); } diff --git a/database/migrations/2017_03_19_091553_create_search_index_table.php b/database/migrations/2017_03_19_091553_create_search_index_table.php index 03a63392a..72be3ccbe 100644 --- a/database/migrations/2017_03_19_091553_create_search_index_table.php +++ b/database/migrations/2017_03_19_091553_create_search_index_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('search_terms', function (Blueprint $table) { $table->increments('id'); @@ -55,10 +53,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // This was removed for v0.24 since these indexes are removed anyway // and will cause issues for db engines that don't support such indexes. diff --git a/database/migrations/2017_04_20_185112_add_revision_counts.php b/database/migrations/2017_04_20_185112_add_revision_counts.php index 891ff8e0a..182d95c75 100644 --- a/database/migrations/2017_04_20_185112_add_revision_counts.php +++ b/database/migrations/2017_04_20_185112_add_revision_counts.php @@ -2,16 +2,15 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->integer('revision_count'); @@ -29,10 +28,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropColumn('revision_count'); diff --git a/database/migrations/2017_07_02_152834_update_db_encoding_to_ut8mb4.php b/database/migrations/2017_07_02_152834_update_db_encoding_to_ut8mb4.php index 7805be700..178cb584f 100644 --- a/database/migrations/2017_07_02_152834_update_db_encoding_to_ut8mb4.php +++ b/database/migrations/2017_07_02_152834_update_db_encoding_to_ut8mb4.php @@ -6,8 +6,6 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -18,8 +16,6 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/database/migrations/2017_08_01_130541_create_comments_table.php b/database/migrations/2017_08_01_130541_create_comments_table.php index f654ebf65..d14785476 100644 --- a/database/migrations/2017_08_01_130541_create_comments_table.php +++ b/database/migrations/2017_08_01_130541_create_comments_table.php @@ -1,17 +1,17 @@ increments('id')->unsigned(); @@ -37,8 +37,8 @@ return new class extends Migration $permissionId = DB::table('role_permissions')->insertGetId([ 'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)), 'display_name' => $op . ' ' . $entity . 's', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); DB::table('permission_role')->insert([ 'role_id' => $adminRoleId, @@ -50,10 +50,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('comments'); // Delete comment role permissions diff --git a/database/migrations/2017_08_29_102650_add_cover_image_display.php b/database/migrations/2017_08_29_102650_add_cover_image_display.php index 5ba3145f2..0f7b7d82a 100644 --- a/database/migrations/2017_08_29_102650_add_cover_image_display.php +++ b/database/migrations/2017_08_29_102650_add_cover_image_display.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('books', function (Blueprint $table) { $table->integer('image_id')->nullable()->default(null); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('books', function (Blueprint $table) { $table->dropColumn('image_id'); diff --git a/database/migrations/2018_07_15_173514_add_role_external_auth_id.php b/database/migrations/2018_07_15_173514_add_role_external_auth_id.php index eb2bf91fc..586947656 100644 --- a/database/migrations/2018_07_15_173514_add_role_external_auth_id.php +++ b/database/migrations/2018_07_15_173514_add_role_external_auth_id.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('roles', function (Blueprint $table) { $table->string('external_auth_id', 180)->default(''); @@ -21,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('roles', function (Blueprint $table) { $table->dropColumn('external_auth_id'); diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php index bd3478bc7..54ccfb6ba 100644 --- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php +++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php @@ -1,5 +1,6 @@ insertGetId([ 'name' => 'bookshelf-' . $dbOpName, 'display_name' => $op . ' ' . 'BookShelves', - 'created_at' => \Carbon\Carbon::now()->toDateTimeString(), - 'updated_at' => \Carbon\Carbon::now()->toDateTimeString(), + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), ]); $rowsToInsert = $roleIdsWithBookPermission->filter(function ($roleId) { @@ -103,10 +102,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Drop created permissions $ops = ['bookshelf-create-all', 'bookshelf-create-own', 'bookshelf-delete-all', 'bookshelf-delete-own', 'bookshelf-update-all', 'bookshelf-update-own', 'bookshelf-view-all', 'bookshelf-view-own']; diff --git a/database/migrations/2019_07_07_112515_add_template_support.php b/database/migrations/2019_07_07_112515_add_template_support.php index 423e02827..cabde549e 100644 --- a/database/migrations/2019_07_07_112515_add_template_support.php +++ b/database/migrations/2019_07_07_112515_add_template_support.php @@ -3,16 +3,15 @@ use Carbon\Carbon; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->boolean('template')->default(false); @@ -35,10 +34,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropColumn('template'); diff --git a/database/migrations/2019_08_17_140214_add_user_invites_table.php b/database/migrations/2019_08_17_140214_add_user_invites_table.php index ce88a2894..1ab4c72f8 100644 --- a/database/migrations/2019_08_17_140214_add_user_invites_table.php +++ b/database/migrations/2019_08_17_140214_add_user_invites_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('user_invites', function (Blueprint $table) { $table->increments('id'); @@ -23,10 +21,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('user_invites'); } diff --git a/database/migrations/2019_12_29_120917_add_api_auth.php b/database/migrations/2019_12_29_120917_add_api_auth.php index 2cf970a8a..99ce8d27c 100644 --- a/database/migrations/2019_12_29_120917_add_api_auth.php +++ b/database/migrations/2019_12_29_120917_add_api_auth.php @@ -3,16 +3,15 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Add API tokens table @@ -42,10 +41,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Remove API tokens table Schema::dropIfExists('api_tokens'); diff --git a/database/migrations/2020_08_04_111754_drop_joint_permissions_id.php b/database/migrations/2020_08_04_111754_drop_joint_permissions_id.php index 902d3c227..882001cad 100644 --- a/database/migrations/2020_08_04_111754_drop_joint_permissions_id.php +++ b/database/migrations/2020_08_04_111754_drop_joint_permissions_id.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('joint_permissions', function (Blueprint $table) { $table->dropColumn('id'); @@ -21,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('joint_permissions', function (Blueprint $table) { $table->dropPrimary(['role_id', 'entity_type', 'entity_id', 'action']); diff --git a/database/migrations/2020_08_04_131052_remove_role_name_field.php b/database/migrations/2020_08_04_131052_remove_role_name_field.php index cd9f64697..10800e11f 100644 --- a/database/migrations/2020_08_04_131052_remove_role_name_field.php +++ b/database/migrations/2020_08_04_131052_remove_role_name_field.php @@ -9,10 +9,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('roles', function (Blueprint $table) { $table->dropColumn('name'); @@ -21,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('roles', function (Blueprint $table) { $table->string('name')->index(); diff --git a/database/migrations/2020_09_19_094251_add_activity_indexes.php b/database/migrations/2020_09_19_094251_add_activity_indexes.php index f7f35b62b..ca1afb1da 100644 --- a/database/migrations/2020_09_19_094251_add_activity_indexes.php +++ b/database/migrations/2020_09_19_094251_add_activity_indexes.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('activities', function (Blueprint $table) { $table->index('key'); @@ -21,10 +19,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('activities', function (Blueprint $table) { $table->dropIndex('activities_key_index'); diff --git a/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php b/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php index 9cc12acdc..bc6c3f18f 100644 --- a/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php +++ b/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('bookshelves', function (Blueprint $table) { $table->softDeletes(); @@ -29,10 +27,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('bookshelves', function (Blueprint $table) { $table->dropSoftDeletes(); diff --git a/database/migrations/2020_09_27_210528_create_deletions_table.php b/database/migrations/2020_09_27_210528_create_deletions_table.php index 3b1098175..96c6c0b0d 100644 --- a/database/migrations/2020_09_27_210528_create_deletions_table.php +++ b/database/migrations/2020_09_27_210528_create_deletions_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('deletions', function (Blueprint $table) { $table->increments('id'); @@ -28,10 +26,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('deletions'); } diff --git a/database/migrations/2020_11_07_232321_simplify_activities_table.php b/database/migrations/2020_11_07_232321_simplify_activities_table.php index 6ebe3fad0..c128a3235 100644 --- a/database/migrations/2020_11_07_232321_simplify_activities_table.php +++ b/database/migrations/2020_11_07_232321_simplify_activities_table.php @@ -9,10 +9,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('activities', function (Blueprint $table) { $table->renameColumn('key', 'type'); @@ -32,10 +30,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { DB::table('activities') ->whereNull('entity_id') diff --git a/database/migrations/2020_12_30_173528_add_owned_by_field_to_entities.php b/database/migrations/2020_12_30_173528_add_owned_by_field_to_entities.php index d9fab7f02..965a061d8 100644 --- a/database/migrations/2020_12_30_173528_add_owned_by_field_to_entities.php +++ b/database/migrations/2020_12_30_173528_add_owned_by_field_to_entities.php @@ -9,10 +9,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { $tables = ['pages', 'books', 'chapters', 'bookshelves']; foreach ($tables as $table) { @@ -30,10 +28,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $tables = ['pages', 'books', 'chapters', 'bookshelves']; foreach ($tables as $table) { diff --git a/database/migrations/2021_01_30_225441_add_settings_type_column.php b/database/migrations/2021_01_30_225441_add_settings_type_column.php index 5d83d15f1..367b93a89 100644 --- a/database/migrations/2021_01_30_225441_add_settings_type_column.php +++ b/database/migrations/2021_01_30_225441_add_settings_type_column.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('settings', function (Blueprint $table) { $table->string('type', 50)->default('string'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('settings', function (Blueprint $table) { $table->dropColumn('type'); diff --git a/database/migrations/2021_03_08_215138_add_user_slug.php b/database/migrations/2021_03_08_215138_add_user_slug.php index c0e1313a7..af01d6672 100644 --- a/database/migrations/2021_03_08_215138_add_user_slug.php +++ b/database/migrations/2021_03_08_215138_add_user_slug.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; @@ -9,10 +10,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('slug', 180); @@ -38,10 +37,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('slug'); diff --git a/database/migrations/2021_05_15_173110_create_favourites_table.php b/database/migrations/2021_05_15_173110_create_favourites_table.php index cdd7f4f64..73fa1b24b 100644 --- a/database/migrations/2021_05_15_173110_create_favourites_table.php +++ b/database/migrations/2021_05_15_173110_create_favourites_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('favourites', function (Blueprint $table) { $table->increments('id'); @@ -26,10 +24,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('favourites'); } diff --git a/database/migrations/2021_06_30_173111_create_mfa_values_table.php b/database/migrations/2021_06_30_173111_create_mfa_values_table.php index d145bf4ae..ea45b8ce1 100644 --- a/database/migrations/2021_06_30_173111_create_mfa_values_table.php +++ b/database/migrations/2021_06_30_173111_create_mfa_values_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('mfa_values', function (Blueprint $table) { $table->increments('id'); @@ -24,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('mfa_values'); } diff --git a/database/migrations/2021_07_03_085038_add_mfa_enforced_to_roles_table.php b/database/migrations/2021_07_03_085038_add_mfa_enforced_to_roles_table.php index 8a180f088..b8f8b1cff 100644 --- a/database/migrations/2021_07_03_085038_add_mfa_enforced_to_roles_table.php +++ b/database/migrations/2021_07_03_085038_add_mfa_enforced_to_roles_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('roles', function (Blueprint $table) { $table->boolean('mfa_enforced'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('roles', function (Blueprint $table) { $table->dropColumn('mfa_enforced'); diff --git a/database/migrations/2021_08_28_161743_add_export_role_permission.php b/database/migrations/2021_08_28_161743_add_export_role_permission.php index 3bacab20b..21f45aa06 100644 --- a/database/migrations/2021_08_28_161743_add_export_role_permission.php +++ b/database/migrations/2021_08_28_161743_add_export_role_permission.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Create new templates-manage permission and assign to admin role $roles = DB::table('roles')->get('id'); @@ -34,10 +32,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Remove content-export permission $contentExportPermission = DB::table('role_permissions') diff --git a/database/migrations/2021_09_26_044614_add_activities_ip_column.php b/database/migrations/2021_09_26_044614_add_activities_ip_column.php index 5f8a95002..6c21f4b26 100644 --- a/database/migrations/2021_09_26_044614_add_activities_ip_column.php +++ b/database/migrations/2021_09_26_044614_add_activities_ip_column.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('activities', function (Blueprint $table) { $table->string('ip', 45)->after('user_id'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('activities', function (Blueprint $table) { $table->dropColumn('ip'); diff --git a/database/migrations/2021_11_26_070438_add_index_for_user_ip.php b/database/migrations/2021_11_26_070438_add_index_for_user_ip.php index 564e68a6d..9a0171bde 100644 --- a/database/migrations/2021_11_26_070438_add_index_for_user_ip.php +++ b/database/migrations/2021_11_26_070438_add_index_for_user_ip.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('activities', function (Blueprint $table) { $table->index('ip', 'activities_ip_index'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('activities', function (Blueprint $table) { $table->dropIndex('activities_ip_index'); diff --git a/database/migrations/2021_12_07_111343_create_webhooks_table.php b/database/migrations/2021_12_07_111343_create_webhooks_table.php index 15d4851d6..69be2273d 100644 --- a/database/migrations/2021_12_07_111343_create_webhooks_table.php +++ b/database/migrations/2021_12_07_111343_create_webhooks_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('webhooks', function (Blueprint $table) { $table->increments('id'); @@ -37,10 +35,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('webhooks'); Schema::dropIfExists('webhook_tracked_events'); diff --git a/database/migrations/2021_12_13_152024_create_jobs_table.php b/database/migrations/2021_12_13_152024_create_jobs_table.php index a786a8910..6098d9b12 100644 --- a/database/migrations/2021_12_13_152024_create_jobs_table.php +++ b/database/migrations/2021_12_13_152024_create_jobs_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('jobs', function (Blueprint $table) { $table->bigIncrements('id'); @@ -26,10 +24,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('jobs'); } diff --git a/database/migrations/2021_12_13_152120_create_failed_jobs_table.php b/database/migrations/2021_12_13_152120_create_failed_jobs_table.php index 17191986b..249da8171 100644 --- a/database/migrations/2021_12_13_152120_create_failed_jobs_table.php +++ b/database/migrations/2021_12_13_152120_create_failed_jobs_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('failed_jobs', function (Blueprint $table) { $table->id(); @@ -26,10 +24,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('failed_jobs'); } diff --git a/database/migrations/2022_01_03_154041_add_webhooks_timeout_error_columns.php b/database/migrations/2022_01_03_154041_add_webhooks_timeout_error_columns.php index cb26fa26a..968568d33 100644 --- a/database/migrations/2022_01_03_154041_add_webhooks_timeout_error_columns.php +++ b/database/migrations/2022_01_03_154041_add_webhooks_timeout_error_columns.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('webhooks', function (Blueprint $table) { $table->unsignedInteger('timeout')->default(3); @@ -23,10 +21,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('webhooks', function (Blueprint $table) { $table->dropColumn('timeout'); diff --git a/database/migrations/2022_04_17_101741_add_editor_change_field_and_permission.php b/database/migrations/2022_04_17_101741_add_editor_change_field_and_permission.php index 17ed0fba0..568e26512 100644 --- a/database/migrations/2022_04_17_101741_add_editor_change_field_and_permission.php +++ b/database/migrations/2022_04_17_101741_add_editor_change_field_and_permission.php @@ -10,10 +10,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Add the new 'editor' column to the pages table Schema::table('pages', function (Blueprint $table) { @@ -46,10 +44,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Drop the new column from the pages table Schema::table('pages', function (Blueprint $table) { diff --git a/database/migrations/2022_04_25_140741_update_polymorphic_types.php b/database/migrations/2022_04_25_140741_update_polymorphic_types.php index 2ec45e7d1..00e1e0688 100644 --- a/database/migrations/2022_04_25_140741_update_polymorphic_types.php +++ b/database/migrations/2022_04_25_140741_update_polymorphic_types.php @@ -32,10 +32,8 @@ return new class extends Migration /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { foreach ($this->columnsByTable as $table => $column) { foreach ($this->changeMap as $oldVal => $newVal) { @@ -48,10 +46,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { foreach ($this->columnsByTable as $table => $column) { foreach ($this->changeMap as $oldVal => $newVal) { diff --git a/database/migrations/2022_07_16_170051_drop_joint_permission_type.php b/database/migrations/2022_07_16_170051_drop_joint_permission_type.php index ac52af2a6..a05290e8a 100644 --- a/database/migrations/2022_07_16_170051_drop_joint_permission_type.php +++ b/database/migrations/2022_07_16_170051_drop_joint_permission_type.php @@ -9,10 +9,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { DB::table('joint_permissions') ->where('action', '!=', 'view') @@ -27,10 +25,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('joint_permissions', function (Blueprint $table) { $table->string('action'); diff --git a/database/migrations/2022_08_17_092941_create_references_table.php b/database/migrations/2022_08_17_092941_create_references_table.php index 4b688c43e..e2580289d 100644 --- a/database/migrations/2022_08_17_092941_create_references_table.php +++ b/database/migrations/2022_08_17_092941_create_references_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('references', function (Blueprint $table) { $table->id(); @@ -24,10 +22,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('references'); } diff --git a/database/migrations/2022_09_02_082910_fix_shelf_cover_image_types.php b/database/migrations/2022_09_02_082910_fix_shelf_cover_image_types.php index b8c23671d..aecb4bca3 100644 --- a/database/migrations/2022_09_02_082910_fix_shelf_cover_image_types.php +++ b/database/migrations/2022_09_02_082910_fix_shelf_cover_image_types.php @@ -7,10 +7,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // This updates the 'type' field for images, uploaded as shelf cover images, // to be cover_bookshelf instead of cover_book. @@ -32,10 +30,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { DB::table('images') ->where('type', '=', 'cover_bookshelf') diff --git a/database/migrations/2022_10_07_091406_flatten_entity_permissions_table.php b/database/migrations/2022_10_07_091406_flatten_entity_permissions_table.php index f1072102f..a086796e9 100644 --- a/database/migrations/2022_10_07_091406_flatten_entity_permissions_table.php +++ b/database/migrations/2022_10_07_091406_flatten_entity_permissions_table.php @@ -10,10 +10,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Remove entries for non-existing roles (Caused by previous lack of deletion handling) $roleIds = DB::table('roles')->pluck('id'); @@ -63,10 +61,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Create old table structure for entity_permissions Schema::create('old_entity_permissions', function (Blueprint $table) { diff --git a/database/migrations/2022_10_08_104202_drop_entity_restricted_field.php b/database/migrations/2022_10_08_104202_drop_entity_restricted_field.php index b2987674d..8e45d9ea5 100644 --- a/database/migrations/2022_10_08_104202_drop_entity_restricted_field.php +++ b/database/migrations/2022_10_08_104202_drop_entity_restricted_field.php @@ -11,10 +11,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Remove entity-permissions on non-restricted entities $deleteInactiveEntityPermissions = function (string $table, string $morphClass) { @@ -61,10 +59,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { // Create restricted columns $createRestrictedColumn = fn(Blueprint $table) => $table->boolean('restricted')->index()->default(0); diff --git a/database/migrations/2023_01_24_104625_refactor_joint_permissions_storage.php b/database/migrations/2023_01_24_104625_refactor_joint_permissions_storage.php index 53994c52b..0e25c1d60 100644 --- a/database/migrations/2023_01_24_104625_refactor_joint_permissions_storage.php +++ b/database/migrations/2023_01_24_104625_refactor_joint_permissions_storage.php @@ -10,10 +10,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Truncate before schema changes to avoid performance issues // since we'll need to rebuild anyway. @@ -34,10 +32,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { DB::table('joint_permissions')->truncate(); diff --git a/database/migrations/2023_01_28_141230_copy_color_settings_for_dark_mode.php b/database/migrations/2023_01_28_141230_copy_color_settings_for_dark_mode.php index 5187dabf4..6f137eca7 100644 --- a/database/migrations/2023_01_28_141230_copy_color_settings_for_dark_mode.php +++ b/database/migrations/2023_01_28_141230_copy_color_settings_for_dark_mode.php @@ -7,10 +7,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { $colorSettings = [ 'app-color', @@ -45,10 +43,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $colorSettings = [ 'app-color-dark', diff --git a/database/migrations/2023_02_20_093655_increase_attachments_path_length.php b/database/migrations/2023_02_20_093655_increase_attachments_path_length.php index f7cb64ce6..b2a81d49e 100644 --- a/database/migrations/2023_02_20_093655_increase_attachments_path_length.php +++ b/database/migrations/2023_02_20_093655_increase_attachments_path_length.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('attachments', function (Blueprint $table) { $table->text('path')->change(); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('attachments', function (Blueprint $table) { $table->string('path')->change(); diff --git a/database/migrations/2023_02_23_200227_add_updated_at_index_to_pages.php b/database/migrations/2023_02_23_200227_add_updated_at_index_to_pages.php index 115bbb0c0..c3dc3fb0a 100644 --- a/database/migrations/2023_02_23_200227_add_updated_at_index_to_pages.php +++ b/database/migrations/2023_02_23_200227_add_updated_at_index_to_pages.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('pages', function (Blueprint $table) { $table->index('updated_at', 'pages_updated_at_index'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('pages', function (Blueprint $table) { $table->dropIndex('pages_updated_at_index'); diff --git a/database/migrations/2023_06_10_071823_remove_guest_user_secondary_roles.php b/database/migrations/2023_06_10_071823_remove_guest_user_secondary_roles.php index 8d04efdd9..05f6be4a1 100644 --- a/database/migrations/2023_06_10_071823_remove_guest_user_secondary_roles.php +++ b/database/migrations/2023_06_10_071823_remove_guest_user_secondary_roles.php @@ -7,10 +7,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { $guestUserId = DB::table('users') ->where('system_name', '=', 'public') @@ -36,8 +34,6 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/database/migrations/2023_06_25_181952_remove_bookshelf_create_entity_permissions.php b/database/migrations/2023_06_25_181952_remove_bookshelf_create_entity_permissions.php index b5dcaee75..540491d3b 100644 --- a/database/migrations/2023_06_25_181952_remove_bookshelf_create_entity_permissions.php +++ b/database/migrations/2023_06_25_181952_remove_bookshelf_create_entity_permissions.php @@ -7,8 +7,6 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -20,8 +18,6 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/database/migrations/2023_07_25_124945_add_receive_notifications_role_permissions.php b/database/migrations/2023_07_25_124945_add_receive_notifications_role_permissions.php index 4872e421e..79e45a762 100644 --- a/database/migrations/2023_07_25_124945_add_receive_notifications_role_permissions.php +++ b/database/migrations/2023_07_25_124945_add_receive_notifications_role_permissions.php @@ -2,15 +2,14 @@ use Carbon\Carbon; use Illuminate\Database\Migrations\Migration; +use Illuminate\Support\Facades\DB; return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { // Create new receive-notifications permission and assign to admin role $permissionId = DB::table('role_permissions')->insertGetId([ @@ -29,10 +28,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $permission = DB::table('role_permissions') ->where('name', '=', 'receive-notifications') diff --git a/database/migrations/2023_07_31_104430_create_watches_table.php b/database/migrations/2023_07_31_104430_create_watches_table.php index e2a5c20d0..cf2c7f105 100644 --- a/database/migrations/2023_07_31_104430_create_watches_table.php +++ b/database/migrations/2023_07_31_104430_create_watches_table.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('watches', function (Blueprint $table) { $table->increments('id'); @@ -27,10 +25,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('watches'); } diff --git a/database/migrations/2023_08_21_174248_increase_cache_size.php b/database/migrations/2023_08_21_174248_increase_cache_size.php index 865472c2e..bca7f9fc3 100644 --- a/database/migrations/2023_08_21_174248_increase_cache_size.php +++ b/database/migrations/2023_08_21_174248_increase_cache_size.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('cache', function (Blueprint $table) { $table->mediumText('value')->change(); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('cache', function (Blueprint $table) { $table->text('value')->change(); diff --git a/database/migrations/2023_12_02_104541_add_default_template_to_books.php b/database/migrations/2023_12_02_104541_add_default_template_to_books.php index c23bebc2e..bfc480a2e 100644 --- a/database/migrations/2023_12_02_104541_add_default_template_to_books.php +++ b/database/migrations/2023_12_02_104541_add_default_template_to_books.php @@ -8,10 +8,8 @@ class AddDefaultTemplateToBooks extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('books', function (Blueprint $table) { $table->integer('default_template_id')->nullable()->default(null); @@ -20,10 +18,8 @@ class AddDefaultTemplateToBooks extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('books', function (Blueprint $table) { $table->dropColumn('default_template_id'); diff --git a/database/migrations/2023_12_17_140913_add_description_html_to_entities.php b/database/migrations/2023_12_17_140913_add_description_html_to_entities.php index 68c52e81b..781197e60 100644 --- a/database/migrations/2023_12_17_140913_add_description_html_to_entities.php +++ b/database/migrations/2023_12_17_140913_add_description_html_to_entities.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { $addColumn = fn(Blueprint $table) => $table->text('description_html'); @@ -22,10 +20,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { $removeColumn = fn(Blueprint $table) => $table->removeColumn('description_html'); diff --git a/database/migrations/2024_01_01_104542_add_default_template_to_chapters.php b/database/migrations/2024_01_01_104542_add_default_template_to_chapters.php index b3a103a01..77df82272 100644 --- a/database/migrations/2024_01_01_104542_add_default_template_to_chapters.php +++ b/database/migrations/2024_01_01_104542_add_default_template_to_chapters.php @@ -8,10 +8,8 @@ class AddDefaultTemplateToChapters extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('chapters', function (Blueprint $table) { $table->integer('default_template_id')->nullable()->default(null); @@ -20,10 +18,8 @@ class AddDefaultTemplateToChapters extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('chapters', function (Blueprint $table) { $table->dropColumn('default_template_id'); diff --git a/database/migrations/2024_02_04_141358_add_views_updated_index.php b/database/migrations/2024_02_04_141358_add_views_updated_index.php index a643b3a1e..bc7538678 100644 --- a/database/migrations/2024_02_04_141358_add_views_updated_index.php +++ b/database/migrations/2024_02_04_141358_add_views_updated_index.php @@ -8,10 +8,8 @@ return new class extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::table('views', function (Blueprint $table) { $table->index(['updated_at'], 'views_updated_at_index'); @@ -20,10 +18,8 @@ return new class extends Migration /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::table('views', function (Blueprint $table) { $table->dropIndex('views_updated_at_index'); From 3250fc732c74ae09566a48da2739c3f5e450665f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Mar 2024 15:41:11 +0000 Subject: [PATCH 08/59] Testing: Updated PHPUnit from 9 to 10 For #4903 --- composer.json | 6 +- composer.lock | 669 +++++++++++++++++++++----------------------------- phpunit.xml | 15 +- 3 files changed, 289 insertions(+), 401 deletions(-) diff --git a/composer.json b/composer.json index f58c2c9dd..7a39c41b2 100644 --- a/composer.json +++ b/composer.json @@ -45,11 +45,11 @@ "fakerphp/faker": "^1.21", "itsgoingd/clockwork": "^5.1", "mockery/mockery": "^1.5", - "nunomaduro/collision": "^6.4", + "nunomaduro/collision": "^7.0", "larastan/larastan": "^2.7", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.0", "squizlabs/php_codesniffer": "^3.7", - "ssddanbrown/asserthtml": "^2.0" + "ssddanbrown/asserthtml": "^3.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 0edbd79bd..9738b9117 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "df0a9795e5dd228d680cabf1f34d3aa6", + "content-hash": "5c83a032875be7a7edcfd5a18264ac7d", "packages": [ { "name": "aws/aws-crt-php", @@ -4820,16 +4820,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.1", + "version": "v0.12.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "39621c73e0754328252f032c6997b983afc50431" + "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/39621c73e0754328252f032c6997b983afc50431", - "reference": "39621c73e0754328252f032c6997b983afc50431", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/9185c66c2165bbf4d71de78a69dccf4974f9538d", + "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d", "shasum": "" }, "require": { @@ -4893,9 +4893,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.1" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.2" }, - "time": "2024-03-15T03:22:57+00:00" + "time": "2024-03-17T01:53:00+00:00" }, { "name": "ralouphie/getallheaders", @@ -8078,76 +8078,6 @@ } ], "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, { "name": "fakerphp/faker", "version": "v1.23.1", @@ -8654,38 +8584,43 @@ }, { "name": "nunomaduro/collision", - "version": "v6.4.0", + "version": "v7.10.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015" + "reference": "49ec67fa7b002712da8526678abd651c09f375b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f05978827b9343cba381ca05b8c7deee346b6015", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2", "shasum": "" }, "require": { - "filp/whoops": "^2.14.5", - "php": "^8.0.0", - "symfony/console": "^6.0.2" + "filp/whoops": "^2.15.3", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.3.4" + }, + "conflict": { + "laravel/framework": ">=11.0.0" }, "require-dev": { - "brianium/paratest": "^6.4.1", - "laravel/framework": "^9.26.1", - "laravel/pint": "^1.1.1", - "nunomaduro/larastan": "^1.0.3", - "nunomaduro/mock-final-classes": "^1.1.0", - "orchestra/testbench": "^7.7", - "phpunit/phpunit": "^9.5.23", - "spatie/ignition": "^1.4.1" + "brianium/paratest": "^7.3.0", + "laravel/framework": "^10.28.0", + "laravel/pint": "^1.13.3", + "laravel/sail": "^1.25.0", + "laravel/sanctum": "^3.3.1", + "laravel/tinker": "^2.8.2", + "nunomaduro/larastan": "^2.6.4", + "orchestra/testbench-core": "^8.13.0", + "pestphp/pest": "^2.23.2", + "phpunit/phpunit": "^10.4.1", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.3.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-develop": "6.x-dev" - }, "laravel": { "providers": [ "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" @@ -8693,6 +8628,9 @@ } }, "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], "psr-4": { "NunoMaduro\\Collision\\": "src/" } @@ -8738,7 +8676,7 @@ "type": "patreon" } ], - "time": "2023-01-03T12:54:54+00:00" + "time": "2023-10-11T15:45:01+00:00" }, { "name": "phar-io/manifest", @@ -9010,16 +8948,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "10.1.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", + "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", "shasum": "" }, "require": { @@ -9027,18 +8965,18 @@ "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -9047,7 +8985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "10.1-dev" } }, "autoload": { @@ -9076,7 +9014,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.14" }, "funding": [ { @@ -9084,32 +9022,32 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-03-12T15:33:41+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -9136,7 +9074,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -9144,28 +9083,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -9173,7 +9112,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -9199,7 +9138,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -9207,32 +9146,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -9258,7 +9197,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -9266,32 +9206,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9317,7 +9257,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -9325,24 +9265,23 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.17", + "version": "10.5.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" + "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7", + "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -9352,27 +9291,26 @@ "myclabs/deep-copy": "^1.10.1", "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -9380,7 +9318,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -9412,7 +9350,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13" }, "funding": [ { @@ -9428,32 +9366,32 @@ "type": "tidelift" } ], - "time": "2024-02-23T13:14:51+00:00" + "time": "2024-03-12T15:37:41+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -9476,7 +9414,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -9484,32 +9423,32 @@ "type": "github" } ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -9532,7 +9471,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -9540,32 +9479,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -9587,7 +9526,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -9595,34 +9534,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -9661,7 +9602,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" }, "funding": [ { @@ -9669,33 +9611,33 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2023-08-14T13:18:12+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -9718,7 +9660,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -9726,33 +9669,33 @@ "type": "github" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -9784,7 +9727,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -9792,27 +9736,27 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -9820,7 +9764,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9839,7 +9783,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -9847,7 +9791,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" }, "funding": [ { @@ -9855,34 +9800,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2023-04-11T05:39:26+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -9924,7 +9869,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { @@ -9932,38 +9878,35 @@ "type": "github" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9982,13 +9925,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -9996,33 +9940,33 @@ "type": "github" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -10045,7 +9989,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -10053,34 +9998,34 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10102,7 +10047,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -10110,32 +10055,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -10157,7 +10102,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -10165,32 +10110,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10220,7 +10165,7 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { @@ -10228,86 +10173,32 @@ "type": "github" } ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -10330,7 +10221,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -10338,29 +10229,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -10383,7 +10274,7 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -10391,7 +10282,7 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -10475,28 +10366,28 @@ }, { "name": "ssddanbrown/asserthtml", - "version": "v2.0.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/ssddanbrown/asserthtml.git", - "reference": "6baf3ef2087f5928ae34f0d41db27aefcdf60414" + "reference": "a2cf9394dfc4138b8d9691e1bd128ccc3d8fcc5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ssddanbrown/asserthtml/zipball/6baf3ef2087f5928ae34f0d41db27aefcdf60414", - "reference": "6baf3ef2087f5928ae34f0d41db27aefcdf60414", + "url": "https://api.github.com/repos/ssddanbrown/asserthtml/zipball/a2cf9394dfc4138b8d9691e1bd128ccc3d8fcc5d", + "reference": "a2cf9394dfc4138b8d9691e1bd128ccc3d8fcc5d", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "php": ">=7.4", - "phpunit/phpunit": "^9.0", - "symfony/css-selector": "^5.0|^6.0", - "symfony/dom-crawler": "^5.0|^6.0" + "php": ">=8.1", + "phpunit/phpunit": "^10.0", + "symfony/css-selector": "^6.0", + "symfony/dom-crawler": "^6.0" }, "require-dev": { - "vimeo/psalm": "^4.10" + "phpstan/phpstan": "^1.10" }, "type": "library", "autoload": { @@ -10511,7 +10402,7 @@ "authors": [ { "name": "Dan Brown", - "email": "ssddanbrown@googlemail.com", + "homepage": "https://danb.me", "role": "Developer" } ], @@ -10519,7 +10410,7 @@ "homepage": "https://github.com/ssddanbrown/asserthtml", "support": { "issues": "https://github.com/ssddanbrown/asserthtml/issues", - "source": "https://github.com/ssddanbrown/asserthtml/tree/v2.0.0" + "source": "https://github.com/ssddanbrown/asserthtml/tree/v3.0.0" }, "funding": [ { @@ -10527,7 +10418,7 @@ "type": "github" } ], - "time": "2023-03-01T16:48:08+00:00" + "time": "2023-05-11T14:26:12+00:00" }, { "name": "symfony/dom-crawler", diff --git a/phpunit.xml b/phpunit.xml index 183e45637..a9e97f0c7 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,13 +1,5 @@ - - - - app/ - - + ./tests/ @@ -62,4 +54,9 @@ + + + app/ + + From 2345fd46777828cd81919f4e230a1d74ab835add Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Mar 2024 16:03:12 +0000 Subject: [PATCH 09/59] Deps: Updated intervention library from 2 to 3 Major version change, required some changes to API For #4903 --- app/Uploads/ImageResizer.php | 27 ++++--- composer.json | 2 +- composer.lock | 134 ++++++++++++++++++++++++----------- 3 files changed, 111 insertions(+), 52 deletions(-) diff --git a/app/Uploads/ImageResizer.php b/app/Uploads/ImageResizer.php index 4dc1b0b99..d09177fff 100644 --- a/app/Uploads/ImageResizer.php +++ b/app/Uploads/ImageResizer.php @@ -6,8 +6,12 @@ use BookStack\Exceptions\ImageUploadException; use Exception; use GuzzleHttp\Psr7\Utils; use Illuminate\Support\Facades\Cache; -use Intervention\Image\Gd\Driver; -use Intervention\Image\Image as InterventionImage; +use Intervention\Image\Decoders\BinaryImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; +use Intervention\Image\Encoders\AutoEncoder; +use Intervention\Image\Encoders\PngEncoder; +use Intervention\Image\Interfaces\ImageInterface as InterventionImage; +use Intervention\Image\ImageManager; class ImageResizer { @@ -124,15 +128,17 @@ class ImageResizer $this->orientImageToOriginalExif($thumb, $imageData); if ($keepRatio) { - $thumb->resize($width, $height, function ($constraint) { - $constraint->aspectRatio(); - $constraint->upsize(); - }); + $thumb->scaleDown($width, $height); } else { - $thumb->fit($width, $height); + $thumb->cover($width, $height); } - $thumbData = (string) $thumb->encode($format); + $encoder = match ($format) { + 'png' => new PngEncoder(), + default => new AutoEncoder(), + }; + + $thumbData = (string) $thumb->encode($encoder); // Use original image data if we're keeping the ratio // and the resizing does not save any space. @@ -150,8 +156,9 @@ class ImageResizer */ protected function interventionFromImageData(string $imageData): InterventionImage { - $driver = new Driver(); - return $driver->decoder->initFromBinary($imageData); + $manager = new ImageManager(new Driver()); + + return $manager->read($imageData, BinaryImageDecoder::class); } /** diff --git a/composer.json b/composer.json index 7a39c41b2..2dce05d38 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "barryvdh/laravel-snappy": "^1.0", "doctrine/dbal": "^3.5", "guzzlehttp/guzzle": "^7.4", - "intervention/image": "^2.7", + "intervention/image": "^3.5", "laravel/framework": "^10.10", "laravel/socialite": "^5.10", "laravel/tinker": "^2.8", diff --git a/composer.lock b/composer.lock index 9738b9117..be9190b1c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5c83a032875be7a7edcfd5a18264ac7d", + "content-hash": "e05f9f4344c239682f6a9fbab0f87cf0", "packages": [ { "name": "aws/aws-crt-php", @@ -1860,50 +1860,32 @@ "time": "2023-12-03T19:50:20+00:00" }, { - "name": "intervention/image", - "version": "2.7.2", + "name": "intervention/gif", + "version": "4.0.2", "source": { "type": "git", - "url": "https://github.com/Intervention/image.git", - "reference": "04be355f8d6734c826045d02a1079ad658322dad" + "url": "https://github.com/Intervention/gif.git", + "reference": "c2b07d1f69709e196c8b4ced423449a7e0f3b925" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad", - "reference": "04be355f8d6734c826045d02a1079ad658322dad", + "url": "https://api.github.com/repos/Intervention/gif/zipball/c2b07d1f69709e196c8b4ced423449a7e0f3b925", + "reference": "c2b07d1f69709e196c8b4ced423449a7e0f3b925", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "guzzlehttp/psr7": "~1.1 || ^2.0", - "php": ">=5.4.0" + "php": "^8.1" }, "require-dev": { - "mockery/mockery": "~0.9.2", - "phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15" - }, - "suggest": { - "ext-gd": "to use GD library based image processing.", - "ext-imagick": "to use Imagick based image processing.", - "intervention/imagecache": "Caching extension for the Intervention Image library" + "phpstan/phpstan": "^1", + "phpunit/phpunit": "^9", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - }, - "laravel": { - "providers": [ - "Intervention\\Image\\ImageServiceProvider" - ], - "aliases": { - "Image": "Intervention\\Image\\Facades\\Image" - } - } - }, "autoload": { "psr-4": { - "Intervention\\Image\\": "src/Intervention/Image" + "Intervention\\Gif\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1917,19 +1899,17 @@ "homepage": "https://intervention.io/" } ], - "description": "Image handling and manipulation library with support for Laravel integration", - "homepage": "http://image.intervention.io/", + "description": "Native PHP GIF Encoder/Decoder", + "homepage": "https://github.com/intervention/gif", "keywords": [ + "animation", "gd", - "image", - "imagick", - "laravel", - "thumbnail", - "watermark" + "gif", + "image" ], "support": { - "issues": "https://github.com/Intervention/image/issues", - "source": "https://github.com/Intervention/image/tree/2.7.2" + "issues": "https://github.com/Intervention/gif/issues", + "source": "https://github.com/Intervention/gif/tree/4.0.2" }, "funding": [ { @@ -1941,7 +1921,79 @@ "type": "github" } ], - "time": "2022-05-21T17:30:32+00:00" + "time": "2024-02-18T15:36:58+00:00" + }, + { + "name": "intervention/image", + "version": "3.5.0", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "408d3655c7705339e8c79731ea7efb51546cfa10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/408d3655c7705339e8c79731ea7efb51546cfa10", + "reference": "408d3655c7705339e8c79731ea7efb51546cfa10", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "intervention/gif": "^4.0.1", + "php": "^8.1" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "phpstan/phpstan": "^1", + "phpunit/phpunit": "^10.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "suggest": { + "ext-exif": "Recommended to be able to read EXIF data properly." + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "PHP image manipulation", + "homepage": "https://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "resize", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/3.5.0" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + } + ], + "time": "2024-03-13T16:26:15+00:00" }, { "name": "knplabs/knp-snappy", From b4b84f81a0f5a85cf0a37a870d46d02c9ca84c98 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Mar 2024 16:32:59 +0000 Subject: [PATCH 10/59] Deps: Updated custom symfony/mailer package Done during #4903 work --- composer.json | 2 +- composer.lock | 35 ++++++++++++++++++++--------------- tests/Unit/ConfigTest.php | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 2dce05d38..79246b7ac 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "socialiteproviders/okta": "^4.2", "socialiteproviders/twitch": "^5.3", "ssddanbrown/htmldiff": "^1.0.2", - "ssddanbrown/symfony-mailer": "6.0.x-dev" + "ssddanbrown/symfony-mailer": "6.4.x-dev" }, "require-dev": { "fakerphp/faker": "^1.21", diff --git a/composer.lock b/composer.lock index be9190b1c..24c2215dd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e05f9f4344c239682f6a9fbab0f87cf0", + "content-hash": "ccfc07d0ecc580962915a0457f0466a7", "packages": [ { "name": "aws/aws-crt-php", @@ -5643,38 +5643,43 @@ }, { "name": "ssddanbrown/symfony-mailer", - "version": "6.0.x-dev", + "version": "6.4.x-dev", "source": { "type": "git", "url": "https://github.com/ssddanbrown/symfony-mailer.git", - "reference": "2219dcdc5f58e4f382ce8f1e6942d16982aa3012" + "reference": "0497d6eb2734fe22b9550f88ae6526611c9df7ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ssddanbrown/symfony-mailer/zipball/2219dcdc5f58e4f382ce8f1e6942d16982aa3012", - "reference": "2219dcdc5f58e4f382ce8f1e6942d16982aa3012", + "url": "https://api.github.com/repos/ssddanbrown/symfony-mailer/zipball/0497d6eb2734fe22b9550f88ae6526611c9df7ae", + "reference": "0497d6eb2734fe22b9550f88ae6526611c9df7ae", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/http-kernel": "<5.4" + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "replace": { "symfony/mailer": "^6.0" }, "require-dev": { - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -5705,9 +5710,9 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/ssddanbrown/symfony-mailer/tree/6.0" + "source": "https://github.com/ssddanbrown/symfony-mailer/tree/6.4" }, - "time": "2023-07-04T14:10:33+00:00" + "time": "2024-03-17T16:25:21+00:00" }, { "name": "symfony/console", diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index 2de32c1b8..aedcb75aa 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -132,7 +132,7 @@ class ConfigTest extends TestCase public function test_smtp_scheme_and_certain_port_forces_tls_usage() { $isMailTlsRequired = function () { - /** @var \BookStack\App\Mail\EsmtpTransport $transport */ + /** @var EsmtpTransport $transport */ $transport = Mail::mailer('smtp')->getSymfonyTransport(); Mail::purge('smtp'); return $transport->getTlsRequirement(); From 28d6292278b9ce2ab728e62a2b622a0beee62c1c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Mar 2024 16:52:19 +0000 Subject: [PATCH 11/59] Framework: Addressed deprecations --- app/Access/Controllers/MfaTotpController.php | 17 ++++++---- app/Access/Mfa/TotpValidationRule.php | 34 +++++++------------ .../2015_08_31_175240_add_search_indexes.php | 6 ++-- .../2015_12_05_145049_fulltext_weighting.php | 6 ++-- ...03_19_091553_create_search_index_table.php | 6 ++-- 5 files changed, 32 insertions(+), 37 deletions(-) diff --git a/app/Access/Controllers/MfaTotpController.php b/app/Access/Controllers/MfaTotpController.php index f60644b84..5202fedc0 100644 --- a/app/Access/Controllers/MfaTotpController.php +++ b/app/Access/Controllers/MfaTotpController.php @@ -19,20 +19,25 @@ class MfaTotpController extends Controller protected const SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret'; + public function __construct( + protected TotpService $totp + ) { + } + /** * Show a view that generates and displays a TOTP QR code. */ - public function generate(TotpService $totp) + public function generate() { if (session()->has(static::SETUP_SECRET_SESSION_KEY)) { $totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY)); } else { - $totpSecret = $totp->generateSecret(); + $totpSecret = $this->totp->generateSecret(); session()->put(static::SETUP_SECRET_SESSION_KEY, encrypt($totpSecret)); } - $qrCodeUrl = $totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser()); - $svg = $totp->generateQrCodeSvg($qrCodeUrl); + $qrCodeUrl = $this->totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser()); + $svg = $this->totp->generateQrCodeSvg($qrCodeUrl); $this->setPageTitle(trans('auth.mfa_gen_totp_title')); @@ -56,7 +61,7 @@ class MfaTotpController extends Controller 'code' => [ 'required', 'max:12', 'min:4', - new TotpValidationRule($totpSecret), + new TotpValidationRule($totpSecret, $this->totp), ], ]); @@ -87,7 +92,7 @@ class MfaTotpController extends Controller 'code' => [ 'required', 'max:12', 'min:4', - new TotpValidationRule($totpSecret), + new TotpValidationRule($totpSecret, $this->totp), ], ]); diff --git a/app/Access/Mfa/TotpValidationRule.php b/app/Access/Mfa/TotpValidationRule.php index c38bde90b..63b575f19 100644 --- a/app/Access/Mfa/TotpValidationRule.php +++ b/app/Access/Mfa/TotpValidationRule.php @@ -2,36 +2,26 @@ namespace BookStack\Access\Mfa; -use Illuminate\Contracts\Validation\Rule; +use Closure; +use Illuminate\Contracts\Validation\ValidationRule; -class TotpValidationRule implements Rule +class TotpValidationRule implements ValidationRule { - protected $secret; - protected $totpService; - /** * Create a new rule instance. * Takes the TOTP secret that must be system provided, not user provided. */ - public function __construct(string $secret) - { - $this->secret = $secret; - $this->totpService = app()->make(TotpService::class); + public function __construct( + protected string $secret, + protected TotpService $totpService, + ) { } - /** - * Determine if the validation rule passes. - */ - public function passes($attribute, $value) + public function validate(string $attribute, mixed $value, Closure $fail): void { - return $this->totpService->verifyCode($value, $this->secret); - } - - /** - * Get the validation error message. - */ - public function message() - { - return trans('validation.totp'); + $passes = $this->totpService->verifyCode($value, $this->secret); + if (!$passes) { + $fail(trans('validation.totp')); + } } } diff --git a/database/migrations/2015_08_31_175240_add_search_indexes.php b/database/migrations/2015_08_31_175240_add_search_indexes.php index 4e0421e9e..3382b2d54 100644 --- a/database/migrations/2015_08_31_175240_add_search_indexes.php +++ b/database/migrations/2015_08_31_175240_add_search_indexes.php @@ -26,9 +26,9 @@ return new class extends Migration public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->listTableDetails('pages'); - $books = $sm->listTableDetails('books'); - $chapters = $sm->listTableDetails('chapters'); + $pages = $sm->introspectTable('pages'); + $books = $sm->introspectTable('books'); + $chapters = $sm->introspectTable('chapters'); if ($pages->hasIndex('search')) { Schema::table('pages', function (Blueprint $table) { diff --git a/database/migrations/2015_12_05_145049_fulltext_weighting.php b/database/migrations/2015_12_05_145049_fulltext_weighting.php index 7f9d2373c..33163e854 100644 --- a/database/migrations/2015_12_05_145049_fulltext_weighting.php +++ b/database/migrations/2015_12_05_145049_fulltext_weighting.php @@ -26,9 +26,9 @@ return new class extends Migration public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->listTableDetails('pages'); - $books = $sm->listTableDetails('books'); - $chapters = $sm->listTableDetails('chapters'); + $pages = $sm->introspectTable('pages'); + $books = $sm->introspectTable('books'); + $chapters = $sm->introspectTable('chapters'); if ($pages->hasIndex('name_search')) { Schema::table('pages', function (Blueprint $table) { diff --git a/database/migrations/2017_03_19_091553_create_search_index_table.php b/database/migrations/2017_03_19_091553_create_search_index_table.php index 72be3ccbe..71f93fa2d 100644 --- a/database/migrations/2017_03_19_091553_create_search_index_table.php +++ b/database/migrations/2017_03_19_091553_create_search_index_table.php @@ -25,9 +25,9 @@ return new class extends Migration }); $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->listTableDetails('pages'); - $books = $sm->listTableDetails('books'); - $chapters = $sm->listTableDetails('chapters'); + $pages = $sm->introspectTable('pages'); + $books = $sm->introspectTable('books'); + $chapters = $sm->introspectTable('chapters'); if ($pages->hasIndex('search')) { Schema::table('pages', function (Blueprint $table) { From fa5395a02bb81dbb0f600860aca51e14be98cc13 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 18 Mar 2024 14:24:14 +0000 Subject: [PATCH 12/59] Meta: Updated workflows, licence and readme - Updated license year - Updated some readme wording, removed lapsed sponsor, Removed twitter link, added link to alt github source - Update cache action for GH workflows since GH was complaining --- .github/workflows/analyse-php.yml | 6 +++--- .github/workflows/test-migrations.yml | 2 +- .github/workflows/test-php.yml | 2 +- LICENSE | 2 +- readme.md | 14 ++++---------- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.github/workflows/analyse-php.yml b/.github/workflows/analyse-php.yml index 4ddf51932..dbeaf9472 100644 --- a/.github/workflows/analyse-php.yml +++ b/.github/workflows/analyse-php.yml @@ -18,7 +18,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.1 + php-version: 8.3 extensions: gd, mbstring, json, curl, xml, mysql, ldap - name: Get Composer Cache Directory @@ -27,10 +27,10 @@ jobs: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-8.1 + key: ${{ runner.os }}-composer-8.3 restore-keys: ${{ runner.os }}-composer- - name: Install composer dependencies diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index 9b13787f7..10cfbe172 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -32,7 +32,7 @@ jobs: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ matrix.php }} diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml index 53087a82f..269f32632 100644 --- a/.github/workflows/test-php.yml +++ b/.github/workflows/test-php.yml @@ -32,7 +32,7 @@ jobs: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ matrix.php }} diff --git a/LICENSE b/LICENSE index 7727542f4..5ed2edf85 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015-2023, Dan Brown and the BookStack Project contributors. +Copyright (c) 2015-2024, Dan Brown and the BookStack Project contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/readme.md b/readme.md index a32e22931..5457ddfb5 100644 --- a/readme.md +++ b/readme.md @@ -7,10 +7,10 @@ [![Lint Status](https://github.com/BookStackApp/BookStack/workflows/lint-php/badge.svg)](https://github.com/BookStackApp/BookStack/actions) [![Maintainability](https://api.codeclimate.com/v1/badges/5551731994dd22fa1f4f/maintainability)](https://codeclimate.com/github/BookStackApp/BookStack/maintainability) +[![Alternate Source](https://img.shields.io/static/v1?label=Alt+Source&message=Git&color=ef391a&logo=git)](https://source.bookstackapp.com/) [![Repo Stats](https://img.shields.io/static/v1?label=GitHub+project&message=stats&color=f27e3f)](https://gh-stats.bookstackapp.com/) [![Discord](https://img.shields.io/static/v1?label=Discord&message=chat&color=738adb&logo=discord)](https://discord.gg/ztkBqR2) [![Mastodon](https://img.shields.io/static/v1?label=Mastodon&message=@bookstack&color=595aff&logo=mastodon)](https://fosstodon.org/@bookstack) -[![X - Formerly Twitter](https://img.shields.io/static/v1?label=Follow&message=@bookstack_app&color=1d9bf0&logo=x)](https://x.com/bookstack_app) [![PeerTube](https://img.shields.io/static/v1?label=PeerTube&message=bookstack@foss.video&color=f2690d&logo=peertube)](https://foss.video/c/bookstack) [![YouTube](https://img.shields.io/static/v1?label=YouTube&message=bookstackapp&color=ff0000&logo=youtube)](https://www.youtube.com/bookstackapp) @@ -29,12 +29,14 @@ A platform for storing and organising information and documentation. Details for ## 📚 Project Definition -BookStack is an opinionated wiki system that provides a pleasant and simple out-of-the-box experience. New users to an instance should find the experience intuitive and only basic word-processing skills should be required to get involved in creating content on BookStack. The platform should provide advanced power features to those that desire it but they should not interfere with the core simple user experience. +BookStack is an opinionated documentation platform that provides a pleasant and simple out-of-the-box experience. New users to an instance should find the experience intuitive and only basic word-processing skills should be required to get involved in creating content on BookStack. The platform should provide advanced power features to those that desire it but they should not interfere with the core simple user experience. BookStack is not designed as an extensible platform to be used for purposes that differ to the statement above. In regard to development philosophy, BookStack has a relaxed, open & positive approach. At the end of the day this is free software developed and maintained by people donating their own free time. +You can read more about the project and its origins in [our FAQ here](https://www.bookstackapp.com/about/project-faq/). + ## 🌟 Project Sponsors Shown below are our bronze, silver and gold project sponsors. @@ -43,14 +45,6 @@ Big thanks to these companies for supporting the project. [Project donation details](https://www.bookstackapp.com/donate/) - [GitHub Sponsors Page](https://github.com/sponsors/ssddanbrown) - [Ko-fi Page](https://ko-fi.com/ssddanbrown) -#### Gold Sponsor - - - -
- Diagrams.net -
- #### Bronze Sponsors From c221a00e1ed2a01a66072f3f6a270464e12bab3c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 19 Mar 2024 10:30:26 +0000 Subject: [PATCH 13/59] Migrations: Added prefix support to schema inspection --- .../migrations/2015_08_31_175240_add_search_indexes.php | 8 +++++--- .../migrations/2015_12_05_145049_fulltext_weighting.php | 8 +++++--- .../2017_03_19_091553_create_search_index_table.php | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/database/migrations/2015_08_31_175240_add_search_indexes.php b/database/migrations/2015_08_31_175240_add_search_indexes.php index 3382b2d54..4d58d9409 100644 --- a/database/migrations/2015_08_31_175240_add_search_indexes.php +++ b/database/migrations/2015_08_31_175240_add_search_indexes.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -26,9 +27,10 @@ return new class extends Migration public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->introspectTable('pages'); - $books = $sm->introspectTable('books'); - $chapters = $sm->introspectTable('chapters'); + $prefix = DB::getTablePrefix(); + $pages = $sm->introspectTable($prefix . 'pages'); + $books = $sm->introspectTable($prefix . 'books'); + $chapters = $sm->introspectTable($prefix . 'chapters'); if ($pages->hasIndex('search')) { Schema::table('pages', function (Blueprint $table) { diff --git a/database/migrations/2015_12_05_145049_fulltext_weighting.php b/database/migrations/2015_12_05_145049_fulltext_weighting.php index 33163e854..b20c04520 100644 --- a/database/migrations/2015_12_05_145049_fulltext_weighting.php +++ b/database/migrations/2015_12_05_145049_fulltext_weighting.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -26,9 +27,10 @@ return new class extends Migration public function down(): void { $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->introspectTable('pages'); - $books = $sm->introspectTable('books'); - $chapters = $sm->introspectTable('chapters'); + $prefix = DB::getTablePrefix(); + $pages = $sm->introspectTable($prefix . 'pages'); + $books = $sm->introspectTable($prefix . 'books'); + $chapters = $sm->introspectTable($prefix . 'chapters'); if ($pages->hasIndex('name_search')) { Schema::table('pages', function (Blueprint $table) { diff --git a/database/migrations/2017_03_19_091553_create_search_index_table.php b/database/migrations/2017_03_19_091553_create_search_index_table.php index 71f93fa2d..56281741e 100644 --- a/database/migrations/2017_03_19_091553_create_search_index_table.php +++ b/database/migrations/2017_03_19_091553_create_search_index_table.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -25,9 +26,10 @@ return new class extends Migration }); $sm = Schema::getConnection()->getDoctrineSchemaManager(); - $pages = $sm->introspectTable('pages'); - $books = $sm->introspectTable('books'); - $chapters = $sm->introspectTable('chapters'); + $prefix = DB::getTablePrefix(); + $pages = $sm->introspectTable($prefix . 'pages'); + $books = $sm->introspectTable($prefix . 'books'); + $chapters = $sm->introspectTable($prefix . 'chapters'); if ($pages->hasIndex('search')) { Schema::table('pages', function (Blueprint $table) { From f7893598865abe24df04c3fc60e22429818709e3 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 22 Mar 2024 14:44:23 +0000 Subject: [PATCH 14/59] Licensing: Added script to build PHP library licensing information --- dev/licensing/gen-php-licenses | 96 +++ dev/licensing/php-library-licenses.txt | 796 +++++++++++++++++++++++++ 2 files changed, 892 insertions(+) create mode 100644 dev/licensing/gen-php-licenses create mode 100644 dev/licensing/php-library-licenses.txt diff --git a/dev/licensing/gen-php-licenses b/dev/licensing/gen-php-licenses new file mode 100644 index 000000000..0c922e281 --- /dev/null +++ b/dev/licensing/gen-php-licenses @@ -0,0 +1,96 @@ +#!/usr/bin/env php +packages; +$packageOutput = array_map(packageToOutput(...), $packages); + +$licenseInfo = implode($outputSeparator, $packageOutput) . "\n"; +file_put_contents($outputPath, $licenseInfo); + +echo "License information written to {$outputPath}\n"; +echo implode("\n", $warnings); + +function packageToOutput(stdClass $package) : string { + $output = ["{$package->name}"]; + + $licenses = is_array($package->license) ? $package->license : [$package->license]; + $output[] = "License: " . implode(' ', $licenses); + + $licenseFile = findLicenseFile($package->name); + if ($licenseFile) { + $output[] = "License File: {$licenseFile}"; + $copyright = findCopyright($licenseFile); + if ($copyright) { + $output[] = "Copyright: {$copyright}"; + } else { + warn("Package {$package->name} has no copyright found in its license"); + } + } + + $source = $package->source->url; + if ($source) { + $output[] = "Source: {$source}"; + } + + $link = $package->homepage ?? $package->source->url ?? ''; + if ($link) { + $output[] = "Link: {$link}"; + } + + return implode("\n", $output); +} + +function findLicenseFile(string $packageName): string { + global $rootPath; + $licenseNameOptions = ['license', 'LICENSE', 'license.*', 'LICENSE.*']; + + $packagePath = "vendor/{$packageName}"; + $filePath = "{$rootPath}/{$packagePath}"; + + $foundLicenses = []; + foreach ($licenseNameOptions as $option) { + $search = glob("{$filePath}/$option"); + array_push($foundLicenses, ...$search); + } + + if (count($foundLicenses) > 1) { + warn("Package {$packagePath} has more than one license file found"); + } + + if (count($foundLicenses) > 0) { + $fileName = basename($foundLicenses[0]); + return "{$packagePath}/{$fileName}"; + } + + warn("Package {$packageName} has no license files found"); + return ''; +} + +function findCopyright(string $licenseFile): string { + $fileContents = file_get_contents($licenseFile); + $pattern = '/^.*?copyright (\(c\)|\d{4})[\s\S]*?(\n\n|\.\n)/mi'; + $matches = []; + preg_match($pattern, $fileContents, $matches); + $copyright = trim($matches[0] ?? ''); + + $emailPattern = '/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i'; + return preg_replace_callback($emailPattern, obfuscateEmail(...), $copyright); +} + +function obfuscateEmail(array $matches): string { + return preg_replace('/[^@.]/', '*', $matches[1]); +} + +function warn(string $text): void { + global $warnings; + $warnings[] = "WARN:" . $text; +} \ No newline at end of file diff --git a/dev/licensing/php-library-licenses.txt b/dev/licensing/php-library-licenses.txt new file mode 100644 index 000000000..2e78ab845 --- /dev/null +++ b/dev/licensing/php-library-licenses.txt @@ -0,0 +1,796 @@ +aws/aws-crt-php +License: Apache-2.0 +License File: vendor/aws/aws-crt-php/LICENSE +Source: https://github.com/awslabs/aws-crt-php.git +Link: https://github.com/awslabs/aws-crt-php +----------- +aws/aws-sdk-php +License: Apache-2.0 +License File: vendor/aws/aws-sdk-php/LICENSE +Source: https://github.com/aws/aws-sdk-php.git +Link: http://aws.amazon.com/sdkforphp +----------- +bacon/bacon-qr-code +License: BSD-2-Clause +License File: vendor/bacon/bacon-qr-code/LICENSE +Copyright: Copyright (c) 2017, Ben Scholzen 'DASPRiD' +All rights reserved. +Source: https://github.com/Bacon/BaconQrCode.git +Link: https://github.com/Bacon/BaconQrCode +----------- +barryvdh/laravel-dompdf +License: MIT +License File: vendor/barryvdh/laravel-dompdf/LICENSE +Copyright: Copyright (c) 2021 barryvdh +Source: https://github.com/barryvdh/laravel-dompdf.git +Link: https://github.com/barryvdh/laravel-dompdf.git +----------- +barryvdh/laravel-snappy +License: MIT +License File: vendor/barryvdh/laravel-snappy/LICENSE +Copyright: Copyright (c) 2018 +Source: https://github.com/barryvdh/laravel-snappy.git +Link: https://github.com/barryvdh/laravel-snappy.git +----------- +brick/math +License: MIT +License File: vendor/brick/math/LICENSE +Copyright: Copyright (c) 2013-present Benjamin Morel +Source: https://github.com/brick/math.git +Link: https://github.com/brick/math.git +----------- +carbonphp/carbon-doctrine-types +License: MIT +License File: vendor/carbonphp/carbon-doctrine-types/LICENSE +Copyright: Copyright (c) 2023 Carbon +Source: https://github.com/CarbonPHP/carbon-doctrine-types.git +Link: https://github.com/CarbonPHP/carbon-doctrine-types.git +----------- +dasprid/enum +License: BSD-2-Clause +License File: vendor/dasprid/enum/LICENSE +Copyright: Copyright (c) 2017, Ben Scholzen 'DASPRiD' +All rights reserved. +Source: https://github.com/DASPRiD/Enum.git +Link: https://github.com/DASPRiD/Enum.git +----------- +dflydev/dot-access-data +License: MIT +License File: vendor/dflydev/dot-access-data/LICENSE +Copyright: Copyright (c) 2012 Dragonfly Development Inc. +Source: https://github.com/dflydev/dflydev-dot-access-data.git +Link: https://github.com/dflydev/dflydev-dot-access-data +----------- +doctrine/cache +License: MIT +License File: vendor/doctrine/cache/LICENSE +Copyright: Copyright (c) 2006-2015 Doctrine Project +Source: https://github.com/doctrine/cache.git +Link: https://www.doctrine-project.org/projects/cache.html +----------- +doctrine/dbal +License: MIT +License File: vendor/doctrine/dbal/LICENSE +Copyright: Copyright (c) 2006-2018 Doctrine Project +Source: https://github.com/doctrine/dbal.git +Link: https://www.doctrine-project.org/projects/dbal.html +----------- +doctrine/deprecations +License: MIT +License File: vendor/doctrine/deprecations/LICENSE +Copyright: Copyright (c) 2020-2021 Doctrine Project +Source: https://github.com/doctrine/deprecations.git +Link: https://www.doctrine-project.org/ +----------- +doctrine/event-manager +License: MIT +License File: vendor/doctrine/event-manager/LICENSE +Copyright: Copyright (c) 2006-2015 Doctrine Project +Source: https://github.com/doctrine/event-manager.git +Link: https://www.doctrine-project.org/projects/event-manager.html +----------- +doctrine/inflector +License: MIT +License File: vendor/doctrine/inflector/LICENSE +Copyright: Copyright (c) 2006-2015 Doctrine Project +Source: https://github.com/doctrine/inflector.git +Link: https://www.doctrine-project.org/projects/inflector.html +----------- +doctrine/lexer +License: MIT +License File: vendor/doctrine/lexer/LICENSE +Copyright: Copyright (c) 2006-2018 Doctrine Project +Source: https://github.com/doctrine/lexer.git +Link: https://www.doctrine-project.org/projects/lexer.html +----------- +dompdf/dompdf +License: LGPL-2.1 +License File: vendor/dompdf/dompdf/LICENSE.LGPL +Copyright: Copyright (C) 1991, 1999 Free Software Foundation, Inc. +Source: https://github.com/dompdf/dompdf.git +Link: https://github.com/dompdf/dompdf +----------- +dragonmantank/cron-expression +License: MIT +License File: vendor/dragonmantank/cron-expression/LICENSE +Copyright: Copyright (c) 2011 Michael Dowling <*********@*****.***>, 2016 Chris Tankersley <*****@***********.***>, and contributors +Source: https://github.com/dragonmantank/cron-expression.git +Link: https://github.com/dragonmantank/cron-expression.git +----------- +egulias/email-validator +License: MIT +License File: vendor/egulias/email-validator/LICENSE +Copyright: Copyright (c) 2013-2023 Eduardo Gulias Davis +Source: https://github.com/egulias/EmailValidator.git +Link: https://github.com/egulias/EmailValidator +----------- +fruitcake/php-cors +License: MIT +License File: vendor/fruitcake/php-cors/LICENSE +Copyright: Copyright (c) 2013-2017 Alexander <***.*****@*****.***> +Copyright (c) 2017-2022 Barryvdh <********@*****.***> +Source: https://github.com/fruitcake/php-cors.git +Link: https://github.com/fruitcake/php-cors +----------- +graham-campbell/result-type +License: MIT +License File: vendor/graham-campbell/result-type/LICENSE +Copyright: Copyright (c) 2020-2023 Graham Campbell <*****@**********.**.**> +Source: https://github.com/GrahamCampbell/Result-Type.git +Link: https://github.com/GrahamCampbell/Result-Type.git +----------- +guzzlehttp/guzzle +License: MIT +License File: vendor/guzzlehttp/guzzle/LICENSE +Copyright: Copyright (c) 2011 Michael Dowling <*********@*****.***> +Copyright (c) 2012 Jeremy Lindblom <**********@*****.***> +Copyright (c) 2014 Graham Campbell <*****@**********.**.**> +Copyright (c) 2015 Márk Sági-Kazár <****.*********@*****.***> +Copyright (c) 2015 Tobias Schultze <*********@**********.**> +Copyright (c) 2016 Tobias Nyholm <******.******@*****.***> +Copyright (c) 2016 George Mponos <*******@*****.***> +Source: https://github.com/guzzle/guzzle.git +Link: https://github.com/guzzle/guzzle.git +----------- +guzzlehttp/promises +License: MIT +License File: vendor/guzzlehttp/promises/LICENSE +Copyright: Copyright (c) 2015 Michael Dowling <*********@*****.***> +Copyright (c) 2015 Graham Campbell <*****@**********.**.**> +Copyright (c) 2017 Tobias Schultze <*********@**********.**> +Copyright (c) 2020 Tobias Nyholm <******.******@*****.***> +Source: https://github.com/guzzle/promises.git +Link: https://github.com/guzzle/promises.git +----------- +guzzlehttp/psr7 +License: MIT +License File: vendor/guzzlehttp/psr7/LICENSE +Copyright: Copyright (c) 2015 Michael Dowling <*********@*****.***> +Copyright (c) 2015 Márk Sági-Kazár <****.*********@*****.***> +Copyright (c) 2015 Graham Campbell <*****@**********.**.**> +Copyright (c) 2016 Tobias Schultze <*********@**********.**> +Copyright (c) 2016 George Mponos <*******@*****.***> +Copyright (c) 2018 Tobias Nyholm <******.******@*****.***> +Source: https://github.com/guzzle/psr7.git +Link: https://github.com/guzzle/psr7.git +----------- +guzzlehttp/uri-template +License: MIT +License File: vendor/guzzlehttp/uri-template/LICENSE +Copyright: Copyright (c) 2014 Michael Dowling <*********@*****.***> +Copyright (c) 2020 George Mponos <*******@*****.***> +Copyright (c) 2020 Graham Campbell <*****@**********.**.**> +Source: https://github.com/guzzle/uri-template.git +Link: https://github.com/guzzle/uri-template.git +----------- +intervention/gif +License: MIT +License File: vendor/intervention/gif/LICENSE +Copyright: Copyright (c) 2020 Oliver Vogel +Source: https://github.com/Intervention/gif.git +Link: https://github.com/intervention/gif +----------- +intervention/image +License: MIT +License File: vendor/intervention/image/LICENSE +Copyright: Copyright (c) 2013-2024 Oliver Vogel +Source: https://github.com/Intervention/image.git +Link: https://image.intervention.io/ +----------- +knplabs/knp-snappy +License: MIT +License File: vendor/knplabs/knp-snappy/LICENSE +Copyright: Copyright (c) 2010 Matthieu Bontemps +Source: https://github.com/KnpLabs/snappy.git +Link: http://github.com/KnpLabs/snappy +----------- +laravel/framework +License: MIT +License File: vendor/laravel/framework/LICENSE.md +Copyright: Copyright (c) Taylor Otwell +Source: https://github.com/laravel/framework.git +Link: https://laravel.com +----------- +laravel/prompts +License: MIT +License File: vendor/laravel/prompts/LICENSE.md +Copyright: Copyright (c) Taylor Otwell +Source: https://github.com/laravel/prompts.git +Link: https://github.com/laravel/prompts.git +----------- +laravel/serializable-closure +License: MIT +License File: vendor/laravel/serializable-closure/LICENSE.md +Copyright: Copyright (c) Taylor Otwell +Source: https://github.com/laravel/serializable-closure.git +Link: https://github.com/laravel/serializable-closure.git +----------- +laravel/socialite +License: MIT +License File: vendor/laravel/socialite/LICENSE.md +Copyright: Copyright (c) Taylor Otwell +Source: https://github.com/laravel/socialite.git +Link: https://laravel.com +----------- +laravel/tinker +License: MIT +License File: vendor/laravel/tinker/LICENSE.md +Copyright: Copyright (c) Taylor Otwell +Source: https://github.com/laravel/tinker.git +Link: https://github.com/laravel/tinker.git +----------- +league/commonmark +License: BSD-3-Clause +License File: vendor/league/commonmark/LICENSE +Copyright: Copyright (c) 2014-2022, Colin O'Dell. All rights reserved. Some code based on commonmark.js (copyright 2014-2018, John MacFarlane) and commonmark-java (copyright 2015-2016, Atlassian Pty Ltd) +Source: https://github.com/thephpleague/commonmark.git +Link: https://commonmark.thephpleague.com +----------- +league/config +License: BSD-3-Clause +License File: vendor/league/config/LICENSE.md +Copyright: Copyright (c) 2022, Colin O'Dell. All rights reserved. +Source: https://github.com/thephpleague/config.git +Link: https://config.thephpleague.com +----------- +league/flysystem +License: MIT +License File: vendor/league/flysystem/LICENSE +Copyright: Copyright (c) 2013-2024 Frank de Jonge +Source: https://github.com/thephpleague/flysystem.git +Link: https://github.com/thephpleague/flysystem.git +----------- +league/flysystem-aws-s3-v3 +License: MIT +License File: vendor/league/flysystem-aws-s3-v3/LICENSE +Copyright: Copyright (c) 2013-2024 Frank de Jonge +Source: https://github.com/thephpleague/flysystem-aws-s3-v3.git +Link: https://github.com/thephpleague/flysystem-aws-s3-v3.git +----------- +league/flysystem-local +License: MIT +License File: vendor/league/flysystem-local/LICENSE +Copyright: Copyright (c) 2013-2024 Frank de Jonge +Source: https://github.com/thephpleague/flysystem-local.git +Link: https://github.com/thephpleague/flysystem-local.git +----------- +league/html-to-markdown +License: MIT +License File: vendor/league/html-to-markdown/LICENSE +Copyright: Copyright (c) 2015 Colin O'Dell; Originally created by Nick Cernis +Source: https://github.com/thephpleague/html-to-markdown.git +Link: https://github.com/thephpleague/html-to-markdown +----------- +league/mime-type-detection +License: MIT +License File: vendor/league/mime-type-detection/LICENSE +Copyright: Copyright (c) 2013-2023 Frank de Jonge +Source: https://github.com/thephpleague/mime-type-detection.git +Link: https://github.com/thephpleague/mime-type-detection.git +----------- +league/oauth1-client +License: MIT +License File: vendor/league/oauth1-client/LICENSE +Copyright: Copyright (c) 2013 Ben Corlett <**********@**.***> +Source: https://github.com/thephpleague/oauth1-client.git +Link: https://github.com/thephpleague/oauth1-client.git +----------- +league/oauth2-client +License: MIT +License File: vendor/league/oauth2-client/LICENSE +Copyright: Copyright (c) 2013-2020 Alex Bilbie <*****@**********.***> +Source: https://github.com/thephpleague/oauth2-client.git +Link: https://github.com/thephpleague/oauth2-client.git +----------- +masterminds/html5 +License: MIT +License File: vendor/masterminds/html5/LICENSE.txt +Copyright: Copyright (c) 2013 The Authors of HTML5-PHP +Source: https://github.com/Masterminds/html5-php.git +Link: http://masterminds.github.io/html5-php +----------- +monolog/monolog +License: MIT +License File: vendor/monolog/monolog/LICENSE +Copyright: Copyright (c) 2011-2020 Jordi Boggiano +Source: https://github.com/Seldaek/monolog.git +Link: https://github.com/Seldaek/monolog +----------- +mtdowling/jmespath.php +License: MIT +License File: vendor/mtdowling/jmespath.php/LICENSE +Copyright: Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling +Source: https://github.com/jmespath/jmespath.php.git +Link: https://github.com/jmespath/jmespath.php.git +----------- +nesbot/carbon +License: MIT +License File: vendor/nesbot/carbon/LICENSE +Copyright: Copyright (C) Brian Nesbitt +Source: https://github.com/briannesbitt/Carbon.git +Link: https://carbon.nesbot.com +----------- +nette/schema +License: BSD-3-Clause GPL-2.0-only GPL-3.0-only +License File: vendor/nette/schema/license.md +Copyright: Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com) +All rights reserved. +Source: https://github.com/nette/schema.git +Link: https://nette.org +----------- +nette/utils +License: BSD-3-Clause GPL-2.0-only GPL-3.0-only +License File: vendor/nette/utils/license.md +Copyright: Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com) +All rights reserved. +Source: https://github.com/nette/utils.git +Link: https://nette.org +----------- +nikic/php-parser +License: BSD-3-Clause +License File: vendor/nikic/php-parser/LICENSE +Copyright: Copyright (c) 2011, Nikita Popov +All rights reserved. +Source: https://github.com/nikic/PHP-Parser.git +Link: https://github.com/nikic/PHP-Parser.git +----------- +nunomaduro/termwind +License: MIT +License File: vendor/nunomaduro/termwind/LICENSE.md +Copyright: Copyright (c) Nuno Maduro <***********@*****.***> +Source: https://github.com/nunomaduro/termwind.git +Link: https://github.com/nunomaduro/termwind.git +----------- +onelogin/php-saml +License: MIT +License File: vendor/onelogin/php-saml/LICENSE +Copyright: Copyright (c) 2010-2016 OneLogin, Inc. +Source: https://github.com/onelogin/php-saml.git +Link: https://developers.onelogin.com/saml/php +----------- +paragonie/constant_time_encoding +License: MIT +License File: vendor/paragonie/constant_time_encoding/LICENSE.txt +Copyright: Copyright (c) 2016 - 2022 Paragon Initiative Enterprises +Source: https://github.com/paragonie/constant_time_encoding.git +Link: https://github.com/paragonie/constant_time_encoding.git +----------- +paragonie/random_compat +License: MIT +License File: vendor/paragonie/random_compat/LICENSE +Copyright: Copyright (c) 2015 Paragon Initiative Enterprises +Source: https://github.com/paragonie/random_compat.git +Link: https://github.com/paragonie/random_compat.git +----------- +phenx/php-font-lib +License: LGPL-2.1-or-later +License File: vendor/phenx/php-font-lib/LICENSE +Copyright: Copyright (C) 1991, 1999 Free Software Foundation, Inc. +Source: https://github.com/dompdf/php-font-lib.git +Link: https://github.com/PhenX/php-font-lib +----------- +phenx/php-svg-lib +License: LGPL-3.0-or-later +License File: vendor/phenx/php-svg-lib/LICENSE +Copyright: Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. +Source: https://github.com/dompdf/php-svg-lib.git +Link: https://github.com/PhenX/php-svg-lib +----------- +phpoption/phpoption +License: Apache-2.0 +License File: vendor/phpoption/phpoption/LICENSE +Source: https://github.com/schmittjoh/php-option.git +Link: https://github.com/schmittjoh/php-option.git +----------- +phpseclib/phpseclib +License: MIT +License File: vendor/phpseclib/phpseclib/LICENSE +Copyright: Copyright (c) 2011-2019 TerraFrost and other contributors +Source: https://github.com/phpseclib/phpseclib.git +Link: http://phpseclib.sourceforge.net +----------- +pragmarx/google2fa +License: MIT +License File: vendor/pragmarx/google2fa/LICENSE.md +Copyright: Copyright 2014-2018 Phil, Antonio Carlos Ribeiro and All Contributors +Source: https://github.com/antonioribeiro/google2fa.git +Link: https://github.com/antonioribeiro/google2fa.git +----------- +predis/predis +License: MIT +License File: vendor/predis/predis/LICENSE +Copyright: Copyright (c) 2009-2020 Daniele Alessandri (original work) +Copyright (c) 2021-2023 Till Krüss (modified work) +Source: https://github.com/predis/predis.git +Link: http://github.com/predis/predis +----------- +psr/cache +License: MIT +License File: vendor/psr/cache/LICENSE.txt +Copyright: Copyright (c) 2015 PHP Framework Interoperability Group +Source: https://github.com/php-fig/cache.git +Link: https://github.com/php-fig/cache.git +----------- +psr/clock +License: MIT +License File: vendor/psr/clock/LICENSE +Copyright: Copyright (c) 2017 PHP Framework Interoperability Group +Source: https://github.com/php-fig/clock.git +Link: https://github.com/php-fig/clock +----------- +psr/container +License: MIT +License File: vendor/psr/container/LICENSE +Copyright: Copyright (c) 2013-2016 container-interop +Copyright (c) 2016 PHP Framework Interoperability Group +Source: https://github.com/php-fig/container.git +Link: https://github.com/php-fig/container +----------- +psr/event-dispatcher +License: MIT +License File: vendor/psr/event-dispatcher/LICENSE +Copyright: Copyright (c) 2018 PHP-FIG +Source: https://github.com/php-fig/event-dispatcher.git +Link: https://github.com/php-fig/event-dispatcher.git +----------- +psr/http-client +License: MIT +License File: vendor/psr/http-client/LICENSE +Copyright: Copyright (c) 2017 PHP Framework Interoperability Group +Source: https://github.com/php-fig/http-client.git +Link: https://github.com/php-fig/http-client +----------- +psr/http-factory +License: MIT +License File: vendor/psr/http-factory/LICENSE +Copyright: Copyright (c) 2018 PHP-FIG +Source: https://github.com/php-fig/http-factory.git +Link: https://github.com/php-fig/http-factory.git +----------- +psr/http-message +License: MIT +License File: vendor/psr/http-message/LICENSE +Copyright: Copyright (c) 2014 PHP Framework Interoperability Group +Source: https://github.com/php-fig/http-message.git +Link: https://github.com/php-fig/http-message +----------- +psr/log +License: MIT +License File: vendor/psr/log/LICENSE +Copyright: Copyright (c) 2012 PHP Framework Interoperability Group +Source: https://github.com/php-fig/log.git +Link: https://github.com/php-fig/log +----------- +psr/simple-cache +License: MIT +License File: vendor/psr/simple-cache/LICENSE.md +Copyright: Copyright (c) 2016 PHP Framework Interoperability Group +Source: https://github.com/php-fig/simple-cache.git +Link: https://github.com/php-fig/simple-cache.git +----------- +psy/psysh +License: MIT +License File: vendor/psy/psysh/LICENSE +Copyright: Copyright (c) 2012-2023 Justin Hileman +Source: https://github.com/bobthecow/psysh.git +Link: http://psysh.org +----------- +ralouphie/getallheaders +License: MIT +License File: vendor/ralouphie/getallheaders/LICENSE +Copyright: Copyright (c) 2014 Ralph Khattar +Source: https://github.com/ralouphie/getallheaders.git +Link: https://github.com/ralouphie/getallheaders.git +----------- +ramsey/collection +License: MIT +License File: vendor/ramsey/collection/LICENSE +Copyright: Copyright (c) 2015-2022 Ben Ramsey <***@*********.***> +Source: https://github.com/ramsey/collection.git +Link: https://github.com/ramsey/collection.git +----------- +ramsey/uuid +License: MIT +License File: vendor/ramsey/uuid/LICENSE +Copyright: Copyright (c) 2012-2023 Ben Ramsey <***@*********.***> +Source: https://github.com/ramsey/uuid.git +Link: https://github.com/ramsey/uuid.git +----------- +robrichards/xmlseclibs +License: BSD-3-Clause +License File: vendor/robrichards/xmlseclibs/LICENSE +Copyright: Copyright (c) 2007-2019, Robert Richards <*********@*********.***>. +Source: https://github.com/robrichards/xmlseclibs.git +Link: https://github.com/robrichards/xmlseclibs +----------- +sabberworm/php-css-parser +License: MIT +License File: vendor/sabberworm/php-css-parser/LICENSE +Copyright: Copyright (c) 2011 Raphael Schweikert, https://www.sabberworm.com/ +Source: https://github.com/MyIntervals/PHP-CSS-Parser.git +Link: https://www.sabberworm.com/blog/2010/6/10/php-css-parser +----------- +socialiteproviders/discord +License: MIT +Source: https://github.com/SocialiteProviders/Discord.git +Link: https://github.com/SocialiteProviders/Discord.git +----------- +socialiteproviders/gitlab +License: MIT +Source: https://github.com/SocialiteProviders/GitLab.git +Link: https://github.com/SocialiteProviders/GitLab.git +----------- +socialiteproviders/manager +License: MIT +License File: vendor/socialiteproviders/manager/LICENSE +Copyright: Copyright (c) 2015 Andy Wendt +Source: https://github.com/SocialiteProviders/Manager.git +Link: https://socialiteproviders.com +----------- +socialiteproviders/microsoft-azure +License: MIT +Source: https://github.com/SocialiteProviders/Microsoft-Azure.git +Link: https://github.com/SocialiteProviders/Microsoft-Azure.git +----------- +socialiteproviders/okta +License: MIT +Source: https://github.com/SocialiteProviders/Okta.git +Link: https://github.com/SocialiteProviders/Okta.git +----------- +socialiteproviders/twitch +License: MIT +Source: https://github.com/SocialiteProviders/Twitch.git +Link: https://github.com/SocialiteProviders/Twitch.git +----------- +ssddanbrown/htmldiff +License: MIT +License File: vendor/ssddanbrown/htmldiff/license.md +Copyright: Copyright (c) 2020 Nathan Herald, Rohland de Charmoy, Dan Brown +Source: https://github.com/ssddanbrown/HtmlDiff.git +Link: https://github.com/ssddanbrown/htmldiff +----------- +ssddanbrown/symfony-mailer +License: MIT +License File: vendor/ssddanbrown/symfony-mailer/LICENSE +Copyright: Copyright (c) 2019-present Fabien Potencier +Source: https://github.com/ssddanbrown/symfony-mailer.git +Link: https://symfony.com +----------- +symfony/console +License: MIT +License File: vendor/symfony/console/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/console.git +Link: https://symfony.com +----------- +symfony/css-selector +License: MIT +License File: vendor/symfony/css-selector/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/css-selector.git +Link: https://symfony.com +----------- +symfony/deprecation-contracts +License: MIT +License File: vendor/symfony/deprecation-contracts/LICENSE +Copyright: Copyright (c) 2020-present Fabien Potencier +Source: https://github.com/symfony/deprecation-contracts.git +Link: https://symfony.com +----------- +symfony/error-handler +License: MIT +License File: vendor/symfony/error-handler/LICENSE +Copyright: Copyright (c) 2019-present Fabien Potencier +Source: https://github.com/symfony/error-handler.git +Link: https://symfony.com +----------- +symfony/event-dispatcher +License: MIT +License File: vendor/symfony/event-dispatcher/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/event-dispatcher.git +Link: https://symfony.com +----------- +symfony/event-dispatcher-contracts +License: MIT +License File: vendor/symfony/event-dispatcher-contracts/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier +Source: https://github.com/symfony/event-dispatcher-contracts.git +Link: https://symfony.com +----------- +symfony/finder +License: MIT +License File: vendor/symfony/finder/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/finder.git +Link: https://symfony.com +----------- +symfony/http-foundation +License: MIT +License File: vendor/symfony/http-foundation/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/http-foundation.git +Link: https://symfony.com +----------- +symfony/http-kernel +License: MIT +License File: vendor/symfony/http-kernel/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/http-kernel.git +Link: https://symfony.com +----------- +symfony/mime +License: MIT +License File: vendor/symfony/mime/LICENSE +Copyright: Copyright (c) 2010-present Fabien Potencier +Source: https://github.com/symfony/mime.git +Link: https://symfony.com +----------- +symfony/polyfill-ctype +License: MIT +License File: vendor/symfony/polyfill-ctype/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier +Source: https://github.com/symfony/polyfill-ctype.git +Link: https://symfony.com +----------- +symfony/polyfill-intl-grapheme +License: MIT +License File: vendor/symfony/polyfill-intl-grapheme/LICENSE +Copyright: Copyright (c) 2015-present Fabien Potencier +Source: https://github.com/symfony/polyfill-intl-grapheme.git +Link: https://symfony.com +----------- +symfony/polyfill-intl-idn +License: MIT +License File: vendor/symfony/polyfill-intl-idn/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier and Trevor Rowbotham <******.*********@**.**> +Source: https://github.com/symfony/polyfill-intl-idn.git +Link: https://symfony.com +----------- +symfony/polyfill-intl-normalizer +License: MIT +License File: vendor/symfony/polyfill-intl-normalizer/LICENSE +Copyright: Copyright (c) 2015-present Fabien Potencier +Source: https://github.com/symfony/polyfill-intl-normalizer.git +Link: https://symfony.com +----------- +symfony/polyfill-mbstring +License: MIT +License File: vendor/symfony/polyfill-mbstring/LICENSE +Copyright: Copyright (c) 2015-present Fabien Potencier +Source: https://github.com/symfony/polyfill-mbstring.git +Link: https://symfony.com +----------- +symfony/polyfill-php72 +License: MIT +License File: vendor/symfony/polyfill-php72/LICENSE +Copyright: Copyright (c) 2015-present Fabien Potencier +Source: https://github.com/symfony/polyfill-php72.git +Link: https://symfony.com +----------- +symfony/polyfill-php80 +License: MIT +License File: vendor/symfony/polyfill-php80/LICENSE +Copyright: Copyright (c) 2020-present Fabien Potencier +Source: https://github.com/symfony/polyfill-php80.git +Link: https://symfony.com +----------- +symfony/polyfill-php83 +License: MIT +License File: vendor/symfony/polyfill-php83/LICENSE +Copyright: Copyright (c) 2022-present Fabien Potencier +Source: https://github.com/symfony/polyfill-php83.git +Link: https://symfony.com +----------- +symfony/polyfill-uuid +License: MIT +License File: vendor/symfony/polyfill-uuid/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier +Source: https://github.com/symfony/polyfill-uuid.git +Link: https://symfony.com +----------- +symfony/process +License: MIT +License File: vendor/symfony/process/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/process.git +Link: https://symfony.com +----------- +symfony/routing +License: MIT +License File: vendor/symfony/routing/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/routing.git +Link: https://symfony.com +----------- +symfony/service-contracts +License: MIT +License File: vendor/symfony/service-contracts/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier +Source: https://github.com/symfony/service-contracts.git +Link: https://symfony.com +----------- +symfony/string +License: MIT +License File: vendor/symfony/string/LICENSE +Copyright: Copyright (c) 2019-present Fabien Potencier +Source: https://github.com/symfony/string.git +Link: https://symfony.com +----------- +symfony/translation +License: MIT +License File: vendor/symfony/translation/LICENSE +Copyright: Copyright (c) 2004-present Fabien Potencier +Source: https://github.com/symfony/translation.git +Link: https://symfony.com +----------- +symfony/translation-contracts +License: MIT +License File: vendor/symfony/translation-contracts/LICENSE +Copyright: Copyright (c) 2018-present Fabien Potencier +Source: https://github.com/symfony/translation-contracts.git +Link: https://symfony.com +----------- +symfony/uid +License: MIT +License File: vendor/symfony/uid/LICENSE +Copyright: Copyright (c) 2020-present Fabien Potencier +Source: https://github.com/symfony/uid.git +Link: https://symfony.com +----------- +symfony/var-dumper +License: MIT +License File: vendor/symfony/var-dumper/LICENSE +Copyright: Copyright (c) 2014-present Fabien Potencier +Source: https://github.com/symfony/var-dumper.git +Link: https://symfony.com +----------- +tijsverkoyen/css-to-inline-styles +License: BSD-3-Clause +License File: vendor/tijsverkoyen/css-to-inline-styles/LICENSE.md +Copyright: Copyright (c) Tijs Verkoyen. All rights reserved. +Source: https://github.com/tijsverkoyen/CssToInlineStyles.git +Link: https://github.com/tijsverkoyen/CssToInlineStyles +----------- +vlucas/phpdotenv +License: BSD-3-Clause +License File: vendor/vlucas/phpdotenv/LICENSE +Copyright: Copyright (c) 2014, Graham Campbell. +Source: https://github.com/vlucas/phpdotenv.git +Link: https://github.com/vlucas/phpdotenv.git +----------- +voku/portable-ascii +License: MIT +License File: vendor/voku/portable-ascii/LICENSE.txt +Copyright: Copyright (C) 2019 Lars Moelleken +Source: https://github.com/voku/portable-ascii.git +Link: https://github.com/voku/portable-ascii +----------- +webmozart/assert +License: MIT +License File: vendor/webmozart/assert/LICENSE +Copyright: Copyright (c) 2014 Bernhard Schussek +Source: https://github.com/webmozarts/assert.git +Link: https://github.com/webmozarts/assert.git From 55a2a6db88bee277ed0cf43720428199f8d6ffc1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 Mar 2024 15:19:58 +0000 Subject: [PATCH 15/59] Licensing: Added script to gen info for JS packages --- dev/licensing/gen-js-licenses | 121 ++ dev/licensing/gen-licenses-shared.php | 4 + dev/licensing/js-library-licenses.txt | 1978 +++++++++++++++++++++++++ 3 files changed, 2103 insertions(+) create mode 100644 dev/licensing/gen-js-licenses create mode 100644 dev/licensing/gen-licenses-shared.php create mode 100644 dev/licensing/js-library-licenses.txt diff --git a/dev/licensing/gen-js-licenses b/dev/licensing/gen-js-licenses new file mode 100644 index 000000000..6c44791aa --- /dev/null +++ b/dev/licensing/gen-js-licenses @@ -0,0 +1,121 @@ +#!/usr/bin/env php +name}"]; + + $license = $package->license ?? ''; + if ($license) { + $output[] = "License: {$license}"; + } else { + warn("Package {$package->name}: No license found"); + } + + $licenseFile = findLicenseFile($package->name, $packagePath); + if ($licenseFile) { + $relLicenseFile = str_replace("{$rootPath}/", '', $licenseFile); + $output[] = "License File: {$relLicenseFile}"; + $copyright = findCopyright($licenseFile); + if ($copyright) { + $output[] = "Copyright: {$copyright}"; + } else { + warn("Package {$package->name}: no copyright found in its license"); + } + } + + $source = $package->repository->url ?? $package->repository ?? ''; + if ($source) { + $output[] = "Source: {$source}"; + } + + $link = $package->homepage ?? $source; + if ($link) { + $output[] = "Link: {$link}"; + } + + return implode("\n", $output); +} + +function findLicenseFile(string $packageName, string $packagePath): string +{ + $licenseNameOptions = [ + 'license', 'LICENSE', 'License', + 'license.*', 'LICENSE.*', 'License.*', + 'license-*.*', 'LICENSE-*.*', 'License-*.*', + ]; + $packageDir = dirname($packagePath); + + $foundLicenses = []; + foreach ($licenseNameOptions as $option) { + $search = glob("{$packageDir}/$option"); + array_push($foundLicenses, ...$search); + } + + if (count($foundLicenses) > 1) { + warn("Package {$packageName}: more than one license file found"); + } + + if (count($foundLicenses) > 0) { + $fileName = basename($foundLicenses[0]); + return "{$packageDir}/{$fileName}"; + } + + warn("Package {$packageName}: no license files found"); + return ''; +} + +function findCopyright(string $licenseFile): string +{ + $fileContents = file_get_contents($licenseFile); + $pattern = '/^.*?copyright (\(c\)|\d{4})[\s\S]*?(\n\n|\.\n)/mi'; + $matches = []; + preg_match($pattern, $fileContents, $matches); + $copyright = trim($matches[0] ?? ''); + + if (str_contains($copyright, 'i.e.')) { + return ''; + } + + $emailPattern = '/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i'; + return preg_replace_callback($emailPattern, obfuscateEmail(...), $copyright); +} + +function obfuscateEmail(array $matches): string +{ + return preg_replace('/[^@.]/', '*', $matches[1]); +} + +function warn(string $text): void +{ + global $warnings; + $warnings[] = "WARN:" . $text; +} \ No newline at end of file diff --git a/dev/licensing/gen-licenses-shared.php b/dev/licensing/gen-licenses-shared.php new file mode 100644 index 000000000..265c209ca --- /dev/null +++ b/dev/licensing/gen-licenses-shared.php @@ -0,0 +1,4 @@ + (sindresorhus.com) +Source: chalk/ansi-regex +Link: chalk/ansi-regex +----------- +ansi-styles +License: MIT +License File: node_modules/ansi-styles/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: chalk/ansi-styles +Link: chalk/ansi-styles +----------- +anymatch +License: ISC +License File: node_modules/anymatch/LICENSE +Copyright: Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com) +Source: https://github.com/micromatch/anymatch +Link: https://github.com/micromatch/anymatch +----------- +argparse +License: Python-2.0 +License File: node_modules/argparse/LICENSE +Source: nodeca/argparse +Link: nodeca/argparse +----------- +array-buffer-byte-length +License: MIT +License File: node_modules/array-buffer-byte-length/LICENSE +Copyright: Copyright (c) 2023 Inspect JS +Source: git+https://github.com/inspect-js/array-buffer-byte-length.git +Link: https://github.com/inspect-js/array-buffer-byte-length#readme +----------- +array-includes +License: MIT +License File: node_modules/array-includes/LICENSE +Copyright: Copyright (C) 2015 Jordan Harband +Source: git://github.com/es-shims/array-includes.git +Link: git://github.com/es-shims/array-includes.git +----------- +array.prototype.filter +License: MIT +License File: node_modules/array.prototype.filter/LICENSE +Copyright: Copyright (c) 2021 Jordan Harband +Source: git+https://github.com/es-shims/Array.prototype.filter.git +Link: https://github.com/es-shims/Array.prototype.filter#readme +----------- +array.prototype.findlastindex +License: MIT +License File: node_modules/array.prototype.findlastindex/LICENSE +Copyright: Copyright (c) 2021 ECMAScript Shims +Source: git+https://github.com/es-shims/Array.prototype.findLastIndex.git +Link: https://github.com/es-shims/Array.prototype.findLastIndex#readme +----------- +array.prototype.flat +License: MIT +License File: node_modules/array.prototype.flat/LICENSE +Copyright: Copyright (c) 2017 ECMAScript Shims +Source: git://github.com/es-shims/Array.prototype.flat.git +Link: git://github.com/es-shims/Array.prototype.flat.git +----------- +array.prototype.flatmap +License: MIT +License File: node_modules/array.prototype.flatmap/LICENSE +Copyright: Copyright (c) 2017 ECMAScript Shims +Source: git://github.com/es-shims/Array.prototype.flatMap.git +Link: git://github.com/es-shims/Array.prototype.flatMap.git +----------- +arraybuffer.prototype.slice +License: MIT +License File: node_modules/arraybuffer.prototype.slice/LICENSE +Copyright: Copyright (c) 2023 ECMAScript Shims +Source: git+https://github.com/es-shims/ArrayBuffer.prototype.slice.git +Link: https://github.com/es-shims/ArrayBuffer.prototype.slice#readme +----------- +available-typed-arrays +License: MIT +License File: node_modules/available-typed-arrays/LICENSE +Copyright: Copyright (c) 2020 Inspect JS +Source: git+https://github.com/inspect-js/available-typed-arrays.git +Link: https://github.com/inspect-js/available-typed-arrays#readme +----------- +balanced-match +License: MIT +License File: node_modules/balanced-match/LICENSE.md +Copyright: Copyright (c) 2013 Julian Gruber <******@************.***> +Source: git://github.com/juliangruber/balanced-match.git +Link: https://github.com/juliangruber/balanced-match +----------- +binary-extensions +License: MIT +License File: node_modules/binary-extensions/license +Copyright: Copyright (c) 2019 Sindre Sorhus <************@*****.***> (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +Source: sindresorhus/binary-extensions +Link: sindresorhus/binary-extensions +----------- +brace-expansion +License: MIT +License File: node_modules/brace-expansion/LICENSE +Copyright: Copyright (c) 2013 Julian Gruber <******@************.***> +Source: git://github.com/juliangruber/brace-expansion.git +Link: https://github.com/juliangruber/brace-expansion +----------- +braces +License: MIT +License File: node_modules/braces/LICENSE +Copyright: Copyright (c) 2014-2018, Jon Schlinkert. +Source: micromatch/braces +Link: https://github.com/micromatch/braces +----------- +call-bind +License: MIT +License File: node_modules/call-bind/LICENSE +Copyright: Copyright (c) 2020 Jordan Harband +Source: git+https://github.com/ljharb/call-bind.git +Link: https://github.com/ljharb/call-bind#readme +----------- +callsites +License: MIT +License File: node_modules/callsites/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/callsites +Link: sindresorhus/callsites +----------- +camelcase +License: MIT +License File: node_modules/camelcase/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/camelcase +Link: sindresorhus/camelcase +----------- +chalk +License: MIT +License File: node_modules/chalk/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: chalk/chalk +Link: chalk/chalk +----------- +chokidar-cli +License: MIT +License File: node_modules/chokidar-cli/LICENSE +Copyright: Copyright (c) 2015 Kimmo Brunfeldt +Source: https://github.com/open-npm-tools/chokidar-cli.git +Link: https://github.com/open-npm-tools/chokidar-cli +----------- +chokidar +License: MIT +License File: node_modules/chokidar/LICENSE +Copyright: Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker +Source: git+https://github.com/paulmillr/chokidar.git +Link: https://github.com/paulmillr/chokidar +----------- +cliui +License: ISC +License File: node_modules/cliui/LICENSE.txt +Copyright: Copyright (c) 2015, Contributors +Source: http://github.com/yargs/cliui.git +Link: http://github.com/yargs/cliui.git +----------- +codemirror +License: MIT +License File: node_modules/codemirror/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others +Source: https://github.com/codemirror/basic-setup.git +Link: https://github.com/codemirror/basic-setup.git +----------- +color-convert +License: MIT +License File: node_modules/color-convert/LICENSE +Copyright: Copyright (c) 2011-2016 Heather Arthur <**********@*****.***> +Source: Qix-/color-convert +Link: Qix-/color-convert +----------- +color-name +License: MIT +License File: node_modules/color-name/LICENSE +Source: git@github.com:colorjs/color-name.git +Link: https://github.com/colorjs/color-name +----------- +concat-map +License: MIT +License File: node_modules/concat-map/LICENSE +Source: git://github.com/substack/node-concat-map.git +Link: git://github.com/substack/node-concat-map.git +----------- +confusing-browser-globals +License: MIT +License File: node_modules/confusing-browser-globals/LICENSE +Copyright: Copyright (c) 2013-present, Facebook, Inc. +Source: https://github.com/facebook/create-react-app.git +Link: https://github.com/facebook/create-react-app.git +----------- +crelt +License: MIT +License File: node_modules/crelt/LICENSE +Copyright: Copyright (C) 2020 by Marijn Haverbeke <******@*********.******> +Source: git+https://github.com/marijnh/crelt.git +Link: https://github.com/marijnh/crelt#readme +----------- +cross-spawn +License: MIT +License File: node_modules/cross-spawn/LICENSE +Copyright: Copyright (c) 2018 Made With MOXY Lda <*****@****.******> +Source: git@github.com:moxystudio/node-cross-spawn.git +Link: https://github.com/moxystudio/node-cross-spawn +----------- +debug +License: MIT +License File: node_modules/debug/LICENSE +Copyright: Copyright (c) 2014-2017 TJ Holowaychuk <**@************.**> +Copyright (c) 2018-2021 Josh Junon +Source: git://github.com/debug-js/debug.git +Link: git://github.com/debug-js/debug.git +----------- +decamelize +License: MIT +License File: node_modules/decamelize/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/decamelize +Link: sindresorhus/decamelize +----------- +deep-is +License: MIT +License File: node_modules/deep-is/LICENSE +Copyright: Copyright (c) 2012, 2013 Thorsten Lorenz <********@***.**> +Copyright (c) 2012 James Halliday <****@********.***> +Copyright (c) 2009 Thomas Robinson <280north.com> +Source: http://github.com/thlorenz/deep-is.git +Link: http://github.com/thlorenz/deep-is.git +----------- +define-data-property +License: MIT +License File: node_modules/define-data-property/LICENSE +Copyright: Copyright (c) 2023 Jordan Harband +Source: git+https://github.com/ljharb/define-data-property.git +Link: https://github.com/ljharb/define-data-property#readme +----------- +define-properties +License: MIT +License File: node_modules/define-properties/LICENSE +Copyright: Copyright (C) 2015 Jordan Harband +Source: git://github.com/ljharb/define-properties.git +Link: git://github.com/ljharb/define-properties.git +----------- +doctrine +License: Apache-2.0 +License File: node_modules/doctrine/LICENSE +Source: eslint/doctrine +Link: https://github.com/eslint/doctrine +----------- +emoji-regex +License: MIT +License File: node_modules/emoji-regex/LICENSE-MIT.txt +Source: https://github.com/mathiasbynens/emoji-regex.git +Link: https://mths.be/emoji-regex +----------- +entities +License: BSD-2-Clause +License File: node_modules/entities/LICENSE +Copyright: Copyright (c) Felix Böhm +All rights reserved. +Source: git://github.com/fb55/entities.git +Link: git://github.com/fb55/entities.git +----------- +error-ex +License: MIT +License File: node_modules/error-ex/LICENSE +Copyright: Copyright (c) 2015 JD Ballard +Source: qix-/node-error-ex +Link: qix-/node-error-ex +----------- +es-abstract +License: MIT +License File: node_modules/es-abstract/LICENSE +Copyright: Copyright (C) 2015 Jordan Harband +Source: git://github.com/ljharb/es-abstract.git +Link: git://github.com/ljharb/es-abstract.git +----------- +es-array-method-boxes-properly +License: MIT +License File: node_modules/es-array-method-boxes-properly/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/ljharb/es-array-method-boxes-properly.git +Link: https://github.com/ljharb/es-array-method-boxes-properly#readme +----------- +es-define-property +License: MIT +License File: node_modules/es-define-property/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/es-define-property.git +Link: https://github.com/ljharb/es-define-property#readme +----------- +es-errors +License: MIT +License File: node_modules/es-errors/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/es-errors.git +Link: https://github.com/ljharb/es-errors#readme +----------- +es-set-tostringtag +License: MIT +License File: node_modules/es-set-tostringtag/LICENSE +Copyright: Copyright (c) 2022 ECMAScript Shims +Source: git+https://github.com/es-shims/es-set-tostringtag.git +Link: https://github.com/es-shims/es-set-tostringtag#readme +----------- +es-shim-unscopables +License: MIT +License File: node_modules/es-shim-unscopables/LICENSE +Copyright: Copyright (c) 2022 Jordan Harband +Source: git+https://github.com/ljharb/es-shim-unscopables.git +Link: https://github.com/ljharb/es-shim-unscopables#readme +----------- +es-to-primitive +License: MIT +License File: node_modules/es-to-primitive/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/ljharb/es-to-primitive.git +Link: git://github.com/ljharb/es-to-primitive.git +----------- +esbuild +License: MIT +License File: node_modules/esbuild/LICENSE.md +Copyright: Copyright (c) 2020 Evan Wallace +Source: git+https://github.com/evanw/esbuild.git +Link: git+https://github.com/evanw/esbuild.git +----------- +escape-string-regexp +License: MIT +License File: node_modules/escape-string-regexp/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/escape-string-regexp +Link: sindresorhus/escape-string-regexp +----------- +eslint-config-airbnb-base +License: MIT +License File: node_modules/eslint-config-airbnb-base/LICENSE.md +Copyright: Copyright (c) 2012 Airbnb +Source: https://github.com/airbnb/javascript +Link: https://github.com/airbnb/javascript +----------- +eslint-import-resolver-node +License: MIT +License File: node_modules/eslint-import-resolver-node/LICENSE +Copyright: Copyright (c) 2015 Ben Mosher +Source: https://github.com/import-js/eslint-plugin-import +Link: https://github.com/import-js/eslint-plugin-import +----------- +eslint-module-utils +License: MIT +License File: node_modules/eslint-module-utils/LICENSE +Copyright: Copyright (c) 2015 Ben Mosher +Source: git+https://github.com/import-js/eslint-plugin-import.git +Link: https://github.com/import-js/eslint-plugin-import#readme +----------- +eslint-plugin-import +License: MIT +License File: node_modules/eslint-plugin-import/LICENSE +Copyright: Copyright (c) 2015 Ben Mosher +Source: https://github.com/import-js/eslint-plugin-import +Link: https://github.com/import-js/eslint-plugin-import +----------- +eslint-scope +License: BSD-2-Clause +License File: node_modules/eslint-scope/LICENSE +Copyright: Copyright (C) 2012-2013 Yusuke Suzuki (twitter: @Constellation) and other contributors. +Source: eslint/eslint-scope +Link: http://github.com/eslint/eslint-scope +----------- +eslint-visitor-keys +License: Apache-2.0 +License File: node_modules/eslint-visitor-keys/LICENSE +Source: eslint/eslint-visitor-keys +Link: https://github.com/eslint/eslint-visitor-keys#readme +----------- +eslint +License: MIT +License File: node_modules/eslint/LICENSE +Source: eslint/eslint +Link: https://eslint.org +----------- +espree +License: BSD-2-Clause +License File: node_modules/espree/LICENSE +Copyright: Copyright (c) Open JS Foundation +All rights reserved. +Source: eslint/espree +Link: https://github.com/eslint/espree +----------- +esquery +License: BSD-3-Clause +License File: node_modules/esquery/license.txt +Copyright: Copyright (c) 2013, Joel Feenstra +All rights reserved. +Source: https://github.com/estools/esquery.git +Link: https://github.com/estools/esquery/ +----------- +esrecurse +License: BSD-2-Clause +Source: https://github.com/estools/esrecurse.git +Link: https://github.com/estools/esrecurse +----------- +estraverse +License: BSD-2-Clause +License File: node_modules/estraverse/LICENSE.BSD +Source: http://github.com/estools/estraverse.git +Link: https://github.com/estools/estraverse +----------- +esutils +License: BSD-2-Clause +License File: node_modules/esutils/LICENSE.BSD +Source: http://github.com/estools/esutils.git +Link: https://github.com/estools/esutils +----------- +fast-deep-equal +License: MIT +License File: node_modules/fast-deep-equal/LICENSE +Copyright: Copyright (c) 2017 Evgeny Poberezkin +Source: git+https://github.com/epoberezkin/fast-deep-equal.git +Link: https://github.com/epoberezkin/fast-deep-equal#readme +----------- +fast-json-stable-stringify +License: MIT +License File: node_modules/fast-json-stable-stringify/LICENSE +Copyright: Copyright (c) 2017 Evgeny Poberezkin +Copyright (c) 2013 James Halliday +Source: git://github.com/epoberezkin/fast-json-stable-stringify.git +Link: https://github.com/epoberezkin/fast-json-stable-stringify +----------- +fast-levenshtein +License: MIT +License File: node_modules/fast-levenshtein/LICENSE.md +Copyright: Copyright (c) 2013 [Ramesh Nair](http://www.hiddentao.com/) +Source: https://github.com/hiddentao/fast-levenshtein.git +Link: https://github.com/hiddentao/fast-levenshtein.git +----------- +fastq +License: ISC +License File: node_modules/fastq/LICENSE +Copyright: Copyright (c) 2015-2020, Matteo Collina <******.*******@*****.***> +Source: git+https://github.com/mcollina/fastq.git +Link: https://github.com/mcollina/fastq#readme +----------- +file-entry-cache +License: MIT +License File: node_modules/file-entry-cache/LICENSE +Copyright: Copyright (c) 2015 Roy Riojas +Source: royriojas/file-entry-cache +Link: royriojas/file-entry-cache +----------- +fill-range +License: MIT +License File: node_modules/fill-range/LICENSE +Copyright: Copyright (c) 2014-present, Jon Schlinkert. +Source: jonschlinkert/fill-range +Link: https://github.com/jonschlinkert/fill-range +----------- +find-up +License: MIT +License File: node_modules/find-up/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/find-up +Link: sindresorhus/find-up +----------- +flat-cache +License: MIT +License File: node_modules/flat-cache/LICENSE +Copyright: Copyright (c) Roy Riojas and Jared Wray +Source: jaredwray/flat-cache +Link: jaredwray/flat-cache +----------- +flatted +License: ISC +License File: node_modules/flatted/LICENSE +Copyright: Copyright (c) 2018-2020, Andrea Giammarchi, @WebReflection +Source: git+https://github.com/WebReflection/flatted.git +Link: https://github.com/WebReflection/flatted#readme +----------- +for-each +License: MIT +License File: node_modules/for-each/LICENSE +Copyright: Copyright (c) 2012 Raynos. +Source: git://github.com/Raynos/for-each.git +Link: https://github.com/Raynos/for-each +----------- +fs.realpath +License: ISC +License File: node_modules/fs.realpath/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git+https://github.com/isaacs/fs.realpath.git +Link: git+https://github.com/isaacs/fs.realpath.git +----------- +function-bind +License: MIT +License File: node_modules/function-bind/LICENSE +Copyright: Copyright (c) 2013 Raynos. +Source: https://github.com/Raynos/function-bind.git +Link: https://github.com/Raynos/function-bind +----------- +function.prototype.name +License: MIT +License File: node_modules/function.prototype.name/LICENSE +Copyright: Copyright (c) 2016 Jordan Harband +Source: git://github.com/es-shims/Function.prototype.name.git +Link: git://github.com/es-shims/Function.prototype.name.git +----------- +functions-have-names +License: MIT +License File: node_modules/functions-have-names/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/inspect-js/functions-have-names.git +Link: https://github.com/inspect-js/functions-have-names#readme +----------- +get-caller-file +License: ISC +License File: node_modules/get-caller-file/LICENSE.md +Copyright: Copyright 2018 Stefan Penner +Source: git+https://github.com/stefanpenner/get-caller-file.git +Link: https://github.com/stefanpenner/get-caller-file#readme +----------- +get-intrinsic +License: MIT +License File: node_modules/get-intrinsic/LICENSE +Copyright: Copyright (c) 2020 Jordan Harband +Source: git+https://github.com/ljharb/get-intrinsic.git +Link: https://github.com/ljharb/get-intrinsic#readme +----------- +get-symbol-description +License: MIT +License File: node_modules/get-symbol-description/LICENSE +Copyright: Copyright (c) 2021 Inspect JS +Source: git+https://github.com/inspect-js/get-symbol-description.git +Link: https://github.com/inspect-js/get-symbol-description#readme +----------- +glob-parent +License: ISC +License File: node_modules/glob-parent/LICENSE +Copyright: Copyright (c) 2015, 2019 Elan Shanker +Source: gulpjs/glob-parent +Link: gulpjs/glob-parent +----------- +glob +License: ISC +License File: node_modules/glob/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git://github.com/isaacs/node-glob.git +Link: git://github.com/isaacs/node-glob.git +----------- +globals +License: MIT +License File: node_modules/globals/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/globals +Link: sindresorhus/globals +----------- +globalthis +License: MIT +License File: node_modules/globalthis/LICENSE +Copyright: Copyright (c) 2016 Jordan Harband +Source: git://github.com/ljharb/System.global.git +Link: git://github.com/ljharb/System.global.git +----------- +gopd +License: MIT +License File: node_modules/gopd/LICENSE +Copyright: Copyright (c) 2022 Jordan Harband +Source: git+https://github.com/ljharb/gopd.git +Link: https://github.com/ljharb/gopd#readme +----------- +graceful-fs +License: ISC +License File: node_modules/graceful-fs/LICENSE +Copyright: Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors +Source: https://github.com/isaacs/node-graceful-fs +Link: https://github.com/isaacs/node-graceful-fs +----------- +graphemer +License: MIT +License File: node_modules/graphemer/LICENSE +Copyright: Copyright 2020 Filament (Anomalous Technologies Limited) +Source: https://github.com/flmnt/graphemer.git +Link: https://github.com/flmnt/graphemer +----------- +has-bigints +License: MIT +License File: node_modules/has-bigints/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/ljharb/has-bigints.git +Link: https://github.com/ljharb/has-bigints#readme +----------- +has-flag +License: MIT +License File: node_modules/has-flag/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/has-flag +Link: sindresorhus/has-flag +----------- +has-property-descriptors +License: MIT +License File: node_modules/has-property-descriptors/LICENSE +Copyright: Copyright (c) 2022 Inspect JS +Source: git+https://github.com/inspect-js/has-property-descriptors.git +Link: https://github.com/inspect-js/has-property-descriptors#readme +----------- +has-proto +License: MIT +License File: node_modules/has-proto/LICENSE +Copyright: Copyright (c) 2022 Inspect JS +Source: git+https://github.com/inspect-js/has-proto.git +Link: https://github.com/inspect-js/has-proto#readme +----------- +has-symbols +License: MIT +License File: node_modules/has-symbols/LICENSE +Copyright: Copyright (c) 2016 Jordan Harband +Source: git://github.com/inspect-js/has-symbols.git +Link: https://github.com/ljharb/has-symbols#readme +----------- +has-tostringtag +License: MIT +License File: node_modules/has-tostringtag/LICENSE +Copyright: Copyright (c) 2021 Inspect JS +Source: git+https://github.com/inspect-js/has-tostringtag.git +Link: https://github.com/inspect-js/has-tostringtag#readme +----------- +hasown +License: MIT +License File: node_modules/hasown/LICENSE +Copyright: Copyright (c) Jordan Harband and contributors +Source: git+https://github.com/inspect-js/hasOwn.git +Link: https://github.com/inspect-js/hasOwn#readme +----------- +hosted-git-info +License: ISC +License File: node_modules/hosted-git-info/LICENSE +Copyright: Copyright (c) 2015, Rebecca Turner +Source: git+https://github.com/npm/hosted-git-info.git +Link: https://github.com/npm/hosted-git-info +----------- +idb-keyval +License: Apache-2.0 +Source: git+https://github.com/jakearchibald/idb-keyval.git +Link: https://github.com/jakearchibald/idb-keyval#readme +----------- +ignore +License: MIT +Source: git@github.com:kaelzhang/node-ignore.git +Link: git@github.com:kaelzhang/node-ignore.git +----------- +immutable +License: MIT +License File: node_modules/immutable/LICENSE +Copyright: Copyright (c) 2014-present, Lee Byron and other contributors. +Source: git://github.com/immutable-js/immutable-js.git +Link: https://immutable-js.com +----------- +import-fresh +License: MIT +License File: node_modules/import-fresh/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/import-fresh +Link: sindresorhus/import-fresh +----------- +imurmurhash +License: MIT +Source: https://github.com/jensyt/imurmurhash-js +Link: https://github.com/jensyt/imurmurhash-js +----------- +inflight +License: ISC +License File: node_modules/inflight/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter +Source: https://github.com/npm/inflight.git +Link: https://github.com/isaacs/inflight +----------- +inherits +License: ISC +License File: node_modules/inherits/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter +Source: git://github.com/isaacs/inherits +Link: git://github.com/isaacs/inherits +----------- +internal-slot +License: MIT +License File: node_modules/internal-slot/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/ljharb/internal-slot.git +Link: https://github.com/ljharb/internal-slot#readme +----------- +is-array-buffer +License: MIT +License File: node_modules/is-array-buffer/LICENSE +Copyright: Copyright (c) 2015 Chen Gengyuan, Inspect JS +Source: git+https://github.com/inspect-js/is-array-buffer.git +Link: https://github.com/inspect-js/is-array-buffer#readme +----------- +is-arrayish +License: MIT +License File: node_modules/is-arrayish/LICENSE +Copyright: Copyright (c) 2015 JD Ballard +Source: https://github.com/qix-/node-is-arrayish.git +Link: https://github.com/qix-/node-is-arrayish.git +----------- +is-bigint +License: MIT +License File: node_modules/is-bigint/LICENSE +Copyright: Copyright (c) 2018 Jordan Harband +Source: git+https://github.com/inspect-js/is-bigint.git +Link: https://github.com/inspect-js/is-bigint#readme +----------- +is-binary-path +License: MIT +License File: node_modules/is-binary-path/license +Copyright: Copyright (c) 2019 Sindre Sorhus <************@*****.***> (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +Source: sindresorhus/is-binary-path +Link: sindresorhus/is-binary-path +----------- +is-boolean-object +License: MIT +License File: node_modules/is-boolean-object/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-boolean-object.git +Link: git://github.com/inspect-js/is-boolean-object.git +----------- +is-callable +License: MIT +License File: node_modules/is-callable/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-callable.git +Link: git://github.com/inspect-js/is-callable.git +----------- +is-core-module +License: MIT +License File: node_modules/is-core-module/LICENSE +Copyright: Copyright (c) 2014 Dave Justice +Source: git+https://github.com/inspect-js/is-core-module.git +Link: https://github.com/inspect-js/is-core-module +----------- +is-date-object +License: MIT +License File: node_modules/is-date-object/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-date-object.git +Link: git://github.com/inspect-js/is-date-object.git +----------- +is-extglob +License: MIT +License File: node_modules/is-extglob/LICENSE +Copyright: Copyright (c) 2014-2016, Jon Schlinkert +Source: jonschlinkert/is-extglob +Link: https://github.com/jonschlinkert/is-extglob +----------- +is-fullwidth-code-point +License: MIT +License File: node_modules/is-fullwidth-code-point/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/is-fullwidth-code-point +Link: sindresorhus/is-fullwidth-code-point +----------- +is-glob +License: MIT +License File: node_modules/is-glob/LICENSE +Copyright: Copyright (c) 2014-2017, Jon Schlinkert. +Source: micromatch/is-glob +Link: https://github.com/micromatch/is-glob +----------- +is-negative-zero +License: MIT +License File: node_modules/is-negative-zero/LICENSE +Copyright: Copyright (c) 2014 Jordan Harband +Source: git://github.com/inspect-js/is-negative-zero.git +Link: https://github.com/inspect-js/is-negative-zero +----------- +is-number-object +License: MIT +License File: node_modules/is-number-object/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-number-object.git +Link: https://github.com/inspect-js/is-number-object#readme +----------- +is-number +License: MIT +License File: node_modules/is-number/LICENSE +Copyright: Copyright (c) 2014-present, Jon Schlinkert. +Source: jonschlinkert/is-number +Link: https://github.com/jonschlinkert/is-number +----------- +is-path-inside +License: MIT +License File: node_modules/is-path-inside/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/is-path-inside +Link: sindresorhus/is-path-inside +----------- +is-regex +License: MIT +License File: node_modules/is-regex/LICENSE +Copyright: Copyright (c) 2014 Jordan Harband +Source: git://github.com/inspect-js/is-regex.git +Link: https://github.com/inspect-js/is-regex +----------- +is-shared-array-buffer +License: MIT +License File: node_modules/is-shared-array-buffer/LICENSE +Copyright: Copyright (c) 2021 Inspect JS +Source: git+https://github.com/inspect-js/is-shared-array-buffer.git +Link: https://github.com/inspect-js/is-shared-array-buffer#readme +----------- +is-string +License: MIT +License File: node_modules/is-string/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/ljharb/is-string.git +Link: git://github.com/ljharb/is-string.git +----------- +is-symbol +License: MIT +License File: node_modules/is-symbol/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-symbol.git +Link: git://github.com/inspect-js/is-symbol.git +----------- +is-typed-array +License: MIT +License File: node_modules/is-typed-array/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/is-typed-array.git +Link: git://github.com/inspect-js/is-typed-array.git +----------- +is-weakref +License: MIT +License File: node_modules/is-weakref/LICENSE +Copyright: Copyright (c) 2020 Inspect JS +Source: git+https://github.com/inspect-js/is-weakref.git +Link: https://github.com/inspect-js/is-weakref#readme +----------- +isarray +License: MIT +License File: node_modules/isarray/LICENSE +Copyright: Copyright (c) 2013 Julian Gruber <******@************.***> +Source: git://github.com/juliangruber/isarray.git +Link: https://github.com/juliangruber/isarray +----------- +isexe +License: ISC +License File: node_modules/isexe/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git+https://github.com/isaacs/isexe.git +Link: https://github.com/isaacs/isexe#readme +----------- +js-yaml +License: MIT +License File: node_modules/js-yaml/LICENSE +Copyright: Copyright (C) 2011-2015 by Vitaly Puzrin +Source: nodeca/js-yaml +Link: nodeca/js-yaml +----------- +json-buffer +License: MIT +License File: node_modules/json-buffer/LICENSE +Copyright: Copyright (c) 2013 Dominic Tarr +Source: git://github.com/dominictarr/json-buffer.git +Link: https://github.com/dominictarr/json-buffer +----------- +json-parse-better-errors +License: MIT +License File: node_modules/json-parse-better-errors/LICENSE.md +Copyright: Copyright 2017 Kat Marchán +Source: https://github.com/zkat/json-parse-better-errors +Link: https://github.com/zkat/json-parse-better-errors +----------- +json-schema-traverse +License: MIT +License File: node_modules/json-schema-traverse/LICENSE +Copyright: Copyright (c) 2017 Evgeny Poberezkin +Source: git+https://github.com/epoberezkin/json-schema-traverse.git +Link: https://github.com/epoberezkin/json-schema-traverse#readme +----------- +json-stable-stringify-without-jsonify +License: MIT +License File: node_modules/json-stable-stringify-without-jsonify/LICENSE +Source: git://github.com/samn/json-stable-stringify.git +Link: https://github.com/samn/json-stable-stringify +----------- +json5 +License: MIT +License File: node_modules/json5/LICENSE.md +Copyright: Copyright (c) 2012-2018 Aseem Kishore, and [others]. +Source: git+https://github.com/json5/json5.git +Link: http://json5.org/ +----------- +keyv +License: MIT +Source: git+https://github.com/jaredwray/keyv.git +Link: https://github.com/jaredwray/keyv +----------- +levn +License: MIT +License File: node_modules/levn/LICENSE +Copyright: Copyright (c) George Zahariev +Source: git://github.com/gkz/levn.git +Link: https://github.com/gkz/levn +----------- +linkify-it +License: MIT +License File: node_modules/linkify-it/LICENSE +Copyright: Copyright (c) 2015 Vitaly Puzrin. +Source: markdown-it/linkify-it +Link: markdown-it/linkify-it +----------- +livereload-js +License: MIT +License File: node_modules/livereload-js/LICENSE +Copyright: Copyright (c) 2010-2012 Andrey Tarantsov +Source: git://github.com/livereload/livereload-js.git +Link: https://github.com/livereload/livereload-js +----------- +livereload +License: MIT +License File: node_modules/livereload/LICENSE +Copyright: Copyright (c) 2010 Joshua Peek +Source: http://github.com/napcs/node-livereload.git +Link: http://github.com/napcs/node-livereload.git +----------- +load-json-file +License: MIT +License File: node_modules/load-json-file/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/load-json-file +Link: sindresorhus/load-json-file +----------- +locate-path +License: MIT +License File: node_modules/locate-path/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/locate-path +Link: sindresorhus/locate-path +----------- +lodash.debounce +License: MIT +License File: node_modules/lodash.debounce/LICENSE +Source: lodash/lodash +Link: https://lodash.com/ +----------- +lodash.merge +License: MIT +License File: node_modules/lodash.merge/LICENSE +Source: lodash/lodash +Link: https://lodash.com/ +----------- +lodash.throttle +License: MIT +License File: node_modules/lodash.throttle/LICENSE +Source: lodash/lodash +Link: https://lodash.com/ +----------- +markdown-it-task-lists +License: ISC +License File: node_modules/markdown-it-task-lists/LICENSE +Copyright: Copyright (c) 2016, Revin Guillen +Source: git@github.com:revin/markdown-it-task-lists.git +Link: https://github.com/revin/markdown-it-task-lists#readme +----------- +markdown-it +License: MIT +License File: node_modules/markdown-it/LICENSE +Copyright: Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. +Source: markdown-it/markdown-it +Link: markdown-it/markdown-it +----------- +mdurl +License: MIT +License File: node_modules/mdurl/LICENSE +Copyright: Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. +Source: markdown-it/mdurl +Link: markdown-it/mdurl +----------- +memorystream +License File: node_modules/memorystream/LICENSE +Copyright: Copyright (C) 2011 Dmitry Nizovtsev +Source: https://github.com/JSBizon/node-memorystream.git +Link: https://github.com/JSBizon/node-memorystream +----------- +minimatch +License: ISC +License File: node_modules/minimatch/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git://github.com/isaacs/minimatch.git +Link: git://github.com/isaacs/minimatch.git +----------- +minimist +License: MIT +License File: node_modules/minimist/LICENSE +Source: git://github.com/minimistjs/minimist.git +Link: https://github.com/minimistjs/minimist +----------- +ms +License: MIT +License File: node_modules/ms/license.md +Copyright: Copyright (c) 2016 Zeit, Inc. +Source: zeit/ms +Link: zeit/ms +----------- +natural-compare +License: MIT +Source: git://github.com/litejs/natural-compare-lite.git +Link: git://github.com/litejs/natural-compare-lite.git +----------- +nice-try +License: MIT +License File: node_modules/nice-try/LICENSE +Copyright: Copyright (c) 2018 Tobias Reich +Source: https://github.com/electerious/nice-try.git +Link: https://github.com/electerious/nice-try +----------- +normalize-package-data +License: BSD-2-Clause +License File: node_modules/normalize-package-data/LICENSE +Copyright: Copyright (c) Meryn Stol ("Author") +All rights reserved. +Source: git://github.com/npm/normalize-package-data.git +Link: git://github.com/npm/normalize-package-data.git +----------- +normalize-path +License: MIT +License File: node_modules/normalize-path/LICENSE +Copyright: Copyright (c) 2014-2018, Jon Schlinkert. +Source: jonschlinkert/normalize-path +Link: https://github.com/jonschlinkert/normalize-path +----------- +npm-run-all +License: MIT +License File: node_modules/npm-run-all/LICENSE +Copyright: Copyright (c) 2015 Toru Nagashima +Source: mysticatea/npm-run-all +Link: https://github.com/mysticatea/npm-run-all +----------- +object-inspect +License: MIT +License File: node_modules/object-inspect/LICENSE +Copyright: Copyright (c) 2013 James Halliday +Source: git://github.com/inspect-js/object-inspect.git +Link: https://github.com/inspect-js/object-inspect +----------- +object-keys +License: MIT +License File: node_modules/object-keys/LICENSE +Copyright: Copyright (C) 2013 Jordan Harband +Source: git://github.com/ljharb/object-keys.git +Link: git://github.com/ljharb/object-keys.git +----------- +object.assign +License: MIT +License File: node_modules/object.assign/LICENSE +Copyright: Copyright (c) 2014 Jordan Harband +Source: git://github.com/ljharb/object.assign.git +Link: git://github.com/ljharb/object.assign.git +----------- +object.entries +License: MIT +License File: node_modules/object.entries/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/es-shims/Object.entries.git +Link: git://github.com/es-shims/Object.entries.git +----------- +object.fromentries +License: MIT +License File: node_modules/object.fromentries/LICENSE +Copyright: Copyright (c) 2018 Jordan Harband +Source: git://github.com/es-shims/Object.fromEntries.git +Link: git://github.com/es-shims/Object.fromEntries.git +----------- +object.groupby +License: MIT +License File: node_modules/object.groupby/LICENSE +Copyright: Copyright (c) 2023 ECMAScript Shims +Source: git+https://github.com/es-shims/Object.groupBy.git +Link: https://github.com/es-shims/Object.groupBy#readme +----------- +object.values +License: MIT +License File: node_modules/object.values/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/es-shims/Object.values.git +Link: git://github.com/es-shims/Object.values.git +----------- +once +License: ISC +License File: node_modules/once/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git://github.com/isaacs/once +Link: git://github.com/isaacs/once +----------- +optionator +License: MIT +License File: node_modules/optionator/LICENSE +Copyright: Copyright (c) George Zahariev +Source: git://github.com/gkz/optionator.git +Link: https://github.com/gkz/optionator +----------- +opts +License: BSD-2-Clause +License File: node_modules/opts/LICENSE.txt +Copyright: Copyright (c) 2010, Joey Mazzarelli +All rights reserved. +Source: github:khtdr/opts +Link: http://khtdr.com/opts +----------- +p-limit +License: MIT +License File: node_modules/p-limit/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/p-limit +Link: sindresorhus/p-limit +----------- +p-locate +License: MIT +License File: node_modules/p-locate/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/p-locate +Link: sindresorhus/p-locate +----------- +p-try +License: MIT +License File: node_modules/p-try/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/p-try +Link: sindresorhus/p-try +----------- +parent-module +License: MIT +License File: node_modules/parent-module/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/parent-module +Link: sindresorhus/parent-module +----------- +parse-json +License: MIT +License File: node_modules/parse-json/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/parse-json +Link: sindresorhus/parse-json +----------- +path-exists +License: MIT +License File: node_modules/path-exists/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/path-exists +Link: sindresorhus/path-exists +----------- +path-is-absolute +License: MIT +License File: node_modules/path-is-absolute/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/path-is-absolute +Link: sindresorhus/path-is-absolute +----------- +path-key +License: MIT +License File: node_modules/path-key/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/path-key +Link: sindresorhus/path-key +----------- +path-parse +License: MIT +License File: node_modules/path-parse/LICENSE +Copyright: Copyright (c) 2015 Javier Blanco +Source: https://github.com/jbgutierrez/path-parse.git +Link: https://github.com/jbgutierrez/path-parse#readme +----------- +path-type +License: MIT +License File: node_modules/path-type/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/path-type +Link: sindresorhus/path-type +----------- +picomatch +License: MIT +License File: node_modules/picomatch/LICENSE +Copyright: Copyright (c) 2017-present, Jon Schlinkert. +Source: micromatch/picomatch +Link: https://github.com/micromatch/picomatch +----------- +pidtree +License: MIT +License File: node_modules/pidtree/license +Copyright: Copyright (c) 2018 Simone Primarosa +Source: github:simonepri/pidtree +Link: http://github.com/simonepri/pidtree#readme +----------- +pify +License: MIT +License File: node_modules/pify/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/pify +Link: sindresorhus/pify +----------- +possible-typed-array-names +License: MIT +License File: node_modules/possible-typed-array-names/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/possible-typed-array-names.git +Link: https://github.com/ljharb/possible-typed-array-names#readme +----------- +prelude-ls +License: MIT +License File: node_modules/prelude-ls/LICENSE +Copyright: Copyright (c) George Zahariev +Source: git://github.com/gkz/prelude-ls.git +Link: http://preludels.com +----------- +punycode +License: MIT +License File: node_modules/punycode/LICENSE-MIT.txt +Source: https://github.com/mathiasbynens/punycode.js.git +Link: https://mths.be/punycode +----------- +queue-microtask +License: MIT +License File: node_modules/queue-microtask/LICENSE +Copyright: Copyright (c) Feross Aboukhadijeh +Source: git://github.com/feross/queue-microtask.git +Link: https://github.com/feross/queue-microtask +----------- +read-pkg +License: MIT +License File: node_modules/read-pkg/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/read-pkg +Link: sindresorhus/read-pkg +----------- +readdirp +License: MIT +License File: node_modules/readdirp/LICENSE +Copyright: Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com) +Source: git://github.com/paulmillr/readdirp.git +Link: https://github.com/paulmillr/readdirp +----------- +regexp.prototype.flags +License: MIT +License File: node_modules/regexp.prototype.flags/LICENSE +Copyright: Copyright (C) 2014 Jordan Harband +Source: git://github.com/es-shims/RegExp.prototype.flags.git +Link: git://github.com/es-shims/RegExp.prototype.flags.git +----------- +require-directory +License: MIT +License File: node_modules/require-directory/LICENSE +Copyright: Copyright (c) 2011 Troy Goode <*********@*****.***> +Source: git://github.com/troygoode/node-require-directory.git +Link: https://github.com/troygoode/node-require-directory/ +----------- +require-main-filename +License: ISC +License File: node_modules/require-main-filename/LICENSE.txt +Copyright: Copyright (c) 2016, Contributors +Source: git+ssh://git@github.com/yargs/require-main-filename.git +Link: https://github.com/yargs/require-main-filename#readme +----------- +resolve-from +License: MIT +License File: node_modules/resolve-from/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/resolve-from +Link: sindresorhus/resolve-from +----------- +resolve +License: MIT +License File: node_modules/resolve/LICENSE +Copyright: Copyright (c) 2012 James Halliday +Source: git://github.com/browserify/resolve.git +Link: git://github.com/browserify/resolve.git +----------- +reusify +License: MIT +License File: node_modules/reusify/LICENSE +Copyright: Copyright (c) 2015 Matteo Collina +Source: git+https://github.com/mcollina/reusify.git +Link: https://github.com/mcollina/reusify#readme +----------- +rimraf +License: ISC +License File: node_modules/rimraf/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git://github.com/isaacs/rimraf.git +Link: git://github.com/isaacs/rimraf.git +----------- +run-parallel +License: MIT +License File: node_modules/run-parallel/LICENSE +Copyright: Copyright (c) Feross Aboukhadijeh +Source: git://github.com/feross/run-parallel.git +Link: https://github.com/feross/run-parallel +----------- +safe-array-concat +License: MIT +License File: node_modules/safe-array-concat/LICENSE +Copyright: Copyright (c) 2023 Jordan Harband +Source: git+https://github.com/ljharb/safe-array-concat.git +Link: https://github.com/ljharb/safe-array-concat#readme +----------- +safe-regex-test +License: MIT +License File: node_modules/safe-regex-test/LICENSE +Copyright: Copyright (c) 2022 Jordan Harband +Source: git+https://github.com/ljharb/safe-regex-test.git +Link: https://github.com/ljharb/safe-regex-test#readme +----------- +sass +License: MIT +License File: node_modules/sass/LICENSE +Copyright: Copyright (c) 2016, Google Inc. +Source: https://github.com/sass/dart-sass +Link: https://github.com/sass/dart-sass +----------- +semver +License: ISC +License File: node_modules/semver/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: https://github.com/npm/node-semver.git +Link: https://github.com/npm/node-semver.git +----------- +set-blocking +License: ISC +License File: node_modules/set-blocking/LICENSE.txt +Copyright: Copyright (c) 2016, Contributors +Source: git+https://github.com/yargs/set-blocking.git +Link: https://github.com/yargs/set-blocking#readme +----------- +set-function-length +License: MIT +License File: node_modules/set-function-length/LICENSE +Copyright: Copyright (c) Jordan Harband and contributors +Source: git+https://github.com/ljharb/set-function-length.git +Link: https://github.com/ljharb/set-function-length#readme +----------- +set-function-name +License: MIT +License File: node_modules/set-function-name/LICENSE +Copyright: Copyright (c) Jordan Harband and contributors +Source: git+https://github.com/ljharb/set-function-name.git +Link: https://github.com/ljharb/set-function-name#readme +----------- +shebang-command +License: MIT +License File: node_modules/shebang-command/license +Copyright: Copyright (c) Kevin Mårtensson <***************@*****.***> (github.com/kevva) +Source: kevva/shebang-command +Link: kevva/shebang-command +----------- +shebang-regex +License: MIT +License File: node_modules/shebang-regex/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/shebang-regex +Link: sindresorhus/shebang-regex +----------- +shell-quote +License: MIT +License File: node_modules/shell-quote/LICENSE +Copyright: Copyright (c) 2013 James Halliday (****@********.***) +Source: http://github.com/ljharb/shell-quote.git +Link: https://github.com/ljharb/shell-quote +----------- +side-channel +License: MIT +License File: node_modules/side-channel/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/ljharb/side-channel.git +Link: https://github.com/ljharb/side-channel#readme +----------- +snabbdom +License: MIT +License File: node_modules/snabbdom/LICENSE +Copyright: Copyright (c) 2015 Simon Friis Vindum +Source: git+https://github.com/snabbdom/snabbdom.git +Link: https://github.com/snabbdom/snabbdom#readme +----------- +sortablejs +License: MIT +License File: node_modules/sortablejs/LICENSE +Source: git://github.com/SortableJS/Sortable.git +Link: git://github.com/SortableJS/Sortable.git +----------- +source-map-js +License: BSD-3-Clause +License File: node_modules/source-map-js/LICENSE +Copyright: Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. +Source: 7rulnik/source-map-js +Link: https://github.com/7rulnik/source-map-js +----------- +spdx-correct +License: Apache-2.0 +License File: node_modules/spdx-correct/LICENSE +Source: jslicense/spdx-correct.js +Link: jslicense/spdx-correct.js +----------- +spdx-exceptions +License: CC-BY-3.0 +Source: kemitchell/spdx-exceptions.json +Link: kemitchell/spdx-exceptions.json +----------- +spdx-expression-parse +License: MIT +License File: node_modules/spdx-expression-parse/LICENSE +Copyright: Copyright (c) 2015 Kyle E. Mitchell & other authors listed in AUTHORS +Source: jslicense/spdx-expression-parse.js +Link: jslicense/spdx-expression-parse.js +----------- +spdx-license-ids +License: CC0-1.0 +Source: jslicense/spdx-license-ids +Link: jslicense/spdx-license-ids +----------- +string-width +License: MIT +License File: node_modules/string-width/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/string-width +Link: sindresorhus/string-width +----------- +string.prototype.padend +License: MIT +License File: node_modules/string.prototype.padend/LICENSE +Copyright: Copyright (c) 2015 EcmaScript Shims +Source: git://github.com/es-shims/String.prototype.padEnd.git +Link: git://github.com/es-shims/String.prototype.padEnd.git +----------- +string.prototype.trim +License: MIT +License File: node_modules/string.prototype.trim/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/es-shims/String.prototype.trim.git +Link: git://github.com/es-shims/String.prototype.trim.git +----------- +string.prototype.trimend +License: MIT +License File: node_modules/string.prototype.trimend/LICENSE +Copyright: Copyright (c) 2017 Khaled Al-Ansari +Source: git://github.com/es-shims/String.prototype.trimEnd.git +Link: git://github.com/es-shims/String.prototype.trimEnd.git +----------- +string.prototype.trimstart +License: MIT +License File: node_modules/string.prototype.trimstart/LICENSE +Copyright: Copyright (c) 2017 Khaled Al-Ansari +Source: git://github.com/es-shims/String.prototype.trimStart.git +Link: git://github.com/es-shims/String.prototype.trimStart.git +----------- +strip-ansi +License: MIT +License File: node_modules/strip-ansi/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: chalk/strip-ansi +Link: chalk/strip-ansi +----------- +strip-bom +License: MIT +License File: node_modules/strip-bom/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: sindresorhus/strip-bom +Link: sindresorhus/strip-bom +----------- +strip-json-comments +License: MIT +License File: node_modules/strip-json-comments/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/strip-json-comments +Link: sindresorhus/strip-json-comments +----------- +style-mod +License: MIT +License File: node_modules/style-mod/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: git+https://github.com/marijnh/style-mod.git +Link: git+https://github.com/marijnh/style-mod.git +----------- +supports-color +License: MIT +License File: node_modules/supports-color/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: chalk/supports-color +Link: chalk/supports-color +----------- +supports-preserve-symlinks-flag +License: MIT +License File: node_modules/supports-preserve-symlinks-flag/LICENSE +Copyright: Copyright (c) 2022 Inspect JS +Source: git+https://github.com/inspect-js/node-supports-preserve-symlinks-flag.git +Link: https://github.com/inspect-js/node-supports-preserve-symlinks-flag#readme +----------- +text-table +License: MIT +License File: node_modules/text-table/LICENSE +Source: git://github.com/substack/text-table.git +Link: https://github.com/substack/text-table +----------- +to-regex-range +License: MIT +License File: node_modules/to-regex-range/LICENSE +Copyright: Copyright (c) 2015-present, Jon Schlinkert. +Source: micromatch/to-regex-range +Link: https://github.com/micromatch/to-regex-range +----------- +tsconfig-paths +License: MIT +License File: node_modules/tsconfig-paths/LICENSE +Copyright: Copyright (c) 2016 Jonas Kello +Source: https://github.com/dividab/tsconfig-paths +Link: https://github.com/dividab/tsconfig-paths +----------- +type-check +License: MIT +License File: node_modules/type-check/LICENSE +Copyright: Copyright (c) George Zahariev +Source: git://github.com/gkz/type-check.git +Link: https://github.com/gkz/type-check +----------- +type-fest +License: (MIT OR CC0-1.0) +License File: node_modules/type-fest/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https:/sindresorhus.com) +Source: sindresorhus/type-fest +Link: sindresorhus/type-fest +----------- +typed-array-buffer +License: MIT +License File: node_modules/typed-array-buffer/LICENSE +Copyright: Copyright (c) 2023 Jordan Harband +Source: git+https://github.com/ljharb/typed-array-buffer.git +Link: https://github.com/ljharb/typed-array-buffer#readme +----------- +typed-array-byte-length +License: MIT +License File: node_modules/typed-array-byte-length/LICENSE +Copyright: Copyright (c) 2020 Inspect JS +Source: git+https://github.com/inspect-js/typed-array-byte-length.git +Link: https://github.com/inspect-js/typed-array-byte-length#readme +----------- +typed-array-byte-offset +License: MIT +License File: node_modules/typed-array-byte-offset/LICENSE +Copyright: Copyright (c) 2020 Inspect JS +Source: git+https://github.com/inspect-js/typed-array-byte-offset.git +Link: https://github.com/inspect-js/typed-array-byte-offset#readme +----------- +typed-array-length +License: MIT +License File: node_modules/typed-array-length/LICENSE +Copyright: Copyright (c) 2020 Inspect JS +Source: git+https://github.com/inspect-js/typed-array-length.git +Link: https://github.com/inspect-js/typed-array-length#readme +----------- +uc.micro +License: MIT +License File: node_modules/uc.micro/LICENSE.txt +Source: markdown-it/uc.micro +Link: markdown-it/uc.micro +----------- +unbox-primitive +License: MIT +License File: node_modules/unbox-primitive/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/ljharb/unbox-primitive.git +Link: https://github.com/ljharb/unbox-primitive#readme +----------- +uri-js +License: BSD-2-Clause +License File: node_modules/uri-js/LICENSE +Copyright: Copyright 2011 Gary Court. All rights reserved. +Source: http://github.com/garycourt/uri-js +Link: https://github.com/garycourt/uri-js +----------- +validate-npm-package-license +License: Apache-2.0 +License File: node_modules/validate-npm-package-license/LICENSE +Source: kemitchell/validate-npm-package-license.js +Link: kemitchell/validate-npm-package-license.js +----------- +w3c-keyname +License: MIT +License File: node_modules/w3c-keyname/LICENSE +Copyright: Copyright (C) 2016 by Marijn Haverbeke <******@*********.******> and others +Source: git+https://github.com/marijnh/w3c-keyname.git +Link: https://github.com/marijnh/w3c-keyname#readme +----------- +which-boxed-primitive +License: MIT +License File: node_modules/which-boxed-primitive/LICENSE +Copyright: Copyright (c) 2019 Jordan Harband +Source: git+https://github.com/inspect-js/which-boxed-primitive.git +Link: https://github.com/inspect-js/which-boxed-primitive#readme +----------- +which-module +License: ISC +License File: node_modules/which-module/LICENSE +Copyright: Copyright (c) 2016, Contributors +Source: git+https://github.com/nexdrew/which-module.git +Link: https://github.com/nexdrew/which-module#readme +----------- +which-typed-array +License: MIT +License File: node_modules/which-typed-array/LICENSE +Copyright: Copyright (c) 2015 Jordan Harband +Source: git://github.com/inspect-js/which-typed-array.git +Link: git://github.com/inspect-js/which-typed-array.git +----------- +which +License: ISC +License File: node_modules/which/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: git://github.com/isaacs/node-which.git +Link: git://github.com/isaacs/node-which.git +----------- +wrap-ansi +License: MIT +License File: node_modules/wrap-ansi/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (sindresorhus.com) +Source: chalk/wrap-ansi +Link: chalk/wrap-ansi +----------- +wrappy +License: ISC +License File: node_modules/wrappy/LICENSE +Copyright: Copyright (c) Isaac Z. Schlueter and Contributors +Source: https://github.com/npm/wrappy +Link: https://github.com/npm/wrappy +----------- +ws +License: MIT +License File: node_modules/ws/LICENSE +Copyright: Copyright (c) 2011 Einar Otto Stangvik <*******@*****.***> +Source: websockets/ws +Link: https://github.com/websockets/ws +----------- +y18n +License: ISC +License File: node_modules/y18n/LICENSE +Copyright: Copyright (c) 2015, Contributors +Source: git@github.com:yargs/y18n.git +Link: https://github.com/yargs/y18n +----------- +yargs-parser +License: ISC +License File: node_modules/yargs-parser/LICENSE.txt +Copyright: Copyright (c) 2016, Contributors +Source: git@github.com:yargs/yargs-parser.git +Link: git@github.com:yargs/yargs-parser.git +----------- +yargs +License: MIT +License File: node_modules/yargs/LICENSE +Copyright: Copyright 2010 James Halliday (****@********.***) +Modified work Copyright 2014 Contributors (***@*****.***) +Source: https://github.com/yargs/yargs.git +Link: https://yargs.js.org/ +----------- +yocto-queue +License: MIT +License File: node_modules/yocto-queue/license +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Source: sindresorhus/yocto-queue +Link: sindresorhus/yocto-queue +----------- +@aashutoshrathi/word-wrap +License: MIT +License File: node_modules/@aashutoshrathi/word-wrap/LICENSE +Copyright: Copyright (c) 2014-2016, Jon Schlinkert +Source: git+https://github.com/aashutoshrathi/word-wrap.git +Link: https://github.com/aashutoshrathi/word-wrap +----------- +@codemirror/autocomplete +License: MIT +License File: node_modules/@codemirror/autocomplete/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/autocomplete.git +Link: https://github.com/codemirror/autocomplete.git +----------- +@codemirror/commands +License: MIT +License File: node_modules/@codemirror/commands/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/commands.git +Link: https://github.com/codemirror/commands.git +----------- +@codemirror/lang-css +License: MIT +License File: node_modules/@codemirror/lang-css/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/lang-css.git +Link: https://github.com/codemirror/lang-css.git +----------- +@codemirror/lang-html +License: MIT +License File: node_modules/@codemirror/lang-html/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/lang-html.git +Link: https://github.com/codemirror/lang-html.git +----------- +@codemirror/lang-javascript +License: MIT +License File: node_modules/@codemirror/lang-javascript/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/lang-javascript.git +Link: https://github.com/codemirror/lang-javascript.git +----------- +@codemirror/lang-json +License: MIT +License File: node_modules/@codemirror/lang-json/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others +Source: https://github.com/codemirror/lang-json.git +Link: https://github.com/codemirror/lang-json.git +----------- +@codemirror/lang-markdown +License: MIT +License File: node_modules/@codemirror/lang-markdown/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/lang-markdown.git +Link: https://github.com/codemirror/lang-markdown.git +----------- +@codemirror/lang-php +License: MIT +License File: node_modules/@codemirror/lang-php/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others +Source: https://github.com/codemirror/lang-php.git +Link: https://github.com/codemirror/lang-php.git +----------- +@codemirror/lang-xml +License: MIT +License File: node_modules/@codemirror/lang-xml/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others +Source: https://github.com/codemirror/lang-xml.git +Link: https://github.com/codemirror/lang-xml.git +----------- +@codemirror/language +License: MIT +License File: node_modules/@codemirror/language/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/language.git +Link: https://github.com/codemirror/language.git +----------- +@codemirror/legacy-modes +License: MIT +License File: node_modules/@codemirror/legacy-modes/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/legacy-modes.git +Link: https://github.com/codemirror/legacy-modes.git +----------- +@codemirror/lint +License: MIT +License File: node_modules/@codemirror/lint/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/lint.git +Link: https://github.com/codemirror/lint.git +----------- +@codemirror/search +License: MIT +License File: node_modules/@codemirror/search/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/search.git +Link: https://github.com/codemirror/search.git +----------- +@codemirror/state +License: MIT +License File: node_modules/@codemirror/state/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/state.git +Link: https://github.com/codemirror/state.git +----------- +@codemirror/theme-one-dark +License: MIT +License File: node_modules/@codemirror/theme-one-dark/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/theme-one-dark.git +Link: https://github.com/codemirror/theme-one-dark.git +----------- +@codemirror/view +License: MIT +License File: node_modules/@codemirror/view/LICENSE +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/codemirror/view.git +Link: https://github.com/codemirror/view.git +----------- +@esbuild/linux-x64 +License: MIT +Source: git+https://github.com/evanw/esbuild.git +Link: git+https://github.com/evanw/esbuild.git +----------- +@eslint-community/eslint-utils +License: MIT +License File: node_modules/@eslint-community/eslint-utils/LICENSE +Copyright: Copyright (c) 2018 Toru Nagashima +Source: https://github.com/eslint-community/eslint-utils +Link: https://github.com/eslint-community/eslint-utils#readme +----------- +@eslint-community/regexpp +License: MIT +License File: node_modules/@eslint-community/regexpp/LICENSE +Copyright: Copyright (c) 2018 Toru Nagashima +Source: https://github.com/eslint-community/regexpp +Link: https://github.com/eslint-community/regexpp#readme +----------- +@eslint/eslintrc +License: MIT +License File: node_modules/@eslint/eslintrc/LICENSE +Source: eslint/eslintrc +Link: https://github.com/eslint/eslintrc#readme +----------- +@eslint/js +License: MIT +License File: node_modules/@eslint/js/LICENSE +Source: https://github.com/eslint/eslint.git +Link: https://eslint.org +----------- +@humanwhocodes/config-array +License: Apache-2.0 +License File: node_modules/@humanwhocodes/config-array/LICENSE +Source: git+https://github.com/humanwhocodes/config-array.git +Link: https://github.com/humanwhocodes/config-array#readme +----------- +@humanwhocodes/module-importer +License: Apache-2.0 +License File: node_modules/@humanwhocodes/module-importer/LICENSE +Source: git+https://github.com/humanwhocodes/module-importer.git +Link: git+https://github.com/humanwhocodes/module-importer.git +----------- +@humanwhocodes/object-schema +License: BSD-3-Clause +License File: node_modules/@humanwhocodes/object-schema/LICENSE +Copyright: Copyright (c) 2019, Human Who Codes +All rights reserved. +Source: git+https://github.com/humanwhocodes/object-schema.git +Link: https://github.com/humanwhocodes/object-schema#readme +----------- +@lezer/common +License: MIT +License File: node_modules/@lezer/common/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/common.git +Link: https://github.com/lezer-parser/common.git +----------- +@lezer/css +License: MIT +License File: node_modules/@lezer/css/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/css.git +Link: https://github.com/lezer-parser/css.git +----------- +@lezer/generator +License: MIT +License File: node_modules/@lezer/generator/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/generator.git +Link: https://github.com/lezer-parser/generator.git +----------- +@lezer/highlight +License: MIT +License File: node_modules/@lezer/highlight/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/highlight.git +Link: https://github.com/lezer-parser/highlight.git +----------- +@lezer/html +License: MIT +License File: node_modules/@lezer/html/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/html.git +Link: https://github.com/lezer-parser/html.git +----------- +@lezer/javascript +License: MIT +License File: node_modules/@lezer/javascript/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/javascript.git +Link: https://github.com/lezer-parser/javascript.git +----------- +@lezer/json +License: MIT +License File: node_modules/@lezer/json/LICENSE +Copyright: Copyright (C) 2020 by Marijn Haverbeke <******@*********.******>, Arun Srinivasan <*******@*****.***>, and others +Source: https://github.com/lezer-parser/json.git +Link: https://github.com/lezer-parser/json.git +----------- +@lezer/lr +License: MIT +License File: node_modules/@lezer/lr/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/lr.git +Link: https://github.com/lezer-parser/lr.git +----------- +@lezer/markdown +License: MIT +License File: node_modules/@lezer/markdown/LICENSE +Copyright: Copyright (C) 2020 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/markdown.git +Link: https://github.com/lezer-parser/markdown.git +----------- +@lezer/php +License: MIT +License File: node_modules/@lezer/php/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/php.git +Link: https://github.com/lezer-parser/php.git +----------- +@lezer/xml +License: MIT +License File: node_modules/@lezer/xml/LICENSE +Copyright: Copyright (C) 2018 by Marijn Haverbeke <******@*********.******> and others +Source: https://github.com/lezer-parser/xml.git +Link: https://github.com/lezer-parser/xml.git +----------- +@nodelib/fs.scandir +License: MIT +License File: node_modules/@nodelib/fs.scandir/LICENSE +Copyright: Copyright (c) Denis Malinochkin +Source: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.scandir +Link: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.scandir +----------- +@nodelib/fs.stat +License: MIT +License File: node_modules/@nodelib/fs.stat/LICENSE +Copyright: Copyright (c) Denis Malinochkin +Source: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.stat +Link: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.stat +----------- +@nodelib/fs.walk +License: MIT +License File: node_modules/@nodelib/fs.walk/LICENSE +Copyright: Copyright (c) Denis Malinochkin +Source: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.walk +Link: https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.walk +----------- +@ssddanbrown/codemirror-lang-smarty +License: MIT +License File: node_modules/@ssddanbrown/codemirror-lang-smarty/LICENSE +Copyright: Copyright (C) 2023 by Dan Brown, Marijn Haverbeke and others +----------- +@ssddanbrown/codemirror-lang-twig +License: MIT +License File: node_modules/@ssddanbrown/codemirror-lang-twig/LICENSE +Copyright: Copyright (C) 2023 by Dan Brown, Marijn Haverbeke and others +----------- +@types/json5 +License: MIT +Source: https://www.github.com/DefinitelyTyped/DefinitelyTyped.git +Link: https://www.github.com/DefinitelyTyped/DefinitelyTyped.git +----------- +@ungap/structured-clone +License: ISC +License File: node_modules/@ungap/structured-clone/LICENSE +Copyright: Copyright (c) 2021, Andrea Giammarchi, @WebReflection +Source: git+https://github.com/ungap/structured-clone.git +Link: https://github.com/ungap/structured-clone#readme From ed956a4cf00473f3b2ba135dbeacff65bc9602b0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 Mar 2024 15:33:05 +0000 Subject: [PATCH 16/59] Licensing: Updated license gen scripts to share logic --- dev/licensing/gen-js-licenses | 66 ++------------------------- dev/licensing/gen-licenses-shared.php | 62 +++++++++++++++++++++++++ dev/licensing/gen-php-licenses | 61 ++++--------------------- phpstan.neon.dist | 1 + 4 files changed, 77 insertions(+), 113 deletions(-) diff --git a/dev/licensing/gen-js-licenses b/dev/licensing/gen-js-licenses index 6c44791aa..dfb2f6651 100644 --- a/dev/licensing/gen-js-licenses +++ b/dev/licensing/gen-js-licenses @@ -4,10 +4,12 @@ // This script reads the project composer.lock file to generate // clear license details for our PHP dependencies. +declare(strict_types=1); +require "gen-licenses-shared.php"; + $rootPath = dirname(__DIR__, 2); $outputPath = "{$rootPath}/dev/licensing/js-library-licenses.txt"; $outputSeparator = "\n-----------\n"; -$warnings = []; $packages = [ ...glob("{$rootPath}/node_modules/*/package.json"), @@ -20,12 +22,7 @@ $licenseInfo = implode($outputSeparator, $packageOutput) . "\n"; file_put_contents($outputPath, $licenseInfo); echo "License information written to {$outputPath}\n"; -echo implode("\n", $warnings); - -function dd(mixed $data): never { - print_r($data); - exit(0); -} +echo implode("\n", getWarnings()); function packageToOutput(string $packagePath): string { @@ -64,58 +61,3 @@ function packageToOutput(string $packagePath): string return implode("\n", $output); } - -function findLicenseFile(string $packageName, string $packagePath): string -{ - $licenseNameOptions = [ - 'license', 'LICENSE', 'License', - 'license.*', 'LICENSE.*', 'License.*', - 'license-*.*', 'LICENSE-*.*', 'License-*.*', - ]; - $packageDir = dirname($packagePath); - - $foundLicenses = []; - foreach ($licenseNameOptions as $option) { - $search = glob("{$packageDir}/$option"); - array_push($foundLicenses, ...$search); - } - - if (count($foundLicenses) > 1) { - warn("Package {$packageName}: more than one license file found"); - } - - if (count($foundLicenses) > 0) { - $fileName = basename($foundLicenses[0]); - return "{$packageDir}/{$fileName}"; - } - - warn("Package {$packageName}: no license files found"); - return ''; -} - -function findCopyright(string $licenseFile): string -{ - $fileContents = file_get_contents($licenseFile); - $pattern = '/^.*?copyright (\(c\)|\d{4})[\s\S]*?(\n\n|\.\n)/mi'; - $matches = []; - preg_match($pattern, $fileContents, $matches); - $copyright = trim($matches[0] ?? ''); - - if (str_contains($copyright, 'i.e.')) { - return ''; - } - - $emailPattern = '/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i'; - return preg_replace_callback($emailPattern, obfuscateEmail(...), $copyright); -} - -function obfuscateEmail(array $matches): string -{ - return preg_replace('/[^@.]/', '*', $matches[1]); -} - -function warn(string $text): void -{ - global $warnings; - $warnings[] = "WARN:" . $text; -} \ No newline at end of file diff --git a/dev/licensing/gen-licenses-shared.php b/dev/licensing/gen-licenses-shared.php index 265c209ca..a8ad350f2 100644 --- a/dev/licensing/gen-licenses-shared.php +++ b/dev/licensing/gen-licenses-shared.php @@ -2,3 +2,65 @@ declare(strict_types=1); +$warnings = []; + +function findLicenseFile(string $packageName, string $packagePath): string +{ + $licenseNameOptions = [ + 'license', 'LICENSE', 'License', + 'license.*', 'LICENSE.*', 'License.*', + 'license-*.*', 'LICENSE-*.*', 'License-*.*', + ]; + $packageDir = dirname($packagePath); + + $foundLicenses = []; + foreach ($licenseNameOptions as $option) { + $search = glob("{$packageDir}/$option"); + array_push($foundLicenses, ...$search); + } + + if (count($foundLicenses) > 1) { + warn("Package {$packageName}: more than one license file found"); + } + + if (count($foundLicenses) > 0) { + $fileName = basename($foundLicenses[0]); + return "{$packageDir}/{$fileName}"; + } + + warn("Package {$packageName}: no license files found"); + return ''; +} + +function findCopyright(string $licenseFile): string +{ + $fileContents = file_get_contents($licenseFile); + $pattern = '/^.*?copyright (\(c\)|\d{4})[\s\S]*?(\n\n|\.\n)/mi'; + $matches = []; + preg_match($pattern, $fileContents, $matches); + $copyright = trim($matches[0] ?? ''); + + if (str_contains($copyright, 'i.e.')) { + return ''; + } + + $emailPattern = '/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i'; + return preg_replace_callback($emailPattern, obfuscateEmail(...), $copyright); +} + +function obfuscateEmail(array $matches): string +{ + return preg_replace('/[^@.]/', '*', $matches[1]); +} + +function warn(string $text): void +{ + global $warnings; + $warnings[] = "WARN:" . $text; +} + +function getWarnings(): array +{ + global $warnings; + return $warnings; +} diff --git a/dev/licensing/gen-php-licenses b/dev/licensing/gen-php-licenses index 0c922e281..ed5a21c5a 100644 --- a/dev/licensing/gen-php-licenses +++ b/dev/licensing/gen-php-licenses @@ -4,11 +4,13 @@ // This script reads the project composer.lock file to generate // clear license details for our PHP dependencies. +declare(strict_types=1); +require "gen-licenses-shared.php"; + $rootPath = dirname(__DIR__, 2); $outputPath = "{$rootPath}/dev/licensing/php-library-licenses.txt"; $composerLock = json_decode(file_get_contents($rootPath . "/composer.lock")); $outputSeparator = "\n-----------\n"; -$warnings = []; $packages = $composerLock->packages; $packageOutput = array_map(packageToOutput(...), $packages); @@ -17,22 +19,25 @@ $licenseInfo = implode($outputSeparator, $packageOutput) . "\n"; file_put_contents($outputPath, $licenseInfo); echo "License information written to {$outputPath}\n"; -echo implode("\n", $warnings); +echo implode("\n", getWarnings()); function packageToOutput(stdClass $package) : string { + global $rootPath; $output = ["{$package->name}"]; $licenses = is_array($package->license) ? $package->license : [$package->license]; $output[] = "License: " . implode(' ', $licenses); - $licenseFile = findLicenseFile($package->name); + $packagePath = "{$rootPath}/vendor/{$package->name}/package.json"; + $licenseFile = findLicenseFile($package->name, $packagePath); if ($licenseFile) { - $output[] = "License File: {$licenseFile}"; + $relLicenseFile = str_replace("{$rootPath}/", '', $licenseFile); + $output[] = "License File: {$relLicenseFile}"; $copyright = findCopyright($licenseFile); if ($copyright) { $output[] = "Copyright: {$copyright}"; } else { - warn("Package {$package->name} has no copyright found in its license"); + warn("Package {$package->name}: no copyright found in its license"); } } @@ -47,50 +52,4 @@ function packageToOutput(stdClass $package) : string { } return implode("\n", $output); -} - -function findLicenseFile(string $packageName): string { - global $rootPath; - $licenseNameOptions = ['license', 'LICENSE', 'license.*', 'LICENSE.*']; - - $packagePath = "vendor/{$packageName}"; - $filePath = "{$rootPath}/{$packagePath}"; - - $foundLicenses = []; - foreach ($licenseNameOptions as $option) { - $search = glob("{$filePath}/$option"); - array_push($foundLicenses, ...$search); - } - - if (count($foundLicenses) > 1) { - warn("Package {$packagePath} has more than one license file found"); - } - - if (count($foundLicenses) > 0) { - $fileName = basename($foundLicenses[0]); - return "{$packagePath}/{$fileName}"; - } - - warn("Package {$packageName} has no license files found"); - return ''; -} - -function findCopyright(string $licenseFile): string { - $fileContents = file_get_contents($licenseFile); - $pattern = '/^.*?copyright (\(c\)|\d{4})[\s\S]*?(\n\n|\.\n)/mi'; - $matches = []; - preg_match($pattern, $fileContents, $matches); - $copyright = trim($matches[0] ?? ''); - - $emailPattern = '/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i'; - return preg_replace_callback($emailPattern, obfuscateEmail(...), $copyright); -} - -function obfuscateEmail(array $matches): string { - return preg_replace('/[^@.]/', '*', $matches[1]); -} - -function warn(string $text): void { - global $warnings; - $warnings[] = "WARN:" . $text; } \ No newline at end of file diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 15a519e20..bcf4e5aa2 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -19,5 +19,6 @@ parameters: excludePaths: - ./Config/**/*.php + - ./dev/**/*.php checkMissingIterableValueType: false \ No newline at end of file From 5f306a11e73a5eface6884374320227123219446 Mon Sep 17 00:00:00 2001 From: Martin Rys Date: Sat, 23 Mar 2024 16:33:11 +0100 Subject: [PATCH 17/59] 15KB lossless optimization via oxipng(PNG) and svgo(SVG) --- public/book_default_cover.png | Bin 5672 -> 3448 bytes public/icon-128.png | Bin 3538 -> 2976 bytes public/icon-180.png | Bin 6167 -> 5769 bytes public/icon-32.png | Bin 1338 -> 753 bytes public/icon-64.png | Bin 1951 -> 1374 bytes public/icon.ico | Bin 10933 -> 10619 bytes public/icon.png | Bin 6900 -> 6350 bytes public/loading_error.png | Bin 2096 -> 1201 bytes public/logo.png | Bin 5415 -> 3302 bytes public/user_avatar.png | Bin 7405 -> 3423 bytes resources/icons/add-circle.svg | 5 +---- resources/icons/attach.svg | 5 +---- resources/icons/auth/discord.svg | 2 +- resources/icons/auth/github.svg | 2 +- resources/icons/auth/gitlab.svg | 2 +- resources/icons/auth/google.svg | 2 +- resources/icons/auth/okta.svg | 2 +- resources/icons/auth/slack.svg | 2 +- resources/icons/auth/twitch.svg | 2 +- resources/icons/auth/twitter.svg | 2 +- resources/icons/back.svg | 5 +---- resources/icons/book.svg | 5 +---- resources/icons/books.svg | 2 +- resources/icons/bookshelf.svg | 2 +- resources/icons/cancel.svg | 5 +---- resources/icons/caret-down.svg | 5 +---- resources/icons/caret-left-circle.svg | 2 +- resources/icons/caret-right-circle.svg | 5 +---- resources/icons/chapter.svg | 5 +---- resources/icons/check-circle.svg | 5 +---- resources/icons/check.svg | 2 +- resources/icons/chevron-up.svg | 5 +---- resources/icons/close.svg | 5 +---- resources/icons/comment.svg | 5 +---- resources/icons/copy.svg | 4 +--- resources/icons/danger.svg | 5 +---- resources/icons/dark-mode.svg | 2 +- resources/icons/delete.svg | 5 +---- resources/icons/download.svg | 2 +- resources/icons/drawing.svg | 5 +---- resources/icons/edit.svg | 5 +---- resources/icons/expand-text.svg | 5 +---- resources/icons/export.svg | 5 +---- resources/icons/file.svg | 2 +- resources/icons/folder.svg | 5 +---- resources/icons/fullscreen.svg | 2 +- resources/icons/grid.svg | 5 +---- resources/icons/grip.svg | 5 +---- resources/icons/groups.svg | 2 +- resources/icons/history.svg | 5 +---- resources/icons/image.svg | 2 +- resources/icons/images.svg | 5 +---- resources/icons/include.svg | 5 +---- resources/icons/info-filled.svg | 4 +--- resources/icons/info.svg | 5 +---- resources/icons/leaderboard.svg | 2 +- resources/icons/light-mode.svg | 2 +- resources/icons/link.svg | 4 +--- resources/icons/list.svg | 5 +---- resources/icons/lock-open.svg | 5 +---- resources/icons/lock.svg | 10 +--------- resources/icons/login.svg | 5 +---- resources/icons/logout.svg | 2 +- resources/icons/more.svg | 5 +---- resources/icons/new-user.svg | 5 +---- resources/icons/notifications.svg | 2 +- resources/icons/oidc.svg | 5 +---- resources/icons/open-book.svg | 10 +--------- resources/icons/page.svg | 5 +---- resources/icons/palette.svg | 2 +- resources/icons/permission.svg | 5 +---- resources/icons/popular.svg | 4 +--- resources/icons/reference.svg | 4 +--- resources/icons/reply.svg | 5 +---- resources/icons/role.svg | 5 +---- resources/icons/saml2.svg | 5 +---- resources/icons/save.svg | 5 +---- resources/icons/search.svg | 5 +---- resources/icons/security.svg | 2 +- resources/icons/settings.svg | 5 +---- resources/icons/shortcuts.svg | 2 +- resources/icons/sort.svg | 5 +---- resources/icons/spanner.svg | 5 +---- resources/icons/star-circle.svg | 4 +--- resources/icons/star-outline.svg | 2 +- resources/icons/star.svg | 6 +----- resources/icons/swap-vertical.svg | 5 +---- resources/icons/tag.svg | 2 +- resources/icons/template.svg | 2 +- resources/icons/time.svg | 6 +----- resources/icons/upload.svg | 2 +- resources/icons/user-preferences.svg | 2 +- resources/icons/user.svg | 5 +---- resources/icons/users-add.svg | 5 +---- resources/icons/users.svg | 5 +---- resources/icons/warning.svg | 5 +---- resources/icons/watch-ignore.svg | 2 +- resources/icons/watch.svg | 4 +--- resources/icons/webhooks.svg | 2 +- 99 files changed, 89 insertions(+), 265 deletions(-) diff --git a/public/book_default_cover.png b/public/book_default_cover.png index 7b6c9953e91d59d03a295e49786889317a3e9ca1..bf73b67a35f09b99c76724e48a17c0f6d96928d6 100644 GIT binary patch delta 3380 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 literal 5672 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 diff --git a/public/icon-128.png b/public/icon-128.png index 46cc2811b5e7f6162e87b8e4e0cf3785f57a922c..333c1e9640ae2d775674f716ba31fe77c6e8b135 100644 GIT binary patch delta 2953 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 delta 3518 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 diff --git a/public/icon-180.png b/public/icon-180.png index 6533a05b3ec340befe94aa2fb3774ff705d1856d..7627b523c89c13ee9deda03779473c34dcfa9e41 100644 GIT binary patch literal 5769 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 literal 6167 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 diff --git a/public/icon-32.png b/public/icon-32.png index 7307ed8f1e88f1e5ade85925d8aedee40d771f64..de94f373da2948976bb6212daf66c2f2a54389f4 100644 GIT binary patch delta 713 zcmV;)0yh1+3h@PyBa=e|6@LKaP)t-s0C52P|NH6i`H;Eb(c|x7qSxl__AHFh4TsQq ztKHq~^T*rmQ=8TE`1|+!{=C!dyVB~Y%I3P!={1qoMV8e_nAjhU*D;UNFpkom#O54~ z*52;)gt6V#=k#u=+2HT>g|gn$+<{Z_xeVc*2dcGr^)5#?)RI);uML}7mC!J!sC;@hb#Z`u&~5*Z=?k z0d!JMQvg8b*k%9#0e_}RL_t(|+MSc>Qo=wGgtG=FO*mBW0wW<{z%xP3fd?KO9?AQ^ zkC|Pt5RoeFKNQtdvtN2nVx@bFTW{;`~Rw>z{4kAsA3RtDdI0_A91(k8MZQzG2GuQ>(`voB;1oZ~(imo^h%phyoqW@v;mv%W`NH%tF?fpmihxx;+a0`C%02f#^B zkv^+Y%0H)$jN{zkwiE-n3B>nZ>CjffF?GrBGwJp6wmvcacyeZ{>S%c(UsTuW>^6Y{(kG9VAnXXK3j(800000NkvXXu0mjfOrV3o delta 1300 zcmV+v1?&3p1-c55BYy(=P)t-s0C4~fhtL3v(h-Q!0FBiYiP9H})D(@-8jIB&jMf*9 z(I1W18j#W~jL;mB(=LtCAClBCj?y8M)-jLMBb3)OkkloW*fo*XCzjbZlGiws*ff>X zIh5Hpmef0y+Cr4mH<;B#mDD+z)E6+N}tzMoYqUA*j1g^OrhFVp4nHQ+D@X|SfJZaqufxW-CCjCQKjBn zqTOMl*Ic9CSf$uvqu5!d*<+;HTBq7%rP^Gm+-0WRU8&t>r`=wv-e;)ZU#s6~so!9% z;BKkeYO3IGs(;#Nt=ns?;c%;hO^**w&91g;efZ|h_&K@xZ{boZHl*r^)4|%Iv7h=Bdl)rp)cC%;~Gn>axu0tk3JS&Fihu?6l78uF>ta&+V_$ z?y1!7wtvv>xzOmb)9<>`>9o`7vefXq((1L;>a*4IywmKq)$6^~?YGwLxYzE!*6z93 z@4wgYy4mo-*zmjC@xs~hyxj7`+VaNQ?7iLd#M|@0-R;NQ?Y`dh!QSr3-0#BQ@X6iq z!{G7C-to)d^334##^UqG)8+Bh=JVC(^w#M0 z*Xj1z>i62~_~7dJ-R$$>>-pR5`Qq&R-0u3`?)2vE_TcaJ=kE96@b~EN_~P;S>G1jE z^7-oV`sDNa>+<{M^!w)Z{Ot7n?e+cd_W$wr`11Gq^Z5Jp`TX_z{rCI+`27F*{{Q;_ z|0MkX`~Uy{il{xc00001bW%=J06^y0W&i*H0b)x>L;#2d9Y~QO7k>fFNklIhp-6gLNBpcwJP5x%2mf4^Q0{g~io$HcxcA6W&F#+RkNaIz6O28gg~L@nbtZU^24 zpx-aFIm`~L?!bk?*n+UMA8VYvEe?EZ3(mHsS@|B-MjD2qsDEFP< z5g}H#q@0P9hDYtmV2(+$^r3d_j9NXx8|G|LXXna0iaZNQBmNNUatg;_YrS!xV8d8q*EK8H1ll#|ON~fZc zIiZi0g*|;n?qvg)eWmnGwNf6geQC#yA=0usy`KL}l$ww9f3P%H}SO(Nvt) z$J_0}*zmvC?})YHhqU2_v*3lY-h8g$aI4#7rP|Wu@YLq>%ir=vmest|>_(T?z0~bU znApD7?(6dVoWkRjzJKK$jMkF808*lo8$B7}82M15~x z{<^qyfarLbKYytB+O^>mL1-K}&UWKISLQbmS^Qi~5HYVcUN zb8sO7q_>l{X*hT-QimqIn}ErH&pPlRKAW+G4l7ryqS`ruTig=kXl##43d!(5Jit46 z4i-w{AyQ4fNr8HPMLdE*fo(K`#5`ICw5Dx{$I-m$i+_hGe{M;&lL+Gf(Mu*pt$Kx> zqm(!Wg?oPoVhUJ4ZBpA$0K|*$#WX0b!#O9lDSd zPQb(jMSoJ`*pgObN|cQpx#@K#_m)q|NDBQ>8in3j3k!=jj8B0m`}%?tC3)n729b!g zAiP)R$Y{b#Tl9jm4wq1=_Ibh4j3*iGjBd}fZa~=KL71&`GP2-EHueGW7j32Pc?+jH zlYeX+pMxgx$1S=;>nwai3ywXx&P=Lq9E!dYBy7cUTPpX4ZKO1<1r0gEWMTp218T05 zPFS(@&IhVEpY@3`<$P_QQJ9H-VE)ccU<+6(te;N{} zK9fA!5P7X2{;sa+Wjy|PLPXqcz~yq+@D}}%V`3ujMj_!m0omFt4W7K*@eJOQTXd{A zJbArjstWKf{VmG&1SY%S@+GV=(jb`picM&&j&9M(0I*@hEouX^d}i>N0%rNpAuyD` x#DQ5qwP;jh_K!Vk+F1d(*=K*T;zfLz{|6f_(sA))NsRyi002ovPDHLkV1lc(!6pCz delta 1918 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 T4e(z863T*%07D3&lY1&UpKu#} delta 10909 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 QFaQ7m07*qoM6N<$f+#NRF8}}l literal 6900 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 literal 2096 zcmb7_dr%YC9>+Ii10e}@lMCSu2@geBDA1xH6sROcq+nz)tbld{qCBDoiV}K3V0oAa z!gX3>1*~nDQd_7l3RrGOWeE?jD3Dr|T2vH-Yi~uaOpPGQ-RyMk+}r-s{&CKnbN2WB ze9xKR%y-q2#8?}a6AJ(Uo48G)Bmkhn=E1ZiPl`+H4v?FwoR}C%Tuh8WQLuk^jywwh ze2$hL4c}yt*w(DHXp(%fgHZkz$w^rCx=SZZd>YEFmb$*XZwXs%6Q|KOPo^s7+mQo` z{F`IMHVAYV)Fmcr0+Jqd$9*QQwF)pzU7lU(Hl;_OK7L~Nfm&L_zQ!*_>DP9p^q)xq zp^fh4Yfo$+X!7#DpZ1>V`-B7bQ`=vamPzXy&O1Pmdd~^j?LOze8;xB=@u|>W&AH7b zi4nQqG1TteXOznW-IM2f-tgSLA!Lh-kk8)R))C~_;Ph{={N%C1tM#Kt0ec89-+W)3s_@=&W^q2VQq$}GjJO?d&M+M&= znvZ(^R+?W_(42SmRP?NNs)R$|@ojYTOz6GAx*MT1Y^3Md-KQx(^;}!?s8h#(%i@Cz z721F4T7IS-5AW&uP}q3RkC9`&7%_k7oqHcKmiAYSHmtue6PD;+{^oVxV!Dfqg(u_c zPE&DF(Tj;!k8_5fScMx3j{23A7|6C*X2i#e01H3`7*FO$lkEVk6`Qud4*&t4=0Q__ z9(9mBv?`2C5L?aASUk|n@rUaI^2o7Jj1b3+9fE;Da;nc#wAEn zDqgcE>C8CM+sVq?kM9s$U4k5{jINp{JA+rNZ4EeM(HXOM<>lRf#HQtz4mfBspOjt% zEK0&GqHzFZLoh&CKrpo?C-a(|K=vQ}_=gLBXOUDIjz!ECZ>U<25B2PpK zed9^=#wb#lI;-;VzrY;#qBV$ReYgncxE8HN975-kagKA57Il1c4#5L=O?0A;fpacI zaQehWRECe2qmI5^spOCKfobrK>1UVCiINBbEiB%~%!_ZN;*H z@iw$uiSHl^?xO}QWJP}~^=zjuCH-LJ5#v{^o8KdMUN+P%KXqR)48}?5~kFMkm*{n@C7(>&uds*gQFYJ9EszfA)>2)Jw+|^OE_zd}Am(Nah;#rL2zTneC~Xd((t`TSbGbog~CR-L_g(F0*tkbcRG zw@Gu4UV)U!=T<;|pjIUzt;C{0^1>b-F68aGT!?&%im4{c%Tc5EORFzE5Y@44AyPQ7 zxq}oNgsDvaRs!+|wWlR2J|<2Uh}eXOFGo*`?LZ?bW>t{o84pdhsPV=8$ilMeRNxU* zC@s^B-8m~}6Av;oz0Hhvo|%ED&5SmRA*C38W`@RWDe5;{>NCi49U`VS?HZQGOt-T$ zm-YGjnldYrF+*LJm!j9*Vqi8O~gevQBFrTOMh; zxsdbR>6~Un)+rvE-L*9Q#Y6VayvRp)dH(G`g`a9UJA8KOz1~MgUhAcWoEK6(87qs8 z_I+1lkpL$-f~SXOcq0LBaw*OM9Z24xK!%5qSb8MV>a3%dmE^ILDhG2T16dZzVxXxU-vTq#( z8~Rp*YgjL`F`}^QfdHyY|S~yk5U{@Zzz|_g65*cjz;0_kQX6`jo zJ9x*MUsF$JMFdb(jTSS_0aB@0KlctkA2?x+J*=1v0NJbhT?L3TaM+D_s!+_3i8I~C zg(JN7)S|_b&@`ggP|(8UyM26qdbr(m$%Q`Y`KQA3cbQ0~>7R|@|D`BLS8WQ4{%Ydq SEB_>a96+2nQFLY_iv0(S!8H~D diff --git a/public/logo.png b/public/logo.png index 585f8895b4f26c872ac9369bd4229811e725b252..b4b80fd88215021b782d36447a872e8c873827aa 100644 GIT binary patch delta 3271 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 FV1hVPHL(By delta 5400 zcmWkycRbYpAOGCpd}T$(A<;P_l$DUJ!<{WFGhZWRQ^py0*Fs;!eeA7}tvVx{lyS)l z3E^-#Gr1#C@$-AU|9JiJ{_C}#ujli*B2+G$DkKa80HC;H-S{NHJWP#I!14cIaYuO? z@w_aauK|P7w~d_Hat(;&pKQcUeaufgosLXE+~#SvV{Z}{*zw(F>8-NkK~>Z~ci`i& zVxlr5?5&AT{BlV5ood{o@deq5=ls=gWEyMjWlkl$ak8yoQPLZb)(}(q-Jv@yT&QFa zDwTRVeNXFvcz3v_o>tJf(D8Z3Z;RVksjtGb+A2 z5R&RT)!VT@zX9uBDaE9noo(U-Y@D1vTyx)M8bBcGHjGw=^0Jt_XJ%%;ZfV*k#K>c+0pgycY5)p1^$1jGZ@(2RxBSAtn#D%3hFc_mv_zjWg zBib1n8X^!)^Kb41SY$n9@d6TzN``A3>%mj>2q2%;U76sSXSHLGAU4ZuYDSkF_cYuY zCxPTrc0yTM*@_=`(*yaj+kE&G?Vs?$!9h-PVBN;k(6c@=gyWBTLt;StKNJ?8X%yWV z@I`qsQqNz@pYMn^mCb+xFU$0^u5dJnK0$eH%`~oj%er~RcPNVq&PmDVu#ExSAp{l# zsTY2RpBMt*IEs0@V|cJ^Kw$G?99lMmcZAVSA}MeCF*P~WPd57D9Wv9?BTvz})6+&^ z!Cq%%n;?*XykcpdqY@p#6z>|=v&0IIp+s1kxfATU@mDP_B*|o$OTAg*tu|ft#e%< z^{G+a?|fanPWOii6DdL}edNKx zhe~~eUXTm{=4n#E>`XgWMc|UlDwwo+(wRr??d^9Ep@wk_9emwG2+|ezF&Yz`i2?^4 zk@YBQGvWBFl`NzkMxi0-5tC!w-F$oY&)1>1{xj4j$IHse4bmA5U49;X(C+G(MY%=6 zD%P#UEwSN|Mq5^KceuO2pBjwGZ23Z8%={x)L7La{4%y$C53{ngAvi`Cu1B38~ zEq7^$#D%d_^kYCBUn1l?1>C6Pd&RDIk>E5HwsE!}1NntU>D+UTC=Hk$fz>&eO)!cR z{2fw9n1Zn?{bSkf9F(byj0{r-gHiodi;mv-Aor3FyiKg}kQb;=OiV0Dywo~ipIVRM zk~l!@zl85yaY zV)nVI4-?Py{`cqRG!A#*4@m58R|udLetABH!v6uLr>Bo$icH;3JXp8>omk*qh8tJV zzq;Zl*?t2on1fZx`zYk(Y5!@~55bpH7L9QQm|;HRTcC5=r2YkB7)R;*hK7)cngmz3M3lJ z4;tWbotm+S_e$!%dX*&&2grzwIJBj{h1h} ztS9D(w3I%WlB#pX&|k%Uaf+t+yliN=T&WN?jyj^e%#oA^HS2aLr&KKg_A+xrKb(&$os_koGgwz z<#$evtO^WNkdipCu@f0n5HO1mJxjwI=YHmBo0|YhY~3Y*+rWnpQO5T> zVclgW598y1*sn;XktI)#TTpc&PgK_eH`N;yqLpLLm9$Og)GQT&F+K3*+a#SSM*Cfr z;6Ki$DyW0HK+Z}ZZL%q5g{6Wf z1 zsb2lv5x6Ys@8lbld9VAo)MK?5#9L(F?^WkAw>39^NfD1GwmM`y*$!>r4bYH5 zNUW_p)6Y}jvF-Y_*mcWLA@Vqs5|c-@K`x&U>oB6rcXe3$>~{>o$H$NQw%zdFbSl{z zv@ZCGJh*R^lxflb6DejbsF2k7NAp|?_gqteb2yMXoBOQ%ndEUIwHH!wu>K(K8N0(C zAM>s{GBHCyh2Jvb4?EP`H~B$

jOcl#@?8*QD&wf3|7p<``?0Y5+UisHcf(e0AYD zB>qhne}_`4u9TxNK$8LAUBg?1m57h*|NXwczOFUG7?wJ)Kx;c=F3pg<2VeW9Yaq)i zD$u#4&7aZan+~b@m7ID<=3J5oYPHJ)w!Y|0;-<)`N;XwYS%&o0fDXCXy2F6`s3~%# zy@fZW#q^DM$~!fn(OjRVdeDunkJ_qztE;Pji+Be5gGN&3xqRoR@pVrWTutf93&OiE zwygy(m`w+=kjFTEOFWTNTZ@Z!6+tmial@Zj_J7_YFks~B2%3RSZik0pxrFA=J-dF(%d~* zM|u9yDRKx7X+r12gX4RD73r-yA1$hAk)Vyiby%YnuJwe)0mUy~tlVZfNPbmUw4IzU z+|%oB$jLxNDEmu8=AqN6v8paL&Djni`V7zg>&X)f}DlYD}mle_vy*41?vW%Ut z(Yqa;M34S*;h3AH13i^8V&Hb1eD1GpaYf-%q}T@_>tlD})vzkj z$Op0LBfJ4dH))~u0ksUG-B0|3MLQ@xV|RjMv#6@LigPLb+!7ks#N6Q1d@21e_q4XN z2~#Tig4<@dqKw>)0r$Dquoh%IpcfDj@N}cK-0zpDQB$>PxDkP?(=^nL{n0uCqMTbquP7;6r zQqiGaCS(&8MAsVUZx8^GY2?mzEHYPLs3WINgqbXX>8$GPVteNESd5jApWo4(MRiNK z)L}syixn5kFSo?|4CEc4U6Im1ew^Be?5d%^2NGspdm0N4U5_g(46C&Dr4A4!w(xqF zqoP%wFLO^`SS?mc{3fWWDlpL?eb5zc^)qv$^)HiLbf;8wk5u|mWnck+WTaXghuJW< zRzo=QrRPd)dZ%sG!WJ_$ANnF<_MKGEE#gV(uB$0nTwk@#iX3HD#&UVXJD_4nSM-7PZYfN1uxukxSRZ!SA z47ElF`(`|3h4p>SqsE@Ej}A#j#Q*Xv)VTYi*1XZaukHDXa&yd$fP-t9)_8OCA^dNf z+dE6W*58I|&)byGqTSB^7%}u2U8k5=F5o=TsmsEKPdQiDs`_~PY%o=LZIuK^3udMK#xu%~ZVXEt7`W??yf2u&ljMjFedDR<*~d{{Q6Y2Id$Sf% z;yyPyZ3=kXwD{I07sh*CX;e(`M*eijx zqn~DNAsd$kk58B{?!uQlz$K^^N3m<%#Y=4srJEXqq;oLB(cjOEvK-0sLmrNGtY>3%taM3hR>1 z;R4O=ddYaG^PD~p&l414crIe0!0Rx(SR(a%vFj*-RpgA|nkPlzzX3iLT7qj^_#T-| zZsEo+3L6SeO-`DhNcRPEA5}% zU7x6gZ{E;ds>g(%Y{iw*uGUU{ww~8!4v(*7q}-^^``B{-)8iuFI3+XEssy;qbjRv~ zy!^fY5)-#F-z(gET!~klr3YtAJ(~pnLs0{28&~7*6@7aTE2?F- zadEh;KqF`1cTXr*nD1*J@z{#N2teN8aNzkxTvv)f{XW}{DDw{iLZV@*3w~`( zfQMC&)VS(V*&fKA*}>}jS~Glebq*iH7&_8G>RJVEv5G4^YK@1q|F`?rk;!1R_ZIMSa$@37 z!?k#>Jk`BBBA)W4mIYJ?=q91<_K8T9%2v>WbbB44)Ib&Q6g8y7-7{ z0438oFr=!wnhm&!wY}^7On~+xFEA835&DRREgSl>6=)VtJTVa-;fr}P($mjceYmYU z7>K@zEHllzq#Q7F+2PGZXZgR!R)F@t{@)@ zcp8Eh+ycA)hU=2Up2kgO#oIbmp8vUwpmPJwd!L;pCMPFhwZBAQ0RsNI;!yYLrsUp4 zK}MRTj*^p=iY-J}4gYGC>=t<-1a$Ee1tIS56L{=TM3VdnW2Rj$LNAK%??Uct`N2Z% z=x~$T_BNQIBw#V~&U*yvzpYS6!?J3njAgzJOr?e{?Wlk6I>w3Z zx}k%vBpFAIyPqKxG5snK``hdBS_Wf@`uG+I%>y(6b=3R2mlPEGZ7j9F`SQ)&lo*Ww zVq_5c>LJgU)h+T4YF|C%+Jre84#GVZZoKNQt*8J1Q&hW>XP^3s+XGOBa#U!=OfBXQ yL@9Sg)`~4~ diff --git a/public/user_avatar.png b/public/user_avatar.png index 26440a9cc7a91301b59732edcf22d81211d701e6..3ec064006a33ad7202bc919cdb07bebbcf9203bf 100644 GIT binary patch literal 3423 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 n|HJrS>hI>1B{%=tOElGlL32-!7 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 - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/attach.svg b/resources/icons/attach.svg index 49c9d57a8..7b666f8c4 100644 --- a/resources/icons/attach.svg +++ b/resources/icons/attach.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/discord.svg b/resources/icons/auth/discord.svg index 7fbbeb792..2d3d277af 100644 --- a/resources/icons/auth/discord.svg +++ b/resources/icons/auth/discord.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/github.svg b/resources/icons/auth/github.svg index ae6dc6f7f..a341e8d4d 100644 --- a/resources/icons/auth/github.svg +++ b/resources/icons/auth/github.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/gitlab.svg b/resources/icons/auth/gitlab.svg index fa1e92a56..6e7d1c5f4 100644 --- a/resources/icons/auth/gitlab.svg +++ b/resources/icons/auth/gitlab.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/resources/icons/auth/google.svg b/resources/icons/auth/google.svg index 34ed1603b..0e416d493 100644 --- a/resources/icons/auth/google.svg +++ b/resources/icons/auth/google.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/okta.svg b/resources/icons/auth/okta.svg index b5f3b1d3f..5bf8d86d4 100644 --- a/resources/icons/auth/okta.svg +++ b/resources/icons/auth/okta.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/slack.svg b/resources/icons/auth/slack.svg index 98e5a32f5..a4ca4a084 100644 --- a/resources/icons/auth/slack.svg +++ b/resources/icons/auth/slack.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/twitch.svg b/resources/icons/auth/twitch.svg index 5dbc76bb9..2736ccfa8 100644 --- a/resources/icons/auth/twitch.svg +++ b/resources/icons/auth/twitch.svg @@ -1 +1 @@ -Glitch \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/twitter.svg b/resources/icons/auth/twitter.svg index fa4d59efd..e926b370d 100644 --- a/resources/icons/auth/twitter.svg +++ b/resources/icons/auth/twitter.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/back.svg b/resources/icons/back.svg index 22aa9d24a..9b3ab40d5 100644 --- a/resources/icons/back.svg +++ b/resources/icons/back.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/book.svg b/resources/icons/book.svg index ce6cd5d94..2f451bec9 100644 --- a/resources/icons/book.svg +++ b/resources/icons/book.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/books.svg b/resources/icons/books.svg index a485a01da..70a9e23f5 100644 --- a/resources/icons/books.svg +++ b/resources/icons/books.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/bookshelf.svg b/resources/icons/bookshelf.svg index f1e45eaf9..c6377d8d1 100644 --- a/resources/icons/bookshelf.svg +++ b/resources/icons/bookshelf.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/cancel.svg b/resources/icons/cancel.svg index a35f16d75..6ea45e3eb 100644 --- a/resources/icons/cancel.svg +++ b/resources/icons/cancel.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/caret-down.svg b/resources/icons/caret-down.svg index 000f58963..bf988ca9f 100644 --- a/resources/icons/caret-down.svg +++ b/resources/icons/caret-down.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/caret-left-circle.svg b/resources/icons/caret-left-circle.svg index a92e0630d..49da4c24a 100644 --- a/resources/icons/caret-left-circle.svg +++ b/resources/icons/caret-left-circle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/caret-right-circle.svg b/resources/icons/caret-right-circle.svg index bcf16cf66..1cd435dea 100644 --- a/resources/icons/caret-right-circle.svg +++ b/resources/icons/caret-right-circle.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/chapter.svg b/resources/icons/chapter.svg index 199917db7..e5d83be5c 100644 --- a/resources/icons/chapter.svg +++ b/resources/icons/chapter.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/check-circle.svg b/resources/icons/check-circle.svg index 669a74872..ad1e0bbd9 100644 --- a/resources/icons/check-circle.svg +++ b/resources/icons/check-circle.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/check.svg b/resources/icons/check.svg index 93607ef7e..134fd657c 100644 --- a/resources/icons/check.svg +++ b/resources/icons/check.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/chevron-up.svg b/resources/icons/chevron-up.svg index 37335dd03..8d308dbff 100644 --- a/resources/icons/chevron-up.svg +++ b/resources/icons/chevron-up.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/close.svg b/resources/icons/close.svg index a0da9e677..c2ef46510 100644 --- a/resources/icons/close.svg +++ b/resources/icons/close.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/comment.svg b/resources/icons/comment.svg index 09e950803..3c4762b2e 100644 --- a/resources/icons/comment.svg +++ b/resources/icons/comment.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/copy.svg b/resources/icons/copy.svg index 3a52e2314..2e1820f0f 100644 --- a/resources/icons/copy.svg +++ b/resources/icons/copy.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/danger.svg b/resources/icons/danger.svg index 5265957a2..6aabc9609 100644 --- a/resources/icons/danger.svg +++ b/resources/icons/danger.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/dark-mode.svg b/resources/icons/dark-mode.svg index 8b00d72a5..d905dccc8 100644 --- a/resources/icons/dark-mode.svg +++ b/resources/icons/dark-mode.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/delete.svg b/resources/icons/delete.svg index fdaba0111..cb0089969 100644 --- a/resources/icons/delete.svg +++ b/resources/icons/delete.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/download.svg b/resources/icons/download.svg index 6299571d6..4b0a289da 100644 --- a/resources/icons/download.svg +++ b/resources/icons/download.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/drawing.svg b/resources/icons/drawing.svg index c07f99271..7ebe067a6 100644 --- a/resources/icons/drawing.svg +++ b/resources/icons/drawing.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/edit.svg b/resources/icons/edit.svg index d4be98b38..9c184a0f4 100644 --- a/resources/icons/edit.svg +++ b/resources/icons/edit.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/expand-text.svg b/resources/icons/expand-text.svg index 9cc7bc168..18bf54f22 100644 --- a/resources/icons/expand-text.svg +++ b/resources/icons/expand-text.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/export.svg b/resources/icons/export.svg index 97e217fd0..a02220929 100644 --- a/resources/icons/export.svg +++ b/resources/icons/export.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/file.svg b/resources/icons/file.svg index 2e87f2ca6..9d65579be 100644 --- a/resources/icons/file.svg +++ b/resources/icons/file.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/folder.svg b/resources/icons/folder.svg index cc56c6fad..f2cb814ff 100644 --- a/resources/icons/folder.svg +++ b/resources/icons/folder.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/fullscreen.svg b/resources/icons/fullscreen.svg index d00b574ff..2691715e6 100644 --- a/resources/icons/fullscreen.svg +++ b/resources/icons/fullscreen.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/grid.svg b/resources/icons/grid.svg index b94b8852a..d6929e11a 100644 --- a/resources/icons/grid.svg +++ b/resources/icons/grid.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/grip.svg b/resources/icons/grip.svg index 7bf189232..86eb08049 100644 --- a/resources/icons/grip.svg +++ b/resources/icons/grip.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/groups.svg b/resources/icons/groups.svg index c99a6b503..474237a0f 100644 --- a/resources/icons/groups.svg +++ b/resources/icons/groups.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/history.svg b/resources/icons/history.svg index ba6c4177e..3f5d475b8 100644 --- a/resources/icons/history.svg +++ b/resources/icons/history.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/image.svg b/resources/icons/image.svg index fcb5e8e85..55454fd75 100644 --- a/resources/icons/image.svg +++ b/resources/icons/image.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/resources/icons/images.svg b/resources/icons/images.svg index 4dd3cf4e6..9966f4772 100644 --- a/resources/icons/images.svg +++ b/resources/icons/images.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/include.svg b/resources/icons/include.svg index 48d2f0f5b..30a2c495b 100644 --- a/resources/icons/include.svg +++ b/resources/icons/include.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/info-filled.svg b/resources/icons/info-filled.svg index 0597dbdf2..20b8f3b42 100644 --- a/resources/icons/info-filled.svg +++ b/resources/icons/info-filled.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/info.svg b/resources/icons/info.svg index 1a24e012d..4082f2cde 100644 --- a/resources/icons/info.svg +++ b/resources/icons/info.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/leaderboard.svg b/resources/icons/leaderboard.svg index 9083330dc..1231490a2 100644 --- a/resources/icons/leaderboard.svg +++ b/resources/icons/leaderboard.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/light-mode.svg b/resources/icons/light-mode.svg index cf2961d2e..6ee1f2c93 100644 --- a/resources/icons/light-mode.svg +++ b/resources/icons/light-mode.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/link.svg b/resources/icons/link.svg index 3e8be1ce7..10117bc1e 100644 --- a/resources/icons/link.svg +++ b/resources/icons/link.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/list.svg b/resources/icons/list.svg index 3cfcee9e4..5dadaf1fa 100644 --- a/resources/icons/list.svg +++ b/resources/icons/list.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/lock-open.svg b/resources/icons/lock-open.svg index 20ff5b686..6855dd563 100644 --- a/resources/icons/lock-open.svg +++ b/resources/icons/lock-open.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/lock.svg b/resources/icons/lock.svg index 594763f58..cf10b4e57 100644 --- a/resources/icons/lock.svg +++ b/resources/icons/lock.svg @@ -1,9 +1 @@ - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/login.svg b/resources/icons/login.svg index b122b44a2..f6601cfdc 100644 --- a/resources/icons/login.svg +++ b/resources/icons/login.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/logout.svg b/resources/icons/logout.svg index b113f5a3a..b6d20b450 100644 --- a/resources/icons/logout.svg +++ b/resources/icons/logout.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/more.svg b/resources/icons/more.svg index 53ffb6554..5dc0c7cfb 100644 --- a/resources/icons/more.svg +++ b/resources/icons/more.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/new-user.svg b/resources/icons/new-user.svg index b58fcd548..76b450a84 100644 --- a/resources/icons/new-user.svg +++ b/resources/icons/new-user.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/notifications.svg b/resources/icons/notifications.svg index 52786954d..54bd7456c 100644 --- a/resources/icons/notifications.svg +++ b/resources/icons/notifications.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/oidc.svg b/resources/icons/oidc.svg index a9a2994a7..66a10efaf 100644 --- a/resources/icons/oidc.svg +++ b/resources/icons/oidc.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/open-book.svg b/resources/icons/open-book.svg index 5987d14e5..2e2f24da4 100644 --- a/resources/icons/open-book.svg +++ b/resources/icons/open-book.svg @@ -1,9 +1 @@ - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/page.svg b/resources/icons/page.svg index 1df12d85d..ab3985c73 100644 --- a/resources/icons/page.svg +++ b/resources/icons/page.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/palette.svg b/resources/icons/palette.svg index 114386302..903fa51d8 100644 --- a/resources/icons/palette.svg +++ b/resources/icons/palette.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/permission.svg b/resources/icons/permission.svg index a9a2994a7..66a10efaf 100644 --- a/resources/icons/permission.svg +++ b/resources/icons/permission.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/popular.svg b/resources/icons/popular.svg index 2ac44f151..84f4c180b 100644 --- a/resources/icons/popular.svg +++ b/resources/icons/popular.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/reference.svg b/resources/icons/reference.svg index 560ec5f37..b83dcafd1 100644 --- a/resources/icons/reference.svg +++ b/resources/icons/reference.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/resources/icons/reply.svg b/resources/icons/reply.svg index a50ddad7a..ab7119c97 100644 --- a/resources/icons/reply.svg +++ b/resources/icons/reply.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/role.svg b/resources/icons/role.svg index e7cad506d..5a274a8d0 100644 --- a/resources/icons/role.svg +++ b/resources/icons/role.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/saml2.svg b/resources/icons/saml2.svg index a9a2994a7..66a10efaf 100644 --- a/resources/icons/saml2.svg +++ b/resources/icons/saml2.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/save.svg b/resources/icons/save.svg index e8acc6594..7be214ab6 100644 --- a/resources/icons/save.svg +++ b/resources/icons/save.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/search.svg b/resources/icons/search.svg index 490937044..c19bbf001 100644 --- a/resources/icons/search.svg +++ b/resources/icons/search.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/security.svg b/resources/icons/security.svg index 4fc0d20b9..0febc8301 100644 --- a/resources/icons/security.svg +++ b/resources/icons/security.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/settings.svg b/resources/icons/settings.svg index dc2d75f0e..b9b62e643 100644 --- a/resources/icons/settings.svg +++ b/resources/icons/settings.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/shortcuts.svg b/resources/icons/shortcuts.svg index 8d23aac2b..f3736f536 100644 --- a/resources/icons/shortcuts.svg +++ b/resources/icons/shortcuts.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/sort.svg b/resources/icons/sort.svg index 9a2e98f64..fa935ffcf 100644 --- a/resources/icons/sort.svg +++ b/resources/icons/sort.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/spanner.svg b/resources/icons/spanner.svg index 8ab25a247..d3eefb67d 100644 --- a/resources/icons/spanner.svg +++ b/resources/icons/spanner.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/resources/icons/star-circle.svg b/resources/icons/star-circle.svg index a7667e48f..cd50c44b5 100644 --- a/resources/icons/star-circle.svg +++ b/resources/icons/star-circle.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/star-outline.svg b/resources/icons/star-outline.svg index 4e83ab42b..ff50719b3 100644 --- a/resources/icons/star-outline.svg +++ b/resources/icons/star-outline.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/star.svg b/resources/icons/star.svg index c7686389d..60ffbf266 100644 --- a/resources/icons/star.svg +++ b/resources/icons/star.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/swap-vertical.svg b/resources/icons/swap-vertical.svg index 35a362c0b..d5166c082 100644 --- a/resources/icons/swap-vertical.svg +++ b/resources/icons/swap-vertical.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/tag.svg b/resources/icons/tag.svg index 1d92d2b18..6e976dfd5 100644 --- a/resources/icons/tag.svg +++ b/resources/icons/tag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/template.svg b/resources/icons/template.svg index 7c142124f..faee3c275 100644 --- a/resources/icons/template.svg +++ b/resources/icons/template.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/time.svg b/resources/icons/time.svg index 2b6e2820e..42cf02e4c 100644 --- a/resources/icons/time.svg +++ b/resources/icons/time.svg @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/upload.svg b/resources/icons/upload.svg index c9b0346a1..2c1318be2 100644 --- a/resources/icons/upload.svg +++ b/resources/icons/upload.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/user-preferences.svg b/resources/icons/user-preferences.svg index 5ae1773ca..6d1dc2259 100644 --- a/resources/icons/user-preferences.svg +++ b/resources/icons/user-preferences.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/user.svg b/resources/icons/user.svg index bdfbc5096..1e9c998bf 100644 --- a/resources/icons/user.svg +++ b/resources/icons/user.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/users-add.svg b/resources/icons/users-add.svg index ea568f2ff..c09ad550a 100644 --- a/resources/icons/users-add.svg +++ b/resources/icons/users-add.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/users.svg b/resources/icons/users.svg index e7cad506d..5a274a8d0 100644 --- a/resources/icons/users.svg +++ b/resources/icons/users.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/warning.svg b/resources/icons/warning.svg index b1d1ad02c..b8e8ba404 100644 --- a/resources/icons/warning.svg +++ b/resources/icons/warning.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/watch-ignore.svg b/resources/icons/watch-ignore.svg index 2c6ffc24a..4363a7127 100644 --- a/resources/icons/watch-ignore.svg +++ b/resources/icons/watch-ignore.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/watch.svg b/resources/icons/watch.svg index 0be661912..71fc7fe8c 100644 --- a/resources/icons/watch.svg +++ b/resources/icons/watch.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/webhooks.svg b/resources/icons/webhooks.svg index fff081413..8f97cd436 100644 --- a/resources/icons/webhooks.svg +++ b/resources/icons/webhooks.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 0c524c7c8f272acd4ae429f04f8678e2f8c7ba4b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 Mar 2024 16:31:13 +0000 Subject: [PATCH 18/59] Licensing: Added licenses app view Extracted many methods to a new "MetaController" in the process. --- app/App/HomeController.php | 45 ----------------- app/App/MetaController.php | 67 +++++++++++++++++++++++++ resources/views/help/licenses.blade.php | 64 +++++++++++++++++++++++ routes/web.php | 10 ++-- 4 files changed, 137 insertions(+), 49 deletions(-) create mode 100644 app/App/MetaController.php create mode 100644 resources/views/help/licenses.blade.php diff --git a/app/App/HomeController.php b/app/App/HomeController.php index 116f5c8a4..0585e0af5 100644 --- a/app/App/HomeController.php +++ b/app/App/HomeController.php @@ -9,7 +9,6 @@ use BookStack\Entities\Queries\QueryRecentlyViewed; use BookStack\Entities\Queries\QueryTopFavourites; use BookStack\Entities\Tools\PageContent; use BookStack\Http\Controller; -use BookStack\Uploads\FaviconHandler; use BookStack\Util\SimpleListOptions; use Illuminate\Http\Request; @@ -112,48 +111,4 @@ class HomeController extends Controller return view('home.default', $commonData); } - - /** - * Show the view for /robots.txt. - */ - public function robots() - { - $sitePublic = setting('app-public', false); - $allowRobots = config('app.allow_robots'); - - if ($allowRobots === null) { - $allowRobots = $sitePublic; - } - - return response() - ->view('misc.robots', ['allowRobots' => $allowRobots]) - ->header('Content-Type', 'text/plain'); - } - - /** - * Show the route for 404 responses. - */ - public function notFound() - { - return response()->view('errors.404', [], 404); - } - - /** - * Serve the application favicon. - * Ensures a 'favicon.ico' file exists at the web root location (if writable) to be served - * directly by the webserver in the future. - */ - public function favicon(FaviconHandler $favicons) - { - $exists = $favicons->restoreOriginalIfNotExists(); - return response()->file($exists ? $favicons->getPath() : $favicons->getOriginalPath()); - } - - /** - * Serve a PWA application manifest. - */ - public function pwaManifest(PwaManifestBuilder $manifestBuilder) - { - return response()->json($manifestBuilder->build()); - } } diff --git a/app/App/MetaController.php b/app/App/MetaController.php new file mode 100644 index 000000000..3d3a8d2c8 --- /dev/null +++ b/app/App/MetaController.php @@ -0,0 +1,67 @@ +view('misc.robots', ['allowRobots' => $allowRobots]) + ->header('Content-Type', 'text/plain'); + } + + /** + * Show the route for 404 responses. + */ + public function notFound() + { + return response()->view('errors.404', [], 404); + } + + /** + * Serve the application favicon. + * Ensures a 'favicon.ico' file exists at the web root location (if writable) to be served + * directly by the webserver in the future. + */ + public function favicon(FaviconHandler $favicons) + { + $exists = $favicons->restoreOriginalIfNotExists(); + return response()->file($exists ? $favicons->getPath() : $favicons->getOriginalPath()); + } + + /** + * Serve a PWA application manifest. + */ + public function pwaManifest(PwaManifestBuilder $manifestBuilder) + { + return response()->json($manifestBuilder->build()); + } + + /** + * Show license information for the application. + */ + public function licenses() + { + $this->setPageTitle('Licenses'); + + return view('help.licenses', [ + 'license' => file_get_contents(base_path('LICENSE')), + 'phpLibData' => file_get_contents(base_path('dev/licensing/php-library-licenses.txt')), + 'jsLibData' => file_get_contents(base_path('dev/licensing/js-library-licenses.txt')), + ]); + } +} diff --git a/resources/views/help/licenses.blade.php b/resources/views/help/licenses.blade.php new file mode 100644 index 000000000..a87d9e958 --- /dev/null +++ b/resources/views/help/licenses.blade.php @@ -0,0 +1,64 @@ +@extends('layouts.simple') + +@section('body') + +

+ +
 
+ +
+ +
+

BookStack License

+
{{ $license }}
+

BookStack® is a UK registered trade mark of Daniel Brown.

+
+ +
+

PHP Library Licenses

+
{{ $phpLibData }}
+
+ +
+

JavaScript Library Licenses

+
{{ $jsLibData }}
+
+ +
+

Other Licenses

+
BookStack makes heavy use of PHP: + License: PHP License, version 3.01 + License File: https://www.php.net/license/3_01.txt + Copyright: Copyright (c) 1999 - 2019 The PHP Group. All rights reserved. + Link: https://www.php.net/ + ----------- + BookStack uses Icons from Google Material Icons: + License: Apache License Version 2.0 + License File: https://github.com/google/material-design-icons/blob/master/LICENSE + Copyright: Copyright 2020 Google LLC + Link: https://github.com/google/material-design-icons + ----------- + BookStack is distributed with TinyMCE: + License: MIT + License File: https://github.com/tinymce/tinymce/blob/release/6.7/LICENSE.TXT + Copyright: Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. + Link: https://github.com/tinymce/tinymce +
+
+
+ +@endsection \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 4620cd08b..03595288f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use BookStack\Activity\Controllers as ActivityControllers; use BookStack\Api\ApiDocsController; use BookStack\Api\UserApiTokenController; use BookStack\App\HomeController; +use BookStack\App\MetaController; use BookStack\Entities\Controllers as EntityControllers; use BookStack\Http\Middleware\VerifyCsrfToken; use BookStack\Permissions\PermissionsController; @@ -18,9 +19,10 @@ use Illuminate\Support\Facades\Route; use Illuminate\View\Middleware\ShareErrorsFromSession; Route::get('/status', [SettingControllers\StatusController::class, 'show']); -Route::get('/robots.txt', [HomeController::class, 'robots']); -Route::get('/favicon.ico', [HomeController::class, 'favicon']); -Route::get('/manifest.json', [HomeController::class, 'pwaManifest']); +Route::get('/robots.txt', [MetaController::class, 'robots']); +Route::get('/favicon.ico', [MetaController::class, 'favicon']); +Route::get('/manifest.json', [MetaController::class, 'pwaManifest']); +Route::get('/licenses', [MetaController::class, 'licenses']); // Authenticated routes... Route::middleware('auth')->group(function () { @@ -350,4 +352,4 @@ Route::post('/password/reset', [AccessControllers\ResetPasswordController::class // Metadata routes Route::view('/help/wysiwyg', 'help.wysiwyg'); -Route::fallback([HomeController::class, 'notFound'])->name('fallback'); +Route::fallback([MetaController::class, 'notFound'])->name('fallback'); From a2fd80954bfd0b2a98d54b9ad2c68628cd1e2b1c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 23 Mar 2024 22:04:18 +0000 Subject: [PATCH 19/59] Licensing: Added links and tests for new licenses endpoint For #4907 --- app/App/MetaController.php | 2 +- dev/build/esbuild.js | 4 ++++ lang/en/settings.php | 8 ++++++++ readme.md | 2 ++ resources/views/help/licenses.blade.php | 23 ++++++++++------------ resources/views/settings/layout.blade.php | 4 +++- tests/LicensesTest.php | 24 +++++++++++++++++++++++ 7 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 tests/LicensesTest.php diff --git a/app/App/MetaController.php b/app/App/MetaController.php index 3d3a8d2c8..1515b4f7e 100644 --- a/app/App/MetaController.php +++ b/app/App/MetaController.php @@ -56,7 +56,7 @@ class MetaController extends Controller */ public function licenses() { - $this->setPageTitle('Licenses'); + $this->setPageTitle(trans('settings.licenses')); return view('help.licenses', [ 'license' => file_get_contents(base_path('LICENSE')), diff --git a/dev/build/esbuild.js b/dev/build/esbuild.js index c47727c2c..53fbf0189 100644 --- a/dev/build/esbuild.js +++ b/dev/build/esbuild.js @@ -30,6 +30,10 @@ esbuild.build({ format: 'esm', minify: isProd, logLevel: 'info', + banner: { + js: '// See the "/licenses" URI for full package license details', + css: '/* See the "/licenses" URI for full package license details */', + }, }).then(result => { fs.writeFileSync('esbuild-meta.json', JSON.stringify(result.metafile)); }).catch(() => process.exit(1)); diff --git a/lang/en/settings.php b/lang/en/settings.php index 7b7f5d2a2..f4c84092c 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/readme.md b/readme.md index 5457ddfb5..17e1a05f6 100644 --- a/readme.md +++ b/readme.md @@ -158,3 +158,5 @@ Note: This is not an exhaustive list of all libraries and projects that would be * [PHPStan](https://phpstan.org/) & [Larastan](https://github.com/nunomaduro/larastan) - _[MIT](https://github.com/phpstan/phpstan/blob/master/LICENSE) and [MIT](https://github.com/nunomaduro/larastan/blob/master/LICENSE.md)_ * [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) - _[BSD 3-Clause](https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt)_ * [JakeArchibald/IDB-Keyval](https://github.com/jakearchibald/idb-keyval) - _[Apache-2.0](https://github.com/jakearchibald/idb-keyval/blob/main/LICENCE)_ + +For a detailed breakdown of the JavaScript & PHP projects imported & used via NPM & composer package managers, along with their licenses, please see the [dev/licensing/js-library-licenses.txt](dev/licensing/js-library-licenses.txt) and [dev/licensing/php-library-licenses.txt](dev/licensing/php-library-licenses.txt) files. \ No newline at end of file diff --git a/resources/views/help/licenses.blade.php b/resources/views/help/licenses.blade.php index a87d9e958..1eb293523 100644 --- a/resources/views/help/licenses.blade.php +++ b/resources/views/help/licenses.blade.php @@ -7,39 +7,36 @@
 
-

Licenses

-

- This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. - Many projects listed may only be used in a development context. -

+

{{ trans('settings.licenses') }}

+

{{ trans('settings.licenses_desc') }}

-

BookStack License

+

{{ trans('settings.licenses_bookstack') }}

{{ $license }}

BookStack® is a UK registered trade mark of Daniel Brown.

-

PHP Library Licenses

+

{{ trans('settings.licenses_php') }}

{{ $phpLibData }}
-

JavaScript Library Licenses

+

{{ trans('settings.licenses_js') }}

{{ $jsLibData }}
-

Other Licenses

+

{{ trans('settings.licenses_other') }}

BookStack makes heavy use of PHP: License: PHP License, version 3.01 License File: https://www.php.net/license/3_01.txt diff --git a/resources/views/settings/layout.blade.php b/resources/views/settings/layout.blade.php index 94a8f7725..a59b58d53 100644 --- a/resources/views/settings/layout.blade.php +++ b/resources/views/settings/layout.blade.php @@ -18,8 +18,10 @@
{{ trans('settings.system_version') }}
diff --git a/tests/LicensesTest.php b/tests/LicensesTest.php new file mode 100644 index 000000000..a7fb803c0 --- /dev/null +++ b/tests/LicensesTest.php @@ -0,0 +1,24 @@ +get('/licenses'); + $resp->assertOk(); + $resp->assertSee('Licenses'); + $resp->assertSee('PHP Library Licenses'); + $resp->assertSee('Dan Brown and the BookStack Project contributors'); + $resp->assertSee('doctrine/dbal'); + $resp->assertSee('@codemirror/lang-html'); + } + + public function test_licenses_linked_to_from_settings() + { + $resp = $this->asAdmin()->get('/settings/features'); + $html = $this->withHtml($resp); + $html->assertLinkExists(url('/licenses'), 'License Details'); + } +} From 3345680f7d7e2a7b199d2a2fd607c769f4c2a672 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 24 Mar 2024 11:58:31 +0000 Subject: [PATCH 20/59] Licensing: Added license gen as composer command --- composer.json | 4 ++++ dev/licensing/gen-js-licenses | 2 +- dev/licensing/gen-php-licenses | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 79246b7ac..b22c7b44d 100644 --- a/composer.json +++ b/composer.json @@ -72,6 +72,10 @@ "lint": "phpcs", "test": "phpunit", "t-reset": "@php artisan test --recreate-databases", + "build-licenses": [ + "@php ./dev/licensing/gen-js-licenses", + "@php ./dev/licensing/gen-php-licenses" + ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi" diff --git a/dev/licensing/gen-js-licenses b/dev/licensing/gen-js-licenses index dfb2f6651..191a16f30 100644 --- a/dev/licensing/gen-js-licenses +++ b/dev/licensing/gen-js-licenses @@ -22,7 +22,7 @@ $licenseInfo = implode($outputSeparator, $packageOutput) . "\n"; file_put_contents($outputPath, $licenseInfo); echo "License information written to {$outputPath}\n"; -echo implode("\n", getWarnings()); +echo implode("\n", getWarnings()) . "\n"; function packageToOutput(string $packagePath): string { diff --git a/dev/licensing/gen-php-licenses b/dev/licensing/gen-php-licenses index ed5a21c5a..79f4c2ff6 100644 --- a/dev/licensing/gen-php-licenses +++ b/dev/licensing/gen-php-licenses @@ -19,7 +19,7 @@ $licenseInfo = implode($outputSeparator, $packageOutput) . "\n"; file_put_contents($outputPath, $licenseInfo); echo "License information written to {$outputPath}\n"; -echo implode("\n", getWarnings()); +echo implode("\n", getWarnings()) . "\n"; function packageToOutput(stdClass $package) : string { global $rootPath; From 76c71662683afff885ac086d259752336f855e1f Mon Sep 17 00:00:00 2001 From: Martin Rys Date: Tue, 26 Mar 2024 12:31:54 +0100 Subject: [PATCH 21/59] Use zopfli for oxipng for extra 3KB~ --- public/book_default_cover.png | Bin 3448 -> 3232 bytes public/icon-128.png | Bin 2976 -> 2965 bytes public/icon-180.png | Bin 5769 -> 5744 bytes public/icon-32.png | Bin 753 -> 746 bytes public/icon-64.png | Bin 1374 -> 1367 bytes public/icon.ico | Bin 10619 -> 10614 bytes public/loading.gif | Bin 11098 -> 8986 bytes public/loading_error.png | Bin 1201 -> 1156 bytes public/logo.png | Bin 3302 -> 3256 bytes public/user_avatar.png | Bin 3423 -> 3180 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/public/book_default_cover.png b/public/book_default_cover.png index bf73b67a35f09b99c76724e48a17c0f6d96928d6..6d088d8b82caf77c94e42ac7f1bd81815c445ed1 100644 GIT binary patch delta 3128 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 Pp8o<^M*inx8E@)VE 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 diff --git a/public/icon-180.png b/public/icon-180.png index 7627b523c89c13ee9deda03779473c34dcfa9e41..4d4ceac3486bb74f282bd644e8dd675bc45681eb 100644 GIT binary patch delta 5133 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 Hu0mjft0Lw( diff --git a/public/icon-32.png b/public/icon-32.png index de94f373da2948976bb6212daf66c2f2a54389f4..deac72d893e629e949f67f682ee7e543e5f07ebe 100644 GIT binary patch delta 690 zcmV;j0!{t#1?mNmM1S}D{`LC(^!fbr`1|tr`tkPo>+<{R@%riT`RMQX=kE9B?e^gB z_1^CE-R$$$==Ig-^wj3_)8+BfdzSi!&)a|^}?7PzH zy3y&m(CD(v>Zr=*r^)4>#O9sDrjEso7+u+GC{IVx!n$qSsZO*HoO=Q=8RDnAk>_)jMf^9)fbA?6p7Lih|vv)(BmYbWdHyG0d!JMQvg8b*k%9#0iQ`k zK~#9!ol^yt<$o{?>u0LFpP8ANnMwD*&&J6x&!}AKIeN0A{Q(a1m$WT^7==uq(x&(f z=z8O1`k3~1fl1Wg!>MTdfOl5!*yX7KV4mkPG^YbHwmLyG|Kx%wimwNLhx}F%mA# zw0>9(7=Hx4Qo2kS9nO@U3J;Hdr~KFe$D&?31DhN*Aw6{dB^Ho<+=1;8F*tHrssdOfOs{99MVU3n z)S%p!o!Z|{8@n%GdS0d0-wvcpRrNfqXZmE~F)O(O>$LfcJ%e+}@#U`Tkm>7v%k(et YAE4-m0sWU(GXMYp07*qoM6N<$f@uJRA^-pY delta 697 zcmV;q0!IDn1@Q%tM1Se<`H;Eb(c|x7qSxl__AHFh4TsQqtKHq~^T*rmQ=8TE`1|+! z{=C!dyVB~Y%I3P!={1qoMV8e_nAjhU*D;UNFpkom#O54~*52;)gt6V#=k#u=+2HT> zg|gn$+<{Z_xeVc*2dcGr^)5#?)RI);uML}7mC!J!sC;@hb#Z z`u&~5*Z=?k0d!JMQvg8b*k%9#0j5br zK~#9!os;QO!hb*zgtG=FO*mBW0wW<{z%xP3fd?KO9?AQ^kC|Pt5RoeFKNQtdvtN2< zw0|hAthLMDnVx@bFTW{;`~ zRw>z{4kAsA3RtDdI0_A91(k8MZQzG2GuQ>(`voB;1oZ~(i zmo^h%phyoqW@v;mv%W`NH%tF?fpmihxx;+a0`C%02f#^Bkv^+Y%0H)$jN{zkwiE-n z3B>nZ>CjffF?GrBGwJp6wlV#9a%QUPXn7%DR5I7;>^6Y{(kG9VAnXXK3j(800000NkvXXu0mjfZry#8 diff --git a/public/icon-64.png b/public/icon-64.png index 8642b24eba3e1549f05609932a0743f55f5a5214..afe4b766dbac3b5142c89294af8f7325d82b4ef1 100644 GIT binary patch delta 1027 zcmV+e1pNEn3fBs-V*!8PNklX`4W~TrDkYmTY zT5lMhIxj^j*33w<|N9*PFj~0z_yi0ej{PL1{`!F-<0Ih^2?VBxDFjGovLun1nS}`q z8t&gnQ3J6!%=uK#00t_4ETF>g?xR>uif?Xit3dz7mxCnX^%#GO2#JeGe^dZQP8A1xCJc0(r7GK3PZ1?G*6MYD*i{ zZW6{B|GvFxZV_eA`{QsLA#J*(pek7ZUn`;vz5C}GPOPqz5O4K;$sCzwgW zm}l4Vfk=P7Z1ehTz;_xXhBKDW?Be(K5j`l95|$R7;;K9miN~^$$!a$Gj4_iw zksuOU=3lBgEa*)UX+LhIn902MVVfIrauC|v24ySb3+Oy)d@6W z6uj$l9EYUUBqeO4sMz#6lRIk?6Qt##e#cv7Mz;#O2$Y`x99DRP1w;PXS=v`EjX4 zY@7xMWt~6CTg6&u{2R64*psUcld>B>=~W8Ct(d9_pVS&t92VJB*vj_q?^0U@kcRTl4DuGcRm( z6117TRZOytz&q`!D9*-@}VP; x+V%s(Kegnj#_*3lZrY&$m~jB3K6rlv{s9{;(s8!wO-29!002ovPDHLkV1m13?@s^# delta 1035 zcmV+m1oZpY3f>B^V*!8WNkls+P{=JV!3Cxbk8hTRk4zSBzPw=oQx!j-pzz+ggY|!s{LwvY0h1TsObLb9 zoIyk=bnMBf0E`VPK6PwLA_ju6R&+5z9YCwyrHD64CPEAr3s_oQnR_AyfaF_>*lo8$ zB7}82M15~x{<^qyfarLbKdAWHwc!&%XdF1scH=%*<~I;o{9H^BHUXH!`MgT8FVB5< ztC-|!@L0HWa3OyJq_>l{X*hT-QimqIn}ErH&pPlRKAW+G4l7ryqS`ruTig=kXl##4 z3d!(5Jit464i-w{AyQ4fNr8HPMLdE*fo(K`#5`ICw5Dx{$I-m$i-#zGZb`M12;%?I zOD09FdWD^%lsE;2dw&OF3RpjFQrk}e#Eb96G$^gZIVXR$DSOEVJ5bPh>l!0*(XIvpPC>EQe~>{#0Nd<^mbB zr7?eugGPVQ!fX0XjLq${4`k}KfY)mS=5dN6c`W}7ivRiz&i963AJqR8P*~;SRF7~l zjb)=+(`+=%giM+;fo-kvLz=^_wwlBI_j5U9($ikHwW&5PPUu){rIZqQBSuzJO{2)UemQR1lNDBQ>8in3j3k!=jj8B0m`}%?t zC3)n729b!gAiP)R$Y{b#Tl9jm4wq1=_Ibh4j3*iGjBd}fZa~=KL71&`GP2-EHueGW z7j32Pc?+jHlWZKHgC_CEExJSNEPO%>jy<`~OsZ}iioOygY{hb0D))wMq%^Gs4LQPO zVgY~T18T05PFS(@&IhVEpMBIOEz~yq+@D}}%V`3ujMj_!m0omFt4W7K* z@eJOQTXd{AJbArjstWKf{VmG&1SY%S@+GV=(jb`picM&&j&9M(0I*@hEouX^d}i>N z0%rNpA(X$wfmuJbXjEhNk3DMISpm4&XMeHcMSPh52OBNYaq(kGjQ{`u07*qoM6Lru FV1gz?@5lfE diff --git a/public/icon.ico b/public/icon.ico index e4752690c711ba2aea5d32663ae6408bd6602e3c..2581b9b335f6be741db4e9eba6b957a08208aaf8 100644 GIT binary patch delta 10553 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 HlR+su{oe+` delta 10558 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 Mi~vIjp_4o*IxEl_*Z=?k diff --git a/public/loading.gif b/public/loading.gif index 5bcdebec3069f64d0be4edc0879a67641c0d9ae4..9efe6b216cdba6687bc2c9c3e5ad3acc3d0fbdb3 100644 GIT binary patch delta 7886 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 diff --git a/public/loading_error.png b/public/loading_error.png index 7030b89e97d1ef734ec41a9caf8190a3fbda50b7..e50039352e2f3cc890bff78feef5039d464c1d0a 100644 GIT binary patch delta 1056 zcmV+*1mF9y34{rdB!6XTLqkw$V`BgSc-oZFGr(109LMqRb8fbc>m|D_+cplaZEk7I zwmH`r$83*HE!mxVGGF|r&tv>S*%j6!sTw^Y5=|$kjv8v6J!h`9_9F!KXa@9C^;CSw zA3VJpnrw#R}B!yfUe2U7X)!z z_G@4LSlTCzf^>5F)M22s0Ia@Wto>r$pNxRg7jPPpr~%6CuQsI1(vfgR2LJ@nz!RM@ zP4)vF7{wSSFc~Wv83Ke!(~SU8tfZLAD2D!LeLK0H$z;$76F|qxaAHJI<$91c`15a5 z-afqn5DkVx&3}ic`OF2i*TRQYrulBSX@1xPmiurj`g4737Yuv>mQ_FdoI9cMQaFC@ zXP>qaPON}7cj9VN1;7F*UN1a72o2{z^UF|gp8U5T@=~Z%+9HD?9{<^C~1_DfE;M9?Ub9Q9l+@vxRTp|M}jtrcm zBLn9mm7%~E88~c_fx{LVIBb!D!xkAhY>|P(78y8f`|B>LggrD4>j6Xns&afO{)xhF{H3&=9S2QeqJRf?D@U-Ef#IuV> z+%16{47V$8e%wmAF>{;erqL}Z8d|i+Xtve5OMei6Sb-r0Baa3sjAIz?Fe+m3#2AaA z7$dd@c8vcB6A(=x=s;|O5Jr#=03yIm0Iy(h4%Qsg5%dFuh(HqYCc{!09D-cL!U&lW zSt9^PoX&7w2Is|r*AQN6ctt{m3)DAI2Fc*OsPfv&OEj;?~rQmLANGBF8@dSL;&hS|Fw*7VVJu}VE z)G*KU3NwB)EzsahlPD+KlZYDEylS^a&2kAr7vKEJv5;AmSzCWciSf>lqmh5s@A}fR zwo!%IIO?9(jyU#ZW?YpIV;A^)Ywvm;oN%N_|HZGkFIQ*9w*()m5ZJb8qUH74hB;Xq zZYAjEO0H99n4dRe*XxM0y9zvSoDeh3Qe~XWSzPJ)rO~lTXM=}?;C{_em}u`l*dM7Kw(gjwP{LaM+h9)9yRB;P^YYKUU2l8;XDy@k;i8F>Y8%cnFfedVp2iqg zKiAX6F{I+w+nc9zn;j%v6Qey6X9{T?T{_e6QkSBSE{&Xm2&niSLd zV>9pP9bcee&Y6hlIQOmRtDdhg3!KfLWuDdFd~5El?~ZFvoUeNw^<-zfbeGN{wmBOZ z({m1_nl(0`eYlE+&+I`9uSGhu-e$qXdggOC8&2o&g{u~9(3HtJU@2WNvzJ4<;22v> zTJa901FAqhz7G2sS8Bjc!w6q?1a-`Q{uO_9pt+m zKl`A}&A8;Xi61(0P6r%SIPjM_rrWWh`u{cwmL1(Q? zhQ}$lI^PY*&)pz%Eo*XR(ZxSPdb3}ZaBQkto3mTt&&;Y7g@$@^S$|&dnG(RvG$VkS zZyR|yFWK9)?*GC5jrGUwmTieDR6l3>Ab}ed>xHk^{WB%|KyRG(jUwJ1EBAbB@XdZJ z{&o5Tg>$d-r|tjxR$k?Q#IN={`;Gpwepz4q`|QDd)4Io>ZZEhW@>lGw`JZRU+wFV) zTztmwRsZIf^PWnt2f{q_*Zp{Me0h+aVfNf-KbKrwUcbO@;n$ZN{kP3t{%)VZhtyX6 zpqi7#S&UCl8^+)H8T9eaq07@Z?$h|D`fVlaZvFqY#s{~n`Q?}JoO?Fgz~x4RvDy8+ zPiM8;vu{L5&pB)U7Z^$EIlK10oV}Fq`j&~-7PIq>gcF(lZlqY>HGeL($jfZg=D}zg`nyYB5`WkznFvW;<)Wk{vt$Y81DuoiFqqlEmhm)#sY7d#umu StN}31GI+ZBxvXBo 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 delta 3258 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 ATmS$7 delta 2501 zcmV;$2|D)d7~dMOMgwjN14%?dRCwC#-A!+lRTziy`A;iFU5kyaC>uAe3uM8fHO5#Z zwD>}mt-?-NY!YckJyX3m@^1(PuhCX+x67k>Z%0Kl@KRFafPnps?<%wTG9F11Rj zt}E{@{_A=LZ-r%OswX$FF|C_OS5)SDdYRHPa&7vlI^9}db=B1=rnMYwZs)%kP|E;>Ap2-!f+5HD}n^r&gB=ajmtu4*E1I_18Gs7bDQ)OCrD7)zdb1Wjy zR)1x=>Tzc3TxLbNmRRj@hPirH+93n4{LEzC+FH{s z6ZzaY)AgyfO=db@WxgJDy(vSx_b_31X8)A2mG3ZRU*vr*=@G;wIWj0+s0F0paSQjJ`CjWUMnHfBcT)IQo+nSV;lsWi`XvobBW_EX2m4Y~Dts)(dhMP!kemN>nA za;uMvx{V$=_62?Hj*{X|Jz1WXW1Hw>Vxt_pP9F;;X*rgirI3MVp> zI4sxhr;vfPTuZZE3gF`%Eabo~8*buWx%M3kIRlHlJWh&qW;=xptdwg_6k-zv*L1Gw zL?=4YiH_p@v%{AZvQQz%syURvgm`hulapg(^fB?C9Q&F+CQf-ie&iH=Y*fpwHPkUu zCAW@K$H+0c^$B&1^rq!hmVZmSnRYpKfi`Ax+@%814ql&R}^Kxc>jw;q3<0#o-XS^h7TctP8I}`Ww0{UDvrjI(P@qLP zUrow^JiDZV%CTW4dB)onUE4Sv!rJ??B0Jkkh0yjWvL9#=-XDr;h5`}H-lK@taj;Mn zr-u~H=wr-3j={Vlnf#vV$MPbJxC9zg6fZIPn06|H7UmvRVZDOe#@HjvG%2th8Kxdv zVL?Hyr?~@#G6l4gpMTJO7-QX@K%X8~5cz3l?Z@Dd0vP3cI9JY%$lRfm%=sVo?&T$_ zFpT5)`B_9OYa>{UZfd2WwU+4OfV601iI9~MQIrWYBQDIG8M~=1(x_F7ZdP8RW?D#@ zhPY9i#EpR)4O~Ud?1DC7Z_z$7=bV}M$oKOn{2n-$m*;&RyMH9B<*^ZF57_7IIeF+E z$L&_?ZZzuju5Ctk>9<2N~kv)y1gB^RYL+)?y{ z;pcM8Kn3^D{o-&yu88)MrH}NECX}W0X68ou&DSr*%0lrTnwwN|WVRkW>$u!Lpnn=DY<$2^`Fb)qG+VKp&|f5iho*#ejEtPy+-`*!l*A{=KouY!BpYNLAzH1W`UICL~0~~)056rW&Hfhor)BMtT=&TrH zo(7%q21y&7Q%>z2N&AesKS9ygfk$R(S(-R=w9HwJt{>*pUP)@C=>F4Zu1I4wN;_*) zWd8WJ!n?o^>RKXIfnb5$aUq)NjI(3aUNbF`*hpzgu1jp63wOqoBy5@Ek#MM6o=OMH zJ2$eH&klcsm9e>T<;eL^I8smM`P4P`cJz&MZpW?tH@Zka4`$-AXt(mFI~2ah2VO4K zeVm_4Deo4J?5XoltNT3CUlQn%r52*GS5(Mt zTes|z<%;H6$m^nwRW*SgVK4WG?p57gMQdQ@5{I`2r6Q52fNgI5?|xgXGy~ z->mlECU5;PRpZ1aS1SLsdtIu^*hD8P_xXR>RGke+qGqSpq$+LQ61DnrcxS5A^@Ed9 zrGb}H#a3Mt^*Qugs@yNLQJM4SQuUs@B5JaKLGr)cu|BGC^;LTR#t<&&3C&Zci*VktEVD!KWcy2yPqO!BaUAi_<1C9cC&&_oQ#akn4vdvsvY@y zN55tsiF~~vUo&STTd%3t)R|a8tyn?7dq%0cPuJOJ#Wpq8i9EfhU30HQp2nqX?%K%H zb<#DrDzY?tSi0s8Z;l+DSFRrqM2>a{*N;t+qeq47$NiC`J;L?lzR1y?!qr*#`+h>W zehfv9UKg$(J0nM)2<*$z$dPXSi51f_#k^dJj_8Pv=!lN!h%P#!BRZlZI-(;wq9Zz@ zBRZlZI-(;wq9eNKh>qxpj_8Pv=!lN!h>qxpj_8OElQ9e?lW+qC7u4eqz_yoOaL9}w P00000NkvXXu0mjfQl0Po From 06ef95dc5fc4635379698cf73bd36d4b370aab69 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Tue, 26 Mar 2024 16:30:04 +0000 Subject: [PATCH 22/59] Change to allow override of CA CERT for LDAPS Using the env LDAP_TLS_CACERTFILE to set a file to use to override the CA CERT used to verify LDAPS connections. This is to make this process easier for docker use. --- app/Access/LdapService.php | 6 ++++++ app/Config/services.php | 1 + 2 files changed, 7 insertions(+) diff --git a/app/Access/LdapService.php b/app/Access/LdapService.php index 9d2667635..56e7aba04 100644 --- a/app/Access/LdapService.php +++ b/app/Access/LdapService.php @@ -209,6 +209,12 @@ class LdapService $this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER); } + // Specify CA Cert file for LDAP. + // This option works globally and must be set before a connection is created. + if ($this->config['tls_cacertfile']) { + $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTFILE, $this->config['tls_cacertfile']); + } + $ldapHost = $this->parseServerString($this->config['server']); $ldapConnection = $this->ldap->connect($ldapHost); diff --git a/app/Config/services.php b/app/Config/services.php index a035f1056..a407b5dc8 100644 --- a/app/Config/services.php +++ b/app/Config/services.php @@ -133,6 +133,7 @@ return [ 'group_attribute' => env('LDAP_GROUP_ATTRIBUTE', 'memberOf'), 'remove_from_groups' => env('LDAP_REMOVE_FROM_GROUPS', false), 'tls_insecure' => env('LDAP_TLS_INSECURE', false), + 'tls_cacertfile' => env('LDAP_TLS_CACERTFILE', false), 'start_tls' => env('LDAP_START_TLS', false), 'thumbnail_attribute' => env('LDAP_THUMBNAIL_ATTRIBUTE', null), ], From 18269f2c6036b346d100fd2b82dab600f4ba362f Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Wed, 27 Mar 2024 13:17:25 +0000 Subject: [PATCH 23/59] Add LDAP_TLS_CACERTFILE to example env file --- .env.example.complete | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example.complete b/.env.example.complete index e8520a24c..3f1a8ab94 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -219,6 +219,7 @@ LDAP_USER_FILTER=false LDAP_VERSION=false LDAP_START_TLS=false LDAP_TLS_INSECURE=false +LDAP_TLS_CACERTFILE=false LDAP_ID_ATTRIBUTE=uid LDAP_EMAIL_ATTRIBUTE=mail LDAP_DISPLAY_NAME_ATTRIBUTE=cn From f5e6f9574da1202d66de482280a0d952fd3ed524 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Apr 2024 14:41:51 +0100 Subject: [PATCH 24/59] JS Build: Split markdown to own file, updated packages Markdown-related code was growing, representing half of app.js main bundle code while only being needed in one view/scenario. This extracts markdown related code to its own built file. Related to #4858 --- dev/build/esbuild.js | 1 + package-lock.json | 727 ++++++++++-------- package.json | 3 +- resources/js/components/markdown-editor.js | 25 +- .../js/markdown/{editor.js => index.mjs} | 0 5 files changed, 420 insertions(+), 336 deletions(-) rename resources/js/markdown/{editor.js => index.mjs} (100%) diff --git a/dev/build/esbuild.js b/dev/build/esbuild.js index 53fbf0189..c5b3c9ef3 100644 --- a/dev/build/esbuild.js +++ b/dev/build/esbuild.js @@ -13,6 +13,7 @@ const entryPoints = { app: path.join(__dirname, '../../resources/js/app.js'), code: path.join(__dirname, '../../resources/js/code/index.mjs'), 'legacy-modes': path.join(__dirname, '../../resources/js/code/legacy-modes.mjs'), + markdown: path.join(__dirname, '../../resources/js/markdown/index.mjs'), }; // Locate our output directory diff --git a/package-lock.json b/package-lock.json index 134911378..63b0d2478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@ssddanbrown/codemirror-lang-twig": "^1.0.0", "codemirror": "^6.0.1", "idb-keyval": "^6.2.1", - "markdown-it": "^13.0.2", + "markdown-it": "^14.1.0", "markdown-it-task-lists": "^2.1.1", "snabbdom": "^3.5.1", "sortablejs": "^1.15.1" @@ -37,7 +37,6 @@ "eslint-plugin-import": "^2.29.0", "livereload": "^0.9.3", "npm-run-all": "^4.1.5", - "punycode": "^2.3.1", "sass": "^1.69.5" } }, @@ -51,9 +50,9 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz", + "integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -156,13 +155,14 @@ } }, "node_modules/@codemirror/lang-xml": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz", - "integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/xml": "^1.0.0" } @@ -181,9 +181,9 @@ } }, "node_modules/@codemirror/legacy-modes": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.3.3.tgz", - "integrity": "sha512-X0Z48odJ0KIoh/HY8Ltz75/4tDYc9msQf1E/2trlxFaFFhgjpVHjZ/BCXe1Lk7s4Gd67LL/CeEEHNI+xHOiESg==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.0.tgz", + "integrity": "sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==", "dependencies": { "@codemirror/language": "^6.0.0" } @@ -225,9 +225,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.1.tgz", - "integrity": "sha512-sBfP4rniPBRQzNakwuQEqjEuiJDWJyF2kqLLqij4WXRoVwPPJfjx966Eq3F7+OPQxDtMt/Q9MWLoZLWjeveBlg==", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.1.tgz", + "integrity": "sha512-wLw0t3R9AwOSQThdZ5Onw8QQtem5asE7+bPlnzc57eubPqiuJKIzwjMZ+C42vQett+iva+J8VgFV4RYWDBh5FA==", "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -235,9 +235,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", - "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -251,9 +251,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", - "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -267,9 +267,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", - "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -283,9 +283,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", - "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -299,9 +299,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", - "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -315,9 +315,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", - "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -331,9 +331,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", - "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -347,9 +347,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", - "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -363,9 +363,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", - "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -379,9 +379,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", - "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -395,9 +395,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", - "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -411,9 +411,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", - "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -427,9 +427,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", - "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -443,9 +443,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", - "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -459,9 +459,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", - "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -475,9 +475,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", - "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -491,9 +491,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", - "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -507,9 +507,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", - "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -523,9 +523,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", - "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -539,9 +539,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", - "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -555,9 +555,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", - "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -571,9 +571,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", - "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -587,9 +587,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", - "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -650,9 +650,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -686,9 +686,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@lezer/common": { @@ -707,9 +707,9 @@ } }, "node_modules/@lezer/generator": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-1.6.0.tgz", - "integrity": "sha512-mDwFNchv4jBEoZBaZbr5GlKR7BM6W/ZanTOZN6p4avuzcmYHTZ0nIbwtBqvXoeBrqmFSvL2zHL5TX9FWkXKc2w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-1.7.0.tgz", + "integrity": "sha512-IJ16tx3biLKlCXUzcK4v8S10AVa2BSM2rB12rtAL6f1hL2TS/HQQlGCoWRvanlL2J4mCYEEIv9uG7n4kVMkVDA==", "dev": true, "dependencies": { "@lezer/common": "^1.1.0", @@ -728,9 +728,9 @@ } }, "node_modules/@lezer/html": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.8.tgz", - "integrity": "sha512-EXseJ3pUzWxE6XQBQdqWHZqqlGQRSuNMBcLb6mZWS2J2v+QZhOObD+3ZIKIcm59ntTzyor4LqFTb72iJc3k23Q==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz", + "integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==", "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", @@ -738,9 +738,9 @@ } }, "node_modules/@lezer/javascript": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz", - "integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==", + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.14.tgz", + "integrity": "sha512-GEdUyspTRgc5dwIGebUk+f3BekvqEWVIYsIuAC3pA8e8wcikGwBZRWRa450L0s8noGWuULwnmi4yjxTnYz9PpA==", "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", @@ -766,9 +766,9 @@ } }, "node_modules/@lezer/markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.2.0.tgz", - "integrity": "sha512-d7MwsfAukZJo1GpPrcPGa3MxaFFOqNp0gbqF+3F7pTeNDOgeJN1muXzx1XXDPt+Ac+/voCzsH7qXqnn+xReG/g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz", + "integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==", "dependencies": { "@lezer/common": "^1.0.0", "@lezer/highlight": "^1.0.0" @@ -785,9 +785,9 @@ } }, "node_modules/@lezer/xml": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.4.tgz", - "integrity": "sha512-WmXKb5eX8+rRfZYSNRR5TPee/ZoDgBdVS/rj1VCJGDKa5gNldIctQYibCoFVyNhvZsyL/8nHbZJZPM4gnXN2Vw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.5.tgz", + "integrity": "sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==", "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", @@ -952,34 +952,16 @@ } }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -990,15 +972,16 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -1088,12 +1071,15 @@ "dev": true }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { @@ -1308,6 +1294,57 @@ "node": ">= 8" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1393,9 +1430,9 @@ "dev": true }, "node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -1413,18 +1450,22 @@ } }, "node_modules/es-abstract": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", - "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.6", + "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", @@ -1432,15 +1473,16 @@ "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", @@ -1448,17 +1490,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.1", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -1467,12 +1509,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -1494,15 +1530,27 @@ "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -1535,9 +1583,9 @@ } }, "node_modules/esbuild": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", - "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -1547,29 +1595,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.1", - "@esbuild/android-arm": "0.20.1", - "@esbuild/android-arm64": "0.20.1", - "@esbuild/android-x64": "0.20.1", - "@esbuild/darwin-arm64": "0.20.1", - "@esbuild/darwin-x64": "0.20.1", - "@esbuild/freebsd-arm64": "0.20.1", - "@esbuild/freebsd-x64": "0.20.1", - "@esbuild/linux-arm": "0.20.1", - "@esbuild/linux-arm64": "0.20.1", - "@esbuild/linux-ia32": "0.20.1", - "@esbuild/linux-loong64": "0.20.1", - "@esbuild/linux-mips64el": "0.20.1", - "@esbuild/linux-ppc64": "0.20.1", - "@esbuild/linux-riscv64": "0.20.1", - "@esbuild/linux-s390x": "0.20.1", - "@esbuild/linux-x64": "0.20.1", - "@esbuild/netbsd-x64": "0.20.1", - "@esbuild/openbsd-x64": "0.20.1", - "@esbuild/sunos-x64": "0.20.1", - "@esbuild/win32-arm64": "0.20.1", - "@esbuild/win32-ia32": "0.20.1", - "@esbuild/win32-x64": "0.20.1" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/escape-string-regexp": { @@ -1585,16 +1633,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -1679,9 +1727,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -1937,9 +1985,9 @@ } }, "node_modules/flatted": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.0.tgz", - "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/for-each": { @@ -2208,9 +2256,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -2386,6 +2434,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -2493,12 +2556,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2644,11 +2710,11 @@ } }, "node_modules/linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/livereload": { @@ -2724,18 +2790,19 @@ "dev": true }, "node_modules/markdown-it": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", - "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dependencies": { "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdown-it-task-lists": { @@ -2744,9 +2811,9 @@ "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" }, "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" }, "node_modules/memorystream": { "version": "0.3.1", @@ -3026,28 +3093,29 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3057,27 +3125,28 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3287,6 +3356,14 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3441,13 +3518,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -3476,9 +3553,9 @@ } }, "node_modules/sass": { - "version": "1.71.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.0.tgz", - "integrity": "sha512-HKKIKf49Vkxlrav3F/w6qRuPcmImGVbIXJ2I3Kg0VMA+3Bav+8yE9G5XmP5lMj6nl4OlqbPftGAscNaNu28b8w==", + "version": "1.74.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.74.1.tgz", + "integrity": "sha512-w0Z9p/rWZWelb88ISOLyvqTWGmtmu2QJICqDBGyNnfG4OUnPX9BBjjYIXUpXCMOOg5MQWNpqzt876la1fsTvUA==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -3508,17 +3585,17 @@ "dev": true }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3570,12 +3647,12 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -3601,9 +3678,9 @@ "integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==" }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -3677,14 +3754,15 @@ } }, "node_modules/string.prototype.padend": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", - "integrity": "sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3694,14 +3772,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3711,28 +3790,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3772,9 +3854,9 @@ } }, "node_modules/style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" }, "node_modules/supports-color": { "version": "7.2.0", @@ -3869,15 +3951,16 @@ } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -3907,9 +3990,9 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -3927,9 +4010,9 @@ } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -4008,16 +4091,16 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 0ec36c129..ba2de38ba 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "eslint-plugin-import": "^2.29.0", "livereload": "^0.9.3", "npm-run-all": "^4.1.5", - "punycode": "^2.3.1", "sass": "^1.69.5" }, "dependencies": { @@ -47,7 +46,7 @@ "@ssddanbrown/codemirror-lang-twig": "^1.0.0", "codemirror": "^6.0.1", "idb-keyval": "^6.2.1", - "markdown-it": "^13.0.2", + "markdown-it": "^14.1.0", "markdown-it-task-lists": "^2.1.1", "snabbdom": "^3.5.1", "sortablejs": "^1.15.1" diff --git a/resources/js/components/markdown-editor.js b/resources/js/components/markdown-editor.js index fa06807a5..cd928de9f 100644 --- a/resources/js/components/markdown-editor.js +++ b/resources/js/components/markdown-editor.js @@ -1,5 +1,4 @@ import {Component} from './component'; -import {init as initEditor} from '../markdown/editor'; export class MarkdownEditor extends Component { @@ -20,17 +19,19 @@ export class MarkdownEditor extends Component { const settingInputs = settingContainer.querySelectorAll('input[type="checkbox"]'); this.editor = null; - initEditor({ - pageId: this.pageId, - container: this.elem, - displayEl: this.display, - inputEl: this.input, - drawioUrl: this.getDrawioUrl(), - settingInputs: Array.from(settingInputs), - text: { - serverUploadLimit: this.serverUploadLimitText, - imageUploadError: this.imageUploadErrorText, - }, + window.importVersioned('markdown').then(markdown => { + return markdown.init({ + pageId: this.pageId, + container: this.elem, + displayEl: this.display, + inputEl: this.input, + drawioUrl: this.getDrawioUrl(), + settingInputs: Array.from(settingInputs), + text: { + serverUploadLimit: this.serverUploadLimitText, + imageUploadError: this.imageUploadErrorText, + }, + }); }).then(editor => { this.editor = editor; this.setupListeners(); diff --git a/resources/js/markdown/editor.js b/resources/js/markdown/index.mjs similarity index 100% rename from resources/js/markdown/editor.js rename to resources/js/markdown/index.mjs From 0f6cb9ed840a61fe211321ae0d2d0cd0bafadfbd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Apr 2024 15:48:39 +0100 Subject: [PATCH 25/59] Content styles: Made links underlined for visibility Inline with A11y recommendations where color may not be reliable on its own. Tested various content link scenarios across chrome, safari & FF. For #4939 --- resources/sass/_content.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/sass/_content.scss b/resources/sass/_content.scss index bde52bb77..f84499364 100644 --- a/resources/sass/_content.scss +++ b/resources/sass/_content.scss @@ -113,6 +113,10 @@ video { max-width: 100%; } + + a { + text-decoration: underline; + } } /** From f05ec4cc26c3381a3bc8ea49f371b89bcf38140b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 15 Apr 2024 18:44:59 +0100 Subject: [PATCH 26/59] Tags: Stopped recycle bin tags being counted on index For #4892 Added test to cover. --- app/Activity/TagRepo.php | 3 ++- tests/Entity/TagTest.php | 20 +++++++++++++++++++- tests/Helpers/EntityProvider.php | 23 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/app/Activity/TagRepo.php b/app/Activity/TagRepo.php index 4f2dbed59..82c26b00e 100644 --- a/app/Activity/TagRepo.php +++ b/app/Activity/TagRepo.php @@ -38,7 +38,8 @@ class TagRepo DB::raw('SUM(IF(entity_type = \'book\', 1, 0)) as book_count'), DB::raw('SUM(IF(entity_type = \'bookshelf\', 1, 0)) as shelf_count'), ]) - ->orderBy($sort, $listOptions->getOrder()); + ->orderBy($sort, $listOptions->getOrder()) + ->whereHas('entity'); if ($nameFilter) { $query->where('name', '=', $nameFilter); diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php index c1240e955..729f93903 100644 --- a/tests/Entity/TagTest.php +++ b/tests/Entity/TagTest.php @@ -9,7 +9,7 @@ use Tests\TestCase; class TagTest extends TestCase { - protected $defaultTagCount = 20; + protected int $defaultTagCount = 20; /** * Get an instance of a page that has many tags. @@ -193,6 +193,24 @@ class TagTest extends TestCase $resp->assertSee('Tags can be assigned via the page editor sidebar'); } + public function test_tag_index_does_not_include_tags_on_recycle_bin_items() + { + $page = $this->entities->page(); + $page->tags()->create(['name' => 'DeleteRecord', 'value' => 'itemToDeleteTest']); + + $resp = $this->asEditor()->get('/tags'); + $resp->assertSee('DeleteRecord'); + $resp = $this->asEditor()->get('/tags?name=DeleteRecord'); + $resp->assertSee('itemToDeleteTest'); + + $this->entities->sendToRecycleBin($page); + + $resp = $this->asEditor()->get('/tags'); + $resp->assertDontSee('DeleteRecord'); + $resp = $this->asEditor()->get('/tags?name=DeleteRecord'); + $resp->assertDontSee('itemToDeleteTest'); + } + public function test_tag_classes_visible_on_entities() { $this->asEditor(); diff --git a/tests/Helpers/EntityProvider.php b/tests/Helpers/EntityProvider.php index 982063421..1897abefa 100644 --- a/tests/Helpers/EntityProvider.php +++ b/tests/Helpers/EntityProvider.php @@ -207,6 +207,29 @@ class EntityProvider return $draftPage; } + /** + * Send an entity to the recycle bin. + */ + public function sendToRecycleBin(Entity $entity) + { + $trash = app()->make(TrashCan::class); + + if ($entity instanceof Page) { + $trash->softDestroyPage($entity); + } elseif ($entity instanceof Chapter) { + $trash->softDestroyChapter($entity); + } elseif ($entity instanceof Book) { + $trash->softDestroyBook($entity); + } elseif ($entity instanceof Bookshelf) { + $trash->softDestroyBookshelf($entity); + } + + $entity->refresh(); + if (is_null($entity->deleted_at)) { + throw new \Exception("Could not send entity type [{$entity->getMorphClass()}] to the recycle bin"); + } + } + /** * Fully destroy the given entity from the system, bypassing the recycle bin * stage. Still runs through main app deletion logic. From 80ac66e0a665d23f05685753318b56b2307ce6f2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 16 Apr 2024 14:44:17 +0100 Subject: [PATCH 27/59] Code Editor: Added scala to language list For #4953 --- resources/views/pages/parts/code-editor.blade.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/views/pages/parts/code-editor.blade.php b/resources/views/pages/parts/code-editor.blade.php index 8700a4ccb..688fe67ef 100644 --- a/resources/views/pages/parts/code-editor.blade.php +++ b/resources/views/pages/parts/code-editor.blade.php @@ -24,9 +24,10 @@ @php $languages = [ 'Bash', 'CSS', 'C', 'C++', 'C#', 'Clojure', 'Dart', 'Diff', 'Fortran', 'F#', 'Go', 'Haskell', 'HTML', 'INI', - 'Java', 'JavaScript', 'JSON', 'Julia', 'Kotlin', 'LaTeX', 'Lua', 'MarkDown', 'MATLAB', 'MSSQL', 'MySQL', 'Nginx', 'OCaml', - 'Octave', 'Pascal', 'Perl', 'PHP', 'PL/SQL', 'PostgreSQL', 'Powershell', 'Python', 'Ruby', 'Rust', 'Scheme', 'Shell', 'Smarty', - 'SQL', 'SQLite', 'Swift', 'Twig', 'TypeScript', 'VBScript', 'VB.NET', 'XML', 'YAML', + 'Java', 'JavaScript', 'JSON', 'Julia', 'Kotlin', 'LaTeX', 'Lua', 'MarkDown', 'MATLAB', 'MSSQL', 'MySQL', + 'Nginx', 'OCaml', 'Octave', 'Pascal', 'Perl', 'PHP', 'PL/SQL', 'PostgreSQL', 'Powershell', 'Python', + 'Ruby', 'Rust', 'Scala', 'Scheme', 'Shell', 'Smarty', 'SQL', 'SQLite', 'Swift', + 'Twig', 'TypeScript', 'VBScript', 'VB.NET', 'XML', 'YAML', ]; @endphp From d640411adb4d828cffefd1248407eb93db2eaee2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 16 Apr 2024 15:19:51 +0100 Subject: [PATCH 28/59] OIDC: Cleaned up provider settings, added extra validation - Added endpoint validation to ensure HTTPS as per spec - Added some missing types - Removed redirectUri from OidcProviderSettings since it's not a provider-based setting, but a setting for the oauth client, so extracted that back to service. --- app/Access/Oidc/OidcProviderSettings.php | 19 +++++++++++++------ app/Access/Oidc/OidcService.php | 6 ++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/Access/Oidc/OidcProviderSettings.php b/app/Access/Oidc/OidcProviderSettings.php index 49ccab6f0..616bf1012 100644 --- a/app/Access/Oidc/OidcProviderSettings.php +++ b/app/Access/Oidc/OidcProviderSettings.php @@ -18,7 +18,6 @@ class OidcProviderSettings public string $issuer; public string $clientId; public string $clientSecret; - public ?string $redirectUri; public ?string $authorizationEndpoint; public ?string $tokenEndpoint; public ?string $endSessionEndpoint; @@ -38,7 +37,7 @@ class OidcProviderSettings /** * Apply an array of settings to populate setting properties within this class. */ - protected function applySettingsFromArray(array $settingsArray) + protected function applySettingsFromArray(array $settingsArray): void { foreach ($settingsArray as $key => $value) { if (property_exists($this, $key)) { @@ -52,7 +51,7 @@ class OidcProviderSettings * * @throws InvalidArgumentException */ - protected function validateInitial() + protected function validateInitial(): void { $required = ['clientId', 'clientSecret', 'redirectUri', 'issuer']; foreach ($required as $prop) { @@ -74,12 +73,20 @@ class OidcProviderSettings public function validate(): void { $this->validateInitial(); + $required = ['keys', 'tokenEndpoint', 'authorizationEndpoint']; foreach ($required as $prop) { if (empty($this->$prop)) { throw new InvalidArgumentException("Missing required configuration \"{$prop}\" value"); } } + + $endpointProperties = ['tokenEndpoint', 'authorizationEndpoint', 'userinfoEndpoint']; + foreach ($endpointProperties as $prop) { + if (is_string($this->$prop) && !str_starts_with($this->$prop, 'https://')) { + throw new InvalidArgumentException("Endpoint value for \"{$prop}\" must start with https://"); + } + } } /** @@ -87,7 +94,7 @@ class OidcProviderSettings * * @throws OidcIssuerDiscoveryException */ - public function discoverFromIssuer(ClientInterface $httpClient, Repository $cache, int $cacheMinutes) + public function discoverFromIssuer(ClientInterface $httpClient, Repository $cache, int $cacheMinutes): void { try { $cacheKey = 'oidc-discovery::' . $this->issuer; @@ -180,9 +187,9 @@ class OidcProviderSettings /** * Get the settings needed by an OAuth provider, as a key=>value array. */ - public function arrayForProvider(): array + public function arrayForOAuthProvider(): array { - $settingKeys = ['clientId', 'clientSecret', 'redirectUri', 'authorizationEndpoint', 'tokenEndpoint', 'userinfoEndpoint']; + $settingKeys = ['clientId', 'clientSecret', 'authorizationEndpoint', 'tokenEndpoint', 'userinfoEndpoint']; $settings = []; foreach ($settingKeys as $setting) { $settings[$setting] = $this->$setting; diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index 467e31417..00ac2b6dc 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -91,7 +91,6 @@ class OidcService 'issuer' => $config['issuer'], 'clientId' => $config['client_id'], 'clientSecret' => $config['client_secret'], - 'redirectUri' => url('/oidc/callback'), 'authorizationEndpoint' => $config['authorization_endpoint'], 'tokenEndpoint' => $config['token_endpoint'], 'endSessionEndpoint' => is_string($config['end_session_endpoint']) ? $config['end_session_endpoint'] : null, @@ -130,7 +129,10 @@ class OidcService */ protected function getProvider(OidcProviderSettings $settings): OidcOAuthProvider { - $provider = new OidcOAuthProvider($settings->arrayForProvider(), [ + $provider = new OidcOAuthProvider([ + ...$settings->arrayForOAuthProvider(), + 'redirectUri' => url('/oidc/callback'), + ], [ 'httpClient' => $this->http->buildClient(5), 'optionProvider' => new HttpBasicAuthOptionProvider(), ]); From 9183e7f2fed7c06c538e5e7258467fe0508538ca Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 16 Apr 2024 15:52:55 +0100 Subject: [PATCH 29/59] OIDC Userinfo: Labelled changes to be made during review --- app/Access/Oidc/OidcService.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index 00ac2b6dc..a7f31e56b 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -241,14 +241,23 @@ class OidcService session()->put("oidc_id_token", $idTokenText); + // TODO - This should not affect id token validation + // TODO - Should only call if we're missing properties if (!empty($settings->userinfoEndpoint)) { $provider = $this->getProvider($settings); $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); $response = $provider->getParsedResponse($request); + // TODO - Ensure response content-type is "application/json" before using in this way (5.3.2) + // TODO - The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token; if they do not match, the UserInfo Response values MUST NOT be used. (5.3.2) + // TODO - Response validation (5.3.4) + // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. + // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. + // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. $claims = $idToken->getAllClaims(); foreach ($response as $key => $value) { $claims[$key] = $value; } + // TODO - Should maybe remain separate from IdToken completely $idToken->replaceClaims($claims); } From a71c8c60b7b6dc0bc20938029b14a86ab9cc95cd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 16 Apr 2024 18:10:32 +0100 Subject: [PATCH 30/59] OIDC: Extracted user detail handling to own OidcUserDetails class Allows a proper defined object instead of an array an extracts related logic out of OidcService. Updated userinfo to only be called if we're missing details. --- app/Access/Oidc/OidcService.php | 123 +++++++--------------------- app/Access/Oidc/OidcUserDetails.php | 83 +++++++++++++++++++ 2 files changed, 114 insertions(+), 92 deletions(-) create mode 100644 app/Access/Oidc/OidcUserDetails.php diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index a7f31e56b..5a73484c1 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -12,7 +12,6 @@ use BookStack\Facades\Theme; use BookStack\Http\HttpRequestService; use BookStack\Theming\ThemeEvents; use BookStack\Users\Models\User; -use Illuminate\Support\Arr; use Illuminate\Support\Facades\Cache; use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; @@ -159,69 +158,6 @@ class OidcService return array_filter($scopeArr); } - /** - * Calculate the display name. - */ - protected function getUserDisplayName(OidcIdToken $token, string $defaultValue): string - { - $displayNameAttrString = $this->config()['display_name_claims'] ?? ''; - $displayNameAttrs = explode('|', $displayNameAttrString); - - $displayName = []; - foreach ($displayNameAttrs as $dnAttr) { - $dnComponent = $token->getClaim($dnAttr) ?? ''; - if ($dnComponent !== '') { - $displayName[] = $dnComponent; - } - } - - if (count($displayName) == 0) { - $displayName[] = $defaultValue; - } - - return implode(' ', $displayName); - } - - /** - * Extract the assigned groups from the id token. - * - * @return string[] - */ - protected function getUserGroups(OidcIdToken $token): array - { - $groupsAttr = $this->config()['groups_claim']; - if (empty($groupsAttr)) { - return []; - } - - $groupsList = Arr::get($token->getAllClaims(), $groupsAttr); - if (!is_array($groupsList)) { - return []; - } - - return array_values(array_filter($groupsList, function ($val) { - return is_string($val); - })); - } - - /** - * Extract the details of a user from an ID token. - * - * @return array{name: string, email: string, external_id: string, groups: string[]} - */ - protected function getUserDetails(OidcIdToken $token): array - { - $idClaim = $this->config()['external_id_claim']; - $id = $token->getClaim($idClaim); - - return [ - 'external_id' => $id, - 'email' => $token->getClaim('email'), - 'name' => $this->getUserDisplayName($token, $id), - 'groups' => $this->getUserGroups($token), - ]; - } - /** * Processes a received access token for a user. Login the user when * they exist, optionally registering them automatically. @@ -241,26 +177,6 @@ class OidcService session()->put("oidc_id_token", $idTokenText); - // TODO - This should not affect id token validation - // TODO - Should only call if we're missing properties - if (!empty($settings->userinfoEndpoint)) { - $provider = $this->getProvider($settings); - $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); - $response = $provider->getParsedResponse($request); - // TODO - Ensure response content-type is "application/json" before using in this way (5.3.2) - // TODO - The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token; if they do not match, the UserInfo Response values MUST NOT be used. (5.3.2) - // TODO - Response validation (5.3.4) - // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. - // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. - // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. - $claims = $idToken->getAllClaims(); - foreach ($response as $key => $value) { - $claims[$key] = $value; - } - // TODO - Should maybe remain separate from IdToken completely - $idToken->replaceClaims($claims); - } - $returnClaims = Theme::dispatch(ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE, $idToken->getAllClaims(), [ 'access_token' => $accessToken->getToken(), 'expires_in' => $accessToken->getExpires(), @@ -281,31 +197,54 @@ class OidcService throw new OidcException("ID token validate failed with error: {$exception->getMessage()}"); } - $userDetails = $this->getUserDetails($idToken); - $isLoggedIn = auth()->check(); + $userDetails = OidcUserDetails::fromToken( + $idToken, + $this->config()['external_id_claim'], + $this->config()['display_name_claims'] ?? '', + $this->config()['groups_claim'] ?? '' + ); - if (empty($userDetails['email'])) { + // TODO - This should not affect id token validation + if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) { + $provider = $this->getProvider($settings); + $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); + $response = $provider->getParsedResponse($request); + // TODO - Ensure response content-type is "application/json" before using in this way (5.3.2) + // TODO - The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token; if they do not match, the UserInfo Response values MUST NOT be used. (5.3.2) + // TODO - Response validation (5.3.4) + // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. + // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. + // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. + $claims = $idToken->getAllClaims(); + foreach ($response as $key => $value) { + $claims[$key] = $value; + } + // TODO - Should maybe remain separate from IdToken completely + $idToken->replaceClaims($claims); + } + + if (empty($userDetails->email)) { throw new OidcException(trans('errors.oidc_no_email_address')); } + $isLoggedIn = auth()->check(); if ($isLoggedIn) { throw new OidcException(trans('errors.oidc_already_logged_in')); } try { $user = $this->registrationService->findOrRegister( - $userDetails['name'], - $userDetails['email'], - $userDetails['external_id'] + $userDetails->name, + $userDetails->email, + $userDetails->externalId ); } catch (UserRegistrationException $exception) { throw new OidcException($exception->getMessage()); } if ($this->shouldSyncGroups()) { - $groups = $userDetails['groups']; $detachExisting = $this->config()['remove_from_groups']; - $this->groupService->syncUserWithFoundGroups($user, $groups, $detachExisting); + $this->groupService->syncUserWithFoundGroups($user, $userDetails->groups ?? [], $detachExisting); } $this->loginService->login($user, 'oidc'); diff --git a/app/Access/Oidc/OidcUserDetails.php b/app/Access/Oidc/OidcUserDetails.php new file mode 100644 index 000000000..1fb40ddc2 --- /dev/null +++ b/app/Access/Oidc/OidcUserDetails.php @@ -0,0 +1,83 @@ +externalId) + || empty($this->email) + || empty($this->name) + || ($groupSyncActive && empty($this->groups)); + + return !$hasEmpty; + } + + /** + * Populate user details from OidcIdToken data. + */ + public static function fromToken( + OidcIdToken $token, + string $idClaim, + string $displayNameClaims, + string $groupsClaim, + ): static { + $id = $token->getClaim($idClaim); + + return new self( + externalId: $id, + email: $token->getClaim('email'), + name: static::getUserDisplayName($displayNameClaims, $token, $id), + groups: static::getUserGroups($groupsClaim, $token), + ); + } + + protected static function getUserDisplayName(string $displayNameClaims, OidcIdToken $token, string $defaultValue): string + { + $displayNameClaimParts = explode('|', $displayNameClaims); + + $displayName = []; + foreach ($displayNameClaimParts as $claim) { + $component = $token->getClaim(trim($claim)) ?? ''; + if ($component !== '') { + $displayName[] = $component; + } + } + + if (count($displayName) === 0) { + $displayName[] = $defaultValue; + } + + return implode(' ', $displayName); + } + + protected static function getUserGroups(string $groupsClaim, OidcIdToken $token): array + { + if (empty($groupsClaim)) { + return []; + } + + $groupsList = Arr::get($token->getAllClaims(), $groupsClaim); + if (!is_array($groupsList)) { + return []; + } + + return array_values(array_filter($groupsList, function ($val) { + return is_string($val); + })); + } +} From 7d7cd32ca72397b635f7be597ad467ca27cffe6e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 17 Apr 2024 18:23:58 +0100 Subject: [PATCH 31/59] OIDC Userinfo: Added userinfo data validation, seperated from id token Wrapped userinfo response in its own class for additional handling and validation. Updated userdetails to take abstract claim data, to be populated by either userinfo data or id token data. --- app/Access/Oidc/OidcIdToken.php | 6 +-- app/Access/Oidc/OidcService.php | 64 ++++++++++++++---------- app/Access/Oidc/OidcUserDetails.php | 22 ++++---- app/Access/Oidc/OidcUserinfoResponse.php | 54 ++++++++++++++++++++ app/Access/Oidc/ProvidesClaims.php | 17 +++++++ 5 files changed, 119 insertions(+), 44 deletions(-) create mode 100644 app/Access/Oidc/OidcUserinfoResponse.php create mode 100644 app/Access/Oidc/ProvidesClaims.php diff --git a/app/Access/Oidc/OidcIdToken.php b/app/Access/Oidc/OidcIdToken.php index 5a395022a..b1da998a5 100644 --- a/app/Access/Oidc/OidcIdToken.php +++ b/app/Access/Oidc/OidcIdToken.php @@ -2,7 +2,7 @@ namespace BookStack\Access\Oidc; -class OidcIdToken +class OidcIdToken implements ProvidesClaims { protected array $header; protected array $payload; @@ -71,10 +71,8 @@ class OidcIdToken /** * Fetch a specific claim from this token. * Returns null if it is null or does not exist. - * - * @return mixed|null */ - public function getClaim(string $claim) + public function getClaim(string $claim): mixed { return $this->payload[$claim] ?? null; } diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index 5a73484c1..fba6dc9a8 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -194,35 +194,10 @@ class OidcService try { $idToken->validate($settings->clientId); } catch (OidcInvalidTokenException $exception) { - throw new OidcException("ID token validate failed with error: {$exception->getMessage()}"); - } - - $userDetails = OidcUserDetails::fromToken( - $idToken, - $this->config()['external_id_claim'], - $this->config()['display_name_claims'] ?? '', - $this->config()['groups_claim'] ?? '' - ); - - // TODO - This should not affect id token validation - if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) { - $provider = $this->getProvider($settings); - $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); - $response = $provider->getParsedResponse($request); - // TODO - Ensure response content-type is "application/json" before using in this way (5.3.2) - // TODO - The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token; if they do not match, the UserInfo Response values MUST NOT be used. (5.3.2) - // TODO - Response validation (5.3.4) - // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. - // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. - // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. - $claims = $idToken->getAllClaims(); - foreach ($response as $key => $value) { - $claims[$key] = $value; - } - // TODO - Should maybe remain separate from IdToken completely - $idToken->replaceClaims($claims); + throw new OidcException("ID token validation failed with error: {$exception->getMessage()}"); } + $userDetails = $this->getUserDetailsFromToken($idToken, $accessToken, $settings); if (empty($userDetails->email)) { throw new OidcException(trans('errors.oidc_no_email_address')); } @@ -252,6 +227,41 @@ class OidcService return $user; } + /** + * @throws OidcException + */ + protected function getUserDetailsFromToken(OidcIdToken $idToken, OidcAccessToken $accessToken, OidcProviderSettings $settings): OidcUserDetails + { + $userDetails = new OidcUserDetails(); + $userDetails->populate( + $idToken, + $this->config()['external_id_claim'], + $this->config()['display_name_claims'] ?? '', + $this->config()['groups_claim'] ?? '' + ); + + if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) { + $provider = $this->getProvider($settings); + $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); + $response = new OidcUserinfoResponse($provider->getResponse($request)); + + try { + $response->validate($idToken->getClaim('sub')); + } catch (OidcInvalidTokenException $exception) { + throw new OidcException("Userinfo endpoint response validation failed with error: {$exception->getMessage()}"); + } + + $userDetails->populate( + $response, + $this->config()['external_id_claim'], + $this->config()['display_name_claims'] ?? '', + $this->config()['groups_claim'] ?? '' + ); + } + + return $userDetails; + } + /** * Get the OIDC config from the application. */ diff --git a/app/Access/Oidc/OidcUserDetails.php b/app/Access/Oidc/OidcUserDetails.php index 1fb40ddc2..172bc9ceb 100644 --- a/app/Access/Oidc/OidcUserDetails.php +++ b/app/Access/Oidc/OidcUserDetails.php @@ -30,23 +30,19 @@ class OidcUserDetails /** * Populate user details from OidcIdToken data. */ - public static function fromToken( - OidcIdToken $token, + public function populate( + ProvidesClaims $claims, string $idClaim, string $displayNameClaims, string $groupsClaim, - ): static { - $id = $token->getClaim($idClaim); - - return new self( - externalId: $id, - email: $token->getClaim('email'), - name: static::getUserDisplayName($displayNameClaims, $token, $id), - groups: static::getUserGroups($groupsClaim, $token), - ); + ): void { + $this->externalId = $claims->getClaim($idClaim) ?? $this->externalId; + $this->email = $claims->getClaim('email') ?? $this->email; + $this->name = static::getUserDisplayName($displayNameClaims, $claims, $this->externalId) ?? $this->name; + $this->groups = static::getUserGroups($groupsClaim, $claims) ?? $this->groups; } - protected static function getUserDisplayName(string $displayNameClaims, OidcIdToken $token, string $defaultValue): string + protected static function getUserDisplayName(string $displayNameClaims, ProvidesClaims $token, string $defaultValue): string { $displayNameClaimParts = explode('|', $displayNameClaims); @@ -65,7 +61,7 @@ class OidcUserDetails return implode(' ', $displayName); } - protected static function getUserGroups(string $groupsClaim, OidcIdToken $token): array + protected static function getUserGroups(string $groupsClaim, ProvidesClaims $token): array { if (empty($groupsClaim)) { return []; diff --git a/app/Access/Oidc/OidcUserinfoResponse.php b/app/Access/Oidc/OidcUserinfoResponse.php new file mode 100644 index 000000000..7c7760434 --- /dev/null +++ b/app/Access/Oidc/OidcUserinfoResponse.php @@ -0,0 +1,54 @@ +getHeader('Content-Type')[0] === 'application/json') { + $this->claims = json_decode($response->getBody()->getContents(), true); + } + + // TODO - Support JWTs + // TODO - Response validation (5.3.4): + // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. + // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. + // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. + } + + /** + * @throws OidcInvalidTokenException + */ + public function validate(string $idTokenSub): bool + { + $sub = $this->getClaim('sub'); + + // Spec: v1.0 5.3.2: The sub (subject) Claim MUST always be returned in the UserInfo Response. + if (!is_string($sub) || empty($sub)) { + throw new OidcInvalidTokenException("No valid subject value found in userinfo data"); + } + + // Spec: v1.0 5.3.2: The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token; + // if they do not match, the UserInfo Response values MUST NOT be used. + if ($idTokenSub !== $sub) { + throw new OidcInvalidTokenException("Subject value provided in the userinfo endpoint does not match the provided ID token value"); + } + + return true; + } + + public function getClaim(string $claim): mixed + { + return $this->claims[$claim] ?? null; + } + + public function getAllClaims(): array + { + return $this->claims; + } +} diff --git a/app/Access/Oidc/ProvidesClaims.php b/app/Access/Oidc/ProvidesClaims.php new file mode 100644 index 000000000..a3cf51655 --- /dev/null +++ b/app/Access/Oidc/ProvidesClaims.php @@ -0,0 +1,17 @@ + Date: Wed, 17 Apr 2024 23:24:57 +0100 Subject: [PATCH 32/59] OIDC Userinfo: Started writing tests to cover userinfo calling --- app/Access/Oidc/OidcProviderSettings.php | 2 +- app/Access/Oidc/OidcService.php | 3 + app/Access/Oidc/OidcUserDetails.php | 10 +- tests/Auth/OidcTest.php | 142 +++++++++++++++++------ 4 files changed, 111 insertions(+), 46 deletions(-) diff --git a/app/Access/Oidc/OidcProviderSettings.php b/app/Access/Oidc/OidcProviderSettings.php index 616bf1012..71c3b5734 100644 --- a/app/Access/Oidc/OidcProviderSettings.php +++ b/app/Access/Oidc/OidcProviderSettings.php @@ -53,7 +53,7 @@ class OidcProviderSettings */ protected function validateInitial(): void { - $required = ['clientId', 'clientSecret', 'redirectUri', 'issuer']; + $required = ['clientId', 'clientSecret', 'issuer']; foreach ($required as $prop) { if (empty($this->$prop)) { throw new InvalidArgumentException("Missing required configuration \"{$prop}\" value"); diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index fba6dc9a8..6d024ae32 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -201,6 +201,9 @@ class OidcService if (empty($userDetails->email)) { throw new OidcException(trans('errors.oidc_no_email_address')); } + if (empty($userDetails->name)) { + $userDetails->name = $userDetails->externalId; + } $isLoggedIn = auth()->check(); if ($isLoggedIn) { diff --git a/app/Access/Oidc/OidcUserDetails.php b/app/Access/Oidc/OidcUserDetails.php index 172bc9ceb..bccc49ee4 100644 --- a/app/Access/Oidc/OidcUserDetails.php +++ b/app/Access/Oidc/OidcUserDetails.php @@ -28,7 +28,7 @@ class OidcUserDetails } /** - * Populate user details from OidcIdToken data. + * Populate user details from the given claim data. */ public function populate( ProvidesClaims $claims, @@ -38,11 +38,11 @@ class OidcUserDetails ): void { $this->externalId = $claims->getClaim($idClaim) ?? $this->externalId; $this->email = $claims->getClaim('email') ?? $this->email; - $this->name = static::getUserDisplayName($displayNameClaims, $claims, $this->externalId) ?? $this->name; + $this->name = static::getUserDisplayName($displayNameClaims, $claims) ?? $this->name; $this->groups = static::getUserGroups($groupsClaim, $claims) ?? $this->groups; } - protected static function getUserDisplayName(string $displayNameClaims, ProvidesClaims $token, string $defaultValue): string + protected static function getUserDisplayName(string $displayNameClaims, ProvidesClaims $token): string { $displayNameClaimParts = explode('|', $displayNameClaims); @@ -54,10 +54,6 @@ class OidcUserDetails } } - if (count($displayName) === 0) { - $displayName[] = $defaultValue; - } - return implode(' ', $displayName); } diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index 661722983..9ed3fa7b9 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -37,6 +37,7 @@ class OidcTest extends TestCase 'oidc.issuer' => OidcJwtHelper::defaultIssuer(), 'oidc.authorization_endpoint' => 'https://oidc.local/auth', 'oidc.token_endpoint' => 'https://oidc.local/token', + 'oidc.userinfo_endpoint' => 'https://oidc.local/userinfo', 'oidc.discover' => false, 'oidc.dump_user_details' => false, 'oidc.additional_scopes' => '', @@ -208,6 +209,8 @@ class OidcTest extends TestCase public function test_auth_fails_if_no_email_exists_in_user_data() { + config()->set('oidc.userinfo_endpoint', null); + $this->runLogin([ 'email' => '', 'sub' => 'benny505', @@ -270,10 +273,38 @@ class OidcTest extends TestCase ]); $resp = $this->followRedirects($resp); - $resp->assertSeeText('ID token validate failed with error: Missing token subject value'); + $resp->assertSeeText('ID token validation failed with error: Missing token subject value'); $this->assertFalse(auth()->check()); } + public function test_auth_fails_if_endpoints_start_with_https() + { + $endpointConfigKeys = [ + 'oidc.token_endpoint' => 'tokenEndpoint', + 'oidc.authorization_endpoint' => 'authorizationEndpoint', + 'oidc.userinfo_endpoint' => 'userinfoEndpoint', + ]; + + foreach ($endpointConfigKeys as $endpointConfigKey => $endpointName) { + $logger = $this->withTestLogger(); + $original = config()->get($endpointConfigKey); + $new = str_replace('https://', 'http://', $original); + config()->set($endpointConfigKey, $new); + + $this->withoutExceptionHandling(); + $err = null; + try { + $resp = $this->runLogin(); + $resp->assertRedirect('/login'); + } catch (\Exception $exception) { + $err = $exception; + } + $this->assertEquals("Endpoint value for \"{$endpointName}\" must start with https://", $err->getMessage()); + + config()->set($endpointConfigKey, $original); + } + } + public function test_auth_login_with_autodiscovery() { $this->withAutodiscovery(); @@ -689,57 +720,92 @@ class OidcTest extends TestCase $this->assertEquals($pkceCode, $bodyParams['code_verifier']); } - protected function withAutodiscovery() + public function test_userinfo_endpoint_used_if_missing_claims_in_id_token() + { + config()->set('oidc.display_name_claims', 'first_name|last_name'); + $this->post('/oidc/login'); + $state = session()->get('oidc_state'); + + $client = $this->mockHttpClient([ + $this->getMockAuthorizationResponse(['name' => null]), + new Response(200, [ + 'Content-Type' => 'application/json', + ], json_encode([ + 'sub' => OidcJwtHelper::defaultPayload()['sub'], + 'first_name' => 'Barry', + 'last_name' => 'Userinfo', + ])) + ]); + + $resp = $this->get('/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=' . $state); + $resp->assertRedirect('/'); + $this->assertEquals(2, $client->requestCount()); + + $userinfoRequest = $client->requestAt(1); + $this->assertEquals('GET', $userinfoRequest->getMethod()); + $this->assertEquals('https://oidc.local/userinfo', (string) $userinfoRequest->getUri()); + + $this->assertEquals('Barry Userinfo', user()->name); + } + + public function test_userinfo_endpoint_fetch_with_different_sub_throws_error() + { + $userinfoResponseData = ['sub' => 'dcba4321']; + $userinfoResponse = new Response(200, ['Content-Type' => 'application/json'], json_encode($userinfoResponseData)); + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: Subject value provided in the userinfo endpoint does not match the provided ID token value'); + } + + public function test_userinfo_endpoint_fetch_returning_no_sub_throws_error() + { + $userinfoResponseData = ['name' => 'testing']; + $userinfoResponse = new Response(200, ['Content-Type' => 'application/json'], json_encode($userinfoResponseData)); + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data'); + } + + public function test_userinfo_endpoint_fetch_can_parsed_nested_groups() + { + config()->set([ + 'oidc.user_to_groups' => true, + 'oidc.groups_claim' => 'my.nested.groups.attr', + 'oidc.remove_from_groups' => false, + ]); + + $roleA = Role::factory()->create(['display_name' => 'Ducks']); + $userinfoResponseData = [ + 'sub' => OidcJwtHelper::defaultPayload()['sub'], + 'my' => ['nested' => ['groups' => ['attr' => ['Ducks', 'Donkeys']]]] + ]; + $userinfoResponse = new Response(200, ['Content-Type' => 'application/json'], json_encode($userinfoResponseData)); + $resp = $this->runLogin(['groups' => null], [$userinfoResponse]); + $resp->assertRedirect('/'); + + $user = User::where('email', OidcJwtHelper::defaultPayload()['email'])->first(); + $this->assertTrue($user->hasRole($roleA->id)); + } + + protected function withAutodiscovery(): void { config()->set([ 'oidc.issuer' => OidcJwtHelper::defaultIssuer(), 'oidc.discover' => true, 'oidc.authorization_endpoint' => null, 'oidc.token_endpoint' => null, + 'oidc.userinfo_endpoint' => null, 'oidc.jwt_public_key' => null, ]); } - protected function runLogin($claimOverrides = []): TestResponse + protected function runLogin($claimOverrides = [], $additionalHttpResponses = []): TestResponse { - // These two variables should perhaps be arguments instead of - // assuming that they're tied to whether discovery is enabled, - // but that's how the tests are written for now. - $claimsInIdToken = !config('oidc.discover'); - $tokenEndpoint = config('oidc.discover') - ? OidcJwtHelper::defaultIssuer() . '/oidc/token' - : 'https://oidc.local/token'; - $this->post('/oidc/login'); $state = session()->get('oidc_state'); + $this->mockHttpClient([$this->getMockAuthorizationResponse($claimOverrides), ...$additionalHttpResponses]); - $providerResponses = [$this->getMockAuthorizationResponse($claimsInIdToken ? $claimOverrides : [])]; - if (!$claimsInIdToken) { - $providerResponses[] = new Response(200, [ - 'Content-Type' => 'application/json', - 'Cache-Control' => 'no-cache, no-store', - 'Pragma' => 'no-cache', - ], json_encode($claimOverrides)); - } - - $transactions = $this->mockHttpClient($providerResponses); - - $response = $this->get('/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=' . $state); - - if (auth()->check()) { - $this->assertEquals($claimsInIdToken ? 1 : 2, $transactions->requestCount()); - $tokenRequest = $transactions->requestAt(0); - $this->assertEquals($tokenEndpoint, (string) $tokenRequest->getUri()); - $this->assertEquals('POST', $tokenRequest->getMethod()); - if (!$claimsInIdToken) { - $userinfoRequest = $transactions->requestAt(1); - $this->assertEquals(OidcJwtHelper::defaultIssuer() . '/oidc/userinfo', (string) $userinfoRequest->getUri()); - $this->assertEquals('GET', $userinfoRequest->getMethod()); - $this->assertEquals('Bearer abc123', $userinfoRequest->getHeader('Authorization')[0]); - } - } - - return $response; + return $this->get('/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=' . $state); } protected function getAutoDiscoveryResponse($responseOverrides = []): Response From 1b1cb18839d813ba112617d6c99daece07b080d3 Mon Sep 17 00:00:00 2001 From: nesges Date: Fri, 19 Apr 2024 09:18:34 +0200 Subject: [PATCH 33/59] fixed mislabeling of name input --- resources/views/auth/register.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index d345b037a..40b69ce60 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -14,7 +14,7 @@ {!! csrf_field() !!}
- + @include('form.text', ['name' => 'name'])
From 31272e60b6f4685ec7a0378553ff57860cd5e387 Mon Sep 17 00:00:00 2001 From: nesges Date: Fri, 19 Apr 2024 09:35:09 +0200 Subject: [PATCH 34/59] add ambrosia-container to registration form as honeypot for bots: new form field "username" must not be filled --- app/Access/Controllers/RegisterController.php | 1 + resources/sass/_forms.scss | 11 +++++++++++ resources/views/auth/register.blade.php | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/app/Access/Controllers/RegisterController.php b/app/Access/Controllers/RegisterController.php index 13b97f03c..25b0a3036 100644 --- a/app/Access/Controllers/RegisterController.php +++ b/app/Access/Controllers/RegisterController.php @@ -87,6 +87,7 @@ class RegisterController extends Controller 'name' => ['required', 'min:2', 'max:100'], 'email' => ['required', 'email', 'max:255', 'unique:users'], 'password' => ['required', Password::default()], + 'username' => ['prohibited'], // this is a honeypot for bots that must not be filled in ]); } } diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index e480531fc..fc0eb49bd 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -389,6 +389,17 @@ input[type=color] { } } +.form-group.ambrosia-container, .form-group.ambrosia-container * { + position:absolute; + height:0px !important; + width:0px !important; + margin:0 !important; + padding:0 !important; + background:transparent !important; + color:transparent !important; + border:none !important; +} + .title-input input[type="text"] { display: block; width: 100%; diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 40b69ce60..c271bb34b 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -13,6 +13,11 @@
{!! csrf_field() !!} +
+ + @include('form.text', ['name' => 'username']) +
+
@include('form.text', ['name' => 'name']) From b18cee3dc4cec028ff9efa69dab960649bb38425 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 19 Apr 2024 14:12:27 +0100 Subject: [PATCH 35/59] OIDC Userinfo: Added JWT signed response support Not yet tested, nor checked all response validations. --- app/Access/Oidc/OidcIdToken.php | 144 +------------------ app/Access/Oidc/OidcJwtWithClaims.php | 174 +++++++++++++++++++++++ app/Access/Oidc/OidcService.php | 6 +- app/Access/Oidc/OidcUserinfoResponse.php | 16 ++- 4 files changed, 196 insertions(+), 144 deletions(-) create mode 100644 app/Access/Oidc/OidcJwtWithClaims.php diff --git a/app/Access/Oidc/OidcIdToken.php b/app/Access/Oidc/OidcIdToken.php index b1da998a5..f3fad0e1e 100644 --- a/app/Access/Oidc/OidcIdToken.php +++ b/app/Access/Oidc/OidcIdToken.php @@ -2,58 +2,8 @@ namespace BookStack\Access\Oidc; -class OidcIdToken implements ProvidesClaims +class OidcIdToken extends OidcJwtWithClaims implements ProvidesClaims { - protected array $header; - protected array $payload; - protected string $signature; - protected string $issuer; - protected array $tokenParts = []; - - /** - * @var array[]|string[] - */ - protected array $keys; - - public function __construct(string $token, string $issuer, array $keys) - { - $this->keys = $keys; - $this->issuer = $issuer; - $this->parse($token); - } - - /** - * Parse the token content into its components. - */ - protected function parse(string $token): void - { - $this->tokenParts = explode('.', $token); - $this->header = $this->parseEncodedTokenPart($this->tokenParts[0]); - $this->payload = $this->parseEncodedTokenPart($this->tokenParts[1] ?? ''); - $this->signature = $this->base64UrlDecode($this->tokenParts[2] ?? '') ?: ''; - } - - /** - * Parse a Base64-JSON encoded token part. - * Returns the data as a key-value array or empty array upon error. - */ - protected function parseEncodedTokenPart(string $part): array - { - $json = $this->base64UrlDecode($part) ?: '{}'; - $decoded = json_decode($json, true); - - return is_array($decoded) ? $decoded : []; - } - - /** - * Base64URL decode. Needs some character conversions to be compatible - * with PHP's default base64 handling. - */ - protected function base64UrlDecode(string $encoded): string - { - return base64_decode(strtr($encoded, '-_', '+/')); - } - /** * Validate all possible parts of the id token. * @@ -61,89 +11,12 @@ class OidcIdToken implements ProvidesClaims */ public function validate(string $clientId): bool { - $this->validateTokenStructure(); - $this->validateTokenSignature(); + parent::validateCommonClaims(); $this->validateTokenClaims($clientId); return true; } - /** - * Fetch a specific claim from this token. - * Returns null if it is null or does not exist. - */ - public function getClaim(string $claim): mixed - { - return $this->payload[$claim] ?? null; - } - - /** - * Get all returned claims within the token. - */ - public function getAllClaims(): array - { - return $this->payload; - } - - /** - * Replace the existing claim data of this token with that provided. - */ - public function replaceClaims(array $claims): void - { - $this->payload = $claims; - } - - /** - * Validate the structure of the given token and ensure we have the required pieces. - * As per https://datatracker.ietf.org/doc/html/rfc7519#section-7.2. - * - * @throws OidcInvalidTokenException - */ - protected function validateTokenStructure(): void - { - foreach (['header', 'payload'] as $prop) { - if (empty($this->$prop) || !is_array($this->$prop)) { - throw new OidcInvalidTokenException("Could not parse out a valid {$prop} within the provided token"); - } - } - - if (empty($this->signature) || !is_string($this->signature)) { - throw new OidcInvalidTokenException('Could not parse out a valid signature within the provided token'); - } - } - - /** - * Validate the signature of the given token and ensure it validates against the provided key. - * - * @throws OidcInvalidTokenException - */ - protected function validateTokenSignature(): void - { - if ($this->header['alg'] !== 'RS256') { - throw new OidcInvalidTokenException("Only RS256 signature validation is supported. Token reports using {$this->header['alg']}"); - } - - $parsedKeys = array_map(function ($key) { - try { - return new OidcJwtSigningKey($key); - } catch (OidcInvalidKeyException $e) { - throw new OidcInvalidTokenException('Failed to read signing key with error: ' . $e->getMessage()); - } - }, $this->keys); - - $parsedKeys = array_filter($parsedKeys); - - $contentToSign = $this->tokenParts[0] . '.' . $this->tokenParts[1]; - /** @var OidcJwtSigningKey $parsedKey */ - foreach ($parsedKeys as $parsedKey) { - if ($parsedKey->verify($contentToSign, $this->signature)) { - return; - } - } - - throw new OidcInvalidTokenException('Token signature could not be validated using the provided keys'); - } - /** * Validate the claims of the token. * As per https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation. @@ -154,27 +27,18 @@ class OidcIdToken implements ProvidesClaims { // 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) // MUST exactly match the value of the iss (issuer) Claim. - if (empty($this->payload['iss']) || $this->issuer !== $this->payload['iss']) { - throw new OidcInvalidTokenException('Missing or non-matching token issuer value'); - } + // Already done in parent. // 2. The Client MUST validate that the aud (audience) Claim contains its client_id value registered // at the Issuer identified by the iss (issuer) Claim as an audience. The ID Token MUST be rejected // if the ID Token does not list the Client as a valid audience, or if it contains additional // audiences not trusted by the Client. - if (empty($this->payload['aud'])) { - throw new OidcInvalidTokenException('Missing token audience value'); - } - + // Partially done in parent. $aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud']; if (count($aud) !== 1) { throw new OidcInvalidTokenException('Token audience value has ' . count($aud) . ' values, Expected 1'); } - if ($aud[0] !== $clientId) { - throw new OidcInvalidTokenException('Token audience value did not match the expected client_id'); - } - // 3. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp Claim is present. // NOTE: Addressed by enforcing a count of 1 above. diff --git a/app/Access/Oidc/OidcJwtWithClaims.php b/app/Access/Oidc/OidcJwtWithClaims.php new file mode 100644 index 000000000..cc13936ab --- /dev/null +++ b/app/Access/Oidc/OidcJwtWithClaims.php @@ -0,0 +1,174 @@ +keys = $keys; + $this->issuer = $issuer; + $this->parse($token); + } + + /** + * Parse the token content into its components. + */ + protected function parse(string $token): void + { + $this->tokenParts = explode('.', $token); + $this->header = $this->parseEncodedTokenPart($this->tokenParts[0]); + $this->payload = $this->parseEncodedTokenPart($this->tokenParts[1] ?? ''); + $this->signature = $this->base64UrlDecode($this->tokenParts[2] ?? '') ?: ''; + } + + /** + * Parse a Base64-JSON encoded token part. + * Returns the data as a key-value array or empty array upon error. + */ + protected function parseEncodedTokenPart(string $part): array + { + $json = $this->base64UrlDecode($part) ?: '{}'; + $decoded = json_decode($json, true); + + return is_array($decoded) ? $decoded : []; + } + + /** + * Base64URL decode. Needs some character conversions to be compatible + * with PHP's default base64 handling. + */ + protected function base64UrlDecode(string $encoded): string + { + return base64_decode(strtr($encoded, '-_', '+/')); + } + + /** + * Validate common parts of OIDC JWT tokens. + * + * @throws OidcInvalidTokenException + */ + protected function validateCommonTokenDetails(): bool + { + $this->validateTokenStructure(); + $this->validateTokenSignature(); + $this->validateCommonClaims(); + + return true; + } + + /** + * Fetch a specific claim from this token. + * Returns null if it is null or does not exist. + */ + public function getClaim(string $claim): mixed + { + return $this->payload[$claim] ?? null; + } + + /** + * Get all returned claims within the token. + */ + public function getAllClaims(): array + { + return $this->payload; + } + + /** + * Replace the existing claim data of this token with that provided. + */ + public function replaceClaims(array $claims): void + { + $this->payload = $claims; + } + + /** + * Validate the structure of the given token and ensure we have the required pieces. + * As per https://datatracker.ietf.org/doc/html/rfc7519#section-7.2. + * + * @throws OidcInvalidTokenException + */ + protected function validateTokenStructure(): void + { + foreach (['header', 'payload'] as $prop) { + if (empty($this->$prop) || !is_array($this->$prop)) { + throw new OidcInvalidTokenException("Could not parse out a valid {$prop} within the provided token"); + } + } + + if (empty($this->signature) || !is_string($this->signature)) { + throw new OidcInvalidTokenException('Could not parse out a valid signature within the provided token'); + } + } + + /** + * Validate the signature of the given token and ensure it validates against the provided key. + * + * @throws OidcInvalidTokenException + */ + protected function validateTokenSignature(): void + { + if ($this->header['alg'] !== 'RS256') { + throw new OidcInvalidTokenException("Only RS256 signature validation is supported. Token reports using {$this->header['alg']}"); + } + + $parsedKeys = array_map(function ($key) { + try { + return new OidcJwtSigningKey($key); + } catch (OidcInvalidKeyException $e) { + throw new OidcInvalidTokenException('Failed to read signing key with error: ' . $e->getMessage()); + } + }, $this->keys); + + $parsedKeys = array_filter($parsedKeys); + + $contentToSign = $this->tokenParts[0] . '.' . $this->tokenParts[1]; + /** @var OidcJwtSigningKey $parsedKey */ + foreach ($parsedKeys as $parsedKey) { + if ($parsedKey->verify($contentToSign, $this->signature)) { + return; + } + } + + throw new OidcInvalidTokenException('Token signature could not be validated using the provided keys'); + } + + /** + * Validate common claims for OIDC JWT tokens. + * As per https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation + * and https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse + * + * @throws OidcInvalidTokenException + */ + public function validateCommonClaims(): void + { + // 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) + // MUST exactly match the value of the iss (issuer) Claim. + if (empty($this->payload['iss']) || $this->issuer !== $this->payload['iss']) { + throw new OidcInvalidTokenException('Missing or non-matching token issuer value'); + } + + // 2. The Client MUST validate that the aud (audience) Claim contains its client_id value registered + // at the Issuer identified by the iss (issuer) Claim as an audience. The ID Token MUST be rejected + // if the ID Token does not list the Client as a valid audience. + if (empty($this->payload['aud'])) { + throw new OidcInvalidTokenException('Missing token audience value'); + } + + $aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud']; + if (!in_array($this->payload['aud'], $aud, true)) { + throw new OidcInvalidTokenException('Token audience value did not match the expected client_id'); + } + } +} diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index 6d024ae32..6bb326e4b 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -246,7 +246,11 @@ class OidcService if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) { $provider = $this->getProvider($settings); $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken()); - $response = new OidcUserinfoResponse($provider->getResponse($request)); + $response = new OidcUserinfoResponse( + $provider->getResponse($request), + $settings->issuer, + $settings->keys, + ); try { $response->validate($idToken->getClaim('sub')); diff --git a/app/Access/Oidc/OidcUserinfoResponse.php b/app/Access/Oidc/OidcUserinfoResponse.php index 7c7760434..bb6c2454a 100644 --- a/app/Access/Oidc/OidcUserinfoResponse.php +++ b/app/Access/Oidc/OidcUserinfoResponse.php @@ -7,14 +7,20 @@ use Psr\Http\Message\ResponseInterface; class OidcUserinfoResponse implements ProvidesClaims { protected array $claims = []; + protected ?OidcJwtWithClaims $jwt = null; - public function __construct(ResponseInterface $response) + public function __construct(ResponseInterface $response, string $issuer, array $keys) { - if ($response->getHeader('Content-Type')[0] === 'application/json') { + $contentType = $response->getHeader('Content-Type')[0]; + if ($contentType === 'application/json') { $this->claims = json_decode($response->getBody()->getContents(), true); } - // TODO - Support JWTs + if ($contentType === 'application/jwt') { + $this->jwt = new OidcJwtWithClaims($response->getBody()->getContents(), $issuer, $keys); + $this->claims = $this->jwt->getAllClaims(); + } + // TODO - Response validation (5.3.4): // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. @@ -26,6 +32,10 @@ class OidcUserinfoResponse implements ProvidesClaims */ public function validate(string $idTokenSub): bool { + if (!is_null($this->jwt)) { + $this->jwt->validateCommonClaims(); + } + $sub = $this->getClaim('sub'); // Spec: v1.0 5.3.2: The sub (subject) Claim MUST always be returned in the UserInfo Response. From 0958909cd999be772c045aada5bc426dffb0a0b1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 19 Apr 2024 15:05:00 +0100 Subject: [PATCH 36/59] OIDC Userinfo: Added additional tests to cover jwks usage --- app/Access/Oidc/OidcJwtWithClaims.php | 4 +- app/Access/Oidc/OidcUserinfoResponse.php | 15 +++--- tests/Auth/OidcTest.php | 62 ++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/app/Access/Oidc/OidcJwtWithClaims.php b/app/Access/Oidc/OidcJwtWithClaims.php index cc13936ab..393ac5f0e 100644 --- a/app/Access/Oidc/OidcJwtWithClaims.php +++ b/app/Access/Oidc/OidcJwtWithClaims.php @@ -59,7 +59,7 @@ class OidcJwtWithClaims implements ProvidesClaims * * @throws OidcInvalidTokenException */ - protected function validateCommonTokenDetails(): bool + public function validateCommonTokenDetails(): bool { $this->validateTokenStructure(); $this->validateTokenSignature(); @@ -151,7 +151,7 @@ class OidcJwtWithClaims implements ProvidesClaims * * @throws OidcInvalidTokenException */ - public function validateCommonClaims(): void + protected function validateCommonClaims(): void { // 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) // MUST exactly match the value of the iss (issuer) Claim. diff --git a/app/Access/Oidc/OidcUserinfoResponse.php b/app/Access/Oidc/OidcUserinfoResponse.php index bb6c2454a..0026d2f0a 100644 --- a/app/Access/Oidc/OidcUserinfoResponse.php +++ b/app/Access/Oidc/OidcUserinfoResponse.php @@ -20,11 +20,6 @@ class OidcUserinfoResponse implements ProvidesClaims $this->jwt = new OidcJwtWithClaims($response->getBody()->getContents(), $issuer, $keys); $this->claims = $this->jwt->getAllClaims(); } - - // TODO - Response validation (5.3.4): - // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. - // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. - // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. } /** @@ -33,7 +28,7 @@ class OidcUserinfoResponse implements ProvidesClaims public function validate(string $idTokenSub): bool { if (!is_null($this->jwt)) { - $this->jwt->validateCommonClaims(); + $this->jwt->validateCommonTokenDetails(); } $sub = $this->getClaim('sub'); @@ -49,6 +44,14 @@ class OidcUserinfoResponse implements ProvidesClaims throw new OidcInvalidTokenException("Subject value provided in the userinfo endpoint does not match the provided ID token value"); } + // Spec v1.0 5.3.4 Defines the following: + // Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125]. + // This is effectively done as part of the HTTP request we're making through CURLOPT_SSL_VERIFYHOST on the request. + // If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration. + // We don't currently support JWT encryption for OIDC + // If the response was signed, the Client SHOULD validate the signature according to JWS [JWS]. + // This is done as part of the validateCommonClaims above. + return true; } diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index 9ed3fa7b9..9bde71c80 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -787,6 +787,68 @@ class OidcTest extends TestCase $this->assertTrue($user->hasRole($roleA->id)); } + public function test_userinfo_endpoint_jwks_response_handled() + { + $userinfoResponseData = OidcJwtHelper::idToken(['name' => 'Barry Jwks']); + $userinfoResponse = new Response(200, ['Content-Type' => 'application/jwt'], $userinfoResponseData); + + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/'); + + $user = User::where('email', OidcJwtHelper::defaultPayload()['email'])->first(); + $this->assertEquals('Barry Jwks', $user->name); + } + + public function test_userinfo_endpoint_jwks_response_returning_no_sub_throws() + { + $userinfoResponseData = OidcJwtHelper::idToken(['sub' => null]); + $userinfoResponse = new Response(200, ['Content-Type' => 'application/jwt'], $userinfoResponseData); + + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data'); + } + + public function test_userinfo_endpoint_jwks_response_returning_non_matching_sub_throws() + { + $userinfoResponseData = OidcJwtHelper::idToken(['sub' => 'zzz123']); + $userinfoResponse = new Response(200, ['Content-Type' => 'application/jwt'], $userinfoResponseData); + + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: Subject value provided in the userinfo endpoint does not match the provided ID token value'); + } + + public function test_userinfo_endpoint_jwks_response_with_invalid_signature_throws() + { + $userinfoResponseData = OidcJwtHelper::idToken(); + $exploded = explode('.', $userinfoResponseData); + $exploded[2] = base64_encode(base64_decode($exploded[2]) . 'ABC'); + $userinfoResponse = new Response(200, ['Content-Type' => 'application/jwt'], implode('.', $exploded)); + + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: Token signature could not be validated using the provided keys'); + } + + public function test_userinfo_endpoint_jwks_response_with_invalid_signature_alg_throws() + { + $userinfoResponseData = OidcJwtHelper::idToken([], ['alg' => 'ZZ512']); + $userinfoResponse = new Response(200, ['Content-Type' => 'application/jwt'], $userinfoResponseData); + + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: Only RS256 signature validation is supported. Token reports using ZZ512'); + } + + public function test_userinfo_endpoint_response_with_invalid_content_type_throws() + { + $userinfoResponse = new Response(200, ['Content-Type' => 'application/beans'], json_encode(OidcJwtHelper::defaultPayload())); + $resp = $this->runLogin(['name' => null], [$userinfoResponse]); + $resp->assertRedirect('/login'); + $this->assertSessionError('Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data'); + } + protected function withAutodiscovery(): void { config()->set([ From 8b14a701a4792ecc0f8dc500d78e5810597eb4ac Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 19 Apr 2024 16:43:51 +0100 Subject: [PATCH 37/59] OIDC Userinfo: Fixed issues with validation logic from changes Also updated test to suit validation changes --- app/Access/Oidc/OidcIdToken.php | 2 +- app/Access/Oidc/OidcJwtWithClaims.php | 8 ++++---- app/Access/Oidc/OidcService.php | 2 +- app/Access/Oidc/OidcUserinfoResponse.php | 4 ++-- tests/Unit/OidcIdTokenTest.php | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Access/Oidc/OidcIdToken.php b/app/Access/Oidc/OidcIdToken.php index f3fad0e1e..68a8aa611 100644 --- a/app/Access/Oidc/OidcIdToken.php +++ b/app/Access/Oidc/OidcIdToken.php @@ -11,7 +11,7 @@ class OidcIdToken extends OidcJwtWithClaims implements ProvidesClaims */ public function validate(string $clientId): bool { - parent::validateCommonClaims(); + parent::validateCommonTokenDetails($clientId); $this->validateTokenClaims($clientId); return true; diff --git a/app/Access/Oidc/OidcJwtWithClaims.php b/app/Access/Oidc/OidcJwtWithClaims.php index 393ac5f0e..06c04d81e 100644 --- a/app/Access/Oidc/OidcJwtWithClaims.php +++ b/app/Access/Oidc/OidcJwtWithClaims.php @@ -59,11 +59,11 @@ class OidcJwtWithClaims implements ProvidesClaims * * @throws OidcInvalidTokenException */ - public function validateCommonTokenDetails(): bool + public function validateCommonTokenDetails(string $clientId): bool { $this->validateTokenStructure(); $this->validateTokenSignature(); - $this->validateCommonClaims(); + $this->validateCommonClaims($clientId); return true; } @@ -151,7 +151,7 @@ class OidcJwtWithClaims implements ProvidesClaims * * @throws OidcInvalidTokenException */ - protected function validateCommonClaims(): void + protected function validateCommonClaims(string $clientId): void { // 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) // MUST exactly match the value of the iss (issuer) Claim. @@ -167,7 +167,7 @@ class OidcJwtWithClaims implements ProvidesClaims } $aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud']; - if (!in_array($this->payload['aud'], $aud, true)) { + if (!in_array($clientId, $aud, true)) { throw new OidcInvalidTokenException('Token audience value did not match the expected client_id'); } } diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index 6bb326e4b..7c1760649 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -253,7 +253,7 @@ class OidcService ); try { - $response->validate($idToken->getClaim('sub')); + $response->validate($idToken->getClaim('sub'), $settings->clientId); } catch (OidcInvalidTokenException $exception) { throw new OidcException("Userinfo endpoint response validation failed with error: {$exception->getMessage()}"); } diff --git a/app/Access/Oidc/OidcUserinfoResponse.php b/app/Access/Oidc/OidcUserinfoResponse.php index 0026d2f0a..9aded654e 100644 --- a/app/Access/Oidc/OidcUserinfoResponse.php +++ b/app/Access/Oidc/OidcUserinfoResponse.php @@ -25,10 +25,10 @@ class OidcUserinfoResponse implements ProvidesClaims /** * @throws OidcInvalidTokenException */ - public function validate(string $idTokenSub): bool + public function validate(string $idTokenSub, string $clientId): bool { if (!is_null($this->jwt)) { - $this->jwt->validateCommonTokenDetails(); + $this->jwt->validateCommonTokenDetails($clientId); } $sub = $this->getClaim('sub'); diff --git a/tests/Unit/OidcIdTokenTest.php b/tests/Unit/OidcIdTokenTest.php index 6302f84c7..739323266 100644 --- a/tests/Unit/OidcIdTokenTest.php +++ b/tests/Unit/OidcIdTokenTest.php @@ -113,7 +113,7 @@ class OidcIdTokenTest extends TestCase // 2. aud claim present ['Missing token audience value', ['aud' => null]], // 2. aud claim validates all values against those expected (Only expect single) - ['Token audience value has 2 values, Expected 1', ['aud' => ['abc', 'def']]], + ['Token audience value has 2 values, Expected 1', ['aud' => ['xxyyzz.aaa.bbccdd.123', 'def']]], // 2. aud claim matches client id ['Token audience value did not match the expected client_id', ['aud' => 'xxyyzz.aaa.bbccdd.456']], // 4. azp claim matches client id if present From 16399b63be640fbe934ada9da1e8cc4f36b2c8d7 Mon Sep 17 00:00:00 2001 From: nesges Date: Sun, 21 Apr 2024 16:08:28 +0200 Subject: [PATCH 38/59] better accessibility for honepot formfield --- resources/sass/_forms.scss | 11 +++++++---- resources/views/auth/register.blade.php | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index fc0eb49bd..e7ee8c285 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -390,14 +390,17 @@ input[type=color] { } .form-group.ambrosia-container, .form-group.ambrosia-container * { - position:absolute; - height:0px !important; - width:0px !important; - margin:0 !important; + position:absolute !important; + height:1px !important; + width:1px !important; + margin:-1px !important; padding:0 !important; background:transparent !important; color:transparent !important; border:none !important; + overflow: hidden !important; + clip: rect(0,0,0,0) !important; + white-space: nowrap !important; } .title-input input[type="text"] { diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index c271bb34b..f9f4e8cb3 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -13,7 +13,7 @@ {!! csrf_field() !!} -
+ From 0d2a268be09ed1ec55e90f2bd085d6e5034d0660 Mon Sep 17 00:00:00 2001 From: nesges Date: Sun, 21 Apr 2024 17:44:01 +0200 Subject: [PATCH 39/59] whitespace only --- resources/sass/_forms.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index e7ee8c285..e6d062ce8 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -400,7 +400,7 @@ input[type=color] { border:none !important; overflow: hidden !important; clip: rect(0,0,0,0) !important; - white-space: nowrap !important; + white-space: nowrap !important; } .title-input input[type="text"] { @@ -552,4 +552,4 @@ input.shortcut-input { width: auto; max-width: 120px; height: auto; -} \ No newline at end of file +} From bb6670d395180f8a81bcbfd92da1896fcfb18d34 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 22 Apr 2024 16:40:42 +0100 Subject: [PATCH 40/59] PDF: Started new command option, merged options, simplified dompdf - Updated DOMPDF to direcly use library instead of depending on barry wrapper. - Merged existing export options file into single exports file. - Defined option for new command option. Related to #4732 --- .env.example.complete | 8 ++ app/Config/app.php | 1 - app/Config/{dompdf.php => exports.php} | 53 +++++++++---- app/Config/snappy.php | 34 -------- app/Entities/Tools/PdfGenerator.php | 56 +++++++++++-- composer.json | 2 +- composer.lock | 105 ++++--------------------- readme.md | 1 - 8 files changed, 110 insertions(+), 150 deletions(-) rename app/Config/{dompdf.php => exports.php} (88%) delete mode 100644 app/Config/snappy.php diff --git a/.env.example.complete b/.env.example.complete index 124296818..b4beb60cc 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -325,6 +325,14 @@ FILE_UPLOAD_SIZE_LIMIT=50 # Can be 'a4' or 'letter'. EXPORT_PAGE_SIZE=a4 +# Export PDF Command +# Set a command which can be used to convert a HTML file into a PDF file. +# When false this will not be used. +# String values represent the command to be called for conversion. +# Supports '{input_html_path}' and '{output_pdf_path}' placeholder values. +# Example: EXPORT_PDF_COMMAND="/scripts/convert.sh {input_html_path} {output_pdf_path}" +EXPORT_PDF_COMMAND=false + # Set path to wkhtmltopdf binary for PDF generation. # Can be 'false' or a path path like: '/home/bins/wkhtmltopdf' # When false, BookStack will attempt to find a wkhtmltopdf in the application diff --git a/app/Config/app.php b/app/Config/app.php index dda787f3f..67f31159f 100644 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -116,7 +116,6 @@ return [ // Application Service Providers 'providers' => ServiceProvider::defaultProviders()->merge([ // Third party service providers - Barryvdh\DomPDF\ServiceProvider::class, Barryvdh\Snappy\ServiceProvider::class, SocialiteProviders\Manager\ServiceProvider::class, diff --git a/app/Config/dompdf.php b/app/Config/exports.php similarity index 88% rename from app/Config/dompdf.php rename to app/Config/exports.php index 09dd91bcc..63cc2419d 100644 --- a/app/Config/dompdf.php +++ b/app/Config/exports.php @@ -1,23 +1,56 @@ 'A4', + 'letter' => 'Letter', +]; + $dompdfPaperSizeMap = [ 'a4' => 'a4', 'letter' => 'letter', ]; +$exportPageSize = env('EXPORT_PAGE_SIZE', 'a4'); + return [ - 'show_warnings' => false, // Throw an Exception on warnings from dompdf + // Set a command which can be used to convert a HTML file into a PDF file. + // When false this will not be used. + // String values represent the command to be called for conversion. + // Supports '{input_html_path}' and '{output_pdf_path}' placeholder values. + // Example: EXPORT_PDF_COMMAND="/scripts/convert.sh {input_html_path} {output_pdf_path}" + 'pdf_command' => env('EXPORT_PDF_COMMAND', false), - 'options' => [ + // 2024-04: Snappy/WKHTMLtoPDF now considered deprecated in regard to BookStack support. + 'snappy' => [ + 'pdf' => [ + 'enabled' => true, + 'binary' => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false), + 'timeout' => false, + 'options' => [ + 'outline' => true, + 'page-size' => $snappyPaperSizeMap[$exportPageSize] ?? 'A4', + ], + 'env' => [], + ], + 'image' => [ + 'enabled' => false, + 'binary' => '/usr/local/bin/wkhtmltoimage', + 'timeout' => false, + 'options' => [], + 'env' => [], + ], + ], + + 'dompdf' => [ /** * The location of the DOMPDF font directory. * @@ -101,7 +134,7 @@ return [ /** * Whether to enable font subsetting or not. */ - 'enable_fontsubsetting' => false, + 'enable_font_subsetting' => false, /** * The PDF rendering backend to use. @@ -165,7 +198,7 @@ return [ * * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.) */ - 'default_paper_size' => $dompdfPaperSizeMap[env('EXPORT_PAGE_SIZE', 'a4')] ?? 'a4', + 'default_paper_size' => $dompdfPaperSizeMap[$exportPageSize] ?? 'a4', /** * The default paper orientation. @@ -268,15 +301,6 @@ return [ */ 'font_height_ratio' => 1.1, - /** - * Enable CSS float. - * - * Allows people to disabled CSS float support - * - * @var bool - */ - 'enable_css_float' => true, - /** * Use the HTML5 Lib parser. * @@ -286,5 +310,4 @@ return [ */ 'enable_html5_parser' => true, ], - ]; diff --git a/app/Config/snappy.php b/app/Config/snappy.php deleted file mode 100644 index a87ce805f..000000000 --- a/app/Config/snappy.php +++ /dev/null @@ -1,34 +0,0 @@ - 'A4', - 'letter' => 'Letter', -]; - -return [ - 'pdf' => [ - 'enabled' => true, - 'binary' => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false), - 'timeout' => false, - 'options' => [ - 'outline' => true, - 'page-size' => $snappyPaperSizeMap[env('EXPORT_PAGE_SIZE', 'a4')] ?? 'A4', - ], - 'env' => [], - ], - 'image' => [ - 'enabled' => false, - 'binary' => '/usr/local/bin/wkhtmltoimage', - 'timeout' => false, - 'options' => [], - 'env' => [], - ], -]; diff --git a/app/Entities/Tools/PdfGenerator.php b/app/Entities/Tools/PdfGenerator.php index d0c9158a9..7502c10ff 100644 --- a/app/Entities/Tools/PdfGenerator.php +++ b/app/Entities/Tools/PdfGenerator.php @@ -2,27 +2,32 @@ namespace BookStack\Entities\Tools; -use Barryvdh\DomPDF\Facade\Pdf as DomPDF; use Barryvdh\Snappy\Facades\SnappyPdf; +use Dompdf\Dompdf; class PdfGenerator { const ENGINE_DOMPDF = 'dompdf'; const ENGINE_WKHTML = 'wkhtml'; + const ENGINE_COMMAND = 'command'; /** * Generate PDF content from the given HTML content. */ public function fromHtml(string $html): string { - if ($this->getActiveEngine() === self::ENGINE_WKHTML) { + $engine = $this->getActiveEngine(); + + if ($engine === self::ENGINE_WKHTML) { $pdf = SnappyPDF::loadHTML($html); $pdf->setOption('print-media-type', true); - } else { - $pdf = DomPDF::loadHTML($html); + return $pdf->output(); + } else if ($engine === self::ENGINE_COMMAND) { + // TODO - Support PDF command + return ''; } - return $pdf->output(); + return $this->renderUsingDomPdf($html); } /** @@ -31,8 +36,45 @@ class PdfGenerator */ public function getActiveEngine(): string { - $useWKHTML = config('snappy.pdf.binary') !== false && config('app.allow_untrusted_server_fetching') === true; + $wkhtmlBinaryPath = config('snappy.pdf.binary'); + if (file_exists(base_path('wkhtmltopdf'))) { + $wkhtmlBinaryPath = base_path('wkhtmltopdf'); + } - return $useWKHTML ? self::ENGINE_WKHTML : self::ENGINE_DOMPDF; + if (is_string($wkhtmlBinaryPath) && config('app.allow_untrusted_server_fetching') === true) { + return self::ENGINE_WKHTML; + } + + return self::ENGINE_DOMPDF; + } + + protected function renderUsingDomPdf(string $html): string + { + $options = config('exports.dompdf'); + $domPdf = new Dompdf($options); + $domPdf->setBasePath(base_path('public')); + + $domPdf->loadHTML($this->convertEntities($html)); + $domPdf->render(); + + return (string) $domPdf->output(); + } + + /** + * Taken from https://github.com/barryvdh/laravel-dompdf/blob/v2.1.1/src/PDF.php + * Copyright (c) 2021 barryvdh, MIT License + * https://github.com/barryvdh/laravel-dompdf/blob/v2.1.1/LICENSE + */ + protected function convertEntities(string $subject): string + { + $entities = [ + '€' => '€', + '£' => '£', + ]; + + foreach ($entities as $search => $replace) { + $subject = str_replace($search, $replace, $subject); + } + return $subject; } } diff --git a/composer.json b/composer.json index b22c7b44d..94f64ec72 100644 --- a/composer.json +++ b/composer.json @@ -17,9 +17,9 @@ "ext-mbstring": "*", "ext-xml": "*", "bacon/bacon-qr-code": "^2.0", - "barryvdh/laravel-dompdf": "^2.0", "barryvdh/laravel-snappy": "^1.0", "doctrine/dbal": "^3.5", + "dompdf/dompdf": "^2.0", "guzzlehttp/guzzle": "^7.4", "intervention/image": "^3.5", "laravel/framework": "^10.10", diff --git a/composer.lock b/composer.lock index 24c2215dd..657a5a7fb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ccfc07d0ecc580962915a0457f0466a7", + "content-hash": "c0c5a3169cb23d9ab8e34324202d4c37", "packages": [ { "name": "aws/aws-crt-php", @@ -209,83 +209,6 @@ }, "time": "2022-12-07T17:46:57+00:00" }, - { - "name": "barryvdh/laravel-dompdf", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "cb37868365f9b937039d316727a1fced1e87b31c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/cb37868365f9b937039d316727a1fced1e87b31c", - "reference": "cb37868365f9b937039d316727a1fced1e87b31c", - "shasum": "" - }, - "require": { - "dompdf/dompdf": "^2.0.3", - "illuminate/support": "^6|^7|^8|^9|^10|^11", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "larastan/larastan": "^1.0|^2.7.0", - "orchestra/testbench": "^4|^5|^6|^7|^8|^9", - "phpro/grumphp": "^1 || ^2.5", - "squizlabs/php_codesniffer": "^3.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - }, - "laravel": { - "providers": [ - "Barryvdh\\DomPDF\\ServiceProvider" - ], - "aliases": { - "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf", - "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf" - } - } - }, - "autoload": { - "psr-4": { - "Barryvdh\\DomPDF\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "A DOMPDF Wrapper for Laravel", - "keywords": [ - "dompdf", - "laravel", - "pdf" - ], - "support": { - "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.1" - }, - "funding": [ - { - "url": "https://fruitcake.nl", - "type": "custom" - }, - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2024-03-15T12:48:39+00:00" - }, { "name": "barryvdh/laravel-snappy", "version": "v1.0.3", @@ -1127,16 +1050,16 @@ }, { "name": "dompdf/dompdf", - "version": "v2.0.4", + "version": "v2.0.7", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/ab0123052b42ad0867348f25df8c228f1ece8f14", + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14", "shasum": "" }, "require": { @@ -1144,7 +1067,7 @@ "ext-mbstring": "*", "masterminds/html5": "^2.0", "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", + "phenx/php-svg-lib": ">=0.5.2 <1.0.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -1183,9 +1106,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.7" }, - "time": "2023-12-12T20:19:39+00:00" + "time": "2024-04-15T12:40:33+00:00" }, { "name": "dragonmantank/cron-expression", @@ -4067,16 +3990,16 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.5.3", + "version": "0.5.4", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf" + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/0e46722c154726a5f9ac218197ccc28adba16fcf", - "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", "shasum": "" }, "require": { @@ -4107,9 +4030,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.3" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" }, - "time": "2024-02-23T20:39:24+00:00" + "time": "2024-04-08T12:52:34+00:00" }, { "name": "phpoption/phpoption", diff --git a/readme.md b/readme.md index 17e1a05f6..5adcc06bb 100644 --- a/readme.md +++ b/readme.md @@ -142,7 +142,6 @@ Note: This is not an exhaustive list of all libraries and projects that would be * [Google Material Icons](https://github.com/google/material-design-icons) - _[Apache-2.0](https://github.com/google/material-design-icons/blob/master/LICENSE)_ * [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists) - _[MIT](https://github.com/markdown-it/markdown-it/blob/master/LICENSE) and [ISC](https://github.com/revin/markdown-it-task-lists/blob/master/LICENSE)_ * [Dompdf](https://github.com/dompdf/dompdf) - _[LGPL v2.1](https://github.com/dompdf/dompdf/blob/master/LICENSE.LGPL)_ -* [BarryVD/Dompdf](https://github.com/barryvdh/laravel-dompdf) - _[MIT](https://github.com/barryvdh/laravel-dompdf/blob/master/LICENSE)_ * [BarryVD/Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy) - _[MIT](https://github.com/barryvdh/laravel-snappy/blob/master/LICENSE)_ * [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html) - _[LGPL v3.0](https://github.com/wkhtmltopdf/wkhtmltopdf/blob/master/LICENSE)_ * [diagrams.net](https://github.com/jgraph/drawio) - _[Embedded Version Terms](https://www.diagrams.net/trust/) / [Source Project - Apache-2.0](https://github.com/jgraph/drawio/blob/dev/LICENSE)_ From 40200856af366f735283da4cc1b28519ddb3586b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 24 Apr 2024 15:13:44 +0100 Subject: [PATCH 41/59] PDF: Removed barryvdh snappy to use snappy direct Also simplifies config format, and updates snappy implmentation to use the new config file. Not yet tested. --- app/Config/app.php | 1 - app/Config/exports.php | 21 ++------ app/Entities/Tools/PdfGenerator.php | 30 +++++++---- composer.json | 2 +- composer.lock | 80 +---------------------------- readme.md | 2 +- 6 files changed, 28 insertions(+), 108 deletions(-) diff --git a/app/Config/app.php b/app/Config/app.php index 67f31159f..b96d0bdb7 100644 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -116,7 +116,6 @@ return [ // Application Service Providers 'providers' => ServiceProvider::defaultProviders()->merge([ // Third party service providers - Barryvdh\Snappy\ServiceProvider::class, SocialiteProviders\Manager\ServiceProvider::class, // BookStack custom service providers diff --git a/app/Config/exports.php b/app/Config/exports.php index 63cc2419d..88dc08cba 100644 --- a/app/Config/exports.php +++ b/app/Config/exports.php @@ -31,22 +31,11 @@ return [ // 2024-04: Snappy/WKHTMLtoPDF now considered deprecated in regard to BookStack support. 'snappy' => [ - 'pdf' => [ - 'enabled' => true, - 'binary' => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false), - 'timeout' => false, - 'options' => [ - 'outline' => true, - 'page-size' => $snappyPaperSizeMap[$exportPageSize] ?? 'A4', - ], - 'env' => [], - ], - 'image' => [ - 'enabled' => false, - 'binary' => '/usr/local/bin/wkhtmltoimage', - 'timeout' => false, - 'options' => [], - 'env' => [], + 'pdf_binary' => env('WKHTMLTOPDF', false), + 'options' => [ + 'print-media-type' => true, + 'outline' => true, + 'page-size' => $snappyPaperSizeMap[$exportPageSize] ?? 'A4', ], ], diff --git a/app/Entities/Tools/PdfGenerator.php b/app/Entities/Tools/PdfGenerator.php index 7502c10ff..e187b9ab2 100644 --- a/app/Entities/Tools/PdfGenerator.php +++ b/app/Entities/Tools/PdfGenerator.php @@ -2,7 +2,7 @@ namespace BookStack\Entities\Tools; -use Barryvdh\Snappy\Facades\SnappyPdf; +use Knp\Snappy\Pdf as SnappyPdf; use Dompdf\Dompdf; class PdfGenerator @@ -19,9 +19,7 @@ class PdfGenerator $engine = $this->getActiveEngine(); if ($engine === self::ENGINE_WKHTML) { - $pdf = SnappyPDF::loadHTML($html); - $pdf->setOption('print-media-type', true); - return $pdf->output(); + return $this->renderUsingWkhtml($html); } else if ($engine === self::ENGINE_COMMAND) { // TODO - Support PDF command return ''; @@ -36,18 +34,23 @@ class PdfGenerator */ public function getActiveEngine(): string { - $wkhtmlBinaryPath = config('snappy.pdf.binary'); - if (file_exists(base_path('wkhtmltopdf'))) { - $wkhtmlBinaryPath = base_path('wkhtmltopdf'); - } - - if (is_string($wkhtmlBinaryPath) && config('app.allow_untrusted_server_fetching') === true) { + if ($this->getWkhtmlBinaryPath() && config('app.allow_untrusted_server_fetching') === true) { return self::ENGINE_WKHTML; } return self::ENGINE_DOMPDF; } + protected function getWkhtmlBinaryPath(): string + { + $wkhtmlBinaryPath = config('exports.snappy.pdf_binary'); + if (file_exists(base_path('wkhtmltopdf'))) { + $wkhtmlBinaryPath = base_path('wkhtmltopdf'); + } + + return $wkhtmlBinaryPath ?: ''; + } + protected function renderUsingDomPdf(string $html): string { $options = config('exports.dompdf'); @@ -60,6 +63,13 @@ class PdfGenerator return (string) $domPdf->output(); } + protected function renderUsingWkhtml(string $html): string + { + $snappy = new SnappyPdf($this->getWkhtmlBinaryPath()); + $options = config('exports.snappy.options'); + return $snappy->getOutputFromHtml($html, $options); + } + /** * Taken from https://github.com/barryvdh/laravel-dompdf/blob/v2.1.1/src/PDF.php * Copyright (c) 2021 barryvdh, MIT License diff --git a/composer.json b/composer.json index 94f64ec72..b90ab224e 100644 --- a/composer.json +++ b/composer.json @@ -17,11 +17,11 @@ "ext-mbstring": "*", "ext-xml": "*", "bacon/bacon-qr-code": "^2.0", - "barryvdh/laravel-snappy": "^1.0", "doctrine/dbal": "^3.5", "dompdf/dompdf": "^2.0", "guzzlehttp/guzzle": "^7.4", "intervention/image": "^3.5", + "knplabs/knp-snappy": "^1.5", "laravel/framework": "^10.10", "laravel/socialite": "^5.10", "laravel/tinker": "^2.8", diff --git a/composer.lock b/composer.lock index 657a5a7fb..ad5648d6b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c0c5a3169cb23d9ab8e34324202d4c37", + "content-hash": "97259e40ffe5518cfcdf1e32eacbb175", "packages": [ { "name": "aws/aws-crt-php", @@ -209,84 +209,6 @@ }, "time": "2022-12-07T17:46:57+00:00" }, - { - "name": "barryvdh/laravel-snappy", - "version": "v1.0.3", - "source": { - "type": "git", - "url": "https://github.com/barryvdh/laravel-snappy.git", - "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/716dcb6db24de4ce8e6ae5941cfab152af337ea0", - "reference": "716dcb6db24de4ce8e6ae5941cfab152af337ea0", - "shasum": "" - }, - "require": { - "illuminate/filesystem": "^9|^10|^11.0", - "illuminate/support": "^9|^10|^11.0", - "knplabs/knp-snappy": "^1.4.4", - "php": ">=7.2" - }, - "require-dev": { - "orchestra/testbench": "^7|^8|^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - }, - "laravel": { - "providers": [ - "Barryvdh\\Snappy\\ServiceProvider" - ], - "aliases": { - "PDF": "Barryvdh\\Snappy\\Facades\\SnappyPdf", - "SnappyImage": "Barryvdh\\Snappy\\Facades\\SnappyImage" - } - } - }, - "autoload": { - "psr-4": { - "Barryvdh\\Snappy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "Snappy PDF/Image for Laravel", - "keywords": [ - "image", - "laravel", - "pdf", - "snappy", - "wkhtmltoimage", - "wkhtmltopdf" - ], - "support": { - "issues": "https://github.com/barryvdh/laravel-snappy/issues", - "source": "https://github.com/barryvdh/laravel-snappy/tree/v1.0.3" - }, - "funding": [ - { - "url": "https://fruitcake.nl", - "type": "custom" - }, - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2024-03-09T19:20:39+00:00" - }, { "name": "brick/math", "version": "0.11.0", diff --git a/readme.md b/readme.md index 5adcc06bb..c46e1641f 100644 --- a/readme.md +++ b/readme.md @@ -142,7 +142,7 @@ Note: This is not an exhaustive list of all libraries and projects that would be * [Google Material Icons](https://github.com/google/material-design-icons) - _[Apache-2.0](https://github.com/google/material-design-icons/blob/master/LICENSE)_ * [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists) - _[MIT](https://github.com/markdown-it/markdown-it/blob/master/LICENSE) and [ISC](https://github.com/revin/markdown-it-task-lists/blob/master/LICENSE)_ * [Dompdf](https://github.com/dompdf/dompdf) - _[LGPL v2.1](https://github.com/dompdf/dompdf/blob/master/LICENSE.LGPL)_ -* [BarryVD/Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy) - _[MIT](https://github.com/barryvdh/laravel-snappy/blob/master/LICENSE)_ +* [KnpLabs/snappy](https://github.com/KnpLabs/snappy) - _[MIT](https://github.com/KnpLabs/snappy/blob/master/LICENSE)_ * [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html) - _[LGPL v3.0](https://github.com/wkhtmltopdf/wkhtmltopdf/blob/master/LICENSE)_ * [diagrams.net](https://github.com/jgraph/drawio) - _[Embedded Version Terms](https://www.diagrams.net/trust/) / [Source Project - Apache-2.0](https://github.com/jgraph/drawio/blob/dev/LICENSE)_ * [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml) - _[MIT](https://github.com/onelogin/php-saml/blob/master/LICENSE)_ From 1c7128c2cb08271aa456951f6d6b4ce930df5cb5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 24 Apr 2024 16:09:53 +0100 Subject: [PATCH 42/59] PDF: Added implmentation of command PDF option Tested quickly manually but not yet covered by PHPUnit tests. --- app/Entities/Tools/PdfGenerator.php | 62 ++++++++++++++++++++++----- app/Exceptions/PdfExportException.php | 7 +++ phpunit.xml | 1 + 3 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 app/Exceptions/PdfExportException.php diff --git a/app/Entities/Tools/PdfGenerator.php b/app/Entities/Tools/PdfGenerator.php index e187b9ab2..4f23ad334 100644 --- a/app/Entities/Tools/PdfGenerator.php +++ b/app/Entities/Tools/PdfGenerator.php @@ -2,8 +2,10 @@ namespace BookStack\Entities\Tools; +use BookStack\Exceptions\PdfExportException; use Knp\Snappy\Pdf as SnappyPdf; use Dompdf\Dompdf; +use Symfony\Component\Process\Process; class PdfGenerator { @@ -13,19 +15,15 @@ class PdfGenerator /** * Generate PDF content from the given HTML content. + * @throws PdfExportException */ public function fromHtml(string $html): string { - $engine = $this->getActiveEngine(); - - if ($engine === self::ENGINE_WKHTML) { - return $this->renderUsingWkhtml($html); - } else if ($engine === self::ENGINE_COMMAND) { - // TODO - Support PDF command - return ''; - } - - return $this->renderUsingDomPdf($html); + return match ($this->getActiveEngine()) { + self::ENGINE_COMMAND => $this->renderUsingCommand($html), + self::ENGINE_WKHTML => $this->renderUsingWkhtml($html), + default => $this->renderUsingDomPdf($html) + }; } /** @@ -34,6 +32,10 @@ class PdfGenerator */ public function getActiveEngine(): string { + if (config('exports.pdf_command')) { + return self::ENGINE_COMMAND; + } + if ($this->getWkhtmlBinaryPath() && config('app.allow_untrusted_server_fetching') === true) { return self::ENGINE_WKHTML; } @@ -63,6 +65,46 @@ class PdfGenerator return (string) $domPdf->output(); } + /** + * @throws PdfExportException + */ + protected function renderUsingCommand(string $html): string + { + $command = config('exports.pdf_command'); + $inputHtml = tempnam(sys_get_temp_dir(), 'bs-pdfgen-html-'); + $outputPdf = tempnam(sys_get_temp_dir(), 'bs-pdfgen-output-'); + + $replacementsByPlaceholder = [ + '{input_html_path}' => $inputHtml, + '{output_html_path}' => $outputPdf, + ]; + + foreach ($replacementsByPlaceholder as $placeholder => $replacement) { + $command = str_replace($placeholder, escapeshellarg($replacement), $command); + } + + file_put_contents($inputHtml, $html); + + $process = Process::fromShellCommandline($command); + $process->setTimeout(15); + $process->run(); + + if (!$process->isSuccessful()) { + throw new PdfExportException("PDF Export via command failed with exit code {$process->getExitCode()}, stdout: {$process->getOutput()}, stderr: {$process->getErrorOutput()}"); + } + + $pdfContents = file_get_contents($outputPdf); + unlink($outputPdf); + + if ($pdfContents === false) { + throw new PdfExportException("PDF Export via command failed, unable to read PDF output file"); + } else if (empty($pdfContents)) { + throw new PdfExportException("PDF Export via command failed, PDF output file is empty"); + } + + return $pdfContents; + } + protected function renderUsingWkhtml(string $html): string { $snappy = new SnappyPdf($this->getWkhtmlBinaryPath()); diff --git a/app/Exceptions/PdfExportException.php b/app/Exceptions/PdfExportException.php new file mode 100644 index 000000000..beeda814f --- /dev/null +++ b/app/Exceptions/PdfExportException.php @@ -0,0 +1,7 @@ + + From 5860e1e2ce1dbcdc86370200fa1301d9ee98d674 Mon Sep 17 00:00:00 2001 From: Zero Date: Thu, 25 Apr 2024 13:35:36 +0800 Subject: [PATCH 43/59] remove space at the beginning of description --- lang/en/preferences.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/en/preferences.php b/lang/en/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/en/preferences.php +++ b/lang/en/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', From f0dd33c1b47a1ae26c58e0d32ef824d2635efeb0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 26 Apr 2024 15:39:40 +0100 Subject: [PATCH 44/59] PDF: Added tests for pdf command, fixed old tests for changes --- app/Entities/Tools/PdfGenerator.php | 2 +- tests/Entity/ExportTest.php | 39 +++++++++++++++++++++++++++-- tests/Unit/ConfigTest.php | 16 ++++++------ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/app/Entities/Tools/PdfGenerator.php b/app/Entities/Tools/PdfGenerator.php index 4f23ad334..7c6dfaa6e 100644 --- a/app/Entities/Tools/PdfGenerator.php +++ b/app/Entities/Tools/PdfGenerator.php @@ -76,7 +76,7 @@ class PdfGenerator $replacementsByPlaceholder = [ '{input_html_path}' => $inputHtml, - '{output_html_path}' => $outputPdf, + '{output_pdf_path}' => $outputPdf, ]; foreach ($replacementsByPlaceholder as $placeholder => $replacement) { diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php index eedcb672c..040f69013 100644 --- a/tests/Entity/ExportTest.php +++ b/tests/Entity/ExportTest.php @@ -6,8 +6,8 @@ use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; use BookStack\Entities\Tools\PdfGenerator; +use BookStack\Exceptions\PdfExportException; use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Str; use Tests\TestCase; class ExportTest extends TestCase @@ -483,7 +483,7 @@ class ExportTest extends TestCase { $page = $this->entities->page(); - config()->set('snappy.pdf.binary', '/abc123'); + config()->set('exports.snappy.pdf_binary', '/abc123'); config()->set('app.allow_untrusted_server_fetching', false); $resp = $this->asEditor()->get($page->getUrl('/export/pdf')); @@ -494,6 +494,41 @@ class ExportTest extends TestCase $resp->assertStatus(500); // Bad response indicates wkhtml usage } + public function test_pdf_command_option_used_if_set() + { + $page = $this->entities->page(); + $command = 'cp {input_html_path} {output_pdf_path}'; + config()->set('exports.pdf_command', $command); + + $resp = $this->asEditor()->get($page->getUrl('/export/pdf')); + $download = $resp->getContent(); + + $this->assertStringContainsString(e($page->name), $download); + $this->assertStringContainsString('set('exports.pdf_command', $command); + + $this->assertThrows(function () use ($page) { + $this->withoutExceptionHandling()->asEditor()->get($page->getUrl('/export/pdf')); + }, PdfExportException::class); + } + + public function test_pdf_command_option_errors_if_command_returns_error_status() + { + $page = $this->entities->page(); + $command = 'exit 1'; + config()->set('exports.pdf_command', $command); + + $this->assertThrows(function () use ($page) { + $this->withoutExceptionHandling()->asEditor()->get($page->getUrl('/export/pdf')); + }, PdfExportException::class); + } + public function test_html_exports_contain_csp_meta_tag() { $entities = [ diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index aedcb75aa..d5c74392f 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -80,22 +80,22 @@ class ConfigTest extends TestCase public function test_dompdf_remote_fetching_controlled_by_allow_untrusted_server_fetching_false() { - $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.options.enable_remote', false); - $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.options.enable_remote', true); + $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'exports.dompdf.enable_remote', false); + $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'exports.dompdf.enable_remote', true); } public function test_dompdf_paper_size_options_are_limited() { - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'dompdf.options.default_paper_size', 'a4'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'dompdf.options.default_paper_size', 'letter'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'dompdf.options.default_paper_size', 'a4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'exports.dompdf.default_paper_size', 'a4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'exports.dompdf.default_paper_size', 'letter'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'exports.dompdf.default_paper_size', 'a4'); } public function test_snappy_paper_size_options_are_limited() { - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'snappy.pdf.options.page-size', 'A4'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'snappy.pdf.options.page-size', 'Letter'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'snappy.pdf.options.page-size', 'A4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'exports.snappy.options.page-size', 'A4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'exports.snappy.options.page-size', 'Letter'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'exports.snappy.options.page-size', 'A4'); } public function test_sendmail_command_is_configurable() From 6b681961e503aa12893218db1ed9e6154c1b750c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 28 Apr 2024 12:29:57 +0100 Subject: [PATCH 45/59] LDAP: Updated default user filter placeholder format To not conflict with env variables, and to align with placeholders used for PDF gen command. Added test to cover, including old format supported for back-compatibility. For #4967 --- .env.example.complete | 2 +- app/Access/LdapService.php | 9 +++++++-- app/Config/services.php | 2 +- tests/Auth/LdapTest.php | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index b4beb60cc..e3b2185cc 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -215,7 +215,7 @@ LDAP_SERVER=false LDAP_BASE_DN=false LDAP_DN=false LDAP_PASS=false -LDAP_USER_FILTER=false +LDAP_USER_FILTER="(&(uid={user}))" LDAP_VERSION=false LDAP_START_TLS=false LDAP_TLS_INSECURE=false diff --git a/app/Access/LdapService.php b/app/Access/LdapService.php index 9d2667635..67f3d6f54 100644 --- a/app/Access/LdapService.php +++ b/app/Access/LdapService.php @@ -249,13 +249,18 @@ class LdapService /** * Build a filter string by injecting common variables. + * Both "${var}" and "{var}" style placeholders are supported. + * Dollar based are old format but supported for compatibility. */ protected function buildFilter(string $filterString, array $attrs): string { $newAttrs = []; foreach ($attrs as $key => $attrText) { - $newKey = '${' . $key . '}'; - $newAttrs[$newKey] = $this->ldap->escape($attrText); + $escapedText = $this->ldap->escape($attrText); + $oldVarKey = '${' . $key . '}'; + $newVarKey = '{' . $key . '}'; + $newAttrs[$oldVarKey] = $escapedText; + $newAttrs[$newVarKey] = $escapedText; } return strtr($filterString, $newAttrs); diff --git a/app/Config/services.php b/app/Config/services.php index a035f1056..da07de13e 100644 --- a/app/Config/services.php +++ b/app/Config/services.php @@ -123,7 +123,7 @@ return [ 'dn' => env('LDAP_DN', false), 'pass' => env('LDAP_PASS', false), 'base_dn' => env('LDAP_BASE_DN', false), - 'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'), + 'user_filter' => env('LDAP_USER_FILTER', '(&(uid={user}))'), 'version' => env('LDAP_VERSION', false), 'id_attribute' => env('LDAP_ID_ATTRIBUTE', 'uid'), 'email_attribute' => env('LDAP_EMAIL_ATTRIBUTE', 'mail'), diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php index 34900ce6f..cb5fc5a87 100644 --- a/tests/Auth/LdapTest.php +++ b/tests/Auth/LdapTest.php @@ -32,7 +32,7 @@ class LdapTest extends TestCase 'services.ldap.id_attribute' => 'uid', 'services.ldap.user_to_groups' => false, 'services.ldap.version' => '3', - 'services.ldap.user_filter' => '(&(uid=${user}))', + 'services.ldap.user_filter' => '(&(uid={user}))', 'services.ldap.follow_referrals' => false, 'services.ldap.tls_insecure' => false, 'services.ldap.thumbnail_attribute' => null, @@ -178,6 +178,38 @@ class LdapTest extends TestCase $this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => 'cooluser456']); } + public function test_user_filter_default_placeholder_format() + { + config()->set('services.ldap.user_filter', '(&(uid={user}))'); + $this->mockUser->name = 'barryldapuser'; + $expectedFilter = '(&(uid=\62\61\72\72\79\6c\64\61\70\75\73\65\72))'; + + $this->commonLdapMocks(1, 1, 1, 1, 1); + $this->mockLdap->shouldReceive('searchAndGetEntries') + ->once() + ->with($this->resourceId, config('services.ldap.base_dn'), $expectedFilter, \Mockery::type('array')) + ->andReturn(['count' => 0, 0 => []]); + + $resp = $this->mockUserLogin(); + $resp->assertRedirect('/login'); + } + + public function test_user_filter_old_placeholder_format() + { + config()->set('services.ldap.user_filter', '(&(username=${user}))'); + $this->mockUser->name = 'barryldapuser'; + $expectedFilter = '(&(username=\62\61\72\72\79\6c\64\61\70\75\73\65\72))'; + + $this->commonLdapMocks(1, 1, 1, 1, 1); + $this->mockLdap->shouldReceive('searchAndGetEntries') + ->once() + ->with($this->resourceId, config('services.ldap.base_dn'), $expectedFilter, \Mockery::type('array')) + ->andReturn(['count' => 0, 0 => []]); + + $resp = $this->mockUserLogin(); + $resp->assertRedirect('/login'); + } + public function test_initial_incorrect_credentials() { $this->commonLdapMocks(1, 1, 1, 0, 1); From 06bb55184c3ae84c64f370d2adb37786ac804c58 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 29 Apr 2024 17:44:56 +0100 Subject: [PATCH 46/59] WYSIWYG: Fixed unexpected clearing of table cell styles Fixes custom table cell clear-format handling since it was being called on many format removals, not just the clear-formatting action. This updates the code to specifically run on the RemoveFormat action which is triggered by the clear formatting button. Fixes #4964 --- resources/js/wysiwyg/fixes.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/resources/js/wysiwyg/fixes.js b/resources/js/wysiwyg/fixes.js index 7f87d4378..61cace660 100644 --- a/resources/js/wysiwyg/fixes.js +++ b/resources/js/wysiwyg/fixes.js @@ -29,12 +29,13 @@ export function handleEmbedAlignmentChanges(editor) { editor.on('FormatApply', event => { const isAlignment = event.format.startsWith('align'); - if (!event.node || !event.node.matches('.mce-preview-object')) { + const isElement = event.node instanceof editor.dom.doc.defaultView.HTMLElement; + if (!isElement || !isAlignment || !event.node.matches('.mce-preview-object')) { return; } const realTarget = event.node.querySelector('iframe, video'); - if (isAlignment && realTarget) { + if (realTarget) { const className = (editor.formatter.get(event.format)[0]?.classes || [])[0]; const toAdd = !realTarget.classList.contains(className); @@ -94,10 +95,12 @@ export function handleTableCellRangeEvents(editor) { // are selected. Here we watch for clear formatting events, so some manual // cleanup can be performed. const attrsToRemove = ['class', 'style', 'width', 'height']; - editor.on('FormatRemove', () => { - for (const cell of selectedCells) { - for (const attr of attrsToRemove) { - cell.removeAttribute(attr); + editor.on('ExecCommand', event => { + if (event.command === 'RemoveFormat') { + for (const cell of selectedCells) { + for (const attr of attrsToRemove) { + cell.removeAttribute(attr); + } } } }); From 493d8027cd99656cdbeb92c01da99b5baa485a09 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 29 Apr 2024 19:21:13 +0100 Subject: [PATCH 47/59] Attachments: Fixed drag into editor in Chrome Seemed to be chrome specific from testing. Required editors to have preventDefault called on dragover. Tested in Chrome, FF, & Safari. Tested in both editors, and re-tested text/image drop to ensure still works. Fixed #4975 --- resources/js/markdown/codemirror.js | 4 ++++ resources/js/wysiwyg/drop-paste-handling.js | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/resources/js/markdown/codemirror.js b/resources/js/markdown/codemirror.js index 9d54c19d7..2ea944865 100644 --- a/resources/js/markdown/codemirror.js +++ b/resources/js/markdown/codemirror.js @@ -44,6 +44,10 @@ export async function init(editor) { editor.actions.insertClipboardImages(clipboardImages, event.pageX, event.pageY); } }, + // Handle dragover event to allow as drop-target in chrome + dragover: event => { + event.preventDefault(); + }, // Handle image paste paste: event => { const clipboard = new Clipboard(event.clipboardData || event.dataTransfer); diff --git a/resources/js/wysiwyg/drop-paste-handling.js b/resources/js/wysiwyg/drop-paste-handling.js index 9668692c8..172ad970f 100644 --- a/resources/js/wysiwyg/drop-paste-handling.js +++ b/resources/js/wysiwyg/drop-paste-handling.js @@ -149,11 +149,26 @@ function drop(editor, options, event) { wrap = null; } +/** + * @param {Editor} editor + * @param {DragEvent} event + */ +function dragOver(editor, event) { + // This custom handling essentially emulates the default TinyMCE behaviour while allowing us + // to specifically call preventDefault on the event to allow the drop of custom elements. + event.preventDefault(); + editor.focus(); + const rangeUtils = window.tinymce.dom.RangeUtils; + const range = rangeUtils.getCaretRangeFromPoint(event.clientX ?? 0, event.clientY ?? 0, editor.getDoc()); + editor.selection.setRng(range); +} + /** * @param {Editor} editor * @param {WysiwygConfigOptions} options */ export function listenForDragAndPaste(editor, options) { + editor.on('dragover', event => dragOver(editor, event)); editor.on('dragstart', () => dragStart(editor)); editor.on('drop', event => drop(editor, options, event)); editor.on('paste', event => paste(editor, options, event)); From f95fb640aff2526e7f822d741be92f04fc52b584 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 1 May 2024 17:20:45 +0100 Subject: [PATCH 48/59] WYSWIYG: Improved use of object tags to embed content - Prevented image toolbars showing for objects embeds due to tinymce image placeholder, and added media toolbar. - Fixed height of object embed placeholder being forced to auto when in the editor, allowing height attributed to be properly reflected as it would on normal page view. Closes #4974 --- resources/js/wysiwyg/toolbars.js | 17 ++++++++++++++++- resources/sass/_content.scss | 14 ++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/resources/js/wysiwyg/toolbars.js b/resources/js/wysiwyg/toolbars.js index bd1ff1b6d..897aa9f06 100644 --- a/resources/js/wysiwyg/toolbars.js +++ b/resources/js/wysiwyg/toolbars.js @@ -60,7 +60,7 @@ function registerLinkContextToolbar(editor) { function registerImageContextToolbar(editor) { editor.ui.registry.addContextToolbar('imagecontexttoolbar', { predicate(node) { - return node.closest('img') !== null; + return node.closest('img') !== null && !node.hasAttribute('data-mce-object'); }, position: 'node', scope: 'node', @@ -68,6 +68,20 @@ function registerImageContextToolbar(editor) { }); } +/** + * @param {Editor} editor + */ +function registerObjectContextToolbar(editor) { + editor.ui.registry.addContextToolbar('objectcontexttoolbar', { + predicate(node) { + return node.closest('img') !== null && node.hasAttribute('data-mce-object'); + }, + position: 'node', + scope: 'node', + items: 'media', + }); +} + /** * @param {Editor} editor */ @@ -75,4 +89,5 @@ export function registerAdditionalToolbars(editor) { registerPrimaryToolbarGroups(editor); registerLinkContextToolbar(editor); registerImageContextToolbar(editor); + registerObjectContextToolbar(editor); } diff --git a/resources/sass/_content.scss b/resources/sass/_content.scss index f84499364..3aa4ac653 100644 --- a/resources/sass/_content.scss +++ b/resources/sass/_content.scss @@ -32,10 +32,6 @@ margin-left: auto; margin-right: auto; } - img { - max-width: 100%; - height:auto; - } h1, h2, h3, h4, h5, h6, pre { clear: left; } @@ -119,6 +115,16 @@ } } +// This is seperated out so we can target it out-of-editor by default +// and use advanced (:not) syntax, not supported by things like PDF gen, +// to target in-editor scenarios to handle edge-case of TinyMCE using an +// image for data placeholders where we'd want height attributes to take effect. +body .page-content img, +.page-content img:not([data-mce-object]) { + max-width: 100%; + height:auto; +} + /** * Callouts */ From 4c1c3155940bd0020117d3bd60772fc3b2759fea Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 2 May 2024 15:20:51 +0100 Subject: [PATCH 49/59] WYSWIYG: Fixed misaligned table cell p line height Removes an editor-specific line-height which was overriding cell paragraph line height, causing mis-aligned style compared to viewing. Checked a range of styles and looked at history, could not see original purpose of the line-height removed here. Closes #4960 --- resources/sass/_tinymce.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/resources/sass/_tinymce.scss b/resources/sass/_tinymce.scss index 29843e424..95294cdf2 100644 --- a/resources/sass/_tinymce.scss +++ b/resources/sass/_tinymce.scss @@ -46,11 +46,6 @@ display: block; } -// In editor line height override -.page-content.mce-content-body p { - line-height: 1.6; -} - // Pad out bottom of editor body.page-content.mce-content-body { padding-bottom: 5rem; From 8087123f2e1823d6584844a540bf4639c55f4fad Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 2 May 2024 22:56:51 +0100 Subject: [PATCH 50/59] LDAP: Review, testing and update of LDAP TLS CA cert control Review of #4913 Added testing to cover option. Updated option so it can be used for a CA directory, or a CA file. Updated option name to be somewhat abstracted from original underling PHP option. Tested against Jumpcloud. Testing took hours due to instability which was due to these settings sticking and being unstable on change until php process restart. Also due to little documentation for these options. X_TLS_CACERTDIR option needs cert files to be named via specific hashes which can be achieved via c_rehash utility. This also adds detail on STARTTLS failure, which took a long time to discover due to little detail out there for deeper PHP LDAP debugging. --- .env.example.complete | 2 +- app/Access/LdapService.php | 42 ++++++++++++++++++++++++++++++++++---- app/Config/services.php | 2 +- tests/Auth/LdapTest.php | 32 +++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index 3f1a8ab94..cfc968192 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -219,7 +219,7 @@ LDAP_USER_FILTER=false LDAP_VERSION=false LDAP_START_TLS=false LDAP_TLS_INSECURE=false -LDAP_TLS_CACERTFILE=false +LDAP_TLS_CA_CERT=false LDAP_ID_ATTRIBUTE=uid LDAP_EMAIL_ATTRIBUTE=mail LDAP_DISPLAY_NAME_ATTRIBUTE=cn diff --git a/app/Access/LdapService.php b/app/Access/LdapService.php index 56e7aba04..e0d7f2615 100644 --- a/app/Access/LdapService.php +++ b/app/Access/LdapService.php @@ -209,10 +209,10 @@ class LdapService $this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER); } - // Specify CA Cert file for LDAP. + // Configure any user-provided CA cert files for LDAP. // This option works globally and must be set before a connection is created. - if ($this->config['tls_cacertfile']) { - $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTFILE, $this->config['tls_cacertfile']); + if ($this->config['tls_ca_cert']) { + $this->configureTlsCaCerts($this->config['tls_ca_cert']); } $ldapHost = $this->parseServerString($this->config['server']); @@ -229,7 +229,14 @@ class LdapService // Start and verify TLS if it's enabled if ($this->config['start_tls']) { - $started = $this->ldap->startTls($ldapConnection); + try { + $started = $this->ldap->startTls($ldapConnection); + } catch (\Exception $exception) { + $error = $exception->getMessage() . ' :: ' . ldap_error($ldapConnection); + ldap_get_option($ldapConnection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detail); + Log::info("LDAP STARTTLS failure: {$error} {$detail}"); + throw new LdapException('Could not start TLS connection. Further details in the application log.'); + } if (!$started) { throw new LdapException('Could not start TLS connection'); } @@ -240,6 +247,33 @@ class LdapService return $this->ldapConnection; } + /** + * Configure TLS CA certs globally for ldap use. + * This will detect if the given path is a directory or file, and set the relevant + * LDAP TLS options appropriately otherwise throw an exception if no file/folder found. + * + * Note: When using a folder, certificates are expected to be correctly named by hash + * which can be done via the c_rehash utility. + * + * @throws LdapException + */ + protected function configureTlsCaCerts(string $caCertPath): void + { + $errMessage = "Provided path [{$caCertPath}] for LDAP TLS CA certs could not be resolved to an existing location"; + $path = realpath($caCertPath); + if ($path === false) { + throw new LdapException($errMessage); + } + + if (is_dir($path)) { + $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTDIR, $path); + } else if (is_file($path)) { + $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTFILE, $path); + } else { + throw new LdapException($errMessage); + } + } + /** * Parse an LDAP server string and return the host suitable for a connection. * Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'. diff --git a/app/Config/services.php b/app/Config/services.php index a407b5dc8..f93ca44f6 100644 --- a/app/Config/services.php +++ b/app/Config/services.php @@ -133,7 +133,7 @@ return [ 'group_attribute' => env('LDAP_GROUP_ATTRIBUTE', 'memberOf'), 'remove_from_groups' => env('LDAP_REMOVE_FROM_GROUPS', false), 'tls_insecure' => env('LDAP_TLS_INSECURE', false), - 'tls_cacertfile' => env('LDAP_TLS_CACERTFILE', false), + 'tls_ca_cert' => env('LDAP_TLS_CA_CERT', false), 'start_tls' => env('LDAP_START_TLS', false), 'thumbnail_attribute' => env('LDAP_THUMBNAIL_ATTRIBUTE', null), ], diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php index 34900ce6f..717167729 100644 --- a/tests/Auth/LdapTest.php +++ b/tests/Auth/LdapTest.php @@ -4,6 +4,7 @@ namespace Tests\Auth; use BookStack\Access\Ldap; use BookStack\Access\LdapService; +use BookStack\Exceptions\LdapException; use BookStack\Users\Models\Role; use BookStack\Users\Models\User; use Illuminate\Testing\TestResponse; @@ -35,6 +36,7 @@ class LdapTest extends TestCase 'services.ldap.user_filter' => '(&(uid=${user}))', 'services.ldap.follow_referrals' => false, 'services.ldap.tls_insecure' => false, + 'services.ldap.tls_ca_cert' => false, 'services.ldap.thumbnail_attribute' => null, ]); $this->mockLdap = $this->mock(Ldap::class); @@ -767,4 +769,34 @@ EBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=')], $this->assertNotNull($user->avatar); $this->assertEquals('8c90748342f19b195b9c6b4eff742ded', md5_file(public_path($user->avatar->path))); } + + public function test_tls_ca_cert_option_throws_if_set_to_invalid_location() + { + $path = 'non_found_' . time(); + config()->set(['services.ldap.tls_ca_cert' => $path]); + + $this->commonLdapMocks(0, 0, 0, 0, 0); + + $this->assertThrows(function () { + $this->withoutExceptionHandling()->mockUserLogin(); + }, LdapException::class, "Provided path [{$path}] for LDAP TLS CA certs could not be resolved to an existing location"); + } + + public function test_tls_ca_cert_option_used_if_set_to_a_folder() + { + $path = $this->files->testFilePath(''); + config()->set(['services.ldap.tls_ca_cert' => $path]); + + $this->mockLdap->shouldReceive('setOption')->once()->with(null, LDAP_OPT_X_TLS_CACERTDIR, rtrim($path, '/'))->andReturn(true); + $this->runFailedAuthLogin(); + } + + public function test_tls_ca_cert_option_used_if_set_to_a_file() + { + $path = $this->files->testFilePath('test-file.txt'); + config()->set(['services.ldap.tls_ca_cert' => $path]); + + $this->mockLdap->shouldReceive('setOption')->once()->with(null, LDAP_OPT_X_TLS_CACERTFILE, $path)->andReturn(true); + $this->runFailedAuthLogin(); + } } From f9e087330b5d90ed5ec23ac0725cfeccd1eb7cb5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 3 May 2024 13:35:30 +0100 Subject: [PATCH 51/59] WYSIWYG: Added text direction support for code editor popup Editor popup will now reflect the direction of the opened code block. This also updates in-editor codemirror instances to correcly reflect/use the direction if set on the inner code elem. This also defaults new code blocks, when in RTL languages, to be started in LTR, which can then be changed via in-editor direction controls if needed. This is on the assumption that most code will be LTR (could not find much examples of RTL code use). Fixes #4943 --- resources/js/code/index.mjs | 21 ++++++++++++++++++--- resources/js/components/code-editor.js | 12 +++++++++++- resources/js/wysiwyg/plugin-codeeditor.js | 19 +++++++++++++------ resources/sass/_components.scss | 2 +- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/resources/js/code/index.mjs b/resources/js/code/index.mjs index ab31e3f74..d2ea12a4c 100644 --- a/resources/js/code/index.mjs +++ b/resources/js/code/index.mjs @@ -38,6 +38,23 @@ function addCopyIcon(editorView) { }); } +/** + * @param {HTMLElement} codeElem + * @returns {String} + */ +function getDirectionFromCodeBlock(codeElem) { + let dir = ''; + const innerCodeElem = codeElem.querySelector('code'); + + if (innerCodeElem && innerCodeElem.hasAttribute('dir')) { + dir = innerCodeElem.getAttribute('dir'); + } else if (codeElem.hasAttribute('dir')) { + dir = codeElem.getAttribute('dir'); + } + + return dir; +} + /** * Add code highlighting to a single element. * @param {HTMLElement} elem @@ -48,16 +65,14 @@ function highlightElem(elem) { const content = elem.textContent.trimEnd(); let langName = ''; - let innerCodeDirection = ''; if (innerCodeElem !== null) { langName = innerCodeElem.className.replace('language-', ''); - innerCodeDirection = innerCodeElem.getAttribute('dir'); } const wrapper = document.createElement('div'); elem.parentNode.insertBefore(wrapper, elem); - const direction = innerCodeDirection || elem.getAttribute('dir') || ''; + const direction = getDirectionFromCodeBlock(elem); if (direction) { wrapper.setAttribute('dir', direction); } diff --git a/resources/js/components/code-editor.js b/resources/js/components/code-editor.js index 1c68c2048..091c3483f 100644 --- a/resources/js/components/code-editor.js +++ b/resources/js/components/code-editor.js @@ -129,7 +129,7 @@ export class CodeEditor extends Component { this.hide(); } - async open(code, language, saveCallback, cancelCallback) { + async open(code, language, direction, saveCallback, cancelCallback) { this.languageInput.value = language; this.saveCallback = saveCallback; this.cancelCallback = cancelCallback; @@ -137,6 +137,7 @@ export class CodeEditor extends Component { await this.show(); this.languageInputChange(language); this.editor.setContent(code); + this.setDirection(direction); } async show() { @@ -156,6 +157,15 @@ export class CodeEditor extends Component { }); } + setDirection(direction) { + const target = this.editorInput.parentElement; + if (direction) { + target.setAttribute('dir', direction); + } else { + target.removeAttribute('dir'); + } + } + hide() { this.getPopup().hide(); this.addHistory(); diff --git a/resources/js/wysiwyg/plugin-codeeditor.js b/resources/js/wysiwyg/plugin-codeeditor.js index f86760214..c01a7eca0 100644 --- a/resources/js/wysiwyg/plugin-codeeditor.js +++ b/resources/js/wysiwyg/plugin-codeeditor.js @@ -6,13 +6,14 @@ function elemIsCodeBlock(elem) { * @param {Editor} editor * @param {String} code * @param {String} language + * @param {String} direction * @param {function(string, string)} callback (Receives (code: string,language: string) */ -function showPopup(editor, code, language, callback) { +function showPopup(editor, code, language, direction, callback) { /** @var {CodeEditor} codeEditor * */ const codeEditor = window.$components.first('code-editor'); const bookMark = editor.selection.getBookmark(); - codeEditor.open(code, language, (newCode, newLang) => { + codeEditor.open(code, language, direction, (newCode, newLang) => { callback(newCode, newLang); editor.focus(); editor.selection.moveToBookmark(bookMark); @@ -27,7 +28,8 @@ function showPopup(editor, code, language, callback) { * @param {CodeBlockElement} codeBlock */ function showPopupForCodeBlock(editor, codeBlock) { - showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), (newCode, newLang) => { + const direction = codeBlock.getAttribute('dir') || ''; + showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), direction, (newCode, newLang) => { codeBlock.setContent(newCode, newLang); }); } @@ -179,13 +181,17 @@ function register(editor) { showPopupForCodeBlock(editor, selectedNode); } else { const textContent = editor.selection.getContent({format: 'text'}); - showPopup(editor, textContent, '', (newCode, newLang) => { + const direction = document.dir === 'rtl' ? 'ltr' : ''; + showPopup(editor, textContent, '', direction, (newCode, newLang) => { const pre = doc.createElement('pre'); const code = doc.createElement('code'); code.classList.add(`language-${newLang}`); code.innerText = newCode; - pre.append(code); + if (direction) { + pre.setAttribute('dir', direction); + } + pre.append(code); editor.insertContent(pre.outerHTML); }); } @@ -205,7 +211,8 @@ function register(editor) { contenteditable: 'false', }); - const direction = el.attr('dir'); + const childCodeBlock = el.children().filter(child => child.name === 'code')[0] || null; + const direction = el.attr('dir') || (childCodeBlock && childCodeBlock.attr('dir')) || ''; if (direction) { wrapper.attr('dir', direction); } diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index ae899357c..fc4ddeba4 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -182,7 +182,7 @@ flex: 0; .popup-title { color: #FFF; - margin-right: auto; + margin-inline-end: auto; padding: 8px $-m; } &.flex-container-row { From 5c28bcf8651474ffd7f15831e3de705aae5a7ef8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 May 2024 13:59:41 +0100 Subject: [PATCH 52/59] Registration: Reviewed added simple honeypot, added testing Also cleaned up old RegistrationController syntax. Review of #4970 --- app/Access/Controllers/RegisterController.php | 20 +++++-------------- resources/views/auth/register.blade.php | 3 ++- tests/Auth/RegistrationTest.php | 19 ++++++++++++++++++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/app/Access/Controllers/RegisterController.php b/app/Access/Controllers/RegisterController.php index 25b0a3036..e9812aa5d 100644 --- a/app/Access/Controllers/RegisterController.php +++ b/app/Access/Controllers/RegisterController.php @@ -15,24 +15,13 @@ use Illuminate\Validation\Rules\Password; class RegisterController extends Controller { - protected SocialDriverManager $socialDriverManager; - protected RegistrationService $registrationService; - protected LoginService $loginService; - - /** - * Create a new controller instance. - */ public function __construct( - SocialDriverManager $socialDriverManager, - RegistrationService $registrationService, - LoginService $loginService + protected SocialDriverManager $socialDriverManager, + protected RegistrationService $registrationService, + protected LoginService $loginService ) { $this->middleware('guest'); $this->middleware('guard:standard'); - - $this->socialDriverManager = $socialDriverManager; - $this->registrationService = $registrationService; - $this->loginService = $loginService; } /** @@ -87,7 +76,8 @@ class RegisterController extends Controller 'name' => ['required', 'min:2', 'max:100'], 'email' => ['required', 'email', 'max:255', 'unique:users'], 'password' => ['required', Password::default()], - 'username' => ['prohibited'], // this is a honeypot for bots that must not be filled in + // Basic honey for bots that must not be filled in + 'username' => ['prohibited'], ]); } } diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index f9f4e8cb3..1ea712e1d 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -13,8 +13,9 @@ {!! csrf_field() !!} + {{-- Simple honeypot field --}} diff --git a/tests/Auth/RegistrationTest.php b/tests/Auth/RegistrationTest.php index ff1a9d66b..60ae17573 100644 --- a/tests/Auth/RegistrationTest.php +++ b/tests/Auth/RegistrationTest.php @@ -184,4 +184,23 @@ class RegistrationTest extends TestCase $resp->assertSee('The email must be a valid email address.'); $resp->assertSee('The password must be at least 8 characters.'); } + + public function test_registration_simple_honeypot_active() + { + $this->setSettings(['registration-enabled' => 'true']); + + $resp = $this->get('/register'); + $this->withHtml($resp)->assertElementExists('form input[name="username"]'); + + $resp = $this->post('/register', [ + 'name' => 'Barry', + 'email' => 'barrybot@example.com', + 'password' => 'barryIsTheBestBot', + 'username' => 'MyUsername' + ]); + $resp->assertRedirect('/register'); + + $resp = $this->followRedirects($resp); + $this->withHtml($resp)->assertElementExists('form input[name="username"].text-neg'); + } } From 3946158e8821308f89ee12811f053527eedc23c2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 4 May 2024 16:28:18 +0100 Subject: [PATCH 53/59] API: Added audit log list endpoint Not yested covered with testing. Changes database columns for more presentable names and for future use to connect additional model types. For #4316 --- app/Activity/ActivityQueries.php | 10 +-- .../Controllers/AuditLogApiController.php | 28 +++++++ .../Controllers/AuditLogController.php | 2 +- app/Activity/Models/Activity.php | 24 +++--- app/Activity/Tools/ActivityLogger.php | 10 +-- app/Console/Commands/ClearActivityCommand.php | 2 +- app/Entities/Models/Entity.php | 2 +- ...54409_rename_activity_relation_columns.php | 30 +++++++ dev/api/responses/audit-log-list.json | 80 +++++++++++++++++++ routes/api.php | 3 + 10 files changed, 165 insertions(+), 26 deletions(-) create mode 100644 app/Activity/Controllers/AuditLogApiController.php create mode 100644 database/migrations/2024_05_04_154409_rename_activity_relation_columns.php create mode 100644 dev/api/responses/audit-log-list.json diff --git a/app/Activity/ActivityQueries.php b/app/Activity/ActivityQueries.php index dae0791b1..9de70f022 100644 --- a/app/Activity/ActivityQueries.php +++ b/app/Activity/ActivityQueries.php @@ -27,14 +27,14 @@ class ActivityQueries public function latest(int $count = 20, int $page = 0): array { $activityList = $this->permissions - ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type') + ->restrictEntityRelationQuery(Activity::query(), 'activities', 'loggable_id', 'loggable_type') ->orderBy('created_at', 'desc') ->with(['user']) ->skip($count * $page) ->take($count) ->get(); - $this->listLoader->loadIntoRelations($activityList->all(), 'entity', false); + $this->listLoader->loadIntoRelations($activityList->all(), 'loggable', false); return $this->filterSimilar($activityList); } @@ -59,8 +59,8 @@ class ActivityQueries $query->where(function (Builder $query) use ($queryIds) { foreach ($queryIds as $morphClass => $idArr) { $query->orWhere(function (Builder $innerQuery) use ($morphClass, $idArr) { - $innerQuery->where('entity_type', '=', $morphClass) - ->whereIn('entity_id', $idArr); + $innerQuery->where('loggable_type', '=', $morphClass) + ->whereIn('loggable_id', $idArr); }); } }); @@ -82,7 +82,7 @@ class ActivityQueries public function userActivity(User $user, int $count = 20, int $page = 0): array { $activityList = $this->permissions - ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type') + ->restrictEntityRelationQuery(Activity::query(), 'activities', 'loggable_id', 'loggable_type') ->orderBy('created_at', 'desc') ->where('user_id', '=', $user->id) ->skip($count * $page) diff --git a/app/Activity/Controllers/AuditLogApiController.php b/app/Activity/Controllers/AuditLogApiController.php new file mode 100644 index 000000000..650d17446 --- /dev/null +++ b/app/Activity/Controllers/AuditLogApiController.php @@ -0,0 +1,28 @@ +checkPermission('settings-manage'); + $this->checkPermission('users-manage'); + + $query = Activity::query()->with(['user']); + + return $this->apiListingResponse($query, [ + 'id', 'type', 'detail', 'user_id', 'loggable_id', 'loggable_type', 'ip', 'created_at', + ]); + } +} diff --git a/app/Activity/Controllers/AuditLogController.php b/app/Activity/Controllers/AuditLogController.php index c3910a26b..641106d7f 100644 --- a/app/Activity/Controllers/AuditLogController.php +++ b/app/Activity/Controllers/AuditLogController.php @@ -32,7 +32,7 @@ class AuditLogController extends Controller $query = Activity::query() ->with([ - 'entity' => fn ($query) => $query->withTrashed(), + 'loggable' => fn ($query) => $query->withTrashed(), 'user', ]) ->orderBy($listOptions->getSort(), $listOptions->getOrder()); diff --git a/app/Activity/Models/Activity.php b/app/Activity/Models/Activity.php index 5fad9f1d3..ebe5d66d6 100644 --- a/app/Activity/Models/Activity.php +++ b/app/Activity/Models/Activity.php @@ -17,24 +17,22 @@ use Illuminate\Support\Str; * @property User $user * @property Entity $entity * @property string $detail - * @property string $entity_type - * @property int $entity_id + * @property string $loggable_type + * @property int $loggable_id * @property int $user_id * @property Carbon $created_at - * @property Carbon $updated_at */ class Activity extends Model { /** - * Get the entity for this activity. + * Get the loggable model related to this activity. + * Currently only used for entities (previously entity_[id/type] columns). + * Could be used for others but will need an audit of uses where assumed + * to be entities. */ - public function entity(): MorphTo + public function loggable(): MorphTo { - if ($this->entity_type === '') { - $this->entity_type = null; - } - - return $this->morphTo('entity'); + return $this->morphTo('loggable'); } /** @@ -47,8 +45,8 @@ class Activity extends Model public function jointPermissions(): HasMany { - return $this->hasMany(JointPermission::class, 'entity_id', 'entity_id') - ->whereColumn('activities.entity_type', '=', 'joint_permissions.entity_type'); + return $this->hasMany(JointPermission::class, 'entity_id', 'loggable_id') + ->whereColumn('activities.loggable_type', '=', 'joint_permissions.entity_type'); } /** @@ -74,6 +72,6 @@ class Activity extends Model */ public function isSimilarTo(self $activityB): bool { - return [$this->type, $this->entity_type, $this->entity_id] === [$activityB->type, $activityB->entity_type, $activityB->entity_id]; + return [$this->type, $this->loggable_type, $this->loggable_id] === [$activityB->type, $activityB->loggable_type, $activityB->loggable_id]; } } diff --git a/app/Activity/Tools/ActivityLogger.php b/app/Activity/Tools/ActivityLogger.php index adda36c1b..415d11084 100644 --- a/app/Activity/Tools/ActivityLogger.php +++ b/app/Activity/Tools/ActivityLogger.php @@ -32,8 +32,8 @@ class ActivityLogger $activity->detail = $detailToStore; if ($detail instanceof Entity) { - $activity->entity_id = $detail->id; - $activity->entity_type = $detail->getMorphClass(); + $activity->loggable_id = $detail->id; + $activity->loggable_type = $detail->getMorphClass(); } $activity->save(); @@ -64,9 +64,9 @@ class ActivityLogger public function removeEntity(Entity $entity): void { $entity->activity()->update([ - 'detail' => $entity->name, - 'entity_id' => null, - 'entity_type' => null, + 'detail' => $entity->name, + 'loggable_id' => null, + 'loggable_type' => null, ]); } diff --git a/app/Console/Commands/ClearActivityCommand.php b/app/Console/Commands/ClearActivityCommand.php index 54085c12b..6ec2e1a2a 100644 --- a/app/Console/Commands/ClearActivityCommand.php +++ b/app/Console/Commands/ClearActivityCommand.php @@ -19,7 +19,7 @@ class ClearActivityCommand extends Command * * @var string */ - protected $description = 'Clear user activity from the system'; + protected $description = 'Clear user (audit-log) activity from the system'; /** * Execute the console command. diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index f07d372c3..0de83c938 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -137,7 +137,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function activity(): MorphMany { - return $this->morphMany(Activity::class, 'entity') + return $this->morphMany(Activity::class, 'loggable') ->orderBy('created_at', 'desc'); } diff --git a/database/migrations/2024_05_04_154409_rename_activity_relation_columns.php b/database/migrations/2024_05_04_154409_rename_activity_relation_columns.php new file mode 100644 index 000000000..ee3358d73 --- /dev/null +++ b/database/migrations/2024_05_04_154409_rename_activity_relation_columns.php @@ -0,0 +1,30 @@ +renameColumn('entity_id', 'loggable_id'); + $table->renameColumn('entity_type', 'loggable_type'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('activities', function (Blueprint $table) { + $table->renameColumn('loggable_id', 'entity_id'); + $table->renameColumn('loggable_type', 'entity_type'); + }); + } +}; diff --git a/dev/api/responses/audit-log-list.json b/dev/api/responses/audit-log-list.json new file mode 100644 index 000000000..15a25e106 --- /dev/null +++ b/dev/api/responses/audit-log-list.json @@ -0,0 +1,80 @@ +{ + "data": [ + { + "id": 1, + "type": "bookshelf_create", + "detail": "", + "user_id": 1, + "loggable_id": 1, + "loggable_type": "bookshelf", + "ip": "124.4.x.x", + "created_at": "2021-09-29T12:32:02.000000Z", + "user": { + "id": 1, + "name": "Admins", + "slug": "admins" + } + }, + { + "id": 2, + "type": "auth_login", + "detail": "standard; (1) Admin", + "user_id": 1, + "loggable_id": null, + "loggable_type": null, + "ip": "127.0.x.x", + "created_at": "2021-09-29T12:32:04.000000Z", + "user": { + "id": 1, + "name": "Admins", + "slug": "admins" + } + }, + { + "id": 3, + "type": "bookshelf_update", + "detail": "", + "user_id": 1, + "loggable_id": 1, + "loggable_type": "bookshelf", + "ip": "127.0.x.x", + "created_at": "2021-09-29T12:32:07.000000Z", + "user": { + "id": 1, + "name": "Admins", + "slug": "admins" + } + }, + { + "id": 4, + "type": "page_create", + "detail": "", + "user_id": 1, + "loggable_id": 1, + "loggable_type": "page", + "ip": "127.0.x.x", + "created_at": "2021-09-29T12:32:13.000000Z", + "user": { + "id": 1, + "name": "Admins", + "slug": "admins" + } + }, + { + "id": 5, + "type": "page_update", + "detail": "", + "user_id": 1, + "loggable_id": 1, + "loggable_type": "page", + "ip": "127.0.x.x", + "created_at": "2021-09-29T12:37:27.000000Z", + "user": { + "id": 1, + "name": "Admins", + "slug": "admins" + } + } + ], + "total": 6088 +} \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 04c94a966..c0919d324 100644 --- a/routes/api.php +++ b/routes/api.php @@ -6,6 +6,7 @@ * Controllers all end with "ApiController" */ +use BookStack\Activity\Controllers\AuditLogApiController; use BookStack\Api\ApiDocsController; use BookStack\Entities\Controllers as EntityControllers; use BookStack\Permissions\ContentPermissionApiController; @@ -89,3 +90,5 @@ Route::delete('recycle-bin/{deletionId}', [EntityControllers\RecycleBinApiContro Route::get('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'read']); Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']); + +Route::get('audit-log', [AuditLogApiController::class, 'list']); From 67df127c2618d1d2bb9bc250e86ad0753f278769 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 May 2024 15:44:58 +0100 Subject: [PATCH 54/59] API: Added to, and updated, testing to cover audit log additions --- app/Activity/ActivityQueries.php | 2 +- app/Activity/Models/Activity.php | 2 +- .../views/common/activity-item.blade.php | 8 +-- tests/Activity/AuditLogApiTest.php | 60 +++++++++++++++++++ tests/{Actions => Activity}/AuditLogTest.php | 8 +-- .../{Actions => Activity}/WebhookCallTest.php | 2 +- .../WebhookFormatTesting.php | 2 +- .../WebhookManagementTest.php | 2 +- tests/Commands/ClearActivityCommandTest.php | 2 +- tests/Settings/RecycleBinTest.php | 12 ++-- tests/TestCase.php | 4 +- tests/User/UserProfileTest.php | 2 +- 12 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 tests/Activity/AuditLogApiTest.php rename tests/{Actions => Activity}/AuditLogTest.php (98%) rename tests/{Actions => Activity}/WebhookCallTest.php (99%) rename tests/{Actions => Activity}/WebhookFormatTesting.php (98%) rename tests/{Actions => Activity}/WebhookManagementTest.php (99%) diff --git a/app/Activity/ActivityQueries.php b/app/Activity/ActivityQueries.php index 9de70f022..86326fb80 100644 --- a/app/Activity/ActivityQueries.php +++ b/app/Activity/ActivityQueries.php @@ -66,7 +66,7 @@ class ActivityQueries }); $activity = $query->orderBy('created_at', 'desc') - ->with(['entity' => function (Relation $query) { + ->with(['loggable' => function (Relation $query) { $query->withTrashed(); }, 'user.avatar']) ->skip($count * ($page - 1)) diff --git a/app/Activity/Models/Activity.php b/app/Activity/Models/Activity.php index ebe5d66d6..ac9fec517 100644 --- a/app/Activity/Models/Activity.php +++ b/app/Activity/Models/Activity.php @@ -15,7 +15,7 @@ use Illuminate\Support\Str; /** * @property string $type * @property User $user - * @property Entity $entity + * @property Entity $loggable * @property string $detail * @property string $loggable_type * @property int $loggable_id diff --git a/resources/views/common/activity-item.blade.php b/resources/views/common/activity-item.blade.php index 89d44b152..1c970084f 100644 --- a/resources/views/common/activity-item.blade.php +++ b/resources/views/common/activity-item.blade.php @@ -16,12 +16,12 @@ {{ $activity->getText() }} - @if($activity->entity && is_null($activity->entity->deleted_at)) - {{ $activity->entity->name }} + @if($activity->loggable && is_null($activity->loggable->deleted_at)) + {{ $activity->loggable->name }} @endif - @if($activity->entity && !is_null($activity->entity->deleted_at)) - "{{ $activity->entity->name }}" + @if($activity->loggable && !is_null($activity->loggable->deleted_at)) + "{{ $activity->loggable->name }}" @endif
diff --git a/tests/Activity/AuditLogApiTest.php b/tests/Activity/AuditLogApiTest.php new file mode 100644 index 000000000..75cc364f8 --- /dev/null +++ b/tests/Activity/AuditLogApiTest.php @@ -0,0 +1,60 @@ +users->editor(); + + $assertPermissionErrorOnCall = function () use ($editor) { + $resp = $this->actingAsForApi($editor)->getJson('/api/audit-log'); + $resp->assertStatus(403); + $resp->assertJson($this->permissionErrorResponse()); + }; + + $assertPermissionErrorOnCall(); + $this->permissions->grantUserRolePermissions($editor, ['users-manage']); + $assertPermissionErrorOnCall(); + $this->permissions->removeUserRolePermissions($editor, ['users-manage']); + $this->permissions->grantUserRolePermissions($editor, ['settings-manage']); + $assertPermissionErrorOnCall(); + + $this->permissions->grantUserRolePermissions($editor, ['settings-manage', 'users-manage']); + $resp = $this->actingAsForApi($editor)->getJson('/api/audit-log'); + $resp->assertOk(); + } + + public function test_index_endpoint_returns_expected_data() + { + $page = $this->entities->page(); + $admin = $this->users->admin(); + $this->actingAsForApi($admin); + Activity::add(ActivityType::PAGE_UPDATE, $page); + + $resp = $this->get("/api/audit-log?filter[loggable_id]={$page->id}"); + $resp->assertJson(['data' => [ + [ + 'type' => 'page_update', + 'detail' => "({$page->id}) {$page->name}", + 'user_id' => $admin->id, + 'loggable_id' => $page->id, + 'loggable_type' => 'page', + 'ip' => '127.0.0.1', + 'user' => [ + 'id' => $admin->id, + 'name' => $admin->name, + 'slug' => $admin->slug, + ], + ] + ]]); + } +} diff --git a/tests/Actions/AuditLogTest.php b/tests/Activity/AuditLogTest.php similarity index 98% rename from tests/Actions/AuditLogTest.php rename to tests/Activity/AuditLogTest.php index 5e355ca09..350cd9287 100644 --- a/tests/Actions/AuditLogTest.php +++ b/tests/Activity/AuditLogTest.php @@ -1,6 +1,6 @@ ActivityType::PAGE_UPDATE, 'ip' => '192.123.45.1', 'user_id' => $editor->id, - 'entity_id' => $page->id, + 'loggable_id' => $page->id, ]); $resp = $this->asAdmin()->get('/settings/audit'); @@ -207,7 +207,7 @@ class AuditLogTest extends TestCase 'type' => ActivityType::PAGE_UPDATE, 'ip' => '127.0.0.1', 'user_id' => $editor->id, - 'entity_id' => $page->id, + 'loggable_id' => $page->id, ]); } @@ -229,7 +229,7 @@ class AuditLogTest extends TestCase 'type' => ActivityType::PAGE_UPDATE, 'ip' => '192.123.x.x', 'user_id' => $editor->id, - 'entity_id' => $page->id, + 'loggable_id' => $page->id, ]); } } diff --git a/tests/Actions/WebhookCallTest.php b/tests/Activity/WebhookCallTest.php similarity index 99% rename from tests/Actions/WebhookCallTest.php rename to tests/Activity/WebhookCallTest.php index 16986ba2e..37c87267a 100644 --- a/tests/Actions/WebhookCallTest.php +++ b/tests/Activity/WebhookCallTest.php @@ -1,6 +1,6 @@ assertDatabaseHas('activities', [ 'type' => 'page_update', - 'entity_id' => $page->id, + 'loggable_id' => $page->id, 'user_id' => $this->users->editor()->id, ]); diff --git a/tests/Settings/RecycleBinTest.php b/tests/Settings/RecycleBinTest.php index 8adc92f25..33284b4b3 100644 --- a/tests/Settings/RecycleBinTest.php +++ b/tests/Settings/RecycleBinTest.php @@ -153,22 +153,22 @@ class RecycleBinTest extends TestCase $this->assertDatabaseHas('activities', [ 'type' => 'page_delete', - 'entity_id' => $page->id, - 'entity_type' => $page->getMorphClass(), + 'loggable_id' => $page->id, + 'loggable_type' => $page->getMorphClass(), ]); $this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}"); $this->assertDatabaseMissing('activities', [ 'type' => 'page_delete', - 'entity_id' => $page->id, - 'entity_type' => $page->getMorphClass(), + 'loggable_id' => $page->id, + 'loggable_type' => $page->getMorphClass(), ]); $this->assertDatabaseHas('activities', [ 'type' => 'page_delete', - 'entity_id' => null, - 'entity_type' => null, + 'loggable_id' => null, + 'loggable_type' => null, 'detail' => $page->name, ]); } diff --git a/tests/TestCase.php b/tests/TestCase.php index c59f843e9..b63de3076 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -248,8 +248,8 @@ abstract class TestCase extends BaseTestCase $detailsToCheck = ['type' => $type]; if ($entity) { - $detailsToCheck['entity_type'] = $entity->getMorphClass(); - $detailsToCheck['entity_id'] = $entity->id; + $detailsToCheck['loggable_type'] = $entity->getMorphClass(); + $detailsToCheck['loggable_id'] = $entity->id; } if ($detail) { diff --git a/tests/User/UserProfileTest.php b/tests/User/UserProfileTest.php index 4bfb3c878..065ae8dc8 100644 --- a/tests/User/UserProfileTest.php +++ b/tests/User/UserProfileTest.php @@ -2,8 +2,8 @@ namespace Tests\User; -use Activity; use BookStack\Activity\ActivityType; +use BookStack\Facades\Activity; use BookStack\Users\Models\User; use Tests\TestCase; From d54c7b4783b05d8a8b4b904b280453d954698732 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 May 2024 16:05:21 +0100 Subject: [PATCH 55/59] Audit Log: Fixed bad reference to linked entity item --- resources/views/settings/audit.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/settings/audit.blade.php b/resources/views/settings/audit.blade.php index 89d743fdc..28cdeb8a5 100644 --- a/resources/views/settings/audit.blade.php +++ b/resources/views/settings/audit.blade.php @@ -94,8 +94,8 @@ class="mr-xs hide-over-m">{{ trans('settings.audit_table_event') }} : {{ $activity->type }}
- @if($activity->entity) - @include('entities.icon-link', ['entity' => $activity->entity]) + @if($activity->loggable instanceof \BookStack\Entities\Models\Entity) + @include('entities.icon-link', ['entity' => $activity->loggable]) @elseif($activity->detail && $activity->isForEntity())
{{ trans('settings.audit_deleted_item') }}
From d206129f3dca103677168e973f66e45c2c636ff6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 5 May 2024 16:30:04 +0100 Subject: [PATCH 56/59] Deps: Updated composer dependencies --- composer.lock | 686 ++++++++++++++++++++++++++++---------------------- 1 file changed, 383 insertions(+), 303 deletions(-) diff --git a/composer.lock b/composer.lock index ad5648d6b..b5b08a902 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "aws/aws-crt-php", - "version": "v1.2.4", + "version": "v1.2.5", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2" + "reference": "0ea1f04ec5aa9f049f97e012d1ed63b76834a31b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2", - "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/0ea1f04ec5aa9f049f97e012d1ed63b76834a31b", + "reference": "0ea1f04ec5aa9f049f97e012d1ed63b76834a31b", "shasum": "" }, "require": { @@ -56,22 +56,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.5" }, - "time": "2023-11-08T00:42:13+00:00" + "time": "2024-04-19T21:30:56+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.301.1", + "version": "3.305.9", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba" + "reference": "a611af9a40a5d93f2f04427b322dbb6044e90327" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0a910d2b35e7087337cdf3569dc9b6ce232aafba", - "reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a611af9a40a5d93f2f04427b322dbb6044e90327", + "reference": "a611af9a40a5d93f2f04427b322dbb6044e90327", "shasum": "" }, "require": { @@ -151,9 +151,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.301.1" + "source": "https://github.com/aws/aws-sdk-php/tree/3.305.9" }, - "time": "2024-03-15T18:14:42+00:00" + "time": "2024-05-03T18:09:03+00:00" }, { "name": "bacon/bacon-qr-code", @@ -211,25 +211,25 @@ }, { "name": "brick/math", - "version": "0.11.0", + "version": "0.12.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", - "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", "shasum": "" }, "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^9.0", - "vimeo/psalm": "5.0.0" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" }, "type": "library", "autoload": { @@ -249,12 +249,17 @@ "arithmetic", "bigdecimal", "bignum", + "bignumber", "brick", - "math" + "decimal", + "integer", + "math", + "mathematics", + "rational" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.11.0" + "source": "https://github.com/brick/math/tree/0.12.1" }, "funding": [ { @@ -262,7 +267,7 @@ "type": "github" } ], - "time": "2023-01-15T23:15:59+00:00" + "time": "2023-11-29T23:19:16+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -553,16 +558,16 @@ }, { "name": "doctrine/dbal", - "version": "3.8.3", + "version": "3.8.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c" + "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c", - "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd", + "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd", "shasum": "" }, "require": { @@ -646,7 +651,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.3" + "source": "https://github.com/doctrine/dbal/tree/3.8.4" }, "funding": [ { @@ -662,7 +667,7 @@ "type": "tidelift" } ], - "time": "2024-03-03T15:55:06+00:00" + "time": "2024-04-25T07:04:44+00:00" }, { "name": "doctrine/deprecations", @@ -972,16 +977,16 @@ }, { "name": "dompdf/dompdf", - "version": "v2.0.7", + "version": "v2.0.8", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14" + "reference": "c20247574601700e1f7c8dab39310fca1964dc52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/ab0123052b42ad0867348f25df8c228f1ece8f14", - "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/c20247574601700e1f7c8dab39310fca1964dc52", + "reference": "c20247574601700e1f7c8dab39310fca1964dc52", "shasum": "" }, "require": { @@ -1028,9 +1033,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.7" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.8" }, - "time": "2024-04-15T12:40:33+00:00" + "time": "2024-04-29T13:06:17+00:00" }, { "name": "dragonmantank/cron-expression", @@ -1160,6 +1165,69 @@ ], "time": "2023-10-06T06:47:41+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v6.10.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "a49db6f0a5033aef5143295342f1c95521b075ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff", + "reference": "a49db6f0a5033aef5143295342f1c95521b075ff", + "shasum": "" + }, + "require": { + "php": "^7.4||^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^6.5||^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^1.0||^2.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.0" + }, + "time": "2023-12-01T16:26:39+00:00" + }, { "name": "fruitcake/php-cors", "version": "v1.3.0", @@ -1706,16 +1774,16 @@ }, { "name": "intervention/gif", - "version": "4.0.2", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/Intervention/gif.git", - "reference": "c2b07d1f69709e196c8b4ced423449a7e0f3b925" + "reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/gif/zipball/c2b07d1f69709e196c8b4ced423449a7e0f3b925", - "reference": "c2b07d1f69709e196c8b4ced423449a7e0f3b925", + "url": "https://api.github.com/repos/Intervention/gif/zipball/3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3", + "reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3", "shasum": "" }, "require": { @@ -1723,7 +1791,7 @@ }, "require-dev": { "phpstan/phpstan": "^1", - "phpunit/phpunit": "^9", + "phpunit/phpunit": "^10.0", "slevomat/coding-standard": "~8.0", "squizlabs/php_codesniffer": "^3.8" }, @@ -1754,7 +1822,7 @@ ], "support": { "issues": "https://github.com/Intervention/gif/issues", - "source": "https://github.com/Intervention/gif/tree/4.0.2" + "source": "https://github.com/Intervention/gif/tree/4.1.0" }, "funding": [ { @@ -1766,25 +1834,25 @@ "type": "github" } ], - "time": "2024-02-18T15:36:58+00:00" + "time": "2024-03-26T17:23:47+00:00" }, { "name": "intervention/image", - "version": "3.5.0", + "version": "3.6.3", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "408d3655c7705339e8c79731ea7efb51546cfa10" + "reference": "2dbfb53bf8909257e710cf6091d10a9ca7500742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/408d3655c7705339e8c79731ea7efb51546cfa10", - "reference": "408d3655c7705339e8c79731ea7efb51546cfa10", + "url": "https://api.github.com/repos/Intervention/image/zipball/2dbfb53bf8909257e710cf6091d10a9ca7500742", + "reference": "2dbfb53bf8909257e710cf6091d10a9ca7500742", "shasum": "" }, "require": { "ext-mbstring": "*", - "intervention/gif": "^4.0.1", + "intervention/gif": "^4.1", "php": "^8.1" }, "require-dev": { @@ -1826,7 +1894,7 @@ ], "support": { "issues": "https://github.com/Intervention/image/issues", - "source": "https://github.com/Intervention/image/tree/3.5.0" + "source": "https://github.com/Intervention/image/tree/3.6.3" }, "funding": [ { @@ -1838,7 +1906,7 @@ "type": "github" } ], - "time": "2024-03-13T16:26:15+00:00" + "time": "2024-05-02T09:03:18+00:00" }, { "name": "knplabs/knp-snappy", @@ -1909,16 +1977,16 @@ }, { "name": "laravel/framework", - "version": "v10.48.3", + "version": "v10.48.10", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "5791c052b41c6b593556adc687076bfbdd13c501" + "reference": "91e2b9e218afa4e5c377510faa11957042831ba3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/5791c052b41c6b593556adc687076bfbdd13c501", - "reference": "5791c052b41c6b593556adc687076bfbdd13c501", + "url": "https://api.github.com/repos/laravel/framework/zipball/91e2b9e218afa4e5c377510faa11957042831ba3", + "reference": "91e2b9e218afa4e5c377510faa11957042831ba3", "shasum": "" }, "require": { @@ -2023,7 +2091,7 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.18", + "orchestra/testbench-core": "^8.23.4", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", @@ -2112,20 +2180,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-03-15T10:17:07+00:00" + "time": "2024-04-30T12:52:59+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.16", + "version": "v0.1.21", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "ca6872ab6aec3ab61db3a61f83a6caf764ec7781" + "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/ca6872ab6aec3ab61db3a61f83a6caf764ec7781", - "reference": "ca6872ab6aec3ab61db3a61f83a6caf764ec7781", + "url": "https://api.github.com/repos/laravel/prompts/zipball/23ea808e8a145653e0ab29e30d4385e49f40a920", + "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920", "shasum": "" }, "require": { @@ -2165,11 +2233,12 @@ "license": [ "MIT" ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.16" + "source": "https://github.com/laravel/prompts/tree/v0.1.21" }, - "time": "2024-02-21T19:25:27+00:00" + "time": "2024-04-30T12:46:16+00:00" }, { "name": "laravel/serializable-closure", @@ -2233,26 +2302,28 @@ }, { "name": "laravel/socialite", - "version": "v5.12.1", + "version": "v5.13.2", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "7dae1b072573809f32ab6dcf4aebb57c8b3e8acf" + "reference": "278d4615f68205722b3a129135774b3764b28a90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/7dae1b072573809f32ab6dcf4aebb57c8b3e8acf", - "reference": "7dae1b072573809f32ab6dcf4aebb57c8b3e8acf", + "url": "https://api.github.com/repos/laravel/socialite/zipball/278d4615f68205722b3a129135774b3764b28a90", + "reference": "278d4615f68205722b3a129135774b3764b28a90", "shasum": "" }, "require": { "ext-json": "*", + "firebase/php-jwt": "^6.4", "guzzlehttp/guzzle": "^6.0|^7.0", "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "league/oauth1-client": "^1.10.1", - "php": "^7.2|^8.0" + "php": "^7.2|^8.0", + "phpseclib/phpseclib": "^3.0" }, "require-dev": { "mockery/mockery": "^1.0", @@ -2299,7 +2370,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2024-02-16T08:58:20+00:00" + "time": "2024-04-26T13:48:16+00:00" }, { "name": "laravel/tinker", @@ -2557,16 +2628,16 @@ }, { "name": "league/flysystem", - "version": "3.25.1", + "version": "3.27.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "abbd664eb4381102c559d358420989f835208f18" + "reference": "4729745b1ab737908c7d055148c9a6b3e959832f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/abbd664eb4381102c559d358420989f835208f18", - "reference": "abbd664eb4381102c559d358420989f835208f18", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f", + "reference": "4729745b1ab737908c7d055148c9a6b3e959832f", "shasum": "" }, "require": { @@ -2631,7 +2702,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.25.1" + "source": "https://github.com/thephpleague/flysystem/tree/3.27.0" }, "funding": [ { @@ -2643,20 +2714,20 @@ "type": "github" } ], - "time": "2024-03-16T12:53:19+00:00" + "time": "2024-04-07T19:17:50+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.25.1", + "version": "3.27.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "6a5be0e6d6a93574e80805c9cc108a4b63c824d8" + "reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/6a5be0e6d6a93574e80805c9cc108a4b63c824d8", - "reference": "6a5be0e6d6a93574e80805c9cc108a4b63c824d8", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/3e6ce2f972f1470db779f04d29c289dcd2c32837", + "reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837", "shasum": "" }, "require": { @@ -2696,7 +2767,7 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.25.1" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.27.0" }, "funding": [ { @@ -2708,7 +2779,7 @@ "type": "github" } ], - "time": "2024-03-15T19:58:44+00:00" + "time": "2024-04-07T19:16:54+00:00" }, { "name": "league/flysystem-local", @@ -3062,16 +3133,16 @@ }, { "name": "masterminds/html5", - "version": "2.8.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", "shasum": "" }, "require": { @@ -3079,7 +3150,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "type": "library", "extra": { @@ -3123,22 +3194,22 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, - "time": "2023-05-10T11:58:31+00:00" + "time": "2024-03-31T07:05:07+00:00" }, { "name": "monolog/monolog", - "version": "3.5.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", "shasum": "" }, "require": { @@ -3161,7 +3232,7 @@ "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.1", + "phpunit/phpunit": "^10.5.17", "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", "symfony/mailer": "^5.4 || ^6", @@ -3214,7 +3285,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.5.0" + "source": "https://github.com/Seldaek/monolog/tree/3.6.0" }, "funding": [ { @@ -3226,7 +3297,7 @@ "type": "tidelift" } ], - "time": "2023-10-27T15:32:31+00:00" + "time": "2024-04-12T21:02:21+00:00" }, { "name": "mtdowling/jmespath.php", @@ -4717,16 +4788,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.2", + "version": "v0.12.3", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d" + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/9185c66c2165bbf4d71de78a69dccf4974f9538d", - "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", "shasum": "" }, "require": { @@ -4790,9 +4861,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.2" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.3" }, - "time": "2024-03-17T01:53:00+00:00" + "time": "2024-04-02T15:57:53+00:00" }, { "name": "ralouphie/getallheaders", @@ -4929,20 +5000,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.5", + "version": "4.7.6", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e" + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", - "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -5005,7 +5076,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.5" + "source": "https://github.com/ramsey/uuid/tree/4.7.6" }, "funding": [ { @@ -5017,7 +5088,7 @@ "type": "tidelift" } ], - "time": "2023-11-08T05:53:05+00:00" + "time": "2024-04-27T21:32:50+00:00" }, { "name": "robrichards/xmlseclibs", @@ -5219,21 +5290,21 @@ }, { "name": "socialiteproviders/manager", - "version": "v4.5.1", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "a67f194f0f4c4c7616c549afc697b78df9658d44" + "reference": "dea5190981c31b89e52259da9ab1ca4e2b258b21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/a67f194f0f4c4c7616c549afc697b78df9658d44", - "reference": "a67f194f0f4c4c7616c549afc697b78df9658d44", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/dea5190981c31b89e52259da9ab1ca4e2b258b21", + "reference": "dea5190981c31b89e52259da9ab1ca4e2b258b21", "shasum": "" }, "require": { "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", - "laravel/socialite": "^5.2", + "laravel/socialite": "^5.5", "php": "^8.0" }, "require-dev": { @@ -5289,26 +5360,26 @@ "issues": "https://github.com/socialiteproviders/manager/issues", "source": "https://github.com/socialiteproviders/manager" }, - "time": "2024-02-17T08:58:03+00:00" + "time": "2024-05-04T07:57:39+00:00" }, { "name": "socialiteproviders/microsoft-azure", - "version": "5.1.0", + "version": "5.2.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Microsoft-Azure.git", - "reference": "7522b27cd8518706b50e03b40a396fb0a6891feb" + "reference": "453d62c9d7e3b3b76e94c913fb46e68a33347b16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/7522b27cd8518706b50e03b40a396fb0a6891feb", - "reference": "7522b27cd8518706b50e03b40a396fb0a6891feb", + "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/453d62c9d7e3b3b76e94c913fb46e68a33347b16", + "reference": "453d62c9d7e3b3b76e94c913fb46e68a33347b16", "shasum": "" }, "require": { "ext-json": "*", - "php": "^7.2 || ^8.0", - "socialiteproviders/manager": "~4.0" + "php": "^8.0", + "socialiteproviders/manager": "^4.4" }, "type": "library", "autoload": { @@ -5340,7 +5411,7 @@ "issues": "https://github.com/socialiteproviders/providers/issues", "source": "https://github.com/socialiteproviders/providers" }, - "time": "2022-03-15T21:17:43+00:00" + "time": "2024-03-15T03:02:10+00:00" }, { "name": "socialiteproviders/okta", @@ -5394,22 +5465,22 @@ }, { "name": "socialiteproviders/twitch", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Twitch.git", - "reference": "7accf30ae7a3139b757b4ca8f34989c09a3dbee7" + "reference": "c8791b9d208195b5f02bea432de89d0e612b955d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/7accf30ae7a3139b757b4ca8f34989c09a3dbee7", - "reference": "7accf30ae7a3139b757b4ca8f34989c09a3dbee7", + "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/c8791b9d208195b5f02bea432de89d0e612b955d", + "reference": "c8791b9d208195b5f02bea432de89d0e612b955d", "shasum": "" }, "require": { "ext-json": "*", - "php": "^7.2 || ^8.0", - "socialiteproviders/manager": "~4.0" + "php": "^8.0", + "socialiteproviders/manager": "^4.4" }, "type": "library", "autoload": { @@ -5428,23 +5499,32 @@ } ], "description": "Twitch OAuth2 Provider for Laravel Socialite", + "keywords": [ + "laravel", + "oauth", + "provider", + "socialite", + "twitch" + ], "support": { - "source": "https://github.com/SocialiteProviders/Twitch/tree/5.3.1" + "docs": "https://socialiteproviders.com/twitch", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" }, - "time": "2020-12-01T23:10:59+00:00" + "time": "2024-04-01T01:15:35+00:00" }, { "name": "ssddanbrown/htmldiff", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/ssddanbrown/HtmlDiff.git", - "reference": "58f81857c02b50b199273edb4cc339876b5a4038" + "reference": "92da405f8138066834b71ac7bedebbda6327761b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ssddanbrown/HtmlDiff/zipball/58f81857c02b50b199273edb4cc339876b5a4038", - "reference": "58f81857c02b50b199273edb4cc339876b5a4038", + "url": "https://api.github.com/repos/ssddanbrown/HtmlDiff/zipball/92da405f8138066834b71ac7bedebbda6327761b", + "reference": "92da405f8138066834b71ac7bedebbda6327761b", "shasum": "" }, "require": { @@ -5476,7 +5556,7 @@ "homepage": "https://github.com/ssddanbrown/htmldiff", "support": { "issues": "https://github.com/ssddanbrown/HtmlDiff/issues", - "source": "https://github.com/ssddanbrown/HtmlDiff/tree/v1.0.2" + "source": "https://github.com/ssddanbrown/HtmlDiff/tree/v1.0.3" }, "funding": [ { @@ -5484,7 +5564,7 @@ "type": "github" } ], - "time": "2022-01-24T20:12:20+00:00" + "time": "2024-03-29T16:51:55+00:00" }, { "name": "ssddanbrown/symfony-mailer", @@ -5525,6 +5605,7 @@ "symfony/messenger": "^6.2|^7.0", "symfony/twig-bridge": "^6.2|^7.0" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -5561,16 +5642,16 @@ }, { "name": "symfony/console", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", - "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", + "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", "shasum": "" }, "require": { @@ -5635,7 +5716,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.4" + "source": "https://github.com/symfony/console/tree/v6.4.7" }, "funding": [ { @@ -5651,20 +5732,20 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:10+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.3", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229" + "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/1c5d5c2103c3762aff27a27e1e2409e30a79083b", + "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b", "shasum": "" }, "require": { @@ -5700,7 +5781,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.3" + "source": "https://github.com/symfony/css-selector/tree/v6.4.7" }, "funding": [ { @@ -5716,20 +5797,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -5738,7 +5819,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5767,7 +5848,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -5783,20 +5864,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c725219bdf2afc59423c32793d5019d2a904e13a" + "reference": "667a072466c6a53827ed7b119af93806b884cbb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c725219bdf2afc59423c32793d5019d2a904e13a", - "reference": "c725219bdf2afc59423c32793d5019d2a904e13a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/667a072466c6a53827ed7b119af93806b884cbb3", + "reference": "667a072466c6a53827ed7b119af93806b884cbb3", "shasum": "" }, "require": { @@ -5842,7 +5923,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.4" + "source": "https://github.com/symfony/error-handler/tree/v6.4.7" }, "funding": [ { @@ -5858,20 +5939,20 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:10+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.3", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef" + "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae9d3a6f3003a6caf56acd7466d8d52378d44fef", - "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d84384f3f67de3cb650db64d685d70395dacfc3f", + "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f", "shasum": "" }, "require": { @@ -5922,7 +6003,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.7" }, "funding": [ { @@ -5938,20 +6019,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", "shasum": "" }, "require": { @@ -5961,7 +6042,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5998,7 +6079,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" }, "funding": [ { @@ -6014,20 +6095,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/finder", - "version": "v6.4.0", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" + "reference": "511c48990be17358c23bf45c5d71ab85d40fb764" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/511c48990be17358c23bf45c5d71ab85d40fb764", + "reference": "511c48990be17358c23bf45c5d71ab85d40fb764", "shasum": "" }, "require": { @@ -6062,7 +6143,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.0" + "source": "https://github.com/symfony/finder/tree/v6.4.7" }, "funding": [ { @@ -6078,20 +6159,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:30:12+00:00" + "time": "2024-04-23T10:36:43+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304" + "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ebc713bc6e6f4b53f46539fc158be85dfcd77304", - "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b4db6b833035477cb70e18d0ae33cb7c2b521759", + "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759", "shasum": "" }, "require": { @@ -6139,7 +6220,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.4" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.7" }, "funding": [ { @@ -6155,20 +6236,20 @@ "type": "tidelift" } ], - "time": "2024-02-08T15:01:18+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.5", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f6947cb939d8efee137797382cb4db1af653ef75" + "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6947cb939d8efee137797382cb4db1af653ef75", - "reference": "f6947cb939d8efee137797382cb4db1af653ef75", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b7b5e6cdef670a0c82d015a966ffc7e855861a98", + "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98", "shasum": "" }, "require": { @@ -6223,6 +6304,7 @@ "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^5.4|^6.0|^7.0", "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.4|^7.0", "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, @@ -6252,7 +6334,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.5" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.7" }, "funding": [ { @@ -6268,20 +6350,20 @@ "type": "tidelift" } ], - "time": "2024-03-04T21:00:47+00:00" + "time": "2024-04-29T11:24:44+00:00" }, { "name": "symfony/mime", - "version": "v6.4.3", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "5017e0a9398c77090b7694be46f20eb796262a34" + "reference": "decadcf3865918ecfcbfa90968553994ce935a5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/5017e0a9398c77090b7694be46f20eb796262a34", - "reference": "5017e0a9398c77090b7694be46f20eb796262a34", + "url": "https://api.github.com/repos/symfony/mime/zipball/decadcf3865918ecfcbfa90968553994ce935a5e", + "reference": "decadcf3865918ecfcbfa90968553994ce935a5e", "shasum": "" }, "require": { @@ -6302,6 +6384,7 @@ "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.3.2|^7.0" @@ -6336,7 +6419,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.3" + "source": "https://github.com/symfony/mime/tree/v6.4.7" }, "funding": [ { @@ -6352,7 +6435,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:32:12+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7067,16 +7150,16 @@ }, { "name": "symfony/process", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "710e27879e9be3395de2b98da3f52a946039f297" + "reference": "cdb1c81c145fd5aa9b0038bab694035020943381" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297", - "reference": "710e27879e9be3395de2b98da3f52a946039f297", + "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381", + "reference": "cdb1c81c145fd5aa9b0038bab694035020943381", "shasum": "" }, "require": { @@ -7108,7 +7191,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.4" + "source": "https://github.com/symfony/process/tree/v6.4.7" }, "funding": [ { @@ -7124,20 +7207,20 @@ "type": "tidelift" } ], - "time": "2024-02-20T12:31:00+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/routing", - "version": "v6.4.5", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4" + "reference": "276e06398f71fa2a973264d94f28150f93cfb907" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/7fe30068e207d9c31c0138501ab40358eb2d49a4", - "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4", + "url": "https://api.github.com/repos/symfony/routing/zipball/276e06398f71fa2a973264d94f28150f93cfb907", + "reference": "276e06398f71fa2a973264d94f28150f93cfb907", "shasum": "" }, "require": { @@ -7191,7 +7274,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.5" + "source": "https://github.com/symfony/routing/tree/v6.4.7" }, "funding": [ { @@ -7207,25 +7290,26 @@ "type": "tidelift" } ], - "time": "2024-02-27T12:33:30+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -7233,7 +7317,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -7273,7 +7357,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -7289,20 +7373,20 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/string", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69", + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69", "shasum": "" }, "require": { @@ -7359,7 +7443,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.4" + "source": "https://github.com/symfony/string/tree/v6.4.7" }, "funding": [ { @@ -7375,20 +7459,20 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:16:41+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/translation", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e" + "reference": "7495687c58bfd88b7883823747b0656d90679123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e", - "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e", + "url": "https://api.github.com/repos/symfony/translation/zipball/7495687c58bfd88b7883823747b0656d90679123", + "reference": "7495687c58bfd88b7883823747b0656d90679123", "shasum": "" }, "require": { @@ -7454,7 +7538,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.4" + "source": "https://github.com/symfony/translation/tree/v6.4.7" }, "funding": [ { @@ -7470,20 +7554,20 @@ "type": "tidelift" } ], - "time": "2024-02-20T13:16:58+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.1", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "06450585bf65e978026bda220cdebca3f867fde7" + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", - "reference": "06450585bf65e978026bda220cdebca3f867fde7", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", "shasum": "" }, "require": { @@ -7492,7 +7576,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -7532,7 +7616,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" }, "funding": [ { @@ -7548,20 +7632,20 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/uid", - "version": "v6.4.3", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0" + "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", - "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", + "url": "https://api.github.com/repos/symfony/uid/zipball/a66efcb71d8bc3a207d9d78e0bd67f3321510355", + "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355", "shasum": "" }, "require": { @@ -7606,7 +7690,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.3" + "source": "https://github.com/symfony/uid/tree/v6.4.7" }, "funding": [ { @@ -7622,20 +7706,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "b439823f04c98b84d4366c79507e9da6230944b1" + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b439823f04c98b84d4366c79507e9da6230944b1", - "reference": "b439823f04c98b84d4366c79507e9da6230944b1", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7", + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7", "shasum": "" }, "require": { @@ -7691,7 +7775,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.4" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.7" }, "funding": [ { @@ -7707,7 +7791,7 @@ "type": "tidelift" } ], - "time": "2024-02-15T11:23:52+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -8167,16 +8251,16 @@ }, { "name": "itsgoingd/clockwork", - "version": "v5.2.0", + "version": "v5.2.2", "source": { "type": "git", "url": "https://github.com/itsgoingd/clockwork.git", - "reference": "df52c7c4d8d60443ea1d14bcf9b182d4eaaeec26" + "reference": "29bc4cedfbe742b419544c30b7b6e15cd9da08ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/df52c7c4d8d60443ea1d14bcf9b182d4eaaeec26", - "reference": "df52c7c4d8d60443ea1d14bcf9b182d4eaaeec26", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/29bc4cedfbe742b419544c30b7b6e15cd9da08ef", + "reference": "29bc4cedfbe742b419544c30b7b6e15cd9da08ef", "shasum": "" }, "require": { @@ -8230,7 +8314,7 @@ ], "support": { "issues": "https://github.com/itsgoingd/clockwork/issues", - "source": "https://github.com/itsgoingd/clockwork/tree/v5.2.0" + "source": "https://github.com/itsgoingd/clockwork/tree/v5.2.2" }, "funding": [ { @@ -8238,20 +8322,20 @@ "type": "github" } ], - "time": "2024-02-20T22:36:44+00:00" + "time": "2024-04-14T10:49:22+00:00" }, { "name": "larastan/larastan", - "version": "v2.9.2", + "version": "v2.9.5", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "a79b46b96060504b400890674b83f66aa7f5db6d" + "reference": "101f1a4470f87326f4d3995411d28679d8800abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/a79b46b96060504b400890674b83f66aa7f5db6d", - "reference": "a79b46b96060504b400890674b83f66aa7f5db6d", + "url": "https://api.github.com/repos/larastan/larastan/zipball/101f1a4470f87326f4d3995411d28679d8800abe", + "reference": "101f1a4470f87326f4d3995411d28679d8800abe", "shasum": "" }, "require": { @@ -8264,15 +8348,15 @@ "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", "php": "^8.0.2", - "phpmyadmin/sql-parser": "^5.8.2", - "phpstan/phpstan": "^1.10.50" + "phpmyadmin/sql-parser": "^5.9.0", + "phpstan/phpstan": "^1.10.66" }, "require-dev": { "doctrine/coding-standard": "^12.0", - "nikic/php-parser": "^4.17.1", - "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.0", - "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.0", - "phpunit/phpunit": "^9.6.13 || ^10.5" + "nikic/php-parser": "^4.19.1", + "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.2", + "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.3", + "phpunit/phpunit": "^9.6.13 || ^10.5.16" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" @@ -8320,7 +8404,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.9.2" + "source": "https://github.com/larastan/larastan/tree/v2.9.5" }, "funding": [ { @@ -8340,20 +8424,20 @@ "type": "patreon" } ], - "time": "2024-02-27T03:16:03+00:00" + "time": "2024-04-16T19:13:34+00:00" }, { "name": "mockery/mockery", - "version": "1.6.9", + "version": "1.6.11", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06" + "reference": "81a161d0b135df89951abd52296adf97deb0723d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", + "url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d", + "reference": "81a161d0b135df89951abd52296adf97deb0723d", "shasum": "" }, "require": { @@ -8365,8 +8449,8 @@ "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.10", - "symplify/easy-coding-standard": "^12.0.8" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", "autoload": { @@ -8423,7 +8507,7 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2023-12-10T02:24:34+00:00" + "time": "2024-03-21T18:34:15+00:00" }, { "name": "myclabs/deep-copy", @@ -8788,16 +8872,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.62", + "version": "1.10.67", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9" + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9", - "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", "shasum": "" }, "require": { @@ -8840,13 +8924,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-13T12:27:20+00:00" + "time": "2024-04-16T07:22:02+00:00" }, { "name": "phpunit/php-code-coverage", @@ -9171,16 +9251,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.13", + "version": "10.5.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7" + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7", - "reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/547d314dc24ec1e177720d45c6263fb226cc2ae3", + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3", "shasum": "" }, "require": { @@ -9252,7 +9332,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.20" }, "funding": [ { @@ -9268,7 +9348,7 @@ "type": "tidelift" } ], - "time": "2024-03-12T15:37:41+00:00" + "time": "2024-04-24T06:32:35+00:00" }, { "name": "sebastian/cli-parser", @@ -9642,16 +9722,16 @@ }, { "name": "sebastian/environment", - "version": "6.0.1", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { @@ -9666,7 +9746,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -9694,7 +9774,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -9702,7 +9782,7 @@ "type": "github" } ], - "time": "2023-04-11T05:39:26+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", @@ -10188,16 +10268,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.0", + "version": "3.9.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", - "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", "shasum": "" }, "require": { @@ -10264,7 +10344,7 @@ "type": "open_collective" } ], - "time": "2024-02-16T15:06:51+00:00" + "time": "2024-04-23T20:25:34+00:00" }, { "name": "ssddanbrown/asserthtml", @@ -10324,16 +10404,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v6.4.4", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531" + "reference": "2088c5da700b1e7a8689fffc10dda6c1f643deea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2088c5da700b1e7a8689fffc10dda6c1f643deea", + "reference": "2088c5da700b1e7a8689fffc10dda6c1f643deea", "shasum": "" }, "require": { @@ -10371,7 +10451,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.4" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.7" }, "funding": [ { @@ -10387,7 +10467,7 @@ "type": "tidelift" } ], - "time": "2024-02-07T09:17:57+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "theseer/tokenizer", From 424e8f503eb6a59c0e3f0b7d8b8a5764bb06327c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 May 2024 11:02:20 +0100 Subject: [PATCH 57/59] Readme: Updated sponsor list --- readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/readme.md b/readme.md index c46e1641f..11bf2c888 100644 --- a/readme.md +++ b/readme.md @@ -45,6 +45,14 @@ Big thanks to these companies for supporting the project. [Project donation details](https://www.bookstackapp.com/donate/) - [GitHub Sponsors Page](https://github.com/sponsors/ssddanbrown) - [Ko-fi Page](https://ko-fi.com/ssddanbrown) +#### Gold Sponsor + +
+ +
+ Federated.computer +
+ #### Bronze Sponsors From 2b9b0f91cbd053ecc248652db2d86ef42fd86817 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 May 2024 15:15:10 +0100 Subject: [PATCH 58/59] Updated translations with latest Crowdin changes (#4890) --- lang/ar/preferences.php | 2 +- lang/ar/settings.php | 8 ++ lang/bg/preferences.php | 2 +- lang/bg/settings.php | 8 ++ lang/bs/preferences.php | 2 +- lang/bs/settings.php | 8 ++ lang/ca/preferences.php | 2 +- lang/ca/settings.php | 8 ++ lang/cs/preferences.php | 2 +- lang/cs/settings.php | 8 ++ lang/cy/preferences.php | 2 +- lang/cy/settings.php | 8 ++ lang/da/activities.php | 26 ++-- lang/da/auth.php | 10 +- lang/da/common.php | 14 +- lang/da/components.php | 26 ++-- lang/da/editor.php | 8 +- lang/da/entities.php | 28 ++-- lang/da/notifications.php | 2 +- lang/da/preferences.php | 74 +++++----- lang/da/settings.php | 20 ++- lang/de/preferences.php | 2 +- lang/de/settings.php | 8 ++ lang/de_informal/entities.php | 2 +- lang/de_informal/preferences.php | 2 +- lang/de_informal/settings.php | 8 ++ lang/el/preferences.php | 2 +- lang/el/settings.php | 8 ++ lang/es/activities.php | 4 +- lang/es/preferences.php | 2 +- lang/es/settings.php | 8 ++ lang/es_AR/activities.php | 2 +- lang/es_AR/notifications.php | 10 +- lang/es_AR/preferences.php | 2 +- lang/es_AR/settings.php | 14 +- lang/et/preferences.php | 2 +- lang/et/settings.php | 8 ++ lang/eu/preferences.php | 2 +- lang/eu/settings.php | 8 ++ lang/fa/settings.php | 8 ++ lang/fi/settings.php | 8 ++ lang/fr/passwords.php | 4 +- lang/fr/preferences.php | 4 +- lang/fr/settings.php | 8 ++ lang/he/preferences.php | 2 +- lang/he/settings.php | 8 ++ lang/hr/preferences.php | 2 +- lang/hr/settings.php | 8 ++ lang/hu/preferences.php | 2 +- lang/hu/settings.php | 8 ++ lang/id/preferences.php | 2 +- lang/id/settings.php | 8 ++ lang/it/activities.php | 26 ++-- lang/it/auth.php | 6 +- lang/it/common.php | 12 +- lang/it/entities.php | 94 ++++++------ lang/it/errors.php | 30 ++-- lang/it/notifications.php | 14 +- lang/it/passwords.php | 4 +- lang/it/preferences.php | 28 ++-- lang/it/settings.php | 236 ++++++++++++++++--------------- lang/it/validation.php | 28 ++-- lang/ja/preferences.php | 2 +- lang/ja/settings.php | 8 ++ lang/ka/preferences.php | 2 +- lang/ka/settings.php | 8 ++ lang/ko/preferences.php | 2 +- lang/ko/settings.php | 8 ++ lang/lt/common.php | 2 +- lang/lt/preferences.php | 22 +-- lang/lt/settings.php | 8 ++ lang/lv/activities.php | 6 +- lang/lv/preferences.php | 2 +- lang/lv/settings.php | 8 ++ lang/nb/preferences.php | 2 +- lang/nb/settings.php | 8 ++ lang/nl/auth.php | 32 ++--- lang/nl/components.php | 2 +- lang/nl/editor.php | 2 +- lang/nl/entities.php | 22 +-- lang/nl/errors.php | 14 +- lang/nl/notifications.php | 2 +- lang/nl/passwords.php | 2 +- lang/nl/preferences.php | 8 +- lang/nl/settings.php | 26 ++-- lang/nn/preferences.php | 2 +- lang/nn/settings.php | 8 ++ lang/pl/activities.php | 6 +- lang/pl/common.php | 2 +- lang/pl/editor.php | 6 +- lang/pl/entities.php | 12 +- lang/pl/errors.php | 2 +- lang/pl/preferences.php | 2 +- lang/pl/settings.php | 10 +- lang/pt/preferences.php | 2 +- lang/pt/settings.php | 8 ++ lang/pt_BR/preferences.php | 2 +- lang/pt_BR/settings.php | 8 ++ lang/ro/preferences.php | 2 +- lang/ro/settings.php | 8 ++ lang/ru/activities.php | 8 +- lang/ru/common.php | 2 +- lang/ru/editor.php | 6 +- lang/ru/entities.php | 34 ++--- lang/ru/errors.php | 10 +- lang/ru/notifications.php | 6 +- lang/ru/preferences.php | 10 +- lang/ru/settings.php | 12 +- lang/sk/activities.php | 18 +-- lang/sk/preferences.php | 2 +- lang/sk/settings.php | 8 ++ lang/sl/activities.php | 6 +- lang/sl/editor.php | 214 ++++++++++++++-------------- lang/sl/preferences.php | 2 +- lang/sl/settings.php | 8 ++ lang/sl/validation.php | 8 +- lang/sq/preferences.php | 2 +- lang/sq/settings.php | 8 ++ lang/sr/editor.php | 112 +++++++-------- lang/sr/preferences.php | 2 +- lang/sr/settings.php | 8 ++ lang/sv/preferences.php | 2 +- lang/sv/settings.php | 8 ++ lang/tr/preferences.php | 2 +- lang/tr/settings.php | 8 ++ lang/uk/activities.php | 6 +- lang/uk/common.php | 2 +- lang/uk/editor.php | 6 +- lang/uk/entities.php | 8 +- lang/uk/errors.php | 2 +- lang/uk/preferences.php | 2 +- lang/uk/settings.php | 10 +- lang/uz/preferences.php | 2 +- lang/uz/settings.php | 8 ++ lang/vi/preferences.php | 2 +- lang/vi/settings.php | 8 ++ lang/zh_CN/preferences.php | 2 +- lang/zh_CN/settings.php | 8 ++ lang/zh_TW/activities.php | 62 ++++---- lang/zh_TW/common.php | 2 +- lang/zh_TW/entities.php | 6 +- lang/zh_TW/errors.php | 2 +- lang/zh_TW/preferences.php | 56 ++++---- lang/zh_TW/settings.php | 10 +- 144 files changed, 1134 insertions(+), 766 deletions(-) diff --git a/lang/ar/preferences.php b/lang/ar/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/ar/preferences.php +++ b/lang/ar/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/ar/settings.php b/lang/ar/settings.php index 287e6a166..f2405e9d5 100644 --- a/lang/ar/settings.php +++ b/lang/ar/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/bg/preferences.php b/lang/bg/preferences.php index 963f1f04c..f954340e2 100644 --- a/lang/bg/preferences.php +++ b/lang/bg/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/bg/settings.php b/lang/bg/settings.php index bf0c8b3bc..97de55b36 100644 --- a/lang/bg/settings.php +++ b/lang/bg/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Последна грешка на:', 'webhooks_last_error_message' => 'Последно съобщение за грешка:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/bs/preferences.php b/lang/bs/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/bs/preferences.php +++ b/lang/bs/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/bs/settings.php b/lang/bs/settings.php index 7b7f5d2a2..f4c84092c 100644 --- a/lang/bs/settings.php +++ b/lang/bs/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/ca/preferences.php b/lang/ca/preferences.php index b56b8b3bb..9d9ed8aa1 100644 --- a/lang/ca/preferences.php +++ b/lang/ca/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Desa les preferències', 'notifications_update_success' => 'S’han actualitzat les preferències de notificacions!', 'notifications_watched' => 'Elements seguits i ignorats', - 'notifications_watched_desc' => ' A continuació hi ha els elements que tenen aplicades preferències de seguiment personalitzades. Per a actualitzar-ne les preferències, consulteu l’element i seleccioneu les opcions de seguiment a la barra lateral.', + 'notifications_watched_desc' => 'A continuació hi ha els elements que tenen aplicades preferències de seguiment personalitzades. Per a actualitzar-ne les preferències, consulteu l’element i seleccioneu les opcions de seguiment a la barra lateral.', 'auth' => 'Accés i seguretat', 'auth_change_password' => 'Canvia la contrasenya', diff --git a/lang/ca/settings.php b/lang/ca/settings.php index d39174c9b..5fe9d3bff 100644 --- a/lang/ca/settings.php +++ b/lang/ca/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Error per darrera vegada:', 'webhooks_last_error_message' => 'Darrer missatge d’error:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/cs/preferences.php b/lang/cs/preferences.php index 295fb5ca1..9a127601e 100644 --- a/lang/cs/preferences.php +++ b/lang/cs/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Uložit preference', 'notifications_update_success' => 'Nastavení oznámení byla aktualizována!', 'notifications_watched' => 'Sledované a ignorované položky', - 'notifications_watched_desc' => ' Níže jsou položky, které mají vlastní nastavení hodinek. Chcete-li aktualizovat vaše předvolby, podívejte se na položku a pak najděte možnosti hodinek v postranním panelu.', + 'notifications_watched_desc' => 'Níže jsou položky, které mají vlastní nastavení hodinek. Chcete-li aktualizovat vaše předvolby, podívejte se na položku a pak najděte možnosti hodinek v postranním panelu.', 'auth' => 'Přístup a zabezpečení', 'auth_change_password' => 'Změnit heslo', diff --git a/lang/cs/settings.php b/lang/cs/settings.php index 75331834e..23820fe87 100644 --- a/lang/cs/settings.php +++ b/lang/cs/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Poslední chyba:', 'webhooks_last_error_message' => 'Poslední chybová zpráva', + // Licensing + 'licenses' => 'Licence', + 'licenses_desc' => 'Na této stránce naleznete kromě informací o projektech a knihovnách, které se v rámci BookStacku používají, také informace o licencích pro BookStack. Mnoho uvedených projektů lze používat pouze ve vývojovém kontextu.', + 'licenses_bookstack' => 'BookStack licence', + 'licenses_php' => 'Licence PHP knihoven', + 'licenses_js' => 'Licence JavaScript knihoven', + 'licenses_other' => 'Ostatní licence', + 'license_details' => 'Podrobnosti o licenci', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/cy/preferences.php b/lang/cy/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/cy/preferences.php +++ b/lang/cy/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/cy/settings.php b/lang/cy/settings.php index 7b7f5d2a2..f4c84092c 100644 --- a/lang/cy/settings.php +++ b/lang/cy/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/da/activities.php b/lang/da/activities.php index 7478e18bf..f374d799a 100644 --- a/lang/da/activities.php +++ b/lang/da/activities.php @@ -15,7 +15,7 @@ return [ 'page_restore' => 'gendannede side', 'page_restore_notification' => 'Siden blev gendannet', 'page_move' => 'flyttede side', - 'page_move_notification' => 'Page successfully moved', + 'page_move_notification' => 'Siden blev flyttet', // Chapters 'chapter_create' => 'oprettede kapitel', @@ -25,7 +25,7 @@ return [ 'chapter_delete' => 'slettede kapitel', 'chapter_delete_notification' => 'Kapitel blev slettet', 'chapter_move' => 'flyttede kapitel', - 'chapter_move_notification' => 'Chapter successfully moved', + 'chapter_move_notification' => 'Kapitlet blev flyttet', // Books 'book_create' => 'oprettede bog', @@ -40,19 +40,19 @@ return [ 'book_sort_notification' => 'Bogen blev re-sorteret', // Bookshelves - 'bookshelf_create' => 'created shelf', - 'bookshelf_create_notification' => 'Shelf successfully created', - 'bookshelf_create_from_book' => 'converted book to shelf', + 'bookshelf_create' => 'oprettede reol', + 'bookshelf_create_notification' => 'Reolen blev oprettet', + 'bookshelf_create_from_book' => 'omdannede bog til reol', 'bookshelf_create_from_book_notification' => 'Bogen blev omdannet til en bogreal', - 'bookshelf_update' => 'updated shelf', - 'bookshelf_update_notification' => 'Shelf successfully updated', - 'bookshelf_delete' => 'deleted shelf', - 'bookshelf_delete_notification' => 'Shelf successfully deleted', + 'bookshelf_update' => 'opdaterede reolen', + 'bookshelf_update_notification' => 'Reolen blev opdateret', + 'bookshelf_delete' => 'slettede reol', + 'bookshelf_delete_notification' => 'Reolen blev slettet', // Revisions - 'revision_restore' => 'restored revision', - 'revision_delete' => 'deleted revision', - 'revision_delete_notification' => 'Revision successfully deleted', + 'revision_restore' => 'gendannede version', + 'revision_delete' => 'slettede version', + 'revision_delete_notification' => 'Versionen blev slettet', // Favourites 'favourite_add_notification' => '":name" er blevet tilføjet til dine favoritter', @@ -62,7 +62,7 @@ return [ 'watch_update_level_notification' => 'Watch preferences successfully updated', // Auth - 'auth_login' => 'logged in', + 'auth_login' => 'loggede ind', 'auth_register' => 'registered as new user', 'auth_password_reset_request' => 'requested user password reset', 'auth_password_reset_update' => 'reset user password', diff --git a/lang/da/auth.php b/lang/da/auth.php index 2d2b7bebb..090e0751e 100644 --- a/lang/da/auth.php +++ b/lang/da/auth.php @@ -39,9 +39,9 @@ return [ 'register_success' => 'Tak for din registrering. Du er nu registeret og logget ind.', // Login auto-initiation - 'auto_init_starting' => 'Attempting Login', - 'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.', - 'auto_init_start_link' => 'Proceed with authentication', + 'auto_init_starting' => 'Forsøger Login', + 'auto_init_starting_desc' => 'Vi kontakter dit godkendelsessystem for at starte loginprocessen. Hvis der ikke er nogen fremskridt efter 5 sekunder, kan du prøve at klikke på linket nedenfor.', + 'auto_init_start_link' => 'Fortsæt med godkendelse', // Password Reset 'reset_password' => 'Nulstil adgangskode', @@ -61,7 +61,7 @@ return [ 'email_confirm_send_error' => 'E-Mail-bekræftelse kræves, men systemet kunne ikke sende E-Mailen. Kontakt administratoren for at sikre, at E-Mail er konfigureret korrekt.', 'email_confirm_success' => 'Din email er blevet bekræftet! Du bør nu kune logge ind med denne emailadresse.', 'email_confirm_resent' => 'Bekræftelsesmail sendt, tjek venligst din indboks.', - 'email_confirm_thanks' => 'Thanks for confirming!', + 'email_confirm_thanks' => 'Tak for bekræftelsen!', 'email_confirm_thanks_desc' => 'Please wait a moment while your confirmation is handled. If you are not redirected after 3 seconds press the "Continue" link below to proceed.', 'email_not_confirmed' => 'E-Mail adresse ikke bekræftet', @@ -103,7 +103,7 @@ return [ 'mfa_gen_totp_verify_setup' => 'Verificer Opsætning', 'mfa_gen_totp_verify_setup_desc' => 'Verify that all is working by entering a code, generated within your authentication app, in the input box below:', 'mfa_gen_totp_provide_code_here' => 'Provide your app generated code here', - 'mfa_verify_access' => 'Verify Access', + 'mfa_verify_access' => 'Bekræft Adgang', 'mfa_verify_access_desc' => 'Your user account requires you to confirm your identity via an additional level of verification before you\'re granted access. Verify using one of your configured methods to continue.', 'mfa_verify_no_methods' => 'Ingen Metoder Konfigureret', 'mfa_verify_no_methods_desc' => 'No multi-factor authentication methods could be found for your account. You\'ll need to set up at least one method before you gain access.', diff --git a/lang/da/common.php b/lang/da/common.php index 5b4c0e822..8c6fa105c 100644 --- a/lang/da/common.php +++ b/lang/da/common.php @@ -6,7 +6,7 @@ return [ // Buttons 'cancel' => 'Annuller', - 'close' => 'Close', + 'close' => 'Luk', 'confirm' => 'Bekræft', 'back' => 'Tilbage', 'save' => 'Gem', @@ -20,13 +20,13 @@ return [ 'description' => 'Beskrivelse', 'role' => 'Rolle', 'cover_image' => 'Coverbillede', - 'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.', + 'cover_image_description' => 'Dette billede skal være omkring 440x250px selvom det vil være fleksibelt skaleret & beskåret for at passe til brugergrænsefladen i forskellige scenarier efter behov. Så de faktiske dimensioner for visning vil være forskellige.', // Actions 'actions' => 'Handlinger', 'view' => 'Vis', 'view_all' => 'Vis alle', - 'new' => 'New', + 'new' => 'Ny', 'create' => 'Opret', 'update' => 'Opdater', 'edit' => 'Rediger', @@ -42,7 +42,7 @@ return [ 'remove' => 'Fjern', 'add' => 'Tilføj', 'configure' => 'Konfigurer', - 'manage' => 'Manage', + 'manage' => 'Administrer', 'fullscreen' => 'Fuld skærm', 'favourite' => 'Foretrukken', 'unfavourite' => 'Fjern som foretrukken', @@ -52,7 +52,7 @@ return [ 'filter_clear' => 'Nulstil Filter', 'download' => 'Hent', 'open_in_tab' => 'Åben i ny fane', - 'open' => 'Open', + 'open' => 'Åbn', // Sort Options 'sort_options' => 'Sorteringsindstillinger', @@ -84,14 +84,14 @@ return [ 'none' => 'Ingen', // Header - 'homepage' => 'Homepage', + 'homepage' => 'Forside', 'header_menu_expand' => 'Udvid header menu', 'profile_menu' => 'Profilmenu', 'view_profile' => 'Vis profil', 'edit_profile' => 'Redigér Profil', 'dark_mode' => 'Mørk tilstand', 'light_mode' => 'Lys tilstand', - 'global_search' => 'Global Search', + 'global_search' => 'Global søgning', // Layout tabs 'tab_info' => 'Info', diff --git a/lang/da/components.php b/lang/da/components.php index bcbf11672..410ed4fc5 100644 --- a/lang/da/components.php +++ b/lang/da/components.php @@ -6,36 +6,36 @@ return [ // Image Manager 'image_select' => 'Billedselektion', - 'image_list' => 'Image List', - 'image_details' => 'Image Details', - 'image_upload' => 'Upload Image', - 'image_intro' => 'Here you can select and manage images that have been previously uploaded to the system.', - 'image_intro_upload' => 'Upload a new image by dragging an image file into this window, or by using the "Upload Image" button above.', + 'image_list' => 'Billede Liste', + 'image_details' => 'Billede Detaljer', + 'image_upload' => 'Upload billede', + 'image_intro' => 'Her kan du vælge og administrere billeder, der tidligere er blevet uploadet til systemet.', + 'image_intro_upload' => 'Upload et nyt billede ved at trække en billedfil ind i dette vindue, eller ved at bruge knappen "Upload billede" ovenfor.', 'image_all' => 'Alt', 'image_all_title' => 'Se alle billeder', 'image_book_title' => 'Vis billeder uploadet til denne bog', 'image_page_title' => 'Vis billeder uploadet til denne side', 'image_search_hint' => 'Søg efter billednavn', 'image_uploaded' => 'Uploadet :uploadedDate', - 'image_uploaded_by' => 'Uploaded by :userName', - 'image_uploaded_to' => 'Uploaded to :pageLink', - 'image_updated' => 'Updated :updateDate', + 'image_uploaded_by' => 'Uploadet af :userName', + 'image_uploaded_to' => 'Uploadet til :pageLink', + 'image_updated' => 'Opdateret :updateDate', 'image_load_more' => 'Indlæse mere', 'image_image_name' => 'Billednavn', 'image_delete_used' => 'Dette billede er brugt på siderne nedenfor.', 'image_delete_confirm_text' => 'Er du sikker på at du vil slette dette billede?', 'image_select_image' => 'Vælg billede', 'image_dropzone' => 'Træk-og-slip billede eller klik her for at uploade', - 'image_dropzone_drop' => 'Drop images here to upload', + 'image_dropzone_drop' => 'Slip billeder her for at uploade', 'images_deleted' => 'Billede slettet', 'image_preview' => 'Billedeksempel', 'image_upload_success' => 'Foto uploadet', 'image_update_success' => 'Billeddetaljer succesfuldt opdateret', 'image_delete_success' => 'Billede slettet', - 'image_replace' => 'Replace Image', - 'image_replace_success' => 'Image file successfully updated', - 'image_rebuild_thumbs' => 'Regenerate Size Variations', - 'image_rebuild_thumbs_success' => 'Image size variations successfully rebuilt!', + 'image_replace' => 'Erstat billede', + 'image_replace_success' => 'Billedfil blev opdateret', + 'image_rebuild_thumbs' => 'Regenerer størrelsesvariationer', + 'image_rebuild_thumbs_success' => 'Variationer i billedstørrelse blev genopbygget!', // Code Editor 'code_editor' => 'Rediger kode', diff --git a/lang/da/editor.php b/lang/da/editor.php index bf45899a8..973c8a902 100644 --- a/lang/da/editor.php +++ b/lang/da/editor.php @@ -14,7 +14,7 @@ return [ 'save' => 'Gem', 'close' => 'Luk', 'undo' => 'Fortryd', - 'redo' => 'Redo', + 'redo' => 'Gendan', 'left' => 'Venstre', 'center' => 'Midten', 'right' => 'Højre', @@ -31,7 +31,7 @@ return [ 'header_large' => 'Stor Overskrift', 'header_medium' => 'Mellemstor Overskrift', 'header_small' => 'Lille Overskrift', - 'header_tiny' => 'Tiny Header', + 'header_tiny' => 'Lille Header', 'paragraph' => 'Paragraf', 'blockquote' => 'Citat', 'inline_code' => 'Inline kode', @@ -125,8 +125,8 @@ return [ 'paste_column_after' => 'Indsæt kolonne efter', 'cell_padding' => 'Cell padding', 'cell_spacing' => 'Cell spacing', - 'caption' => 'Caption', - 'show_caption' => 'Show caption', + 'caption' => 'Citat', + 'show_caption' => 'Vis citat', 'constrain' => 'Constrain proportions', 'cell_border_solid' => 'Solid', 'cell_border_dotted' => 'Prikket', diff --git a/lang/da/entities.php b/lang/da/entities.php index c952f147b..1e8b38fa9 100644 --- a/lang/da/entities.php +++ b/lang/da/entities.php @@ -34,7 +34,7 @@ return [ 'no_pages_viewed' => 'Du har ikke besøgt nogle sider', 'no_pages_recently_created' => 'Ingen sider er blevet oprettet for nyligt', 'no_pages_recently_updated' => 'Ingen sider er blevet opdateret for nyligt', - 'export' => 'Exporter', + 'export' => 'Eksporter', 'export_html' => 'Indeholdt webfil', 'export_pdf' => 'PDF-fil', 'export_text' => 'Almindelig tekstfil', @@ -155,14 +155,14 @@ return [ 'books_sort_show_other' => 'Vis andre bøger', 'books_sort_save' => 'Gem ny ordre', 'books_sort_show_other_desc' => 'Add other books here to include them in the sort operation, and allow easy cross-book reorganisation.', - 'books_sort_move_up' => 'Move Up', - 'books_sort_move_down' => 'Move Down', - 'books_sort_move_prev_book' => 'Move to Previous Book', - 'books_sort_move_next_book' => 'Move to Next Book', - 'books_sort_move_prev_chapter' => 'Move Into Previous Chapter', - 'books_sort_move_next_chapter' => 'Move Into Next Chapter', - 'books_sort_move_book_start' => 'Move to Start of Book', - 'books_sort_move_book_end' => 'Move to End of Book', + 'books_sort_move_up' => 'Flyt op', + 'books_sort_move_down' => 'Flyt ned', + 'books_sort_move_prev_book' => 'Flyt til forrige bog', + 'books_sort_move_next_book' => 'Flyt til næste bog', + 'books_sort_move_prev_chapter' => 'Flyt Til Foregående Kapitel', + 'books_sort_move_next_chapter' => 'Flyt Til Næste Kapitel', + 'books_sort_move_book_start' => 'Flyt til Start af bog', + 'books_sort_move_book_end' => 'Flyt til slutningen af bogen', 'books_sort_move_before_chapter' => 'Move to Before Chapter', 'books_sort_move_after_chapter' => 'Move to After Chapter', 'books_copy' => 'Kopier Bog', @@ -229,7 +229,7 @@ return [ 'pages_edit_enter_changelog' => 'Indtast ændringsoversigt', 'pages_editor_switch_title' => 'Skift Editor', 'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?', - 'pages_editor_switch_consider_following' => 'Consider the following when changing editors:', + 'pages_editor_switch_consider_following' => 'Overvej følgende ved skift af redaktører:', 'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.', 'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.', 'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.', @@ -241,7 +241,7 @@ return [ 'pages_md_insert_image' => 'Indsæt billede', 'pages_md_insert_link' => 'Indsæt emnelink', 'pages_md_insert_drawing' => 'Indsæt tegning', - 'pages_md_show_preview' => 'Show preview', + 'pages_md_show_preview' => 'Vis forhåndsvisning', 'pages_md_sync_scroll' => 'Sync preview scroll', 'pages_drawing_unsaved' => 'Unsaved Drawing Found', 'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?', @@ -261,7 +261,7 @@ return [ 'pages_revisions_created_by' => 'Oprettet af', 'pages_revisions_date' => 'Revisionsdato', 'pages_revisions_number' => '#', - 'pages_revisions_sort_number' => 'Revision Number', + 'pages_revisions_sort_number' => 'Revisionsnummer', 'pages_revisions_numbered' => 'Revision #:id', 'pages_revisions_numbered_changes' => 'Revision #:id ændringer', 'pages_revisions_editor' => 'Editor Type', @@ -299,7 +299,7 @@ return [ 'pages_is_template' => 'Sideskabelon', // Editor Sidebar - 'toggle_sidebar' => 'Toggle Sidebar', + 'toggle_sidebar' => 'Sidebjælke til/fra', 'page_tags' => 'Sidetags', 'chapter_tags' => 'Kapiteltags', 'book_tags' => 'Bogtags', @@ -412,7 +412,7 @@ return [ 'references_to_desc' => 'Listed below is all the known content in the system that links to this item.', // Watch Options - 'watch' => 'Watch', + 'watch' => 'Overvåg', 'watch_title_default' => 'Default Preferences', 'watch_desc_default' => 'Revert watching to just your default notification preferences.', 'watch_title_ignore' => 'Ignore', diff --git a/lang/da/notifications.php b/lang/da/notifications.php index 61a44f1f0..00b0c464f 100644 --- a/lang/da/notifications.php +++ b/lang/da/notifications.php @@ -20,7 +20,7 @@ return [ 'detail_updated_by' => 'Updated By:', 'action_view_comment' => 'View Comment', - 'action_view_page' => 'View Page', + 'action_view_page' => 'Vis Side', 'footer_reason' => 'This notification was sent to you because :link cover this type of activity for this item.', 'footer_reason_link' => 'your notification preferences', diff --git a/lang/da/preferences.php b/lang/da/preferences.php index 2b88f9671..9b9436dba 100644 --- a/lang/da/preferences.php +++ b/lang/da/preferences.php @@ -5,47 +5,47 @@ */ return [ - 'my_account' => 'My Account', + 'my_account' => 'Min konto', - 'shortcuts' => 'Shortcuts', - 'shortcuts_interface' => 'UI Shortcut Preferences', - 'shortcuts_toggle_desc' => 'Here you can enable or disable keyboard system interface shortcuts, used for navigation and actions.', - 'shortcuts_customize_desc' => 'You can customize each of the shortcuts below. Just press your desired key combination after selecting the input for a shortcut.', - 'shortcuts_toggle_label' => 'Keyboard shortcuts enabled', + 'shortcuts' => 'Genveje', + 'shortcuts_interface' => 'Genveje', + 'shortcuts_toggle_desc' => 'Her kan du aktivere eller deaktivere genveje, der bruges til navigation og handlinger.', + 'shortcuts_customize_desc' => 'Du kan tilpasse hver af genvejene nedenfor. Tryk på din ønskede tastekombination efter at have valgt feltet for genvejen.', + 'shortcuts_toggle_label' => 'Tastaturgenveje aktiveret', 'shortcuts_section_navigation' => 'Navigation', - 'shortcuts_section_actions' => 'Common Actions', - 'shortcuts_save' => 'Save Shortcuts', - 'shortcuts_overlay_desc' => 'Note: When shortcuts are enabled a helper overlay is available via pressing "?" which will highlight the available shortcuts for actions currently visible on the screen.', - 'shortcuts_update_success' => 'Shortcut preferences have been updated!', - 'shortcuts_overview_desc' => 'Manage keyboard shortcuts you can use to navigate the system user interface.', + 'shortcuts_section_actions' => 'Almindelige handlinger', + 'shortcuts_save' => 'Gem Genveje', + 'shortcuts_overlay_desc' => 'Bemærk: Når genveje er aktiveret kan du altid se de tilgængelige genveje ved at trykke på "?" på dit tastatur.', + 'shortcuts_update_success' => 'Genvejspræferencer er blevet opdateret!', + 'shortcuts_overview_desc' => 'Håndtér tastaturgenveje, du kan bruge til at navigere i systemets brugergrænseflade.', - 'notifications' => 'Notification Preferences', - 'notifications_desc' => 'Control the email notifications you receive when certain activity is performed within the system.', - 'notifications_opt_own_page_changes' => 'Notify upon changes to pages I own', - 'notifications_opt_own_page_comments' => 'Notify upon comments on pages I own', - 'notifications_opt_comment_replies' => 'Notify upon replies to my comments', - 'notifications_save' => 'Save Preferences', - 'notifications_update_success' => 'Notification preferences have been updated!', - 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications' => 'Notifikationer', + 'notifications_desc' => 'Administrer de e-mail-notifikationer, du modtager, når visse aktiviteter udføres i systemet.', + 'notifications_opt_own_page_changes' => 'Adviser ved ændringer af sider, jeg ejer', + 'notifications_opt_own_page_comments' => 'Adviser ved kommentarer på sider, jeg ejer', + 'notifications_opt_comment_replies' => 'Adviser ved svar på mine kommentarer', + 'notifications_save' => 'Gem Indstillinger', + 'notifications_update_success' => 'Indstillinger for notifikationer er blevet opdateret!', + 'notifications_watched' => 'Overvågede & Ignorerede', + 'notifications_watched_desc' => 'Nedenfor er de elementer, der har brugerdefinerede overvågning aktivt. For at opdatere dine præferencer for disse, gå til elementet og find derefter overvågning i sidepanelet.', - 'auth' => 'Access & Security', - 'auth_change_password' => 'Change Password', - 'auth_change_password_desc' => 'Change the password you use to log-in to the application. This must be at least 8 characters long.', - 'auth_change_password_success' => 'Password has been updated!', + 'auth' => 'Adgang & Sikkerhed', + 'auth_change_password' => 'Skift adgangskode', + 'auth_change_password_desc' => 'Skift den adgangskode, du bruger til at logge ind med. Den skal være mindst 8 tegn lang.', + 'auth_change_password_success' => 'Adgangskoden er blevet opdateret!', - 'profile' => 'Profile Details', - 'profile_desc' => 'Manage the details of your account which represents you to other users, in addition to details that are used for communication and system personalisation.', - 'profile_view_public' => 'View Public Profile', - 'profile_name_desc' => 'Configure your display name which will be visible to other users in the system through the activity you perform, and content you own.', - 'profile_email_desc' => 'This email will be used for notifications and, depending on active system authentication, system access.', - 'profile_email_no_permission' => 'Unfortunately you don\'t have permission to change your email address. If you want to change this, you\'d need to ask an administrator to change this for you.', - 'profile_avatar_desc' => 'Select an image which will be used to represent yourself to others in the system. Ideally this image should be square and about 256px in width and height.', - 'profile_admin_options' => 'Administrator Options', - 'profile_admin_options_desc' => 'Additional administrator-level options, like those to manage role assignments, can be found for your user account in the "Settings > Users" area of the application.', + 'profile' => 'Profil', + 'profile_desc' => 'Administrer detaljerne på din konto, som repræsenterer dig over for andre brugere.', + 'profile_view_public' => 'Vis offentlig profil', + 'profile_name_desc' => 'Konfigurer dit visningsnavn, som vil være synligt for andre brugere i systemet gennem den aktivitet, du udfører, og indhold du ejer.', + 'profile_email_desc' => 'Denne e-mail vil blive brugt til notifikationer og, afhængigt af aktiv systemgodkendelse, systemadgang.', + 'profile_email_no_permission' => 'Desværre har du ikke tilladelse til at ændre din e-mailadresse. Hvis du ønsker at ændre dette, skal du bede en administrator om at ændre dette for dig.', + 'profile_avatar_desc' => 'Vælg et billede som vil blive brugt til at repræsentere dig selv over for andre i systemet. Ideelt set bør dette billede være kvadrat og omkring 256px i bredde og højde.', + 'profile_admin_options' => 'Administrator Indstillinger', + 'profile_admin_options_desc' => 'Yderligere indstillinger på administratorniveau, såsom dem der håndterer rolleopgaver, kan findes for din brugerkonto i området "Indstillinger > Brugere".', - 'delete_account' => 'Delete Account', - 'delete_my_account' => 'Delete My Account', - 'delete_my_account_desc' => 'This will fully delete your user account from the system. You will not be able to recover this account or revert this action. Content you\'ve created, such as created pages and uploaded images, will remain.', - 'delete_my_account_warning' => 'Are you sure you want to delete your account?', + 'delete_account' => 'Slet konto', + 'delete_my_account' => 'Slet min konto', + 'delete_my_account_desc' => 'Dette vil fuldt ud slette din brugerkonto fra systemet. Du vil ikke være i stand til at gendanne denne konto eller fortryde denne handling. Indhold, du har oprettet, såsom oprettede sider og uploadede billeder, vil ikke blive slettet.', + 'delete_my_account_warning' => 'Er du sikker at du vil slette din konto?', ]; diff --git a/lang/da/settings.php b/lang/da/settings.php index b777ea14a..276bb4995 100644 --- a/lang/da/settings.php +++ b/lang/da/settings.php @@ -51,8 +51,8 @@ return [ 'color_scheme' => 'Application Color Scheme', 'color_scheme_desc' => 'Set the colors to use in the application user interface. Colors can be configured separately for dark and light modes to best fit the theme and ensure legibility.', 'ui_colors_desc' => 'Set the application primary color and default link color. The primary color is mainly used for the header banner, buttons and interface decorations. The default link color is used for text-based links and actions, both within written content and in the application interface.', - 'app_color' => 'Primary Color', - 'link_color' => 'Default Link Color', + 'app_color' => 'Primær farve', + 'link_color' => 'Standard Link Farve', 'content_colors_desc' => 'Set colors for all elements in the page organisation hierarchy. Choosing colors with a similar brightness to the default colors is recommended for readability.', 'bookshelf_color' => 'Bogreolfarve', 'book_color' => 'Bogfarve', @@ -92,7 +92,7 @@ return [ 'maint_send_test_email_mail_text' => 'Tillykke! Da du har modtaget denne mailnotifikation, ser det ud som om, at dine mailindstillinger er opsat korrekt.', 'maint_recycle_bin_desc' => 'Slettede hylder, bøger, kapitler og sider overføres til papirkurven, så de kan gendannes eller slettes permanent. Ældre elementer i papirkurven fjernes automatisk efter et stykke tid afhængigt af systemets konfiguration.', 'maint_recycle_bin_open' => 'Åbn papirkurven', - 'maint_regen_references' => 'Regenerate References', + 'maint_regen_references' => 'Regenerer Referencer', 'maint_regen_references_desc' => 'This action will rebuild the cross-item reference index within the database. This is usually handled automatically but this action can be useful to index old content or content added via unofficial methods.', 'maint_regen_references_success' => 'Reference index has been regenerated!', 'maint_timeout_command_note' => 'Note: This action can take time to run, which can lead to timeout issues in some web environments. As an alternative, this action be performed using a terminal command.', @@ -139,7 +139,7 @@ return [ 'roles_index_desc' => 'Roles are used to group users & provide system permission to their members. When a user is a member of multiple roles the privileges granted will stack and the user will inherit all abilities.', 'roles_x_users_assigned' => ':count user assigned|:count users assigned', 'roles_x_permissions_provided' => ':count permission|:count permissions', - 'roles_assigned_users' => 'Assigned Users', + 'roles_assigned_users' => 'Tildelte brugere', 'roles_permissions_provided' => 'Provided Permissions', 'role_create' => 'Opret en ny rolle', 'role_delete' => 'Slet rolle', @@ -214,8 +214,8 @@ return [ 'users_social_accounts_info' => 'Her kan du forbinde dine andre konti for hurtigere og lettere login. Afbrydelse af en konto her tilbagekalder ikke tidligere autoriseret adgang. Tilbagekald adgang fra dine profilindstillinger på den tilsluttede sociale konto.', 'users_social_connect' => 'Forbind konto', 'users_social_disconnect' => 'Frakobl konto', - 'users_social_status_connected' => 'Connected', - 'users_social_status_disconnected' => 'Disconnected', + 'users_social_status_connected' => 'Tilsuttet', + 'users_social_status_disconnected' => 'Afbrudt', 'users_social_connected' => ':socialAccount kontoen blev knyttet til din profil.', 'users_social_disconnected' => ':socialAccount kontoen blev afbrudt fra din profil.', 'users_api_tokens' => 'API Tokens', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Sidst Fejlet:', 'webhooks_last_error_message' => 'Sidste fejlmeddelelse:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/de/preferences.php b/lang/de/preferences.php index 66c7f6f12..291e0f9f6 100644 --- a/lang/de/preferences.php +++ b/lang/de/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Einstellungen speichern', 'notifications_update_success' => 'Benachrichtigungseinstellungen wurden aktualisiert!', 'notifications_watched' => 'Beobachtete und ignorierte Elemente', - 'notifications_watched_desc' => ' Nachfolgend finden Sie die Elemente, für die benutzerdefinierten Überwachungspräferenzen gelten. Um Ihre Einstellungen für diese Elemente zu aktualisieren, sehen Sie sich das Element an und suchen dann die Überwachungsoptionen in der Seitenleiste.', + 'notifications_watched_desc' => 'Nachfolgend finden Sie die Elemente, für die benutzerdefinierten Überwachungspräferenzen gelten. Um Ihre Einstellungen für diese Elemente zu aktualisieren, sehen Sie sich das Element an und suchen dann die Überwachungsoptionen in der Seitenleiste.', 'auth' => 'Zugang & Sicherheit', 'auth_change_password' => 'Passwort ändern', diff --git a/lang/de/settings.php b/lang/de/settings.php index f25576e27..f237ea532 100644 --- a/lang/de/settings.php +++ b/lang/de/settings.php @@ -277,6 +277,14 @@ Hinweis: Benutzer können ihre E-Mail-Adresse nach erfolgreicher Registrierung 'webhooks_last_errored' => 'Letzter Fehler:', 'webhooks_last_error_message' => 'Letzte Fehlermeldung:', + // Licensing + 'licenses' => 'Lizenzen', + 'licenses_desc' => 'Diese Seite beschreibt Lizenzinformationen für BookStack zusätzlich zu den Projekten und Bibliotheken, die in BookStack verwendet werden. Viele aufgelistete Projekte dürfen nur in einem Entwicklungskontext verwendet werden.', + 'licenses_bookstack' => 'BookStack-Lizenz', + 'licenses_php' => 'PHP-Bibliothekslizenzen', + 'licenses_js' => 'JavaScript-Bibliothekslizenzen', + 'licenses_other' => 'Andere Lizenzen', + 'license_details' => 'Lizenzdetails', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/de_informal/entities.php b/lang/de_informal/entities.php index 9ed27c9d1..f65e15ee8 100644 --- a/lang/de_informal/entities.php +++ b/lang/de_informal/entities.php @@ -398,7 +398,7 @@ return [ 'convert_to_shelf' => 'In Regal umwandeln', 'convert_to_shelf_contents_desc' => 'Du kannst dieses Buch in ein neues Regal mit demselben Inhalt umwandeln. Die in diesem Buch enthaltenen Kapitel werden in neue Bücher umgewandelt. Wenn dieses Buch Seiten enthält, die nicht in einem Kapitel enthalten sind, wird das Buch umbenannt und enthält diese Seiten, und das Buch wird Teil des neuen Regals.', 'convert_to_shelf_permissions_desc' => 'Alle Berechtigungen, die für dieses Buch festgelegt wurden, werden in das neue Regal und in alle neuen untergeordneten Bücher kopiert, für die keine eigenen Berechtigungen festgelegt wurden. Beachte, dass Berechtigungen für Regale nicht automatisch auf den Inhalt übertragen werden, wie es bei Büchern der Fall ist.', - 'convert_book' => 'In Buch umwandeln', + 'convert_book' => 'Buch umwandeln', 'convert_book_confirm' => 'Bist du dir sicher, dass du dieses Buch umwandelt möchtest?', 'convert_undo_warning' => 'Das kann nicht so einfach rückgängig gemacht werden.', 'convert_to_book' => 'In Buch umwandeln', diff --git a/lang/de_informal/preferences.php b/lang/de_informal/preferences.php index a2fc60a14..8211e2336 100644 --- a/lang/de_informal/preferences.php +++ b/lang/de_informal/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Einstellungen speichern', 'notifications_update_success' => 'Benachrichtigungseinstellungen wurden aktualisiert!', 'notifications_watched' => 'Beobachtete und ignorierte Elemente', - 'notifications_watched_desc' => ' Nachfolgend finden Sie die Elemente, für die benutzerdefinierten Überwachungspräferenzen gelten. Um deine Einstellungen für diese Elemente zu aktualisieren, sieh dir das Element an und suche dann die Überwachungsoptionen in der Seitenleiste.', + 'notifications_watched_desc' => 'Nachfolgend finden Sie die Elemente, für die benutzerdefinierten Überwachungspräferenzen gelten. Um deine Einstellungen für diese Elemente zu aktualisieren, sieh dir das Element an und suche dann die Überwachungsoptionen in der Seitenleiste.', 'auth' => 'Zugang & Sicherheit', 'auth_change_password' => 'Passwort ändern', diff --git a/lang/de_informal/settings.php b/lang/de_informal/settings.php index ea65bef55..4398edebd 100644 --- a/lang/de_informal/settings.php +++ b/lang/de_informal/settings.php @@ -277,6 +277,14 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'webhooks_last_errored' => 'Letzter Fehler:', 'webhooks_last_error_message' => 'Letzte Fehlermeldung:', + // Licensing + 'licenses' => 'Lizenzen', + 'licenses_desc' => 'Diese Seite beschreibt Lizenzinformationen für BookStack zusätzlich zu den Projekten und Bibliotheken, die in BookStack verwendet werden. Viele aufgelistete Projekte dürfen nur in einem Entwicklungskontext verwendet werden.', + 'licenses_bookstack' => 'BookStack-Lizenz', + 'licenses_php' => 'PHP-Bibliothekslizenzen', + 'licenses_js' => 'JavaScript-Bibliothekslizenzen', + 'licenses_other' => 'Andere Lizenzen', + 'license_details' => 'Lizenzdetails', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/el/preferences.php b/lang/el/preferences.php index a06aff547..4f7e97d52 100644 --- a/lang/el/preferences.php +++ b/lang/el/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/el/settings.php b/lang/el/settings.php index 43a27b13b..8f0e20bac 100644 --- a/lang/el/settings.php +++ b/lang/el/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Τελευταίο σφάλμα:', 'webhooks_last_error_message' => 'Τελευταίο μήνυμα λάθους:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/es/activities.php b/lang/es/activities.php index bd1e0dbd0..9431eeb9f 100644 --- a/lang/es/activities.php +++ b/lang/es/activities.php @@ -6,7 +6,7 @@ return [ // Pages - 'page_create' => 'página creada', + 'page_create' => 'Página creada', 'page_create_notification' => 'Página creada correctamente', 'page_update' => 'página actualizada', 'page_update_notification' => 'Página actualizada correctamente', @@ -72,7 +72,7 @@ return [ 'mfa_remove_method_notification' => 'Método de Autenticación en Dos Pasos eliminado correctamente', // Settings - 'settings_update' => 'ajustes actualizados', + 'settings_update' => 'configuración actualizada', 'settings_update_notification' => 'Configuración actualizada correctamente', 'maintenance_action_run' => 'ejecutada acción de mantenimiento', diff --git a/lang/es/preferences.php b/lang/es/preferences.php index 3974683f7..13af93d29 100644 --- a/lang/es/preferences.php +++ b/lang/es/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Guardar preferencias', 'notifications_update_success' => '¡Se han actualizado las preferencias de notificaciones!', 'notifications_watched' => 'Elementos vistos e ignorados', - 'notifications_watched_desc' => ' A continuación se muestran los elementos que tienen preferencias personalizadas de monitorización. Para actualizar sus preferencias, vea el artículo y las opciones se mostrarán en la barra lateral.', + 'notifications_watched_desc' => 'A continuación se muestran los elementos que tienen preferencias personalizadas de monitorización. Para actualizar sus preferencias, vea el elemento y las opciones se mostrarán en la barra lateral.', 'auth' => 'Acceso y seguridad', 'auth_change_password' => 'Cambiar contraseña', diff --git a/lang/es/settings.php b/lang/es/settings.php index 0d0cf221e..b040fda12 100644 --- a/lang/es/settings.php +++ b/lang/es/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Último error:', 'webhooks_last_error_message' => 'Último mensaje de error:', + // Licensing + 'licenses' => 'Licencias', + 'licenses_desc' => 'Esta página detalla información sobre la licencia de BookStack además de los proyectos y bibliotecas que se utilizan en BookStack. Muchos proyectos enumerados aquí pueden ser utilizados solo en un contexto de desarrollo.', + 'licenses_bookstack' => 'Licencia BookStack', + 'licenses_php' => 'Licencias de la biblioteca PHP', + 'licenses_js' => 'Licencias de la biblioteca JavaScript', + 'licenses_other' => 'Otras Licencias', + 'license_details' => 'Datos de la licencia', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/es_AR/activities.php b/lang/es_AR/activities.php index 41c26d2c4..f0afe2d43 100644 --- a/lang/es_AR/activities.php +++ b/lang/es_AR/activities.php @@ -59,7 +59,7 @@ return [ 'favourite_remove_notification' => '".name" se eliminó de sus favoritos', // Watching - 'watch_update_level_notification' => 'Preferencias de suscripciones actualizadas correctamente', + 'watch_update_level_notification' => 'Preferencias de visualización actualizadas con éxito', // Auth 'auth_login' => 'sesión iniciada', diff --git a/lang/es_AR/notifications.php b/lang/es_AR/notifications.php index 5ebc42129..a75b30f55 100644 --- a/lang/es_AR/notifications.php +++ b/lang/es_AR/notifications.php @@ -10,11 +10,11 @@ return [ 'new_page_intro' => 'Una nueva página ha sido creada en :appName:', 'updated_page_subject' => 'Página actualizada: :pageName', 'updated_page_intro' => 'Una página ha sido actualizada en :appName:', - 'updated_page_debounce' => 'Para prevenir notificaciones en masa, durante un tiempo no se enviarán notificaciones para futuras ediciones de esta página por el mismo editor.', + 'updated_page_debounce' => 'Para evitar una avalancha de notificaciones, durante un tiempo no se enviarán notificaciones sobre más ediciones de esta página por el mismo editor.', - 'detail_page_name' => 'Nombre de página:', + 'detail_page_name' => 'Nombre de la página:', 'detail_page_path' => 'Ruta de la página:', - 'detail_commenter' => 'Autor del comentario:', + 'detail_commenter' => 'Comentarista:', 'detail_comment' => 'Comentario:', 'detail_created_by' => 'Creado por:', 'detail_updated_by' => 'Actualizado por:', @@ -22,6 +22,6 @@ return [ 'action_view_comment' => 'Ver comentario', 'action_view_page' => 'Ver página', - 'footer_reason' => 'Esta notificación fue enviada porque :link cubre este tipo de actividad para este artículo.', - 'footer_reason_link' => 'sus preferencias de notificación', + 'footer_reason' => 'Esta notificación le fue enviada porque :link cubre este tipo de actividad para este elemento.', + 'footer_reason_link' => 'nuestras preferencias de notificación', ]; diff --git a/lang/es_AR/preferences.php b/lang/es_AR/preferences.php index f037d0d92..2bf3f3f96 100644 --- a/lang/es_AR/preferences.php +++ b/lang/es_AR/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Guardar preferencias', 'notifications_update_success' => '¡Se han actualizado las preferencias de notificaciones!', 'notifications_watched' => 'Elementos vistos e ignorados', - 'notifications_watched_desc' => ' A continuación se muestran los elementos que tienen preferencias personalizadas de monitorización. Para actualizar sus preferencias, vea el artículo y las opciones se mostrarán en la barra lateral.', + 'notifications_watched_desc' => 'A continuación se muestran los elementos que tienen preferencias personalizadas de monitorización. Para actualizar sus preferencias, vea el artículo y las opciones se mostrarán en la barra lateral.', 'auth' => 'Acceso y seguridad', 'auth_change_password' => 'Cambiar contraseña', diff --git a/lang/es_AR/settings.php b/lang/es_AR/settings.php index 344a9c87b..10da1a0a6 100644 --- a/lang/es_AR/settings.php +++ b/lang/es_AR/settings.php @@ -195,7 +195,7 @@ return [ 'users_send_invite_option' => 'Enviar correo electrónico de invitación al usuario.', 'users_external_auth_id' => 'ID externo de autenticación', 'users_external_auth_id_desc' => 'Cuando un sistema de autenticación externa está en uso (como SAML2, OIDC o LDAP) este es el ID que vincula este usuario de BookStack a la cuenta del sistema de autenticación. Puede ignorar este campo si utiliza la autenticación por defecto basada en correo electrónico.', - 'users_password_warning' => 'Solo debe rellenar este campo si desea cambiar la contraseña pora este usuario.', + 'users_password_warning' => 'Solo complete lo siguiente si desea cambiar la contraseña para este usuario.', 'users_system_public' => 'Este usuario representa cualquier usuario invitado que visita la aplicación. No puede utilizarse para hacer login sino que es asignado automáticamente.', 'users_delete' => 'Borrar usuario', 'users_delete_named' => 'Borrar usuario :userName', @@ -211,7 +211,7 @@ return [ 'users_preferred_language' => 'Lenguaje preferido', 'users_preferred_language_desc' => 'Esta opción cambiará el idioma de la interfaz de usuario en la aplicación. No afectará al contenido creado por los usuarios.', 'users_social_accounts' => 'Cuentas sociales', - 'users_social_accounts_desc' => 'Ver el estado de las cuentas sociales conectadas para este usuario. Las cuentas sociales se pueden utilizar adicionalmente al sistema de autenticación primaria para el acceso al sistema.', + 'users_social_accounts_desc' => 'Vea el estado de las cuentas sociales conectadas para este usuario. Las cuentas sociales se pueden usar además del sistema de autenticación principal para el acceso al sistema.', 'users_social_accounts_info' => 'Aquí puede conectar sus otras cuentas para un acceso rápido y más fácil. Desconectando una cuenta aquí no revoca accesos ya autorizados. Revoque el acceso desde los ajustes de perfil en la cuenta social conectada.', 'users_social_connect' => 'Conectar cuenta', 'users_social_disconnect' => 'Desconectar cuenta', @@ -220,7 +220,7 @@ return [ 'users_social_connected' => 'La cuenta :socialAccount ha sido exitosamente añadida a su perfil.', 'users_social_disconnected' => 'La cuenta :socialAccount ha sido desconectada exitosamente de su perfil.', 'users_api_tokens' => 'Tokens API', - 'users_api_tokens_desc' => 'Crear y administrar los tokens de acceso utilizados para autenticar con la REST API de BookStack. Los permisos para el API se administran a través del usuario al que pertenece el token.', + 'users_api_tokens_desc' => 'Cree y administre los tokens de acceso utilizados para autenticarse con la API REST de BookStack. Los permisos para la API se gestionan a través del usuario al que pertenece el token.', 'users_api_tokens_none' => 'No se han creado tokens API para este usuario', 'users_api_tokens_create' => 'Crear token', 'users_api_tokens_expires' => 'Expira', @@ -277,6 +277,14 @@ return [ 'webhooks_last_errored' => 'Último error:', 'webhooks_last_error_message' => 'Último mensaje de error:', + // Licensing + 'licenses' => 'Licencias', + 'licenses_desc' => 'Esta página detalla información sobre la licencia de BookStack además de los proyectos y bibliotecas que se utilizan en BookStack. Muchos proyectos enumerados aquí pueden ser utilizados solo en un contexto de desarrollo.', + 'licenses_bookstack' => 'Licencia BookStack', + 'licenses_php' => 'Licencias de la biblioteca PHP', + 'licenses_js' => 'Licencias de la biblioteca JavaScript', + 'licenses_other' => 'Otras Licencias', + 'license_details' => 'Datos de la licencia', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/et/preferences.php b/lang/et/preferences.php index 9ac77a965..f4ba5e6ae 100644 --- a/lang/et/preferences.php +++ b/lang/et/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Salvesta eelistused', 'notifications_update_success' => 'Teavituste eelistused on salvestatud!', 'notifications_watched' => 'Jälgitud ja ignoreeritud objektid', - 'notifications_watched_desc' => ' Allpool on objektid, millele on määratud kohaldatud jälgimise eelistused. Eelistuste muutmiseks ava vastav objekt ning leia jälgimise valikud külgmenüüs.', + 'notifications_watched_desc' => 'Allpool on objektid, millele on määratud kohaldatud jälgimise eelistused. Eelistuste muutmiseks ava vastav objekt ning leia jälgimise valikud külgmenüüs.', 'auth' => 'Ligipääs ja turvalisus', 'auth_change_password' => 'Muuda parool', diff --git a/lang/et/settings.php b/lang/et/settings.php index 3eefefe56..e73cde10b 100644 --- a/lang/et/settings.php +++ b/lang/et/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Viimati ebaõnnestunud:', 'webhooks_last_error_message' => 'Viimane veateade:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/eu/preferences.php b/lang/eu/preferences.php index 3e83a9784..da7638593 100644 --- a/lang/eu/preferences.php +++ b/lang/eu/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/eu/settings.php b/lang/eu/settings.php index 441e53bd5..0bd0d8257 100644 --- a/lang/eu/settings.php +++ b/lang/eu/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/fa/settings.php b/lang/fa/settings.php index 4df6e99a0..d2df873a9 100644 --- a/lang/fa/settings.php +++ b/lang/fa/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'آخرین خطا:', 'webhooks_last_error_message' => 'آخرین پیغام خطا:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/fi/settings.php b/lang/fi/settings.php index eceb41d1f..ee47d30d0 100644 --- a/lang/fi/settings.php +++ b/lang/fi/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Viimeisin virhe:', 'webhooks_last_error_message' => 'Viimeisin virheviesti:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/fr/passwords.php b/lang/fr/passwords.php index e209c2178..17dd15d01 100644 --- a/lang/fr/passwords.php +++ b/lang/fr/passwords.php @@ -7,8 +7,8 @@ return [ 'password' => 'Les mots de passe doivent faire au moins 8 caractères et correspondre à la confirmation.', - 'user' => "Nous n'avons pas trouvé d'utilisateur avec cette adresse.", - 'token' => 'Le mot de passe reset du token n\'est pas valide pour cette adresse e-mail.', + 'user' => "Nous n'avons pas trouvé d'utilisateur avec cette adresse e-mail.", + 'token' => 'Le jeton de réinitialisation du mot de passe n\'est pas valide pour cette adresse e-mail.', 'sent' => 'Nous vous avons envoyé un lien de réinitialisation de mot de passe par e-mail !', 'reset' => 'Votre mot de passe a été réinitialisé !', diff --git a/lang/fr/preferences.php b/lang/fr/preferences.php index f26972d7c..2180ed70c 100644 --- a/lang/fr/preferences.php +++ b/lang/fr/preferences.php @@ -8,7 +8,7 @@ return [ 'my_account' => 'Mon compte', 'shortcuts' => 'Raccourcis', - 'shortcuts_interface' => 'Préférences de raccourci de l\'interface utilisateur', + 'shortcuts_interface' => 'Préférences de raccourcis de l\'interface utilisateur', 'shortcuts_toggle_desc' => 'Ici vous pouvez activer ou désactiver les raccourcis clavier, utilisés pour la navigation et les actions.', 'shortcuts_customize_desc' => 'Vous pouvez personnaliser chaque raccourci ci-dessous. Il vous suffit d\'appuyer sur la combinaison de touche choisie après avoir sélectionné l\'entrée pour un raccourci.', 'shortcuts_toggle_label' => 'Raccourcis clavier activés', @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Enregistrer les préférences', 'notifications_update_success' => 'Les préférences de notification ont été mises à jour !', 'notifications_watched' => 'Éléments surveillés et ignorés', - 'notifications_watched_desc' => ' Voici les éléments qui ont des préférences de surveillance personnalisées appliquées. Pour mettre à jour vos préférences pour celles-ci, consultez l\'élément puis trouvez les options de surveillance dans la barre latérale.', + 'notifications_watched_desc' => 'Voici les éléments qui ont des préférences de surveillance personnalisées appliquées. Pour mettre à jour vos préférences pour celles-ci, consultez l\'élément puis trouvez les options de surveillance dans la barre latérale.', 'auth' => 'Accès et sécurité', 'auth_change_password' => 'Changer le mot de passe', diff --git a/lang/fr/settings.php b/lang/fr/settings.php index 928fed4b3..fa7433c48 100644 --- a/lang/fr/settings.php +++ b/lang/fr/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Dernier en erreur :', 'webhooks_last_error_message' => 'Dernier message d\'erreur : ', + // Licensing + 'licenses' => 'Licences', + 'licenses_desc' => 'Cette page détaille les informations de licence pour BookStack ainsi que les projets et librairies utilisées dans BookStack. Nombre des projets listés peuvent n\'être utilisés que dans un contexte de développement.', + 'licenses_bookstack' => 'Licences BookStack', + 'licenses_php' => 'Licences de librairies PHP', + 'licenses_js' => 'Licences de librairies JavaScript', + 'licenses_other' => 'Autres Licences', + 'license_details' => 'Détails de la licence', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/he/preferences.php b/lang/he/preferences.php index 28c8b127c..f0f997f26 100644 --- a/lang/he/preferences.php +++ b/lang/he/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/he/settings.php b/lang/he/settings.php index e16fdb299..b8bbfbe26 100644 --- a/lang/he/settings.php +++ b/lang/he/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/hr/preferences.php b/lang/hr/preferences.php index 520d9da73..2f409f8d3 100644 --- a/lang/hr/preferences.php +++ b/lang/hr/preferences.php @@ -29,7 +29,7 @@ Obavijesti o komentarima na stranicama koje posjedujem', 'notifications_save' => 'Spremi Postavke', 'notifications_update_success' => 'Postavke obavijesti su ažurirane!', 'notifications_watched' => 'Praćene i ignorirane stavke', - 'notifications_watched_desc' => ' Ispod su stavke na koje su primijenjene prilagođene postavke praćenja. Da biste ažurirali svoje postavke za ove stavke, pregledajte stavku, a zatim pronađite opcije praćenja u bočnoj traci.', + 'notifications_watched_desc' => 'Ispod su stavke na koje su primijenjene prilagođene postavke praćenja. Da biste ažurirali svoje postavke za ove stavke, pregledajte stavku, a zatim pronađite opcije praćenja u bočnoj traci.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/hr/settings.php b/lang/hr/settings.php index 42c033a29..4d010ba78 100644 --- a/lang/hr/settings.php +++ b/lang/hr/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Zadnja pogreška:', 'webhooks_last_error_message' => 'Posljednja poruka o pogrešci:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/hu/preferences.php b/lang/hu/preferences.php index 65f6088ec..11d145064 100644 --- a/lang/hu/preferences.php +++ b/lang/hu/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Beállítások mentése', 'notifications_update_success' => 'Az értesítési beállítások frissítve lettek!', 'notifications_watched' => 'Megfigyelt és figyelmen kívül hagyott elemek', - 'notifications_watched_desc' => ' Az alábbi elemekre egyedi figyelési beállítások vannak alkalmazva. A beállítások frissítéséhez tekintsd meg az elemet, majd keress a figyelési lehetőségeket az oldalsávban.', + 'notifications_watched_desc' => 'Az alábbi elemekre egyedi figyelési beállítások vannak alkalmazva. A beállítások frissítéséhez tekintsd meg az elemet, majd keress a figyelési lehetőségeket az oldalsávban.', 'auth' => 'Hozzáférés és Biztonság', 'auth_change_password' => 'Jelszó módosítása', diff --git a/lang/hu/settings.php b/lang/hu/settings.php index a7a3d0f19..9bf8880d3 100644 --- a/lang/hu/settings.php +++ b/lang/hu/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Utolsó hiba:', 'webhooks_last_error_message' => 'Utolsó hibaüzenet:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/id/preferences.php b/lang/id/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/id/preferences.php +++ b/lang/id/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/id/settings.php b/lang/id/settings.php index 540133628..3b57776f0 100644 --- a/lang/id/settings.php +++ b/lang/id/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/it/activities.php b/lang/it/activities.php index 518ffb269..39b6859e4 100644 --- a/lang/it/activities.php +++ b/lang/it/activities.php @@ -6,7 +6,7 @@ return [ // Pages - 'page_create' => 'pagina creata', + 'page_create' => 'ha creato la pagina', 'page_create_notification' => 'Pagina creata con successo', 'page_update' => 'ha aggiornato la pagina', 'page_update_notification' => 'Pagina aggiornata con successo', @@ -14,7 +14,7 @@ return [ 'page_delete_notification' => 'Pagina eliminata con successo', 'page_restore' => 'ha ripristinato la pagina', 'page_restore_notification' => 'Pagina ripristinata con successo', - 'page_move' => 'ha mosso la pagina', + 'page_move' => 'ha spostato la pagina', 'page_move_notification' => 'Pagina spostata con successo', // Chapters @@ -30,7 +30,7 @@ return [ // Books 'book_create' => 'ha creato il libro', 'book_create_notification' => 'Libro creato con successo', - 'book_create_from_chapter' => 'convertito da capitolo a libro', + 'book_create_from_chapter' => 'ha convertito da capitolo a libro', 'book_create_from_chapter_notification' => 'Capitolo convertito con successo in libro', 'book_update' => 'ha aggiornato il libro', 'book_update_notification' => 'Libro aggiornato con successo', @@ -40,18 +40,18 @@ return [ 'book_sort_notification' => 'Libro reindicizzato con successo', // Bookshelves - 'bookshelf_create' => 'libreria creata', + 'bookshelf_create' => 'ha creato la libreria', 'bookshelf_create_notification' => 'Libreria creata con successo', - 'bookshelf_create_from_book' => 'libro convertito in libreria', + 'bookshelf_create_from_book' => 'ha convertito libro in libreria', 'bookshelf_create_from_book_notification' => 'Libro convertito con successo in libreria', - 'bookshelf_update' => 'libreria aggiornata', + 'bookshelf_update' => 'ha aggiornato la libreria', 'bookshelf_update_notification' => 'Libreria aggiornata con successo', - 'bookshelf_delete' => 'Iibreria eliminata', + 'bookshelf_delete' => 'ha eliminato la libreria', 'bookshelf_delete_notification' => 'Libreria eliminata con successo', // Revisions - 'revision_restore' => 'revisione ripristinata', - 'revision_delete' => 'revisione eliminata', + 'revision_restore' => 'ha ripristinato la revisione', + 'revision_delete' => 'ha eliminato la revisione', 'revision_delete_notification' => 'Revisione eliminata con successo', // Favourites @@ -64,11 +64,11 @@ return [ // Auth 'auth_login' => 'connesso', 'auth_register' => 'registrato come nuovo utente', - 'auth_password_reset_request' => 'richiesta di reimpostazione della password utente', - 'auth_password_reset_update' => 'reimposta password utente', - 'mfa_setup_method' => 'metodo MFA configurato', + 'auth_password_reset_request' => 'ha richiesto di reimpostare la password utente', + 'auth_password_reset_update' => 'ha reimpostato la password utente', + 'mfa_setup_method' => 'ha configurato un metodo multi-fattore', 'mfa_setup_method_notification' => 'Metodo multi-fattore impostato con successo', - 'mfa_remove_method' => 'metodo MFA rimosso', + 'mfa_remove_method' => 'ha rimosso un metodo multi-fattore', 'mfa_remove_method_notification' => 'Metodo multi-fattore rimosso con successo', // Settings diff --git a/lang/it/auth.php b/lang/it/auth.php index b9bc685aa..00ecf9443 100644 --- a/lang/it/auth.php +++ b/lang/it/auth.php @@ -25,15 +25,15 @@ return [ 'forgot_password' => 'Password dimenticata?', 'remember_me' => 'Ricordami', 'ldap_email_hint' => 'Inserisci un email per usare quest\'account.', - 'create_account' => 'Crea Account', + 'create_account' => 'Crea un account', 'already_have_account' => 'Hai già un account?', 'dont_have_account' => 'Non hai un account?', 'social_login' => 'Login Social', 'social_registration' => 'Registrazione Social', - 'social_registration_text' => 'Registrati usando un altro servizio.', + 'social_registration_text' => 'Registrati e accedi utilizzando un altro servizio.', 'register_thanks' => 'Grazie per esserti registrato!', - 'register_confirm' => 'Controlla la tua mail e clicca il bottone di conferma per accedere a :appName.', + 'register_confirm' => 'Controlla la tua mail e clicca il pulsante di conferma per accedere a :appName.', 'registrations_disabled' => 'La registrazione è disabilitata', 'registration_email_domain_invalid' => 'Questo dominio della mail non ha accesso a questa applicazione', 'register_success' => 'Grazie per la registrazione! Sei registrato e loggato.', diff --git a/lang/it/common.php b/lang/it/common.php index b886ac35c..6410081d2 100644 --- a/lang/it/common.php +++ b/lang/it/common.php @@ -35,16 +35,16 @@ return [ 'copy' => 'Copia', 'reply' => 'Rispondi', 'delete' => 'Elimina', - 'delete_confirm' => 'Conferma Eliminazione', + 'delete_confirm' => 'Conferma eliminazione', 'search' => 'Cerca', - 'search_clear' => 'Pulisci Ricerca', + 'search_clear' => 'Pulisci ricerca', 'reset' => 'Azzera', 'remove' => 'Rimuovi', 'add' => 'Aggiungi', 'configure' => 'Configura', 'manage' => 'Gestisci', 'fullscreen' => 'Schermo intero', - 'favourite' => 'Aggiungi ai Preferiti', + 'favourite' => 'Aggiungi ai preferiti', 'unfavourite' => 'Rimuovi dai preferiti', 'next' => 'Successivo', 'previous' => 'Precedente', @@ -56,9 +56,9 @@ return [ // Sort Options 'sort_options' => 'Opzioni Ordinamento', - 'sort_direction_toggle' => 'Inverti Direzione Ordinamento', - 'sort_ascending' => 'Ordine Ascendente', - 'sort_descending' => 'Ordine Discendente', + 'sort_direction_toggle' => 'Inverti direzione ordinamento', + 'sort_ascending' => 'Ordine ascendente', + 'sort_descending' => 'Ordine discendente', 'sort_name' => 'Nome', 'sort_default' => 'Predefinito', 'sort_created_at' => 'Data Creazione', diff --git a/lang/it/entities.php b/lang/it/entities.php index 4c49dae5e..22bc359ba 100644 --- a/lang/it/entities.php +++ b/lang/it/entities.php @@ -39,8 +39,8 @@ return [ 'export_pdf' => 'File PDF', 'export_text' => 'File di testo', 'export_md' => 'File Markdown', - 'default_template' => 'Modello Di Pagina Predefinito', - 'default_template_explain' => 'Assegna un modello di pagina che sarà usato come contenuto predefinito per tutte le pagine create in questo elemento. Tenere presente che questo verrà utilizzato solo se il creatore della pagina ha accesso alla pagina del modello scelto.', + 'default_template' => 'Modello di Pagina Predefinito', + 'default_template_explain' => 'Assegna un modello di pagina che sarà usato come contenuto predefinito per tutte le pagine create in questo elemento. Tieni presente che questo verrà utilizzato solo se il creatore della pagina ha accesso alla pagina del modello scelto.', 'default_template_select' => 'Seleziona una pagina modello', // Permissions and restrictions @@ -61,15 +61,15 @@ return [ 'search_clear' => 'Pulisci Ricerca', 'search_no_pages' => 'Nessuna pagina corrisponde alla ricerca', 'search_for_term' => 'Ricerca per :term', - 'search_more' => 'Più Risultati', + 'search_more' => 'Più risultati', 'search_advanced' => 'Ricerca Avanzata', 'search_terms' => 'Termini Ricerca', 'search_content_type' => 'Tipo di Contenuto', 'search_exact_matches' => 'Corrispondenza Esatta', 'search_tags' => 'Ricerche Tag', 'search_options' => 'Opzioni', - 'search_viewed_by_me' => 'Visti', - 'search_not_viewed_by_me' => 'Non visti', + 'search_viewed_by_me' => 'Visti da me', + 'search_not_viewed_by_me' => 'Non visti da me', 'search_permissions_set' => 'Permessi impostati', 'search_created_by_me' => 'Creati da me', 'search_updated_by_me' => 'Aggiornati da me', @@ -112,7 +112,7 @@ return [ 'shelves_permissions_create' => 'Le autorizzazioni per la creazione di librerie sono utilizzate solo per copiare le autorizzazioni ai libri figli utilizzando l\'azione sottostante. Non controllano la capacità di creare libri.', 'shelves_copy_permissions_to_books' => 'Copia Permessi ai Libri', 'shelves_copy_permissions' => 'Copia Permessi', - 'shelves_copy_permissions_explain' => 'Verranno applicati tutti i permessi della libreria ai libri al suo interno. Prima dell\'attivazione, assicurati che ogni permesso di questa libreria sia salvato.', + 'shelves_copy_permissions_explain' => 'Verranno applicati tutti i permessi della libreria ai libri al suo interno. Prima dell\'attivazione, assicurati di aver salvato le modifiche ai permessi di questa libreria.', 'shelves_copy_permission_success' => 'Permessi della libreria copiati in :count libri', // Books @@ -145,7 +145,7 @@ return [ 'books_search_this' => 'Cerca in questo libro', 'books_navigation' => 'Navigazione Libro', 'books_sort' => 'Ordina il contenuto del libro', - 'books_sort_desc' => 'Spostare capitoli e pagine all\'interno di un libro per riorganizzarne il contenuto. È possibile aggiungere altri libri, per spostare facilmente capitoli e pagine da un libro all\'altro.', + 'books_sort_desc' => 'Sposta capitoli e pagine all\'interno di un libro per riorganizzarne il contenuto. È possibile aggiungere altri libri, per spostare facilmente capitoli e pagine da un libro all\'altro.', 'books_sort_named' => 'Ordina il libro :bookName', 'books_sort_name' => 'Ordina per Nome', 'books_sort_created' => 'Ordina per Data di Creazione', @@ -154,17 +154,17 @@ return [ 'books_sort_chapters_last' => 'Capitoli Per Ultimi', 'books_sort_show_other' => 'Mostra Altri Libri', 'books_sort_save' => 'Salva il nuovo ordine', - 'books_sort_show_other_desc' => 'Aggiungere qui altri libri per includerli nell\'operazione di ordinamento e consentire una facile riorganizzazione incrociata dei libri.', + 'books_sort_show_other_desc' => 'Aggiungi qui altri libri per includerli nell\'operazione di ordinamento e consentire una facile riorganizzazione incrociata dei libri.', 'books_sort_move_up' => 'Muovi su', 'books_sort_move_down' => 'Muovi giù', - 'books_sort_move_prev_book' => 'Passare al libro precedente', - 'books_sort_move_next_book' => 'Passare al libro successivo', - 'books_sort_move_prev_chapter' => 'Passare al capitolo precedente', - 'books_sort_move_next_chapter' => 'Passare al capitolo successivo', - 'books_sort_move_book_start' => 'Spostarsi all\'inizio del libro', - 'books_sort_move_book_end' => 'Spostarsi alla fine del libro', - 'books_sort_move_before_chapter' => 'Passare al capitolo precedente', - 'books_sort_move_after_chapter' => 'Passare al capitolo successivo', + 'books_sort_move_prev_book' => 'Passa al libro precedente', + 'books_sort_move_next_book' => 'Passa al libro successivo', + 'books_sort_move_prev_chapter' => 'Passa al capitolo precedente', + 'books_sort_move_next_chapter' => 'Passa al capitolo successivo', + 'books_sort_move_book_start' => 'Passa all\'inizio del libro', + 'books_sort_move_book_end' => 'Passa alla fine del libro', + 'books_sort_move_before_chapter' => 'Passa al capitolo precedente', + 'books_sort_move_after_chapter' => 'Passa al capitolo successivo', 'books_copy' => 'Copia Libro', 'books_copy_success' => 'Libro copiato con successo', @@ -177,7 +177,7 @@ return [ 'chapters_create' => 'Crea un nuovo capitolo', 'chapters_delete' => 'Elimina Capitolo', 'chapters_delete_named' => 'Elimina il capitolo :chapterName', - 'chapters_delete_explain' => 'Procedendo si eliminerà il capitolo denominato \':chapterName\'. Anche le pagine in esso contenute saranno eliminate.', + 'chapters_delete_explain' => 'Procedendo si eliminerà il capitolo denominato \':chapterName\'. Anche le pagine all\'interno saranno eliminate.', 'chapters_delete_confirm' => 'Sei sicuro di voler eliminare questo capitolo?', 'chapters_edit' => 'Elimina Capitolo', 'chapters_edit_named' => 'Modifica il capitolo :chapterName', @@ -207,7 +207,7 @@ return [ 'pages_delete_draft' => 'Elimina Bozza Pagina', 'pages_delete_success' => 'Pagina eliminata', 'pages_delete_draft_success' => 'Bozza di una pagina eliminata', - 'pages_delete_warning_template' => 'Questa pagina è in uso attivo come modello di pagina predefinito del libro o del capitolo. Questi libri o capitoli non avranno più un modello di pagina predefinito assegnato dopo che questa pagina è stata eliminata.', + 'pages_delete_warning_template' => 'Questa pagina è in uso come modello di pagina predefinito del libro o del capitolo. Questi libri o capitoli non avranno più un modello di pagina predefinito assegnato dopo che questa pagina sarà eliminata.', 'pages_delete_confirm' => 'Sei sicuro di voler eliminare questa pagina?', 'pages_delete_draft_confirm' => 'Sei sicuro di voler eliminare la bozza di questa pagina?', 'pages_editing_named' => 'Modifica :pageName', @@ -229,8 +229,8 @@ return [ 'pages_edit_enter_changelog' => 'Inserisci Changelog', 'pages_editor_switch_title' => 'Cambia Editor', 'pages_editor_switch_are_you_sure' => 'Sei sicuro di voler cambiare l\'editor di questa pagina?', - 'pages_editor_switch_consider_following' => 'Considerare quanto segue quando si cambia editor:', - 'pages_editor_switch_consideration_a' => 'Una volta salvata, la nuova opzione di editor sarà utilizzata da qualsiasi editor futuro, inclusi quelli che potrebbero non essere in grado di cambiare il tipo di editor da solo.', + 'pages_editor_switch_consider_following' => 'Considera quanto segue quando si cambia editor:', + 'pages_editor_switch_consideration_a' => 'Una volta salvata, la nuova opzione di editor sarà utilizzata da chi modificherà in futuro, inclusi quelli che potrebbero non essere in grado di cambiare il tipo di editor da soli.', 'pages_editor_switch_consideration_b' => 'Ciò può potenzialmente portare a una perdita di dettagli e sintassi in determinate circostanze.', 'pages_editor_switch_consideration_c' => 'Le modifiche al tag o al changelog, fatte dall\'ultimo salvataggio, non persisteranno in questa modifica.', 'pages_save' => 'Salva Pagina', @@ -277,19 +277,19 @@ return [ 'pages_pointer_label' => 'Opzioni Sezione Pagina', 'pages_pointer_permalink' => 'Permalink Sezione Pagina', 'pages_pointer_include_tag' => 'Sezione Pagina Includi Tag', - 'pages_pointer_toggle_link' => 'Modalità Permalink, Premi per mostrare il tag includi', - 'pages_pointer_toggle_include' => 'Modo includi tag, premi per mostrare permalink', + 'pages_pointer_toggle_link' => 'Modalità Permalink, Premi per mostrare includi tag', + 'pages_pointer_toggle_include' => 'Modalità includi tag, premi per mostrare permalink', 'pages_permissions_active' => 'Permessi Pagina Attivi', 'pages_initial_revision' => 'Pubblicazione iniziale', 'pages_references_update_revision' => 'Aggiornamento automatico di sistema dei collegamenti interni', 'pages_initial_name' => 'Nuova Pagina', 'pages_editing_draft_notification' => 'Stai modificando una bozza che è stata salvata il :timeDiff.', - 'pages_draft_edited_notification' => 'Questa pagina è stata aggiornata. È consigliabile scartare questa bozza.', - 'pages_draft_page_changed_since_creation' => 'Questa pagina è stata aggiornata da quando è stata creata questa bozza. Si consiglia di scartare questa bozza o fare attenzione a non sovrascrivere alcun cambiamento di pagina.', + 'pages_draft_edited_notification' => 'Questa pagina è stata aggiornata. Si consiglia di scartare questa bozza.', + 'pages_draft_page_changed_since_creation' => 'Questa pagina è stata aggiornata da quando è stata creata questa bozza. Si consiglia di scartare questa bozza o di fare attenzione a non sovrascrivere alcun cambiamento alla pagina.', 'pages_draft_edit_active' => [ - 'start_a' => ':count hanno iniziato a modificare questa pagina', + 'start_a' => ':count utenti hanno iniziato a modificare questa pagina', 'start_b' => ':userName ha iniziato a modificare questa pagina', - 'time_a' => 'da quando le pagine sono state aggiornate', + 'time_a' => 'dall\'ultimo aggiornamento della pagina', 'time_b' => 'negli ultimi :minCount minuti', 'message' => ':start :time. Assicurati di non sovrascrivere le modifiche degli altri!', ], @@ -299,31 +299,31 @@ return [ 'pages_is_template' => 'Template Pagina', // Editor Sidebar - 'toggle_sidebar' => 'Attiva/Disattiva Barra Laterale', + 'toggle_sidebar' => 'Attiva/disattiva barra laterale', 'page_tags' => 'Tag Pagina', 'chapter_tags' => 'Tag Capitolo', 'book_tags' => 'Tag Libro', 'shelf_tags' => 'Tag Libreria', 'tag' => 'Tag', 'tags' => 'Tag', - 'tags_index_desc' => 'I tag possono essere applicati ai contenuti del sistema per applicare una forma flessibile di categorizzazione. I tag possono avere contemporaneamente una chiave e un valore, mentre il valore è opzionale. Una volta applicati, i contenuti possono essere interrogati utilizzando il nome e il valore del tag.', - 'tag_name' => 'Nome Tag', - 'tag_value' => 'Valore (Opzionale)', + 'tags_index_desc' => 'I tag possono essere applicati ai contenuti del sistema per applicare una forma flessibile di categorizzazione. I tag possono avere una chiave e un valore, il valore è opzionale. Una volta applicati, i contenuti possono essere cercati utilizzando il nome e il valore del tag.', + 'tag_name' => 'Nome del tag', + 'tag_value' => 'Valore tag (opzionale)', 'tags_explain' => "Aggiungi tag per categorizzare meglio il contenuto. \n Puoi assegnare un valore ai tag per una migliore organizzazione.", 'tags_add' => 'Aggiungi un altro tag', 'tags_remove' => 'Rimuovi questo tag', 'tags_usages' => 'Utilizzo totale dei tag', - 'tags_assigned_pages' => 'Assegnato alle Pagine', + 'tags_assigned_pages' => 'Assegnato alle pagine', 'tags_assigned_chapters' => 'Assegnato ai capitoli', - 'tags_assigned_books' => 'Assegnato a Libri', - 'tags_assigned_shelves' => 'Assegnato alle Librerie', + 'tags_assigned_books' => 'Assegnato ai libri', + 'tags_assigned_shelves' => 'Assegnato alle librerie', 'tags_x_unique_values' => ':count valori univoci', 'tags_all_values' => 'Tutti i valori', 'tags_view_tags' => 'Visualizza tag', 'tags_view_existing_tags' => 'Usa i tag esistenti', - 'tags_list_empty_hint' => 'I tag possono essere assegnati tramite la barra laterale dell\'editor di pagina o durante la modifica dei dettagli di un libro, capitolo o libreria.', + 'tags_list_empty_hint' => 'I tag possono essere assegnati tramite la barra laterale dell\'editor di pagina o durante la modifica dei dettagli di un libro, di un capitolo o di una libreria.', 'attachments' => 'Allegati', - 'attachments_explain' => 'Carica alcuni file o allega link per visualizzarli nella pagina. Questi sono visibili nella sidebar della pagina.', + 'attachments_explain' => 'Carica alcuni file o allega link per visualizzarli nella pagina. Questi sono visibili nella barra laterale della pagina.', 'attachments_explain_instant_save' => 'I cambiamenti qui sono salvati istantaneamente.', 'attachments_upload' => 'Carica File', 'attachments_link' => 'Allega Link', @@ -338,10 +338,10 @@ return [ 'attachments_link_url' => 'Link al file', 'attachments_link_url_hint' => 'Url del sito o del file', 'attach' => 'Allega', - 'attachments_insert_link' => 'Aggiungi Link Allegato alla Pagina', - 'attachments_edit_file' => 'Modifica File', - 'attachments_edit_file_name' => 'Nome File', - 'attachments_edit_drop_upload' => 'Rilascia file o clicca qui per caricare e sovrascrivere', + 'attachments_insert_link' => 'Aggiungi link allegato alla pagina', + 'attachments_edit_file' => 'Modifica file', + 'attachments_edit_file_name' => 'Nome file', + 'attachments_edit_drop_upload' => 'Trascina file qui o clicca per caricare e sovrascrivere', 'attachments_order_updated' => 'Ordine allegato aggiornato', 'attachments_updated_success' => 'Dettagli allegato aggiornati', 'attachments_deleted' => 'Allegato eliminato', @@ -349,11 +349,11 @@ return [ 'attachments_file_updated' => 'File aggiornato correttamente', 'attachments_link_attached' => 'Link allegato correttamente alla pagina', 'templates' => 'Modello', - 'templates_set_as_template' => 'La pagina è un template', - 'templates_explain_set_as_template' => 'Puoi impostare questa pagina come template in modo che il suo contenuto sia utilizzato quando si creano altre pagine. Gli altri utenti potranno utilizzare questo template se avranno i permessi di visualizzazione per questa pagina.', + 'templates_set_as_template' => 'La pagina è un modello', + 'templates_explain_set_as_template' => 'Puoi impostare questa pagina come modello in modo da utilizzare il suo contenuto quando si creano altre pagine. Gli altri utenti potranno utilizzare questo modello se avranno i permessi di visualizzazione per questa pagina.', 'templates_replace_content' => 'Rimpiazza contenuto della pagina', 'templates_append_content' => 'Appendi al contenuto della pagina', - 'templates_prepend_content' => 'Prependi al contenuto della pagina', + 'templates_prepend_content' => 'Anteponi al contenuto della pagina', // Profile View 'profile_user_for_x' => 'Utente da :time', @@ -361,7 +361,7 @@ return [ 'profile_not_created_pages' => ':userName non ha creato pagine', 'profile_not_created_chapters' => ':userName non ha creato capitoli', 'profile_not_created_books' => ':userName non ha creato libri', - 'profile_not_created_shelves' => ':userName non ha creato alcuna libreria', + 'profile_not_created_shelves' => ':userName non ha creato librerie', // Comments 'comment' => 'Commento', @@ -387,17 +387,17 @@ return [ 'revision_cannot_delete_latest' => 'Impossibile eliminare l\'ultima revisione.', // Copy view - 'copy_consider' => 'Per favore, considerate quanto segue quando copiate il contenuto.', + 'copy_consider' => 'Considera quanto segue quando copi il contenuto.', 'copy_consider_permissions' => 'Le impostazioni dei permessi personalizzati non saranno copiate.', 'copy_consider_owner' => 'Diventerai il proprietario di tutti i contenuti copiati.', 'copy_consider_images' => 'I file delle immagini delle pagine non saranno duplicati e le immagini originali manterranno la loro relazione con la pagina su cui sono state originariamente caricate.', 'copy_consider_attachments' => 'Gli allegati della pagina non saranno copiati.', - 'copy_consider_access' => 'Un cambiamento di luogo, di proprietario o di autorizzazioni può far sì che questo contenuto sia accessibile a chi prima non aveva accesso.', + 'copy_consider_access' => 'Un cambiamento di posizione, di proprietario o di autorizzazioni può far sì che questo contenuto sia accessibile a chi prima non aveva accesso.', // Conversions 'convert_to_shelf' => 'Converti in Libreria', - 'convert_to_shelf_contents_desc' => 'È possibile convertire questo libro in una nuova libreria con gli stessi contenuti. I capitoli contenuti in questo libro saranno convertiti in nuovi libri. Se il libro contiene pagine che non fanno parte di un capitolo, questo libro verrà rinominato e conterrà tali pagine e diventerà parte della nuova libreria.', - 'convert_to_shelf_permissions_desc' => 'Tutti i permessi impostati su questo libro saranno copiati sulla nuova libreria e su tutti i nuovi libri figli che non hanno i loro permessi applicati. Si noti che i permessi delle librerie non si trasmettono automaticamente ai contenuti al loro interno, come avviene per i libri.', + 'convert_to_shelf_contents_desc' => 'Puoi convertire questo libro in una nuova libreria con gli stessi contenuti. I capitoli contenuti in questo libro saranno convertiti in nuovi libri. Se il libro contiene pagine che non fanno parte di un capitolo, questo libro verrà rinominato e conterrà tali pagine e diventerà parte della nuova libreria.', + 'convert_to_shelf_permissions_desc' => 'Tutti i permessi impostati su questo libro saranno copiati sulla nuova libreria e su tutti i nuovi libri figli che non hanno i loro permessi applicati. Nota che i permessi delle librerie non si trasmettono automaticamente ai contenuti al loro interno, come avviene per i libri.', 'convert_book' => 'Converti Libro', 'convert_book_confirm' => 'Sei sicuro di voler convertire questo libro?', 'convert_undo_warning' => 'Questo non può essere annullato con la stessa facilità.', diff --git a/lang/it/errors.php b/lang/it/errors.php index ea24eeeab..05bf5373f 100644 --- a/lang/it/errors.php +++ b/lang/it/errors.php @@ -27,7 +27,7 @@ return [ 'oidc_no_email_address' => 'Impossibile trovare un indirizzo email, per questo utente, nei dati forniti dal sistema di autenticazione esterno', 'oidc_fail_authed' => 'Accesso con :system non riuscito, il sistema non ha fornito l\'autorizzazione', 'social_no_action_defined' => 'Nessuna azione definita', - 'social_login_bad_response' => "Ricevuto error durante il login con :socialAccount : \n:error", + 'social_login_bad_response' => "Ricevuto errore durante il login con :socialAccount : \n:error", 'social_account_in_use' => 'Questo account :socialAccount è già utilizzato, prova a loggarti usando l\'opzione :socialAccount.', 'social_account_email_in_use' => 'La mail :email è già in uso. Se hai già un account puoi connettere il tuo account :socialAccount dalle impostazioni del tuo profilo.', 'social_account_existing' => 'Questo account :socialAccount è già connesso al tuo profilo.', @@ -41,13 +41,13 @@ return [ // System 'path_not_writable' => 'Il percorso :filePath non è scrivibile. Controlla che abbia i permessi corretti.', 'cannot_get_image_from_url' => 'Impossibile scaricare immagine da :url', - 'cannot_create_thumbs' => 'Il server non può creare thumbnail. Controlla che l\'estensione GD sia installata.', + 'cannot_create_thumbs' => 'Il server non può creare miniature. Controlla che l\'estensione GD sia installata.', 'server_upload_limit' => 'Il server non permette un upload di questa grandezza. Prova con un file più piccolo.', 'server_post_limit' => 'Il server non può ricevere la quantità di dati fornita. Riprovare con meno dati o con un file più piccolo.', 'uploaded' => 'Il server non consente upload di questa grandezza. Prova un file più piccolo.', // Drawing & Images - 'image_upload_error' => 'C\'è stato un errore caricando l\'immagine', + 'image_upload_error' => 'Si è verificato un errore nel caricamento dell\'immagine', 'image_upload_type_error' => 'Il tipo di immagine caricata non è valido', 'image_upload_replace_type' => 'Le sostituzioni di file immagine devono essere dello stesso tipo', 'image_upload_memory_limit' => 'Impossibile gestire il caricamento d\'immagini e/o creare miniature a causa dei limiti delle risorse di sistema.', @@ -71,7 +71,7 @@ return [ 'page_not_found' => 'Pagina non trovata', 'chapter_not_found' => 'Capitolo non trovato', 'selected_book_not_found' => 'Il libro selezionato non è stato trovato', - 'selected_book_chapter_not_found' => 'Il libro selezionato o il capitolo non sono stati trovati', + 'selected_book_chapter_not_found' => 'Il libro o il capitolo selezionati non sono stati trovati', 'guests_cannot_save_drafts' => 'Gli ospiti non possono salvare bozze', // Users @@ -81,27 +81,27 @@ return [ // Roles 'role_cannot_be_edited' => 'Questo ruolo non può essere modificato', 'role_system_cannot_be_deleted' => 'Questo ruolo è di sistema e non può essere eliminato', - 'role_registration_default_cannot_delete' => 'Questo ruolo non può essere eliminato finchè è impostato come default alla registrazione', - 'role_cannot_remove_only_admin' => 'Questo utente è l\'unico con assegnato il ruolo di amministratore. Assegna il ruolo di amministratore ad un altro utente prima di rimuoverlo qui.', + 'role_registration_default_cannot_delete' => 'Questo ruolo non può essere eliminato finchè è impostato come ruolo di registrazione predefinito', + 'role_cannot_remove_only_admin' => 'Questo utente è l\'unico con assegnato il ruolo di amministratore. Assegna il ruolo di amministratore ad un altro utente prima di rimuoverlo.', // Comments - 'comment_list' => 'C\'è stato un errore scaricando i commenti.', + 'comment_list' => 'Si è verificato un errore durante il recupero dei commenti.', 'cannot_add_comment_to_draft' => 'Non puoi aggiungere commenti a una bozza.', - 'comment_add' => 'C\'è stato un errore aggiungendo / aggiornando il commento.', - 'comment_delete' => 'C\'è stato un errore eliminando il commento.', + 'comment_add' => 'Si è verificato un errore durante l\'aggiunta / l\'aggiornamento del commento.', + 'comment_delete' => 'Si è verificato un errore durante l’eliminazione del commento.', 'empty_comment' => 'Impossibile aggiungere un commento vuoto.', // Error pages - '404_page_not_found' => 'Pagina Non Trovata', - 'sorry_page_not_found' => 'La pagina che stavi cercando non è stata trovata.', + '404_page_not_found' => 'Pagina non trovata', + 'sorry_page_not_found' => 'Siamo spiacenti, la pagina che stavi cercando non è stata trovata.', 'sorry_page_not_found_permission_warning' => 'Se pensi che questa pagina possa esistere, potresti non avere i permessi per visualizzarla.', 'image_not_found' => 'Immagine non trovata', 'image_not_found_subtitle' => 'Spiacente, l\'immagine che stai cercando non è stata trovata.', - 'image_not_found_details' => 'Se ti aspettavi che questa immagine esistesse, potrebbe essere stata cancellata.', + 'image_not_found_details' => 'Se pensi che questa immagine possa esistere, potrebbe essere stata cancellata.', 'return_home' => 'Ritorna alla home', - 'error_occurred' => 'C\'è Stato un errore', - 'app_down' => ':appName è offline', - 'back_soon' => 'Ritornerà presto.', + 'error_occurred' => 'Si è verificato un errore', + 'app_down' => ':appName è offline al momento', + 'back_soon' => 'Tornerà presto online.', // API errors 'api_no_authorization_found' => 'Nessun token di autorizzazione trovato nella richiesta', diff --git a/lang/it/notifications.php b/lang/it/notifications.php index 3b902600f..6b8932ebe 100644 --- a/lang/it/notifications.php +++ b/lang/it/notifications.php @@ -4,23 +4,23 @@ */ return [ - 'new_comment_subject' => 'Nuovo commento alla pagina: :pageName', + 'new_comment_subject' => 'Nuovo commento sulla pagina: :pageName', 'new_comment_intro' => 'Un utente ha commentato una pagina in :appName:', 'new_page_subject' => 'Nuova pagina: :pageName', 'new_page_intro' => 'Una nuova pagina è stata creata in :appName:', 'updated_page_subject' => 'Pagina aggiornata: :pageName', 'updated_page_intro' => 'Una pagina è stata aggiornata in :appName:', - 'updated_page_debounce' => 'Per evitare una massa di notifiche, per un po \'non verranno inviate notifiche per ulteriori modifiche a questa pagina dallo stesso editor.', + 'updated_page_debounce' => 'Per evitare una massa di notifiche, per un po\' non ti verranno inviate notifiche per ulteriori modifiche a questa pagina dallo stesso editor.', - 'detail_page_name' => 'Nome Della Pagina:', + 'detail_page_name' => 'Nome della pagina:', 'detail_page_path' => 'Percorso della pagina:', 'detail_commenter' => 'Commentatore:', 'detail_comment' => 'Commento:', - 'detail_created_by' => 'Creato Da:', - 'detail_updated_by' => 'Aggiornato Da:', + 'detail_created_by' => 'Creato da:', + 'detail_updated_by' => 'Aggiornato da:', - 'action_view_comment' => 'Visualizza Commento', - 'action_view_page' => 'Visualizza Pagina', + 'action_view_comment' => 'Vedi commento', + 'action_view_page' => 'Vedi pagina', 'footer_reason' => 'Questa notifica è stata inviata perché :link copre questo tipo di attività per questo elemento.', 'footer_reason_link' => 'le tue preferenze di notifica', diff --git a/lang/it/passwords.php b/lang/it/passwords.php index 7099d54f3..ac46ca06f 100644 --- a/lang/it/passwords.php +++ b/lang/it/passwords.php @@ -6,8 +6,8 @@ */ return [ - 'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.', - 'user' => "Non possiamo trovare un utente per quella mail.", + 'password' => 'La password deve avere almeno otto caratteri e corrispondere alla conferma.', + 'user' => "Nessun utente trovato per quella mail.", 'token' => 'Il token per reimpostare la password non è valido per questo indirizzo email.', 'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!', 'reset' => 'La tua password è stata reimpostata!', diff --git a/lang/it/preferences.php b/lang/it/preferences.php index c06374e69..f25138401 100644 --- a/lang/it/preferences.php +++ b/lang/it/preferences.php @@ -5,47 +5,47 @@ */ return [ - 'my_account' => 'Il Mio Account', + 'my_account' => 'Il mio account', 'shortcuts' => 'Scorciatoie', 'shortcuts_interface' => 'Preferenze di scelta rapida dell\'Interfaccia Utente', 'shortcuts_toggle_desc' => 'Qui puoi abilitare o disabilitare le scorciatoie dell\'interfaccia di sistema da tastiera, utilizzate per la navigazione e le azioni.', - 'shortcuts_customize_desc' => 'È possibile personalizzare ciascuna delle scorciatoie riportate di seguito. È sufficiente premere la combinazione di tasti desiderata dopo aver selezionato l\'input per una scelta rapida.', + 'shortcuts_customize_desc' => 'È possibile personalizzare ciascuna delle scorciatoie riportate di seguito. È sufficiente premere la combinazione di tasti desiderata dopo aver selezionato l\'input per una scorciatoia.', 'shortcuts_toggle_label' => 'Scorciatoie da tastiera attivate', 'shortcuts_section_navigation' => 'Navigazione', - 'shortcuts_section_actions' => 'Azioni Comuni', - 'shortcuts_save' => 'Salva Scorciatoie', + 'shortcuts_section_actions' => 'Azioni comuni', + 'shortcuts_save' => 'Salva scorciatoie', 'shortcuts_overlay_desc' => 'Nota: quando le scorciatoie sono abilitate, premendo "?" è possibile visualizzare le scorciatoie disponibili per le azioni attualmente visibili sullo schermo.', 'shortcuts_update_success' => 'Le preferenze delle scorciatoie sono state aggiornate!', 'shortcuts_overview_desc' => 'Gestisci le scorciatoie da tastiera che puoi usare per navigare nell\'interfaccia utente di sistema.', - 'notifications' => 'Preferenze Di Notifica', + 'notifications' => 'Preferenze notifiche', 'notifications_desc' => 'Controlla le notifiche email che ricevi quando viene eseguita una determinata attività all\'interno del sistema.', 'notifications_opt_own_page_changes' => 'Notifica in caso di modifiche alle pagine che possiedo', 'notifications_opt_own_page_comments' => 'Notifica i commenti sulle pagine che possiedo', 'notifications_opt_comment_replies' => 'Notificare le risposte ai miei commenti', - 'notifications_save' => 'Salva Preferenze', + 'notifications_save' => 'Salva preferenze', 'notifications_update_success' => 'Le preferenze di notifica sono state aggiornate!', - 'notifications_watched' => 'Oggetti Osservati E Ignorati', - 'notifications_watched_desc' => 'Di seguito sono riportati gli articoli a cui sono state applicate le preferenze di monitoraggio personalizzate. Per aggiornare le preferenze, visualizzare l\'articolo e trovare le opzioni di monitoraggio nella barra laterale.', + 'notifications_watched' => 'Oggetti osservati e ignorati', + 'notifications_watched_desc' => 'Di seguito sono riportati gli elementi a cui sono state applicate le preferenze di monitoraggio personalizzate. Per aggiornare le preferenze, visualizza l\'elemento e usa le opzioni di monitoraggio nella barra laterale.', - 'auth' => 'Accesso E Sicurezza', + 'auth' => 'Accesso e sicurezza', 'auth_change_password' => 'Modifica password', 'auth_change_password_desc' => 'Modifica la password che usi per accedere all\'applicazione. Deve essere lunga almeno 8 caratteri.', 'auth_change_password_success' => 'La password è stata aggiornata!', 'profile' => 'Dettagli del profilo', 'profile_desc' => 'Gestisci i dettagli dell\'account che ti rappresenta agli altri utenti, oltre ai dettagli utilizzati per la comunicazione e la personalizzazione del sistema.', - 'profile_view_public' => 'Visualizza Profilo Pubblico', + 'profile_view_public' => 'Visualizza profilo pubblico', 'profile_name_desc' => 'Configura il tuo nome visualizzato che sarà visibile ad altri utenti del sistema attraverso l\'attività che esegui e il contenuto che possiedi.', 'profile_email_desc' => 'Questa email verrà utilizzata per le notifiche e, a seconda dell\'autenticazione al sistema attiva, per l\'accesso al sistema.', - 'profile_email_no_permission' => 'Purtroppo non hai il permesso di modificare il tuo indirizzo email. Se si desidera modificarlo, è necessario chiedere ad un amministratore di farlo per te.', + 'profile_email_no_permission' => 'Purtroppo non hai il permesso di modificare il tuo indirizzo email. Se vuoi modificarlo, devi chiedere a un amministratore di farlo per te.', 'profile_avatar_desc' => 'Seleziona un\'immagine che verrà usata per rappresentarti agli altri utenti del sistema. Idealmente questa immagine dovrebbe essere quadrata e di circa 256px in larghezza e altezza.', - 'profile_admin_options' => 'Opzioni Amministratore', + 'profile_admin_options' => 'Opzioni amministratore', 'profile_admin_options_desc' => 'Ulteriori opzioni di livello amministrativo, come quelle per gestire le assegnazioni dei ruoli, possono essere trovate per il tuo account utente nell\'area "Impostazioni > Utenti".', - 'delete_account' => 'Elimina Account', - 'delete_my_account' => 'Elimina Il Mio Account', + 'delete_account' => 'Elimina account', + 'delete_my_account' => 'Elimina il mio account', 'delete_my_account_desc' => 'Questa azione eliminerà completamente il tuo account utente dal sistema. Non sarai in grado di recuperare l\'account né di annullare questa azione. Il contenuto che hai creato, come le pagine create e le immagini caricate, rimarrà nel sistema.', 'delete_my_account_warning' => 'Sei sicuro di voler eliminare il tuo account?', ]; diff --git a/lang/it/settings.php b/lang/it/settings.php index a6e5537be..ccbc505b7 100644 --- a/lang/it/settings.php +++ b/lang/it/settings.php @@ -8,63 +8,63 @@ return [ // Common Messages 'settings' => 'Impostazioni', - 'settings_save' => 'Salva Impostazioni', - 'system_version' => 'Versione Del Sistema', + 'settings_save' => 'Salva impostazioni', + 'system_version' => 'Versione del sistema', 'categories' => 'Categorie', // App Settings 'app_customization' => 'Personalizzazione', - 'app_features_security' => 'Funzioni & Sicurezza', + 'app_features_security' => 'Funzioni e sicurezza', 'app_name' => 'Nome applicazione', - 'app_name_desc' => 'Questo nome è mostrato nell\'header e in tutte le mail.', - 'app_name_header' => 'Mostrare il nome nell\'header', - 'app_public_access' => 'Accesso Pubblico', + 'app_name_desc' => 'Questo nome è mostrato nell\'intestazione e in tutte le email inviate dal sistema.', + 'app_name_header' => 'Mostra il nome nell\'header', + 'app_public_access' => 'Accesso pubblico', 'app_public_access_desc' => 'Abilitando questa opzione, i visitatori, che non sono loggati, potranno accedere ai contenuti nella tua istanza BookStack.', 'app_public_access_desc_guest' => 'L\'accesso ai visitatori pubblici può essere controllato attraverso l\'utente "Guest".', 'app_public_access_toggle' => 'Permetti accesso pubblico', 'app_public_viewing' => 'Consentire la visione pubblica?', - 'app_secure_images' => 'Abilitare una sicurezza maggiore per le immagini caricate?', - 'app_secure_images_toggle' => 'Abilita sicurezza aggiuntiva negli upload delle immagini', - 'app_secure_images_desc' => 'Per una ragione di prestazioni, tutte le immagini sono pubbliche. Questa opzione aaggiunge una stringa, difficile da indovinare, random negli url delle immagini. Assicurati che il listing delle cartelle non sia abilitato per prevenire un accesso semplice.', - 'app_default_editor' => 'Editor Di Pagina Predefinito', - 'app_default_editor_desc' => 'Seleziona quale editor sarà usato per impostazione predefinita quando modifichi nuove pagine. Questa impostazione potrà essere sovrascritta a livello di pagina dove i permessi lo permettano.', - 'app_custom_html' => 'Contenuto Head HTML Custom', + 'app_secure_images' => 'Sicurezza aggiuntiva per le immagini caricate', + 'app_secure_images_toggle' => 'Abilita sicurezza aggiuntiva per le immagini caricate', + 'app_secure_images_desc' => 'Per ragioni di prestazioni, tutte le immagini sono pubbliche. Questa opzione aggiunge una stringa casuale, difficile da indovinare, davanti agli url delle immagini. Assicurati che l\'indicizzazione delle cartelle non sia abilitato per prevenire un accesso semplice.', + 'app_default_editor' => 'Editor di pagina predefinito', + 'app_default_editor_desc' => 'Seleziona quale editor sarà usato per impostazione predefinita quando modifichi nuove pagine. Questa impostazione potrà essere sovrascritta a livello di pagina dove i permessi lo consentono.', + 'app_custom_html' => 'Contenuto Head HTML personalizzato', 'app_custom_html_desc' => 'Qualsiasi contenuto aggiunto qui verrà inserito alla fine della sezione di tutte le pagine. Questo è utile per sovrascrivere lo stile o aggiungere il codice per gli analytics.', - 'app_custom_html_disabled_notice' => 'Il contenuto HTML personalizzato è disabilitato su questa pagina impostazioni per garantire che eventuali modifiche possano essere ripristinate.', + 'app_custom_html_disabled_notice' => 'Il contenuto Head HTML personalizzato è disabilitato su questa pagina delle impostazioni per garantire che eventuali modifiche distruttive possano essere annullate.', 'app_logo' => 'Logo applicazione', 'app_logo_desc' => 'Viene utilizzata nella barra di intestazione dell\'applicazione, tra le altre aree. L\'immagine deve avere un\'altezza di 86px. Le immagini più grandi saranno ridimensionate.', - 'app_icon' => 'Icona Applicazione', + 'app_icon' => 'Icona applicazione', 'app_icon_desc' => 'Questa icona viene utilizzata per le schede del browser e per le icone di collegamento. Deve essere un\'immagine PNG quadrata di 256px.', - 'app_homepage' => 'Homepage Applicazione', - 'app_homepage_desc' => 'Seleziona una pagina da mostrare nella home anzichè quella di default. I permessi della pagina sono ignorati per quella selezionata.', + 'app_homepage' => 'Homepage applicazione', + 'app_homepage_desc' => 'Seleziona una pagina da mostrare nella home anzichè quella di default. I permessi della pagina sono ignorati per le pagine selezionate.', 'app_homepage_select' => 'Seleziona una pagina', - 'app_footer_links' => 'Link in basso', + 'app_footer_links' => 'Link a piè di pagina', 'app_footer_links_desc' => 'Aggiungi link da mostrare in basso nel sito. Questi saranno visibili in fondo alla maggior parte delle pagine, incluse quelle che non richiedono un autenticazione. Puoi usare l\'etichetta "trans::" per utilizzare le traduzioni implementate nella piattaforma. Esempio: usando "trans::common.privacy_policy" mostrerà il testo tradotto "Norme sulla privacy" e "trans::common.terms_of_service" mostrerà il testo tradotto "Condizioni del Servizio".', - 'app_footer_links_label' => 'Etichetta del Link', - 'app_footer_links_url' => 'URL del Link', - 'app_footer_links_add' => 'Aggiungi Link in basso', - 'app_disable_comments' => 'Disattiva commenti', - 'app_disable_comments_toggle' => 'Disabilita commenti', - 'app_disable_comments_desc' => 'Disabilita i commenti su tutte le pagine nell\'applicazione. I commenti esistenti non sono mostrati. ', + 'app_footer_links_label' => 'Etichetta del link', + 'app_footer_links_url' => 'URL del link', + 'app_footer_links_add' => 'Aggiungi link in basso', + 'app_disable_comments' => 'Disabilita commenti', + 'app_disable_comments_toggle' => 'Disabilita i commenti', + 'app_disable_comments_desc' => 'Disabilita i commenti su tutte le pagine dell\'applicazione.
I commenti esistenti non sono mostrati.', // Color settings 'color_scheme' => 'Schema di colore dell\'applicazione', - 'color_scheme_desc' => 'Impostare i colori da utilizzare nell\'interfaccia utente dell\'applicazione. I colori possono essere configurati separatamente per le modalità scura e chiara, per adattarsi al meglio al tema e garantire la leggibilità.', + 'color_scheme_desc' => 'Imposta i colori da utilizzare nell\'interfaccia utente dell\'applicazione. I colori possono essere configurati separatamente per le modalità scura e chiara, per adattarsi al meglio al tema e garantire la leggibilità.', 'ui_colors_desc' => 'Imposta il colore primario dell\'applicazione e il colore predefinito dei collegamenti. Il colore primario è utilizzato principalmente per il banner dell\'intestazione, i pulsanti e le decorazioni dell\'interfaccia. Il colore predefinito dei collegamenti viene utilizzato per i collegamenti e le azioni basate sul testo, sia all\'interno dei contenuti scritti che nell\'interfaccia dell\'applicazione.', - 'app_color' => 'Colore Principale', + 'app_color' => 'Colore principale', 'link_color' => 'Colore preferito del link', 'content_colors_desc' => 'Impostare i colori per tutti gli elementi nella gerarchia dell\'organizzazione della pagina. Si consiglia di scegliere colori con una luminosità simile a quella dei colori predefiniti per garantire la leggibilità.', 'bookshelf_color' => 'Colore della libreria', 'book_color' => 'Colore del libro', 'chapter_color' => 'Colore del capitolo', - 'page_color' => 'Colore della Pagina', + 'page_color' => 'Colore della pagina', 'page_draft_color' => 'Colore della bozza', // Registration Settings - 'reg_settings' => 'Impostazioni Registrazione', - 'reg_enable' => 'Abilita Registrazione', + 'reg_settings' => 'Impostazioni registrazione', + 'reg_enable' => 'Abilita registrazione', 'reg_enable_toggle' => 'Abilita registrazione', - 'reg_enable_desc' => 'Quando la registrazione è abilitata, l\utente sarà in grado di registrarsi all\'applicazione. Al momento della registrazione gli verrà associato un ruolo utente predefinito.', + 'reg_enable_desc' => 'Quando la registrazione è abilitata, l\utente sarà in grado di registrarsi autonomamente all\'applicazione. Al momento della registrazione gli verrà associato un ruolo utente predefinito.', 'reg_default_role' => 'Ruolo predefinito dopo la registrazione', 'reg_enable_external_warning' => 'L\'opzione precedente viene ignorata se l\'autenticazione esterna tramite LDAP o SAML è attiva. Se l\'autenticazione (effettuata sul sistema esterno) sarà valida, gli account di eventuali membri non registrati saranno creati in automatico.', 'reg_email_confirmation' => 'Conferma Email', @@ -76,42 +76,42 @@ return [ // Maintenance settings 'maint' => 'Manutenzione', - 'maint_image_cleanup' => 'Pulizia Immagini', - 'maint_image_cleanup_desc' => 'Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.', + 'maint_image_cleanup' => 'Pulizia immagini', + 'maint_image_cleanup_desc' => 'Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare un backup completo del database e delle immagini prima di eseguire la pulizia.', 'maint_delete_images_only_in_revisions' => 'Elimina anche le immagini che esistono solo nelle vecchie revisioni della pagina', - 'maint_image_cleanup_run' => 'Esegui Pulizia', - 'maint_image_cleanup_warning' => ':count immagini potenzialmente inutilizzate sono state trovate. Sei sicuro di voler eliminare queste immagini?', + 'maint_image_cleanup_run' => 'Esegui pulizia', + 'maint_image_cleanup_warning' => 'Sono state trovate :count immagini potenzialmente inutilizzate. Sei sicuro di voler eliminare queste immagini?', 'maint_image_cleanup_success' => ':count immagini potenzialmente inutilizzate trovate e eliminate!', - 'maint_image_cleanup_nothing_found' => 'Nessuna immagine non utilizzata trovata, Nulla è stato cancellato!', - 'maint_send_test_email' => 'Invia un Email di Test', - 'maint_send_test_email_desc' => 'Questo invia un\'email di prova al tuo indirizzo email specificato nel tuo profilo.', + 'maint_image_cleanup_nothing_found' => 'Nessuna immagine non utilizzata trovata, non è stato cancellato nulla!', + 'maint_send_test_email' => 'Invia un\'email di test', + 'maint_send_test_email_desc' => 'Questo comando invia un\'email di prova al tuo indirizzo email specificato nel tuo profilo.', 'maint_send_test_email_run' => 'Invia email di test', 'maint_send_test_email_success' => 'Email inviata a :address', - 'maint_send_test_email_mail_subject' => 'Email di Test', + 'maint_send_test_email_mail_subject' => 'Email di test', 'maint_send_test_email_mail_greeting' => 'L\'invio delle email sembra funzionare!', 'maint_send_test_email_mail_text' => 'Congratulazioni! Siccome hai ricevuto questa notifica email, le tue impostazioni sembrano essere configurate correttamente.', 'maint_recycle_bin_desc' => 'Le librerie, i libri, i capitoli e le pagine cancellati vengono inviati al cestino in modo che possano essere ripristinati o eliminati definitivamente. Gli elementi più vecchi nel cestino possono essere automaticamente rimossi dopo un certo periodo, a seconda della configurazione del sistema.', 'maint_recycle_bin_open' => 'Apri il Cestino', - 'maint_regen_references' => 'Rigenera Riferimenti', + 'maint_regen_references' => 'Rigenera riferimenti', 'maint_regen_references_desc' => 'Questa azione ricostruirà l\'indice dei riferimenti incrociati all\'interno del database. Di solito questa operazione è gestita automaticamente, ma può essere utile per indicizzare contenuti vecchi o aggiunti con metodi non ufficiali.', 'maint_regen_references_success' => 'L\'indice di riferimento è stato rigenerato!', - 'maint_timeout_command_note' => 'Nota: Questa azione può richiedere del tempo per essere eseguita e può causare problemi di timeout in alcuni ambienti Web. In alternativa, questa azione può essere eseguita usando un comando da terminale.', + 'maint_timeout_command_note' => 'Nota: Questa azione può richiedere del tempo per essere eseguita e può causare problemi di timeout in alcuni ambienti web. In alternativa, questa azione può essere eseguita usando un comando da terminale.', // Recycle Bin 'recycle_bin' => 'Cestino', 'recycle_bin_desc' => 'Qui è possibile ripristinare gli elementi che sono stati eliminati o scegliere di rimuoverli definitivamente dal sistema. Questo elenco non è filtrato a differenza di elenchi di attività simili nel sistema in cui vengono applicati i filtri autorizzazioni.', - 'recycle_bin_deleted_item' => 'Elimina Elemento', + 'recycle_bin_deleted_item' => 'Elemento eliminato', 'recycle_bin_deleted_parent' => 'Superiore', 'recycle_bin_deleted_by' => 'Cancellato da', 'recycle_bin_deleted_at' => 'Orario Cancellazione', - 'recycle_bin_permanently_delete' => 'Elimina Definitivamente', + 'recycle_bin_permanently_delete' => 'Elimina definitivamente', 'recycle_bin_restore' => 'Ripristina', 'recycle_bin_contents_empty' => 'Al momento il cestino è vuoto', 'recycle_bin_empty' => 'Svuota Cestino', 'recycle_bin_empty_confirm' => 'Questa operazione cancellerà definitivamente tutti gli elementi presenti nel cestino, inclusi i contenuti relativi a ciascun elemento. Sei sicuro di voler svuotare il cestino?', 'recycle_bin_destroy_confirm' => 'Questa azione eliminerà definitivamente questo elemento dal sistema, insieme a qualsiasi elemento figlio elencato di seguito, e non sarai in grado di ripristinare questo contenuto. Sei sicuro di voler eliminare definitivamente questo elemento?', - 'recycle_bin_destroy_list' => 'Elementi da Eliminare definitivamente', - 'recycle_bin_restore_list' => 'Elementi da Ripristinare', + 'recycle_bin_destroy_list' => 'Elementi da eliminare definitivamente', + 'recycle_bin_restore_list' => 'Elementi da ripristinare', 'recycle_bin_restore_confirm' => 'Questa azione ripristinerà l\'elemento eliminato, compresi gli elementi figli, nella loro posizione originale. Se la posizione originale è stata eliminata, ed è ora nel cestino, anche l\'elemento padre dovrà essere ripristinato.', 'recycle_bin_restore_deleted_parent' => 'L\'elemento padre di questo elemento è stato eliminato. Questo elemento rimarrà eliminato fino a che l\'elemento padre non sarà ripristinato.', 'recycle_bin_restore_parent' => 'Ripristina Superiore', @@ -121,13 +121,13 @@ return [ // Audit Log 'audit' => 'Registro di Controllo', 'audit_desc' => 'Questo registro di controllo mostra la lista delle attività registrate dal sistema. Questa lista, a differenza di altre liste del sistema a cui vengono applicate dei filtri, è integrale.', - 'audit_event_filter' => 'Filtra Eventi', - 'audit_event_filter_no_filter' => 'Nessun Filtro', - 'audit_deleted_item' => 'Elimina Elemento', + 'audit_event_filter' => 'Filtro eventi', + 'audit_event_filter_no_filter' => 'Nessun filtro', + 'audit_deleted_item' => 'Elemento eliminato', 'audit_deleted_item_name' => 'Nome: :name', 'audit_table_user' => 'Utente', 'audit_table_event' => 'Evento', - 'audit_table_related' => 'Elemento o Dettaglio correlato', + 'audit_table_related' => 'Elemento o dettaglio correlato', 'audit_table_ip' => 'Indirizzo IP', 'audit_table_date' => 'Data attività', 'audit_date_from' => 'Dalla data', @@ -139,89 +139,89 @@ return [ 'roles_index_desc' => 'I ruoli sono utilizzati per raggruppare gli utenti e fornire ai loro membri i permessi di sistema. Quando un utente è membro di più ruoli, i privilegi concessi si sovrappongono e l\'utente eredita tutte le abilità.', 'roles_x_users_assigned' => ':count utente assegnato|:count utenti assegnati', 'roles_x_permissions_provided' => ':count permesso|:count permessi', - 'roles_assigned_users' => 'Utenti Assegnati', + 'roles_assigned_users' => 'Utenti assegnati', 'roles_permissions_provided' => 'Autorizzazioni fornite', - 'role_create' => 'Crea Nuovo Ruolo', - 'role_delete' => 'Elimina Ruolo', + 'role_create' => 'Crea nuovo ruolo', + 'role_delete' => 'Elimina ruolo', 'role_delete_confirm' => 'Questo eliminerà il ruolo con il nome \':roleName\'.', 'role_delete_users_assigned' => 'Questo ruolo ha :userCount utenti assegnati. Se vuoi migrare gli utenti da questo ruolo selezionane uno nuovo sotto.', 'role_delete_no_migration' => "Non migrare gli utenti", 'role_delete_sure' => 'Sei sicuro di voler eliminare questo ruolo?', - 'role_edit' => 'Modifica Ruolo', - 'role_details' => 'Dettagli Ruolo', - 'role_name' => 'Nome Ruolo', - 'role_desc' => 'Breve Descrizione del Ruolo', + 'role_edit' => 'Modifica ruolo', + 'role_details' => 'Dettagli ruolo', + 'role_name' => 'Nome ruolo', + 'role_desc' => 'Breve descrizione del ruolo', 'role_mfa_enforced' => 'Richiesta autenticazione multi-fattore', - 'role_external_auth_id' => 'ID Autenticazione Esterna', - 'role_system' => 'Permessi di Sistema', + 'role_external_auth_id' => 'ID autenticazione esterna', + 'role_system' => 'Permessi di sistema', 'role_manage_users' => 'Gestire gli utenti', - 'role_manage_roles' => 'Gestire ruoli e permessi di essi', + 'role_manage_roles' => 'Gestire ruoli e permessi di ruoli', 'role_manage_entity_permissions' => 'Gestire tutti i permessi di libri, capitoli e pagine', 'role_manage_own_entity_permissions' => 'Gestire i permessi sui propri libri, capitoli e pagine', - 'role_manage_page_templates' => 'Gestisci modelli di pagina', - 'role_access_api' => 'API sistema d\'accesso', + 'role_manage_page_templates' => 'Gestire modelli di pagina', + 'role_access_api' => 'Accedere alle API di sistema', 'role_manage_settings' => 'Gestire impostazioni app', - 'role_export_content' => 'Esporta contenuto', - 'role_editor_change' => 'Cambia editor di pagina', - 'role_notifications' => 'Ricevi & gestisci le notifiche', - 'role_asset' => 'Permessi Entità', - 'roles_system_warning' => 'Siate consapevoli che l\'accesso a uno dei tre permessi qui sopra, può consentire a un utente di modificare i propri privilegi o i privilegi di altri nel sistema. Assegna ruoli con questi permessi solo ad utenti fidati.', - 'role_asset_desc' => 'Questi permessi controllano l\'accesso di default alle entità. I permessi nei Libri, Capitoli e Pagine sovrascriveranno questi.', + 'role_export_content' => 'Esportare contenuto', + 'role_editor_change' => 'Cambiare editor di pagina', + 'role_notifications' => 'Ricevere e gestire le notifiche', + 'role_asset' => 'Permessi entità', + 'roles_system_warning' => 'Siate consapevoli che l\'accesso a uno dei tre permessi qui sopra può consentire a un utente di modificare i propri privilegi o i privilegi di altri nel sistema. Assegna ruoli con questi permessi solo ad utenti fidati.', + 'role_asset_desc' => 'Questi permessi controllano l\'accesso predefinito alle entità. I permessi in libri, capitoli e pagine sovrascriveranno questi.', 'role_asset_admins' => 'Gli amministratori hanno automaticamente accesso a tutti i contenuti ma queste opzioni possono mostrare o nascondere le opzioni della UI.', - 'role_asset_image_view_note' => 'Questo si riferisce alla visibilità all\'interno del gestore di immagini. L\'accesso effettivo ai file di immagine caricati dipenderà dall\'opzione di archiviazione delle immagini di sistema.', + 'role_asset_image_view_note' => 'Questo si riferisce alla visibilità all\'interno del gestore delle immagini. L\'accesso effettivo ai file di immagine caricati dipenderà dall\'opzione di archiviazione delle immagini di sistema.', 'role_all' => 'Tutti', 'role_own' => 'Propri', 'role_controlled_by_asset' => 'Controllato dall\'entità in cui sono caricati', - 'role_save' => 'Salva Ruolo', + 'role_save' => 'Salva ruolo', 'role_users' => 'Utenti in questo ruolo', 'role_users_none' => 'Nessun utente assegnato a questo ruolo', // Users 'users' => 'Utenti', 'users_index_desc' => 'Crea e gestisci account utente individuali all\'interno del sistema. Gli account utente sono utilizzati per il login e l\'attribuzione di contenuti e attività. Le autorizzazioni di accesso sono principalmente basate sui ruoli, ma la proprietà dei contenuti dell\'utente, insieme ad altri fattori, può influenzare le autorizzazioni e l\'accesso.', - 'user_profile' => 'Profilo Utente', + 'user_profile' => 'Profilo utente', 'users_add_new' => 'Aggiungi Nuovo Utente', - 'users_search' => 'Cerca Utenti', - 'users_latest_activity' => 'Ultima Attività', - 'users_details' => 'Dettagli Utente', + 'users_search' => 'Cerca utenti', + 'users_latest_activity' => 'Ultima attività', + 'users_details' => 'Dettagli utente', 'users_details_desc' => 'Imposta un nome e un indirizzo email per questo utente. L\'indirizzo email verrà utilizzato per accedere all\'applicazione.', 'users_details_desc_no_email' => 'Imposta un nome per questo utente così gli altri possono riconoscerlo.', - 'users_role' => 'Ruoli Utente', + 'users_role' => 'Ruoli utente', 'users_role_desc' => 'Seleziona a quali ruoli verrà assegnato questo utente. Se un utente è assegnato a più ruoli riceverà tutte le abilità dei ruoli assegnati.', - 'users_password' => 'Password Utente', + 'users_password' => 'Password utente', 'users_password_desc' => 'Imposta una password usata per accedere all\'applicazione. Deve essere lunga almeno 8 caratteri.', 'users_send_invite_text' => 'Puoi scegliere di inviare a questo utente un\'email di invito che permette loro di impostare la propria password altrimenti puoi impostare la password tu stesso.', 'users_send_invite_option' => 'Invia email di invito', - 'users_external_auth_id' => 'ID Autenticazioni Esterna', + 'users_external_auth_id' => 'ID autenticazione esterna', 'users_external_auth_id_desc' => 'Quando è in uso un sistema di autenticazione esterno (come SAML2, OIDC o LDAP) questo è l\'ID che collega questo utente BookStack all\'account del sistema di autenticazione. È possibile ignorare questo campo se si utilizza l\'autenticazione predefinita basata su email.', 'users_password_warning' => 'Compila la parte sottostante solo se desideri cambiare la password per questo utente.', 'users_system_public' => 'Questo utente rappresente qualsiasi ospite che visita il sito. Non può essere usato per effettuare il login ma è assegnato automaticamente.', - 'users_delete' => 'Elimina Utente', + 'users_delete' => 'Elimina utente', 'users_delete_named' => 'Elimina l\'utente :userName', 'users_delete_warning' => 'Questo eliminerà completamente l\'utente \':userName\' dal sistema.', 'users_delete_confirm' => 'Sei sicuro di voler eliminare questo utente?', - 'users_migrate_ownership' => 'Cambia Proprietario', + 'users_migrate_ownership' => 'Cambia proprietario', 'users_migrate_ownership_desc' => 'Seleziona qui un utente se vuoi che un altro utente diventi il proprietario di tutti gli elementi attualmente di proprietà di questo utente.', 'users_none_selected' => 'Nessun utente selezionato', - 'users_edit' => 'Modifica Utente', - 'users_edit_profile' => 'Modifica Profilo', - 'users_avatar' => 'Avatar Utente', - 'users_avatar_desc' => 'Quest\'immagine dovrebbe essere approssimativamente 256px quadrata.', - 'users_preferred_language' => 'Lingua Preferita', + 'users_edit' => 'Modifica utente', + 'users_edit_profile' => 'Modifica profilo', + 'users_avatar' => 'Avatar utente', + 'users_avatar_desc' => 'Quest\'immagine dovrebbe essere quadrata e alta circa 256px.', + 'users_preferred_language' => 'Lingua preferita', 'users_preferred_language_desc' => 'Questa opzione cambierà la lingua utilizzata per l\'interfaccia utente dell\'applicazione. Questo non influirà su alcun contenuto creato dall\'utente.', - 'users_social_accounts' => 'Account Social', + 'users_social_accounts' => 'Account social', 'users_social_accounts_desc' => 'Visualizza lo stato degli account social connessi per questo utente. Gli account social possono essere utilizzati in aggiunta al sistema di autenticazione primaria per l\'accesso al sistema.', 'users_social_accounts_info' => 'Qui puoi connettere gli altri account per un accesso più veloce e semplice. Disconnettere un account qui non rimuoverà le altre sessioni. Revoca l\'accesso dal tuo profilo negli account social connessi.', - 'users_social_connect' => 'Connetti Account', - 'users_social_disconnect' => 'Disconnetti Account', + 'users_social_connect' => 'Connetti account', + 'users_social_disconnect' => 'Disconnetti account', 'users_social_status_connected' => 'Connesso', 'users_social_status_disconnected' => 'Disconnesso', 'users_social_connected' => 'L\'account :socialAccount è stato connesso correttamente al tuo profilo.', 'users_social_disconnected' => 'L\'account :socialAccount è stato disconnesso correttamente dal tuo profilo.', 'users_api_tokens' => 'Token API', - 'users_api_tokens_desc' => 'Creare e gestire i token di accesso utilizzati per autenticarsi con l\'API REST di BookStack. I permessi per l\'API sono gestiti tramite l\'utente a cui appartiene il token.', + 'users_api_tokens_desc' => 'Crea e gestisci i token di accesso utilizzati per autenticarsi con l\'API REST di BookStack. I permessi per l\'API sono gestiti tramite l\'utente a cui appartiene il token.', 'users_api_tokens_none' => 'Nessun token API è stato creato per questo utente', - 'users_api_tokens_create' => 'Crea Token', + 'users_api_tokens_create' => 'Crea token', 'users_api_tokens_expires' => 'Scade', 'users_api_tokens_docs' => 'Documentazione API', 'users_mfa' => 'Autenticazione multi-fattore', @@ -230,52 +230,60 @@ return [ 'users_mfa_configure' => 'Configura metodi', // API Tokens - 'user_api_token_create' => 'Crea Token API', + 'user_api_token_create' => 'Crea token API', 'user_api_token_name' => 'Nome', 'user_api_token_name_desc' => 'Assegna al tuo token un nome leggibile per ricordarne la funzionalità in futuro.', 'user_api_token_expiry' => 'Data di scadenza', 'user_api_token_expiry_desc' => 'Imposta una data di scadenza per questo token. Dopo questa data, le richieste che utilizzeranno questo token non funzioneranno più. Lasciando questo campo vuoto si imposterà la scadenza tra 100 anni.', - 'user_api_token_create_secret_message' => 'Immediatamente dopo aver creato questo token, un "Token ID" e un "Segreto Token" saranno generati e mostrati. Il segreto verrà mostrato unicamente questa volta, assicurati, quindi, di copiare il valore in un posto sicuro prima di procedere.', + 'user_api_token_create_secret_message' => 'Immediatamente dopo aver creato questo token, un "ID del Token" e una "Chiave segreta Token" saranno generati e mostrati. La chiave segreta verrà mostrata unicamente questa volta, assicurati, quindi, di copiare il valore in un posto sicuro prima di procedere.', 'user_api_token' => 'Token API', - 'user_api_token_id' => 'Token ID', + 'user_api_token_id' => 'ID del Token', 'user_api_token_id_desc' => 'Questo è un identificativo non modificabile generato dal sistema per questo token e che sarà necessario fornire per le richieste tramite API.', - 'user_api_token_secret' => 'Token Segreto', - 'user_api_token_secret_desc' => 'Questo è un segreto generato dal sistema per questo token che sarà necessario fornire per le richieste via API. Questo valore sarà visibile unicamente in questo momento pertanto copialo in un posto sicuro.', + 'user_api_token_secret' => 'Chiave segreta token', + 'user_api_token_secret_desc' => 'Questo è una chiave segreta generata dal sistema per questo token che sarà necessario fornire per le richieste via API. Questo valore sarà visibile unicamente in questo momento pertanto copialo in un posto sicuro.', 'user_api_token_created' => 'Token Aggiornato :timeAgo', - 'user_api_token_updated' => 'Token Aggiornato :timeAgo', - 'user_api_token_delete' => 'Elimina Token', + 'user_api_token_updated' => 'Token aggiornato :timeAgo', + 'user_api_token_delete' => 'Elimina token', 'user_api_token_delete_warning' => 'Questa operazione eliminerà irreversibilmente dal sistema il token API denominato \':tokenName\'.', 'user_api_token_delete_confirm' => 'Sei sicuri di voler eliminare questo token API?', // Webhooks - 'webhooks' => 'Webhooks', - 'webhooks_index_desc' => 'I webhook sono un modo per inviare dati a URL esterne quando si verificano determinate azioni ed eventi all\'interno del sistema, consentendo l\'integrazione basata sugli eventi con piattaforme esterne, come sistemi di messaggistica o di notifica.', + 'webhooks' => 'Webhook', + 'webhooks_index_desc' => 'I webhook sono un modo per inviare dati a URL esterni quando si verificano determinate azioni ed eventi all\'interno del sistema, consentendo l\'integrazione basata sugli eventi con piattaforme esterne, come sistemi di messaggistica o di notifica.', 'webhooks_x_trigger_events' => ':count evento trigger|:count eventi trigger', - 'webhooks_create' => 'Crea Nuovo Webhook', + 'webhooks_create' => 'Crea nuovo webhook', 'webhooks_none_created' => 'Nessun webhook è stato creato.', - 'webhooks_edit' => 'Modifica Webhook', - 'webhooks_save' => 'Salva Webhook', - 'webhooks_details' => 'Dettagli Webhook', - 'webhooks_details_desc' => 'Fornire un nome di facile utilizzo e un endpoint POST come posizione per i dati del webhook da inviare.', - 'webhooks_events' => 'Eventi Webhook', + 'webhooks_edit' => 'Modifica webhook', + 'webhooks_save' => 'Salva webhook', + 'webhooks_details' => 'Dettagli webhook', + 'webhooks_details_desc' => 'Fornisci un nome di facile utilizzo e un endpoint POST come posizione per i dati del webhook da inviare.', + 'webhooks_events' => 'Eventi webhook', 'webhooks_events_desc' => 'Seleziona tutti gli eventi che dovrebbero attivare questo webhook da chiamare.', - 'webhooks_events_warning' => 'Tieni presente che questi eventi saranno attivati per tutti gli eventi selezionati, anche se vengono applicati permessi personalizzati. Assicurarsi che l\'uso di questo webhook non esporrà contenuti riservati.', + 'webhooks_events_warning' => 'Tieni presente che questi eventi saranno attivati per tutti gli eventi selezionati, anche se vengono applicati permessi personalizzati. Assicurati che l\'uso di questo webhook non esporrà contenuti riservati.', 'webhooks_events_all' => 'Tutti gli eventi di sistema', - 'webhooks_name' => 'Nome Webhook', - 'webhooks_timeout' => 'Timeout Richiesta Webhook (Secondi)', - 'webhooks_endpoint' => 'Endpoint Webhook', - 'webhooks_active' => 'Webhook Attivo', + 'webhooks_name' => 'Nome webhook', + 'webhooks_timeout' => 'Timeout richiesta webhook (secondi)', + 'webhooks_endpoint' => 'Endpoint webhook', + 'webhooks_active' => 'Webhook attivo', 'webhook_events_table_header' => 'Eventi', - 'webhooks_delete' => 'Elimina Webhook', - 'webhooks_delete_warning' => 'Questo eliminerà completamente questo webhook, con il nome \':webhookName\', dal sistema.', + 'webhooks_delete' => 'Elimina webhook', + 'webhooks_delete_warning' => 'Questo eliminerà completamente questo webhook chiamato \':webhookName\' dal sistema.', 'webhooks_delete_confirm' => 'Sei sicuro di voler eliminare questo webhook?', - 'webhooks_format_example' => 'Esempio Di Formato Webhook', - 'webhooks_format_example_desc' => 'I dati Webhook vengono inviati come richiesta POST all\'endpoint configurato come JSON seguendo il formato sottostante. Le proprietà "related_item" e "url" sono opzionali e dipenderanno dal tipo di evento attivato.', - 'webhooks_status' => 'Stato Webhook', - 'webhooks_last_called' => 'Ultima Chiamata:', - 'webhooks_last_errored' => 'Ultimo Errore:', - 'webhooks_last_error_message' => 'Ultimo Messaggio Di Errore:', + 'webhooks_format_example' => 'Esempio di formato webhook', + 'webhooks_format_example_desc' => 'I dati del webhook vengono inviati come richiesta POST all\'endpoint configurato come JSON seguendo il formato sottostante. Le proprietà "related_item" e "url" sono opzionali e dipenderanno dal tipo di evento attivato.', + 'webhooks_status' => 'Stato webhook', + 'webhooks_last_called' => 'Ultima chiamata:', + 'webhooks_last_errored' => 'Ultimo errore:', + 'webhooks_last_error_message' => 'Ultimo messaggio di errore:', + // Licensing + 'licenses' => 'Licenze', + 'licenses_desc' => 'Questa pagina contiene informazioni dettagliate sulle licenze di BookStack, oltre ai progetti e alle librerie utilizzate all\'interno di BookStack. Molti dei progetti elencati possono essere utilizzati solo in un contesto di sviluppo.', + 'licenses_bookstack' => 'Licenza BookStack', + 'licenses_php' => 'Licenze Librerie PHP', + 'licenses_js' => 'Licenze Librerie JavaScript', + 'licenses_other' => 'Altre Licenze', + 'license_details' => 'Dettagli Licenza', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/it/validation.php b/lang/it/validation.php index a782986bf..f8f59a3ac 100644 --- a/lang/it/validation.php +++ b/lang/it/validation.php @@ -12,18 +12,18 @@ return [ 'active_url' => ':attribute non è uno URL valido.', 'after' => ':attribute deve essere una data dopo il :date.', 'alpha' => ':attribute deve contenere solo lettere.', - 'alpha_dash' => ':attribute deve contenere solo lettere, numeri e meno.', + 'alpha_dash' => ':attribute deve contenere solo lettere, numeri, trattini e trattini bassi.', 'alpha_num' => ':attribute deve contenere solo lettere e numeri.', 'array' => ':attribute deve essere un array.', 'backup_codes' => 'Il codice fornito non è valido o è già stato utilizzato.', 'before' => ':attribute deve essere una data prima del :date.', 'between' => [ 'numeric' => 'Il campo :attribute deve essere tra :min e :max.', - 'file' => 'Il campo :attribute deve essere tra :min e :max kilobytes.', + 'file' => 'Il campo :attribute deve essere tra :min e :max kilobyte.', 'string' => 'Il campo :attribute deve essere tra :min e :max caratteri.', - 'array' => 'Il campo :attribute deve essere tra :min e :max oggetti.', + 'array' => 'Il campo :attribute deve avere tra :min e :max oggetti.', ], - 'boolean' => ':attribute deve contenere vero o falso.', + 'boolean' => ':attribute deve essere vero o falso.', 'confirmed' => 'La conferma di :attribute non corrisponde.', 'date' => ':attribute non è una data valida.', 'date_format' => 'Il campo :attribute non corrisponde al formato :format.', @@ -36,17 +36,17 @@ return [ 'filled' => 'Il campo :attribute field is required.', 'gt' => [ 'numeric' => ':attribute deve essere maggiore di :value.', - 'file' => ':attribute deve essere maggiore di :value kilobytes.', + 'file' => ':attribute deve essere maggiore di :value kilobyte.', 'string' => ':attribute deve essere maggiore di :value caratteri.', 'array' => ':attribute deve avere più di :value elementi.', ], 'gte' => [ 'numeric' => ':attribute deve essere maggiore o uguale a :value.', - 'file' => ':attribute deve essere maggiore o uguale a :value kilobytes.', + 'file' => ':attribute deve essere maggiore o uguale a :value kilobyte.', 'string' => ':attribute deve essere maggiore o uguale a :value caratteri.', - 'array' => ':attribute deve avere :value elementi o più.', + 'array' => ':attribute deve avere :value o più elementi.', ], - 'exists' => 'Il campo :attribute non è valido.', + 'exists' => 'Il campo :attribute selezionato non è valido.', 'image' => 'Il campo :attribute deve essere un\'immagine.', 'image_extension' => ':attribute deve avere un\'estensione immagine valida e supportata.', 'in' => 'Il campo :attribute selezionato non è valido.', @@ -57,26 +57,26 @@ return [ 'json' => ':attribute deve essere una stringa JSON valida.', 'lt' => [ 'numeric' => ':attribute deve essere inferiore a :value.', - 'file' => ':attribute deve essere inferiore a :value kilobytes.', + 'file' => ':attribute deve essere inferiore a :value kilobyte.', 'string' => ':attribute deve essere inferiore a :value caratteri.', 'array' => ':attribute deve avere meno di :value elementi.', ], 'lte' => [ 'numeric' => ':attribute deve essere minore o uguale :value.', - 'file' => ':attribute deve essere minore o uguale a :value kilobytes.', + 'file' => ':attribute deve essere minore o uguale a :value kilobyte.', 'string' => ':attribute deve essere minore o uguale a :value caratteri.', 'array' => ':attribute non deve avere più di :value elementi.', ], 'max' => [ 'numeric' => 'Il campo :attribute non deve essere maggiore di :max.', - 'file' => 'Il campo :attribute non deve essere maggiore di :max kilobytes.', + 'file' => 'Il campo :attribute non deve essere maggiore di :max kilobyte.', 'string' => 'Il campo :attribute non deve essere maggiore di :max caratteri.', 'array' => 'Il campo :attribute non deve avere più di :max oggetti.', ], 'mimes' => 'Il campo :attribute deve essere: :values.', 'min' => [ 'numeric' => 'Il campo :attribute deve essere almeno :min.', - 'file' => 'Il campo :attribute deve essere almeno :min kilobytes.', + 'file' => 'Il campo :attribute deve essere almeno :min kilobyte.', 'string' => 'Il campo :attribute deve essere almeno :min caratteri.', 'array' => 'Il campo :attribute deve contenere almeno :min elementi.', ], @@ -94,14 +94,14 @@ return [ 'safe_url' => 'Il link inserito potrebbe non essere sicuro.', 'size' => [ 'numeric' => 'Il campo :attribute deve essere :size.', - 'file' => 'Il campo :attribute deve essere :size kilobytes.', + 'file' => 'Il campo :attribute deve essere :size kilobyte.', 'string' => 'Il campo :attribute deve essere di :size caratteri.', 'array' => 'Il campo :attribute deve contenere :size elementi.', ], 'string' => ':attribute deve essere una stringa.', 'timezone' => ':attribute deve essere una zona valida.', 'totp' => 'Il codice fornito non è valido o è scaduto.', - 'unique' => ':attribute è già preso.', + 'unique' => ':attribute è già usato.', 'url' => 'Il formato :attribute non è valido.', 'uploaded' => 'Il file non può essere caricato. Il server potrebbe non accettare file di questa dimensione.', diff --git a/lang/ja/preferences.php b/lang/ja/preferences.php index 0e5685260..0207596a9 100644 --- a/lang/ja/preferences.php +++ b/lang/ja/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => '設定を保存', 'notifications_update_success' => '通知設定を更新しました。', 'notifications_watched' => 'ウォッチ/通知無効 項目', - 'notifications_watched_desc' => ' 以下はカスタムウォッチの設定が適用されている項目です。 これらの設定を更新するには、項目を表示してサイドバーのウォッチオプションを参照してください。', + 'notifications_watched_desc' => '以下はカスタムウォッチの設定が適用されている項目です。 これらの設定を更新するには、項目を表示してサイドバーのウォッチオプションを参照してください。', 'auth' => 'アクセス & セキュリティ', 'auth_change_password' => 'パスワードの変更', diff --git a/lang/ja/settings.php b/lang/ja/settings.php index c88fa106a..9e992d480 100644 --- a/lang/ja/settings.php +++ b/lang/ja/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => '最後のエラー:', 'webhooks_last_error_message' => '最後のエラーのメッセージ:', + // Licensing + 'licenses' => 'ライセンス', + 'licenses_desc' => 'このページではBookStackとBookStackで使用されるプロジェクトやライブラリのライセンス情報を詳しく説明します。開発環境でのみ使用するものも多数含まれています。', + 'licenses_bookstack' => 'BookStack ライセンス', + 'licenses_php' => 'PHPライブラリライセンス', + 'licenses_js' => 'JavaScriptライブラリライセンス', + 'licenses_other' => 'その他のライセンス', + 'license_details' => 'ライセンス詳細', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/ka/preferences.php b/lang/ka/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/ka/preferences.php +++ b/lang/ka/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/ka/settings.php b/lang/ka/settings.php index 7b7f5d2a2..f4c84092c 100644 --- a/lang/ka/settings.php +++ b/lang/ka/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/ko/preferences.php b/lang/ko/preferences.php index ccc09e7a3..ded933923 100644 --- a/lang/ko/preferences.php +++ b/lang/ko/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => '환경설정 저장', 'notifications_update_success' => '알림 환경설정이 업데이트되었습니다!', 'notifications_watched' => '주시 및 무시한 항목', - 'notifications_watched_desc' => ' 아래는 사용자 지정 시계 환경설정이 적용된 항목입니다. 이러한 항목에 대한 환경설정을 업데이트하려면 해당 항목을 본 다음 사이드바에서 시계 옵션을 찾습니다.', + 'notifications_watched_desc' => '아래는 사용자 지정 시계 환경설정이 적용된 항목입니다. 이러한 항목에 대한 환경설정을 업데이트하려면 해당 항목을 본 다음 사이드바에서 시계 옵션을 찾습니다.', 'auth' => '액세스 및 보안', 'auth_change_password' => '패스워드 변경', diff --git a/lang/ko/settings.php b/lang/ko/settings.php index 70a15a5af..d52e5064f 100644 --- a/lang/ko/settings.php +++ b/lang/ko/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => '마지막 에러:', 'webhooks_last_error_message' => '마지막 에러 메시지:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/lt/common.php b/lang/lt/common.php index b4fd096d3..052b6cdec 100644 --- a/lang/lt/common.php +++ b/lang/lt/common.php @@ -6,7 +6,7 @@ return [ // Buttons 'cancel' => 'Atšaukti', - 'close' => 'Close', + 'close' => 'Uždaryti', 'confirm' => 'Patvirtinti', 'back' => 'Grįžti', 'save' => 'Išsaugoti', diff --git a/lang/lt/preferences.php b/lang/lt/preferences.php index 2b88f9671..5c38d191c 100644 --- a/lang/lt/preferences.php +++ b/lang/lt/preferences.php @@ -5,14 +5,14 @@ */ return [ - 'my_account' => 'My Account', + 'my_account' => 'Mano paskyra', 'shortcuts' => 'Shortcuts', 'shortcuts_interface' => 'UI Shortcut Preferences', 'shortcuts_toggle_desc' => 'Here you can enable or disable keyboard system interface shortcuts, used for navigation and actions.', 'shortcuts_customize_desc' => 'You can customize each of the shortcuts below. Just press your desired key combination after selecting the input for a shortcut.', 'shortcuts_toggle_label' => 'Keyboard shortcuts enabled', - 'shortcuts_section_navigation' => 'Navigation', + 'shortcuts_section_navigation' => 'Navigacija', 'shortcuts_section_actions' => 'Common Actions', 'shortcuts_save' => 'Save Shortcuts', 'shortcuts_overlay_desc' => 'Note: When shortcuts are enabled a helper overlay is available via pressing "?" which will highlight the available shortcuts for actions currently visible on the screen.', @@ -27,16 +27,16 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', - 'auth' => 'Access & Security', - 'auth_change_password' => 'Change Password', - 'auth_change_password_desc' => 'Change the password you use to log-in to the application. This must be at least 8 characters long.', - 'auth_change_password_success' => 'Password has been updated!', + 'auth' => 'Prieiga ir saugumas', + 'auth_change_password' => 'Pasikeisti slaptažodį', + 'auth_change_password_desc' => 'Pakeistas slaptažodis bus naudojamas prisijungti prie aplikacijos. Slaptažodis turi būti bent 8 simbolių ilgio.', + 'auth_change_password_success' => 'Slaptažodis atnaujintas!', - 'profile' => 'Profile Details', + 'profile' => 'Profilio informacija', 'profile_desc' => 'Manage the details of your account which represents you to other users, in addition to details that are used for communication and system personalisation.', - 'profile_view_public' => 'View Public Profile', + 'profile_view_public' => 'Rodyti viešąjį profilį', 'profile_name_desc' => 'Configure your display name which will be visible to other users in the system through the activity you perform, and content you own.', 'profile_email_desc' => 'This email will be used for notifications and, depending on active system authentication, system access.', 'profile_email_no_permission' => 'Unfortunately you don\'t have permission to change your email address. If you want to change this, you\'d need to ask an administrator to change this for you.', @@ -44,8 +44,8 @@ return [ 'profile_admin_options' => 'Administrator Options', 'profile_admin_options_desc' => 'Additional administrator-level options, like those to manage role assignments, can be found for your user account in the "Settings > Users" area of the application.', - 'delete_account' => 'Delete Account', - 'delete_my_account' => 'Delete My Account', + 'delete_account' => 'Ištrinti paskyrą', + 'delete_my_account' => 'Ištrinti mano paskyrą', 'delete_my_account_desc' => 'This will fully delete your user account from the system. You will not be able to recover this account or revert this action. Content you\'ve created, such as created pages and uploaded images, will remain.', 'delete_my_account_warning' => 'Are you sure you want to delete your account?', ]; diff --git a/lang/lt/settings.php b/lang/lt/settings.php index db985e9aa..cd7205140 100644 --- a/lang/lt/settings.php +++ b/lang/lt/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/lv/activities.php b/lang/lv/activities.php index b28295639..f7db090d8 100644 --- a/lang/lv/activities.php +++ b/lang/lv/activities.php @@ -93,11 +93,11 @@ return [ 'user_delete_notification' => 'Lietotājs veiksmīgi dzēsts', // API Tokens - 'api_token_create' => 'created API token', + 'api_token_create' => 'izveidoja API žetonu', 'api_token_create_notification' => 'API žetons veiksmīgi izveidots', - 'api_token_update' => 'updated API token', + 'api_token_update' => 'atjaunoja API žetonu', 'api_token_update_notification' => 'API žetons veiksmīgi atjaunināts', - 'api_token_delete' => 'deleted API token', + 'api_token_delete' => 'izdzēsa API žetonu', 'api_token_delete_notification' => 'API žetons veiksmīgi dzēsts', // Roles diff --git a/lang/lv/preferences.php b/lang/lv/preferences.php index ac820f61e..18def9f5c 100644 --- a/lang/lv/preferences.php +++ b/lang/lv/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Saglabāt iestatījumus', 'notifications_update_success' => 'Paziņojumu iestatījumi ir atjaunoti!', 'notifications_watched' => 'Vērotie un ignorētie vienumi', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Piekļuve un drošība', 'auth_change_password' => 'Mainīt paroli', diff --git a/lang/lv/settings.php b/lang/lv/settings.php index 53c764ed6..cb38482da 100644 --- a/lang/lv/settings.php +++ b/lang/lv/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Pedējoreiz kļūda:', 'webhooks_last_error_message' => 'Pēdējais kļūdas paziņojums:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/nb/preferences.php b/lang/nb/preferences.php index 502a34342..245c9c954 100644 --- a/lang/nb/preferences.php +++ b/lang/nb/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Lagre innstillinger', 'notifications_update_success' => 'Varslingsinnstillingene er oppdatert!', 'notifications_watched' => 'Overvåka & ignorerte elementer', - 'notifications_watched_desc' => ' Nedenfor er elementene som har egendefinerte varslingsinnstillinger i bruk. For å oppdatere innstillingene for disse, se elementet, finn varslingsalternativene i sidepanelet.', + 'notifications_watched_desc' => 'Nedenfor er elementene som har egendefinerte varslingsinnstillinger i bruk. For å oppdatere innstillingene for disse, se elementet, finn varslingsalternativene i sidepanelet.', 'auth' => 'Tilgang og sikkerhet', 'auth_change_password' => 'Endre passord', diff --git a/lang/nb/settings.php b/lang/nb/settings.php index f1f2adbe8..e426eca4a 100644 --- a/lang/nb/settings.php +++ b/lang/nb/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Siste feil:', 'webhooks_last_error_message' => 'Siste feilmelding:', + // Licensing + 'licenses' => 'Lisenser', + 'licenses_desc' => 'Denne siden detaljerer lisensinformasjonen for BookStack, i tillegg til prosjektene & bibliotekene som brukes i BookStack. Mange av de oppførte prosjektene kan bare brukes i utviklingssammenheng.', + 'licenses_bookstack' => 'BookStack lisens', + 'licenses_php' => 'PHP Bibliotek lisenser', + 'licenses_js' => 'JavaScript bibliotek-lisenser', + 'licenses_other' => 'Andre lisenser', + 'license_details' => 'Lisens detaljer', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/nl/auth.php b/lang/nl/auth.php index e81d31ccb..a0dc79ab1 100644 --- a/lang/nl/auth.php +++ b/lang/nl/auth.php @@ -40,7 +40,7 @@ return [ // Login auto-initiation 'auto_init_starting' => 'Poging tot inloggen', - 'auto_init_starting_desc' => 'We maken contact met uw authenticatiesysteem om het inlogproces te starten. Als er na 5 seconden geen vooruitgang is, kunt u proberen op de onderstaande link te klikken.', + 'auto_init_starting_desc' => 'We maken contact met jouw authenticatiesysteem om het inlogproces te starten. Als er na 5 seconden geen vooruitgang is, kun je proberen op de onderstaande link te klikken.', 'auto_init_start_link' => 'Ga verder met authenticatie', // Password Reset @@ -59,10 +59,10 @@ return [ 'email_confirm_text' => 'Bevestig je e-mailadres door op onderstaande knop te drukken:', 'email_confirm_action' => 'Bevestig je e-mail', 'email_confirm_send_error' => 'Een e-mailbevestiging is vereist, maar het systeem kon de e-mail niet verzenden. Neem contact op met de beheerder.', - 'email_confirm_success' => 'Uw e-mailadres is bevestigd! U zou nu moeten kunnen inloggen met dit e-mailadres.', + 'email_confirm_success' => 'Je e-mailadres is bevestigd! Je zou nu moeten kunnen inloggen met dit e-mailadres.', 'email_confirm_resent' => 'Bevestigingsmail opnieuw verzonden, controleer je inbox.', 'email_confirm_thanks' => 'Bedankt voor de bevestiging!', - 'email_confirm_thanks_desc' => 'Wacht even terwijl uw bevestiging wordt behandeld. Als u na 3 seconden niet wordt doorverwezen, drukt u op de onderstaande link "Doorgaan" om verder te gaan.', + 'email_confirm_thanks_desc' => 'Wacht even terwijl jouw bevestiging wordt behandeld. Als je na 3 seconden niet wordt doorverwezen, druk dan op de onderstaande link "Doorgaan" om verder te gaan.', 'email_not_confirmed' => 'E-mailadres nog niet bevestigd', 'email_not_confirmed_text' => 'Je e-mailadres is nog niet bevestigd.', @@ -78,40 +78,40 @@ return [ 'user_invite_page_welcome' => 'Welkom bij :appName!', 'user_invite_page_text' => 'Om je account af te ronden en toegang te krijgen moet je een wachtwoord instellen dat gebruikt wordt om in te loggen op :appName bij toekomstige bezoeken.', 'user_invite_page_confirm_button' => 'Bevestig wachtwoord', - 'user_invite_success_login' => 'Wachtwoord ingesteld, u zou nu moeten kunnen inloggen met uw ingestelde wachtwoord om toegang te krijgen tot :appName!', + 'user_invite_success_login' => 'Wachtwoord ingesteld, je zou nu moeten kunnen inloggen met je ingestelde wachtwoord om toegang te krijgen tot :appName!', // Multi-factor Authentication 'mfa_setup' => 'Multi-factor authenticatie instellen', - 'mfa_setup_desc' => 'Stel multi-factor authenticatie in als een extra beveiligingslaag voor uw gebruikersaccount.', + 'mfa_setup_desc' => 'Stel multi-factor authenticatie in als een extra beveiligingslaag voor je gebruikersaccount.', 'mfa_setup_configured' => 'Reeds geconfigureerd', 'mfa_setup_reconfigure' => 'Herconfigureren', 'mfa_setup_remove_confirmation' => 'Weet je zeker dat je deze multi-factor authenticatie methode wilt verwijderen?', 'mfa_setup_action' => 'Instellen', - 'mfa_backup_codes_usage_limit_warning' => 'U heeft minder dan 5 back-upcodes over. Genereer en sla een nieuwe set op voordat je geen codes meer hebt om te voorkomen dat je buiten je account wordt gesloten.', + 'mfa_backup_codes_usage_limit_warning' => 'Je hebt minder dan 5 back-upcodes over. Genereer en sla een nieuwe set op voordat je geen codes meer hebt om te voorkomen dat je buiten je account wordt gesloten.', 'mfa_option_totp_title' => 'Mobiele app', - 'mfa_option_totp_desc' => 'Om multi-factor authenticatie te gebruiken heeft u een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', + 'mfa_option_totp_desc' => 'Om multi-factor authenticatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', 'mfa_option_backup_codes_title' => 'Back-up Codes', - 'mfa_option_backup_codes_desc' => 'Bewaar veilig een set eenmalige back-upcodes die u kunt invoeren om uw identiteit te verifiëren.', + 'mfa_option_backup_codes_desc' => 'Bewaar veilig een set eenmalige back-upcodes die je kunt invoeren om je identiteit te verifiëren.', 'mfa_gen_confirm_and_enable' => 'Bevestigen en inschakelen', 'mfa_gen_backup_codes_title' => 'Back-up codes instellen', 'mfa_gen_backup_codes_desc' => 'Bewaar de onderstaande lijst met codes op een veilige plaats. Bij toegang tot het systeem kun je een van de codes gebruiken als tweede verificatiemechanisme.', 'mfa_gen_backup_codes_download' => 'Download Codes', 'mfa_gen_backup_codes_usage_warning' => 'Elke code kan slechts eenmaal gebruikt worden', 'mfa_gen_totp_title' => 'Mobiele app installatie', - 'mfa_gen_totp_desc' => 'Om multi-factor authenticatie te gebruiken heeft u een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', - 'mfa_gen_totp_scan' => 'Scan de onderstaande QR-code door gebruik te maken van uw favoriete authenticatie app om aan de slag te gaan.', + 'mfa_gen_totp_desc' => 'Om multi-factor authenticatie te gebruiken heb je een mobiele applicatie nodig die TOTP ondersteunt, zoals Google Authenticator, Authy of Microsoft Authenticator.', + 'mfa_gen_totp_scan' => 'Scan de onderstaande QR-code door gebruik te maken van je favoriete authenticatie-app om aan de slag te gaan.', 'mfa_gen_totp_verify_setup' => 'Installatie verifiëren', - 'mfa_gen_totp_verify_setup_desc' => 'Controleer of alles werkt door het invoeren van een code, die wordt gegenereerd binnen uw authenticatie-app, in het onderstaande invoerveld:', - 'mfa_gen_totp_provide_code_here' => 'Geef uw app gegenereerde code hier', + 'mfa_gen_totp_verify_setup_desc' => 'Controleer of alles werkt door het invoeren van een code, die wordt gegenereerd binnen je authenticatie-app, in het onderstaande invoerveld:', + 'mfa_gen_totp_provide_code_here' => 'Vul je app-gegenereerde code hier in', 'mfa_verify_access' => 'Verifieer toegang', - 'mfa_verify_access_desc' => 'Uw gebruikersaccount vereist dat u uw identiteit bevestigt via een extra verificatieniveau voordat u toegang krijgt. Verifieer met een van de door u geconfigureerde methoden om verder te gaan.', + 'mfa_verify_access_desc' => 'Je moet jouw identiteit bevestigen via een extra verificatieniveau voordat je toegang krijgt tot je gebruikersaccount. Verifieer met een van de door u geconfigureerde methoden om verder te gaan.', 'mfa_verify_no_methods' => 'Geen methode geconfigureerd', - 'mfa_verify_no_methods_desc' => 'Er konden geen meervoudige verificatie methoden voor uw account gevonden worden. Je zult minstens één methode moeten instellen voordat u toegang krijgt.', + 'mfa_verify_no_methods_desc' => 'Er konden geen meervoudige verificatie methoden voor je account gevonden worden. Je zult minstens één methode moeten instellen voordat je toegang krijgt.', 'mfa_verify_use_totp' => 'Verifieer met een mobiele app', 'mfa_verify_use_backup_codes' => 'Verifieer met een back-up code', 'mfa_verify_backup_code' => 'Back-up code', - 'mfa_verify_backup_code_desc' => 'Voer een van uw resterende back-up codes hieronder in:', + 'mfa_verify_backup_code_desc' => 'Voer één van je resterende back-up codes hieronder in:', 'mfa_verify_backup_code_enter_here' => 'Voer hier de back-up code in', - 'mfa_verify_totp_desc' => 'Voer de code, gegenereerd met uw mobiele app, hieronder in:', + 'mfa_verify_totp_desc' => 'Voer de code, gegenereerd met je mobiele app, hieronder in:', 'mfa_setup_login_notification' => 'Meervoudige verificatie methode geconfigureerd, Gelieve opnieuw in te loggen met de geconfigureerde methode.', ]; diff --git a/lang/nl/components.php b/lang/nl/components.php index 852a7ea85..a7fdc3725 100644 --- a/lang/nl/components.php +++ b/lang/nl/components.php @@ -23,7 +23,7 @@ return [ 'image_load_more' => 'Laad meer', 'image_image_name' => 'Afbeeldingsnaam', 'image_delete_used' => 'Deze afbeelding is op onderstaande pagina\'s in gebruik.', - 'image_delete_confirm_text' => 'Weet u zeker dat u deze afbeelding wilt verwijderen?', + 'image_delete_confirm_text' => 'Weet je zeker dat je deze afbeelding wilt verwijderen?', 'image_select_image' => 'Kies afbeelding', 'image_dropzone' => 'Sleep afbeeldingen naar hier of klik hier om te uploaden', 'image_dropzone_drop' => 'Sleep hier de afbeeldingen naar toe', diff --git a/lang/nl/editor.php b/lang/nl/editor.php index 4c20c8ea2..481f99ded 100644 --- a/lang/nl/editor.php +++ b/lang/nl/editor.php @@ -143,7 +143,7 @@ return [ 'source' => 'Bron', 'alt_desc' => 'Alternatieve beschrijving', 'embed' => 'Insluiten', - 'paste_embed' => 'Plak uw insluitcode hieronder:', + 'paste_embed' => 'Plak jouw insluitcode hieronder:', 'url' => 'URL', 'text_to_display' => 'Weer te geven tekst', 'title' => 'Titel', diff --git a/lang/nl/entities.php b/lang/nl/entities.php index 8236a6a8e..23e5c9750 100644 --- a/lang/nl/entities.php +++ b/lang/nl/entities.php @@ -104,7 +104,7 @@ return [ 'shelves_delete' => 'Verwijder Boekenplank', 'shelves_delete_named' => 'Verwijder Boekenplank :name', 'shelves_delete_explain' => "Dit zal de boekenplank met de naam ':naam' verwijderen. Boeken die op deze plank staan worden echter niet verwijderd.", - 'shelves_delete_confirmation' => 'Weet u zeker dat u deze boekenplank wilt verwijderen?', + 'shelves_delete_confirmation' => 'Weet je zeker dat je deze boekenplank wilt verwijderen?', 'shelves_permissions' => 'Boekenplank Machtigingen', 'shelves_permissions_updated' => 'Boekenplank Machtigingen Bijgewerkt', 'shelves_permissions_active' => 'Machtigingen op Boekenplank Actief', @@ -228,7 +228,7 @@ return [ '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_editor_switch_title' => 'Schakel Bewerker', - 'pages_editor_switch_are_you_sure' => 'Weet u zeker dat u de bewerker voor deze pagina wilt wijzigen?', + 'pages_editor_switch_are_you_sure' => 'Weet je zeker dat je de bewerker voor deze pagina wilt wijzigen?', 'pages_editor_switch_consider_following' => 'Houd rekening met het volgende als u van bewerker verandert:', 'pages_editor_switch_consideration_a' => 'Eenmaal opgeslagen, zal de nieuwe bewerker keuze gebruikt worden door alle toekomstige gebruikers, ook diegene die zelf niet van bewerker type kunnen veranderen.', 'pages_editor_switch_consideration_b' => 'Dit kan mogelijks tot een verlies van detail en syntax leiden in bepaalde omstandigheden.', @@ -244,7 +244,7 @@ return [ 'pages_md_show_preview' => 'Toon voorbeeld', 'pages_md_sync_scroll' => 'Synchroniseer scrollen van voorbeeld', 'pages_drawing_unsaved' => 'Niet-opgeslagen Tekening Gevonden', - 'pages_drawing_unsaved_confirm' => 'Er zijn niet-opgeslagen tekeninggegevens gevonden van een eerdere mislukte poging om de tekening op te slaan. Wilt u deze niet-opgeslagen tekening herstellen en verder bewerken?', + 'pages_drawing_unsaved_confirm' => 'Er zijn niet-opgeslagen tekeninggegevens gevonden van een eerdere mislukte poging om de tekening op te slaan. Wil je deze niet-opgeslagen tekening herstellen en verder bewerken?', 'pages_not_in_chapter' => 'Pagina is niet in een hoofdstuk', 'pages_move' => 'Pagina verplaatsten', 'pages_copy' => 'Pagina kopiëren', @@ -254,7 +254,7 @@ return [ 'pages_permissions_success' => 'Pagina machtigingen bijgewerkt', 'pages_revision' => 'Revisie', 'pages_revisions' => 'Pagina revisies', - 'pages_revisions_desc' => 'Hieronder staan alle vorige versies van deze pagina. U kunt oude paginaversies terugkijken, vergelijken en herstellen indien de rechten dit toelaten. De volledige geschiedenis van de pagina wordt hier mogelijk niet volledig weergegeven omdat, afhankelijk van de systeemconfiguratie, oude versies al automatisch verwijderd kunnen zijn.', + 'pages_revisions_desc' => 'Hieronder staan alle vorige versies van deze pagina. Je kunt oude paginaversies terugkijken, vergelijken en herstellen indien de rechten dit toelaten. De volledige geschiedenis van de pagina wordt hier mogelijk niet volledig weergegeven omdat, afhankelijk van de systeemconfiguratie, oude versies al automatisch verwijderd kunnen zijn.', 'pages_revisions_named' => 'Pagina revisies voor :pageName', 'pages_revision_named' => 'Pagina revisie voor :pageName', 'pages_revision_restored_from' => 'Hersteld van #:id; :samenvatting', @@ -284,7 +284,7 @@ return [ 'pages_references_update_revision' => 'Automatische systeemupdate van interne links', 'pages_initial_name' => 'Nieuwe pagina', 'pages_editing_draft_notification' => 'U bewerkt momenteel een concept dat voor het laatst is opgeslagen op :timeDiff.', - 'pages_draft_edited_notification' => 'Deze pagina is sindsdien bijgewerkt. Het wordt aanbevolen dat u dit concept verwijderd.', + 'pages_draft_edited_notification' => 'Deze pagina is sindsdien bijgewerkt. Het wordt aanbevolen dat je dit concept verwijderd.', 'pages_draft_page_changed_since_creation' => 'Deze pagina is bijgewerkt sinds het aanmaken van dit concept. Het wordt aanbevolen dat u dit concept verwijdert of ervoor zorgt dat u wijzigingen op de pagina niet overschrijft.', 'pages_draft_edit_active' => [ 'start_a' => ':count gebruikers zijn begonnen deze pagina te bewerken', @@ -309,7 +309,7 @@ return [ 'tags_index_desc' => 'Labels kunnen worden toegepast op inhoud binnen het systeem om een flexibele vorm van categorisering toe te passen. Labels kunnen zowel een sleutel als een waarde hebben, waarbij de waarde optioneel is. Eenmaal toegepast, kan de inhoud worden opgevraagd aan de hand van de naam en de waarde van het label.', 'tag_name' => 'Labelnaam', 'tag_value' => 'Labelwaarde (Optioneel)', - 'tags_explain' => "Voeg enkele labels toe om uw inhoud beter te categoriseren. \nJe kunt een waarde aan een label toekennen voor een meer gedetailleerde organisatie.", + 'tags_explain' => "Voeg enkele labels toe om jouw inhoud beter te categoriseren. \nJe kunt een waarde aan een label toekennen voor een meer gedetailleerde organisatie.", 'tags_add' => 'Voeg nog een label toe', 'tags_remove' => 'Verwijder deze label', 'tags_usages' => 'Totaal aantal label-toepassingen', @@ -327,9 +327,9 @@ return [ 'attachments_explain_instant_save' => 'Wijzigingen worden meteen opgeslagen.', 'attachments_upload' => 'Bestand uploaden', 'attachments_link' => 'Link toevoegen', - 'attachments_upload_drop' => 'Je kan ook een bestand hiernaartoe slepen om het als bijlage to uploaden.', + 'attachments_upload_drop' => 'Je kan ook een bestand hiernaartoe slepen om het als bijlage te uploaden.', 'attachments_set_link' => 'Zet link', - 'attachments_delete' => 'Weet u zeker dat u deze bijlage wilt verwijderen?', + 'attachments_delete' => 'Weet je zeker dat je deze bijlage wilt verwijderen?', 'attachments_dropzone' => 'Sleep hier de bestanden naar toe', 'attachments_no_files' => 'Er zijn geen bestanden geüpload', 'attachments_explain_link' => 'Je kunt een hyperlink toevoegen als je geen bestanden wilt uploaden. Dit kan een link naar een andere pagina op deze website zijn, maar ook een link naar een andere website.', @@ -382,8 +382,8 @@ return [ '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_delete_confirm' => 'Weet u zeker dat u deze revisie wilt verwijderen?', - 'revision_restore_confirm' => 'Weet u zeker dat u deze revisie wilt herstellen? De huidige pagina-inhoud wordt vervangen.', + 'revision_delete_confirm' => 'Weet je zeker dat je deze revisie wilt verwijderen?', + 'revision_restore_confirm' => 'Weet je zeker dat je deze revisie wilt herstellen? De huidige pagina-inhoud wordt vervangen.', 'revision_cannot_delete_latest' => 'Kan de laatste revisie niet verwijderen.', // Copy view @@ -396,7 +396,7 @@ return [ // Conversions 'convert_to_shelf' => 'Converteer naar Boekenplank', - 'convert_to_shelf_contents_desc' => 'U kunt dit boek converteren naar een nieuwe boekenplank met dezelfde inhoud. Hoofdstukken in dit boek zullen worden geconverteerd naar nieuwe boeken. Als dit boek pagina\'s bevat, die niet in een hoofdstuk staan, zal dit boek een nieuwe naam krijgen en deze pagina\'s bevatten, en zal dit boek deel gaan uitmaken van de nieuwe boekenplank.', + 'convert_to_shelf_contents_desc' => 'Je kunt dit boek converteren naar een nieuwe boekenplank met dezelfde inhoud. Hoofdstukken in dit boek zullen worden geconverteerd naar nieuwe boeken. Als dit boek pagina\'s bevat, die niet in een hoofdstuk staan, zal dit boek een nieuwe naam krijgen en deze pagina\'s bevatten, en zal dit boek deel gaan uitmaken van de nieuwe boekenplank.', 'convert_to_shelf_permissions_desc' => 'Elke machtiging ingesteld op dit boek zal gekopieerd worden naar de nieuwe boekenplank en naar alle nieuwe onderliggende boeken die geen eigen machtiging hebben afgedwongen. Merk op dat boekenplank-machtigingen niet automatisch overdragen naar inhoud binnenin de boekenplank, zoals dat wel gebeurd bij boeken.', 'convert_book' => 'Converteer Boek', 'convert_book_confirm' => 'Weet je zeker dat je dit boek wil converteren?', diff --git a/lang/nl/errors.php b/lang/nl/errors.php index ba39e0a69..74b14e08d 100644 --- a/lang/nl/errors.php +++ b/lang/nl/errors.php @@ -5,8 +5,8 @@ return [ // Permissions - 'permission' => 'U heeft geen machtiging om de gevraagde pagina te openen.', - 'permissionJson' => 'U heeft geen machtiging om de gevraagde actie uit te voeren.', + 'permission' => 'Je hebt geen machtiging om de gevraagde pagina te openen.', + 'permissionJson' => 'Je hebt geen machtiging om de gevraagde actie uit te voeren.', // Auth 'error_user_exists_different_creds' => 'Er bestaat al een gebruiker met het e-mailadres :email, maar met andere inloggegevens.', @@ -36,7 +36,7 @@ return [ 'social_account_register_instructions' => 'Als je nog geen account hebt, kun je je registreren met de :socialAccount optie.', 'social_driver_not_found' => 'Social driver niet gevonden', 'social_driver_not_configured' => 'Je :socialAccount instellingen zijn niet correct geconfigureerd.', - 'invite_token_expired' => 'Deze uitnodigingslink is verlopen. U kunt in plaats daarvan proberen uw wachtwoord opnieuw in te stellen.', + 'invite_token_expired' => 'Deze uitnodigingslink is verlopen. Je kunt in plaats daarvan proberen je wachtwoord opnieuw in te stellen.', // System 'path_not_writable' => 'Bestandspad :filePath kon niet naar geüpload worden. Zorg dat je schrijfrechten op de server hebt.', @@ -53,7 +53,7 @@ return [ 'image_upload_memory_limit' => 'Het uploaden van afbeeldingen en/of het maken van miniaturen is mislukt vanwege te beperkte systeemmiddelen.', 'image_thumbnail_memory_limit' => 'Het maken van variaties in afbeeldingsgrootte is mislukt vanwege te beperkte systeemmiddelen.', 'image_gallery_thumbnail_memory_limit' => 'Het maken van galerij miniaturen is mislukt vanwege te beperkte systeemmiddelen.', - 'drawing_data_not_found' => 'De gegevens van de tekening konden niet worden geladen. Het tekenbestand bestaat misschien niet meer of u hebt geen machtiging om het te openen.', + 'drawing_data_not_found' => 'De gegevens van de tekening konden niet worden geladen. Het tekenbestand bestaat misschien niet meer of je hebt geen machtiging om het te openen.', // Attachments 'attachment_not_found' => 'Bijlage niet gevonden', @@ -86,7 +86,7 @@ return [ // Comments 'comment_list' => 'Er is een fout opgetreden tijdens het ophalen van de reacties.', - 'cannot_add_comment_to_draft' => 'U kunt geen reacties toevoegen aan een concept.', + 'cannot_add_comment_to_draft' => 'Je kunt geen reacties toevoegen aan een concept.', 'comment_add' => 'Er is een fout opgetreden tijdens het aanpassen / toevoegen van de reactie.', 'comment_delete' => 'Er is een fout opgetreden tijdens het verwijderen van de reactie.', 'empty_comment' => 'Kan geen lege reactie toevoegen.', @@ -94,10 +94,10 @@ return [ // Error pages '404_page_not_found' => 'Pagina Niet Gevonden', 'sorry_page_not_found' => 'Sorry, de pagina die je zocht kan niet gevonden worden.', - 'sorry_page_not_found_permission_warning' => 'Als u verwachtte dat deze pagina zou bestaan, hebt u misschien geen machtiging om deze te bekijken.', + 'sorry_page_not_found_permission_warning' => 'Als je verwachtte dat deze pagina zou bestaan, heb je misschien geen machtiging om deze te bekijken.', 'image_not_found' => 'Afbeelding niet gevonden', 'image_not_found_subtitle' => 'Sorry, de afbeelding die je zocht is niet beschikbaar.', - 'image_not_found_details' => 'Als u verwachtte dat deze afbeelding zou bestaan, dan is deze misschien verwijderd.', + 'image_not_found_details' => 'Als je verwachtte dat deze afbeelding zou bestaan, dan is deze misschien verwijderd.', 'return_home' => 'Terug naar home', 'error_occurred' => 'Er Ging Iets Fout', 'app_down' => ':appName is nu niet beschikbaar', diff --git a/lang/nl/notifications.php b/lang/nl/notifications.php index 79c7e7e8b..bc5f380c3 100644 --- a/lang/nl/notifications.php +++ b/lang/nl/notifications.php @@ -22,6 +22,6 @@ return [ 'action_view_comment' => 'Bekijk Opmerking', 'action_view_page' => 'Bekijk Pagina', - 'footer_reason' => 'Deze melding is naar u verzonden omdat :link dit type activiteit voor dit artikel dekt.', + 'footer_reason' => 'Deze melding is naar je verzonden omdat :link dit type activiteit voor dit artikel dekt.', 'footer_reason_link' => 'je meldingsvoorkeuren', ]; diff --git a/lang/nl/passwords.php b/lang/nl/passwords.php index 1f1d71925..1781256f2 100644 --- a/lang/nl/passwords.php +++ b/lang/nl/passwords.php @@ -8,7 +8,7 @@ return [ 'password' => 'Wachtwoorden moeten uit ten minste acht tekens bestaan en overeenkomen met de bevestiging.', 'user' => "We kunnen niemand vinden met dat e-mailadres.", - 'token' => 'Het wachtwoord reset token is ongeldig voor dit e-mailadres.', + 'token' => 'De wachtwoord reset token is ongeldig voor dit e-mailadres.', 'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!', 'reset' => 'Je wachtwoord is hersteld!', diff --git a/lang/nl/preferences.php b/lang/nl/preferences.php index 41ed3c547..5e385276c 100644 --- a/lang/nl/preferences.php +++ b/lang/nl/preferences.php @@ -9,8 +9,8 @@ return [ 'shortcuts' => 'Snelkoppelingen', 'shortcuts_interface' => 'Snelkoppelingen', - 'shortcuts_toggle_desc' => 'Hier kunt u toetscombinaties voor de gebruikersinterface in- of uitschakelen voor navigatie en acties.', - 'shortcuts_customize_desc' => 'U kunt elk van de onderstaande toetsencombinaties aanpassen. Druk simpelweg op de gewenste toetscombinatie na het selecteren van de invoer voor een toetscombinatie.', + 'shortcuts_toggle_desc' => 'Hier kun je toetscombinaties voor de gebruikersinterface in- of uitschakelen voor navigatie en acties.', + 'shortcuts_customize_desc' => 'Je kunt elk van de onderstaande toetsencombinaties aanpassen. Druk simpelweg op de gewenste toetscombinatie na het selecteren van de invoer voor een toetscombinatie.', 'shortcuts_toggle_label' => 'Toetsencombinaties ingeschakeld', 'shortcuts_section_navigation' => 'Navigatie', 'shortcuts_section_actions' => 'Gebruikelijke acties', @@ -27,11 +27,11 @@ return [ 'notifications_save' => 'Voorkeuren opslaan', 'notifications_update_success' => 'Voorkeuren voor meldingen zijn bijgewerkt!', 'notifications_watched' => 'Gevolgde & Genegeerde Items', - 'notifications_watched_desc' => ' Hieronder staan de items waarvoor aangepaste \'Volg\'-voorkeuren zijn toegepast. Om je voorkeuren voor deze items bij te werken, bekijk je het item en zoek je naar de \'Volg\' opties in de zijbalk.', + 'notifications_watched_desc' => 'Hieronder staan de items waarvoor aangepaste \'Volg\'-voorkeuren zijn toegepast. Om je voorkeuren voor deze items bij te werken, bekijk je het item en zoek je naar de \'Volg\' opties in de zijbalk.', 'auth' => 'Toegang & Beveiliging', 'auth_change_password' => 'Wachtwoord Wijzigen', - 'auth_change_password_desc' => 'Wijzig hier je wachtwoord om in te loggen op de applicatie. Minstens 8 tekens gebruiken.', + 'auth_change_password_desc' => 'Wijzig hier je wachtwoord die je gebruikt om in te loggen op de applicatie. Gebruik minimaal 8 tekens.', 'auth_change_password_success' => 'Wachtwoord is bijgewerkt!', 'profile' => 'Profielgegevens', diff --git a/lang/nl/settings.php b/lang/nl/settings.php index 340d1d899..828036c1b 100644 --- a/lang/nl/settings.php +++ b/lang/nl/settings.php @@ -39,7 +39,7 @@ return [ 'app_homepage_desc' => 'Selecteer een weergave om weer te geven op de startpagina in plaats van de standaard weergave. Paginamachtigingen worden genegeerd voor geselecteerde pagina\'s.', 'app_homepage_select' => 'Selecteer een pagina', 'app_footer_links' => 'Voettekst hyperlinks', - 'app_footer_links_desc' => 'Voeg hyperlinks toe aan de voettekst van de applicatie. Deze zullen onderaan de meeste pagina\'s getoond worden, ook aan pagina\'s die geen login vereisen. U kunt een label van "trans::" gebruiken om systeem-gedefinieerde vertalingen te gebruiken. Bijvoorbeeld: Het gebruik van "trans::common.privacy_policy" zal de vertaalde tekst "Privacy Policy" opleveren en "trans::common.terms_of_service" zal de vertaalde tekst "Gebruiksvoorwaarden" opleveren.', + 'app_footer_links_desc' => 'Voeg hyperlinks toe aan de voettekst van de applicatie. Deze zullen onderaan de meeste pagina\'s getoond worden, ook aan pagina\'s die geen login vereisen. Je kunt een label van "trans::" gebruiken om systeem-gedefinieerde vertalingen te gebruiken. Bijvoorbeeld: Het gebruik van "trans::common.privacy_policy" zal de vertaalde tekst "Privacy Policy" opleveren en "trans::common.terms_of_service" zal de vertaalde tekst "Gebruiksvoorwaarden" opleveren.', 'app_footer_links_label' => 'Link label', 'app_footer_links_url' => 'Link URL', 'app_footer_links_add' => 'Voettekst link toevoegen', @@ -80,7 +80,7 @@ return [ 'maint_image_cleanup_desc' => 'Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database- en afbeelding back-up maakt voordat je dit uitvoert.', 'maint_delete_images_only_in_revisions' => 'Ook afbeeldingen verwijderen die alleen in oude pagina revisies bestaan', 'maint_image_cleanup_run' => 'Opschonen uitvoeren', - 'maint_image_cleanup_warning' => ':count potentieel ongebruikte afbeeldingen gevonden. Weet u zeker dat u deze afbeeldingen wilt verwijderen?', + 'maint_image_cleanup_warning' => ':count potentieel ongebruikte afbeeldingen gevonden. Weet je zeker dat je deze afbeeldingen wilt verwijderen?', 'maint_image_cleanup_success' => ':count potentieel ongebruikte afbeeldingen gevonden en verwijderd!', 'maint_image_cleanup_nothing_found' => 'Geen ongebruikte afbeeldingen gevonden, niets verwijderd!', 'maint_send_test_email' => 'Stuur een test e-mail', @@ -99,7 +99,7 @@ return [ // Recycle Bin 'recycle_bin' => 'Prullenbak', - 'recycle_bin_desc' => 'Hier kunt u items herstellen die zijn verwijderd of ervoor kiezen om ze permanent uit het systeem te verwijderen. Deze lijst is ongefilterd, in tegenstelling tot vergelijkbare activiteitenlijsten in het systeem waar machtigingenfilters worden toegepast.', + 'recycle_bin_desc' => 'Hier kun je items herstellen die zijn verwijderd of ervoor kiezen om ze permanent uit het systeem te verwijderen. Deze lijst is ongefilterd, in tegenstelling tot vergelijkbare activiteitenlijsten in het systeem waar machtigingenfilters worden toegepast.', 'recycle_bin_deleted_item' => 'Verwijderde Item', 'recycle_bin_deleted_parent' => 'Bovenliggende', 'recycle_bin_deleted_by' => 'Verwijderd door', @@ -108,7 +108,7 @@ return [ 'recycle_bin_restore' => 'Herstellen', 'recycle_bin_contents_empty' => 'De prullenbak is momenteel leeg', 'recycle_bin_empty' => 'Prullenbak legen', - 'recycle_bin_empty_confirm' => 'Dit zal permanent alle items in de prullenbak vernietigen, inclusief de inhoud die in elk item zit. Weet u zeker dat u de prullenbak wilt legen?', + 'recycle_bin_empty_confirm' => 'Dit zal permanent alle items in de prullenbak vernietigen, inclusief de inhoud die in elk item zit. Weet je zeker dat je de prullenbak wil legen?', 'recycle_bin_destroy_confirm' => 'Deze actie zal dit item permanent verwijderen uit het systeem, samen met onderstaande onderliggende elementen, en u zal deze inhoud niet kunnen herstellen. Bent u zeker dat u dit item permanent wilt verwijderen?', 'recycle_bin_destroy_list' => 'Te vernietigen items', 'recycle_bin_restore_list' => 'Items te herstellen', @@ -190,7 +190,7 @@ return [ 'users_role_desc' => 'Selecteer aan welke rollen deze gebruiker zal worden toegewezen. Als een gebruiker aan meerdere rollen wordt toegewezen, worden de machtigingen van die rollen samengevoegd en krijgt hij alle mogelijkheden van de toegewezen rollen.', 'users_password' => 'Wachtwoord gebruiker', 'users_password_desc' => 'Stel een wachtwoord in om op de applicatie in te loggen. Dit moet minstens 8 tekens lang zijn.', - 'users_send_invite_text' => 'U kunt ervoor kiezen om deze gebruiker een uitnodigingsmail te sturen waarmee hij zijn eigen wachtwoord kan instellen, anders kunt u zelf zijn wachtwoord instellen.', + 'users_send_invite_text' => 'Je kunt ervoor kiezen om deze gebruiker een uitnodigingsmail te sturen waarmee hij zijn eigen wachtwoord kan instellen, anders kun je zelf zijn wachtwoord instellen.', 'users_send_invite_option' => 'Stuur gebruiker uitnodigings e-mail', 'users_external_auth_id' => 'Externe authenticatie ID', 'users_external_auth_id_desc' => 'Wanneer een extern authenticatiesysteem wordt gebruikt (zoals SAML2, OIDC of LDAP) is dit de ID die deze BookStack-gebruiker koppelt aan het account van het authenticatiesysteem. Je kunt dit veld negeren als je de standaard op e-mail gebaseerde verificatie gebruikt.', @@ -211,7 +211,7 @@ return [ 'users_preferred_language_desc' => 'Deze optie wijzigt de taal die gebruikt wordt voor de gebruikersinterface. Dit heeft geen invloed op door gebruiker gemaakte inhoud.', 'users_social_accounts' => 'Sociale media accounts', 'users_social_accounts_desc' => 'Bekijk de status van de verbonden socialmedia-accounts voor deze gebruiker. socialmedia-accounts kunnen worden gebruikt naast het primaire authenticatiesysteem voor systeemtoegang.', - 'users_social_accounts_info' => 'Hier kunt u uw andere accounts koppelen om sneller en eenvoudiger in te loggen. Als u hier een account loskoppelt, wordt de eerder gemachtigde toegang niet ingetrokken. U kunt de toegang intrekken via uw profielinstellingen op het gekoppelde socialemedia-account zelf.', + 'users_social_accounts_info' => 'Hier kun je je andere accounts koppelen om sneller en eenvoudiger in te loggen. Als je hier een account loskoppelt, wordt de eerder gemachtigde toegang niet ingetrokken. Je kunt de toegang intrekken via je profielinstellingen op het gekoppelde socialemedia-account zelf.', 'users_social_connect' => 'Account Verbinden', 'users_social_disconnect' => 'Account Ontkoppelen', 'users_social_status_connected' => 'Verbonden', @@ -225,7 +225,7 @@ return [ 'users_api_tokens_expires' => 'Verloopt', 'users_api_tokens_docs' => 'API-Documentatie', 'users_mfa' => 'Meervoudige Verificatie', - 'users_mfa_desc' => 'Stel meervoudige verificatie in als extra beveiligingslaag voor uw gebruikersaccount.', + 'users_mfa_desc' => 'Stel meervoudige verificatie in als extra beveiligingslaag voor je gebruikersaccount.', 'users_mfa_x_methods' => ':count methode geconfigureerd|:count methoden geconfigureerd', 'users_mfa_configure' => 'Configureer methoden', @@ -245,7 +245,7 @@ return [ 'user_api_token_updated' => 'Token :timeAgo geleden bijgewerkt', 'user_api_token_delete' => 'Token Verwijderen', 'user_api_token_delete_warning' => 'Dit zal de API-token met de naam \':tokenName\' volledig uit het systeem verwijderen.', - 'user_api_token_delete_confirm' => 'Weet u zeker dat u deze API-token wilt verwijderen?', + 'user_api_token_delete_confirm' => 'Weet je zeker dat je deze API-token wilt verwijderen?', // Webhooks 'webhooks' => 'Webhooks', @@ -268,7 +268,7 @@ return [ 'webhook_events_table_header' => 'Gebeurtenissen', 'webhooks_delete' => 'Verwijder Webhook', 'webhooks_delete_warning' => 'Dit zal de webhook met naam \':webhookName\' volledig verwijderen van het systeem.', - 'webhooks_delete_confirm' => 'Weet u zeker dat u deze webhook wil verwijderen?', + 'webhooks_delete_confirm' => 'Weet je zeker dat je deze webhook wilt verwijderen?', 'webhooks_format_example' => 'Voorbeeld Webhook Formaat', 'webhooks_format_example_desc' => 'Webhook gegevens worden verzonden als een POST verzoek naar het geconfigureerde eindpunt als JSON volgens het onderstaande formaat. De "related_item" en "url" eigenschappen zijn optioneel en hangen af van het type gebeurtenis die geactiveerd wordt.', 'webhooks_status' => 'Webhook Status', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Laatst Gefaald:', 'webhooks_last_error_message' => 'Laatste Foutmelding:', + // Licensing + 'licenses' => 'Licenties', + 'licenses_desc' => 'Deze pagina beschrijft licentie-informatie voor BookStack naast de projecten & bibliotheken die binnen BookStack worden gebruikt. Veel van de vermelde projecten worden alleen in een ontwikkelingscontext gebruikt.', + 'licenses_bookstack' => 'BookStack Licentie', + 'licenses_php' => 'PHP Bibliotheek Licenties', + 'licenses_js' => 'JavaScript Bibliotheek Licenties', + 'licenses_other' => 'Andere Licenties', + 'license_details' => 'Licentie Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/nn/preferences.php b/lang/nn/preferences.php index 4e6e6c1ff..ac6dc1b77 100644 --- a/lang/nn/preferences.php +++ b/lang/nn/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Lagre innstillinger', 'notifications_update_success' => 'Varslingsinnstillingene er oppdatert!', 'notifications_watched' => 'Overvåka & ignorerte elementer', - 'notifications_watched_desc' => ' Nedenfor er elementene som har egendefinerte varslingsinnstillinger i bruk. For å oppdatere innstillingene for disse, se elementet, finn varslingsalternativene i sidepanelet.', + 'notifications_watched_desc' => 'Nedenfor er elementene som har egendefinerte varslingsinnstillinger i bruk. For å oppdatere innstillingene for disse, se elementet, finn varslingsalternativene i sidepanelet.', 'auth' => 'Tilgang og tryggleik', 'auth_change_password' => 'Endre passord', diff --git a/lang/nn/settings.php b/lang/nn/settings.php index ba8586ce2..df5399f90 100644 --- a/lang/nn/settings.php +++ b/lang/nn/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Siste feil:', 'webhooks_last_error_message' => 'Siste feilmelding:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/pl/activities.php b/lang/pl/activities.php index fffb5499e..25f9e23c6 100644 --- a/lang/pl/activities.php +++ b/lang/pl/activities.php @@ -93,11 +93,11 @@ return [ 'user_delete_notification' => 'Użytkownik pomyślnie usunięty', // API Tokens - 'api_token_create' => 'created API token', + 'api_token_create' => 'utworzył token API', 'api_token_create_notification' => 'Token API został poprawnie utworzony', - 'api_token_update' => 'updated API token', + 'api_token_update' => 'zaktualizował token API', 'api_token_update_notification' => 'Token API został pomyślnie zaktualizowany', - 'api_token_delete' => 'deleted API token', + 'api_token_delete' => 'usunął token API', 'api_token_delete_notification' => 'Token API został pomyślnie usunięty', // Roles diff --git a/lang/pl/common.php b/lang/pl/common.php index 2c176ff94..e3feb2f02 100644 --- a/lang/pl/common.php +++ b/lang/pl/common.php @@ -20,7 +20,7 @@ return [ 'description' => 'Opis', 'role' => 'Rola', 'cover_image' => 'Okładka', - 'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.', + 'cover_image_description' => 'Ten obraz powinien być o rozmiarze około 440x250px, chociaż zostanie elastycznie przeskalowany i przycięty, aby dopasować interfejs użytkownika do różnych scenariuszy w zależności od potrzeb, więc faktyczne wymiary wyświetlania będą się różnić.', // Actions 'actions' => 'Akcje', diff --git a/lang/pl/editor.php b/lang/pl/editor.php index ca18521c2..f4ed4b5f2 100644 --- a/lang/pl/editor.php +++ b/lang/pl/editor.php @@ -81,9 +81,9 @@ return [ 'table_properties' => 'Właściwości tabeli', 'table_properties_title' => 'Właściwości Tabeli', 'delete_table' => 'Usuń tabelę', - 'table_clear_formatting' => 'Clear table formatting', - 'resize_to_contents' => 'Resize to contents', - 'row_header' => 'Row header', + 'table_clear_formatting' => 'Wyczyść formatowanie tabeli', + 'resize_to_contents' => 'Dostosuj rozmiar do zawartości', + 'row_header' => 'Wiersz nagłówka', 'insert_row_before' => 'Wstaw wiersz przed', 'insert_row_after' => 'Wstaw wiersz za', 'delete_row' => 'Usuń wiersz', diff --git a/lang/pl/entities.php b/lang/pl/entities.php index b178f680f..b99de72be 100644 --- a/lang/pl/entities.php +++ b/lang/pl/entities.php @@ -23,7 +23,7 @@ return [ 'meta_updated' => 'Zaktualizowano :timeLength', 'meta_updated_name' => 'Zaktualizowano :timeLength przez :user', 'meta_owned_name' => 'Właściciel: :user', - 'meta_reference_count' => 'Referenced by :count item|Referenced by :count items', + 'meta_reference_count' => 'Odniesienie w :count elemencie|Odniesienia w :count elementach', 'entity_select' => 'Wybór obiektu', 'entity_select_lack_permission' => 'Nie masz wymaganych uprawnień do wybrania tej pozycji', 'images' => 'Obrazki', @@ -39,9 +39,9 @@ return [ 'export_pdf' => 'Plik PDF', 'export_text' => 'Plik tekstowy', 'export_md' => 'Pliki Markdown', - 'default_template' => 'Default Page Template', - 'default_template_explain' => 'Assign a page template that will be used as the default content for all pages created within this item. Keep in mind this will only be used if the page creator has view access to the chosen template page.', - 'default_template_select' => 'Select a template page', + 'default_template' => 'Domyślny szablon strony', + 'default_template_explain' => 'Przypisz szablon strony, który będzie używany jako domyślna zawartość dla wszystkich stron utworzonych w tym elemencie. Pamiętaj, że będzie to używane tylko wtedy, gdy twórca strony ma dostęp do wybranej strony szablonu.', + 'default_template_select' => 'Wybierz stronę szablonu', // Permissions and restrictions 'permissions' => 'Uprawnienia', @@ -207,7 +207,7 @@ return [ 'pages_delete_draft' => 'Usuń wersje roboczą', 'pages_delete_success' => 'Strona usunięta pomyślnie', 'pages_delete_draft_success' => 'Werjsa robocza usunięta pomyślnie', - 'pages_delete_warning_template' => 'This page is in active use as a book or chapter default page template. These books or chapters will no longer have a default page template assigned after this page is deleted.', + 'pages_delete_warning_template' => 'Ta strona jest aktualnie używana jako domyślny szablon strony książki lub rozdziału. Po usunięciu tej strony te książki lub rozdziały nie będą już miały przypisanego domyślnego szablonu strony.', 'pages_delete_confirm' => 'Czy na pewno chcesz usunąć tę stronę?', 'pages_delete_draft_confirm' => 'Czy na pewno chcesz usunąć wersje roboczą strony?', 'pages_editing_named' => 'Edytowanie strony :pageName', @@ -409,7 +409,7 @@ return [ // References 'references' => 'Odniesienia', 'references_none' => 'Brak śledzonych odwołań do tego elementu.', - 'references_to_desc' => 'Listed below is all the known content in the system that links to this item.', + 'references_to_desc' => 'Wymienione poniżej są wszystkie znane treści w systemie, które nawiązują do tego elementu.', // Watch Options 'watch' => 'Obserwuj', diff --git a/lang/pl/errors.php b/lang/pl/errors.php index eb7435424..8b1ae1608 100644 --- a/lang/pl/errors.php +++ b/lang/pl/errors.php @@ -10,7 +10,7 @@ return [ // Auth 'error_user_exists_different_creds' => 'Użytkownik o adresie :email już istnieje, ale używa innych poświadczeń.', - 'auth_pre_register_theme_prevention' => 'User account could not be registered for the provided details', + 'auth_pre_register_theme_prevention' => 'Konto użytkownika nie może być zarejestrowane z podanymi danymi', 'email_already_confirmed' => 'E-mail został potwierdzony, spróbuj się zalogować.', 'email_confirmation_invalid' => 'Ten token jest nieprawidłowy lub został już wykorzystany. Spróbuj zarejestrować się ponownie.', 'email_confirmation_expired' => 'Ten token potwierdzający wygasł. Wysłaliśmy Ci kolejny.', diff --git a/lang/pl/preferences.php b/lang/pl/preferences.php index 6d67dc1b3..dd3482102 100644 --- a/lang/pl/preferences.php +++ b/lang/pl/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Zapisz preferencje', 'notifications_update_success' => 'Preferencje powiadomień zostały zaktualizowane!', 'notifications_watched' => 'Obserwowane i ignorowane elementy', - 'notifications_watched_desc' => ' Poniżej znajdują się elementy, które mają własne preferencje obserwowania. Aby zaktualizować swoje preferencje, zobacz dany element, a następnie znajdź opcje obserwowania na pasku bocznym.', + 'notifications_watched_desc' => 'Poniżej znajdują się elementy, które mają własne preferencje obserwowania. Aby zaktualizować swoje preferencje, zobacz dany element, a następnie znajdź opcje obserwowania na pasku bocznym.', 'auth' => 'Dostęp i bezpieczeństwo', 'auth_change_password' => 'Zmień hasło', diff --git a/lang/pl/settings.php b/lang/pl/settings.php index 295bb5dd9..89bbba377 100644 --- a/lang/pl/settings.php +++ b/lang/pl/settings.php @@ -109,7 +109,7 @@ return [ 'recycle_bin_contents_empty' => 'Kosz jest pusty', 'recycle_bin_empty' => 'Opróżnij kosz', 'recycle_bin_empty_confirm' => 'To na stałe zniszczy wszystkie przedmioty w koszu, w tym zawartość w każdym elemencie. Czy na pewno chcesz opróżnić kosz?', - 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item from the system, along with any child elements listed below, and you will not be able to restore this content. Are you sure you want to permanently delete this item?', + 'recycle_bin_destroy_confirm' => 'Ta akcja trwale usunie ten element z systemu, wraz z elementami podrzędnymi wymienionymi poniżej i nie będziesz już mógł przywrócić tej zawartości. Czy na pewno chcesz trwale usunąć ten element?', 'recycle_bin_destroy_list' => 'Elementy do usunięcia', 'recycle_bin_restore_list' => 'Elementy do przywrócenia', 'recycle_bin_restore_confirm' => 'Ta akcja przywróci usunięty element, w tym elementy podrzędne, do ich oryginalnej lokalizacji. Jeśli oryginalna lokalizacja została od tego czasu usunięta, a teraz znajduje się w koszu, element nadrzędny będzie również musiał zostać przywrócony.', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Ostatni błąd:', 'webhooks_last_error_message' => 'Ostatni komunikat o błędzie:', + // Licensing + 'licenses' => 'Licencje', + 'licenses_desc' => 'Ta strona podaje szczegóły dotyczące licencji dla BookStack w powiązaniu z projektami i bibliotekami używanymi w BookStack. Wiele wymienionych projektów może zezwalać na wykorzystanie wyłącznie w kontekście rozwoju oprogramowania.', + 'licenses_bookstack' => 'Licencja BookStack', + 'licenses_php' => 'Licencje bibliotek PHP', + 'licenses_js' => 'Licencje bibliotek JavaScript', + 'licenses_other' => 'Inne licencje', + 'license_details' => 'Szczegóły licencji', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/pt/preferences.php b/lang/pt/preferences.php index 1d6ec7d4c..ec5e54bba 100644 --- a/lang/pt/preferences.php +++ b/lang/pt/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Guardar preferências', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Acesso e Segurança', 'auth_change_password' => 'Alterar Palavra-passe', diff --git a/lang/pt/settings.php b/lang/pt/settings.php index eb637d8bd..7a25d635e 100644 --- a/lang/pt/settings.php +++ b/lang/pt/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Último erro:', 'webhooks_last_error_message' => 'Última mensagem de erro:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/pt_BR/preferences.php b/lang/pt_BR/preferences.php index aa354a9ad..28d0e4978 100644 --- a/lang/pt_BR/preferences.php +++ b/lang/pt_BR/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Salvar Preferências', 'notifications_update_success' => 'Preferências de notificação foram atualizadas!', 'notifications_watched' => 'Itens assistidos e ignorados', - 'notifications_watched_desc' => ' Abaixo estão os itens que possuem preferências de relógio personalizadas aplicadas. Para atualizar suas preferências para estes, veja o item e encontre as opções de relógio na barra lateral.', + 'notifications_watched_desc' => 'Abaixo estão os itens que possuem preferências de relógio personalizadas aplicadas. Para atualizar suas preferências para estes, veja o item e encontre as opções de relógio na barra lateral.', 'auth' => 'Acesso & Segurança', 'auth_change_password' => 'Mudar a senha', diff --git a/lang/pt_BR/settings.php b/lang/pt_BR/settings.php index cd30b9e20..1107855a6 100644 --- a/lang/pt_BR/settings.php +++ b/lang/pt_BR/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Último Erro:', 'webhooks_last_error_message' => 'Última mensagem de erro:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/ro/preferences.php b/lang/ro/preferences.php index 893b44eaf..f7529305c 100644 --- a/lang/ro/preferences.php +++ b/lang/ro/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Salvează Preferințe', 'notifications_update_success' => 'Preferințele de notificare au fost actualizate!', 'notifications_watched' => 'Articole urmărite și ignorate', - 'notifications_watched_desc' => ' Mai jos sunt elementele care au fost aplicate preferințe personalizate. Pentru a actualiza preferințele pentru acestea, vizualizați elementul și apoi găsiți opțiunile de ceas în bara laterală.', + 'notifications_watched_desc' => 'Mai jos sunt elementele care au fost aplicate preferințe personalizate. Pentru a actualiza preferințele pentru acestea, vizualizați elementul și apoi găsiți opțiunile de ceas în bara laterală.', 'auth' => 'Acces & Securitate', 'auth_change_password' => 'Schimbă Parola', diff --git a/lang/ro/settings.php b/lang/ro/settings.php index 508ab595a..32954a8ea 100644 --- a/lang/ro/settings.php +++ b/lang/ro/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Ultima eroare:', 'webhooks_last_error_message' => 'Ultimul mesaj de eroare:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/ru/activities.php b/lang/ru/activities.php index 1c4fd5da1..df6ae9062 100644 --- a/lang/ru/activities.php +++ b/lang/ru/activities.php @@ -66,7 +66,7 @@ return [ 'auth_register' => 'зарегистрировался как новый пользователь', 'auth_password_reset_request' => 'запросил смену пароля пользователя', 'auth_password_reset_update' => 'сбросил пароль пользователя', - 'mfa_setup_method' => 'ностроил метод МФА', + 'mfa_setup_method' => 'настроил метод МФА', 'mfa_setup_method_notification' => 'Многофакторный метод аутентификации успешно настроен', 'mfa_remove_method' => 'удалил метод МФА', 'mfa_remove_method_notification' => 'Многофакторный метод аутентификации успешно удален', @@ -93,11 +93,11 @@ return [ 'user_delete_notification' => 'Пользователь успешно удален', // API Tokens - 'api_token_create' => 'created API token', + 'api_token_create' => 'создан API токен', 'api_token_create_notification' => 'API токен успешно создан', - 'api_token_update' => 'updated API token', + 'api_token_update' => 'обновлён API токен', 'api_token_update_notification' => 'API токен успешно обновлен', - 'api_token_delete' => 'deleted API token', + 'api_token_delete' => 'обновил API токен', 'api_token_delete_notification' => 'API токен успешно удален', // Roles diff --git a/lang/ru/common.php b/lang/ru/common.php index b2af5fdef..26b725ebc 100644 --- a/lang/ru/common.php +++ b/lang/ru/common.php @@ -20,7 +20,7 @@ return [ 'description' => 'Описание', 'role' => 'Роль', 'cover_image' => 'Обложка', - 'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.', + 'cover_image_description' => 'Это изображение должно быть приблизительно 440x250px, хотя оно и будет гибко масштабироваться и обрезаться, чтобы соответствовать пользовательскому интерфейсу в различных необходимых сценариях. Так что фактические размеры дисплея будут отличаться.', // Actions 'actions' => 'Действия', diff --git a/lang/ru/editor.php b/lang/ru/editor.php index 756925f58..b93bd8840 100644 --- a/lang/ru/editor.php +++ b/lang/ru/editor.php @@ -81,9 +81,9 @@ return [ 'table_properties' => 'Свойства таблицы', 'table_properties_title' => 'Свойства таблицы', 'delete_table' => 'Удалить таблицу', - 'table_clear_formatting' => 'Clear table formatting', - 'resize_to_contents' => 'Resize to contents', - 'row_header' => 'Row header', + 'table_clear_formatting' => 'Очистить форматирование таблицы', + 'resize_to_contents' => 'Изменить размер содержимого', + 'row_header' => 'Заголовок строки', 'insert_row_before' => 'Вставить строку выше', 'insert_row_after' => 'Вставить строку ниже', 'delete_row' => 'Удалить строку', diff --git a/lang/ru/entities.php b/lang/ru/entities.php index deafa2e85..c18c00e79 100644 --- a/lang/ru/entities.php +++ b/lang/ru/entities.php @@ -23,7 +23,7 @@ return [ 'meta_updated' => 'Обновлено :timeLength', 'meta_updated_name' => ':user обновил :timeLength', 'meta_owned_name' => 'Владелец :user', - 'meta_reference_count' => 'Referenced by :count item|Referenced by :count items', + 'meta_reference_count' => 'Ссылается :count элемент|Ссылается :count элементов', 'entity_select' => 'Выбор объекта', 'entity_select_lack_permission' => 'У вас нет разрешения на выбор этого элемента', 'images' => 'Изображения', @@ -39,9 +39,9 @@ return [ 'export_pdf' => 'PDF файл', 'export_text' => 'Текстовый файл', 'export_md' => 'Файл Markdown', - 'default_template' => 'Default Page Template', - 'default_template_explain' => 'Assign a page template that will be used as the default content for all pages created within this item. Keep in mind this will only be used if the page creator has view access to the chosen template page.', - 'default_template_select' => 'Select a template page', + 'default_template' => 'Шаблон страницы по умолчанию', + 'default_template_explain' => 'Назначить шаблон страницы, который будет использоваться в качестве содержимого по умолчанию для всех страниц, созданных в этом элементе. Имейте в виду, что это будет работать, только если создатель страницы имеет доступ к выбранной странице шаблона.', + 'default_template_select' => 'Выберите страницу шаблона', // Permissions and restrictions 'permissions' => 'Разрешения', @@ -207,7 +207,7 @@ return [ 'pages_delete_draft' => 'Удалить черновик', 'pages_delete_success' => 'Страница удалена', 'pages_delete_draft_success' => 'Черновик удален', - 'pages_delete_warning_template' => 'This page is in active use as a book or chapter default page template. These books or chapters will no longer have a default page template assigned after this page is deleted.', + 'pages_delete_warning_template' => 'Эта страница активно используется как шаблон страницы по умолчанию для книги или главы. Эти книги или главы больше не будут иметь шаблон страницы по умолчанию, назначенный после удаления этой страницы.', 'pages_delete_confirm' => 'Вы действительно хотите удалить эту страницу?', 'pages_delete_draft_confirm' => 'Вы действительно хотите удалить этот черновик?', 'pages_editing_named' => 'Редактирование страницы :pageName', @@ -243,8 +243,8 @@ return [ 'pages_md_insert_drawing' => 'Вставить рисунок', 'pages_md_show_preview' => 'Предпросмотр', 'pages_md_sync_scroll' => 'Синхронизировать прокрутку', - 'pages_drawing_unsaved' => 'Unsaved Drawing Found', - 'pages_drawing_unsaved_confirm' => 'Unsaved drawing data was found from a previous failed drawing save attempt. Would you like to restore and continue editing this unsaved drawing?', + 'pages_drawing_unsaved' => 'Найден несохраненный чертеж', + 'pages_drawing_unsaved_confirm' => 'Несохраненные данные были найдены из предыдущей неудачной попытки сохранения рисунка. Вы хотите восстановить и продолжить редактирование несохраненного рисунка?', 'pages_not_in_chapter' => 'Страница не находится в главе', 'pages_move' => 'Переместить страницу', 'pages_copy' => 'Скопировать страницу', @@ -273,12 +273,12 @@ return [ 'pages_revisions_none' => 'У этой страницы нет других версий', 'pages_copy_link' => 'Копировать ссылку', 'pages_edit_content_link' => 'Перейти к разделу в редакторе', - 'pages_pointer_enter_mode' => 'Enter section select mode', + 'pages_pointer_enter_mode' => 'Войти в режим выбора раздела', 'pages_pointer_label' => 'Настройки раздела страницы', 'pages_pointer_permalink' => 'Постоянная ссылка на раздел страницы', 'pages_pointer_include_tag' => 'Раздел страницы с тегом', - 'pages_pointer_toggle_link' => 'Permalink mode, Press to show include tag', - 'pages_pointer_toggle_include' => 'Include tag mode, Press to show permalink', + 'pages_pointer_toggle_link' => 'Режим постоянной ссылки. Нажмите, чтобы показать включение тега', + 'pages_pointer_toggle_include' => 'Включить режим тега. Нажмите для отображения постоянной ссылки', 'pages_permissions_active' => 'Действующие разрешения на страницу', 'pages_initial_revision' => 'Первоначальное издание', 'pages_references_update_revision' => 'Система автоматически обновила внутренние ссылки', @@ -299,7 +299,7 @@ return [ 'pages_is_template' => 'Шаблон страницы', // Editor Sidebar - 'toggle_sidebar' => 'Toggle Sidebar', + 'toggle_sidebar' => 'Переключить боковую панель', 'page_tags' => 'Теги страницы', 'chapter_tags' => 'Теги главы', 'book_tags' => 'Теги книги', @@ -409,25 +409,25 @@ return [ // References 'references' => 'Ссылки', 'references_none' => 'Нет отслеживаемых ссылок на этот элемент.', - 'references_to_desc' => 'Listed below is all the known content in the system that links to this item.', + 'references_to_desc' => 'Ниже перечислены все известные материалы в системе, которые ссылаются на этот элемент.', // Watch Options - 'watch' => 'Watch', + 'watch' => 'Наблюдать', 'watch_title_default' => 'Свойства по умолчанию', - 'watch_desc_default' => 'Revert watching to just your default notification preferences.', + 'watch_desc_default' => 'Вернуть просмотр только ваших настроек уведомлений по умолчанию.', 'watch_title_ignore' => 'Игнорировать', 'watch_desc_ignore' => 'Игнорировать все уведомления, включая уведомления из пользовательского уровня.', 'watch_title_new' => 'Новые страницы', 'watch_desc_new' => 'Уведомлять при создании новой страницы внутри этого элемента.', 'watch_title_updates' => 'Все обновления страницы', - 'watch_desc_updates' => 'Notify upon all new pages and page changes.', - 'watch_desc_updates_page' => 'Notify upon all page changes.', + 'watch_desc_updates' => 'Уведомлять обо всех новых страницах и изменениях страницы.', + 'watch_desc_updates_page' => 'Уведомлять о всех изменениях страницы.', 'watch_title_comments' => 'Все обновления и комментарии страниц', 'watch_desc_comments' => 'Уведомлять обо всех новых страницах, изменениях страниц и новых комментариях.', 'watch_desc_comments_page' => 'Уведомлять об изменениях страниц и новых комментариях.', 'watch_change_default' => 'Изменить настройки уведомлений по умолчанию', 'watch_detail_ignore' => 'Игнорирование уведомлений', - 'watch_detail_new' => 'Watching for new pages', + 'watch_detail_new' => 'Наблюдение за новыми страницами', 'watch_detail_updates' => 'Просмотр новых страниц и обновлений', 'watch_detail_comments' => 'Просмотр новых страниц, обновлений и комментариев', 'watch_detail_parent_book' => 'Просмотр через родительскую книгу', diff --git a/lang/ru/errors.php b/lang/ru/errors.php index 0ff14e9f5..1fe57af2f 100644 --- a/lang/ru/errors.php +++ b/lang/ru/errors.php @@ -10,7 +10,7 @@ return [ // Auth 'error_user_exists_different_creds' => 'Пользователь с электронной почтой :email уже существует, но с другими учетными данными.', - 'auth_pre_register_theme_prevention' => 'User account could not be registered for the provided details', + 'auth_pre_register_theme_prevention' => 'Пользователь не может быть зарегистрирован по предоставленной информации', 'email_already_confirmed' => 'Адрес электронной почты уже был подтвержден, попробуйте войти в систему.', 'email_confirmation_invalid' => 'Этот токен подтверждения недействителен или уже используется. Повторите попытку регистрации.', 'email_confirmation_expired' => 'Истек срок действия токена. Отправлено новое письмо с подтверждением.', @@ -43,16 +43,16 @@ return [ 'cannot_get_image_from_url' => 'Не удается получить изображение из :url', 'cannot_create_thumbs' => 'Сервер не может создавать эскизы. Убедитесь, что у вас установлено расширение GD PHP.', 'server_upload_limit' => 'Сервер не разрешает загрузку файлов такого размера. Попробуйте уменьшить размер файла.', - 'server_post_limit' => 'The server cannot receive the provided amount of data. Try again with less data or a smaller file.', + 'server_post_limit' => 'Сервер не может получить указанный объем данных. Повторите попытку, используя меньшее количество данных или файл меньшего размера.', 'uploaded' => 'Сервер не позволяет загружать файлы такого размера. Пожалуйста, попробуйте файл меньше.', // Drawing & Images 'image_upload_error' => 'Произошла ошибка при загрузке изображения', 'image_upload_type_error' => 'Неправильный тип загружаемого изображения', 'image_upload_replace_type' => 'Замена файла изображения должна быть того же типа', - 'image_upload_memory_limit' => 'Failed to handle image upload and/or create thumbnails due to system resource limits.', - 'image_thumbnail_memory_limit' => 'Failed to create image size variations due to system resource limits.', - 'image_gallery_thumbnail_memory_limit' => 'Failed to create gallery thumbnails due to system resource limits.', + 'image_upload_memory_limit' => 'Не удалось выполнить загрузку изображений и/или создать эскизы из-за ограничения системных ресурсов.', + 'image_thumbnail_memory_limit' => 'Не удалось создать вариации размера изображения из-за ограничений системных ресурсов.', + 'image_gallery_thumbnail_memory_limit' => 'Не удалось создать эскизы галереи из-за ограниченности системных ресурсов.', 'drawing_data_not_found' => 'Данные чертежа не могут быть загружены. Возможно, файл чертежа больше не существует или у вас нет разрешения на доступ к нему.', // Attachments diff --git a/lang/ru/notifications.php b/lang/ru/notifications.php index f37f11986..c5e98da80 100644 --- a/lang/ru/notifications.php +++ b/lang/ru/notifications.php @@ -10,10 +10,10 @@ return [ 'new_page_intro' => 'Новая страница была создана в :appName:', 'updated_page_subject' => 'Обновлена страница: :pageName', 'updated_page_intro' => 'Страница была обновлена в :appName:', - 'updated_page_debounce' => 'To prevent a mass of notifications, for a while you won\'t be sent notifications for further edits to this page by the same editor.', + 'updated_page_debounce' => 'Чтобы предотвратить массовые уведомления, в течение некоторого времени вы не будете получать уведомления о дальнейших правках этой страницы этим же редактором.', 'detail_page_name' => 'Имя страницы:', - 'detail_page_path' => 'Page Path:', + 'detail_page_path' => 'Путь страницы:', 'detail_commenter' => 'Комментатор:', 'detail_comment' => 'Комментарий:', 'detail_created_by' => 'Создано:', @@ -22,6 +22,6 @@ return [ 'action_view_comment' => 'Просмотреть комментарий', 'action_view_page' => 'Посмотреть страницу', - 'footer_reason' => 'This notification was sent to you because :link cover this type of activity for this item.', + 'footer_reason' => 'Это уведомление было отправлено, потому что :link покрывает этот тип активности для этого элемента.', 'footer_reason_link' => 'ваши настройки уведомлений', ]; diff --git a/lang/ru/preferences.php b/lang/ru/preferences.php index 1cfd1c24b..27217815d 100644 --- a/lang/ru/preferences.php +++ b/lang/ru/preferences.php @@ -8,7 +8,7 @@ return [ 'my_account' => 'Моя учетная запись', 'shortcuts' => 'Горячие клавиши', - 'shortcuts_interface' => 'UI Shortcut Preferences', + 'shortcuts_interface' => 'Настройки горячих клавиш', 'shortcuts_toggle_desc' => 'Здесь вы можете включить или отключить горячие клавиши системного интерфейса, используемые для навигации и действий.', 'shortcuts_customize_desc' => 'Вы можете настроить каждую из горячих клавиш ниже. Просто нажмите комбинацию клавиш после выбора вставки для горячих клавиш.', 'shortcuts_toggle_label' => 'Горячие клавиши включены', @@ -26,8 +26,8 @@ return [ 'notifications_opt_comment_replies' => 'Уведомлять об ответах на мои комментарии', 'notifications_save' => 'Сохранить настройки', 'notifications_update_success' => 'Настройки уведомлений были обновлены!', - 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched' => 'Просмотренные и игнорированные элементы', + 'notifications_watched_desc' => 'Ниже приведены элементы, которые имеют пользовательские настройки наблюдения. Чтобы обновить ваши предпочтения, посмотрите этот пункт и найдите варианты наблюдения в боковой панели.', 'auth' => 'Доступ и безопасность', 'auth_change_password' => 'Изменить пароль', @@ -35,9 +35,9 @@ return [ 'auth_change_password_success' => 'Пароль был обновлен!', 'profile' => 'Детали профиля', - 'profile_desc' => 'Manage the details of your account which represents you to other users, in addition to details that are used for communication and system personalisation.', + 'profile_desc' => 'Управляйте деталями вашей учетной записи, что представляют вас другим пользователям, в дополнение к деталям, используемым для персонализации коммуникации и системы.', 'profile_view_public' => 'Просмотреть публичный профиль', - 'profile_name_desc' => 'Configure your display name which will be visible to other users in the system through the activity you perform, and content you own.', + 'profile_name_desc' => 'Настройте отображаемое имя, видимое другим пользователям системы через действия, что вы выполняете, и контент, которым вы владеете.', 'profile_email_desc' => 'Этот адрес электронной почты будет использоваться для уведомлений и, в зависимости от активной системы аутентификации, для доступа к системе.', 'profile_email_no_permission' => 'К сожалению, у вас нет разрешения на изменение адреса электронной почты. Если вам действительно необходимо его изменить, нужно попросить администратора сделать это.', 'profile_avatar_desc' => 'Выберите изображение, которое будет использоваться для представления себя другим в системе. По возможности это изображение должно быть квадратным и около 256 пикселей по ширине и высоте.', diff --git a/lang/ru/settings.php b/lang/ru/settings.php index e78b2869f..238a1da6b 100644 --- a/lang/ru/settings.php +++ b/lang/ru/settings.php @@ -86,7 +86,7 @@ return [ 'maint_send_test_email' => 'Отправить тестовое письмо', 'maint_send_test_email_desc' => 'Отправить тестовое письмо на адрес электронной почты, указанный в профиле.', 'maint_send_test_email_run' => 'Отправить письмо', - 'maint_send_test_email_success' => 'На адрес :address отравлено письмо', + 'maint_send_test_email_success' => 'Письмо отправлено на :address', 'maint_send_test_email_mail_subject' => 'Проверка электронной почты', 'maint_send_test_email_mail_greeting' => 'Доставка электронной почты работает!', 'maint_send_test_email_mail_text' => 'Поздравляем! Поскольку вы получили это письмо, электронная почта настроена правильно.', @@ -109,7 +109,7 @@ return [ 'recycle_bin_contents_empty' => 'На данный момент корзина пуста', 'recycle_bin_empty' => 'Очистить корзину', 'recycle_bin_empty_confirm' => 'Это действие навсегда уничтожит все элементы в корзине, включая содержимое, содержащееся в каждом элементе. Вы уверены, что хотите очистить корзину?', - 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item from the system, along with any child elements listed below, and you will not be able to restore this content. Are you sure you want to permanently delete this item?', + 'recycle_bin_destroy_confirm' => 'Это действие навсегда удалит этот элемент из системы, вместе с любыми дочерними элементами, перечисленными ниже, и вы не сможете восстановить этот контент. Вы уверены, что хотите навсегда удалить этот элемент?', 'recycle_bin_destroy_list' => 'Элементы для удаления', 'recycle_bin_restore_list' => 'Элементы для восстановления', 'recycle_bin_restore_confirm' => 'Это действие восстановит удаленный элемент, включая дочерние, в исходное место. Если исходное место было удалено и теперь находится в корзине, родительский элемент также необходимо будет восстановить.', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Последняя ошибка:', 'webhooks_last_error_message' => 'Последнее сообщение об ошибке:', + // Licensing + 'licenses' => 'Лицензии', + 'licenses_desc' => 'Эта страница содержит сведения о лицензиях для BookStack в дополнение к проектам и библиотекам, которые используются в BookStack. Многие перечисленные проекты могут использоваться только в контексте разработки.', + 'licenses_bookstack' => 'Лицензия BookStack', + 'licenses_php' => 'Лицензии PHP библиотек', + 'licenses_js' => 'Лицензии JavaScript библиотек', + 'licenses_other' => 'Прочие лицензии', + 'license_details' => 'Подробности о лицензии', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/sk/activities.php b/lang/sk/activities.php index 2422ea7f6..6dad803e0 100644 --- a/lang/sk/activities.php +++ b/lang/sk/activities.php @@ -15,7 +15,7 @@ return [ 'page_restore' => 'obnovil(a) stránku', 'page_restore_notification' => 'Stránka úspešne obnovená', 'page_move' => 'presunul(a) stránku', - 'page_move_notification' => 'Page successfully moved', + 'page_move_notification' => 'Stránka bola úspešne presunutá', // Chapters 'chapter_create' => 'vytvoril(a) kapitolu', @@ -25,7 +25,7 @@ return [ 'chapter_delete' => 'odstránil(a) kapitolu', 'chapter_delete_notification' => 'Kapitola úspešne odstránená', 'chapter_move' => 'presunul(a) kapitolu', - 'chapter_move_notification' => 'Chapter successfully moved', + 'chapter_move_notification' => 'Kapitola bola úspešne presunutá', // Books 'book_create' => 'vytvoril(a) knihu', @@ -72,8 +72,8 @@ return [ 'mfa_remove_method_notification' => 'Viacúrovňový spôsob overenia úspešne odstránený', // Settings - 'settings_update' => 'updated settings', - 'settings_update_notification' => 'Settings successfully updated', + 'settings_update' => 'aktualizované nastavenia', + 'settings_update_notification' => 'Nastavenia boli úspešne aktualizované', 'maintenance_action_run' => 'ran maintenance action', // Webhooks @@ -85,11 +85,11 @@ return [ 'webhook_delete_notification' => 'Webhook úspešne odstránený', // Users - 'user_create' => 'created user', + 'user_create' => 'užívateľ vytvorený', 'user_create_notification' => 'User successfully created', - 'user_update' => 'updated user', + 'user_update' => 'používateľ aktualizovaný', 'user_update_notification' => 'Používateľ úspešne upravený', - 'user_delete' => 'deleted user', + 'user_delete' => 'odstránený používateľ', 'user_delete_notification' => 'Používateľ úspešne zmazaný', // API Tokens @@ -105,7 +105,7 @@ return [ 'role_create_notification' => 'Rola úspešne vytvorená', 'role_update' => 'updated role', 'role_update_notification' => 'Rola úspešne aktualizovaná', - 'role_delete' => 'deleted role', + 'role_delete' => 'odstrániť rolu', 'role_delete_notification' => 'Rola úspešne zmazaná', // Recycle Bin @@ -117,7 +117,7 @@ return [ 'commented_on' => 'komentoval(a)', 'comment_create' => 'added comment', 'comment_update' => 'updated comment', - 'comment_delete' => 'deleted comment', + 'comment_delete' => 'odstrániť komentár', // Other 'permissions_update' => 'aktualizované oprávnenia', diff --git a/lang/sk/preferences.php b/lang/sk/preferences.php index b3152848f..85da4f331 100644 --- a/lang/sk/preferences.php +++ b/lang/sk/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/sk/settings.php b/lang/sk/settings.php index b6beb5e6a..d2190f851 100644 --- a/lang/sk/settings.php +++ b/lang/sk/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Posledná chyba:', 'webhooks_last_error_message' => 'Posledná chybová správa:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/sl/activities.php b/lang/sl/activities.php index e82b174c9..027c17f87 100644 --- a/lang/sl/activities.php +++ b/lang/sl/activities.php @@ -93,11 +93,11 @@ return [ 'user_delete_notification' => 'Uporabnik uspešno izbrisan', // API Tokens - 'api_token_create' => 'created API token', + 'api_token_create' => 'ustvarjen žeton API', 'api_token_create_notification' => 'Žeton API uspešno ustvarjen', - 'api_token_update' => 'updated API token', + 'api_token_update' => 'posodobljen žeton API', 'api_token_update_notification' => 'Žeton API uspešno posodobljen', - 'api_token_delete' => 'deleted API token', + 'api_token_delete' => 'izbrisan žeton API', 'api_token_delete_notification' => 'Žeton API uspešno izbrisan', // Roles diff --git a/lang/sl/editor.php b/lang/sl/editor.php index de9aa0ece..b6f462eb5 100644 --- a/lang/sl/editor.php +++ b/lang/sl/editor.php @@ -7,105 +7,105 @@ */ return [ // General editor terms - 'general' => 'General', - 'advanced' => 'Advanced', - 'none' => 'None', - 'cancel' => 'Cancel', - 'save' => 'Save', - 'close' => 'Close', - 'undo' => 'Undo', - 'redo' => 'Redo', - 'left' => 'Left', - 'center' => 'Center', - 'right' => 'Right', - 'top' => 'Top', - 'middle' => 'Middle', - 'bottom' => 'Bottom', - 'width' => 'Width', - 'height' => 'Height', - 'More' => 'More', - 'select' => 'Select...', + 'general' => 'Splošno', + 'advanced' => 'Napredno', + 'none' => 'Brez', + 'cancel' => 'Prekliči', + 'save' => 'Shrani', + 'close' => 'Zapri', + 'undo' => 'Razveljavi', + 'redo' => 'Ponovi', + 'left' => 'Levo', + 'center' => 'Sredinsko', + 'right' => 'Desno', + 'top' => 'Zgoraj', + 'middle' => 'Sredina', + 'bottom' => 'Spodaj', + 'width' => 'Širina', + 'height' => 'Višina', + 'More' => 'Več', + 'select' => 'Izberi ...', // Toolbar - 'formats' => 'Formats', - 'header_large' => 'Large Header', - 'header_medium' => 'Medium Header', - 'header_small' => 'Small Header', - 'header_tiny' => 'Tiny Header', - 'paragraph' => 'Paragraph', - 'blockquote' => 'Blockquote', - 'inline_code' => 'Inline code', - 'callouts' => 'Callouts', - 'callout_information' => 'Information', - 'callout_success' => 'Success', - 'callout_warning' => 'Warning', - 'callout_danger' => 'Danger', - 'bold' => 'Bold', - 'italic' => 'Italic', - 'underline' => 'Underline', - 'strikethrough' => 'Strikethrough', - 'superscript' => 'Superscript', - 'subscript' => 'Subscript', - 'text_color' => 'Text color', - 'custom_color' => 'Custom color', - 'remove_color' => 'Remove color', - 'background_color' => 'Background color', - 'align_left' => 'Align left', - 'align_center' => 'Align center', - 'align_right' => 'Align right', - 'align_justify' => 'Justify', - 'list_bullet' => 'Bullet list', - 'list_numbered' => 'Numbered list', - 'list_task' => 'Task list', - 'indent_increase' => 'Increase indent', - 'indent_decrease' => 'Decrease indent', - 'table' => 'Table', - 'insert_image' => 'Insert image', - 'insert_image_title' => 'Insert/Edit Image', - 'insert_link' => 'Insert/edit link', - 'insert_link_title' => 'Insert/Edit Link', - 'insert_horizontal_line' => 'Insert horizontal line', + 'formats' => 'Oblike', + 'header_large' => 'Velika glava', + 'header_medium' => 'Srednja glava', + 'header_small' => 'Majhna glava', + 'header_tiny' => 'Drobna glava', + 'paragraph' => 'Odstavek', + 'blockquote' => 'Navedek', + 'inline_code' => 'Vgrajena koda', + 'callouts' => 'Opombe', + 'callout_information' => 'Informacija', + 'callout_success' => 'Uspešno', + 'callout_warning' => 'Opozorilo', + 'callout_danger' => 'Nevarnost', + 'bold' => 'Krepko', + 'italic' => 'Ležeče', + 'underline' => 'Podčrtano', + 'strikethrough' => 'Prečrtano', + 'superscript' => 'Nadpisano', + 'subscript' => 'Podpisano', + 'text_color' => 'Barva besedila', + 'custom_color' => 'Barva po meri', + 'remove_color' => 'Odstrani barvo', + 'background_color' => 'Barva ozadja', + 'align_left' => 'Poravnaj levo', + 'align_center' => 'Poravnaj na sredino', + 'align_right' => 'Poravnaj desno', + 'align_justify' => 'Poravnaj obojestransko', + 'list_bullet' => 'Seznam z oznakami', + 'list_numbered' => 'Oštevilčen seznam', + 'list_task' => 'Seznam opravil', + 'indent_increase' => 'Povečaj zamik', + 'indent_decrease' => 'Zmanjšaj zamik', + 'table' => 'Tabela', + 'insert_image' => 'Vstavi sliko', + 'insert_image_title' => 'Vstavi/Obdelaj sliko', + 'insert_link' => 'Vstavi/Obdelaj povezavo', + 'insert_link_title' => 'Vstavi/obdelaj povezavo', + 'insert_horizontal_line' => 'Vstavi vodoravno črto', 'insert_code_block' => 'Insert code block', 'edit_code_block' => 'Edit code block', - 'insert_drawing' => 'Insert/edit drawing', + 'insert_drawing' => 'Vstavi/Obdelaj risbo', 'drawing_manager' => 'Drawing manager', 'insert_media' => 'Insert/edit media', 'insert_media_title' => 'Insert/Edit Media', - 'clear_formatting' => 'Clear formatting', - 'source_code' => 'Source code', - 'source_code_title' => 'Source Code', - 'fullscreen' => 'Fullscreen', - 'image_options' => 'Image options', + 'clear_formatting' => 'Odstrani oblikovanje', + 'source_code' => 'Izvorna koda', + 'source_code_title' => 'Izvorna koda', + 'fullscreen' => 'Celozaslonski način', + 'image_options' => 'Možnosti za slike', // Tables - 'table_properties' => 'Table properties', - 'table_properties_title' => 'Table Properties', - 'delete_table' => 'Delete table', - 'table_clear_formatting' => 'Clear table formatting', - 'resize_to_contents' => 'Resize to contents', - 'row_header' => 'Row header', - 'insert_row_before' => 'Insert row before', - 'insert_row_after' => 'Insert row after', - 'delete_row' => 'Delete row', - 'insert_column_before' => 'Insert column before', - 'insert_column_after' => 'Insert column after', - 'delete_column' => 'Delete column', - 'table_cell' => 'Cell', - 'table_row' => 'Row', - 'table_column' => 'Column', - 'cell_properties' => 'Cell properties', - 'cell_properties_title' => 'Cell Properties', - 'cell_type' => 'Cell type', - 'cell_type_cell' => 'Cell', - 'cell_scope' => 'Scope', - 'cell_type_header' => 'Header cell', - 'merge_cells' => 'Merge cells', - 'split_cell' => 'Split cell', - 'table_row_group' => 'Row Group', - 'table_column_group' => 'Column Group', - 'horizontal_align' => 'Horizontal align', - 'vertical_align' => 'Vertical align', - 'border_width' => 'Border width', + 'table_properties' => 'Lastnosti tabele', + 'table_properties_title' => 'Lastnosti tabele', + 'delete_table' => 'Izbriši tabelo', + 'table_clear_formatting' => 'Odstrani oblikovanje tabele', + 'resize_to_contents' => 'Prilagodi vsebini', + 'row_header' => 'Glava vrstice', + 'insert_row_before' => 'Vstavi vrstico pred', + 'insert_row_after' => 'Vstavi vrstico po', + 'delete_row' => 'Izbriši vrstico', + 'insert_column_before' => 'Vstavi stolpec pred', + 'insert_column_after' => 'Vstavi stolpec po', + 'delete_column' => 'Izbriši stolpec', + 'table_cell' => 'Celica', + 'table_row' => 'Vrstica', + 'table_column' => 'Stolpec', + 'cell_properties' => 'Lastnosti celice', + 'cell_properties_title' => 'Lastnosti celice', + 'cell_type' => 'Vrsta celice', + 'cell_type_cell' => 'Celica', + 'cell_scope' => 'Obseg', + 'cell_type_header' => 'Naslovna celica', + 'merge_cells' => 'Združi celice', + 'split_cell' => 'Razdeli celice', + 'table_row_group' => 'Skupina vrstic', + 'table_column_group' => 'Skupina stolpcev', + 'horizontal_align' => 'Vodoravna poravnava', + 'vertical_align' => 'Navpična poravnava', + 'border_width' => 'Debelina roba', 'border_style' => 'Border style', 'border_color' => 'Border color', 'row_properties' => 'Row properties', @@ -153,25 +153,25 @@ return [ 'open_link_new' => 'New window', 'remove_link' => 'Remove link', 'insert_collapsible' => 'Insert collapsible block', - 'collapsible_unwrap' => 'Unwrap', - 'edit_label' => 'Edit label', - 'toggle_open_closed' => 'Toggle open/closed', - 'collapsible_edit' => 'Edit collapsible block', - 'toggle_label' => 'Toggle label', + 'collapsible_unwrap' => 'Odpri', + 'edit_label' => 'Uredi oznako', + 'toggle_open_closed' => 'Odpri/Zapri', + 'collapsible_edit' => 'Uredi zložljivi blok', + 'toggle_label' => 'Preklopi oznako', // About view - 'about' => 'About the editor', - 'about_title' => 'About the WYSIWYG Editor', - 'editor_license' => 'Editor License & Copyright', - 'editor_tiny_license' => 'This editor is built using :tinyLink which is provided under the MIT license.', - 'editor_tiny_license_link' => 'The copyright and license details of TinyMCE can be found here.', - 'save_continue' => 'Save Page & Continue', - 'callouts_cycle' => '(Keep pressing to toggle through types)', - 'link_selector' => 'Link to content', - 'shortcuts' => 'Shortcuts', - 'shortcut' => 'Shortcut', - 'shortcuts_intro' => 'The following shortcuts are available in the editor:', + 'about' => 'O urejevalniku', + 'about_title' => 'O Urejevalniku WYSIWYG', + 'editor_license' => 'Licenca in avtorske pravice Urejevalnika', + 'editor_tiny_license' => 'Urejevalnik je ustvarjen z uporabo :tinyLink pod pogoji licence MIT.', + 'editor_tiny_license_link' => 'Podrobnosti o avtorskih pravicah in licenci za TinyMCE lahko preberete tukaj.', + 'save_continue' => 'Shrani stran in Nadaljuj', + 'callouts_cycle' => '(Večkrat pritisnite, da preklopite med vrstami opomb)', + 'link_selector' => 'Povezava do vsebine', + 'shortcuts' => 'Bližnjice', + 'shortcut' => 'Bližnjica', + 'shortcuts_intro' => 'Sledeče bližnjice so na voljo v urejevalniku:', 'windows_linux' => '(Windows/Linux)', 'mac' => '(Mac)', - 'description' => 'Description', + 'description' => 'Opis', ]; diff --git a/lang/sl/preferences.php b/lang/sl/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/sl/preferences.php +++ b/lang/sl/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/sl/settings.php b/lang/sl/settings.php index 272f1b114..72a45a14b 100644 --- a/lang/sl/settings.php +++ b/lang/sl/settings.php @@ -277,6 +277,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/sl/validation.php b/lang/sl/validation.php index 92060dd6d..012bfe4a7 100644 --- a/lang/sl/validation.php +++ b/lang/sl/validation.php @@ -12,10 +12,10 @@ return [ 'active_url' => ':attribute ni veljaven URL.', 'after' => ':attribute mora biti datum po :date.', 'alpha' => ':attribute lahko vsebuje samo črke.', - 'alpha_dash' => ':attribute lahko vsebuje samo ?rke, ?tevilke in ?rtice.', + 'alpha_dash' => ':attribute lahko vsebuje samo črke, številke, pomišljaje in podčrtaje.', 'alpha_num' => ':attribute lahko vsebuje samo črke in številke.', 'array' => ':attribute mora biti niz.', - 'backup_codes' => 'The provided code is not valid or has already been used.', + 'backup_codes' => 'Podana koda ni veljavna ali je že uporabljena.', 'before' => ':attribute mora biti datum pred :date.', 'between' => [ 'numeric' => ':attribute mora biti med :min in :max.', @@ -32,7 +32,7 @@ return [ 'digits_between' => ':attribute mora biti med :min in :max števkami.', 'email' => ':attribute mora biti veljaven e-naslov.', 'ends_with' => 'The :attribute se mora končati z eno od določenih: :vrednost/values', - 'file' => 'The :attribute must be provided as a valid file.', + 'file' => ':attribute ni veljavna datoteka.', 'filled' => 'Polje ne sme biti prazno.', 'gt' => [ 'numeric' => ':attribute mora biti večji kot :vrednost.', @@ -100,7 +100,7 @@ return [ ], 'string' => ':attribute mora biti niz.', 'timezone' => ':attribute mora biti veljavna cona.', - 'totp' => 'The provided code is not valid or has expired.', + 'totp' => 'Podana koda ni veljavna ali je zapadla.', 'unique' => ':attribute je že zaseden.', 'url' => ':attribute oblika ni veljavna.', 'uploaded' => 'Datoteke ni bilo mogoče naložiti. Strežnik morda ne sprejema datotek te velikosti.', diff --git a/lang/sq/preferences.php b/lang/sq/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/sq/preferences.php +++ b/lang/sq/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/sq/settings.php b/lang/sq/settings.php index 7b7f5d2a2..f4c84092c 100644 --- a/lang/sq/settings.php +++ b/lang/sq/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/sr/editor.php b/lang/sr/editor.php index ad670af98..b376e542c 100644 --- a/lang/sr/editor.php +++ b/lang/sr/editor.php @@ -102,58 +102,58 @@ return [ 'merge_cells' => 'Обједини ћелије', 'split_cell' => 'Подели ћелију', 'table_row_group' => 'Група редова', - 'table_column_group' => 'Column Group', - 'horizontal_align' => 'Horizontal align', - 'vertical_align' => 'Vertical align', - 'border_width' => 'Border width', - 'border_style' => 'Border style', - 'border_color' => 'Border color', - 'row_properties' => 'Row properties', - 'row_properties_title' => 'Row Properties', - 'cut_row' => 'Cut row', - 'copy_row' => 'Copy row', - 'paste_row_before' => 'Paste row before', - 'paste_row_after' => 'Paste row after', - 'row_type' => 'Row type', - 'row_type_header' => 'Header', - 'row_type_body' => 'Body', - 'row_type_footer' => 'Footer', - 'alignment' => 'Alignment', - 'cut_column' => 'Cut column', - 'copy_column' => 'Copy column', - 'paste_column_before' => 'Paste column before', - 'paste_column_after' => 'Paste column after', - 'cell_padding' => 'Cell padding', - 'cell_spacing' => 'Cell spacing', - 'caption' => 'Caption', - 'show_caption' => 'Show caption', - 'constrain' => 'Constrain proportions', - 'cell_border_solid' => 'Solid', - 'cell_border_dotted' => 'Dotted', - 'cell_border_dashed' => 'Dashed', - 'cell_border_double' => 'Double', - 'cell_border_groove' => 'Groove', - 'cell_border_ridge' => 'Ridge', - 'cell_border_inset' => 'Inset', - 'cell_border_outset' => 'Outset', - 'cell_border_none' => 'None', - 'cell_border_hidden' => 'Hidden', + 'table_column_group' => 'Група колона', + 'horizontal_align' => 'Хоризонтално поравнање', + 'vertical_align' => 'Вертикално поравнати', + 'border_width' => 'Ширина ивице', + 'border_style' => 'Стил ивице', + 'border_color' => 'Боја ивице', + 'row_properties' => 'Својства реда', + 'row_properties_title' => 'Својства реда', + 'cut_row' => 'Пресеци ред', + 'copy_row' => 'Копирај ред', + 'paste_row_before' => 'Налепите ред пре', + 'paste_row_after' => 'Налепите ред после', + 'row_type' => 'Врста реда', + 'row_type_header' => 'Заглавље', + 'row_type_body' => 'Садржај', + 'row_type_footer' => 'Подножје', + 'alignment' => 'Поравнавање', + 'cut_column' => 'Изрежите колону', + 'copy_column' => 'Копирај колону', + 'paste_column_before' => 'Налепите колону пре', + 'paste_column_after' => 'Налепите колону после', + 'cell_padding' => 'Попуна ћелија', + 'cell_spacing' => 'Размак ћелија', + 'caption' => 'Опис', + 'show_caption' => 'Прикажи титл', + 'constrain' => 'Ограничавају размере', + 'cell_border_solid' => 'Чврсто тело', + 'cell_border_dotted' => 'Тачкасто', + 'cell_border_dashed' => 'Испрекидана', + 'cell_border_double' => 'Двострук', + 'cell_border_groove' => 'Жлеб', + 'cell_border_ridge' => 'Гребен', + 'cell_border_inset' => 'Уметак', + 'cell_border_outset' => 'Почетак', + 'cell_border_none' => 'Без', + 'cell_border_hidden' => 'Сакривено', // Images, links, details/summary & embed - 'source' => 'Source', - 'alt_desc' => 'Alternative description', - 'embed' => 'Embed', - 'paste_embed' => 'Paste your embed code below:', - 'url' => 'URL', - 'text_to_display' => 'Text to display', - 'title' => 'Title', - 'open_link' => 'Open link', - 'open_link_in' => 'Open link in...', - 'open_link_current' => 'Current window', - 'open_link_new' => 'New window', - 'remove_link' => 'Remove link', - 'insert_collapsible' => 'Insert collapsible block', - 'collapsible_unwrap' => 'Unwrap', + 'source' => 'Извор', + 'alt_desc' => 'Алтернативни опис', + 'embed' => 'Угради', + 'paste_embed' => 'Налепите свој код за уградњу испод:', + 'url' => 'УРЛ', + 'text_to_display' => 'Текст за приказ', + 'title' => 'Наслов', + 'open_link' => 'Отвори везу', + 'open_link_in' => 'Отвори везу у...', + 'open_link_current' => 'Тренутни прозор', + 'open_link_new' => 'Нови Прозор', + 'remove_link' => 'Уклони везу', + 'insert_collapsible' => 'Уредите склопиви блок', + 'collapsible_unwrap' => 'Одмотати', 'edit_label' => 'Уреди ознаку', 'toggle_open_closed' => 'Отварање/затварање', 'collapsible_edit' => 'Уредите склопиви блок', @@ -166,12 +166,12 @@ return [ 'editor_tiny_license' => 'Овај уређивач је направљен помоћу :tinyLink који је обезбеђен под МИТ лиценцом.', 'editor_tiny_license_link' => 'Детаље о ауторским правима и лиценци за ТиниМЦЕ можете пронаћи овде.', 'save_continue' => 'Сачувај страницу и настави', - 'callouts_cycle' => '(Keep pressing to toggle through types)', - 'link_selector' => 'Link to content', - 'shortcuts' => 'Shortcuts', - 'shortcut' => 'Shortcut', - 'shortcuts_intro' => 'The following shortcuts are available in the editor:', + 'callouts_cycle' => '(Наставите да притискате да бисте прелазили између типова)', + 'link_selector' => 'Линк до садржаја', + 'shortcuts' => 'Пречице', + 'shortcut' => 'Пречица', + 'shortcuts_intro' => 'Следеће пречице су доступне у уређивачу:', 'windows_linux' => '(Windows/Linux)', 'mac' => '(Mac)', - 'description' => 'Description', + 'description' => 'Опис', ]; diff --git a/lang/sr/preferences.php b/lang/sr/preferences.php index 2b88f9671..2872f5f3c 100644 --- a/lang/sr/preferences.php +++ b/lang/sr/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/sr/settings.php b/lang/sr/settings.php index 5d02cc89a..3ae7d7607 100644 --- a/lang/sr/settings.php +++ b/lang/sr/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Last Error Message:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/sv/preferences.php b/lang/sv/preferences.php index 9ca2c40b7..e06c0fbaa 100644 --- a/lang/sv/preferences.php +++ b/lang/sv/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/sv/settings.php b/lang/sv/settings.php index 30b099977..3ce6567b0 100644 --- a/lang/sv/settings.php +++ b/lang/sv/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Senast felande:', 'webhooks_last_error_message' => 'Senaste felmeddelande:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/tr/preferences.php b/lang/tr/preferences.php index 94a25df73..1ce7b01fd 100644 --- a/lang/tr/preferences.php +++ b/lang/tr/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/tr/settings.php b/lang/tr/settings.php index 6daca434e..36c52e52a 100644 --- a/lang/tr/settings.php +++ b/lang/tr/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Last Errored:', 'webhooks_last_error_message' => 'Son Hata Mesajı:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/uk/activities.php b/lang/uk/activities.php index f7d6d284c..1ab0eca61 100644 --- a/lang/uk/activities.php +++ b/lang/uk/activities.php @@ -93,11 +93,11 @@ return [ 'user_delete_notification' => 'Користувача успішно видалено', // API Tokens - 'api_token_create' => 'created API token', + 'api_token_create' => 'створений APi токен', 'api_token_create_notification' => 'API токен успішно створений', - 'api_token_update' => 'updated API token', + 'api_token_update' => 'оновлено API токен', 'api_token_update_notification' => 'Токен API успішно оновлено', - 'api_token_delete' => 'deleted API token', + 'api_token_delete' => 'видалено API токен', 'api_token_delete_notification' => 'API-токен успішно видалено', // Roles diff --git a/lang/uk/common.php b/lang/uk/common.php index c173e81d2..6e372914c 100644 --- a/lang/uk/common.php +++ b/lang/uk/common.php @@ -20,7 +20,7 @@ return [ 'description' => 'Опис', 'role' => 'Роль', 'cover_image' => 'Обкладинка', - 'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.', + 'cover_image_description' => 'Це зображення має бути приблизно 440х250пікс, щоб його було легко масштабувати та обводити відповідно до інтерфейсу користувача у різних сценаріях, як це необхідно, тому реальні розміри для відображення відрізняються.', // Actions 'actions' => 'Дії', diff --git a/lang/uk/editor.php b/lang/uk/editor.php index fb0d420b7..176f7fab7 100644 --- a/lang/uk/editor.php +++ b/lang/uk/editor.php @@ -81,9 +81,9 @@ return [ 'table_properties' => 'Властивості таблиці', 'table_properties_title' => 'Властивості таблиці', 'delete_table' => 'Видалити таблицю', - 'table_clear_formatting' => 'Clear table formatting', - 'resize_to_contents' => 'Resize to contents', - 'row_header' => 'Row header', + 'table_clear_formatting' => 'Очистити форматування таблиці', + 'resize_to_contents' => 'Змінити розмір до вмісту', + 'row_header' => 'Заголовок рядка', 'insert_row_before' => 'Вставити рядок перед', 'insert_row_after' => 'Вставити рядок після', 'delete_row' => 'Видалити рядок', diff --git a/lang/uk/entities.php b/lang/uk/entities.php index c26848d75..f2af67768 100644 --- a/lang/uk/entities.php +++ b/lang/uk/entities.php @@ -39,9 +39,9 @@ return [ 'export_pdf' => 'PDF файл', 'export_text' => 'Текстовий файл', 'export_md' => 'Файл розмітки', - 'default_template' => 'Default Page Template', - 'default_template_explain' => 'Assign a page template that will be used as the default content for all pages created within this item. Keep in mind this will only be used if the page creator has view access to the chosen template page.', - 'default_template_select' => 'Select a template page', + 'default_template' => 'Типовий шаблон сторінки', + 'default_template_explain' => 'Призначити шаблон сторінки, який буде використовуватися як типовий вміст для всіх сторінок, створених у цьому елементі. Майте на увазі, що ця сторінка буде використана лише у випадку, якщо вона має доступ до обраної сторінки шаблону.', + 'default_template_select' => 'Виберіть сторінку шаблону', // Permissions and restrictions 'permissions' => 'Дозволи', @@ -207,7 +207,7 @@ return [ 'pages_delete_draft' => 'Видалити чернетку', 'pages_delete_success' => 'Сторінка видалена', 'pages_delete_draft_success' => 'Чернетка видалена', - 'pages_delete_warning_template' => 'This page is in active use as a book or chapter default page template. These books or chapters will no longer have a default page template assigned after this page is deleted.', + 'pages_delete_warning_template' => 'Ця сторінка використовується в якості шаблону сторінки за промовчанням. У цих книгах або розділах більше не буде встановлено шаблон стандартної сторінки, який використовується після того, як ця сторінка буде видалена.', 'pages_delete_confirm' => 'Ви впевнені, що хочете видалити цю сторінку?', 'pages_delete_draft_confirm' => 'Ви впевнені, що хочете видалити цю чернетку?', 'pages_editing_named' => 'Редагування сторінки :pageName', diff --git a/lang/uk/errors.php b/lang/uk/errors.php index ece86cf89..92d91c183 100644 --- a/lang/uk/errors.php +++ b/lang/uk/errors.php @@ -10,7 +10,7 @@ return [ // Auth 'error_user_exists_different_creds' => 'Користувач з електронною адресою: електронна адреса вже існує, але з іншими обліковими даними.', - 'auth_pre_register_theme_prevention' => 'User account could not be registered for the provided details', + 'auth_pre_register_theme_prevention' => 'Обліковий запис користувача не може бути зареєстрований за наданими деталями', 'email_already_confirmed' => 'Електронна пошта вже підтверджена, спробуйте увійти.', 'email_confirmation_invalid' => 'Цей токен підтвердження недійсний або вже був використаний, будь ласка, спробуйте знову зареєструватися.', 'email_confirmation_expired' => 'Термін дії токена підтвердження минув, новий електронний лист підтвердження був відправлений.', diff --git a/lang/uk/preferences.php b/lang/uk/preferences.php index 2383c6793..14989d2a7 100644 --- a/lang/uk/preferences.php +++ b/lang/uk/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Зберегти налаштування', 'notifications_update_success' => 'Налаштування сповіщень було оновлено!', 'notifications_watched' => 'Переглянуті та ігноровані елементи', - 'notifications_watched_desc' => ' Нижче наведені предмети, які мають застосовані налаштування перегляду. Щоб оновити ваші налаштування для них, перегляньте елемент, а потім знайдіть параметри перегляду на бічній панелі.', + 'notifications_watched_desc' => 'Нижче наведені предмети, які мають застосовані налаштування перегляду. Щоб оновити ваші налаштування для них, перегляньте елемент, а потім знайдіть параметри перегляду на бічній панелі.', 'auth' => 'Доступ і безпека', 'auth_change_password' => 'Змінити пароль', diff --git a/lang/uk/settings.php b/lang/uk/settings.php index 3aaed0ef4..fb04a2930 100644 --- a/lang/uk/settings.php +++ b/lang/uk/settings.php @@ -109,7 +109,7 @@ return [ 'recycle_bin_contents_empty' => 'Зараз кошик порожній', 'recycle_bin_empty' => 'Очистити кошик', 'recycle_bin_empty_confirm' => 'Це назавжди знищить усі елементи в кошику, включаючи вміст кожного елементу. Ви впевнені, що хочете очистити кошик?', - 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item from the system, along with any child elements listed below, and you will not be able to restore this content. Are you sure you want to permanently delete this item?', + 'recycle_bin_destroy_confirm' => 'Ця дія назавжди видалить цей елемент з системи, разом з будь-яким дочірнім елементом, перерахованим нижче, і ви не зможете відновити цей контент. Ви дійсно бажаєте остаточно видалити цей елемент?', 'recycle_bin_destroy_list' => 'Елементи для знищення', 'recycle_bin_restore_list' => 'Елементи для відновлення', 'recycle_bin_restore_confirm' => 'Ця дія відновить видалений елемент у початкове місце, включаючи всі дочірні елементи. Якщо вихідне розташування відтоді було видалено, і знаходиться у кошику, батьківський елемент також потрібно буде відновити.', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Остання помилка:', 'webhooks_last_error_message' => 'Останнє повідомлення про помилку:', + // Licensing + 'licenses' => 'Ліцензії', + 'licenses_desc' => 'На цій сторінці детально описано ліцензійну інформацію для BookStack на додаток до проектів і бібліотек, які використовуються в BookStack. Багато проектів із списку можна використовувати лише в контексті розробки.', + 'licenses_bookstack' => 'Ліцензія BookStack', + 'licenses_php' => 'Ліцензії на бібліотеки PHP', + 'licenses_js' => 'Ліцензії бібліотеки JavaScript', + 'licenses_other' => 'Інші ліцензії', + 'license_details' => 'Про ліцензію', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/uz/preferences.php b/lang/uz/preferences.php index 9dedb0fb5..de36b953e 100644 --- a/lang/uz/preferences.php +++ b/lang/uz/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Afzalliklarni saqlash', 'notifications_update_success' => 'Bildirishnoma sozlamalari yangilandi!', 'notifications_watched' => 'Koʻrilgan va e\'tiborga olinmagan narsalar', - 'notifications_watched_desc' => ' Quyida maxsus soat sozlamalari qoʻllaniladigan elementlar mavjud. Bular uchun afzalliklaringizni yangilash uchun elementni koʻring, soʻngra yon paneldagi tomosha parametrlarini toping.', + 'notifications_watched_desc' => 'Quyida maxsus soat sozlamalari qoʻllaniladigan elementlar mavjud. Bular uchun afzalliklaringizni yangilash uchun elementni koʻring, soʻngra yon paneldagi tomosha parametrlarini toping.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/uz/settings.php b/lang/uz/settings.php index 07bbb2485..0d7c0415b 100644 --- a/lang/uz/settings.php +++ b/lang/uz/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Oxirgi xato:', 'webhooks_last_error_message' => 'Oxirgi xato xabari:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/vi/preferences.php b/lang/vi/preferences.php index 8c5fc5230..76bc0be16 100644 --- a/lang/vi/preferences.php +++ b/lang/vi/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => 'Save Preferences', 'notifications_update_success' => 'Notification preferences have been updated!', 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_watched_desc' => 'Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', 'auth' => 'Access & Security', 'auth_change_password' => 'Change Password', diff --git a/lang/vi/settings.php b/lang/vi/settings.php index 3ffb37fd3..a15128c2b 100644 --- a/lang/vi/settings.php +++ b/lang/vi/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => 'Lần cuối xảy ra lỗi:', 'webhooks_last_error_message' => 'Nội dung lỗi gần nhất:', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack License', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => 'Other Licenses', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/zh_CN/preferences.php b/lang/zh_CN/preferences.php index 0b5044137..f1ef3957d 100644 --- a/lang/zh_CN/preferences.php +++ b/lang/zh_CN/preferences.php @@ -27,7 +27,7 @@ return [ 'notifications_save' => '保存偏好设置', 'notifications_update_success' => '通知偏好设置已更新!', 'notifications_watched' => '已关注和忽略的项目', - 'notifications_watched_desc' => ' 下面是已应用自定义关注选项的项目。要更新您的关注设置,请查看该项目,然后在该项目的侧边栏中找到关注选项。', + 'notifications_watched_desc' => '下面是已应用自定义关注选项的项目。要更新您的关注设置,请查看该项目,然后在该项目的侧边栏中找到关注选项。', 'auth' => '访问与安全', 'auth_change_password' => '更改密码', diff --git a/lang/zh_CN/settings.php b/lang/zh_CN/settings.php index 4bf868af6..f5fcacdf1 100644 --- a/lang/zh_CN/settings.php +++ b/lang/zh_CN/settings.php @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => '最后一个错误:', 'webhooks_last_error_message' => '最后一个错误消息:', + // Licensing + 'licenses' => '许可证', + 'licenses_desc' => '除了 BookStack 中使用的项目和库之外,此页面还详细介绍了 BookStack 的许可证信息。列出的许多项目只能在开发环境中使用。', + 'licenses_bookstack' => 'BookStack 许可证', + 'licenses_php' => 'PHP 库许可证', + 'licenses_js' => 'JavaScript 库许可证', + 'licenses_other' => '其他许可证', + 'license_details' => '许可证细节', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. diff --git a/lang/zh_TW/activities.php b/lang/zh_TW/activities.php index 597131e77..dddca399a 100644 --- a/lang/zh_TW/activities.php +++ b/lang/zh_TW/activities.php @@ -50,31 +50,31 @@ return [ 'bookshelf_delete_notification' => '書棧已刪除', // Revisions - 'revision_restore' => 'restored revision', - 'revision_delete' => 'deleted revision', - 'revision_delete_notification' => 'Revision successfully deleted', + 'revision_restore' => '還原的版本', + 'revision_delete' => '刪除的版本', + 'revision_delete_notification' => '修訂已成功刪除', // Favourites 'favourite_add_notification' => '":name" 已加入到你的最愛', 'favourite_remove_notification' => '":name" 已從你的最愛移除', // Watching - 'watch_update_level_notification' => 'Watch preferences successfully updated', + 'watch_update_level_notification' => '追蹤偏好設定已成功更新', // Auth - 'auth_login' => 'logged in', - 'auth_register' => 'registered as new user', - 'auth_password_reset_request' => 'requested user password reset', - 'auth_password_reset_update' => 'reset user password', - 'mfa_setup_method' => 'configured MFA method', + 'auth_login' => '已登入', + 'auth_register' => '註冊為新用戶', + 'auth_password_reset_request' => '請求重置用戶密碼', + 'auth_password_reset_update' => '重置使用者密碼', + 'mfa_setup_method' => '設定MFA方式', 'mfa_setup_method_notification' => '多重身份驗證已設定成功', - 'mfa_remove_method' => 'removed MFA method', + 'mfa_remove_method' => '移除MFA方式', 'mfa_remove_method_notification' => '多重身份驗證已移除成功', // Settings - 'settings_update' => 'updated settings', + 'settings_update' => '更新設定', 'settings_update_notification' => '設定更新成功', - 'maintenance_action_run' => 'ran maintenance action', + 'maintenance_action_run' => '執行維護動作', // Webhooks 'webhook_create' => '建立 Webhook', @@ -85,39 +85,39 @@ return [ 'webhook_delete_notification' => 'Webhook 已刪除成功', // Users - 'user_create' => 'created user', - 'user_create_notification' => 'User successfully created', - 'user_update' => 'updated user', + 'user_create' => '建立使用者', + 'user_create_notification' => '使用者已成功建立。', + 'user_update' => '更新使用者', 'user_update_notification' => '使用者已成功更新。', - 'user_delete' => 'deleted user', + 'user_delete' => '已刪除使用者', 'user_delete_notification' => '使用者移除成功', // API Tokens - 'api_token_create' => 'created API token', - 'api_token_create_notification' => 'API token successfully created', - 'api_token_update' => 'updated API token', - 'api_token_update_notification' => 'API token successfully updated', - 'api_token_delete' => 'deleted API token', - 'api_token_delete_notification' => 'API token successfully deleted', + 'api_token_create' => '建立 API 權杖', + 'api_token_create_notification' => '成功建立 API 權杖', + 'api_token_update' => '已更新 API 權杖', + 'api_token_update_notification' => '成功更新 API 權杖', + 'api_token_delete' => '已刪除 API 權杖', + 'api_token_delete_notification' => 'API 權杖已成功刪除', // Roles - 'role_create' => 'created role', + 'role_create' => '創建角色', 'role_create_notification' => '建立角色成功', - 'role_update' => 'updated role', + 'role_update' => '已更新角色', 'role_update_notification' => '更新角色成功', - 'role_delete' => 'deleted role', + 'role_delete' => '已刪除角色', 'role_delete_notification' => '刪除角色成功', // Recycle Bin - 'recycle_bin_empty' => 'emptied recycle bin', - 'recycle_bin_restore' => 'restored from recycle bin', - 'recycle_bin_destroy' => 'removed from recycle bin', + 'recycle_bin_empty' => '清理資源回收筒', + 'recycle_bin_restore' => '從資源回收筒復原', + 'recycle_bin_destroy' => '從資源回收筒刪除', // Comments 'commented_on' => '評論', - 'comment_create' => 'added comment', - 'comment_update' => 'updated comment', - 'comment_delete' => 'deleted comment', + 'comment_create' => '新增評論', + 'comment_update' => '更新評論', + 'comment_delete' => '已刪除之評論', // Other 'permissions_update' => '更新權限', diff --git a/lang/zh_TW/common.php b/lang/zh_TW/common.php index 72f5969b8..1532d69dd 100644 --- a/lang/zh_TW/common.php +++ b/lang/zh_TW/common.php @@ -20,7 +20,7 @@ return [ 'description' => '描述', 'role' => '角色', 'cover_image' => '封面圖片', - 'cover_image_description' => 'This image should be approximately 440x250px although it will be flexibly scaled & cropped to fit the user interface in different scenarios as required, so actual dimensions for display will differ.', + 'cover_image_description' => '雖然圖片會在不同情境下自動調整顯示方式,但應接近 440x250 像素', // Actions 'actions' => '動作', diff --git a/lang/zh_TW/entities.php b/lang/zh_TW/entities.php index 3eb77f030..44f6e4754 100644 --- a/lang/zh_TW/entities.php +++ b/lang/zh_TW/entities.php @@ -327,7 +327,7 @@ return [ 'attachments_explain_instant_save' => '此處的變動將會立刻儲存。', 'attachments_upload' => '上傳檔案', 'attachments_link' => '附加連結', - 'attachments_upload_drop' => 'Alternatively you can drag and drop a file here to upload it as an attachment.', + 'attachments_upload_drop' => '你也可以將檔案拖曳到此來上傳附加檔案', 'attachments_set_link' => '設定連結', 'attachments_delete' => '您確定要刪除此附件嗎?', 'attachments_dropzone' => 'Drop files here to upload', @@ -379,7 +379,7 @@ return [ 'comment_updated_success' => '評論已更新', 'comment_delete_confirm' => '您確定要刪除這則評論?', 'comment_in_reply_to' => '回覆 :commentId', - 'comment_editor_explain' => 'Here are the comments that have been left on this page. Comments can be added & managed when viewing the saved page.', + 'comment_editor_explain' => '此為頁面上的評論。在查看檢視與儲存頁面的同時,可以新增和管理評論。', // Revision 'revision_delete_confirm' => '您確定要刪除此修訂版本嗎?', @@ -412,7 +412,7 @@ return [ 'references_to_desc' => 'Listed below is all the known content in the system that links to this item.', // Watch Options - 'watch' => 'Watch', + 'watch' => '追蹤', 'watch_title_default' => '預設偏好設定', 'watch_desc_default' => 'Revert watching to just your default notification preferences.', 'watch_title_ignore' => 'Ignore', diff --git a/lang/zh_TW/errors.php b/lang/zh_TW/errors.php index 4345d1613..05f7b035c 100644 --- a/lang/zh_TW/errors.php +++ b/lang/zh_TW/errors.php @@ -49,7 +49,7 @@ return [ // Drawing & Images 'image_upload_error' => '上傳圖片時發生錯誤', 'image_upload_type_error' => '上傳圖片類型無效', - 'image_upload_replace_type' => 'Image file replacements must be of the same type', + 'image_upload_replace_type' => '必須使用的檔案類型才能置換圖檔', 'image_upload_memory_limit' => 'Failed to handle image upload and/or create thumbnails due to system resource limits.', 'image_thumbnail_memory_limit' => 'Failed to create image size variations due to system resource limits.', 'image_gallery_thumbnail_memory_limit' => 'Failed to create gallery thumbnails due to system resource limits.', diff --git a/lang/zh_TW/preferences.php b/lang/zh_TW/preferences.php index 9bed83fd1..4900ca152 100644 --- a/lang/zh_TW/preferences.php +++ b/lang/zh_TW/preferences.php @@ -5,10 +5,10 @@ */ return [ - 'my_account' => 'My Account', + 'my_account' => '帳號設定', 'shortcuts' => '快捷鍵', - 'shortcuts_interface' => 'UI Shortcut Preferences', + 'shortcuts_interface' => '快速鍵設定', 'shortcuts_toggle_desc' => '您可以在此處啟用或停用鍵盤系統介面快捷鍵,這些快捷鍵用於導覽與操作。', 'shortcuts_customize_desc' => '您可以自訂下方的每個快捷鍵。只要在選取快捷鍵輸入後按下您想要使用的按鍵組合即可。', 'shortcuts_toggle_label' => '鍵盤快捷鍵已啟用', @@ -17,35 +17,35 @@ return [ 'shortcuts_save' => '儲存快捷鍵', 'shortcuts_overlay_desc' => '注意:當快捷鍵啟用時,可以按下「?」來使用小幫手覆蓋畫面。這將會在目前的畫面上突顯可見動作的快捷鍵。', 'shortcuts_update_success' => '快捷鍵偏好設定已更新!', - 'shortcuts_overview_desc' => 'Manage keyboard shortcuts you can use to navigate the system user interface.', + 'shortcuts_overview_desc' => '你可使用鍵盤快速鍵來快速瀏覽系統界面', - 'notifications' => 'Notification Preferences', - 'notifications_desc' => 'Control the email notifications you receive when certain activity is performed within the system.', - 'notifications_opt_own_page_changes' => 'Notify upon changes to pages I own', - 'notifications_opt_own_page_comments' => 'Notify upon comments on pages I own', - 'notifications_opt_comment_replies' => 'Notify upon replies to my comments', + 'notifications' => '通知設定', + 'notifications_desc' => '控制在系統有特定活動時,是否要接收電子郵件通知', + 'notifications_opt_own_page_changes' => '當我的頁面有異動時發送通知', + 'notifications_opt_own_page_comments' => '當我的頁面有評論時發送通知', + 'notifications_opt_comment_replies' => '當我的評論有新的回覆時發送通知', 'notifications_save' => '儲存偏好設定', - 'notifications_update_success' => 'Notification preferences have been updated!', - 'notifications_watched' => 'Watched & Ignored Items', - 'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.', + 'notifications_update_success' => '通知設定已更新', + 'notifications_watched' => '追蹤與忽略的項目', + 'notifications_watched_desc' => '以下是已經套用自訂追蹤設定的項目。若要調整,請至該項目側邊欄中的「追蹤」更新設定', - 'auth' => 'Access & Security', - 'auth_change_password' => 'Change Password', - 'auth_change_password_desc' => 'Change the password you use to log-in to the application. This must be at least 8 characters long.', - 'auth_change_password_success' => 'Password has been updated!', + 'auth' => '存取、安全', + 'auth_change_password' => '變更密碼', + 'auth_change_password_desc' => '修改登入時使用的密碼,密碼長度至少需要有 8 個字', + 'auth_change_password_success' => '密碼已更新', - 'profile' => 'Profile Details', - 'profile_desc' => 'Manage the details of your account which represents you to other users, in addition to details that are used for communication and system personalisation.', - 'profile_view_public' => 'View Public Profile', - 'profile_name_desc' => 'Configure your display name which will be visible to other users in the system through the activity you perform, and content you own.', - 'profile_email_desc' => 'This email will be used for notifications and, depending on active system authentication, system access.', - 'profile_email_no_permission' => 'Unfortunately you don\'t have permission to change your email address. If you want to change this, you\'d need to ask an administrator to change this for you.', - 'profile_avatar_desc' => 'Select an image which will be used to represent yourself to others in the system. Ideally this image should be square and about 256px in width and height.', - 'profile_admin_options' => 'Administrator Options', - 'profile_admin_options_desc' => 'Additional administrator-level options, like those to manage role assignments, can be found for your user account in the "Settings > Users" area of the application.', + 'profile' => '個人檔案', + 'profile_desc' => '管理欲呈現給其他使用的個人資料,另外資料也用於交流與系統個人化', + 'profile_view_public' => '檢視公開的個人檔案', + 'profile_name_desc' => '設定欲公開顯示的名稱,系統中的其他使用者將會透過內容、活動記錄看到您設定的名稱', + 'profile_email_desc' => 'Email 將用於使用者通知以及系統存取授權 (若有啟用)', + 'profile_email_no_permission' => '很遺憾您沒有權限變更您的 email,如果有需要,請洽詢系統管理員協助變更 email', + 'profile_avatar_desc' => ' 選一張圖片供顯示給其他使用者看,理想的圖片大小為 256x256 像素', + 'profile_admin_options' => '管理選項', + 'profile_admin_options_desc' => '系統管理層選項可在「設定」=>「使用者」找到,像是角色管理等', - 'delete_account' => 'Delete Account', - 'delete_my_account' => 'Delete My Account', - 'delete_my_account_desc' => 'This will fully delete your user account from the system. You will not be able to recover this account or revert this action. Content you\'ve created, such as created pages and uploaded images, will remain.', - 'delete_my_account_warning' => 'Are you sure you want to delete your account?', + 'delete_account' => '刪除帳號', + 'delete_my_account' => '刪除我的帳號', + 'delete_my_account_desc' => '將從系統中刪除所有帳號資料,此動作無法復原。你所建立的內容、頁面以及上傳的圖片將會保留。', + 'delete_my_account_warning' => '您確定要刪除您的帳戶嗎?', ]; diff --git a/lang/zh_TW/settings.php b/lang/zh_TW/settings.php index df7b0821b..938a1000c 100644 --- a/lang/zh_TW/settings.php +++ b/lang/zh_TW/settings.php @@ -34,7 +34,7 @@ return [ 'app_logo' => '應用程式圖示', 'app_logo_desc' => '這個設定會被使用在應用程式標題欄等區域;圖片的高度應為 86 像素,大型圖片將會按比例縮小。', 'app_icon' => '應用程式圖示', - 'app_icon_desc' => 'This icon is used for browser tabs and shortcut icons. This should be a 256px square PNG image.', + 'app_icon_desc' => '這個圖示將顯示在瀏覽器分頁以及捷徑,應為 256 像素的的正方形 PNG 圖片', 'app_homepage' => '應用程式首頁', 'app_homepage_desc' => '選取要作為首頁的頁面,這將會取代預設首頁。選定頁面的頁面權限將會被忽略。', 'app_homepage_select' => '選取頁面', @@ -276,6 +276,14 @@ return [ 'webhooks_last_errored' => '上次錯誤', 'webhooks_last_error_message' => '上次錯誤信息', + // Licensing + 'licenses' => 'Licenses', + 'licenses_desc' => 'This page details license information for BookStack in addition to the projects & libraries that are used within BookStack. Many projects listed may only be used in a development context.', + 'licenses_bookstack' => 'BookStack 授權', + 'licenses_php' => 'PHP Library Licenses', + 'licenses_js' => 'JavaScript Library Licenses', + 'licenses_other' => '其它授權', + 'license_details' => 'License Details', //! If editing translations files directly please ignore this in all //! languages apart from en. Content will be auto-copied from en. From a3a776d4a6d3a4d8d79c2a27a0e89dd929bd8b14 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 May 2024 15:47:38 +0100 Subject: [PATCH 59/59] Updated translator & dependency attribution before release v24.05 --- .github/translators.txt | 14 +++++- dev/licensing/js-library-licenses.txt | 60 +++++++++++++++++++------- dev/licensing/php-library-licenses.txt | 23 ++++------ 3 files changed, 65 insertions(+), 32 deletions(-) diff --git a/.github/translators.txt b/.github/translators.txt index f44042cd5..cf77951b0 100644 --- a/.github/translators.txt +++ b/.github/translators.txt @@ -389,7 +389,7 @@ Marc Hagen (MarcHagen) :: Dutch Kasper Alsøe (zeonos) :: Danish sultani :: Persian renge :: Korean -TheGatesDev (thegatesdev) :: Dutch +Tim (thegatesdev) :: Dutch; German Informal; Romanian; French; Catalan; Czech; Danish; German; Finnish; Hungarian; Italian; Japanese; Korean; Polish; Russian; Ukrainian; Chinese Simplified; Chinese Traditional; Portuguese, Brazilian; Persian; Spanish, Argentina; Croatian; Norwegian Nynorsk; Estonian; Uzbek; Norwegian Bokmal Irdi (irdiOL) :: Albanian KateBarber :: Welsh Twister (theuncles75) :: Hebrew @@ -410,3 +410,15 @@ cracrayol :: French CapuaSC :: Dutch Guardian75 :: German Informal mr-kanister :: German +Michele Bastianelli (makoblaster) :: Italian +jespernissen :: Danish +Andrey (avmaksimov) :: Russian +Gonzalo Loyola (AlFcl) :: Spanish, Argentina; Spanish +grobert63 :: French +wusst. (Supporti) :: German +MaximMaximS :: Czech +damian-klima :: Slovak +crow_ :: Latvian +JocelynDelalande :: French +Jan (JW-CH) :: German Informal +Timo B (lommes) :: German Informal diff --git a/dev/licensing/js-library-licenses.txt b/dev/licensing/js-library-licenses.txt index 56dc1ff75..8211a4a44 100644 --- a/dev/licensing/js-library-licenses.txt +++ b/dev/licensing/js-library-licenses.txt @@ -60,13 +60,6 @@ Copyright: Copyright (C) 2015 Jordan Harband Source: git://github.com/es-shims/array-includes.git Link: git://github.com/es-shims/array-includes.git ----------- -array.prototype.filter -License: MIT -License File: node_modules/array.prototype.filter/LICENSE -Copyright: Copyright (c) 2021 Jordan Harband -Source: git+https://github.com/es-shims/Array.prototype.filter.git -Link: https://github.com/es-shims/Array.prototype.filter#readme ------------ array.prototype.findlastindex License: MIT License File: node_modules/array.prototype.findlastindex/LICENSE @@ -112,7 +105,8 @@ Link: https://github.com/juliangruber/balanced-match binary-extensions License: MIT License File: node_modules/binary-extensions/license -Copyright: Copyright (c) 2019 Sindre Sorhus <************@*****.***> (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +Copyright: Copyright (c) Sindre Sorhus <************@*****.***> (https://sindresorhus.com) +Copyright (c) Paul Miller (https://paulmillr.com) Source: sindresorhus/binary-extensions Link: sindresorhus/binary-extensions ----------- @@ -226,6 +220,27 @@ Copyright: Copyright (c) 2018 Made With MOXY Lda <*****@****.******> Source: git@github.com:moxystudio/node-cross-spawn.git Link: https://github.com/moxystudio/node-cross-spawn ----------- +data-view-buffer +License: MIT +License File: node_modules/data-view-buffer/LICENSE +Copyright: Copyright (c) 2023 Jordan Harband +Source: git+https://github.com/ljharb/data-view-buffer.git +Link: https://github.com/ljharb/data-view-buffer#readme +----------- +data-view-byte-length +License: MIT +License File: node_modules/data-view-byte-length/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/data-view-byte-length.git +Link: https://github.com/ljharb/data-view-byte-length#readme +----------- +data-view-byte-offset +License: MIT +License File: node_modules/data-view-byte-offset/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/data-view-byte-offset.git +Link: https://github.com/ljharb/data-view-byte-offset#readme +----------- debug License: MIT License File: node_modules/debug/LICENSE @@ -298,13 +313,6 @@ Copyright: Copyright (C) 2015 Jordan Harband Source: git://github.com/ljharb/es-abstract.git Link: git://github.com/ljharb/es-abstract.git ----------- -es-array-method-boxes-properly -License: MIT -License File: node_modules/es-array-method-boxes-properly/LICENSE -Copyright: Copyright (c) 2019 Jordan Harband -Source: git+https://github.com/ljharb/es-array-method-boxes-properly.git -Link: https://github.com/ljharb/es-array-method-boxes-properly#readme ------------ es-define-property License: MIT License File: node_modules/es-define-property/LICENSE @@ -319,6 +327,13 @@ Copyright: Copyright (c) 2024 Jordan Harband Source: git+https://github.com/ljharb/es-errors.git Link: https://github.com/ljharb/es-errors#readme ----------- +es-object-atoms +License: MIT +License File: node_modules/es-object-atoms/LICENSE +Copyright: Copyright (c) 2024 Jordan Harband +Source: git+https://github.com/ljharb/es-object-atoms.git +Link: https://github.com/ljharb/es-object-atoms#readme +----------- es-set-tostringtag License: MIT License File: node_modules/es-set-tostringtag/LICENSE @@ -758,6 +773,13 @@ Copyright: Copyright (c) 2014 Dave Justice Source: git+https://github.com/inspect-js/is-core-module.git Link: https://github.com/inspect-js/is-core-module ----------- +is-data-view +License: MIT +License File: node_modules/is-data-view/LICENSE +Copyright: Copyright (c) 2024 Inspect JS +Source: git+https://github.com/inspect-js/is-data-view.git +Link: https://github.com/inspect-js/is-data-view#readme +----------- is-date-object License: MIT License File: node_modules/is-date-object/LICENSE @@ -1233,6 +1255,12 @@ Copyright: Copyright (c) George Zahariev Source: git://github.com/gkz/prelude-ls.git Link: http://preludels.com ----------- +punycode.js +License: MIT +License File: node_modules/punycode.js/LICENSE-MIT.txt +Source: https://github.com/mathiasbynens/punycode.js.git +Link: https://mths.be/punycode +----------- punycode License: MIT License File: node_modules/punycode/LICENSE-MIT.txt @@ -1753,7 +1781,7 @@ Link: https://github.com/codemirror/lang-php.git @codemirror/lang-xml License: MIT License File: node_modules/@codemirror/lang-xml/LICENSE -Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <*******@*****.***> and others +Copyright: Copyright (C) 2018-2021 by Marijn Haverbeke <******@*********.******> and others Source: https://github.com/codemirror/lang-xml.git Link: https://github.com/codemirror/lang-xml.git ----------- diff --git a/dev/licensing/php-library-licenses.txt b/dev/licensing/php-library-licenses.txt index 2e78ab845..045d64670 100644 --- a/dev/licensing/php-library-licenses.txt +++ b/dev/licensing/php-library-licenses.txt @@ -18,20 +18,6 @@ All rights reserved. Source: https://github.com/Bacon/BaconQrCode.git Link: https://github.com/Bacon/BaconQrCode ----------- -barryvdh/laravel-dompdf -License: MIT -License File: vendor/barryvdh/laravel-dompdf/LICENSE -Copyright: Copyright (c) 2021 barryvdh -Source: https://github.com/barryvdh/laravel-dompdf.git -Link: https://github.com/barryvdh/laravel-dompdf.git ------------ -barryvdh/laravel-snappy -License: MIT -License File: vendor/barryvdh/laravel-snappy/LICENSE -Copyright: Copyright (c) 2018 -Source: https://github.com/barryvdh/laravel-snappy.git -Link: https://github.com/barryvdh/laravel-snappy.git ------------ brick/math License: MIT License File: vendor/brick/math/LICENSE @@ -124,6 +110,13 @@ Copyright: Copyright (c) 2013-2023 Eduardo Gulias Davis Source: https://github.com/egulias/EmailValidator.git Link: https://github.com/egulias/EmailValidator ----------- +firebase/php-jwt +License: BSD-3-Clause +License File: vendor/firebase/php-jwt/LICENSE +Copyright: Copyright (c) 2011, Neuman Vong +Source: https://github.com/firebase/php-jwt.git +Link: https://github.com/firebase/php-jwt +----------- fruitcake/php-cors License: MIT License File: vendor/fruitcake/php-cors/LICENSE @@ -186,7 +179,7 @@ Link: https://github.com/guzzle/uri-template.git intervention/gif License: MIT License File: vendor/intervention/gif/LICENSE -Copyright: Copyright (c) 2020 Oliver Vogel +Copyright: Copyright (c) 2020-2024 Oliver Vogel Source: https://github.com/Intervention/gif.git Link: https://github.com/intervention/gif -----------