1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

'v3.6.4.1'

This commit is contained in:
gnosygnu
2016-06-26 01:10:38 -04:00
parent 8afc115176
commit b3c2d3bb5f
108 changed files with 1813 additions and 873 deletions

View File

@@ -29,6 +29,6 @@ public class Pfunc_grammar extends Pf_func_base {
boolean pass = false;
try {pass = lang.Grammar().Grammar_eval(bfr, lang, word, argx);}
catch (Exception e) {Err_.Noop(e);}
if (!pass) Xot_invk_tkn.Print_not_found(bfr, ctx.Wiki().Ns_mgr(), this.Name());
if (!pass) Xot_invk_tkn.Print_not_found__w_template(bfr, ctx.Wiki().Ns_mgr(), this.Name());
}
}

View File

@@ -16,7 +16,6 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.xowa.htmls.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.tmpls.*;
public class Pfunc_tag extends Pf_func_base {
@@ -24,108 +23,57 @@ public class Pfunc_tag extends Pf_func_base {
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_tag().Name_(name);}
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
byte[] tag_name = Eval_argx(ctx, src, caller, self); if (tag_name.length == 0) return;
int args_len = self.Args_len();
Xoae_app app = ctx.App();
Bry_bfr tmp = app.Utl__bfr_mkr().Get_b512();
// make <xnde> based on {{#tag}}; EX: {{#tag:ref|a|name=1}} -> <ref name='1'>a</ref>
Bry_bfr tmp_bfr = ctx.App().Utl__bfr_mkr().Get_b512();
try {
int tag_idx = ++tag__next_id;
// get tag_idx, tag_data, and tag_is_ref
int tag_idx = -1;
synchronized (next_id_lock) {tag_idx = ++next_id_val;}
byte[] tag_name = Eval_argx(ctx, src, caller, self); if (tag_name.length == 0) return;
Xop_xnde_tag tag = (Xop_xnde_tag)ctx.Xnde_tag_regy().Get_trie(ctx.Xnde_names_tid()).Match_exact(tag_name, 0, tag_name.length);
boolean tag_is_ref = tag != null && tag.Id() == Xop_xnde_tag_.Tid__ref;
// open tag
if (tag_is_ref) // <ref>; add <xtag_bgn> to handle nested refs; PAGE:en.w:Battle_of_Midway; DATE:2014-06-27
tmp.Add(Xtag_bgn_lhs).Add_int_pad_bgn(Byte_ascii.Num_0, 10, tag_idx).Add(Xtag_rhs);
tmp.Add_byte(Byte_ascii.Lt).Add(tag_name);
if (args_len > 1) {
tmp_bfr.Add(Xtag_bgn_lhs).Add_int_pad_bgn(Byte_ascii.Num_0, 10, tag_idx).Add(Xtag_rhs);
tmp_bfr.Add_byte(Byte_ascii.Lt).Add(tag_name); // EX: "<ref"
// iterate args and build attributes; EX: "|a=1|b=2" -> "a='1' b='2'"
int args_len = self.Args_len();
if (args_len > 1) { // NOTE: starting from 1 b/c 0 is innerText
Pfunc_tag_kvp_wtr kvp_wtr = new Pfunc_tag_kvp_wtr();
for (int i = 1; i < args_len; i++) {
byte[] arg = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, i); // NOTE: must evaluate arg; don't try to parse arg_tkn's key / val separately; EX:{{#tag:pre|a|{{#switch:a|a=id}}=c}}
if (arg.length == 0) continue; // skip empty atrs
tmp.Add_byte(Byte_ascii.Space);
Pfunc_tag_kv_bldr.Add_arg_as_html_atr(arg, tmp);
if (arg.length == 0) continue; // skip empty atrs
tmp_bfr.Add_byte(Byte_ascii.Space); // write space between html_args
kvp_wtr.Write_as_html_atr(tmp_bfr, arg); // write html_arg
}
}
tmp.Add_byte(Byte_ascii.Gt);
if (args_len > 0) // TODO_OLD: trim should not be called on content; WHEN: adding src[] back to tmpl_eval
tmp.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0));
tmp.Add_byte(Byte_ascii.Lt).Add_byte(Byte_ascii.Slash).Add(tag_name).Add_byte(Byte_ascii.Gt);
tmp_bfr.Add_byte(Byte_ascii.Gt); // EX: ">"
// add innerText;
if (args_len > 0) // handle no args; EX: "{{#tag:ref}}" -> "<ref></ref>"
tmp_bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0));
// close tag
tmp_bfr.Add_byte(Byte_ascii.Lt).Add_byte(Byte_ascii.Slash).Add(tag_name).Add_byte(Byte_ascii.Gt); // EX: "</ref>"
if (tag_is_ref) // <ref>; add <xtag_end> to handle nested refs; PAGE:en.w:Battle_of_Midway; DATE:2014-06-27
tmp.Add(Xtag_end_lhs).Add_int_pad_bgn(Byte_ascii.Num_0, 10, tag_idx).Add(Xtag_rhs);
bfr.Add_bfr_and_clear(tmp);
tmp_bfr.Add(Xtag_end_lhs).Add_int_pad_bgn(Byte_ascii.Num_0, 10, tag_idx).Add(Xtag_rhs);
bfr.Add_bfr_and_clear(tmp_bfr);
}
finally {tmp.Mkr_rls();}
finally {tmp_bfr.Mkr_rls();}
}
public static final int
Xtag_len = 27 // <xtag_bgn id='1234567890'/>
, Xtag_bgn = 14 // <xtag_bgn id='
, Id_len = 10
;
public static final byte[]
Xtag_bgn_lhs = Bry_.new_a7("<xtag_bgn id='")
, Xtag_end_lhs = Bry_.new_a7("<xtag_end id='")
, Xtag_rhs = Bry_.new_a7("'/>")
;
private static int tag__next_id = 0; // NOTE:must be app-level variable, not page-level, b/c pre-compiled templates can reserve tag #s; PAGE:de.s:Seite:NewtonPrincipien.djvu/465 DATE:2015-02-03
}
class Pfunc_tag_kv_bldr {
public int Key_bgn() {return key_bgn;} private int key_bgn;
public int KeyEnd() {return key_end;} private int key_end;
public Pfunc_tag_kv_bldr Key_rng_(int bgn, int end) {key_bgn = bgn; key_end = end; return this;}
public int Val_bgn() {return val_bgn;} private int val_bgn;
public int Val_end() {return val_end;} private int val_end;
public Pfunc_tag_kv_bldr Val_rng_(int bgn, int end) {val_bgn = bgn; val_end = end; return this;}
public boolean Valid() {
return key_bgn != -1 && key_end != -1 && val_bgn != -1 && val_end != -1 && key_bgn <= key_end && val_bgn <= val_end;
}
public void Clear() {
key_bgn = key_end = val_bgn = val_end = -1;
}
public static void Add_arg_as_html_atr(byte[] src, Bry_bfr tmp) {
synchronized (kv_bldr) {
ParseKeyVal(src, kv_bldr);
if (kv_bldr.Val_bgn() == -1) return; // ignore atrs with empty vals: EX:{{#tag:ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич DATE:2014-07-03
if (kv_bldr.Key_bgn() != -1)
tmp.Add(Bry_.Mid(src, kv_bldr.Key_bgn(), kv_bldr.KeyEnd()));
if (kv_bldr.Val_bgn() != -1) {
if (kv_bldr.Key_bgn() != -1) {
tmp.Add_byte(Byte_ascii.Eq);
}
tmp.Add_byte(Byte_ascii.Quote);
tmp.Add(Bry_.Mid(src, kv_bldr.Val_bgn(), kv_bldr.Val_end()));
tmp.Add_byte(Byte_ascii.Quote);
}
kv_bldr.Clear();
}
}
private static void ParseKeyVal(byte[] src, Pfunc_tag_kv_bldr kv_bldr) {
kv_bldr.Clear(); // do not forget to clear; DATE:2014-07-20
int itm_bgn = -1, itm_end = -1, src_len = src.length;
boolean mode_is_key = true;
for (int i = 0; i < src_len; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Eq:
if (mode_is_key) {
mode_is_key = false;
if (itm_end == -1) itm_end = i;
kv_bldr.Key_rng_(itm_bgn, itm_end);
itm_bgn = itm_end = -1;
}
break;
case Byte_ascii.Quote:
case Byte_ascii.Apos: // NOTE: quotes cannot be escaped; regx takes first two quotes; REF:MW:CoreParserFunctions.php|tagObj
if (itm_bgn == -1)
itm_bgn = i + 1;
else if (itm_end == -1)
itm_end = i;
break;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:// NOTE: do not need to handle ws, b/c argBldr will trim it EX: {{#tag|a| b = c }}; " b " and " c " are automatically trimmed
break;
default:
if (itm_bgn == -1) itm_bgn = i;
break;
}
}
if (itm_end == -1) itm_end = src_len;
kv_bldr.Val_rng_(itm_bgn, itm_end);
}
private static Pfunc_tag_kv_bldr kv_bldr = new Pfunc_tag_kv_bldr();
public static final int
Xtag_len = 27 // <xtag_bgn id='1234567890'/>
, Xtag_bgn = 14 // <xtag_bgn id='
, Id_len = 10
;
private static final Object next_id_lock = new Object();
private static int next_id_val = 0;// NOTE:must be app-level variable, not page-level, b/c pre-compiled templates can reserve tag #s; PAGE:de.s:Seite:NewtonPrincipien.djvu/465 DATE:2015-02-03
}

View 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.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
class Pfunc_tag_kvp_wtr {
private int key_bgn, key_end;
private int val_bgn, val_end;
public void Write_as_html_atr(Bry_bfr tmp, byte[] kvp_bry) {
Parse(kvp_bry);
// write as html
if (val_bgn == -1) return; // ignore atrs with empty vals: EX:{{#tag:ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич DATE:2014-07-03
if (key_bgn != -1)
tmp.Add(Bry_.Mid(kvp_bry, key_bgn, key_end));
if (val_bgn != -1) {
if (key_bgn != -1)
tmp.Add_byte(Byte_ascii.Eq);
tmp.Add_byte(Byte_ascii.Quote);
tmp.Add(Bry_.Mid(kvp_bry, val_bgn, val_end));
tmp.Add_byte(Byte_ascii.Quote);
}
}
private void Parse(byte[] src) {
this.key_bgn = this.key_end = this.val_bgn = this.val_end = -1; // NOTE: must clear; DATE:2014-07-20
int itm_bgn = -1, itm_end = -1, src_len = src.length;
byte quote_byte = Byte_ascii.Null;
boolean mode_is_key = true;
for (int i = 0; i < src_len; ++i) {
byte b = src[i];
switch (b) {
case Byte_ascii.Eq:
if (mode_is_key) {
mode_is_key = false;
if (itm_end == -1) itm_end = i;
this.key_bgn = itm_bgn;
this.key_end = itm_end;
itm_bgn = itm_end = -1;
}
break;
// quote-char encountered ...
// NOTE: quotes cannot be escaped; also, in case of multiple quotes (a="b"c") regx uses first two quotes; REF:MW:CoreParserFunctions.php|tagObj
case Byte_ascii.Quote:
case Byte_ascii.Apos:
if (itm_bgn == -1) { // ... quote hasn't started; start quote
itm_bgn = i + 1;
quote_byte = b;
}
else if (itm_end == -1 // ... quote has started and quote hasn't ended; note that this ends quote immediately; EX: 'id="a"b"' -> 'id=a' x> 'id=a"b'
&& b == quote_byte) // handle alternating quotes; EX: id="a'b" -> id=a'b x> id=a; PAGE:en.s:The_formative_period_in_Colby%27s_history; DATE:2016-06-23
itm_end = i;
break;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:// NOTE: do not need to handle ws, b/c argBldr will trim it EX: {{#tag|a| b = c }}; " b " and " c " are automatically trimmed
break;
default:
if (itm_bgn == -1) itm_bgn = i;
break;
}
}
if (itm_end == -1) itm_end = src_len;
this.val_bgn = itm_bgn;
this.val_end = itm_end;
}
}

View File

@@ -18,17 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_tag_tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {fxt.Test_html_full_str("{{#tag:pre|a|id=b|style=c}}" , "<pre id=\"b\" style=\"c\">a</pre>");}
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {fxt.Test_html_full_str("{{#tag:pre|a|id=b|style=c}}" , "<pre id=\"b\" style=\"c\">a</pre>");}
@Test public void Atr2_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=b|}}" , "<pre id=\"b\">a</pre>");} // see {{Reflist|colwidth=30em}} -> <ref group=a>a</ref>{{#tag:references||group=a|}} -> "<references group=a/>"
@Test public void Val_apos() {fxt.Test_html_full_str("{{#tag:pre|a|id='b'}}" , "<pre id=\"b\">a</pre>");}
@Test public void Val_quote() {fxt.Test_html_full_str("{{#tag:pre|a|id=\"b\"}}" , "<pre id=\"b\">a</pre>");}
@Test public void Val_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=}}" , "<pre>a</pre>");} // PURPOSE: ignore atrs with no val; EX:{{#ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич; DATE:2014-07-03
@Test public void Val_quote_w_apos() {fxt.Test_html_full_str("{{#tag:pre|c|id=\"a'b\"}}" , "<pre id=\"a.27b\">c</pre>");} // PURPOSE.fix: tag was not handling apos within quotes; PAGE:en.s:The_formative_period_in_Colby%27s_history DATE:2016-06-23
@Test public void Tmpl() {fxt.Test_html_full_str("{{#tag:pre|a|{{#switch:a|a=id}}=c}}" , "<pre id=\"c\">a</pre>");} // PURPOSE: args must be evaluated
@Test public void Ws_all() {fxt.Test_html_full_str("{{#tag:pre|a| id = b }}" , "<pre id=\"b\">a</pre>");}
@Test public void Ws_quoted() {fxt.Test_html_full_str("{{#tag:pre|a| id = ' b ' }}" , "<pre id=\"_b_\">a</pre>");}
@Test public void Err_bad_key() {fxt.Test_html_full_str("{{#tag:pre|a|id=val|b}}" , "<pre id=\"val\">a</pre>");} // PURPOSE: b was failing b/c id was larger and key_end set to 4 (whereas b was len=1)
// @Test public void Missing_val() {fxt.ini_Msg(Mwl_tag_rsc.Instance.Invalid).Test_parse_tmpl_str_test("{{#tag:pre|a|id=}}" , "{{test}}" , "");} // see {{Reflist|colwidth=30em}} -> <ref group=a>a</ref>{{#tag:references||group=}} -> ""
@Test public void Atr2_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=b|}}" , "<pre id=\"b\">a</pre>");} // see {{Reflist|colwidth=30em}} -> <ref group=a>a</ref>{{#tag:references||group=a|}} -> "<references group=a/>"
@Test public void Val_apos() {fxt.Test_html_full_str("{{#tag:pre|a|id='b'}}" , "<pre id=\"b\">a</pre>");}
@Test public void Val_quote() {fxt.Test_html_full_str("{{#tag:pre|a|id=\"b\"}}" , "<pre id=\"b\">a</pre>");}
@Test public void Val_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=}}" , "<pre>a</pre>");} // PURPOSE: ignore atrs with no val; EX:{{#ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич; DATE:2014-07-03
@Test public void Tmpl() {fxt.Test_html_full_str("{{#tag:pre|a|{{#switch:a|a=id}}=c}}" , "<pre id=\"c\">a</pre>");} // PURPOSE: args must be evaluated
@Test public void Ws_all() {fxt.Test_html_full_str("{{#tag:pre|a| id = b }}" , "<pre id=\"b\">a</pre>");}
@Test public void Ws_quoted() {fxt.Test_html_full_str("{{#tag:pre|a| id = ' b ' }}" , "<pre id=\"_b_\">a</pre>");}
@Test public void Err_bad_key() {fxt.Test_html_full_str("{{#tag:pre|a|id=val|b}}" , "<pre id=\"val\">a</pre>");} // PURPOSE: b was failing b/c id was larger and key_end set to 4 (whereas b was len=1)
// @Test public void Err() {
// fxt.Test_parse_tmpl_str_test("{{#tag:ref|George Robertson announced in January 2003 that he would be stepping down in December.<ref> {{cite news|title =NATO Secretary General to Leave His Post in December After 4 Years |first = Craig | last = Smith | work = The New York Times | date = January 23, 2003| url = http://www.nytimes.com/2003/01/23/world/nato-secretary-general-to-leave-his-post-in-december-after-4-years.html?scp=2&sq=lord+robertson&st=nyt|accessdate = 2009-03-29}}</ref> Jaap de Hoop Scheffer was selected as his successor, but could not assume the office until January 2004 because of his commitment in the Dutch Parliament.<ref> {{cite news|title = Jaap de Hoop Scheffer | work = Newsmakers | issue = 1 | publisher = Thomson Gale | date = January 1, 2005}}</ref> Robertson was asked to extend his term until Scheffer was ready, but declined, so Minuto-Rizzo, the Deputy Secretary General, took over in the interim.<ref name =\"ncsd\" /> |group=N|}}"
// , "{{test}}" , "<pre id=\" b \">a</pre>");}

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.xtns.pfuncs.ttls; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_anchorencode_tst {
private final Xop_fxt fxt = new Xop_fxt();
private final Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Lnke() {fxt.Test_parse_tmpl_str_test("{{anchorencode:[irc://a b c]}}" , "{{test}}" , "b_c");}
@Test public void Apos_bold() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a ''b'' c}}" , "{{test}}" , "a_b_c");}
@@ -30,6 +30,6 @@ public class Pfunc_anchorencode_tst {
@Test public void Html_ncr() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a &#34; b}}" , "{{test}}" , "a_.22_b");}
@Test public void Html_ref() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a &quot; b}}" , "{{test}}" , "a_.22_b");}
@Test public void Tmpl_missing_basic() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{a}}}}" , "{{test}}" , "Template:a");}
@Test public void Tmpl_missing_colon() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{:a}}}}" , "{{test}}" , "Template:A");}
@Test public void Tmpl_missing_colon() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{:a}}}}" , "{{test}}" , "a");} // NOTE: changed from "Template:A" to "a"; DATE:2016-06-24
@Test public void Lnki_literal() {fxt.Test_parse_tmpl_str_test("{{anchorencode:[[:a]]}}" , "{{test}}" , "a");}
}