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:
205
400_xowa/src_500_tmpl/gplx/xowa/Arg_bldr.java
Normal file
205
400_xowa/src_500_tmpl/gplx/xowa/Arg_bldr.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
class Arg_bldr {
|
||||
public boolean Bld(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_arg_wkr wkr, int wkr_typ, Xop_root_tkn root, Xop_tkn_itm tkn, int bgn_pos, int cur_pos, int loop_bgn, int loop_end, byte[] src) {
|
||||
boolean ws_bgn_chk = true, colon_chk = false, itm_is_static = true, key_exists = false; int ws_bgn_idx = -1, ws_end_idx = -1, cur_itm_subs_len = 0, cur_nde_idx = -1; Arg_nde_tkn cur_nde = null; Arg_itm_tkn cur_itm = null;
|
||||
int brack_count = 0;
|
||||
Xop_tkn_itm eq_pending = null;
|
||||
for (int i = loop_bgn; i < loop_end; i++) { // loop over subs between bookends; if lnki, all tkns between [[ and ]]; if tmpl, {{ and }}
|
||||
Xop_tkn_itm sub = root.Subs_get(i);
|
||||
int sub_pos_bgn = sub.Src_bgn_grp(root, i);
|
||||
if (cur_nde == null) {
|
||||
cur_nde = tkn_mkr.ArgNde(++cur_nde_idx, sub_pos_bgn);
|
||||
brack_count = 0; key_exists = false;
|
||||
}
|
||||
if (cur_itm == null) {
|
||||
cur_itm = tkn_mkr.ArgItm(sub_pos_bgn, -1);
|
||||
itm_is_static = ws_bgn_chk = true; cur_itm_subs_len = 0; ws_bgn_idx = ws_end_idx = -1;
|
||||
if (eq_pending != null) { // something like "A==B" encountered; zh.w:Wikipedia:条目评选; DATE:2014-08-27
|
||||
eq_pending.Src_end_(eq_pending.Src_end() -1); // remove an "=" EX:"A==B" -> "A","=","=B"
|
||||
cur_itm.Subs_add_grp(eq_pending, root, i); cur_itm_subs_len++; // add the tkn to cur_itm
|
||||
eq_pending = null;
|
||||
}
|
||||
}
|
||||
switch (sub.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_ignore: // comment or *include* tkn; mark itm as non_static for tmpl (forces re-eval)
|
||||
switch (wkr_typ) {
|
||||
case Xop_arg_wkr_.Typ_tmpl:
|
||||
case Xop_arg_wkr_.Typ_prm:
|
||||
itm_is_static = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_para: // NOTE: para can appear in following: [[File:A.png| \n 40px]]; EX: w:Supreme_Court_of_the_United_States; DATE:2014-04-05
|
||||
case Xop_tkn_itm_.Tid_newLine: case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab: // whitespace
|
||||
if (ws_bgn_chk) ws_bgn_idx = cur_itm_subs_len; // definite ws at bgn; set ws_bgn_idx, and keep setting until text tkn reached; handles mixed sequence of \s\n\t where last tkn should be ws_bgn_idx
|
||||
else {if (ws_end_idx == -1) ws_end_idx = cur_itm_subs_len;}; // possible ws at end; may be overriden later; see AdjustWsForTxtTkn
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_colon:
|
||||
if (wkr_typ == Xop_arg_wkr_.Typ_tmpl) { // treat colons as text; tmpl will do its own : parsing for 1st arg; NOTE: must do ws check else 2nd colon will break; EX: "{{#ifeq: :|a|b|c}}"; DATE:2013-12-10
|
||||
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
}
|
||||
else {
|
||||
if (cur_nde_idx == 0 && !colon_chk) { // if 1st arg, mark colon pos; needed for lnki; EX: [[Category:A]]; {{#ifeq:1}}
|
||||
colon_chk = true;
|
||||
cur_nde.Arg_colon_pos_(sub_pos_bgn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_brack_bgn: ++brack_count; if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_brack_end: --brack_count; if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_eq:
|
||||
if (wkr_typ == Xop_arg_wkr_.Typ_tmpl && brack_count > 0) {}
|
||||
else if (wkr_typ == Xop_arg_wkr_.Typ_prm) {} // always ignore for prm
|
||||
else {
|
||||
if ( cur_nde_idx != 0 // if 1st arg, treat equal_tkn as txt_tkn; i.e.: eq should not be used to separate key/val
|
||||
&& cur_nde.Eq_tkn() == Xop_tkn_null.Null_tkn // only mark key if key is not set; handle multiple-keys; EX: {{name|key1=b=c}}; DATE:2014-02-09
|
||||
) {
|
||||
Xop_eq_tkn sub_as_eq = (Xop_eq_tkn)sub;
|
||||
int sub_as_eq_len = sub_as_eq.Eq_len();
|
||||
boolean eq_is_spr
|
||||
= sub_as_eq_len == 1 // eq with len of 1 are considered separators; MW.REF:Preprocessor_DOM.php|preprocessToXml; "if ( $count == 1 && $findEquals )" PAGE:en.w:Wikipedia:Picture_of_the_day/June_2014; DATE:2014-07-21
|
||||
|| ( cur_itm.Subs_len() > 0 // or eq.len > 1 that occur later in itm; EX: a==b; zh.w:Wikipedia:条目评选; DATE:2014-08-27
|
||||
&& cur_itm.Subs_get(0).Tkn_tid() != Xop_tkn_itm_.Tid_eq // and 1st tkn is not ==; EX:==a==; 2nd == should not be eq b/c 1st == "deactivates" nde; DATE:2014-08-27
|
||||
);
|
||||
if (eq_is_spr) {
|
||||
if (sub_as_eq_len == 1) // =.len == 1
|
||||
cur_nde.Eq_tkn_(sub); // set as eq tkn
|
||||
else // =.len > 1
|
||||
eq_pending = sub; // do not set as eq tkn; note that Eq_tkn exists for bookkeeping and is not printed out,
|
||||
key_exists = true;
|
||||
Arg_itm_end(ctx, cur_nde, cur_itm, ws_bgn_idx, ws_end_idx, cur_itm_subs_len, sub_pos_bgn, wkr_typ, key_exists, true, itm_is_static, src, cur_nde_idx);
|
||||
cur_nde.Key_tkn_(cur_itm);
|
||||
cur_itm = null;
|
||||
continue; // do not add tkn to cur_itm
|
||||
}
|
||||
}
|
||||
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_pipe:
|
||||
if (cur_nde_idx == 0
|
||||
&& ws_bgn_chk
|
||||
&& !colon_chk
|
||||
&& wkr_typ == Xop_arg_wkr_.Typ_tmpl
|
||||
) return false; // 1st arg, but no name; EX: "{{|a}}", "{{ }}"; disregard if lnki, since "[[|a]]" is valid
|
||||
if (wkr_typ == Xop_arg_wkr_.Typ_tmpl && brack_count > 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
Arg_itm_end(ctx, cur_nde, cur_itm, ws_bgn_idx, ws_end_idx, cur_itm_subs_len, sub_pos_bgn, wkr_typ, key_exists, false, itm_is_static, src, cur_nde_idx);
|
||||
cur_nde.Val_tkn_(cur_itm);
|
||||
if (!wkr.Args_add(ctx, src, tkn, cur_nde, cur_nde_idx)) return false; // NOTE: if invalid, exit now; lnki_wkr expects false if any argument is invalid; DATE:2014-06-06
|
||||
cur_nde = null; cur_itm = null; key_exists = false; // reset
|
||||
continue; // do not add tkn to cur_itm
|
||||
}
|
||||
case Xop_tkn_itm_.Tid_tmpl_prm: // nested prm (3 {) or invk (2 {); mark itm_is_static = false and treat tkn as txt
|
||||
case Xop_tkn_itm_.Tid_tmpl_invk:
|
||||
itm_is_static = false;
|
||||
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_xnde:
|
||||
Xop_xnde_tkn sub_as_xnde = (Xop_xnde_tkn)sub;
|
||||
switch (sub_as_xnde.Tag().Id()) {
|
||||
case Xop_xnde_tag_.Tid_noinclude: case Xop_xnde_tag_.Tid_includeonly: case Xop_xnde_tag_.Tid_onlyinclude:
|
||||
itm_is_static = false;
|
||||
break;
|
||||
}
|
||||
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
default:
|
||||
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
|
||||
break;
|
||||
}
|
||||
cur_itm.Subs_add_grp(sub, root, i); cur_itm_subs_len++;
|
||||
}
|
||||
if (brack_count > 0) return false;
|
||||
if (cur_nde == null) // occurs when | is last tkn; EX: {{name|a|}};
|
||||
cur_nde = tkn_mkr.ArgNde(++cur_nde_idx, bgn_pos);
|
||||
if (cur_itm == null) { // occurs when = is last tkn; EX: {{name|a=}};
|
||||
cur_itm = tkn_mkr.ArgItm(bgn_pos, -1);
|
||||
itm_is_static = ws_bgn_chk = true; cur_itm_subs_len = 0; ws_bgn_idx = ws_end_idx = -1; key_exists = false;
|
||||
}
|
||||
Arg_itm_end(ctx, cur_nde, cur_itm, ws_bgn_idx, ws_end_idx, cur_itm_subs_len, bgn_pos, wkr_typ, key_exists, false, itm_is_static, src, cur_nde_idx);
|
||||
cur_nde.Val_tkn_(cur_itm);
|
||||
return wkr.Args_add(ctx, src, tkn, cur_nde, cur_nde_idx);
|
||||
}
|
||||
private void Arg_itm_end(Xop_ctx ctx, Arg_nde_tkn nde, Arg_itm_tkn itm, int ws_bgn_idx, int ws_end_idx, int subs_len, int lxr_bgn, int wkr_typ, boolean key_exists, boolean cur_itm_is_key, boolean itm_is_static, byte[] src, int arg_idx) {
|
||||
// PURPOSE: mark tkns Ignore; find dat_bgn, dat_end
|
||||
int dat_bgn = itm.Src_bgn(), dat_end = lxr_bgn; boolean trim = false;
|
||||
// trim ws at bgn
|
||||
boolean wkr_is_not_prm = wkr_typ != Xop_arg_wkr_.Typ_prm;
|
||||
if (ws_bgn_idx != -1) { // ignore ws if (ws_found_at_bgn && (tmpl_arg || (lnki_arg && key))); lnki_arg && val does not ignore at bgn; EX: [[alt= a b c]] -> " a b c"
|
||||
switch (wkr_typ) {
|
||||
case Xop_arg_wkr_.Typ_prm : trim = arg_idx == 0; break;
|
||||
case Xop_arg_wkr_.Typ_tmpl: trim = key_exists || arg_idx == 0; break;
|
||||
case Xop_arg_wkr_.Typ_lnki: trim = cur_itm_is_key || !key_exists; break; // NOTE: trim if "a= b"; skip if " a=b" or " a"
|
||||
}
|
||||
if (trim) {
|
||||
for (int i = 0; i <= ws_bgn_idx; i++) {
|
||||
Xop_tkn_itm sub_tkn = itm.Subs_get(i); // NOTE: tknTypeId should be space, newline, or tab
|
||||
if (wkr_is_not_prm)
|
||||
sub_tkn.Ignore_y_grp_(ctx, itm, i); // mark tkn ignore unless wkr is prm; SEE:NOTE_1
|
||||
if (i == ws_bgn_idx)
|
||||
dat_bgn = sub_tkn.Src_end_grp(itm, i); // if last_tkn, set dat_bgn to bgn
|
||||
}
|
||||
}
|
||||
}
|
||||
// trim ws at end
|
||||
if (ws_end_idx != -1) { // ignore ws if (ws_found_at_end && (tmpl_arg || (lnki_arg && val))); lnki_arg && key does not ignore at end; EX: [[alt =a b c]] -> unrecognized nde ("alt ")
|
||||
trim = false;
|
||||
switch (wkr_typ) {
|
||||
case Xop_arg_wkr_.Typ_prm : trim = arg_idx == 0; break;
|
||||
case Xop_arg_wkr_.Typ_tmpl: trim = key_exists || arg_idx == 0; break;
|
||||
case Xop_arg_wkr_.Typ_lnki: trim = !cur_itm_is_key; break;
|
||||
}
|
||||
if (trim) {
|
||||
for (int i = ws_end_idx; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub_tkn = itm.Subs_get(i); // NOTE: tknTypeId should be space, newline, or tab
|
||||
if (wkr_is_not_prm)
|
||||
sub_tkn.Ignore_y_grp_(ctx, itm, i); // mark tkn ignore unless wkr is prm; SEE:NOTE_1
|
||||
if (i == ws_end_idx)
|
||||
dat_end = sub_tkn.Src_bgn_grp(itm, i); // if 1st_tkn; set dat_end to bgn
|
||||
}
|
||||
}
|
||||
}
|
||||
itm.Src_end_(lxr_bgn); nde.Src_end_(lxr_bgn); // NOTE: src_end is lxr_bgn; EX: {{a}} has src_end at 3; lxr_bgn for }}
|
||||
itm.Dat_rng_(dat_bgn, dat_end); // always set dat, even if itm has dynamic parts; EX: {{{ a{{{1}}}b }}} has 4,13, not 3,14 (ignore ws)
|
||||
|
||||
// if (itm_is_static)
|
||||
// itm.Dat_ary_(dat_end == dat_bgn ? Bry_.Empty : Bry_.Mid(src, dat_bgn, dat_end));
|
||||
itm.Itm_static_(itm_is_static);
|
||||
}
|
||||
public static final Arg_bldr _ = new Arg_bldr(); Arg_bldr() {}
|
||||
}
|
||||
/*
|
||||
NOTE_1:mark tkn ignore unless wkr is prm;
|
||||
need to trim ws when parsing prm_idx/prm_key, but need to preserve raw for output
|
||||
EX: {{{ 1 }}}
|
||||
. parsing will set prm_idx = 1 (ws is ignored)
|
||||
. when calling with {{test|a}} -> "a"
|
||||
. when calling with {{test}} -> "{{{ 1 }}}"
|
||||
so basically, "trim" to get Dat_bgn and Dat_end, but do not mark tkn as ignore
|
||||
alternative would be to set trim = false and then have prm_idx/prm_key do trim; however that would
|
||||
1) ... involve duplication of trim code
|
||||
2) ... be less performant (iterating subs again)
|
||||
*/
|
||||
77
400_xowa/src_500_tmpl/gplx/xowa/Arg_itm_tkn.java
Normal file
77
400_xowa/src_500_tmpl/gplx/xowa/Arg_itm_tkn.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public interface Arg_itm_tkn extends Xop_tkn_itm {
|
||||
int Dat_bgn();
|
||||
int Dat_end();
|
||||
Arg_itm_tkn Dat_end_(int v);
|
||||
Arg_itm_tkn Dat_rng_(int bgn, int end);
|
||||
Arg_itm_tkn Dat_rng_ary_(byte[] src, int bgn, int end);
|
||||
byte[] Dat_ary();
|
||||
Arg_itm_tkn Dat_ary_(byte[] dat_ary);
|
||||
byte[] Dat_to_bry(byte[] src);
|
||||
boolean Dat_ary_had_subst(); void Dat_ary_had_subst_y_();
|
||||
byte Itm_static(); Arg_itm_tkn Itm_static_(boolean v);
|
||||
Arg_itm_tkn Subs_add_ary(Xop_tkn_itm... ary);
|
||||
}
|
||||
class Arg_itm_tkn_null extends Xop_tkn_null implements Arg_itm_tkn { public int Dat_bgn() {return -1;}
|
||||
public int Dat_end() {return -1;} public Arg_itm_tkn Dat_end_(int v) {return this;}
|
||||
public Arg_itm_tkn Dat_rng_(int bgn, int end) {return this;}
|
||||
public Arg_itm_tkn Dat_rng_ary_(byte[] src, int bgn, int end) {return this;}
|
||||
public byte[] Dat_ary() {return Bry_.Empty;} public Arg_itm_tkn Dat_ary_(byte[] dat_ary) {return this;}
|
||||
public byte[] Dat_to_bry(byte[] src) {return Bry_.Empty;}
|
||||
public Arg_itm_tkn Subs_add_ary(Xop_tkn_itm... ary) {return this;}
|
||||
public boolean Dat_ary_had_subst() {return false;} public void Dat_ary_had_subst_y_() {}
|
||||
public byte Itm_static() {return Bool_.__byte;} public Arg_itm_tkn Itm_static_(boolean v) {return this;}
|
||||
public static final Arg_itm_tkn_null Null_arg_itm = new Arg_itm_tkn_null(); Arg_itm_tkn_null() {}
|
||||
}
|
||||
class Arg_itm_tkn_base extends Xop_tkn_itm_base implements Arg_itm_tkn {
|
||||
public Arg_itm_tkn_base() {} // for mock
|
||||
public Arg_itm_tkn_base(int bgn, int end) {this.Tkn_ini_pos(false, bgn, end); dat_bgn = bgn;}
|
||||
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_arg_itm;}
|
||||
public int Dat_bgn() {return dat_bgn;} private int dat_bgn = -1;
|
||||
public int Dat_end() {return dat_end;} public Arg_itm_tkn Dat_end_(int v) {dat_end = v; return this;} private int dat_end = -1;
|
||||
public byte[] Dat_to_bry(byte[] src) {return Bry_.Len_eq_0(dat_ary) ? Bry_.Mid(src, dat_bgn, dat_end) : dat_ary;}
|
||||
public byte[] Dat_ary() {return dat_ary;} private byte[] dat_ary = Bry_.Empty;
|
||||
public Arg_itm_tkn Dat_ary_(byte[] dat_ary) {this.dat_ary = dat_ary; return this;}
|
||||
public Arg_itm_tkn Dat_rng_(int bgn, int end) {dat_bgn = bgn; dat_end = end; return this;}
|
||||
public boolean Dat_ary_had_subst() {return dat_ary_had_subst;} public void Dat_ary_had_subst_y_() {dat_ary_had_subst = true;} private boolean dat_ary_had_subst = false;
|
||||
public Arg_itm_tkn Dat_rng_ary_(byte[] src, int bgn, int end) {
|
||||
dat_bgn = bgn; dat_end = end;
|
||||
dat_ary = Bry_.Mid(src, bgn, end);
|
||||
return this;
|
||||
}
|
||||
public byte Itm_static() {return itm_static;} public Arg_itm_tkn Itm_static_(boolean v) {itm_static = v ? Bool_.Y_byte : Bool_.N_byte; return this;} private byte itm_static = Bool_.__byte;
|
||||
@Override public void Tmpl_compile(Xop_ctx ctx, byte[] src, Xot_compile_data prep_data) {
|
||||
int subs_len = this.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub = this.Subs_get(i);
|
||||
sub.Tmpl_compile(ctx, src, prep_data);
|
||||
}
|
||||
}
|
||||
@Override public boolean Tmpl_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) {
|
||||
if (dat_ary == Bry_.Empty) {
|
||||
int subs_len = this.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
this.Subs_get(i).Tmpl_evaluate(ctx, src, caller, bfr);
|
||||
}
|
||||
else bfr.Add(dat_ary);
|
||||
return true;
|
||||
}
|
||||
public Arg_itm_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm sub : ary) Subs_add(sub); return this;}
|
||||
}
|
||||
43
400_xowa/src_500_tmpl/gplx/xowa/Arg_nde_tkn.java
Normal file
43
400_xowa/src_500_tmpl/gplx/xowa/Arg_nde_tkn.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Arg_nde_tkn extends Xop_tkn_itm_base {
|
||||
public Arg_nde_tkn() {} // for mock
|
||||
public Arg_nde_tkn(int arg_idx, int bgn) {this.arg_idx = arg_idx; this.Tkn_ini_pos(false, bgn, -1);} private int arg_idx;
|
||||
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_arg_nde;}
|
||||
public byte Arg_compiled() {return arg_compiled;} public Arg_nde_tkn Arg_compiled_(byte v) {arg_compiled = v; return this;} private byte arg_compiled = Bool_.__byte;
|
||||
public int Arg_colon_pos() {return arg_colon_pos;} public Arg_nde_tkn Arg_colon_pos_(int v) {arg_colon_pos = v; return this;} private int arg_colon_pos = -1;
|
||||
public Arg_itm_tkn Key_tkn() {return key_tkn;} public Arg_nde_tkn Key_tkn_(Arg_itm_tkn v) {key_tkn = v; return this;} Arg_itm_tkn key_tkn = Arg_itm_tkn_null.Null_arg_itm;
|
||||
public Arg_itm_tkn Val_tkn() {return val_tkn;} public Arg_nde_tkn Val_tkn_(Arg_itm_tkn v) {val_tkn = v; return this;} Arg_itm_tkn val_tkn = Arg_itm_tkn_null.Null_arg_itm;
|
||||
@gplx.Virtual public boolean KeyTkn_exists() {return key_tkn != Arg_itm_tkn_null.Null_arg_itm;}
|
||||
public Xop_tkn_itm Eq_tkn() {return eq_tkn;} public Arg_nde_tkn Eq_tkn_(Xop_tkn_itm v) {eq_tkn = v; return this;} private Xop_tkn_itm eq_tkn = Xop_tkn_null.Null_tkn;
|
||||
@Override public void Tmpl_fmt(Xop_ctx ctx, byte[] src, Xot_fmtr fmtr) {fmtr.Reg_arg(ctx, src, arg_idx, this);}
|
||||
@Override public void Tmpl_compile(Xop_ctx ctx, byte[] src, Xot_compile_data prep_data) {
|
||||
key_tkn.Tmpl_compile(ctx, src, prep_data);
|
||||
eq_tkn.Tmpl_compile(ctx, src, prep_data);
|
||||
val_tkn.Tmpl_compile(ctx, src, prep_data);
|
||||
}
|
||||
@Override public boolean Tmpl_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) {
|
||||
key_tkn.Tmpl_evaluate(ctx, src, caller, bfr);
|
||||
eq_tkn.Tmpl_evaluate(ctx, src, caller, bfr);
|
||||
val_tkn.Tmpl_evaluate(ctx, src, caller, bfr);
|
||||
return true;
|
||||
}
|
||||
public static final Arg_nde_tkn[] Ary_empty = new Arg_nde_tkn[0];
|
||||
public static final Arg_nde_tkn Null = new Arg_nde_tkn(-1, -1);
|
||||
}
|
||||
41
400_xowa/src_500_tmpl/gplx/xowa/Arg_nde_tkn_mock.java
Normal file
41
400_xowa/src_500_tmpl/gplx/xowa/Arg_nde_tkn_mock.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Arg_nde_tkn_mock extends Arg_nde_tkn { public Arg_nde_tkn_mock(boolean arg_key_is_int, String k, String v) {
|
||||
this.key_exists = !arg_key_is_int;
|
||||
if (key_exists)
|
||||
this.Key_tkn_(new Arg_itm_tkn_mock(k));
|
||||
this.Val_tkn_(new Arg_itm_tkn_mock(v));
|
||||
}
|
||||
public Arg_nde_tkn_mock(String k, String v) {
|
||||
key_exists = k != null;
|
||||
if (key_exists)
|
||||
this.Key_tkn_(new Arg_itm_tkn_mock(k));
|
||||
this.Val_tkn_(new Arg_itm_tkn_mock(v));
|
||||
}
|
||||
@Override public boolean KeyTkn_exists() {return key_exists;} private boolean key_exists;
|
||||
}
|
||||
class Arg_itm_tkn_mock extends Arg_itm_tkn_base {
|
||||
public Arg_itm_tkn_mock(String v) {
|
||||
byte[] dat_ary = Bry_.new_u8(v);
|
||||
this.Subs_add(new Xop_bry_tkn(-1, -1, dat_ary));
|
||||
this.Dat_ary_(dat_ary);
|
||||
this.val = v;
|
||||
} String val;
|
||||
@Override public boolean Tmpl_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) {bfr.Add_str(val); return true;}
|
||||
}
|
||||
30
400_xowa/src_500_tmpl/gplx/xowa/Xop_brack_bgn_lxr.java
Normal file
30
400_xowa/src_500_tmpl/gplx/xowa/Xop_brack_bgn_lxr.java
Normal file
@@ -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; import gplx.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Xop_brack_bgn_lxr implements Xop_lxr {
|
||||
public byte Lxr_tid() {return Xop_lxr_.Tid_brack_bgn;}
|
||||
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Xop_tkn_.Lnki_bgn, this);}
|
||||
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
|
||||
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
|
||||
Xop_tkn_itm tkn = tkn_mkr.Brack_bgn(bgn_pos, cur_pos);
|
||||
ctx.Subs_add_and_stack(root, tkn);
|
||||
return cur_pos;
|
||||
}
|
||||
public static final Xop_brack_bgn_lxr _ = new Xop_brack_bgn_lxr(); Xop_brack_bgn_lxr() {}
|
||||
}
|
||||
33
400_xowa/src_500_tmpl/gplx/xowa/Xop_brack_end_lxr.java
Normal file
33
400_xowa/src_500_tmpl/gplx/xowa/Xop_brack_end_lxr.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Xop_brack_end_lxr implements Xop_lxr {
|
||||
public byte Lxr_tid() {return Xop_lxr_.Tid_brack_end;}
|
||||
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Xop_tkn_.Lnki_end, this);}
|
||||
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
|
||||
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
|
||||
int acs_pos = ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_brack_bgn);
|
||||
if (acs_pos != -1 && ctx.Cur_tkn_tid() != Xop_tkn_itm_.Tid_tmpl_curly_bgn) // NOTE: do not pop tkn if inside tmpl; EX: [[a|{{#switch:{{{1}}}|b=c]]|d=e]]|f]]}}
|
||||
ctx.Stack_pop_til(root, src, acs_pos, true, bgn_pos, cur_pos, Xop_tkn_itm_.Tid_tmpl_curly_bgn);
|
||||
Xop_tkn_itm tkn = tkn_mkr.Brack_end(bgn_pos, cur_pos);
|
||||
ctx.Subs_add(root, tkn);
|
||||
return cur_pos;
|
||||
}
|
||||
public static final Xop_brack_end_lxr _ = new Xop_brack_end_lxr(); Xop_brack_end_lxr() {}
|
||||
}
|
||||
36
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_bgn_lxr.java
Normal file
36
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_bgn_lxr.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.parsers.tblws.*;
|
||||
public class Xop_curly_bgn_lxr implements Xop_lxr {
|
||||
public byte Lxr_tid() {return Xop_lxr_.Tid_curly_bgn;}
|
||||
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Hook, this);} public static final byte[] Hook = new byte[] {Byte_ascii.Curly_bgn, Byte_ascii.Curly_bgn};
|
||||
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
|
||||
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {return ctx.Curly().MakeTkn_bgn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos);}
|
||||
public static final Xop_curly_bgn_lxr _ = new Xop_curly_bgn_lxr(); Xop_curly_bgn_lxr() {}
|
||||
public static Btrie_fast_mgr tmpl_bgn_trie_() { // hook sequences for adding new_line to tmpl return; "{|" "|-" ":" ";" "#" "*"; EX: "{{a}}" returns "*"; convert to "\n*"
|
||||
Btrie_fast_mgr rv = Btrie_fast_mgr.cs_();
|
||||
rv.Add(Xop_tblw_lxr_ws.Hook_tb, Bry_.Empty);
|
||||
rv.Add(Bry_.new_a7("|-"), Bry_.Empty);
|
||||
rv.Add(Byte_ascii.Colon, Bry_.Empty);
|
||||
rv.Add(Byte_ascii.Semic, Bry_.Empty);
|
||||
rv.Add(Byte_ascii.Hash, Bry_.Empty);
|
||||
rv.Add(Byte_ascii.Star, Bry_.Empty);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
23
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_bgn_tkn.java
Normal file
23
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_bgn_tkn.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Xop_curly_bgn_tkn extends Xop_tkn_itm_base {
|
||||
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tmpl_curly_bgn;}
|
||||
public Xop_curly_bgn_tkn(int bgn, int end) {this.Tkn_ini_pos(false, bgn, end);}
|
||||
}
|
||||
26
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_end_lxr.java
Normal file
26
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_end_lxr.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Xop_curly_end_lxr implements Xop_lxr {
|
||||
public byte Lxr_tid() {return Xop_lxr_.Tid_curly_end;}
|
||||
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Hook, this);} public static final byte[] Hook = new byte[] {Byte_ascii.Curly_end, Byte_ascii.Curly_end};
|
||||
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
|
||||
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {return ctx.Curly().MakeTkn_end(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos);}
|
||||
public static final Xop_curly_end_lxr _ = new Xop_curly_end_lxr(); Xop_curly_end_lxr() {}
|
||||
}
|
||||
158
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_wkr.java
Normal file
158
400_xowa/src_500_tmpl/gplx/xowa/Xop_curly_wkr.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Xop_curly_wkr implements Xop_ctx_wkr {
|
||||
public void Ctor_ctx(Xop_ctx ctx) {}
|
||||
public void Page_bgn(Xop_ctx ctx, Xop_root_tkn root) {}
|
||||
public void Page_end(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int src_len) {}
|
||||
public void AutoClose(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos, Xop_tkn_itm tkn) {}
|
||||
public int MakeTkn_bgn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos) {
|
||||
int lxr_end_pos = Bry_finder.Find_fwd_while(src, lxr_cur_pos, src_len, Byte_ascii.Curly_bgn); // NOTE: can be many consecutive {; EX: {{{{{1}}}|a}}
|
||||
ctx.Subs_add_and_stack(root, tkn_mkr.Tmpl_curly_bgn(lxr_bgn_pos, lxr_end_pos));
|
||||
return lxr_end_pos;
|
||||
}
|
||||
public int MakeTkn_end(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos) {
|
||||
if (ctx.Cur_tkn_tid() == Xop_tkn_itm_.Tid_brack_bgn) // WORKAROUND: ignore }} if inside lnki; EX.CM:Template:Protected; {{#switch:a|b=[[a|ja=}}]]}}
|
||||
return ctx.Lxr_make_txt_(lxr_cur_pos);
|
||||
int lxr_end_pos = Bry_finder.Find_fwd_while(src, lxr_cur_pos, src_len, Byte_ascii.Curly_end); // NOTE: can be many consecutive }; EX: {{a|{{{1}}}}}
|
||||
int end_tkn_len = lxr_end_pos - lxr_bgn_pos;
|
||||
boolean vnt_enabled = ctx.Wiki().Lang().Vnt_mgr().Enabled();
|
||||
while (end_tkn_len > 0) {
|
||||
int acs_pos = -1, acs_len = ctx.Stack_len();
|
||||
for (int i = acs_len - 1; i > -1; i--) { // find auto-close pos
|
||||
Xop_tkn_itm stack_tkn = ctx.Stack_get(i);
|
||||
switch (stack_tkn.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_tmpl_curly_bgn: // found curly_bgn; mark and exit
|
||||
acs_pos = i;
|
||||
i = -1;
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_brack_bgn: // found no curly_bgn, but found brack_bgn; note that extra }} should not close any frames beyond lnki; EX:w:Template:Cite wikisource; w:John Fletcher (playwright)
|
||||
i = -1;
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_xnde: // found xnde; ignore; handle {{template|<poem>}}</poem>}} DATE:2014-03-03
|
||||
Xop_xnde_tkn stack_xnde = (Xop_xnde_tkn)stack_tkn;
|
||||
if (stack_xnde.Tag().Xtn())
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (acs_pos == -1) { // "}}+" found but no "{{+" found; warn and output literal tkn
|
||||
ctx.Msg_log().Add_itm_none(Xop_curly_log.Bgn_not_found, src, lxr_bgn_pos, lxr_end_pos);
|
||||
ctx.Subs_add(root, tkn_mkr.Txt(lxr_bgn_pos, lxr_end_pos));
|
||||
return lxr_end_pos;
|
||||
}
|
||||
|
||||
Xop_curly_bgn_tkn bgn_tkn = (Xop_curly_bgn_tkn)ctx.Stack_pop_til(root, src, acs_pos, true, lxr_bgn_pos, lxr_end_pos, Xop_tkn_itm_.Tid_tmpl_curly_bgn); // NOTE: in theory, an unclosed [[ can be on stack; for now, ignore
|
||||
int bgn_tkn_len = bgn_tkn.Src_end() - bgn_tkn.Src_bgn();
|
||||
int bgn_tkn_pos_bgn = bgn_tkn.Src_bgn();// save original pos_bgn
|
||||
boolean vnt_dash_adjust = false;
|
||||
if (vnt_enabled ) {
|
||||
int curly_bgn_dash = bgn_tkn.Src_bgn() - 1;
|
||||
if (curly_bgn_dash > -1 && src[curly_bgn_dash] == Byte_ascii.Dash) { // "-" exists before curlies; EX: "-{{"
|
||||
int curly_end_dash = lxr_end_pos;
|
||||
if (curly_end_dash < src_len && src[curly_end_dash] == Byte_ascii.Dash) { // "-" exists after curlies; EX: "}}-"
|
||||
if (bgn_tkn_len > 2 && end_tkn_len > 2) { // more than 3 curlies at bgn / end with flanking dashes; EX: "-{{{ }}}-"; NOTE: 3 is needed b/c 2 will never be reduced; EX: "-{{" will always be "-" and "{{", not "-{" and "{"
|
||||
int numeric_val = Bry_.Xto_int_or(src, bgn_tkn.Src_end(), lxr_bgn_pos, -1);
|
||||
if ( numeric_val != -1 // do not apply if numeric val; EX:"-{{{0}}}-" vs "-{{{#expr:0}}}-" sr.w:Template:Link_FA
|
||||
&& bgn_tkn_len == 3 && end_tkn_len == 3 // exactly 3 tokens; assume param token; "-{{{" -> "-" + "{{{" x> -> "-{" + "{{"; if unbalanced (3,4 or 4,3) fall into code below
|
||||
) {
|
||||
} // noop; PAGE:sr.w:ДНК; EX:<span id="interwiki-{{{1}}}-fa"></span> DATE:2014-07-03
|
||||
else {
|
||||
--bgn_tkn_len; // reduce bgn curlies by 1; EX: "{{{" -> "{{"
|
||||
++bgn_tkn_pos_bgn; // add one to bgn tkn_pos;
|
||||
--end_tkn_len; // reduce end curlies by 1; EX: "}}}" -> "}}"
|
||||
--lxr_end_pos; // reduce end by 1; this will "reprocess" the final "}" as a text tkn; EX: "}}}-" -> "}}" and position before "}-"
|
||||
vnt_dash_adjust = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int new_tkn_len = 0;
|
||||
if (bgn_tkn_len == end_tkn_len) // exact match; should be majority of cases
|
||||
new_tkn_len = bgn_tkn_len;
|
||||
else if (bgn_tkn_len > end_tkn_len) // more bgn than end; use end, and deduct bgn; EX: {{{{{1}}}|a}}
|
||||
new_tkn_len = end_tkn_len;
|
||||
else /*bgn_tkn_len < end_tkn_len*/ // more end than bgn; use bgn, and deduct end; EX: {{a|{{{1}}}}}
|
||||
new_tkn_len = bgn_tkn_len;
|
||||
|
||||
int keep_curly_bgn = 0;
|
||||
/* NOTE: this is a semi-hack; if bgn_tkn > new_tkn, then pretend bgn_tkn fits new_tkn, give to bldr, and then adjust back later
|
||||
EX: {{{{{1}}}|a}} -> bgn_tkn_len=5,new_tkn_len=3 -> change bgn(0, 5) to bgn(2, 5)
|
||||
The "correct" way is to insert a new_bgn_tkn after cur_bgn_tkn on root, but this would have performance implications: array would have to be resized, and all subs will have to be reindexed
|
||||
NOTE: bgn curlies should also be preserved if new_tkn_len > 3; EX: {{{{{{1}}}}}}; note that bgn = end, but len > 3
|
||||
*/
|
||||
if (bgn_tkn_len > new_tkn_len || new_tkn_len > 3) {
|
||||
bgn_tkn.Tkn_ini_pos(false, bgn_tkn.Src_end() - new_tkn_len, bgn_tkn.Src_end());
|
||||
keep_curly_bgn = 1; // preserves {{
|
||||
}
|
||||
switch (new_tkn_len) {
|
||||
case 0: // EXC_CASE: should not happen; warn;
|
||||
ctx.Msg_log().Add_itm_none(Xop_curly_log.Bgn_len_0, src, bgn_tkn.Src_bgn(), lxr_end_pos);
|
||||
break;
|
||||
// case 1: // EXC_CASE: SEE:NOTE_1;
|
||||
// break;
|
||||
case 2: // USE_CASE: make invk_tkn
|
||||
ctx.Invk().Make_tkn(ctx, root, src, lxr_bgn_pos, lxr_bgn_pos + new_tkn_len, bgn_tkn, keep_curly_bgn);
|
||||
break;
|
||||
default: // USE_CASE: make prm_tkn; NOTE: 3 or more
|
||||
new_tkn_len = 3; // gobble 3 at a time; EX: 6 -> 3 -> 0; EX: 7 -> 4 -> 1;
|
||||
prm_wkr.Make_tkn(ctx, tkn_mkr, root, src, src_len, lxr_bgn_pos, lxr_bgn_pos + new_tkn_len, bgn_tkn, keep_curly_bgn);
|
||||
break;
|
||||
}
|
||||
switch (bgn_tkn_len - new_tkn_len) { // continuation of semi-hack above; some bgn still left over; adjust and throw back on stack
|
||||
case 1: // 1 tkn; convert curly to generic text tkn
|
||||
bgn_tkn.Src_end_(bgn_tkn.Src_end() - 1); // NOTE: shorten end of bgn_tkn by 1; TEST
|
||||
ctx.Stack_add(tkn_mkr.Txt(bgn_tkn_pos_bgn, bgn_tkn.Src_end() - new_tkn_len));
|
||||
break;
|
||||
case 0: // noop
|
||||
break;
|
||||
default:
|
||||
bgn_tkn.Tkn_ini_pos(false, bgn_tkn_pos_bgn, bgn_tkn.Src_end() - new_tkn_len); // bgn(2, 5) -> bgn (0, 2)
|
||||
ctx.Stack_add(bgn_tkn);
|
||||
break;
|
||||
}
|
||||
if (vnt_dash_adjust) {
|
||||
Xop_tkn_itm text_tkn = root.Subs_get_or_null(root.Subs_len() - 2); // -2 to get tkn before newly-created tmpl / prm
|
||||
if (text_tkn == null || text_tkn.Tkn_tid() != Xop_tkn_itm_.Tid_txt)
|
||||
ctx.Wiki().Appe().Usr_dlg().Warn_many("", "", "token before curly_bgn was not text tkn; src=~{0}", String_.new_u8(src, lxr_bgn_pos, lxr_end_pos));
|
||||
else
|
||||
text_tkn.Src_end_(text_tkn.Src_end() + 1); // +1 to extend txt_tkn with dash be 1 to include curly; EX: "-" "{{{" -> "-{" "{{"
|
||||
}
|
||||
|
||||
end_tkn_len -= new_tkn_len;
|
||||
lxr_bgn_pos += new_tkn_len; // move lxr_bgn_pos along
|
||||
if (end_tkn_len == 1) { // SEE:NOTE_1:
|
||||
ctx.Subs_add(root, tkn_mkr.Txt(lxr_bgn_pos, lxr_bgn_pos + 1));
|
||||
end_tkn_len = 0;
|
||||
++lxr_bgn_pos;
|
||||
}
|
||||
}
|
||||
return lxr_end_pos;
|
||||
}
|
||||
private Xot_prm_wkr prm_wkr = Xot_prm_wkr._;
|
||||
public static final byte[] Hook_prm_bgn = new byte[] {Byte_ascii.Curly_bgn, Byte_ascii.Curly_bgn, Byte_ascii.Curly_bgn}, Hook_prm_end = new byte[] {Byte_ascii.Curly_end, Byte_ascii.Curly_end, Byte_ascii.Curly_end};
|
||||
}
|
||||
/*
|
||||
NOTE_1:
|
||||
. end_tkn_len = 1 can happen when 4 on either side, or other permutations; EX: {{{{leaf_1}}}};
|
||||
. cannot put in switch(new_tkn_len) b/c the 1 } will pop any {{ or {{{ off stack;
|
||||
.. EX: "{{#switch:a|{{{1}}}}=y|n}}"; 4th } will pop {{ of #switch off stack
|
||||
.. make separate check near end
|
||||
*/
|
||||
80
400_xowa/src_500_tmpl/gplx/xowa/Xop_subst_tst.java
Normal file
80
400_xowa/src_500_tmpl/gplx/xowa/Xop_subst_tst.java
Normal file
@@ -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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xop_subst_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Reset();
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("xo_print", "{{{1}}}");
|
||||
fxt.Init_defn_add("!", "|");
|
||||
}
|
||||
@Test public void Wiki_txt_subst() {fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{subst:test|a}}" , "a");}
|
||||
@Test public void Wiki_txt_subst_ws() {fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{ subst:test|a}}" , "a");}
|
||||
@Test public void Wiki_txt_safesubst() {fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{safesubst:test|a}}" , "a");}
|
||||
@Test public void Tmpl_txt_subst_empty() {fxt.Test_parse_tmpl_str_test("{{subst:}}" , "{{test}}" , "{{subst:}}");}
|
||||
@Test public void Tmpl_txt_safesubst() {fxt.Test_parse_tmpl_str_test("{{safesubst:xo_print|a}}" , "{{test}}" , "a");}
|
||||
@Test public void Tmpl_prm_subst() {fxt.Test_parse_tmpl_str_test("{{{{{1|subst:}}}xo_print|a}}" , "{{test}}" , "{{subst:xo_print|a}}");}
|
||||
@Test public void Tmpl_prm_subst_ws() {fxt.Test_parse_tmpl_str_test("{{{{{1| subst:}}}xo_print|a}}" , "{{test}}" , "{{ subst:xo_print|a}}");}
|
||||
@Test public void Tmpl_prm_safesubst() {fxt.Test_parse_tmpl_str_test("{{{{{1|safesubst:}}}xo_print|a}}" , "{{test}}" , "a");}
|
||||
@Test public void Tmpl_prm_safesubst_empty() {fxt.Test_parse_tmpl_str_test("{{{{{|safesubst:}}}xo_print|a}}" , "{{test}}" , "a");}
|
||||
@Test public void Tmpl_txt_subst_pf() {fxt.Test_parse_tmpl_str_test("{{subst:#expr:0}}" , "{{test}}" , "0");}
|
||||
@Test public void Tmpl_txt_safesubst_prm() {fxt.Test_parse_tmpl_str_test("{{{{{|safesubst:}}}#if:{{{1|}}}{{{{{|safesubst:}}}!}}c1|c2}}" , "{{test}}" , "c2");}
|
||||
@Test public void Exc_tmpl_prm_safesubst_ns() {fxt.Test_parse_tmpl_str_test("{{{{{|safesubst}}}:NAMESPACE}}" , "{{test}}" , "");}
|
||||
@Test public void Unreferenced() { // PURPOSE: if subst, but in tmpl stage, do not actually subst; PAGE:en.w:Unreferenced; DATE:2013-01-31
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("substcheck", "SUBST");
|
||||
fxt.Init_defn_add("ifsubst", String_.Concat_lines_nl
|
||||
( "{{ {{{|safesubst:}}}#ifeq:{{ {{{|safesubst:}}}NAMESPACE}}|{{NAMESPACE}}"
|
||||
, " |{{{no|{{{2|}}}}}}"
|
||||
, " |{{{yes|{{{1|}}}}}}"
|
||||
, "}}"
|
||||
));
|
||||
fxt.Test_parse_tmpl_str_test("{{ {{{|safesubst:}}}ifsubst |yes|<includeonly>{{subst:substcheck}}</includeonly>}}", "{{test}}", "{{subst:substcheck}}");
|
||||
}
|
||||
@Test public void Urlencode_missing_ttl() { // PURPOSE: handle missing ttl inside {{does-template-exist}}; EX: en.d:Kazakhstan; DATE:2014-03-25
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test", "{{safesubst:urlencode:{{safesubst:Template:{{{1}}}}}}}");
|
||||
fxt.Test_parse_page_tmpl_str("{{test|xyz}}", "%5B%5B%3ATemplate%3AXyz%5D%5D"); // url-encoded version of [[:Template:xyz]]
|
||||
}
|
||||
@Test public void Urlencode_invalid_ttl() { // PURPOSE: handle invalid ttl inside does-template-exist; EX: en.d:peace; DATE:2014-03-31
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test", "{{safesubst:urlencode:{{safesubst:Template:{{{1}}}}}}}");
|
||||
fxt.Init_log_(Xop_ttl_log.Invalid_char);
|
||||
fxt.Test_parse_page_tmpl_str("{{test|[xyz]}}", "%7B%7Bsafesubst%3ATemplate%3A%5Bxyz%5D%7D%7D"); // url-encoded version of {{safesubst:Template:xyz}}
|
||||
}
|
||||
@Test public void Urlencode_template_ttl() { // PURPOSE: handle template ttl inside does-template-exist; based on above; DATE:2014-03-31
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test", "{{safesubst:urlencode:{{Template:{{{1}}}}}}}");
|
||||
fxt.Init_log_(Xop_ttl_log.Invalid_char);
|
||||
fxt.Test_parse_page_tmpl_str("{{test|Template:[xyz]}}", "%7B%7BTemplate%3ATemplate%3A%5Bxyz%5D%7D%7D"); // url-encoded version of {{safesubst:Template:xyz}}
|
||||
}
|
||||
@Test public void Nowiki() { // PURPOSE: stack overflow; PAGE:Близкие_друзья_(Сезон_2) DATE:2014-10-21
|
||||
fxt.Init_defn_add("ET", "");
|
||||
fxt.Init_defn_add("ds", "<includeonly>{{subst:</includeonly><includeonly>ET|<nowiki>{{subst:ds}}</nowiki>}}</includeonly>");
|
||||
fxt.Test_parse_page_tmpl_str("{{subst:ds}}", ""); // {{subst:ds}} causes stack overflow; {{ds}} does not
|
||||
}
|
||||
|
||||
// NOTE: these are actually not good tests; MW does subst just before save; it doesn't do subst on load; in this case, the tests are testing load (which will noop); they need to test save (which xowa doesn't do)
|
||||
// @Test public void Tmpl_txt_subst() {fxt.Test_parse_tmpl_str_test("{{subst:xo_print|a}}" , "{{test}}" , "a");}
|
||||
// @Test public void Tmpl_txt_subst_prm() {fxt.Test_parse_tmpl_str_test("{{subst:xo_print|{{{1}}}}}" , "{{test|a}}" , "a");}
|
||||
|
||||
//@Test public void Tmpl_txt_safesubst_prm() {fxt.Test_parse_tmpl_str_test("{{{{{|safesubst:}}}ns:Category}}" , "{{test}}" , "Category");}
|
||||
//@Test public void Tmpl_txt_subst_immed() {fxt.Test_parse_tmpl_str_test("{{xo_print{{subst:!}}a}}" , "{{test}}" , "a");}
|
||||
}
|
||||
26
400_xowa/src_500_tmpl/gplx/xowa/Xop_tkn_.java
Normal file
26
400_xowa/src_500_tmpl/gplx/xowa/Xop_tkn_.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Xop_tkn_ {
|
||||
public static final byte[]
|
||||
Lnki_bgn = new byte[] {Byte_ascii.Brack_bgn, Byte_ascii.Brack_bgn}
|
||||
, Lnki_end = new byte[] {Byte_ascii.Brack_end, Byte_ascii.Brack_end}
|
||||
, Anchor = new byte[] {Byte_ascii.Hash}
|
||||
;
|
||||
public static final int Lnki_bgn_len = 2, Lnki_end_len = 2;
|
||||
}
|
||||
40
400_xowa/src_500_tmpl/gplx/xowa/Xop_tkn_print_tst.java
Normal file
40
400_xowa/src_500_tmpl/gplx/xowa/Xop_tkn_print_tst.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xop_tkn_print_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Text() {tst_Print("a ''b'' c [[d]] e");}
|
||||
@Test public void Prm() {tst_Print("{{{1}}}");}
|
||||
@Test public void Prm_dflt() {tst_Print("{{{1|a}}}");}
|
||||
@Test public void Prm_dflt_prm() {tst_Print("{{{1|{{{2}}}}}}");}
|
||||
@Test public void Tmpl() {tst_Print("{{a}}");}
|
||||
@Test public void Tmpl_arg() {tst_Print("{{a|1|2}}");}
|
||||
@Test public void Tmpl_arg_prm() {tst_Print("{{a|1|{{{1}}}}}");}
|
||||
@Test public void Tmpl_arg_tmpl() {tst_Print("{{a|1|{{b}}}}");}
|
||||
@Test public void Tmpl_pf() {tst_Print("{{#expr:1}}");}
|
||||
private void tst_Print(String raw) {
|
||||
Xop_ctx ctx = fxt.Ctx();
|
||||
byte[] raw_bry = Bry_.new_u8(raw);
|
||||
Xot_defn_tmpl defn = fxt.run_Parse_tmpl(Bry_.Empty, raw_bry);
|
||||
Xot_fmtr_prm raw_fmtr = new Xot_fmtr_prm();
|
||||
defn.Root().Tmpl_fmt(ctx, raw_bry, raw_fmtr);
|
||||
raw_fmtr.Print(tst_Print_bb);
|
||||
Tfds.Eq(raw, tst_Print_bb.Xto_str_and_clear());
|
||||
} private Bry_bfr tst_Print_bb = Bry_bfr.new_();
|
||||
}
|
||||
23
400_xowa/src_500_tmpl/gplx/xowa/Xot_compile_data.java
Normal file
23
400_xowa/src_500_tmpl/gplx/xowa/Xot_compile_data.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
public class Xot_compile_data {
|
||||
public boolean OnlyInclude_exists;
|
||||
public boolean Arg_nde_has_key() {return arg_nde_has_key;} public Xot_compile_data Arg_nde_has_key_(boolean v) {arg_nde_has_key = v; return this;} private boolean arg_nde_has_key;
|
||||
public static final Xot_compile_data Null = new Xot_compile_data();
|
||||
}
|
||||
34
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn.java
Normal file
34
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public interface Xot_defn extends RlsAble {
|
||||
byte Defn_tid();
|
||||
byte[] Name();
|
||||
int Cache_size();
|
||||
boolean Defn_require_colon_arg();
|
||||
Xot_defn Clone(int id, byte[] name);
|
||||
}
|
||||
class Xot_defn_null implements Xot_defn {
|
||||
public byte Defn_tid() {return Xot_defn_.Tid_null;}
|
||||
public boolean Defn_require_colon_arg() {return false;}
|
||||
public byte[] Name() {return Bry_.Empty;}
|
||||
public Xot_defn Clone(int id, byte[] name) {return this;}
|
||||
public int Cache_size() {return 0;}
|
||||
public void Rls() {}
|
||||
public static final Xot_defn_null _ = new Xot_defn_null(); Xot_defn_null() {}
|
||||
}
|
||||
37
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_.java
Normal file
37
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_.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; import gplx.*;
|
||||
public class Xot_defn_ {
|
||||
public static final Xot_defn Null = Xot_defn_null._;
|
||||
public static final byte
|
||||
Tid_null = 0
|
||||
, Tid_func = 1
|
||||
, Tid_tmpl = 2
|
||||
, Tid_subst = Xol_kwd_grp_.Id_subst
|
||||
, Tid_safesubst = Xol_kwd_grp_.Id_safesubst
|
||||
, Tid_raw = Xol_kwd_grp_.Id_raw
|
||||
, Tid_msg = Xol_kwd_grp_.Id_msg
|
||||
, Tid_msgnw = Xol_kwd_grp_.Id_msgnw
|
||||
;
|
||||
public static boolean Tid_is_substing(byte v) {
|
||||
switch (v) {
|
||||
case Tid_subst: return true; // NOTE: safesubst should not return true, else stack overflow; PAGE:en.w:Wikipedia:WikiProject_Celtic_history_and_culture DATE:2015-01-02
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_subst.java
Normal file
27
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_subst.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
public class Xot_defn_subst implements Xot_defn {
|
||||
public Xot_defn_subst(byte tid, byte[] name) {this.tid = tid; this.name = name;}
|
||||
public byte Defn_tid() {return tid;} private byte tid;
|
||||
public byte[] Name() {return name;} private byte[] name;
|
||||
public Xot_defn Clone(int id, byte[] name) {return new Xot_defn_subst(tid, name);}
|
||||
public boolean Defn_require_colon_arg() {return true;}
|
||||
public void Rls() {name = null;}
|
||||
public int Cache_size() {return 1024;} // arbitrary size
|
||||
}
|
||||
93
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_tmpl.java
Normal file
93
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_tmpl.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Xot_defn_tmpl implements Xot_defn {
|
||||
public byte Defn_tid() {return Xot_defn_.Tid_tmpl;}
|
||||
public boolean Defn_require_colon_arg() {return false;}
|
||||
public int Cache_size() {return data_raw.length;}
|
||||
public byte[] Name() {return name;} private byte[] name; private byte[] full_name;
|
||||
public byte[] Frame_ttl() {return frame_ttl;} public void Frame_ttl_(byte[] v) {frame_ttl = v;} private byte[] frame_ttl;
|
||||
public byte[] Data_raw() {return data_raw;} private byte[] data_raw;
|
||||
public byte[] Data_mid() {return data_mid;} public Xot_defn_tmpl Data_mid_(byte[] v) {data_mid = v; return this;} private byte[] data_mid;
|
||||
public Xop_ctx Ctx() {return ctx;} public Xot_defn_tmpl Ctx_(Xop_ctx v) {ctx = v; return this;} private Xop_ctx ctx;
|
||||
public Xop_root_tkn Root() {return root;} private Xop_root_tkn root;
|
||||
public void Init_by_new(Xow_ns ns, byte[] name, byte[] data_raw, Xop_root_tkn root, boolean onlyInclude) {
|
||||
this.ns = ns; this.name = name; this.data_raw = data_raw; this.root = root; this.onlyInclude_exists = onlyInclude;
|
||||
ns_id = ns.Id();
|
||||
this.full_name = ns.Gen_ttl(name);
|
||||
} private Xow_ns ns; int ns_id;
|
||||
public void Init_by_raw(Xop_root_tkn root, boolean onlyInclude_exists) {
|
||||
this.root = root; this.onlyInclude_exists = onlyInclude_exists;
|
||||
}
|
||||
byte[] Extract_onlyinclude(byte[] src, Bry_bfr_mkr bfr_mkr) {
|
||||
Bry_bfr bfr = bfr_mkr.Get_m001();
|
||||
int pos = 0;
|
||||
int src_len = src.length;
|
||||
while (true) {
|
||||
int find_bgn = Bry_finder.Find_fwd(src, Bry_onlyinclude_bgn, pos, src_len);
|
||||
if (find_bgn == Bry_.NotFound) {
|
||||
break;
|
||||
}
|
||||
int find_bgn_lhs = find_bgn + Bry_onlyinclude_bgn_len;
|
||||
int find_end = Bry_finder.Find_fwd(src, Bry_onlyinclude_end, find_bgn_lhs, src_len);
|
||||
if (find_end == Bry_.NotFound) {
|
||||
break;
|
||||
}
|
||||
bfr.Add_mid(src, find_bgn_lhs, find_end);
|
||||
pos = find_end + Bry_onlyinclude_end_len;
|
||||
}
|
||||
return bfr.To_bry_and_rls();
|
||||
}
|
||||
private static final byte[] Bry_onlyinclude_bgn = Bry_.new_a7("<onlyinclude>"), Bry_onlyinclude_end = Bry_.new_a7("</onlyinclude>");
|
||||
private static int Bry_onlyinclude_bgn_len = Bry_onlyinclude_bgn.length, Bry_onlyinclude_end_len = Bry_onlyinclude_end.length;
|
||||
public void Rls() {
|
||||
if (root != null) root.Clear();
|
||||
root = null;
|
||||
}
|
||||
public void Parse_tmpl(Xop_ctx ctx) {ctx.Wiki().Parser().Parse_text_to_defn(this, ctx, ctx.Tkn_mkr(), ns, name, data_raw);} boolean onlyinclude_parsed = false;
|
||||
public boolean Tmpl_evaluate(Xop_ctx ctx, Xot_invk caller, Bry_bfr bfr) {
|
||||
if (root == null) Parse_tmpl(ctx);
|
||||
Xoae_page page = ctx.Cur_page();
|
||||
if (!page.Tmpl_stack_add(full_name)) {
|
||||
bfr.Add_str_a7("<span class=\"error\">Template loop detected:" + String_.new_u8(name) + "</span>");
|
||||
return false;
|
||||
}
|
||||
boolean rv = true;
|
||||
if (onlyInclude_exists) {
|
||||
Xowe_wiki wiki = ctx.Wiki();
|
||||
if (!onlyinclude_parsed) {
|
||||
onlyinclude_parsed = true;
|
||||
byte[] new_data = Extract_onlyinclude(data_raw, wiki.Utl__bfr_mkr());
|
||||
Xop_ctx new_ctx = Xop_ctx.new_sub_(wiki);
|
||||
Xot_defn_tmpl tmpl = wiki.Parser().Parse_text_to_defn_obj(new_ctx, new_ctx.Tkn_mkr(), wiki.Ns_mgr().Ns_template(), Bry_.Empty, new_data);
|
||||
tmpl.Root().Tmpl_compile(new_ctx, new_data, Xot_compile_data.Null);
|
||||
data_raw = new_data;
|
||||
root = tmpl.Root();
|
||||
}
|
||||
}
|
||||
int subs_len = root.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
boolean result = root.Subs_get(i).Tmpl_evaluate(ctx, data_raw, caller, bfr);
|
||||
if (!result) rv = false;
|
||||
}
|
||||
page.Tmpl_stack_del();
|
||||
return rv;
|
||||
}
|
||||
public Xot_defn Clone(int id, byte[] name) {throw Exc_.new_unimplemented();}
|
||||
boolean onlyInclude_exists;
|
||||
}
|
||||
69
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_tmpl_.java
Normal file
69
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_tmpl_.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
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
|
||||
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());
|
||||
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_(wiki.Ns_mgr().Ns_template().Gen_ttl(Xoa_ttl.Replace_unders(frame_ttl))); // NOTE: always prepend "Template:" to frame_ttl; DATE:2014-06-13; NOTE: always use spaces; DATE:2014-08-14
|
||||
int orig_args_len = orig.Args_len();
|
||||
boolean tmpl_args_parsing_orig = ctx.Tmpl_args_parsing();
|
||||
ctx.Tmpl_args_parsing_(true);
|
||||
for (int i = 0; i < orig_args_len; i++) {
|
||||
Arg_nde_tkn orig_arg = orig.Args_get_by_idx(i);
|
||||
Arg_nde_tkn copy_arg = tkn_mkr.ArgNde(-1, 0);
|
||||
if (orig_arg.KeyTkn_exists()) {
|
||||
Arg_itm_tkn key_tkn = orig_arg.Key_tkn();
|
||||
copy_arg.Key_tkn_(Make_itm(false, ctx, tkn_mkr, src, key_tkn, caller, orig_arg));
|
||||
rv.Args_add_by_key(copy_arg.Key_tkn().Dat_ary(), copy_arg); // NOTE: was originally Bry_.Mid(caller.Src(), key_tkn.Dat_bgn(), key_tkn.Dat_end()) which was wrong; caused {{{increment}}} instead of "increment"
|
||||
}
|
||||
else
|
||||
rv.Args_add_by_idx(copy_arg); // NOTE: not a key, so add to idx_hash; DATE:2014-07-23
|
||||
copy_arg.Val_tkn_(Make_itm(true, ctx, tkn_mkr, src, orig_arg.Val_tkn(), caller, orig_arg));
|
||||
rv.Args_add(copy_arg);
|
||||
}
|
||||
ctx.Tmpl_args_parsing_(tmpl_args_parsing_orig);
|
||||
return rv;
|
||||
}
|
||||
private static Arg_itm_tkn Make_itm(boolean val_tkn, Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, byte[] src, Arg_itm_tkn orig, Xot_invk caller, Arg_nde_tkn orig_arg) {
|
||||
int subs_len = orig.Subs_len();
|
||||
Bry_bfr arg_bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
orig.Subs_get(i).Tmpl_evaluate(ctx, src, caller, arg_bfr);
|
||||
Arg_itm_tkn rv = tkn_mkr.ArgItm(-1, -1); // NOTE: was -1, 0; DATE:2013-04-10
|
||||
byte[] rv_ary = orig_arg.KeyTkn_exists() && val_tkn ? arg_bfr.Xto_bry_and_clear_and_trim() : arg_bfr.Xto_bry_and_clear(); // // NOTE: must trim if key_exists; DUPE:TRIM_IF_KEY; PAGE:en.w:Coord in Chernobyl disaster, Sahara
|
||||
rv.Dat_ary_(rv_ary);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
/*
|
||||
NOTE_1: Creates an invk_temp from an invk
|
||||
|
||||
page {{test_1|a}}
|
||||
test_1 {{test_2|{{{1|nil_1}}}}}
|
||||
test_2 {{{1|nil_2}}}
|
||||
|
||||
page : invk_temp gets created for {{test1|a}} where name=test1 and arg1=a
|
||||
test_1 : invk_temp gets created for {{test_2|{{{1|nil_1}}}}}
|
||||
1) create the invk_tmp tkn, with name=test2
|
||||
2) copy the args and resolve; in this case -> {{test2|a}}
|
||||
now we can use the invk_temp to call test_2 (and so on if needed)
|
||||
*/
|
||||
63
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace.java
Normal file
63
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.core.primitives.*;
|
||||
public interface Xot_defn_trace {
|
||||
void Clear();
|
||||
void Trace_bgn(Xop_ctx ctx, byte[] src, byte[] name, Xot_invk caller, Xot_invk self, Xot_defn defn);
|
||||
void Trace_end(int trg_bgn, Bry_bfr trg);
|
||||
void Print(byte[] src, Bry_bfr bb);
|
||||
}
|
||||
class Xot_defn_trace_null implements Xot_defn_trace {
|
||||
public void Clear() {}
|
||||
public void Trace_bgn(Xop_ctx ctx, byte[] src, byte[] name, Xot_invk caller, Xot_invk self, Xot_defn defn) {}
|
||||
public void Trace_end(int trg_bgn, Bry_bfr trg) {}
|
||||
public void Print(byte[] src, Bry_bfr bb) {}
|
||||
public static final Xot_defn_trace_null _ = new Xot_defn_trace_null(); Xot_defn_trace_null() {}
|
||||
}
|
||||
class Xot_defn_trace_brief implements Xot_defn_trace {
|
||||
public int Count() {return hash.Count();}
|
||||
public Xot_defn_trace_itm_brief GetAt(int i) {return (Xot_defn_trace_itm_brief)hash.Get_at(i);}
|
||||
public void Trace_bgn(Xop_ctx ctx, byte[] src, byte[] name, Xot_invk caller, Xot_invk self, Xot_defn defn) {
|
||||
int hashKey = Bry_obj_ref.CalcHashCode(name, 0, name.length);
|
||||
Object o = hash.Get_by(hashKey);
|
||||
Xot_defn_trace_itm_brief itm = null;
|
||||
if (o == null) {
|
||||
itm = new Xot_defn_trace_itm_brief().Name_(name);
|
||||
hash.Add(hashKey, itm);
|
||||
}
|
||||
else
|
||||
itm = (Xot_defn_trace_itm_brief)o;
|
||||
itm.Count_add();
|
||||
} private Ordered_hash hash = Ordered_hash_.new_();
|
||||
public void Trace_end(int trg_bgn, Bry_bfr trg) {}
|
||||
public void Print(byte[] src, Bry_bfr bb) {
|
||||
int count = hash.Count(); if (count == 0) return;
|
||||
if (bb.Len() != 0) bb.Add_byte_nl(); // only add newLine if something in bb; needed for tests
|
||||
for (int i = 0; i < count; i++) {
|
||||
Xot_defn_trace_itm_brief itm = (Xot_defn_trace_itm_brief)hash.Get_at(i);
|
||||
bb.Add_int_fixed(itm.Count(), 4).Add_byte(Byte_ascii.Space);
|
||||
bb.Add(itm.Name()).Add_byte_nl();
|
||||
}
|
||||
}
|
||||
public void Clear() {hash.Clear();}
|
||||
}
|
||||
class Xot_defn_trace_itm_brief {// name,count,depth,args,
|
||||
public byte[] Name() {return name;} public Xot_defn_trace_itm_brief Name_(byte[] v) {name = v; return this;} private byte[] name = Bry_.Empty;
|
||||
public int Count() {return count;} public Xot_defn_trace_itm_brief Count_(int v) {count = v; return this;} public void Count_add() {++count;} private int count;
|
||||
}
|
||||
@@ -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; import gplx.*;
|
||||
import org.junit.*; import gplx.core.strings.*;
|
||||
public class Xot_defn_trace_brief_tst {
|
||||
Xot_defn_trace_fxt fxt = new Xot_defn_trace_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("leaf_a", "{{{1}}}");
|
||||
fxt.Init_defn_add("leaf_b", "{{{1}}}");
|
||||
fxt.Ctx().Defn_trace_(new Xot_defn_trace_brief());
|
||||
}
|
||||
@Test public void Basic_a_1() {fxt.tst_("{{leaf_a}}" , "0001 leaf_a");}
|
||||
@Test public void Basic_a_2() {fxt.tst_("{{leaf_a}} {{leaf_a}}" , "0002 leaf_a");}
|
||||
@Test public void Basic_a_b() {fxt.tst_("{{leaf_a}} {{leaf_b}}" , "0001 leaf_a", "0001 leaf_b");}
|
||||
}
|
||||
class Xot_defn_trace_fxt {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
public Xop_ctx Ctx() {return fxt.Ctx();}
|
||||
public void Init_defn_clear() {fxt.Init_defn_clear();}
|
||||
public void Init_defn_add(String name, String raw) {fxt.Init_defn_add(name, raw);}
|
||||
public void tst_(String raw, String... expd_ary) {
|
||||
Xop_ctx ctx = fxt.Ctx();
|
||||
ctx.Defn_trace().Clear();
|
||||
byte[] src = Bry_.new_u8(raw);
|
||||
ctx.Cur_page().Ttl_(Xoa_ttl.parse_(fxt.Wiki(), Bry_.new_a7("test")));
|
||||
Xop_root_tkn root = ctx.Tkn_mkr().Root(src);
|
||||
fxt.Parser().Parse_page_all_clear(root, ctx, ctx.Tkn_mkr(), src);
|
||||
ctx.Defn_trace().Print(src, tmp);
|
||||
String[] actl_ary = String_.Split(tmp.Xto_str_and_clear(), (char)Byte_ascii.Nl);
|
||||
Tfds.Eq_ary(expd_ary, actl_ary);
|
||||
} private Bry_bfr tmp = Bry_bfr.new_();
|
||||
String[] XtoStr(Xot_defn_trace_itm_brief[] ary) {
|
||||
String[] rv = new String[ary.length];
|
||||
for (int i = 0; i < rv.length; i++) {
|
||||
Xot_defn_trace_itm_brief itm = ary[i];
|
||||
sb.Add(String_.new_u8(itm.Name())).Add("|").Add(itm.Count());
|
||||
rv[i] = sb.Xto_str_and_clear();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
}
|
||||
141
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace_dbg.java
Normal file
141
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace_dbg.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Xot_defn_trace_dbg implements Xot_defn_trace {
|
||||
public void Trace_bgn(Xop_ctx ctx, byte[] src, byte[] name, Xot_invk caller, Xot_invk invk, Xot_defn defn) {
|
||||
if (count++ != 0) bfr.Add_byte_nl(); // do not add new line for 1st template
|
||||
indent += 2;
|
||||
// *invk
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent).Add(Ary_invk_lbl);
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent).Add(Xop_curly_bgn_lxr.Hook).Add(name);
|
||||
if (defn.Defn_tid() == Xot_defn_.Tid_func) {
|
||||
byte[] argx_ary = ((Pf_func_base)defn).Argx_dat();
|
||||
bfr.Add_byte(Byte_ascii.Colon).Add(argx_ary);
|
||||
}
|
||||
int args_len = invk.Args_len();
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
bfr.Add_byte(Byte_ascii.Pipe);
|
||||
Arg_nde_tkn nde = invk.Args_get_by_idx(i);
|
||||
if (nde.KeyTkn_exists()) {
|
||||
// bfr.Add_mid(src, nde.KeyTkn().Dat_bgn(), nde.KeyTkn().Dat_end()).Add_byte(Byte_ascii.Eq);
|
||||
bfr.Add(nde.Key_tkn().Dat_ary()).Add_byte(Byte_ascii.Eq);
|
||||
}
|
||||
// Arg_itm_tkn val_tkn = nde.ValTkn();
|
||||
// if (val_tkn.Itm_static() == Bool_.Y_byte) {
|
||||
// bfr.Add_mid(src, val_tkn.Dat_bgn(), val_tkn.Dat_end());
|
||||
// }
|
||||
// else {
|
||||
// Xot_fmtr_prm raw_fmtr = Xot_fmtr_prm._;
|
||||
// nde.ValTkn().Tmpl_fmt(ctx, src, raw_fmtr);
|
||||
// raw_fmtr.Print(bfr);
|
||||
// }
|
||||
byte[] val_dat_ary = nde.Val_tkn().Dat_ary();
|
||||
if (val_dat_ary == Bry_.Empty) {
|
||||
Xot_fmtr_prm raw_fmtr = prm_fmtr;
|
||||
nde.Val_tkn().Tmpl_fmt(ctx, src, raw_fmtr);
|
||||
raw_fmtr.Print(bfr);
|
||||
}
|
||||
else
|
||||
bfr.Add(nde.Val_tkn().Dat_ary());
|
||||
}
|
||||
bfr.Add(Xop_curly_end_lxr.Hook);
|
||||
bfr.Add_byte_nl();
|
||||
|
||||
// *name
|
||||
bfr .Add_byte_repeat(Byte_ascii.Space, indent).Add(Ary_lnk_lbl)
|
||||
.Add(Xop_tkn_.Lnki_bgn)
|
||||
.Add(ctx.Wiki().Ns_mgr().Ns_template().Name_db_w_colon())
|
||||
.Add(defn.Name())
|
||||
.Add(Xop_tkn_.Lnki_end).Add_byte_nl();
|
||||
|
||||
if (defn.Defn_tid() == Xot_defn_.Tid_tmpl) {
|
||||
// *args
|
||||
argKeys.Clear();
|
||||
int caller_args = invk.Args_len();
|
||||
int key_max = 0;
|
||||
bfr .Add_byte_repeat(Byte_ascii.Space, indent).Add(Ary_args_lbl);
|
||||
for (int i = 0; i < caller_args; i++) {
|
||||
Arg_nde_tkn arg = invk.Args_get_by_idx(i);
|
||||
int digits = Int_.DigitCount(i + 1);
|
||||
// byte[] val_ary = Bry_.Mid(src, arg.ValTkn().Dat_bgn(), arg.ValTkn().Dat_end());
|
||||
bfr .Add_byte_repeat(Byte_ascii.Space, indent + 2)
|
||||
.Add_byte_repeat(Byte_ascii.Space, 4 - digits)
|
||||
.Add_int_fixed(i + 1, digits)
|
||||
.Add_byte(Byte_ascii.Colon).Add_byte(Byte_ascii.Space)
|
||||
.Add(arg.Val_tkn().Dat_ary()).Add_byte_nl()
|
||||
// .Add(val_ary).Add_byte_nl()
|
||||
;
|
||||
if (arg.KeyTkn_exists()) {
|
||||
// byte[] key_ary = Bry_.Mid(src, arg.KeyTkn().Dat_bgn(), arg.KeyTkn().Dat_end());
|
||||
String key_str = String_.new_u8(arg.Key_tkn().Dat_ary());
|
||||
int key_str_len = String_.Len(key_str);
|
||||
if (key_str_len > key_max) key_max = key_str_len;
|
||||
argKeys.Add(key_str + "=" + String_.new_u8(arg.Val_tkn().Dat_ary()));
|
||||
}
|
||||
}
|
||||
argKeys.Sort();
|
||||
for (int i = 0; i < argKeys.Count(); i++) {
|
||||
String s = (String)argKeys.Get_at(i);
|
||||
String key = String_.GetStrBefore(s, "=");
|
||||
String val = String_.GetStrAfter(s, "=");
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent + 2).Add_str(key)
|
||||
.Add_byte_repeat(Byte_ascii.Space, key_max - String_.Len(key))
|
||||
.Add_byte(Byte_ascii.Colon).Add_byte(Byte_ascii.Space).Add_str(val).Add_byte_nl();
|
||||
}
|
||||
}
|
||||
|
||||
if (defn.Defn_tid() == Xot_defn_.Tid_tmpl) {
|
||||
Xot_defn_tmpl defn_tmpl = ((Xot_defn_tmpl)defn);
|
||||
Xop_root_tkn root = defn_tmpl.Root();
|
||||
// Fmt(ctx, defn_tmpl.Src(), root, Ary_raw_lbl , null, false);
|
||||
// Fmt(ctx, defn_tmpl.Src(), root, Ary_fmt_lbl , invk, true);
|
||||
Fmt(ctx, defn_tmpl.Data_raw(), root, Ary_eval_lbl, invk, false);
|
||||
}
|
||||
} private Bry_bfr bfr = Bry_bfr.new_(128); List_adp argKeys = List_adp_.new_(); Xot_fmtr_prm prm_fmtr = new Xot_fmtr_prm();
|
||||
private void Fmt(Xop_ctx ctx, byte[] src, Xop_tkn_itm root, byte[] lbl, Xot_invk caller, boolean newLineArgs) {
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent).Add(lbl);
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent);
|
||||
prm_fmtr.Caller_(caller).NewLineArgs_(newLineArgs);
|
||||
root.Tmpl_fmt(ctx, src, prm_fmtr);
|
||||
prm_fmtr.Print(bfr);
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
public void Trace_end(int trg_bgn, Bry_bfr trg) {
|
||||
indent -= 2;
|
||||
bfr .Add_byte_repeat(Byte_ascii.Space, indent).Add(Ary_result_lbl);
|
||||
if (trg_bgn < trg.Len())
|
||||
bfr .Add_byte_repeat(Byte_ascii.Space, indent).Add_mid(trg.Bfr(), trg_bgn, trg.Len())
|
||||
.Add_byte_nl();
|
||||
}
|
||||
public void Print(byte[] src, Bry_bfr bb) {
|
||||
if (bfr.Len() == 0) return;
|
||||
if (bb.Len() != 0) bb.Add_byte_nl(); // only add newLine if something in bb; needed for tests
|
||||
bb .Add(Ary_source_lbl)
|
||||
.Add(src).Add_byte_nl();
|
||||
bb.Add_bfr_and_preserve(bfr);
|
||||
bfr.Clear();
|
||||
}
|
||||
public void Clear() {bfr.Clear(); indent = 0; count = 0;}
|
||||
int indent = 0, count = 0;
|
||||
public static final Xot_defn_trace_dbg _ = new Xot_defn_trace_dbg(); Xot_defn_trace_dbg() {}
|
||||
private static final byte[] Ary_invk_lbl = Bry_.new_a7("*invk\n"), Ary_lnk_lbl = Bry_.new_a7("*lnk: "), Ary_args_lbl = Bry_.new_a7("*args\n")
|
||||
, Ary_result_lbl = Bry_.new_a7("*result\n")
|
||||
, Ary_eval_lbl = Bry_.new_a7("*eval\n")
|
||||
, Ary_source_lbl = Bry_.new_a7("*source\n");
|
||||
}
|
||||
49
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace_dbg_tst.java
Normal file
49
400_xowa/src_500_tmpl/gplx/xowa/Xot_defn_trace_dbg_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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_defn_trace_dbg_tst {
|
||||
Xot_defn_trace_fxt fx = new Xot_defn_trace_fxt();
|
||||
@Before public void init() {
|
||||
fx.Init_defn_clear();
|
||||
fx.Init_defn_add("print", "{{{1}}}");
|
||||
fx.Init_defn_add("concat", "{{{1}}}{{{2}}}");
|
||||
fx.Init_defn_add("bool_str", "{{#ifeq:{{{1}}}|1|y|n}}");
|
||||
fx.Init_defn_add("mid_1", "{{print|[ {{concat|{{{1}}}|{{{2}}}}} ]}}");
|
||||
fx.Ctx().Defn_trace_(Xot_defn_trace_dbg._);
|
||||
}
|
||||
@Test public void Tmpl() {
|
||||
fx.tst_
|
||||
( "{{print|a|key1=b}}"
|
||||
, "*source"
|
||||
, "{{print|a|key1=b}}"
|
||||
, " *invk"
|
||||
, " {{print|a|key1=b}}"
|
||||
, " *lnk: [[Template:print]]"
|
||||
, " *args"
|
||||
, " 1: a"
|
||||
, " 2: b"
|
||||
, " key1: b"
|
||||
, " *eval"
|
||||
, " a"
|
||||
, "*result"
|
||||
, "a"
|
||||
);
|
||||
}
|
||||
//@Test public void Basic_b() {fx.tst_("{{mwo_b|2}}" , "[[Test page]]", "00 11 {{mwo_b|1}} -> b");}
|
||||
}
|
||||
131
400_xowa/src_500_tmpl/gplx/xowa/Xot_examples_tst.java
Normal file
131
400_xowa/src_500_tmpl/gplx/xowa/Xot_examples_tst.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_examples_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {
|
||||
Io_mgr.I.InitEngine_mem();
|
||||
fxt.Reset();
|
||||
}
|
||||
@Test public void Arg_0() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For}}" , "For other uses, see [[Test page (disambiguation)]].");}
|
||||
@Test public void Arg_1() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For|a}}" , "For a, see [[Test page (disambiguation)]].");}
|
||||
@Test public void Arg_2() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For|a|b}}" , "For a, see [[b]].");}
|
||||
@Test public void Arg_3() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For|a|b|c}}" , "For a, see [[b]] and [[c]].");}
|
||||
@Test public void Arg_4() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For|a|b|c|d}}" , "For a, see [[b]], [[c]], and [[d]].");}
|
||||
@Test public void Arg_5() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For|a|b|c|d|e}}" , "For a, see [[b]], [[c]], [[d]], and [[e]].");}
|
||||
@Test public void Arg_1_nil() {Init_tmpl_for(); fxt.Test_parse_tmpl_str("{{For||a|b}}" , "For other uses, see [[a]] and [[b]].");}
|
||||
@Test public void Main() {
|
||||
Init_tmpl_main(); fxt.Test_parse_tmpl_str("{{Main|a}}", "Main article: [[a|a]]");
|
||||
}
|
||||
@Test public void About() {
|
||||
Init_tmpl_about(); fxt.Test_parse_tmpl_str("{{About|abc}}", "This article is about abc.  For other uses, see [[Test page (disambiguation)]].");
|
||||
}
|
||||
@Test public void About_2() { // PAGE:en.w:{{About|the NASA space mission||Messenger (disambiguation)}}
|
||||
Init_tmpl_about(); fxt.Test_parse_tmpl_str("{{About|a||b{{!}}c}}", "This article is about a.  For other uses, see [[b|c]].");
|
||||
}
|
||||
@Test public void OtherUses() {
|
||||
Init_tmpl_other_uses(); fxt.Test_parse_tmpl_str("{{Other uses|abc}}", "For other uses, see [[abc]].");
|
||||
}
|
||||
@Test public void SeeAlso() {
|
||||
Init_tmpl_see_also(); fxt.Test_parse_tmpl_str("{{See also|abc}}", "See also: [[abc]]");
|
||||
}
|
||||
@Test public void Redirect() {
|
||||
Init_tmpl_redirect(); fxt.Test_parse_tmpl_str("{{Redirect|abc}}", "\"abc\" redirects here. For other uses, see [[abc (disambiguation)]].");
|
||||
}
|
||||
private void Init_tmpl_main() {
|
||||
fxt.Init_page_create("Template:Main", String_.Concat_lines_nl
|
||||
( "{{#ifeq:{{SUBJECTSPACE}}|Category|The main {{#ifeq:{{NAMESPACE:{{{1}}}}}||article|page}}{{#if:{{{2|}}}|s}} for this [[Wikipedia:Categorization|category]] {{#if:{{{2|}}}|are|is}}|Main {{#ifeq:{{NAMESPACE:{{{1}}}}}||article|page}}{{#if:{{{2|}}}|s}}:}} [[{{{1|{{PAGENAME}}}}}|{{{l1|{{{1|{{PAGENAME}}}}}}}}]]{{#if:{{{2| }}}"
|
||||
, " |{{#if:{{{3|}}}|, | and }}[[{{{2}}}|{{{l2|{{{2}}}}}}]]}}{{#if:{{{3|}}}"
|
||||
, " |{{#if:{{{4|}}}|, |, and }}[[{{{3}}}|{{{l3|{{{3}}}}}}]]}}{{#if:{{{4|}}}"
|
||||
, " |{{#if:{{{5|}}}|, |, and }}[[{{{4}}}|{{{l4|{{{4}}}}}}]]}}{{#if:{{{5|}}}"
|
||||
, " |{{#if:{{{6|}}}|, |, and }}[[{{{5}}}|{{{l5|{{{5}}}}}}]]}}{{#if:{{{6|}}}"
|
||||
, " |{{#if:{{{7|}}}|, |, and }}[[{{{6}}}|{{{l6|{{{6}}}}}}]]}}{{#if:{{{7|}}}"
|
||||
, " |{{#if:{{{8|}}}|, |, and }}[[{{{7}}}|{{{l7|{{{7}}}}}}]]}}{{#if:{{{8|}}}"
|
||||
, " |{{#if:{{{9|}}}|, |, and }}[[{{{8}}}|{{{l8|{{{8}}}}}}]]}}{{#if:{{{9|}}}"
|
||||
, " |{{#if:{{{10|}}}|, |, and }}[[{{{9}}}|{{{l9|{{{9}}}}}}]]}}{{#if:{{{10|}}}"
|
||||
, " |, and [[{{{10}}}|{{{l10|{{{10}}}}}}]]}}{{#if:{{{11| }}}|  (too many parameters in {{[[Template:main|main]]}})}}"
|
||||
));
|
||||
}
|
||||
private void Init_tmpl_for() {
|
||||
fxt.Init_page_create("Template:For", "For {{#if:{{{1|}}}|{{{1}}}|other uses}}, see [[{{{2|{{PAGENAME}} (disambiguation)}}}]]{{#if:{{{3|}}}|{{#if:{{{4|}}}|, [[{{{3}}}]], {{#if:{{{5|}}}|[[{{{4}}}]], and [[{{{5}}}]]|and [[{{{4}}}]]}}| and [[{{{3}}}]]}}}}.");
|
||||
}
|
||||
private void Init_tmpl_other_uses() {
|
||||
Init_tmpl_about();
|
||||
fxt.Init_page_create("Template:Other uses", "{{#if:{{{2|}}}|{{about|||{{{1}}}|and|{{{2|}}}|_nocat=1}}|{{about|||{{{1|{{PAGENAME}} (disambiguation)}}}|_nocat=1}}}}");
|
||||
}
|
||||
private void Init_tmpl_about() {
|
||||
fxt.Init_page_create("Template:!", "|");
|
||||
fxt.Init_page_create("Template:About", String_.Concat_lines_nl
|
||||
( "{{#if: {{{1|}}}|<!--"
|
||||
, " -->This {{#ifeq:{{NAMESPACE}}|{{ns:0}}|article|page}} is about {{{1}}}.  }}<!--"
|
||||
, "-->For {{#if:{{{2|}}}|{{{2}}}|other uses}}, see {{#if:{{{3|}}}|[[{{{3}}}]]{{#ifeq:{{{4|}}}|and| and {{#if:{{{5|}}}|[[{{{5}}}]]|[[{{PAGENAME}} (disambiguation)]]}}}}|[[{{PAGENAME}} (disambiguation)]]}}.<!--"
|
||||
, "-->{{#if:{{{2|}}}|{{#if:{{{4|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{4|}}}|and||<!-- 'and' is a special word, don't output 'For and, ...'"
|
||||
, " -->  For {{#ifeq:{{{4}}}|1|other uses|{{{4}}}}}, see {{#if:{{{5|}}}|[[{{{5}}}]]{{#ifeq:{{{6|}}}|and| and {{#if:{{{7|}}}|[[{{{7}}}]]|[[{{PAGENAME}} (disambiguation)]]}}}}|[[{{PAGENAME}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->{{#if:{{{6|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{6|}}}|and||<!--"
|
||||
, " -->  For {{#ifeq:{{{6}}}|1|other uses|{{{6}}}}}, see {{#if:{{{7|}}}|[[{{{7}}}]]{{#ifeq:{{{8|}}}|and| and {{#if:{{{9|}}}|[[{{{9}}}]]|[[{{PAGENAME}} (disambiguation)]]}}}}|[[{{PAGENAME}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->{{#if:{{{8|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{8|}}}|and||<!--"
|
||||
, " -->  For {{#ifeq:{{{8}}}|1|other uses|{{{8}}}}}, see {{#if:{{{9|}}}|[[{{{9}}}]]|[[{{PAGENAME}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->}}<!--"
|
||||
, " -->}}<!--"
|
||||
, "-->}}}}<!--"
|
||||
, "-->{{#if:{{{_nocat|}}}||{{#if:{{{1|}}}{{{2|}}}||{{#if:{{{3|}}}|[[Category:Hatnote templates using unusual parameters|A{{PAGENAME}}]]}}}}{{#ifeq:{{str left|{{{1}}}|3}}|is |[[Category:Hatnote templates using unusual parameters|B{{PAGENAME}}]]}}}}"
|
||||
));
|
||||
}
|
||||
private void Init_tmpl_see_also() {
|
||||
fxt.Init_page_create("Template:See also", String_.Concat_lines_nl
|
||||
( "See also: {{#if:{{{1<includeonly>|</includeonly>}}} |<!--then:-->[[{{{1}}}{{#if:{{{label 1|{{{l1|}}}}}}|{{!}}{{{label 1|{{{l1}}}}}}}}]] |<!--else:-->'''Error: [[Template:See also|Template must be given at least one article name]]'''"
|
||||
, "}}{{#if:{{{2|}}}|{{#if:{{{3|}}}|, | and }} [[{{{2}}}{{#if:{{{label 2|{{{l2|}}}}}}|{{!}}{{{label 2|{{{l2}}}}}}}}]]"
|
||||
, "}}{{#if:{{{3|}}}|{{#if:{{{4|}}}|, |, and }} [[{{{3}}}{{#if:{{{label 3|{{{l3|}}}}}}|{{!}}{{{label 3|{{{l3}}}}}}}}]]"
|
||||
, "}}{{#if:{{{4|}}}|{{#if:{{{5|}}}|, |, and }} [[{{{4}}}{{#if:{{{label 4|{{{l4|}}}}}}|{{!}}{{{label 4|{{{l4}}}}}}}}]]"
|
||||
, "}}{{#if:{{{5|}}}|{{#if:{{{6|}}}|, |, and }} [[{{{5}}}{{#if:{{{label 5|{{{l5|}}}}}}|{{!}}{{{label 5|{{{l5}}}}}}}}]]"
|
||||
, "}}{{#if:{{{6|}}}|{{#if:{{{7|}}}|, |, and }} [[{{{6}}}{{#if:{{{label 6|{{{l6|}}}}}}|{{!}}{{{label 6|{{{l6}}}}}}}}]]"
|
||||
, "}}{{#if:{{{7|}}}|{{#if:{{{8|}}}|, |, and }} [[{{{7}}}{{#if:{{{label 7|{{{l7|}}}}}}|{{!}}{{{label 7|{{{l7}}}}}}}}]]"
|
||||
, "}}{{#if:{{{8|}}}|{{#if:{{{9|}}}|, |, and }} [[{{{8}}}{{#if:{{{label 8|{{{l8|}}}}}}|{{!}}{{{label 8|{{{l8}}}}}}}}]]"
|
||||
, "}}{{#if:{{{9|}}}|{{#if:{{{10|}}}|, |, and }} [[{{{9}}}{{#if:{{{label 9|{{{l9|}}}}}}|{{!}}{{{label 9|{{{l9}}}}}}}}]]"
|
||||
, "}}{{#if:{{{10|}}}|{{#if:{{{11|}}}|, |, and }} [[{{{10}}}{{#if:{{{label 10|{{{l10|}}}}}}|{{!}}{{{label 10|{{{l10}}}}}}}}]]"
|
||||
, "}}{{#if:{{{11|}}}|{{#if:{{{12|}}}|, |, and }} [[{{{11}}}{{#if:{{{label 11|{{{l11|}}}}}}|{{!}}{{{label 11|{{{l11}}}}}}}}]]"
|
||||
, "}}{{#if:{{{12|}}}|{{#if:{{{13|}}}|, |, and }} [[{{{12}}}{{#if:{{{label 12|{{{l12|}}}}}}|{{!}}{{{label 12|{{{l12}}}}}}}}]]"
|
||||
, "}}{{#if:{{{13|}}}|{{#if:{{{14|}}}|, |, and }} [[{{{13}}}{{#if:{{{label 13|{{{l13|}}}}}}|{{!}}{{{label 13|{{{l13}}}}}}}}]]"
|
||||
, "}}{{#if:{{{14|}}}|{{#if:{{{15|}}}|, |, and }} [[{{{14}}}{{#if:{{{label 14|{{{l14||}}}}}}|{{!}}{{{label 14|{{{l14}}}}}}}}]]"
|
||||
, "}}{{#if:{{{15|}}}|, and [[{{{15}}}{{#if:{{{label 15|{{{l15}}}}}}|{{!}}{{{label 15|{{{l15}}}}}}}}]]"
|
||||
, "}}{{#if:{{{16|}}}| — '''<br/>Error: [[Template:See also|Too many links specified (maximum is 15)]]'''"
|
||||
, "}}"
|
||||
));
|
||||
}
|
||||
private void Init_tmpl_redirect() {
|
||||
fxt.Init_page_create("Template:Redirect", String_.Concat_lines_nl
|
||||
( "\"{{{1}}}\" redirects here. For {{#if:{{{2|}}}|{{{2}}}|other uses}}, see {{#if:{{{3|}}}|[[{{{3}}}]]{{#ifeq:{{{4|}}}|and| and {{#if:{{{5|}}}|[[{{{5}}}]]|[[{{{1}}} (disambiguation)]]}}}}|[[{{{1}}} (disambiguation)]]}}.<!--"
|
||||
, "-->{{#if:{{{2|}}}|{{#if:{{{4|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{4|}}}|and||<!-- \"and\" is a special word, don't output \"For and, ...\""
|
||||
, " -->  For {{#ifeq:{{{4}}}|1|other uses|{{{4}}}}}, see {{#if:{{{5|}}}|[[{{{5}}}]]{{#ifeq:{{{6|}}}|and| and {{#if:{{{7|}}}|[[{{{7}}}]]|[[{{{4}}} (disambiguation)]]}}}}|[[{{{4}}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->{{#if:{{{6|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{6|}}}|and||<!--"
|
||||
, " -->  For {{#ifeq:{{{6}}}|1|other uses|{{{6}}}}}, see {{#if:{{{7|}}}|[[{{{7}}}]]{{#ifeq:{{{8|}}}|and| and {{#if:{{{9|}}}|[[{{{9}}}]]|[[{{{6}}} (disambiguation)]]}}}}|[[{{{6}}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->{{#if:{{{8|}}}|<!--"
|
||||
, " -->{{#ifeq:{{{8|}}}|and||<!--"
|
||||
, " -->  For {{#ifeq:{{{8}}}|1|other uses|{{{8}}}}}, see {{#if:{{{9|}}}|[[{{{9}}}]]|[[{{{8}}} (disambiguation)]]}}.}}<!--"
|
||||
, " -->}}<!--"
|
||||
, " -->}}<!--"
|
||||
, "-->}}}}"
|
||||
));
|
||||
}
|
||||
}
|
||||
75
400_xowa/src_500_tmpl/gplx/xowa/Xot_fmtr.java
Normal file
75
400_xowa/src_500_tmpl/gplx/xowa/Xot_fmtr.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public interface Xot_fmtr {
|
||||
void Reg_ary(Xop_ctx ctx, byte[] src, boolean tmpl_static, int src_bgn, int src_end, int subs_len, Xop_tkn_itm[] subs);
|
||||
void Reg_prm(Xop_ctx ctx, byte[] src, Xot_prm_tkn self, int prm_idx, byte[] prm_key, Xop_tkn_itm dflt_tkn);
|
||||
void Reg_tmpl(Xop_ctx ctx, byte[] src, Xop_tkn_itm name_tkn, int args_len, Arg_nde_tkn[] args);
|
||||
void Reg_arg(Xop_ctx ctx, byte[] src, int arg_idx, Arg_nde_tkn self_tkn);
|
||||
}
|
||||
class Xot_fmtr_prm implements Xot_fmtr {
|
||||
public Xot_fmtr_prm Caller_(Xot_invk v) {this.caller = v; return this;} private Xot_invk caller;
|
||||
public Xot_fmtr_prm NewLineArgs_(boolean v) {this.newLineArgs = v; return this;} private boolean newLineArgs = false;
|
||||
public void Reg_ary(Xop_ctx ctx, byte[] src, boolean tmpl_static, int src_bgn, int src_end, int subs_len, Xop_tkn_itm[] subs) {
|
||||
if (tmpl_static && src_bgn != -1) trg.Add_mid(src, src_bgn, src_end); // HACK: fails for {{IPA-de|l|lang|De-Ludwig_van_Beethoven.ogg}}
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
subs[i].Tmpl_fmt(ctx, src, this);
|
||||
}
|
||||
public void Reg_prm(Xop_ctx ctx, byte[] src, Xot_prm_tkn self, int prm_idx, byte[] prm_key, Xop_tkn_itm dflt_tkn) {
|
||||
if (caller == null) { // raw mode
|
||||
trg.Add(Bry_bgn);
|
||||
if (prm_idx == -1) {if (prm_key != null) trg.Add(prm_key);}
|
||||
else trg.Add_int_variable(prm_idx);
|
||||
if (dflt_tkn != null) {
|
||||
trg.Add_byte(Byte_ascii.Pipe);
|
||||
dflt_tkn.Tmpl_fmt(ctx, src, this);
|
||||
}
|
||||
trg.Add(Bry_end);
|
||||
}
|
||||
else // invk mode
|
||||
self.Tmpl_evaluate(ctx, src, caller, trg);
|
||||
} static final byte[] Bry_bgn = new byte[] {Byte_ascii.Curly_bgn, Byte_ascii.Curly_bgn, Byte_ascii.Curly_bgn}, Bry_end = new byte[] {Byte_ascii.Curly_end, Byte_ascii.Curly_end, Byte_ascii.Curly_end};
|
||||
public void Reg_tmpl(Xop_ctx ctx, byte[] src, Xop_tkn_itm name_tkn, int args_len, Arg_nde_tkn[] args) {
|
||||
trg.Add(Xop_curly_bgn_lxr.Hook);
|
||||
++depth;
|
||||
name_tkn.Tmpl_fmt(ctx, src, this);
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
if (depth == 1 && newLineArgs) trg.Add_byte_nl();
|
||||
trg.Add_byte(Byte_ascii.Pipe);
|
||||
args[i].Tmpl_fmt(ctx, src, this);
|
||||
}
|
||||
--depth;
|
||||
trg.Add(Xop_curly_end_lxr.Hook);
|
||||
}
|
||||
public void Write(byte b) {trg.Add_byte(b);}
|
||||
public void Reg_arg(Xop_ctx ctx, byte[] src, int arg_idx, Arg_nde_tkn self_tkn) {
|
||||
self_tkn.Key_tkn().Tmpl_fmt(ctx, src, this);
|
||||
if (self_tkn.KeyTkn_exists()) {
|
||||
if (arg_idx == 0) {
|
||||
if (self_tkn.Eq_tkn().Tkn_tid() == Xop_tkn_itm_.Tid_colon)
|
||||
trg.Add_byte(Byte_ascii.Colon);
|
||||
}
|
||||
else
|
||||
trg.Add_byte(Byte_ascii.Eq);
|
||||
}
|
||||
self_tkn.Val_tkn().Tmpl_fmt(ctx, src, this);
|
||||
}
|
||||
public void Print(Bry_bfr bb) {bb.Add_bfr_and_preserve(trg); trg.Clear(); depth = 0;}
|
||||
Bry_bfr trg = Bry_bfr.new_(); int depth = 0;
|
||||
public static final Xot_fmtr_prm _ = new Xot_fmtr_prm();
|
||||
}
|
||||
33
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk.java
Normal file
33
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
public interface Xot_invk {
|
||||
byte Defn_tid();
|
||||
int Src_bgn();
|
||||
int Src_end();
|
||||
boolean Frame_is_root();
|
||||
byte Frame_tid(); void Frame_tid_(byte v);
|
||||
byte[] Frame_ttl(); void Frame_ttl_(byte[] v);
|
||||
int Frame_lifetime(); void Frame_lifetime_(int v);
|
||||
boolean Rslt_is_redirect(); void Rslt_is_redirect_(boolean v);
|
||||
int Args_len();
|
||||
Arg_nde_tkn Name_tkn();
|
||||
Arg_nde_tkn Args_get_by_idx(int i);
|
||||
Arg_nde_tkn Args_eval_by_idx(byte[] src, int idx);
|
||||
Arg_nde_tkn Args_get_by_key(byte[] src, byte[] key);
|
||||
}
|
||||
97
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_mock.java
Normal file
97
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_mock.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa; import gplx.*;
|
||||
import gplx.xowa.xtns.scribunto.*;
|
||||
public class Xot_invk_mock implements Xot_invk {
|
||||
Xot_invk_mock(byte defn_tid, int idx_adj, byte[] frame_ttl) {
|
||||
this.defn_tid = defn_tid; this.idx_adj = idx_adj; this.frame_ttl = frame_ttl;
|
||||
} private int idx_adj; // SEE NOTE_1:
|
||||
public int Src_bgn() {return -1;}
|
||||
public int Src_end() {return -1;}
|
||||
public byte Defn_tid() {return defn_tid;} private byte defn_tid = Xot_defn_.Tid_null;
|
||||
public boolean Frame_is_root() {return false;}
|
||||
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;
|
||||
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 Arg_nde_tkn Name_tkn() {return Arg_nde_tkn.Null;}
|
||||
public int Args_len() {return args.Count() + idx_adj;} private Ordered_hash args = Ordered_hash_.new_bry_();
|
||||
public Arg_nde_tkn Args_get_by_idx(int i) {return (Arg_nde_tkn)args.Get_at(i - idx_adj);}
|
||||
public Arg_nde_tkn Args_eval_by_idx(byte[] src, int idx) {// DUPE:MW_ARG_RETRIEVE
|
||||
int cur = 0, list_len = args.Count();
|
||||
if (idx >= list_len) return null;
|
||||
for (int i = 0; i < list_len; i++) { // iterate over list to find nth *non-keyd* arg; SEE:NOTE_1
|
||||
Arg_nde_tkn nde = (Arg_nde_tkn)args.Get_at(i);
|
||||
if (nde.KeyTkn_exists()) {
|
||||
int key_int = Bry_.Xto_int_or(nde.Key_tkn().Dat_ary(), -1);
|
||||
if (key_int == -1)
|
||||
continue;
|
||||
else { // key is numeric
|
||||
if (key_int + idx_adj - 1 == idx) {
|
||||
return nde;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((cur + idx_adj) == idx) return nde;
|
||||
else ++cur;
|
||||
}
|
||||
return Args_get_by_key(src, Bry_.XtoStrBytesByInt(idx + 1, 1));
|
||||
}
|
||||
public Arg_nde_tkn Args_get_by_key(byte[] src, byte[] key) {return (Arg_nde_tkn)args.Get_by(key);}
|
||||
public static Xot_invk_mock new_(byte defn_tid, byte[] frame_ttl, KeyVal... args) {return new_(defn_tid, 1, frame_ttl, args);}
|
||||
public static Xot_invk_mock new_(byte[] frame_ttl, KeyVal... args) {return new_(Xot_defn_.Tid_null, 1, frame_ttl, args);}
|
||||
public static Xot_invk_mock test_(byte[] frame_ttl, KeyVal... args) {return new_(Xot_defn_.Tid_null, 0, frame_ttl, args);}
|
||||
public static Xot_invk_mock new_(byte defn_tid, int idx_adj, byte[] frame_ttl, KeyVal... args) {
|
||||
Xot_invk_mock rv = new Xot_invk_mock(defn_tid, idx_adj, frame_ttl);
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
KeyVal kv = args[i];
|
||||
String kv_key_str = kv.Key();
|
||||
Object kv_key_obj = kv.Key_as_obj();
|
||||
Arg_nde_tkn_mock nde_tkn = null;
|
||||
if (ClassAdp_.Eq_typeSafe(kv_key_obj, Int_.Cls_ref_type)) // key is int; EX: 1 => val
|
||||
nde_tkn = new Arg_nde_tkn_mock(null, kv.Val_to_str_or_empty()); // add w/o key
|
||||
else if (ClassAdp_.Eq_typeSafe(kv.Val(), Bool_.Cls_ref_type)) { // val is boolean; EX: key => true || key => false
|
||||
boolean kv_val_bool = Bool_.cast_(kv.Val());
|
||||
if (kv_val_bool)
|
||||
nde_tkn = new Arg_nde_tkn_mock(kv_key_str, "1"); // true => 1 (PHP behavior)
|
||||
else
|
||||
continue; // false => "" (PHP behavior), but dropped from list (emulate MW behavior) wherein Parser.php!argSubstitution silently drops keyVals with value of false; "if ( $text === false && $Object === false )"; DATE:2014-01-02
|
||||
}
|
||||
else // regular nde
|
||||
nde_tkn = new Arg_nde_tkn_mock(kv_key_str, kv.Val_to_str_or_empty()); // add regular key, val strings
|
||||
rv.args.Add_if_dupe_use_nth(Bry_.new_u8(kv_key_str), nde_tkn);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final Xot_invk_mock Null = new Xot_invk_mock(Xot_defn_.Tid_null, 1, Bry_.Empty);
|
||||
}
|
||||
/*
|
||||
NOTE_1: Xot_invk_mock is being used as a container for two functions
|
||||
(1) As a substitute for an Invk_tkn; EX: {{#invoke:Mod|Func|arg_1|arg_2}}
|
||||
. in this case, idx_adj is 1 b/c args will always be 1-based
|
||||
. EX: Eval_by_idx(1) should return "arg_1". This would be list[0]
|
||||
. said another way, requested_idx - idx_adj = list_idx; or 1 - 1 = 0
|
||||
. Hence, 1 is the idx_adj;
|
||||
(2) As a substitute for Xot_defn_tmpl_.CopyNew; which occurs in ExpandTemplate
|
||||
. in this case, idx_adj is 0 b/c args are 0-based
|
||||
. note that Xot_defn_tmpl_ creates a temporary Object, and its args are 0 based (it doesn't emulate the list[0] for the func_name
|
||||
*/
|
||||
48
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_sandbox_tst.java
Normal file
48
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_sandbox_tst.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_invk_sandbox_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Reset();
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("concat", "{{{1}}}{{{2}}}");
|
||||
}
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_tmpl_str("{{concat|a|b}}", "ab");
|
||||
}
|
||||
@Test public void Basic_too_many() { // c gets ignored
|
||||
fxt.Test_parse_tmpl_str("{{concat|a|b|c}}", "ab");
|
||||
}
|
||||
@Test public void Basic_too_few() {
|
||||
fxt.Test_parse_tmpl_str("{{concat|a}}", "a{{{2}}}");
|
||||
}
|
||||
@Test public void Basic_else() {
|
||||
fxt.Init_defn_add("concat", "{{{1}}}{{{2|?}}}");
|
||||
fxt.Test_parse_tmpl_str("{{concat|a}}", "a?");
|
||||
}
|
||||
@Test public void Eq_2() {
|
||||
fxt.Init_defn_add("concat", "{{{lkp1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{concat|lkp1=a=b}}", "a=b");
|
||||
}
|
||||
@Test public void Recurse() {fxt.Test_parse_tmpl_str_test("<{{concat|{{{1}}}|{{{2}}}}}>" , "{{test|a|b}}", "<ab>");}
|
||||
@Test public void Recurse_mix() {fxt.Test_parse_tmpl_str_test("{{concat|.{{{1}}}.|{{{2}}}}}" , "{{test|a|b}}", ".a.b");}
|
||||
@Test public void Recurse_err() {fxt.Test_parse_tmpl_str_test("{{concat|{{{1}}}|{{{2}}}}}" , "{{test1|a|b}}", "[[:Template:test1]]");} // NOTE: make sure test1 does not match test
|
||||
@Test public void KeyNewLine() {fxt.Test_parse_tmpl_str_test("{{\n concat|a|b}}" , "{{\n test}}", "ab");}
|
||||
}
|
||||
86
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_temp.java
Normal file
86
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_temp.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
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; 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;
|
||||
}
|
||||
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 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 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_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_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);
|
||||
int key_as_int = Bry_.Xto_int_or(key, Int_.MinValue);
|
||||
if (key_as_int != Int_.MinValue) // key is int; add it to arg_idx_hash; EX:{{A|1=a}} vs {{A|a}}; DATE:2014-07-23
|
||||
Arg_idx_hash_add(key_as_int - List_adp_.Base1, arg);
|
||||
}
|
||||
public void Args_add_by_idx(Arg_nde_tkn arg) {Arg_idx_hash_add(++args_add_by_idx, arg);} private int args_add_by_idx = -1; // NOTE: args_add_by_idx needs to be a separate variable; keeps track of args which don't have a key;
|
||||
private void Arg_idx_hash_add(int int_key, Arg_nde_tkn arg) {
|
||||
if (arg_idx_hash == null) {
|
||||
arg_idx_hash = Hash_adp_.new_();
|
||||
arg_idx_ref = Int_obj_ref.neg1_();
|
||||
}
|
||||
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
|
||||
}
|
||||
/*
|
||||
NOTE_1:
|
||||
The nth arg refers to the nth non-keyd arg;
|
||||
EX:
|
||||
defn is {{{1}}}
|
||||
invk is {{test|key1=a|b}}
|
||||
{{{1}}} is b b/c b is the 1st non-keyd arg (even though it is the 2nd arg)
|
||||
*/
|
||||
/*
|
||||
NOTE_2:
|
||||
Consider a Page with the following Wiki text in the Preview box
|
||||
WIKI: "a {{mwo_concat|{{{1}}}|b}} c"
|
||||
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
|
||||
*/
|
||||
475
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_tkn.java
Normal file
475
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_tkn.java
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.vnts.*; import gplx.xowa.langs.cnvs.*;
|
||||
import gplx.xowa.wikis.caches.*; import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.pfuncs.*; import gplx.xowa.xtns.pfuncs.ttls.*; import gplx.xowa.pages.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
public Arg_nde_tkn Name_tkn() {return name_tkn;} public Xot_invk_tkn Name_tkn_(Arg_nde_tkn v) {name_tkn = v; return this;} Arg_nde_tkn name_tkn = Arg_nde_tkn.Null;
|
||||
public byte Defn_tid() {return defn_tid;} private byte defn_tid = Xot_defn_.Tid_null;
|
||||
public int Tmpl_subst_bgn() {return tmpl_subst_bgn;} private int tmpl_subst_bgn;
|
||||
public int Tmpl_subst_end() {return tmpl_subst_end;} private int tmpl_subst_end;
|
||||
public Xot_invk_tkn Tmpl_subst_props_(byte tid, int bgn, int end) {defn_tid = tid; tmpl_subst_bgn = bgn; tmpl_subst_end = end; return this;}
|
||||
public Xot_defn Tmpl_defn() {return tmpl_defn;} public Xot_invk_tkn Tmpl_defn_(Xot_defn v) {tmpl_defn = v; return this;} private Xot_defn tmpl_defn = Xot_defn_.Null;
|
||||
public boolean Frame_is_root() {return false;}
|
||||
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;
|
||||
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;
|
||||
@Override public void Tmpl_fmt(Xop_ctx ctx, byte[] src, Xot_fmtr fmtr) {fmtr.Reg_tmpl(ctx, src, name_tkn, args_len, args);}
|
||||
@Override public void Tmpl_compile(Xop_ctx ctx, byte[] src, Xot_compile_data prep_data) {
|
||||
name_tkn.Tmpl_compile(ctx, src, prep_data);
|
||||
int args_len = this.Args_len();
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn nde = args[i];
|
||||
Xop_tkn_itm key = nde.Key_tkn(); int key_subs_len = key.Subs_len();
|
||||
for (int j = 0; j < key_subs_len; j++)
|
||||
key.Subs_get(j).Tmpl_compile(ctx, src, prep_data);
|
||||
Xop_tkn_itm val = nde.Val_tkn(); int val_subs_len = val.Subs_len();
|
||||
for (int j = 0; j < val_subs_len; j++)
|
||||
val.Subs_get(j).Tmpl_compile(ctx, src, prep_data);
|
||||
}
|
||||
}
|
||||
@Override public boolean Tmpl_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) { // this="{{t|{{{0}}}}}" caller="{{t|1}}"
|
||||
boolean rv = false;
|
||||
Xot_defn defn = tmpl_defn; Xowe_wiki wiki = ctx.Wiki(); Xol_lang lang = wiki.Lang();
|
||||
byte[] name_ary = defn.Name(), argx_ary = Bry_.Empty; Arg_itm_tkn name_key_tkn = name_tkn.Key_tkn();
|
||||
byte[] name_ary_orig = Bry_.Empty;
|
||||
int name_bgn = 0, name_ary_len = 0;
|
||||
boolean subst_found = false;
|
||||
boolean name_had_subst = false;
|
||||
if (defn == Xot_defn_.Null) { // tmpl_name is not exact match; may be dynamic, subst, transclusion, etc..
|
||||
if (name_key_tkn.Itm_static() == Bool_.N_byte) { // tmpl is dynamic; EX:{{{{{1}}}|a}}
|
||||
Bry_bfr name_tkn_bfr = Bry_bfr.new_(name_tkn.Src_end() - name_tkn.Src_bgn());
|
||||
if (defn_tid == Xot_defn_.Tid_subst)
|
||||
name_tkn_bfr.Add(Get_first_subst_itm(lang.Kwd_mgr()));
|
||||
name_tkn.Tmpl_evaluate(ctx, src, caller, name_tkn_bfr);
|
||||
name_ary = name_tkn_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
else // tmpl is static; note that dat_ary is still valid but rest of name may not be; EX: {{subst:name{{{1}}}}}
|
||||
name_ary = Bry_.Mid(src, name_key_tkn.Dat_bgn(), name_key_tkn.Dat_end());
|
||||
name_had_subst = name_key_tkn.Dat_ary_had_subst();
|
||||
name_ary_orig = name_ary; // cache name_ary_orig
|
||||
name_ary_len = name_ary.length;
|
||||
name_bgn = Bry_finder.Find_fwd_while_not_ws(name_ary, 0, name_ary_len);
|
||||
if ( name_ary_len == 0 // name is blank; can occur with failed inner tmpl; EX: {{ {{does not exist}} }}
|
||||
|| name_bgn == name_ary_len // name is ws; EX: {{test| }} -> {{{{{1}}}}}is whitespace String; PAGE:en.d:wear_one's_heart_on_one's_sleeve; EX:{{t+|fr|avoir le cœur sur la main| }}
|
||||
) {
|
||||
bfr.Add(Ary_unknown_bgn).Add(Ary_dynamic_is_blank).Add(Ary_unknown_end); // FUTURE: excerpt actual String; WHEN: add raw to defn
|
||||
return false;
|
||||
}
|
||||
if (name_ary[name_bgn] == Byte_ascii.Colon) { // check 1st letter for transclusion
|
||||
return Transclude(ctx, wiki, bfr, name_ary, caller, src); // transclusion; EX: {{:Name of page}}
|
||||
}
|
||||
|
||||
// ignore "{{Template:"; EX: {{Template:a}} is the same thing as {{a}}
|
||||
boolean template_prefix_found = false;
|
||||
int tmpl_ns_len = wiki.Ns_mgr().Tmpls_get_w_colon(name_ary, name_bgn, name_ary_len);
|
||||
if (tmpl_ns_len != Bry_.NotFound) {
|
||||
name_ary = Bry_.Mid(name_ary, name_bgn + tmpl_ns_len, name_ary_len);
|
||||
name_ary_len = name_ary.length;
|
||||
name_bgn = 0;
|
||||
template_prefix_found = true;
|
||||
}
|
||||
byte[] ns_template_prefix = wiki.Ns_mgr().Ns_template().Name_db_w_colon(); int ns_template_prefix_len = ns_template_prefix.length;
|
||||
if (name_ary_len > ns_template_prefix_len && Bry_.Match(name_ary, name_bgn, name_bgn + ns_template_prefix_len, ns_template_prefix)) {
|
||||
name_ary = Bry_.Mid(name_ary, name_bgn + ns_template_prefix_len, name_ary_len);
|
||||
name_ary_len = name_ary.length;
|
||||
name_bgn = 0;
|
||||
}
|
||||
|
||||
Object ns_eval = wiki.Ns_mgr().Names_get_w_colon(name_ary, 0, name_ary_len); // match {{:Portal or {{:Wikipedia
|
||||
if (ns_eval != null && !template_prefix_found) // do not transclude ns if Template prefix seen earlier; EX: {{Template:Wikipedia:A}} should not transclude "Wikipedia:A"; DATE:2013-04-03
|
||||
return SubEval(ctx, wiki, bfr, name_ary, caller, src);
|
||||
|
||||
Xol_func_name_itm finder = lang.Func_regy().Find_defn(name_ary, name_bgn, name_ary_len);
|
||||
defn = finder.Func();
|
||||
int colon_pos = -1;
|
||||
switch (finder.Tid()) {
|
||||
case Xot_defn_.Tid_subst: // subst is added verbatim; EX: {{subst:!}} -> {{subst:!}}; logic below is to handle printing of arg which could be standardized if src[] was available for tmpl
|
||||
bfr.Add(Xop_curly_bgn_lxr.Hook).Add(name_ary);
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn nde = args[i];
|
||||
bfr.Add_byte(Byte_ascii.Pipe); // add |
|
||||
bfr.Add_mid(src, nde.Src_bgn(), nde.Src_end()); // add entire arg; "k=v"; note that src must be added, not evaluated, else <nowiki> may be dropped and cause stack overflow; PAGE:ru.w:Близкие_друзья_(Сезон_2) DATE:2014-10-21
|
||||
}
|
||||
Xot_fmtr_prm._.Print(bfr);
|
||||
bfr.Add(Xop_curly_end_lxr.Hook);
|
||||
return true; // NOTE: nothing else to do; return
|
||||
case Xot_defn_.Tid_safesubst:
|
||||
name_ary = Bry_.Mid(name_ary, finder.Subst_end(), name_ary_len); // chop off "safesubst:"
|
||||
name_ary_len = name_ary.length;
|
||||
if (defn != Xot_defn_.Null) { // func found
|
||||
if (finder.Colon_pos() != -1) colon_pos = finder.Func().Name().length; // set colon_pos; SEE NOTE_1
|
||||
}
|
||||
subst_found = true;
|
||||
break;
|
||||
case Xot_defn_.Tid_func:
|
||||
if (defn.Defn_require_colon_arg()) {
|
||||
colon_pos = Bry_finder.Find_fwd(name_ary, Byte_ascii.Colon);
|
||||
if (colon_pos == Bry_.NotFound)
|
||||
defn = Xot_defn_.Null;
|
||||
}
|
||||
else {
|
||||
colon_pos = finder.Colon_pos();
|
||||
}
|
||||
break;
|
||||
case Xot_defn_.Tid_raw:
|
||||
case Xot_defn_.Tid_msg:
|
||||
int raw_colon_pos = Bry_finder.Find_fwd(name_ary, Byte_ascii.Colon);
|
||||
if (raw_colon_pos == Bry_.NotFound) {} // colon missing; EX: {{raw}}; noop and assume template name; DATE:2014-02-11
|
||||
else { // colon present;
|
||||
name_ary = Bry_.Mid(name_ary, finder.Subst_end() + 1, name_ary_len); // chop off "raw"; +1 is for ":"; note that +1 is in bounds b/c raw_colon was found
|
||||
name_ary_len = name_ary.length;
|
||||
Object ns_eval2 = wiki.Ns_mgr().Names_get_w_colon(name_ary, 0, name_ary_len); // match {{:Portal or {{:Wikipedia
|
||||
if (ns_eval2 != null) {
|
||||
Xow_ns ns_eval_itm = (Xow_ns)ns_eval2;
|
||||
int pre_len = ns_eval_itm.Name_enc().length;
|
||||
if (pre_len < name_ary_len && name_ary[pre_len] == Byte_ascii.Colon)
|
||||
return SubEval(ctx, wiki, bfr, name_ary, caller, src);
|
||||
}
|
||||
}
|
||||
switch (finder.Tid()) {
|
||||
case Xot_defn_.Tid_msg:
|
||||
defn = Xot_defn_.Null; // null out defn to force template load below; DATE:2014-07-10
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (subst_found) {// subst found; remove Template: if it exists; EX: {{safesubst:Template:A}} -> {{A}} not {{Template:A}}; EX:en.d:Kazakhstan; DATE:2014-03-25
|
||||
ns_template_prefix = wiki.Ns_mgr().Ns_template().Name_db_w_colon(); ns_template_prefix_len = ns_template_prefix.length;
|
||||
if (name_ary_len > ns_template_prefix_len && Bry_.Match(name_ary, name_bgn, name_bgn + ns_template_prefix_len, ns_template_prefix)) {
|
||||
name_ary = Bry_.Mid(name_ary, name_bgn + ns_template_prefix_len, name_ary_len);
|
||||
name_ary_len = name_ary.length;
|
||||
name_bgn = 0;
|
||||
template_prefix_found = true;
|
||||
}
|
||||
}
|
||||
if (colon_pos != -1) { // func; separate name_ary into name_ary and arg_x
|
||||
argx_ary = Bry_.Trim(name_ary, colon_pos + 1, name_ary_len); // trim bgn ws; needed for "{{formatnum:\n{{#expr:2}}\n}}"
|
||||
name_ary = Bry_.Mid(name_ary, 0, colon_pos);
|
||||
}
|
||||
if (defn == Xot_defn_.Null) {
|
||||
if (ctx.Tid_is_popup()) { // popup && cur_tmpl > tmpl_max
|
||||
if (Popup_skip(ctx, name_ary, bfr)) return false;
|
||||
}
|
||||
defn = wiki.Cache_mgr().Defn_cache().Get_by_key(name_ary);
|
||||
if (defn == null) {
|
||||
if (name_ary_len != 0 ) { // name_ary_len != 0 for direct template inclusions; PAGE:en.w:Human evolution and {{:Human evolution/Species chart}}; && ctx.Tmpl_whitelist().Has(name_ary)
|
||||
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, Bry_.Add(wiki.Ns_mgr().Ns_template().Name_db_w_colon(), name_ary));
|
||||
if (ttl == null) { // ttl is not valid; just output orig; REF.MW:Parser.php|braceSubstitution|if ( !$found ) $text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args );
|
||||
byte[] missing_ttl
|
||||
= subst_found || template_prefix_found // if "subst:" or "Template:" found, use orig name; DATE:2014-03-31
|
||||
? name_ary_orig
|
||||
: name_ary
|
||||
;
|
||||
bfr.Add(Xop_curly_bgn_lxr.Hook).Add(missing_ttl).Add(Xop_curly_end_lxr.Hook);
|
||||
return false;
|
||||
}
|
||||
else { // some templates produce null ttls; EX: "Citation needed{{subst"
|
||||
defn = wiki.Cache_mgr().Defn_cache().Get_by_key(ttl.Page_db());
|
||||
if (defn == null && ctx.Tmpl_load_enabled())
|
||||
defn = Load_defn(wiki, ctx, this, ttl, name_ary);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defn == null) defn = Xot_defn_.Null;
|
||||
}
|
||||
}
|
||||
if ( defn.Defn_tid() == Xot_defn_.Tid_null // name is not a known defn
|
||||
&& lang.Vnt_mgr().Enabled()) { // lang has vnts
|
||||
Xowd_page_itm page = lang.Vnt_mgr().Convert_ttl(wiki, wiki.Ns_mgr().Ns_template(), name_ary);
|
||||
if (page != Xowd_page_itm.Null) {
|
||||
name_ary = page.Ttl_page_db();
|
||||
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, Bry_.Add(wiki.Ns_mgr().Ns_template().Name_db_w_colon(), name_ary));
|
||||
if (ttl == null) { // ttl is not valid; just output orig; REF.MW:Parser.php|braceSubstitution|if ( !$found ) $text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args );
|
||||
bfr.Add(Xop_curly_bgn_lxr.Hook).Add(name_ary).Add(Xop_curly_end_lxr.Hook);
|
||||
return false;
|
||||
}
|
||||
defn = wiki.Cache_mgr().Defn_cache().Get_by_key(name_ary);
|
||||
if (defn == null && ctx.Tmpl_load_enabled())
|
||||
defn = Load_defn(wiki, ctx, this, ttl, name_ary);
|
||||
if (defn == null) defn = Xot_defn_.Null;
|
||||
}
|
||||
}
|
||||
Xot_defn_trace trace = ctx.Defn_trace(); int trg_bgn = bfr.Len();
|
||||
switch (defn.Defn_tid()) {
|
||||
case Xot_defn_.Tid_null: // defn is unknown
|
||||
if (ignore_hash == null) { // ignore SafeSubst templates
|
||||
ignore_hash = Hash_adp_bry.ci_ascii_();
|
||||
ignore_hash.Add_str_obj("Citation needed{{subst", String_.Empty);
|
||||
ignore_hash.Add_str_obj("Clarify{{subst", String_.Empty);
|
||||
}
|
||||
if (ignore_hash.Get_by_bry(name_ary) == null) {
|
||||
if (Pfunc_rel2abs.Rel2abs_ttl(name_ary, name_bgn, name_ary_len)) {// rel_path; EX: {{/../Peer page}}; DATE:2013-03-27
|
||||
Bry_bfr tmp_bfr = ctx.App().Utl__bfr_mkr().Get_b512();
|
||||
name_ary = Pfunc_rel2abs.Rel2abs(tmp_bfr, Bry_.Mid(name_ary, name_bgn, name_ary_len), ctx.Cur_page().Ttl().Raw());
|
||||
tmp_bfr.Mkr_rls();
|
||||
return SubEval(ctx, wiki, bfr, name_ary, caller, src);
|
||||
}
|
||||
if (subst_found)
|
||||
return Transclude(ctx, wiki, bfr, name_ary, caller, src);
|
||||
Print_not_found(bfr, wiki.Ns_mgr(), name_ary);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Xot_defn_.Tid_func:
|
||||
try {
|
||||
Eval_func(ctx, src, caller, this, bfr, defn, argx_ary);
|
||||
rv = true;
|
||||
} catch (Exception e) {
|
||||
if (Env_.Mode_testing())
|
||||
throw Exc_.new_exc(e, "xo", "failed to evaluate function", "page", String_.new_u8(ctx.Cur_page().Ttl().Full_txt()), "defn", String_.new_u8(defn.Name()), "src", String_.new_u8(src, this.Src_bgn(), this.Src_end()));
|
||||
else {
|
||||
wiki.Appe().Usr_dlg().Warn_many("", "", "failed to evaluate function: page=~{0} defn=~{1} src=~{2} err=~{3}", String_.new_u8(ctx.Cur_page().Ttl().Full_txt()), String_.new_u8(defn.Name()), String_.new_u8(src, this.Src_bgn(), this.Src_end()), Err_.Message_gplx_brief(e));
|
||||
rv = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
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);
|
||||
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);
|
||||
|
||||
Bry_bfr rslt_bfr = wiki.Utl__bfr_mkr().Get_k004();
|
||||
try {
|
||||
Bld_key(invk_tmpl, name_ary, rslt_bfr);
|
||||
byte[] rslt_key = rslt_bfr.Xto_bry_and_clear();
|
||||
Object o = wiki.Cache_mgr().Tmpl_result_cache().Get_by(rslt_key);
|
||||
Xopg_tmpl_prepend_mgr prepend_mgr = ctx.Cur_page().Tmpl_prepend_mgr().Bgn(bfr);
|
||||
if (o != null) {
|
||||
byte[] rslt = (byte[])o;
|
||||
prepend_mgr.End(ctx, bfr, rslt, rslt.length, Bool_.Y);
|
||||
bfr.Add(rslt);
|
||||
}
|
||||
else {
|
||||
rv = defn_tmpl.Tmpl_evaluate(ctx, invk_tmpl, rslt_bfr);
|
||||
prepend_mgr.End(ctx, bfr, rslt_bfr.Bfr(), rslt_bfr.Len(), Bool_.Y);
|
||||
if (name_had_subst) { // current invk had "subst:"; parse incoming invk again to remove effects of subst; PAGE:pt.w:Argentina DATE:2014-09-24
|
||||
byte[] tmp_src = rslt_bfr.Xto_bry_and_clear();
|
||||
rslt_bfr.Add(wiki.Parser().Parse_text_to_wtxt(tmp_src)); // this could be cleaner / more optimized
|
||||
}
|
||||
if (Cache_enabled) {
|
||||
byte[] rslt_val = rslt_bfr.Xto_bry_and_clear();
|
||||
bfr.Add(rslt_val);
|
||||
Hash_adp cache = wiki.Cache_mgr().Tmpl_result_cache();
|
||||
cache.Del(rslt_key);
|
||||
cache.Add(rslt_key, rslt_val);
|
||||
}
|
||||
else
|
||||
bfr.Add_bfr_and_clear(rslt_bfr);
|
||||
}
|
||||
trace.Trace_end(trg_bgn, bfr);
|
||||
} finally {rslt_bfr.Mkr_rls();}
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
} private static final byte[] Ary_unknown_bgn = Bry_.new_a7("(? [["), Ary_unknown_end = Bry_.new_a7("]] ?)"), Ary_dynamic_is_blank = Bry_.new_a7("dynamic is blank");
|
||||
private boolean Popup_skip(Xop_ctx ctx, byte[] ttl, Bry_bfr bfr) {
|
||||
boolean skip = false;
|
||||
skip = this.Src_end() - this.Src_bgn() > ctx.Tmpl_tkn_max();
|
||||
if (!skip) {
|
||||
gplx.xowa.html.modules.popups.keeplists.Xop_keeplist_wiki tmpl_keeplist = ctx.Tmpl_keeplist();
|
||||
if (tmpl_keeplist != null && tmpl_keeplist.Enabled()) {
|
||||
byte[] ttl_lower = Xoa_ttl.Replace_spaces(ctx.Wiki().Lang().Case_mgr().Case_build_lower(ttl));
|
||||
skip = !tmpl_keeplist.Match(ttl_lower);
|
||||
// if (skip) Tfds.Write_bry(ttl_lower);
|
||||
}
|
||||
}
|
||||
if (skip) {
|
||||
bfr.Add(gplx.xowa.Xop_comm_lxr.Xowa_skip_comment_bry); // add comment tkn; need something to separate ''{{lang|la|Ragusa}}'' else will become ''''; PAGE:en.w:Republic_of_Ragusa; DATE:2014-06-28
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public static void Eval_func(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk invk, Bry_bfr bfr, Xot_defn defn, byte[] argx_ary) {
|
||||
Pf_func_base defn_func = (Pf_func_base)defn;
|
||||
int defn_func_id = defn_func.Id();
|
||||
defn_func = (Pf_func_base)defn_func.New(defn_func_id, defn_func.Name()); // NOTE: always make copy b/c argx_ary may be dynamic
|
||||
if (argx_ary != Bry_.Empty) defn_func.Argx_dat_(argx_ary);
|
||||
defn_func.Eval_argx(ctx, src, caller, invk);
|
||||
if (defn_func_id == Xol_kwd_grp_.Id_invoke) // NOTE: if #invoke, set frame_ttl to argx, not name; EX:{{#invoke:A}}
|
||||
invk.Frame_ttl_(ctx.Wiki().Ns_mgr().Ns_module().Gen_ttl(Xoa_ttl.Replace_unders(defn_func.Argx_dat()))); // NOTE: always prepend "Module:" to frame_ttl; DATE:2014-06-13; NOTE: always use spaces; DATE:2014-08-14
|
||||
Bry_bfr bfr_func = Bry_bfr.new_();
|
||||
defn_func.Func_evaluate(ctx, src, caller, invk, bfr_func);
|
||||
if (caller.Rslt_is_redirect()) // do not prepend if page is redirect; EX:"#REDIRECT" x> "\n#REDIRECT" DATE:2014-07-11
|
||||
caller.Rslt_is_redirect_(false); // reset flag; needed for TEST; kludgy, but Rslt_is_redirect is intended for single use
|
||||
else
|
||||
ctx.Cur_page().Tmpl_prepend_mgr().End(ctx, bfr, bfr_func.Bfr(), bfr_func.Len(), Bool_.N);
|
||||
bfr.Add_bfr_and_clear(bfr_func);
|
||||
}
|
||||
private static Hash_adp_bry ignore_hash;
|
||||
public static boolean Cache_enabled = false;
|
||||
private static void Bld_key(Xot_invk invk, byte[] name_ary, Bry_bfr bfr) {
|
||||
bfr.Clear();
|
||||
bfr.Add(name_ary);
|
||||
int args_len = invk.Args_len();
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn nde = invk.Args_get_by_idx(i);
|
||||
bfr.Add_byte(Byte_ascii.Pipe);
|
||||
if (nde.KeyTkn_exists()) {
|
||||
bfr.Add(nde.Key_tkn().Dat_ary());
|
||||
bfr.Add_byte(Byte_ascii.Eq);
|
||||
}
|
||||
bfr.Add(nde.Val_tkn().Dat_ary());
|
||||
}
|
||||
}
|
||||
private boolean Transclude(Xop_ctx ctx, Xowe_wiki wiki, Bry_bfr bfr, byte[] name_ary, Xot_invk caller, byte[] src) {
|
||||
Xoa_ttl page_ttl = Xoa_ttl.parse_(wiki, name_ary); if (page_ttl == null) return false; // ttl not valid; EX: {{:[[abc]]}}
|
||||
byte[] transclude_src = null;
|
||||
if (page_ttl.Ns().Id_tmpl()) { // ttl is template; check tmpl_regy first before going to data_mgr
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db());
|
||||
if (tmpl != null) transclude_src = tmpl.Data_raw();
|
||||
}
|
||||
if (transclude_src == null && ctx.Tmpl_load_enabled()) { // ttl is template not in cache, or some other ns; do load
|
||||
Xow_page_cache_itm cache_itm = wiki.Cache_mgr().Page_cache().Get_or_load_as_itm(page_ttl);
|
||||
if ( cache_itm != null
|
||||
// && Bry_.Eq(cache_itm.Ttl().Full_db(), ctx.Cur_page().Page_ttl().Full_db()) // make sure that transcluded item is not same as page_ttl; DATE:2014-01-10
|
||||
) {
|
||||
transclude_src = cache_itm.Wtxt();
|
||||
page_ttl = cache_itm.Ttl();
|
||||
}
|
||||
}
|
||||
if (transclude_src != null) {
|
||||
Xot_defn_tmpl transclude_tmpl = ctx.Wiki().Parser().Parse_text_to_defn_obj(ctx, ctx.Tkn_mkr(), page_ttl.Ns(), page_ttl.Page_db(), transclude_src);
|
||||
return Eval_sub(ctx, transclude_tmpl, caller, src, bfr);
|
||||
}
|
||||
else {
|
||||
Print_not_found(bfr, wiki.Ns_mgr(), page_ttl.Full_txt());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private boolean Eval_sub(Xop_ctx ctx, 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());
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
Xopg_tmpl_prepend_mgr prepend_mgr = ctx.Cur_page().Tmpl_prepend_mgr().Bgn(doc);
|
||||
rv = transclude_tmpl.Tmpl_evaluate(ctx, tmp_tmpl, tmp_bfr);
|
||||
prepend_mgr.End(ctx, doc, tmp_bfr.Bfr(), tmp_bfr.Len(), Bool_.Y);
|
||||
doc.Add_bfr_and_clear(tmp_bfr);
|
||||
return rv;
|
||||
}
|
||||
public static Xot_defn_tmpl Load_defn(Xowe_wiki wiki, Xop_ctx ctx, Xot_invk_tkn invk_tkn, Xoa_ttl ttl, byte[] name_ary) {
|
||||
Xow_page_cache_itm tmpl_page_itm = wiki.Cache_mgr().Page_cache().Get_or_load_as_itm(ttl);
|
||||
byte[] tmpl_page_bry = tmpl_page_itm == null ? null : tmpl_page_itm.Wtxt();
|
||||
Xot_defn_tmpl rv = null;
|
||||
if (tmpl_page_bry != null) {
|
||||
byte old_parse_tid = ctx.Parse_tid(); // NOTE: reusing ctxs is a bad idea; will change Parse_tid and cause strange errors; however, keeping for PERF reasons
|
||||
Xow_ns ns_tmpl = wiki.Ns_mgr().Ns_template();
|
||||
rv = wiki.Parser().Parse_text_to_defn_obj(ctx, ctx.Tkn_mkr(), ns_tmpl, name_ary, tmpl_page_bry);
|
||||
byte[] frame_ttl = tmpl_page_itm.Ttl().Full_txt(); // NOTE: (1) must have ns (Full); (2) must be txt (space, not underscore); EX:Template:Location map+; DATE:2014-08-22
|
||||
rv.Frame_ttl_(frame_ttl); // set defn's frame_ttl; needed for redirect_trg; PAGE:en.w:Statutory_city; DATE:2014-08-22
|
||||
ctx.Parse_tid_(old_parse_tid);
|
||||
wiki.Cache_mgr().Defn_cache().Add(rv, ns_tmpl.Case_match());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static void Print_not_found(Bry_bfr bfr, Xow_ns_mgr ns_mgr, byte[] name_ary) { // print missing as [[:Template:Missing]]; REF:MW: Parser.php|braceSubstitution|$text = "[[:$titleText]]"; EX:en.d:Kazakhstan; DATE:2014-03-25
|
||||
byte[] template_ns_name = ns_mgr.Ns_template().Name_bry();
|
||||
bfr.Add(Xop_tkn_.Lnki_bgn).Add_byte(Byte_ascii.Colon).Add(template_ns_name).Add_byte(Byte_ascii.Colon).Add(name_ary).Add(Xop_tkn_.Lnki_end);
|
||||
}
|
||||
private boolean SubEval(Xop_ctx ctx, Xowe_wiki wiki, Bry_bfr bfr, byte[] name_ary, Xot_invk caller, byte[] src_for_tkn) {
|
||||
Xoa_ttl page_ttl = Xoa_ttl.parse_(wiki, name_ary); if (page_ttl == null) return false; // ttl not valid; EX: {{:[[abc]]}}
|
||||
Xot_defn_tmpl transclude_tmpl = null;
|
||||
switch (page_ttl.Ns().Id()) {
|
||||
case Xow_ns_.Id_template: // ttl is template not in cache, or some other ns; do load
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db());
|
||||
if (tmpl != null) {
|
||||
if (tmpl.Root() == null) tmpl.Parse_tmpl(ctx);
|
||||
transclude_tmpl = tmpl;
|
||||
}
|
||||
break;
|
||||
case Xow_ns_.Id_special:
|
||||
bfr.Add(Xop_tkn_.Lnki_bgn).Add_byte(Byte_ascii.Colon).Add(name_ary).Add(Xop_tkn_.Lnki_end);
|
||||
return true;
|
||||
}
|
||||
if (transclude_tmpl == null && ctx.Tmpl_load_enabled()) { // ttl is template not in cache, or some other ns; do load
|
||||
Xow_page_cache_itm cache_itm = wiki.Cache_mgr().Page_cache().Get_or_load_as_itm(page_ttl);
|
||||
if ( cache_itm != null) {
|
||||
if (!Bry_.Eq(cache_itm.Ttl().Full_db(), ctx.Cur_page().Ttl().Full_db())) { // make sure that transcluded item is not same as page_ttl; DATE:2014-01-10
|
||||
transclude_tmpl = ctx.Wiki().Parser().Parse_text_to_defn_obj(ctx, ctx.Tkn_mkr(), page_ttl.Ns(), page_ttl.Page_db(), cache_itm.Wtxt());
|
||||
page_ttl = cache_itm.Ttl();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (transclude_tmpl == null) {
|
||||
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);
|
||||
}
|
||||
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];}
|
||||
public Arg_nde_tkn Args_eval_by_idx(byte[] src, int idx) {
|
||||
int cur = 0;
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn nde = args[i];
|
||||
if (nde.KeyTkn_exists()) continue;
|
||||
if (cur++ == idx) return nde;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Arg_nde_tkn Args_get_by_key(byte[] src, byte[] key) {
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn nde = args[i];
|
||||
if (!nde.KeyTkn_exists()) continue;
|
||||
if (Bry_.Match(src, nde.Key_tkn().Dat_bgn(), nde.Key_tkn().Dat_end(), key)) return nde; // NOTE: dat_ary is guaranteed to exist
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void Args_add(Xop_ctx ctx, Arg_nde_tkn arg) {
|
||||
int newLen = args_len + 1;
|
||||
if (newLen > args_max) {
|
||||
args_max = newLen * 2;
|
||||
args = Resize(args, args_len, args_max);
|
||||
}
|
||||
args[args_len] = arg;
|
||||
arg.Tkn_grp_(this, args_len);
|
||||
args_len = newLen;
|
||||
} Arg_nde_tkn[] args = Arg_nde_tkn.Ary_empty; int args_max;
|
||||
Arg_nde_tkn[] Resize(Arg_nde_tkn[] src, int cur_len, int new_len) {
|
||||
Arg_nde_tkn[] rv = new Arg_nde_tkn[new_len];
|
||||
Array_.CopyTo(src, 0, rv, 0, cur_len);
|
||||
return rv;
|
||||
}
|
||||
public Xot_invk_tkn(int bgn, int end) {this.Tkn_ini_pos(false, bgn, end);}
|
||||
@Override public byte Tkn_tid() {return typeId;} private byte typeId = Xop_tkn_itm_.Tid_tmpl_invk;
|
||||
public void Tkn_tid_to_txt() {typeId = Xop_tkn_itm_.Tid_txt;}
|
||||
byte[] Get_first_subst_itm(Xol_kwd_mgr kwd_mgr) {
|
||||
Xol_kwd_grp grp = kwd_mgr.Get_at(Xol_kwd_grp_.Id_subst); if (grp == null) return Bry_.Empty;
|
||||
Xol_kwd_itm[] itms = grp.Itms();
|
||||
return itms.length == 0 ? Bry_.Empty : itms[0].Val();
|
||||
}
|
||||
}
|
||||
/*
|
||||
NOTE_1: if (finder.Colon_pos() != -1) colon_pos = finder.Func().Name().length;
|
||||
Two issues here:
|
||||
1) "if (finder.Colon_pos() != -1)"
|
||||
Colon_pos can either be -1 or >0
|
||||
EX: -1: safesubst:NAMESPACE
|
||||
EX: >0: safesubst:#expr:0
|
||||
if -1, don't do anything; this will leave colon_pos as -1
|
||||
2) "finder.Func().Name().length"
|
||||
Colon_pos is >0, but refers to String before it was chopped
|
||||
EX: "safesubst:#expr:0" has Colon_pos of 15 but String is now "#expr:0"
|
||||
so, get colon_pos by taking the finder.Func().Name().length
|
||||
NOTE: whitespace does not matter b/c "safesubst: #expr:0" would never be a func;
|
||||
*/
|
||||
118
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr.java
Normal file
118
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import gplx.xowa.langs.*;
|
||||
public class Xot_invk_wkr implements Xop_ctx_wkr, Xop_arg_wkr {
|
||||
public void Ctor_ctx(Xop_ctx ctx) {}
|
||||
public void Page_bgn(Xop_ctx ctx, Xop_root_tkn root) {this.tkn_mkr = ctx.Tkn_mkr();} private Xop_tkn_mkr tkn_mkr;
|
||||
public void Page_end(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int src_len) {}
|
||||
public void AutoClose(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos, Xop_tkn_itm tkn) {}
|
||||
private static Arg_bldr arg_bldr = Arg_bldr._;
|
||||
public int Make_tkn(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int lxr_cur_pos, int lxr_end_pos, Xop_curly_bgn_tkn bgn_tkn, int keep_curly_bgn) {
|
||||
Xot_invk_tkn invk = tkn_mkr.Tmpl_invk(bgn_tkn.Src_bgn(), lxr_end_pos);
|
||||
int loop_bgn = bgn_tkn.Tkn_sub_idx() + 1, loop_end = root.Subs_len();
|
||||
if (loop_bgn == loop_end) { // empty template; EX: "{{}}"
|
||||
root.Subs_del_after(bgn_tkn.Tkn_sub_idx()); // del invk_bgn_tkn
|
||||
root.Subs_add(tkn_mkr.Txt(bgn_tkn.Src_bgn(), lxr_end_pos));
|
||||
ctx.Msg_log().Add_itm_none(Xop_tmpl_log.Tmpl_is_empty, src, bgn_tkn.Src_bgn(), lxr_end_pos);
|
||||
return lxr_cur_pos;
|
||||
}
|
||||
boolean made = arg_bldr.Bld(ctx, tkn_mkr, this, Xop_arg_wkr_.Typ_tmpl, root, invk, lxr_cur_pos, lxr_end_pos, loop_bgn, loop_end, src);
|
||||
Arg_itm_tkn key_tkn = invk.Name_tkn().Key_tkn();
|
||||
if (!made
|
||||
|| (key_tkn.Dat_bgn() == key_tkn.Dat_end() && key_tkn.Dat_bgn() != -1)) { // key_tkn is entirely whitespace; EX: {{\n}}
|
||||
invk.Tkn_tid_to_txt();
|
||||
ctx.Subs_add(root, tkn_mkr.Txt(lxr_cur_pos, lxr_end_pos));
|
||||
return lxr_cur_pos;
|
||||
}
|
||||
root.Subs_del_after(bgn_tkn.Tkn_sub_idx() + keep_curly_bgn); // all tkns should now be converted; delete everything in root
|
||||
root.Subs_add(invk);
|
||||
return lxr_cur_pos;
|
||||
}
|
||||
public boolean Args_add(Xop_ctx ctx, byte[] src, Xop_tkn_itm tkn, Arg_nde_tkn nde, int nde_idx) {
|
||||
Xot_invk_tkn invk = (Xot_invk_tkn)tkn;
|
||||
if (nde_idx == 0) // 1st arg; name_tkn
|
||||
AddNameArg(ctx, src, invk, nde);
|
||||
else
|
||||
invk.Args_add(ctx, nde);
|
||||
return true;
|
||||
}
|
||||
private static void AddNameArg(Xop_ctx ctx, byte[] src, Xot_invk_tkn invk, Arg_nde_tkn nde) {
|
||||
// make valTkn into a keyTkn; note that argBldr will only generate a valTkn
|
||||
Arg_itm_tkn key_tkn = nde.Val_tkn(), val_tkn = nde.Key_tkn();
|
||||
nde.Key_tkn_(key_tkn).Val_tkn_(val_tkn);
|
||||
invk.Name_tkn_(nde);
|
||||
|
||||
if (key_tkn.Itm_static() != Bool_.Y_byte) return; // dynamic tkn; can't identify func/name
|
||||
int colon_pos = -1, txt_bgn = key_tkn.Dat_bgn(), txt_end = key_tkn.Dat_end();
|
||||
Xol_func_name_itm finder = ctx.Wiki().Lang().Func_regy().Find_defn(src, txt_bgn, txt_end);
|
||||
Xot_defn finder_func = finder.Func();
|
||||
byte finder_typeId = finder.Tid();
|
||||
switch (finder_typeId) {
|
||||
case Xot_defn_.Tid_func: // func
|
||||
colon_pos = finder.Colon_pos();
|
||||
break;
|
||||
case Xot_defn_.Tid_subst: // subst/safesubst; mark invk_tkn
|
||||
case Xot_defn_.Tid_safesubst:
|
||||
int subst_bgn = finder.Subst_bgn(), subst_end = finder.Subst_end();
|
||||
invk.Tmpl_subst_props_(finder_typeId, subst_bgn, subst_end);
|
||||
if ((ctx.Parse_tid() == Xop_parser_.Parse_tid_tmpl && finder_typeId == Xot_defn_.Tid_subst) // NOTE: if subst, but in tmpl stage, do not actually subst; PAGE:en.w:Unreferenced; DATE:2013-01-31
|
||||
|| ctx.Cur_page().Ttl().Ns().Id_tmpl()) { // also, if on tmpl page, never evaluate (questionable, but seems to be needed)
|
||||
}
|
||||
else {
|
||||
key_tkn.Dat_rng_ary_(src, subst_end, txt_end); // redo txt_rng to ignore subst
|
||||
key_tkn.Dat_ary_had_subst_y_();
|
||||
}
|
||||
if (finder_func != Xot_defn_.Null) {
|
||||
colon_pos = finder.Colon_pos();
|
||||
txt_bgn = subst_end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (colon_pos == -1) return; // no func
|
||||
invk.Tmpl_defn_(finder_func);
|
||||
// split key_subs into val based on ":"; note that this does some of the same ws_at_bgn logic as arg_bldr
|
||||
val_tkn = ctx.Tkn_mkr().ArgItm(colon_pos + 1, key_tkn.Src_end());
|
||||
nde.Val_tkn_(val_tkn);
|
||||
|
||||
int del_idx = -1; int val_txt_bgn = - 1;
|
||||
for (int i = 0; i < key_tkn.Subs_len(); i++) {
|
||||
Xop_tkn_itm sub = key_tkn.Subs_get(i);
|
||||
int sub_bgn = sub.Src_bgn();
|
||||
if (sub_bgn < colon_pos && !sub.Tkn_immutable()) {}
|
||||
else if (sub_bgn == colon_pos) {del_idx = i; nde.Eq_tkn_(sub);}
|
||||
else {
|
||||
if (val_txt_bgn == -1) { // txt_sub not found yet
|
||||
switch (sub.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab: case Xop_tkn_itm_.Tid_newLine:
|
||||
sub.Ignore_y_grp_(ctx, key_tkn, i);
|
||||
break;
|
||||
default: // txt_sub found
|
||||
val_txt_bgn = sub_bgn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
val_tkn.Subs_add_grp(sub, key_tkn, i);
|
||||
}
|
||||
}
|
||||
if (val_txt_bgn == -1) val_txt_bgn = txt_end; // default to txt_end to handle empty; EX: {{padleft: |}}
|
||||
key_tkn.Subs_del_after(del_idx);
|
||||
key_tkn.Dat_rng_ary_(src, txt_bgn, colon_pos);
|
||||
val_tkn.Dat_rng_ary_(src, val_txt_bgn, txt_end);
|
||||
}
|
||||
}
|
||||
453
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr_basic_tst.java
Normal file
453
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr_basic_tst.java
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_invk_wkr_basic_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_page_tmpl("{{a}}", fxt.tkn_tmpl_invk_w_name(0, 5, 2, 3));
|
||||
}
|
||||
@Test public void Arg_many() {
|
||||
fxt.Test_parse_page_tmpl("{{a|b|c|d}}", fxt.tkn_tmpl_invk_w_name(0, 11, 2, 3)
|
||||
.Args_(fxt.tkn_arg_val_txt_(4, 5), fxt.tkn_arg_val_txt_(6, 7), fxt.tkn_arg_val_txt_(8, 9)));
|
||||
}
|
||||
@Test public void Kv() {
|
||||
fxt.Test_parse_page_tmpl("{{a|b=c}}", fxt.tkn_tmpl_invk_w_name(0, 9, 2, 3)
|
||||
.Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
. Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(4, 5)))
|
||||
. Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(6, 7)))
|
||||
));
|
||||
}
|
||||
@Test public void Kv_arg() {
|
||||
fxt.Test_parse_tmpl("{{a|b={{{1}}}}}", fxt.tkn_tmpl_invk_w_name(0, 15, 2, 3)
|
||||
.Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
. Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(4, 5)))
|
||||
. Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_tmpl_prm_find_(fxt.tkn_txt_(9, 10))))
|
||||
));
|
||||
}
|
||||
@Test public void Kv_tmpl_compiled() {
|
||||
fxt.Test_parse_tmpl("{{a|b={{c}}}}", fxt.tkn_tmpl_invk_w_name(0, 13, 2, 3)
|
||||
.Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
. Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(4, 5)))
|
||||
. Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_tmpl_invk_w_name(6, 11, 8, 9)))
|
||||
));
|
||||
}
|
||||
@Test public void Kv_tmpl_dynamic() {
|
||||
fxt.Test_parse_tmpl("{{a|b={{c|{{{1}}}}}}}", fxt.tkn_tmpl_invk_w_name(0, 21, 2, 3)
|
||||
.Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
. Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(4, 5)))
|
||||
. Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_tmpl_invk_w_name(6, 19, 8, 9).Args_(fxt.tkn_arg_nde_().Val_tkn_(fxt.tkn_arg_itm_().Subs_(fxt.tkn_tmpl_prm_find_(fxt.tkn_txt_(13, 14))))))
|
||||
)
|
||||
));
|
||||
}
|
||||
@Test public void Nest() {
|
||||
fxt.Test_parse_page_tmpl("{{a|b{{c|d}}e}}", fxt.tkn_tmpl_invk_w_name(0, 15, 2, 3).Args_
|
||||
( fxt.tkn_arg_nde_().Val_tkn_(fxt.tkn_arg_itm_
|
||||
( fxt.tkn_txt_(4, 5)
|
||||
, fxt.tkn_tmpl_invk_w_name(5, 12, 7, 8).Args_
|
||||
( fxt.tkn_arg_val_txt_(9, 10)
|
||||
)
|
||||
, fxt.tkn_txt_(12, 13)
|
||||
))
|
||||
));
|
||||
}
|
||||
@Test public void Whitespace() {
|
||||
fxt.Test_parse_page_tmpl("{{a| b = c }}", fxt.tkn_tmpl_invk_w_name(0, 13, 2, 3).Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
.Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_space_(4, 5).Ignore_y_(), fxt.tkn_txt_(5, 6), fxt.tkn_space_( 6, 7).Ignore_y_()))
|
||||
.Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_space_(8, 9).Ignore_y_(), fxt.tkn_txt_(9, 10), fxt.tkn_space_(10, 11).Ignore_y_()))
|
||||
));
|
||||
}
|
||||
@Test public void Whitespace_nl() {
|
||||
fxt.Test_parse_page_tmpl("{{a|b=c\n}}", fxt.tkn_tmpl_invk_w_name(0, 10, 2, 3).Args_
|
||||
( fxt.tkn_arg_nde_()
|
||||
.Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(4, 5)))
|
||||
.Val_tkn_(fxt.tkn_arg_itm_(fxt.tkn_txt_(6, 7), fxt.tkn_nl_char_(7, 8).Ignore_y_()))
|
||||
));
|
||||
}
|
||||
@Test public void Err_noName() { // WP: [[Russian language]]
|
||||
fxt.Test_parse_page_tmpl("{{|}}", fxt.tkn_curly_bgn_(0), fxt.tkn_pipe_(2), fxt.tkn_txt_(3, 5));
|
||||
}
|
||||
@Test public void Err_noName_nl() {
|
||||
fxt.Test_parse_page_tmpl("{{\n|}}", fxt.tkn_curly_bgn_(0), fxt.tkn_nl_char_len1_(2), fxt.tkn_pipe_(3), fxt.tkn_txt_(4, 6));
|
||||
}
|
||||
@Test public void Err_noName_tab() {
|
||||
fxt.Test_parse_page_tmpl("{{\t|}}", fxt.tkn_curly_bgn_(0), fxt.tkn_tab_(2), fxt.tkn_pipe_(3), fxt.tkn_txt_(4, 6));
|
||||
}
|
||||
@Test public void Err_empty() { // WP: [[Set theory]]
|
||||
fxt.Test_parse_page_tmpl("{{}}", fxt.tkn_txt_(0, 4));
|
||||
}
|
||||
@Test public void DynamicName() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("proc_1", "proc_1 called");
|
||||
fxt.Init_defn_add("proc_2", "proc_2 called");
|
||||
fxt.Test_parse_tmpl_str_test("{{proc_{{{1}}}}}" , "{{test|1}}" , "proc_1 called");
|
||||
fxt.Test_parse_tmpl_str_test("{{proc_{{{1}}}}}" , "{{test|2}}" , "proc_2 called");
|
||||
fxt.Test_parse_tmpl_str_test("{{proc_{{#expr:1}}}}" , "{{test}}" , "proc_1 called");
|
||||
}
|
||||
@Test public void Comment() {
|
||||
fxt.Test_parse_tmpl_str_test("b" , "{{test<!--a-->}}" , "b");
|
||||
}
|
||||
@Test public void Err_equal() { // WP:[[E (mathematical constant)]]
|
||||
fxt.Test_parse_page_tmpl("{{=}}", fxt.tkn_tmpl_invk_(0, 5).Name_tkn_(fxt.tkn_arg_nde_(2, 3).Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_eq_(2)))));
|
||||
}
|
||||
@Test public void Err_dangling() { // WP:[[Antoni Salieri]]; {{icon it}\n
|
||||
fxt.Test_parse_page_tmpl("{{fail} {{pass}}", fxt.tkn_curly_bgn_(0), fxt.tkn_txt_(2, 7), fxt.tkn_space_(7, 8), fxt.tkn_tmpl_invk_w_name(8, 16, 10, 14));
|
||||
}
|
||||
@Test public void MultipleColon() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("H:IPA", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str_test("{{H:IPA|{{{1}}}}}" , "{{test|a}}" , "a");
|
||||
}
|
||||
@Test public void RedundantTemplate() { // {{Template:a}} == {{a}}
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("a", "a");
|
||||
fxt.Test_parse_tmpl_str_test("{{Template:a}}" , "{{test}}" , "a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Lnki() { // PURPOSE: pipe inside lnki should not be interpreted for tmpl: WP:[[Template:Quote]]
|
||||
fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|[[a|b]]|c}}" , "[[a|b]]c");
|
||||
}
|
||||
@Test public void Lnki2() {// PURPOSE: pipe inside lnki inside tmpl should be interpreted WP:[[H:IPA]]
|
||||
fxt.Test_parse_tmpl_str_test("[[a|{{#switch:{{{1}}}|b=c]]|d=e]]|f]]}}" , "{{test|b}}" , "[[a|c]]");
|
||||
}
|
||||
@Test public void Nowiki() { // PURPOSE: nowiki tag should be ignored: en.w:Template:Main
|
||||
fxt.Test_parse_tmpl_str_test("<div <nowiki>class='a'</nowiki> />" , "{{test}}" , "<div <nowiki>class='a'</nowiki> />");
|
||||
}
|
||||
@Test public void Nowiki_if() { // PURPOSE: templates and functions inside nowiki should not be evaluated
|
||||
fxt.Test_parse_tmpl_str_test("a <nowiki>{{#if:|y|n}}</nowiki> b" , "{{test}}" , "a <nowiki>{{#if:|y|n}}</nowiki> b");
|
||||
}
|
||||
@Test public void Nowiki_endtag() { // PURPOSE: <nowiki/> should not match </nowiki>
|
||||
fxt.Test_parse_page_all_str("<nowiki /> ''b'' <nowiki>c</nowiki>" , " <i>b</i> c");
|
||||
}
|
||||
@Test public void Nowiki_xnde_frag() { // PURPOSE: nowiki did not handle xnde frag and literalized; nowiki_xnde_frag; DATE:2013-01-27
|
||||
fxt.Test_parse_page_all_str("<nowiki><pre></nowiki>{{#expr:1}}<pre>b</pre>" , "<pre>1<pre>b</pre>");
|
||||
}
|
||||
@Test public void Nowiki_lnki() { // PURPOSE: nowiki should noop lnkis; DATE:2013-01-27
|
||||
fxt.Test_parse_page_all_str("<nowiki>[[A]]</nowiki>" , "[[A]]");
|
||||
}
|
||||
@Test public void Nowiki_underscore() { // PURPOSE: nowiki did not handle __DISAMBIG__; DATE:2013-07-28
|
||||
fxt.Test_parse_page_all_str("<nowiki>__DISAMBIG__</nowiki>" , "__DISAMBIG__");
|
||||
}
|
||||
@Test public void Nowiki_asterisk() { // PURPOSE: nowiki should noop lists; DATE:2013-08-26
|
||||
fxt.Test_parse_page_all_str("<nowiki>*a</nowiki>", "*a");
|
||||
}
|
||||
@Test public void Nowiki_space() { // PURPOSE: nowiki should noop space (else pre); DATE:2013-09-03
|
||||
fxt.Init_para_y_();
|
||||
fxt.Test_parse_page_all_str("a\n<nowiki> </nowiki>b", "<p>a\n b\n</p>\n");
|
||||
fxt.Init_para_n_();
|
||||
}
|
||||
@Test public void LnkiWithPipe_basic() { // PURPOSE: pipe in link should not count towards tmpl: WP:{{H:title|dotted=no|pronunciation:|[[File:Loudspeaker.svg|11px|link=|alt=play]]}}
|
||||
fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|[[b=c|d]]}}" , "[[b=c|d]]{{{2}}}");
|
||||
}
|
||||
@Test public void LnkiWithPipe_nested() {
|
||||
fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|[[b=c|d[[e|f]]g]]}}" , "[[b=c|d[[e|f]]g]]{{{2}}}");
|
||||
}
|
||||
@Test public void LnkiWithPipe_unclosed() {
|
||||
fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|[[b=c|d}}" , "{{test|[[b=c|d}}");
|
||||
}
|
||||
@Test public void Err_tmp_empty() { // PURPOSE: {{{{R from misspelling}} }}
|
||||
fxt.Init_log_(Xop_ttl_log.Invalid_char).Test_parse_tmpl_str_test("{{{1}}}" , "{{ {{a}} }}" , "{{[[:Template:a]]}}");
|
||||
}
|
||||
@Test public void Mismatch_bgn() { // PURPOSE: handle {{{ }}; WP:Paris Commune; Infobox Former Country
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("!", "|");
|
||||
fxt.Test_parse_tmpl_str_test("{{#if:|{{{!}}{{!}}}|x}}" , "{{test}}" , "x");
|
||||
}
|
||||
@Test public void Mismatch_tblw() { // PURPOSE: handle {{{!}}; WP:Soviet Union
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("!", "|");
|
||||
fxt.Test_parse_page_all_str("a\n{{{!}}\n|b\n|}", String_.Concat_lines_nl_skip_last
|
||||
( "a"
|
||||
, "<table>"
|
||||
, " <tr>"
|
||||
, " <td>b"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, ""
|
||||
)
|
||||
);
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Lnki_space() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("c", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{c|[[a|b ]]}}", "[[a|b ]]");
|
||||
}
|
||||
@Test public void Bug_innerTemplate() { // PURPOSE: issue with inner templates not using correct key
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("temp_1", "{{temp_2|key1=val1}}");
|
||||
fxt.Init_defn_add("temp_2", "{{{key1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{temp_1}}", "val1");
|
||||
}
|
||||
@Test public void Missing() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_template", "{{[[Template:{{{1}}}|{{{1}}}]]}}");
|
||||
fxt.Init_log_(Xop_ttl_log.Invalid_char).Test_parse_tmpl_str("{{test_template|a}}", "{{[[Template:a|a]]}}");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Missing_foreign() {
|
||||
Xow_ns ns = fxt.Wiki().Ns_mgr().Ns_template();
|
||||
byte[] old_ns = ns.Name_bry();
|
||||
ns.Name_bry_(Bry_.new_a7("Template_foreign"));
|
||||
fxt.Test_parse_tmpl_str("{{Missing}}", "[[:Template_foreign:Missing]]");
|
||||
ns.Name_bry_(old_ns);
|
||||
}
|
||||
@Test public void Xnde_xtn_preserved() { // PURPOSE: tmpl was dropping .Xtn ndes; EX: below was just ab
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_template", "{{{1}}}");
|
||||
fxt.Test_parse_page_all_str("{{test_template|a<source>1</source>b}}", "a<pre>1</pre>b");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Recurse() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_recurse", "bgn:{{test_recurse}}:end");
|
||||
fxt.Test_parse_page_all_str("{{test_recurse}}", "bgn:<span class=\"error\">Template loop detected:test_recurse</span>:end");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_nl() {
|
||||
fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{test|\na}}" , "\na");
|
||||
}
|
||||
@Test public void Ws_trimmed_key_0() { // PURPOSE: control test for key_1, key_2
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{test_2|{{{1}}}}}");
|
||||
fxt.Init_defn_add("test_2", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| a }}", " a ");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_trimmed_key_1() { // PURPOSE: trim prm when passed as key;
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{test_2|key={{{1}}}}}");
|
||||
fxt.Init_defn_add("test_2", "{{{key}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| a }}", "a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_trimmed_key_2() { // PURPOSE: trim prm; note that 1 is key not idx; PAGE:en.w:Coord in Chernobyl disaster, Sahara
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{test_2|1={{{1}}}}}");
|
||||
fxt.Init_defn_add("test_2", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| a }}", "a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_trimmed_key_3() { // PURPOSE: trim entire arg only, not individual prm
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{test_2|1={{{1}}}{{{2}}}}}");
|
||||
fxt.Init_defn_add("test_2", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| a | b }}", "a b");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_eval_prm() { // PURPOSE: skip ws in prm_idx; EX:it.w:Portale:Giochi_da_tavolo; it.w:Template:Alternate; DATE:2014-02-09
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", String_.Concat_lines_nl_skip_last
|
||||
( "{{{ {{#expr: 1}} }}}"
|
||||
));
|
||||
fxt.Test_parse_tmpl_str("{{test_1|a}}", "a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Keyd_arg_is_trimmed() { // PURPOSE: trim entire arg only, not individual prm; PAGE:en.w:William Shakespeare; {{Relatebardtree}}
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{test_2|1={{{{{{1}}}}}}}}");
|
||||
fxt.Init_defn_add("test_2", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| b | b = x }}", "x");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ws_arg() { // PURPOSE: whitespace arg should not throw array index out of bounds; EX.WIKT: wear one's heart on one's sleeve
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{{{{1}}}}}");
|
||||
fxt.Test_parse_tmpl_str("{{test_1| }}", "(? [[dynamic is blank]] ?)");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Xnde_xtn_ref_not_arg() { // PURPOSE: <ref name= should not be interpreted as arg; EX: {{tmp|a<ref name="b"/>}}; arg1 is a<ref name="b"/> not "b"; PAGE:en.w:WWI
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{{1}}}");
|
||||
fxt.Test_parse_page_tmpl_str("{{test_1|a<ref name=b />}}", "a<ref name=b />");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Multi_bgn_5_end_3_2() {
|
||||
fxt.Test_parse_tmpl("{{{{{1}}}|a}}", fxt.tkn_tmpl_invk_(0, 13)
|
||||
.Name_tkn_(fxt.tkn_arg_nde_(2, 9).Key_tkn_(fxt.tkn_arg_itm_(fxt.tkn_tmpl_prm_find_(fxt.tkn_txt_(5, 6)))))
|
||||
.Args_
|
||||
( fxt.tkn_arg_val_txt_(10, 11)
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Lnki_has_invk_end() {// PURPOSE: [[A|bcd}}]] should not break enclosing templates; EX.CM:Template:Protect
|
||||
fxt.Test_parse_page_tmpl_str(String_.Concat_lines_nl_skip_last
|
||||
( "{{#switch:y"
|
||||
, " |y=[[A|b}}]]"
|
||||
, " |#default=n"
|
||||
, "}}"
|
||||
), "[[A|b}}]]");
|
||||
}
|
||||
@Test public void Lnki_has_prm_end() {// PURPOSE: [[A|bcd}}}]] should not break enclosing templates; EX.CM:Template:Protect
|
||||
fxt.Test_parse_page_tmpl_str(String_.Concat_lines_nl_skip_last
|
||||
( "{{#switch:y"
|
||||
, " |y=[[A|b}}}]]"
|
||||
, " |#default=n"
|
||||
, "}}"
|
||||
), "[[A|b}}}]]");
|
||||
}
|
||||
@Test public void Tmpl_overrides_pfunc() { // PURPOSE: {{plural|}} overrides {{plural:}}
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("plural", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("{{plural|a}}" , "a");
|
||||
fxt.Test_parse_tmpl_str("{{plural:2|a|b}}" , "b"); // make sure pfunc still works
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Tmpl_aliases() { // PURPOSE: handled aliases for Template ns
|
||||
fxt.Wiki().Ns_mgr().Aliases_add(Xow_ns_.Id_template, "TemplateAlias");
|
||||
fxt.Wiki().Ns_mgr().Init();
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("tmpl_key", "tmpl_val");
|
||||
fxt.Test_parse_tmpl_str("{{TemplateAlias:tmpl_key}}" , "tmpl_val");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Tmpl_aliases_2() { // PURPOSE: handled aliases for other ns; DATE:2013-02-08
|
||||
fxt.Wiki().Ns_mgr().Aliases_add(Xow_ns_.Id_project, "WP");
|
||||
fxt.Wiki().Ns_mgr().Init();
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_page_create("Project:tmpl_key", "tmpl_val");
|
||||
fxt.Test_parse_tmpl_str("{{WP:tmpl_key}}" , "tmpl_val");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Template_loop_across_namespaces() {// PURPOSE: {{Institution:Louvre}} results in template loop b/c it calls {{Louvre}}; EX: c:Mona Lisa
|
||||
fxt.Init_page_create("Template:Test", "test");
|
||||
fxt.Init_page_create("Category:Test", "{{Test}}");
|
||||
fxt.Test_parse_page_all_str("{{Category:Test}}", "test");
|
||||
}
|
||||
@Test public void Closing_braces_should_not_extend_beyond_lnki() { // PURPOSE: extra }} should not close any frames beyond lnki; EX:w:Template:Cite wikisource; w:John Fletcher (playwright)
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_b", "{{{test_b_0|}}}");
|
||||
fxt.Init_defn_add("test_a", "{{test_b|test_b_0=[[{{{test_a_0}}}}}]]}}"); // NOTE: extra 2 }}; should render literally and not close "{{test_b"
|
||||
fxt.Test_parse_tmpl_str("{{test_a|test_a_0=1}}" , "[[1}}]]");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
// @Test public void Trim_ws_on_sub_tmpls() { // PURPOSE: ws should be trimmed on eval tkns; EX:w:Lackawanna Cut-Off; {{Lackawanna Cut-Off}}; DELETE: no longer needed; DATE:2014-02-04
|
||||
// fxt.Init_defn_clear();
|
||||
// fxt.Init_defn_add("test_b", "\n\nb\n\n");
|
||||
// fxt.Init_defn_add("test_a", "a{{test_b}}c");
|
||||
// fxt.Test_parse_tmpl_str("{{test_a}}" , "a\n\nbc");
|
||||
// fxt.Init_defn_clear();
|
||||
// }
|
||||
@Test public void Nowiki_tblw() { // PURPOSE: nowiki does not exclude sections with pipe; will cause tables to fail; EX: de.wikipedia.org/wiki/Hilfe:Vorlagenprogrammierung
|
||||
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
|
||||
( "{|"
|
||||
, "|-"
|
||||
, "|<nowiki>{{ #time:M|Jan}}</nowiki>"
|
||||
, "|}"
|
||||
), String_.Concat_lines_nl_skip_last
|
||||
( "<table>"
|
||||
, " <tr>"
|
||||
, " <td>{{ #time:M|Jan}}"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, ""
|
||||
));
|
||||
}
|
||||
@Test public void Template_plus_other_ns() { // PURPOSE.fix: Template:Wikipedia:A was transcluding "Wikipedia:A" instead of "Template:Wikipedia:A"; DATE:2013-04-03
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_page_create("Template:Wikipedia:A" , "B");
|
||||
fxt.Test_parse_tmpl_str("{{Template:Wikipedia:A}}" , "B");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Return_nl() { // PURPOSE: allow \n to be returned by tmpl; do not trim; EX: zh.wikipedia.org/wiki/北區_(香港); DATE:2014-02-04
|
||||
fxt.Init_defn_add("1x", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str("a{{1x|\n}}b", "a\nb");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ignore_hdr() { // PURPOSE: hdr-like tkns inside tmpl should not be treated as "=" in tmpl_prm; EX: key_1\n==a==; EX:it.b:Wikibooks:Vetrina; DATE:2014-02-09
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{{key_1|null_key_1}}}");
|
||||
fxt.Test_parse_tmpl_str(String_.Concat_lines_nl_skip_last // == a === should be treated as hdr;
|
||||
( "{{test_1|key_1"
|
||||
, "== a =="
|
||||
, "}}"
|
||||
)
|
||||
, "null_key_1"
|
||||
);
|
||||
fxt.Test_parse_tmpl_str(String_.Concat_lines_nl_skip_last // = a = should not be treated as hdr;
|
||||
( "{{test_1|key_1"
|
||||
, "= a ="
|
||||
, "}}"
|
||||
)
|
||||
, "a ="
|
||||
);
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ignore_hdr_2() { // PURPOSE: hdr-like logic did not work for "== \n"; PAGE:nl.q:Geert_Wilders; DATE:2014-06-05
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Hdr_w_space", String_.Concat_lines_nl_skip_last
|
||||
( "{{#if:{{{key|}}} | "
|
||||
, "==={{{key}}}=== " // NOTE " " after "==="
|
||||
, "|}}"
|
||||
));
|
||||
fxt.Test_parse_page_tmpl_str(String_.Concat_lines_nl_skip_last
|
||||
( "{{Hdr_w_space"
|
||||
, "|key=A"
|
||||
, "}}"
|
||||
), "===A==="
|
||||
);
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ignore_hdr_3() { // PURPOSE: tkn with multiple eq should have be treated as value, not header; PAGE:zh.w:Wikipedia:条目评选; DATE:2014-08-27
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{{key_1|null_key_1}}}");
|
||||
fxt.Test_parse_page_tmpl_str(String_.Concat_lines_nl_skip_last
|
||||
( "{{test_1"
|
||||
, "|key_1===A==" // note that this is not "===A==", but "=","===A=="
|
||||
, "}}"
|
||||
), "==A=="
|
||||
);
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Ignore_hdr_4() { // PURPOSE: variation of above; make sure 2nd "==" doesn't trigger another key; DATE:2014-08-27
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_1", "{{{key_1|null_key_1}}}");
|
||||
fxt.Test_parse_page_tmpl_str(String_.Concat_lines_nl_skip_last
|
||||
( "{{test_1"
|
||||
, "|key_1===A===B" // = should be at "==A", not "==B"
|
||||
, "}}"
|
||||
), "==A===B"
|
||||
);
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Tmpl_case_match() { // PURPOSE: template name should match by case; EX:es.d:eclipse; DATE:2014-02-12
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("CASE_MATCH", "found", Xow_ns_case_.Id_all);
|
||||
fxt.Test_parse_tmpl_str("{{case_match}}", "[[:Template:case_match]]"); // Xot_invk_tkn will do 2 searches: "test" and "Test"
|
||||
fxt.Test_parse_tmpl_str("{{cASE_MATCH}}", "found"); // Xot_invk_tkn will do 2 searches: "tEST" and "TEST"
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Kv_same() { // PURPOSE: multiple identical keys should retrieve last, not first; EX: {{A|1=a|1=b}}; PAGE:el.d:ἔχω DATE:2014-07-23
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("tmpl_1", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str_test("{{tmpl_1|1=a|1=b}}" , "{{test}}" , "b"); // duplicate "1"; use last
|
||||
fxt.Test_parse_tmpl_str_test("{{tmpl_1|a|1=b}}" , "{{test}}" , "b"); // "a" has implicit key of "1"; overwritten by "1=b"; verified against MW
|
||||
fxt.Test_parse_tmpl_str_test("{{tmpl_1|1=a|b}}" , "{{test}}" , "b"); // "b" has implicit key of "1"; overwritten by "1=b"; verified against MW
|
||||
}
|
||||
@Test public void Bang() { // PURPOSE: support new bang keyword; DATE:2014-08-05
|
||||
fxt.Test_parse_tmpl_str("{{!}}", "|");
|
||||
}
|
||||
}
|
||||
121
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr_prepend_nl_tst.java
Normal file
121
400_xowa/src_500_tmpl/gplx/xowa/Xot_invk_wkr_prepend_nl_tst.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_invk_wkr_prepend_nl_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Basic() { // PURPOSE: if {| : ; # *, auto add new_line REF.MW:Parser.php|braceSubstitution
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_inner", "# a");
|
||||
fxt.Test_parse_tmpl_str_test("{{test_inner}}" , "z {{test}}" , "z \n# a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Skip_if_nl_exists() {
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_inner", "# a");
|
||||
fxt.Test_parse_tmpl_str_test("{{test_inner}}" , "z \n{{test}}" , "z \n# a"); // NOTE: no \n
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Skip_if_nl_exists_2() { // PURPOSE: \n inside template args should not print \n\n; PAGE:bn.w:লিওনেল_মেসি |ko.w:도쿄_지하철_히비야_선|DATE:2014-05-27
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("test_list", "# a");
|
||||
fxt.Init_defn_add("test_print", "{{{1}}}");
|
||||
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
|
||||
( "{{test_print|"
|
||||
, "{{test_list}}" // note that there is a "\n" here, but test_list will return "#"; "#" should not be prepended with \n
|
||||
, "{{test_list}}"
|
||||
, "}}"
|
||||
), "{{test}}"
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "" // NOTE: \n still prints b/c of \n between "{{test_print|" and "{{test_list}}"; should trim ws at start;
|
||||
, "# a"
|
||||
, "# a"
|
||||
));
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Pfunc() {// PURPOSE: if {| : ; # *, auto add new_line; parser_function variant; PAGE:en.w:Soviet Union; Infobox former country
|
||||
fxt.Test_parse_tmpl_str_test("" , "z {{#if:true|#a|n}}" , "z \n#a");
|
||||
}
|
||||
@Test public void Bos() { // PURPOSE: function should expand "*a" to "\n*a" even if "*a" is bos; SEE:NOTE_1 PAGE:en.w:Rome and Panoramas; DATE:2014-02-05
|
||||
fxt.Test_parse_page_tmpl_str("{{#if:x|*a}}", "\n*a");
|
||||
}
|
||||
@Test public void Tmpl_arg() { // PURPOSE: tmpl arg should auto-create; PAGE:vi.w:Friedrich_II_của_Phổ; DATE:2014-04-26
|
||||
fxt.Init_defn_add("cquote" , "*b");
|
||||
fxt.Init_defn_add("blockquote" , "<blockquote>{{{1}}}</blockquote>");
|
||||
fxt.Test_html_full_str("a\n{{blockquote|{{cquote}}}}"
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "a"
|
||||
, "<blockquote>"
|
||||
, "<ul>"
|
||||
, " <li>b"
|
||||
, " </li>"
|
||||
, "</ul></blockquote>"
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Nested_1_n() { // PURPOSE: handled nested templates; PAGE:en.w:Central_Line en.w:Panama_Canal; DATE:2014-08-21
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Nest_1" , "a{{Nest_1_1}}"); // 0: no \n
|
||||
fxt.Init_defn_add("Nest_1_1" , "b\n{{Nest_1_1_1}}"); // 1: \n
|
||||
fxt.Init_defn_add("Nest_1_1_1" , "*c"); // 2: "*" should not prepend \n b/c (1) has \n; used to only check (0)
|
||||
fxt.Test_parse_tmpl_str_test("{{Nest_1}}", "{{test}}", String_.Concat_lines_nl_skip_last
|
||||
( "ab" // not prepended
|
||||
, "*c"
|
||||
));
|
||||
}
|
||||
@Test public void Nested_1_y() { // PURPOSE: handled nested templates; PAGE:en.w:Lackawanna_Cut-Off; DATE:2014-08-21
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Nest_1" , "a\n{{Nest_1_1}}"); // 0: no \n
|
||||
fxt.Init_defn_add("Nest_1_1" , "b{{Nest_1_1_1}}"); // 1: char
|
||||
fxt.Init_defn_add("Nest_1_1_1" , "*c"); // 2: "*" should prepend \n b/c (1) has char; used to check (0) and not prepend
|
||||
fxt.Test_parse_tmpl_str_test("{{Nest_1}}", "{{test}}", String_.Concat_lines_nl_skip_last
|
||||
( "a"
|
||||
, "b" // prepended
|
||||
, "*c"
|
||||
));
|
||||
}
|
||||
@Test public void Nested_0_n() { // PURPOSE: handled nested templates variation of above; DATE:2014-08-21
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Nest_1" , "a\n{{Nest_1_1}}"); // 0: \n
|
||||
fxt.Init_defn_add("Nest_1_1" , "{{Nest_1_1_1}}"); // 1: ""
|
||||
fxt.Init_defn_add("Nest_1_1_1" , "*b"); // 2: "*" should not prepend \n b/c (1) is empty and (0) has \n
|
||||
fxt.Test_parse_tmpl_str_test("{{Nest_1}}", "{{test}}", String_.Concat_lines_nl_skip_last
|
||||
( "a" // not prepended
|
||||
, "*b"
|
||||
));
|
||||
}
|
||||
@Test public void Nested_0_y() { // PURPOSE: handled nested templates variation of above; DATE:2014-08-21
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Nest_1" , "a{{Nest_1_1}}"); // 0: no \n
|
||||
fxt.Init_defn_add("Nest_1_1" , "{{Nest_1_1_1}}"); // 1: ""
|
||||
fxt.Init_defn_add("Nest_1_1_1" , "*b"); // 2: "*" should prepend \n b/c (1) is empty and (0) has char
|
||||
fxt.Test_parse_tmpl_str_test("{{Nest_1}}", "{{test}}", String_.Concat_lines_nl_skip_last
|
||||
( "a" // prepended
|
||||
, "*b"
|
||||
));
|
||||
}
|
||||
}
|
||||
/*
|
||||
NOTE_1: function should expand "*a" to "\n*a" even if "*a" is bos
|
||||
consider following
|
||||
Template:Test with text of "#a"
|
||||
a) "a{{test}}" would return "a\n#a" b/c of rule for auto-adding \n
|
||||
b) bug was that "{{test}}" would return "#a" b/c "#a" was at bos which would expand to list later
|
||||
however, needs to be "\n#a" b/c appended to other strings wherein bos would be irrelevant.
|
||||
Actual situation was very complicated. PAGE:en.w:Rome;
|
||||
*/
|
||||
@@ -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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_invk_wkr_raw_msg_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@After public void term() {fxt.Init_defn_clear();}
|
||||
@Test public void Raw() { // PURPOSE: {{raw:A}} is same as {{A}}; EX.WIKT:android; {{raw:ja/script}}
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Test 1", "{{#if:|y|{{{1}}}}}");
|
||||
fxt.Test_parse_tmpl_str("{{raw:Test 1|a}}", "a");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Raw_spanish() { // PURPOSE.fix: {{raw}} should not fail; EX:es.s:Carta_a_Silvia; DATE:2014-02-11
|
||||
fxt.Test_parse_tmpl_str("{{raw}}", "[[:Template:raw]]"); // used to fail; now tries to get Template:Raw which doesn't exist
|
||||
}
|
||||
@Test public void Special() { // PURPOSE: {{Special:Whatlinkshere}} is same as [[:Special:Whatlinkshere]]; EX.WIKT:android; isValidPageName
|
||||
fxt.Test_parse_page_tmpl_str("{{Special:Whatlinkshere}}", "[[:Special:Whatlinkshere]]");
|
||||
}
|
||||
@Test public void Special_arg() { // PURPOSE: make sure Special still works with {{{1}}}
|
||||
fxt.Init_defn_clear();
|
||||
fxt.Init_defn_add("Test1", "{{Special:Whatlinkshere/{{{1}}}}}");
|
||||
fxt.Test_parse_tmpl_str("{{Test1|-1}}", "[[:Special:Whatlinkshere/-1]]");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Raw_special() { // PURPOSE: {{raw:A}} is same as {{A}}; EX.WIKT:android; {{raw:ja/script}}
|
||||
fxt.Test_parse_tmpl_str("{{raw:Special:Whatlinkshere}}", "[[:Special:Whatlinkshere]]");
|
||||
fxt.Init_defn_clear();
|
||||
}
|
||||
@Test public void Msg() {
|
||||
fxt.Init_defn_add("CURRENTMONTH", "a");
|
||||
fxt.Test_parse_tmpl_str("{{msg:CURRENTMONTH}}", "a");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_invk_wkr_transclude_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@After public void term() {fxt.Init_defn_clear();}
|
||||
@Test public void Template() { // PURPOSE: {{:Template:Test}} is same as {{Template:Test}}; EX.WIKT:android; japanese and {{:Template:ja/script}}
|
||||
fxt.Init_defn_add("Test_1", "{{#if:|y|n}}"); // NOTE: must be of form "Test 1"; test_1 will fail
|
||||
fxt.Test_parse_tmpl_str("{{:Template:Test 1}}", "n");
|
||||
}
|
||||
@Test public void Arguments() { // PURPOSE: transclusion test with arguments
|
||||
fxt.Init_page_create("PageToTransclude", "a{{{key}}}c");
|
||||
fxt.Test_parse_tmpl_str("some text to make this page longer than transclusion {{:PageToTransclude|key=b}}" , "some text to make this page longer than transclusion abc");
|
||||
}
|
||||
@Test public void Redirect() { // PURPOSE: StackOverflowError when transcluded sub-page redirects back to root_page; DATE:2014-01-07
|
||||
fxt.Init_page_create("Root/Leaf", "#REDIRECT [[Root]]");
|
||||
fxt.Init_page_create("Root", "<gallery>A.png|a{{/Leaf}}b</gallery>"); // NOTE: gallery neeeded for XOWA to fail; MW fails if just {{/Leaf}}
|
||||
fxt.Test_parse_page("Root", "<gallery>A.png|a{{/Leaf}}b</gallery>");
|
||||
}
|
||||
@Test public void Missing() { // PURPOSE: transclusion of a missing page should create a link, not print an empty String; EX: it.u:Dipartimento:Design; DATE:2014-02-12
|
||||
fxt.Page_ttl_("Test_Page");
|
||||
fxt.Test_parse_tmpl_str("{{/Sub}}", "[[Test_Page/Sub]]");
|
||||
}
|
||||
}
|
||||
89
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_tkn.java
Normal file
89
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_tkn.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Xot_prm_tkn extends Xop_tkn_itm_base {
|
||||
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tmpl_prm;}
|
||||
@Override public void Tmpl_fmt(Xop_ctx ctx, byte[] src, Xot_fmtr fmtr) {fmtr.Reg_prm(ctx, src, this, prm_idx, prm_key, dflt_tkn);}
|
||||
@Override public void Tmpl_compile(Xop_ctx ctx, byte[] src, Xot_compile_data prep_data) {
|
||||
if (find_tkn != null) { // NOTE: find_tkn defaults to null
|
||||
int subs_len = find_tkn.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub = find_tkn.Subs_get(i);
|
||||
switch (sub.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_tmpl_invk: case Xop_tkn_itm_.Tid_tmpl_prm: case Xop_tkn_itm_.Tid_ignore: case Xop_tkn_itm_.Tid_xnde:
|
||||
find_tkn_static = false;
|
||||
break;
|
||||
}
|
||||
sub.Tmpl_compile(ctx, src, prep_data);
|
||||
}
|
||||
if (find_tkn_static) { // subs_are_static, so extract idx/key; EX: {{{a b}}} will have 3 subs which are all static; {{{a{{{1}}}b}}} will be dynamic
|
||||
int find_tkn_bgn = find_tkn.Dat_bgn(), find_tkn_end = find_tkn.Dat_end();
|
||||
if (find_tkn_end - find_tkn_bgn > 0) { // NOTE: handles empty find_tkns; EX: {{{|safesubst:}}}
|
||||
prm_idx = Bry_.Xto_int_or(src, find_tkn_bgn, find_tkn_end, -1); // parse as number first; note that bgn,end should not include ws; EX: " 1 " will fail
|
||||
if (prm_idx == -1) prm_key = Bry_.Mid(src, find_tkn_bgn, find_tkn_end);// not a number; parse as key
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dflt_tkn != null) dflt_tkn.Tmpl_compile(ctx, src, prep_data);
|
||||
}
|
||||
@Override public boolean Tmpl_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) {
|
||||
if (!find_tkn_static) {
|
||||
int subs_len = find_tkn.Subs_len();
|
||||
Bry_bfr find_bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
find_tkn.Subs_get(i).Tmpl_evaluate(ctx, src, caller, find_bfr);
|
||||
prm_idx = Bry_.Xto_int_or_trim(find_bfr.Bfr(), 0, find_bfr.Len(), -1); // parse as number first; NOTE: trim needed to transform "{{{ 1 }}}" to "1"; it.w:Portale:Giochi_da_tavolo; DATE:2014-02-09
|
||||
if (prm_idx == -1)
|
||||
prm_key = find_bfr.Xto_bry_and_clear_and_trim(); // not a number; parse as key; NOTE: must trim; PAGE:en.w:William Shakespeare; {{Relatebardtree}}
|
||||
}
|
||||
Arg_nde_tkn arg_nde = null;
|
||||
if (prm_idx == -1) { // prm is key; EX: "{{{key1}}}"
|
||||
if (prm_key != Bry_.Empty) // NOTE: handles empty find_tkns; EX: {{{|safesubst:}}}
|
||||
arg_nde = caller.Args_get_by_key(src, prm_key);
|
||||
if (arg_nde == null) {Tmpl_write_missing(ctx, src, caller, bfr); return true;}
|
||||
}
|
||||
else { // prm is idx; EX: "{{{1}}}"
|
||||
// int invk_args_len = caller.Args_len();
|
||||
// if (prm_idx > invk_args_len) {Tmpl_write_missing(ctx, src, caller, bfr); return true;}
|
||||
arg_nde = caller.Args_eval_by_idx(src, prm_idx - List_adp_.Base1); // MW args are Base1; EX: {{test|a|b}}; a is {{{1}}}; b is {{{2}}}
|
||||
if (arg_nde == null) {Tmpl_write_missing(ctx, src, caller, bfr); return true;} // EX: handles "{{{1}}}{{{2}}}" "{{test|a|keyd=b}}" -> "a{{{2}}}"
|
||||
}
|
||||
Arg_itm_tkn arg_val = arg_nde.Val_tkn();
|
||||
if (arg_val.Itm_static() == Bool_.Y_byte)
|
||||
bfr.Add_mid(src, arg_val.Dat_bgn(), arg_val.Dat_end());
|
||||
else {// compile arg if dynamic; EX: [[MESSENGER]] "{{About|the NASA space mission||Messenger (disambiguation){{!}}Messenger}}"; {{!}} causes {{{2}}} to be dynamic and its dat_ary will be an empty-String ("")
|
||||
Bry_bfr arg_val_bfr = Bry_bfr.new_();
|
||||
arg_val.Tmpl_evaluate(ctx, src, caller, arg_val_bfr);
|
||||
bfr.Add_bfr_and_clear(arg_val_bfr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private void Tmpl_write_missing(Xop_ctx ctx, byte[] src, Xot_invk caller, Bry_bfr bfr) {
|
||||
if (dflt_tkn == null) { // dflt absent; write orig; {{{1}}} or {{{key}}};
|
||||
bfr.Add(Xop_curly_wkr.Hook_prm_bgn);
|
||||
int subs_len = find_tkn.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
find_tkn.Subs_get(i).Tmpl_evaluate(ctx, src, caller, bfr);
|
||||
bfr.Add(Xop_curly_wkr.Hook_prm_end);
|
||||
} else dflt_tkn.Tmpl_evaluate(ctx, src, caller, bfr); // dflt exists; write it
|
||||
}
|
||||
int prm_idx = -1; byte[] prm_key = Bry_.Empty; boolean find_tkn_static = true;
|
||||
public Arg_itm_tkn Find_tkn() {return find_tkn;} public Xot_prm_tkn Find_tkn_(Arg_itm_tkn v) {find_tkn = v; return this;} Arg_itm_tkn find_tkn;
|
||||
public Xot_prm_tkn Dflt_tkn_(Arg_itm_tkn v) {dflt_tkn = v; return this;} Arg_itm_tkn dflt_tkn;
|
||||
public Xot_prm_tkn(int bgn, int end) {this.Tkn_ini_pos(false, bgn, end);}
|
||||
}
|
||||
57
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_tkn_tst.java
Normal file
57
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_tkn_tst.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; import gplx.*;
|
||||
import org.junit.*;
|
||||
public class Xot_prm_tkn_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Idx_1() {fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{test|a|b}}" , "a");}
|
||||
@Test public void Idx_2() {fxt.Test_parse_tmpl_str_test("{{{2}}}" , "{{test|a|b}}" , "b");}
|
||||
@Test public void Idx_3_nil() {fxt.Test_parse_tmpl_str_test("{{{3}}}" , "{{test|a|b}}" , "{{{3}}}");}
|
||||
@Test public void Idx_3_dflt() {fxt.Test_parse_tmpl_str_test("{{{3|c}}}" , "{{test|a|b}}" , "c");}
|
||||
@Test public void Idx_3_dflt_len0() {fxt.Test_parse_tmpl_str_test("{{{1|}}}" , "{{test}}" , "");}
|
||||
@Test public void Idx_1_and_2() {fxt.Test_parse_tmpl_str_test("({{{1}}} {{{2}}})" , "{{test|a|b}}" , "(a b)");}
|
||||
@Test public void Idx_2_len0() {fxt.Test_parse_tmpl_str_test("{{{1}}}" , "{{test||b}}" , "");}// should not fail
|
||||
@Test public void Key() {fxt.Test_parse_tmpl_str_test("{{{k1}}}" , "{{test|k1=a|k2=b}}" , "a");}
|
||||
@Test public void Key_nil() {fxt.Test_parse_tmpl_str_test("{{{k3|c}}}" , "{{test|k1=a|k2=b}}" , "c");}
|
||||
@Test public void Key_exact() {fxt.Test_parse_tmpl_str_test("{{{k|}}}{{{k2|}}}" , "{{test|k=a}}" , "a");} // only {{{k}}} matched
|
||||
@Test public void Var() {fxt.Test_parse_tmpl_str_test("{{{1|-{{PAGENAME}}-}}}" , "{{test}}" , "-Test page-");}
|
||||
@Test public void Newline_bgn() {fxt.Test_parse_tmpl_str_test("{{{1}}} {{{2}}}" , "{{test|a|\nb}}" , "a \nb");}
|
||||
@Test public void Newline_end() {fxt.Test_parse_tmpl_str_test("{{{1}}} {{{2}}}" , "{{test|a|b\n}}" , "a b\n");}
|
||||
@Test public void Exc_lkp_nil() {fxt.Test_parse_tmpl_str_test("{{{}}}" , "{{test|a|b}}" , "{{{}}}");}
|
||||
@Test public void Exc_lkp_and_args1() {fxt.Test_parse_tmpl_str_test("{{{|}}}" , "{{test|a|b}}" , "");}
|
||||
@Test public void Exc_lkp_nil_args1_txt() {fxt.Test_parse_tmpl_str_test("{{{|a}}}" , "{{test|a|b}}" , "a");}
|
||||
@Test public void Ws_idx() {fxt.Test_parse_tmpl_str_test("{{{ 1 }}}" , "{{test|a|b}}" , "a");}
|
||||
@Test public void Ws_idx_nil() {fxt.Test_parse_tmpl_str_test("{{{ 1 }}}" , "{{test}}" , "{{{ 1 }}}");}
|
||||
@Test public void Ws_key() {fxt.Test_parse_tmpl_str_test("{{{ k1 }}}" , "{{test|k1=a|k2=b}}" , "a");}
|
||||
@Test public void Ws_dflt() {fxt.Test_parse_tmpl_str_test("{{{1| a }}}" , "{{test}}" , " a ");}
|
||||
@Test public void Dflt_multiple() {fxt.Test_parse_tmpl_str_test("{{{1|a|b}}}" , "{{test}}" , "a");}
|
||||
@Test public void Keyd_not_idxd() {fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|a|key=b}}" , "a{{{2}}}");}
|
||||
@Test public void Keyd_not_idxd_ints() {fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|1=a|2=b}}" , "ab");}
|
||||
@Test public void Recurse_1() {fxt.Test_parse_tmpl_str_test("{{{1{{{2|}}}|}}}" , "{{test|a}}" , "a");} // used in {{See}} to test if argument 2 is last
|
||||
@Test public void Recurse_2() {fxt.Test_parse_tmpl_str_test("{{{1{{{2|}}}|}}}" , "{{test|a|b}}" , "");}
|
||||
@Test public void Keyd_int() {fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|2=a|b}}" , "ba");}
|
||||
@Test public void Keyd_int2() {fxt.Test_parse_tmpl_str_test("{{{1}}}{{{2}}}" , "{{test|2=a|1=b}}" , "ba");}
|
||||
@Test public void Keyd_int3() {fxt.Test_parse_tmpl_str_test("{{{12}}}" , "{{test|12=a}}" , "a");}
|
||||
@Test public void Equal_ignored() {fxt.Test_parse_tmpl_str_test("{{{1|b=c}}}" , "{{test}}" , "b=c");}
|
||||
@Test public void Unresolved() {fxt.Test_parse_tmpl_str_test("" , "{{{a|b}}}" , "b");}
|
||||
@Test public void Six_ltr() {fxt.Test_parse_tmpl_str_test("{{{{{{1}}}}}}" , "{{test|a}}" , "{{{a}}}");}
|
||||
@Test public void Six_num() {fxt.Test_parse_tmpl_str_test("{{{{{{1}}}}}}" , "{{test|1}}" , "1");}
|
||||
}
|
||||
/*
|
||||
*/
|
||||
46
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_wkr.java
Normal file
46
400_xowa/src_500_tmpl/gplx/xowa/Xot_prm_wkr.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
class Xot_prm_wkr implements Xop_arg_wkr {
|
||||
private static Arg_bldr arg_bldr = Arg_bldr._;
|
||||
public boolean Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos, Xop_curly_bgn_tkn bgn, int keep_curly_bgn) {
|
||||
int loop_bgn = bgn.Tkn_sub_idx() + 1; // +1 to ignore curly_bgn
|
||||
int loop_end = root.Subs_len();
|
||||
if (loop_bgn == loop_end) {// no tkns; output literal {{{}}} // 2012.03.27:commented out due to {{{{{{}}}}}}
|
||||
root.Subs_del_after(bgn.Tkn_sub_idx());
|
||||
ctx.Msg_log().Add_itm_none(Xot_prm_log.Lkp_is_nil, src, lxr_bgn_pos, lxr_cur_pos);
|
||||
ctx.Subs_add(root, tkn_mkr.Txt(bgn.Src_bgn(), lxr_cur_pos));
|
||||
return false;
|
||||
}
|
||||
Xot_prm_tkn prm_tkn = tkn_mkr.Tmpl_prm(bgn.Src_bgn(), lxr_cur_pos);
|
||||
arg_bldr.Bld(ctx, tkn_mkr, Xot_prm_wkr._, Xop_arg_wkr_.Typ_prm, root, prm_tkn, lxr_bgn_pos, lxr_cur_pos, loop_bgn, loop_end, src);
|
||||
root.Subs_del_after(bgn.Tkn_sub_idx() + keep_curly_bgn); // NOTE: keep_curly_bgn determines whether or not to delete opening {{{
|
||||
root.Subs_add(prm_tkn);
|
||||
return true;
|
||||
}
|
||||
public boolean Args_add(Xop_ctx ctx, byte[] src, Xop_tkn_itm tkn, Arg_nde_tkn arg, int arg_idx) {
|
||||
Xot_prm_tkn prm = (Xot_prm_tkn)tkn;
|
||||
switch (arg_idx) {
|
||||
case 0: prm.Find_tkn_(arg.Val_tkn()); break;
|
||||
case 1: prm.Dflt_tkn_(arg.Val_tkn()); break;
|
||||
default: ctx.Msg_log().Add_itm_none(Xot_prm_log.Prm_has_2_or_more, src, arg.Src_bgn(), arg.Src_end()); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static final Xot_prm_wkr _ = new Xot_prm_wkr(); Xot_prm_wkr() {}
|
||||
}
|
||||
112
400_xowa/src_500_tmpl/gplx/xowa/Xot_tmpl_wtr.java
Normal file
112
400_xowa/src_500_tmpl/gplx/xowa/Xot_tmpl_wtr.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
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; import gplx.*;
|
||||
public class Xot_tmpl_wtr {
|
||||
public byte[] Write_all(Xop_ctx ctx, Xop_root_tkn root, byte[] src) {
|
||||
// synchronized (this) { // THREAD:added synchronized after "failed to write tkn" DATE:2015-04-29
|
||||
Bry_bfr rslt_bfr = ctx.App().Utl__bfr_mkr().Get_m001();
|
||||
ctx.Tmpl_output_(rslt_bfr);
|
||||
rslt_bfr.Reset_if_gt(Io_mgr.Len_mb);
|
||||
Write_tkn(ctx, src, src.length, rslt_bfr, root);
|
||||
ctx.Tmpl_output_(null);
|
||||
return rslt_bfr.To_bry_and_rls();
|
||||
// }
|
||||
}
|
||||
private void Write_tkn(Xop_ctx ctx, byte[] src, int src_len, Bry_bfr rslt_bfr, Xop_tkn_itm tkn) {
|
||||
switch (tkn.Tkn_tid()) {
|
||||
case Xop_tkn_itm_.Tid_root: // write each sub
|
||||
int subs_len = tkn.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub_tkn = tkn.Subs_get(i);
|
||||
if (!sub_tkn.Ignore())
|
||||
Write_tkn(ctx, src, src_len, rslt_bfr, sub_tkn);
|
||||
}
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_bry:
|
||||
Xop_bry_tkn bry = (Xop_bry_tkn)tkn;
|
||||
rslt_bfr.Add(bry.Val());
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_space:
|
||||
if (tkn.Tkn_immutable())
|
||||
rslt_bfr.Add_byte(Byte_ascii.Space);
|
||||
else
|
||||
rslt_bfr.Add_byte_repeat(Byte_ascii.Space, tkn.Src_end() - tkn.Src_bgn());
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_xnde:
|
||||
Xop_xnde_tkn xnde = (Xop_xnde_tkn)tkn;
|
||||
int xnde_tag_id = xnde.Tag().Id();
|
||||
switch (xnde_tag_id) {
|
||||
case Xop_xnde_tag_.Tid_onlyinclude: {
|
||||
// NOTE: originally "if (ctx.Parse_tid() == Xop_parser_.Parse_tid_page_tmpl) {" but if not needed; Xot_tmpl_wtr should not be called for tmpls and <oi> 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);
|
||||
ctx.Only_include_evaluate_(false);
|
||||
rslt_bfr.Add_bfr_and_preserve(tmp_bfr);
|
||||
break;
|
||||
}
|
||||
case Xop_xnde_tag_.Tid_includeonly: // noop; DATE:2014-02-12
|
||||
break;
|
||||
case Xop_xnde_tag_.Tid_nowiki: {
|
||||
if (xnde.Tag_close_bgn() == Int_.MinValue)
|
||||
rslt_bfr.Add_mid(src, tkn.Src_bgn(), tkn.Src_end()); // write src from bgn/end
|
||||
else { // NOTE: if nowiki then "deactivate" all xndes by swapping out < for < nowiki_xnde_frag; DATE:2013-01-27
|
||||
Bry_bfr tmp_bfr = ctx.Wiki().Appe().Utl__bfr_mkr().Get_k004();
|
||||
int nowiki_content_bgn = xnde.Tag_open_end(), nowiki_content_end = xnde.Tag_close_bgn();
|
||||
boolean escaped = gplx.xowa.parsers.tmpls.Nowiki_escape_itm.Escape(tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
||||
rslt_bfr.Add_bfr_or_mid(escaped, tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Xop_xnde_tag_.Tid_xowa_cmd:
|
||||
gplx.xowa.xtns.xowa_cmds.Xop_xowa_cmd xowa_cmd = (gplx.xowa.xtns.xowa_cmds.Xop_xowa_cmd)xnde.Xnde_xtn();
|
||||
rslt_bfr.Add(xowa_cmd.Xtn_html());
|
||||
break;
|
||||
default:
|
||||
rslt_bfr.Add_mid(src, tkn.Src_bgn(), tkn.Src_end()); // write src from bgn/end
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_tvar:
|
||||
gplx.xowa.xtns.translates.Xop_tvar_tkn tvar_tkn = (gplx.xowa.xtns.translates.Xop_tvar_tkn)tkn;
|
||||
rslt_bfr.Add(tvar_tkn.Wikitext());
|
||||
break;
|
||||
case Xop_tkn_itm_.Tid_tmpl_invk:
|
||||
try {
|
||||
tkn.Tmpl_evaluate(ctx, src, Xot_invk_temp.Page_is_caller.Src_(src), rslt_bfr);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Err_string = String_.new_u8(src, tkn.Src_bgn(), tkn.Src_end()) + "|" + ClassAdp_.NameOf_obj(e) + "|" + Err_.Message_lang(e);
|
||||
if (Env_.Mode_testing())
|
||||
throw Exc_.new_exc(e, "xo", Err_string);
|
||||
else
|
||||
ctx.App().Usr_dlg().Warn_many("", "", "failed to write tkn: page=~{0} err=~{1}", String_.new_u8(ctx.Cur_page().Ttl().Page_db()), Err_string);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static String Err_string = "";
|
||||
public static final Xot_tmpl_wtr _ = new Xot_tmpl_wtr(); Xot_tmpl_wtr() {}
|
||||
}
|
||||
Reference in New Issue
Block a user