commit: 7f13e9b5f59ee496db5b8af7ab093a17c8f76066 Author: Lucas Ramage <ramage.lucas <AT> protonmail <DOT> com> AuthorDate: Thu Apr 11 19:21:27 2019 +0000 Commit: Göktürk Yüksek <gokturk <AT> gentoo <DOT> org> CommitDate: Thu Dec 19 20:52:49 2019 +0000 URL: https://gitweb.gentoo.org/proj/devmanual.git/commit/?id=7f13e9b5
Implement search functionality via lunr.js Bug: https://bugs.gentoo.org/674378 Signed-off-by: Lucas Ramage <ramage.lucas <AT> protonmail.com> Signed-off-by: Göktürk Yüksek <gokturk <AT> gentoo.org> .gitignore | 1 + Makefile | 6 +++++- devbook.xsl | 48 +++++++++++++++++++++++++++++++++++++++++++++ search.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ search_index.py | 26 +++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 720d4d6..ce644c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.html *.png +documents.js eclass-reference/ diff --git a/Makefile b/Makefile index 61daef4..4a52cc0 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,10 @@ prereq: { echo "dev-libs/libxml2 is required" >&2;\ exit 1; } +index: + @echo -n "var documents = " > documents.js + @./search_index.py text.xml >> documents.js + %.png : %.svg convert $< $@ @@ -42,6 +46,6 @@ validate: prereq && echo "xmllint validation successful" clean: - rm -f $(HTMLS) $(IMAGES) + rm -f $(HTMLS) $(IMAGES) documents.js .PHONY: all prereq validate clean diff --git a/devbook.xsl b/devbook.xsl index 96a0508..71dde54 100644 --- a/devbook.xsl +++ b/devbook.xsl @@ -536,7 +536,45 @@ </div> </div> </nav> + <nav class="navbar navbar-grey navbar-stick" id="devmanual-actions" role="navigation"> + <div class="container"> + <div class="row"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#gw-toolbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + <div class="collapse navbar-collapse" id="gw-toolbar"> + <div class="input-group"> + <input type="search" name="search" placeholder="Search" title="Search Gentoo Developer Manual [f]" accesskey="f" id="searchInput" class="form-control"/> + <div class="input-group-btn"> + <input type="submit" name="fulltext" value="Search" title="Search the pages for this text" id="mw-searchButton" class="searchButton btn btn-default" onclick="search()"/> + </div> + </div> + </div> + </div> + </div> + </nav> </header> + <div id="searchResults" class="modal fade" role="dialog"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal">x</button> + <h4 class="modal-title">Search Results</h4> + </div> + <div class="modal-body"> + <p>No results found.</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> <div class="container"> <div class="row"> <div class="col-md010"> @@ -583,6 +621,16 @@ </footer> <script src="https://assets.gentoo.org/tyrian/jquery.min.js"></script> <script src="https://assets.gentoo.org/tyrian/bootstrap.min.js"></script> + <script src="https://unpkg.com/lunr/lunr.js"></script> + <xsl:variable name="relative_path_depth" select="string-length(/guide/@self)-string-length(translate(/guide/@self, '/' , ''))"/> + <xsl:variable name="relative_path_depth_recursion"> + <xsl:call-template name="str:repeatString"> + <xsl:with-param name="count" select="$relative_path_depth"/> + <xsl:with-param name="append">../</xsl:with-param> + </xsl:call-template> + </xsl:variable> + <script src="{$relative_path_depth_recursion}documents.js"></script> + <script src="{$relative_path_depth_recursion}search.js"></script> </body> </html> </xsl:template> diff --git a/search.js b/search.js new file mode 100644 index 0000000..0b9292f --- /dev/null +++ b/search.js @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Gentoo Authors + * Distributed under the terms of the GNU GPL version 2 or later + */ +"use strict"; + +var search_index = lunr(function () { + this.ref('name'); + this.field('text'); + this.field('url'); + + documents.forEach(function (doc) { + this.add(doc); + }, this); +}); + +var search_input = document.getElementById("searchInput"); + +search_input.addEventListener("keyup", function(event) { + if(event.keyCode === 13) { + event.preventDefault(); + document.getElementById("mw-searchButton").click(); + } +}); + +function getContents(docs, article) { + var contents = { text: "", url: "" }; + + for (var i = 0; i< docs.length; i++) { + if (docs[i].name == article) { + contents.text = docs[i].text; + contents.url = docs[i].url; + } + } + return contents; +} + +function search() { + var term = document.getElementById("searchInput").value; + if (term !== "") { + var results = search_index.search(term); + if (results.length > 0) { + $("#searchResults .modal-body").empty(); + $.each(results, function(index, result) { + var title = result.ref; + var contents = getContents(documents, title); + + $("#searchResults .modal-body").append(`<article><h5><a href="${contents.url}"> + ${title}</a></h5><p>${contents.text}</p></article>`); + }); + } else { + $("#searchResults .modal-body").empty(); + $("#searchResults .modal-body").append("<p>No results found.</p>"); + } + } else { + $("#searchResults .modal-body").empty(); + $("#searchResults .modal-body").append("<p>No search term defined.</p>"); + } + $("#searchResults").modal(); +} diff --git a/search_index.py b/search_index.py new file mode 100755 index 0000000..2ab79f1 --- /dev/null +++ b/search_index.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +# Copyright 2019 Gentoo Authors +# Distributed under the terms of the GNU GPL version 2 or later +import json +import os +import sys +import xml.etree.ElementTree as ET + +xmlFile = sys.argv[1] +documents = [] + +for path, dirs, files in os.walk('.'): + if xmlFile in files: + tree = ET.parse(path + '/' + xmlFile) + root = tree.getroot() + for chapter in root.findall('chapter'): + try: + documents.append({"name": chapter.find('title').text, + "text": chapter.find('body').find('p').text, + "url": path }) + except: + pass + if '.git' in dirs: + dirs.remove('.git') # don't visit git directories + +print(json.dumps(documents))
