mirror of https://github.com/tiyn/amphora-wiki
parent
51682d00f0
commit
3c49ea6687
@ -1 +1,2 @@
|
||||
__pycache__/
|
||||
indexdir/
|
||||
|
@ -1,10 +1,58 @@
|
||||
import config
|
||||
import search
|
||||
|
||||
import datetime
|
||||
from datetime import datetime
|
||||
import markdown
|
||||
import os
|
||||
from os import path
|
||||
import pathlib
|
||||
|
||||
import config
|
||||
import markdown
|
||||
|
||||
ENTRY_DIR = config.ENTRY_DIR
|
||||
WEBSITE = config.WEBSITE
|
||||
|
||||
|
||||
def gen_stand_string(path_ex):
|
||||
filename = os.path.join(ENTRY_DIR, path_ex)
|
||||
content_string = ''
|
||||
if path.exists(filename):
|
||||
title = open(filename).readline().rstrip('\n')
|
||||
text = open(filename).readlines()[1:]
|
||||
filename_no_end = filename.split('.', 1)[0]
|
||||
content_string += '<h1>' + title + '</h1>\n'
|
||||
if filename.endswith('.md'):
|
||||
content_string += gen_md_content(filename, 1)
|
||||
return content_string
|
||||
|
||||
|
||||
def gen_md_content(path_ex, depth):
|
||||
content_string = ''
|
||||
if path.exists(path_ex):
|
||||
filename = path_ex.split('.', 1)
|
||||
fileend = filename[len(filename) - 1]
|
||||
header = '#'
|
||||
for i in range(depth):
|
||||
header += '#'
|
||||
header += ' '
|
||||
markdown_lines = open(path_ex, "r").readlines()[1:]
|
||||
markdown_text = ''
|
||||
for line in markdown_lines:
|
||||
markdown_text += line.replace('# ', header)
|
||||
content_string = markdown.markdown(
|
||||
markdown_text, extensions=["fenced_code", "tables"]
|
||||
)
|
||||
return content_string
|
||||
|
||||
|
||||
ENTRY_DIR = 'templates/entry'
|
||||
def gen_query_res_string(query_str):
|
||||
src_results = search.search(query_str)
|
||||
res_string = ''
|
||||
res_string += '<ul>\n'
|
||||
for result in src_results:
|
||||
title = result['title']
|
||||
path = result['path']
|
||||
path = '/entry/' + path.split('/', 2)[2]
|
||||
res_string += '<li><a href="' + path + '">' + title + '</a></li>'
|
||||
res_string += '</ul>\n'
|
||||
return res_string
|
||||
|
@ -0,0 +1,11 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf import CSRFProtect
|
||||
from wtforms import TextField, SubmitField, ValidationError, validators
|
||||
|
||||
csrf = CSRFProtect()
|
||||
|
||||
|
||||
class SearchForm(FlaskForm):
|
||||
query_str = TextField(
|
||||
"Query", [validators.Required("Please enter the search term")])
|
||||
submit = SubmitField("Send")
|
@ -1,2 +1,5 @@
|
||||
Flask==1.1.2
|
||||
Markdown==3.1.1
|
||||
WTForms==2.2.1
|
||||
Flask==1.1.2
|
||||
Flask_WTF==0.14.3
|
||||
Whoosh==2.7.4
|
||||
|
@ -0,0 +1,55 @@
|
||||
import config
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from whoosh import scoring
|
||||
from whoosh.index import create_in, open_dir
|
||||
from whoosh.fields import Schema, TEXT, ID
|
||||
from whoosh.qparser import QueryParser
|
||||
|
||||
INDEX_DIR = "indexdir"
|
||||
DEF_TOPN = 10
|
||||
ENTRY_DIR = config.ENTRY_DIR
|
||||
|
||||
|
||||
def createSearchableData(root):
|
||||
'''
|
||||
Schema definition: title(name of file), path(as ID), content(indexed but not stored), textdata (stored text content)
|
||||
source:
|
||||
https://appliedmachinelearning.blog/2018/07/31/developing-a-fast-indexing-and-full-text-search-engine-with-whoosh-a-pure-pythhon-library/
|
||||
'''
|
||||
schema = Schema(title=TEXT(stored=True),
|
||||
path=ID(stored=True), content=TEXT)
|
||||
if not os.path.exists(INDEX_DIR):
|
||||
os.mkdir(INDEX_DIR)
|
||||
ix = create_in(INDEX_DIR, schema)
|
||||
writer = ix.writer()
|
||||
for r, d, f in os.walk(root):
|
||||
for file in f:
|
||||
path = os.path.join(r, file)
|
||||
fp = open(path)
|
||||
title = fp.readline()
|
||||
text = title + fp.read()
|
||||
writer.add_document(title=title, path=path, content=text)
|
||||
fp.close()
|
||||
writer.commit()
|
||||
|
||||
|
||||
def search_times(query_str, topN):
|
||||
ix = open_dir(INDEX_DIR)
|
||||
results = []
|
||||
with ix.searcher(weighting=scoring.BM25F) as s:
|
||||
query = QueryParser("content", ix.schema).parse(query_str)
|
||||
matches = s.search(query, limit=topN)
|
||||
for match in matches:
|
||||
results.append(
|
||||
{'title': match['title'], 'path': match['path'], 'match': match.score})
|
||||
return results
|
||||
|
||||
|
||||
def search(query_str):
|
||||
return search_times(query_str, DEF_TOPN)
|
||||
|
||||
|
||||
createSearchableData(ENTRY_DIR)
|
@ -0,0 +1,10 @@
|
||||
{% extends "template.html" %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
{% autoescape off %}
|
||||
<span>{{ content }}</span>
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
Test Entry Title 4
|
||||
This is a markdown file
|
||||
[link to entry3](../test-entry3.md)
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,10 @@
|
||||
Test Entry Title 5
|
||||
This is a markdown file
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,10 @@
|
||||
Test Entry Title 6
|
||||
This is a markdown file
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,15 @@
|
||||
{% extends "template.html" %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<form action="{{ url_for('search') }}" method=post>
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.query_str }}
|
||||
{{ form.submit }}
|
||||
</form>
|
||||
{% autoescape off %}
|
||||
<span>{{ content }}</span>
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Reference in new issue