Commit 6e1e0d09 authored by colmoneill's avatar colmoneill

major milestone: search!

search integration via tipue search plugin, which binds the jquery plugin to pelican.
The pelican plugin generates the json of all the content, then tipue search integrates into a form for local search in a static site

commit includes appropriate changes to templates, will add local versions of js now
parent 8fbff451
Pipeline #16373997 passed with stages
in 2 minutes and 41 seconds
Title: It Looks Like We Are Sending A Letter
Date: 2011-04-15 15:33
Author: OSP
Tags: SansGuilt, Type
Tags: foundry, Intellectual property, letters, Libre Fonts, Licenses, Open Fonts
Tags: SansGuilt, Type, foundry, Intellectual property, letters, Libre Fonts, Licenses, Open Fonts
Slug: it-looks-like-we-are-sending-a-letter
Status: published
......
......@@ -21,6 +21,8 @@ AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None
THEME = "theme/osp-blog"
CSS_FILE = 'screen.css'
THEME_STATIC_DIR = 'theme'
DEFAULT_PAGINATION = 10
......@@ -38,5 +40,12 @@ ARTICLE_LANG_SAVE_AS = '{category}/{slug}-{lang}.html'
PAGE_LANG_URL = '{slug}-{lang}.html'
PAGE_LANG_SAVE_AS = '{slug}-{lang}.html'
DIRECT_TEMPLATES = ['search']
PLUGIN_PATHS = ['plugins']
PLUGINS = ['tipue_search',]
TIPUE_SEARCH = True
# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True
Tipue Search
============
A Pelican plugin to serialize generated HTML to JSON that can be used by jQuery plugin - Tipue Search.
Copyright (c) Talha Mansoor
Author | Talha Mansoor
----------------|-----
Author Email | talha131@gmail.com
Author Homepage | http://onCrashReboot.com
Github Account | https://github.com/talha131
Why do you need it?
===================
Static sites do not offer search feature out of the box. [Tipue Search](http://www.tipue.com/search/)
is a jQuery plugin that search the static site without using any third party service, like DuckDuckGo or Google.
Tipue Search offers 4 search modes. Its [JSON search mode](http://www.tipue.com/search/docs/json/) is the best search mode
especially for large sites.
Tipue's JSON search mode requires the textual content of site in JSON format.
Requirements
============
Tipue Search requires BeautifulSoup.
```bash
pip install beautifulsoup4
```
How Tipue Search works
=========================
Tipue Search serializes the generated HTML into JSON. Format of JSON is as follows
```python
{
"pages": [
{
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero.",
"tags": "Example Category",
"url" : "http://oncrashreboot.com/plugin-example.html",
"title": "Everything you want to know about Lorem Ipsum"
},
{
"text": "Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh.",
"tags": "Example Category",
"url" : "http://oncrashreboot.com/plugin-example-2.html",
"title": "Review of the book Lorem Ipsum"
}
]
}
```
JSON is written to file `tipuesearch_content.json` which is created in the root of `output` directory.
How to use
==========
To utilize JSON Search mode, your theme needs to have Tipue Search properly configured in it. [Official documentation](http://www.tipue.com/search/docs/#json) has the required details.
Pelican [Elegant Theme](https://github.com/talha131/pelican-elegant) and [Plumage
theme](https://github.com/kdeldycke/plumage) have Tipue Search configured. You can view their
code to understand the configuration.
from .tipue_search import *
# -*- coding: utf-8 -*-
"""
Tipue Search
============
A Pelican plugin to serialize generated HTML to JSON
that can be used by jQuery plugin - Tipue Search.
Copyright (c) Talha Mansoor
"""
from __future__ import unicode_literals
import os.path
import json
from bs4 import BeautifulSoup
from codecs import open
try:
from urlparse import urljoin
except ImportError:
from urllib.parse import urljoin
from pelican import signals
class Tipue_Search_JSON_Generator(object):
def __init__(self, context, settings, path, theme, output_path, *null):
self.output_path = output_path
self.context = context
self.siteurl = settings.get('SITEURL')
self.tpages = settings.get('TEMPLATE_PAGES')
self.output_path = output_path
self.json_nodes = []
def create_json_node(self, page):
if getattr(page, 'status', 'published') != 'published':
return
soup_title = BeautifulSoup(page.title.replace(' ', ' '), 'html.parser')
page_title = soup_title.get_text(' ', strip=True).replace('“', '"').replace('”', '"').replace('’', "'").replace('^', '^')
soup_text = BeautifulSoup(page.content, 'html.parser')
page_text = soup_text.get_text(' ', strip=True).replace('“', '"').replace('”', '"').replace('’', "'").replace('¶', ' ').replace('^', '^')
page_text = ' '.join(page_text.split())
page_category = page.category.name if getattr(page, 'category', 'None') != 'None' else ''
page_url = page.url if page.url else '.'
node = {'title': page_title,
'text': page_text,
'tags': page_category,
'url': page_url}
self.json_nodes.append(node)
def create_tpage_node(self, srclink):
srcfile = open(os.path.join(self.output_path, self.tpages[srclink]), encoding='utf-8')
soup = BeautifulSoup(srcfile, 'html.parser')
page_title = soup.title.string if soup.title is not None else ''
page_text = soup.get_text()
# Should set default category?
page_category = ''
page_url = urljoin(self.siteurl, self.tpages[srclink])
node = {'title': page_title,
'text': page_text,
'tags': page_category,
'url': page_url}
self.json_nodes.append(node)
def generate_output(self, writer):
path = os.path.join(self.output_path, 'tipuesearch_content.json')
pages = self.context['pages'] + self.context['articles']
for article in self.context['articles']:
pages += article.translations
for srclink in self.tpages:
self.create_tpage_node(srclink)
for page in pages:
self.create_json_node(page)
root_node = {'pages': self.json_nodes}
with open(path, 'w', encoding='utf-8') as fd:
json.dump(root_node, fd, separators=(',', ':'), ensure_ascii=False)
def get_generators(generators):
return Tipue_Search_JSON_Generator
def register():
signals.get_generators.connect(get_generators)
......@@ -31,6 +31,11 @@
{% if TAG_FEED_RSS and tag %}
<link href="{{ FEED_DOMAIN }}/{{ TAG_FEED_RSS|format(tag.slug) }}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" />
{% endif %}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Tipue-Search/5.0.0/tipuesearch_content.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Tipue-Search/5.0.0/tipuesearch_set.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Tipue-Search/5.0.0/tipuesearch.min.js"></script>
{% endblock head %}
</head>
......@@ -42,17 +47,17 @@
{% for title, link in MENUITEMS %}
<li><a href="{{ link }}">{{ title }}</a></li>
{% endfor %}
{% if DISPLAY_PAGES_ON_MENU %}
{% for p in pages %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% else %}
{% if DISPLAY_CATEGORIES_ON_MENU %}
{% for cat, null in categories %}
<li{% if cat == category %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a></li>
{% endfor %}
{% endif %}
{% endif %}
<li>
<form class="navbar-search" action="{{ SITEURL }}/search.html" onsubmit="return validateForm(this.elements['q'].value);">
<input type="text" class="search-query" placeholder="Search" name="q" id="tipue_search_input">
</form>
</li>
{% for p in pages %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% for cat, null in categories %}
<li{% if cat == category %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a></li>
{% endfor %}
</ul></nav><!-- /#menu -->
<div class="container">
{% block content %}
......@@ -60,5 +65,12 @@
</div>
<footer id="contentinfo" class="body">
</footer><!-- /#contentinfo -->
<script>
function validateForm(query)
{
return (query.length > 0);
}
</script>
</body>
</html>
......@@ -11,7 +11,7 @@
<header> <h2 class="entry-title"><a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h2> </header>
<footer class="post-info">
Category:{{article.category}}<br>
Tags:{{article.tags}}<br>
Tags:{% for tag in article.tags %}<a href="{{tag.url}}">{{ tag }}</a>, {% endfor %}<br>
<time class="published" datetime="{{ article.date.isoformat() }}"> {{ article.locale_date }} </time>
<address class="vcard author">By
{% for author in article.authors %}
......
{% extends 'base.html' %}
{% block content %}
HELOOO
<article>
search results:
<div class="span8 offset2">
<div id="tipue_search_content"><div id="tipue_search_loading"></div></div>
</div>
</article>
<script>
$(document).ready(function() {
$('#tipue_search_input').tipuesearch({
'mode' : 'json',
'show': 10,
'newWindow': false,
'contentLocation': 'tipuesearch_content.json'
});
});
</script>
{% endblock content %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment