summaryrefslogtreecommitdiff
path: root/script/provider/markdown.lua
blob: fe1b26b2998bcb0973be6178a3ba501ca88265b6 (plain)
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
---@class markdown
local mt = {}
mt.__index = mt
mt.__name = 'markdown'

mt._splitLine = false

function mt:__tostring()
    return self:string()
end

---@param language string
---@param text? string|markdown
function mt:add(language, text)
    if not text then
        return self
    end
    self._cacheResult = nil
    if type(text) == 'table' then
        self[#self+1] = {
            type     = 'markdown',
            markdown = text,
        }
    else
        text = tostring(text)
        self[#self+1] = {
            type     = 'text',
            language = language,
            text     = text,
        }
    end
    return self
end

function mt:splitLine()
    self._cacheResult = nil
    self[#self+1] = {
        type = 'splitline',
    }
    return self
end

function mt:emptyLine()
    self._cacheResult = nil
    self[#self+1] = {
        type = 'emptyline',
    }
    return self
end

---@return string
function mt:string(nl)
    if self._cacheResult then
        return self._cacheResult
    end
    local lines = {}
    local language = 'md'

    local function concat(markdown)
        for _, obj in ipairs(markdown) do
            if obj.type == 'splitline' then
                if language ~= 'md' then
                    lines[#lines+1] = '```'
                    language = 'md'
                end
                if #lines > 0
                and lines[#lines] ~= '---' then
                    lines[#lines+1] = ''
                    lines[#lines+1] = '---'
                end
            elseif obj.type == 'emptyline' then
                if  #lines > 0
                and lines[#lines] ~= '' then
                    if language ~= 'md' then
                        language = 'md'
                        lines[#lines+1] = '```'
                    end
                    lines[#lines+1] = ''
                end
            elseif obj.type == 'markdown' then
                concat(obj.markdown)
            else
                if obj.language ~= language then
                    if language ~= 'md' then
                        lines[#lines+1] = '```'
                    end
                    if #lines > 0 then
                        lines[#lines+1] = ''
                    end
                    if obj.language ~= 'md' then
                        lines[#lines+1] = '```' .. obj.language
                    end
                end
                if obj.language == 'md' and #lines > 0 then
                    local last = lines[#lines]
                    if obj.text:sub(1, 1) == '@'
                    or last:sub(1, 1) == '@' then
                        if lines[#lines] ~= '' then
                            lines[#lines+1] = ''
                        end
                    elseif last == '---' then
                        if lines[#lines] ~= '' then
                            lines[#lines+1] = ''
                        end
                    end
                end
                lines[#lines+1] = obj.text
                language = obj.language
            end
        end
    end

    concat(self)
    if language ~= 'md' then
        lines[#lines+1] = '```'
    end
    while true do
        if lines[#lines] == '---'
        or lines[#lines] == '' then
            lines[#lines] = nil
        else
            break
        end
    end

    local result = table.concat(lines, nl or '\n')
    self._cacheResult = result
    return result
end

return function ()
    return setmetatable({}, mt)
end