Add opensearch declaration (#1058)

* feat: Add opensearch declaration

* cleanup

---------

Co-authored-by: Johannes Zorn <johannes.zorn@zollsoft.com>
Co-authored-by: Sascha Ißbrücker <sascha.issbruecker@gmail.com>
This commit is contained in:
Johannes Zorn
2025-05-17 09:52:26 +02:00
committed by GitHub
parent da9371e33c
commit 9a00ae4b93
6 changed files with 54 additions and 0 deletions

View File

@@ -7,6 +7,7 @@
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'apple-touch-icon.png' %}">
<link rel="mask-icon" href="{% static 'safari-pinned-tab.svg' %}" color="#5856e0">
<link rel="manifest" href="{% url 'linkding:manifest' %}">
<link rel="search" type="application/opensearchdescription+xml" title="Linkding" href="{% url 'linkding:opensearch' %}"/>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimal-ui">
<meta name="description" content="Self-hosted bookmark service">

View File

@@ -0,0 +1,7 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>Linkding</ShortName>
<Description>Linkding</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/x-icon">{{base_url}}static/favicon.ico</Image>
<Url type="text/html" template="{{ bookmarks_url }}?client=opensearch&amp;q={searchTerms}"/>
</OpenSearchDescription>

View File

@@ -0,0 +1,25 @@
from django.test import TestCase
from django.urls import reverse
class OpenSearchViewTestCase(TestCase):
def test_opensearch_configuration(self):
response = self.client.get(reverse("linkding:opensearch"))
self.assertEqual(response.status_code, 200)
self.assertEqual(
response["content-type"], "application/opensearchdescription+xml"
)
base_url = "http://testserver"
expected_content = f"""
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>Linkding</ShortName>
<Description>Linkding</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/x-icon">{base_url}/static/favicon.ico</Image>
<Url type="text/html" template="{base_url}/bookmarks?client=opensearch&amp;q={{searchTerms}}"/>
</OpenSearchDescription>
"""
content = response.content.decode()
self.assertXMLEqual(content, expected_content)

View File

@@ -80,6 +80,8 @@ urlpatterns = [
path("manifest.json", views.manifest, name="manifest"),
# Custom CSS
path("custom_css", views.custom_css, name="custom_css"),
# OpenSearch
path("opensearch.xml", views.opensearch, name="opensearch"),
]
# Put all linkding URLs into a linkding namespace

View File

@@ -7,3 +7,4 @@ from .health import health
from .manifest import manifest
from .custom_css import custom_css
from .root import root
from .opensearch import opensearch

View File

@@ -0,0 +1,18 @@
from django.urls import reverse
from django.shortcuts import render
def opensearch(request):
base_url = request.build_absolute_uri(reverse("linkding:root"))
bookmarks_url = request.build_absolute_uri(reverse("linkding:bookmarks.index"))
return render(
request,
"opensearch.xml",
{
"base_url": base_url,
"bookmarks_url": bookmarks_url,
},
content_type="application/opensearchdescription+xml",
status=200,
)