commit 0925786f0de5440b6e42e3b714e8ff953cdb0145 Author: chimchooree Date: Fri May 26 10:42:12 2023 -0500 bflw diff --git a/Delete b/Delete new file mode 100644 index 0000000..afd59d3 --- /dev/null +++ b/Delete @@ -0,0 +1,14 @@ +Single Word +Flabby Words +Power Words +Prompt +Word of the Day +2020 +pH +C +David Mullich +Pieper +ite +Chris +Chris Keegan +Beautiful diff --git a/bflw/lazy_wiki.sqlite3 b/bflw/lazy_wiki.sqlite3 new file mode 100644 index 0000000..3b00e1b Binary files /dev/null and b/bflw/lazy_wiki.sqlite3 differ diff --git a/copy-code.sh b/copy-code.sh new file mode 100755 index 0000000..6a792b1 --- /dev/null +++ b/copy-code.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +scp -r lazywiki_uneditable vps: +ssh vps docker build -t lazywiki lazywiki_uneditable +ssh vps ./wiki.sh diff --git a/copy-db.sh b/copy-db.sh new file mode 100755 index 0000000..903cff3 --- /dev/null +++ b/copy-db.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +scp ~/bflw/lazy_wiki.sqlite3 vps: +ssh vps docker cp lazy_wiki.sqlite3 lazywiki:/db/lazy_wiki.sqlite3 +ssh vps docker restart lazywiki diff --git a/lazywiki/.gitignore b/lazywiki/.gitignore new file mode 100644 index 0000000..da2ae59 --- /dev/null +++ b/lazywiki/.gitignore @@ -0,0 +1,4 @@ +*.pyc +*.swp +venv/ +*.egg-info/ diff --git a/lazywiki/Dockerfile b/lazywiki/Dockerfile new file mode 100644 index 0000000..d2d3a4d --- /dev/null +++ b/lazywiki/Dockerfile @@ -0,0 +1,8 @@ +FROM python +WORKDIR /app +COPY . . +RUN pip install . +EXPOSE 8080 +VOLUME /db +ENTRYPOINT lazywiki /db + diff --git a/lazywiki/MANIFEST.in b/lazywiki/MANIFEST.in new file mode 100644 index 0000000..c452bf6 --- /dev/null +++ b/lazywiki/MANIFEST.in @@ -0,0 +1 @@ +include lazy_wiki/views/* diff --git a/lazywiki/build/lib/lazy_wiki/__init__.py b/lazywiki/build/lib/lazy_wiki/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lazywiki/build/lib/lazy_wiki/__main__.py b/lazywiki/build/lib/lazy_wiki/__main__.py new file mode 100644 index 0000000..f42c908 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/__main__.py @@ -0,0 +1,9 @@ +from . import web + +def main(): + + web.app.run(host = '0.0.0.0', port = 8080) + +if __name__ == '__main__': + print("444444") + main() diff --git a/lazywiki/build/lib/lazy_wiki/db.py b/lazywiki/build/lib/lazy_wiki/db.py new file mode 100644 index 0000000..c749f07 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/db.py @@ -0,0 +1,88 @@ +from sqlalchemy import create_engine +from sqlalchemy.sql import select, update, insert +from sqlalchemy.sql.expression import literal +from .schema import metadata, articles +from markdown import markdown +from string import whitespace, punctuation +import re +import os +import sys + +db_file = os.path.join(sys.argv[1], 'lazy_wiki.sqlite3') +regex = re.compile(r'^\W+|^\W*\w+\W*') + +# instantiate an engine for connecting to a database +engine = create_engine('sqlite:///{}'.format(db_file)) +# create tables if they don't exist +metadata.create_all(engine) +# connect to the database +dbc = engine.connect() + +def select_longest_keyword_string_starts_with(string): + ''' + Fetch the longest keyword that the given string starts with. + ''' + + query = select([articles]) \ + .where(literal(string).ilike(articles.c.title + '%')) + # may be bottleneck + results = [dict(u) for u in dbc.execute(query).fetchall()] + if not results: + return None + return max(results, key = lambda keyword : len(keyword['title'])) + +def select_article(keyword): + ''' + Fetch an article associated with the given keyword. + ''' + + query = select([articles]) \ + .where(articles.c.title == literal(keyword)) + try: + return dict(dbc.execute(query).fetchone()) + except: + return None + +def select_formatted_article(keyword): + ''' + Fetch an article associated with the given keyword, + add hyperlinks to it, and format it to HTML. + ''' + + # get article content + article = select_article(keyword) + raw = article['content'] + # add hyperlinks to the content + formatted = '' + # until the raw content is empty + while raw: + # if the remaining raw content starts with a keyword + word = select_longest_keyword_string_starts_with(raw) + if word and raw[len(word['title'])] in punctuation + whitespace: + # use original capitalization for hyperlink text + original = raw[:len(word['title'])] + # create a Markdown hyperlink + word = '[{}](/view/{})'.format(original, word['title']) + # cut off the start of the raw content + raw = raw[len(original):] + else: + # cut a word off the start of the raw content + word = regex.search(raw).group() + raw = raw[len(word):] + # add the hyperlink or word to the formatted content + formatted += word + + article['content'] = markdown(formatted) + return article + +def insert_article(**kwargs): + + query = insert(articles).values(**kwargs) + dbc.execute(query) + +def update_article(title, **kwargs): + + query = update(articles) \ + .where(articles.c.title == literal(title)) \ + .values(**kwargs) + dbc.execute(query) diff --git a/lazywiki/build/lib/lazy_wiki/schema.py b/lazywiki/build/lib/lazy_wiki/schema.py new file mode 100644 index 0000000..718f2d4 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/schema.py @@ -0,0 +1,10 @@ +from sqlalchemy import Table, Column, Integer, String, MetaData + +metadata = MetaData() + +articles = Table ( + 'article', metadata, + Column('id', Integer, primary_key = True), + Column('content', String, nullable = False), + Column('title', String, nullable = False) +) diff --git a/lazywiki/build/lib/lazy_wiki/views/delete.tpl b/lazywiki/build/lib/lazy_wiki/views/delete.tpl new file mode 100644 index 0000000..2494f4b --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/views/delete.tpl @@ -0,0 +1,19 @@ + + + + + % include('head.tpl', title = article['title']) + + + +
+ +

Delete {{article['title']}}?

+
+ -yes--no- + +
+ + + + diff --git a/lazywiki/build/lib/lazy_wiki/views/edit.tpl b/lazywiki/build/lib/lazy_wiki/views/edit.tpl new file mode 100644 index 0000000..a0504f3 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/views/edit.tpl @@ -0,0 +1,25 @@ + + + + + % include('head.tpl', title = 'Edit Article') + + + +
+ +
+
+

+ Synonyms:
+

Separate synonyms with bullets: cat•cats•catting•catted

+
+

+

+
+ +
+ + + + diff --git a/lazywiki/build/lib/lazy_wiki/views/head.tpl b/lazywiki/build/lib/lazy_wiki/views/head.tpl new file mode 100644 index 0000000..934cec9 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/views/head.tpl @@ -0,0 +1,7 @@ + + LazyWiki - {{title}} + + + + + diff --git a/lazywiki/build/lib/lazy_wiki/views/view.tpl b/lazywiki/build/lib/lazy_wiki/views/view.tpl new file mode 100644 index 0000000..48cafa0 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/views/view.tpl @@ -0,0 +1,31 @@ + + + + + % include('head.tpl', title = article['title']) + + + +
+ +
+

{{article['title']}}

+
+ -edit- +
+
+
+ +
+
+
+ {{!article['content']}} +
+
+
+ +
+ + + + diff --git a/lazywiki/build/lib/lazy_wiki/web.py b/lazywiki/build/lib/lazy_wiki/web.py new file mode 100644 index 0000000..00e1902 --- /dev/null +++ b/lazywiki/build/lib/lazy_wiki/web.py @@ -0,0 +1,69 @@ +from . import db +import bottle +from urllib.parse import unquote, quote +import os +import pathlib + +static_dir = os.path.join(os.path.expanduser('~'), 'lazy_wiki') +bottle.TEMPLATE_PATH = [os.path.join(os.path.dirname(__file__), 'views')] +app = bottle.Bottle() + +# Serve CSS +@app.get('/static/css/') +def serve_css(filename): + return bottle.static_file(filename, root=pathlib.Path(__file__).parent / 'static/css') + +@app.get('/favicon.ico', method='GET') +def get_favicon(): + return bottle.static_file('favicon.ico', root=pathlib.Path(__file__).parent / 'static/img') + + +@app.get('/edit/') +def new_article(): + ''' + Write a new article. + ''' + + return bottle.template('edit', article = {'title' : '', 'content' : ''}) + +@app.get('/delete/') +def delete_article(keyword): + ''' + Delete an article. + ''' + + article = db.select_formatted_article(unquote(keyword)) + return bottle.template('view', article = article) + +@app.get('/edit/') +def edit_article(keyword): + ''' + Edit an existing article. + ''' + + article = db.select_article(unquote(keyword)) + return bottle.template('edit', article = article) + +@app.get('/view/') +def get_article(keyword): + ''' + Get an article. + ''' + + article = db.select_formatted_article(unquote(keyword)) + return bottle.template('view', article = article) + +@app.post('/article') +def post_article(): + ''' + Post a new article. + ''' + + POST = bottle.request.POST.decode() + article = db.select_article(POST['title']) + if article: + db.update_article(**POST) + else: + db.insert_article(**POST) + + bottle.redirect('/view/{}'.format(quote(POST['title']))) diff --git a/lazywiki/lazy_wiki/__init__.py b/lazywiki/lazy_wiki/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lazywiki/lazy_wiki/__main__.py b/lazywiki/lazy_wiki/__main__.py new file mode 100644 index 0000000..985e47b --- /dev/null +++ b/lazywiki/lazy_wiki/__main__.py @@ -0,0 +1,9 @@ +from . import web +import sys + +def main(): + + web.app.run(host = '0.0.0.0', port = int(sys.argv[2])) + +if __name__ == '__main__': + main() diff --git a/lazywiki/lazy_wiki/db.py b/lazywiki/lazy_wiki/db.py new file mode 100644 index 0000000..7d2a473 --- /dev/null +++ b/lazywiki/lazy_wiki/db.py @@ -0,0 +1,87 @@ +from sqlalchemy import create_engine +from sqlalchemy.sql import select, update, insert +from sqlalchemy.sql.expression import literal +from .schema import metadata, articles +from markdown import markdown +import re +import os +import sys + +db_file = os.path.join(sys.argv[1], 'lazy_wiki.sqlite3') +regex = re.compile(r'^\W+|^\W*\w+\W*') + +# instantiate an engine for connecting to a database +engine = create_engine('sqlite:///{}'.format(db_file)) +# create tables if they don't exist +metadata.create_all(engine) +# connect to the database +dbc = engine.connect() + +def select_longest_keyword_string_starts_with(string): + ''' + Fetch the longest keyword that the given string starts with. + ''' + + query = select([articles]) \ + .where(literal(string).ilike(articles.c.title + '%')) + # may be bottleneck + results = [dict(u) for u in dbc.execute(query).fetchall()] + if not results: + return None + return max(results, key = lambda keyword : len(keyword['title'])) + +def select_article(keyword): + ''' + Fetch an article associated with the given keyword. + ''' + + query = select([articles]) \ + .where(articles.c.title == literal(keyword)) + try: + return dict(dbc.execute(query).fetchone()) + except: + return None + +def select_formatted_article(keyword): + ''' + Fetch an article associated with the given keyword, + add hyperlinks to it, and format it to HTML. + ''' + + # get article content + article = select_article(keyword) + raw = article['content'] + # add hyperlinks to the content + formatted = '' + # until the raw content is empty + while raw: + # if the remaining raw content starts with a keyword + word = select_longest_keyword_string_starts_with(raw) + if word: + # use original capitalization for hyperlink text + original = raw[:len(word['title'])] + # create a Markdown hyperlink + word = '[{}](/view/{})'.format(original, word['title']) + # cut off the start of the raw content + raw = raw[len(original):] + else: + # cut a word off the start of the raw content + word = regex.search(raw).group() + raw = raw[len(word):] + # add the hyperlink or word to the formatted content + formatted += word + + article['content'] = markdown(formatted) + return article + +def insert_article(**kwargs): + + query = insert(articles).values(**kwargs) + dbc.execute(query) + +def update_article(title, **kwargs): + + query = update(articles) \ + .where(articles.c.title == literal(title)) \ + .values(**kwargs) + dbc.execute(query) diff --git a/lazywiki/lazy_wiki/schema.py b/lazywiki/lazy_wiki/schema.py new file mode 100644 index 0000000..718f2d4 --- /dev/null +++ b/lazywiki/lazy_wiki/schema.py @@ -0,0 +1,10 @@ +from sqlalchemy import Table, Column, Integer, String, MetaData + +metadata = MetaData() + +articles = Table ( + 'article', metadata, + Column('id', Integer, primary_key = True), + Column('content', String, nullable = False), + Column('title', String, nullable = False) +) diff --git a/lazywiki/lazy_wiki/static/css/reset.css b/lazywiki/lazy_wiki/static/css/reset.css new file mode 100644 index 0000000..e29c0f5 --- /dev/null +++ b/lazywiki/lazy_wiki/static/css/reset.css @@ -0,0 +1,48 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/lazywiki/lazy_wiki/static/css/view.css b/lazywiki/lazy_wiki/static/css/view.css new file mode 100644 index 0000000..a2c5458 --- /dev/null +++ b/lazywiki/lazy_wiki/static/css/view.css @@ -0,0 +1,103 @@ +* { + padding:0; + margin:0; + font-family: sans-serif; + background-color: #171321; + font-size: 1em; + color: #d2c1e5; + font-family: Ubuntu; +} +html, body {padding:0; margin:0; height:100%;} +footer { +} +a, a:link, a:visited, a:hover, a:active, b, p, ul, ol, li, h1, h2, h3, h4, h5, img, i, hr, pre, code { + background-color: transparent; +} +a, a:link, a:visited, a:hover, a:active { + text-decoration: none; +} +a:link, a:visited { + color: #A68BA7; +} +a:hover, a:active { + color: #FCECC9; +} +p { + text-indent: 2em; +} +ul, ol { + list-style-type: disc; + list-style-position: inside; + margin-bottom: 1.5em; +} +li { + padding-left: 2em; +} +h1 { + font-size: 1.5em; +} +h1 a, h1 a:visited, h1 a:hover, h1 a:active { +} +h2 a:hover, h2 a:active { +} +h2 { + font-size: 1.4em; +} +h3 { + font-size: 1.3em; +} +h4 { + font-size: 1.2em; +} +h4 { + font-size: 1.1em; +} +p { + line-height: 2em; + margin-bottom: 1.5em; +} +pre, code { + font-size: 0.9em; + margin-top: 1.5em; + margin-bottom: 1.5em; + padding-left: 0.5em; + padding-right: 0.5em; + padding-bottom: 0.1em; +} +img { + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +input, textarea { + padding: .5em; + border: 2px solid #3b3748; +} +::-moz-selection { /* Code for Firefox */ + background: #c76199; +} + +::selection { + background: #c76199; +} + +.container { + margin: 2em; +} +.title { + margin: 0em; +} +.edit { + font-size: .8em; + color: #3b3748; + margin: 0em; +} +.edit a { + color: #3b3748; +} +.content { + width: 80%; + max-width: 75ch; + margin: auto; + margin-top: 1em; +} diff --git a/lazywiki/lazy_wiki/static/img/favicon.ico b/lazywiki/lazy_wiki/static/img/favicon.ico new file mode 100644 index 0000000..28502c9 Binary files /dev/null and b/lazywiki/lazy_wiki/static/img/favicon.ico differ diff --git a/lazywiki/lazy_wiki/views/delete.tpl b/lazywiki/lazy_wiki/views/delete.tpl new file mode 100644 index 0000000..2494f4b --- /dev/null +++ b/lazywiki/lazy_wiki/views/delete.tpl @@ -0,0 +1,19 @@ + + + + + % include('head.tpl', title = article['title']) + + + +
+ +

Delete {{article['title']}}?

+
+ -yes--no- + +
+ + + + diff --git a/lazywiki/lazy_wiki/views/edit.tpl b/lazywiki/lazy_wiki/views/edit.tpl new file mode 100644 index 0000000..067e48e --- /dev/null +++ b/lazywiki/lazy_wiki/views/edit.tpl @@ -0,0 +1,25 @@ + + + + + % include('head.tpl', title = 'Edit Article') + + + +
+ +
+
+

+ +
+

+

+
+ +
+ + + + diff --git a/lazywiki/lazy_wiki/views/head.tpl b/lazywiki/lazy_wiki/views/head.tpl new file mode 100644 index 0000000..934cec9 --- /dev/null +++ b/lazywiki/lazy_wiki/views/head.tpl @@ -0,0 +1,7 @@ + + LazyWiki - {{title}} + + + + + diff --git a/lazywiki/lazy_wiki/views/view.tpl b/lazywiki/lazy_wiki/views/view.tpl new file mode 100644 index 0000000..48cafa0 --- /dev/null +++ b/lazywiki/lazy_wiki/views/view.tpl @@ -0,0 +1,31 @@ + + + + + % include('head.tpl', title = article['title']) + + + +
+ +
+

{{article['title']}}

+
+ -edit- +
+
+
+ +
+
+
+ {{!article['content']}} +
+
+
+ +
+ + + + diff --git a/lazywiki/lazy_wiki/web.py b/lazywiki/lazy_wiki/web.py new file mode 100644 index 0000000..00e1902 --- /dev/null +++ b/lazywiki/lazy_wiki/web.py @@ -0,0 +1,69 @@ +from . import db +import bottle +from urllib.parse import unquote, quote +import os +import pathlib + +static_dir = os.path.join(os.path.expanduser('~'), 'lazy_wiki') +bottle.TEMPLATE_PATH = [os.path.join(os.path.dirname(__file__), 'views')] +app = bottle.Bottle() + +# Serve CSS +@app.get('/static/css/') +def serve_css(filename): + return bottle.static_file(filename, root=pathlib.Path(__file__).parent / 'static/css') + +@app.get('/favicon.ico', method='GET') +def get_favicon(): + return bottle.static_file('favicon.ico', root=pathlib.Path(__file__).parent / 'static/img') + + +@app.get('/edit/') +def new_article(): + ''' + Write a new article. + ''' + + return bottle.template('edit', article = {'title' : '', 'content' : ''}) + +@app.get('/delete/') +def delete_article(keyword): + ''' + Delete an article. + ''' + + article = db.select_formatted_article(unquote(keyword)) + return bottle.template('view', article = article) + +@app.get('/edit/') +def edit_article(keyword): + ''' + Edit an existing article. + ''' + + article = db.select_article(unquote(keyword)) + return bottle.template('edit', article = article) + +@app.get('/view/') +def get_article(keyword): + ''' + Get an article. + ''' + + article = db.select_formatted_article(unquote(keyword)) + return bottle.template('view', article = article) + +@app.post('/article') +def post_article(): + ''' + Post a new article. + ''' + + POST = bottle.request.POST.decode() + article = db.select_article(POST['title']) + if article: + db.update_article(**POST) + else: + db.insert_article(**POST) + + bottle.redirect('/view/{}'.format(quote(POST['title']))) diff --git a/lazywiki/setup.py b/lazywiki/setup.py new file mode 100644 index 0000000..b94ec15 --- /dev/null +++ b/lazywiki/setup.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +from setuptools import setup, find_packages + +setup ( + name = 'Lazy Wiki', + version = '0.0.2', + packages = find_packages(), + include_package_data = True, + entry_points = { + 'console_scripts' : [ + 'lazywiki=lazy_wiki.__main__:main' + ] + }, + install_requires = [ + 'sqlalchemy==1.4.42', + 'bottle', + 'markdown' + ] +) diff --git a/lazywiki_uneditable/.gitignore b/lazywiki_uneditable/.gitignore new file mode 100644 index 0000000..da2ae59 --- /dev/null +++ b/lazywiki_uneditable/.gitignore @@ -0,0 +1,4 @@ +*.pyc +*.swp +venv/ +*.egg-info/ diff --git a/lazywiki_uneditable/Dockerfile b/lazywiki_uneditable/Dockerfile new file mode 100644 index 0000000..d2d3a4d --- /dev/null +++ b/lazywiki_uneditable/Dockerfile @@ -0,0 +1,8 @@ +FROM python +WORKDIR /app +COPY . . +RUN pip install . +EXPOSE 8080 +VOLUME /db +ENTRYPOINT lazywiki /db + diff --git a/lazywiki_uneditable/MANIFEST.in b/lazywiki_uneditable/MANIFEST.in new file mode 100644 index 0000000..c452bf6 --- /dev/null +++ b/lazywiki_uneditable/MANIFEST.in @@ -0,0 +1 @@ +include lazy_wiki/views/* diff --git a/lazywiki_uneditable/lazy_wiki/__init__.py b/lazywiki_uneditable/lazy_wiki/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lazywiki_uneditable/lazy_wiki/__main__.py b/lazywiki_uneditable/lazy_wiki/__main__.py new file mode 100644 index 0000000..4480afa --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/__main__.py @@ -0,0 +1,9 @@ +from . import web + +def main(): + + web.app.run(host = '0.0.0.0', port = 8080) + +if __name__ == '__main__': + print("33333") + main() diff --git a/lazywiki_uneditable/lazy_wiki/db.py b/lazywiki_uneditable/lazy_wiki/db.py new file mode 100644 index 0000000..7d2a473 --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/db.py @@ -0,0 +1,87 @@ +from sqlalchemy import create_engine +from sqlalchemy.sql import select, update, insert +from sqlalchemy.sql.expression import literal +from .schema import metadata, articles +from markdown import markdown +import re +import os +import sys + +db_file = os.path.join(sys.argv[1], 'lazy_wiki.sqlite3') +regex = re.compile(r'^\W+|^\W*\w+\W*') + +# instantiate an engine for connecting to a database +engine = create_engine('sqlite:///{}'.format(db_file)) +# create tables if they don't exist +metadata.create_all(engine) +# connect to the database +dbc = engine.connect() + +def select_longest_keyword_string_starts_with(string): + ''' + Fetch the longest keyword that the given string starts with. + ''' + + query = select([articles]) \ + .where(literal(string).ilike(articles.c.title + '%')) + # may be bottleneck + results = [dict(u) for u in dbc.execute(query).fetchall()] + if not results: + return None + return max(results, key = lambda keyword : len(keyword['title'])) + +def select_article(keyword): + ''' + Fetch an article associated with the given keyword. + ''' + + query = select([articles]) \ + .where(articles.c.title == literal(keyword)) + try: + return dict(dbc.execute(query).fetchone()) + except: + return None + +def select_formatted_article(keyword): + ''' + Fetch an article associated with the given keyword, + add hyperlinks to it, and format it to HTML. + ''' + + # get article content + article = select_article(keyword) + raw = article['content'] + # add hyperlinks to the content + formatted = '' + # until the raw content is empty + while raw: + # if the remaining raw content starts with a keyword + word = select_longest_keyword_string_starts_with(raw) + if word: + # use original capitalization for hyperlink text + original = raw[:len(word['title'])] + # create a Markdown hyperlink + word = '[{}](/view/{})'.format(original, word['title']) + # cut off the start of the raw content + raw = raw[len(original):] + else: + # cut a word off the start of the raw content + word = regex.search(raw).group() + raw = raw[len(word):] + # add the hyperlink or word to the formatted content + formatted += word + + article['content'] = markdown(formatted) + return article + +def insert_article(**kwargs): + + query = insert(articles).values(**kwargs) + dbc.execute(query) + +def update_article(title, **kwargs): + + query = update(articles) \ + .where(articles.c.title == literal(title)) \ + .values(**kwargs) + dbc.execute(query) diff --git a/lazywiki_uneditable/lazy_wiki/schema.py b/lazywiki_uneditable/lazy_wiki/schema.py new file mode 100644 index 0000000..718f2d4 --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/schema.py @@ -0,0 +1,10 @@ +from sqlalchemy import Table, Column, Integer, String, MetaData + +metadata = MetaData() + +articles = Table ( + 'article', metadata, + Column('id', Integer, primary_key = True), + Column('content', String, nullable = False), + Column('title', String, nullable = False) +) diff --git a/lazywiki_uneditable/lazy_wiki/static/css/reset.css b/lazywiki_uneditable/lazy_wiki/static/css/reset.css new file mode 100644 index 0000000..e29c0f5 --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/static/css/reset.css @@ -0,0 +1,48 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/lazywiki_uneditable/lazy_wiki/static/css/view.css b/lazywiki_uneditable/lazy_wiki/static/css/view.css new file mode 100644 index 0000000..7d4f8dc --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/static/css/view.css @@ -0,0 +1,101 @@ +* { + padding:0; + margin:0; + font-family: sans-serif; + /*background-color: #171321;*/ + font-size: 1em; + color: #d2c1e5; + font-family: Ubuntu; +} +html {padding:0; margin:0; height:100%;} +body { + padding:0; margin:0; height:100%; + background-image: linear-gradient(#060114, #0F0233); + background-repeat: no-repeat; + background-attachment: fixed; +} +footer { +} +a, a:link, a:visited, a:hover, a:active, b, p, ul, ol, li, h1, h2, h3, h4, h5, img, i, hr, pre, code { + background-color: transparent; +} +a, a:link, a:visited, a:hover, a:active { + text-decoration: none; +} +a:link, a:visited { + color: #A68BA7; +} +a:hover, a:active { + color: #FCECC9; +} +p { + text-indent: 2em; +} +ul, ol { + list-style-type: disc; + list-style-position: inside; + margin-bottom: 1.5em; +} +li { + padding-left: 2em; +} +h1 { + font-size: 1.5em; +} +h1 a, h1 a:visited, h1 a:hover, h1 a:active { +} +h2 a:hover, h2 a:active { +} +h2 { + font-size: 1.4em; +} +h3 { + font-size: 1.3em; +} +h4 { + font-size: 1.2em; +} +h4 { + font-size: 1.1em; +} +p { + line-height: 2em; + margin-bottom: 1.5em; +} +pre, code { + font-size: 0.9em; + margin-top: 1.5em; + margin-bottom: 1.5em; + padding-left: 0.5em; + padding-right: 0.5em; + padding-bottom: 0.1em; +} +img { + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +input, textarea { + padding: .5em; + border: 2px solid #3b3748; +} +.container { + margin: 2em; +} +.title { + margin: 0em; +} +.edit { + font-size: .8em; + color: #3b3748; + margin: 0em; +} +.edit a { + color: #3b3748; +} +.content { + width: 80%; + max-width: 75ch; + margin: auto; + margin-top: 1em; +} diff --git a/lazywiki_uneditable/lazy_wiki/static/img/favicon.ico b/lazywiki_uneditable/lazy_wiki/static/img/favicon.ico new file mode 100644 index 0000000..28502c9 Binary files /dev/null and b/lazywiki_uneditable/lazy_wiki/static/img/favicon.ico differ diff --git a/lazywiki_uneditable/lazy_wiki/views/head.tpl b/lazywiki_uneditable/lazy_wiki/views/head.tpl new file mode 100644 index 0000000..934cec9 --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/views/head.tpl @@ -0,0 +1,7 @@ + + LazyWiki - {{title}} + + + + + diff --git a/lazywiki_uneditable/lazy_wiki/views/view.tpl b/lazywiki_uneditable/lazy_wiki/views/view.tpl new file mode 100644 index 0000000..140e99c --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/views/view.tpl @@ -0,0 +1,31 @@ + + + + + % include('head.tpl', title = article['title']) + + + +
+ +
+

{{article['title']}}

+ +
+
+ +
+
+
+ {{!article['content']}} +
+
+
+ +
+ + + + diff --git a/lazywiki_uneditable/lazy_wiki/web.py b/lazywiki_uneditable/lazy_wiki/web.py new file mode 100644 index 0000000..c2da439 --- /dev/null +++ b/lazywiki_uneditable/lazy_wiki/web.py @@ -0,0 +1,54 @@ +from . import db +import bottle +from urllib.parse import unquote, quote +import os +import pathlib + +static_dir = os.path.join(os.path.expanduser('~'), 'lazy_wiki') +bottle.TEMPLATE_PATH = [os.path.join(os.path.dirname(__file__), 'views')] +app = bottle.Bottle() + +# Serve CSS +@app.get('/static/css/') +def serve_css(filename): + return bottle.static_file(filename, root=pathlib.Path(__file__).parent / 'static/css') + +@app.get('/favicon.ico', method='GET') +def get_favicon(): + return bottle.static_file('favicon.ico', root=pathlib.Path(__file__).parent / 'static/img') + +# Error Page +@app.error(404) +def error404(error): + return "unfortunately, a 404 error. the page you're searching for doesn't exist. (or is it just in hiding?) try another page! -return to blessfrey- " +@app.error(500) +def error500(error): + return "unfortunately, a 500 error. something is wrong with the page you're trying to find, if it exists at all. try another page! -return to blessfrey-" +@app.error(502) +def error502(error): + return "unfortunately, a 502 error. this was likely due to website maintenance. usually it'll be back up before you finish reading this, but otherwise, I'll notice something's wrong soon! -return to blessfrey-" + +@app.get('/') +def home(): + return get_article(Main_Page) +@app.get('/Home') +def home1(): + return get_article(Main_Page) +@app.get('/Index') +def home2(): + return get_article(Main_Page) +@app.get('/Main') +def home3(): + return get_article(Main_Page) +@app.get('/Main_Page') +def home4(): + return get_article(Main_Page) + +@app.get('/view/') +def get_article(keyword): + ''' + Get an article. + ''' + + article = db.select_formatted_article(unquote(keyword)) + return bottle.template('view', article = article) diff --git a/lazywiki_uneditable/setup.py b/lazywiki_uneditable/setup.py new file mode 100644 index 0000000..18ff8d1 --- /dev/null +++ b/lazywiki_uneditable/setup.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from setuptools import setup, find_packages + +setup ( + name = 'Lazy Wiki', + version = '0.0.3', + packages = find_packages(), + include_package_data = True, + entry_points = { + 'console_scripts' : [ + 'lazywiki=lazy_wiki.__main__:main' + ] + }, + install_requires = [ + 'sqlalchemy==1.4.42', + 'bottle', + 'markdown' + ], + data_files = [ + ('/', + [ + 'lazy_wiki/static/css/view.css', + 'lazy_wiki/static/css/reset.css', + 'lazy_wiki/static/img/favicon.ico' + ] + ) + ] +)