fix plugins in example root
s-ol
1 year, 5 months ago
0 | local div, span, sup, a, i, b | |
1 | do | |
2 | local _obj_0 = require('mmm.dom') | |
3 | div, span, sup, a, i, b = _obj_0.div, _obj_0.span, _obj_0.sup, _obj_0.a, _obj_0.i, _obj_0.b | |
4 | end | |
5 | local parse_bibtex | |
6 | parse_bibtex = function(src) | |
7 | local type, key, kv = src:match('@(%w+){(.-),(.*)}') | |
8 | do | |
9 | local info = { | |
10 | _type = type, | |
11 | _key = key | |
12 | } | |
13 | for key, val in kv:gmatch('([a-z]-)%s*=%s*(%b{})') do | |
14 | val:sub(2, -2) | |
15 | info[key] = val:gsub('[{}]', '') | |
16 | end | |
17 | for key, val in kv:gmatch('([a-z]-)%s*=%s*(%d+)') do | |
18 | info[key] = val | |
19 | end | |
20 | return info | |
21 | end | |
22 | end | |
23 | local title | |
24 | title = function(self) | |
25 | assert(self.title, "cite doesn't have title") | |
26 | local inner = i(self.title) | |
27 | if self.url then | |
28 | return a(inner, { | |
29 | href = self.url, | |
30 | style = { | |
31 | display = 'inline' | |
32 | } | |
33 | }) | |
34 | else | |
35 | return b(inner) | |
36 | end | |
37 | end | |
38 | local format_full | |
39 | format_full = function(self) | |
40 | local tt = title(self) | |
41 | local dot, com | |
42 | if self.title:match('[.?!]$') then | |
43 | dot, com = '', '' | |
44 | else | |
45 | dot, com = '.', ',' | |
46 | end | |
47 | self.author = self.author or 'N. N.' | |
48 | local _exp_0 = self._type | |
49 | if 'book' == _exp_0 or 'article' == _exp_0 then | |
50 | return span((function() | |
51 | do | |
52 | local _with_0 = setmetatable({ }, { | |
53 | __index = table | |
54 | }) | |
55 | _with_0:insert(tostring(self.author) .. " (" .. tostring(self.year) .. "), ") | |
56 | _with_0:insert(tt) | |
57 | if self.journal then | |
58 | _with_0:insert(tostring(dot) .. " ") | |
59 | _with_0:insert(i(self.journal)) | |
60 | if self.volume then | |
61 | _with_0:insert(", volume " .. tostring(self.volume)) | |
62 | end | |
63 | else | |
64 | if self.series then | |
65 | _with_0:insert(tostring(dot) .. " ") | |
66 | _with_0:insert(i(self.series)) | |
67 | if self.number then | |
68 | _with_0:insert(", No. " .. tostring(self.number)) | |
69 | end | |
70 | end | |
71 | end | |
72 | if self.pages then | |
73 | _with_0:insert(", pages " .. tostring(self.pages)) | |
74 | end | |
75 | if self.publisher then | |
76 | _with_0:insert(tostring(dot) .. " " .. tostring(self.publisher)) | |
77 | end | |
78 | if self.doi then | |
79 | _with_0:insert(tostring(dot) .. " ") | |
80 | _with_0:insert(a("doi:" .. tostring(self.doi), { | |
81 | href = "https://doi.org/" .. tostring(self.doi) | |
82 | })) | |
83 | end | |
84 | return _with_0 | |
85 | end | |
86 | end)()) | |
87 | elseif 'web' == _exp_0 or 'online' == _exp_0 then | |
88 | return span((function() | |
89 | do | |
90 | local _with_0 = setmetatable({ }, { | |
91 | __index = table | |
92 | }) | |
93 | _with_0:insert(tostring(self.author)) | |
94 | if self.year then | |
95 | _with_0:insert(" (" .. tostring(self.year) .. ")") | |
96 | end | |
97 | _with_0:insert(", ") | |
98 | _with_0:insert(tt) | |
99 | _with_0:insert(tostring(com) .. " " .. tostring(self.url)) | |
100 | if self.visited then | |
101 | _with_0:insert(" from " .. tostring(self.visited)) | |
102 | end | |
103 | return _with_0 | |
104 | end | |
105 | end)()) | |
106 | else | |
107 | span((function() | |
108 | do | |
109 | local _with_0 = setmetatable({ }, { | |
110 | __index = table | |
111 | }) | |
112 | _with_0:insert(tostring(self.author) .. " (" .. tostring(self.year) .. "), ") | |
113 | _with_0:insert(tt) | |
114 | if self.publisher then | |
115 | _with_0:insert(tostring(dot) .. " " .. tostring(self.publisher)) | |
116 | end | |
117 | return _with_0 | |
118 | end | |
119 | end)()) | |
120 | return span(tbl) | |
121 | end | |
122 | end | |
123 | return { | |
124 | { | |
125 | inp = 'cite/doi', | |
126 | out = 'URL -> text/bibtex', | |
127 | cost = 0.1, | |
128 | transform = function(self, doi) | |
129 | doi = doi:match('(10%.%d%d%d%d%d?%d?%d?%d?%d?/[%d%w%.%-_:;%(%)]+)') | |
130 | return "http://api.crossref.org/works/" .. tostring(doi) .. "/transform/application/x-bibtex" | |
131 | end | |
132 | }, | |
133 | { | |
134 | inp = 'text/bibtex', | |
135 | out = 'mmm/dom', | |
136 | cost = 1, | |
137 | transform = function(self, bib) | |
138 | return format_full(parse_bibtex(bib)) | |
139 | end | |
140 | } | |
141 | } |
0 | local pre, div, button | |
1 | do | |
2 | local _obj_0 = require('mmm.dom') | |
3 | pre, div, button = _obj_0.pre, _obj_0.div, _obj_0.button | |
4 | end | |
5 | local languages | |
6 | languages = require('mmm.highlighting').languages | |
7 | local Editor | |
8 | do | |
9 | local _class_0 | |
10 | local o | |
11 | local _base_0 = { | |
12 | EDITOR = true, | |
13 | change = function(self) | |
14 | self.timeout = nil | |
15 | local doc = self.cm:getDoc() | |
16 | if self.lastPreview and doc:isClean(self.lastPreview) then | |
17 | return | |
18 | end | |
19 | self.lastPreview = doc:changeGeneration() | |
20 | local value = doc:getValue() | |
21 | self.fileder.facets[self.key] = value | |
22 | return BROWSER:refresh() | |
23 | end, | |
24 | save = function(self, e) | |
25 | e:preventDefault() | |
26 | local doc = self.cm:getDoc() | |
27 | self.fileder:set(self.key, doc:getValue()) | |
28 | self.lastSave = doc:changeGeneration(true) | |
29 | end | |
30 | } | |
31 | _base_0.__index = _base_0 | |
32 | _class_0 = setmetatable({ | |
33 | __init = function(self, value, mode, fileder, key) | |
34 | self.fileder, self.key = fileder, key | |
35 | self.node = div({ | |
36 | class = 'editor' | |
37 | }) | |
38 | do | |
39 | local _with_0 = button('save') | |
40 | _with_0.disabled = true | |
41 | _with_0.onclick = function(_, e) | |
42 | return self:save(e) | |
43 | end | |
44 | self.saveBtn = _with_0 | |
45 | end | |
46 | self.cm = window:CodeMirror(self.node, o({ | |
47 | value = value, | |
48 | mode = mode, | |
49 | lineNumber = true, | |
50 | lineWrapping = true, | |
51 | autoRefresh = true, | |
52 | theme = 'hybrid' | |
53 | })) | |
54 | self.lastSave = self.cm:getDoc():changeGeneration(true) | |
55 | return self.cm:on('changes', function(_, mirr) | |
56 | local doc = self.cm:getDoc() | |
57 | self.saveBtn.disabled = doc:isClean(self.lastSave) | |
58 | if self.timeout then | |
59 | window:clearTimeout(self.timeout) | |
60 | end | |
61 | self.timeout = window:setTimeout((function() | |
62 | return self:change() | |
63 | end), 300) | |
64 | end) | |
65 | end, | |
66 | __base = _base_0, | |
67 | __name = "Editor" | |
68 | }, { | |
69 | __index = _base_0, | |
70 | __call = function(cls, ...) | |
71 | local _self_0 = setmetatable({}, _base_0) | |
72 | cls.__init(_self_0, ...) | |
73 | return _self_0 | |
74 | end | |
75 | }) | |
76 | _base_0.__class = _class_0 | |
77 | local self = _class_0 | |
78 | if MODE == 'CLIENT' then | |
79 | local mkobj = window:eval("(function () { return {}; })") | |
80 | o = function(tbl) | |
81 | do | |
82 | local obj = mkobj() | |
83 | for k, v in pairs(tbl) do | |
84 | obj[k] = v | |
85 | end | |
86 | return obj | |
87 | end | |
88 | end | |
89 | end | |
90 | Editor = _class_0 | |
91 | end | |
92 | local _ = [[ editors: if MODE == 'CLIENT' then { | |
93 | { | |
94 | inp: 'text/([^ ]*).*' | |
95 | out: 'mmm/dom' | |
96 | cost: 0 | |
97 | transform: (value, fileder, key) => | |
98 | mode = @from\match @convert.inp | |
99 | Editor value, mode, fileder, key | |
100 | } | |
101 | { | |
102 | inp: 'URL.*' | |
103 | out: 'mmm/dom' | |
104 | cost: 0 | |
105 | transform: (value, fileder, key) => | |
106 | Editor value, nil, fileder, key | |
107 | } | |
108 | } | |
109 | ]] | |
110 | return { | |
111 | { | |
112 | inp = 'text/([^ ]*).*', | |
113 | out = 'mmm/dom', | |
114 | cost = 5, | |
115 | transform = function(self, val) | |
116 | local lang = self.from:match(self.convert.inp) | |
117 | return pre(languages[lang](val)) | |
118 | end | |
119 | } | |
120 | } |
0 | local tourl | |
1 | tourl = (require('mmm.mmmfs.util'))({ }).tourl | |
2 | return function(self) | |
3 | return "\n <link rel=\"stylesheet\" type=\"text/css\" href=\"" .. tostring(self:gett('style: URL -> text/css')) .. "\" />" .. [[<!-- | |
4 | <link rel="stylesheet" type="text/css" href="//unpkg.com/codemirror@5.49.2/lib/codemirror.css" /> | |
5 | <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/lib/codemirror.js"></script> | |
6 | <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/mode/lua/lua.js"></script> | |
7 | <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/mode/markdown/markdown.js"></script> | |
8 | <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/addon/display/autorefresh.js"></script> | |
9 | --> | |
10 | ]] | |
11 | end |
0 | local dom = require('mmm.dom') | |
1 | return { | |
2 | { | |
3 | inp = 'URL -> model/gltf-binary', | |
4 | out = 'mmm/dom', | |
5 | cost = 1, | |
6 | transform = function(self, href) | |
7 | return dom['model-viewer']({ | |
8 | src = href, | |
9 | ['auto-rotate'] = true, | |
10 | ['camera-controls'] = true, | |
11 | ['camera-orbit'] = "548.2deg 117deg 282.4m" | |
12 | }) | |
13 | end | |
14 | } | |
15 | } |
0 | local markdown | |
1 | if MODE == 'SERVER' then | |
2 | local success, discount = pcall(require, 'discount') | |
3 | assert(success, "couldn't require 'discount'") | |
4 | markdown = function(md) | |
5 | local res = assert(discount.compile(md, 'githubtags', 'fencedcode')) | |
6 | return res.body | |
7 | end | |
8 | else | |
9 | assert(window and window.marked, "marked.js not found") | |
10 | local o | |
11 | do | |
12 | local mkobj = window:eval("(function () { return {}; })") | |
13 | o = function(tbl) | |
14 | do | |
15 | local obj = mkobj() | |
16 | for k, v in pairs(tbl) do | |
17 | obj[k] = v | |
18 | end | |
19 | return obj | |
20 | end | |
21 | end | |
22 | end | |
23 | local trim | |
24 | trim = function(str) | |
25 | return str:match('^ *(..-) *$') | |
26 | end | |
27 | window.marked:setOptions(o({ | |
28 | gfm = true, | |
29 | smartypants = true, | |
30 | langPrefix = 'lang-', | |
31 | highlight = function(self, code, lang) | |
32 | code = trim(code) | |
33 | local result | |
34 | if lang and #lang > 0 then | |
35 | result = window.hljs:highlight(lang, code, true) | |
36 | else | |
37 | result = window.hljs:highlightAuto(code) | |
38 | end | |
39 | return result.value | |
40 | end | |
41 | })) | |
42 | do | |
43 | local _base_0 = window | |
44 | local _fn_0 = _base_0.marked | |
45 | markdown = function(...) | |
46 | return _fn_0(_base_0, ...) | |
47 | end | |
48 | end | |
49 | end | |
50 | assert(markdown, "no markdown implementation found") | |
51 | return { | |
52 | { | |
53 | inp = 'text/markdown', | |
54 | out = 'text/html+frag', | |
55 | cost = 1, | |
56 | transform = function(self, md) | |
57 | return "<div class=\"markdown\">" .. tostring(markdown(md)) .. "</div>" | |
58 | end | |
59 | }, | |
60 | { | |
61 | inp = 'text/markdown%+sidenotes', | |
62 | out = 'text/html+frag', | |
63 | cost = 1, | |
64 | transform = function(self, md) | |
65 | return "<div class=\"markdown sidenote-container\">" .. tostring(markdown(md)) .. "</div>" | |
66 | end | |
67 | }, | |
68 | { | |
69 | inp = 'text/markdown%+wide', | |
70 | out = 'text/html+frag', | |
71 | cost = 1, | |
72 | transform = function(self, md) | |
73 | return "<div class=\"markdown wide\">" .. tostring(markdown(md)) .. "</div>" | |
74 | end | |
75 | }, | |
76 | { | |
77 | inp = 'text/markdown%+span', | |
78 | out = 'text/html+frag', | |
79 | cost = 1, | |
80 | transform = function(self, source) | |
81 | local html = markdown(source) | |
82 | html = html:gsub('^%s*<p>%s*', '<span>') | |
83 | html = html:gsub('%s*</p>%s*$', '</span>') | |
84 | return html | |
85 | end | |
86 | } | |
87 | } |
0 | if not (window and window.mermaid) then | |
1 | return | |
2 | end | |
3 | window.mermaid:initialize({ | |
4 | startOnLoad = false, | |
5 | fontFamily = 'monospace' | |
6 | }) | |
7 | local id_counter = 1 | |
8 | return { | |
9 | { | |
10 | inp = 'text/mermaid-graph', | |
11 | out = 'mmm/dom', | |
12 | cost = 1, | |
13 | transform = function(self, source, fileder, key) | |
14 | id_counter = id_counter + 1 | |
15 | local id = "mermaid-" .. tostring(id_counter) | |
16 | do | |
17 | local container = document:createElement('div') | |
18 | local cb | |
19 | cb = function(self, svg) | |
20 | container.innerHTML = svg | |
21 | container.firstElementChild.style.width = '100%' | |
22 | container.firstElementChild.style.height = 'auto' | |
23 | end | |
24 | window:setImmediate(function(_) | |
25 | return window.mermaid:render(id, source, cb, container) | |
26 | end) | |
27 | return container | |
28 | end | |
29 | end | |
30 | } | |
31 | } |
0 | if MODE == 'CLIENT' then | |
1 | return { } | |
2 | end | |
3 | local _, moon = assert(pcall(require, 'moonscript.base')) | |
4 | local _load = moon.load or moon.loadstring | |
5 | return { | |
6 | { | |
7 | inp = 'text/moonscript -> (.+)', | |
8 | out = '%1', | |
9 | cost = 1, | |
10 | transform = function(self, val, fileder, key) | |
11 | local func = _load(val, tostring(fileder) .. "#" .. tostring(key)) | |
12 | return func() | |
13 | end | |
14 | }, | |
15 | { | |
16 | inp = 'text/moonscript -> (.+)', | |
17 | out = 'text/lua -> %1', | |
18 | cost = 2, | |
19 | transform = function(self, val) | |
20 | return moon.to_lua(val) | |
21 | end | |
22 | } | |
23 | } |
0 | if MODE == 'CLIENT' | |
1 | return {} | |
2 | ||
3 | _, moon = assert pcall require, 'moonscript.base' | |
4 | _load = moon.load or moon.loadstring | |
5 | ||
6 | { | |
7 | { | |
8 | inp: 'text/moonscript -> (.+)', | |
9 | out: '%1', | |
10 | cost: 1 | |
11 | transform: (val, fileder, key) => | |
12 | func = _load val, "#{fileder}##{key}" | |
13 | func! | |
14 | }, | |
15 | { | |
16 | inp: 'text/moonscript -> (.+)', | |
17 | out: 'text/lua -> %1', | |
18 | cost: 2 | |
19 | transform: (val) => moon.to_lua val | |
20 | }, | |
21 | } |
0 | if MODE == 'CLIENT' then | |
1 | return { } | |
2 | end | |
3 | local posix = require('posix') | |
4 | return { | |
5 | { | |
6 | inp = 'text/x-scss', | |
7 | out = 'text/css', | |
8 | cost = 1, | |
9 | transform = function(self, content) | |
10 | local r0, w0 = posix.pipe() | |
11 | local r1, w1 = posix.pipe() | |
12 | local r2, w2 = posix.pipe() | |
13 | local pid = assert(posix.fork()) | |
14 | if pid == 0 then | |
15 | posix.close(w0) | |
16 | posix.close(r1) | |
17 | posix.close(r2) | |
18 | posix.dup2(r0, posix.fileno(io.stdin)) | |
19 | posix.dup2(w1, posix.fileno(io.stdout)) | |
20 | posix.dup2(w2, posix.fileno(io.stderr)) | |
21 | posix.close(r0) | |
22 | posix.close(w1) | |
23 | posix.close(w2) | |
24 | local err = assert(posix.execp('sassc', '-s')) | |
25 | posix._exit(err) | |
26 | return | |
27 | else | |
28 | posix.close(r0) | |
29 | posix.close(w1) | |
30 | posix.close(w2) | |
31 | posix.write(w0, content) | |
32 | posix.close(w0) | |
33 | local _, status | |
34 | _, _, status = posix.wait(pid) | |
35 | local out | |
36 | if status == 0 then | |
37 | out = r1 | |
38 | else | |
39 | out = r2 | |
40 | end | |
41 | out = assert(posix.fdopen(out, 'r')) | |
42 | out = out:read('a') | |
43 | posix.close(r1) | |
44 | posix.close(r2) | |
45 | if status == 0 then | |
46 | return out | |
47 | else | |
48 | return error(out) | |
49 | end | |
50 | end | |
51 | end | |
52 | } | |
53 | } |
0 | local div, blockquote, a | |
1 | do | |
2 | local _obj_0 = require('mmm.dom') | |
3 | div, blockquote, a = _obj_0.div, _obj_0.blockquote, _obj_0.a | |
4 | end | |
5 | local iframe | |
6 | iframe = require('mmm.dom').iframe | |
7 | return { | |
8 | { | |
9 | inp = 'URL -> twitter/tweet', | |
10 | out = 'mmm/dom', | |
11 | cost = -4, | |
12 | transform = function(self, href) | |
13 | local user, id = assert((href:match('twitter.com/([^/]-)/status/(%d*)')), "couldn't parse twitter/tweet URL: '" .. tostring(href) .. "'") | |
14 | return iframe({ | |
15 | width = 550, | |
16 | height = 560, | |
17 | border = 0, | |
18 | frameBorder = 0, | |
19 | allowfullscreen = true, | |
20 | src = "//twitframe.com/show?url=https%3A%2F%2Ftwitter.com%2F" .. tostring(user) .. "%2F" .. tostring(id) | |
21 | }) | |
22 | end | |
23 | } | |
24 | } |
0 | local iframe | |
1 | iframe = require('mmm.dom').iframe | |
2 | return { | |
3 | { | |
4 | inp = 'URL -> youtube/video', | |
5 | out = 'mmm/dom', | |
6 | cost = -4, | |
7 | transform = function(self, link) | |
8 | local id = link:match('youtu%.be/([^/]+)') | |
9 | id = id or link:match('youtube.com/watch.*[?&]v=([^&]+)') | |
10 | id = id or link:match('youtube.com/[ev]/([^/]+)') | |
11 | id = id or link:match('youtube.com/embed/([^/]+)') | |
12 | assert(id, "couldn't parse youtube URL: '" .. tostring(link) .. "'") | |
13 | return iframe({ | |
14 | width = 560, | |
15 | height = 315, | |
16 | border = 0, | |
17 | frameborder = 0, | |
18 | allowfullscreen = true, | |
19 | src = "//www.youtube.com/embed/" .. tostring(id) | |
20 | }) | |
21 | end | |
22 | } | |
23 | } |