mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.7.2.1
This commit is contained in:
104
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_anchorencode.java
Normal file
104
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_anchorencode.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.btries.*;
|
||||
import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*;
|
||||
public class Pfunc_anchorencode extends Pf_func_base { // EX: {{anchorencode:a b}} -> a+b
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_url_anchorencode;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_anchorencode().Name_(name);}
|
||||
public static void Func_init(Xop_ctx ctx) {
|
||||
if (anchor_ctx != null) return;// NOTE: called by Scrib_uri
|
||||
encode_trie.Add(Byte_ascii.Colon, Bry_fmtr_arg_.byt_(Byte_ascii.Colon));
|
||||
encode_trie.Add(Byte_ascii.Space, Bry_fmtr_arg_.byt_(Byte_ascii.Underline));
|
||||
anchor_ctx = Xop_ctx.new_sub_(ctx.Wiki());
|
||||
anchor_ctx.Para().Enabled_n_();
|
||||
anchor_tkn_mkr = anchor_ctx.Tkn_mkr();
|
||||
anchor_parser = ctx.Wiki().Utl_mgr().Anchor_encode_parser();
|
||||
}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
if (anchor_ctx == null) Func_init(ctx);
|
||||
byte[] val_ary = Eval_argx(ctx, src, caller, self); if (val_ary == Bry_.Empty) return;
|
||||
Anchor_encode(val_ary, bfr, ctx.App().Utl__bfr_mkr().Get_b512().Mkr_rls());
|
||||
}
|
||||
public static void Anchor_encode(byte[] src, Bry_bfr bfr, Bry_bfr tmp_bfr) {
|
||||
Xop_root_tkn root = anchor_ctx.Tkn_mkr().Root(src);
|
||||
anchor_parser.Parse_wtxt_to_wdom(root, anchor_ctx, anchor_tkn_mkr, src, Xop_parser_.Doc_bgn_bos);
|
||||
// anchor_parser.Parse_page_tmpl(root, anchor_ctx, anchor_tkn_mkr, src);
|
||||
int subs_len = root.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub = root.Subs_get(i);
|
||||
Tkn(src, sub, root, i, tmp_bfr);
|
||||
}
|
||||
byte[] unencoded = tmp_bfr.Xto_bry_and_clear();
|
||||
encoder.Encode(tmp_bfr, unencoded);
|
||||
bfr.Add_bfr_and_clear(tmp_bfr);
|
||||
}
|
||||
private static Url_encoder encoder = Url_encoder.new_html_id_();
|
||||
private static void Tkn(byte[] src, Xop_tkn_itm sub, Xop_tkn_grp grp, int sub_idx, Bry_bfr tmp_bfr) {
|
||||
switch (sub.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_lnke: Lnke(src, (Xop_lnke_tkn)sub, tmp_bfr); break; // FUTURE: need to move number to lnke_tkn so that number will be correct/consistent?
|
||||
case Xop_tkn_itm_.Tid_lnki: Lnki(src, (Xop_lnki_tkn)sub, tmp_bfr); break;
|
||||
case Xop_tkn_itm_.Tid_apos: break; // noop
|
||||
case Xop_tkn_itm_.Tid_xnde: Xnde(src, (Xop_xnde_tkn)sub, tmp_bfr); break;
|
||||
case Xop_tkn_itm_.Tid_html_ncr: tmp_bfr.Add_u8_int(((Xop_amp_tkn_num)sub).Val()); break;
|
||||
case Xop_tkn_itm_.Tid_html_ref: tmp_bfr.Add_u8_int(((Xop_amp_tkn_txt)sub).Char_int()); break;
|
||||
case Xop_tkn_itm_.Tid_tmpl_invk:
|
||||
Xot_invk_tkn invk_tkn = (Xot_invk_tkn)sub;
|
||||
Arg_itm_tkn name_tkn = invk_tkn.Name_tkn().Key_tkn();
|
||||
int name_ary_bgn = name_tkn.Src_bgn() + 1, name_ary_end = name_tkn.Src_end();
|
||||
byte[] name_ary = Bry_.Mid(src, name_ary_bgn, name_ary_end); // + 1 to skip :
|
||||
int name_ary_len = name_ary_end - name_ary_bgn;
|
||||
if (name_ary_len > 0 && name_ary[0] == Byte_ascii.Colon) // has initial colon; EX: {{:a}
|
||||
tmp_bfr.Add_mid(name_ary, 1, name_ary_len); // 1 to skip initial colon
|
||||
else // regular tmpl; EX: {{a}}
|
||||
tmp_bfr.Add(anchor_ctx.Wiki().Ns_mgr().Ns_template().Gen_ttl(name_ary));
|
||||
break;
|
||||
default: tmp_bfr.Add_mid(src, sub.Src_bgn_grp(grp, sub_idx), sub.Src_end_grp(grp, sub_idx)); break;
|
||||
}
|
||||
}
|
||||
private static void Lnke(byte[] src, Xop_lnke_tkn lnke, Bry_bfr tmp_bfr) {
|
||||
int subs_len = lnke.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm lnke_sub = lnke.Subs_get(i);
|
||||
tmp_bfr.Add_mid(src, lnke_sub.Src_bgn_grp(lnke, i), lnke_sub.Src_end_grp(lnke, i));
|
||||
}
|
||||
}
|
||||
private static void Lnki(byte[] src, Xop_lnki_tkn lnki, Bry_bfr tmp_bfr) {
|
||||
int src_end = lnki.Src_end();
|
||||
int trg_end = lnki.Trg_tkn().Src_end();
|
||||
|
||||
if (trg_end == src_end - Xop_tkn_.Lnki_end_len) { // only trg
|
||||
int trg_bgn = lnki.Trg_tkn().Src_bgn();
|
||||
if (lnki.Ttl().ForceLiteralLink()) ++trg_bgn; // literal link; skip colon; EX: [[:a]] -> a
|
||||
tmp_bfr.Add_mid(src, trg_bgn, trg_end);
|
||||
}
|
||||
else {
|
||||
tmp_bfr.Add_mid(src, trg_end + 1, src_end - Xop_tkn_.Lnki_end_len); //+1 is len of pipe
|
||||
}
|
||||
}
|
||||
private static void Xnde(byte[] src, Xop_xnde_tkn xnde, Bry_bfr tmp_bfr) {
|
||||
int subs_len = xnde.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Tkn(src, xnde.Subs_get(i), xnde, i, tmp_bfr);
|
||||
}
|
||||
}
|
||||
private static Btrie_fast_mgr encode_trie = Btrie_fast_mgr.cs_();
|
||||
private static Xop_ctx anchor_ctx; static Xop_tkn_mkr anchor_tkn_mkr;
|
||||
private static Xop_parser anchor_parser;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_anchorencode_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Lnke() {fxt.Test_parse_tmpl_str_test("{{anchorencode:[irc://a b c]}}" , "{{test}}" , "b_c");}
|
||||
@Test public void Apos_bold() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a ''b'' c}}" , "{{test}}" , "a_b_c");}
|
||||
@Test public void Apos_1() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a 'b c}}" , "{{test}}" , "a_.27b_c");}
|
||||
@Test public void Lnki_trg() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a [[b]] c}}" , "{{test}}" , "a_b_c");}
|
||||
@Test public void Lnki_caption() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a [[b|c]] c}}" , "{{test}}" , "a_c_c");}
|
||||
@Test public void Lnki_file() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a [[Image:b|thumb|c]] d}}" , "{{test}}" , "a_thumb.7Cc_d");}
|
||||
@Test public void Xnde() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a <i>b</i> c}}" , "{{test}}" , "a_b_c");}
|
||||
@Test public void Html_ncr() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a " b}}" , "{{test}}" , "a_.22_b");}
|
||||
@Test public void Html_ref() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a " b}}" , "{{test}}" , "a_.22_b");}
|
||||
@Test public void Tmpl_missing_basic() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{a}}}}" , "{{test}}" , "Template:a");}
|
||||
@Test public void Tmpl_missing_colon() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{:a}}}}" , "{{test}}" , "Template:A");}
|
||||
@Test public void Lnki_literal() {fxt.Test_parse_tmpl_str_test("{{anchorencode:[[:a]]}}" , "{{test}}" , "a");}
|
||||
}
|
||||
58
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_filepath.java
Normal file
58
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_filepath.java
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.files.*; import gplx.xowa.files.repos.*;
|
||||
import gplx.xowa.files.origs.*;
|
||||
public class Pfunc_filepath extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_url_filepath;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_filepath().Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] val_ary = Eval_argx(ctx, src, caller, self); if (val_ary == Bry_.Empty) return;
|
||||
Xowe_wiki wiki = ctx.Wiki();
|
||||
Xoa_ttl ttl = wiki.Ttl_parse(Xow_ns_.Id_file, val_ary); if (ttl == null) return; // text is not valid ttl; exit;
|
||||
Xoae_page page = Load_page(wiki, ttl); if (page.Missing()) return; // page not found in wiki or commons; exit;
|
||||
byte[] ttl_bry = page.Ttl().Page_url();
|
||||
|
||||
// Xof_orig_itm orig_itm = wiki.File_mgr().Orig_mgr().Find_by_ttl_or_null(ttl_bry);
|
||||
// if (orig_itm == Xof_orig_itm.Null) return;
|
||||
// Xof_repo_itm repo = wiki.File_mgr().Repo_mgr().Get_trg_by_id_or_null(orig_itm.Repo()).Trg();
|
||||
// url_bldr.Init_for_trg_html(Xof_repo_itm_.Mode_orig, repo, orig_itm.Ttl(), Xof_file_wkr_.Md5_fast(orig_itm.Ttl()), orig_itm.Ext(), -1, -1, -1);
|
||||
// bfr.Add(url_bldr.Xto_bry());
|
||||
|
||||
Xofw_file_finder_rslt tmp_rslt = wiki.File_mgr().Repo_mgr().Page_finder_locate(ttl_bry);
|
||||
if (tmp_rslt.Repo_idx() == Byte_.Max_value_127) return;
|
||||
Xof_repo_itm trg_repo = wiki.File_mgr().Repo_mgr().Repos_get_at(tmp_rslt.Repo_idx()).Trg();
|
||||
xfer_itm.Orig_ttl_and_redirect_(ttl_bry, Bry_.Empty); // redirect is empty b/c Get_page does all redirect lookups
|
||||
byte[] url = url_bldr.Init_for_trg_html(Xof_repo_itm_.Mode_orig, trg_repo, ttl_bry, xfer_itm.Orig_ttl_md5(), xfer_itm.Orig_ext(), Xof_img_size.Size_null_deprecated, Xof_lnki_time.Null, Xof_lnki_page.Null).Xto_bry();
|
||||
bfr.Add(url);
|
||||
}
|
||||
private static final Xof_xfer_itm xfer_itm = new Xof_xfer_itm();
|
||||
private static final Xof_url_bldr url_bldr = new Xof_url_bldr();
|
||||
private static Xoae_page Load_page(Xowe_wiki wiki, Xoa_ttl ttl) {
|
||||
Xoae_page page = wiki.Data_mgr().Get_page(ttl, false);
|
||||
if (page.Missing()) { // file not found in current wiki; try commons;
|
||||
Xowe_wiki commons_wiki = wiki.Appe().Wiki_mgr().Get_by_key_or_null(wiki.Commons_wiki_key());
|
||||
if (commons_wiki != null) { // commons_wiki not installed; exit; DATE:2013-06-08
|
||||
if (!Env_.Mode_testing()) commons_wiki.Init_assert();// must assert load else page_zip never detected; DATE:2013-03-10
|
||||
page = commons_wiki.Data_mgr().Get_page(ttl, false);
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*; import gplx.dbs.*;
|
||||
import gplx.xowa.tdbs.*;
|
||||
import gplx.xowa.files.*; import gplx.xowa.files.exts.*; import gplx.xowa.files.origs.*;
|
||||
import gplx.xowa.wikis.*;
|
||||
public class Pfunc_filepath_tst {
|
||||
private final Xop_fxt fxt = new Xop_fxt();
|
||||
private final Xofw_wiki_wkr_mock mock_wkr = new Xofw_wiki_wkr_mock();
|
||||
private Xowe_wiki en_wiki, commons_wiki;
|
||||
@Before public void init() {
|
||||
fxt.Reset();
|
||||
Io_mgr.I.InitEngine_mem();
|
||||
Db_conn_bldr.I.Reg_default_mem();
|
||||
Xoae_app app = fxt.App();
|
||||
en_wiki = fxt.Wiki();
|
||||
// Init_orig_mgr(en_wiki);
|
||||
commons_wiki = Xoa_app_fxt.wiki_(app, Xow_domain_.Domain_str_commons);
|
||||
mock_wkr.Clear_commons(); // assume all files are in repo 0
|
||||
en_wiki.File_mgr().Repo_mgr().Page_finder_(mock_wkr);
|
||||
commons_wiki.Db_mgr().Load_mgr().Clear();
|
||||
en_wiki.Db_mgr().Load_mgr().Clear();
|
||||
app.Wiki_mgr().Add(commons_wiki);
|
||||
app.File_mgr().Repo_mgr().Set("src_commons", "mem/xowa/file/commons/src/", commons_wiki.Domain_str());
|
||||
app.File_mgr().Repo_mgr().Set("trg_commons", "mem/xowa/file/commons/trg/", commons_wiki.Domain_str());
|
||||
en_wiki.File_mgr().Repo_mgr().Add_repo(Bry_.new_u8("src_commons"), Bry_.new_u8("trg_commons"));
|
||||
Io_mgr.I.CreateDir(Io_url_.new_dir_("mem/xowa/wiki/commons.wikimedia.org/ns/000/page/")); // HACK: create page_dir so Scan_dirs_zip will not identify commons as zipped; FIX: remove; WHEN: after redoing commons.css download logic
|
||||
}
|
||||
@Test public void Wiki_is_local() {
|
||||
fxt.Init_page_create(en_wiki, "File:A.png", "");
|
||||
mock_wkr.Redirect_("A.png", "A.png").Repo_idx_(0);
|
||||
fxt.Test_parse_tmpl_str_test("{{filepath:A.png}}", "{{test}}", "file:///mem/wiki/repo/trg/orig/7/0/A.png");
|
||||
}
|
||||
@Test public void Wiki_is_commons() {
|
||||
fxt.Init_page_create(commons_wiki, "File:A.png", "");
|
||||
commons_wiki.Tdb_fsys_mgr().Tdb_dir_regy()[Xotdb_dir_info_.Tid_page].Ext_tid_(gplx.ios.Io_stream_.Tid_raw);
|
||||
mock_wkr.Redirect_("A.png", "A.png").Repo_idx_(1);
|
||||
fxt.Test_parse_tmpl_str_test("{{filepath:A.png}}", "{{test}}", "file:///mem/xowa/file/commons/trg/orig/7/0/1/c/A.png");
|
||||
}
|
||||
@Test public void Not_found() {
|
||||
fxt.Test_parse_tmpl_str_test("{{filepath:B.png}}", "{{test}}", "");
|
||||
}
|
||||
@Test public void Invalid() { // PURPOSE: handle invalid ttls; EX:w:Germicidin
|
||||
fxt.Init_log_(Xop_ttl_log.Invalid_char);
|
||||
fxt.Test_parse_tmpl_str_test("{{filepath:{{{ImageFile}}}}}", "{{test}}", "");
|
||||
}
|
||||
// private static void Init_orig_mgr(Xow_wiki wiki) {
|
||||
// Xof_orig_tbl orig_tbl = null;
|
||||
// wiki.File__orig_mgr().Init_by_wiki(wiki, Xof_fsdb_mode.new_v2_gui(), new Xof_orig_tbl[] {orig_tbl}, Xof_url_bldr.new_v2());
|
||||
// }
|
||||
}
|
||||
57
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ns.java
Normal file
57
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ns.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_ns extends Pf_func_base { // EX: {{ns:6}} -> File
|
||||
private boolean encode;
|
||||
public Pfunc_ns(boolean encode) {this.encode = encode; if (canonical == null) canonical_();}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_url_ns;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ns(encode).Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self); if (val_dat_ary == Bry_.Empty) return;
|
||||
|
||||
int val_dat_ary_len = val_dat_ary.length;
|
||||
int ns_id = Bry_.Xto_int_or(val_dat_ary, 0, val_dat_ary_len, Int_.MinValue);
|
||||
if (ns_id == Int_.MinValue) {
|
||||
Object o = ctx.Wiki().Ns_mgr().Names_get_or_null(val_dat_ary, 0, val_dat_ary_len);
|
||||
if (o == null
|
||||
&& !Bry_.Eq(ctx.Lang().Key_bry(), Xol_lang_.Key_en)) // foreign language; english canonical names are still valid; REF.MW: Language.php|getNsIndex
|
||||
o = canonical.Get_by_mid(val_dat_ary, 0, val_dat_ary_len);
|
||||
if (o != null) {
|
||||
Xow_ns itm = (Xow_ns)o;
|
||||
if (itm.Id() == Xow_ns_.Id_file) itm = ctx.Wiki().Ns_mgr().Ns_file(); // handles "Image" -> "File"
|
||||
bfr.Add(encode ? itm.Name_enc() : itm.Name_txt());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Xow_ns itm = (Xow_ns)ctx.Wiki().Ns_mgr().Ids_get_or_null(ns_id);
|
||||
if (itm == null) return; // occurs when ns_id is not known; EX: {{ns:999}}; SEE: Wiktionary:Grease pit archive/2007/October; "{{ns:114}}"
|
||||
bfr.Add(encode ? itm.Name_enc() : itm.Name_txt());
|
||||
}
|
||||
}
|
||||
private static Hash_adp_bry canonical;
|
||||
private static void canonical_() {
|
||||
canonical = Hash_adp_bry.ci_ascii_(); // ASCII:canonical English names
|
||||
for (Xow_ns ns : Xow_ns_.Canonical)
|
||||
canonical_add(ns.Id(), ns.Name_bry());
|
||||
}
|
||||
private static void canonical_add(int ns_id, byte[] ns_name) {
|
||||
Xow_ns ns = new Xow_ns(ns_id, Xow_ns_case_.Id_all, ns_name, false);
|
||||
canonical.Add(ns_name, ns);
|
||||
}
|
||||
}
|
||||
37
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ns_tst.java
Normal file
37
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ns_tst.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_ns_tst {
|
||||
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Ns_0() {fxt.Test_parse_tmpl_str_test("{{ns:0}}" , "{{test}}", "");}
|
||||
@Test public void Ns_10() {fxt.Test_parse_tmpl_str_test("{{ns:10}}" , "{{test}}", "Template");}
|
||||
@Test public void Ns_11() {fxt.Test_parse_tmpl_str_test("{{ns:11}}" , "{{test}}", "Template talk");}
|
||||
@Test public void Ns_11_ws() {fxt.Test_parse_tmpl_str_test("{{ns: 11 }}" , "{{test}}", "Template talk");}
|
||||
@Test public void Ns_Template() {fxt.Test_parse_tmpl_str_test("{{ns:Template}}" , "{{test}}", "Template");}
|
||||
@Test public void Ns_invalid() {fxt.Test_parse_tmpl_str_test("{{ns:252}}" , "{{test}}", "");}
|
||||
@Test public void Nse_10() {fxt.Test_parse_tmpl_str_test("{{nse:10}}" , "{{test}}", "Template");}
|
||||
@Test public void Nse_11() {fxt.Test_parse_tmpl_str_test("{{nse:11}}" , "{{test}}", "Template_talk");}
|
||||
@Test public void Ns_Image() {fxt.Test_parse_tmpl_str_test("{{ns:Image}}" , "{{test}}", "File");}
|
||||
@Test public void Ns_Templatex() {fxt.Test_parse_tmpl_str_test("{{ns:Templatex}}" , "{{test}}", "");}
|
||||
@Test public void Ns_Talk() { // PURPOSE: non-English wikis may have parameterized Project Talk ($1 talk); swap out with ns:4; REF.MW: Language.php!fixVariableInNamespace
|
||||
fxt.Wiki().Ns_mgr().Clear().Add_new(4, "wiki").Add_new(5, "$1 talk").Add_new(10, "Template").Init();
|
||||
fxt.Test_parse_tmpl_str_test("{{ns:5}}" , "{{test}}", "wiki talk");
|
||||
}
|
||||
@Test public void Ns_neg1() {fxt.Test_parse_tmpl_str_test("{{ns:-1}}" , "{{test}}", "Special");} // PURPOSE.FIX:handle special; DATE:2015-05-18
|
||||
}
|
||||
183
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_rel2abs.java
Normal file
183
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_rel2abs.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
public class Pfunc_rel2abs extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
private static final byte[] Ary_dot_slash = Bry_.new_a7("./"), Ary_dot_dot = Bry_.new_a7(".."), Ary_dot_dot_slash = Bry_.new_a7("../");
|
||||
private static void qry_bgns_with_init() {
|
||||
qry_bgns_with = Btrie_fast_mgr.cs_();
|
||||
qry_bgns_with.Add(Byte_ascii.Slash, Int_obj_ref.new_(Id_slash));
|
||||
qry_bgns_with.Add(Byte_ascii.Dot, Int_obj_ref.new_(Id_dot));
|
||||
qry_bgns_with.Add(Ary_dot_slash, Int_obj_ref.new_(Id_dot_slash));
|
||||
qry_bgns_with.Add(Ary_dot_dot, Int_obj_ref.new_(Id_dot_dot));
|
||||
qry_bgns_with.Add(Ary_dot_dot_slash, Int_obj_ref.new_(Id_dot_dot_slash));
|
||||
} static Btrie_fast_mgr qry_bgns_with;
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {// REF.MW:ParserFunctions_body.php
|
||||
byte[] qry = Eval_argx(ctx, src, caller, self);
|
||||
byte[] orig = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 0);
|
||||
if (orig.length == 0) orig = ctx.Cur_page().Ttl().Full_txt();
|
||||
bb.Add(Rel2abs(ctx.App().Utl__bfr_mkr().Get_b512().Mkr_rls(), qry, orig));
|
||||
}
|
||||
public static boolean Rel2abs_ttl(byte[] ttl, int bgn, int end) {
|
||||
int last = end - 1;
|
||||
if (end - bgn > Xoa_ttl.Max_len) return false; // NOTE: some tmpls have long #if statements; quicker to fail here than wait for invalid char below
|
||||
boolean rv = false;
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
switch (ttl[i]) {
|
||||
case Byte_ascii.Gt: case Byte_ascii.Pipe: // simplified version of Xoa_ttl parse; note that Xoa_ttl accepts these if anchor is seen; this proc assumes that anything with anchor and invalid char is an invalid rel2abs; EX: "A../b#c[d" is not valid; DATE:2013-03-31
|
||||
case Byte_ascii.Brack_bgn: case Byte_ascii.Brack_end: case Byte_ascii.Curly_bgn: case Byte_ascii.Curly_end:
|
||||
return false;
|
||||
case Byte_ascii.Slash:
|
||||
if ( !rv &&
|
||||
( (i == bgn) // bgns with "/"
|
||||
|| (i > bgn && ttl[i - 1] == Byte_ascii.Dot) // "./"
|
||||
|| (i < last && ttl[i + 1] == Byte_ascii.Dot) // "/."
|
||||
)
|
||||
) rv = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static final Int_obj_ref ignore_rel2abs_tid = Int_obj_ref.zero_();
|
||||
public static byte[] Rel2abs(Bry_bfr tmp_bfr, byte[] qry, byte[] src) {return Rel2abs(tmp_bfr, qry, src, ignore_rel2abs_tid);}
|
||||
public static byte[] Rel2abs(Bry_bfr tmp_bfr, byte[] qry, byte[] src, Int_obj_ref rel2abs_tid) {
|
||||
if (qry_bgns_with == null) qry_bgns_with_init();
|
||||
int qry_len = qry.length, src_len = src.length;
|
||||
|
||||
// qry_len = RTrim(qry, Byte_ascii.Slash, qry_bgn, qry_len); // not needed, but test anyway
|
||||
if (qry_len == 0) return src;// no qry; return src; EX:{{#rel2abs:|a/b}} -> a/b
|
||||
|
||||
byte[] tmp = src;
|
||||
int tmp_adj = 0, i = 0, prv_slash_end = 0, tmp_len = src_len, seg_pos = 0;
|
||||
boolean tmp_is_1st = true;
|
||||
Object o = qry_bgns_with.Match_bgn(qry, 0, qry_len); // check if qry begins with ".", "/", "./", "../"; if it doesn't return;
|
||||
if (o != null) {
|
||||
int id = ((Int_obj_ref)o).Val();
|
||||
rel2abs_tid.Val_(id);
|
||||
switch (id) {
|
||||
case Id_dot: // "."
|
||||
break;
|
||||
case Id_slash: // "/"
|
||||
case Id_dot_slash: // "./"
|
||||
case Id_dot_dot_slash: // "../"
|
||||
break; // qry is relative to src; noop
|
||||
case Id_dot_dot: // ".."
|
||||
int match_end = qry_bgns_with.Match_pos();
|
||||
if (match_end < qry_len && qry[match_end] == Byte_ascii.Dot) // NOTE: handles "..."; if "...*" then treat as invalid and return; needed for en.wiktionary.org/wiki/Wiktionary:Requests for cleanup/archive/2006
|
||||
return qry;
|
||||
break;
|
||||
default:
|
||||
return qry; // NOTE: lnki parsing currently has fuzzy logic to try to detect rel2abs; for now, if false match, then return original
|
||||
}
|
||||
}
|
||||
else { // qry is not relative to src; src is ignored; EX:{{#rel2abs:c|a/b}} -> c
|
||||
src_len = 0;
|
||||
tmp = qry;
|
||||
tmp_len = qry_len;
|
||||
tmp_is_1st = false;
|
||||
}
|
||||
// create segs; see NOTE_1 for approach
|
||||
byte b = Byte_.Zero;
|
||||
boolean loop = true, dot_mode = true;
|
||||
while (loop) {
|
||||
if (i == tmp_len) { // finished an ary (either src or qry)
|
||||
if (tmp_is_1st) { // finished src; EX: A/b
|
||||
tmp_is_1st = false;
|
||||
tmp = qry;
|
||||
tmp_adj = src_len + 1;
|
||||
tmp_len = src_len + 1 + qry_len;
|
||||
}
|
||||
else // finished qry; EX: ../c
|
||||
loop = false;
|
||||
b = Byte_ascii.Slash; // fake a slash between ary and src
|
||||
}
|
||||
else // inside ary
|
||||
b = tmp[i - tmp_adj];
|
||||
switch (b) {
|
||||
case Byte_ascii.Dot: // "."; ignore; note that dot_mode defaults to true
|
||||
break;
|
||||
default: // something else besides dot or slash; reset dot_mode
|
||||
dot_mode = false;
|
||||
break;
|
||||
case Byte_ascii.Slash: // "/"; seg finished
|
||||
int seg_len = i - prv_slash_end; // EX: "a/b/c" prv_slash_end = 2; i = 3; len = 1
|
||||
boolean create_seg = false;
|
||||
switch (seg_len) {
|
||||
case 0: // "//"; ignore
|
||||
break;
|
||||
case 1: // "/?/"
|
||||
if (dot_mode) {} // "/./"; current seg; ignore;
|
||||
else create_seg = true; // something else (EX: /A/); create seg;
|
||||
break;
|
||||
case 2:
|
||||
if (dot_mode) { // "/../"; pop seg_ary
|
||||
seg_pos -= 2;
|
||||
if (seg_pos < 0) return Bry_.Empty; // FUTURE: return MediaWiki error
|
||||
}
|
||||
else create_seg = true; // something else; create seg
|
||||
break;
|
||||
default: // something else; create seg
|
||||
create_seg = true;
|
||||
break;
|
||||
}
|
||||
if (create_seg) {
|
||||
seg_ary[seg_pos++] = prv_slash_end;
|
||||
seg_ary[seg_pos++] = i;
|
||||
}
|
||||
prv_slash_end = i + 1; // +1: place after slash
|
||||
dot_mode = true; // reset dot_mode
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// write segs
|
||||
tmp = src; tmp_adj = 0; tmp_is_1st = true; tmp_len = src_len;
|
||||
if (src_len == 0) {
|
||||
tmp = qry;
|
||||
tmp_len = qry_len;
|
||||
tmp_is_1st = false;
|
||||
}
|
||||
for (int j = 0; j < seg_pos; j += 2) {
|
||||
if (j != 0) tmp_bfr.Add_byte(Byte_ascii.Slash);
|
||||
if (seg_ary[j] >= tmp_len) {
|
||||
tmp = qry;
|
||||
tmp_adj = src_len + 1;
|
||||
}
|
||||
tmp_bfr.Add_mid(tmp, seg_ary[j] - tmp_adj, seg_ary[j+1] - tmp_adj);
|
||||
}
|
||||
return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
private static int[] seg_ary = new int[Xoa_ttl.Max_len];
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_rel2abs;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_rel2abs().Name_(name);}
|
||||
public static final int Id_null = 0, Id_slash = 1, Id_dot = 2, Id_dot_slash = 3, Id_dot_dot = 4, Id_dot_dot_slash = 5;
|
||||
}
|
||||
/*
|
||||
NOTE_1:approach (easiest explained with an example)
|
||||
given qry = "../C/./D" and src = "A/B"
|
||||
. combine two into a pseudo-array: "A/B/../C/./D"
|
||||
. iterate over every slash to create "segs_ary"
|
||||
A -> [A] add
|
||||
B -> [A, B] add
|
||||
.. -> [A] pop
|
||||
C -> [A, C] add
|
||||
. -> [A, C] noop
|
||||
D -> [A, C, D] add
|
||||
*/
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_rel2abs_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Slash_lvl3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/d|a/b/c}}" , "{{test}}" , "a/b/c/d");}
|
||||
@Test public void Cur_lvl1() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:./d|a}}" , "{{test}}" , "a/d");}
|
||||
@Test public void Cur_lvl2() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:./d|a/b}}" , "{{test}}" , "a/b/d");}
|
||||
@Test public void Cur_lvl3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:./d|a/b/c}}" , "{{test}}" , "a/b/c/d");}
|
||||
@Test public void Owner_lvl3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:../d|a/b/c}}" , "{{test}}" , "a/b/d");}
|
||||
@Test public void Owner_cur_lvl3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:../.|a/b/c}}" , "{{test}}" , "a/b");}
|
||||
@Test public void Text_lvl3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:d|a/b/c}}" , "{{test}}" , "d");}
|
||||
@Test public void Slash_mult() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/d//e|a/b/c}}" , "{{test}}" , "a/b/c/d/e");}
|
||||
@Test public void Slash_cur_mult() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/d/./e|a/b/c}}" , "{{test}}" , "a/b/c/d/e");}
|
||||
@Test public void Qry_ends_w_slash() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/d/|a/b/c}}" , "{{test}}" , "a/b/c/d");}
|
||||
@Test public void Qry_is_empty() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:|a/b/c}}" , "{{test}}" , "a/b/c");}
|
||||
@Test public void Qry_is_dot() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:.|a/b/c}}" , "{{test}}" , "a/b/c");}
|
||||
@Test public void DotDot_mult2() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/../..|a/b/c}}" , "{{test}}" , "a");}
|
||||
@Test public void DotDot_mult3() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/../../..|a/b/c}}" , "{{test}}" , "");}
|
||||
@Test public void Src_is_empty() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/d|}}" , "{{test}}" , "Test page/d");}
|
||||
@Test public void Err_owner() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:..}}" , "{{test}}" , "");} // PURPOSE.fix: should not fail
|
||||
@Test public void Err_owner_2() {fxt.Test_parse_tmpl_str_test("{{#rel2abs:/../../b|a}}" , "{{test}}" , "");} // PURPOSE.fix: should not fail
|
||||
@Test public void Ns_should_be_included_for_cur_page() {// PURPOSE.fix: current title was not returning ns; EX: de.wikipedia.org/wiki/Hilfe:Vorlagenprogrammierung#Funktion_rel2abs
|
||||
fxt.Page_ttl_("Help:A"); // set page to title with namespace
|
||||
fxt.Test_parse_tmpl_str_test("{{#rel2abs:.}}" , "{{test}}" , "Help:A");
|
||||
}
|
||||
@Test public void Owner_lvl0() {// PURPOSE.fix: old rel2abs was producing "/c"; EX: de.wikipedia.org/wiki/Hilfe:Vorlagenprogrammierung#Funktion_rel2abs
|
||||
fxt.Test_parse_tmpl_str_test("{{#rel2abs:../c|a}}" , "{{test}}" , "c");
|
||||
}
|
||||
@Test public void Rel2abs_slash() {
|
||||
fxt.Page_ttl_("Page_1");
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test" , "{{/B}}");
|
||||
fxt.Init_page_create("Page_1/B" , "Page_1/B text");
|
||||
fxt.Test_parse_tmpl_str("{{test}}" , "Page_1/B text");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Rel2abs_dot() {
|
||||
fxt.Page_ttl_("Page_1/A");
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test" , "{{../C}}");
|
||||
fxt.Init_page_create("Page_1/C" , "Page_1/C text");
|
||||
fxt.Test_parse_tmpl_str("{{test}}" , "Page_1/C text");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Rel2abs_ttl() {
|
||||
Tst_rel2abs_ttl("a../b", true);
|
||||
Tst_rel2abs_ttl("a../[b", false);
|
||||
}
|
||||
private void Tst_rel2abs_ttl(String raw, boolean expd) {Tfds.Eq(expd, Pfunc_rel2abs.Rel2abs_ttl(Bry_.new_a7(raw), 0, String_.Len(raw)));}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.ints.*; import gplx.xowa.xtns.pfuncs.times.*;
|
||||
public class Pfunc_titleparts extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {// REF.MW:ParserFunctions_body.php
|
||||
// get argx
|
||||
int args_len = self.Args_len();
|
||||
byte[] argx = Eval_argx(ctx, src, caller, self); if (argx == null) return; // no argx; return empty
|
||||
Xoa_ttl argx_as_ttl = Xoa_ttl.new_(ctx.Wiki(), ctx.App().Msg_log_null(), argx, 0, argx.length); // transform to title in order to upper first, replace _, etc..
|
||||
if (argx_as_ttl == null) {bb.Add(argx); return;} // NOTE: argx_as_ttl will be null if invalid, such as [[a|b]]; PAGE:en.w:owl and {{taxobox/showtaxon|Dinosauria}}
|
||||
else argx = argx_as_ttl.Full_txt();
|
||||
|
||||
// get parts_len
|
||||
byte[] parts_len_ary = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0);
|
||||
int parts_len = parts_len_ary == Bry_.Empty ? Int_.MinValue : Bry_.Xto_int_or(parts_len_ary, Int_.MaxValue);
|
||||
if (parts_len == Int_.MaxValue) {// len is not an int; EX: "a";
|
||||
ctx.Msg_log().Add_itm_none(Pfunc_titleparts_log.Len_is_invalid, src, caller.Src_bgn(), caller.Src_end());
|
||||
bb.Add(argx);
|
||||
return;
|
||||
}
|
||||
|
||||
// get parts_bgn
|
||||
byte[] parts_bgn_arg = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 1);
|
||||
int parts_bgn = parts_bgn_arg == Bry_.Empty ? 0 : Bry_.Xto_int_or(parts_bgn_arg, Int_.MinValue);
|
||||
if (parts_bgn == Int_.MinValue) {// parts_bgn is not an int; EX: "a"
|
||||
ctx.Msg_log().Add_itm_none(Pfunc_titleparts_log.Bgn_is_invalid, src, caller.Src_bgn(), caller.Src_end());
|
||||
parts_bgn = 0; // NOTE: do not return
|
||||
}
|
||||
else if (parts_bgn > 0) parts_bgn -= List_adp_.Base1; // adjust for base1
|
||||
bb.Add(TitleParts(argx, parts_len, parts_bgn));
|
||||
}
|
||||
private byte[] TitleParts(byte[] src, int parts_len, int parts_bgn) {
|
||||
// find dlm positions; EX: ab/cde/f/ will have -1,2,6,8
|
||||
int src_len = src.length; int dlms_ary_len = 1; // 1 b/c dlms_ary[0] will always be -1
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
if (src[i] == Byte_ascii.Slash) dlms_ary[dlms_ary_len++] = i;
|
||||
}
|
||||
dlms_ary[dlms_ary_len] = src_len; // put src_len into last dlms_ary; makes dlms_ary[] logic easier
|
||||
|
||||
// calc bgn_idx; must occur before adjust parts_len
|
||||
int bgn_idx = parts_bgn > -1 ? parts_bgn : parts_bgn + dlms_ary_len; // negative parts_bgn means calc from end of dlms_ary_len; EX a/b/c|1|-1 means start from 2
|
||||
if ( bgn_idx < 0 // bgn_idx can be negative when parts_len is negative and greater than array; EX: {{#titleparts:a/b|-1|-2}} results in dlms_ary_len of 1 and parts_bgn of -2 which will be parts_bgn of -1
|
||||
|| bgn_idx > dlms_ary_len) return Bry_.Empty; // if bgn > len, return ""; EX: {{#titleparts:a/b|1|3}} should return ""
|
||||
|
||||
// adjust parts_len for negative/null
|
||||
if (parts_len == Int_.MinValue) parts_len = dlms_ary_len; // no parts_len; default to dlms_ary_len
|
||||
else if (parts_len < 0) { // neg parts_len; shorten parts now and default to rest of String; EX: a/b/c|-1 -> makes String a/b/c and get 2 parts
|
||||
dlms_ary_len += parts_len;
|
||||
parts_len = dlms_ary_len;
|
||||
if (parts_len < 1) return Bry_.Empty; // NOTE: if zerod'd b/c of neg length, return empty; contrast with line below; EX: a/b/c|-4
|
||||
}
|
||||
if (parts_len == 0) return src; // if no dlms, return orig
|
||||
|
||||
// calc idxs for extraction
|
||||
int bgn_pos = dlms_ary[bgn_idx] + 1; // +1 to start after slash
|
||||
int end_idx = bgn_idx + parts_len;
|
||||
int end_pos = end_idx > dlms_ary_len ? dlms_ary[dlms_ary_len] : dlms_ary[end_idx];
|
||||
if (end_pos < bgn_pos) return Bry_.Empty;
|
||||
return Bry_.Mid(src, bgn_pos, end_pos);
|
||||
} static int[] dlms_ary = new Int_ary_bldr(255).Set(0, -1).Xto_int_ary(); // set pos0 to -1; makes +1 logic easier
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_titleparts;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_titleparts().Name_(name);}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_titleparts_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Len1() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|1}}" , "{{test}}", "A");}
|
||||
@Test public void Len2() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|2}}" , "{{test}}", "A/b");}
|
||||
@Test public void Len2_Bgn2() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|2|2}}" , "{{test}}", "b/c");}
|
||||
@Test public void LenNeg1() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|-1}}" , "{{test}}", "A/b/c");}
|
||||
@Test public void LenNeg1Bgn2() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|-1|2}}" , "{{test}}", "b/c");}
|
||||
|
||||
@Test public void Exc_len0() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|0}}" , "{{test}}", "A/b/c/d");}
|
||||
@Test public void Exc_lenNeg4() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|-4}}" , "{{test}}", "");}
|
||||
@Test public void Exc_lenNeg5() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|-5}}" , "{{test}}", "");}
|
||||
@Test public void Exc_no_dlm() {fxt.Test_parse_tmpl_str_test("{{#titleparts:abcd|1}}" , "{{test}}", "Abcd");}
|
||||
@Test public void Exc_parts0() {fxt.Test_parse_tmpl_str_test("{{#titleparts:abcd|0}}" , "{{test}}", "Abcd");}
|
||||
@Test public void Exc_many_segs() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b|1|4}}" , "{{test}}", "");} // PURPOSE: bgn=4, len=1 requested; only bgn=1,2 available
|
||||
|
||||
@Test public void Exc_bad_len() {fxt.Init_log_(Pfunc_titleparts_log.Len_is_invalid).Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|bad}}" , "{{test}}", "A/b/c/d");}
|
||||
@Test public void Exc_bad_bgn() {fxt.Init_log_(Pfunc_titleparts_log.Bgn_is_invalid).Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d|1|bad}}" , "{{test}}", "A");}
|
||||
@Test public void Exc_1() {fxt.Test_parse_tmpl_str_test("{{#titleparts:50|1|1}}" , "{{test}}", "50");}
|
||||
@Test public void Exc_2() {fxt.Test_parse_tmpl_str_test("{{#titleparts:50|1|2}}" , "{{test}}", "");}
|
||||
|
||||
@Test public void Lnki() {fxt.Test_parse_tmpl_str_test("{{#titleparts:[[a|b]]|1}}" , "{{test}}", "[[a|b]]");} // PURPOSE: invalid title was not being rendered
|
||||
@Test public void Invalid_table() {// PURPOSE: Template:Taxobox/showtaxon calls #titleparts on table fragments; do not remove new lines; PAGE:en.w:Owl
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("!", "|");
|
||||
fxt.Init_defn_add("!!", "||");
|
||||
fxt.Test_parse_tmpl_str_test
|
||||
( String_.Concat_lines_nl_skip_last
|
||||
( "{|"
|
||||
, "|-"
|
||||
, "{{#titleparts:"
|
||||
, "{{!}} Order: {{!!}} '''Strigiformes'''"
|
||||
, "{{!}}-|1}}"
|
||||
, "|}"
|
||||
)
|
||||
, "{{test}}"
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "" // NOTE: don't know why this new line is necessary, but hopefully it is benign
|
||||
, "{|"
|
||||
, "|-"
|
||||
, "| Order: || '''Strigiformes'''"
|
||||
, "|-"
|
||||
, "|}"
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Invalid_xml() {// PURPOSE: handle calls like {{#titleparts:a<span id='b'>c</span>d|1}}; PAGE:en.w:Triceratops
|
||||
fxt.Test_parse_tmpl_str_test
|
||||
( "{{#titleparts:a<span id='b'>c</span>d/e|1}}"
|
||||
, "{{test}}"
|
||||
, "a<span id='b'>c</span>d/e"
|
||||
);
|
||||
}
|
||||
@Test public void Bgn_neg_1() {fxt.Test_parse_tmpl_str_test("{{#titleparts:a/b/c/d||-1}}" , "{{test}}", "d");}
|
||||
@Test public void Bgn_neg_2() { // PURPOSE: EX: Wikisource:Requests for comment/Annotations and derivative works; DATE:2013-12-19
|
||||
fxt.Test_parse_tmpl_str_test
|
||||
( "{{#titleparts:a/b|-1|-2}}"
|
||||
, "{{test}}"
|
||||
, "A"
|
||||
);
|
||||
}
|
||||
}
|
||||
51
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ttl.java
Normal file
51
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ttl.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_ttl extends Pf_func_base {
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] val_dat_ary = Eval_argx_or_null(ctx, src, caller, self, this.Name());
|
||||
if (val_dat_ary == Bry_.Empty) return; // if argx is empty, return EX: {{PAGENAME:}}; DATE:2013-02-20
|
||||
Xoa_ttl ttl = val_dat_ary == null ? ctx.Cur_page().Ttl() : Xoa_ttl.parse_(ctx.Wiki(), val_dat_ary);
|
||||
if (ttl == null) return;
|
||||
switch (id) {
|
||||
case Xol_kwd_grp_.Id_ttl_page_txt: bfr.Add(ttl.Page_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_page_url: bfr.Add(ttl.Page_url()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_full_txt: bfr.Add(ttl.Full_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_full_url: bfr.Add(ttl.Full_url()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_leaf_txt: bfr.Add(ttl.Leaf_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_leaf_url: bfr.Add(ttl.Leaf_url()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_base_txt: bfr.Add(ttl.Base_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_base_url: bfr.Add(ttl.Base_url()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_subj_txt: bfr.Add(ttl.Subj_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_subj_url: bfr.Add(ttl.Subj_url()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_talk_txt: bfr.Add(ttl.Talk_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ttl_talk_url: bfr.Add(ttl.Talk_url()); break;
|
||||
case Xol_kwd_grp_.Id_ns_num: bfr.Add_int_variable(ttl.Ns().Id()); break;
|
||||
case Xol_kwd_grp_.Id_ns_txt: bfr.Add(ttl.Ns().Name_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ns_url: bfr.Add(ttl.Ns().Name_enc()); break;
|
||||
case Xol_kwd_grp_.Id_ns_subj_txt: bfr.Add(ctx.Wiki().Ns_mgr().Ords_get_at(ttl.Ns().Ord_subj_id()).Name_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ns_subj_url: bfr.Add(ctx.Wiki().Ns_mgr().Ords_get_at(ttl.Ns().Ord_subj_id()).Name_enc()); break;
|
||||
case Xol_kwd_grp_.Id_ns_talk_txt: bfr.Add(ctx.Wiki().Ns_mgr().Ords_get_at(ttl.Ns().Ord_talk_id()).Name_txt()); break;
|
||||
case Xol_kwd_grp_.Id_ns_talk_url: bfr.Add(ctx.Wiki().Ns_mgr().Ords_get_at(ttl.Ns().Ord_talk_id()).Name_enc()); break;
|
||||
}
|
||||
}
|
||||
public Pfunc_ttl(int id) {this.id = id;}
|
||||
@Override public int Id() {return id;} private int id;
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ttl(id).Name_(name);}
|
||||
public static final Pfunc_ttl _ = new Pfunc_ttl(-1);
|
||||
}
|
||||
49
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ttl_tst.java
Normal file
49
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_ttl_tst.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_ttl_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Ttl_page_txt() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAME}}" , "{{test}}", "A b");}
|
||||
@Test public void Ttl_page_txt_empty() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAME:}}" , "{{test}}", "");}
|
||||
@Test public void Ttl_page_txt_empty_2() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAME:{{{a|}}}}}" , "{{test}}", "");} // PURPOSE.fix: {{PAGENAME:{{{nom|}}}}} should return ""; pt.wikipedia.org/wiki/Nicholas Kratzer; DATE:2013-02-20
|
||||
@Test public void Ttl_page_txt_arg() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAME:c d}}" , "{{test}}", "C d");}
|
||||
@Test public void Ttl_page_txt_amp() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAME:c & d}}" , "{{test}}", "C & d");}
|
||||
@Test public void Ttl_page_url() {fxt.Page_ttl_("a b"); fxt.Test_parse_tmpl_str_test("{{PAGENAMEE}}" , "{{test}}", "A_b");}
|
||||
@Test public void Ttl_full_txt() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{FULLPAGENAME}}" , "{{test}}", "Help:A b");}
|
||||
@Test public void Ttl_full_url() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{FULLPAGENAMEE}}" , "{{test}}", "Help:A_b");}
|
||||
@Test public void Ttl_leaf_txt() {fxt.Page_ttl_("a b/c/d e"); fxt.Test_parse_tmpl_str_test("{{SUBPAGENAME}}" , "{{test}}", "d e");}
|
||||
@Test public void Ttl_leaf_url() {fxt.Page_ttl_("a b/c/d e"); fxt.Test_parse_tmpl_str_test("{{SUBPAGENAMEE}}" , "{{test}}", "d_e");}
|
||||
@Test public void Ttl_base_txt() {fxt.Page_ttl_("a b/c/d e"); fxt.Test_parse_tmpl_str_test("{{BASEPAGENAME}}" , "{{test}}", "A b/c");}
|
||||
@Test public void Ttl_base_url() {fxt.Page_ttl_("a b/c/d e"); fxt.Test_parse_tmpl_str_test("{{BASEPAGENAMEE}}" , "{{test}}", "A_b/c");}
|
||||
@Test public void Ttl_subj_txt() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{SUBJECTPAGENAME}}" , "{{test}}", "Help:A b");}
|
||||
@Test public void Ttl_subj_url() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{SUBJECTPAGENAMEE}}" , "{{test}}", "Help:A_b");}
|
||||
@Test public void Ttl_talk_txt() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{TALKPAGENAME}}" , "{{test}}", "Help talk:A b");}
|
||||
@Test public void Ttl_talk_url() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{TALKPAGENAMEE}}" , "{{test}}", "Help_talk:A_b");}
|
||||
@Test public void Ns_num() {fxt.Page_ttl_("Help:A"); fxt.Test_parse_tmpl_str_test("{{NAMESPACENUMBER}}" , "{{test}}", "12");}
|
||||
@Test public void Ns_txt() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{NAMESPACE}}" , "{{test}}", "Help talk");}
|
||||
@Test public void Ns_url() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{NAMESPACEE}}" , "{{test}}", "Help_talk");}
|
||||
@Test public void Ns_subj_txt() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{SUBJECTSPACE}}" , "{{test}}", "Help");}
|
||||
@Test public void Ns_subj_url() {fxt.Page_ttl_("Help talk:a b"); fxt.Test_parse_tmpl_str_test("{{SUBJECTSPACEE}}" , "{{test}}", "Help");}
|
||||
@Test public void Ns_talk_txt() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{TALKSPACE}}" , "{{test}}", "Help talk");}
|
||||
@Test public void Ns_talk_url() {fxt.Page_ttl_("Help:a b"); fxt.Test_parse_tmpl_str_test("{{TALKSPACEE}}" , "{{test}}", "Help_talk");}
|
||||
@Test public void Ns_safesubst() {fxt.Page_ttl_("Help:a"); fxt.Test_parse_tmpl_str_test("{{{{{|safesubst:}}}NAMESPACE}}" , "{{test}}", "Help");} // PURPOSE: "safesubst:NAMESPACE" was being interpreted as "NAMESPACE:" due to false colon detection; DATE:2013-11-11
|
||||
@Test public void Ns_safesubst2() {fxt.Page_ttl_("Help:a"); fxt.Test_parse_tmpl_str_test("{{{{{|safesubst:}}}NAMESPACE:}}" , "{{test}}", "");} //PURPOSE: makes sure "safesubst:NAMESPACE:" still returns ""
|
||||
@Test public void Exc_empty2() {fxt.Page_ttl_("Test"); fxt.Test_parse_tmpl_str_test("{{NAMESPACE:<noinclude>x</noinclude>}}" , "{{test}}", "");} // {{NMS:<ni>x</ni>}} -> {{NMS:}}
|
||||
}
|
||||
29
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_urlencode.java
Normal file
29
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_urlencode.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_urlencode extends Pf_func_base { // EX: {{urlencode:a b}} -> a+b
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
byte[] val_ary = Eval_argx(ctx, src, caller, self); if (val_ary == Bry_.Empty) return;
|
||||
Xoa_app_.Utl__encoder_mgr().Http_url().Encode(urlEncodeBfr, val_ary);
|
||||
bb.Add_bfr_and_preserve(urlEncodeBfr);
|
||||
urlEncodeBfr.Clear();
|
||||
} private Bry_bfr urlEncodeBfr = Bry_bfr.new_(128);
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_url_urlencode;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_urlencode().Name_(name);}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_urlencode_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Numbers() {fxt.Test_parse_tmpl_str_test("{{urlencode:0123456789}}" , "{{test}}", "0123456789");}
|
||||
@Test public void Ltrs_lower() {fxt.Test_parse_tmpl_str_test("{{urlencode:abcdefghijklmnopqrstuvwxyz}}" , "{{test}}", "abcdefghijklmnopqrstuvwxyz");}
|
||||
@Test public void Ltrs_upper() {fxt.Test_parse_tmpl_str_test("{{urlencode:ABCDEFGHIJKLMNOPQRSTUVWXYZ}}" , "{{test}}", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");}
|
||||
@Test public void Syms_allowed() {fxt.Test_parse_tmpl_str_test("{{urlencode:-_.}}" , "{{test}}", "-_.");}
|
||||
@Test public void Space() {fxt.Test_parse_tmpl_str_test("{{urlencode:a b}}" , "{{test}}", "a+b");}
|
||||
@Test public void Syms() {fxt.Test_parse_tmpl_str_test("{{urlencode:!?^~:}}" , "{{test}}", "%21%3F%5E%7E%3A");}
|
||||
@Test public void Extended() {fxt.Test_parse_tmpl_str_test("{{urlencode:aéb}}" , "{{test}}", "a%C3%A9b");}
|
||||
}
|
||||
65
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_urlfunc.java
Normal file
65
400_xowa/src/gplx/xowa/xtns/pfuncs/ttls/Pfunc_urlfunc.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.wikis.xwikis.*;
|
||||
import gplx.xowa.html.hrefs.*;
|
||||
public class Pfunc_urlfunc extends Pf_func_base { // EX: {{lc:A}} -> a
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self); if (val_dat_ary.length == 0) return;
|
||||
byte[] qry_arg = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 0);
|
||||
UrlString(ctx, tid, encode, val_dat_ary, bb, qry_arg);
|
||||
}
|
||||
public static void UrlString(Xop_ctx ctx, byte tid, boolean encode, byte[] src, Bry_bfr trg, byte[] qry_arg) {
|
||||
Xowe_wiki wiki = ctx.Wiki();
|
||||
Xoa_ttl ttl = Xoa_ttl.new_(wiki, ctx.Msg_log(), src, 0, src.length);
|
||||
if (ttl == null) return; // NOTE: guard against null ttl; EX: {{fullurl:{{transclude|{{{1}}}}}|action=edit}} -> {{fullurl:Template:{{{1}}}|action=edit}} -> Template:{{{1}}} will be a null ttl
|
||||
byte[] ttl_ary = ttl.Full_url();// NOTE: Full_url does encoding; don't encode again
|
||||
Xow_xwiki_itm xwiki = ttl.Wik_itm();
|
||||
if (xwiki != null) { // xwiki exists; add as //commons.wikimedia.org/wiki/A#b?c=d
|
||||
if (tid == Tid_canonical)
|
||||
trg.Add(Xoh_href_parser.Href_https_bry); // "https://"
|
||||
else
|
||||
trg.Add(Xoa_consts.Url_relative_prefix); // "//"
|
||||
trg.Add(xwiki.Domain_bry()) // "commons.wikimedia.org"
|
||||
.Add(Xoh_href_parser.Href_wiki_bry) // "/wiki/"
|
||||
.Add_mid(ttl_ary, xwiki.Key_bry().length + 1, ttl_ary.length); // "A#b?c=d"; +1 for colon after "commons:"; NOTE: ugly way of getting rest of url, but ttl currently does not have Full_wo_wiki
|
||||
}
|
||||
else {
|
||||
Bry_bfr tmp_bfr = ctx.App().Utl__bfr_mkr().Get_b512().Mkr_rls();
|
||||
switch (tid) {
|
||||
case Tid_local: tmp_bfr.Add(ctx.Wiki().Props().ArticlePath());break;
|
||||
case Tid_full: tmp_bfr.Add(Bry_relative_url).Add(ctx.Wiki().Props().ServerName()).Add(ctx.Wiki().Props().ArticlePath()); break;
|
||||
case Tid_canonical: tmp_bfr.Add(ctx.Wiki().Props().Server()).Add(ctx.Wiki().Props().ArticlePath()); break;
|
||||
default: throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
tmp_bfr.Add(ttl_ary);
|
||||
trg.Add_bfr_and_clear(tmp_bfr);
|
||||
}
|
||||
if (qry_arg != Bry_.Empty) trg.Add_byte(Byte_ascii.Question).Add(qry_arg);
|
||||
}
|
||||
public Pfunc_urlfunc(int id, byte tid, boolean encode) {this.id = id; this.tid = tid; this.encode = encode;} private byte tid; boolean encode;
|
||||
@Override public int Id() {return id;} private int id;
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_urlfunc(id, tid, encode).Name_(name);}
|
||||
public static final byte Tid_local = 0, Tid_full = 1, Tid_canonical = 2;
|
||||
public static final byte[] Bry_relative_url = Bry_.new_a7("//");
|
||||
}
|
||||
/*
|
||||
NOTE: Both fullurle: and localurle: performed additional character escaping on the resulting link, but no example is known where that still has any additional effect.
|
||||
http://meta.wikimedia.org/wiki/Help:Parser_function
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_urlfunc_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Localurl() {fxt.Test_parse_tmpl_str_test("{{localurl:a&b! c}}" , "{{test}}", "/wiki/A%26b!_c");}
|
||||
@Test public void Fullurl() {fxt.Test_parse_tmpl_str_test("{{fullurl:a&b! c}}" , "{{test}}", "//en.wikipedia.org/wiki/A%26b!_c");}
|
||||
@Test public void Canonicalurl() {fxt.Test_parse_tmpl_str_test("{{canonicalurl:a&b! c}}" , "{{test}}", "http://en.wikipedia.org/wiki/A%26b!_c");}
|
||||
@Test public void Canonicalurl_case() {fxt.Test_parse_tmpl_str_test("{{CANONICALURL:a&b! c}}" , "{{test}}", "http://en.wikipedia.org/wiki/A%26b!_c");}
|
||||
@Test public void Localurle() {fxt.Test_parse_tmpl_str_test("{{localurle:a&b! c}}" , "{{test}}", "/wiki/A%26b!_c");}
|
||||
@Test public void Fullurle() {fxt.Test_parse_tmpl_str_test("{{fullurle:a&b! c}}" , "{{test}}", "//en.wikipedia.org/wiki/A%26b!_c");}
|
||||
@Test public void Canonicalurle() {fxt.Test_parse_tmpl_str_test("{{canonicalurle:a&b! c}}" , "{{test}}", "http://en.wikipedia.org/wiki/A%26b!_c");}
|
||||
@Test public void Fullurl_arg() {fxt.Test_parse_tmpl_str_test("{{fullurle:a&b! c|action=edit}}" , "{{test}}", "//en.wikipedia.org/wiki/A%26b!_c?action=edit");}
|
||||
@Test public void Random() {fxt.Test_parse_tmpl_str_test("{{fullurle:a&b! c|action=edit}}" , "{{test|a|b|c}}", "//en.wikipedia.org/wiki/A%26b!_c?action=edit");}
|
||||
@Test public void Xwiki() {
|
||||
fxt.Wiki().Xwiki_mgr().Add_full("commons", "commons.wikimedia.org");
|
||||
fxt.Reset().Test_parse_tmpl_str_test("{{localurl:commons:A}}" , "{{test}}", "//commons.wikimedia.org/wiki/A");
|
||||
fxt.Reset().Test_parse_tmpl_str_test("{{fullurl:commons:A}}" , "{{test}}", "//commons.wikimedia.org/wiki/A");
|
||||
fxt.Reset().Test_parse_tmpl_str_test("{{canonicalurl:commons:A}}" , "{{test}}", "https://commons.wikimedia.org/wiki/A");
|
||||
}
|
||||
@Test public void Xwiki_qarg_fix() {
|
||||
fxt.Wiki().Xwiki_mgr().Add_full("commons", "commons.wikimedia.org");
|
||||
fxt.Reset().Test_parse_tmpl_str_test("{{fullurl:commons:A|key=val}}" , "{{test}}", "//commons.wikimedia.org/wiki/A?key=val");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user