1- const rasterisks = / ^ \s * \* /
1+ const rlists = / ^ \s * ( [ \* - ] ) /
22const rblockquote = / ^ \s * & g t ; /
33const rheaders = / ^ * ( \= + ) * ( [ ^ \n \r ] + ?) [ = \s ] * $ /
44
5- const space = '(^|\\s)'
5+ const space = '(^|\\s|\\( )'
66const quoted = ' "([^"]+)"'
77const bracketed = '(?: ([^\\]]+))?'
88
@@ -11,6 +11,7 @@ const url = `(https?://${urlpart})`
1111const relativeLink = `(/${ urlpart } )`
1212const hashLink = `(#${ urlpart } )`
1313const camelCaseLink = `([A-Z][a-z]+[A-Z]${ urlpart } )`
14+ const tracTicketLink = `trac:#(${ urlpart } )`
1415const tracLink = `trac:(${ urlpart } )`
1516const wikiLink = `wiki:(${ urlpart } )`
1617const wikipediaLink = `wikipedia:(${ urlpart } )`
@@ -44,6 +45,12 @@ module.exports = function tracToHTML(text) {
4445 )
4546 return `<pre class="wiki"></pre>`
4647 } )
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>' )
4754 // Linkify http links outside brackets
4855 . replace ( new RegExp ( `${ space } ${ url } ` , 'g' ) , function ( _match , space , url ) {
4956 return `${
@@ -104,6 +111,20 @@ module.exports = function tracToHTML(text) {
104111 } </a>`
105112 }
106113 )
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+ )
107128 // Linkify trac links
108129 . replace (
109130 new RegExp (
@@ -146,8 +167,11 @@ module.exports = function tracToHTML(text) {
146167 } </a>`
147168 }
148169 )
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+ )
151175 // Linkify CamelCase to wiki
152176 . replace (
153177 new RegExp ( `${ space } (!)?${ camelCaseLink } ` , 'g' ) ,
@@ -158,10 +182,6 @@ module.exports = function tracToHTML(text) {
158182 return `${ space || '' } <a href="/wiki/${ page } ">${ page } </a>`
159183 }
160184 )
161- // Convert ---- to <hr>
162- . replace ( / ^ - - + $ / gm, '<hr />' )
163- // Replace three single quotes with <strong>
164- . replace ( / ' ' ' ( [ ^ ' ] + ) ' ' ' / g, '<strong>$1</strong>' )
165185 // Remove certain trac macros
166186 . replace ( / \[ \[ ( [ ^ \] ] + ) \] \] / g, function ( match , name ) {
167187 for ( const macro in excludeMacros ) {
@@ -171,9 +191,10 @@ module.exports = function tracToHTML(text) {
171191 } )
172192 // Replace double newlines with paragraphs
173193 . split ( / (?: \r ? \n ) / g)
194+ // Work on single lines
174195 . map ( ( line ) => {
175196 let ret = ''
176- if ( listStarted && ! rasterisks . test ( line ) ) {
197+ if ( listStarted && ! rlists . test ( line ) ) {
177198 listStarted = false
178199 ret += '</ul>'
179200 } else if ( blockquoteStarted && ! rblockquote . test ( line ) ) {
@@ -186,14 +207,6 @@ module.exports = function tracToHTML(text) {
186207 if ( line . startsWith ( '<pre' ) ) {
187208 return ret + line
188209 }
189- // Blockquotes
190- if ( rblockquote . test ( line ) ) {
191- if ( ! blockquoteStarted ) {
192- blockquoteStarted = true
193- ret += '<blockquote>'
194- }
195- return ret + line . replace ( rblockquote , ' ' )
196- }
197210 // Headers
198211 if ( rheaders . test ( line ) ) {
199212 return (
@@ -204,14 +217,23 @@ module.exports = function tracToHTML(text) {
204217 } )
205218 )
206219 }
207- if ( rasterisks . test ( line ) ) {
220+ // Lists
221+ if ( rlists . test ( line ) ) {
208222 line = line . replace (
209- / ( ^ | \s + ) \* ( [ ^ \n ] + ) / g,
223+ / ( ^ | \s + ) [ \* - ] ( [ ^ ] + ) / g,
210224 `$1${ listStarted ? '' : '<ul>' } <li>$2</li>`
211225 )
212226 listStarted = true
213227 return ret + line
214228 }
229+ // Blockquotes
230+ if ( rblockquote . test ( line ) ) {
231+ if ( ! blockquoteStarted ) {
232+ blockquoteStarted = true
233+ ret += '<blockquote>'
234+ }
235+ return ret + line . replace ( rblockquote , ' ' )
236+ }
215237 return ret + `<p>${ line } </p>`
216238 } )
217239 . join ( '' )
0 commit comments