diff --git a/README.md b/README.md index c4d73dc2..2fff2efb 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Current features include: arguments, derived types, programs, and modules from the source code. - the ability to extract documentation from comments in the source code. - LaTeX support in documentation using [MathJax](https://www.mathjax.org/). -- searchable documentation, using Tipue Search. +- searchable documentation, using [Lunr Search](https://lunrjs.com). - author description and social media (including Github!) links. - links to download the source code. - links to individual files, both in their raw form or in HTML with syntax diff --git a/docs/index.rst b/docs/index.rst index fe56afe5..201e3de8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,8 +29,8 @@ Current features include: code, - LaTeX support in documentation using `MathJax `__, -- searchable documentation, using `Tipue Search - `__, +- searchable documentation, using `Lunr Search + `__, - author description and social media (including Github!) links, - links to download the source code, - links to individual files, both in their raw form or in HTML with diff --git a/ford/output.py b/ford/output.py index 0f958209..775987ed 100644 --- a/ford/output.py +++ b/ford/output.py @@ -289,7 +289,7 @@ def writeout(self) -> None: if self.data["graph"]: self.graphs.output_graphs(self.njobs) if self.data["search"]: - copytree(loc / "tipuesearch", out_dir / "tipuesearch") + copytree(loc / "search", out_dir / "search") self.tipue.print_output() try: diff --git a/ford/search/load_search.js b/ford/search/load_search.js new file mode 100644 index 00000000..3b6e61c3 --- /dev/null +++ b/ford/search/load_search.js @@ -0,0 +1,62 @@ + var items = tipuesearch['pages']; + var documents = tipuesearch["pages"] + var counter = 0 + + for (item in documents){ + documents[item]['id'] = counter; + counter = counter +1; + } + + var idx = lunr(function () { + this.ref('id') + this.field('title') + this.field('url') + this.field('text', { boost: 10 }) + this.field('tags') + + items.forEach(function (doc) { + this.add(doc) + }, this) +}) + +function lunr_search(term) { + document.getElementById('lunrsearchresults').innerHTML = '
    '; + if(term) { + document.getElementById('lunrsearchresults').innerHTML = "

    Search results for '" + term + "'

    " + document.getElementById('lunrsearchresults').innerHTML; + //put results on the screen. + var results = idx.search(term); + if(results.length>0){ + //console.log(idx.search(term)); + //if results + for (var i = 0; i < results.length; i++) { + // more statements + var ref = results[i]['ref']; + var url = documents[ref]['url']; + var title = documents[ref]['title']; + var body = documents[ref]['text'].substring(0,160)+'...'; + document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML = document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML + "
  • " + title + "
    "+ body +"
    "+ url +"
  • "; + } + } else { + document.querySelectorAll('#lunrsearchresults ul')[0].innerHTML = "
  • No results found...
  • "; + } + } + return false; +} + +function getQueryVariable(variable) { + var query = window.location.search.substring(1); + var vars = query.split('&'); + + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split('='); + + if (pair[0] === variable) { + return decodeURIComponent(pair[1].replace(/\+/g, '%20')); + } + } +} + +var searchTerm = getQueryVariable('q'); +if (searchTerm) { + lunr_search(searchTerm) +} diff --git a/ford/templates/base.html b/ford/templates/base.html index e0c18f31..ce2be81f 100644 --- a/ford/templates/base.html +++ b/ford/templates/base.html @@ -19,14 +19,9 @@ - {% if search|lower == 'true' %} - - {% endif %} {% if css %} {% endif %} - - @@ -170,12 +165,5 @@ {% endif %} - - {% if search|lower == 'true' %} - - - - {% endif %} - diff --git a/ford/templates/search.html b/ford/templates/search.html index d68d2c6f..de8288df 100644 --- a/ford/templates/search.html +++ b/ford/templates/search.html @@ -3,28 +3,19 @@ Search Results – {{ project }} {% endblock %} {% block body %} -
    -
    -

    Search Results

    -
    -
    -
    - - +
    +
    +

    Search Results

    +
    +
      +
      +
      +
      + +{% if search|lower == 'true' %} + + + +{% endif %} {% endblock %} diff --git a/ford/tipue_search.py b/ford/tipue_search.py index a40091e2..7b8554bc 100644 --- a/ford/tipue_search.py +++ b/ford/tipue_search.py @@ -43,7 +43,6 @@ from ford.settings import EntitySettings - class Tipue_Search_JSON_Generator: def __init__(self, output_path: os.PathLike, project_url: str): self.output_path = pathlib.Path(output_path) @@ -89,13 +88,13 @@ def create_node(self, html, loc, meta: EntitySettings): "title": page_title, "text": page_text, "tags": page_category, - "loc": str(page_url), + "url": str(page_url), } self.json_nodes.append(node) def print_output(self): - path = self.output_path / "tipuesearch" / "tipuesearch_content.js" + path = self.output_path / "search" / "search_database.json" root_node = {"pages": self.json_nodes} output = json.dumps(root_node, separators=(",", ":"), ensure_ascii=False) diff --git a/ford/tipuesearch/img/loader.gif b/ford/tipuesearch/img/loader.gif deleted file mode 100644 index 9c97738a..00000000 Binary files a/ford/tipuesearch/img/loader.gif and /dev/null differ diff --git a/ford/tipuesearch/img/search.png b/ford/tipuesearch/img/search.png deleted file mode 100644 index 8c6943d4..00000000 Binary files a/ford/tipuesearch/img/search.png and /dev/null differ diff --git a/ford/tipuesearch/tipuesearch.css b/ford/tipuesearch/tipuesearch.css deleted file mode 100644 index 5a94440f..00000000 --- a/ford/tipuesearch/tipuesearch.css +++ /dev/null @@ -1,158 +0,0 @@ - -/* -Tipue Search 4.0 -Copyright (c) 2014 Tipue -Tipue Search is released under the MIT License -http://www.tipue.com/search -*/ - - -/* -#tipue_search_input -{ - font: 13px/1.6 'open sans', sans-serif; - color: #333; - padding: 12px 12px 12px 40px; - width: 170px; - border: 1px solid #e2e2e2; - border-radius: 0; - -moz-appearance: none; - -webkit-appearance: none; - box-shadow: none; - outline: 0; - margin: 0; - background: #fff url('img/search.png') no-repeat 15px 15px; -} -*/ - -#tipue_search_content -{ - max-width: 650px; - padding-top: 15px; - margin: 0; -} -#tipue_search_loading -{ - padding-top: 60px; - background: #fff url('img/loader.gif') no-repeat left; -} - -#tipue_search_warning_head -{ - font: 300 15px/1.6 'Open Sans', sans-serif; - color: #555; -} -#tipue_search_warning -{ - font: 300 13px/1.6 'Open Sans', sans-serif; - color: #333; - margin: 7px 0; -} -#tipue_search_warning a -{ - color: #36c; - font-weight: 300; - text-decoration: none; -} -#tipue_search_warning a:hover -{ - color: #333; -} -#tipue_search_results_count -{ - font: 300 13px/1.6 'Open Sans', sans-serif; - color: #333; -} -.tipue_search_content_title -{ - font: 300 25px/1.7 'Open Sans', sans-serif; - text-rendering: optimizelegibility; - margin-top: 23px; -} -.tipue_search_content_title a -{ - color: #333; - text-decoration: none; -} -.tipue_search_content_title a:hover -{ - color: #555; -} -.tipue_search_content_url -{ - font: 300 13px/1.7 'Open Sans', sans-serif; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -} -.tipue_search_content_url a -{ - color: #06c; - text-decoration: none; -} -.tipue_search_content_url a:hover -{ - color: #333; -} -.tipue_search_content_text -{ - font: 300 15px/1.6 'Open Sans', sans-serif; - color: #555; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; - margin-top: 3px; -} -.h01 -{ - color: #333; - font-weight: 400; -} - -#tipue_search_foot -{ - margin: 51px 0 21px 0; -} -#tipue_search_foot_boxes -{ - padding: 0; - margin: 0; - font: 12px/1 'Open Sans', sans-serif; -} -#tipue_search_foot_boxes li -{ - list-style: none; - margin: 0; - padding: 0; - display: inline; -} -#tipue_search_foot_boxes li a -{ - padding: 9px 15px 10px 15px; - background-color: #f1f1f1; - border: 1px solid #dcdcdc; - border-radius: 1px; - color: #333; - margin-right: 7px; - text-decoration: none; - text-align: center; -} -#tipue_search_foot_boxes li.current -{ - padding: 9px 15px 10px 15px; - background: #fff; - border: 1px solid #dcdcdc; - border-radius: 1px; - color: #333; - margin-right: 7px; - text-align: center; -} -#tipue_search_foot_boxes li a:hover -{ - border: 1px solid #ccc; - background-color: #f3f3f3; -} diff --git a/ford/tipuesearch/tipuesearch.js b/ford/tipuesearch/tipuesearch.js deleted file mode 100644 index b411af5d..00000000 --- a/ford/tipuesearch/tipuesearch.js +++ /dev/null @@ -1,452 +0,0 @@ - -/* -Tipue Search 4.0 -Copyright (c) 2014 Tipue -Tipue Search is released under the MIT License -http://www.tipue.com/search -*/ - - -(function($) { - - $.fn.tipuesearch = function(options) { - - var set = $.extend( { - - 'show' : 7, - 'newWindow' : false, - 'showURL' : true, - 'minimumLength' : 3, - 'descriptiveWords' : 25, - 'highlightTerms' : true, - 'highlightEveryTerm' : false, - 'mode' : 'static', - 'liveDescription' : '*', - 'liveContent' : '*', - 'contentLocation' : 'tipuesearch/tipuesearch_content.json' - - }, options); - - return this.each(function() { - - var tipuesearch_in = { - pages: [] - }; - $.ajaxSetup({ - async: false - }); - - if (set.mode == 'live') - { - for (var i = 0; i < tipuesearch_pages.length; i++) - { - $.get(tipuesearch_pages[i], '', - function (html) - { - var cont = $(set.liveContent, html).text(); - cont = cont.replace(/\s+/g, ' '); - var desc = $(set.liveDescription, html).text(); - desc = desc.replace(/\s+/g, ' '); - - var t_1 = html.toLowerCase().indexOf(''); - var t_2 = html.toLowerCase().indexOf('', t_1 + 7); - if (t_1 != -1 && t_2 != -1) - { - var tit = html.slice(t_1 + 7, t_2); - } - else - { - var tit = 'No title'; - } - - tipuesearch_in.pages.push({ - "title": tit, - "text": desc, - "tags": cont, - "loc": tipuesearch_pages[i] - }); - } - ); - } - } - - if (set.mode == 'json') - { - $.getJSON(set.contentLocation, - function(json) - { - tipuesearch_in = $.extend({}, json); - } - ); - } - - if (set.mode == 'static') - { - tipuesearch_in = $.extend({}, tipuesearch); - } - - var tipue_search_w = ''; - if (set.newWindow) - { - tipue_search_w = ' target="_blank"'; - } - - function getURLP(name) - { - return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20')) || null; - } - if (getURLP('q')) - { - $('#tipue_search_input').val(getURLP('q')); - getTipueSearch(0, true); - } - - $(this).keyup(function(event) - { - if(event.keyCode == '13') - { - getTipueSearch(0, true); - } - }); - - function getTipueSearch(start, replace) - { - $('#tipue_search_content').hide(); - var out = ''; - var results = ''; - var show_replace = false; - var show_stop = false; - var standard = true; - var c = 0; - found = new Array(); - - var d = $('#tipue_search_input').val().toLowerCase(); - d = $.trim(d); - - if ((d.match("^\"") && d.match("\"$")) || (d.match("^'") && d.match("'$"))) - { - standard = false; - } - - if (standard) - { - var d_w = d.split(' '); - d = ''; - for (var i = 0; i < d_w.length; i++) - { - var a_w = true; - for (var f = 0; f < tipuesearch_stop_words.length; f++) - { - if (d_w[i] == tipuesearch_stop_words[f]) - { - a_w = false; - show_stop = true; - } - } - if (a_w) - { - d = d + ' ' + d_w[i]; - } - } - d = $.trim(d); - d_w = d.split(' '); - } - else - { - d = d.substring(1, d.length - 1); - } - - if (d.length >= set.minimumLength) - { - if (standard) - { - if (replace) - { - var d_r = d; - for (var i = 0; i < d_w.length; i++) - { - for (var f = 0; f < tipuesearch_replace.words.length; f++) - { - if (d_w[i] == tipuesearch_replace.words[f].word) - { - d = d.replace(d_w[i], tipuesearch_replace.words[f].replace_with); - show_replace = true; - } - } - } - d_w = d.split(' '); - } - - var d_t = d; - for (var i = 0; i < d_w.length; i++) - { - for (var f = 0; f < tipuesearch_stem.words.length; f++) - { - if (d_w[i] == tipuesearch_stem.words[f].word) - { - d_t = d_t + ' ' + tipuesearch_stem.words[f].stem; - } - } - } - d_w = d_t.split(' '); - - for (var i = 0; i < tipuesearch_in.pages.length; i++) - { - var score = 1000000000; - var s_t = tipuesearch_in.pages[i].text; - for (var f = 0; f < d_w.length; f++) - { - var pat = new RegExp(d_w[f], 'i'); - if (tipuesearch_in.pages[i].title.search(pat) != -1) - { - score -= (200000 - i); - } - if (tipuesearch_in.pages[i].text.search(pat) != -1) - { - score -= (150000 - i); - } - - if (set.highlightTerms) - { - if (set.highlightEveryTerm) - { - var patr = new RegExp('(' + d_w[f] + ')', 'gi'); - } - else - { - var patr = new RegExp('(' + d_w[f] + ')', 'i'); - } - s_t = s_t.replace(patr, "$1"); - } - if (tipuesearch_in.pages[i].tags.search(pat) != -1) - { - score -= (100000 - i); - } - - if (d_w[f].match("^-")) - { - pat = new RegExp(d_w[f].substring(1), 'i'); - if (tipuesearch_in.pages[i].title.search(pat) != -1 || tipuesearch_in.pages[i].text.search(pat) != -1 || tipuesearch_in.pages[i].tags.search(pat) != -1) - { - score = 1000000000; - } - } - } - - if (score < 1000000000) - { - found[c++] = score + '^' + tipuesearch_in.pages[i].title + '^' + s_t + '^' + tipuesearch_in.pages[i].loc; - } - } - } - else - { - for (var i = 0; i < tipuesearch_in.pages.length; i++) - { - var score = 1000000000; - var s_t = tipuesearch_in.pages[i].text; - var pat = new RegExp(d, 'i'); - if (tipuesearch_in.pages[i].title.search(pat) != -1) - { - score -= (200000 - i); - } - if (tipuesearch_in.pages[i].text.search(pat) != -1) - { - score -= (150000 - i); - } - - if (set.highlightTerms) - { - if (set.highlightEveryTerm) - { - var patr = new RegExp('(' + d + ')', 'gi'); - } - else - { - var patr = new RegExp('(' + d + ')', 'i'); - } - s_t = s_t.replace(patr, "$1"); - } - if (tipuesearch_in.pages[i].tags.search(pat) != -1) - { - score -= (100000 - i); - } - - if (score < 1000000000) - { - found[c++] = score + '^' + tipuesearch_in.pages[i].title + '^' + s_t + '^' + tipuesearch_in.pages[i].loc; - } - } - } - - if (c != 0) - { - if (show_replace == 1) - { - out += '
      Showing results for ' + d + '
      '; - out += '
      Search instead for ' + d_r + '
      '; - } - if (c == 1) - { - out += '
      1 result
      '; - } - else - { - c_c = c.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); - out += '
      ' + c_c + ' results
      '; - } - - found.sort(); - var l_o = 0; - for (var i = 0; i < found.length; i++) - { - var fo = found[i].split('^'); - if (l_o >= start && l_o < set.show + start) - { - out += ''; - - if (set.showURL) - { - out += ''; - } - - var t = fo[2]; - var t_d = ''; - var t_w = t.split(' '); - if (t_w.length < set.descriptiveWords) - { - t_d = t; - } - else - { - for (var f = 0; f < set.descriptiveWords; f++) - { - t_d += t_w[f] + ' '; - } - } - t_d = $.trim(t_d); - if (t_d.charAt(t_d.length - 1) != '.') - { - t_d += ' ...'; - } - out += '
      ' + t_d + '
      '; - } - l_o++; - } - - if (c > set.show) - { - var pages = Math.ceil(c / set.show); - var page = (start / set.show); - out += '