From ee03d795363d86f473fcdffc0cd65fbd2c9b49ba Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Sat, 25 May 2019 17:19:47 -0400 Subject: [PATCH] Scribunto: Set frame title for pages when invoking Scribunto code [#476] --- .../gplx/xowa/parsers/tmpls/Xot_defn_.java | 3 +- .../xowa/parsers/tmpls/Xot_defn_tmpl_.java | 9 ++- .../xowa/parsers/tmpls/Xot_invk_temp.java | 48 +++++++++------ .../gplx/xowa/parsers/tmpls/Xot_invk_tkn.java | 10 ++-- .../gplx/xowa/parsers/tmpls/Xot_tmpl_wtr.java | 7 ++- .../src/gplx/xowa/xtns/lst/Lst_pfunc_itm.java | 2 +- .../xtns/scribunto/Scrib_invoke_func_fxt.java | 2 +- .../scribunto/engines/mocks/Mock_engine.java | 59 +++++++++++++++++++ .../engines/mocks/Mock_proc_fxt.java | 54 ++++++++++++----- .../engines/mocks/Mock_scrib_fxt.java | 28 ++++++++- .../libs/Scrib_lib_mw__frame_tst.java | 48 +++++++++++++++ 11 files changed, 220 insertions(+), 50 deletions(-) create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_engine.java create mode 100644 400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_mw__frame_tst.java diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_.java index 5da6109e3..65e9111c2 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_.java @@ -16,11 +16,12 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*; import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*; public class Xot_defn_ { - public static final Xot_defn Null = Xot_defn_null.Instance; + public static final Xot_defn Null = Xot_defn_null.Instance; public static final byte Tid_null = 0 , Tid_func = 1 , Tid_tmpl = 2 + , Tid_page = 3 , Tid_subst = Xol_kwd_grp_.Id_subst , Tid_safesubst = Xol_kwd_grp_.Id_safesubst , Tid_raw = Xol_kwd_grp_.Id_raw diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_tmpl_.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_tmpl_.java index abff391a7..87a6ea8b1 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_tmpl_.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_defn_tmpl_.java @@ -16,13 +16,16 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*; import gplx.xowa.wikis.nss.*; public class Xot_defn_tmpl_ { - public static Xot_invk CopyNew(Xop_ctx ctx, Xot_defn_tmpl orig_defn, Xot_invk orig, Xot_invk caller, byte[] src, byte[] frame_ttl) { // SEE:NOTE_1 + public static Xot_invk CopyNew(Xop_ctx ctx, Xot_defn_tmpl orig_defn, Xot_invk orig, Xot_invk caller, byte[] src, int frame_ns, byte[] frame_ttl) { // SEE:NOTE_1 Xop_tkn_mkr tkn_mkr = ctx.Tkn_mkr(); byte[] orig_src = orig_defn.Data_raw(); Xowe_wiki wiki = ctx.Wiki(); - Xot_invk_temp rv = new Xot_invk_temp(orig.Defn_tid(), orig_src, orig.Name_tkn(), caller.Src_bgn(), caller.Src_end()); + Xot_invk_temp rv = Xot_invk_temp.New(orig.Defn_tid(), orig.Name_tkn(), orig_src, caller.Src_bgn(), caller.Src_end()); frame_ttl = wiki.Lang().Case_mgr().Case_reuse_1st_upper(frame_ttl); // NOTE: always uppercase 1st; EX:{{navbox -> "Template:Navbox"; PAGE:en.w:Achilles DATE:2014-06-21 - rv.Frame_ttl_(Bry_.Add(wiki.Ns_mgr().Ns_template().Name_db_w_colon(), Xoa_ttl.Replace_unders(frame_ttl))); // NOTE: always prepend "Template:" to frame_ttl; DATE:2014-06-13; always use spaces; DATE:2014-08-14; must be local language; Russian "Шаблон" not English "Template"; PAGE:ru.w:Королевство_Нидерландов DATE:2016-11-23 + frame_ttl = Xoa_ttl.Replace_unders(frame_ttl); + if (frame_ns == Xow_ns_.Tid__template) + frame_ttl = Bry_.Add(wiki.Ns_mgr().Ns_template().Name_db_w_colon(), Xoa_ttl.Replace_unders(frame_ttl)); // NOTE: always prepend "Template:" to frame_ttl; DATE:2014-06-13; always use spaces; DATE:2014-08-14; must be local language; Russian "Шаблон" not English "Template"; PAGE:ru.w:Королевство_Нидерландов DATE:2016-11-23 + rv.Frame_ttl_(frame_ttl); int orig_args_len = orig.Args_len(); boolean tmpl_args_parsing_orig = ctx.Tmpl_args_parsing(); ctx.Tmpl_args_parsing_(true); diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_temp.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_temp.java index c640b673d..8f33d2456 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_temp.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_temp.java @@ -17,36 +17,39 @@ package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx. import gplx.core.primitives.*; import gplx.xowa.xtns.scribunto.*; public class Xot_invk_temp implements Xot_invk { - private List_adp list = List_adp_.New(); - private Hash_adp_bry arg_key_hash; - private Hash_adp arg_idx_hash; private Int_obj_ref arg_idx_ref; - Xot_invk_temp() {} - public Xot_invk_temp(boolean root_frame) {this.root_frame = root_frame;} - public Xot_invk_temp(byte defn_tid, byte[] src, Arg_nde_tkn name_tkn, int src_bgn, int src_end) { - this.defn_tid = defn_tid; this.src = src; - this.name_tkn = name_tkn; this.src_bgn = src_bgn; this.src_end = src_end; + private List_adp list; + private Hash_adp_bry arg_key_hash; + private Hash_adp arg_idx_hash; private Int_obj_ref arg_idx_ref; + Xot_invk_temp(boolean root_frame, byte defn_tid, Arg_nde_tkn name_tkn, byte[] src, int src_bgn, int src_end) { + this.root_frame = root_frame; + this.defn_tid = defn_tid; + this.name_tkn = name_tkn; + this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; } + public byte Defn_tid() {return defn_tid;} private final byte defn_tid; + public Arg_nde_tkn Name_tkn() {return name_tkn;} private final Arg_nde_tkn name_tkn; public byte[] Src() {return src;} private byte[] src; public Xot_invk_temp Src_(byte[] src) {this.src = src; return this;} - public byte Defn_tid() {return defn_tid;} private byte defn_tid = Xot_defn_.Tid_null; - public boolean Frame_is_root() {return root_frame;} private boolean root_frame; + public int Src_bgn() {return src_bgn;} private final int src_bgn; + public int Src_end() {return src_end;} private final int src_end; + public boolean Frame_is_root() {return root_frame;} private final boolean root_frame; public byte Frame_tid() {return scrib_tid;} public void Frame_tid_(byte v) {scrib_tid = v;} private byte scrib_tid; public byte[] Frame_ttl() {return frame_ttl;} public void Frame_ttl_(byte[] v) {frame_ttl = v;} private byte[] frame_ttl = Bry_.Empty; // NOTE: set frame_ttl to non-null value; PAGE:en.w:Constantine_the_Great {{Christianity}}; DATE:2014-06-26 public int Frame_lifetime() {return frame_lifetime;} public void Frame_lifetime_(int v) {frame_lifetime = v;} private int frame_lifetime; public boolean Rslt_is_redirect() {return rslt_is_redirect;} public void Rslt_is_redirect_(boolean v) {rslt_is_redirect = v;} private boolean rslt_is_redirect; - public int Src_bgn() {return src_bgn;} private int src_bgn; - public int Src_end() {return src_end;} private int src_end; - public Arg_nde_tkn Name_tkn() {return name_tkn;} private Arg_nde_tkn name_tkn; - public int Args_len() {return list.Count();} + public int Args_len() {return list == null ? 0 : list.Count();} public Arg_nde_tkn Args_eval_by_idx(byte[] src, int idx) { // NOTE: idx is base0 return arg_idx_hash == null // only true if no args, or all args are keys; EX: {{A|b=1|c=2}} ? null : (Arg_nde_tkn)arg_idx_hash.Get_by(arg_idx_ref.Val_(idx)); // lookup int in hash; needed b/c multiple identical keys should retrieve last, not first; EX: {{A|1=a|1=b}}; PAGE:el.d:ἔχω DATE:2014-07-23 } - public Arg_nde_tkn Args_get_by_idx(int i) {return (Arg_nde_tkn)list.Get_at(i);} + public Arg_nde_tkn Args_get_by_idx(int i) {return list == null ? null : (Arg_nde_tkn)list.Get_at(i);} public Arg_nde_tkn Args_get_by_key(byte[] src, byte[] key) { return arg_key_hash == null ? null : (Arg_nde_tkn)arg_key_hash.Get_by_bry(key); } - public void Args_add(Arg_nde_tkn arg) {list.Add(arg);} + public void Args_add(Arg_nde_tkn arg) { + if (list == null) list = List_adp_.New(); + list.Add(arg); + } public void Args_add_by_key(byte[] key, Arg_nde_tkn arg) { if (arg_key_hash == null) arg_key_hash = Hash_adp_bry.cs(); // PERF: lazy arg_key_hash.Add_if_dupe_use_nth(key, arg); @@ -63,8 +66,17 @@ public class Xot_invk_temp implements Xot_invk { arg_idx_hash.Add_if_dupe_use_nth(Int_obj_ref.New(int_key), arg); // Add_if_dupe_use_nth to keep latest version; needed for {{A|1=a|1=b}} DATE:2014-07-23 } - public static final Xot_invk_temp Page_is_caller = new Xot_invk_temp(true); // SEE NOTE_2 public static final Xot_invk Null_frame = null; + + public static Xot_invk_temp New_root_w_src(byte[] src) { + return new Xot_invk_temp(true, Xot_defn_.Tid_page, null, src, 0, src.length); + } + public static Xot_invk_temp New_root() { + return new Xot_invk_temp(true, Xot_defn_.Tid_page, null, null, -1, -1); + } + public static Xot_invk_temp New(byte defn_tid, Arg_nde_tkn name_tkn, byte[] src, int src_bgn, int src_end) { + return new Xot_invk_temp(false, defn_tid, name_tkn, src, src_bgn, src_end); + } } /* NOTE_1: @@ -83,6 +95,4 @@ TEXT: "a {{{1}}}b c" Note that in order to resolve mwo_concat we need to pass in an Xot_invk This Xot_invk is the "Page_is_caller" ref Note this has no parameters and is always empty - -Does this static ref have multi-threaded issues? DATE:2017-09-01 */ diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_tkn.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_tkn.java index 4b5131c77..6fde8ea7b 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_tkn.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_tkn.java @@ -269,7 +269,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk { default: Xot_defn_tmpl defn_tmpl = (Xot_defn_tmpl)defn; if (defn_tmpl.Root() == null) defn_tmpl.Parse_tmpl(ctx); // NOTE: defn_tmpl.Root can be null after clearing out cache; must be non-null else will fail in trace; DATE:2013-02-01 - Xot_invk invk_tmpl = Xot_defn_tmpl_.CopyNew(ctx, defn_tmpl, this, caller, src, name_ary); + Xot_invk invk_tmpl = Xot_defn_tmpl_.CopyNew(ctx, defn_tmpl, this, caller, src, Xow_ns_.Tid__template, name_ary); invk_tmpl.Frame_ttl_(defn_tmpl.Frame_ttl()); // set frame_ttl; needed for redirects; PAGE:en.w:Statutory_city; DATE:2014-08-22 trace.Trace_bgn(ctx, src, name_ary, caller, invk_tmpl, defn); @@ -344,16 +344,16 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk { if (transclude_src != null) { // NOTE: must use new page, not current, else transcluded page can cause inconsistent TOC state; PAGE:de.w:Game_of_Thrones DATE:2016-11-21 Xot_defn_tmpl transclude_tmpl = ctx.Wiki().Parser_mgr().Main().Parse_text_to_defn_obj(Xop_ctx.New__sub(wiki, ctx, Xoae_page.New(wiki, page_ttl)), ctx.Tkn_mkr(), page_ttl.Ns(), page_ttl.Page_db(), transclude_src); - return Eval_sub(ctx, transclude_tmpl, caller, src, bfr); + return Eval_sub(ctx, page_ttl, transclude_tmpl, caller, src, bfr); } else { Xot_invk_tkn_.Print_not_found__by_transclude(bfr, wiki.Ns_mgr(), template_prefix_found, name_ary); return false; } } - private boolean Eval_sub(Xop_ctx ctx, Xot_defn_tmpl transclude_tmpl, Xot_invk caller, byte[] src, Bry_bfr doc) { + private boolean Eval_sub(Xop_ctx ctx, Xoa_ttl transclude_ttl, Xot_defn_tmpl transclude_tmpl, Xot_invk caller, byte[] src, Bry_bfr doc) { boolean rv = false; - Xot_invk tmp_tmpl = Xot_defn_tmpl_.CopyNew(ctx, transclude_tmpl, this, caller, src, transclude_tmpl.Name()); + Xot_invk tmp_tmpl = Xot_defn_tmpl_.CopyNew(ctx, transclude_tmpl, this, caller, src, transclude_ttl.Ns().Id(), transclude_tmpl.Name()); Bry_bfr tmp_bfr = Bry_bfr_.New(); Xopg_tmpl_prepend_mgr prepend_mgr = ctx.Page().Tmpl_prepend_mgr().Bgn(doc); rv = transclude_tmpl.Tmpl_evaluate(ctx, tmp_tmpl, tmp_bfr); @@ -389,7 +389,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk { bfr.Add(Xop_tkn_.Lnki_bgn).Add(name_ary).Add(Xop_tkn_.Lnki_end); // indicate template was not found; DATE:2014-02-12 return false; } - return Eval_sub(ctx, transclude_tmpl, caller, src_for_tkn, bfr); + return Eval_sub(ctx, page_ttl, transclude_tmpl, caller, src_for_tkn, bfr); } public int Args_len() {return args_len;} private int args_len = 0; public Arg_nde_tkn Args_get_by_idx(int idx) {return args[idx];} diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_tmpl_wtr.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_tmpl_wtr.java index 4d38c6e1e..9e72ae433 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_tmpl_wtr.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_tmpl_wtr.java @@ -53,7 +53,7 @@ public class Xot_tmpl_wtr { // NOTE: originally "if (ctx.Parse_tid() == Xop_parser_tid_.Tid__tmpl) {" but if not needed; Xot_tmpl_wtr should not be called for tmpls and should not make it to page_wiki Bry_bfr tmp_bfr = Bry_bfr_.New(); ctx.Only_include_evaluate_(true); - xnde.Tmpl_evaluate(ctx, src, Xot_invk_temp.Page_is_caller, tmp_bfr); + xnde.Tmpl_evaluate(ctx, src, Xot_invk_temp.New_root(), tmp_bfr); ctx.Only_include_evaluate_(false); rslt_bfr.Add_bfr_and_preserve(tmp_bfr); break; @@ -89,7 +89,7 @@ public class Xot_tmpl_wtr { rslt_bfr.Add_mid(src, tkn.Src_bgn(), tkn.Src_end()); break; // write src from bgn/end case Xop_tkn_itm_.Tid_ignore: break; // hide comments and <*include*> ndes case Xop_tkn_itm_.Tid_tmpl_prm: - tkn.Tmpl_evaluate(ctx, src, Xot_invk_temp.Page_is_caller.Src_(src), rslt_bfr); + tkn.Tmpl_evaluate(ctx, src, Xot_invk_temp.New_root_w_src(src), rslt_bfr); break; case Xop_tkn_itm_.Tid_tvar: gplx.xowa.xtns.translates.Xop_tvar_tkn tvar_tkn = (gplx.xowa.xtns.translates.Xop_tvar_tkn)tkn; @@ -98,7 +98,8 @@ public class Xot_tmpl_wtr { case Xop_tkn_itm_.Tid_tmpl_invk: try { if (frame == Xot_invk_temp.Null_frame) { // NOTE: should probably remove lazy-instantiation and always force frame to be passed in; DATE:2017-09-03 - frame = Xot_invk_temp.Page_is_caller.Src_(src); + frame = Xot_invk_temp.New_root_w_src(src); + frame.Frame_ttl_(ctx.Page().Ttl().Full_txt_raw()); } tkn.Tmpl_evaluate(ctx, src, frame, rslt_bfr); } diff --git a/400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_itm.java b/400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_itm.java index 88dda0025..93f8fe5f4 100644 --- a/400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_itm.java +++ b/400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_itm.java @@ -45,7 +45,7 @@ public class Lst_pfunc_itm { // eval tmpl Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001(); try { - tmpl.Tmpl_evaluate(sub_ctx, Xot_invk_temp.Page_is_caller, tmp_bfr); + tmpl.Tmpl_evaluate(sub_ctx, Xot_invk_temp.New_root(), tmp_bfr); sub_src = tmp_bfr.To_bry_and_clear(); } finally { tmp_bfr.Mkr_rls(); 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 681e093c5..29abd67e1 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 @@ -115,7 +115,7 @@ public class Scrib_invoke_func_fxt { fxt = new Xop_fxt(app, Xoa_app_fxt.Make__wiki__edit(app, domain, app.Lang_mgr().Get_by_or_new(Bry_.new_u8(lang)))); // NOTE: don't try to cache fxt on func_fxt level; causes errors in Language_lib core_fxt = new Scrib_core_fxt(fxt); core = core_fxt.Core(); - Xot_invk parent_frame = new Xot_invk_temp(true); parent_frame.Frame_tid_(Scrib_frame_.Tid_null); + Xot_invk parent_frame = Xot_invk_temp.New_root(); 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(fxt.Page()); diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_engine.java b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_engine.java new file mode 100644 index 000000000..e47770744 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/engines/mocks/Mock_engine.java @@ -0,0 +1,59 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +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.*; +import gplx.core.lists.hashs.*; +public class Mock_engine implements Scrib_engine { + private final Hash_adp__int fnc_hash = new Hash_adp__int(); + private final Hash_adp mod_init_hash = Hash_adp_.New(); + private final Hash_adp__int mod_fnc_hash = new Hash_adp__int(); + + 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 (Scrib_lua_proc)mod_init_hash.Get_by(name); + } + public Keyval[] CallFunction(int id, Keyval[] args) { + Mock_proc_fxt fnc = (Mock_proc_fxt)fnc_hash.Get_by_or_fail(id); + return fnc.Exec_by_scrib(args); + } + public void RegisterLibrary(Keyval[] functions_ary) {} + public Keyval[] ExecuteModule(int mod_id) {throw Err_.new_unimplemented();} + public void CleanupChunks(Keyval[] ids) {} + public void Clear() {fnc_hash.Clear();} + + public void InitFunctionForTest(Mock_proc_fxt proc) { + fnc_hash.Add(proc.Id(), proc); + } + + public void Init_module(String mod_name, int mod_id) { + mod_init_hash.Add_if_dupe_use_nth(mod_name, new Scrib_lua_proc(mod_name, mod_id)); + } + public void Init_module_func(int mod_id, Mock_proc_fxt fnc) { + Hash_adp funcs = (Hash_adp)mod_fnc_hash.Get_by_or_null(mod_id); + if (funcs == null) { + funcs = Hash_adp_.New(); + mod_fnc_hash.Add(mod_id, funcs); + } + fnc_hash.Add(fnc.Id(), fnc); + funcs.Add(fnc.Key(), fnc.To_scrib_lua_proc()); + } + public Scrib_lua_proc Get_module_func(int mod_id, String fnc_name) { + Hash_adp funcs = (Hash_adp)mod_fnc_hash.Get_by_or_fail(mod_id); + return (Scrib_lua_proc)funcs.Get_by_or_fail(fnc_name); + } +} 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 index 5c100595f..3c0750fe2 100644 --- 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 @@ -15,6 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ 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.*; +import gplx.xowa.xtns.scribunto.procs.*; 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; @@ -22,21 +23,44 @@ public abstract class Mock_proc_fxt { 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.New_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); +class Mock_exec_module extends Mock_proc_fxt { private final Mock_engine engine; + public Mock_exec_module(int mod_id, Mock_engine engine) {super(mod_id, "mockExecuteModule"); + this.engine = engine; } - public void RegisterLibrary(Keyval[] functions_ary) {} - public Keyval[] ExecuteModule(int mod_id) {return null;} - public void CleanupChunks(Keyval[] ids) {} - public void Clear() {hash.Clear();} - public void RegisterLibraryForTest(Mock_proc_fxt proc) { - hash.Add(Int_obj_ref.New(proc.Id()), proc); + @Override public Keyval[] Exec_by_scrib(Keyval[] args) { + Scrib_lua_proc mod_proc = (Scrib_lua_proc)args[0].Val(); + String fnc_name = (String)args[1].Val(); + return new Keyval[] {Keyval_.int_(0, true), Keyval_.int_(1, engine.Get_module_func(mod_proc.Id(), fnc_name))}; + } +} +class Mock_exec_function extends Mock_proc_fxt { private final Mock_engine engine; + public Mock_exec_function(int func_id, Mock_engine engine) {super(func_id, "mockExecuteFuntion"); + this.engine = engine; + } + @Override public Keyval[] Exec_by_scrib(Keyval[] args) { + Scrib_lua_proc mod_proc = (Scrib_lua_proc)args[0].Val(); + return engine.CallFunction(mod_proc.Id(), args); + } +} +class Mock_exec_lib extends Mock_proc_fxt { private Scrib_lib lib; + private String proc_name; + private Keyval[] proc_args; + public Mock_exec_lib(int fnc_id, String fnc_name, Scrib_lib lib, String proc_name, Object... proc_obj_args) {super(fnc_id, fnc_name); + this.lib = lib; + this.proc_name = proc_name; + int len = proc_obj_args.length; + this.proc_args = new Keyval[len]; + for (int i = 0; i < len; i++) { + proc_args[i] = Keyval_.int_(i + 1, proc_obj_args[i]); + } + } + @Override public Keyval[] Exec_by_scrib(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(proc_args), proc_rslt); + return Extract_rslt(proc_rslt); + } + private Keyval[] Extract_rslt(Scrib_proc_rslt proc_rslt) { + return new Keyval[] {Keyval_.int_(1, Object_.Xto_str_strict_or_null_mark(proc_rslt.Ary()[0].Val()))}; } } 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 index 5424f0261..c458100f2 100644 --- 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 @@ -19,7 +19,9 @@ import gplx.xowa.xtns.scribunto.procs.*; public class Mock_scrib_fxt { private final Mock_engine engine = new Mock_engine(); private final Mock_server server = new Mock_server(); + private int mock_mod_id_next = 10; public Scrib_core Core() {return core;} private Scrib_core core; + public Mock_engine Engine() {return engine;} public Xop_fxt Parser_fxt() {return parser_fxt;} private Xop_fxt parser_fxt; public void Clear() {Clear("en.wikipedia.org", "en");} public void Clear(String domain, String lang) { @@ -29,7 +31,7 @@ public class Mock_scrib_fxt { core = wiki.Parser_mgr().Scrib().Core_init(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 parent_frame = Xot_invk_temp.New_root(); 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()); @@ -37,9 +39,30 @@ public class Mock_scrib_fxt { public void Init__cbk(Mock_proc_fxt... ary) { engine.Clear(); for (Mock_proc_fxt proc : ary) - engine.RegisterLibraryForTest(proc); + engine.InitFunctionForTest(proc); } public void Init__page(String ttl, String txt) {parser_fxt.Init_page_create(ttl, txt);} + public void Init__mock_mod_system() { + Scrib_lua_mod mod = new Scrib_lua_mod(core, "mw.lua"); + core.Lib_mw().Mod_(mod); + mod.Fncs_add(new Scrib_lua_proc("executeModule", 8)); + mod.Fncs_add(new Scrib_lua_proc("executeFunction", 9)); + engine.InitFunctionForTest(new Mock_exec_module(8, engine)); + engine.InitFunctionForTest(new Mock_exec_function(9, engine)); + } + public void Init__mock_mod(Scrib_lib lib, String mod_name, Mock_proc_fxt... prc_ary) { + int mod_id = mock_mod_id_next++; + String mod_text = ""; + engine.Init_module("=" + mod_name, mod_id); + for (Mock_proc_fxt prc : prc_ary) { + mod_text = mod_text + prc.Key() + "\n"; + engine.Init_module_func(mod_id, prc); + } + parser_fxt.Init_page_create(mod_name, mod_text); + } + public Mock_proc_fxt Init__mock_fnc_for_lib(String fnc_name, Scrib_lib lib, String proc_name, Object... proc_args) { + return new Mock_exec_lib(mock_mod_id_next++, fnc_name, lib, proc_name, proc_args); + } public void Test__proc__ints (Scrib_lib lib, String proc_name, Object[] args, int expd) {Test__proc__kvps(lib, proc_name, Bool_.Y, Int_.To_str(expd), Scrib_kv_utl_.base1_many_(args));} public void Test__proc__objs__flat(Scrib_lib lib, String proc_name, Object[] args, String expd) {Test__proc__kvps(lib, proc_name, Bool_.Y, expd, Scrib_kv_utl_.base1_many_(args));} public void Test__proc__objs__nest(Scrib_lib lib, String proc_name, Object[] args, Keyval[] expd) {Test__proc__kvps(lib, proc_name, Bool_.N, Keyval_.Ary__to_str__nest(new Keyval[] {Keyval_.int_(Scrib_core.Base_1, expd)}), Scrib_kv_utl_.base1_many_(args));} @@ -62,6 +85,7 @@ public class Mock_scrib_fxt { Object[] actl_ary = Mock_scrib_fxt_.Kvp_vals_to_objs(actl_kvs); Tfds.Eq_ary(expd_ary, actl_ary); } + public void Test__parse__tmpl_to_html(String raw, String expd) {parser_fxt.Test__parse__tmpl_to_html(raw, expd);} } class Mock_scrib_fxt_ { public static Keyval[] Test__lib_proc__core(Scrib_lib lib, String proc_name, Keyval[] args) { diff --git a/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_mw__frame_tst.java b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_mw__frame_tst.java new file mode 100644 index 000000000..721fdd9e8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/scribunto/libs/Scrib_lib_mw__frame_tst.java @@ -0,0 +1,48 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +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.*; +import gplx.xowa.xtns.scribunto.procs.*; +public class Scrib_lib_mw__frame_tst { + private final Mock_scrib_fxt fxt = new Mock_scrib_fxt(); private Scrib_lib lib; + @Before public void init() { + fxt.Clear(); + fxt.Init__mock_mod_system(); + lib = fxt.Core().Lib_mw().Init(); + + fxt.Init__mock_mod(lib, "Module:Mod_1" + , fxt.Init__mock_fnc_for_lib("Get_frame_title_current", lib, Scrib_lib_mw.Invk_getFrameTitle, "current") + , fxt.Init__mock_fnc_for_lib("Get_frame_title_parent", lib, Scrib_lib_mw.Invk_getFrameTitle, "parent") + ); + } + @Test public void GetFrameTitle__template() { + fxt.Init__page("Template:Template_1", "{{#invoke:Mod_1|Get_frame_title_{{{1}}}}}"); + fxt.Test__parse__tmpl_to_html("{{Template_1|current}}", "Module:Mod 1"); + fxt.Test__parse__tmpl_to_html("{{Template_1|parent}}" , "Template:Template 1"); + } + @Test public void GetFrameTitle__transclude() { + fxt.Init__page("Page_1", "{{#invoke:Mod_1|Get_frame_title_parent}}"); + fxt.Test__parse__tmpl_to_html("{{:Page_1}}", "Page 1"); + + fxt.Init__page("Page_2", "{{#invoke:Mod_1|Get_frame_title_current}}"); + fxt.Test__parse__tmpl_to_html("{{:Page_2}}", "Module:Mod 1"); + } + @Test public void GetFrameTitle__page() { + fxt.Test__parse__tmpl_to_html("{{#invoke:Mod_1|Get_frame_title_parent}}", "Test page"); + fxt.Test__parse__tmpl_to_html("{{#invoke:Mod_1|Get_frame_title_current}}", "Module:Mod 1"); + } +} \ No newline at end of file