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('/index')
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
node='index'
|
return redirect(url_for('.node', 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 [],
|
|
||||||
)
|
|
||||||
|
|
||||||
@bp.route('/help')
|
@bp.route('/help')
|
||||||
def help():
|
def help():
|
||||||
|
@ -117,7 +106,8 @@ def jump():
|
||||||
def node(node):
|
def node(node):
|
||||||
|
|
||||||
n = G.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)
|
search_subnodes = db.search_subnodes(node)
|
||||||
|
|
||||||
|
@ -133,8 +123,30 @@ def node(node):
|
||||||
query=n.wikilink.replace('-', '%20')
|
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>')
|
@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))
|
return render_template('subnode_rendered.html', subnode=db.subnode_by_uri(subnode), backlinks=db.subnodes_by_outlink(subnode))
|
||||||
|
|
||||||
@bp.route('/u/<user>')
|
@bp.route('/u/<user>')
|
||||||
|
|
13
app/db.py
13
app/db.py
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
import cachetools.func
|
import cachetools.func
|
||||||
import glob
|
import glob
|
||||||
import marko
|
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
from . import config
|
from . import config
|
||||||
|
from . import render
|
||||||
from . import util
|
from . import util
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from fuzzywuzzy import fuzz
|
from fuzzywuzzy import fuzz
|
||||||
|
@ -212,6 +212,13 @@ class Subnode:
|
||||||
# hack hack
|
# hack hack
|
||||||
return 100-fuzz.ratio(self.wikilink, other.wikilink)
|
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):
|
def go(self):
|
||||||
"""
|
"""
|
||||||
returns a set of go links contained in this subnode
|
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)]
|
subnodes = [subnode for subnode in G.subnodes() if re.search(query, subnode.content, re.IGNORECASE)]
|
||||||
return subnodes
|
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):
|
def subnodes_by_user(user):
|
||||||
subnodes = [subnode for subnode in G.subnodes() if subnode.user == user]
|
subnodes = [subnode for subnode in G.subnodes() if subnode.user == user]
|
||||||
return subnodes
|
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 {
|
.subnode-header {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subnode-id {
|
||||||
|
text-align: left;
|
||||||
|
align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subnode-links {
|
||||||
|
text-align: left;
|
||||||
|
align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.links {
|
.links {
|
||||||
|
@ -137,6 +150,11 @@ nav { font-family: sans-serif}
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wikilink-marker {
|
||||||
|
/* deemphasize */
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
|
||||||
/* hypothes.is
|
/* hypothes.is
|
||||||
This totally doesn't work, at all, and I have no idea why :)
|
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">
|
<div class="node">
|
||||||
<span class="node-header"><strong>Node</strong> <a href="/node/{{node.uri}}">[[{{node.uri}}]]</a></span>
|
<span class="node-header"><strong>Node</strong> <a href="/node/{{node.uri}}">[[{{node.uri}}]]</a></span>
|
||||||
|
|
||||||
|
|
||||||
{% for subnode in node.subnodes %}
|
{% for subnode in node.subnodes %}
|
||||||
<div class="subnode">
|
<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>
|
<div class="subnode-header">
|
||||||
{{ subnode.content|markdown|linkify|safe }}
|
<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>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,7 +51,7 @@ Try listing all <a href="/nodes">nodes</a> or perhaps <a href="/search">search</
|
||||||
{% for subnode in node.subnodes %}
|
{% for subnode in node.subnodes %}
|
||||||
<div class="subnode">
|
<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>
|
<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>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,6 +13,15 @@
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
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 />
|
<br />
|
||||||
<div class="search">
|
<div class="search">
|
||||||
|
@ -27,13 +36,4 @@ No search results.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if not subnode %}
|
|
||||||
|
{% if not subnode and not node %}
|
||||||
<div class="message">
|
<div class="message">
|
||||||
No subnode found matching '{{subnode}}'.
|
No subnodes found matching '{{subnode}}'.
|
||||||
<br /><br />
|
<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>
|
</div>
|
||||||
{% endif %}
|
{% 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">
|
<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>
|
<div class="subnode-header">
|
||||||
{{ subnode.content|markdown|linkify|safe }}
|
<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>
|
||||||
|
|
||||||
|
<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="links">
|
||||||
<div class="backlinks">
|
<div class="backlinks">
|
||||||
<span class="backlinks-header">To see links, go up to node <a href="/node/{{subnode.wikilink}}">[[{{subnode.wikilink}}]]</a>.</span>
|
<span class="backlinks-header">To see links, go up to node <a href="/node/{{subnode.wikilink}}">[[{{subnode.wikilink}}]]</a>.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<!-- end: old_subnode uses this -->
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -34,7 +34,7 @@ Go back to <a href="/nodes">/nodes</a>?
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for subnode in subnodes %}
|
{% for subnode in subnodes %}
|
||||||
<a href="{{subnode.url}}">{{subnode.wikilink}}</a><br />
|
<a href="/@{{subnode.user}}/{{subnode.wikilink}}">{{subnode.wikilink}}</a><br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
18
app/util.py
18
app/util.py
|
@ -21,15 +21,20 @@ def rank(l, user):
|
||||||
# hack hack
|
# hack hack
|
||||||
return sorted(l, key=lambda x: x.user)
|
return sorted(l, key=lambda x: x.user)
|
||||||
|
|
||||||
def uprank(l, user):
|
def uprank(l, users):
|
||||||
# hack hack
|
# hack hack
|
||||||
def score(n):
|
def score(n):
|
||||||
if n.user == user:
|
if n.user in users:
|
||||||
return -1
|
# 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 0
|
||||||
|
|
||||||
return sorted(l, key=score)
|
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):
|
def canonical_wikilink(wikilink):
|
||||||
|
|
||||||
if is_journal(wikilink):
|
if is_journal(wikilink):
|
||||||
|
@ -42,10 +47,13 @@ def canonical_wikilink(wikilink):
|
||||||
# hack hack
|
# hack hack
|
||||||
wikilink = (
|
wikilink = (
|
||||||
wikilink.lower()
|
wikilink.lower()
|
||||||
|
# chars that convert to -, slug-like.
|
||||||
.replace(' ', '-')
|
.replace(' ', '-')
|
||||||
.replace('\'', '')
|
|
||||||
.replace(',', '')
|
|
||||||
.replace('/', '-')
|
.replace('/', '-')
|
||||||
|
.replace('\'', '')
|
||||||
|
# chars that are elided.
|
||||||
|
.replace('%', '')
|
||||||
|
.replace(',', '')
|
||||||
)
|
)
|
||||||
return wikilink
|
return wikilink
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue