-
Notifications
You must be signed in to change notification settings - Fork 97
/
untwee
executable file
·170 lines (134 loc) · 5.08 KB
/
untwee
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python2
from tiddlywiki import TiddlyWiki
from collections import defaultdict
from getopt import GetoptError, getopt
from glob import glob
import re, sys
verbose = False
def detectCompiler(head, wiki):
'''Do a best effort to determine which program compiled the HTML.
Returns a pair consisting of the tool name in lower case and the version string.
If the tool name or the version string cannot be determined, the corresponding
position in the pair will be None.
'''
tool, version = None, None
# Look for "VERSION" replacement.
# Twine/Twee uses "Made in", Tweego uses "Compiled with".
m = re.search(r'(?:Made in|Compiled with) ([^(\n]*)(\(.*?\))?', head)
if m:
madeParts = m.group(1).split()
if madeParts:
tool = madeParts[0].lower()
if tool == 'tweego':
version = m.group(2).lstrip('(').split(';')[0].rstrip()
elif len(madeParts) == 2:
version = madeParts[1]
if verbose:
print >>sys.stderr, '"VERSION" string:', tool, version
# Look at the modifier (author) of the tiddlers (passages).
if tool is None or verbose:
modifierCounts = defaultdict(int)
for tiddler in wiki.tiddlers.itervalues():
modifierCounts[tiddler.modifier] += 1
modifiers = sorted(modifierCounts.iteritems(), key = lambda (name, count): count, reverse = True)
if verbose:
print >>sys.stderr, 'Passage creators:', ', '.join(
'%s (%d passages)' % (name or 'unknown', count)
for name, count in modifiers
)
if tool is None and modifiers:
tool = modifiers[0][0]
return tool, version
def makeOrder(wiki):
'''Computes a linear passage order for the given story.
'''
tiddlers = wiki.tiddlers
storyPassages = set(
name
for name, tiddler in tiddlers.iteritems()
if tiddler.isStoryPassage()
)
infoPassages = set(tiddlers) - storyPassages
ordered = []
# Begin with the special passages, in a fixed order.
for name in ('StoryBanner', 'StoryTitle', 'StorySubtitle', 'StoryAuthor', 'StoryCaption',
'StoryMenu', 'MenuStory', 'MenuOptions', 'MenuShare',
'StorySettings', 'StoryIncludes', 'StoryInit', 'PassageReady', 'PassageDone'):
if name in infoPassages:
ordered.append(name)
infoPassages.remove(name)
# Add passages with special tags, in a fixed tag order.
for tag in ('script', 'widget', 'stylesheet', 'Twine.image', 'annotation'):
tagged = set(passage for passage in infoPassages if tag in tiddlers[passage].tags)
ordered.extend(sorted(tagged))
infoPassages -= tagged
# Append any remaining info passages.
ordered.extend(sorted(infoPassages))
# Append all story passages.
ordered.extend(sorted(storyPassages))
return ordered
def usage():
print >> sys.stderr, 'usage: untwee [-r|--reorder auto|on|off] source'
def main(argv):
if not argv:
usage()
sys.exit(2)
# read command line arguments
try:
opts, args = getopt(argv, 'r:', ['reorder='])
except GetoptError:
usage()
sys.exit(2)
reorder = None
for opt, arg in opts:
if opt in ('-r', '--reorder'):
try:
reorder = {'auto': None, 'on': True, 'off': False}[arg]
except KeyError:
print >> sys.stderr, 'Invalid argument for %s: %s' % (opt, arg)
usage()
sys.exit(2)
sources = [
filename
for arg in args
for filename in glob(arg)
]
if len(sources) != 1:
print >> sys.stderr, 'untwee: %s HTML files specified' % ('multiple' if sources else 'no')
sys.exit(2)
source, = sources
# populate a TiddlyWiki
wiki = TiddlyWiki()
html = wiki.read(source)
order = wiki.addHtml(html)
# figure out which tool generated the HTML
m = re.search(r'<head>(.*?)</head>', html, re.I | re.S)
head = m.group(1) if m else ''
tool, version = detectCompiler(head, wiki)
print >>sys.stderr, 'Compiled by:', 'unknown tool' if tool is None else \
'%s %s' % (tool.capitalize(), version or '(unknown version)')
# determine passage order
if reorder is None: # autodetect
if tool == 'tweego':
# Tweego has always preserved order.
reorder = False
elif tool == 'twee':
# Order preservation was added during the Twine 1.4.2 development cycle.
reorder = version in (None, '1.4', '1.4.1')
else:
# Twine doesn't have an order to preserve.
# Braid doesn't preserve order.
reorder = True
if reorder:
print >>sys.stderr, 'Reordering passages.'
order = makeOrder(wiki)
else:
print >>sys.stderr, 'Preserving passage order.'
# generate output
output = wiki.toTwee(order)
if sys.stdout.isatty():
print output
else:
print output.encode('utf_8_sig')
if __name__ == '__main__':
main(sys.argv[1:])