1
- const rasterisks = / ^ \s * \* /
1
+ const rlists = / ^ \s * ( [ \* - ] ) /
2
2
const rblockquote = / ^ \s * & g t ; /
3
3
const rheaders = / ^ * ( \= + ) * ( [ ^ \n \r ] + ?) [ = \s ] * $ /
4
4
5
- const space = '(^|\\s)'
5
+ const space = '(^|\\s|\\( )'
6
6
const quoted = ' "([^"]+)"'
7
7
const bracketed = '(?: ([^\\]]+))?'
8
8
@@ -11,6 +11,7 @@ const url = `(https?://${urlpart})`
11
11
const relativeLink = `(/${ urlpart } )`
12
12
const hashLink = `(#${ urlpart } )`
13
13
const camelCaseLink = `([A-Z][a-z]+[A-Z]${ urlpart } )`
14
+ const tracTicketLink = `trac:#(${ urlpart } )`
14
15
const tracLink = `trac:(${ urlpart } )`
15
16
const wikiLink = `wiki:(${ urlpart } )`
16
17
const wikipediaLink = `wikipedia:(${ urlpart } )`
@@ -44,6 +45,12 @@ module.exports = function tracToHTML(text) {
44
45
)
45
46
return `<pre class="wiki"></pre>`
46
47
} )
48
+ // Convert ---- to <hr>
49
+ . replace ( / ^ - - + $ / gm, '<hr />' )
50
+ // Replace three single quotes with <strong>
51
+ . replace ( / ' ' ' ( [ ^ ' ] + ?) ' ' ' / g, '<strong>$1</strong>' )
52
+ // Replace two slashses with <em>
53
+ . replace ( / (?< ! : ) \/ \/ ( [ ^ \/ ] + ?) \/ \/ / g, '<em>$1</em>' )
47
54
// Linkify http links outside brackets
48
55
. replace ( new RegExp ( `${ space } ${ url } ` , 'g' ) , function ( _match , space , url ) {
49
56
return `${
@@ -104,6 +111,20 @@ module.exports = function tracToHTML(text) {
104
111
} </a>`
105
112
}
106
113
)
114
+ // Linkify trac ticket links
115
+ . replace (
116
+ new RegExp (
117
+ `${ space } (?:(?:\\[${ tracTicketLink } ${ quoted } \\])|(?:\\[${ tracTicketLink } ${ bracketed } \\]))` ,
118
+ 'ig'
119
+ ) ,
120
+ function ( _match , space , quotepage , quotedtext , page , text ) {
121
+ return `${ space || '' } <a href="https://trac.edgewall.org/ticket/${
122
+ quotepage || page
123
+ } " class="ext-link"><span class="icon"></span>${
124
+ quotedtext || text || page
125
+ } </a>`
126
+ }
127
+ )
107
128
// Linkify trac links
108
129
. replace (
109
130
new RegExp (
@@ -146,8 +167,11 @@ module.exports = function tracToHTML(text) {
146
167
} </a>`
147
168
}
148
169
)
149
- // Linkify ticket references (avoid trac ticket links)
150
- . replace ( / # ( \d + ) (? ! < = > ) / g, `<a href="/ticket/$1">$&</a>` )
170
+ // Linkify ticket references
171
+ . replace (
172
+ new RegExp ( `${ space } #(\\d+)` , 'g' ) ,
173
+ `$1<a href="/ticket/$2">#$2</a>`
174
+ )
151
175
// Linkify CamelCase to wiki
152
176
. replace (
153
177
new RegExp ( `${ space } (!)?${ camelCaseLink } ` , 'g' ) ,
@@ -158,10 +182,6 @@ module.exports = function tracToHTML(text) {
158
182
return `${ space || '' } <a href="/wiki/${ page } ">${ page } </a>`
159
183
}
160
184
)
161
- // Convert ---- to <hr>
162
- . replace ( / ^ - - + $ / gm, '<hr />' )
163
- // Replace three single quotes with <strong>
164
- . replace ( / ' ' ' ( [ ^ ' ] + ) ' ' ' / g, '<strong>$1</strong>' )
165
185
// Remove certain trac macros
166
186
. replace ( / \[ \[ ( [ ^ \] ] + ) \] \] / g, function ( match , name ) {
167
187
for ( const macro in excludeMacros ) {
@@ -171,9 +191,10 @@ module.exports = function tracToHTML(text) {
171
191
} )
172
192
// Replace double newlines with paragraphs
173
193
. split ( / (?: \r ? \n ) / g)
194
+ // Work on single lines
174
195
. map ( ( line ) => {
175
196
let ret = ''
176
- if ( listStarted && ! rasterisks . test ( line ) ) {
197
+ if ( listStarted && ! rlists . test ( line ) ) {
177
198
listStarted = false
178
199
ret += '</ul>'
179
200
} else if ( blockquoteStarted && ! rblockquote . test ( line ) ) {
@@ -186,14 +207,6 @@ module.exports = function tracToHTML(text) {
186
207
if ( line . startsWith ( '<pre' ) ) {
187
208
return ret + line
188
209
}
189
- // Blockquotes
190
- if ( rblockquote . test ( line ) ) {
191
- if ( ! blockquoteStarted ) {
192
- blockquoteStarted = true
193
- ret += '<blockquote>'
194
- }
195
- return ret + line . replace ( rblockquote , ' ' )
196
- }
197
210
// Headers
198
211
if ( rheaders . test ( line ) ) {
199
212
return (
@@ -204,14 +217,23 @@ module.exports = function tracToHTML(text) {
204
217
} )
205
218
)
206
219
}
207
- if ( rasterisks . test ( line ) ) {
220
+ // Lists
221
+ if ( rlists . test ( line ) ) {
208
222
line = line . replace (
209
- / ( ^ | \s + ) \* ( [ ^ \n ] + ) / g,
223
+ / ( ^ | \s + ) [ \* - ] ( [ ^ ] + ) / g,
210
224
`$1${ listStarted ? '' : '<ul>' } <li>$2</li>`
211
225
)
212
226
listStarted = true
213
227
return ret + line
214
228
}
229
+ // Blockquotes
230
+ if ( rblockquote . test ( line ) ) {
231
+ if ( ! blockquoteStarted ) {
232
+ blockquoteStarted = true
233
+ ret += '<blockquote>'
234
+ }
235
+ return ret + line . replace ( rblockquote , ' ' )
236
+ }
215
237
return ret + `<p>${ line } </p>`
216
238
} )
217
239
. join ( '' )
0 commit comments