diff --git a/docs/index.rst b/docs/index.rst
index 3f40e6337..a190afa97 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -12,3 +12,4 @@ Welcome to libkiwix's documentation!
usage
api/ref_api
+ widget
diff --git a/docs/widget.rst b/docs/widget.rst
new file mode 100644
index 000000000..40104b37c
--- /dev/null
+++ b/docs/widget.rst
@@ -0,0 +1,82 @@
+Kiwix serve widget
+====================
+
+Introduction
+------------
+
+The kiwix-serve widget provides an easy to embed way to show the `kiwix-serve` homepage.
+
+Usage
+-----
+
+To use the widget, simply add an iframe with its `src` attribute set to the `widget` endpoint.
+Example HTML Page ::
+
+
+
+
+ Widget Test
+
+
+
+
+
+
+This creates an iframe with the kiwix-serve homepage contents.
+
+Arguments are explained below.
+
+Possible Arguments
+-------------------
+
+Currently, the following arguments are supported.
+
+disabledesc (value = N/A)
+ Disables the description part of a tile.
+
+disablefilter (value = N/A)
+ Disables the search filters: language, category, tag and search function.
+
+disableclick (value = N/A)
+ Disables clicking the book to open it for reading.
+
+disabledownload (value = N/A)
+ Disables the download button (if avaialable at all) on the tile.
+
+
+Custom CSS and JS
+-----------------
+
+You can add your custom CSS rules and Javascript code to the widget.
+
+To do that, use the following code as template::
+
+
+
+
+
+
+The CSS/JS fields are optional, you may send both or only one.
+
diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp
index 43411260f..7127658e9 100644
--- a/src/server/internalServer.cpp
+++ b/src/server/internalServer.cpp
@@ -577,6 +577,9 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r
if (isEndpointUrl(url, "catch"))
return handle_catch(request);
+ if (isEndpointUrl(url, "widget"))
+ return handle_widget(request);
+
std::string contentUrl = m_root + "/content" + url;
const std::string query = request.get_query();
if ( ! query.empty() )
@@ -866,6 +869,11 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re
}
}
+std::unique_ptr InternalServer::handle_widget(const RequestContext& request)
+{
+ return ContentResponse::build(*this, RESOURCE::templates::widget_html, get_default_data(), "text/html; charset=utf-8", true);
+}
+
std::unique_ptr InternalServer::handle_captured_external(const RequestContext& request)
{
std::string source = "";
diff --git a/src/server/internalServer.h b/src/server/internalServer.h
index 82574378c..f49b58189 100644
--- a/src/server/internalServer.h
+++ b/src/server/internalServer.h
@@ -143,6 +143,7 @@ class InternalServer {
std::unique_ptr handle_content(const RequestContext& request);
std::unique_ptr handle_raw(const RequestContext& request);
std::unique_ptr handle_locally_customized_resource(const RequestContext& request);
+ std::unique_ptr handle_widget(const RequestContext& request);
std::vector search_catalog(const RequestContext& request,
kiwix::OPDSDumper& opdsDumper);
diff --git a/static/resources_list.txt b/static/resources_list.txt
index 653fadd2f..79ec99a58 100644
--- a/static/resources_list.txt
+++ b/static/resources_list.txt
@@ -9,6 +9,7 @@ skin/iso6391To3.js
skin/isotope.pkgd.min.js
skin/index.js
skin/autoComplete.min.js
+skin/widget.js
skin/taskbar.css
skin/index.css
skin/fonts/Poppins.ttf
@@ -20,6 +21,7 @@ templates/search_result.xml
templates/error.html
templates/error.xml
templates/index.html
+templates/widget.html
templates/suggestion.json
templates/head_taskbar.html
templates/taskbar_part.html
diff --git a/static/skin/index.js b/static/skin/index.js
index fd1c338ea..8847b076f 100644
--- a/static/skin/index.js
+++ b/static/skin/index.js
@@ -1,4 +1,4 @@
-(function() {
+const kiwixServe = (function() {
const root = document.querySelector(`link[type='root']`).getAttribute('href');
const incrementalLoadingParams = {
start: 0,
@@ -17,6 +17,7 @@
let params = new URLSearchParams(window.location.search || filters || '');
let timer;
let languages = {};
+ let allowBookClick = true;
function queryUrlBuilder() {
let url = `${root}/catalog/search?`;
@@ -85,7 +86,7 @@
}
function generateBookHtml(book, sort = false) {
- const link = book.querySelector('link[type="text/html"]').getAttribute('href');
+ let link = book.querySelector('link[type="text/html"]').getAttribute('href');
let iconUrl;
book.querySelectorAll('link[rel="http://opds-spec.org/image/thumbnail"]').forEach(link => {
if (link.getAttribute('type').split(';')[1] == 'width=48' && !iconUrl) {
@@ -120,6 +121,9 @@
}
const faviconAttr = iconUrl != undefined ? `style="background-image: url('${iconUrl}')"` : '';
const languageAttr = langCode != '' ? `title="${language}" aria-label="${language}"` : 'style="background-color: transparent"';
+ if (!allowBookClick) {
+ link = "javascript:void(0)";
+ }
divTag.innerHTML = `