From 686d56fdabd8e087c7f99364206e14ec9189a76e Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Sun, 24 Jan 2016 22:50:55 -0500 Subject: [PATCH] v3.1.4.1 --- 100_core/src/gplx/KeyVal_.java | 8 +- 100_core/src/gplx/String_.java | 6 +- 100_core/src/gplx/String__tst.java | 2 +- .../src/gplx/core/btries/Btrie_slim_mgr.java | 9 ++ .../gplx/core/primitives/String_obj_val.java | 2 +- 140_dbs/src/gplx/dbs/diffs/Gfdb_diff_db_.java | 11 +- 140_dbs/src/gplx/dbs/diffs/Gfdb_diff_tbl.java | 2 +- 140_dbs/src/gplx/dbs/diffs/Gfdb_rdr_utl_.java | 1 + .../gplx/dbs/diffs/builds/Gfdb_diff_bldr.java | 5 +- .../dbs/diffs/builds/Gfdb_diff_bldr_tst.java | 4 +- .../gplx/dbs/diffs/builds/Gfdb_diff_wkr.java | 2 +- .../dbs/diffs/builds/Gfdb_diff_wkr__db.java | 75 ++++----- .../src/gplx/dbs/diffs/tbls/Gdif_txn_tbl.java | 58 +++++++ 400_xowa/src/gplx/langs/htmls/Gfh_atr_.java | 3 + 400_xowa/src/gplx/langs/htmls/Gfh_utl.java | 12 ++ .../jsons/Json_parser__list_nde__base.java | 2 +- .../langs/mustaches/Mustache_doc_itm.java | 54 +++++++ .../langs/mustaches/Mustache_dom_itm.java | 53 +++--- .../langs/mustaches/Mustache_itm_parser.java | 110 +++++++++++++ .../mustaches/Mustache_itm_parser_tst.java | 39 +++++ .../langs/mustaches/Mustache_render_ctx.java | 32 ++++ 400_xowa/src/gplx/xowa/Xoa_app_.java | 2 +- 400_xowa/src/gplx/xowa/bldrs/Xob_cmd_mgr.java | 2 + .../bldrs/cmds/diffs/Bfr_arg__dump_dir.java | 9 +- .../bldrs/cmds/diffs/Xob_diff_build_wkr.java | 49 +++--- .../wms/sites/Site_meta_parser__general.java | 2 +- 400_xowa/src/gplx/xowa/drds/Xod_app.java | 18 ++- 400_xowa/src/gplx/xowa/drds/Xod_app_tst.java | 12 ++ .../src/gplx/xowa/drds/Xod_search_cmd.java | 22 +++ .../src/gplx/xowa/drds/Xod_search_cmd_.java | 74 +++++++++ .../src/gplx/xowa/files/Xof_file_wkr_.java | 31 +++- .../gplx/xowa/files/Xof_file_wkr__tst.java | 33 ++++ .../src/gplx/xowa/files/Xof_url_bldr_tst.java | 2 +- .../core/htmls/utls/Xoh_lnki_wtr_utl.java | 34 ---- .../xowa/htmls/core/wkrs/Xoh_hdoc_ctx.java | 4 +- .../htmls/core/wkrs/hdrs/Xoh_hdr_data.java | 5 +- .../core/wkrs/hdrs/Xoh_hdr_hzip_tst.java | 21 +++ .../htmls/core/wkrs/imgs/Xoh_img_hzip.java | 2 +- .../wkrs/imgs/Xoh_img_hzip__dump__tst.java | 33 +++- .../htmls/core/wkrs/lnkis/Xoh_lnki_data.java | 4 +- .../htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java | 1 + .../wkrs/lnkis/Xoh_lnki_hzip__ns__tst.java | 6 +- .../core/wkrs/thms/Xoh_thm_hzip_tst.java | 4 +- .../htmls/core/wkrs/thms/Xoh_thm_wtr.java | 15 +- .../xowa/htmls/css/Xowd_css_core_mgr.java | 33 ++-- .../src/gplx/xowa/langs/Xol_lang_itm_.java | 1 + .../gplx/xowa/langs/kwds/Xol_kwd_grp_.java | 4 +- .../xowa/parsers/utils/Xop_sanitizer.java | 10 ++ .../wikis/ttls/Xow_ttl__html_entity_tst.java | 3 +- .../xowa/xtns/dynamicPageList/Dpl_xnde.java | 53 +++--- .../xtns/dynamicPageList/Dpl_xnde_tst.java | 49 +++++- .../gplx/xowa/xtns/pagebanners/Pb_xnde.java | 42 ----- .../gplx/xowa/xtns/pagebanners/Pgbnr_cfg.java | 150 +++++++++++++++++ .../xowa/xtns/pagebanners/Pgbnr_func.java | 79 +++++++++ .../{Pb_xtn.java => Pgbnr_func_tst.java} | 12 +- .../src/gplx/xowa/xtns/pfuncs/Pf_func_.java | 2 + .../pfuncs/wikis/Pfunc_pagesincategory.java | 23 --- .../gplx/xowa/xtns/scribunto/Scrib_core.java | 1 + .../xtns/scribunto/Scrib_err_filter_mgr.java | 2 +- .../xtns/scribunto/Scrib_invoke_func_fxt.java | 36 +++-- .../xtns/scribunto/engines/Scrib_engine.java | 14 +- .../xtns/scribunto/engines/Scrib_server.java | 16 +- .../engines/mocks/Mock_proc_fxt.java | 44 +++++ .../engines/mocks/Mock_scrib_fxt.java | 97 +++++++++++ .../xtns/scribunto/errs/Gfo_comp_op_1.java | 8 +- .../scribunto/libs/Scrib_lib_ustring.java | 32 +++- .../libs/Scrib_lib_ustring__find__tst.java | 50 ++++++ .../libs/Scrib_lib_ustring__gmatch__tst.java | 53 ++++++ .../libs/Scrib_lib_ustring__gsub__tst.java | 101 ++++++++++++ .../libs/Scrib_lib_ustring__lib_tst.java | 151 ------------------ .../libs/Scrib_lib_ustring__match__tst.java | 51 ++++++ ...=> Scrib_lib_ustring__shell_cmd__tst.java} | 2 +- .../scribunto/libs/Scrib_regx_converter.java | 33 ++-- .../libs/Scrib_regx_converter_tst.java | 3 + .../en.wikipedia.org-file-user.xowa | Bin 57344 -> 57344 bytes .../en.wikipedia.org-file.xowa | Bin 57344 -> 57344 bytes .../en.wikipedia.org-text.xowa | Bin 36864 -> 36864 bytes 77 files changed, 1543 insertions(+), 487 deletions(-) create mode 100644 140_dbs/src/gplx/dbs/diffs/tbls/Gdif_txn_tbl.java create mode 100644 400_xowa/src/gplx/langs/mustaches/Mustache_doc_itm.java create mode 100644 400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser.java create mode 100644 400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser_tst.java create mode 100644 400_xowa/src/gplx/langs/mustaches/Mustache_render_ctx.java create mode 100644 400_xowa/src/gplx/xowa/drds/Xod_search_cmd.java create mode 100644 400_xowa/src/gplx/xowa/drds/Xod_search_cmd_.java create mode 100644 400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java delete mode 100644 400_xowa/src/gplx/xowa/htmls/core/htmls/utls/Xoh_lnki_wtr_utl.java delete mode 100644 400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xnde.java create mode 100644 400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_cfg.java create mode 100644 400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func.java rename 400_xowa/src/gplx/xowa/xtns/pagebanners/{Pb_xtn.java => Pgbnr_func_tst.java} (65%) create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_proc_fxt.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_scrib_fxt.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__find__tst.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gmatch__tst.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gsub__tst.java delete mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__lib_tst.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__match__tst.java rename 400_xowa/src/gplx/xowa/xtns/scribunto/libs/{Scrib_lib_ustring__invoke_tst.java => Scrib_lib_ustring__shell_cmd__tst.java} (97%) diff --git a/100_core/src/gplx/KeyVal_.java b/100_core/src/gplx/KeyVal_.java index 101bf8fa8..e109c0390 100644 --- a/100_core/src/gplx/KeyVal_.java +++ b/100_core/src/gplx/KeyVal_.java @@ -63,12 +63,12 @@ public class KeyVal_ { } return null; } - public static String Ary_to_str_nested(KeyVal... ary) { + public static String Ary__to_str__nest(KeyVal... ary) { Bry_bfr bfr = Bry_bfr.new_(); - Ary_to_str_nested(bfr, 0, ary); + Ary__to_str__nest(bfr, 0, ary); return bfr.To_str_and_clear(); } - private static void Ary_to_str_nested(Bry_bfr bfr, int indent, KeyVal[] ary) { + private static void Ary__to_str__nest(Bry_bfr bfr, int indent, KeyVal[] ary) { int len = ary.length; for (int i = 0; i < len; ++i) { KeyVal itm = ary[i]; @@ -82,7 +82,7 @@ public class KeyVal_ { Class val_type = Type_adp_.ClassOf_obj(val); if (Type_adp_.Eq(val_type, KeyVal[].class)) { // val is KeyVal[]; recurse bfr.Add_byte_nl(); // add nl : "\n" - Ary_to_str_nested(bfr, indent + 1, (KeyVal[])val); + Ary__to_str__nest(bfr, indent + 1, (KeyVal[])val); continue; // don't add \n below } else if (Type_adp_.Eq(val_type, Bool_.Cls_ref_type)) { // val is boolean diff --git a/100_core/src/gplx/String_.java b/100_core/src/gplx/String_.java index a8c927171..f1c37b842 100644 --- a/100_core/src/gplx/String_.java +++ b/100_core/src/gplx/String_.java @@ -117,7 +117,7 @@ public class String_ implements GfoInvkAble { public static boolean EqNot(String lhs, String rhs) {return !Object_.Eq(lhs, rhs);} public static boolean EqEmpty(String lhs) {return lhs.equals("");} public static String IfNullOrEmpty(String s, String or) {return s == null || s.length() == 0 ? or : s;} - public static int Compare(String lhs, String rhs) {return lhs.compareTo(rhs);} // NOTE: Compare instead of compareTo b/c javafy lowercases compareTo + public static int Compare_as_ordinals(String lhs, String rhs) {return lhs.compareTo(rhs);} public static int Compare_ignoreCase(String lhs, String rhs) { if (lhs == null && rhs != null) return CompareAble_.Less; else if (lhs != null && rhs == null) return CompareAble_.More; @@ -131,8 +131,8 @@ public class String_ implements GfoInvkAble { else return lhs.compareToIgnoreCase(rhs); */ } - public static int Compare_strict(String lhs, String rhs) { - int compare = String_.Compare(lhs, rhs); + public static int Compare(String lhs, String rhs) { + int compare = lhs.compareTo(rhs); if (compare == CompareAble_.Same) return CompareAble_.Same; else if (compare < CompareAble_.Same) return CompareAble_.Less; else /* (compare > CompareAble_.Same) */ return CompareAble_.More; diff --git a/100_core/src/gplx/String__tst.java b/100_core/src/gplx/String__tst.java index 21dc0f83c..295e6087d 100644 --- a/100_core/src/gplx/String__tst.java +++ b/100_core/src/gplx/String__tst.java @@ -166,7 +166,7 @@ public class String__tst { tst_Compare_byteAry("ac", "ab", CompareAble_.More); tst_Compare_byteAry("a", "ab", CompareAble_.Less); tst_Compare_byteAry("ab", "a", CompareAble_.More); - tst_Compare_byteAry("101", "1-0-1", CompareAble_.More); // NOTE: regular String_.Compare returns Less in .NET, More in Java + tst_Compare_byteAry("101", "1-0-1", CompareAble_.More); // NOTE: regular String_.Compare_as_ordinals returns Less in .NET, More in Java tst_Compare_byteAry("1-0-1", "101 (album)", CompareAble_.Less); } void tst_Compare_byteAry(String lhs, String rhs, int expd) {Tfds.Eq(expd, String_.Compare_byteAry(lhs, rhs));} @Test public void FindBwd() { // WORKAROUND.CS:String.LastIndexOf returns -1 for multi-chars; diff --git a/100_core/src/gplx/core/btries/Btrie_slim_mgr.java b/100_core/src/gplx/core/btries/Btrie_slim_mgr.java index b16f5a87a..afd3987fa 100644 --- a/100_core/src/gplx/core/btries/Btrie_slim_mgr.java +++ b/100_core/src/gplx/core/btries/Btrie_slim_mgr.java @@ -71,6 +71,15 @@ public class Btrie_slim_mgr implements Btrie_mgr { Add_obj(ary[i], obj); return this; } + public Btrie_slim_mgr Add_ary_byte(byte... ary) { + int len = ary.length; + for (int i = 0; i < len; ++i) { + byte b = ary[i]; + Byte_obj_val bval = Byte_obj_val.new_(b); + Add_obj(Bry_.New_by_byte(b), bval); + } + return this; + } public Btrie_slim_mgr Add_replace_many(String trg_str, String... src_ary) {return Add_replace_many(Bry_.new_u8(trg_str), src_ary);} public Btrie_slim_mgr Add_replace_many(byte[] trg_bry, String... src_ary) { int len = src_ary.length; diff --git a/100_core/src/gplx/core/primitives/String_obj_val.java b/100_core/src/gplx/core/primitives/String_obj_val.java index b042bea43..e4356c8ed 100644 --- a/100_core/src/gplx/core/primitives/String_obj_val.java +++ b/100_core/src/gplx/core/primitives/String_obj_val.java @@ -21,7 +21,7 @@ public class String_obj_val implements CompareAble { @Override public String toString() {return val;} public int compareTo(Object obj) { String_obj_val comp = (String_obj_val)obj; - return String_.Compare_strict(val, comp.val); + return String_.Compare(val, comp.val); } public static String_obj_val new_(String val) {return new String_obj_val(val);} String_obj_val(String val) {this.val = val;} } diff --git a/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_db_.java b/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_db_.java index c8cf3c41e..b767d05ae 100644 --- a/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_db_.java +++ b/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_db_.java @@ -18,12 +18,11 @@ along with this program. If not, see . package gplx.dbs.diffs; import gplx.*; import gplx.dbs.*; public class Gfdb_diff_db_ { public static final String - Fld__diff_site = "diff_site" // -1 for single-site merge; 0+ for multiple-site merges where 0+ is defined in a registry - , Fld__diff_time = "diff_time" // -1 for single-time merge; 0+ for multiple-time merges where 0+ is defined in a registry - , Fld__diff_db_trg = "diff_db_trg" // -1 for single-db tables; 0+ for multiple-db tables - , Fld__diff_db_src = "diff_db_src" // -1 for I,U,D; 0+ for M - , Fld__diff_type = "diff_type" // I,U,D,M - , Fld__diff_uid = "diff_uid" // 0+ + Fld__dif_txn = "dif_txn" // 0+ where 0+ is defined in a tbl + , Fld__dif_uid = "dif_uid" // 0+ + , Fld__dif_type = "dif_type" // I,U,D,M + , Fld__dif_db_trg = "dif_db_trg" // -1 for single-db tables; 0+ for multiple-db tables + , Fld__dif_db_src = "dff_db_src" // -1 for I,U,D; 0+ for M ; public static final byte Tid__insert = 0 diff --git a/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_tbl.java b/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_tbl.java index 4dcd066a7..c0ffd3bd9 100644 --- a/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_tbl.java +++ b/140_dbs/src/gplx/dbs/diffs/Gfdb_diff_tbl.java @@ -26,7 +26,7 @@ public class Gfdb_diff_tbl { public final Dbmeta_fld_itm[] Keys; public final Dbmeta_fld_itm[] Vals; public Db_rdr Make_rdr(Db_conn conn) { - Db_stmt stmt = conn.Stmt_select(Name, Dbmeta_fld_itm.To_str_ary(Flds)); + Db_stmt stmt = conn.Stmt_select_order(Name, Dbmeta_fld_itm.To_str_ary(Flds), Dbmeta_fld_itm.Str_ary_empty, Dbmeta_fld_itm.To_str_ary(Keys)); return stmt.Exec_select__rls_auto(); } diff --git a/140_dbs/src/gplx/dbs/diffs/Gfdb_rdr_utl_.java b/140_dbs/src/gplx/dbs/diffs/Gfdb_rdr_utl_.java index 17f8d5bc0..5b8885007 100644 --- a/140_dbs/src/gplx/dbs/diffs/Gfdb_rdr_utl_.java +++ b/140_dbs/src/gplx/dbs/diffs/Gfdb_rdr_utl_.java @@ -26,6 +26,7 @@ public class Gfdb_rdr_utl_ { int tid = fld.Type().Tid_ansi(); switch (tid) { case Dbmeta_fld_tid.Tid__bool: comp = Bool_.Compare (lhs_rdr.Read_bool_by_byte(fld_name), rhs_rdr.Read_bool_by_byte(fld_name)); break; + case Dbmeta_fld_tid.Tid__byte: comp = Byte_.Compare (lhs_rdr.Read_byte(fld_name) , rhs_rdr.Read_byte(fld_name)); break; case Dbmeta_fld_tid.Tid__int: comp = Int_.Compare (lhs_rdr.Read_int(fld_name) , rhs_rdr.Read_int(fld_name)); break; case Dbmeta_fld_tid.Tid__long: comp = Long_.Compare (lhs_rdr.Read_long(fld_name) , rhs_rdr.Read_long(fld_name)); break; case Dbmeta_fld_tid.Tid__float: comp = Float_.Compare (lhs_rdr.Read_float(fld_name) , rhs_rdr.Read_float(fld_name)); break; diff --git a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr.java b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr.java index 3bfd67df9..19d73f45f 100644 --- a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr.java +++ b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr.java @@ -21,10 +21,10 @@ public class Gfdb_diff_bldr { private Gfdb_diff_rdr_comparer rdr_comparer = new Gfdb_diff_rdr_comparer(); private Gfdb_diff_wkr diff_wkr; public void Init(Gfdb_diff_wkr diff_wkr) {this.diff_wkr = diff_wkr;} - public void Compare(Gfdb_diff_tbl tbl, Db_conn old_conn, Db_conn new_conn) { + public void Compare(int txn, Gfdb_diff_tbl tbl, Db_conn old_conn, Db_conn new_conn) { Db_rdr old_rdr = tbl.Make_rdr(old_conn), new_rdr = tbl.Make_rdr(new_conn); rdr_comparer.Init_rdrs(tbl, old_rdr, new_rdr); - diff_wkr.Init_rdrs(tbl, old_rdr, new_rdr); + diff_wkr.Init_rdrs(txn, tbl, old_rdr, new_rdr); boolean loop = true; while (loop) { int rslt = rdr_comparer.Compare(); @@ -35,5 +35,6 @@ public class Gfdb_diff_bldr { case Gfdb_diff_rdr_comparer.Rslt__done: loop = false; break; } } + diff_wkr.Term_tbls(); } } diff --git a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr_tst.java b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr_tst.java index b85b2047a..83b294c62 100644 --- a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr_tst.java +++ b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_bldr_tst.java @@ -76,7 +76,7 @@ class Gfdb_diff_bldr_fxt { public void Init__tbl__old(Object[]... rows) {Db_conn_utl.Tbl__new(old_conn, "tbl", flds_ary, rows);} public void Init__tbl__cur(Object[]... rows) {Db_conn_utl.Tbl__new(new_conn, "tbl", flds_ary, rows);} public void Test__bld(String... expd) { - bldr.Compare(tbl, old_conn, new_conn); + bldr.Compare(-1, tbl, old_conn, new_conn); Tfds.Eq_ary_str(expd, wkr.To_str_ary()); } } @@ -84,7 +84,7 @@ class Gfdb_diff_wkr__test implements Gfdb_diff_wkr { private final List_adp list = List_adp_.new_(); private final Bry_bfr bfr = Bry_bfr.new_(); private Db_rdr old_rdr, new_rdr; - public void Init_rdrs(Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr) { + public void Init_rdrs(int txn, Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr) { this.old_rdr = old_rdr; this.new_rdr = new_rdr; } public void Term_tbls() {} diff --git a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr.java b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr.java index 48b425007..944263b4a 100644 --- a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr.java +++ b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr.java @@ -17,7 +17,7 @@ along with this program. If not, see . */ package gplx.dbs.diffs.builds; import gplx.*; import gplx.dbs.*; import gplx.dbs.diffs.*; public interface Gfdb_diff_wkr { - void Init_rdrs(Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr); + void Init_rdrs(int txn, Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr); void Term_tbls(); void Handle_same(); void Handle_old_missing(); diff --git a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr__db.java b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr__db.java index 7cfdee1d3..889302d15 100644 --- a/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr__db.java +++ b/140_dbs/src/gplx/dbs/diffs/builds/Gfdb_diff_wkr__db.java @@ -19,58 +19,53 @@ package gplx.dbs.diffs.builds; import gplx.*; import gplx.dbs.*; import gplx.dbs import gplx.dbs.metas.*; public class Gfdb_diff_wkr__db implements Gfdb_diff_wkr { private Dbmeta_fld_itm[] val_flds; private int val_flds_len; - private Gfdb_diff_tbl tbl; - private Db_conn diff_conn; private Db_stmt stmt; - private Db_rdr old_rdr, new_rdr; - private int uid__upsert, uid__delete; private int prog_interval, prog_count; - public void Init_conn(Gfdb_diff_db diff_db, int prog_interval) {this.diff_conn = diff_db.Conn(); this.prog_interval = prog_interval;} - public void Init_rdrs(Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr) { + private Gfdb_diff_tbl tbl; private Db_rdr old_rdr, new_rdr; + private Db_conn dif_conn; private Db_stmt stmt; + private int txn, uid, prog_interval, prog_count; + public void Init_conn(Gfdb_diff_db diff_db, int prog_interval) {this.dif_conn = diff_db.Conn(); this.prog_interval = prog_interval;} + public void Init_rdrs(int txn, Gfdb_diff_tbl tbl, Db_rdr old_rdr, Db_rdr new_rdr) { this.tbl = tbl; this.old_rdr = old_rdr; this.new_rdr = new_rdr; this.val_flds = tbl.Vals; val_flds_len = val_flds.length; - this.uid__upsert = 0; uid__delete = 0; this.prog_count = 0; - String tbl_name = tbl.Name; - Dbmeta_fld_itm[] diff_flds = Gfdb_diff_wkr__db_.New_diff_flds(tbl.Flds); - if (!diff_conn.Meta_tbl_exists(tbl_name)) diff_conn.Ddl_create_tbl(Dbmeta_tbl_itm.New(tbl_name, diff_flds)); - this.stmt = diff_conn.Stmt_insert(tbl_name, Gfdb_diff_wkr__db_.To_str_ary(diff_flds)); - diff_conn.Txn_bgn("diff_db"); - } - public void Term_tbls() { - diff_conn.Txn_end(); + this.txn = txn; this.uid = -1; this.prog_count = 0; + + String dif_tbl = tbl.Name; Dbmeta_fld_itm[] dif_flds = Gfdb_diff_wkr__db_.New_dif_flds(tbl.Flds); + if (!dif_conn.Meta_tbl_exists(dif_tbl)) dif_conn.Ddl_create_tbl(Dbmeta_tbl_itm.New(dif_tbl, dif_flds)); + this.stmt = dif_conn.Stmt_insert(dif_tbl, Gfdb_diff_wkr__db_.To_str_ary(dif_flds)); + dif_conn.Txn_bgn("dif_db_tbl_" + dif_tbl); } + public void Term_tbls() {dif_conn.Txn_end();} + public void Handle_old_missing() {Insert(Gfdb_diff_db_.Tid__insert, ++uid, new_rdr, tbl.Flds);} + public void Handle_new_missing() {Insert(Gfdb_diff_db_.Tid__delete, ++uid, old_rdr, tbl.Flds);} public void Handle_same() { if (Gfdb_rdr_utl_.Compare(val_flds, val_flds_len, old_rdr, new_rdr) != CompareAble_.Same) - Insert(Gfdb_diff_db_.Tid__update, uid__upsert++, tbl.Flds, new_rdr); + Insert(Gfdb_diff_db_.Tid__update, ++uid, new_rdr, tbl.Flds); } - public void Handle_old_missing() {Insert(Gfdb_diff_db_.Tid__insert, uid__upsert++, tbl.Flds, new_rdr);} - public void Handle_new_missing() {Insert(Gfdb_diff_db_.Tid__delete, uid__delete++, tbl.Keys, old_rdr);} - private void Insert(byte diff_type, int uid, Dbmeta_fld_itm[] flds, Db_rdr rdr) { - stmt.Val_int (Gfdb_diff_db_.Fld__diff_site , -1) - .Val_int (Gfdb_diff_db_.Fld__diff_time , -1) - .Val_int (Gfdb_diff_db_.Fld__diff_db_trg , -1) - .Val_int (Gfdb_diff_db_.Fld__diff_db_src , -1) - .Val_byte (Gfdb_diff_db_.Fld__diff_type , diff_type) - .Val_int (Gfdb_diff_db_.Fld__diff_type , uid) - ; + private void Insert(byte dif_type, int uid, Db_rdr rdr, Dbmeta_fld_itm[] flds) { + stmt.Clear(); + stmt.Val_int (Gfdb_diff_db_.Fld__dif_txn , txn) + .Val_int (Gfdb_diff_db_.Fld__dif_uid , uid) + .Val_int (Gfdb_diff_db_.Fld__dif_type , dif_type) + .Val_int (Gfdb_diff_db_.Fld__dif_db_src , -1) + .Val_int (Gfdb_diff_db_.Fld__dif_db_trg , -1); Gfdb_rdr_utl_.Stmt_args(stmt, flds, flds.length, rdr); stmt.Exec_insert(); - if ((++prog_count % prog_interval) == 0) diff_conn.Txn_sav(); + if ((++prog_count % prog_interval) == 0) dif_conn.Txn_sav(); } } class Gfdb_diff_wkr__db_ { - public static Dbmeta_fld_itm[] New_diff_flds(Dbmeta_fld_itm[] all_flds) { - int len = all_flds.length; - int system_flds = 6; - Dbmeta_fld_itm[] rv = new Dbmeta_fld_itm[len + system_flds]; - rv[0] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__diff_site); - rv[1] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__diff_time); - rv[2] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__diff_db_trg); - rv[3] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__diff_db_src); - rv[4] = Dbmeta_fld_itm.new_byte(Gfdb_diff_db_.Fld__diff_type); - rv[5] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__diff_uid); + public static Dbmeta_fld_itm[] New_dif_flds(Dbmeta_fld_itm[] cur_flds) { + int len = cur_flds.length; + int sys_flds = 5; + Dbmeta_fld_itm[] rv = new Dbmeta_fld_itm[len + sys_flds]; + rv[0] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__dif_txn); + rv[1] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__dif_uid); + rv[2] = Dbmeta_fld_itm.new_byte (Gfdb_diff_db_.Fld__dif_type); + rv[3] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__dif_db_trg); + rv[4] = Dbmeta_fld_itm.new_int (Gfdb_diff_db_.Fld__dif_db_src); for (int i = 0; i < len; ++i) { - Dbmeta_fld_itm orig_fld = all_flds[i]; - Dbmeta_fld_itm diff_fld = new Dbmeta_fld_itm(orig_fld.Name(), orig_fld.Type()).Nullable_y_(); // keep same name and type, but make nullable - all_flds[i + system_flds] = diff_fld; + Dbmeta_fld_itm cur_fld = cur_flds[i]; + Dbmeta_fld_itm dif_fld = new Dbmeta_fld_itm(cur_fld.Name(), cur_fld.Type()); + rv[i + sys_flds] = dif_fld; } return rv; } diff --git a/140_dbs/src/gplx/dbs/diffs/tbls/Gdif_txn_tbl.java b/140_dbs/src/gplx/dbs/diffs/tbls/Gdif_txn_tbl.java new file mode 100644 index 000000000..f8549dc9d --- /dev/null +++ b/140_dbs/src/gplx/dbs/diffs/tbls/Gdif_txn_tbl.java @@ -0,0 +1,58 @@ +/* +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.dbs.diffs.tbls; import gplx.*; import gplx.dbs.*; import gplx.dbs.diffs.*; +import gplx.dbs.*; +/* +reg: +id,name,made_by,made_on,meta +0,'Diffs for Simple Wikipedia betwee 2015-11-16 and 2015-12-23',gnosygnu,2015-12-23'dif;simplewiki;20151223;20151116' +cmd: +owner,id,tid,meta +0,0,data_comp_tid,page +0,1,data_comp_tid,cat_core +0,2,data_comp_tid,cat_link +txn: +reg_id,txn_id,cmd_id,owner_txn +0,0,0,-1,page +0,1,-1,-1,cat +0,2,-1,1,mid +0,3,1,2,cat_core +0,4,2,2,cat_link +*/ +class Gdif_txn_tbl implements Rls_able { + private String tbl_name = "gdif_txn"; + private String fld_owner, fld_id; + private final Dbmeta_fld_list flds = Dbmeta_fld_list.new_(); + private final Db_conn conn; private Db_stmt stmt_insert; + public Gdif_txn_tbl(Db_conn conn) { + this.conn = conn; + fld_owner = flds.Add_int("txn_owner"); fld_id = flds.Add_int("txn_id"); + conn.Rls_reg(this); + } + public void Create_tbl() {conn.Ddl_create_tbl(Dbmeta_tbl_itm.New(tbl_name, flds.To_fld_ary(), Dbmeta_idx_itm.new_unique_by_tbl(tbl_name, "main", fld_owner, fld_id)));} + public void Insert(int txn_owner, int txn_id) { + if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds); + stmt_insert.Clear() + .Val_int(fld_owner , txn_owner) + .Val_int(fld_id , txn_id) + .Exec_insert(); + } + public void Rls() { + stmt_insert = Db_stmt_.Rls(stmt_insert); + } +} diff --git a/400_xowa/src/gplx/langs/htmls/Gfh_atr_.java b/400_xowa/src/gplx/langs/htmls/Gfh_atr_.java index 2b05f468e..724c80986 100644 --- a/400_xowa/src/gplx/langs/htmls/Gfh_atr_.java +++ b/400_xowa/src/gplx/langs/htmls/Gfh_atr_.java @@ -54,4 +54,7 @@ public class Gfh_atr_ { public static byte[] Make(Bry_bfr bfr, byte[] key, byte[] val) { return bfr.Add_byte_space().Add(key).Add_byte_eq().Add_byte_quote().Add(val).Add_byte_quote().To_bry_and_clear(); } + public static void Add(Bry_bfr bfr, byte[] key, byte[] val) { + bfr.Add_byte_space().Add(key).Add_byte_eq().Add_byte_quote().Add(val).Add_byte_quote(); + } } diff --git a/400_xowa/src/gplx/langs/htmls/Gfh_utl.java b/400_xowa/src/gplx/langs/htmls/Gfh_utl.java index 42b4447c2..a3051312c 100644 --- a/400_xowa/src/gplx/langs/htmls/Gfh_utl.java +++ b/400_xowa/src/gplx/langs/htmls/Gfh_utl.java @@ -178,6 +178,18 @@ public class Gfh_utl { return bfr.To_bry_and_clear(); } public static String Replace_apos(String s) {return String_.Replace(s, "'", "\"");} + public static String Replace_apos_concat_lines(String... lines) { + Bry_bfr bfr = Bry_bfr.new_(); + int len = lines.length; + for (int i = 0; i < len; ++i) { + String line_str = lines[i]; + byte[] line_bry = Bry_.new_u8(line_str); + Bry_.Replace_all_direct(line_bry, Byte_ascii.Apos, Byte_ascii.Quote, 0, line_bry.length); + if (i != 0) bfr.Add_byte_nl(); + bfr.Add(line_bry); + } + return bfr.To_str_and_clear(); + } public static void Log(Exception e, String head, byte[] page_url, byte[] src, int pos) { Err err = Err_.cast_or_make(e); if (err.Logged()) return; String msg = String_.Format("{0}; page={1} err={2} mid={3} trace={4}", head, page_url, Err_.To_str(e), Bry_.Escape_ws(Bry_.Mid_by_len_safe(src, pos, 255)), err.To_str__log()); diff --git a/400_xowa/src/gplx/langs/jsons/Json_parser__list_nde__base.java b/400_xowa/src/gplx/langs/jsons/Json_parser__list_nde__base.java index 6a560d368..9cc600c6e 100644 --- a/400_xowa/src/gplx/langs/jsons/Json_parser__list_nde__base.java +++ b/400_xowa/src/gplx/langs/jsons/Json_parser__list_nde__base.java @@ -41,7 +41,7 @@ public class Json_parser__list_nde__base extends Json_parser__itm__base { for (int j = 0; j < atr_len; ++j) { Json_kv atr = nde.Get_at_as_kv(j); Object idx_obj = hash.Get_by_bry(atr.Key_as_bry()); - if (idx_obj == null) {Warn("unknown key", atr); continue;} + if (idx_obj == null) {Warn("unknown json parser key", atr); continue;} int idx_int = ((Int_obj_val)idx_obj).Val(); atrs[idx_int] = atr; } diff --git a/400_xowa/src/gplx/langs/mustaches/Mustache_doc_itm.java b/400_xowa/src/gplx/langs/mustaches/Mustache_doc_itm.java new file mode 100644 index 000000000..3ed228c05 --- /dev/null +++ b/400_xowa/src/gplx/langs/mustaches/Mustache_doc_itm.java @@ -0,0 +1,54 @@ +/* +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.langs.mustaches; import gplx.*; import gplx.langs.*; +import gplx.langs.jsons.*; +interface Mustache_doc_itm { + byte[] Get_by_key(byte[] key); + Mustache_doc_itm Get_owner(); + void Move_next(); + void Move_down(byte[] key); + void Move_up(); +} +class Mustache_doc_itm_ { + public static final byte[] Null_val = null; + public static final Mustache_doc_itm Null_itm = null; +} +class Mustache_doc_itm__json implements Mustache_doc_itm { + // private Json_doc jdoc; + private final List_adp stack = List_adp_.new_(); + private Json_nde cur; private int cur_idx = -1; + public void Init_by_jdoc(Json_doc jdoc) { + // this.jdoc = jdoc; + this.cur = jdoc.Root_nde(); + } + public byte[] Get_by_key(byte[] key) {return cur.Get_bry_or_null(key);} + public Mustache_doc_itm Get_owner() {return Mustache_doc_itm_.Null_itm;} + public void Move_next() { + ++cur_idx; + // cur = cur.Owner().Get_at(); + } + public void Move_down(byte[] key) { + stack.Add(cur); + cur_idx = 0; + cur = (Json_nde)cur.Get_itm(key); + } + public void Move_up() { + if (cur_idx == 0) {} + cur = (Json_nde)stack.Get_at_last(); + } +} diff --git a/400_xowa/src/gplx/langs/mustaches/Mustache_dom_itm.java b/400_xowa/src/gplx/langs/mustaches/Mustache_dom_itm.java index eeb964582..a86fcff32 100644 --- a/400_xowa/src/gplx/langs/mustaches/Mustache_dom_itm.java +++ b/400_xowa/src/gplx/langs/mustaches/Mustache_dom_itm.java @@ -16,21 +16,12 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; -/* -root -txt -key -txt -section - txt - key - txt -txt -*/ interface Mustache_elem_itm { int Tid(); byte[] Key(); - Mustache_elem_itm[] Subs(); + Mustache_elem_itm[] Subs_ary(); + void Subs_ary_(Mustache_elem_itm[] v); + void Render(Bry_bfr bfr, Mustache_render_ctx ctx); } class Mustache_elem_itm_ {// for types, see http://mustache.github.io/mustache.5.html public static final int Tid__root = 0, Tid__text = 1, Tid__variable = 2, Tid__escape = 3, Tid__section = 4, Tid__inverted = 5, Tid__comment = 6, Tid__partial = 7, Tid__delimiter = 8; @@ -40,16 +31,42 @@ abstract class Mustache_elem_base implements Mustache_elem_itm { public Mustache_elem_base(int tid, byte[] key) {this.tid = tid; this.key = key;} public int Tid() {return tid;} private final int tid; public byte[] Key() {return key;} private final byte[] key; - @gplx.Virtual public Mustache_elem_itm[] Subs() {return Mustache_elem_itm_.Ary_empty;} + @gplx.Virtual public Mustache_elem_itm[] Subs_ary() {return Mustache_elem_itm_.Ary_empty;} + @gplx.Virtual public void Subs_ary_(Mustache_elem_itm[] v) {} + @gplx.Virtual public void Render(Bry_bfr bfr, Mustache_render_ctx ctx) {} +} +class Mustache_elem_root extends Mustache_elem_base { // EX: {{variable}} -> <a> + private Mustache_elem_itm[] subs_ary; + public Mustache_elem_root() {super(Mustache_elem_itm_.Tid__root, Bry_.Empty);} + @Override public Mustache_elem_itm[] Subs_ary() {return subs_ary;} + @Override public void Subs_ary_(Mustache_elem_itm[] v) {subs_ary = v;} + @Override public void Render(Bry_bfr bfr, Mustache_render_ctx ctx) { + int subs_len = subs_ary.length; + for (int i = 0; i < subs_len; ++i) { + Mustache_elem_itm sub = subs_ary[i]; + sub.Render(bfr, ctx); + } + } } class Mustache_elem_text extends Mustache_elem_base { // EX: text -> text - public Mustache_elem_text(byte[] val) {super(Mustache_elem_itm_.Tid__text, Bry_.Empty); - this.val = val; + private final byte[] src; private final int src_bgn, src_end; + public Mustache_elem_text(byte[] src, int src_bgn, int src_end) {super(Mustache_elem_itm_.Tid__text, Bry_.Empty); + this.src = src; + this.src_bgn = src_bgn; + this.src_end = src_end; + } + @Override public void Render(Bry_bfr bfr, Mustache_render_ctx ctx) { + bfr.Add_mid(src, src_bgn, src_end); } - public byte[] Val() {return val;} private final byte[] val; } -class Mustache_elem_val extends Mustache_elem_base { // EX: {{variable}} -> <a> - public Mustache_elem_val(byte[] key) {super(Mustache_elem_itm_.Tid__variable, key);} +class Mustache_elem_variable extends Mustache_elem_base { // EX: {{variable}} -> <a> + public Mustache_elem_variable(byte[] key) {super(Mustache_elem_itm_.Tid__variable, key);} + @Override public void Render(Bry_bfr bfr, Mustache_render_ctx ctx) { + byte[] key = this.Key(); + byte[] val = ctx.Render_variable(key); + if (val != Mustache_doc_itm_.Null_val) // if not found, return empty String by default + bfr.Add(val); + } } class Mustache_elem_escape extends Mustache_elem_base { // EX: {{{variable}}} -> public Mustache_elem_escape(byte[] key) {super(Mustache_elem_itm_.Tid__escape, key);} diff --git a/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser.java b/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser.java new file mode 100644 index 000000000..9ec7fef54 --- /dev/null +++ b/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser.java @@ -0,0 +1,110 @@ +/* +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.langs.mustaches; import gplx.*; import gplx.langs.*; +import gplx.core.btries.*; +class Mustache_itm_parser { + private byte[] src; private int src_end; + private final Mustache_tkn_def tkn_def = new Mustache_tkn_def(); + public Mustache_elem_itm Parse(byte[] src, int src_bgn, int src_end) { + this.src = src; this.src_end = src_end; + Mustache_elem_root root = new Mustache_elem_root(); + Parse_grp(root, src_bgn); + return root; + } + private void Parse_grp(Mustache_elem_itm owner, int src_bgn) { + List_adp subs_list = List_adp_.new_(); + int pos = src_bgn; + boolean loop = true; + while (loop) { + int tkn_lhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_lhs, pos, src_end); // next "{{" + if (tkn_lhs_bgn == Bry_find_.Not_found) { // no "{{"; EOS + loop = false; + tkn_lhs_bgn = src_end; + } + subs_list.Add(new Mustache_elem_text(src, pos, tkn_lhs_bgn)); // add everything between last "}}" and cur "{{" + if (!loop) break; + pos = Parse_itm(subs_list, tkn_lhs_bgn + tkn_def.Variable_lhs_len); + } + if (subs_list.Count() > 0) + owner.Subs_ary_((Mustache_elem_itm[])subs_list.To_ary_and_clear(Mustache_elem_itm.class)); + } + private int Parse_itm(List_adp subs_list, int tkn_lhs_end) { + if (tkn_lhs_end >= src_end) throw Fail(tkn_lhs_end, "early eos"); + byte b = src[tkn_lhs_end]; + int tkn_rhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_rhs, tkn_lhs_end, src_end); + if (tkn_rhs_bgn == Bry_find_.Not_found) throw Fail(tkn_lhs_end, "dangling tkn"); + byte[] tkn_val = Bry_.Mid(src, tkn_lhs_end, tkn_rhs_bgn); + Mustache_elem_itm elem = null; + byte rhs_chk_byte = Byte_ascii.Null; + switch (b) { + default: elem = new Mustache_elem_variable(tkn_val); break; + case Mustache_tkn_def.Comment: elem = new Mustache_elem_comment(tkn_val); break; + case Mustache_tkn_def.Partial: elem = new Mustache_elem_partial(tkn_val); break; + case Mustache_tkn_def.Delimiter_bgn: elem = new Mustache_elem_delimiter(tkn_val); rhs_chk_byte = Mustache_tkn_def.Delimiter_end; break; // TODO: change tkn_def{{=<% %>=}} + case Mustache_tkn_def.Escape_bgn: elem = new Mustache_elem_escape(tkn_val); rhs_chk_byte = Mustache_tkn_def.Escape_end; break; + case Mustache_tkn_def.Section: elem = new Mustache_elem_section(tkn_val); break; + case Mustache_tkn_def.Inverted: elem = new Mustache_elem_inverted(tkn_val); break; + case Mustache_tkn_def.Grp_end: break; + } + subs_list.Add(elem); + if (rhs_chk_byte != Byte_ascii.Null) { + if (src[tkn_rhs_bgn] != rhs_chk_byte) throw Fail(tkn_lhs_end, "invalid check byte"); + ++tkn_rhs_bgn; + } + return tkn_rhs_bgn + tkn_def.Variable_rhs_len; + } + private Err Fail(int pos, String fmt, Object... args) { + return Err_.new_("mustache", fmt, "excerpt", Bry_.Mid_by_len_safe(src, pos, 32)); + } +} +class Mustache_tkn_def { + public byte[] Variable_lhs = Dflt_variable_lhs; + public byte[] Variable_rhs = Dflt_variable_rhs; + public int Variable_lhs_len; + public int Variable_rhs_len; + public static final byte[] + Dflt_variable_lhs = Bry_.new_a7("{{") + , Dflt_variable_rhs = Bry_.new_a7("}}") + ; + public static final byte + Escape_bgn = Byte_ascii.Curly_bgn // {{{escape}}} + , Escape_end = Byte_ascii.Curly_end // {{{escape}}} + , Section = Byte_ascii.Hash // {{#section}} + , Grp_end = Byte_ascii.Slash // {{/section}} + , Inverted = Byte_ascii.Pow // {{^inverted}} + , Comment = Byte_ascii.Bang // {{!comment}} + , Partial = Byte_ascii.Angle_bgn // {{>partial}} + , Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}} + , Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}} + ; + public Mustache_tkn_def() { + Variable_lhs_len = Variable_lhs.length; + Variable_rhs_len = Variable_rhs.length; + } +} +/* +root +txt +key +txt +section + txt + key + txt +txt +*/ diff --git a/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser_tst.java b/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser_tst.java new file mode 100644 index 000000000..972469777 --- /dev/null +++ b/400_xowa/src/gplx/langs/mustaches/Mustache_itm_parser_tst.java @@ -0,0 +1,39 @@ +/* +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.langs.mustaches; import gplx.*; import gplx.langs.*; +import org.junit.*; +public class Mustache_itm_parser_tst { + private final Mustache_itm_parser_fxt fxt = new Mustache_itm_parser_fxt(); + @Test public void Basic() { + fxt.Test_parse("a{{b}}c", "ac"); + } + @Test public void Comment() { + fxt.Test_parse("a{{!b}}c", "ac"); + } +} +class Mustache_itm_parser_fxt { + private final Mustache_itm_parser parser = new Mustache_itm_parser(); + private final Mustache_render_ctx ctx = new Mustache_render_ctx(); + private final Bry_bfr tmp_bfr = Bry_bfr.new_(); + public void Test_parse(String src_str, String expd) { + byte[] src_bry = Bry_.new_a7(src_str); + Mustache_elem_itm actl_itm = parser.Parse(src_bry, 0, src_bry.length); + actl_itm.Render(tmp_bfr, ctx); + Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_clear()); + } +} diff --git a/400_xowa/src/gplx/langs/mustaches/Mustache_render_ctx.java b/400_xowa/src/gplx/langs/mustaches/Mustache_render_ctx.java new file mode 100644 index 000000000..489bde598 --- /dev/null +++ b/400_xowa/src/gplx/langs/mustaches/Mustache_render_ctx.java @@ -0,0 +1,32 @@ +/* +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.langs.mustaches; import gplx.*; import gplx.langs.*; +class Mustache_render_ctx { + private Mustache_doc_itm doc; + public void Init_dom_doc(Mustache_doc_itm doc) {this.doc = doc;} + public byte[] Render_variable(byte[] key) { + byte[] rv = Mustache_doc_itm_.Null_val; + Mustache_doc_itm cur = doc; + while (cur != Mustache_doc_itm_.Null_itm) { + rv = doc.Get_by_key(key); + if (rv != Mustache_doc_itm_.Null_val) break; + cur = cur.Get_owner(); + } + return rv; + } +} diff --git a/400_xowa/src/gplx/xowa/Xoa_app_.java b/400_xowa/src/gplx/xowa/Xoa_app_.java index 5fd7d284d..1576957e3 100644 --- a/400_xowa/src/gplx/xowa/Xoa_app_.java +++ b/400_xowa/src/gplx/xowa/Xoa_app_.java @@ -34,7 +34,7 @@ public class Xoa_app_ { } } public static final String Name = "xowa"; - public static final String Version = "3.1.3.1"; + public static final String Version = "3.1.4.1"; public static String Build_date = "2012-12-30 00:00:00"; public static String Op_sys_str; public static String User_agent = ""; diff --git a/400_xowa/src/gplx/xowa/bldrs/Xob_cmd_mgr.java b/400_xowa/src/gplx/xowa/bldrs/Xob_cmd_mgr.java index cd0046201..47fff3d4b 100644 --- a/400_xowa/src/gplx/xowa/bldrs/Xob_cmd_mgr.java +++ b/400_xowa/src/gplx/xowa/bldrs/Xob_cmd_mgr.java @@ -19,6 +19,7 @@ package gplx.xowa.bldrs; import gplx.*; import gplx.xowa.*; import gplx.core.primitives.*; import gplx.xowa.wikis.*; import gplx.xowa.xtns.wdatas.imports.*; import gplx.xowa.bldrs.cmds.texts.*; import gplx.xowa.bldrs.cmds.texts.sqls.*; import gplx.xowa.bldrs.cmds.texts.tdbs.*; import gplx.xowa.bldrs.cmds.files.*; import gplx.xowa.bldrs.cmds.ctgs.*; import gplx.xowa.bldrs.cmds.utils.*; import gplx.xowa.bldrs.cmds.wikis.*; +import gplx.xowa.bldrs.cmds.diffs.*; import gplx.xowa.files.origs.*; import gplx.xowa.htmls.core.bldrs.*; public class Xob_cmd_mgr implements GfoInvkAble { public Xob_cmd_mgr(Xob_bldr bldr) {this.bldr = bldr;} private Xob_bldr bldr; @@ -76,6 +77,7 @@ public class Xob_cmd_mgr implements GfoInvkAble { else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_tdb_core_term)) return Add(new Xob_term_txt(bldr, wiki)); else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_tdb_text_wdata_qid)) return Xml_rdr_direct_add(wiki, new Xob_wdata_qid_txt().Ctor(bldr, wiki)); else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_tdb_text_wdata_pid)) return Xml_rdr_direct_add(wiki, new Xob_wdata_pid_txt().Ctor(bldr, wiki)); + else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_diff_build)) return Add(new Xob_diff_build_cmd(bldr, wiki)); else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_diff_regy_exec)) return Add(new Xob_diff_regy_exec_cmd(bldr, wiki)); else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_diff_regy_make)) return Add(new Xob_diff_regy_make_cmd(bldr, wiki)); else if (String_.Eq(cmd_key, Xob_cmd_keys.Key_exec_sql)) return Add(new Xob_exec_sql_cmd(bldr, wiki)); diff --git a/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Bfr_arg__dump_dir.java b/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Bfr_arg__dump_dir.java index 69470ee30..e1c734cc6 100644 --- a/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Bfr_arg__dump_dir.java +++ b/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Bfr_arg__dump_dir.java @@ -17,7 +17,7 @@ along with this program. If not, see . */ package gplx.xowa.bldrs.cmds.diffs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*; import gplx.core.brys.*; import gplx.xowa.wikis.*; -class Bfr_arg__dump_dir implements Bfr_arg { // .dump_dir = "C:\xowa\wiki\en.wikipedia.org" +class Bfr_arg__dump_dir implements Bfr_arg { // .dump_dir = "/xowa/wiki/en.wikipedia.org/" private final Xow_wiki wiki; public Bfr_arg__dump_dir(Xow_wiki wiki) {this.wiki = wiki;} public void Bfr_arg__add(Bry_bfr bfr) { @@ -28,7 +28,7 @@ class Bfr_arg__dump_core implements Bfr_arg {// .dump_core = "en.wikipedia.org-c private final Xow_wiki wiki; public Bfr_arg__dump_core(Xow_wiki wiki) {this.wiki = wiki;} public void Bfr_arg__add(Bry_bfr bfr) { - bfr.Add(wiki.Data__core_mgr().Db__core().Url().RawBry()); + bfr.Add_str_u8(wiki.Data__core_mgr().Db__core().Url().NameAndExt()); } } class Bfr_arg__dump_domain implements Bfr_arg {// .dump_domain = en.wikipedia.org @@ -38,3 +38,8 @@ class Bfr_arg__dump_domain implements Bfr_arg {// .dump_domain = en.wikipedia.or bfr.Add(wiki.Domain_bry()); } } +class Bfr_arg__dir_spr implements Bfr_arg {// .dir_spr = "/" + public void Bfr_arg__add(Bry_bfr bfr) { + bfr.Add_byte(gplx.core.envs.Op_sys.Cur().Fsys_dir_spr_byte()); + } +} diff --git a/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Xob_diff_build_wkr.java b/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Xob_diff_build_wkr.java index ce24842f8..f99729a2f 100644 --- a/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Xob_diff_build_wkr.java +++ b/400_xowa/src/gplx/xowa/bldrs/cmds/diffs/Xob_diff_build_wkr.java @@ -20,37 +20,39 @@ import gplx.core.brys.*; import gplx.core.brys.fmtrs.*; import gplx.dbs.*; import gplx.dbs.metas.*; import gplx.dbs.diffs.*; import gplx.dbs.diffs.builds.*; class Xob_diff_build_wkr { private final Gfdb_diff_bldr dif_bldr = new Gfdb_diff_bldr(); - private Db_conn prv_conn, cur_conn, dif_conn; - public Xob_diff_build_wkr(Xob_bldr bldr, Xowe_wiki wiki, String prv_url, String cur_url, String dif_url, int commit_interval) { + private Db_conn old_conn, new_conn, dif_conn; + public Xob_diff_build_wkr(Xob_bldr bldr, Xowe_wiki wiki, String old_url, String new_url, String dif_url, int commit_interval) { + wiki.Init_by_wiki(); Bry_fmt url_fmt = Bry_fmt.New("").Args_(New_url_args(wiki)); Bry_bfr tmp_bfr = Bry_bfr.new_(); - prv_conn = New_conn(Bool_.N, wiki, url_fmt, prv_url, tmp_bfr); - cur_conn = New_conn(Bool_.N, wiki, url_fmt, cur_url, tmp_bfr); + old_conn = New_conn(Bool_.N, wiki, url_fmt, old_url, tmp_bfr); + new_conn = New_conn(Bool_.N, wiki, url_fmt, new_url, tmp_bfr); dif_conn = New_conn(Bool_.Y, wiki, url_fmt, dif_url, tmp_bfr); - Tfds.Dbg(prv_conn, cur_conn, dif_conn); } public void Exec() { Gfdb_diff_db dif_db = new Gfdb_diff_db(dif_conn); Gfdb_diff_wkr__db dif_wkr = new Gfdb_diff_wkr__db(); dif_wkr.Init_conn(dif_db, 1000); dif_bldr.Init(dif_wkr); - Dbmeta_tbl_mgr prv_tbl_mgr = prv_conn.Meta_tbl_load_all(); - Dbmeta_tbl_mgr cur_tbl_mgr = prv_conn.Meta_tbl_load_all(); - int cur_tbl_len = cur_tbl_mgr.Len(); - for (int i = 0; i < cur_tbl_len; ++i) { - Dbmeta_tbl_itm cur_tbl = cur_tbl_mgr.Get_at(i); - Dbmeta_tbl_itm prv_tbl = prv_tbl_mgr.Get_by(cur_tbl.Name()); if (prv_tbl == null) continue; - Gfdb_diff_tbl dif_tbl = Gfdb_diff_tbl.New(cur_tbl); - dif_bldr.Compare(dif_tbl, prv_conn, cur_conn); - } - int prv_tbl_len = prv_tbl_mgr.Len(); - for (int i = 0; i < prv_tbl_len; ++i) { - Dbmeta_tbl_itm prv_tbl = prv_tbl_mgr.Get_at(i); - Dbmeta_tbl_itm cur_tbl = cur_tbl_mgr.Get_by(prv_tbl.Name()); - if (cur_tbl == null) { - // delete all - } + Dbmeta_tbl_mgr old_tbl_mgr = old_conn.Meta_tbl_load_all(); + Dbmeta_tbl_mgr new_tbl_mgr = old_conn.Meta_tbl_load_all(); + int new_tbl_len = new_tbl_mgr.Len(); + int txn = -1; + for (int i = 0; i < new_tbl_len; ++i) { + Dbmeta_tbl_itm new_tbl = new_tbl_mgr.Get_at(i); + Dbmeta_tbl_itm old_tbl = old_tbl_mgr.Get_by(new_tbl.Name()); if (old_tbl == null) continue; + Gfdb_diff_tbl dif_tbl = Gfdb_diff_tbl.New(new_tbl); + dif_bldr.Compare(++txn, dif_tbl, old_conn, new_conn); + // save txn } +// int old_tbl_len = old_tbl_mgr.Len(); +// for (int i = 0; i < old_tbl_len; ++i) { +// Dbmeta_tbl_itm old_tbl = old_tbl_mgr.Get_at(i); +// Dbmeta_tbl_itm new_tbl = new_tbl_mgr.Get_by(old_tbl.Name()); +// if (new_tbl == null) { +// // delete all +// } +// } } public static Db_conn New_conn(boolean autocreate, Xow_wiki wiki, Bry_fmt fmtr, String url_fmt, Bry_bfr tmp_bfr) { fmtr.Fmt_(url_fmt).Bld_bfr_many(tmp_bfr); @@ -61,10 +63,11 @@ class Xob_diff_build_wkr { { new Bfr_fmt_arg(Bry_.new_a7(".dump_dir"), new Bfr_arg__dump_dir(wiki)) , new Bfr_fmt_arg(Bry_.new_a7(".dump_core"), new Bfr_arg__dump_core(wiki)) , new Bfr_fmt_arg(Bry_.new_a7(".dump_domain"), new Bfr_arg__dump_domain(wiki)) + , new Bfr_fmt_arg(Bry_.new_a7(".dir_spr"), new Bfr_arg__dir_spr()) }; return rv; } - //prv_url='~{.dump_dir}-prev/~{.dump_core}'; - //cur_url='~{.dump_dir}/~{.dump_core}'; + //old_url='~{.dump_dir}-prev/~{.dump_core}'; + //new_url='~{.dump_dir}/~{.dump_core}'; //dif_url='~{.dump_dir}/~{.dump_domain}-diff.xowa'; } diff --git a/400_xowa/src/gplx/xowa/bldrs/wms/sites/Site_meta_parser__general.java b/400_xowa/src/gplx/xowa/bldrs/wms/sites/Site_meta_parser__general.java index dab8149b5..4c147b91f 100644 --- a/400_xowa/src/gplx/xowa/bldrs/wms/sites/Site_meta_parser__general.java +++ b/400_xowa/src/gplx/xowa/bldrs/wms/sites/Site_meta_parser__general.java @@ -240,7 +240,7 @@ class Site_meta_parser__showhook extends Json_parser__list_nde__base { int atr_len = subscribers_nde.Len(); for (int j = 0; j < atr_len; ++j) { Json_kv atr = subscribers_nde.Get_at_as_kv(j); - if (!Bry_.Eq(atr.Key_as_bry(), Key__scribunto)) {Warn("unknown key", atr); continue;} + if (!Bry_.Eq(atr.Key_as_bry(), Key__scribunto)) {Warn("unknown subscriber key", atr); continue;} scribunto = atr.Val_as_bry(); } } diff --git a/400_xowa/src/gplx/xowa/drds/Xod_app.java b/400_xowa/src/gplx/xowa/drds/Xod_app.java index 9a61799ac..44fe6f4e5 100644 --- a/400_xowa/src/gplx/xowa/drds/Xod_app.java +++ b/400_xowa/src/gplx/xowa/drds/Xod_app.java @@ -20,6 +20,7 @@ import gplx.xowa.drds.pages.*; import gplx.xowa.drds.files.*; import gplx.xowa.apps.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.wikis.nss.*; import gplx.xowa.files.gui.*; import gplx.xowa.specials.search.*; import gplx.xowa.specials.randoms.*; +import gplx.langs.htmls.encoders.*; import gplx.xowa.htmls.hrefs.*; public class Xod_app { private final Xoav_app app; private final Xod_page_mgr page_mgr = new Xod_page_mgr(); @@ -27,10 +28,6 @@ public class Xod_app { public Xod_app(Xoav_app app) { this.app = app; } - public int Wikis__count() { - int rv = app.Wiki_mgri().Count(); - return rv - 1; // ignore home wiki - } public Xow_wiki Wikis__get_by_domain(String wiki_domain) { Xow_wiki rv = app.Wiki_mgri().Get_by_or_make_init_y(Bry_.new_u8(wiki_domain)); if (rv != null && rv.Data__core_mgr() == null) rv.Init_by_wiki(); @@ -54,7 +51,20 @@ public class Xod_app { } return rv; } + public void Wiki__search(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, String search, Xod_search_cmd[] cmds) { + for (Xod_search_cmd cmd : cmds) + cmd.Search(cancelable, wiki, ui_async, search); + } public void Page__load_files(Xow_wiki wiki, Xod_page_itm pg, Xog_js_wkr js_wkr) { file_mgr.Load_files(wiki, pg, js_wkr); + app.User().User_db_mgr().Cache_mgr().Db_save(); + } + public static byte[] To_page_url(Xow_wiki wiki, String canonical_str) {// NOTE: need canonical_url to handle "A:B" where "A:" is not a ns, even though PageTitle treats "A:" as a namespace + byte[] canonical_bry = Bry_.new_u8(canonical_str); + int page_bgn = Bry_find_.Move_fwd(canonical_bry, Xoh_href_.Bry__wiki, 0); if (page_bgn == Bry_find_.Not_found) throw Err_.new_("drd", "uknown url format: no '/wiki/'", "url", canonical_bry); + byte[] page_bry = Bry_.Mid(canonical_bry, page_bgn, canonical_bry.length); // get bry; EX: https://en.wikipedia.org/wiki/A -> A + page_bry = Gfo_url_encoder_.Http_url.Decode(page_bry); // decode %-encoding; convert + to space + page_bry = Xoa_ttl.Replace_spaces(page_bry); // convert spaces to unders; canonical-url has spaces + return page_bry; } } diff --git a/400_xowa/src/gplx/xowa/drds/Xod_app_tst.java b/400_xowa/src/gplx/xowa/drds/Xod_app_tst.java index 5a30a172b..d99dc32e4 100644 --- a/400_xowa/src/gplx/xowa/drds/Xod_app_tst.java +++ b/400_xowa/src/gplx/xowa/drds/Xod_app_tst.java @@ -25,6 +25,14 @@ public class Xod_app_tst { tstr.Data_mgr().Html__insert(1, "abc"); tstr.Test__get("A", tstr.Make_page(1, "A", "2015-10-19T00:01:02Z", tstr.Make_section(0, 2, "", "", "abc"))); } + @Test public void To_page_db() { + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/A" , "A"); + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/A:B" , "A:B"); + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/Help:A" , "Help:A"); + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/A B" , "A_B"); // NOTE:canonical url has spaces; + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/A%27B" , "A'B"); // NOTE:canonical url has percent-encoding; + tstr.Test__to_page_url("http://en.wikipedia.org/wiki/A+B" , "A_B"); // NOTE:canonical url sometimes has "+" for space + } } class Xod_app_tstr { private final gplx.xowa.apps.Xoav_app app; private final Xowv_wiki wiki; @@ -46,6 +54,10 @@ class Xod_app_tstr { Xod_page_itm itm = drd_provider.Wiki__get_by_url(wiki, page_url); Tfds.Eq(expd.To_str(), itm.To_str()); } + public void Test__to_page_url(String raw, String expd) { + // // canonical url has spaces as well as %-encoding; PAGE:en.w:List_of_Fire_Emblem:Shadow_Dragon_characters + Tfds.Eq_bry(Bry_.new_u8(expd), Xod_app.To_page_url(wiki, raw)); + } public Xod_page_itm Make_page(int page_id, String ttl, String modified_on, Xoh_section_itm... section_ary) { Xod_page_itm rv = new Xod_page_itm(); rv.Init(page_id, page_id, ttl, ttl, null, null, modified_on, Bool_.N, Bool_.N, Bool_.N, 1, null, null, null); diff --git a/400_xowa/src/gplx/xowa/drds/Xod_search_cmd.java b/400_xowa/src/gplx/xowa/drds/Xod_search_cmd.java new file mode 100644 index 000000000..815c00d0c --- /dev/null +++ b/400_xowa/src/gplx/xowa/drds/Xod_search_cmd.java @@ -0,0 +1,22 @@ +/* +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.drds; import gplx.*; import gplx.xowa.*; +import gplx.xowa.specials.search.*; +public interface Xod_search_cmd { + void Search(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, String search); +} diff --git a/400_xowa/src/gplx/xowa/drds/Xod_search_cmd_.java b/400_xowa/src/gplx/xowa/drds/Xod_search_cmd_.java new file mode 100644 index 000000000..fd33b040f --- /dev/null +++ b/400_xowa/src/gplx/xowa/drds/Xod_search_cmd_.java @@ -0,0 +1,74 @@ +/* +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.drds; import gplx.*; import gplx.xowa.*; +import gplx.xowa.specials.search.*; +import gplx.xowa.wikis.data.tbls.*; +public class Xod_search_cmd_ { + public static final Xod_search_cmd + New__page_eq = Xod_search_cmd__page_eq.Instance + , New__page_like = Xod_search_cmd__page_like.Instance + , New__word_eq = Xod_search_cmd__word_tbl.Instance_eq + , New__word_like = Xod_search_cmd__word_tbl.Instance_like + ; +} +class Xod_search_cmd__page_eq implements Xod_search_cmd { + public void Search(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, String search) { + Xowd_page_itm page_itm = new Xowd_page_itm(); + if (wiki.Data__core_mgr().Tbl__page().Select_by_ttl(page_itm, wiki.Ns_mgr().Ns_main(), Bry_.Ucase__1st(Bry_.new_u8(search)))) { + Xows_db_row search_itm = new Xows_db_row(wiki.Domain_bry(), wiki.Ttl_parse(page_itm.Ttl_page_db()), page_itm.Id(), page_itm.Text_len()); + ui_async.Add(search_itm); + } + } + public static final Xod_search_cmd__page_eq Instance = new Xod_search_cmd__page_eq(); Xod_search_cmd__page_eq() {} +} +class Xod_search_cmd__page_like implements Xod_search_cmd {// NOTE: slow; takes at least 10+ seconds + public void Search(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, String search) { + List_adp tmp_list = List_adp_.new_(); + wiki.Data__core_mgr().Tbl__page().Select_by_search(cancelable, tmp_list, Bry_.Ucase__1st(Bry_.new_u8(search + "*")), 50); + int len = tmp_list.Count(); + for (int i = 0; i < len; ++i) { + Xowd_page_itm page_itm = (Xowd_page_itm)tmp_list.Get_at(i); + Xows_db_row search_itm = new Xows_db_row(wiki.Domain_bry(), wiki.Ttl_parse(page_itm.Ttl_page_db()), page_itm.Id(), page_itm.Text_len()); + ui_async.Add(search_itm); + } + } + public static final Xod_search_cmd__page_like Instance = new Xod_search_cmd__page_like(); Xod_search_cmd__page_like() {} +} +class Xod_search_cmd__word_tbl implements Xod_search_cmd { + private final boolean wildcard; + private final int results_wanted; + private final Xows_db_wkr search_wkr = new Xows_db_wkr(); + Xod_search_cmd__word_tbl(boolean wildcard, int results_wanted) {this.wildcard = wildcard; this.results_wanted = results_wanted;} + public void Search(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, String search) { + search_wkr.Search_by_drd(cancelable, wiki, ui_async, Bry_.new_u8(Standardize_search(search, wildcard)), results_wanted); + } + public static final Xod_search_cmd__word_tbl Instance_eq = new Xod_search_cmd__word_tbl(Bool_.N, 10), Instance_like = new Xod_search_cmd__word_tbl(Bool_.Y, 50); + private static String Standardize_search(String search, boolean wildcard) { + String rv = ""; + String[] words = String_.Split(search, " "); + int words_len = words.length; + for (int i = 0; i < words_len; ++i) { + String word = words[i]; + if (String_.Len(word) < 3) continue; + if (String_.Len(rv) != 0) rv += " "; + rv += word; + if (wildcard) rv += "*"; + } + return rv; + } +} diff --git a/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java b/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java index 7e71a9d17..ebbdb2304 100644 --- a/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java +++ b/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java @@ -24,15 +24,30 @@ public class Xof_file_wkr_ { ttl = Md5_decoder.Decode(Ttl_standardize(ttl)); return Xof_file_wkr_.Md5_fast(ttl); // NOTE: md5 is calculated off of url_decoded ttl; EX: A%2Cb is converted to A,b and then md5'd. note that A%2Cb still remains the title } - public static byte[] Ttl_standardize(byte[] ttl) { - int ttl_len = ttl.length; - for (int i = 0; i < ttl_len; i++) { // convert all spaces to _; NOTE: not same as lnki.Ttl().Page_url(), b/c Page_url does incompatible encoding - byte b = ttl[i]; - if (b == Byte_ascii.Space) ttl[i] = Byte_ascii.Underline; - if (i == 0) { - if (b > 96 && b < 123) ttl[i] -= 32; // NOTE: file automatically uppercases 1st letter + public static byte[] Ttl_standardize(byte[] src) { + int len = src.length; if (len == 0) return src; + byte[] rv = null; + boolean dirty = false; + byte b = src[0]; + if (b > 96 && b < 123) { + dirty = true; + rv = new byte[len]; + rv[0] = (byte)(b - 32); // NOTE: [[File:]] automatically uppercases 1st letter for md5; EX:en.d:File:wikiquote-logo.png has md5 of "32" (W...) not "82" (w...); PAGE:en.d:freedom_of_speech DATE:2016-01-21 + } + for (int i = 1; i < len; ++i) { + b = src[i]; + if (b == Byte_ascii.Space) { + if (!dirty) { + dirty = true; + rv = new byte[len]; Bry_.Copy_by_pos(src, 0, i, rv, 0); + } + rv[i] = Byte_ascii.Underline; + } + else { + if (dirty) + rv[i] = b; } } - return ttl; + return dirty ? rv : src; } } diff --git a/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java b/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java new file mode 100644 index 000000000..4cd780a4a --- /dev/null +++ b/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java @@ -0,0 +1,33 @@ +/* +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.files; import gplx.*; import gplx.xowa.*; +import org.junit.*; +public class Xof_file_wkr__tst { + private final Xof_file_wkr___fxt fxt = new Xof_file_wkr___fxt(); + @Test public void Ttl_standardize() { + fxt.Test__ttl_standardize("Abc.png" , "Abc.png"); // basic + fxt.Test__ttl_standardize("A b.png" , "A_b.png"); // spaces -> unders + fxt.Test__ttl_standardize("A b c.png" , "A_b_c.png"); // spaces -> unders; multiple + fxt.Test__ttl_standardize("abc.png" , "Abc.png"); // ucase 1st + } +} +class Xof_file_wkr___fxt { + public void Test__ttl_standardize(String src_str, String expd) { + Tfds.Eq_bry(Bry_.new_u8(expd), Xof_file_wkr_.Ttl_standardize(Bry_.new_u8(src_str))); + } +} diff --git a/400_xowa/src/gplx/xowa/files/Xof_url_bldr_tst.java b/400_xowa/src/gplx/xowa/files/Xof_url_bldr_tst.java index 863735cc3..331702ec7 100644 --- a/400_xowa/src/gplx/xowa/files/Xof_url_bldr_tst.java +++ b/400_xowa/src/gplx/xowa/files/Xof_url_bldr_tst.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.files; import gplx.*; import gplx.xowa.*; -import org.junit.*; import gplx.xowa.files.*; import gplx.xowa.files.repos.*; +import org.junit.*; import gplx.xowa.files.repos.*; public class Xof_url_bldr_tst { private Xof_url_bldr_fxt fxt = new Xof_url_bldr_fxt(); @Before public void init() {fxt.Clear();} diff --git a/400_xowa/src/gplx/xowa/htmls/core/htmls/utls/Xoh_lnki_wtr_utl.java b/400_xowa/src/gplx/xowa/htmls/core/htmls/utls/Xoh_lnki_wtr_utl.java deleted file mode 100644 index 5a83588bf..000000000 --- a/400_xowa/src/gplx/xowa/htmls/core/htmls/utls/Xoh_lnki_wtr_utl.java +++ /dev/null @@ -1,34 +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 . -*/ -package gplx.xowa.htmls.core.htmls.utls; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.htmls.*; -import gplx.langs.htmls.*; import gplx.xowa.htmls.hrefs.*; import gplx.xowa.htmls.core.htmls.*; -public class Xoh_lnki_wtr_utl { - private final Xoa_app app; private final Xow_wiki wiki; private final Xoh_href_wtr href_wtr; private final Bry_bfr tmp_bfr = Bry_bfr.new_(255); - public Xoh_lnki_wtr_utl(Xow_wiki wiki, Xoh_href_wtr href_wtr) { - this.app = wiki.App(); - this.wiki = wiki; this.href_wtr = href_wtr; - } - public byte[] Bld_href(byte[] page) {return Bld_href(wiki.Domain_bry(), wiki.Ttl_parse(page));} - public byte[] Bld_href(byte[] domain_bry, Xoa_ttl ttl) { - href_wtr.Build_to_bfr(tmp_bfr, app, Xoh_wtr_ctx.Mode_popup, domain_bry, ttl); - return tmp_bfr.To_bry_and_clear(); - } - public byte[] Bld_title(byte[] text) { - return gplx.langs.htmls.Gfh_utl.Escape_html_as_bry(tmp_bfr, text, Bool_.N, Bool_.N, Bool_.N, Bool_.Y, Bool_.Y); - } -} diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/Xoh_hdoc_ctx.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/Xoh_hdoc_ctx.java index 599f9d719..e195c1163 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/Xoh_hdoc_ctx.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/Xoh_hdoc_ctx.java @@ -48,8 +48,8 @@ public class Xoh_hdoc_ctx { this.fsys__root = fsys_mgr.Root_dir().To_http_file_bry(); this.fsys__file = fsys_mgr.File_dir().To_http_file_bry(); this.fsys__file__comm = Bry_.Add(fsys__file, Xow_domain_itm_.Bry__commons, Byte_ascii.Slash_bry); - Xou_cache_mgr cache_mgr = app.User().User_db_mgr().Cache_mgr(); - if (cache_mgr != null) file__mgr = Xou_cache_finder_.New_db(cache_mgr); // NOTE: this effectively only loads the cache db in app mode (and not in test mode) + // Xou_cache_mgr cache_mgr = app.User().User_db_mgr().Cache_mgr(); + // if (cache_mgr != null) file__mgr = Xou_cache_finder_.New_db(cache_mgr); // NOTE: this effectively only loads the cache db in app mode (and not in test mode) pool_mgr__hzip.Init(); } public void Init_by_page(Xow_wiki wiki, byte[] page_url) { diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_data.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_data.java index b71ccff65..fd01a47bd 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_data.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_data.java @@ -42,9 +42,10 @@ public class Xoh_hdr_data implements Xoh_data_itm { Gfh_atr anch_atr = span_head.Atrs__get_by_or_fail(Gfh_atr_.Bry__id); this.anch_bgn = anch_atr.Val_bgn(); this.anch_end = anch_atr.Val_end(); this.capt_bgn = span_head.Src_end(); - Gfh_tag hdr_tail = tag_rdr.Tag__move_fwd_tail(hdr_level); // find not since can be nested, but

cannot - Gfh_tag span_tail = tag_rdr.Tag__peek_bwd_tail(Gfh_tag_.Id__span); // get before

+ Gfh_tag hdr_tail = tag_rdr.Tag__move_fwd_tail(hdr_level); // find not since can be nested, but

cannot + Gfh_tag span_tail = tag_rdr.Tag__peek_bwd_tail(Gfh_tag_.Id__span); // get before

this.capt_end = span_tail.Src_bgn(); + if (capt_end < src_bgn) return false; //
is before ; occurs b/c TIDY will relocate out of if has center; PAGE:en.s:On_the_Vital_Principle/Book_2/Prelude_to_Chapter_2; DATE:2016-01-21 if (span_tail.Src_end() != hdr_tail.Src_bgn()) { capt_rhs_bgn = span_tail.Src_end(); capt_rhs_end = hdr_tail.Src_bgn(); } diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_hzip_tst.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_hzip_tst.java index 43263c419..23506f52d 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_hzip_tst.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/hdrs/Xoh_hdr_hzip_tst.java @@ -70,4 +70,25 @@ public class Xoh_hdr_hzip_tst { , "
AB
" ); } + @Test public void Tidy__no_span() { // PURPOSE.TIDY: tidy will duplicate hdr if content has center; will fail if span/div is nearby; EX: ==
A
==\n
; PAGE:en.s:On_the_Vital_Principle/Book_2/Prelude_to_Chapter_2 DATE:2016-01-21 + fxt.Test__encode(String_.Concat_lines_nl_skip_last + ( "\"+A" + , "
" + , "

A

" + , "
" + , "" + , "
" + , "

abc

" + , "
" + ), String_.Concat_lines_nl_skip_last + ( "

" + , "
" + , "

A

" + , "
" + , "" + , "
" + , "

abc

" + , "
" + )); + } } diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip.java index f4a3ddc5d..be065e38f 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip.java @@ -218,7 +218,7 @@ public class Xoh_img_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { tmp_bfr.Add(Xoh_href_.Bry__wiki).Add(page_ttl_bry); } else { - byte[] ns_bry = anch__ns_is_custom ? ns_custom_bry : Xow_ns_.Bry__file; + byte[] ns_bry = anch__ns_is_custom ? ns_custom_bry : hctx.Wiki__ttl_parser().Ns_mgr().Ns_file().Name_db(); tmp_bfr.Add(Xoh_href_.Bry__wiki).Add(ns_bry).Add_byte_colon(); tmp_bfr.Add(page_db); // Gfo_url_encoder_.Href.Encode(tmp_bfr, page_db); // encode needed for ?; PAGE:en.w:Voiceless_alveolar_affricate; DATE:2016-01-04 diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip__dump__tst.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip__dump__tst.java index 82975463a..01c1b9b00 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip__dump__tst.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/imgs/Xoh_img_hzip__dump__tst.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.htmls.core.wkrs.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; -import org.junit.*; import gplx.xowa.htmls.core.hzips.*; +import org.junit.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.wikis.nss.*; public class Xoh_img_hzip__dump__tst { private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_(); @Before public void Clear() {fxt.Clear();} @@ -60,6 +60,29 @@ public class Xoh_img_hzip__dump__tst { String html = "
\"A'b_capt\""; fxt.Test__bicode_raw("~%#oA%27b_link~A'b.png~#)#SA'b_capt~", html, html); } + @Test public void Href__image() { // [[Image:A.png|abc]] + fxt.Test__bicode + ( "~%-%A.png~Image~)#Sabc~" + , "abc" + ); + } + @Test public void Ns__cs() { // [[image:a.png|abc]]; PAGE:en.d:freedom_of_speech DATE:2016-01-21 + fxt.Wiki().Ns_mgr().Ns_file().Case_match_(gplx.xowa.wikis.nss.Xow_ns_case_.Tid__all); + fxt.Test__bicode + ( "~%-%a.png~image~)#Sabc~" + , "abc" + ); + fxt.Wiki().Ns_mgr().Ns_file().Case_match_(gplx.xowa.wikis.nss.Xow_ns_case_.Tid__1st); + } + @Test public void Ns__foreign() { // [[Fichier:a.png|abc]]; PAGE:fr.w: DATE:2016-01-21 + Xow_ns_mgr ns_mgr = fxt.Wiki().Ns_mgr(); + ns_mgr.Ns_file().Name_bry_(Bry_.new_u8("Fichier")); ns_mgr.Init_w_defaults(); + fxt.Test__bicode + ( "~%!!a.png~)#Sabc~" + , "abc" + ); + ns_mgr.Ns_file().Name_bry_(Bry_.new_u8("File")); ns_mgr.Init_w_defaults(); + } @Test public void Link__cs() { // [[File:A.png|link=File:a.ogg|abc]] fxt.Test__bicode ( "~%!Aa.ogg~A.png~)#Sabc~" @@ -121,7 +144,7 @@ public class Xoh_img_hzip__dump__tst { ); } @Test public void Link__ns_alias() { // [[File:A.png|link=WP:MCB]]; PAGE:en.w:Wikipedia:WikiProject_Molecular_and_Cell_Biology; DATE:2016-01-11 - fxt.Init__ns_alias__add("WP", gplx.xowa.wikis.nss.Xow_ns_.Tid__project); + fxt.Init__ns_alias__add("WP", Xow_ns_.Tid__project); fxt.Test__bicode ( "~%/+MCB~A.png~'WP~)!q" , "" @@ -134,12 +157,6 @@ public class Xoh_img_hzip__dump__tst { , "" ); } - @Test public void Href__image() { // [[Image:A.png|abc]] - fxt.Test__bicode - ( "~%-%A.png~Image~)#Sabc~" - , "abc" - ); - } @Test public void Missing() { // PURPOSE: bad dump shouldn't write corrupt data fxt.Test__bicode ( "%|\"\\QA.png!!!!A" diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_data.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_data.java index 6a4e7c7c9..5e444e403 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_data.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_data.java @@ -128,7 +128,7 @@ public class Xoh_lnki_data { title_bgn = title_atr.Val_bgn(); title_end = title_atr.Val_end(); if (href_ns_name != null) { // ns_name exists int title_bgn_wo_ns = title_bgn + href_ns_name_len; - if (Bry_.Match(src, title_bgn, title_bgn_wo_ns, href_ns_name)) // title matches ns_name; + if (Bry_.Match(src, title_bgn, title_bgn_wo_ns, href_ns_name)) // title matches href_ns; title_bgn = title_bgn_wo_ns; // skip ns; "Help:" else title_missing_ns = true; @@ -136,7 +136,7 @@ public class Xoh_lnki_data { if (title_end == -1) title_tid = Title__missing; else { - if (Bry_.Match(src, title_bgn, title_end, href_src, href_bgn, href_end)) + if (Bry_.Match(src, title_bgn, title_end, href_src, href_bgn, href_end) && !title_missing_ns) // NOTE: do not mark title=href if href omitted title; PAGE:en.b:Wikibooks:WikiProject; DATE:2016-01-20 title_tid = Title__href; else if (Bry_.Match(src, title_bgn, title_end, src, capt_bgn, capt_end)) title_tid = Title__capt; diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java index 4d06ab4c3..e409dca4b 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java @@ -76,6 +76,7 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { byte href_type = flag_bldr.Get_as_byte(Flag__href_type); int capt_cs0_tid = flag_bldr.Get_as_int(Flag__capt_cs0_tid); byte text_type = flag_bldr.Get_as_byte(Flag__text_type); + // Tfds.Dbg(cls_tid, title_missing_ns, ttl_is_main_page, ns_custom_exists, title_tid, capt_has_ns, ns_is_not_main, href_type, capt_cs0_tid, text_type); int site_bgn = -1, site_end = -1; if (href_type == Xoh_anch_href_data.Tid__site) {site_bgn = rdr.Pos(); site_end = rdr.Find_fwd_lr();} int ns_id = ns_is_not_main ? Xoh_lnki_dict_.Ns_decode(rdr) : Xow_ns_.Tid__main; diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip__ns__tst.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip__ns__tst.java index 0471a90ef..57c4e74c8 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip__ns__tst.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip__ns__tst.java @@ -68,7 +68,8 @@ public class Xoh_lnki_hzip__ns__tst { fxt.Test__bicode("~${3h)Image~A%C3%BC.png~b~Image:Aü.png~", "b"); } @Test public void Ctg__main() { // links at bottom of pages in main ns; DATE:2015-12-28 - fxt.Test__bicode("~$|$t'1A~", "A"); + fxt.Test__bicode("~$|%\"(1A~", "A"); + fxt.Test__decode("~$|$t'1A~", "A"); // NOTE:backward compatibility for en.w:2015-12; delete after 2016-01 is uploaded } @Test public void Ctg__tree() { // links on Category pages; fxt.Test__bicode("~$|&3J1A~", "A"); @@ -79,4 +80,7 @@ public class Xoh_lnki_hzip__ns__tst { @Test public void Ctg__xnav__under() { // previous / next 200 links on Category pages; PAGE:en.w:Category:Public_transit_articles_with_unsupported_infobox_fields; DATE:2016-01-14 fxt.Test__bicode("~$|&`Z1A B?pageuntil=C,_D#mw-pages~previous 200~Category:A_B~", "previous 200"); } + @Test public void Outlier__title_wo_ns() {// should not happen, but handle situation wherein title doesnot have ns PAGE:en.b:Wikibooks:WikiProject DATE:2016-01-20 + fxt.Test__bicode("~${Tr/A B~", "A B"); + } } diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_hzip_tst.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_hzip_tst.java index e89d816fa..6365438d3 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_hzip_tst.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_hzip_tst.java @@ -302,7 +302,7 @@ public class Xoh_thm_hzip_tst { , "
" )); } - @Test public void Dump() { +// @Test public void Dump() { // Xowe_wiki en_d = fxt.Init_wiki_alias("wikt", "en.wiktionary.org"); // gplx.xowa.wikis.nss.Xow_ns_mgr ns_mgr = en_d.Ns_mgr(); // ns_mgr.Ns_main().Case_match_(gplx.xowa.wikis.nss.Xow_ns_case_.Tid__all); @@ -313,5 +313,5 @@ public class Xoh_thm_hzip_tst { // fxt.Init_mode_is_b256_(Bool_.N); // fxt.Exec_write_to_fsys(Io_url_.new_dir_("J:\\xowa\\dev_rls\\html\\"), "debug.html"); // fxt.Init_mode_is_b256_(Bool_.N); - } +// } } diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_wtr.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_wtr.java index c786698b7..0ce492019 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_wtr.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/thms/Xoh_thm_wtr.java @@ -27,11 +27,12 @@ public class Xoh_thm_wtr implements gplx.core.brys.Bfr_arg { private final Bfr_arg__bry_ary div_2_magnify = new Bfr_arg__bry_ary(); private final Bfr_arg__bry capt_2 = Bfr_arg__bry.New(Bry_.Empty); private final Bfr_arg__bry capt_3 = Bfr_arg__bry.New(Bry_.Empty); + private final Bfr_arg__bry enlarge = Bfr_arg__bry.New(Bry_.Empty); private final Bry_bfr tmp_bfr = Bry_bfr.new_(255); private Bfr_arg div_1_img = Bfr_arg_.Noop, capt_1 = Bfr_arg_.Noop; private byte[] img_is_vid_nl, trailing_space; public Xoh_thm_wtr Clear() { - Bfr_arg_.Clear(div_0_align, div_1_id, div_2_href, capt_2, capt_3); // , div_1_width, div_2_magnify + Bfr_arg_.Clear(div_0_align, div_1_id, div_2_href, enlarge, capt_2, capt_3); // , div_1_width, div_2_magnify div_1_img = capt_1 = Bfr_arg_.Noop; img_is_vid_nl = Bry_.Empty; return this; @@ -48,6 +49,11 @@ public class Xoh_thm_wtr implements gplx.core.brys.Bfr_arg { this.div_1_img = img_wtr; this.div_2_href.Set_by_bry(div_2_href); div_2_magnify.Set(hctx.Fsys__root(), bry_div_2_magnify); + Xow_wiki wiki = (Xow_wiki)hctx.Wiki__ttl_parser(); + if (wiki.Type_is_edit()) + enlarge.Set_by_val(wiki.Lang().Msg_mgr().Itm_by_id_or_null(gplx.xowa.langs.msgs.Xol_msg_itm_.Id_file_enlarge).Val()); + else + enlarge.Set_by_val(Bry__enlarge); this.capt_1 = capt_1; if (capt_2_exists) { if (capt_2_is_tidy) @@ -66,15 +72,16 @@ public class Xoh_thm_wtr implements gplx.core.brys.Bfr_arg { this.Bfr_arg__add(bfr); } public void Bfr_arg__add(Bry_bfr bfr) { - fmtr.Bld_bfr_many(bfr, div_0_align, div_1_id, div_1_width, img_is_vid_nl, div_1_img, trailing_space, div_2_href, div_2_magnify, capt_1, capt_2, capt_3); + fmtr.Bld_bfr_many(bfr, div_0_align, div_1_id, div_1_width, img_is_vid_nl, div_1_img, trailing_space, div_2_href, div_2_magnify, enlarge, capt_1, capt_2, capt_3); } + private static final byte[] Bry__enlarge = Bry_.new_a7("Enlarge"); private static final Bry_fmtr fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last ( "
" , "~{img_is_vid_nl}~{div_1_img}~{trailing_space}" // NOTE: trailing space is intentional; matches jtidy behavior , "
" - , "
" + , "
" , "~{capt_1}
~{capt_2}
~{capt_3}" - ), "div_0_align", "div_1_id", "div_1_width", "img_is_vid_nl", "div_1_img", "trailing_space", "div_2_href", "div_2_magnify", "capt_1", "capt_2", "capt_3"); + ), "div_0_align", "div_1_id", "div_1_width", "img_is_vid_nl", "div_1_img", "trailing_space", "div_2_href", "div_2_magnify", "enlarge", "capt_1", "capt_2", "capt_3"); private static final Bry_fmtr alt_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last ( "" , "
" diff --git a/400_xowa/src/gplx/xowa/htmls/css/Xowd_css_core_mgr.java b/400_xowa/src/gplx/xowa/htmls/css/Xowd_css_core_mgr.java index 2daa78977..898d9c754 100644 --- a/400_xowa/src/gplx/xowa/htmls/css/Xowd_css_core_mgr.java +++ b/400_xowa/src/gplx/xowa/htmls/css/Xowd_css_core_mgr.java @@ -44,18 +44,27 @@ public class Xowd_css_core_mgr { catch (Exception e) {conn.Txn_cxl(); throw e;} } public static boolean Get(Xowd_css_core_tbl core_tbl, Xowd_css_file_tbl file_tbl, Io_url css_dir, String key) { - int css_id = core_tbl.Select_id_by_key(key); if (css_id == Xowd_css_core_tbl.Id_null) return false; // unknown key; return false (not found) - Xowd_css_file_itm[] file_list = file_tbl.Select_by_owner(css_id); - // Io_mgr.Instance.DeleteDirDeep(css_dir); // NOTE: do not delete existing files; just overwrite; - int len = file_list.length; - if (len == 0) return false; // no css files in db - for (int i = 0; i < len; ++i) { - Xowd_css_file_itm file = file_list[i]; - Io_url file_url = Io_url_.new_fil_(css_dir.Gen_sub_path_for_os(file.Path())); - if (file.Data() == null) continue; // NOTE: sqlite will return 0 length fields as NULL; if no data, just ignore, else error below - Io_mgr.Instance.SaveFilBry(file_url, file.Data()); - } - return true; + String dbg = "enter"; + try { + int css_id = core_tbl.Select_id_by_key(key); + dbg += ";css_id"; + if (css_id == Xowd_css_core_tbl.Id_null) return false; // unknown key; return false (not found) + dbg += ";select_by_owner"; + Xowd_css_file_itm[] file_list = file_tbl.Select_by_owner(css_id); + dbg += ";file_list:" + file_list.length; + // Io_mgr.Instance.DeleteDirDeep(css_dir); // NOTE: do not delete existing files; just overwrite; + int len = file_list.length; + if (len == 0) return false; // no css files in db + for (int i = 0; i < len; ++i) { + Xowd_css_file_itm file = file_list[i]; + dbg += ";file_url:" + file.Path(); + Io_url file_url = Io_url_.new_fil_(css_dir.Gen_sub_path_for_os(file.Path())); + if (file.Data() == null) continue; // NOTE: sqlite will return 0 length fields as NULL; if no data, just ignore, else error below + Io_mgr.Instance.SaveFilBry(file_url, file.Data()); + dbg += ";file_data:" + file.Data().length; + } + return true; + } catch (Exception e) {throw Err_.new_exc(e, "css", "Xowd_css_core_mgr.Get failed", "dbg", dbg, "err", Err_.Message_gplx_log(e));} } public static final String Key_default = "xowa.default", Key_mobile = "xowa.mobile"; } diff --git a/400_xowa/src/gplx/xowa/langs/Xol_lang_itm_.java b/400_xowa/src/gplx/xowa/langs/Xol_lang_itm_.java index bf656fff7..476328f94 100644 --- a/400_xowa/src/gplx/xowa/langs/Xol_lang_itm_.java +++ b/400_xowa/src/gplx/xowa/langs/Xol_lang_itm_.java @@ -267,5 +267,6 @@ kwd_mgr.New(Bool_.N, Xol_kwd_grp_.Id_pagesincategory_pages, "pagesincategory_pag kwd_mgr.New(Bool_.N, Xol_kwd_grp_.Id_pagesincategory_subcats, "pagesincategory_subcats", "subcats"); kwd_mgr.New(Bool_.N, Xol_kwd_grp_.Id_pagesincategory_files, "pagesincategory_files", "files"); kwd_mgr.New(Bool_.Y, Xol_kwd_grp_.Id_rev_revisionsize, "REVISIONSIZE"); +kwd_mgr.New(Bool_.Y, Xol_kwd_grp_.Id_pagebanner, "PAGEBANNER"); // NOTE: must be casematch; EX:{{pagebanner}} } } diff --git a/400_xowa/src/gplx/xowa/langs/kwds/Xol_kwd_grp_.java b/400_xowa/src/gplx/xowa/langs/kwds/Xol_kwd_grp_.java index a0ecc5bd2..cb45476f0 100644 --- a/400_xowa/src/gplx/xowa/langs/kwds/Xol_kwd_grp_.java +++ b/400_xowa/src/gplx/xowa/langs/kwds/Xol_kwd_grp_.java @@ -229,8 +229,9 @@ public static final int , Id_pagesincategory_subcats = 207 , Id_pagesincategory_files = 208 , Id_rev_revisionsize = 209 +, Id_pagebanner = 210 ; -public static final int Id__max = 210; +public static final int Id__max = 211; private static byte[] ary_itm_(int id) { switch (id) { @@ -444,6 +445,7 @@ case Xol_kwd_grp_.Id_pagesincategory_pages: return Bry_.new_u8("pagesincategory_ case Xol_kwd_grp_.Id_pagesincategory_subcats: return Bry_.new_u8("pagesincategory_subcats"); case Xol_kwd_grp_.Id_pagesincategory_files: return Bry_.new_u8("pagesincategory_files"); case Xol_kwd_grp_.Id_rev_revisionsize: return Bry_.new_u8("revisionsize"); +case Xol_kwd_grp_.Id_pagebanner: return Bry_.new_u8("pagebanner"); default: throw Err_.new_unhandled(id); } } diff --git a/400_xowa/src/gplx/xowa/parsers/utils/Xop_sanitizer.java b/400_xowa/src/gplx/xowa/parsers/utils/Xop_sanitizer.java index 521940c36..62ff86e54 100644 --- a/400_xowa/src/gplx/xowa/parsers/utils/Xop_sanitizer.java +++ b/400_xowa/src/gplx/xowa/parsers/utils/Xop_sanitizer.java @@ -96,6 +96,16 @@ public class Xop_sanitizer { } return dirty; } + public static byte[] Escape_cls(byte[] v) { + return v; + } +// static function escapeClass( $class ) { +// // Convert ugly stuff to underscores and kill underscores in ugly places +// return rtrim( preg_replace( +// array( '/(^[0-9\\-])|[\\x00-\\x20!"#$%&\'()*+,.\\/:;<=>?@[\\]^`{|}~]|\\xC2\\xA0/', '/_+/' ), +// '_', +// $class ), '_' ); +// } static final byte Tid_amp = 1, Tid_space = 2, Tid_colon = 3, Tid_percent = 4; } /* diff --git a/400_xowa/src/gplx/xowa/wikis/ttls/Xow_ttl__html_entity_tst.java b/400_xowa/src/gplx/xowa/wikis/ttls/Xow_ttl__html_entity_tst.java index 045775308..2cb865d70 100644 --- a/400_xowa/src/gplx/xowa/wikis/ttls/Xow_ttl__html_entity_tst.java +++ b/400_xowa/src/gplx/xowa/wikis/ttls/Xow_ttl__html_entity_tst.java @@ -16,13 +16,14 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.wikis.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*; -import org.junit.*; +import org.junit.*; import gplx.xowa.wikis.nss.*; public class Xow_ttl__html_entity_tst { @Before public void init() {fxt.Reset();} private Xow_ttl_fxt fxt = new Xow_ttl_fxt(); @Test public void Eacute() {fxt.Init_ttl("é").Expd_page_txt("é").Test();} //É @Test public void Amp_at_end() {fxt.Init_ttl("Bisc &").Expd_page_txt("Bisc &").Test();} @Test public void Ncr_dec() {fxt.Init_ttl("Ab").Expd_page_txt("Ab").Test();} @Test public void Ncr_hex() {fxt.Init_ttl("Ab").Expd_page_txt("Ab").Test();} + // @Test public void Ncr_hex_ns() {fxt.Init_ttl("Help:A").Expd_ns_id(Xow_ns_.Tid__help).Expd_page_txt("A").Test();} @Test public void Nbsp() {fxt.Init_ttl("A b").Expd_page_txt("A b").Test();} // NOTE:   must convert to space; EX:w:United States [[Image:Dust Bowl - Dallas, South Dakota 1936.jpg|220px|alt=]] @Test public void Amp() {fxt.Init_ttl("A&b").Expd_page_txt("A&b").Test();} // PURPOSE: A&B -> A&B; PAGE:en.w:Amadou Bagayoko?redirect=n; DATE:2014-09-23 } \ No newline at end of file diff --git a/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java b/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java index cd1fd9c52..6830a1241 100644 --- a/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java +++ b/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java @@ -17,9 +17,9 @@ along with this program. If not, see . */ 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: 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\""); } diff --git a/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java b/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java index f753399ec..3c9f2470d 100644 --- a/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java +++ b/400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ 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 { , ""), 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 ( "" , "category=Ctg_0" , "namespace=Talk" - , ""), fxt.Ul(Itm_html_null, "A")); + , ""), Gfh_utl.Replace_apos_concat_lines + ( "
    " + , "
  • A B
  • " + , "
" + )); } - @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 ( "" , "category=Ctg_0" , "shownamespace=true" - , ""), fxt.Ul(Itm_html_null, "Talk:A")); + , ""), Gfh_utl.Replace_apos_concat_lines + ( "" + )); fxt.Ul_pages(String_.Concat_lines_nl_skip_last ( "" , "category=Ctg_0" , "shownamespace=false" - , ""), fxt.Ul(Itm_html_null, "A")); + , ""), Gfh_utl.Replace_apos_concat_lines + ( "
    " + , "
  • A
  • " + , "
" + )); } @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("category=a", "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 { , "") , 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 + ( "" + , "category=Ctg_0" + , "nofollow=true" + , ""), Gfh_utl.Replace_apos_concat_lines + ( "
    " + , "
  • A B
  • " // "/wiki/A_B" not "/wiki/A B" + , "
" + )); + } + @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 + ( "" + , "category=Ctg_0" + , "nofollow=true" + , ""), Gfh_utl.Replace_apos_concat_lines + ( "
    " + , "
  • A"B
  • " // "/wiki/A_B" not "/wiki/A B" + , "
" + )); + } private static final String Itm_html_null = null; } class Dpl_page_mok { diff --git a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xnde.java b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xnde.java deleted file mode 100644 index e0f888606..000000000 --- a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xnde.java +++ /dev/null @@ -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 . -*/ -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("
\n") -// , Html__div_end = Bry_.new_a7("
\n") -// ; -} diff --git a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_cfg.java b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_cfg.java new file mode 100644 index 000000000..3684568be --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_cfg.java @@ -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 . +*/ +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; +// } +} diff --git a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func.java b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func.java new file mode 100644 index 000000000..ed40cccb2 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func.java @@ -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 . +*/ +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); +} diff --git a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xtn.java b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func_tst.java similarity index 65% rename from 400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xtn.java rename to 400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func_tst.java index 41984a483..7b2d5b3fd 100644 --- a/400_xowa/src/gplx/xowa/xtns/pagebanners/Pb_xtn.java +++ b/400_xowa/src/gplx/xowa/xtns/pagebanners/Pgbnr_func_tst.java @@ -16,10 +16,10 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ 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}}", ""); + } } diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java index f35bd9e1f..efe336db8 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java @@ -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(); diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/wikis/Pfunc_pagesincategory.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/wikis/Pfunc_pagesincategory.java index 91edb4620..35e1618e9 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/wikis/Pfunc_pagesincategory.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/wikis/Pfunc_pagesincategory.java @@ -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() {} } diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_core.java b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_core.java index bc3be7dea..475a4fbd1 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_core.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_core.java @@ -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); diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_err_filter_mgr.java b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_err_filter_mgr.java index 8dd4873b6..c056055f3 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_err_filter_mgr.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_err_filter_mgr.java @@ -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; diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_invoke_func_fxt.java b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_invoke_func_fxt.java index 7bceeb3af..828a09521 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_invoke_func_fxt.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/Scrib_invoke_func_fxt.java @@ -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); diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_engine.java b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_engine.java index 9af52169c..18b4d17b5 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_engine.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_engine.java @@ -17,11 +17,11 @@ along with this program. If not, see . */ 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); } diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_server.java b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_server.java index 1bac9e479..537b75fca 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_server.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/Scrib_server.java @@ -17,12 +17,12 @@ along with this program. If not, see . */ 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(); } diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_proc_fxt.java b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_proc_fxt.java new file mode 100644 index 000000000..cfd76740d --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_proc_fxt.java @@ -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 . +*/ +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); + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_scrib_fxt.java b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_scrib_fxt.java new file mode 100644 index 000000000..f1478ddee --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_scrib_fxt.java @@ -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 . +*/ +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() {} +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/errs/Gfo_comp_op_1.java b/400_xowa/src/gplx/xowa/xtns/scribunto/errs/Gfo_comp_op_1.java index 9e46f25c8..f9ccbc41f 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/errs/Gfo_comp_op_1.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/errs/Gfo_comp_op_1.java @@ -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;} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring.java index d989ef376..9df58d25d 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring.java @@ -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]; } diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__find__tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__find__tst.java new file mode 100644 index 000000000..84a9503e8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__find__tst.java @@ -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 . +*/ +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); + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gmatch__tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gmatch__tst.java new file mode 100644 index 000000000..9346f2418 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gmatch__tst.java @@ -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 . +*/ +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" + )); + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gsub__tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gsub__tst.java new file mode 100644 index 000000000..03602f6bf --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__gsub__tst.java @@ -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 . +*/ +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; + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__lib_tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__lib_tst.java deleted file mode 100644 index 6cbfb43fc..000000000 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__lib_tst.java +++ /dev/null @@ -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 . -*/ -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); - } -} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__match__tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__match__tst.java new file mode 100644 index 000000000..46af8d28b --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__match__tst.java @@ -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 . +*/ +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); + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__invoke_tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__shell_cmd__tst.java similarity index 97% rename from 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__invoke_tst.java rename to 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__shell_cmd__tst.java index ca72f273a..dd536c68a 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__invoke_tst.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_ustring__shell_cmd__tst.java @@ -17,7 +17,7 @@ along with this program. If not, see . */ 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}}"); diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter.java index 83b57c9d3..df742bb0a 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter.java @@ -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) diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter_tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter_tst.java index 1dc1b8b27..cfdb814f8 100644 --- a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter_tst.java +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_regx_converter_tst.java @@ -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; diff --git a/tst/400_xowa/root/wiki/en.wikipedia.org/en.wikipedia.org-file-user.xowa b/tst/400_xowa/root/wiki/en.wikipedia.org/en.wikipedia.org-file-user.xowa index 12ab58138432bc8ee401717a7c36956b88e7bcc3..fab91334b94c579c161b8fddba5bf6331bfaaf31 100644 GIT binary patch delta 187 zcmZoTz}#?vc|*Ufib<#sWeZ2lvc!KY1( h!NSt4s?vgtlNZQ}PF|v$L!2EZdi#KOeAeUL2mmqjH%b5i delta 198 zcmZoTz}#?vc|)13ijireVX{fGk*>K>vazm-WtyR`rMX$EZi-QAlBubMNs_Ta%H&zH z%_;_I$rfqJmc~G7<3wE(3)58HL^FdFU32r~By(fqlw@;5i^-01yBLi(|B=h!(+x;`0N7GE761SM diff --git a/tst/400_xowa/root/wiki/en.wikipedia.org/en.wikipedia.org-text.xowa b/tst/400_xowa/root/wiki/en.wikipedia.org/en.wikipedia.org-text.xowa index 61954b0eca765adebd35362fef8ab74725eec904..3ec98d90b41bf9b4fa954e4760915924edb582f8 100644 GIT binary patch delta 302 zcmZozz|^pSX~QvDl@!ZFOEW`DW8GBqq(ohlBvW(UB$LEc-K3N>vy?;=OH<=Sv&pYy zcQKkwUMhD{CC$V<*(AjjsNBdPN!KJT#a!3Y45%?F#lYOmA_XX5nYwwFygVOq2H(}) z2Q+w&-ZgDv3}%&LRh8yvoV-9@Wb;OSZ2_WOv&mtdzK)TJk%5tcsSy|Re06qd$3IG5A delta 302 zcmZozz|^pSX~QvD6@#>7i?n1*V_i#g<3wE(3)58HL^FdFU32r~By(fqlw@;5i^;EK zcQG1IUMhD{#mvGe)yUk`MAyX7EJ@cSDbZZl(lpsXH^nsB%qY#w(!|8VVDl__c|PI{ zzN@?BSRw-Q!eKJN=)1g ojN%-cjEo!{jC{@|>G4KJ28Lz^hA=ggZ{^Eyz&M-#