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
|
import text, code from require 'lib.dom'
import tohtml from require 'lib.component'
-- limit function to one argument
single = (func) -> (val) -> func val
-- list of converts
-- converts each have
-- * inp - input type. can capture subtypes using `(.+)`
-- * out - output type. can substitute subtypes from inp with %1, %2 etc.
-- * transform - function (val: inp, fileder) -> val: out
converts = {
{
inp: 'moon -> (.+)',
out: '%1',
transform: (val, fileder) -> val fileder
},
{
inp: 'text/plain',
out: 'mmm/dom',
transform: single text
},
{
inp: 'alpha',
out: 'mmm/dom',
transform: single code
},
{
inp: 'URL -> .*',
out: 'mmm/dom',
transform: single code
},
{
inp: 'mmm/component',
out: 'mmm/dom',
transform: single tohtml
},
{
inp: 'mmm/dom',
out: 'text/html',
transform: (node) -> if MODE == 'SERVER' then node else node.outerHTML
},
{
inp: 'text/html',
out: 'mmm/dom',
transform: if MODE == 'SERVER'
(...) -> ...
else
(html) ->
tmp = document\createElement 'div'
tmp.innerHTML = html
if tmp.childElementCount == 1
tmp.firstChild
else
tmp
}
}
do
local markdown
if MODE == 'SERVER'
success, discount = pcall require, 'discount'
markdown = discount if success
else
markdown = window and window.marked and window\marked
if markdown
table.insert converts, {
inp: 'text/markdown',
out: 'text/html',
transform: single markdown
}
count = (base, pattern='->') -> select 2, base\gsub pattern, ''
escape_inp = (inp) -> "^#{inp\gsub '([-/])', '%%%1'}$"
-- attempt to find a conversion path from 'have' to 'want'
-- * have - start type string or list of type strings
-- * want - stop type string
-- * limit - limit conversion amount
-- returns a list of conversion steps
get_conversions = (want, have, limit=3) ->
assert have, 'need starting type(s)'
if 'string' == type have
have = { have }
assert #have > 0, 'need starting type(s) (list was empty)'
iterations = limit + math.max table.unpack [count type for type in *have]
have = [{ :start, rest: start, conversions: {} } for start in *have]
for i=1, iterations
next_have, c = {}, 1
for { :start, :rest, :conversions } in *have
if want == rest
return conversions, start
else
for convert in *converts
inp = escape_inp convert.inp
matches = { rest\match inp }
continue unless #matches > 0
result = rest\gsub inp, convert.out
if result
next_have[c] = {
:start,
rest: result,
conversions: { convert, table.unpack conversions }
}
c += 1
have = next_have
return unless #have > 0
{
:converts
:get_conversions
}
|