Move to marko rendering; change subnode URLs; and much more.
This commit is contained in:
parent
4b66bd2581
commit
0c85e5f8d7
9 changed files with 168 additions and 39 deletions
40
app/agora.py
40
app/agora.py
|
@ -28,18 +28,7 @@ G = db.G
|
|||
@bp.route('/index')
|
||||
@bp.route('/')
|
||||
def index():
|
||||
node='index'
|
||||
n = G.node(node)
|
||||
n.subnodes = util.rank(n.subnodes, user='agora')
|
||||
return render_template(
|
||||
'node_rendered.html',
|
||||
node=n,
|
||||
backlinks=n.back_links(),
|
||||
pull_nodes=n.pull_nodes() if n else [],
|
||||
pulling_nodes=n.pulling_nodes() if n else [],
|
||||
pushing_nodes=n.pushing_nodes() if n else [],
|
||||
forwardlinks=n.forward_links() if n else [],
|
||||
)
|
||||
return redirect(url_for('.node', node='index'))
|
||||
|
||||
@bp.route('/help')
|
||||
def help():
|
||||
|
@ -117,7 +106,8 @@ def jump():
|
|||
def node(node):
|
||||
|
||||
n = G.node(node)
|
||||
n.subnodes = util.uprank(n.subnodes, user='flancian')
|
||||
# earlier in the list means more highly ranked.
|
||||
n.subnodes = util.uprank(n.subnodes, users=['agora', 'flancian'])
|
||||
|
||||
search_subnodes = db.search_subnodes(node)
|
||||
|
||||
|
@ -133,8 +123,30 @@ def node(node):
|
|||
query=n.wikilink.replace('-', '%20')
|
||||
)
|
||||
|
||||
@bp.route('/node/<node>@<user>')
|
||||
@bp.route('/@<user>/<node>')
|
||||
def subnode(node, user):
|
||||
|
||||
n = G.node(node)
|
||||
|
||||
n.subnodes = util.filter(n.subnodes, user)
|
||||
search_subnodes = db.search_subnodes_by_user(node, user)
|
||||
|
||||
return render_template(
|
||||
'subnode_rendered.html',
|
||||
node=n,
|
||||
#backlinks=n.back_links(),
|
||||
#pull_nodes=n.pull_nodes() if n else [],
|
||||
#forwardlinks=n.forward_links() if n else [],
|
||||
#search=search_subnodes,
|
||||
#pulling_nodes=n.pulling_nodes(),
|
||||
#pushing_nodes=n.pushing_nodes(),
|
||||
#query=n.wikilink.replace('-', '%20')
|
||||
)
|
||||
|
||||
|
||||
@bp.route('/subnode/<path:subnode>')
|
||||
def subnode(subnode):
|
||||
def old_subnode(subnode):
|
||||
return render_template('subnode_rendered.html', subnode=db.subnode_by_uri(subnode), backlinks=db.subnodes_by_outlink(subnode))
|
||||
|
||||
@bp.route('/u/<user>')
|
||||
|
|
13
app/db.py
13
app/db.py
|
@ -14,10 +14,10 @@
|
|||
|
||||
import cachetools.func
|
||||
import glob
|
||||
import marko
|
||||
import re
|
||||
import os
|
||||
from . import config
|
||||
from . import render
|
||||
from . import util
|
||||
from collections import defaultdict
|
||||
from fuzzywuzzy import fuzz
|
||||
|
@ -212,6 +212,13 @@ class Subnode:
|
|||
# hack hack
|
||||
return 100-fuzz.ratio(self.wikilink, other.wikilink)
|
||||
|
||||
def render(self):
|
||||
# hack hack
|
||||
if self.uri.endswith('md') or self.uri.endswith('MD'):
|
||||
return render.markdown(self.content)
|
||||
if self.uri.endswith('org') or self.uri.endswith('ORG'):
|
||||
return render.markdown(self.content)
|
||||
|
||||
def go(self):
|
||||
"""
|
||||
returns a set of go links contained in this subnode
|
||||
|
@ -336,6 +343,10 @@ def search_subnodes(query):
|
|||
subnodes = [subnode for subnode in G.subnodes() if re.search(query, subnode.content, re.IGNORECASE)]
|
||||
return subnodes
|
||||
|
||||
def search_subnodes_by_user(query, user):
|
||||
subnodes = [subnode for subnode in G.subnodes() if re.search(query, subnode.content, re.IGNORECASE) and subnode.user == user]
|
||||
return subnodes
|
||||
|
||||
def subnodes_by_user(user):
|
||||
subnodes = [subnode for subnode in G.subnodes() if subnode.user == user]
|
||||
return subnodes
|
||||
|
|
51
app/render.py
Normal file
51
app/render.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# This file contains renderers from the supported input formats.
|
||||
# As of [[2020-01-09]]:
|
||||
# - markdown
|
||||
# - orgmode
|
||||
|
||||
import re
|
||||
from . import config
|
||||
from . import util
|
||||
from marko import Markdown, inline
|
||||
|
||||
|
||||
# Markdown
|
||||
class WikilinkElement(inline.InlineElement):
|
||||
pattern = r'\[\[ *(.+?) *\]\]'
|
||||
parse_children = True
|
||||
|
||||
def __init__(self, match):
|
||||
self.target = match.group(1)
|
||||
|
||||
class WikilinkRendererMixin(object):
|
||||
|
||||
# This name is magic; it must match render_<class_name_in_snake_case>.
|
||||
def render_wikilink_element(self, element):
|
||||
return '<span class="wikilink-marker">[[</span><a href="{}">{}</a><span class="wikilink-marker">]]</span>'.format(
|
||||
# util.canonical_wikilink(self.escape_url(element.target)), self.render_children(element)
|
||||
util.canonical_wikilink(element.target), self.render_children(element)
|
||||
)
|
||||
|
||||
class Wikilinks():
|
||||
elements = [WikilinkElement]
|
||||
renderer_mixins = [WikilinkRendererMixin]
|
||||
|
||||
markdown = Markdown(extensions=[Wikilinks])
|
||||
|
||||
|
||||
# Org-mode goes here.
|
|
@ -80,6 +80,19 @@ nav { font-family: sans-serif}
|
|||
.subnode-header {
|
||||
font-style: italic;
|
||||
margin-bottom: 1em;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.subnode-id {
|
||||
text-align: left;
|
||||
align: left;
|
||||
}
|
||||
|
||||
.subnode-links {
|
||||
text-align: left;
|
||||
align: left;
|
||||
}
|
||||
|
||||
.links {
|
||||
|
@ -137,6 +150,11 @@ nav { font-family: sans-serif}
|
|||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.wikilink-marker {
|
||||
/* deemphasize */
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
/* hypothes.is
|
||||
This totally doesn't work, at all, and I have no idea why :)
|
||||
*/
|
||||
|
|
|
@ -31,10 +31,14 @@ Try listing all <a href="/nodes">nodes</a> or perhaps <a href="/search">search</
|
|||
<div class="node">
|
||||
<span class="node-header"><strong>Node</strong> <a href="/node/{{node.uri}}">[[{{node.uri}}]]</a></span>
|
||||
|
||||
|
||||
{% for subnode in node.subnodes %}
|
||||
<div class="subnode">
|
||||
<span class="subnode-header"><strong>Subnode</strong> <a href="{{subnode.url}}">{{subnode.uri}}</a> by <a href="/@{{subnode.user}}">@{{subnode.user}}</a></span>
|
||||
{{ subnode.content|markdown|linkify|safe }}
|
||||
<div class="subnode-header">
|
||||
<span><strong>Subnode</strong> <a href="/@{{subnode.user}}/{{node.uri}}">[[{{node.uri}}@{{subnode.user}}]]</a></span>
|
||||
<span class="subnode-links">(by <a href="/@{{subnode.user}}">@{{subnode.user}}</a>)</span>
|
||||
</div>
|
||||
{{ subnode.render()|linkify|safe }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -47,7 +51,7 @@ Try listing all <a href="/nodes">nodes</a> or perhaps <a href="/search">search</
|
|||
{% for subnode in node.subnodes %}
|
||||
<div class="subnode">
|
||||
<span class="subnode-header"><strong>Subnode</strong> <a href="{{subnode.url}}">{{subnode.uri}}</a> by <a href="/@{{subnode.user}}">@{{subnode.user}}</a></span>
|
||||
{{ subnode.content|markdown|linkify|safe }}
|
||||
{{ subnode.render()|linkify|safe }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<br />
|
||||
|
||||
<div class="search">
|
||||
<strong>Search (the internet)</strong> <br />
|
||||
<a href="https://www.google.com/search?q={{query}}">Google</a> <br />
|
||||
<a href="https://www.duckduckgo.com/{{query}}">DuckDuckGo</a> <br />
|
||||
<a href="https://en.wikipedia.org/w/index.php?search={{query}}&title=Special%3ASearch&fulltext=1">Wikipedia</a> <br />
|
||||
<a href="https://twitter.com/search/?f=live&q={{query}}">Twitter</a> <br />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<div class="search">
|
||||
|
@ -27,13 +36,4 @@ No search results.
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="search">
|
||||
<strong>Search (the internet)</strong> <br />
|
||||
<a href="https://www.google.com/search?q={{query}}">Google</a> <br />
|
||||
<a href="https://www.duckduckgo.com/{{query}}">DuckDuckGo</a> <br />
|
||||
<a href="https://en.wikipedia.org/w/index.php?search={{query}}&title=Special%3ASearch&fulltext=1">Wikipedia</a> <br />
|
||||
<a href="https://twitter.com/search/?f=live&q={{query}}">Twitter</a> <br />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -16,25 +16,50 @@
|
|||
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
{% if not subnode %}
|
||||
|
||||
{% if not subnode and not node %}
|
||||
<div class="message">
|
||||
No subnode found matching '{{subnode}}'.
|
||||
No subnodes found matching '{{subnode}}'.
|
||||
<br /><br />
|
||||
Try listing <a href="/subnodes">subnodes</a> or perhaps <a href="/search">search</a>.
|
||||
Try listing <a href="/nodes">nodes</a> or perhaps <a href="/search">search</a>.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if subnode %}
|
||||
<!-- the new subnode route uses this, actually receiving a node whose subnodes are partial -->
|
||||
{% if node %}
|
||||
{% for subnode in node.subnodes %}
|
||||
<div class="subnode">
|
||||
<span class="subnode-header"><strong>Subnode</strong> <a href="{{subnode.url}}">{{subnode.uri}}</a> by <a href="/@{{subnode.user}}">@{{subnode.user}}</a> in node <a href="/node/{{subnode.wikilink}}">[[{{subnode.wikilink}}]]</a></span>
|
||||
{{ subnode.content|markdown|linkify|safe }}
|
||||
<div class="subnode-header">
|
||||
<span><strong>Subnode</strong> <a href="/@{{subnode.user}}/{{node.uri}}">[[{{node.uri}}@{{subnode.user}}]]</a></span>
|
||||
<span class="subnode-links">(<a href="/@{{subnode.user}}">user</a>) (<a href="/node/{{subnode.wikilink}}">up to node</a>) (<a href="{{subnode.url}}">source</a>)</span>
|
||||
</div>
|
||||
{{ subnode.render()|linkify|safe }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<div class="backlinks">
|
||||
<span class="backlinks-header">To see links, go up to node <a href="/node/{{node.uri}}">[[{{node.uri}}]]</a>.</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- end new subnode route -->
|
||||
|
||||
<!-- old_subnode uses this -->
|
||||
{% if subnode %}
|
||||
<div class="subnode">
|
||||
<span class="subnode-header"><strong>Subnode</strong> <a href="/{{subnode.uri}}">[[{{subnode.uri}}]]</a> by <a href="/@{{subnode.user}}">@{{subnode.user}}</a> in node <a href="/node/{{subnode.wikilink}}">[[{{subnode.wikilink}}]]</a></span>
|
||||
{{ subnode.render()|linkify|safe }}
|
||||
</div>
|
||||
<div class="links">
|
||||
<div class="backlinks">
|
||||
<span class="backlinks-header">To see links, go up to node <a href="/node/{{subnode.wikilink}}">[[{{subnode.wikilink}}]]</a>.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endif %}
|
||||
<!-- end: old_subnode uses this -->
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -34,7 +34,7 @@ Go back to <a href="/nodes">/nodes</a>?
|
|||
{% endif %}
|
||||
|
||||
{% for subnode in subnodes %}
|
||||
<a href="{{subnode.url}}">{{subnode.wikilink}}</a><br />
|
||||
<a href="/@{{subnode.user}}/{{subnode.wikilink}}">{{subnode.wikilink}}</a><br />
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
|
18
app/util.py
18
app/util.py
|
@ -21,15 +21,20 @@ def rank(l, user):
|
|||
# hack hack
|
||||
return sorted(l, key=lambda x: x.user)
|
||||
|
||||
def uprank(l, user):
|
||||
def uprank(l, users):
|
||||
# hack hack
|
||||
def score(n):
|
||||
if n.user == user:
|
||||
return -1
|
||||
if n.user in users:
|
||||
# the earlier in the list a user comes, the more highly ranked it is.
|
||||
return users.index(n.user) - len(users) - 1
|
||||
return 0
|
||||
|
||||
return sorted(l, key=score)
|
||||
|
||||
def filter(l, projection):
|
||||
# hack hack
|
||||
return [n for n in l if n.user == projection]
|
||||
|
||||
def canonical_wikilink(wikilink):
|
||||
|
||||
if is_journal(wikilink):
|
||||
|
@ -42,10 +47,13 @@ def canonical_wikilink(wikilink):
|
|||
# hack hack
|
||||
wikilink = (
|
||||
wikilink.lower()
|
||||
# chars that convert to -, slug-like.
|
||||
.replace(' ', '-')
|
||||
.replace('\'', '')
|
||||
.replace(',', '')
|
||||
.replace('/', '-')
|
||||
.replace('\'', '')
|
||||
# chars that are elided.
|
||||
.replace('%', '')
|
||||
.replace(',', '')
|
||||
)
|
||||
return wikilink
|
||||
|
||||
|
|
Loading…
Reference in a new issue