diff --git a/400_xowa/src/gplx/xowa/Xoa_ttl.java b/400_xowa/src/gplx/xowa/Xoa_ttl.java index f906c501b..233260e11 100644 --- a/400_xowa/src/gplx/xowa/Xoa_ttl.java +++ b/400_xowa/src/gplx/xowa/Xoa_ttl.java @@ -20,7 +20,11 @@ import gplx.core.primitives.*; import gplx.core.btries.*; import gplx.langs.htmls.entitys.*; import gplx.xowa.wikis.nss.*; import gplx.xowa.wikis.xwikis.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.miscs.*; -import gplx.xowa.apps.utls.*; import gplx.langs.htmls.encoders.*; import gplx.xowa.langs.cases.*; +import gplx.xowa.apps.utls.*; import gplx.langs.htmls.encoders.*; import gplx.xowa.langs.cases.*; +/* TODO.XO + Is_known + Create_fragment_target +*/ public class Xoa_ttl { // PAGE:en.w:http://en.wikipedia.org/wiki/Help:Link; REF.MW: Ttl.php|secureAndSplit; private int wik_bgn = -1, ns_bgn = -1, page_bgn = 0, leaf_bgn = -1, anch_bgn = -1, root_bgn = -1; private byte[] tors_txt; @@ -136,7 +140,7 @@ public class Xoa_ttl { // PAGE:en.w:http://en.wikipedia.org/wiki/Help:Link; REF. public byte[] Get_prefixed_db_key() {return Full_db();} public boolean Has_fragment() {return anch_bgn != -1;} public byte[] Get_fragment() {return Anch_txt();} - public byte[] Get_link_url(byte[] query, boolean query2, boolean proto) { + public byte[] Get_link_url(gplx.xowa.mws.htmls.Xomw_qry_mgr qry_mgr, boolean query2, boolean proto) { // if ( $this->isExternal() || $proto !== false ) { // $ret = $this->getFullURL( $query, $query2, $proto ); // } @@ -190,6 +194,12 @@ public class Xoa_ttl { // PAGE:en.w:http://en.wikipedia.org/wiki/Help:Link; REF. // } return false; } + public boolean Is_known() { + return true; + } + public Xoa_ttl Create_fragment_target() { + return this; + } public boolean Is_external() {return this.wik_bgn != -1;} diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java index fde27a9fc..c998234fd 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java @@ -18,6 +18,7 @@ along with this program. If not, see . package gplx.xowa.mws; import gplx.*; import gplx.xowa.*; import gplx.core.btries.*; import gplx.xowa.mws.htmls.*; +import gplx.xowa.mws.linkers.*; public class Xomw_linker { private final Bry_bfr tmp = Bry_bfr_.New(); private final Linker_rel_splitter splitter = new Linker_rel_splitter(); @@ -27,95 +28,88 @@ public class Xomw_linker { private final byte[][] split_trail_rv = new byte[2][]; private Btrie_slim_mgr split_trail_trie; private static final byte[] Atr__class = Bry_.new_a7("class"), Atr__rel = Bry_.new_a7("rel"), Atr__href = Bry_.new_a7("href"), Rel__nofollow = Bry_.new_a7("nofollow"); + private final Xomw_link_renderer link_renderer; + public Xomw_linker(Xomw_link_renderer link_renderer) { + this.link_renderer = link_renderer; + } public void Init_by_wiki(Btrie_slim_mgr trie) { this.split_trail_trie = trie; } -// /** -// * This function returns an HTML link to the given target. It serves a few -// * purposes: -// * 1) If $target is a Title, the correct URL to link to will be figured -// * out automatically. -// * 2) It automatically adds the usual classes for various types of link -// * targets: "new" for red links, "stub" for short articles, etc. -// * 3) It escapes all attribute values safely so there's no risk of XSS. -// * 4) It provides a default tooltip if the target is a Title (the page -// * name of the target). -// * link() replaces the old functions in the makeLink() family. -// * -// * @since 1.18 Method exists since 1.16 as non-static, made static in 1.18. -// * @deprecated since 1.28, use MediaWiki\Linker\LinkRenderer instead -// * -// * @param Title $target Can currently only be a Title, but this may -// * change to support Images, literal URLs, etc. -// * @param String $html The HTML contents of the element, i.e., -// * the link text. This is raw HTML and will not be escaped. If null, -// * defaults to the prefixed text of the Title; or if the Title is just a -// * fragment, the contents of the fragment. -// * @param array $customAttribs A key => value array of extra HTML attributes, -// * such as title and class. (href is ignored.) Classes will be -// * merged with the default classes, while other attributes will replace -// * default attributes. All passed attribute values will be HTML-escaped. -// * A false attribute value means to suppress that attribute. -// * @param array $query The query String to append to the URL -// * you're linking to, in key => value array form. Query keys and values -// * will be URL-encoded. -// * @param String|array $options String or array of strings: -// * 'known': Page is known to exist, so don't check if it does. -// * 'broken': Page is known not to exist, so don't check if it does. -// * 'noclasses': Don't add any classes automatically (includes "new", -// * "stub", "mw-redirect", "extiw"). Only use the class attribute -// * provided, if any, so you get a simple blue link with no funny i- -// * cons. -// * 'forcearticlepath': Use the article path always, even with a querystring. -// * Has compatibility issues on some setups, so avoid wherever possible. -// * 'http': Force a full URL with http:// as the scheme. -// * 'https': Force a full URL with https:// as the scheme. -// * 'stubThreshold' => (int): Stub threshold to use when determining link classes. -// * @return String HTML attribute -// */ -// public static function link( -// $target, $html = null, $customAttribs = [], $query = [], $options = [] -// ) { -// if ( !$target instanceof Title ) { -// wfWarn( __METHOD__ . ': Requires $target to be a Title Object.', 2 ); -// return "$html"; -// } -// -// if ( is_string( $query ) ) { -// // some functions withing core using this still hand over query strings -// wfDeprecated( __METHOD__ . ' with parameter $query as String (should be array)', '1.20' ); -// $query = wfCgiToArray( $query ); -// } -// -// $services = MediaWikiServices::getInstance(); -// $options = (array)$options; -// if ( $options ) { -// // Custom options, create new LinkRenderer -// if ( !isset( $options['stubThreshold'] ) ) { -// $defaultLinkRenderer = $services->getLinkRenderer(); -// $options['stubThreshold'] = $defaultLinkRenderer->getStubThreshold(); -// } -// $linkRenderer = $services->getLinkRendererFactory() -// ->createFromLegacyOptions( $options ); -// } else { -// $linkRenderer = $services->getLinkRenderer(); -// } -// -// if ( $html !== null ) { -// $text = new HtmlArmor( $html ); -// } else { -// $text = $html; // null -// } -// if ( in_array( 'known', $options, true ) ) { -// return $linkRenderer->makeKnownLink( $target, $text, $customAttribs, $query ); -// } elseif ( in_array( 'broken', $options, true ) ) { -// return $linkRenderer->makeBrokenLink( $target, $text, $customAttribs, $query ); -// } elseif ( in_array( 'noclasses', $options, true ) ) { -// return $linkRenderer->makePreloadedLink( $target, $text, '', $customAttribs, $query ); -// } else { -// return $linkRenderer->makeLink( $target, $text, $customAttribs, $query ); -// } -// } + // This function returns an HTML link to the given target. It serves a few + // purposes: + // 1) If $target is a Title, the correct URL to link to will be figured + // out automatically. + // 2) It automatically adds the usual classes for various types of link + // targets: "new" for red links, "stub" for short articles, etc. + // 3) It escapes all attribute values safely so there's no risk of XSS. + // 4) It provides a default tooltip if the target is a Title (the page + // name of the target). + // link() replaces the old functions in the makeLink() family. + // + // @since 1.18 Method exists since 1.16 as non-static, made static in 1.18. + // @deprecated since 1.28, use MediaWiki\Linker\LinkRenderer instead + // + // @param Title $target Can currently only be a Title, but this may + // change to support Images, literal URLs, etc. + // @param String $html The HTML contents of the element, i.e., + // the link text. This is raw HTML and will not be escaped. If null, + // defaults to the prefixed text of the Title; or if the Title is just a + // fragment, the contents of the fragment. + // @param array $customAttribs A key => value array of extra HTML attributes, + // such as title and class. (href is ignored.) Classes will be + // merged with the default classes, while other attributes will replace + // default attributes. All passed attribute values will be HTML-escaped. + // A false attribute value means to suppress that attribute. + // @param array $query The query String to append to the URL + // you're linking to, in key => value array form. Query keys and values + // will be URL-encoded. + // @param String|array $options String or array of strings: + // 'known': Page is known to exist, so don't check if it does. + // 'broken': Page is known not to exist, so don't check if it does. + // 'noclasses': Don't add any classes automatically (includes "new", + // "stub", "mw-redirect", "extiw"). Only use the class attribute + // provided, if any, so you get a simple blue link with no funny i- + // cons. + // 'forcearticlepath': Use the article path always, even with a querystring. + // Has compatibility issues on some setups, so avoid wherever possible. + // 'http': Force a full URL with http:// as the scheme. + // 'https': Force a full URL with https:// as the scheme. + // 'stubThreshold' => (int): Stub threshold to use when determining link classes. + // @return String HTML attribute + public void Link(Bry_bfr bfr, Xoa_ttl target, byte[] html, Xomw_atr_mgr custom_attribs, Xomw_qry_mgr query, Xomw_opt_mgr options) { + // XO.MW.UNSUPPORTED:MW has different renderers -- presumably for forcing "https:" and others; XO only has one + //if (options != null) { + // // Custom options, create new LinkRenderer + // if (!isset($options['stubThreshold'])) { + // $defaultLinkRenderer = $services->getLinkRenderer(); + // $options['stubThreshold'] = $defaultLinkRenderer->getStubThreshold(); + // } + // $linkRenderer = $services->getLinkRendererFactory()->createFromLegacyOptions($options); + //} + //else { + // $linkRenderer = $services->getLinkRenderer(); + //} + + byte[] text = null; + if (html != null) { + // $text = new HtmlArmor($html); + } + else { + text = html; // null + } + if (options.known) { + link_renderer.Make_known_link(bfr, target, text, custom_attribs, query); + } + else if (options.broken) { +// return $linkRenderer->makeBrokenLink($target, $text, $customAttribs, $query); + } + else if (options.no_classes) { + link_renderer.Make_preloaded_link(bfr, target, text, Bry_.Empty, custom_attribs, query); + } + else { +// $linkRenderer->makeLink($target, $text, $customAttribs, $query); + } + } public void Make_self_link_obj(Bry_bfr bfr, Xoa_ttl nt, byte[] html, byte[] query, byte[] trail, byte[] prefix) { // MW.HOOK:SelfLinkBegin if (html == Bry_.Empty) { @@ -130,12 +124,12 @@ public class Xomw_linker { bfr.Add_str_a7(""); bfr.Add(trail); } - public void Make_external_link(Bry_bfr bfr, byte[] url, byte[] text, boolean escape, byte[] link_type, Xomwh_atr_mgr attribs, byte[] title) { + public void Make_external_link(Bry_bfr bfr, byte[] url, byte[] text, boolean escape, byte[] link_type, Xomw_atr_mgr attribs, byte[] title) { tmp.Add_str_a7("external"); if (link_type != null) { tmp.Add_byte_space().Add(link_type); } - Xomwh_atr_itm cls_itm = attribs.Get_by_or_make(Atr__class); + Xomw_atr_itm cls_itm = attribs.Get_by_or_make(Atr__class); if (cls_itm.Val() != null) { tmp.Add(cls_itm.Val()); } @@ -148,23 +142,23 @@ public class Xomw_linker { title = wg_title; byte[] new_rel = Get_external_link_rel(url, title); - Xomwh_atr_itm cur_rel_atr = attribs.Get_by_or_make(Atr__rel); + Xomw_atr_itm cur_rel_atr = attribs.Get_by_or_make(Atr__rel); if (cur_rel_atr.Val() == null) { cur_rel_atr.Val_(new_rel); } else { // Merge the rel attributes. byte[] cur_rel = cur_rel_atr.Val(); - Bry_split_.Split(new_rel, 0, new_rel.length, Byte_ascii.Space, Bool_.N, splitter); // $newRels = explode( ' ', $newRel ); - Bry_split_.Split(cur_rel, 0, cur_rel.length, Byte_ascii.Space, Bool_.N, splitter); // $oldRels = explode( ' ', $attribs['rel'] ); - cur_rel_atr.Val_(splitter.To_bry()); // $attribs['rel'] = implode( ' ', $combined ); + Bry_split_.Split(new_rel, 0, new_rel.length, Byte_ascii.Space, Bool_.N, splitter); // $newRels = explode(' ', $newRel); + Bry_split_.Split(cur_rel, 0, cur_rel.length, Byte_ascii.Space, Bool_.N, splitter); // $oldRels = explode(' ', $attribs['rel']); + cur_rel_atr.Val_(splitter.To_bry()); // $attribs['rel'] = implode(' ', $combined); } //$link = ''; - //$success = Hooks::run( 'LinkerMakeExternalLink', - // [ &$url, &$text, &$link, &$attribs, $linktype ] ); - //if ( !$success ) { - // wfDebug( "Hook LinkerMakeExternalLink changed the output of link " - // . "with url {$url} and text {$text} to {$link}\n", true ); + //$success = Hooks::run('LinkerMakeExternalLink', + // [ &$url, &$text, &$link, &$attribs, $linktype ]); + //if (!$success) { + // wfDebug("Hook LinkerMakeExternalLink changed the output of link " + // . "with url {$url} and text {$text} to {$link}\n", true); // return $link; //} attribs.Set(Atr__href, url); @@ -174,9 +168,9 @@ public class Xomw_linker { private byte[] Get_external_link_rel(byte[] url, byte[] title) { // global $wgNoFollowLinks, $wgNoFollowNsExceptions, $wgNoFollowDomainExceptions; // $ns = $title ? $title->getNamespace() : false; - // if ( $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions ) - // && !wfMatchesDomainList( $url, $wgNoFollowDomainExceptions ) - // ) { + // if ($wgNoFollowLinks && !in_array($ns, $wgNoFollowNsExceptions) + // && !wfMatchesDomainList($url, $wgNoFollowDomainExceptions) + //) { return Rel__nofollow; // } // return null; @@ -388,7 +382,7 @@ public class Xomw_linker { // $paramName = 'no-link'; // $value = true; // $validated = true; -// } elseif (preg_match("/^((?i)$prots)/", $value)) { +// } else if (preg_match("/^((?i)$prots)/", $value)) { // if (preg_match("/^((?i)$prots)$addr$chars*$/u", $value, $m)) { // $paramName = 'link-url'; // $this->mOutput->addExternalLink($value); @@ -537,19 +531,8 @@ public class Xomw_linker { // } // return [ $this->mImageParams[$handlerClass], $this->mImageParamsMagicArray[$handlerClass] ]; // } -// /** -// * Make HTML for a thumbnail including image, border and caption -// * @param Title $title -// * @param File|boolean $file File Object or false if it doesn't exist -// * @param String $label -// * @param String $alt -// * @param String $align -// * @param array $params -// * @param boolean $framed -// * @param String $manualthumb -// * @return String -// */ -// public static function makeThumbLinkObj( Title $title, $file, $label = '', $alt, +// // Make HTML for a thumbnail including image, border and caption +// public static function makeThumbLinkObj(Title $title, $file, $label = '', $alt, // $align = 'right', $params = [], $framed = false, $manualthumb = "" // ) { // $frameParams = [ @@ -557,227 +540,189 @@ public class Xomw_linker { // 'caption' => $label, // 'align' => $align // ]; -// if ( $framed ) { +// if ($framed) { // $frameParams['framed'] = true; // } -// if ( $manualthumb ) { +// if ($manualthumb) { // $frameParams['manualthumb'] = $manualthumb; // } -// return self::makeThumbLink2( $title, $file, $frameParams, $params ); +// return self::makeThumbLink2($title, $file, $frameParams, $params); // } -// -// /** -// * @param Title $title -// * @param File $file -// * @param array $frameParams -// * @param array $handlerParams -// * @param boolean $time -// * @param String $query -// * @return String -// */ -// public static function makeThumbLink2( Title $title, $file, $frameParams = [], + +// public static function makeThumbLink2(Title $title, $file, $frameParams = [], // $handlerParams = [], $time = false, $query = "" // ) { // $exists = $file && $file->exists(); // -// $page = isset( $handlerParams['page'] ) ? $handlerParams['page'] : false; -// if ( !isset( $frameParams['align'] ) ) { +// $page = isset($handlerParams['page']) ? $handlerParams['page'] : false; +// if (!isset($frameParams['align'])) { // $frameParams['align'] = 'right'; // } -// if ( !isset( $frameParams['alt'] ) ) { +// if (!isset($frameParams['alt'])) { // $frameParams['alt'] = ''; // } -// if ( !isset( $frameParams['title'] ) ) { +// if (!isset($frameParams['title'])) { // $frameParams['title'] = ''; // } -// if ( !isset( $frameParams['caption'] ) ) { +// if (!isset($frameParams['caption'])) { // $frameParams['caption'] = ''; // } // -// if ( empty( $handlerParams['width'] ) ) { +// if (empty($handlerParams['width'])) { // // Reduce width for upright images when parameter 'upright' is used -// $handlerParams['width'] = isset( $frameParams['upright'] ) ? 130 : 180; +// $handlerParams['width'] = isset($frameParams['upright']) ? 130 : 180; // } // $thumb = false; // $noscale = false; // $manualthumb = false; // -// if ( !$exists ) { +// if (!$exists) { // $outerWidth = $handlerParams['width'] + 2; // } else { -// if ( isset( $frameParams['manualthumb'] ) ) { -// # Use manually specified thumbnail -// $manual_title = Title::makeTitleSafe( NS_FILE, $frameParams['manualthumb'] ); -// if ( $manual_title ) { -// $manual_img = wfFindFile( $manual_title ); -// if ( $manual_img ) { -// $thumb = $manual_img->getUnscaledThumb( $handlerParams ); +// if (isset($frameParams['manualthumb'])) { +// // Use manually specified thumbnail +// $manual_title = Title::makeTitleSafe(NS_FILE, $frameParams['manualthumb']); +// if ($manual_title) { +// $manual_img = wfFindFile($manual_title); +// if ($manual_img) { +// $thumb = $manual_img->getUnscaledThumb($handlerParams); // $manualthumb = true; // } else { // $exists = false; // } // } -// } elseif ( isset( $frameParams['framed'] ) ) { +// } else if (isset($frameParams['framed'])) { // // Use image dimensions, don't scale -// $thumb = $file->getUnscaledThumb( $handlerParams ); +// $thumb = $file->getUnscaledThumb($handlerParams); // $noscale = true; // } else { -// # Do not present an image bigger than the source, for bitmap-style images -// # This is a hack to maintain compatibility with arbitrary pre-1.10 behavior -// $srcWidth = $file->getWidth( $page ); -// if ( $srcWidth && !$file->mustRender() && $handlerParams['width'] > $srcWidth ) { +// // Do not present an image bigger than the source, for bitmap-style images +// // This is a hack to maintain compatibility with arbitrary pre-1.10 behavior +// $srcWidth = $file->getWidth($page); +// if ($srcWidth && !$file->mustRender() && $handlerParams['width'] > $srcWidth) { // $handlerParams['width'] = $srcWidth; // } -// $thumb = $file->transform( $handlerParams ); +// $thumb = $file->transform($handlerParams); // } // -// if ( $thumb ) { +// if ($thumb) { // $outerWidth = $thumb->getWidth() + 2; // } else { // $outerWidth = $handlerParams['width'] + 2; // } // } // -// # ThumbnailImage::toHtml() already adds page= onto the end of DjVu URLs -// # So we don't need to pass it here in $query. However, the URL for the -// # zoom icon still needs it, so we make a unique query for it. See bug 14771 -// $url = $title->getLocalURL( $query ); -// if ( $page ) { -// $url = wfAppendQuery( $url, [ 'page' => $page ] ); +// // ThumbnailImage::toHtml() already adds page= onto the end of DjVu URLs +// // So we don't need to pass it here in $query. However, the URL for the +// // zoom icon still needs it, so we make a unique query for it. See bug 14771 +// $url = $title->getLocalURL($query); +// if ($page) { +// $url = wfAppendQuery($url, [ 'page' => $page ]); // } -// if ( $manualthumb -// && !isset( $frameParams['link-title'] ) -// && !isset( $frameParams['link-url'] ) -// && !isset( $frameParams['no-link'] ) ) { +// if ($manualthumb +// && !isset($frameParams['link-title']) +// && !isset($frameParams['link-url']) +// && !isset($frameParams['no-link'])) { // $frameParams['link-url'] = $url; // } // // $s = "
" // . "
"; // -// if ( !$exists ) { -// $s .= self::makeBrokenImageLinkObj( $title, $frameParams['title'], '', '', '', $time == true ); +// if (!$exists) { +// $s .= self::makeBrokenImageLinkObj($title, $frameParams['title'], '', '', '', $time == true); // $zoomIcon = ''; -// } elseif ( !$thumb ) { -// $s .= wfMessage( 'thumbnail_error', '' )->escaped(); +// } else if (!$thumb) { +// $s .= wfMessage('thumbnail_error', '')->escaped(); // $zoomIcon = ''; // } else { -// if ( !$noscale && !$manualthumb ) { -// self::processResponsiveImages( $file, $thumb, $handlerParams ); +// if (!$noscale && !$manualthumb) { +// self::processResponsiveImages($file, $thumb, $handlerParams); // } // $params = [ // 'alt' => $frameParams['alt'], // 'title' => $frameParams['title'], -// 'img-class' => ( isset( $frameParams['class'] ) && $frameParams['class'] !== '' +// 'img-class' => (isset($frameParams['class']) && $frameParams['class'] !== '' // ? $frameParams['class'] . ' ' -// : '' ) . 'thumbimage' +// : '') . 'thumbimage' // ]; -// $params = self::getImageLinkMTOParams( $frameParams, $query ) + $params; -// $s .= $thumb->toHtml( $params ); -// if ( isset( $frameParams['framed'] ) ) { +// $params = self::getImageLinkMTOParams($frameParams, $query) + $params; +// $s .= $thumb->toHtml($params); +// if (isset($frameParams['framed'])) { // $zoomIcon = ""; // } else { -// $zoomIcon = Html::rawElement( 'div', [ 'class' => 'magnify' ], -// Html::rawElement( 'a', [ +// $zoomIcon = Html::rawElement('div', [ 'class' => 'magnify' ], +// Html::rawElement('a', [ // 'href' => $url, // 'class' => '@gplx.Internal protected', -// 'title' => wfMessage( 'thumbnail-more' )->text() ], -// "" ) ); +// 'title' => wfMessage('thumbnail-more')->text() ], +// "")); // } // } // $s .= '
' . $zoomIcon . $frameParams['caption'] . "
"; -// return str_replace( "\n", ' ', $s ); +// return str_replace("\n", ' ', $s); // } -// /** -// * Make a "broken" link to an image -// * -// * @since 1.16.3 -// * @param Title $title -// * @param String $label Link label (plain text) -// * @param String $query Query String -// * @param String $unused1 Unused parameter kept for b/c -// * @param String $unused2 Unused parameter kept for b/c -// * @param boolean $time A file of a certain timestamp was requested -// * @return String -// */ -// public static function makeBrokenImageLinkObj( $title, $label = '', +// // Make a "broken" link to an image +// public static function makeBrokenImageLinkObj($title, $label = '', // $query = '', $unused1 = '', $unused2 = '', $time = false // ) { -// if ( !$title instanceof Title ) { -// wfWarn( __METHOD__ . ': Requires $title to be a Title Object.' ); -// return "" . htmlspecialchars( $label ); +// if (!$title instanceof Title) { +// wfWarn(__METHOD__ . ': Requires $title to be a Title Object.'); +// return "" . htmlspecialchars($label); // } // // global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl; -// if ( $label == '' ) { +// if ($label == '') { // $label = $title->getPrefixedText(); // } -// $encLabel = htmlspecialchars( $label ); -// $currentExists = $time ? ( wfFindFile( $title ) != false ) : false; +// $encLabel = htmlspecialchars($label); +// $currentExists = $time ? (wfFindFile($title) != false) : false; // -// if ( ( $wgUploadMissingFileUrl || $wgUploadNavigationUrl || $wgEnableUploads ) +// if (($wgUploadMissingFileUrl || $wgUploadNavigationUrl || $wgEnableUploads) // && !$currentExists // ) { -// $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title ); +// $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect($title); // -// if ( $redir ) { +// if ($redir) { // // We already know it's a redirect, so mark it // // accordingly // return self::link( // $title, // $encLabel, // [ 'class' => 'mw-redirect' ], -// wfCgiToArray( $query ), +// wfCgiToArray($query), // [ 'known', 'noclasses' ] // ); // } // -// $href = self::getUploadUrl( $title, $query ); +// $href = self::getUploadUrl($title, $query); // -// return '
' . +// return '' . // $encLabel . ''; // } // -// return self::link( $title, $encLabel, [], wfCgiToArray( $query ), [ 'known', 'noclasses' ] ); +// return self::link($title, $encLabel, [], wfCgiToArray($query), [ 'known', 'noclasses' ]); // } -// /** -// * Create a direct link to a given uploaded file. -// * -// * @since 1.16.3 -// * @param Title $title -// * @param String $html Pre-sanitized HTML -// * @param String $time MW timestamp of file creation time -// * @return String HTML -// */ -// public static function makeMediaLinkObj( $title, $html = '', $time = false ) { -// $img = wfFindFile( $title, [ 'time' => $time ] ); -// return self::makeMediaLinkFile( $title, $img, $html ); +// // Create a direct link to a given uploaded file. +// public static function makeMediaLinkObj($title, $html = '', $time = false) { +// $img = wfFindFile($title, [ 'time' => $time ]); +// return self::makeMediaLinkFile($title, $img, $html); // } // -// /** -// * Create a direct link to a given uploaded file. -// * This will make a broken link if $file is false. -// * -// * @since 1.16.3 -// * @param Title $title -// * @param File|boolean $file File Object or false -// * @param String $html Pre-sanitized HTML -// * @return String HTML -// * -// * @todo Handle invalid or missing images better. -// */ -// public static function makeMediaLinkFile( Title $title, $file, $html = '' ) { -// if ( $file && $file->exists() ) { +// // Create a direct link to a given uploaded file. +// // This will make a broken link if $file is false. +// public static function makeMediaLinkFile(Title $title, $file, $html = '') { +// if ($file && $file->exists()) { // $url = $file->getUrl(); // $class = '@gplx.Internal protected'; // } else { -// $url = self::getUploadUrl( $title ); +// $url = self::getUploadUrl($title); // $class = 'new'; // } // // $alt = $title->getText(); -// if ( $html == '' ) { +// if ($html == '') { // $html = $alt; // } // @@ -788,21 +733,34 @@ public class Xomw_linker { // 'title' => $alt // ]; // -// if ( !Hooks::run( 'LinkerMakeMediaLinkFile', -// [ $title, $file, &$html, &$attribs, &$ret ] ) ) { -// wfDebug( "Hook LinkerMakeMediaLinkFile changed the output of link " -// . "with url {$url} and text {$html} to {$ret}\n", true ); +// if (!Hooks::run('LinkerMakeMediaLinkFile', +// [ $title, $file, &$html, &$attribs, &$ret ])) { +// wfDebug("Hook LinkerMakeMediaLinkFile changed the output of link " +// . "with url {$url} and text {$html} to {$ret}\n", true); // return $ret; // } // -// return Html::rawElement( 'a', $attribs, $html ); +// return Html::rawElement('a', $attribs, $html); // } + public static Xoa_ttl Normalise_special_page(Xoa_ttl target) { +// if (target.Ns().Id_is_special() && !target.Is_external()) { +// list($name, $subpage) = SpecialPageFactory::resolveAlias($target->getDBkey()); +// if (!$name) { +// return $target; +// } +// $ret = SpecialPage::getTitleValueFor($name, $subpage, $target->getFragment()); +// return $ret; +// } +// else { + return target; +// } + } private static final byte[] Bry__dot2 = Bry_.new_a7("../"); } class Linker_rel_splitter implements gplx.core.brys.Bry_split_wkr { private final Hash_adp_bry hash = Hash_adp_bry.cs(); private final Bry_bfr bfr = Bry_bfr_.New(); - public int Split(byte[] src, int itm_bgn, int itm_end) { // $combined = array_unique( array_merge( $newRels, $oldRels ) ); + public int Split(byte[] src, int itm_bgn, int itm_end) { // $combined = array_unique(array_merge($newRels, $oldRels)); byte[] val = (byte[])hash.Get_by_mid(src, itm_bgn, itm_end); if (val == null) { val = Bry_.Mid(src, itm_bgn, itm_end); diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java index 52242692f..b2869dd67 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java @@ -28,7 +28,7 @@ public class Xomw_linker__normalize_subpage_link__tst { @Test public void Dot2__trailing() {fxt.Test__normalize_subpage_link("A/B/C" , "../../Z/" , "" , "A/Z" , "Z");} } class Xomw_linker__normalize_subpage_link__fxt { - private final Xomw_linker mgr = new Xomw_linker(); + private final Xomw_linker mgr = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer()); private final Xowe_wiki wiki; private final Xomw_linker__normalize_subpage_link normalize_subpage_link = new Xomw_linker__normalize_subpage_link(); public Xomw_linker__normalize_subpage_link__fxt() { diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java index a9fb0f647..33764246f 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java @@ -23,7 +23,7 @@ public class Xomw_linker__split_trail__tst { @Test public void None() {fxt.Test__split_trail(" abc" , null , " abc");} } class Xomw_linker__split_trail__fxt { - private final Xomw_linker linker = new Xomw_linker(); + private final Xomw_linker linker = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer()); private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs(); public Xomw_linker__split_trail__fxt() { String[] ary = new String[] {"a", "b", "c", "d", "e", "f"}; diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_itm.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_itm.java similarity index 91% rename from 400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_itm.java rename to 400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_itm.java index 44d95d70a..15bdd74cb 100644 --- a/400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_itm.java +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_itm.java @@ -16,8 +16,8 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.mws.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; -public class Xomwh_atr_itm { - public Xomwh_atr_itm(int key_int, byte[] key, byte[] val) { +public class Xomw_atr_itm { + public Xomw_atr_itm(int key_int, byte[] key, byte[] val) { this.key_int = key_int; this.key_bry = key; this.val = val; diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_mgr.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java similarity index 58% rename from 400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_mgr.java rename to 400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java index 59d27ee82..ad3f58396 100644 --- a/400_xowa/src/gplx/xowa/mws/htmls/Xomwh_atr_mgr.java +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java @@ -16,38 +16,45 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.mws.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; -public class Xomwh_atr_mgr { +public class Xomw_atr_mgr { private final Ordered_hash hash = Ordered_hash_.New(); public int Len() {return hash.Len();} - public Xomwh_atr_itm Get_at(int i) {return (Xomwh_atr_itm)hash.Get_at(i);} - public Xomwh_atr_mgr Clear() {hash.Clear(); return this;} - public void Add(byte[] key, byte[] val) {hash.Add(key, new Xomwh_atr_itm(-1, key, val));} - public void Add(Xomwh_atr_itm itm) {hash.Add(itm.Key_bry(), itm);} + public Xomw_atr_itm Get_at(int i) {return (Xomw_atr_itm)hash.Get_at(i);} + public Xomw_atr_mgr Clear() {hash.Clear(); return this;} + public void Add(byte[] key, byte[] val) {hash.Add(key, new Xomw_atr_itm(-1, key, val));} + public void Add(Xomw_atr_itm itm) {hash.Add(itm.Key_bry(), itm);} public void Del(byte[] key) {hash.Del(key);} public void Set(byte[] key, byte[] val) { - Xomwh_atr_itm atr = Get_by_or_make(key); + Xomw_atr_itm atr = Get_by_or_make(key); atr.Val_(val); } - public void Add_or_set(Xomwh_atr_itm src) { - Xomwh_atr_itm trg = (Xomwh_atr_itm)hash.Get_by(src.Key_bry()); + public void Add_or_set(Xomw_atr_itm src) { + Xomw_atr_itm trg = (Xomw_atr_itm)hash.Get_by(src.Key_bry()); if (trg == null) this.Add(src); else trg.Val_(src.Val()); } - public Xomwh_atr_itm Get_by_or_null(byte[] k) { - return (Xomwh_atr_itm)hash.Get_by(k); + public Xomw_atr_itm Get_by_or_null(byte[] k) { + return (Xomw_atr_itm)hash.Get_by(k); } - public Xomwh_atr_itm Get_by_or_make(byte[] k) { - Xomwh_atr_itm rv = (Xomwh_atr_itm)hash.Get_by(k); + public Xomw_atr_itm Get_by_or_make(byte[] k) { + Xomw_atr_itm rv = (Xomw_atr_itm)hash.Get_by(k); if (rv == null) { - rv = new Xomwh_atr_itm(-1, k, null); + rv = new Xomw_atr_itm(-1, k, null); Add(rv); } return rv; } public byte[] Get_val_or_null(byte[] k) { - Xomwh_atr_itm atr = (Xomwh_atr_itm)hash.Get_by(k); + Xomw_atr_itm atr = (Xomw_atr_itm)hash.Get_by(k); return atr == null ? null : atr.Val(); } + public void Merge(Xomw_atr_mgr src) { + int src_len = src.Len(); + for (int i = 0; i < src_len; i++) { + Xomw_atr_itm src_atr = src.Get_at(i); + this.Add(src_atr); + } + } } diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl.java index be42394f4..afd0461c6 100644 --- a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl.java +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl.java @@ -21,7 +21,7 @@ import gplx.langs.phps.utls.*; public class Xomw_html_utl { private final Bry_bfr tmp = Bry_bfr_.New(); private final Btrie_rv trv = new Btrie_rv(); - public void Raw_element(Bry_bfr bfr, byte[] element, Xomwh_atr_mgr attribs, byte[] contents) { + public void Raw_element(Bry_bfr bfr, byte[] element, Xomw_atr_mgr attribs, byte[] contents) { Bry_.Lcase__all(element); // XO:lcase element Open_element__lcased(bfr, element, attribs); @@ -33,7 +33,7 @@ public class Xomw_html_utl { Close_element__lcased(bfr, element); } } - private void Open_element__lcased(Bry_bfr bfr, byte[] element, Xomwh_atr_mgr attribs) { + private void Open_element__lcased(Bry_bfr bfr, byte[] element, Xomw_atr_mgr attribs) { // This is not required in HTML5, but let's do it anyway, for // consistency and better compression. // $element = strtolower($element); // XO:handled by callers @@ -58,10 +58,10 @@ public class Xomw_html_utl { Expand_attributes(bfr, attribs); // TODO.XO:self::dropDefaults($element, $attribs) bfr.Add_byte(Byte_ascii.Angle_end); } - public void Expand_attributes(Bry_bfr bfr, Xomwh_atr_mgr atrs) { + public void Expand_attributes(Bry_bfr bfr, Xomw_atr_mgr atrs) { int len = atrs.Len(); for (int i = 0; i < len; i++) { - Xomwh_atr_itm atr = (Xomwh_atr_itm)atrs.Get_at(i); + Xomw_atr_itm atr = (Xomw_atr_itm)atrs.Get_at(i); byte[] key = atr.Key_bry(); byte[] val = atr.Val(); diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl__expand_attributes__tst.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl__expand_attributes__tst.java index d55fbb700..e3417b0c2 100644 --- a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl__expand_attributes__tst.java +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_html_utl__expand_attributes__tst.java @@ -25,12 +25,12 @@ class Xomw_html_utl__expand_attributes__fxt { private final Xomw_html_utl utl = new Xomw_html_utl(); private final Bry_bfr bfr = Bry_bfr_.New(); public void Test__expand_attributes(String expd, String... kvs) { - Xomwh_atr_mgr atrs = new Xomwh_atr_mgr(); + Xomw_atr_mgr atrs = new Xomw_atr_mgr(); int kvs_len = kvs.length; for (int i = 0; i < kvs_len; i += 2) { byte[] key = Bry_.new_a7(kvs[i]); byte[] val = Bry_.new_a7(kvs[i + 1]); - Xomwh_atr_itm itm = new Xomwh_atr_itm(-1, key, val); + Xomw_atr_itm itm = new Xomw_atr_itm(-1, key, val); atrs.Add(itm); } utl.Expand_attributes(bfr, atrs); diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_opt_mgr.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_opt_mgr.java new file mode 100644 index 000000000..49ca5b582 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_opt_mgr.java @@ -0,0 +1,23 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.mws.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; +public class Xomw_opt_mgr { + public boolean known; + public boolean broken; + public boolean no_classes; +} diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_qry_mgr.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_qry_mgr.java new file mode 100644 index 000000000..7afb2e1c5 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_qry_mgr.java @@ -0,0 +1,27 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.mws.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; +public class Xomw_qry_mgr { + public byte[] action; + public int redlink; + public Xomw_qry_mgr Clear() { + action = null; + redlink = -1; + return this; + } +} diff --git a/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java index 5bf99ccb7..0fd471455 100644 --- a/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java +++ b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java @@ -18,31 +18,46 @@ along with this program. If not, see . package gplx.xowa.mws.linkers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; import gplx.langs.htmls.*; import gplx.xowa.mws.htmls.*; +/* TODO.XO + * titleFormatter->gePrefixedTex + * $html = HtmlArmor::getHtml($text); + * Get_link_url + * Normalise_special_page + * Merge_attribs + * Get_link_classes +*/ public class Xomw_link_renderer { private boolean expand_urls = false; private final Xomw_html_utl html_utl = new Xomw_html_utl(); - private final Xomwh_atr_mgr attribs = new Xomwh_atr_mgr(); + private final Xomw_atr_mgr attribs = new Xomw_atr_mgr(); + + // XO.MW:SYNC:1.29; DATE:2017-01-31 + public void Make_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, byte[] classes, Xomw_atr_mgr extra_atrs, Xomw_qry_mgr query) { + if (target.Is_known()) { + this.Make_known_link(bfr, target, text, extra_atrs, query); + } else { + this.Make_broken_link(bfr, target, text, extra_atrs, query); + } + } // If you have already looked up the proper CSS classes using LinkRenderer::getLinkClasses() // or some other method, use this to avoid looking it up again. - public void Make_preloaded_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, byte[] classes, Xomwh_atr_mgr extra_atrs, byte[] query) { - // IGNORE: $this->runBeginHook --> 'HtmlPageLinkRendererBegin', 'LinkBegin' + // XO.MW:SYNC:1.29; DATE:2017-01-31 + public void Make_preloaded_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, byte[] classes, Xomw_atr_mgr extra_atrs, Xomw_qry_mgr query) { + // XO.MW.HOOK: $this->runBeginHook --> 'HtmlPageLinkRendererBegin', 'LinkBegin' - // $target = $this->normalizeTarget( $target ); // normalizeSpecialPage + target = Normalize_target(target); byte[] url = Get_link_url(target, query); attribs.Clear(); - attribs.Add(Gfh_atr_.Bry__href, url); // NOTE: add url 1st; MW does attribs["url", url] + attribs + extra_attribs - if (classes.length > 0) // XO:do not bother adding if empty + attribs.Add(Gfh_atr_.Bry__href, url); // XO.MW: add url 1st; MW does attribs["url", url] + attribs + extra_attribs + if (classes.length > 0) // XO.MW:do not bother adding if empty attribs.Add(Gfh_atr_.Bry__class, classes); byte[] prefixed_text = target.Get_prefixed_text(); if (prefixed_text != Bry_.Empty) { attribs.Add(Gfh_atr_.Bry__title, prefixed_text); } - int extra_atrs_len = extra_atrs.Len(); - for (int i = 0; i < extra_atrs_len; i++) { - attribs.Add_or_set(extra_atrs.Get_at(i)); - } + attribs.Merge(extra_atrs); if (text == null) { text = this.Get_link_text(target); @@ -50,32 +65,68 @@ public class Xomw_link_renderer { Build_a_element(bfr, target,text, attribs, true); } - private void Build_a_element(Bry_bfr bfr, Xoa_ttl target, byte[] text, Xomwh_atr_mgr attribs, boolean is_known) { - // IGNORE: if ( !Hooks::run( 'HtmlPageLinkRendererEnd', + + // XO.MW:SYNC:1.29; DATE:2017-01-31 + public void Make_known_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, Xomw_atr_mgr extra_atrs, Xomw_qry_mgr query) { + byte[] classes = Bry_.Empty; + if (target.Is_external()) { + classes = Bry__classes__extiw; + } + byte[] colour = Get_link_classes(target); + if (colour != Bry_.Empty) { + classes = Bry_.Add(classes, Byte_ascii.Space_bry, colour); + } - byte[] html = text; - // $html = HtmlArmor::getHtml( $text ); + Make_preloaded_link(bfr, target, text, classes, extra_atrs, query); + } + // XO.MW:SYNC:1.29; DATE:2017-01-31 + public void Make_broken_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, Xomw_atr_mgr extra_atrs, Xomw_qry_mgr query) { + // XO.MW.HOOK: Run legacy hook - // IGNORE: if ( Hooks::isRegistered( 'LinkEnd' ) ) { + // We don't want to include fragments for broken links, because they + // generally make no sense. + if (target.Has_fragment()) { + target = target.Create_fragment_target(); + } + target = Normalize_target(target); - html_utl.Raw_element(bfr, Gfh_tag_.Bry__a, attribs, html); + if (query.action == null && target.Ns().Id() != gplx.xowa.wikis.nss.Xow_ns_.Tid__special) { + query.action = Bry_.new_a7("edit"); + query.redlink = 1; + } + + byte[] url = Get_link_url(target, query); + attribs.Clear(); + attribs.Add(Gfh_atr_.Bry__href, url); // $attribs = ['href' => $url,] + $this->mergeAttribs($attribs, $extraAttribs); + attribs.Add(Gfh_atr_.Bry__class, Bry_.new_a7("new")); + attribs.Merge(extra_atrs); + +// $prefixedText = $this->titleFormatter->getPrefixedText($target); +// if ($prefixedText !== '') { +// // This ends up in parser cache! +// $attribs['title'] = wfMessage('red-link-title', $prefixedText) +// ->inContentLanguage() +// ->text(); +// } + + if (text == null) { + text = Get_link_text(target); + } + + Build_a_element(bfr, target, text, attribs, false); } - private byte[] Get_link_url(Xoa_ttl target, byte[] query) { - // TODO: Use a LinkTargetResolver service instead of Title - // if ( $this->forceArticlePath ) { - // $realQuery = $query; - // $query = []; - // } - // else { - // $realQuery = []; - // } - byte[] url = target.Get_link_url(query, false, expand_urls); + // XO.MW:SYNC:1.29; DATE:2017-01-31 + private void Build_a_element(Bry_bfr bfr, Xoa_ttl target, byte[] text, Xomw_atr_mgr attribs, boolean is_known) { + // XO.MW.HOOK:HtmlPageLinkRendererEnd - // if ( $this->forceArticlePath && $realQuery ) { - // $url = wfAppendQuery( $url, $realQuery ); - // } - return url; + byte[] html = text; +// $html = HtmlArmor::getHtml($text); + + // XO.MW.HOOK:LinkEnd + + html_utl.Raw_element(bfr, Gfh_tag_.Bry__a, attribs, html); } + // XO.MW:SYNC:1.29; DATE:2017-01-31 private byte[] Get_link_text(Xoa_ttl target) { byte[] prefixed_text = target.Get_prefixed_text(); // If the target is just a fragment, with no title, we return the fragment @@ -85,48 +136,57 @@ public class Xomw_link_renderer { } return prefixed_text; } -// private function normalizeTarget( LinkTarget $target ) { -// return Linker::normaliseSpecialPage( $target ); -// } -// public static function normaliseSpecialPage( LinkTarget $target ) { -// if ( $target->getNamespace() == NS_SPECIAL && !$target->isExternal() ) { -// list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $target->getDBkey() ); -// if ( !$name ) { -// return $target; -// } -// $ret = SpecialPage::getTitleValueFor( $name, $subpage, $target->getFragment() ); -// return $ret; -// } else { -// return $target; + private byte[] Get_link_url(Xoa_ttl target, Xomw_qry_mgr query) { + // TODO: Use a LinkTargetResolver service instead of Title + +// if ($this->forceArticlePath) { +// $realQuery = $query; +// $query = []; // } -// } - private static final byte[] Bry__classes__extiw = Bry_.new_a7("extiw"); - public void Make_known_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, Xomwh_atr_mgr extra_atrs, byte[] query) { - byte[] classes = Bry_.Empty; - if (target.Is_external()) { - classes = Bry__classes__extiw; - } - byte[] colour = Get_link_classes(target); - if (colour != Bry_.Empty) { - classes = Bry_.Add(classes, Byte_ascii.Space_bry, colour); - } +// else { +// $realQuery = []; +// } + byte[] url = target.Get_link_url(query, false, expand_urls); - Make_preloaded_link(bfr, target, text, classes, extra_atrs, query); +// if ($this->forceArticlePath && $realQuery) { +// $url = wfAppendQuery($url, $realQuery); +// } + return url; + } + // XO.MW:SYNC:1.29; DATE:2017-01-31 + private Xoa_ttl Normalize_target(Xoa_ttl target) { + return Xomw_linker.Normalise_special_page(target); } +// private function mergeAttribs( $defaults, $attribs ) { +// if ( !$attribs ) { +// return $defaults; +// } +// // Merge the custom attribs with the default ones, and iterate +// // over that, deleting all "false" attributes. +// $ret = []; +// $merged = Sanitizer::mergeAttributes( $defaults, $attribs ); +// foreach ( $merged as $key => $val ) { +// # A false value suppresses the attribute +// if ( $val !== false ) { +// $ret[$key] = $val; +// } +// } +// return $ret; +// } public byte[] Get_link_classes(Xoa_ttl target) { // Make sure the target is in the cache -// $id = $this->linkCache->addLinkObj( $target ); -// if ( $id == 0 ) { +// $id = $this->linkCache->addLinkObj($target); +// if ($id == 0) { // // Doesn't exist // return ''; // } -// if ( $this->linkCache->getGoodLinkFieldObj( $target, 'redirect' ) ) { +// if ($this->linkCache->getGoodLinkFieldObj($target, 'redirect')) { // Page is a redirect // return 'mw-redirect'; // } -// elseif ( $this->stubThreshold > 0 && MWNamespace::isContent( $target->getNamespace() ) -// && $this->linkCache->getGoodLinkFieldObj( $target, 'length' ) < $this->stubThreshold +// elseif ($this->stubThreshold > 0 && MWNamespace::isContent($target->getNamespace()) +// && $this->linkCache->getGoodLinkFieldObj($target, 'length') < $this->stubThreshold // ) { // Page is a stub // return 'stub'; @@ -134,4 +194,5 @@ public class Xomw_link_renderer { return Bry_.Empty; } + private static final byte[] Bry__classes__extiw = Bry_.new_a7("extiw"); } diff --git a/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer__tst.java b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer__tst.java new file mode 100644 index 000000000..45066f61c --- /dev/null +++ b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer__tst.java @@ -0,0 +1,35 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.mws.linkers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; +// import org.junit.*; +// public class Xomw_link_renderer__tst { +// private final Xomw_link_renderer__fxt fxt = new Xomw_link_renderer__fxt(); +/* +Make_broken_link +target.Has_fragment() +*/ +// } +// class Xomw_link_renderer__fxt { +// private final Xomw_link_renderer wkr = new Xomw_link_renderer(new Xomw_parser()); +// public void Test__parse(String src_str, String expd) { +// byte[] src_bry = Bry_.new_u8(src_str); +// wkr.Replace_external_links(new Xomw_parser_ctx(), pbfr.Init(src_bry)); +// if (apos) expd = gplx.langs.htmls.Gfh_utl.Replace_apos(expd); +// Tfds.Eq_str_lines(expd, pbfr.Rslt().To_str_and_clear(), src_str); +// } +// } diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders.java index 3860613ee..962b51a18 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders.java @@ -25,7 +25,8 @@ public class Xomw_link_holders { private final Bry_bfr tmp; private int link_id = 0; // MOVED:Parser.php private final Xomw_link_holder_list internals = new Xomw_link_holder_list(); - private final Xomwh_atr_mgr extra_atrs = new Xomwh_atr_mgr(); + private final Xomw_atr_mgr extra_atrs = new Xomw_atr_mgr(); + private final Xomw_qry_mgr query = new Xomw_qry_mgr(); public Xomw_link_holders(Xomw_link_renderer link_renderer, Bry_bfr tmp) { this.link_renderer = link_renderer; this.tmp = tmp; @@ -136,7 +137,7 @@ public class Xomw_link_holders { // } bfr.Add_mid(src, prv, link_bgn); - link_renderer.Make_preloaded_link(bfr, item.Title(), item.Text(), Bry_.Empty, extra_atrs, Bry_.Empty); + link_renderer.Make_preloaded_link(bfr, item.Title(), item.Text(), Bry_.Empty, extra_atrs, query.Clear()); cur = key_end + Gfh_tag_.Comm_end_len; prv = cur; } diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java index acb205e42..548d23685 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java @@ -45,7 +45,7 @@ public class Xomw_parser { // private final Xomw_prepro_wkr prepro_wkr = new Xomw_prepro_wkr(); public Xomw_strip_state Strip_state() {return strip_state;} private final Xomw_strip_state strip_state = new Xomw_strip_state(); public Xomw_sanitizer Sanitizer() {return sanitizer;} private final Xomw_sanitizer sanitizer = new Xomw_sanitizer(); - public Xomw_linker Linker() {return linker;} private final Xomw_linker linker = new Xomw_linker(); + public Xomw_linker Linker() {return linker;} private final Xomw_linker linker; public Bry_bfr Tmp() {return tmp;} private final Bry_bfr tmp = Bry_bfr_.New(); public Xomw_quote_wkr Quote_wkr() {return quote_wkr;} private final Xomw_quote_wkr quote_wkr; public Xomw_lnki_wkr Lnki_wkr() {return lnki_wkr;} private final Xomw_lnki_wkr lnki_wkr; @@ -61,6 +61,7 @@ public class Xomw_parser { } } + this.linker = new Xomw_linker(link_renderer); this.protocols_trie = Xomw_parser.Protocols__dflt(); this.holders = new Xomw_link_holders(link_renderer, tmp); this.table_wkr = new Xomw_table_wkr(this); @@ -266,7 +267,7 @@ public class Xomw_parser { strip_state.Add_general(marker, text); return marker; } - public Xomwh_atr_mgr Get_external_link_attribs(Xomwh_atr_mgr atrs) { + public Xomw_atr_mgr Get_external_link_attribs(Xomw_atr_mgr atrs) { atrs.Clear(); byte[] rel = Get_external_link_rel; diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr.java index 433eedc5a..5ea23fc3f 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr.java @@ -26,7 +26,7 @@ public class Xomw_lnke_wkr {// THREAD.UNSAFE: caching for repeated calls private int autonumber; private final Xomw_parser parser; private final Xomw_linker linker; - private final Xomwh_atr_mgr attribs = new Xomwh_atr_mgr(); + private final Xomw_atr_mgr attribs = new Xomw_atr_mgr(); private Xomw_regex_url regex_url; private Xomw_regex_space regex_space; public Xomw_lnke_wkr(Xomw_parser parser) { diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java index e9db20cc7..1d25638db 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java @@ -35,7 +35,8 @@ public class Xomw_lnki_wkr {// THREAD.UNSAFE: caching for repeated calls private final Xomw_linker__normalize_subpage_link normalize_subpage_link = new Xomw_linker__normalize_subpage_link(); private final Bry_bfr tmp; private final Xomw_parser parser; - private final Xomwh_atr_mgr extra_atrs = new Xomwh_atr_mgr(); + private final Xomw_atr_mgr extra_atrs = new Xomw_atr_mgr(); + private final Xomw_qry_mgr query = new Xomw_qry_mgr(); public Xomw_lnki_wkr(Xomw_parser parser, Xomw_link_holders holders, Xomw_link_renderer link_renderer, Btrie_slim_mgr protocols_trie) { this.parser = parser; this.holders = holders; @@ -436,7 +437,7 @@ public class Xomw_lnki_wkr {// THREAD.UNSAFE: caching for repeated calls tmp.Add_bry_escape_html(inside); text = tmp.To_bry_and_clear(); - link_renderer.Make_known_link(bfr, nt, text, extra_atrs, Bry_.Empty); + link_renderer.Make_known_link(bfr, nt, text, extra_atrs, query); byte[] link = bfr.To_bry_and_clear(); parser.Armor_links(bfr, link, 0, link.length); bfr.Add(trail); diff --git a/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr.java b/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr.java index 83f1aa024..bf3612bcc 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr.java @@ -19,7 +19,6 @@ package gplx.xowa.mws.parsers.magiclinks; import gplx.*; import gplx.xowa.*; imp import gplx.core.primitives.*; import gplx.core.btries.*; import gplx.core.net.*; import gplx.langs.phps.utls.*; import gplx.xowa.mws.htmls.*; import gplx.langs.regxs.*; -// TODO.XO: getExternalLinkAttribs($url) // TODO.XO: this->getConverterLanguage()->markNoConversion($url, true), public class Xomw_magiclinks_wkr { private final Btrie_slim_mgr regex_trie = Btrie_slim_mgr.ci_a7(); // NOTE: must be ci to handle protocols; EX: "https:" and "HTTPS:" @@ -32,7 +31,7 @@ public class Xomw_magiclinks_wkr { private final Xomw_regex_url regex_url; private final Xomw_sanitizer sanitizer; private final Xomw_linker linker; - private final Xomwh_atr_mgr atrs = new Xomwh_atr_mgr(); + private final Xomw_atr_mgr atrs = new Xomw_atr_mgr(); private byte[] page_title; private static final byte Regex__anch = 1, Regex__elem = 2, Regex__free = 3;