forked from tiddlyweb/twikifier
/
twikified.py
141 lines (117 loc) · 4.72 KB
/
twikified.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""
Serialization that uses twikifier to render.
It can render in two ways. If config['twikified.render'] is
True, the default, then rendering will be done serverside
with a nodje.js based socket server. Otherwise rendering will be
delegated to the client.
If config['twikified.serializer'] is True (the default is False)
use this code as a serialization, not just a renderer. Whether
rendering is done by the serialization server side or client side
is controlled by twikified.render.
The socket is at config['twikified.socket'], '/tmp/wst.sock' by
default. Running the server is up to the human installer at this point.
If client side rendering is used, then a bunch of javascript is
expected to be found in config['twikified.container'], defaulting
to '/bags/common/tiddlers/'. The human installer is expected to get the
right tiddlers in the right place (for now).
"""
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import Cookie
import socket
from tiddlywebplugins.atom.htmllinks import Serialization as HTMLSerialization
from tiddlyweb.model.bag import Bag
from tiddlyweb.model.recipe import Recipe
from tiddlyweb.web.util import (escape_attribute_value, html_encode,
encode_name, recipe_url, bag_url)
SERIALIZERS = {
'text/html': ['twikified', 'text/html; charset=UTF-8'],
'default': ['twikified', 'text/html; charset=UTF-8'],
}
def init(config):
if config.get('twikified.serializer', False):
config['serializers'].update(SERIALIZERS)
if config.get('twikified.render', True):
config['wikitext.default_renderer'] = 'twikified'
def render(tiddler, environ):
if tiddler.recipe:
collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers'
else:
collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers'
try:
user_cookie = environ['HTTP_COOKIE']
cookie = Cookie.SimpleCookie()
cookie.load(user_cookie)
tiddlyweb_cookie = 'tiddlyweb_user=' + cookie['tiddlyweb_user'].value
except KeyError:
tiddlyweb_cookie = ''
socket_path = environ['tiddlyweb.config'].get('twikified.socket',
'/tmp/wst.sock')
twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
twik_socket.connect('/tmp/wst.sock')
except IOError:
output = """
<div class='error'>There was a problem rendering this tiddler. The raw text is given instead below.</div>
<pre class='wikitext'>%s</pre>
"""%(escape_attribute_value(tiddler.text))
return output
twik_socket.sendall('%s\x00%s\x00%s\n' % (collection, tiddler.title, tiddlyweb_cookie))
output = ''
try:
while True:
data = twik_socket.recv(1024)
if data:
output += data
else:
break
finally:
twik_socket.close()
return output.decode('UTF-8')
class Serialization(HTMLSerialization):
def _render(self, tiddler):
return HTMLSerialization.tiddler_as(self, tiddler)
def tiddler_as(self, tiddler):
"""
Send out the bare minimum required to make webtwik know there is
a tiddler.
"""
# branch away if we are going to use the render system
if self.environ['tiddlyweb.config'].get('twikified.render', True):
return self._render(tiddler)
common_container = self.environ.get(
'tiddlyweb.config', {}).get(
'twikified.container', '/bags/common/tiddlers/')
scripts = """
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"
type="text/javascript"></script>
<script>
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView",
"false");
}
});
</script>
<script src="%(container)stwikifier" type="text/javascript"></script>
<script src="%(container)stwik" type="text/javascript"></script>
<script src="%(container)swebtwik" type="text/javascript"></script>
""" % {'container': common_container}
tiddler_div = '<div class="tiddler" title="%s" %s><pre>%s</pre></div>' % (
escape_attribute_value(tiddler.title),
self._tiddler_provenance(tiddler),
self._text(tiddler))
self.environ['tiddlyweb.title'] = tiddler.title
return tiddler_div + scripts
def _text(self, tiddler):
print tiddler.type
if not tiddler.type or tiddler.type == 'None':
return html_encode(tiddler.text)
return ''
def _tiddler_provenance(self, tiddler):
if tiddler.recipe:
return 'server.recipe="%s"' % escape_attribute_value(tiddler.recipe)
else:
return 'server.bag="%s"' % escape_attribute_value(tiddler.bag)