1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2014-06-30 00:04:32 -04:00
parent 85594d3cdd
commit bae88e739c
2482 changed files with 198730 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
/*
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 Xop_tblw_lxr implements Xop_lxr {
public byte Lxr_tid() {return Xop_lxr_.Tid_tblw;}
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 rv = Handle_bang(wlxr_type, ctx, ctx.Tkn_mkr(), root, src, src_len, bgn_pos, cur_pos);
if (rv != Continue) return rv;
rv = Handle_lnki(wlxr_type, ctx, ctx.Tkn_mkr(), root, src, src_len, bgn_pos, cur_pos);
if (rv != Continue) return rv;
return ctx.Tblw().Make_tkn_bgn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, false, wlxr_type, Xop_tblw_wkr.Called_from_general, -1, -1);
}
public static final int Continue = -2; // -2 b/c -1 used by Called_from_pre
public static int Handle_bang(int wlxr_type, Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
// standalone "!" should be ignored if no tblw present; EX: "a b! c" should not trigger ! for header
switch (wlxr_type) {
case Xop_tblw_wkr.Tblw_type_th: // \n!
case Xop_tblw_wkr.Tblw_type_th2: // !!
case Xop_tblw_wkr.Tblw_type_td: // \n|
Xop_tkn_itm owner_tblw_tb = ctx.Stack_get_typ(Xop_tkn_itm_.Tid_tblw_tb); // check entire stack for tblw; DATE:2014-03-11
if ( owner_tblw_tb == null // no tblw in stack; highly probably that current sequence is not tblw tkn
|| ctx.Cur_tkn_tid() == Xop_tkn_itm_.Tid_lnki // cur tid is lnki; PAGE:en.w:Pink_(singer); DATE:2014-06-25
) {
int lnki_pos = ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_lnki);
if (lnki_pos != Xop_ctx.Stack_not_found && wlxr_type == Xop_tblw_wkr.Tblw_type_td) {// lnki present;// NOTE: added Xop_tblw_wkr.Tblw_type_td b/c th should not apply when tkn_mkr.Pipe() is called below; DATE:2013-04-24
Xop_tkn_itm lnki_tkn = ctx.Stack_pop_til(root, src, lnki_pos, false, bgn_pos, cur_pos); // pop any intervening nodes until lnki
ctx.Stack_add(lnki_tkn); // push lnki back onto stack; TODO: combine these 2 lines into 1
// NOTE: this is a "\n|" inside a [[ ]]; must create two tokens for lnki to build correctly;
ctx.Subs_add(root, tkn_mkr.NewLine(bgn_pos, bgn_pos + 1, Xop_nl_tkn.Tid_char, 1));
return Xop_pipe_lxr._.Make_tkn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos); // NOTE: need to call pipe_lxr in order to invalidate if lnki; DATE:2014-06-06
}
else { // \n| or \n! but no tbl
if ( bgn_pos != Xop_parser_.Doc_bgn_bos // avoid ! at BOS
&& src[bgn_pos] == Byte_ascii.NewLine) // handle "!" etc.
return Xop_tblw_wkr.Handle_false_tblw_match(ctx, root, src, bgn_pos, cur_pos, tkn_mkr.Txt(bgn_pos + 1, cur_pos), true); // +1 to ignore \n of "\n!", "\n!!", "\n|"; DATE:2014-02-19
else // handle "!!" only
return ctx.Lxr_make_txt_(cur_pos);
}
}
break;
}
return Continue;
}
public static int Handle_lnki(int wlxr_type, 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 last_tkn = ctx.Stack_get_last();
if ( last_tkn != null
&& last_tkn.Tkn_tid() == Xop_tkn_itm_.Tid_lnki) {
Xop_lnki_tkn lnki = (Xop_lnki_tkn)last_tkn;
if ( lnki.Pipe_count_is_zero()) { // 1st pipe; EX: [[A\n|+B]]
boolean invalidate = false;
switch (wlxr_type) { // tblw found; check if in lnki and validate ttl; DATE:2014-03-29
case Xop_tblw_wkr.Tblw_type_tb: // \n{|
case Xop_tblw_wkr.Tblw_type_tc: // \n|+
case Xop_tblw_wkr.Tblw_type_tr: // \n|-
case Xop_tblw_wkr.Tblw_type_te: // \n|}
invalidate = true; // always invalidate
break;
case Xop_tblw_wkr.Tblw_type_td2: // ||; EX: [[A||B]]
if (ctx.Tid_is_image_map()) { // if in ImageMap, then treat "||" as "pipe" (not "pipe_text"); note that outer tbl is ignored; EX:w:United_States_presidential_election,_1992
ctx.Subs_add(root, tkn_mkr.Pipe(bgn_pos, cur_pos));
return cur_pos;
}
invalidate = !Xop_lnki_wkr_.Parse_ttl(ctx, src, lnki, bgn_pos); // check if invalid; EX: "[[A<||]]" would be invalid b/c of <
if (!invalidate) { // "valid" title, but "||" must be converted to pipe inside lnki; EX:cs.w:Main_Page; DATE:2014-05-09
ctx.Subs_add(root, tkn_mkr.Pipe(bgn_pos, cur_pos)); // NOTE: technically need to check if pipe or pipe_text; for now, do pipe as pipe_text could break [[File:A.png||20px]]; DATE:2014-05-06
return cur_pos;
}
break;
}
if (invalidate) {
ctx.Stack_pop_last();
return Xop_lnki_wkr_.Invalidate_lnki(ctx, src, root, lnki, bgn_pos);
}
}
else { // nth pipe; no need to check for invalidate
switch (wlxr_type) {
case Xop_tblw_wkr.Tblw_type_tc: // \n|+
case Xop_tblw_wkr.Tblw_type_tr: // \n|-
case Xop_tblw_wkr.Tblw_type_td: // \n|
//case Xop_tblw_wkr.Tblw_type_te: // |} // NOTE: ignore "|}"; needed for incomplete lnkis; EX: |[[a\n|}; EX:w:Wikipedia:Changing_attribution_for_an_edit; DATE:2014-03-16
ctx.Subs_add(root, tkn_mkr.NewLine(bgn_pos, bgn_pos + 1, Xop_nl_tkn.Tid_char, 1));
ctx.Subs_add(root, tkn_mkr.Pipe(bgn_pos + 1, bgn_pos + 2));
return bgn_pos + 2; // +2 to skip "\n|", but still look at 3rd char; ("+", "-", or "}")
case Xop_tblw_wkr.Tblw_type_td2: // ||
ctx.Subs_add(root, tkn_mkr.Pipe(bgn_pos, cur_pos));
return cur_pos;
case Xop_tblw_wkr.Tblw_type_th2: // !!
case Xop_tblw_wkr.Tblw_type_th: // !
ctx.Subs_add(root, tkn_mkr.Txt(bgn_pos, cur_pos)); // NOTE: cur_pos should handle ! and !!
return cur_pos;
}
}
}
return Continue;
}
public Xop_tblw_lxr(byte wlxr_type) {this.wlxr_type = wlxr_type;} private byte wlxr_type;
public static final Xop_tblw_lxr _ = new Xop_tblw_lxr(); Xop_tblw_lxr() {}
public void Init_by_wiki(Xow_wiki wiki, ByteTrieMgr_fast core_trie) {
core_trie.Add(Hook_tb, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_tb));
core_trie.Add(Hook_te, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_te));
core_trie.Add(Hook_tr, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_tr));
core_trie.Add(Hook_td, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_td));
core_trie.Add(Hook_th, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_th));
core_trie.Add(Hook_tc, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_tc));
core_trie.Add(Hook_td2, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_td2));
core_trie.Add(Hook_th2, new Xop_tblw_lxr(Xop_tblw_wkr.Tblw_type_th2));
}
public void Init_by_lang(Xol_lang lang, ByteTrieMgr_fast core_trie) {}
public static final byte[] Hook_tb = Bry_.new_ascii_("\n{|"), Hook_te = Bry_.new_ascii_("\n|}"), Hook_tr = Bry_.new_ascii_("\n|-")
, Hook_td = Bry_.new_ascii_("\n|"), Hook_th = Bry_.new_ascii_("\n!"), Hook_tc = Bry_.new_ascii_("\n|+")
, Hook_td2 = Bry_.new_ascii_("||"), Hook_th2 = Bry_.new_ascii_("!!");
}

View File

@@ -0,0 +1,110 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
public class Xop_tblw_lxr_ws {
public static int Make(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, byte wlxr_type, boolean called_from_pre) {
int rv = Xop_tblw_lxr.Handle_bang(wlxr_type, ctx, ctx.Tkn_mkr(), root, src, src_len, bgn_pos, cur_pos);
if (rv != Xop_tblw_lxr.Continue) return rv;
rv = Xop_tblw_lxr.Handle_lnki(wlxr_type, ctx, ctx.Tkn_mkr(), root, src, src_len, bgn_pos, cur_pos);
if (rv != Xop_tblw_lxr.Continue) return rv;
if (!called_from_pre) { // skip if called from pre, else will return text, since pre_lxr has not created \n tkn yet; EX: "\n ! a"; DATE:2014-02-14
// find first non-ws tkn; check if nl or para
int root_subs_len = root.Subs_len();
int tkn_idx = root_subs_len - 1;
boolean loop = true, nl_found = false;
while (loop) {
if (tkn_idx < 0) break;
Xop_tkn_itm tkn = root.Subs_get(tkn_idx);
switch (tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab: // ws: keep moving backwards
tkn_idx--;
break;
case Xop_tkn_itm_.Tid_newLine:
case Xop_tkn_itm_.Tid_para:
loop = false;
nl_found = true;
break;
default:
loop = false;
break;
}
}
if (tkn_idx == -1) { // bos reached; all tkns are ws;
if (wlxr_type == Xop_tblw_wkr.Tblw_type_tb) { // wlxr_type is {|;
root.Subs_del_after(0); // trim
return ctx.Tblw().Make_tkn_bgn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, false, wlxr_type, Xop_tblw_wkr.Called_from_general, -1, -1); // process {|
}
else // wlxr_type is something else, but invalid since no containing {|
return ctx.Lxr_make_txt_(cur_pos);
}
if (!nl_found && wlxr_type == Xop_tblw_wkr.Tblw_type_td) // | but no nl; return control to pipe_lxr for further processing
return Tblw_ws_cell_pipe;
if (nl_found)
root.Subs_del_after(tkn_idx);
}
return ctx.Tblw().Make_tkn_bgn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, false, wlxr_type, Xop_tblw_wkr.Called_from_general, -1, -1);
}
public static final byte[] Hook_tb = Bry_.new_ascii_("{|"), Hook_te = Bry_.new_ascii_("|}"), Hook_tr = Bry_.new_ascii_("|-")
, Hook_th = Bry_.new_ascii_("!"), Hook_tc = Bry_.new_ascii_("|+");
public static final int Tblw_ws_cell_pipe = -1;
}
class Xop_tblw_ws_itm {
public byte Tblw_type() {return tblw_type;} private byte tblw_type;
public int Hook_len() {return hook_len;} private int hook_len;
public Xop_tblw_ws_itm(byte tblw_type, int hook_len) {this.tblw_type = tblw_type; this.hook_len = hook_len;}
public static final byte Type_tb = Xop_tblw_wkr.Tblw_type_tb, Type_te = Xop_tblw_wkr.Tblw_type_te, Type_tr = Xop_tblw_wkr.Tblw_type_tr, Type_tc = Xop_tblw_wkr.Tblw_type_tc
, Type_th = Xop_tblw_wkr.Tblw_type_th, Type_td = Xop_tblw_wkr.Tblw_type_td, Type_nl = 16, Type_xnde = 17;
public static ByteTrieMgr_slim trie_() {// MW.REF:Parser.php|doBlockLevels
ByteTrieMgr_slim rv = ByteTrieMgr_slim.cs_();
trie_itm(rv, Type_tb, Xop_tblw_lxr_ws.Hook_tb);
trie_itm(rv, Type_te, Xop_tblw_lxr_ws.Hook_te);
trie_itm(rv, Type_tr, Xop_tblw_lxr_ws.Hook_tr);
trie_itm(rv, Type_th, Xop_tblw_lxr_ws.Hook_th);
trie_itm(rv, Type_tc, Xop_tblw_lxr_ws.Hook_tc);
trie_itm(rv, Type_td, Bry_.bytes_(Byte_ascii.Pipe));
trie_itm(rv, Type_nl, Bry_.bytes_(Byte_ascii.NewLine));
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_table);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_tr);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_td);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_th);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_blockquote);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h1);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h2);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h3);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h4);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h5);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_h6);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_pre);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_p);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_div);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_hr);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_li);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_ul);
trie_itm_xnde(rv, Xop_xnde_tag_.Tag_ol);
return rv;
}
private static void trie_itm(ByteTrieMgr_slim trie, byte type, byte[] bry) {trie.Add(bry, new Xop_tblw_ws_itm(type, bry.length));}
private static void trie_itm_xnde(ByteTrieMgr_slim trie, Xop_xnde_tag tag) {
byte[] tag_name = tag.Name_bry();
int tag_name_len = tag_name.length;
trie.Add(Bry_.Add(Bry_xnde_bgn, tag_name), new Xop_tblw_ws_itm(Type_xnde, tag_name_len));
trie.Add(Bry_.Add(Bry_xnde_end, tag_name), new Xop_tblw_ws_itm(Type_xnde, tag_name_len + 1));
} static byte[] Bry_xnde_bgn = new byte[] {Byte_ascii.Lt, Byte_ascii.Slash}, Bry_xnde_end = new byte[] {Byte_ascii.Lt};
}

View 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 Xop_tblw_tb_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
public Xop_tblw_tb_tkn(int bgn, int end, boolean tblw_xml, boolean auto_created) {
this.tblw_xml = tblw_xml; this.Tkn_ini_pos(false, bgn, end);
if (auto_created) // auto-created should be marked as having no attributes, else text may get gobbled up incorrectly; EX:Paris#Demographics DATE:2014-03-18
atrs_bgn = atrs_end = bgn;
}
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tblw_tb;}
public int Tblw_tid() {return Xop_xnde_tag_.Tid_table;}
public int Atrs_bgn() {return atrs_bgn;} private int atrs_bgn = Xop_tblw_wkr.Atrs_null;
public int Atrs_end() {return atrs_end;} private int atrs_end = -1;
public void Atrs_rng_set(int bgn, int end) {this.atrs_bgn = bgn; this.atrs_end = end;}
public Xop_xatr_itm[] Atrs_ary() {return atrs_ary;} public Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v) {atrs_ary = v; return this;} private Xop_xatr_itm[] atrs_ary;
public boolean Tblw_xml() {return tblw_xml;} private boolean tblw_xml;
public void Tblw_xml_(boolean v) {tblw_xml = v;}
public int Tblw_subs_len() {return tblw_subs_len;} public void Tblw_subs_len_add_() {++tblw_subs_len;} private int tblw_subs_len;
public int Caption_count() {return caption_count;} public Xop_tblw_tb_tkn Caption_count_(int v) {caption_count = v; return this;} private int caption_count = 0;
public Xop_tblw_tb_tkn Caption_count_add_1() {++caption_count; return this;}
public Xop_tblw_tb_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
}

View 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.*;
public class Xop_tblw_tc_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tblw_tc;}
public int Tblw_tid() {return Xop_xnde_tag_.Tid_caption;}
public int Atrs_bgn() {return atrs_bgn;} private int atrs_bgn = Xop_tblw_wkr.Atrs_null;
public int Atrs_end() {return atrs_end;} private int atrs_end = -1;
public void Atrs_rng_set(int bgn, int end) {this.atrs_bgn = bgn; this.atrs_end = end;}
public Xop_xatr_itm[] Atrs_ary() {return atrs_ary;} public Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v) {atrs_ary = v; return this;} private Xop_xatr_itm[] atrs_ary;
public boolean Tblw_xml() {return tblw_xml;} private boolean tblw_xml;
public int Tblw_subs_len() {return tblw_subs_len;} public void Tblw_subs_len_add_() {++tblw_subs_len;} private int tblw_subs_len;
public Xop_tblw_tc_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
public Xop_tblw_tc_tkn(int bgn, int end, boolean tblw_xml) {this.tblw_xml = tblw_xml; this.Tkn_ini_pos(false, bgn, end);}
}

View 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.*;
public class Xop_tblw_td_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tblw_td;}
public int Tblw_tid() {return Xop_xnde_tag_.Tid_td;}
public int Atrs_bgn() {return atrs_bgn;} private int atrs_bgn = Xop_tblw_wkr.Atrs_null;
public int Atrs_end() {return atrs_end;} private int atrs_end = -1;
public void Atrs_rng_set(int bgn, int end) {this.atrs_bgn = bgn; this.atrs_end = end;}
public Xop_xatr_itm[] Atrs_ary() {return atrs_ary;} public Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v) {atrs_ary = v; return this;} private Xop_xatr_itm[] atrs_ary;
public boolean Tblw_xml() {return tblw_xml;} private boolean tblw_xml;
public int Tblw_subs_len() {return tblw_subs_len;} public void Tblw_subs_len_add_() {++tblw_subs_len;} private int tblw_subs_len;
public Xop_tblw_td_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
public Xop_tblw_td_tkn(int bgn, int end, boolean tblw_xml) {this.tblw_xml = tblw_xml; this.Tkn_ini_pos(false, bgn, end);}
}

View 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.*;
public class Xop_tblw_th_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tblw_th;}
public int Tblw_tid() {return Xop_xnde_tag_.Tid_th;}
public int Atrs_bgn() {return atrs_bgn;} private int atrs_bgn = Xop_tblw_wkr.Atrs_null;
public int Atrs_end() {return atrs_end;} private int atrs_end = -1;
public void Atrs_rng_set(int bgn, int end) {this.atrs_bgn = bgn; this.atrs_end = end;}
public Xop_xatr_itm[] Atrs_ary() {return atrs_ary;} public Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v) {atrs_ary = v; return this;} private Xop_xatr_itm[] atrs_ary;
public boolean Tblw_xml() {return tblw_xml;} private boolean tblw_xml;
public int Tblw_subs_len() {return tblw_subs_len;} public void Tblw_subs_len_add_() {++tblw_subs_len;} private int tblw_subs_len;
public Xop_tblw_th_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
public Xop_tblw_th_tkn(int bgn, int end, boolean tblw_xml) {this.tblw_xml = tblw_xml; this.Tkn_ini_pos(false, bgn, end);}
}

View 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 interface Xop_tblw_tkn extends Xop_tkn_itm {
int Tblw_tid();
boolean Tblw_xml();
int Tblw_subs_len(); void Tblw_subs_len_add_();
int Atrs_bgn();
int Atrs_end();
void Atrs_rng_set(int bgn, int end);
Xop_xatr_itm[] Atrs_ary(); Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v);
}

View 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 class Xop_tblw_tr_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
public Xop_tblw_tr_tkn(int bgn, int end, boolean tblw_xml, boolean auto_created) {
this.tblw_xml = tblw_xml; this.Tkn_ini_pos(false, bgn, end);
if (auto_created) // auto-created should be marked as having no attributes, else text may get gobbled up incorrectly; EX:Paris#Demographics DATE:2014-03-18
atrs_bgn = atrs_end = bgn;
}
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_tblw_tr;}
public int Tblw_tid() {return Xop_xnde_tag_.Tid_tr;}
public int Atrs_bgn() {return atrs_bgn;} private int atrs_bgn = Xop_tblw_wkr.Atrs_null;
public int Atrs_end() {return atrs_end;} private int atrs_end = -1;
public void Atrs_rng_set(int bgn, int end) {this.atrs_bgn = bgn; this.atrs_end = end;}
public Xop_xatr_itm[] Atrs_ary() {return atrs_ary;} public Xop_tblw_tkn Atrs_ary_as_tblw_(Xop_xatr_itm[] v) {atrs_ary = v; return this;} private Xop_xatr_itm[] atrs_ary;
public boolean Tblw_xml() {return tblw_xml;} private boolean tblw_xml;
public int Tblw_subs_len() {return tblw_subs_len;} public void Tblw_subs_len_add_() {++tblw_subs_len;} private int tblw_subs_len;
public Xop_tblw_tr_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
}

View File

@@ -0,0 +1,531 @@
/*
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_tblw_wkr implements Xop_ctx_wkr {
private int tblw_te_ignore_count = 0;
public boolean Cell_pipe_seen() {return cell_pipe_seen;} public Xop_tblw_wkr Cell_pipe_seen_(boolean v) {cell_pipe_seen = v; return this;} private boolean cell_pipe_seen; // status of 1st cell pipe; EX: \n| a | b | c || -> flag pipe between a and b but ignore b and c
public void Ctor_ctx(Xop_ctx ctx) {}
public void Page_bgn(Xop_ctx ctx, Xop_root_tkn root) {cell_pipe_seen = false; tblw_te_ignore_count = 0;}
public void Page_end(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int src_len) {}
public void AutoClose(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, Xop_tkn_itm tkn) {
tkn.Subs_move(root);
tkn.Src_end_(cur_pos);
}
public static final byte Called_from_general = 0, Called_from_list = 1, Called_from_pre = 2;
public int Make_tkn_bgn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, boolean tbl_is_xml, byte wlxr_type, byte called_from, int atrs_bgn, int atrs_end) {// REF.MW: Parser|doTableStuff
if (bgn_pos == Xop_parser_.Doc_bgn_bos) {
bgn_pos = 0; // do not allow -1 pos
}
int list_tkn_idx = ctx.Stack_idx_find_but_stop_at_tbl(Xop_tkn_itm_.Tid_list);
if ( list_tkn_idx != -1 // list is in effect; DATE:2014-05-05
&& !tbl_is_xml // tbl is wiki-syntax; ie: auto-close if "{|" but do not close if "<table>"; DATE:2014-02-05
&& called_from != Called_from_list // do not close if called from list; EX: consider "{|"; "* a {|" is called from list_wkr, and should not close; "* a\n{|" is called from tblw_lxr and should close; DATE:2014-02-14
) {
if (wlxr_type == Tblw_type_td2) { // if in list, treat "||" as lnki, not tblw; EX: es.d:casa; es.d:tres; DATE:2014-02-15
ctx.Subs_add(root, ctx.Tkn_mkr().Pipe(bgn_pos, cur_pos)); // NOTE: technically need to check if pipe or pipe_text; for now, do pipe as pipe_text could break [[File:A.png||20px]]; DATE:2014-05-06
return cur_pos;
}
else {
Xop_list_wkr_.Close_list_if_present(ctx, root, src, bgn_pos, cur_pos);
}
}
if (ctx.Apos().Stack_len() > 0) // open apos; note that apos keeps its own stack, as they are not "structural" (not sure about this)
ctx.Apos().EndFrame(ctx, root, src, cur_pos, true); // close it
Xop_tblw_tkn prv_tkn = ctx.Stack_get_tbl();
if ( prv_tkn == null // prv_tkn not found; i.e.: no earlier "{|" or "<table>"
|| ( ctx.Stack_get_tblw_tb() == null // no {| on stack; DATE:2014-05-05
&& !tbl_is_xml // and cur is tblw (i.e.: not xnde); DATE:2014-05-05
)
) {
switch (wlxr_type) {
case Tblw_type_tb: // "{|";
break; // noop; by definition "{|" does not need to have a previous "{|"
case Tblw_type_td: // "|"
case Tblw_type_td2: // "||"
if (tbl_is_xml) { // <td> should automatically add <table><tr>
ctx.Subs_add_and_stack_tblw(root, prv_tkn, tkn_mkr.Tblw_tb(bgn_pos, bgn_pos, tbl_is_xml, true));
prv_tkn = tkn_mkr.Tblw_tr(bgn_pos, bgn_pos, tbl_is_xml, true);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, prv_tkn);
break;
}
else {
if (called_from == Called_from_pre)
return -1;
else { // DATE:2014-02-19; NOTE: do not add nl if ||; DATE:2014-04-14
if (wlxr_type == Tblw_type_td) { // "\n|"
ctx.Subs_add(root, ctx.Tkn_mkr().NewLine(bgn_pos, bgn_pos + 1, Xop_nl_tkn.Tid_char, 1));
ctx.Subs_add(root, ctx.Tkn_mkr().Pipe(bgn_pos + 1, cur_pos));
}
else // "||"
ctx.Subs_add(root, ctx.Tkn_mkr().Pipe(bgn_pos, cur_pos));
return cur_pos;
}
}
case Tblw_type_th: // "!"
case Tblw_type_th2: // "!!"
case Tblw_type_tc: // "|+"
case Tblw_type_tr: // "|-"
if (tbl_is_xml) { // <tr> should automatically add <table>; DATE:2014-02-13
prv_tkn = tkn_mkr.Tblw_tb(bgn_pos, bgn_pos, tbl_is_xml, true);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, prv_tkn);
break;
}
else {
if (called_from == Called_from_pre)
return -1;
else
return Xop_tblw_wkr.Handle_false_tblw_match(ctx, root, src, bgn_pos, cur_pos, ctx.Tkn_mkr().Txt(bgn_pos + 1, cur_pos), true); // DATE:2014-02-19
}
case Tblw_type_te: // "|}"
if (tblw_te_ignore_count > 0) {
--tblw_te_ignore_count;
return cur_pos;
}
else {
if (called_from == Called_from_pre)
return -1;
else
return Xop_tblw_wkr.Handle_false_tblw_match(ctx, root, src, bgn_pos, cur_pos, tkn_mkr.Txt(bgn_pos + 1, cur_pos), true); // +1 to skip "\n" in "\n|}" (don't convert \n to text); DATE:2014-02-19
}
default: throw Err_.unhandled(wlxr_type);
}
}
int prv_tid = prv_tkn == null ? Xop_tkn_itm_.Tid_null : prv_tkn.Tkn_tid();
if (prv_tkn != null && !prv_tkn.Tblw_xml()) { // note that this logic is same as Atrs_close; repeated here for "perf"
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_tb: case Xop_tkn_itm_.Tid_tblw_tr:
Atrs_make(ctx, src, root, this, prv_tkn);
break;
}
}
if (wlxr_type == Tblw_type_te)
return Make_tkn_end(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, Xop_tkn_itm_.Tid_tblw_te, wlxr_type, prv_tkn, prv_tid, tbl_is_xml);
else
return Make_tkn_bgn_tblw(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, wlxr_type, tbl_is_xml, atrs_bgn, atrs_end, prv_tkn, prv_tid);
}
private int Make_tkn_bgn_tblw(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, byte wlxr_type, boolean tbl_is_xml, int atrs_bgn, int atrs_end, Xop_tblw_tkn prv_tkn, int prv_tid) {
if (wlxr_type != Tblw_type_tb) // NOTE: do not ignore ws if {|; will cause strange behavior with pre; DATE:2013-02-12
Ignore_ws(ctx, root);
Xop_tblw_tkn new_tkn = null;
switch (wlxr_type) {
case Tblw_type_tb: // <table>
boolean ignore_prv = false, auto_create = false;
switch (prv_tid) {
case Xop_tkn_itm_.Tid_null: // noop; <table>
break;
case Xop_tkn_itm_.Tid_tblw_td: // noop; <td><table>
case Xop_tkn_itm_.Tid_tblw_th: // noop; <th><table>
break;
case Xop_tkn_itm_.Tid_tblw_tb: // fix; <table><table> -> <table>; ignore current table; DATE:2014-02-02
if (prv_tkn.Tblw_xml()) { // fix: <table><table> -> <table>; earlier tbl is xnde; ignore; EX:en.b:Wikibooks:Featured books; DATE:2014-02-08
((Xop_tblw_tb_tkn)prv_tkn).Tblw_xml_(false); // if <table>{|, discard <table>, but mark {| as <table>; needed to handle <table>\n{|\n| where "|" must be treated as tblw dlm; DATE:2014-02-22
ignore_prv = true;
}
// else // fix: <table><table> -> <table><tr><td><table>; earlier tbl is tblw; auto-create; EX:it.w:Main_Page; DATE:2014-02-08; TIDY:depend on tidy to fix; PAGE: it.w:Portal:Animali; DATE:2014-05-31
// auto_create = true;
break;
case Xop_tkn_itm_.Tid_tblw_tr: // noop: <table><tr><table> -> <table><tr><td><table>; should probably auto-create td, but MW does not; DATE:2014-03-18
case Xop_tkn_itm_.Tid_tblw_tc: // noop; <caption><table>; TIDY:was <caption></caption><tr><td><table>; PAGE: es.w:Savilla DATE:2014-06-29
break;
}
if (ignore_prv) {
ctx.Subs_add(root, tkn_mkr.Ignore(bgn_pos, cur_pos, Xop_ignore_tkn.Ignore_tid_htmlTidy_tblw));
++tblw_te_ignore_count;
cur_pos = Bry_finder.Find_fwd_until(src, cur_pos, src_len, Byte_ascii.NewLine); // NOTE: minor hack; this tblw tkn will be ignored, so ignore any of its attributes as well; gobble up all chars till nl. see: if two consecutive tbs, ignore attributes on 2nd; en.wikibooks.org/wiki/Wikibooks:Featured books
return cur_pos;
}
if (auto_create) {
ctx.Subs_add_and_stack_tblw(root, prv_tkn, tkn_mkr.Tblw_tr(bgn_pos, bgn_pos, tbl_is_xml, true));
ctx.Subs_add_and_stack_tblw(root, prv_tkn, tkn_mkr.Tblw_td(bgn_pos, bgn_pos, tbl_is_xml));
}
Xop_tblw_tb_tkn tb_tkn = tkn_mkr.Tblw_tb(bgn_pos, cur_pos, tbl_is_xml, false);
new_tkn = tb_tkn;
break;
case Tblw_type_tr: // <tr>
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_tb: break; // noop; <table><tr>
case Xop_tkn_itm_.Tid_tblw_tc: // fix; <caption><tr> -> <caption></caption><tr>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tc), true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_td: // fix; <td><tr> -> <td></td></tr><tr>
case Xop_tkn_itm_.Tid_tblw_th: // fix; <th><tr> -> <th></th></tr><tr>
if (!tbl_is_xml)
ctx.Para().Process_nl(ctx, root, src, bgn_pos, bgn_pos + 1); // simulate "\n"; 2012-12-08
int stack_pos = ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr);
if (stack_pos != Xop_ctx.Stack_not_found) // don't pop <tr> if none found; EX:en.w:Turks_in_Denmark DATE:2014-03-02
ctx.Stack_pop_til(root, src, stack_pos, true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_tr: // fix; <tr><tr> -> <tr>
if (prv_tkn.Tblw_subs_len() == 0) { // NOTE: set prv_row to ignore, but do not pop; see Tr_dupe_xnde and [[Jupiter]]; only invoke if same type; EX: <tr><tr> but not |-<tr>; DATE:2013-12-09
Xop_tkn_itm prv_row = ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr), false, bgn_pos, bgn_pos);
prv_row.Ignore_y_();
}
else
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr), true, bgn_pos, bgn_pos);
break;
}
Xop_tblw_tr_tkn tr_tkn = tkn_mkr.Tblw_tr(bgn_pos, cur_pos, tbl_is_xml, false);
new_tkn = tr_tkn;
break;
case Tblw_type_td: // <td>
case Tblw_type_td2:
boolean create_th = false;
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_tr: break; // noop; <tr><td>
case Xop_tkn_itm_.Tid_tblw_td: // fix; <td><td> -> <td></td><td>
if (!tbl_is_xml) // only for "\n|" not <td>
ctx.Para().Process_nl(ctx, root, src, bgn_pos, bgn_pos + 1); // simulate "\n"; DATE:2014-02-20; ru.w:;[[Help:Download]]; DATE:2014-02-20
ctx.Para().Process_block__bgn_y__end_n(Xop_xnde_tag_.Tag_td); // <td>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(prv_tid), true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_th: // fix; <th><td> -> <th></th><td>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(prv_tid), true, bgn_pos, bgn_pos);
if (wlxr_type == Tblw_type_td2) create_th = true; // !a||b -> <th><th>; but !a|b -> <th><td>
break;
case Xop_tkn_itm_.Tid_tblw_tb: // fix; <table><td> -> <table><tr><td>
if (wlxr_type == Tblw_type_td2) { // NOTE: ignore || if preceded by {|; {|a||b\n
prv_tkn.Atrs_rng_set(-1, -1); // reset atrs_bgn; remainder of line will become part of tb atr
return cur_pos;
}
else {
new_tkn = tkn_mkr.Tblw_tr(bgn_pos, cur_pos, tbl_is_xml, true);
new_tkn.Atrs_rng_set(bgn_pos, bgn_pos);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, new_tkn);
prv_tid = new_tkn.Tkn_tid();
}
break;
case Xop_tkn_itm_.Tid_tblw_tc: // fix; <caption><td> -> <caption></caption><tr><td>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tc), true, bgn_pos, bgn_pos);
new_tkn = tkn_mkr.Tblw_tr(bgn_pos, cur_pos, tbl_is_xml, true);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, new_tkn);
prv_tid = new_tkn.Tkn_tid();
break;
}
// if (prv_tid == Xop_tkn_itm_.Tid_xnde)
// ctx.Stack_autoClose(root, src, prv_tkn, prv_tkn.Src_bgn(), prv_tkn.Src_end());
if (create_th) new_tkn = tkn_mkr.Tblw_th(bgn_pos, cur_pos, tbl_is_xml);
else new_tkn = tkn_mkr.Tblw_td(bgn_pos, cur_pos, tbl_is_xml);
cell_pipe_seen = false;
break;
case Tblw_type_th: // <th>
case Tblw_type_th2:
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_tr: break; // noop; <tr><th>
case Xop_tkn_itm_.Tid_tblw_th: // fix; <th><th> -> <th></th><th>
if (tbl_is_xml // tbl_is_xml always closes previous token
|| (wlxr_type == Tblw_type_th2 || wlxr_type == Tblw_type_th)) // ! always closes; EX: "! !!"; "!! !!"; REMOVE: 2012-05-07; had (&& !ws_enabled) but caused "\n !" to fail; guard is no longer necessary since tblw_ws changed...
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(prv_tid), true, bgn_pos, bgn_pos);
else {
ctx.Subs_add(root, tkn_mkr.Txt(bgn_pos, cur_pos));
return cur_pos;
}
break;
case Xop_tkn_itm_.Tid_tblw_td: // fix; <td><th> -> <td></td><th> NOTE: common use of using <th> after <td> for formatting
if (tbl_is_xml // tbl_is_xml always closes previous token
|| (wlxr_type == Tblw_type_th)) // "| !" closes; "| !!" does not;
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(prv_tid), true, bgn_pos, bgn_pos);
else {
ctx.Subs_add(root, tkn_mkr.Txt(bgn_pos, cur_pos));
return cur_pos;
}
break;
case Xop_tkn_itm_.Tid_tblw_tb: // fix; <table><th> -> <table><tr><th>
ctx.Subs_add_and_stack_tblw(root, prv_tkn, tkn_mkr.Tblw_tr(bgn_pos, cur_pos, tbl_is_xml, true));
break;
case Xop_tkn_itm_.Tid_tblw_tc: // fix; <caption><th> -> <caption></caption><tr><th>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tc), true, bgn_pos, bgn_pos);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, tkn_mkr.Tblw_tr(bgn_pos, cur_pos, tbl_is_xml, true));
break;
}
new_tkn = tkn_mkr.Tblw_th(bgn_pos, cur_pos, tbl_is_xml);
cell_pipe_seen = false;
break;
case Tblw_type_tc: // <caption>
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_tb: break; // noop; <table><caption>
case Xop_tkn_itm_.Tid_tblw_tr: // fix; <tr><caption> -> <tr></tr><caption> TODO: caption should be ignored and placed in quarantine
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr), true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_td: // fix; <td><caption> -> <td></td><caption>
case Xop_tkn_itm_.Tid_tblw_th: // fix; <th><caption> -> <th></th><caption>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr), true, bgn_pos, bgn_pos); // NOTE: closing <tr> in order to close <td>/<th>
ctx.Msg_log().Add_itm_none(Xop_tblw_log.Caption_after_td, src, prv_tkn.Src_bgn(), bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_tc: // fix; <caption><caption> -> <caption></caption><caption>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tc), true, bgn_pos, bgn_pos);
ctx.Msg_log().Add_itm_none(Xop_tblw_log.Caption_after_tc, src, prv_tkn.Src_bgn(), bgn_pos);
break;
}
new_tkn = tkn_mkr.Tblw_tc(bgn_pos, cur_pos, tbl_is_xml);
Xop_tblw_tb_tkn tblw_tb_tkn = (Xop_tblw_tb_tkn)ctx.Stack_get_typ(Xop_tkn_itm_.Tid_tblw_tb);
tblw_tb_tkn.Caption_count_add_1(); // NOTE: null check is not necessary (impossible to have a caption without a tblw); DATE:2013-12-20
cell_pipe_seen = false; // NOTE: always mark !seen; see Atrs_tc()
break;
}
ctx.Subs_add_and_stack_tblw(root, prv_tkn, new_tkn);
if (atrs_bgn > Xop_tblw_wkr.Atrs_ignore_check) {
new_tkn.Atrs_rng_set(atrs_bgn, atrs_end);
if (ctx.Parse_tid() == Xop_parser_.Parse_tid_page_wiki) {
Xop_xatr_itm[] atrs = ctx.App().Xatr_parser().Parse(ctx.Msg_log(), src, atrs_bgn, atrs_end);
new_tkn.Atrs_ary_as_tblw_(atrs);
}
}
switch (wlxr_type) {
case Tblw_type_tb:
case Tblw_type_tr:
ctx.Para().Process_block__bgn_y__end_n(Xop_xnde_tag_.Tag_tr);
break;
case Tblw_type_td:
case Tblw_type_th:
ctx.Para().Process_block__bgn_n__end_y(Xop_xnde_tag_.Tag_td);
break;
}
return cur_pos;
}
public int Make_tkn_end(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, int typeId, byte wlxr_type, Xop_tblw_tkn prv_tkn, int prv_tid, boolean tbl_is_xml) {
if (!tbl_is_xml) // only for "\n|}" not </table>
ctx.Para().Process_nl(ctx, root, src, bgn_pos, bgn_pos + 1); // simulate "\n"; process para (which will create paras for cells) 2012-12-08
if (tbl_is_xml && typeId == Xop_tkn_itm_.Tid_tblw_tb // tblx: </table>
&& prv_tkn != null && !prv_tkn.Tblw_xml()) { // tblw is prv_tkn
++tblw_te_ignore_count; // suppress subsequent occurrences of "|}"; EX:ru.q:Авель; DATE:2014-02-22
}
Ignore_ws(ctx, root);
if (wlxr_type == Tblw_type_te) {
switch (prv_tid) {
case Xop_tkn_itm_.Tid_tblw_td: // fix; <td></table> -> <td></td></tr></table>
case Xop_tkn_itm_.Tid_tblw_th: // fix; <th></table> -> <th></th></tr></table>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tr), true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_tc: // fix; <caption></table> -> <caption></caption></table>
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tc), true, bgn_pos, bgn_pos);
break;
case Xop_tkn_itm_.Tid_tblw_tr: // fix; <tr></table> -> </table> : tr but no tds; remove tr
boolean blank = true;
for (int j = prv_tkn.Tkn_sub_idx() + 1; j < root.Subs_len(); j++) {
Xop_tkn_itm t = root.Subs_get(j);
switch (t.Tkn_tid()) {
case Xop_tkn_itm_.Tid_newLine:
case Xop_tkn_itm_.Tid_para:
break;
default:
blank = false;
j = root.Subs_len();
break;
}
}
if (blank)
root.Subs_del_after(prv_tkn.Tkn_sub_idx());
break;
case Xop_tkn_itm_.Tid_tblw_tb: // fix; <table></table> -> <table><tr><td></td></tr></table>
boolean has_subs = false;
for (int i = prv_tkn.Tkn_sub_idx() + 1; i < root.Subs_len(); i++) {
int cur_id = root.Subs_get(i).Tkn_tid();
switch (cur_id) {
case Xop_tkn_itm_.Tid_tblw_tc:
case Xop_tkn_itm_.Tid_tblw_td:
case Xop_tkn_itm_.Tid_tblw_th:
case Xop_tkn_itm_.Tid_tblw_tr:
has_subs = true;
i = root.Subs_len();
break;
}
}
if (!has_subs) {
Xop_tkn_itm new_tkn = tkn_mkr.Tblw_tr(bgn_pos, bgn_pos, tbl_is_xml, true);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, new_tkn);
new_tkn = tkn_mkr.Tblw_td(bgn_pos, bgn_pos, tbl_is_xml);
ctx.Subs_add_and_stack_tblw(root, prv_tkn, new_tkn);
ctx.Stack_pop_til(root, src, ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tb), true, bgn_pos, bgn_pos);
return cur_pos;
}
break;
}
int tb_idx = ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_tblw_tb);
if (tb_idx == -1) return cur_pos; // NOTE: tb_idx can be -1 when called from Pipe in Tmpl mode
Xop_tblw_tb_tkn tb = (Xop_tblw_tb_tkn)ctx.Stack_pop_til(root, src, tb_idx, false, bgn_pos, bgn_pos); // NOTE: need to pop manually in order to set all intermediate node ends to bgn_pos, but tb ent to cur_pos; EX: for stack of "tb,tr,td" tr and td get End_() of bgn_pos but tb gets End_() of cur_pos
tb.Subs_move(root);
tb.Src_end_(cur_pos);
ctx.Para().Process_block__bgn_n__end_y(Xop_xnde_tag_.Tag_table); // NOTE: must clear block state that was started by <tr>; code implicitly relies on td clearing block state, but no td was created
return cur_pos;
}
int acs_typeId = typeId;
if (prv_tid != typeId // NOTE: special logic to handle auto-close of <td></th> or <th></td>
&& ( (prv_tid == Xop_tkn_itm_.Tid_tblw_td && typeId == Xop_tkn_itm_.Tid_tblw_th)
|| (prv_tid == Xop_tkn_itm_.Tid_tblw_th && typeId == Xop_tkn_itm_.Tid_tblw_td)
)
)
acs_typeId = prv_tid;
int acs_pos = -1, acs_len = ctx.Stack_len();
for (int i = acs_len - 1; i > -1; i--) { // find auto-close pos
byte cur_acs_tid = ctx.Stack_get(i).Tkn_tid();
switch (acs_typeId) {
case Xop_tkn_itm_.Tid_tblw_tb: // if </table>, match <table> only; note that it needs to be handled separately b/c of tb logic below
if (acs_typeId == cur_acs_tid) {
acs_pos = i;
i = -1; // force break;
}
break;
default: // if </t*>, match <t*> but stop at <table>; do not allow </t*> to close <t*> outside <table>
if (cur_acs_tid == Xop_tkn_itm_.Tid_tblw_tb) // <table>; do not allow </t*> to close any <t*>'s above <table>; EX:w:Enthalpy_of_fusion; {{States of matter}}
i = -1; // this will skip acs_pos != -1 below and discard token
else if (cur_acs_tid == acs_typeId) { // </t*> matches <t*>
acs_pos = i;
i = -1; // force break
}
break;
}
}
if (acs_pos != -1) {
Xop_tblw_tkn bgn_tkn = (Xop_tblw_tkn)ctx.Stack_pop_til(root, src, acs_pos, false, bgn_pos, cur_pos);
switch (wlxr_type) {
case Tblw_type_tb:
ctx.Para().Process_block__bgn_n__end_y(Xop_xnde_tag_.Tag_table);
break;
case Tblw_type_td:
case Tblw_type_th:
ctx.Para().Process_block__bgn_y__end_n(Xop_xnde_tag_.Tag_td);
break;
}
bgn_tkn.Subs_move(root);
bgn_tkn.Src_end_(cur_pos);
}
return cur_pos;
}
public static void Atrs_close(Xop_ctx ctx, byte[] src, Xop_root_tkn root) {
Xop_tblw_tkn prv_tkn = ctx.Stack_get_tbl();
if (prv_tkn == null || prv_tkn.Tblw_xml()) return; // no tblw or tblw_xnde (which does not have tblw atrs)
switch (prv_tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_tblw_tb: case Xop_tkn_itm_.Tid_tblw_tr: // only tb and tr have tblw atrs (EX: "{|id=1\n"); td/th use pipes for atrs (EX: "|id=1|a"); tc has no atrs; te is never on stack
Xop_tblw_wkr.Atrs_make(ctx, src, root, ctx.Tblw(), prv_tkn);
break;
}
}
public static boolean Atrs_make(Xop_ctx ctx, byte[] src, Xop_root_tkn root, Xop_tblw_wkr wkr, Xop_tblw_tkn prv_tblw) {
if (prv_tblw.Atrs_bgn() != Xop_tblw_wkr.Atrs_null) return false; // atr_bgn/end is empty or already has explicit value; ignore;
int subs_bgn = prv_tblw.Tkn_sub_idx() + 1, subs_end = root.Subs_len() - 1;
int subs_pos = subs_bgn;
Xop_tkn_itm last_atr_tkn = null;
boolean loop = true;
while (loop) { // loop over tkns after prv_tkn to find last_atr_tkn
if (subs_pos > subs_end) break;
Xop_tkn_itm tmp_tkn = root.Subs_get(subs_pos);
switch (tmp_tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_newLine: // nl stops; EX: "{| a b c \nd"; bgn at {| and pick up " a b c " as atrs
case Xop_tkn_itm_.Tid_hdr: case Xop_tkn_itm_.Tid_hr: // hdr/hr incorporate nl into tkn so include these as well; EX: "{|a\n==b==" becomes tblw,txt,hdr (note that \n is part of hdr
case Xop_tkn_itm_.Tid_list: // list stops; EX: "{| a b c\n* d"; "*d" ends atrs; EX: ru.d: DATE:2014-02-22
loop = false;
break;
default:
++subs_pos;
last_atr_tkn = tmp_tkn;
break;
}
}
if (last_atr_tkn == null) { // no atrs found; mark tblw_tkn as Atrs_empty
prv_tblw.Atrs_rng_set(Xop_tblw_wkr.Atrs_empty, Xop_tblw_wkr.Atrs_empty);
return false;
}
root.Subs_del_between(ctx, subs_bgn, subs_pos);
int atrs_bgn = prv_tblw.Src_end(), atrs_end = last_atr_tkn.Src_end();
if (prv_tblw.Tkn_tid() == Xop_tkn_itm_.Tid_tblw_tr) // NOTE: if "|-" gobble all trailing dashes; REF: Parser.php!doTableStuff; $line = preg_replace( '#^\|-+#', '', $line ); DATE:2013-06-21
atrs_bgn = Bry_finder.Find_fwd_while(src, atrs_bgn, src.length, Byte_ascii.Dash);
prv_tblw.Atrs_rng_set(atrs_bgn, atrs_end);
if (ctx.Parse_tid() == Xop_parser_.Parse_tid_page_wiki && atrs_bgn != -1) {
Xop_xatr_itm[] atrs = ctx.App().Xatr_parser().Parse(ctx.Msg_log(), src, atrs_bgn, atrs_end);
prv_tblw.Atrs_ary_as_tblw_(atrs);
}
wkr.Cell_pipe_seen_(true);
return true;
}
private void Ignore_ws(Xop_ctx ctx, Xop_root_tkn root) {
int end = root.Subs_len() - 1;
// get last tr, tc, tb; cannot use ctx.Stack_get_tblw b/c this gets last open tblw, and we want last tblw; EX: "<table><tr></tr>"; Stack_get_tblw gets <table> want </tr>
boolean found = false;
Xop_tkn_itm prv_tkn = null;
for (int i = end; i > -1; i--) {
prv_tkn = root.Subs_get(i);
switch (prv_tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_tblw_tr:
case Xop_tkn_itm_.Tid_tblw_tc:
case Xop_tkn_itm_.Tid_tblw_tb:
found = true;
i = -1;
break;
case Xop_tkn_itm_.Tid_tblw_td: // exclude td
case Xop_tkn_itm_.Tid_tblw_th: // exclude th
i = -1;
break;
}
}
if (!found) return;
int bgn = prv_tkn.Tkn_sub_idx() + 1;
int rv = Ignore_ws_rng(ctx, root, bgn, end, true);
if (rv == -1) return; // entire range is ws; don't bother trimming end
Ignore_ws_rng(ctx, root, end, bgn, false);
}
private int Ignore_ws_rng(Xop_ctx ctx, Xop_root_tkn root, int bgn, int end, boolean fwd) {
int cur = bgn, adj = fwd ? 1 : -1;
while (true) {
if (fwd) {
if (cur > end) return -1;
}
else {
if (cur < end) return -1;
}
Xop_tkn_itm ws_tkn = root.Subs_get(cur);
switch (ws_tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab: case Xop_tkn_itm_.Tid_newLine:
case Xop_tkn_itm_.Tid_para:
ws_tkn.Ignore_y_grp_(ctx, root, cur);
break;
case Xop_tkn_itm_.Tid_xnde:
if (ws_tkn.Src_bgn() == ws_tkn.Src_end() // NOTE: para_wkr inserts <br/>. these should be disabled in Ignore_ws_rng; they are identified as having bgn == end; normal <br/>s will have bgn < end
&& ((Xop_xnde_tkn)ws_tkn).Tag().Id() == Xop_xnde_tag_.Tid_br)
ws_tkn.Ignore_y_grp_(ctx, root, cur);
break;
default:
return cur;
}
cur += adj;
}
}
public static int Handle_false_tblw_match(Xop_ctx ctx, Xop_root_tkn root, byte[] src, int bgn_pos, int cur_pos, Xop_tkn_itm tkn, boolean add_nl) {
if (add_nl)
ctx.Para().Process_nl(ctx, root, src, bgn_pos, cur_pos);
ctx.Subs_add(root, tkn);
return cur_pos;
}
public static final int Atrs_null = -1, Atrs_empty = -2, Atrs_ignore_check = -1;
public static final byte Tblw_type_tb = 0, Tblw_type_te = 1, Tblw_type_tr = 2, Tblw_type_td = 3, Tblw_type_th = 4, Tblw_type_tc = 5, Tblw_type_td2 = 6, Tblw_type_th2 = 7;
}
/*
NOTE_1:
Code tries to emulate HTML tidy behavior. Specifically:
- ignore <table> when directly under <table>
- if tblw, scan to end of line to ignore attributes
- ignore any closing tblws
EX:
{|id=1
{|id=2 <- ignore id=2
|}
|}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
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_tblw_wkr_dangling_tst {
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Dangling_tb_in_xnde() {// PURPOSE: dangling tblw incorrectly auto-closed by </xnde>; NOTE: this test is not correct; needs HTML tidy to close </div> earlier; EX:w:Atlanta_Olympics; DATE:2014-03-18
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<div align='center'>"
, "{|"
, "|-"
, "|"
, "{|"
, "|-"
, "|a"
, "|}"
, "</div>"
, "b"
)
, String_.Concat_lines_nl
( "<div align='center'>"
, "<table>"
, " <tr>"
, " <td>"
, " <table>"
, " <tr>"
, " <td>a"
, " </td>"
, " </tr>"
, " </table>"
, ""
, "<p>b"
, " </td>"
, " </tr>"
, "</table>"
, "</div>"
, "</p>"
));
}
}

View File

@@ -0,0 +1,109 @@
/*
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_tblw_wkr_double_pipe_tst {
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void No_tblw() { // PURPOSE: if || has no tblw, treat as lnki; none; DATE:2014-05-06
fxt.Test_parse_page_all_str("[[A||b|c]]", String_.Concat_lines_nl_skip_last
( "<p><a href=\"/wiki/A\">b|c</a>" // NOTE: technically this should be "|b|c", but difficult to implement; DATE:2014-05-06
, "</p>"
, ""
));
}
@Test public void Image_map() {// PURPOSE: if || is inside table and imagemap, treat as lnki; EX:w:United_States_presidential_election,_1992; DATE:2014-03-29; DATE:2014-05-06
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "| z"
, "<imagemap>"
, "File:A.png||123px|b" // NOTE: "||" should not be tblw; also should not be pipe + text; if it is pipe + text, then caption will be "|123px" and width will be -1; DATE:2014-05-06
, "</imagemap>"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td> z"
, "<a href=\"/wiki/File:A.png\" class=\"image\" xowa_title=\"A.png\"><img id=\"xowa_file_img_0\" alt=\"b\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" /></a>" // NOTE: width must be 123, not 0
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Tblw_lnki_nth() { // PURPOSE: if || is nth pipe, then treat as lnki; EX:en.w:Main_Page;de.w:Main_Page; DATE:2014-05-06
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|[[File:A.png|b||c]]"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td><a href=\"/wiki/File:A.png\" class=\"image\" xowa_title=\"A.png\"><img id=\"xowa_file_img_0\" alt=\"c\" src=\"file:///mem/wiki/repo/trg/orig/7/0/A.png\" width=\"0\" height=\"0\" /></a>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Tblw_lnki_list_1st() { // PURPOSE: if || is 1st pipe, but inside list, then treat as lnki; EX:w:Second_Boer_War; DATE:2014-05-05
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|"
, "*[[A||b]]"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>"
, ""
, " <ul>"
, " <li><a href=\"/wiki/A\">b</a>" // NOTE: technically this should be "|b", but difficult to implement; DATE:2014-05-06
, " </li>"
, " </ul>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Tblw_lnki_double_bang() { // PURPOSE: do not treat !! as tblw; PAGE:en.w:Pink_(singer); DATE:2014-06-25
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|"
, "[[A!!b]]"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>"
, ""
, "<p><a href=\"/wiki/A!!b\">A!!b</a>"
, "</p>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
}

View File

@@ -0,0 +1,200 @@
/*
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_tblw_wkr_nested_tst {
private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_parse_page_wiki(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "|"
, "{|"
, "|-"
, "|a"
, "|}"
, "|b"
, "|}"
)
, fxt.tkn_tblw_tb_(0, 25).Subs_
( fxt.tkn_tblw_tr_(2, 22).Subs_
( fxt.tkn_tblw_td_(5, 19).Subs_
( fxt.tkn_tblw_tb_(7, 19).Subs_
( fxt.tkn_tblw_tr_(10, 16).Subs_
( fxt.tkn_tblw_td_(13, 16).Subs_(fxt.tkn_txt_(15, 16), fxt.tkn_para_blank_(17))
)
)
, fxt.tkn_para_blank_(20)
)
, fxt.tkn_tblw_td_(19, 22).Subs_(fxt.tkn_txt_(21, 22), fxt.tkn_para_blank_(23))
)
)
);
}
@Test public void Leading_ws() {
fxt.Init_para_y_();
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|id='a'"
, "|-"
, "|a"
, "|-"
, "|id='b'|"
, " {|id='c'"
, " |-"
, " |d"
, " |}"
, "|}"
)
, String_.Concat_lines_nl_skip_last
( "<table id='a'>"
, " <tr>"
, " <td>a"
, " </td>"
, " </tr>"
, " <tr>"
, " <td id='b'>"
, " <table id='c'>"
, " <tr>"
, " <td>d"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
fxt.Init_para_n_();
}
@Test public void Tblx_tblw() { // PURPOSE: if <table> followed by {|, ignore 2nd table; EX: en.b:Wikibooks:Featured_books; DATE:2014-02-08
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<table cellpadding=\"0\">"
, "{| cellspacing=\"0\""
, "|a"
, "|}"
, "</table>"
), String_.Concat_lines_nl_skip_last
( "<table cellpadding=\"0\">"
, " <tr>"
, " <td>a"
, " </td>"
, " </tr>"
, "</table>"
, ""
));
}
@Test public void Caption_and_tblw() { // TIDY: don't try to fix <caption><table> sequence; PAGE:es.w:Sevilla; DATE:2014-06-29
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|+"
, "{|"
, "|}"
, "|}"), String_.Concat_lines_nl_skip_last
( "<table>"
, " <caption>"
, " <table>"
, " <tr>"
, " <td>"
, " </td>"
, " </tr>"
, " </table>"
, " </caption>"
, "</table>"
, ""
));
}
@Test public void Tb_tr_tb() { // PURPOSE: if <tr><table>, auto-create <tr><td>; EX:w:Paris; DATE:2014-03-18
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "{|"
, "|}"
, "|}"), String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <table>"
, " <tr>"
, " <td>"
, " </td>"
, " </tr>"
, " </table>"
, " </tr>"
, "</table>"
, ""
));
}
@Test public void Tblw_tblx_tblw_fails() { // PURPOSE: {| -> <table> -> \n| was not rendering as <td>; EX:en.w:Paris#Demographics; DATE:2014-03-18
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "|a"
, "</td></tr>"
, "<tr><td><table>"
, "<tr><td>b</td>"
, "</tr>"
, "|c"
, "</td></tr></table>"
, "|}"
), String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, " </td>"
, " </tr>"
, " <tr>"
, " <td>"
, " <table>"
, " <tr>"
, " <td>b"
, " </td>"
, " </tr>"
, " <tr>"
, " <td>c"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
// @Test public void Nested_tbl_missing() { // PURPOSE: nested table not rendering properly; EX:ar.s:; DATE:2014-03-18
// fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
// ( "{|"
// , "|-"
// , "{|"
// , "|-"
// , "|}"
// , "| width='50%' | a"
// , "|}"
// ), String_.Concat_lines_nl_skip_last
// ( "<table>"
// , " <tr>"
// , " <td>a"
// , " </td>"
// , " <td>[[b|c"
// , " </td>"
// , " </tr>"
// , "</table>"
// , ""
// , "<p>d"
// , "</p>"
// ));
// }
}

View File

@@ -0,0 +1,156 @@
/*
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_tblw_wkr_para_tst {
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Para() { // PURPOSE: para causing strange breaks; SEE:[[John F. Kennedy]] and "two Supreme Court appointments"
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "<p></p>"
, "|a"
, "<p></p>"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table><p></p>"
, " <tr>"
, " <td>a"
, "<p></p>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Nl() { // PURPOSE: para causing strange breaks; SEE:[[John F. Kennedy]] and "two Supreme Court appointments"
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "!a"
, ""
, "|-"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <th>a"
, " </th>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Unnecessary_para() { // PURPOSE: tblw causes unnecessary <p>; [[Help:Download]]; DATE:2014-02-20
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "|"
, "a<br/>"
, "b"
, "|"
, "c<br/>"
, "d"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>"
, ""
, "<p>a<br/>"
, "b"
, "</p>"
, " </td>"
, " <td>"
, ""
, "<p>c<br/>"
, "d"
, "</p>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Ws_leading() { // EX.WP: AGPLv3
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, " !a"
, " !b"
, "|}"
)
, String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <th>a"
, " </th>"
, " <th>b"
, " </th>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Ws_th_2() { // "\n\s!" should still be interpreted as tblw; s.w:Manchester; DATE:2014-02-14
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "|!style='color:red'|a"
, " !style=\"color:blue\"|b"
, "|}"
)
, String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, " </td>"
, " <th style=\"color:blue\">b"
, " </th>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Ws_th_3() { // "\n\s!" and "!!" breaks tblw; ru.w:Храмы_Санкт-Петербурга (List of churches in St Petersburg); DATE:2014-02-20
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, " ! id='1' | a !! id='2' | b"
, "|}"
)
, String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <th id='1'> a "
, " </th>"
, " <th id='2'> b"
, " </th>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Tblw_td2_should_not_create_ws() { // PURPOSE: a||b -> a\n||b; EX:none;discovered during luaj test; DATE:2014-04-14
fxt.Test_parse_page_wiki_str("a||b", "<p>a||b\n</p>");
}
}

View File

@@ -0,0 +1,71 @@
/*
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_tblw_wkr_tblx_tst {
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Ignore_td() { // PURPOSE: do not parse pipe as td if in <table>; EX:ru.w:Сочи; DATE:2014-02-22
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, "| b"
, " </td>"
, " </tr>"
, "</table>"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, "| b"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Ignore_tr() { // PURPOSE: do not parse "\n|-", "\n!" if in <table>; EX:s.w:Uranus; DATE:2014-05-05
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, "|-"
, "! b"
, "| c"
, " </td>"
, " </tr>"
, "</table>"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, ""
, "<p>|-"
, "! b"
, "| c"
, "</p>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
}

View File

@@ -0,0 +1,83 @@
/*
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_tblw_wkr_uncommon_tst {
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Tr_pops_entire_stack() { // PURPOSE: in strange cases, tr will pop entire stack; EX:en.w:Turks_in_Denmark; DATE:2014-03-02
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "{|"
, "<caption>a"
, "|b"
, "|-"
, "|c"
, "|}"
)
, String_.Concat_lines_nl
( "<table>"
, " <caption>a"
, " </caption>"
, " <tr>"
, " <td>b"
, " </td>"
, " </tr>"
, " <tr>"
, " <td>c"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Atrs_defect() { // PURPOSE: < in atrs was causing premature termination; EX:en.w:Wikipedia:List of hoaxes on Wikipedia
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|id=\"a<b\""
, "|a"
, "|}"), String_.Concat_lines_nl_skip_last
( "<table id=\"a.3Cb\">"
, " <tr>"
, " <td>a"
, " </td>"
, " </tr>"
, "</table>"
, ""
));
}
@Test public void Broken_lnki() { // PURPOSE: broken lnki was not closing table properly; EX:en.w:Wikipedia:Changing_attribution_for_an_edit; DATE:2014-03-16
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "|a"
, "|[[b|c"
, "|}"
, "d"
), String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td>a"
, " </td>"
, " <td>[[b|c"
, " </td>"
, " </tr>"
, "</table>"
, ""
, "<p>d"
, "</p>"
));
}
}