@@ -381,11 +381,14 @@ function module_code(library_namespace) {
381381 *
382382 * @see https://zh.wikipedia.org/w/api.php?action=query&meta=siteinfo&siprop=protocols&utf8&format=json
383383 */
384- var PATTERN_external_link_global = new RegExp (
384+ var PATTERN_external_link = new RegExp (
385385 PATTERN_URL_WITH_PROTOCOL_GLOBAL . source
386386 // 允許 [//example.com/]
387387 . replace ( '):)' , '):|\\/\\/)' ) . replace ( / ^ \( [ ^ ( ) ] + \) / , / \[ / . source )
388- + / (?: ( [ ^ \S \n ] + ) ( [ ^ \] ] * ) ) ? \] / . source , 'ig' ) ,
388+ + / (?: ( [ ^ \S \n ] + ) ( [ ^ \] ] * ) ) ? \] / . source , 'i' ) ,
389+
390+ PATTERN_external_link_global = new RegExp ( PATTERN_external_link . source ,
391+ 'ig' ) ,
389392
390393 // 若包含 br|hr| 會導致 "aa<br>\nbb</br>\ncc" 解析錯誤!
391394 /** {String}以"|"分開之 wiki tag name。 [[Help:Wiki markup]], HTML tags. 不包含 <a>! */
@@ -1362,7 +1365,7 @@ function module_code(library_namespace) {
13621365 previous = '' ;
13631366 }
13641367 library_namespace . debug ( previous + ' + ' + parameters , 4 ,
1365- 'parse_wikitext.convert ' ) ;
1368+ 'parse_wikitext.language_conversion ' ) ;
13661369
13671370 // console.log(parameters);
13681371
@@ -1658,10 +1661,28 @@ function module_code(library_namespace) {
16581661
16591662 }
16601663
1661- // bare external link
1664+ // bare external link, parse_url()
16621665 // [[w:en:Wikipedia:Bare URLs]]
1663- function parse_url ( all , previous , URL ) {
1666+ function parse_bare_url ( all , previous , URL , protocol , URL_others ) {
16641667 var following = '' ;
1668+ // protocol.length: 排除 IPv6 之類正規 URL。
1669+ var index = protocol . length ;
1670+ var matched = URL_others . match ( wiki_API . PATTERN_IPv6_prefix ) ;
1671+ if ( matched ) {
1672+ index += matched [ 0 ] . length ;
1673+ }
1674+ index = URL . indexOf ( '[' , index ) ;
1675+ if ( index !== NOT_FOUND ) {
1676+ following = URL . slice ( index )
1677+ // assert: following === ''
1678+ // + (following || '')
1679+ ;
1680+ URL = URL . slice ( 0 , index ) ;
1681+ }
1682+ if ( URL === protocol ) {
1683+ return all ;
1684+ }
1685+
16651686 if ( URL . includes ( include_mark ) ) {
16661687 // 內部包含{{!}}之類,需再進一步處理。
16671688
@@ -1682,9 +1703,7 @@ function module_code(library_namespace) {
16821703 return all ;
16831704
16841705 following = URL . slice ( invalid_token_data [ 0 ] . length )
1685- // assert: following === ''
1686- // + (following || '')
1687- ;
1706+ + following ;
16881707 URL = invalid_token_data [ 0 ] ;
16891708 }
16901709
@@ -1708,10 +1727,46 @@ function module_code(library_namespace) {
17081727 function parse_external_link ( all , URL , protocol , URL_others , delimiter ,
17091728 parameters ) {
17101729 // assert: all === URL + (delimiter || '') + (parameters || '')
1730+ // URL === protocol + URL_others
17111731
1712- // including "'''". e.g., [http://a.b/''disply text'']
1713- var matched = URL . match ( / ^ ( .+ ?) ( ' ' .* ) $ / ) ;
1714- if ( matched ) {
1732+ // [...] 自 end_mark 向前回溯。
1733+ var index = all . length ,
1734+ // 在先的,在前的,前面的; preceding
1735+ // (previous 反義詞 following, preceding 反義詞 exceeds)
1736+ previous = '' ;
1737+ var matched ;
1738+ // 1 + protocol.length: ('[' + protocol).length - 排除 IPv6 之類正規 URL。
1739+ while ( index > 1 + protocol . length
1740+ && ( index = all . lastIndexOf ( '[' , index - 1 ) ) > 1 + protocol . length ) {
1741+ matched = all . slice ( index ) ;
1742+ matched = matched . match ( PATTERN_external_link ) ;
1743+ if ( ! matched ) {
1744+ continue ;
1745+ }
1746+
1747+ // shift arguments
1748+ URL = matched [ 1 ] ;
1749+ protocol = matched [ 2 ] ;
1750+ URL_others = matched [ 3 ] ;
1751+ delimiter = matched [ 4 ] ;
1752+ parameters = matched [ 5 ] ;
1753+ previous = all . slice ( 0 , matched . index ) ;
1754+ // assert: previous.startsWith('[')
1755+ break ;
1756+ }
1757+ library_namespace . debug ( previous + ' + ' + URL + ' + '
1758+ + ( delimiter || '' ) + ' + ' + ( parameters || '' ) , 4 ,
1759+ 'parse_wikitext.external_link' ) ;
1760+
1761+ // 往後追溯,從不合理的字元開始算作 display text。
1762+ // "''" including "'''". e.g., [http://a.b/''disply text'']
1763+
1764+ // 排除 IPv6 之類正規 URL。
1765+ if ( wiki_API . PATTERN_IPv6_prefix . test ( URL_others ) ) {
1766+ ;
1767+ }
1768+ matched = URL . match ( / ^ ( .+ ?) ( (?: \[ | ' ' ) .* ) $ / ) ;
1769+ if ( matched && ! wiki_API . PATTERN_IPv6_prefix . test ( URL_others ) ) {
17151770 // assert: 本階段尚未執行過 split_text_apostrophe_unit(wikitext)
17161771 URL = matched [ 1 ] ;
17171772 if ( delimiter ) {
@@ -1883,7 +1938,7 @@ function module_code(library_namespace) {
18831938
18841939 _set_wiki_type ( URL , 'external_link' ) ;
18851940 queue . push ( URL ) ;
1886- return include_mark + ( queue . length - 1 ) + end_mark ;
1941+ return previous + include_mark + ( queue . length - 1 ) + end_mark ;
18871942 }
18881943
18891944 function parse_odd_external_link ( all , URL , delimiter , parameters ) {
@@ -5046,7 +5101,7 @@ function module_code(library_namespace) {
50465101 if ( ! options . inside_url ) {
50475102 // 不可跨行。
50485103 wikitext = wikitext . replace_till_stable (
5049- PATTERN_URL_WITH_PROTOCOL_GLOBAL , parse_url ) ;
5104+ PATTERN_URL_WITH_PROTOCOL_GLOBAL , parse_bare_url ) ;
50505105 }
50515106
50525107 // ----------------------------------------------------
0 commit comments