'jsLibData' => file_get_contents(base_path('dev/licensing/js-library-licenses.txt')),
]);
}
+
+ /**
+ * Show the view for /opensearch.xml.
+ */
+ public function opensearch()
+ {
+ return response()
+ ->view('misc.opensearch')
+ ->header('Content-Type', 'application/opensearchdescription+xml');
+ }
}
// Not directly used but available for convenience to users.
'privacy_policy' => 'Privacy Policy',
'terms_of_service' => 'Terms of Service',
+
+ // OpenSearch
+ 'opensearch_description' => 'Search :appName',
];
<link rel="manifest" href="{{ url('/manifest.json') }}">
<meta name="mobile-web-app-capable" content="yes">
+ <!-- OpenSearch -->
+ <link rel="search" type="application/opensearchdescription+xml" title="{{ setting('app-name') }}" href="{{ url('/opensearch.xml') }}">
+
@yield('head')
<!-- Custom Styles & Head Content -->
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>{{ mb_strimwidth(setting('app-name'), 0, 16) }}</ShortName>
+ <Description>{{ trans('common.opensearch_description', ['appName' => setting('app-name')]) }}</Description>
+ <Image width="256" height="256" type="image/png">{{ setting('app-icon') ?: url('/icon.png') }}</Image>
+ <Image width="180" height="180" type="image/png">{{ setting('app-icon-180') ?: url('/icon-180.png') }}</Image>
+ <Image width="128" height="128" type="image/png">{{ setting('app-icon-128') ?: url('/icon-128.png') }}</Image>
+ <Image width="64" height="64" type="image/png">{{ setting('app-icon-64') ?: url('/icon-64.png') }}</Image>
+ <Image width="32" height="32" type="image/png">{{ setting('app-icon-32') ?: url('/icon-32.png') }}</Image>
+ <Url type="text/html" rel="results" template="{{ url('/search') }}?term={searchTerms}"/>
+ <Url type="application/opensearchdescription+xml" rel="self" template="{{ url('/opensearch.xml') }}"/>
+</OpenSearchDescription>
Route::get('/favicon.ico', [MetaController::class, 'favicon']);
Route::get('/manifest.json', [MetaController::class, 'pwaManifest']);
Route::get('/licenses', [MetaController::class, 'licenses']);
+Route::get('/opensearch.xml', [MetaController::class, 'opensearch']);
// Authenticated routes...
Route::middleware('auth')->group(function () {
<?php
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
class HelpTest extends TestCase
{
<?php
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
class LicensesTest extends TestCase
{
<?php
-namespace Tests;
+namespace Tests\Meta;
use BookStack\Entities\Repos\BaseRepo;
use BookStack\Entities\Repos\BookRepo;
use Illuminate\Support\Str;
use Illuminate\Testing\TestResponse;
+use Tests\TestCase;
class OpenGraphTest extends TestCase
{
--- /dev/null
+<?php
+
+namespace Tests\Meta;
+
+use Tests\TestCase;
+
+class OpensearchTest extends TestCase
+{
+ public function test_opensearch_endpoint()
+ {
+ $appName = 'MyAppNameThatsReallyLongLikeThis';
+ setting()->put('app-name', $appName);
+ $resultUrl = url('/search') . '?term={searchTerms}';
+ $selfUrl = url('/opensearch.xml');
+
+ $resp = $this->get('/opensearch.xml');
+ $resp->assertOk();
+
+ $html = $this->withHtml($resp);
+
+ $html->assertElementExists('OpenSearchDescription > ShortName');
+ $html->assertElementContains('OpenSearchDescription > ShortName', mb_strimwidth($appName, 0, 16));
+ $html->assertElementNotContains('OpenSearchDescription > ShortName', $appName);
+
+ $html->assertElementExists('OpenSearchDescription > Description');
+ $html->assertElementContains('OpenSearchDescription > Description', "Search {$appName}");
+ $html->assertElementExists('OpenSearchDescription > Image');
+ $html->assertElementExists('OpenSearchDescription > Url[rel="results"][template="' . htmlspecialchars($resultUrl) . '"]');
+ $html->assertElementExists('OpenSearchDescription > Url[rel="self"][template="' . htmlspecialchars($selfUrl) . '"]');
+ }
+
+ public function test_opensearch_linked_to_from_home()
+ {
+ $appName = setting('app-name');
+ $endpointUrl = url('/opensearch.xml');
+
+ $resp = $this->asViewer()->get('/');
+ $html = $this->withHtml($resp);
+
+ $html->assertElementExists('head > link[rel="search"][type="application/opensearchdescription+xml"][title="' . htmlspecialchars($appName) . '"][href="' . htmlspecialchars($endpointUrl) . '"]');
+ }
+}
<?php
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
class PwaManifestTest extends TestCase
{
--- /dev/null
+<?php
+
+namespace Tests\Meta;
+
+use Tests\TestCase;
+
+class RobotsTest extends TestCase
+{
+ public function test_robots_effected_by_public_status()
+ {
+ $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+
+ $this->setSettings(['app-public' => 'true']);
+
+ $resp = $this->get('/robots.txt');
+ $resp->assertSee("User-agent: *\nDisallow:");
+ $resp->assertDontSee('Disallow: /');
+ }
+
+ public function test_robots_effected_by_setting()
+ {
+ $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+
+ config()->set('app.allow_robots', true);
+
+ $resp = $this->get('/robots.txt');
+ $resp->assertSee("User-agent: *\nDisallow:");
+ $resp->assertDontSee('Disallow: /');
+
+ // Check config overrides app-public setting
+ config()->set('app.allow_robots', false);
+ $this->setSettings(['app-public' => 'true']);
+ $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+ }
+}
$resp->assertDontSee($page->name);
}
- public function test_robots_effected_by_public_status()
- {
- $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
-
- $this->setSettings(['app-public' => 'true']);
-
- $resp = $this->get('/robots.txt');
- $resp->assertSee("User-agent: *\nDisallow:");
- $resp->assertDontSee('Disallow: /');
- }
-
- public function test_robots_effected_by_setting()
- {
- $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
-
- config()->set('app.allow_robots', true);
-
- $resp = $this->get('/robots.txt');
- $resp->assertSee("User-agent: *\nDisallow:");
- $resp->assertDontSee('Disallow: /');
-
- // Check config overrides app-public setting
- config()->set('app.allow_robots', false);
- $this->setSettings(['app-public' => 'true']);
- $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
- }
-
public function test_default_favicon_file_created_upon_access()
{
$faviconPath = public_path('favicon.ico');