Skip to content

Commit 7726ef7

Browse files
committed
fix(config): make regex readable; add support for wiki/wikipedia links; fix blockquotes
1 parent d775de6 commit 7726ef7

File tree

4 files changed

+217
-122
lines changed

4 files changed

+217
-122
lines changed

_data/wiki.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,4 +619,4 @@
619619
"comment": "",
620620
"readonly": 0
621621
}
622-
]
622+
]

_includes/layouts/base.njk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,4 @@
146146
})
147147
</script>
148148
</body>
149-
</html>
149+
</html>

content/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ breadcrumb: WikiStart
77

88
jQuery UI is in **maintenance-only mode**. Users should not expect any new releases. Patches may be issued to resolve critical security, interoperability, or regression bugs. See the [blog post](https://blog.jqueryui.com/2021/10/jquery-maintainers-update-and-transition-jquery-ui-as-part-of-overall-modernization-efforts/) for more information.
99

10-
jQuery UI issues were moved to <a href="https://github.com/jquery/jquery-ui/issues">GitHub</a>. This site is now a static, read-only archive of the old <a href="https://trac.edgewall.org/">Trac</a> site. Any critical issues should be filed on the project's GitHub repository.
10+
jQuery UI issues were moved to <a href="https://github.com/jquery/jquery-ui/issues">GitHub</a>. This site is now a static, read-only archive of the old <a href="https://trac.edgewall.org/">Trac</a> site. Any critical issues should be filed on the project's <a href="https://github.com/jquery/jquery-ui/issues">GitHub repository</a>.
1111

12-
_Search_ is still supported for tickets and milestones, but some functions and pages no longer work.
12+
**Search** is still supported for tickets and milestones, but some functions and pages no longer work.

eleventy.config.tracToHTML.js

Lines changed: 213 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
const rasterisks = /^\s*\* /
2+
const rblockquote = /^\s*&gt; /
23
const rheaders = /^ *(\=+) *([^\n\r]+?)[=\s]*$/
4+
5+
const space = '(^|\\s)'
6+
const quoted = ' "([^"]+)"'
7+
const bracketed = '(?: ([^\\]]+))?'
8+
9+
const urlpart = '[^\\s\\]]+'
10+
const url = `(https?://${urlpart})`
11+
const relativeLink = `(/${urlpart})`
12+
const hashLink = `(#${urlpart})`
13+
const camelCaseLink = `([A-Z][a-z]+[A-Z]${urlpart})`
14+
const tracLink = `trac:(${urlpart})`
15+
const wikiLink = `wiki:(${urlpart})`
16+
const wikipediaLink = `wikipedia:(${urlpart})`
17+
318
let listStarted = false
19+
let blockquoteStarted = false
20+
21+
const excludeMacros = ['br', 'tracguidetoc', 'pageoutline']
422

523
function escapeHTML(string) {
624
return string.replace(/</g, '&lt;').replace(/>/g, '&gt;')
@@ -9,127 +27,204 @@ function escapeHTML(string) {
927
module.exports = function tracToHTML(text) {
1028
const codes = []
1129
const pres = []
12-
return (
13-
escapeHTML(text)
14-
// Newlines have extra escapes in the strings
15-
.replace(/\\\n/g, '\n')
16-
// Replace `` with <code> tags
17-
.replace(/`([^\r\n`]+?)`/g, (_match, code) => {
18-
codes.push(code) // Save the code for later
19-
return `<code></code>`
20-
})
21-
// Replace {{{ }}} with <pre> tags
22-
.replace(/{{{([^]+?)}}}/g, (_match, code) => {
23-
// Save the code for later
24-
pres.push(
25-
// Remove language hints
26-
code.replace(/^#!\w+\r?\n/, '')
27-
)
28-
return `<pre class="wiki"></pre>`
29-
})
30-
// Linkify http links outside brackets
31-
.replace(/(^|\s)(https?:\/\/[^\s]+)/g, function (_match, space, url) {
32-
return `${
33-
space || ''
34-
}<a href="${url}" class="ext-link"><span class="icon"></span>${url}</a>`
35-
})
36-
// Linkify http links in brackets
37-
.replace(
38-
/(^|\s)(?:(?:\[https?:\/\/([^ ]+) "([^"]+)"\])|(?:\[https?:\/\/([^\s\]]+)(?: ([^\]]+))?\]))/g,
39-
function (_match, space, quotedurl, quotedtext, url, text) {
40-
return `${space || ''}<a href="${
41-
quotedurl || url
42-
}" class="ext-link"><span class="icon"></span>${
43-
quotedtext || text || url
44-
}</a>`
45-
}
46-
)
47-
// Linkify hash links in brackets
48-
.replace(
49-
/(^|\s)(?:(?:\[(#[^ ]+) "([^"]+)"\])|(?:\[(#[^\s\]]+)(?: ([^\]]+))?\]))/g,
50-
function (_match, space, quotedurl, quotedtext, url, text) {
51-
return `${space || ''}<a href="${
52-
quotedurl || url
53-
}" class="ext-link"><span class="icon"></span>${
54-
quotedtext || text || url
55-
}</a>`
56-
}
57-
)
58-
// Linkify CamelCase links in brackets
59-
.replace(
60-
/(^|\s)(?:(?:\[([A-Z][a-z]+[A-Z][^ ]+) "([^"]+)"\])|(?:\[([A-Z][a-z]+[A-Z][^\s\]]+)(?: ([^\]]+))?\]))/g,
61-
function (_match, space, quotedpage, quotedtext, page, text) {
62-
return `${space || ''}<a href="/wiki/${quotedpage || page}">${
63-
quotedtext || text || page
64-
}</a>`
65-
}
30+
let html = escapeHTML(text)
31+
// Newlines have extra escapes in the strings
32+
.replace(/\\\n/g, '\n')
33+
// Replace `` with <code> tags
34+
.replace(/`([^\r\n`]+?)`/g, (_match, code) => {
35+
codes.push(code) // Save the code for later
36+
return `<code></code>`
37+
})
38+
// Replace {{{ }}} with <pre> tags
39+
.replace(/{{{([^]+?)}}}/g, (_match, code) => {
40+
// Save the code for later
41+
pres.push(
42+
// Remove language hints
43+
code.replace(/^#!\w+\r?\n/, '')
6644
)
67-
// Linkify trac links
68-
.replace(
69-
/(^|\s)(?:(?:\[trac:([^ ]+) "([^"]+)"\])|(?:\[trac:([^\s\]]+)(?: ([^\]]+))?\]))/g,
70-
function (_match, space, quotepage, quotedtext, page, text) {
71-
return `${space || ''}<a href="https://trac.edgewall.org/intertrac/${
72-
quotepage || page
73-
}" class="ext-link"><span class="icon"></span>${
74-
quotedtext || text || page
75-
}</a>`
45+
return `<pre class="wiki"></pre>`
46+
})
47+
// Linkify http links outside brackets
48+
.replace(new RegExp(`${space}${url}`, 'g'), function (_match, space, url) {
49+
return `${
50+
space || ''
51+
}<a href="${url}" class="ext-link"><span class="icon"></span>${url}</a>`
52+
})
53+
// Linkify http links in brackets
54+
.replace(
55+
new RegExp(
56+
`${space}(?:(?:\\[${url}${quoted}\\])|(?:\\[${url}${bracketed}\\]))`,
57+
'g'
58+
),
59+
function (_match, space, quotedurl, quotedtext, url, text) {
60+
return `${space || ''}<a href="${
61+
quotedurl || url
62+
}" class="ext-link"><span class="icon"></span>${
63+
quotedtext || text || url
64+
}</a>`
65+
}
66+
)
67+
// Linkify relative links in brackets
68+
.replace(
69+
new RegExp(
70+
`${space}(?:(?:\\[${relativeLink}${quoted}\\])|(?:\\[${relativeLink}${bracketed}\\]))`,
71+
'g'
72+
),
73+
function (_match, space, quotedurl, quotedtext, url, text) {
74+
return `${space || ''}<a href="${
75+
quotedurl || url
76+
}" class="ext-link"><span class="icon"></span>${
77+
quotedtext || text || url
78+
}</a>`
79+
}
80+
)
81+
// Linkify hash links in brackets
82+
.replace(
83+
new RegExp(
84+
`${space}(?:(?:\\[${hashLink}${quoted}\\])|(?:\\[${hashLink}${bracketed}\\]))`,
85+
'g'
86+
),
87+
function (_match, space, quotedurl, quotedtext, url, text) {
88+
return `${space || ''}<a href="${
89+
quotedurl || url
90+
}" class="ext-link"><span class="icon"></span>${
91+
quotedtext || text || url
92+
}</a>`
93+
}
94+
)
95+
// Linkify CamelCase links in brackets
96+
.replace(
97+
new RegExp(
98+
`${space}(?:(?:\\[${camelCaseLink}${quoted}\\])|(?:\\[${camelCaseLink}${bracketed}\\]))`,
99+
'g'
100+
),
101+
function (_match, space, quotedpage, quotedtext, page, text) {
102+
return `${space || ''}<a href="/wiki/${quotedpage || page}">${
103+
quotedtext || text || page
104+
}</a>`
105+
}
106+
)
107+
// Linkify trac links
108+
.replace(
109+
new RegExp(
110+
`${space}(?:(?:\\[${tracLink}${quoted}\\])|(?:\\[${tracLink}${bracketed}\\]))`,
111+
'ig'
112+
),
113+
function (_match, space, quotepage, quotedtext, page, text) {
114+
return `${space || ''}<a href="https://trac.edgewall.org/intertrac/${
115+
quotepage || page
116+
}" class="ext-link"><span class="icon"></span>${
117+
quotedtext || text || page
118+
}</a>`
119+
}
120+
)
121+
// Linkify wiki links
122+
.replace(
123+
new RegExp(
124+
`${space}(?:(?:\\[${wikiLink}${quoted}\\])|(?:\\[${wikiLink}${bracketed}\\]))`,
125+
'ig'
126+
),
127+
function (_match, space, quotepage, quotedtext, page, text) {
128+
return `${space || ''}<a href="/wiki/${
129+
quotepage || page
130+
}" class="ext-link"><span class="icon"></span>${
131+
quotedtext || text || page
132+
}</a>`
133+
}
134+
)
135+
// Linkify wikipedia links
136+
.replace(
137+
new RegExp(
138+
`${space}(?:(?:\\[${wikipediaLink}${quoted}\\])|(?:\\[${wikipediaLink}${bracketed}\\]))`,
139+
'ig'
140+
),
141+
function (_match, space, quotepage, quotedtext, page, text) {
142+
return `${space || ''}<a href="https://wikipedia.org/wiki/${
143+
quotepage || page
144+
}" class="ext-link"><span class="icon"></span>${
145+
quotedtext || text || page
146+
}</a>`
147+
}
148+
)
149+
// Linkify ticket references (avoid trac ticket links)
150+
.replace(/#(\d+)(?!<=>)/g, `<a href="/ticket/$1">$&</a>`)
151+
// Linkify CamelCase to wiki
152+
.replace(
153+
new RegExp(`${space}(!)?${camelCaseLink}`, 'g'),
154+
function (_match, space, excl, page) {
155+
if (excl) {
156+
return `${space || ''}${page}`
76157
}
77-
)
78-
// Linkify ticket references (avoid trac ticket links)
79-
.replace(/#(\d+)(?!<=>)/g, `<a href="/ticket/$1">$&</a>`)
80-
// Linkify CamelCase to wiki
81-
.replace(
82-
/(^|\s)(!)?([A-Z][a-z]+[A-Z][\w:]+(?:#\w+)?)(?!\w)/g,
83-
function (_match, space, excl, page) {
84-
if (excl) {
85-
return `${space || ''}${page}`
86-
}
87-
return `${space || ''}<a href="/wiki/${page}">${page}</a>`
88-
}
89-
)
90-
// Convert ---- to <hr>
91-
.replace(/^--+$/gm, '<hr />')
92-
// Replace three single quotes with <strong>
93-
.replace(/'''([^']+)'''/g, '<strong>$1</strong>')
94-
// Replace double newlines with paragraphs
95-
.split(/(?:\r?\n)/g)
96-
.map((line) => {
97-
let ret = ''
98-
if (listStarted && !rasterisks.test(line)) {
99-
listStarted = false
100-
ret += '</ul>'
101-
}
102-
if (!line.trim()) {
103-
return ret
104-
}
105-
if (line.startsWith('<pre')) {
106-
return ret + line
107-
}
108-
// Blockquotes
109-
if (line.startsWith('> ')) {
110-
return ret + `<blockquote>${line.slice(2)}</blockquote>`
111-
}
112-
// Headers
113-
if (rheaders.test(line)) {
114-
return (
115-
ret +
116-
line.replace(rheaders, (_all, equals, content) => {
117-
const level = equals.length
118-
return `<h${level}>${content}</h${level}>`
119-
})
120-
)
158+
return `${space || ''}<a href="/wiki/${page}">${page}</a>`
159+
}
160+
)
161+
// Convert ---- to <hr>
162+
.replace(/^--+$/gm, '<hr />')
163+
// Replace three single quotes with <strong>
164+
.replace(/'''([^']+)'''/g, '<strong>$1</strong>')
165+
// Remove certain trac macros
166+
.replace(/\[\[([^\]]+)\]\]/g, function (match, name) {
167+
for (const macro in excludeMacros) {
168+
if (name.toLowerCase().startsWith(excludeMacros[macro])) return ''
169+
}
170+
return match
171+
})
172+
// Replace double newlines with paragraphs
173+
.split(/(?:\r?\n)/g)
174+
.map((line) => {
175+
let ret = ''
176+
if (listStarted && !rasterisks.test(line)) {
177+
listStarted = false
178+
ret += '</ul>'
179+
} else if (blockquoteStarted && !rblockquote.test(line)) {
180+
blockquoteStarted = false
181+
ret += '</blockquote>'
182+
}
183+
if (!line.trim()) {
184+
return ret
185+
}
186+
if (line.startsWith('<pre')) {
187+
return ret + line
188+
}
189+
// Blockquotes
190+
if (rblockquote.test(line)) {
191+
if (!blockquoteStarted) {
192+
blockquoteStarted = true
193+
ret += '<blockquote>'
121194
}
122-
if (rasterisks.test(line)) {
123-
line = line.replace(
124-
/(^|\s+)\* ([^\n]+)/g,
125-
`$1${listStarted ? '' : '<ul>'}<li>$2</li>`
126-
)
127-
listStarted = true
128-
return ret + line
129-
}
130-
return ret + `<p>${line}</p>`
131-
})
132-
.join('')
195+
return ret + line.replace(rblockquote, ' ')
196+
}
197+
// Headers
198+
if (rheaders.test(line)) {
199+
return (
200+
ret +
201+
line.replace(rheaders, (_all, equals, content) => {
202+
const level = equals.length
203+
return `<h${level}>${content}</h${level}>`
204+
})
205+
)
206+
}
207+
if (rasterisks.test(line)) {
208+
line = line.replace(
209+
/(^|\s+)\* ([^\n]+)/g,
210+
`$1${listStarted ? '' : '<ul>'}<li>$2</li>`
211+
)
212+
listStarted = true
213+
return ret + line
214+
}
215+
return ret + `<p>${line}</p>`
216+
})
217+
.join('')
218+
219+
if (listStarted) {
220+
html += '</ul>'
221+
}
222+
if (blockquoteStarted) {
223+
html += '</blockquote>'
224+
}
225+
226+
return (
227+
html
133228
// Reinsert code
134229
.replace(/<code><\/code>/g, () => {
135230
const code = codes.shift()

0 commit comments

Comments
 (0)