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
|
local wssymbol = require("core.workspace-symbol")
local guide = require("parser.guide")
---@class markdown
local mt = {}
mt.__index = mt
mt.__name = 'markdown'
mt._splitLine = false
---@async
---Converts `[mySymbol](lua://mySymbol)` into a link that points to the origin of `mySymbol`.
---@param txt string
local function processSymbolReferences(txt)
local function replacer(linkText, symbol)
local source ---@type table
for _, match in ipairs(wssymbol(symbol)) do
if match.name == symbol then
source = match.source
break
end
end
if not source then
log.warn(string.format("Failed to find source of %q symbol in markdown comment", symbol))
return
end
local row, _ = guide.rowColOf(source.start)
local uri = string.format("%s#%i", guide.getUri(source), row + 1)
return string.format("[%s](%s)", linkText, uri)
end
return string.gsub(txt, "%[([^]]*)%]%(lua://([^)]+)%)", replacer)
end
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] = processSymbolReferences(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
|