1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2016-01-24 22:50:55 -05:00
parent 235228976e
commit 686d56fdab
77 changed files with 1543 additions and 487 deletions

View File

@@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.encoders.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.wikis.dbs.*; import gplx.xowa.wikis.ctgs.*; import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.htmls.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.htmls.*; import gplx.xowa.parsers.amps.*;
public class Dpl_xnde implements Xox_xnde {
private Dpl_itm itm = new Dpl_itm(); private List_adp pages = List_adp_.new_();
public void Xatr__set(Xowe_wiki wiki, byte[] src, Mwh_atr_itm xatr, Object xatr_id_obj) {} // NOTE: <dynamicPageList> has no attributes
@@ -45,29 +45,34 @@ public class Dpl_xnde implements Xox_xnde {
if (itm.Count() != Int_.Min_value && itms_bgn + itm.Count() < itms_len) {
itms_len = itms_bgn + itm.Count();
}
boolean showns = itm.Show_ns();
bfr.Add(html_mode.Grp_bgn()).Add_byte_nl();
for (int i = itms_bgn; i < itms_len; i++) {
Xowd_page_itm page = (Xowd_page_itm)pages.Get_at(i);
Xoa_ttl ttl = Xoa_ttl.parse(wiki, page.Ns_id(), page.Ttl_page_db());
byte[] ttl_page_txt = showns ? ttl.Full_txt() : ttl.Page_txt();
if (ttl_page_txt == null) continue; // NOTE: apparently DynamicPageList allows null pages; DATE:2013-07-22
switch (html_mode.Tid()) {
case Dpl_html_data.Tid_list_ul:
case Dpl_html_data.Tid_list_ol:
bfr.Add(Xoh_consts.Space_2).Add(html_mode.Itm_bgn()).Add(Gfh_bldr_.Bry__a_lhs_w_href);
bfr.Add_str_a7("/wiki/").Add(ttl_page_txt);
bfr.Add(Gfh_bldr_.Bry__title__nth).Add(ttl_page_txt).Add_byte(Byte_ascii.Quote);
if (itm.No_follow()) bfr.Add(Bry_nofollow);
bfr.Add_byte(Byte_ascii.Gt);
bfr.Add(ttl_page_txt);
bfr.Add(Gfh_bldr_.Bry__a_rhs).Add(html_mode.Itm_end()).Add_byte_nl();
break;
default:
break;
boolean show_ns = itm.Show_ns();
Bry_bfr tmp_bfr = Bry_bfr_.Get();
Xop_amp_mgr amp_mgr = wiki.Appe().Parser_amp_mgr();
try {
bfr.Add(html_mode.Grp_bgn()).Add_byte_nl();
for (int i = itms_bgn; i < itms_len; i++) {
Xowd_page_itm page = (Xowd_page_itm)pages.Get_at(i);
Xoa_ttl ttl = Xoa_ttl.parse(wiki, page.Ns_id(), page.Ttl_page_db());
byte[] ttl_page_txt = show_ns ? ttl.Full_txt() : ttl.Page_txt();
if (ttl_page_txt == null) continue; // NOTE: apparently DynamicPageList allows null pages; DATE:2013-07-22
switch (html_mode.Tid()) {
case Dpl_html_data.Tid_list_ul:
case Dpl_html_data.Tid_list_ol:
bfr.Add(Xoh_consts.Space_2).Add(html_mode.Itm_bgn()).Add(Gfh_bldr_.Bry__a_lhs_w_href);
bfr.Add_str_a7("/wiki/").Add(Gfo_url_encoder_.Href.Encode(ttl.Full_db())).Add_byte_quote(); // NOTE: Full_db to encode spaces as underscores; PAGE:en.q:Wikiquote:Speedy_deletions DATE:2016-01-19
Gfh_atr_.Add(bfr, Gfh_atr_.Bry__title, Xoh_html_wtr_escaper.Escape(amp_mgr, tmp_bfr, ttl.Full_txt())); // NOTE: Full_txt b/c title always includes ns, even if show_ns is off; PAGE:en.b:Wikibooks:WikiProject DATE:2016-01-20
if (itm.No_follow()) bfr.Add(Bry_nofollow);
bfr.Add_byte(Byte_ascii.Gt);
Xoh_html_wtr_escaper.Escape(amp_mgr, bfr, ttl_page_txt, 0, ttl_page_txt.length, false, false);
bfr.Add(Gfh_bldr_.Bry__a_rhs).Add(html_mode.Itm_end()).Add_byte_nl();
// TODO: lnki_wtr.Clear().Href_wiki_(ttl).Title_(ttl).Nofollow_().Write_head(bfr).Write_text(bfr).Write_tail(bfr)
break;
default:
break;
}
}
}
bfr.Add(html_mode.Grp_end()).Add_byte_nl();
bfr.Add(html_mode.Grp_end()).Add_byte_nl();
} finally {tmp_bfr.Mkr_rls();}
}
private static byte[] Bry_nofollow = Bry_.new_a7(" rel=\"nofollow\"");
}

View File

@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.core.strings.*; import gplx.xowa.apps.cfgs.*; import gplx.xowa.wikis.nss.*;
import org.junit.*; import gplx.core.strings.*; import gplx.xowa.apps.cfgs.*; import gplx.xowa.wikis.nss.*; import gplx.langs.htmls.*;
public class Dpl_xnde_tst {
private Dpl_xnde_fxt fxt = new Dpl_xnde_fxt();
@Before public void init() {fxt.Clear();}
@@ -126,25 +126,37 @@ public class Dpl_xnde_tst {
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "C"));
}
@Test public void Ns() {
fxt.Ctg_create("Ctg_0", "Talk:A", "B");
fxt.Ctg_create("Ctg_0", "Talk:A B", "B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "namespace=Talk"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A"));
, "</DynamicPageList>"), Gfh_utl.Replace_apos_concat_lines
( "<ul>"
, " <li><a href='/wiki/Talk:A_B' title='Talk:A B'>A B</a></li>"
, "</ul>"
));
}
@Test public void Showns() {
@Test public void Show_ns() {
fxt.Ctg_create("Ctg_0", "Talk:A");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "shownamespace=true"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "Talk:A"));
, "</DynamicPageList>"), Gfh_utl.Replace_apos_concat_lines
( "<ul>"
, " <li><a href='/wiki/Talk:A' title='Talk:A'>Talk:A</a></li>"
, "</ul>"
));
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "shownamespace=false"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A"));
, "</DynamicPageList>"), Gfh_utl.Replace_apos_concat_lines
( "<ul>"
, " <li><a href='/wiki/Talk:A' title='Talk:A'>A</a></li>"
, "</ul>"
));
}
@Test public void Comment() { // PURPOSE: comment should be ignored; en.n:Portal:Federally_Administered_Tribal_Areas; DATE:2014-01-18
fxt.Ctg_create("Ctg_0", "B", "A");
@@ -172,6 +184,7 @@ public class Dpl_xnde_tst {
fxt.Wiki().Cfg_parser().Xtns().Itm_pages().Reset(); // must reset to clear cached valid ns_page from previous tests
fxt.Fxt().Test_parse_page_wiki_str("<dynamicpagelist>category=a</dynamicpagelist>", "No pages meet these criteria.");
fxt.Wiki().Cfg_parser().Xtns().Itm_pages().Reset(); // must reset to clear cached invalid ns_page for next tests
fxt.Wiki().Ns_mgr().Add_new(0, "").Init(); // call .Clear() to remove ns for Page / Index
}
@Test public void Ordermethod__invalid() { // PURPOSE: do not fail if ordermethod is invalid; PAGE:sr.d:Викиречник:Википројекат_1001_арапска_реч/Списак_уноса; DATE:2015-10-16
fxt.Ctg_create("Ctg_0", "A", "B", "C");
@@ -183,6 +196,30 @@ public class Dpl_xnde_tst {
, "</DynamicPageList>")
, fxt.Ul(Itm_html_null, "A", "B", "C"));
}
@Test public void Encode_spaces() {// PURPOSE:encode spaces in href; PAGE:en.q:Wikiquote:Speedy_deletions DATE:2016-01-19
fxt.Ctg_create("Ctg_0", "A B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "nofollow=true"
, "</DynamicPageList>"), Gfh_utl.Replace_apos_concat_lines
( "<ul>"
, " <li><a href='/wiki/A_B' title='A B' rel='nofollow'>A B</a></li>" // "/wiki/A_B" not "/wiki/A B"
, "</ul>"
));
}
@Test public void Encode_quotes() {// PURPOSE:encode quotes; PAGE:en.b:Wikibooks:Alphabetical_classification/All_Books; DATE:2016-01-21
fxt.Ctg_create("Ctg_0", "A\"B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "nofollow=true"
, "</DynamicPageList>"), Gfh_utl.Replace_apos_concat_lines
( "<ul>"
, " <li><a href='/wiki/A%22B' title='A&quot;B' rel='nofollow'>A&quot;B</a></li>" // "/wiki/A_B" not "/wiki/A B"
, "</ul>"
));
}
private static final String Itm_html_null = null;
}
class Dpl_page_mok {

View File

@@ -1,42 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.logs.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.htmls.*;
public class Pb_xnde implements Xox_xnde {
// private Pb_xtn xtn;
public void Xatr__set(Xowe_wiki wiki, byte[] src, Mwh_atr_itm xatr, Object xatr_id_obj) {}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_bgn);
// this.xtn = (Pb_xtn)wiki.Xtn_mgr().Get_or_fail(Pb_xtn.Xtn_key_static);
// xtn.Xtn_init_assert(wiki);
// ctx.Cur_page().Html_data().Head_mgr().Itm__graph().Enabled_y_();
// boolean log_wkr_enabled = Log_wkr != Xop_log_basic_wkr.Null; if (log_wkr_enabled) Log_wkr.Log_end_xnde(ctx.Cur_page(), Xop_log_basic_wkr.Tid_graph, src, xnde);
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end);
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
// bfr.Add(Html__div_bgn);
// bfr.Add_mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
// bfr.Add(Html__div_end);
}
public static Xop_log_basic_wkr Log_wkr = Xop_log_basic_wkr.Null;
// private static final byte[]
// Html__div_bgn = Bry_.new_a7("<div class='mw-wiki-graph'>\n")
// , Html__div_end = Bry_.new_a7("</div>\n")
// ;
}

View File

@@ -0,0 +1,150 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.parsers.*;
class Pgbnr_cfg {
public byte[] Default_file() {return null;}
public boolean Enabled_in_ns(int ns_id) {return false;}
}
class Pgbnr_icon {
public byte[] Name;
public byte[] Title;
public byte[] Url;
public Pgbnr_icon(byte[] name, byte[] title, byte[] url) {
this.Name = name; this.Title = title; this.Url = url;
}
public static final Pgbnr_icon[] Ary_empty = new Pgbnr_icon[0];
}
class Pgbnr_itm {
public byte[] Name;
public byte[] Tooltip;
public byte[] Title;
public boolean Bottomtoc;
public boolean Toc;
public Xoa_ttl File_ttl;
public Pgbnr_icon[] Icons;
public Pgbnr_itm(byte[] name, byte[] tooltip, byte[] title, boolean bottomtoc, boolean toc, Xoa_ttl file_ttl, Pgbnr_icon[] icons) {
this.Name = name;
this.Tooltip = tooltip; this.Title = title; this.Bottomtoc = bottomtoc; this.Toc = toc; this.File_ttl = file_ttl; this.Icons = icons;
}
// public static void Do(Bry_bfr bfr, Xop_ctx ctx, Pgbnr_cfg cfg, Pgbnr_itm itm) {
// if (itm != null) {
// byte[] name = itm.Name;
//// if ( isset( $params['icons'] ) ){
//// $out->enableOOUI();
//// $params['icons'] = self::expandIconTemplateOptions( $params['icons'] );
//// }
// // $banner = $wpbFunctionsClass::getBannerHtml( $bannername, $params );
// }
// else {}
// }
public static void Get_banner_html(Bry_bfr bfr, byte[] banner_name, Pgbnr_itm itm, Pgbnr_cfg cfg) {
byte[][] urls = Bry_.Ary(Bry_.Empty); // $urls = static::getStandardSizeUrls( $bannername );
if (urls.length == 0) return;
}
// public static function getBannerHtml( $bannername, $options = array() ) {
// // @var int index variable
// $i = 0;
// foreach ( $urls as $url ) {
// $size = $config->get( 'WPBStandardSizes' );
// $size = $size[$i];
// // add url with width and a comma if not adding the last url
// if ( $i < count( $urls ) ) {
// $srcset[] = "$url {$size}w";
// }
// $i++;
// }
// // create full src set from individual urls, separated by comma
// $srcset = implode( ',', $srcset );
// // use largest image url as src attribute
// $bannerurl = $urls[count( $urls ) - 1];
// $bannerfile = Title::newFromText( "File:$bannername" );
// $templateParser = new TemplateParser( __DIR__ . '/../templates' );
// $options['bannerfile'] = $bannerfile->getLocalUrl();
// $options['banner'] = $bannerurl;
// $options['srcset'] = $srcset;
// $file = wfFindFile( $bannerfile );
// $options['maxWidth'] = $file->getWidth();
// $options['isHeadingOverrideEnabled'] = $config->get( 'WPBEnableHeadingOverride' );
// $banner = $templateParser->processTemplate(
// 'banner',
// $options
// );
// }
// public static function addBanner( OutputPage $out, Skin $skin ) {
// $config = WikidataPageBannerFunctions::getWPBConfig();
// $title = $out->getTitle();
// $isDiff = $out->getRequest()->getVal( 'diff' );
// $wpbFunctionsClass = self::$wpbFunctionsClass;
//
// // if banner-options are set and not a diff page, add banner anyway
// if ( $out->getProperty( 'wpb-banner-options' ) !== null && !$isDiff ) {
// $params = $out->getProperty( 'wpb-banner-options' );
// $bannername = $params['name'];
// $banner = $wpbFunctionsClass::getBannerHtml( $bannername, $params );
// // attempt to get WikidataBanner
// if ( $banner === null ) {
// $bannername = $wpbFunctionsClass::getWikidataBanner( $title );
// $banner = $wpbFunctionsClass::getBannerHtml( $bannername, $params );
// }
// // only add banner and styling if valid banner generated
// if ( $banner !== null ) {
// if ( isset( $params['toc'] ) ) {
// $out->addModuleStyles( 'ext.WikidataPageBanner.toc.styles' );
// }
// $wpbFunctionsClass::insertBannerIntoOutputPage( $out, $banner );
//
// // FIXME: This is currently only needed to support testing
// $out->setProperty( 'articlebanner-name', $bannername );
// }
// }
// // if the page uses no 'PAGEBANNER' invocation and if article page, insert default banner
// elseif (
// $title->isKnown() &&
// $out->isArticle() &&
// $config->get( 'WPBEnableDefaultBanner' ) &&
// !$isDiff
// ) {
// $ns = $title->getNamespace();
// // banner only on specified namespaces, and not Main Page of wiki
// if ( in_array( $ns, $config->get( 'WPBNamespaces' ) )
// && !$title->isMainPage() ) {
// // first try to obtain bannername from Wikidata
// $bannername = $wpbFunctionsClass::getWikidataBanner( $title );
// if ( $bannername === null ) {
// // if Wikidata banner not found, set bannername to default banner
// $bannername = $config->get( 'WPBImage' );
// }
// // add title to template parameters
// $paramsForBannerTemplate = array( 'title' => $title );
// $banner = $wpbFunctionsClass::
// getBannerHtml( $bannername, $paramsForBannerTemplate );
// // only add banner and styling if valid banner generated
// if ( $banner !== null ) {
// $wpbFunctionsClass::insertBannerIntoOutputPage( $out, $banner );
//
// // set articlebanner property on OutputPage
// // FIXME: This is currently only needed to support testing
// $out->setProperty( 'articlebanner-name', $bannername );
// }
// }
// }
// return true;
// }
}

View File

@@ -0,0 +1,79 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*; import gplx.xowa.xtns.pfuncs.*; import gplx.xowa.langs.kwds.*;
import gplx.xowa.parsers.utils.*;
public class Pgbnr_func extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_pagebanner;}
@Override public Pf_func New(int id, byte[] name) {return new Pgbnr_func().Name_(name);}
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { // WikidataPageBanner.hooks.php|addCustomBanner
Xowe_wiki wiki = ctx.Wiki();
Pgbnr_cfg cfg = new Pgbnr_cfg(); // ctx.Wiki().Xtn_mgr().Xtn_pgbnr();
Xoa_ttl ttl = ctx.Cur_page().Ttl();
if ( !cfg.Enabled_in_ns(ttl.Ns().Id()) // chk if ns allows banner
|| Bry_.Eq(ttl.Page_db(), wiki.Props().Main_page())) // never show on main page
return;
Bry_bfr tmp_bfr = Bry_bfr.new_();
boolean bottomtoc = false, toc = false;
byte[] tooltip = ttl.Page_txt();
byte[] title = ttl.Page_txt();
int args_len = self.Args_len();
List_adp icons_list = null;
for (int i = 0; i < args_len; ++i) {
Arg_nde_tkn arg = self.Args_get_by_idx(i);
byte[] key = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Key_tkn());
byte[] val = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Val_tkn());
int tid = arg_hash.Get_as_int_or(key, -1);
if (tid == Arg__pgname)
tooltip = title = val;
if (tid == Arg__tooltip) // note that this overrides pgname above
tooltip = val;
if (tid == Arg__bottomtoc && Bry_.Eq(val, Bry__yes))
bottomtoc = true;
if (tid == Arg__toc && Bry_.Eq(val, Bry__yes))
toc = true;
if (tid == -1 && Bry_.Has_at_bgn(key, Bry__icon) && Bry_.Len_gt_0(val)) {
if (icons_list == null) icons_list = List_adp_.new_();
byte[] icon_name = Xop_sanitizer.Escape_cls(val);
byte[] icon_title = icon_name;
Xoa_ttl icon_url_ttl = wiki.Ttl_parse(val);
byte[] icon_url_bry = Bry_.Empty;
if (icon_url_ttl == null) icon_url_bry = Bry__url_dflt;
else {
icon_url_bry = Bry_.Empty;// $iconUrl->getLocalUrl();
icon_title = ttl.Page_txt();
}
icons_list.Add(new Pgbnr_icon(icon_name, icon_title, icon_url_bry));
tid = Arg__icon;
}
if (tid == -1) Gfo_usr_dlg_.Instance.Warn_many("", "", "unknown arg type; page=~{0} key=~{1} val=~{2}", "page", ctx.Cur_page().Url_bry_safe(), key, val);
// WikidataPageBannerFunctions::addFocus( $paramsForBannerTemplate, $argumentsFromParserFunction );
}
byte[] name = Eval_argx(ctx, src, caller, self);
if (Bry_.Len_eq_0(name))
name = cfg.Default_file();
Xoa_ttl file_ttl = wiki.Ttl_parse(name);
Pgbnr_itm itm = new Pgbnr_itm(name, tooltip, title, bottomtoc, toc, file_ttl, icons_list == null ? Pgbnr_icon.Ary_empty : (Pgbnr_icon[])icons_list.To_ary_and_clear(Pgbnr_icon.class));
Tfds.Write(itm);
}
private static final byte[] Bry__yes = Bry_.new_a7("yes"), Bry__icon = Bry_.new_a7("icon-"), Bry__url_dflt = Bry_.new_a7("#");
private static final int Arg__pgname = 0, Arg__tooltip = 1, Arg__bottomtoc = 2, Arg__toc = 3, Arg__icon = 4;
private static final Hash_adp_bry arg_hash = Hash_adp_bry.cs().Add_str_int("pgname", Arg__pgname)
.Add_str_int("tooltip", Arg__tooltip).Add_str_int("bottomtoc", Arg__bottomtoc).Add_str_int("toc", Arg__toc);
}

View File

@@ -16,10 +16,10 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Pb_xtn extends Xox_mgr_base implements GfoInvkAble {
@Override public boolean Enabled_default() {return true;}
@Override public byte[] Xtn_key() {return Xtn_key_static;} public static final byte[] Xtn_key_static = Bry_.new_a7("graph");
@Override public Xox_mgr Clone_new() {return new Pb_xtn();}
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {}
public void Xtn_init_assert(Xowe_wiki wiki) {}
import org.junit.*; import gplx.xowa.wikis.pages.skins.*;
public class Pgbnr_func_tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_html_full_str("{{PAGEBANNER}}", "");
}
}

View File

@@ -238,6 +238,7 @@ public class Pf_func_ {
, Xol_kwd_grp_.Id_pagesUsingPendingChanges
, Xol_kwd_grp_.Id_bang
, Xol_kwd_grp_.Id_rev_revisionsize
, Xol_kwd_grp_.Id_pagebanner
};
public static Xot_defn Get_prototype(int id) {
switch (id) {
@@ -387,6 +388,7 @@ public class Pf_func_ {
case Xol_kwd_grp_.Id_lst: return gplx.xowa.xtns.lst.Lst_pfunc_lst.Instance;
case Xol_kwd_grp_.Id_lstx: return gplx.xowa.xtns.lst.Lst_pfunc_lstx.Instance;
case Xol_kwd_grp_.Id_invoke: return new gplx.xowa.xtns.scribunto.Scrib_invoke_func();
case Xol_kwd_grp_.Id_pagebanner: return new gplx.xowa.xtns.pagebanners.Pgbnr_func();
case Xol_kwd_grp_.Id_property: return new gplx.xowa.xtns.wdatas.pfuncs.Wdata_pf_property();
case Xol_kwd_grp_.Id_noexternallanglinks: return new gplx.xowa.xtns.wdatas.pfuncs.Wdata_pf_noExternalLangLinks();

View File

@@ -59,28 +59,5 @@ public class Pfunc_pagesincategory extends Pf_func_base {
byte[] rslt = fmt_num ? lang.Num_mgr().Format_num(num_bry) : lang.Num_mgr().Raw(num_bry);
bfr.Add(rslt);
}
public void Func_evaluate_old(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] ctg_ttl_bry = Eval_argx(ctx, src, caller, self); if (Bry_.Len_eq_0(ctg_ttl_bry)) {bfr.Add_int_digits(1, 0); return;} // no title; return 0; EX: "{{PAGESINCATEGORY:}}"
ctg_ttl_bry = Xoa_ttl.Replace_spaces(ctg_ttl_bry);
Xowe_wiki wiki = ctx.Wiki();
int ctg_len = wiki.Db_mgr().Load_mgr().Load_ctg_count(ctg_ttl_bry);
if (ctg_len == 0) {bfr.Add_int_digits(1, 0); return;}
Xol_lang_itm lang = wiki.Lang();
Btrie_slim_mgr num_format_trie = Xol_kwd_mgr.trie_(lang.Kwd_mgr(), Xol_kwd_grp_.Id_str_rawsuffix);
// Btrie_slim_mgr type_page_trie = Xol_kwd_mgr.trie_(lang.Kwd_mgr(), Xol_kwd_grp_.Id_pagesincategory_pages);
// Btrie_slim_mgr type_subc_trie = Xol_kwd_mgr.trie_(lang.Kwd_mgr(), Xol_kwd_grp_.Id_pagesincategory_subcats);
// Btrie_slim_mgr type_file_trie = Xol_kwd_mgr.trie_(lang.Kwd_mgr(), Xol_kwd_grp_.Id_pagesincategory_files);
int self_args_len = self.Args_len();
boolean fmt_num = true;
if (self_args_len == 1) {
byte[] arg1 = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
if (arg1 != Bry_.Empty && num_format_trie.Match_exact(arg1, 0, arg1.length) != null)
fmt_num = false;
}
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b128().Mkr_rls();
byte[] ctg_len_bry = tmp_bfr.Add_int_variable(ctg_len).To_bry_and_clear();
byte[] rslt = fmt_num ? lang.Num_mgr().Format_num(ctg_len_bry) : lang.Num_mgr().Raw(ctg_len_bry);
bfr.Add(rslt);
}
public static final Pfunc_pagesincategory Instance = new Pfunc_pagesincategory(); Pfunc_pagesincategory() {}
}

View File

@@ -46,6 +46,7 @@ public class Scrib_core {
@gplx.Internal protected void Wiki_(Xowe_wiki v) {this.wiki = v;} // TEST:
public Xoae_page Page() {return page;} private Xoae_page page;
public boolean Enabled() {return enabled;} private boolean enabled = true;
public void Engine_(Scrib_engine v) {this.engine = v;}
private void Engine_(byte type, boolean luaj_debug_enabled) {
if (type == Scrib_engine_type.Type_lua)
engine = new gplx.xowa.xtns.scribunto.engines.process.Process_engine(app, this);

View File

@@ -26,7 +26,7 @@ public class Scrib_err_filter_mgr implements GfoInvkAble {
boolean match = false;
for (int i = 0; i < itms_len; ++i) {
Scrib_err_filter_itm itm = (Scrib_err_filter_itm)itms.Get_at(i);
if (String_.Has_at_bgn(err, itm.Err())) {
if (String_.Has(err, itm.Err())) {
match = true;
itm.Count_actl_add_1();
break;

View File

@@ -124,14 +124,28 @@ public class Scrib_invoke_func_fxt {
}
public void Test_scrib_proc_str(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test_scrib_proc_str(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test_scrib_proc_str(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, args);
KeyVal[] actl = Test__lib_proc__core(lib, proc_name, args);
Tfds.Eq(Object_.Xto_str_strict_or_null_mark(expd), Object_.Xto_str_strict_or_null_mark(actl[0].Val()));
}
public void Test_scrib_proc_kv_vals(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test_scrib_proc_kv_vals(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test_scrib_proc_kv_vals(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {
KeyVal[] actl_ary = Test_scrib_proc_rv(lib, proc_name, args);
public void Test__proc__kvps__flat(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test__proc__kvps__flat(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test__proc__kvps__flat(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {
KeyVal[] actl_ary = Test__lib_proc__core(lib, proc_name, args);
Tfds.Eq(expd, Kv_ary_to_kv_vals_str(actl_ary));
}
public void Test_scrib_proc_kv_objs(Scrib_lib lib, String proc_name, KeyVal[] args, Object... expd_ary) {
KeyVal[] actl_kvs = Test__lib_proc__core(lib, proc_name, args);
Object[] actl_ary = KeyVal_to_obj_ary(actl_kvs);
Tfds.Eq_ary(expd_ary, actl_ary);
}
private static Object[] KeyVal_to_obj_ary(KeyVal[] kv_ary) {
int len = kv_ary.length;
Object[] rv = new Object[len];
for (int i = 0; i < len; ++i) {
KeyVal kv = kv_ary[i];
rv[i] = kv.Val();
}
return rv;
}
private String Kv_ary_to_kv_vals_str(KeyVal[] ary) {
Bry_bfr bfr = Bry_bfr.new_();
int len = ary.length;
@@ -146,29 +160,29 @@ public class Scrib_invoke_func_fxt {
public void Test_scrib_proc_int(Scrib_lib lib, String proc_name, Object[] args, int expd) {Test_scrib_proc_obj(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test_scrib_proc_obj(Scrib_lib lib, String proc_name, Object[] args, Object expd) {Test_scrib_proc_obj(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test_scrib_proc_obj(Scrib_lib lib, String proc_name, KeyVal[] args, Object expd) {
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, args);
KeyVal[] actl = Test__lib_proc__core(lib, proc_name, args);
Tfds.Eq(expd, actl[0].Val());
}
public void Test_scrib_proc_empty(Scrib_lib lib, String proc_name, Object[] args) {Test_scrib_proc_empty(lib, proc_name, Scrib_kv_utl_.base1_many_(args));}
public void Test_scrib_proc_empty(Scrib_lib lib, String proc_name, KeyVal[] args) {
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, args);
KeyVal[] actl = Test__lib_proc__core(lib, proc_name, args);
Tfds.Eq(0, actl.length);
}
public void Test_scrib_proc_str_ary(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test_scrib_proc_str_ary(lib, proc_name, Scrib_kv_utl_.base1_many_(args), expd);}
public void Test_scrib_proc_str_ary(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {
KeyVal[] actl_ary = Test_scrib_proc_rv(lib, proc_name, args);
String actl = KeyVal_.Ary_to_str_nested(actl_ary);
KeyVal[] actl_ary = Test__lib_proc__core(lib, proc_name, args);
String actl = KeyVal_.Ary__to_str__nest(actl_ary);
Tfds.Eq_str_lines(expd, actl);
}
public KeyVal[] Test_scrib_proc_rv_as_kv_ary(Scrib_lib lib, String proc_name, Object[] args) {
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
KeyVal[] actl = Test__lib_proc__core(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
return (KeyVal[])actl[0].Val();
}
public Object Test_scrib_proc_rv_as_obj(Scrib_lib lib, String proc_name, Object[] args) {
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
KeyVal[] actl = Test__lib_proc__core(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
return actl[0].Val();
}
private KeyVal[] Test_scrib_proc_rv(Scrib_lib lib, String proc_name, KeyVal[] args) {
private KeyVal[] Test__lib_proc__core(Scrib_lib lib, String proc_name, KeyVal[] args) {
Scrib_proc proc = lib.Procs().Get_by_key(proc_name);
Scrib_proc_rslt proc_rslt = new Scrib_proc_rslt();
proc.Proc_exec(new Scrib_proc_args(args), proc_rslt);

View File

@@ -17,11 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.engines; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
public interface Scrib_engine {
boolean Dbg_print(); void Dbg_print_(boolean v);
Scrib_server Server(); void Server_(Scrib_server v);
Scrib_lua_proc LoadString(String name, String text);
KeyVal[] CallFunction(int id, KeyVal[] args);
void RegisterLibrary(KeyVal[] functions_ary);
KeyVal[] ExecuteModule(int mod_id);
void CleanupChunks(KeyVal[] ids);
boolean Dbg_print(); void Dbg_print_(boolean v);
Scrib_server Server(); void Server_(Scrib_server v);
Scrib_lua_proc LoadString(String name, String text);
KeyVal[] CallFunction(int id, KeyVal[] args);
void RegisterLibrary(KeyVal[] functions_ary);
KeyVal[] ExecuteModule(int mod_id);
void CleanupChunks(KeyVal[] ids);
}

View File

@@ -17,12 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.engines; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
public interface Scrib_server {
void Init(String... process_args);
int Server_timeout(); Scrib_server Server_timeout_(int v);
int Server_timeout_polling(); Scrib_server Server_timeout_polling_(int v);
int Server_timeout_busy_wait(); Scrib_server Server_timeout_busy_wait_(int v);
byte[] Server_comm(byte[] cmd, Object[] cmd_objs);
void Server_send(byte[] cmd, Object[] cmd_objs);
byte[] Server_recv();
void Term();
void Init(String... process_args);
int Server_timeout(); Scrib_server Server_timeout_(int v);
int Server_timeout_polling(); Scrib_server Server_timeout_polling_(int v);
int Server_timeout_busy_wait(); Scrib_server Server_timeout_busy_wait_(int v);
byte[] Server_comm(byte[] cmd, Object[] cmd_objs);
void Server_send(byte[] cmd, Object[] cmd_objs);
byte[] Server_recv();
void Term();
}

View File

@@ -0,0 +1,44 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.engines.mocks; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.scribunto.engines.*;
import gplx.core.primitives.*;
public abstract class Mock_proc_fxt {
public Mock_proc_fxt(int id, String key) {this.id = id; this.key = key;}
public int Id() {return id;} private final int id;
public String Key() {return key;} private final String key;
public Scrib_lua_proc To_scrib_lua_proc() {return new Scrib_lua_proc(key, id);}
public abstract KeyVal[] Exec_by_scrib(KeyVal[] args);
}
class Mock_engine implements Scrib_engine {
private final Hash_adp hash = Hash_adp_.new_();
private final Int_obj_ref tmp_hash_id = Int_obj_ref.neg1_();
public boolean Dbg_print() {return false;} public void Dbg_print_(boolean v) {}
public Scrib_server Server() {return server;} public void Server_(Scrib_server v) {} private final Mock_server server = new Mock_server();
public Scrib_lua_proc LoadString(String name, String text) {return null;}
public KeyVal[] CallFunction(int id, KeyVal[] args) {
Mock_proc_fxt proc = (Mock_proc_fxt)hash.Get_by_or_fail(tmp_hash_id.Val_(id));
return proc.Exec_by_scrib(args);
}
public void RegisterLibrary(KeyVal[] functions_ary) {}
public KeyVal[] ExecuteModule(int mod_id) {return null;}
public void CleanupChunks(KeyVal[] ids) {}
public void Clear() {}
public void RegisterLibraryForTest(Mock_proc_fxt proc) {
hash.Add(Int_obj_ref.new_(proc.Id()), proc);
}
}

View File

@@ -0,0 +1,97 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.engines.mocks; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.scribunto.engines.*;
import gplx.xowa.parsers.tmpls.*;
public class Mock_scrib_fxt {
private final Mock_engine engine = new Mock_engine();
private final Mock_server server = new Mock_server();
private Xop_fxt parser_fxt;
public Scrib_core Core() {return core;} private Scrib_core core;
public void Clear() {Clear("en.wikipedia.org", "en");}
public void Clear(String domain, String lang) {
Xoae_app app = Xoa_app_fxt.app_();
Xowe_wiki wiki = Xoa_app_fxt.wiki_(app, domain, app.Lang_mgr().Get_by_or_new(Bry_.new_u8(lang)));
parser_fxt = new Xop_fxt(app, wiki); // NOTE: always new(); don't try to cache; causes errors in Language_lib
core = Scrib_core.Core_new_(app, wiki.Parser_mgr().Ctx());
core.Engine_(engine); engine.Clear();
core.Interpreter().Server_(server);
Xot_invk parent_frame = new Xot_invk_temp(true); parent_frame.Frame_tid_(Scrib_frame_.Tid_null);
Xot_invk current_frame = Xot_invk_mock.test_(Bry_.new_a7("Module:Mod_0"));
core.Invoke_init(core.Wiki(), core.Ctx(), Bry_.Empty, parent_frame, current_frame);
core.When_page_changed(parser_fxt.Page());
}
public void Init__cbk(Mock_proc_fxt... ary) {
for (Mock_proc_fxt proc : ary)
engine.RegisterLibraryForTest(proc);
}
public void Test__proc__objs__flat(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test__proc__kvps(lib, proc_name, expd, Bool_.Y, Scrib_kv_utl_.base1_many_(args));}
public void Test__proc__objs__nest(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test__proc__kvps(lib, proc_name, expd, Bool_.N, Scrib_kv_utl_.base1_many_(args));}
public void Test__proc__kvps__flat(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {Test__proc__kvps(lib, proc_name, expd, Bool_.Y, args);}
public void Test__proc__kvps__nest(Scrib_lib lib, String proc_name, KeyVal[] args, String expd) {Test__proc__kvps(lib, proc_name, expd, Bool_.N, args);}
private static void Test__proc__kvps(Scrib_lib lib, String proc_name, String expd, boolean flat, KeyVal[] args) {
KeyVal[] actl_ary = Mock_scrib_fxt_.Test__lib_proc__core(lib, proc_name, args);
if (flat)
Tfds.Eq(expd, Mock_scrib_fxt_.Kvp_vals_to_str(actl_ary));
else
Tfds.Eq_str_lines(expd, KeyVal_.Ary__to_str__nest(actl_ary));
}
public void Test__proc__objs__empty(Scrib_lib lib, String proc_name, Object[] args) {Test__proc__kvps__empty(lib, proc_name, Scrib_kv_utl_.base1_many_(args));}
public void Test__proc__kvps__empty(Scrib_lib lib, String proc_name, KeyVal[] args) {
Tfds.Eq(0, Mock_scrib_fxt_.Test__lib_proc__core(lib, proc_name, args).length);
}
public void Test__proc__kvps__vals(Scrib_lib lib, String proc_name, KeyVal[] args, Object... expd_ary) {
KeyVal[] actl_kvs = Mock_scrib_fxt_.Test__lib_proc__core(lib, proc_name, args);
Object[] actl_ary = Mock_scrib_fxt_.Kvp_vals_to_objs(actl_kvs);
Tfds.Eq_ary(expd_ary, actl_ary);
}
}
class Mock_scrib_fxt_ {
public static KeyVal[] Test__lib_proc__core(Scrib_lib lib, String proc_name, KeyVal[] args) {
Scrib_proc proc = lib.Procs().Get_by_key(proc_name);
Scrib_proc_rslt proc_rslt = new Scrib_proc_rslt();
proc.Proc_exec(new Scrib_proc_args(args), proc_rslt);
return proc_rslt.Ary();
}
public static Object[] Kvp_vals_to_objs(KeyVal[] kvps) {
int len = kvps.length;
Object[] rv = new Object[len];
for (int i = 0; i < len; ++i)
rv[i] = kvps[i].Val();
return rv;
}
public static String Kvp_vals_to_str(KeyVal[] ary) {
Bry_bfr bfr = Bry_bfr.new_();
int len = ary.length;
for (int i = 0; i < len; ++i) {
if (i != 0) bfr.Add_byte(Byte_ascii.Semic);
KeyVal kv = ary[i];
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(kv.Val()));
}
return bfr.To_str_and_clear();
}
}
class Mock_server implements Scrib_server {
public void Init(String... process_args) {}
public int Server_timeout() {return server_timeout;} public Scrib_server Server_timeout_(int v) {server_timeout = v; return this;} private int server_timeout = 60;
public int Server_timeout_polling() {return server_timeout_polling;} public Scrib_server Server_timeout_polling_(int v) {server_timeout_polling = v; return this;} private int server_timeout_polling = 1;
public int Server_timeout_busy_wait() {return server_timeout_busy_wait;} public Scrib_server Server_timeout_busy_wait_(int v) {server_timeout_busy_wait = v; return this;} private int server_timeout_busy_wait = 1;
public byte[] Server_comm(byte[] cmd, Object[] cmd_objs) {return Bry_.Empty;}
public void Server_send(byte[] cmd, Object[] cmd_objs) {}
public byte[] Server_recv() {return Bry_.Empty;}
public void Term() {}
}

View File

@@ -73,7 +73,7 @@ class Gfo_comp_op_lt implements Gfo_comp_op_1 {
public boolean Comp_double(double val, double comp) {return val < comp;}
public boolean Comp_decimal(Decimal_adp val, Decimal_adp comp) {return val.Comp_lt(comp);}
public boolean Comp_char(char val, char comp) {return val < comp;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) < CompareAble_.Same;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) == CompareAble_.Same;}
public boolean Comp_bry(byte[] val, byte[] comp) {return Bry_.Compare(val, comp) < CompareAble_.Same;}
public boolean Comp_date(DateAdp val, DateAdp comp) {return val.compareTo(comp) < CompareAble_.Same;}
public boolean Comp_url(Io_url val, Io_url comp) {return val.compareTo(comp) < CompareAble_.Same;}
@@ -89,7 +89,7 @@ class Gfo_comp_op_lte implements Gfo_comp_op_1 {
public boolean Comp_double(double val, double comp) {return val <= comp;}
public boolean Comp_decimal(Decimal_adp val, Decimal_adp comp) {return val.Comp_lte(comp);}
public boolean Comp_char(char val, char comp) {return val <= comp;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) <= CompareAble_.Same;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) != CompareAble_.More;}
public boolean Comp_bry(byte[] val, byte[] comp) {return Bry_.Compare(val, comp) <= CompareAble_.Same;}
public boolean Comp_date(DateAdp val, DateAdp comp) {return val.compareTo(comp) <= CompareAble_.Same;}
public boolean Comp_url(Io_url val, Io_url comp) {return val.compareTo(comp) <= CompareAble_.Same;}
@@ -105,7 +105,7 @@ class Gfo_comp_op_mt implements Gfo_comp_op_1 {
public boolean Comp_double(double val, double comp) {return val > comp;}
public boolean Comp_decimal(Decimal_adp val, Decimal_adp comp) {return val.Comp_lt(comp);}
public boolean Comp_char(char val, char comp) {return val > comp;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) > CompareAble_.Same;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) == CompareAble_.More;}
public boolean Comp_bry(byte[] val, byte[] comp) {return Bry_.Compare(val, comp) > CompareAble_.Same;}
public boolean Comp_date(DateAdp val, DateAdp comp) {return val.compareTo(comp) > CompareAble_.Same;}
public boolean Comp_url(Io_url val, Io_url comp) {return val.compareTo(comp) > CompareAble_.Same;}
@@ -121,7 +121,7 @@ class Gfo_comp_op_mte implements Gfo_comp_op_1 {
public boolean Comp_double(double val, double comp) {return val >= comp;}
public boolean Comp_decimal(Decimal_adp val, Decimal_adp comp) {return val.Comp_lte(comp);}
public boolean Comp_char(char val, char comp) {return val >= comp;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) >= CompareAble_.Same;}
public boolean Comp_str(String val, String comp) {return String_.Compare(val, comp) != CompareAble_.Less;}
public boolean Comp_bry(byte[] val, byte[] comp) {return Bry_.Compare(val, comp) >= CompareAble_.Same;}
public boolean Comp_date(DateAdp val, DateAdp comp) {return val.compareTo(comp) >= CompareAble_.Same;}
public boolean Comp_url(Io_url val, Io_url comp) {return val.compareTo(comp) >= CompareAble_.Same;}

View File

@@ -20,7 +20,7 @@ import gplx.langs.regxs.*; import gplx.core.intls.*;
import gplx.xowa.parsers.*;
public class Scrib_lib_ustring implements Scrib_lib {
private final String_surrogate_utl surrogate_utl = new String_surrogate_utl();
public Scrib_lib_ustring(Scrib_core core) {this.core = core; gsub_mgr = new Scrib_lib_ustring_gsub_mgr(core, regx_converter);} private Scrib_core core; Scrib_lib_ustring_gsub_mgr gsub_mgr;
public Scrib_lib_ustring(Scrib_core core) {this.core = core;} private Scrib_core core;
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
public int String_len_max() {return string_len_max;} public Scrib_lib_ustring String_len_max_(int v) {string_len_max = v; return this;} private int string_len_max = Xoa_page_.Page_len_max;
public int Pattern_len_max() {return pattern_len_max;} public Scrib_lib_ustring Pattern_len_max_(int v) {pattern_len_max = v; return this;} private int pattern_len_max = 10000;
@@ -112,7 +112,30 @@ public class Scrib_lib_ustring implements Scrib_lib {
}
return rslt.Init_many_list(tmp_list);
}
public boolean Gsub(Scrib_proc_args args, Scrib_proc_rslt rslt) {return gsub_mgr.Exec(args, rslt);}
private Scrib_lib_ustring_gsub_mgr[] gsub_mgr_ary = Scrib_lib_ustring_gsub_mgr.Ary_empty;
private int gsub_mgr_max = 0, gsub_mgr_len = -1;
private final Object gsub_mgr_lock = new Object();
public boolean Gsub(Scrib_proc_args args, Scrib_proc_rslt rslt) {
boolean rv = false;
synchronized (gsub_mgr_lock) { // handle recursive gsub calls; PAGE:en.d:כלב; DATE:2016-01-22
int new_len = gsub_mgr_len + 1;
if (new_len == gsub_mgr_max) {
this.gsub_mgr_max = new_len == 0 ? 2 : new_len * 2;
Scrib_lib_ustring_gsub_mgr[] new_gsub_mgr_ary = new Scrib_lib_ustring_gsub_mgr[gsub_mgr_max];
Array_.Copy(gsub_mgr_ary, new_gsub_mgr_ary);
gsub_mgr_ary = new_gsub_mgr_ary;
}
Scrib_lib_ustring_gsub_mgr cur = gsub_mgr_ary[new_len];
if (cur == null) {
cur = new Scrib_lib_ustring_gsub_mgr(core, regx_converter);
gsub_mgr_ary[new_len] = cur;
}
this.gsub_mgr_len = new_len;
rv = cur.Exec(args, rslt);
--gsub_mgr_len;
}
return rv;
}
public boolean Gmatch_init(Scrib_proc_args args, Scrib_proc_rslt rslt) {
// String text = Scrib_kv_utl_.Val_to_str(values, 0);
byte[] regx = args.Pull_bry(1);
@@ -143,7 +166,7 @@ public class Scrib_lib_ustring implements Scrib_lib {
if ( j < capts_len // bounds check b/c null can be passed
&& Bool_.cast(capts[j].Val()) // check if true; indicates that group is "()" or "anypos" see regex converter; DATE:2014-04-23
)
tmp_list.Add(Int_.To_str(grp.Bgn() + Scrib_lib_ustring.Base1)); // return index only for (); NOTE: always return as String; callers expect String, and may do operations like len(result), which will fail if int; DATE:2013-12-20
tmp_list.Add(grp.Bgn() + Scrib_lib_ustring.Base1); // return index only for "()"; NOTE: do not return as String; callers expect int and will fail typed comparisons; DATE:2016-01-21
else
tmp_list.Add(grp.Val()); // return match
}
@@ -325,5 +348,6 @@ class Scrib_lib_ustring_gsub_mgr {
default: throw Err_.new_unhandled(repl_tid);
}
}
static final byte Repl_tid_null = 0, Repl_tid_string = 1, Repl_tid_table = 2, Repl_tid_luacbk = 3;
private static final byte Repl_tid_null = 0, Repl_tid_string = 1, Repl_tid_table = 2, Repl_tid_luacbk = 3;
public static final Scrib_lib_ustring_gsub_mgr[] Ary_empty = new Scrib_lib_ustring_gsub_mgr[0];
}

View File

@@ -0,0 +1,50 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*; import gplx.xowa.xtns.scribunto.engines.mocks.*;
public class Scrib_lib_ustring__find__tst {
private final Mock_scrib_fxt fxt = new Mock_scrib_fxt(); private Scrib_lib lib;
@Before public void init() {
fxt.Clear();
lib = fxt.Core().Lib_ustring().Init();
}
@Test public void Basic() {
Exec_find("abcd" , "b" , 1, Bool_.N, "2;2"); // basic
Exec_find("abac" , "a" , 2, Bool_.N, "3;3"); // bgn
Exec_find("()()" , "(" , 2, Bool_.Y, "3;3"); // plain; note that ( would "break" regx
Exec_find("a bcd e" , "(b(c)d)" , 2, Bool_.N, "3;5;bcd;c"); // groups
Exec_find("a bcd e" , "()(b)" , 2, Bool_.N, "3;3;3;b"); // groups; empty capture
Exec_find("abcd" , "x" , 1, Bool_.N, ""); // empty
Exec_find("abcd" , "" , 2, Bool_.Y, "2;1"); // empty regx should return values; plain; EX:w:Fool's_mate; DATE:2014-03-04
Exec_find("abcd" , "" , 2, Bool_.N, "2;1"); // empty regx should return values; regx; EX:w:Fool's_mate; DATE:2014-03-04
Exec_find("abcd" , "^(c)" , 3, Bool_.N, "3;3;c"); // ^ should be converted to \G; regx; EX:cs.n:Category:1._září_2008; DATE:2014-05-07
}
@Test public void Arg_int() { // PURPOSE: allow int find; PAGE:ro.w:Innsbruck DATE:2015-09-12
fxt.Test__proc__kvps__flat(lib, Scrib_lib_ustring.Invk_find, Scrib_kv_utl_.base1_many_(123, "2", 1, Bool_.N), "2;2");
}
@Test public void Return_int() {
fxt.Test__proc__kvps__vals(lib, Scrib_lib_ustring.Invk_find, Scrib_kv_utl_.base1_many_("a", "()", 2, Bool_.N), 2, 1, 2);
}
@Test public void Surrogate() { // PURPOSE: handle surrogates in Find PAGE:zh.w:南北鐵路_(越南); DATE:2014-08-28
Exec_find("aé𡼾\nbî𡼾\n" , "\n" , 1, Bool_.N, "4;4"); // 4 b/c \n starts at pos 4 (super 1)
Exec_find("aé𡼾\nbî𡼾\n" , "\n" , 5, Bool_.N, "8;8"); // 8 b/c \n starts at pos 8 (super 1)
}
private void Exec_find(String text, String regx, int bgn, boolean plain, String expd) {
fxt.Test__proc__kvps__flat(lib, Scrib_lib_ustring.Invk_find, Scrib_kv_utl_.base1_many_(text, regx, bgn, plain), expd);
}
}

View File

@@ -0,0 +1,53 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*; import gplx.xowa.xtns.scribunto.engines.mocks.*;
public class Scrib_lib_ustring__gmatch__tst {
private final Mock_scrib_fxt fxt = new Mock_scrib_fxt(); private Scrib_lib lib;
@Before public void init() {
fxt.Clear();
lib = fxt.Core().Lib_ustring().Init();
}
@Test public void Init__basic() {
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_init, Object_.Ary("abcabc", "a(b)") , "1=a(b)\n2=\n 1=false");
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_init, Object_.Ary("abcabc", "a()(b)") , "1=a()(b)\n2=\n 1=true\n 2=false");
}
@Test public void Callback__basic() {
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 0) , "1=2\n2=\n 1=b");
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 2) , "1=5\n2=\n 1=b");
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 8) , "1=8\n2=");
}
@Test public void Callback__nomatch() {// PURPOSE.fix: was originally returning "" instead of original String; EX:vi.d:trở_thành; DATE:2014-04-23
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("a", "a" , KeyVal_.Ary_empty, 0) , "1=1\n2=\n 1=a");
}
@Test public void Callback__anypos() {// PURPOSE.fix: was not handling $capt argument; EX:vi.d:trở_thành; DATE:2014-04-23
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("a bcd e", "()(b)" , Scrib_kv_utl_.base1_many_(true, false), 0), String_.Concat_lines_nl_skip_last
( "1=3"
, "2="
, " 1=3"
, " 2=b"
));
}
@Test public void Callback__text_as_number() { // PURPOSE: Gmatch_callback must be able to take non String value; DATE:2013-12-20
fxt.Test__proc__objs__nest(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary(1234, "1(2)", Scrib_kv_utl_.base1_many_(false), 0), String_.Concat_lines_nl_skip_last
( "1=2"
, "2="
, " 1=2"
));
}
}

View File

@@ -0,0 +1,101 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*; import gplx.langs.regxs.*; import gplx.xowa.xtns.scribunto.engines.mocks.*;
public class Scrib_lib_ustring__gsub__tst {
private final Mock_scrib_fxt fxt = new Mock_scrib_fxt(); private Scrib_lib lib;
@Before public void init() {
fxt.Clear();
lib = fxt.Core().Lib_ustring().Init();
}
@Test public void Replace__basic() {
Exec_gsub("abcd", "[a]" , -1, "A" , "Abcd;1");
Exec_gsub("aaaa", "[a]" , 2, "A" , "AAaa;2");
Exec_gsub("a" , "(a)" , 1, "%%%1" , "%a;1");
Exec_gsub("à{b}c", "{b}" , 1, "b" , "àbc;1"); // utf8
Exec_gsub("àbc", "^%s*(.-)%s*$" , 1, "%1" , "àbc;1"); // utf8; regx is for trim line
Exec_gsub("a" , "[^]" , 1, "b" , "a;0"); // invalid regx should not fail; should return self; DATE:2013-10-20
}
@Test public void Replace__none() {// PURPOSE: gsub with no replace argument should not fail; EX:d:'orse; DATE:2013-10-14
fxt.Test__proc__objs__flat(lib, Scrib_lib_ustring.Invk_gsub, Object_.Ary("text", "regx") , "text"); // NOTE: repl, limit deliberately omitted
}
@Test public void Replace__int() { // PURPOSE: do not fail if integer is passed in for @replace; PAGE:en.d:λύω DATE:2014-09-02
Exec_gsub("abcd", 1 , -1, 1 , "abcd;0");
}
@Test public void Replace__table() {
Exec_gsub("abcd", "[ac]" , -1, Scrib_kv_utl_.flat_many_("a", "A", "c", "C") , "AbCd;2");
Exec_gsub("abc" , "[ab]" , -1, Scrib_kv_utl_.flat_many_("a", "A") , "Abc;2"); // PURPOSE: match not in regex should still print itself; in this case [c] is not in tbl regex; DATE:2014-03-31
}
@Test public void Replace__table__match() {// PURPOSE: replace using group, not found term; EX:"b" not "%b%" PAGE:en.w:Bannered_routes_of_U.S._Route_60; DATE:2014-08-15
Exec_gsub("a%b%c", "%%(%w+)%%" , -1, Scrib_kv_utl_.flat_many_("b", "B") , "aBc;1");
}
@Test public void Replace__proc__recursive() { // PURPOSE:handle recursive gsub calls; PAGE:en.d:כלב; DATE:2016-01-22
Bry_bfr bfr = Bry_bfr.new_();
Mock_proc__recursive proc_lvl2 = new Mock_proc__recursive(fxt, lib, bfr, 2, null);
Mock_proc__recursive proc_lvl1 = new Mock_proc__recursive(fxt, lib, bfr, 1, proc_lvl2);
Mock_proc__recursive proc_root = new Mock_proc__recursive(fxt, lib, bfr, 0, proc_lvl1);
fxt.Init__cbk(proc_root, proc_lvl1, proc_lvl2);
Exec_gsub("ab", ".", -1, proc_root.To_scrib_lua_proc(), "ab;2"); // fails if "ab;4"
Tfds.Eq_str("0;1;2;0;1;2;", bfr.To_str_and_clear()); // fails if "0;1;1;1"
}
@Test public void Regx__int() { // PURPOSE: do not fail if integer is passed in for @regx; PAGE:en.d:λύω DATE:2014-09-02
Exec_gsub("abcd", 1 , -1, "A" , "abcd;0");
}
@Test public void Regx__dash() { // PURPOSE: "-" at end of regx should be literal; EX:[A-]; PAGE:en.d:frei DATE:2016-01-23
Exec_gsub("abc", "[a-]", -1, "d", "dbc;1");
}
@Test public void Regx__word_class() { // PURPOSE: handle %w in extended regex; PAGE:en.w:A♯_(musical_note) DATE:2015-06-10
Exec_gsub("(a b)", "[^%w%p%s]", -1, "x", "(a b);0"); // was returning "(x x)" b/c ^%w was incorrectly matching "a" and "b"
}
@Test public void Regx__balanced_group() { // PURPOSE: handle balanced group regex; EX:"%b()"; NOTE:test will fail if run in 1.6 environment; DATE:2013-12-20
Exec_gsub("(a)", "%b()", 1, "c", "c;1");
}
@Test public void Regx__capture() {
Exec_gsub("aa" , "(a)%1" , 1, "%0z", "aaz;1"); // capture; handle %0; PAGE:en.w:Wikipedia:Wikipedia_Signpost/Templates/Voter/testcases; DATE:2015-08-02
Exec_gsub("aa" , "(a)%1" , 1, "%1z", "az;1"); // capture; handle %1+; PAGE:en.w:Wikipedia:Wikipedia_Signpost/Templates/Voter/testcases; DATE:2015-08-02
Exec_gsub("a\"b'c\"d" , "([\"'])(.-)%1" , 1, "%1z", "a\"zd;1"); // capture; http://www.lua.org/pil/20.3.html; {{#invoke:test|gsub_string|a"b'c"d|(["'])(.-)%1|%1z}}
}
@Test public void Regx__frontier_pattern() { // PURPOSE: handle frontier pattern; EX:"%f[%a]"; DATE:2015-07-21
Exec_gsub("a b c", "%f[%W]", 5, "()", "a() b() c();3");
Exec_gsub("abC DEF gHI JKm NOP", "%f[%a]%u+%f[%A]", Int_.Max_value, "()", "abC () gHI JKm ();2"); // based on http://lua-users.org/wiki/FrontierPattern
}
@Test public void Regx__frontier_pattern_utl() {// PURPOSE: standalone test for \0 logic in frontier pattern; note that verified against PHP: echo(preg_match( "/[\w]/us", "\0" )); DATE:2015-07-21
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "a")); // \0 not matched by a
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "0")); // \0 not matched by numeric 0
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "[\\w]")); // \0 not matched by word_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\W]")); // \0 matched by !word_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\x]")); // \0 matched by any_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\X]")); // \0 matched by !any_char
}
private void Exec_gsub(String text, Object regx, int limit, Object repl, String expd) {
fxt.Test__proc__kvps__flat(lib, Scrib_lib_ustring.Invk_gsub, Scrib_kv_utl_.base1_many_(text, regx, repl, limit), expd);
}
}
class Mock_proc__recursive extends Mock_proc_fxt { private final Mock_scrib_fxt fxt; private final Scrib_lib lib; private final Mock_proc__recursive inner;
private final Bry_bfr bfr;
public Mock_proc__recursive(Mock_scrib_fxt fxt, Scrib_lib lib, Bry_bfr bfr, int id, Mock_proc__recursive inner) {super(id, "recur");
this.fxt = fxt; this.lib = lib; this.inner = inner;
this.bfr = bfr;
}
@Override public KeyVal[] Exec_by_scrib(KeyVal[] args) {
bfr.Add_int_variable(this.Id()).Add_byte_semic();
if (inner != null)
fxt.Test__proc__kvps__flat(lib, Scrib_lib_ustring.Invk_gsub, Scrib_kv_utl_.base1_many_("a", ".", inner.To_scrib_lua_proc(), -1), "a;1");
return args;
}
}

View File

@@ -1,151 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*; import gplx.langs.regxs.*;
public class Scrib_lib_ustring__lib_tst {
@Before public void init() {
fxt.Clear_for_lib();
lib = fxt.Core().Lib_ustring().Init();
} private Scrib_invoke_func_fxt fxt = new Scrib_invoke_func_fxt(); private Scrib_lib lib;
@Test public void Find() {
Exec_find("abcd" , "b" , 1, Bool_.N, "2;2"); // basic
Exec_find("abac" , "a" , 2, Bool_.N, "3;3"); // bgn
Exec_find("()()" , "(" , 2, Bool_.Y, "3;3"); // plain; note that ( would "break" regx
Exec_find("a bcd e" , "(b(c)d)" , 2, Bool_.N, "3;5;bcd;c"); // groups
Exec_find("a bcd e" , "()(b)" , 2, Bool_.N, "3;3;3;b"); // groups; empty capture
Exec_find("abcd" , "x" , 1, Bool_.N, ""); // empty
Exec_find("abcd" , "" , 2, Bool_.Y, "2;1"); // empty regx should return values; plain; EX:w:Fool's_mate; DATE:2014-03-04
Exec_find("abcd" , "" , 2, Bool_.N, "2;1"); // empty regx should return values; regx; EX:w:Fool's_mate; DATE:2014-03-04
Exec_find("abcd" , "^(c)" , 3, Bool_.N, "3;3;c"); // ^ should be converted to \G; regx; EX:cs.n:Category:1._září_2008; DATE:2014-05-07
}
@Test public void Find_int() { // PURPOSE: allow int find; PAGE:ro.w:Innsbruck DATE:2015-09-12
fxt.Test_scrib_proc_kv_vals(lib, Scrib_lib_ustring.Invk_find, Scrib_kv_utl_.base1_many_(123, "2", 1, Bool_.N), "2;2");
}
@Test public void Find_surrogate() { // PURPOSE: handle surrogates in Find PAGE:zh.w:南北鐵路_(越南); DATE:2014-08-28
Exec_find("aé𡼾\nbî𡼾\n" , "\n" , 1, Bool_.N, "4;4"); // 4 b/c \n starts at pos 4 (super 1)
Exec_find("aé𡼾\nbî𡼾\n" , "\n" , 5, Bool_.N, "8;8"); // 8 b/c \n starts at pos 8 (super 1)
}
@Test public void Match() {
Exec_match("abcd" , "bc" , 1, "bc"); // basic
Exec_match("abcd" , "x" , 1, String_.Null_mark); // empty
Exec_match("abcd" , "a" , 2, String_.Null_mark); // bgn
Exec_match("abcd" , "b(c)" , 1, "c"); // group
Exec_match(" a b " , "^%s*(.-)%s*$" , 1, "a b;"); // trim; NOTE: changed from "a b" to "a b;"; DATE:2015-01-30
Exec_match("abcd" , "a" , 0, "a"); // handle 0; note that php/lua is super-1, but some modules pass in 0; ru.w:Module:Infocards; DATE:2013-11-08
Exec_match("abcd" , "." , -1, "d"); // -1
Exec_match("aaa" , "a" , 1, "a"); // should return 1st match not many
Exec_match("aaa" , "(a)" , 1, "a;a;a"); // should return all matches
Exec_match("a b" , "%S" , 1, "a"); // %S was returning every match instead of 1st; PAGE:en.w:Bertrand_Russell; DATE:2014-04-02
Exec_match(1 , "a" , 1, String_.Null_mark); // Module can pass raw ints; PAGE:en.w:Budget_of_the_European_Union; DATE:2015-01-22
Exec_match("" , "a?" , 1, ""); // no results with ? should return "" not nil; PAGE:en.d:民; DATE:2015-01-30
}
@Test public void Match_args_out_of_order() {
fxt.Test_scrib_proc_empty(lib, Scrib_lib_ustring.Invk_match, KeyVal_.Ary(KeyVal_.int_(2, "[a]")));
}
@Test public void Gsub() {
Exec_gsub_regx("abcd", "[a]" , -1, "A" , "Abcd;1");
Exec_gsub_regx("aaaa", "[a]" , 2, "A" , "AAaa;2");
Exec_gsub_regx("a" , "(a)" , 1, "%%%1" , "%a;1");
Exec_gsub_regx("à{b}c", "{b}" , 1, "b" , "àbc;1"); // utf8
Exec_gsub_regx("àbc", "^%s*(.-)%s*$", 1, "%1" , "àbc;1"); // utf8; regx is for trim line
Exec_gsub_regx("a" , "[^]" , 1, "b" , "a;0"); // invalid regx should not fail; should return self; DATE:2013-10-20
}
@Test public void Gsub_table() {
Exec_gsub_regx("abcd", "[ac]" , -1, Scrib_kv_utl_.flat_many_("a", "A", "c", "C") , "AbCd;2");
Exec_gsub_regx("abc" , "[ab]" , -1, Scrib_kv_utl_.flat_many_("a", "A") , "Abc;2"); // PURPOSE: match not in regex should still print itself; in this case [c] is not in tbl regex; DATE:2014-03-31
}
@Test public void Gsub_table_match() { // PURPOSE: replace using group, not found term; EX:"b" not "%b%" PAGE:en.w:Bannered_routes_of_U.S._Route_60; DATE:2014-08-15
Exec_gsub_regx("a%b%c", "%%(%w+)%%" , -1, Scrib_kv_utl_.flat_many_("b", "B") , "aBc;1");
}
@Test public void Gsub_capture() {
Exec_gsub_regx("aa" , "(a)%1" , 1, "%0z", "aaz;1"); // capture; handle %0; PAGE:en.w:Wikipedia:Wikipedia_Signpost/Templates/Voter/testcases; DATE:2015-08-02
Exec_gsub_regx("aa" , "(a)%1" , 1, "%1z", "az;1"); // capture; handle %1+; PAGE:en.w:Wikipedia:Wikipedia_Signpost/Templates/Voter/testcases; DATE:2015-08-02
Exec_gsub_regx("a\"b'c\"d" , "([\"'])(.-)%1" , 1, "%1z", "a\"zd;1"); // capture; http://www.lua.org/pil/20.3.html; {{#invoke:test|gsub_string|a"b'c"d|(["'])(.-)%1|%1z}}
}
@Test public void Gsub_no_replace() {// PURPOSE: gsub with no replace argument should not fail; EX:d:'orse; DATE:2013-10-14
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gsub, Object_.Ary("text", "regx") , "1=text"); // NOTE: repl, limit deliberately omitted
}
@Test public void Gsub_pattern_is_int() { // PURPOSE: do not fail if integer is passed in for @regx; PAGE:en.d:λύω DATE:2014-09-02
Exec_gsub_regx("abcd", 1 , -1, "A" , "abcd;0");
}
@Test public void Gsub_replace_is_int() { // PURPOSE: do not fail if integer is passed in for @replace; PAGE:en.d:λύω DATE:2014-09-02
Exec_gsub_regx("abcd", 1 , -1, 1 , "abcd;0");
}
@Test public void Gsub_word_class() { // PURPOSE: handle %w in extended regex; PAGE:en.w:A♯_(musical_note) DATE:2015-06-10
Exec_gsub_regx("(a b)", "[^%w%p%s]", -1, "x", "(a b);0"); // was returning "(x x)" b/c ^%w was incorrectly matching "a" and "b"
}
@Test public void Gmatch_init() {
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_init, Object_.Ary("abcabc", "a(b)") , "1=a(b)\n2=\n 1=false");
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_init, Object_.Ary("abcabc", "a()(b)") , "1=a()(b)\n2=\n 1=true\n 2=false");
}
@Test public void Gmatch_callback() {
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 0) , "1=2\n2=\n 1=b");
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 2) , "1=5\n2=\n 1=b");
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("abcabc", "a(b)", Scrib_kv_utl_.base1_many_(false), 8) , "1=8\n2=");
}
@Test public void Gmatch_callback_nomatch() {// PURPOSE.fix: was originally returning "" instead of original String; EX:vi.d:trở_thành; DATE:2014-04-23
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("a", "a" , KeyVal_.Ary_empty, 0) , "1=1\n2=\n 1=a");
}
@Test public void Gmatch_callback_anypos() {// PURPOSE.fix: was not handling $capt argument; EX:vi.d:trở_thành; DATE:2014-04-23
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary("a bcd e", "()(b)" , Scrib_kv_utl_.base1_many_(true, false), 0), String_.Concat_lines_nl_skip_last
( "1=3"
, "2="
, " 1=3"
, " 2=b"
));
}
@Test public void Gsub_balanced_group() { // PURPOSE: handle balanced group regex; EX:"%b()"; NOTE:test will fail if run in 1.6 environment; DATE:2013-12-20
fxt.Init_cbk(Scrib_core.Key_mw_interface, fxt.Core().Lib_ustring(), Scrib_lib_ustring.Invk_gsub);
Exec_gsub_regx("(a)", "%b()", 1, "c", "c;1");
}
@Test public void Gmatch_callback__text_as_number() { // PURPOSE: Gmatch_callback must be able to take non String value; DATE:2013-12-20
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_ustring.Invk_gmatch_callback, Object_.Ary(1234, "1(2)", Scrib_kv_utl_.base1_many_(false), 0), String_.Concat_lines_nl_skip_last
( "1=2"
, "2="
, " 1=2"
));
}
@Test public void Gsub_frontier_pattern() { // PURPOSE: handle frontier pattern; EX:"%f[%a]"; DATE:2015-07-21
fxt.Init_cbk(Scrib_core.Key_mw_interface, fxt.Core().Lib_ustring(), Scrib_lib_ustring.Invk_gsub);
Exec_gsub_regx("a b c", "%f[%W]", 5, "()", "a() b() c();3");
Exec_gsub_regx("abC DEF gHI JKm NOP", "%f[%a]%u+%f[%A]", Int_.Max_value, "()", "abC () gHI JKm ();2"); // based on http://lua-users.org/wiki/FrontierPattern
}
@Test public void Gsub_frontier_pattern_utl() {// PURPOSE: standalone test for \0 logic in frontier pattern; note that verified against PHP: echo(preg_match( "/[\w]/us", "\0" )); DATE:2015-07-21
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "a")); // \0 not matched by a
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "0")); // \0 not matched by numeric 0
Tfds.Eq(Bool_.N, Regx_adp_.Match("\0", "[\\w]")); // \0 not matched by word_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\W]")); // \0 matched by !word_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\x]")); // \0 matched by any_char
Tfds.Eq(Bool_.Y, Regx_adp_.Match("\0", "[\\X]")); // \0 matched by !any_char
}
// @Test public void Match_viwiktionary() {
// fxt.Init_cbk(Scrib_core.Key_mw_interface, fxt.Core().Lib_ustring(), Scrib_lib_ustring.Invk_match);
// Exec_match("tr" , "()(r)", 1, ";"); // should return all matches
// Exec_match("tr" , "^([b]*).-([c]*)$", 1, ";"); // should return all matches
// }
private void Exec_find(String text, String regx, int bgn, boolean plain, String expd) {
fxt.Test_scrib_proc_kv_vals(lib, Scrib_lib_ustring.Invk_find, Scrib_kv_utl_.base1_many_(text, regx, bgn, plain), expd);
}
private void Exec_match(Object text, String regx, int bgn, String expd) {
fxt.Test_scrib_proc_kv_vals(lib, Scrib_lib_ustring.Invk_match, Scrib_kv_utl_.base1_many_(text, regx, bgn), expd);
}
private void Exec_gsub_regx(String text, Object regx, int limit, Object repl, String expd) {Exec_gsub(text, regx, limit, repl, expd);}
private void Exec_gsub(String text, Object regx, int limit, Object repl, String expd) {
fxt.Test_scrib_proc_kv_vals(lib, Scrib_lib_ustring.Invk_gsub, Scrib_kv_utl_.base1_many_(text, regx, repl, limit), expd);
}
}

View File

@@ -0,0 +1,51 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*; import gplx.xowa.xtns.scribunto.engines.mocks.*;
public class Scrib_lib_ustring__match__tst {
private final Mock_scrib_fxt fxt = new Mock_scrib_fxt(); private Scrib_lib lib;
@Before public void init() {
fxt.Clear();
lib = fxt.Core().Lib_ustring().Init();
}
@Test public void Basic() {
Exec_match("abcd" , "bc" , 1, "bc"); // basic
Exec_match("abcd" , "x" , 1, String_.Null_mark); // empty
Exec_match("abcd" , "a" , 2, String_.Null_mark); // bgn
Exec_match("abcd" , "b(c)" , 1, "c"); // group
Exec_match(" a b " , "^%s*(.-)%s*$" , 1, "a b;"); // trim; NOTE: changed from "a b" to "a b;"; DATE:2015-01-30
Exec_match("abcd" , "a" , 0, "a"); // handle 0; note that php/lua is super-1, but some modules pass in 0; ru.w:Module:Infocards; DATE:2013-11-08
Exec_match("abcd" , "." , -1, "d"); // -1
Exec_match("aaa" , "a" , 1, "a"); // should return 1st match not many
Exec_match("aaa" , "(a)" , 1, "a;a;a"); // should return all matches
Exec_match("a b" , "%S" , 1, "a"); // %S was returning every match instead of 1st; PAGE:en.w:Bertrand_Russell; DATE:2014-04-02
Exec_match(1 , "a" , 1, String_.Null_mark); // Module can pass raw ints; PAGE:en.w:Budget_of_the_European_Union; DATE:2015-01-22
Exec_match("" , "a?" , 1, ""); // no results with ? should return "" not nil; PAGE:en.d:民; DATE:2015-01-30
}
@Test public void Args_out_of_order() {
fxt.Test__proc__kvps__empty(lib, Scrib_lib_ustring.Invk_match, KeyVal_.Ary(KeyVal_.int_(2, "[a]")));
}
// @Test public void Match_viwiktionary() {
// fxt.Init_cbk(Scrib_core.Key_mw_interface, fxt.Core().Lib_ustring(), Scrib_lib_ustring.Invk_match);
// Exec_match("tr" , "()(r)", 1, ";"); // should return all matches
// Exec_match("tr" , "^([b]*).-([c]*)$", 1, ";"); // should return all matches
// }
private void Exec_match(Object text, String regx, int bgn, String expd) {
fxt.Test__proc__kvps__flat(lib, Scrib_lib_ustring.Invk_match, Scrib_kv_utl_.base1_many_(text, regx, bgn), expd);
}
}

View File

@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
import org.junit.*;
public class Scrib_lib_ustring__invoke_tst {
public class Scrib_lib_ustring__shell_cmd__tst {
@Before public void init() {
fxt.Clear_for_invoke();
fxt.Init_page("{{#invoke:Mod_0|Func_0}}");

View File

@@ -190,15 +190,30 @@ public class Scrib_regx_converter {
break;
default:
boolean normal = true;
if (i + 2 < len) {
byte dash_1 = src[i + 1];
byte dash_2 = src[i + 2];
if (dash_1 == Byte_ascii.Dash && dash_2 != Byte_ascii.Brack_end) {
Regx_quote(bfr, tmp_b);
bfr.Add_byte(Byte_ascii.Dash);
Regx_quote(bfr, dash_2);
i += 2;
normal = false;
int lhs_pos = i; // NOTE: following block handles MBCS; EX:[𠀀-𯨟] PAGE:en.d:どう DATE:2016-01-22
int lhs_len = gplx.core.intls.Utf8_.Len_of_char_by_1st_byte(src[lhs_pos]);
int dash_pos = i + lhs_len;
if (dash_pos < len) {
byte dash_char = src[dash_pos];
if (dash_char == Byte_ascii.Dash) {
int rhs_pos = dash_pos + 1;
if (rhs_pos < len) {
byte rhs_byte = src[rhs_pos];
if (rhs_byte != Byte_ascii.Brack_end) {// ignore dash if followed by brack_end; EX: [a-]; PAGE:en.d:frei; DATE:2016-01-23
int rhs_len = gplx.core.intls.Utf8_.Len_of_char_by_1st_byte(rhs_byte);
if (lhs_len == 1)
Regx_quote(bfr, src[i]);
else
bfr.Add_mid(src, i, i + lhs_len);
bfr.Add_byte(Byte_ascii.Dash);
if (rhs_len == 1)
Regx_quote(bfr, src[rhs_pos]);
else
bfr.Add_mid(src, rhs_pos, rhs_pos + rhs_len);
i = rhs_pos + rhs_len - 1; // -1 b/c for() will do ++i
normal = false;
}
}
}
}
if (normal)

View File

@@ -46,6 +46,9 @@ public class Scrib_regx_converter_tst {
fxt.Test_replace("a(2(1)2)c" , "%b()", "b", "abc");
fxt.Test_replace("a(3(2(1)2)3)c" , "%b()", "b", "a(3b3)c");
}
@Test public void Mbcs() { // PURPOSE: handle regex for multi-byte chars; PAGE:en.d:どう; DATE:2016-01-22; .NET.REGX:fails
fxt.Test_replace("𠀀" , "[𠀀-𯨟]" , "a", "a");
}
}
class Scrib_regx_converter_fxt {
private Scrib_regx_converter under;