Merge branch 'master' into release

This commit is contained in:
Dan Brown 2021-06-13 14:25:39 +01:00
commit be26253a18
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
25 changed files with 436 additions and 308 deletions

View File

@ -332,7 +332,7 @@ class PageContent
protected function fetchSectionOfPage(Page $page, string $sectionId): string protected function fetchSectionOfPage(Page $page, string $sectionId): string
{ {
$topLevelTags = ['table', 'ul', 'ol']; $topLevelTags = ['table', 'ul', 'ol'];
$doc = $this->loadDocumentFromHtml('<body>' . $page->html . '</body>'); $doc = $this->loadDocumentFromHtml($page->html);
// Search included content for the id given and blank out if not exists. // Search included content for the id given and blank out if not exists.
$matchingElem = $doc->getElementById($sectionId); $matchingElem = $doc->getElementById($sectionId);
@ -363,6 +363,7 @@ class PageContent
{ {
libxml_use_internal_errors(true); libxml_use_internal_errors(true);
$doc = new DOMDocument(); $doc = new DOMDocument();
$html = '<body>' . $html . '</body>';
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
return $doc; return $doc;
} }

View File

@ -14,16 +14,14 @@ use Illuminate\Validation\ValidationException;
class AttachmentController extends Controller class AttachmentController extends Controller
{ {
protected $attachmentService; protected $attachmentService;
protected $attachment;
protected $pageRepo; protected $pageRepo;
/** /**
* AttachmentController constructor. * AttachmentController constructor.
*/ */
public function __construct(AttachmentService $attachmentService, Attachment $attachment, PageRepo $pageRepo) public function __construct(AttachmentService $attachmentService, PageRepo $pageRepo)
{ {
$this->attachmentService = $attachmentService; $this->attachmentService = $attachmentService;
$this->attachment = $attachment;
$this->pageRepo = $pageRepo; $this->pageRepo = $pageRepo;
} }
@ -67,7 +65,7 @@ class AttachmentController extends Controller
'file' => 'required|file' 'file' => 'required|file'
]); ]);
$attachment = $this->attachment->newQuery()->findOrFail($attachmentId); $attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('view', $attachment->page); $this->checkOwnablePermission('view', $attachment->page);
$this->checkOwnablePermission('page-update', $attachment->page); $this->checkOwnablePermission('page-update', $attachment->page);
$this->checkOwnablePermission('attachment-create', $attachment); $this->checkOwnablePermission('attachment-create', $attachment);
@ -89,7 +87,7 @@ class AttachmentController extends Controller
*/ */
public function getUpdateForm(string $attachmentId) public function getUpdateForm(string $attachmentId)
{ {
$attachment = $this->attachment->findOrFail($attachmentId); $attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('page-update', $attachment->page); $this->checkOwnablePermission('page-update', $attachment->page);
$this->checkOwnablePermission('attachment-create', $attachment); $this->checkOwnablePermission('attachment-create', $attachment);
@ -104,8 +102,8 @@ class AttachmentController extends Controller
*/ */
public function update(Request $request, string $attachmentId) public function update(Request $request, string $attachmentId)
{ {
$attachment = $this->attachment->newQuery()->findOrFail($attachmentId); /** @var Attachment $attachment */
$attachment = Attachment::query()->findOrFail($attachmentId);
try { try {
$this->validate($request, [ $this->validate($request, [
'attachment_edit_name' => 'required|string|min:1|max:255', 'attachment_edit_name' => 'required|string|min:1|max:255',
@ -160,7 +158,7 @@ class AttachmentController extends Controller
$attachmentName = $request->get('attachment_link_name'); $attachmentName = $request->get('attachment_link_name');
$link = $request->get('attachment_link_url'); $link = $request->get('attachment_link_url');
$attachment = $this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId)); $this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId));
return view('attachments.manager-link-form', [ return view('attachments.manager-link-form', [
'pageId' => $pageId, 'pageId' => $pageId,
@ -202,9 +200,10 @@ class AttachmentController extends Controller
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws NotFoundException * @throws NotFoundException
*/ */
public function get(string $attachmentId) public function get(Request $request, string $attachmentId)
{ {
$attachment = $this->attachment->findOrFail($attachmentId); /** @var Attachment $attachment */
$attachment = Attachment::query()->findOrFail($attachmentId);
try { try {
$page = $this->pageRepo->getById($attachment->uploaded_to); $page = $this->pageRepo->getById($attachment->uploaded_to);
} catch (NotFoundException $exception) { } catch (NotFoundException $exception) {
@ -217,8 +216,13 @@ class AttachmentController extends Controller
return redirect($attachment->path); return redirect($attachment->path);
} }
$fileName = $attachment->getFileName();
$attachmentContents = $this->attachmentService->getAttachmentFromStorage($attachment); $attachmentContents = $this->attachmentService->getAttachmentFromStorage($attachment);
return $this->downloadResponse($attachmentContents, $attachment->getFileName());
if ($request->get('open') === 'true') {
return $this->inlineDownloadResponse($attachmentContents, $fileName);
}
return $this->downloadResponse($attachmentContents, $fileName);
} }
/** /**
@ -227,7 +231,8 @@ class AttachmentController extends Controller
*/ */
public function delete(string $attachmentId) public function delete(string $attachmentId)
{ {
$attachment = $this->attachment->findOrFail($attachmentId); /** @var Attachment $attachment */
$attachment = Attachment::query()->findOrFail($attachmentId);
$this->checkOwnablePermission('attachment-delete', $attachment); $this->checkOwnablePermission('attachment-delete', $attachment);
$this->attachmentService->deleteFile($attachment); $this->attachmentService->deleteFile($attachment);
return response()->json(['message' => trans('entities.attachments_deleted')]); return response()->json(['message' => trans('entities.attachments_deleted')]);

View File

@ -6,6 +6,7 @@ use BookStack\Facades\Activity;
use BookStack\Interfaces\Loggable; use BookStack\Interfaces\Loggable;
use BookStack\HasCreatorAndUpdater; use BookStack\HasCreatorAndUpdater;
use BookStack\Model; use BookStack\Model;
use finfo;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\Exceptions\HttpResponseException;
@ -121,6 +122,20 @@ abstract class Controller extends BaseController
]); ]);
} }
/**
* Create a file download response that provides the file with a content-type
* correct for the file, in a way so the browser can show the content in browser.
*/
protected function inlineDownloadResponse(string $content, string $fileName): Response
{
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->buffer($content) ?: 'application/octet-stream';
return response()->make($content, 200, [
'Content-Type' => $mime,
'Content-Disposition' => 'inline; filename="' . $fileName . '"'
]);
}
/** /**
* Show a positive, successful notification to the user on next view load. * Show a positive, successful notification to the user on next view load.
*/ */

View File

@ -3,12 +3,14 @@
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Model; use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater; use BookStack\Traits\HasCreatorAndUpdater;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** /**
* @property int id * @property int id
* @property string name * @property string name
* @property string path * @property string path
* @property string extension * @property string extension
* @property ?Page page
* @property bool external * @property bool external
*/ */
class Attachment extends Model class Attachment extends Model
@ -31,9 +33,8 @@ class Attachment extends Model
/** /**
* Get the page this file was uploaded to. * Get the page this file was uploaded to.
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */
public function page() public function page(): BelongsTo
{ {
return $this->belongsTo(Page::class, 'uploaded_to'); return $this->belongsTo(Page::class, 'uploaded_to');
} }
@ -41,12 +42,12 @@ class Attachment extends Model
/** /**
* Get the url of this file. * Get the url of this file.
*/ */
public function getUrl(): string public function getUrl($openInline = false): string
{ {
if ($this->external && strpos($this->path, 'http') !== 0) { if ($this->external && strpos($this->path, 'http') !== 0) {
return $this->path; return $this->path;
} }
return url('/attachments/' . $this->id); return url('/attachments/' . $this->id . ($openInline ? '?open=true' : ''));
} }
/** /**

View File

@ -3,8 +3,10 @@
use BookStack\Exceptions\FileUploadException; use BookStack\Exceptions\FileUploadException;
use Exception; use Exception;
use Illuminate\Contracts\Filesystem\Factory as FileSystem; use Illuminate\Contracts\Filesystem\Factory as FileSystem;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance; use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Log;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
class AttachmentService class AttachmentService
@ -38,11 +40,9 @@ class AttachmentService
/** /**
* Get an attachment from storage. * Get an attachment from storage.
* @param Attachment $attachment * @throws FileNotFoundException
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/ */
public function getAttachmentFromStorage(Attachment $attachment) public function getAttachmentFromStorage(Attachment $attachment): string
{ {
return $this->getStorage()->get($attachment->path); return $this->getStorage()->get($attachment->path);
} }
@ -202,7 +202,7 @@ class AttachmentService
try { try {
$storage->put($attachmentPath, $attachmentData); $storage->put($attachmentPath, $attachmentData);
} catch (Exception $e) { } catch (Exception $e) {
\Log::error('Error when attempting file upload:' . $e->getMessage()); Log::error('Error when attempting file upload:' . $e->getMessage());
throw new FileUploadException(trans('errors.path_not_writable', ['filePath' => $attachmentPath])); throw new FileUploadException(trans('errors.path_not_writable', ['filePath' => $attachmentPath]));
} }

View File

@ -1,7 +1,6 @@
<?php namespace BookStack\Util; <?php namespace BookStack\Util;
use DOMDocument; use DOMDocument;
use DOMNode;
use DOMNodeList; use DOMNodeList;
use DOMXPath; use DOMXPath;
@ -16,6 +15,7 @@ class HtmlContentFilter
return $html; return $html;
} }
$html = '<body>' . $html . '</body>';
libxml_use_internal_errors(true); libxml_use_internal_errors(true);
$doc = new DOMDocument(); $doc = new DOMDocument();
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
@ -61,11 +61,10 @@ class HtmlContentFilter
/** /**
* Removed all of the given DOMNodes. * Removed all of the given DOMNodes.
*/ */
static protected function removeNodes(DOMNodeList $nodes): void protected static function removeNodes(DOMNodeList $nodes): void
{ {
foreach ($nodes as $node) { foreach ($nodes as $node) {
$node->parentNode->removeChild($node); $node->parentNode->removeChild($node);
} }
} }
}
}

View File

@ -8,6 +8,7 @@
"php": "^7.3|^8.0", "php": "^7.3|^8.0",
"ext-curl": "*", "ext-curl": "*",
"ext-dom": "*", "ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*", "ext-gd": "*",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",

305
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "b26d29958d84c91b164a8234d1a7e9e9", "content-hash": "eb3108f1a3a757df9b9a3a4f82b5db3b",
"packages": [ "packages": [
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.183.9", "version": "3.184.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "3b3aafdceac4cb820e2ae65a8785e4d07db471a7" "reference": "78fe691ab466fecf195209672f6c00c5d4ed219a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3b3aafdceac4cb820e2ae65a8785e4d07db471a7", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/78fe691ab466fecf195209672f6c00c5d4ed219a",
"reference": "3b3aafdceac4cb820e2ae65a8785e4d07db471a7", "reference": "78fe691ab466fecf195209672f6c00c5d4ed219a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -92,9 +92,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.183.9" "source": "https://github.com/aws/aws-sdk-php/tree/3.184.2"
}, },
"time": "2021-05-28T18:28:19+00:00" "time": "2021-06-11T18:20:15+00:00"
}, },
{ {
"name": "barryvdh/laravel-dompdf", "name": "barryvdh/laravel-dompdf",
@ -951,16 +951,16 @@
}, },
{ {
"name": "facade/flare-client-php", "name": "facade/flare-client-php",
"version": "1.8.0", "version": "1.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/facade/flare-client-php.git", "url": "https://github.com/facade/flare-client-php.git",
"reference": "69742118c037f34ee1ef86dc605be4a105d9e984" "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/facade/flare-client-php/zipball/69742118c037f34ee1ef86dc605be4a105d9e984", "url": "https://api.github.com/repos/facade/flare-client-php/zipball/47b639dc02bcfdfc4ebb83de703856fa01e35f5f",
"reference": "69742118c037f34ee1ef86dc605be4a105d9e984", "reference": "47b639dc02bcfdfc4ebb83de703856fa01e35f5f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1004,7 +1004,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/facade/flare-client-php/issues", "issues": "https://github.com/facade/flare-client-php/issues",
"source": "https://github.com/facade/flare-client-php/tree/1.8.0" "source": "https://github.com/facade/flare-client-php/tree/1.8.1"
}, },
"funding": [ "funding": [
{ {
@ -1012,7 +1012,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-04-30T11:11:50+00:00" "time": "2021-05-31T19:23:29+00:00"
}, },
{ {
"name": "facade/ignition", "name": "facade/ignition",
@ -1203,16 +1203,16 @@
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.12.1", "version": "2.13.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/filp/whoops.git", "url": "https://github.com/filp/whoops.git",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd" "reference": "2edbc73a4687d9085c8f20f398eebade844e8424"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd", "url": "https://api.github.com/repos/filp/whoops/zipball/2edbc73a4687d9085c8f20f398eebade844e8424",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd", "reference": "2edbc73a4687d9085c8f20f398eebade844e8424",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1262,7 +1262,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/filp/whoops/issues", "issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.12.1" "source": "https://github.com/filp/whoops/tree/2.13.0"
}, },
"funding": [ "funding": [
{ {
@ -1270,7 +1270,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-04-25T12:00:00+00:00" "time": "2021-06-04T12:00:00+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@ -2408,16 +2408,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.48.1", "version": "2.49.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16" "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8d1f50f1436fb4b05e7127360483dd9c6e73da16", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16", "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2497,7 +2497,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-26T22:08:38+00:00" "time": "2021-06-02T07:31:40+00:00"
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
@ -4072,16 +4072,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "1b15ca1b1bedda86f98064da9ff5d800560d4c6d" "reference": "a62acecdf5b50e314a4f305cd01b5282126f3095"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/1b15ca1b1bedda86f98064da9ff5d800560d4c6d", "url": "https://api.github.com/repos/symfony/console/zipball/a62acecdf5b50e314a4f305cd01b5282126f3095",
"reference": "1b15ca1b1bedda86f98064da9ff5d800560d4c6d", "reference": "a62acecdf5b50e314a4f305cd01b5282126f3095",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4141,7 +4141,7 @@
"description": "Eases the creation of beautiful and testable command line interfaces", "description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v4.4.24" "source": "https://github.com/symfony/console/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4157,20 +4157,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-13T06:28:07+00:00" "time": "2021-05-26T11:20:16+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/css-selector.git", "url": "https://github.com/symfony/css-selector.git",
"reference": "947cacaf1b3a2af6f13a435392873d5ddaba5f70" "reference": "c1e29de6dc893b130b45d20d8051efbb040560a9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/947cacaf1b3a2af6f13a435392873d5ddaba5f70", "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1e29de6dc893b130b45d20d8051efbb040560a9",
"reference": "947cacaf1b3a2af6f13a435392873d5ddaba5f70", "reference": "c1e29de6dc893b130b45d20d8051efbb040560a9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4206,7 +4206,7 @@
"description": "Converts CSS selectors to XPath expressions", "description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/css-selector/tree/v4.4.24" "source": "https://github.com/symfony/css-selector/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4222,20 +4222,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T09:52:47+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/debug", "name": "symfony/debug",
"version": "v4.4.22", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/debug.git", "url": "https://github.com/symfony/debug.git",
"reference": "45b2136377cca5f10af858968d6079a482bca473" "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/45b2136377cca5f10af858968d6079a482bca473", "url": "https://api.github.com/repos/symfony/debug/zipball/a8d2d5c94438548bff9f998ca874e202bb29d07f",
"reference": "45b2136377cca5f10af858968d6079a482bca473", "reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4275,7 +4275,7 @@
"description": "Provides tools to ease debugging PHP code", "description": "Provides tools to ease debugging PHP code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/debug/tree/v4.4.22" "source": "https://github.com/symfony/debug/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4291,7 +4291,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-02T07:50:12+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@ -4362,16 +4362,16 @@
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
"version": "v4.4.23", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/error-handler.git", "url": "https://github.com/symfony/error-handler.git",
"reference": "21d75bfbdfdd3581a7f97080deb98926987f14a7" "reference": "310a756cec00d29d89a08518405aded046a54a8b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/21d75bfbdfdd3581a7f97080deb98926987f14a7", "url": "https://api.github.com/repos/symfony/error-handler/zipball/310a756cec00d29d89a08518405aded046a54a8b",
"reference": "21d75bfbdfdd3581a7f97080deb98926987f14a7", "reference": "310a756cec00d29d89a08518405aded046a54a8b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4411,7 +4411,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code", "description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/error-handler/tree/v4.4.23" "source": "https://github.com/symfony/error-handler/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4427,20 +4427,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-02T20:47:26+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v4.4.20", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
"reference": "c352647244bd376bf7d31efbd5401f13f50dad0c" "reference": "047773e7016e4fd45102cedf4bd2558ae0d0c32f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c352647244bd376bf7d31efbd5401f13f50dad0c", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/047773e7016e4fd45102cedf4bd2558ae0d0c32f",
"reference": "c352647244bd376bf7d31efbd5401f13f50dad0c", "reference": "047773e7016e4fd45102cedf4bd2558ae0d0c32f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4494,7 +4494,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v4.4.20" "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4510,7 +4510,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-01-27T09:09:26+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/event-dispatcher-contracts", "name": "symfony/event-dispatcher-contracts",
@ -4593,16 +4593,16 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "a96bc19ed87c88eec78e1a4c803bdc1446952983" "reference": "ed33314396d968a8936c95f5bd1b88bd3b3e94a3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/a96bc19ed87c88eec78e1a4c803bdc1446952983", "url": "https://api.github.com/repos/symfony/finder/zipball/ed33314396d968a8936c95f5bd1b88bd3b3e94a3",
"reference": "a96bc19ed87c88eec78e1a4c803bdc1446952983", "reference": "ed33314396d968a8936c95f5bd1b88bd3b3e94a3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4634,7 +4634,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v4.4.24" "source": "https://github.com/symfony/finder/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4650,7 +4650,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T12:27:45+00:00" "time": "2021-05-26T11:20:16+00:00"
}, },
{ {
"name": "symfony/http-client-contracts", "name": "symfony/http-client-contracts",
@ -4732,16 +4732,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v4.4.23", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "2ffb43bd6c589a274ee1e93a5fd6b7ef1577b9c5" "reference": "0c79d5a65ace4fe66e49702658c024a419d2438b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/2ffb43bd6c589a274ee1e93a5fd6b7ef1577b9c5", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0c79d5a65ace4fe66e49702658c024a419d2438b",
"reference": "2ffb43bd6c589a274ee1e93a5fd6b7ef1577b9c5", "reference": "0c79d5a65ace4fe66e49702658c024a419d2438b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4780,7 +4780,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v4.4.23" "source": "https://github.com/symfony/http-foundation/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4796,20 +4796,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-05T07:40:41+00:00" "time": "2021-05-26T11:20:16+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "59925ee79f2541b4c6e990843e1a42768e898254" "reference": "3795165596fe81a52296b78c9aae938d434069cc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/59925ee79f2541b4c6e990843e1a42768e898254", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3795165596fe81a52296b78c9aae938d434069cc",
"reference": "59925ee79f2541b4c6e990843e1a42768e898254", "reference": "3795165596fe81a52296b78c9aae938d434069cc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4884,7 +4884,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v4.4.24" "source": "https://github.com/symfony/http-kernel/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -4900,20 +4900,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-19T12:12:19+00:00" "time": "2021-06-01T07:12:08+00:00"
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
"version": "v5.2.9", "version": "v5.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "64258e870f8cc75c3dae986201ea2df58c210b52" "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/64258e870f8cc75c3dae986201ea2df58c210b52", "url": "https://api.github.com/repos/symfony/mime/zipball/ed710d297b181f6a7194d8172c9c2423d58e4852",
"reference": "64258e870f8cc75c3dae986201ea2df58c210b52", "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4967,7 +4967,7 @@
"mime-type" "mime-type"
], ],
"support": { "support": {
"source": "https://github.com/symfony/mime/tree/v5.2.9" "source": "https://github.com/symfony/mime/tree/v5.3.0"
}, },
"funding": [ "funding": [
{ {
@ -4983,7 +4983,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T13:07:46+00:00" "time": "2021-05-26T17:43:10+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@ -5635,16 +5635,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v4.4.22", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "f5481b22729d465acb1cea3455fc04ce84b0148b" "reference": "cd61e6dd273975c6625316de9d141ebd197f93c9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/f5481b22729d465acb1cea3455fc04ce84b0148b", "url": "https://api.github.com/repos/symfony/process/zipball/cd61e6dd273975c6625316de9d141ebd197f93c9",
"reference": "f5481b22729d465acb1cea3455fc04ce84b0148b", "reference": "cd61e6dd273975c6625316de9d141ebd197f93c9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5676,7 +5676,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v4.4.22" "source": "https://github.com/symfony/process/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -5692,20 +5692,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-07T16:22:29+00:00" "time": "2021-05-26T11:20:16+00:00"
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "b42c3631fd9e3511610afb2ba081ea7e38d9fa38" "reference": "3a3c2f197ad0846ac6413225fc78868ba1c61434"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/b42c3631fd9e3511610afb2ba081ea7e38d9fa38", "url": "https://api.github.com/repos/symfony/routing/zipball/3a3c2f197ad0846ac6413225fc78868ba1c61434",
"reference": "b42c3631fd9e3511610afb2ba081ea7e38d9fa38", "reference": "3a3c2f197ad0846ac6413225fc78868ba1c61434",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5764,7 +5764,7 @@
"url" "url"
], ],
"support": { "support": {
"source": "https://github.com/symfony/routing/tree/v4.4.24" "source": "https://github.com/symfony/routing/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -5780,7 +5780,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T09:52:47+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
@ -5863,16 +5863,16 @@
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "424d29dfcc15575af05196de0100d7b52f650602" "reference": "dfe132c5c6d89f90ce7f961742cc532e9ca16dd4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/424d29dfcc15575af05196de0100d7b52f650602", "url": "https://api.github.com/repos/symfony/translation/zipball/dfe132c5c6d89f90ce7f961742cc532e9ca16dd4",
"reference": "424d29dfcc15575af05196de0100d7b52f650602", "reference": "dfe132c5c6d89f90ce7f961742cc532e9ca16dd4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5931,7 +5931,7 @@
"description": "Provides tools to internationalize your application", "description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/translation/tree/v4.4.24" "source": "https://github.com/symfony/translation/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -5947,7 +5947,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T09:52:47+00:00" "time": "2021-05-26T17:39:37+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@ -6029,16 +6029,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v4.4.22", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "c194bcedde6295f3ec3e9eba1f5d484ea97c41a7" "reference": "31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/c194bcedde6295f3ec3e9eba1f5d484ea97c41a7", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0",
"reference": "c194bcedde6295f3ec3e9eba1f5d484ea97c41a7", "reference": "31ea689a8e7d2410016b0d25fc15a1ba05a6e2e0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6098,7 +6098,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v4.4.22" "source": "https://github.com/symfony/var-dumper/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -6114,7 +6114,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-19T13:36:17+00:00" "time": "2021-05-27T09:48:32+00:00"
}, },
{ {
"name": "tijsverkoyen/css-to-inline-styles", "name": "tijsverkoyen/css-to-inline-styles",
@ -6250,16 +6250,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "barryvdh/laravel-debugbar", "name": "barryvdh/laravel-debugbar",
"version": "v3.5.7", "version": "v3.6.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git", "url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "88fd9cfa144b06b2549e9d487fdaec68265e791e" "reference": "f6f0f895a33cac801286a74355d146bb5384a5da"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/88fd9cfa144b06b2549e9d487fdaec68265e791e", "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f6f0f895a33cac801286a74355d146bb5384a5da",
"reference": "88fd9cfa144b06b2549e9d487fdaec68265e791e", "reference": "f6f0f895a33cac801286a74355d146bb5384a5da",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6319,7 +6319,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues", "issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.7" "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.1"
}, },
"funding": [ "funding": [
{ {
@ -6327,7 +6327,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-05-13T20:18:35+00:00" "time": "2021-06-02T06:42:22+00:00"
}, },
{ {
"name": "barryvdh/laravel-ide-helper", "name": "barryvdh/laravel-ide-helper",
@ -6469,16 +6469,16 @@
}, },
{ {
"name": "composer/ca-bundle", "name": "composer/ca-bundle",
"version": "1.2.9", "version": "1.2.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/ca-bundle.git", "url": "https://github.com/composer/ca-bundle.git",
"reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5" "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/78a0e288fdcebf92aa2318a8d3656168da6ac1a5", "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8",
"reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5", "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6525,7 +6525,7 @@
"support": { "support": {
"irc": "irc://irc.freenode.org/composer", "irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues", "issues": "https://github.com/composer/ca-bundle/issues",
"source": "https://github.com/composer/ca-bundle/tree/1.2.9" "source": "https://github.com/composer/ca-bundle/tree/1.2.10"
}, },
"funding": [ "funding": [
{ {
@ -6541,20 +6541,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-01-12T12:10:35+00:00" "time": "2021-06-07T13:58:28+00:00"
}, },
{ {
"name": "composer/composer", "name": "composer/composer",
"version": "2.0.14", "version": "2.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/composer.git", "url": "https://github.com/composer/composer.git",
"reference": "92b2ccbef65292ba9f2004271ef47c7231e2eed5" "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/composer/zipball/92b2ccbef65292ba9f2004271ef47c7231e2eed5", "url": "https://api.github.com/repos/composer/composer/zipball/fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
"reference": "92b2ccbef65292ba9f2004271ef47c7231e2eed5", "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6589,7 +6589,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.0-dev" "dev-master": "2.1-dev"
} }
}, },
"autoload": { "autoload": {
@ -6623,7 +6623,7 @@
"support": { "support": {
"irc": "irc://irc.freenode.org/composer", "irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/composer/issues", "issues": "https://github.com/composer/composer/issues",
"source": "https://github.com/composer/composer/tree/2.0.14" "source": "https://github.com/composer/composer/tree/2.1.3"
}, },
"funding": [ "funding": [
{ {
@ -6639,7 +6639,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-21T15:03:37+00:00" "time": "2021-06-09T14:31:20+00:00"
}, },
{ {
"name": "composer/metadata-minifier", "name": "composer/metadata-minifier",
@ -8161,16 +8161,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "9.5.4", "version": "9.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "c73c6737305e779771147af66c96ca6a7ed8a741" "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276",
"reference": "c73c6737305e779771147af66c96ca6a7ed8a741", "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8200,7 +8200,7 @@
"sebastian/global-state": "^5.0.1", "sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3", "sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3", "sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^2.3", "sebastian/type": "^2.3.2",
"sebastian/version": "^3.0.2" "sebastian/version": "^3.0.2"
}, },
"require-dev": { "require-dev": {
@ -8248,7 +8248,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5"
}, },
"funding": [ "funding": [
{ {
@ -8260,7 +8260,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-03-23T07:16:29+00:00" "time": "2021-06-05T04:49:07+00:00"
}, },
{ {
"name": "react/promise", "name": "react/promise",
@ -8818,16 +8818,16 @@
}, },
{ {
"name": "sebastian/global-state", "name": "sebastian/global-state",
"version": "5.0.2", "version": "5.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git", "url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "a90ccbddffa067b51f574dea6eb25d5680839455" "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49",
"reference": "a90ccbddffa067b51f574dea6eb25d5680839455", "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8870,7 +8870,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues", "issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2" "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3"
}, },
"funding": [ "funding": [
{ {
@ -8878,7 +8878,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-26T15:55:19+00:00" "time": "2021-06-11T13:31:12+00:00"
}, },
{ {
"name": "sebastian/lines-of-code", "name": "sebastian/lines-of-code",
@ -9169,16 +9169,16 @@
}, },
{ {
"name": "sebastian/type", "name": "sebastian/type",
"version": "2.3.1", "version": "2.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/type.git", "url": "https://github.com/sebastianbergmann/type.git",
"reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0d1c587401514d17e8f9258a27e23527cb1b06c1",
"reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9213,7 +9213,7 @@
"homepage": "https://github.com/sebastianbergmann/type", "homepage": "https://github.com/sebastianbergmann/type",
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/type/issues", "issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/2.3.1" "source": "https://github.com/sebastianbergmann/type/tree/2.3.2"
}, },
"funding": [ "funding": [
{ {
@ -9221,7 +9221,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-26T13:18:59+00:00" "time": "2021-06-04T13:02:07+00:00"
}, },
{ {
"name": "sebastian/version", "name": "sebastian/version",
@ -9445,16 +9445,16 @@
}, },
{ {
"name": "symfony/dom-crawler", "name": "symfony/dom-crawler",
"version": "v4.4.24", "version": "v4.4.25",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dom-crawler.git", "url": "https://github.com/symfony/dom-crawler.git",
"reference": "fc0bd1f215b0cd9f4efdc63bb66808f3417331bc" "reference": "41d15bb6d6b95d2be763c514bb2494215d9c5eef"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/fc0bd1f215b0cd9f4efdc63bb66808f3417331bc", "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/41d15bb6d6b95d2be763c514bb2494215d9c5eef",
"reference": "fc0bd1f215b0cd9f4efdc63bb66808f3417331bc", "reference": "41d15bb6d6b95d2be763c514bb2494215d9c5eef",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9498,7 +9498,7 @@
"description": "Eases DOM navigation for HTML and XML documents", "description": "Eases DOM navigation for HTML and XML documents",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/dom-crawler/tree/v4.4.24" "source": "https://github.com/symfony/dom-crawler/tree/v4.4.25"
}, },
"funding": [ "funding": [
{ {
@ -9514,20 +9514,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-16T09:52:47+00:00" "time": "2021-05-26T11:20:16+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v5.2.7", "version": "v5.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0" "reference": "348116319d7fb7d1faa781d26a48922428013eb2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/056e92acc21d977c37e6ea8e97374b2a6c8551b0", "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2",
"reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0", "reference": "348116319d7fb7d1faa781d26a48922428013eb2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9560,7 +9560,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v5.2.7" "source": "https://github.com/symfony/filesystem/tree/v5.3.0"
}, },
"funding": [ "funding": [
{ {
@ -9576,7 +9576,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-01T10:42:13+00:00" "time": "2021-05-26T17:43:10+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
@ -9696,6 +9696,7 @@
"php": "^7.3|^8.0", "php": "^7.3|^8.0",
"ext-curl": "*", "ext-curl": "*",
"ext-dom": "*", "ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*", "ext-gd": "*",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",

40
package-lock.json generated
View File

@ -14,11 +14,11 @@
}, },
"devDependencies": { "devDependencies": {
"chokidar-cli": "^2.1.0", "chokidar-cli": "^2.1.0",
"esbuild": "0.12.5", "esbuild": "0.12.8",
"livereload": "^0.9.3", "livereload": "^0.9.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"punycode": "^2.1.1", "punycode": "^2.1.1",
"sass": "^1.34.0" "sass": "^1.34.1"
} }
}, },
"node_modules/ansi-regex": { "node_modules/ansi-regex": {
@ -313,9 +313,9 @@
} }
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.12.5", "version": "0.12.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.5.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.8.tgz",
"integrity": "sha512-vcuP53pA5XiwUU4FnlXM+2PnVjTfHGthM7uP1gtp+9yfheGvFFbq/KyuESThmtoHPUrfZH5JpxGVJIFDVD1Egw==", "integrity": "sha512-sx/LwlP/SWTGsd9G4RlOPrXnIihAJ2xwBUmzoqe2nWwbXORMQWtAGNJNYLBJJqa3e9PWvVzxdrtyFZJcr7D87g==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
@ -384,9 +384,9 @@
} }
}, },
"node_modules/glob-parent": { "node_modules/glob-parent": {
"version": "5.1.1", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"is-glob": "^4.0.1" "is-glob": "^4.0.1"
@ -980,9 +980,9 @@
} }
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.34.0", "version": "1.34.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.34.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.34.1.tgz",
"integrity": "sha512-rHEN0BscqjUYuomUEaqq3BMgsXqQfkcMVR7UhscsAVub0/spUrZGBMxQXFS2kfiDsPLZw5yuU9iJEFNC2x38Qw==", "integrity": "sha512-scLA7EIZM+MmYlej6sdVr0HRbZX5caX5ofDT9asWnUJj21oqgsC+1LuNfm0eg+vM0fCTZHhwImTiCU0sx9h9CQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": ">=3.0.0 <4.0.0" "chokidar": ">=3.0.0 <4.0.0"
@ -1521,9 +1521,9 @@
} }
}, },
"esbuild": { "esbuild": {
"version": "0.12.5", "version": "0.12.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.5.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.8.tgz",
"integrity": "sha512-vcuP53pA5XiwUU4FnlXM+2PnVjTfHGthM7uP1gtp+9yfheGvFFbq/KyuESThmtoHPUrfZH5JpxGVJIFDVD1Egw==", "integrity": "sha512-sx/LwlP/SWTGsd9G4RlOPrXnIihAJ2xwBUmzoqe2nWwbXORMQWtAGNJNYLBJJqa3e9PWvVzxdrtyFZJcr7D87g==",
"dev": true "dev": true
}, },
"escape-string-regexp": { "escape-string-regexp": {
@ -1570,9 +1570,9 @@
"dev": true "dev": true
}, },
"glob-parent": { "glob-parent": {
"version": "5.1.1", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true, "dev": true,
"requires": { "requires": {
"is-glob": "^4.0.1" "is-glob": "^4.0.1"
@ -2032,9 +2032,9 @@
} }
}, },
"sass": { "sass": {
"version": "1.34.0", "version": "1.34.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.34.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.34.1.tgz",
"integrity": "sha512-rHEN0BscqjUYuomUEaqq3BMgsXqQfkcMVR7UhscsAVub0/spUrZGBMxQXFS2kfiDsPLZw5yuU9iJEFNC2x38Qw==", "integrity": "sha512-scLA7EIZM+MmYlej6sdVr0HRbZX5caX5ofDT9asWnUJj21oqgsC+1LuNfm0eg+vM0fCTZHhwImTiCU0sx9h9CQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": ">=3.0.0 <4.0.0" "chokidar": ">=3.0.0 <4.0.0"

View File

@ -16,11 +16,11 @@
}, },
"devDependencies": { "devDependencies": {
"chokidar-cli": "^2.1.0", "chokidar-cli": "^2.1.0",
"esbuild": "0.12.5", "esbuild": "0.12.8",
"livereload": "^0.9.3", "livereload": "^0.9.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"punycode": "^2.1.1", "punycode": "^2.1.1",
"sass": "^1.34.0" "sass": "^1.34.1"
}, },
"dependencies": { "dependencies": {
"clipboard": "^2.0.8", "clipboard": "^2.0.8",

View File

@ -0,0 +1,47 @@
/**
* Attachments List
* Adds '?open=true' query to file attachment links
* when ctrl/cmd is pressed down.
* @extends {Component}
*/
class AttachmentsList {
setup() {
this.container = this.$el;
this.setupListeners();
}
setupListeners() {
const isExpectedKey = (event) => event.key === 'Control' || event.key === 'Meta';
window.addEventListener('keydown', event => {
if (isExpectedKey(event)) {
this.addOpenQueryToLinks();
}
}, {passive: true});
window.addEventListener('keyup', event => {
if (isExpectedKey(event)) {
this.removeOpenQueryFromLinks();
}
}, {passive: true});
}
addOpenQueryToLinks() {
const links = this.container.querySelectorAll('a.attachment-file');
for (const link of links) {
if (link.href.split('?')[1] !== 'open=true') {
link.href = link.href + '?open=true';
link.setAttribute('target', '_blank');
}
}
}
removeOpenQueryFromLinks() {
const links = this.container.querySelectorAll('a.attachment-file');
for (const link of links) {
link.href = link.href.split('?')[0];
link.removeAttribute('target');
}
}
}
export default AttachmentsList;

View File

@ -2,6 +2,7 @@ import addRemoveRows from "./add-remove-rows.js"
import ajaxDeleteRow from "./ajax-delete-row.js" import ajaxDeleteRow from "./ajax-delete-row.js"
import ajaxForm from "./ajax-form.js" import ajaxForm from "./ajax-form.js"
import attachments from "./attachments.js" import attachments from "./attachments.js"
import attachmentsList from "./attachments-list.js"
import autoSuggest from "./auto-suggest.js" import autoSuggest from "./auto-suggest.js"
import backToTop from "./back-to-top.js" import backToTop from "./back-to-top.js"
import bookSort from "./book-sort.js" import bookSort from "./book-sort.js"
@ -56,6 +57,7 @@ const componentMapping = {
"ajax-delete-row": ajaxDeleteRow, "ajax-delete-row": ajaxDeleteRow,
"ajax-form": ajaxForm, "ajax-form": ajaxForm,
"attachments": attachments, "attachments": attachments,
"attachments-list": attachmentsList,
"auto-suggest": autoSuggest, "auto-suggest": autoSuggest,
"back-to-top": backToTop, "back-to-top": backToTop,
"book-sort": bookSort, "book-sort": bookSort,

View File

@ -31,7 +31,7 @@ return [
'app_custom_html_desc' => 'Cualquier contenido agregado aquí será agregado al final de la sección <head> de cada página. Esto es útil para sobreescribir estilos o agregar código para analíticas.', 'app_custom_html_desc' => 'Cualquier contenido agregado aquí será agregado al final de la sección <head> de cada página. Esto es útil para sobreescribir estilos o agregar código para analíticas.',
'app_custom_html_disabled_notice' => 'El contenido personailzado para la cabecera HTML está deshabilitado en esta configuración para garantizar que cualquier cambio importante se pueda revertir.', 'app_custom_html_disabled_notice' => 'El contenido personailzado para la cabecera HTML está deshabilitado en esta configuración para garantizar que cualquier cambio importante se pueda revertir.',
'app_logo' => 'Logo de la aplicación', 'app_logo' => 'Logo de la aplicación',
'app_logo_desc' => 'Esta imagen debería ser de 43px en altura. <br>Las imágenes grandes seán escaladas.', 'app_logo_desc' => 'Esta imagen debería ser de 43px en altura. <br>Las imágenes grandes serán achicadas.',
'app_primary_color' => 'Color primario de la aplicación', 'app_primary_color' => 'Color primario de la aplicación',
'app_primary_color_desc' => 'Esto debería ser un valor hexadecimal. <br>Deje el valor vacío para reiniciar al valor por defecto.', 'app_primary_color_desc' => 'Esto debería ser un valor hexadecimal. <br>Deje el valor vacío para reiniciar al valor por defecto.',
'app_homepage' => 'Página de inicio de la Aplicación', 'app_homepage' => 'Página de inicio de la Aplicación',

View File

@ -40,10 +40,10 @@ return [
'remove' => 'Hapus', 'remove' => 'Hapus',
'add' => 'Tambah', 'add' => 'Tambah',
'fullscreen' => 'Layar Penuh', 'fullscreen' => 'Layar Penuh',
'favourite' => 'Favourite', 'favourite' => 'Favorit',
'unfavourite' => 'Unfavourite', 'unfavourite' => 'Tidak favorit',
'next' => 'Next', 'next' => 'Lanjut',
'previous' => 'Previous', 'previous' => 'Sebelumnya',
// Sort Options // Sort Options
'sort_options' => 'Sortir Pilihan', 'sort_options' => 'Sortir Pilihan',

View File

@ -27,8 +27,8 @@ return [
'images' => 'Gambar-gambar', 'images' => 'Gambar-gambar',
'my_recent_drafts' => 'Draf Terbaru Saya', 'my_recent_drafts' => 'Draf Terbaru Saya',
'my_recently_viewed' => 'Baru saja saya lihat', 'my_recently_viewed' => 'Baru saja saya lihat',
'my_most_viewed_favourites' => 'My Most Viewed Favourites', 'my_most_viewed_favourites' => 'Favorit Saya yang Paling Banyak Dilihat',
'my_favourites' => 'My Favourites', 'my_favourites' => 'Favoritku',
'no_pages_viewed' => 'Anda belum melihat halaman apa pun', 'no_pages_viewed' => 'Anda belum melihat halaman apa pun',
'no_pages_recently_created' => 'Tidak ada halaman yang baru saja dibuat', 'no_pages_recently_created' => 'Tidak ada halaman yang baru saja dibuat',
'no_pages_recently_updated' => 'Tidak ada halaman yang baru-baru ini diperbarui', 'no_pages_recently_updated' => 'Tidak ada halaman yang baru-baru ini diperbarui',
@ -120,7 +120,7 @@ return [
'books_delete_explain' => 'Ini akan menghapus buku dengan nama \': bookName\'. Semua halaman dan bab akan dihapus.', 'books_delete_explain' => 'Ini akan menghapus buku dengan nama \': bookName\'. Semua halaman dan bab akan dihapus.',
'books_delete_confirmation' => 'Apakah Anda yakin ingin menghapus buku ini?', 'books_delete_confirmation' => 'Apakah Anda yakin ingin menghapus buku ini?',
'books_edit' => 'Edit Buku', 'books_edit' => 'Edit Buku',
'books_edit_named' => 'Edit Buku :bookName', 'books_edit_named' => 'Sunting Buku :bookName',
'books_form_book_name' => 'Nama Buku', 'books_form_book_name' => 'Nama Buku',
'books_save' => 'Simpan Buku', 'books_save' => 'Simpan Buku',
'books_permissions' => 'Izin Buku', 'books_permissions' => 'Izin Buku',
@ -154,7 +154,7 @@ return [
'chapters_delete_explain' => 'Ini akan menghapus chapter dengan nama \':chapterName\'. Semua halaman yang ada dalam bab ini juga akan dihapus.', 'chapters_delete_explain' => 'Ini akan menghapus chapter dengan nama \':chapterName\'. Semua halaman yang ada dalam bab ini juga akan dihapus.',
'chapters_delete_confirm' => 'Anda yakin ingin menghapus bab ini?', 'chapters_delete_confirm' => 'Anda yakin ingin menghapus bab ini?',
'chapters_edit' => 'Edit Bab', 'chapters_edit' => 'Edit Bab',
'chapters_edit_named' => 'Edit Bab :chapterName', 'chapters_edit_named' => 'Sunting Bab :chapterName',
'chapters_save' => 'Simpan Bab', 'chapters_save' => 'Simpan Bab',
'chapters_move' => 'Pindahkan Bab', 'chapters_move' => 'Pindahkan Bab',
'chapters_move_named' => 'Pindahkan Bab :chapterName', 'chapters_move_named' => 'Pindahkan Bab :chapterName',
@ -181,7 +181,7 @@ return [
'pages_delete_draft_success' => 'Halaman draf dihapus', 'pages_delete_draft_success' => 'Halaman draf dihapus',
'pages_delete_confirm' => 'Anda yakin ingin menghapus halaman ini?', 'pages_delete_confirm' => 'Anda yakin ingin menghapus halaman ini?',
'pages_delete_draft_confirm' => 'Anda yakin ingin menghapus halaman draf ini?', 'pages_delete_draft_confirm' => 'Anda yakin ingin menghapus halaman draf ini?',
'pages_editing_named' => 'Mengedit Halaman :pageName', 'pages_editing_named' => 'Menyunting Halaman :pageName',
'pages_edit_draft_options' => 'Opsi Draf', 'pages_edit_draft_options' => 'Opsi Draf',
'pages_edit_save_draft' => 'Simpan Draf', 'pages_edit_save_draft' => 'Simpan Draf',
'pages_edit_draft' => 'Edit Halaman Draf', 'pages_edit_draft' => 'Edit Halaman Draf',
@ -190,7 +190,7 @@ return [
'pages_edit_draft_save_at' => 'Draf disimpan pada ', 'pages_edit_draft_save_at' => 'Draf disimpan pada ',
'pages_edit_delete_draft' => 'Hapus Draf', 'pages_edit_delete_draft' => 'Hapus Draf',
'pages_edit_discard_draft' => 'Buang Draf', 'pages_edit_discard_draft' => 'Buang Draf',
'pages_edit_set_changelog' => 'Setel Changelog', 'pages_edit_set_changelog' => 'Atur Changelog',
'pages_edit_enter_changelog_desc' => 'Masukkan deskripsi singkat tentang perubahan yang Anda buat', 'pages_edit_enter_changelog_desc' => 'Masukkan deskripsi singkat tentang perubahan yang Anda buat',
'pages_edit_enter_changelog' => 'Masuk ke Changelog', 'pages_edit_enter_changelog' => 'Masuk ke Changelog',
'pages_save' => 'Simpan Halaman', 'pages_save' => 'Simpan Halaman',
@ -226,20 +226,20 @@ return [
'pages_revisions_restore' => 'Mengembalikan', 'pages_revisions_restore' => 'Mengembalikan',
'pages_revisions_none' => 'Halaman ini tidak memiliki revisi', 'pages_revisions_none' => 'Halaman ini tidak memiliki revisi',
'pages_copy_link' => 'Salin tautan', 'pages_copy_link' => 'Salin tautan',
'pages_edit_content_link' => 'Edit Konten', 'pages_edit_content_link' => 'Sunting Konten',
'pages_permissions_active' => 'Izin Halaman Aktif', 'pages_permissions_active' => 'Izin Halaman Aktif',
'pages_initial_revision' => 'Penerbitan awal', 'pages_initial_revision' => 'Penerbitan awal',
'pages_initial_name' => 'Halaman Baru', 'pages_initial_name' => 'Halaman Baru',
'pages_editing_draft_notification' => 'Anda sedang mengedit draf yang terakhir disimpan :timeDiff.', 'pages_editing_draft_notification' => 'Anda sedang menyunting konsep yang terakhir disimpan :timeDiff.',
'pages_draft_edited_notification' => 'Halaman ini telah diperbarui sejak saat itu. Anda disarankan untuk membuang draf ini.', 'pages_draft_edited_notification' => 'Halaman ini telah diperbarui sejak saat itu. Anda disarankan untuk membuang draf ini.',
'pages_draft_edit_active' => [ 'pages_draft_edit_active' => [
'start_a' => ':count pengguna sudah mulai mengedit halaman ini', 'start_a' => ':count pengguna sudah mulai mengedit halaman ini',
'start_b' => ':userName sudah mulai mengedit halaman ini', 'start_b' => ':userName telah memulai menyunting halaman ini',
'time_a' => 'perubahan di sini disimpan secara instan', 'time_a' => 'semenjak halaman terakhir diperbarui',
'time_b' => 'di akhir :minCount menit', 'time_b' => 'di akhir :minCount menit',
'message' => ':start :time. Berhati-hatilah untuk tidak menimpa pembaruan satu sama lain!', 'message' => ':start :time. Berhati-hatilah untuk tidak menimpa pembaruan satu sama lain!',
], ],
'pages_draft_discarded' => 'Draf dibuang, Editor telah diperbarui dengan konten halaman saat ini', 'pages_draft_discarded' => 'Konsep dibuang, Penyunting telah diperbarui dengan konten halaman saat ini',
'pages_specific' => 'Halaman Tertentu', 'pages_specific' => 'Halaman Tertentu',
'pages_is_template' => 'Template Halaman', 'pages_is_template' => 'Template Halaman',
@ -256,29 +256,29 @@ return [
'tags_add' => 'Tambahkan tag lain', 'tags_add' => 'Tambahkan tag lain',
'tags_remove' => 'Hapus tag ini', 'tags_remove' => 'Hapus tag ini',
'attachments' => 'Lampiran', 'attachments' => 'Lampiran',
'attachments_explain' => 'Unggah beberapa file atau lampirkan beberapa tautan untuk ditampilkan di laman Anda. Ini terlihat di sidebar halaman.', 'attachments_explain' => 'Unggah beberapa berkas atau lampirkan beberapa tautan untuk ditampilkan di laman Anda. Ini terlihat di sidebar halaman.',
'attachments_explain_instant_save' => 'Perubahan di sini disimpan secara instan.', 'attachments_explain_instant_save' => 'Perubahan di sini disimpan secara instan.',
'attachments_items' => 'Item Terlampir', 'attachments_items' => 'Item Terlampir',
'attachments_upload' => 'Unggah File', 'attachments_upload' => 'Unggah Berkas',
'attachments_link' => 'Lampirkan Tautan', 'attachments_link' => 'Lampirkan Tautan',
'attachments_set_link' => 'Setel Tautan', 'attachments_set_link' => 'Setel Tautan',
'attachments_delete' => 'Anda yakin ingin menghapus lampiran ini?', 'attachments_delete' => 'Anda yakin ingin menghapus lampiran ini?',
'attachments_dropzone' => 'Jatuhkan file atau klik di sini untuk melampirkan file', 'attachments_dropzone' => 'Jatuhkan file atau klik di sini untuk melampirkan file',
'attachments_no_files' => 'Tidak ada file yang telah diunggah', 'attachments_no_files' => 'Tidak ada berkas yang telah diunggah',
'attachments_explain_link' => 'Anda dapat melampirkan link jika Anda memilih untuk tidak mengupload file. Ini bisa berupa tautan ke halaman lain atau tautan ke file di cloud.', 'attachments_explain_link' => 'Anda dapat melampirkan sebuah tautan jika Anda memilih untuk tidak mengunggah berkas. Ini bisa berupa sebuah tautan ke halaman lain atau tautan ke sebuah berkas di cloud.',
'attachments_link_name' => 'Nama Tautan', 'attachments_link_name' => 'Nama Tautan',
'attachment_link' => 'Lampiran Tautan', 'attachment_link' => 'Lampiran Tautan',
'attachments_link_url' => 'Tautan ke file', 'attachments_link_url' => 'Tautan ke file',
'attachments_link_url_hint' => 'Url situs atau file', 'attachments_link_url_hint' => 'Alamat url situs atau berkas',
'attach' => 'Melampirkan', 'attach' => 'Melampirkan',
'attachments_insert_link' => 'Tambahkan Tautan Lampiran ke Halaman', 'attachments_insert_link' => 'Tambahkan Tautan Lampiran ke Halaman',
'attachments_edit_file' => 'Edit File', 'attachments_edit_file' => 'Edit File',
'attachments_edit_file_name' => 'Nama file', 'attachments_edit_file_name' => 'Nama file',
'attachments_edit_drop_upload' => 'Lepaskan file atau klik di sini untuk mengupload dan menimpa', 'attachments_edit_drop_upload' => 'Jatuhkan berkas atau klik di sini untuk mengunggah dan menimpa',
'attachments_order_updated' => 'Urutan lampiran diperbarui', 'attachments_order_updated' => 'Urutan lampiran diperbarui',
'attachments_updated_success' => 'Detail lampiran diperbarui', 'attachments_updated_success' => 'Detail lampiran diperbarui',
'attachments_deleted' => 'Lampiran dihapus', 'attachments_deleted' => 'Lampiran dihapus',
'attachments_file_uploaded' => 'File berhasil diunggah', 'attachments_file_uploaded' => 'Berkas berhasil diunggah',
'attachments_file_updated' => 'File berhasil diperbarui', 'attachments_file_updated' => 'File berhasil diperbarui',
'attachments_link_attached' => 'Tautan berhasil dilampirkan ke halaman', 'attachments_link_attached' => 'Tautan berhasil dilampirkan ke halaman',
'templates' => 'Template', 'templates' => 'Template',

View File

@ -15,42 +15,42 @@ return [
'email_confirmation_expired' => 'Token konfirmasi telah kedaluwarsa, Email konfirmasi baru telah dikirim.', 'email_confirmation_expired' => 'Token konfirmasi telah kedaluwarsa, Email konfirmasi baru telah dikirim.',
'email_confirmation_awaiting' => 'Alamat email untuk akun yang digunakan perlu dikonfirmasi', 'email_confirmation_awaiting' => 'Alamat email untuk akun yang digunakan perlu dikonfirmasi',
'ldap_fail_anonymous' => 'Akses LDAP gagal menggunakan pengikatan anonim', 'ldap_fail_anonymous' => 'Akses LDAP gagal menggunakan pengikatan anonim',
'ldap_fail_authed' => 'Akses LDAP gagal menggunakan detail dn & sandi yang diberikan', 'ldap_fail_authed' => 'Akses LDAP gagal menggunakan rincian dn & sandi yang diberikan',
'ldap_extension_not_installed' => 'Ekstensi LDAP PHP tidak terpasang', 'ldap_extension_not_installed' => 'Ekstensi LDAP PHP tidak terpasang',
'ldap_cannot_connect' => 'Tidak dapat terhubung ke server ldap, Koneksi awal gagal', 'ldap_cannot_connect' => 'Tidak dapat terhubung ke server ldap, Koneksi awal gagal',
'saml_already_logged_in' => 'Telah masuk', 'saml_already_logged_in' => 'Telah masuk',
'saml_user_not_registered' => 'Pengguna :name tidak terdaftar dan pendaftaran otomatis dinonaktifkan', 'saml_user_not_registered' => 'Pengguna :name tidak terdaftar dan pendaftaran otomatis dinonaktifkan',
'saml_no_email_address' => 'Tidak dapat menemukan alamat email untuk pengguna ini dalam data yang diberikan oleh sistem autentikasi eksternal', 'saml_no_email_address' => 'Tidak dapat menemukan sebuah alamat email untuk pengguna ini, dalam data yang diberikan oleh sistem autentikasi eksternal',
'saml_invalid_response_id' => 'Permintaan dari sistem otentikasi eksternal tidak dikenali oleh proses yang dimulai oleh aplikasi ini. Menavigasi kembali setelah masuk dapat menyebabkan masalah ini.', 'saml_invalid_response_id' => 'Permintaan dari sistem otentikasi eksternal tidak dikenali oleh sebuah proses yang dimulai oleh aplikasi ini. Menavigasi kembali setelah masuk dapat menyebabkan masalah ini.',
'saml_fail_authed' => 'Login menggunakan :system gagal, sistem tidak memberikan otorisasi yang berhasil', 'saml_fail_authed' => 'Masuk menggunakan :system gagal, sistem tidak memberikan otorisasi yang berhasil',
'social_no_action_defined' => 'Tidak ada tindakan yang ditentukan', 'social_no_action_defined' => 'Tidak ada tindakan yang ditentukan',
'social_login_bad_response' => "Kesalahan diterima selama :socialAccount :\n:error", 'social_login_bad_response' => "Kesalahan yang diterima selama masuk menggunakan :socialAccount : \n:error",
'social_account_in_use' => 'Ini:socialAccount sudah digunakan, Coba masuk melalui opsi :socialAccount.', 'social_account_in_use' => 'Akun :socialAccount ini sudah digunakan, Coba masuk melalui opsi :socialAccount.',
'social_account_email_in_use' => 'Email :email sudah digunakan. Jika Anda sudah memiliki akun, Anda dapat menghubungkan :socialAccount Anda dari pengaturan profil Anda.', 'social_account_email_in_use' => 'Email :email sudah digunakan. Jika Anda sudah memiliki akun, Anda dapat menghubungkan :socialAccount Anda dari pengaturan profil Anda.',
'social_account_existing' => 'Akun ini :socialAccount sudah dilampirkan ke profil Anda.', 'social_account_existing' => 'Akun :socialAccount ini sudah dilampirkan ke profil Anda.',
'social_account_already_used_existing' => 'Akun ini :socialAccount sudah digunakan oleh pengguna lain.', 'social_account_already_used_existing' => 'Akun :socialAccount ini sudah digunakan oleh pengguna lain.',
'social_account_not_used' => 'Akun :socialAccount tidak ditautkan ke pengguna mana pun. Harap lampirkan di pengaturan profil Anda. ', 'social_account_not_used' => 'Akun :socialAccount ini tidak ditautkan ke pengguna mana pun. Harap lampirkan di dalam pengaturan profil Anda. ',
'social_account_register_instructions' => 'Jika Anda belum memiliki akun, Anda dapat mendaftarkan akun menggunakan opsi :socialAccount.', 'social_account_register_instructions' => 'Jika Anda belum memiliki akun, Anda dapat mendaftarkan akun menggunakan opsi :socialAccount.',
'social_driver_not_found' => 'Pengemudi sosial tidak ditemukan', 'social_driver_not_found' => 'Pengemudi sosial tidak ditemukan',
'social_driver_not_configured' => 'Pengaturan sosial :socialAccount Anda tidak dikonfigurasi dengan benar.', 'social_driver_not_configured' => 'Pengaturan sosial :socialAccount Anda tidak dikonfigurasi dengan benar.',
'invite_token_expired' => 'Tautan undangan ini telah kedaluwarsa. Sebagai gantinya, Anda dapat mencoba mengatur ulang kata sandi akun Anda.', 'invite_token_expired' => 'Tautan undangan ini telah kedaluwarsa. Sebagai gantinya, Anda dapat mencoba mengatur ulang kata sandi akun Anda.',
// System // System
'path_not_writable' => 'Jalur file :filePath tidak dapat diunggah ke. Pastikan itu dapat ditulis ke server.', 'path_not_writable' => 'Jalur berkas :filePath tidak dapat diunggah. Pastikan berkas tersebut dapat ditulis ke server.',
'cannot_get_image_from_url' => 'Tidak bisa mendapatkan gambar dari :url', 'cannot_get_image_from_url' => 'Tidak dapat mengambil gambar dari :url',
'cannot_create_thumbs' => 'Server tidak dapat membuat thumbnail. Harap periksa apakah Anda telah memasang ekstensi GD PHP.', 'cannot_create_thumbs' => 'Server tidak dapat membuat thumbnail. Harap periksa apakah Anda telah memasang ekstensi GD PHP.',
'server_upload_limit' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran file yang lebih kecil.', 'server_upload_limit' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran berkas yang lebih kecil.',
'uploaded' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran file yang lebih kecil.', 'uploaded' => 'Server tidak mengizinkan unggahan dengan ukuran ini. Harap coba ukuran berkas yang lebih kecil.',
'image_upload_error' => 'Terjadi kesalahan saat mengupload gambar', 'image_upload_error' => 'Terjadi kesalahan saat mengunggah gambar',
'image_upload_type_error' => 'Jenis gambar yang diunggah tidak valid', 'image_upload_type_error' => 'Jenis gambar yang diunggah tidak valid',
'file_upload_timeout' => 'Waktu unggah file telah habis.', 'file_upload_timeout' => 'Unggahan berkas telah habis waktu.',
// Attachments // Attachments
'attachment_not_found' => 'Lampiran tidak ditemukan', 'attachment_not_found' => 'Lampiran tidak ditemukan',
// Pages // Pages
'page_draft_autosave_fail' => 'Gagal menyimpan draf. Pastikan Anda memiliki koneksi internet sebelum menyimpan halaman ini', 'page_draft_autosave_fail' => 'Gagal menyimpan draf. Pastikan Anda memiliki koneksi internet sebelum menyimpan halaman ini',
'page_custom_home_deletion' => 'Tidak dapat menghapus halaman saat disetel sebagai beranda', 'page_custom_home_deletion' => 'Tidak dapat menghapus sebuah halaman saat diatur sebagai sebuah halaman beranda',
// Entities // Entities
'entity_not_found' => 'Entitas tidak ditemukan', 'entity_not_found' => 'Entitas tidak ditemukan',
@ -67,7 +67,7 @@ return [
'users_cannot_delete_guest' => 'Anda tidak dapat menghapus pengguna tamu', 'users_cannot_delete_guest' => 'Anda tidak dapat menghapus pengguna tamu',
// Roles // Roles
'role_cannot_be_edited' => 'Peran ini tidak dapat diedit', 'role_cannot_be_edited' => 'Peran ini tidak dapat disunting',
'role_system_cannot_be_deleted' => 'Peran ini adalah peran sistem dan tidak dapat dihapus', 'role_system_cannot_be_deleted' => 'Peran ini adalah peran sistem dan tidak dapat dihapus',
'role_registration_default_cannot_delete' => 'Peran ini tidak dapat dihapus jika disetel sebagai peran pendaftaran default', 'role_registration_default_cannot_delete' => 'Peran ini tidak dapat dihapus jika disetel sebagai peran pendaftaran default',
'role_cannot_remove_only_admin' => 'Pengguna ini adalah satu-satunya pengguna yang ditetapkan ke peran administrator. Tetapkan peran administrator untuk pengguna lain sebelum mencoba untuk menghapusnya di sini.', 'role_cannot_remove_only_admin' => 'Pengguna ini adalah satu-satunya pengguna yang ditetapkan ke peran administrator. Tetapkan peran administrator untuk pengguna lain sebelum mencoba untuk menghapusnya di sini.',
@ -83,9 +83,9 @@ return [
'404_page_not_found' => 'Halaman tidak ditemukan', '404_page_not_found' => 'Halaman tidak ditemukan',
'sorry_page_not_found' => 'Maaf, Halaman yang Anda cari tidak dapat ditemukan.', 'sorry_page_not_found' => 'Maaf, Halaman yang Anda cari tidak dapat ditemukan.',
'sorry_page_not_found_permission_warning' => 'Jika Anda mengharapkan halaman ini ada, Anda mungkin tidak memiliki izin untuk melihatnya.', 'sorry_page_not_found_permission_warning' => 'Jika Anda mengharapkan halaman ini ada, Anda mungkin tidak memiliki izin untuk melihatnya.',
'image_not_found' => 'Image Not Found', 'image_not_found' => 'Gambar tidak ditemukan',
'image_not_found_subtitle' => 'Sorry, The image file you were looking for could not be found.', 'image_not_found_subtitle' => 'Maaf, Berkas gambar yang Anda cari tidak dapat ditemukan.',
'image_not_found_details' => 'If you expected this image to exist it might have been deleted.', 'image_not_found_details' => 'Jika Anda mengharapkan gambar ini ada, gambar itu mungkin telah dihapus.',
'return_home' => 'Kembali ke home', 'return_home' => 'Kembali ke home',
'error_occurred' => 'Terjadi kesalahan', 'error_occurred' => 'Terjadi kesalahan',
'app_down' => ':appName sedang down sekarang', 'app_down' => ':appName sedang down sekarang',

View File

@ -214,7 +214,7 @@ return [
'user_api_token_update_success' => 'Token API berhasil diperbarui', 'user_api_token_update_success' => 'Token API berhasil diperbarui',
'user_api_token' => 'Token API', 'user_api_token' => 'Token API',
'user_api_token_id' => 'Token ID', 'user_api_token_id' => 'Token ID',
'user_api_token_id_desc' => 'Ini adalah pengenal yang dibuat oleh sistem yang tidak dapat diedit untuk token ini yang perlu disediakan dalam permintaan API.', 'user_api_token_id_desc' => 'Ini adalah sebuah pengenal yang dihasilkan oleh sistem yang tidak dapat disunting untuk token ini yang perlu untuk disediakan dalam permintaan API.',
'user_api_token_secret' => 'Token Secret', 'user_api_token_secret' => 'Token Secret',
'user_api_token_secret_desc' => 'Ini adalah rahasia yang dihasilkan sistem untuk token ini yang perlu disediakan dalam permintaan API. Ini hanya akan ditampilkan kali ini jadi salin nilai ini ke tempat yang aman dan terlindungi.', 'user_api_token_secret_desc' => 'Ini adalah rahasia yang dihasilkan sistem untuk token ini yang perlu disediakan dalam permintaan API. Ini hanya akan ditampilkan kali ini jadi salin nilai ini ke tempat yang aman dan terlindungi.',
'user_api_token_created' => 'Token dibuat :timeAgo', 'user_api_token_created' => 'Token dibuat :timeAgo',

View File

@ -100,7 +100,7 @@ return [
'timezone' => ':attribute harus menjadi zona yang valid.', 'timezone' => ':attribute harus menjadi zona yang valid.',
'unique' => ':attribute sudah diambil.', 'unique' => ':attribute sudah diambil.',
'url' => ':attribute format tidak valid.', 'url' => ':attribute format tidak valid.',
'uploaded' => 'File tidak dapat diunggah. Server mungkin tidak menerima file dengan ukuran ini.', 'uploaded' => 'Berkas tidak dapat diunggah. Server mungkin tidak menerima berkas dengan ukuran ini.',
// Custom validation lines // Custom validation lines
'custom' => [ 'custom' => [

View File

@ -13,7 +13,7 @@ return [
'sign_up' => '注册', 'sign_up' => '注册',
'log_in' => '登录', 'log_in' => '登录',
'log_in_with' => '以:socialDriver登录', 'log_in_with' => '以:socialDriver登录',
'sign_up_with' => '注册:socialDriver', 'sign_up_with' => '通过 :socialDriver 账号登录',
'logout' => '注销', 'logout' => '注销',
'name' => '名称', 'name' => '名称',
@ -27,10 +27,10 @@ return [
'ldap_email_hint' => '请输入用于此帐户的电子邮件。', 'ldap_email_hint' => '请输入用于此帐户的电子邮件。',
'create_account' => '创建账户', 'create_account' => '创建账户',
'already_have_account' => '您已经有账号?', 'already_have_account' => '您已经有账号?',
'dont_have_account' => '您还没注册', 'dont_have_account' => '您还没有账号吗',
'social_login' => 'SNS登录', 'social_login' => 'SNS登录',
'social_registration' => 'SNS注册', 'social_registration' => '使用社交网站账号注册',
'social_registration_text' => '其他服务注册/登录。', 'social_registration_text' => '使用其他服务注册并登录。',
'register_thanks' => '注册完成!', 'register_thanks' => '注册完成!',
'register_confirm' => '请点击查收您的Email并点击确认。', 'register_confirm' => '请点击查收您的Email并点击确认。',

View File

@ -1,8 +1,10 @@
@foreach($attachments as $attachment) <div component="attachments-list">
<div class="attachment icon-list"> @foreach($attachments as $attachment)
<a class="icon-list-item py-xs" href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif> <div class="attachment icon-list">
<span class="icon">@icon($attachment->external ? 'export' : 'file')</span> <a class="icon-list-item py-xs attachment-{{ $attachment->external ? 'link' : 'file' }}" href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif>
<span>{{ $attachment->name }}</span> <span class="icon">@icon($attachment->external ? 'export' : 'file')</span>
</a> <span>{{ $attachment->name }}</span>
</div> </a>
@endforeach </div>
@endforeach
</div>

View File

@ -6,9 +6,11 @@
<div class="card mb-xl px-l pb-l pt-l"> <div class="card mb-xl px-l pb-l pt-l">
<div class="grid half v-center"> <div class="grid half v-center">
<div> <div>
<h1 class="list-heading">{{ $message ?? trans('errors.404_page_not_found') }}</h1> @include('errors.parts.not-found-text', [
<h5>{{ $subtitle ?? trans('errors.sorry_page_not_found') }}</h5> 'title' => $message ?? trans('errors.404_page_not_found'),
<p>{{ $details ?? trans('errors.sorry_page_not_found_permission_warning') }}</p> 'subtitle' => $subtitle ?? trans('errors.sorry_page_not_found'),
'details' => $details ?? trans('errors.sorry_page_not_found_permission_warning'),
])
</div> </div>
<div class="text-right"> <div class="text-right">
@if(!signedInUser()) @if(!signedInUser())

View File

@ -0,0 +1,5 @@
{{--The below text may be dynamic based upon language and scenario.--}}
{{--It's safer to add new text sections here rather than altering existing ones.--}}
<h1 class="list-heading">{{ $title }}</h1>
<h5>{{ $subtitle }}</h5>
<p>{{ $details }}</p>

View File

@ -12,7 +12,7 @@ class ExportTest extends TestCase
public function test_page_text_export() public function test_page_text_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asEditor(); $this->asEditor();
$resp = $this->get($page->getUrl('/export/plaintext')); $resp = $this->get($page->getUrl('/export/plaintext'));
@ -23,7 +23,7 @@ class ExportTest extends TestCase
public function test_page_pdf_export() public function test_page_pdf_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asEditor(); $this->asEditor();
$resp = $this->get($page->getUrl('/export/pdf')); $resp = $this->get($page->getUrl('/export/pdf'));
@ -33,7 +33,7 @@ class ExportTest extends TestCase
public function test_page_html_export() public function test_page_html_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asEditor(); $this->asEditor();
$resp = $this->get($page->getUrl('/export/html')); $resp = $this->get($page->getUrl('/export/html'));
@ -44,7 +44,7 @@ class ExportTest extends TestCase
public function test_book_text_export() public function test_book_text_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$book = $page->book; $book = $page->book;
$this->asEditor(); $this->asEditor();
@ -57,7 +57,7 @@ class ExportTest extends TestCase
public function test_book_pdf_export() public function test_book_pdf_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$book = $page->book; $book = $page->book;
$this->asEditor(); $this->asEditor();
@ -68,7 +68,7 @@ class ExportTest extends TestCase
public function test_book_html_export() public function test_book_html_export()
{ {
$page = Page::first(); $page = Page::query()->first();
$book = $page->book; $book = $page->book;
$this->asEditor(); $this->asEditor();
@ -95,7 +95,7 @@ class ExportTest extends TestCase
public function test_chapter_text_export() public function test_chapter_text_export()
{ {
$chapter = Chapter::first(); $chapter = Chapter::query()->first();
$page = $chapter->pages[0]; $page = $chapter->pages[0];
$this->asEditor(); $this->asEditor();
@ -108,7 +108,7 @@ class ExportTest extends TestCase
public function test_chapter_pdf_export() public function test_chapter_pdf_export()
{ {
$chapter = Chapter::first(); $chapter = Chapter::query()->first();
$this->asEditor(); $this->asEditor();
$resp = $this->get($chapter->getUrl('/export/pdf')); $resp = $this->get($chapter->getUrl('/export/pdf'));
@ -118,7 +118,7 @@ class ExportTest extends TestCase
public function test_chapter_html_export() public function test_chapter_html_export()
{ {
$chapter = Chapter::first(); $chapter = Chapter::query()->first();
$page = $chapter->pages[0]; $page = $chapter->pages[0];
$this->asEditor(); $this->asEditor();
@ -131,7 +131,7 @@ class ExportTest extends TestCase
public function test_page_html_export_contains_custom_head_if_set() public function test_page_html_export_contains_custom_head_if_set()
{ {
$page = Page::first(); $page = Page::query()->first();
$customHeadContent = "<style>p{color: red;}</style>"; $customHeadContent = "<style>p{color: red;}</style>";
$this->setSettings(['app-custom-head' => $customHeadContent]); $this->setSettings(['app-custom-head' => $customHeadContent]);
@ -140,9 +140,21 @@ class ExportTest extends TestCase
$resp->assertSee($customHeadContent); $resp->assertSee($customHeadContent);
} }
public function test_page_html_export_does_not_break_with_only_comments_in_custom_head()
{
$page = Page::query()->first();
$customHeadContent = "<!-- A comment -->";
$this->setSettings(['app-custom-head' => $customHeadContent]);
$resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertStatus(200);
$resp->assertSee($customHeadContent);
}
public function test_page_html_export_use_absolute_dates() public function test_page_html_export_use_absolute_dates()
{ {
$page = Page::first(); $page = Page::query()->first();
$resp = $this->asEditor()->get($page->getUrl('/export/html')); $resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertSee($page->created_at->formatLocalized('%e %B %Y %H:%M:%S')); $resp->assertSee($page->created_at->formatLocalized('%e %B %Y %H:%M:%S'));
@ -153,7 +165,7 @@ class ExportTest extends TestCase
public function test_page_export_does_not_include_user_or_revision_links() public function test_page_export_does_not_include_user_or_revision_links()
{ {
$page = Page::first(); $page = Page::query()->first();
$resp = $this->asEditor()->get($page->getUrl('/export/html')); $resp = $this->asEditor()->get($page->getUrl('/export/html'));
$resp->assertDontSee($page->getUrl('/revisions')); $resp->assertDontSee($page->getUrl('/revisions'));
@ -163,7 +175,7 @@ class ExportTest extends TestCase
public function test_page_export_sets_right_data_type_for_svg_embeds() public function test_page_export_sets_right_data_type_for_svg_embeds()
{ {
$page = Page::first(); $page = Page::query()->first();
Storage::disk('local')->makeDirectory('uploads/images/gallery'); Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>'); Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
$page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg">'; $page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg">';
@ -179,7 +191,7 @@ class ExportTest extends TestCase
public function test_page_image_containment_works_on_multiple_images_within_a_single_line() public function test_page_image_containment_works_on_multiple_images_within_a_single_line()
{ {
$page = Page::first(); $page = Page::query()->first();
Storage::disk('local')->makeDirectory('uploads/images/gallery'); Storage::disk('local')->makeDirectory('uploads/images/gallery');
Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>'); Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
Storage::disk('local')->put('uploads/images/gallery/svg_test2.svg', '<svg></svg>'); Storage::disk('local')->put('uploads/images/gallery/svg_test2.svg', '<svg></svg>');
@ -195,7 +207,7 @@ class ExportTest extends TestCase
public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder() public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder()
{ {
$page = Page::first(); $page = Page::query()->first();
$page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg"/>' $page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg"/>'
.'<img src="http://localhost/uploads/svg_test.svg"/>' .'<img src="http://localhost/uploads/svg_test.svg"/>'
.'<img src="/uploads/svg_test.svg"/>'; .'<img src="/uploads/svg_test.svg"/>';
@ -233,7 +245,7 @@ class ExportTest extends TestCase
public function test_page_export_with_deleted_creator_and_updater() public function test_page_export_with_deleted_creator_and_updater()
{ {
$user = $this->getViewer(['name' => 'ExportWizardTheFifth']); $user = $this->getViewer(['name' => 'ExportWizardTheFifth']);
$page = Page::first(); $page = Page::query()->first();
$page->created_by = $user->id; $page->created_by = $user->id;
$page->updated_by = $user->id; $page->updated_by = $user->id;
$page->save(); $page->save();

View File

@ -13,8 +13,8 @@ class PageContentTest extends TestCase
public function test_page_includes() public function test_page_includes()
{ {
$page = Page::first(); $page = Page::query()->first();
$secondPage = Page::where('id', '!=', $page->id)->first(); $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$secondPage->html = "<p id='section1'>Hello, This is a test</p><p id='section2'>This is a second block of content</p>"; $secondPage->html = "<p id='section1'>Hello, This is a test</p><p id='section2'>This is a second block of content</p>";
$secondPage->save(); $secondPage->save();
@ -42,8 +42,8 @@ class PageContentTest extends TestCase
public function test_saving_page_with_includes() public function test_saving_page_with_includes()
{ {
$page = Page::first(); $page = Page::query()->first();
$secondPage = Page::where('id', '!=', $page->id)->first(); $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$this->asEditor(); $this->asEditor();
$includeTag = '{{@' . $secondPage->id . '}}'; $includeTag = '{{@' . $secondPage->id . '}}';
@ -60,8 +60,8 @@ class PageContentTest extends TestCase
public function test_page_includes_do_not_break_tables() public function test_page_includes_do_not_break_tables()
{ {
$page = Page::first(); $page = Page::query()->first();
$secondPage = Page::where('id', '!=', $page->id)->first(); $secondPage = Page::query()->where('id', '!=', $page->id)->first();
$content = '<table id="table"><tbody><tr><td>test</td></tr></tbody></table>'; $content = '<table id="table"><tbody><tr><td>test</td></tr></tbody></table>';
$secondPage->html = $content; $secondPage->html = $content;
@ -97,7 +97,7 @@ class PageContentTest extends TestCase
public function test_page_content_scripts_removed_by_default() public function test_page_content_scripts_removed_by_default()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
$script = 'abc123<script>console.log("hello-test")</script>abc123'; $script = 'abc123<script>console.log("hello-test")</script>abc123';
$page->html = "escape {$script}"; $page->html = "escape {$script}";
$page->save(); $page->save();
@ -120,7 +120,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -145,7 +145,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -171,7 +171,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -192,7 +192,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -215,7 +215,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -232,7 +232,7 @@ class PageContentTest extends TestCase
public function test_page_inline_on_attributes_removed_by_default() public function test_page_inline_on_attributes_removed_by_default()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
$script = '<p onmouseenter="console.log(\'test\')">Hello</p>'; $script = '<p onmouseenter="console.log(\'test\')">Hello</p>';
$page->html = "escape {$script}"; $page->html = "escape {$script}";
$page->save(); $page->save();
@ -255,7 +255,7 @@ class PageContentTest extends TestCase
]; ];
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
foreach ($checks as $check) { foreach ($checks as $check) {
$page->html = $check; $page->html = $check;
@ -271,7 +271,7 @@ class PageContentTest extends TestCase
public function test_page_content_scripts_show_when_configured() public function test_page_content_scripts_show_when_configured()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
config()->push('app.allow_content_scripts', 'true'); config()->push('app.allow_content_scripts', 'true');
$script = 'abc123<script>console.log("hello-test")</script>abc123'; $script = 'abc123<script>console.log("hello-test")</script>abc123';
@ -286,7 +286,7 @@ class PageContentTest extends TestCase
public function test_page_inline_on_attributes_show_if_configured() public function test_page_inline_on_attributes_show_if_configured()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
config()->push('app.allow_content_scripts', 'true'); config()->push('app.allow_content_scripts', 'true');
$script = '<p onmouseenter="console.log(\'test\')">Hello</p>'; $script = '<p onmouseenter="console.log(\'test\')">Hello</p>';
@ -301,7 +301,7 @@ class PageContentTest extends TestCase
public function test_duplicate_ids_does_not_break_page_render() public function test_duplicate_ids_does_not_break_page_render()
{ {
$this->asEditor(); $this->asEditor();
$pageA = Page::first(); $pageA = Page::query()->first();
$pageB = Page::query()->where('id', '!=', $pageA->id)->first(); $pageB = Page::query()->where('id', '!=', $pageA->id)->first();
$content = '<ul id="bkmrk-xxx-%28"></ul> <ul id="bkmrk-xxx-%28"></ul>'; $content = '<ul id="bkmrk-xxx-%28"></ul> <ul id="bkmrk-xxx-%28"></ul>';
@ -318,7 +318,7 @@ class PageContentTest extends TestCase
public function test_duplicate_ids_fixed_on_page_save() public function test_duplicate_ids_fixed_on_page_save()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
$content = '<ul id="bkmrk-test"><li>test a</li><li><ul id="bkmrk-test"><li>test b</li></ul></li></ul>'; $content = '<ul id="bkmrk-test"><li>test a</li><li><ul id="bkmrk-test"><li>test b</li></ul></li></ul>';
$pageSave = $this->put($page->getUrl(), [ $pageSave = $this->put($page->getUrl(), [
@ -328,14 +328,14 @@ class PageContentTest extends TestCase
]); ]);
$pageSave->assertRedirect(); $pageSave->assertRedirect();
$updatedPage = Page::where('id', '=', $page->id)->first(); $updatedPage = Page::query()->where('id', '=', $page->id)->first();
$this->assertEquals(substr_count($updatedPage->html, "bkmrk-test\""), 1); $this->assertEquals(substr_count($updatedPage->html, "bkmrk-test\""), 1);
} }
public function test_anchors_referencing_non_bkmrk_ids_rewritten_after_save() public function test_anchors_referencing_non_bkmrk_ids_rewritten_after_save()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); $page = Page::query()->first();
$content = '<h1 id="non-standard-id">test</h1><p><a href="#non-standard-id">link</a></p>'; $content = '<h1 id="non-standard-id">test</h1><p><a href="#non-standard-id">link</a></p>';
$this->put($page->getUrl(), [ $this->put($page->getUrl(), [
@ -344,7 +344,7 @@ class PageContentTest extends TestCase
'summary' => '' 'summary' => ''
]); ]);
$updatedPage = Page::where('id', '=', $page->id)->first(); $updatedPage = Page::query()->where('id', '=', $page->id)->first();
$this->assertStringContainsString('id="bkmrk-test"', $updatedPage->html); $this->assertStringContainsString('id="bkmrk-test"', $updatedPage->html);
$this->assertStringContainsString('href="#bkmrk-test"', $updatedPage->html); $this->assertStringContainsString('href="#bkmrk-test"', $updatedPage->html);
} }
@ -484,6 +484,25 @@ class PageContentTest extends TestCase
$pageView->assertElementExists('.page-content p > s'); $pageView->assertElementExists('.page-content p > s');
} }
public function test_page_markdown_single_html_comment_saving()
{
$this->asEditor();
$page = Page::query()->first();
$content = '<!-- Test Comment -->';
$this->put($page->getUrl(), [
'name' => $page->name, 'markdown' => $content,
'html' => '', 'summary' => ''
]);
$page->refresh();
$this->assertStringMatchesFormat($content, $page->html);
$pageView = $this->get($page->getUrl());
$pageView->assertStatus(200);
$pageView->assertSee($content);
}
public function test_base64_images_get_extracted_from_page_content() public function test_base64_images_get_extracted_from_page_content()
{ {
$this->asEditor(); $this->asEditor();

View File

@ -4,11 +4,9 @@ use BookStack\Entities\Tools\TrashCan;
use BookStack\Entities\Repos\PageRepo; use BookStack\Entities\Repos\PageRepo;
use BookStack\Uploads\Attachment; use BookStack\Uploads\Attachment;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Uploads\AttachmentService; use BookStack\Uploads\AttachmentService;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestResponse;
class AttachmentTest extends TestCase class AttachmentTest extends TestCase
{ {
@ -57,7 +55,7 @@ class AttachmentTest extends TestCase
public function test_file_upload() public function test_file_upload()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$admin = $this->getAdmin(); $admin = $this->getAdmin();
$fileName = 'upload_test_file.txt'; $fileName = 'upload_test_file.txt';
@ -85,7 +83,7 @@ class AttachmentTest extends TestCase
public function test_file_upload_does_not_use_filename() public function test_file_upload_does_not_use_filename()
{ {
$page = Page::first(); $page = Page::query()->first();
$fileName = 'upload_test_file.txt'; $fileName = 'upload_test_file.txt';
@ -99,7 +97,7 @@ class AttachmentTest extends TestCase
public function test_file_display_and_access() public function test_file_display_and_access()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$fileName = 'upload_test_file.txt'; $fileName = 'upload_test_file.txt';
@ -119,7 +117,7 @@ class AttachmentTest extends TestCase
public function test_attaching_link_to_page() public function test_attaching_link_to_page()
{ {
$page = Page::first(); $page = Page::query()->first();
$admin = $this->getAdmin(); $admin = $this->getAdmin();
$this->asAdmin(); $this->asAdmin();
@ -156,7 +154,7 @@ class AttachmentTest extends TestCase
public function test_attachment_updating() public function test_attachment_updating()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$attachment = $this->createAttachment($page); $attachment = $this->createAttachment($page);
@ -180,7 +178,7 @@ class AttachmentTest extends TestCase
public function test_file_deletion() public function test_file_deletion()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$fileName = 'deletion_test.txt'; $fileName = 'deletion_test.txt';
$this->uploadFile($fileName, $page->id); $this->uploadFile($fileName, $page->id);
@ -202,7 +200,7 @@ class AttachmentTest extends TestCase
public function test_attachment_deletion_on_page_deletion() public function test_attachment_deletion_on_page_deletion()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$fileName = 'deletion_test.txt'; $fileName = 'deletion_test.txt';
$this->uploadFile($fileName, $page->id); $this->uploadFile($fileName, $page->id);
@ -230,7 +228,7 @@ class AttachmentTest extends TestCase
{ {
$admin = $this->getAdmin(); $admin = $this->getAdmin();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$page = Page::first(); /** @var Page $page */ $page = Page::query()->first(); /** @var Page $page */
$this->actingAs($admin); $this->actingAs($admin);
$fileName = 'permission_test.txt'; $fileName = 'permission_test.txt';
@ -253,7 +251,7 @@ class AttachmentTest extends TestCase
public function test_data_and_js_links_cannot_be_attached_to_a_page() public function test_data_and_js_links_cannot_be_attached_to_a_page()
{ {
$page = Page::first(); $page = Page::query()->first();
$this->asAdmin(); $this->asAdmin();
$badLinks = [ $badLinks = [
@ -291,4 +289,22 @@ class AttachmentTest extends TestCase
]); ]);
} }
} }
public function test_file_access_with_open_query_param_provides_inline_response_with_correct_content_type()
{
$page = Page::query()->first();
$this->asAdmin();
$fileName = 'upload_test_file.txt';
$upload = $this->uploadFile($fileName, $page->id);
$upload->assertStatus(200);
$attachment = Attachment::query()->orderBy('id', 'desc')->take(1)->first();
$attachmentGet = $this->get($attachment->getUrl(true));
// http-foundation/Response does some 'fixing' of responses to add charsets to text responses.
$attachmentGet->assertHeader('Content-Type', 'text/plain; charset=UTF-8');
$attachmentGet->assertHeader('Content-Disposition', "inline; filename=\"upload_test_file.txt\"");
$this->deleteUploads();
}
} }