Attachment 'Asciinema.py'
Download 1 # -*- coding: utf-8 -*-
2 """
3 MoinMoin - Asciinema
4
5 This macro allows to attach asciinema cast-files to a page and
6 play them. Maybe you like it, too.
7
8 Based on and inspired by:
9 https://github.com/asciinema/asciinema-player
10
11 Thanks for this cool set of tools to the asciinema-project!
12 Thanks for MoinMoin!
13
14 The github page also documents all the asciinema-player options.
15 (I just snake_cased the options for the plugin).
16
17 Installation:
18 1. Drop the latest release (.js+.css) of the following github-repo
19 into your static files (Probably into:
20 "/usr/share/moin/htdocs/asciinema")
21 2. Drop the macro in your site-specific "data/plugin/macro" directory.
22 3. Restart server.
23 4. Attach .cast file to site.
24 5. Use macro.
25
26
27 Usage:
28 <<Asciinema(attached_file.cast, pagename, theme, cols, rows
29 autoplay, preload, loop, start_at,
30 speed, poster, font_size,
31 title, author, author_url, author_img_url)>>
32
33 Some hints:
34 cols=([80]|Num)
35 rows=([24]|Num)
36
37 font-size=([small]|medium|big|Num(px,em,…)
38
39 poster=(npt:mm:ss|"data:text/plain,Poster text")
40
41 theme=([asciinema]|tango|solarized-dark|solarized-light|monokai)
42
43 @copyright: 2019 Tobias Stein
44 @license: GNU GPLv2 or later
45
46 I'm not a frontend-, web- or python-programmer,
47 i just wanted to have sth. like this.
48 If you like - your free to improve code quality.
49
50 No warranty for nothing, usage on your on own responsibility.
51
52 Changelog:
53 * 1.0:
54 * Working implementation
55 * Probably vulnerable to javescript injection
56 "author_url" and "author_img_url"
57 """
58
59 import re
60 from MoinMoin import wikiutil
61 from MoinMoin.action.AttachFile import getAttachUrl, getFilename, exists
62 from MoinMoin.Page import Page
63
64 generates_headings = False
65
66 def macro_Asciinema(
67 macro, filename=None, pagename=None,
68 theme=None, cols=None, rows=24,
69 autoplay=None, preload=None, loop=None, start_at=None,
70 speed="1.0", poster="npt:1", font_size="small",
71 title="Asciinema", author=None, author_url=None, author_img_url=None):
72
73 if not pagename:
74 pagename = macro.formatter.page.page_name
75
76 request = macro.request
77 formatter = macro.formatter
78
79 if not exists(request, pagename, filename):
80 return formatter.text(
81 'Attachment "%s" does not exist on page "%s"'
82 % (filename, pagename))
83 else:
84
85 src=getAttachUrl(pagename, filename, request)
86 player_opts = []
87 if theme is not None:
88 pattern = re.compile("^(asciinema|tango|solarized-dark|solarized-light|monokai)$")
89 if pattern.match(theme):
90 player_opts.extend([formatter.rawHTML('theme="%s"' % theme)])
91 else:
92 return formatter.text(
93 'Theme is unknown.')
94 if rows is not None:
95 if isinstance(rows, int):
96 player_opts.extend([formatter.rawHTML('rows="%s"' % rows)])
97 else:
98 return formatter.text(
99 'Unable to determine rows.')
100 if cols is not None:
101 if isinstance(rows, int):
102 player_opts.extend([formatter.rawHTML('cols="%s"' % cols)])
103 else:
104 return formatter.text(
105 'Unable to determine cols.')
106 if autoplay is not None:
107 player_opts.extend([formatter.rawHTML('autoplay="%s"' % True)])
108 if preload is not None:
109 player_opts.extend([formatter.rawHTML('preload="%s"' % True)])
110 if loop is not None:
111 player_opts.extend([formatter.rawHTML('loop="%s"' % True)])
112 if start_at is not None:
113 player_opts.extend([formatter.rawHTML('start-at="%s"' % start_at)])
114 if speed is not None:
115 if isinstance(speed, (int, float)):
116 player_opts.extend([formatter.rawHTML('speed="%s"' % speed)])
117 elif isinstance(float(speed), (int, float)):
118 player_opts.extend([formatter.rawHTML('speed="%s"' % float(speed))])
119 else:
120 return formatter.text(
121 'Unable to determine speed.')
122 if poster is not None:
123 player_opts.extend([formatter.rawHTML('poster="%s"' % poster)])
124 if font_size is not None:
125 pattern = re.compile("^(small|medium|big|\d\+(px|r?em))$")
126 if pattern.match(font_size):
127 player_opts.extend([formatter.rawHTML('font-size="%s"' % font_size)])
128 else:
129 return formatter.text(
130 'Unable to determine font-size.')
131 if title is not None:
132 title_html = wikiutil.escape(title)
133 title_html = title_html.strip()
134 player_opts.extend([formatter.rawHTML('title="%s"' % title_html)])
135 if author is not None:
136 author_html = wikiutil.escape(author)
137 author_html = author_html.strip()
138 player_opts.extend([formatter.rawHTML('author="%s"' % author_html)])
139 if author_url is not None:
140 player_opts.extend([formatter.rawHTML('author-url="%s"' % author_url)])
141 if author_img_url is not None:
142 player_opts.extend([formatter.rawHTML('author-img-url="%s"' % author_img_url)])
143
144 ret = []
145 ret.extend([formatter.rawHTML(asciinemaRessource(request, "asciinema-player", "css"))])
146 ret.extend([formatter.rawHTML(asciinemaRessource(request, "asciinema-player", "js"))])
147 ret.extend([formatter.rawHTML(
148 '<asciinema-player %s src="%s"></asciinema-player>' %
149 (' '.join(player_opts), src))])
150
151 return ''.join(ret)
152
153
154 def asciinemaRessource(request, name, suffix):
155 """ Format external script html """
156 uri = '%s/asciinema/%s.%s' % (request.cfg.url_prefix_static, name, suffix)
157 if suffix == 'css':
158 tag = '<link rel="stylesheet" type="text/css" media="all" href="%s">' % uri
159 if suffix == 'js':
160 tag = '<script type="text/javascript" src="%s"></script>' % uri
161 return tag
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.