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
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import gplx.xowa.html.*; import gplx.xowa.html.hrefs.*;
import gplx.xowa.net.*;
public class Xoh_lnke_wtr {
private Xoae_app app;
public Xoh_lnke_wtr(Xowe_wiki wiki) {this.app = wiki.Appe();}
public void Write_all(Bry_bfr bfr, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_ctx ctx, byte[] src, Xop_lnke_tkn lnke) {
int lnke_bgn = lnke.Lnke_bgn(), lnke_end = lnke.Lnke_end(); boolean proto_is_xowa = lnke.Proto_tid() == Xoo_protocol_itm.Tid_xowa;
if (!hctx.Mode_is_alt()) { // write href, unless mode is alt
if (hctx.Mode_is_hdump()) {
if (lnke.Lnke_typ() == Xop_lnke_tkn.Lnke_typ_text)
bfr.Add_str_a7("<a xtid='a_lnke_txt' href=\"");
else {
if (lnke.Subs_len() == 0)
bfr.Add_str_a7("<a xtid='a_lnke_brk_n' href=\"");
else
bfr.Add_str_a7("<a xtid='a_lnke_brk_y' href=\"");
}
}
else
bfr.Add(Xoh_consts.A_bgn);
if (Write_href(bfr, ctx, src, lnke, lnke_bgn, lnke_end, proto_is_xowa))
bfr.Add(A_lhs_end_external);
else
bfr.Add(A_lhs_end_internal);
}
Write_caption(bfr, html_wtr, hctx, ctx, src, lnke, lnke_bgn, lnke_end, proto_is_xowa);
if (!hctx.Mode_is_alt()) {
if (proto_is_xowa) // add <img />
bfr.Add(Xoh_consts.Img_bgn).Add(html_wtr.Html_mgr().Img_xowa_protocol()).Add(Xoh_consts.__inline_quote);
bfr.Add(Xoh_consts.A_end);
}
}
public boolean Write_href(Bry_bfr bfr, Xop_ctx ctx, byte[] src, Xop_lnke_tkn lnke, int lnke_bgn, int lnke_end, boolean proto_is_xowa) {
byte[] lnke_xwiki_wiki = lnke.Lnke_xwiki_wiki();
if (lnke_xwiki_wiki == null) {
if (lnke.Lnke_relative()) { // relative; EX: //a.org
bfr.Add(app.Utl__url_parser().Url_parser().Relative_url_protocol_bry()).Add_mid(src, lnke_bgn, lnke_end);
return true;
}
else { // xowa or regular; EX: http://a.org
if (proto_is_xowa) {
bfr.Add(Xop_lnke_wkr.Bry_xowa_protocol);
Xoa_app_.Utl__encoder_mgr().Gfs().Encode(bfr, src, lnke_bgn, lnke_end);
return false;
}
else { // regular; add href
bfr.Add_mid(src, lnke_bgn, lnke_end);
return true;
}
}
}
else { // xwiki
Url_encoder href_encoder = Xoa_app_.Utl__encoder_mgr().Href_quotes();
bfr.Add(Xoh_href_parser.Href_site_bry).Add(lnke_xwiki_wiki).Add(Xoh_href_parser.Href_wiki_bry)
.Add(href_encoder.Encode(lnke.Lnke_xwiki_page())); // NOTE: must encode page; EX:%22%3D -> '">' which will end attribute; PAGE:en.w:List_of_Category_A_listed_buildings_in_West_Lothian DATE:2014-07-15
if (lnke.Lnke_xwiki_qargs() != null)
Xoa_url_arg_hash.Concat_bfr(bfr, href_encoder, lnke.Lnke_xwiki_qargs()); // NOTE: must encode args
return false;
}
}
public void Write_caption(Bry_bfr bfr, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_ctx ctx, byte[] src, Xop_lnke_tkn lnke, int lnke_bgn, int lnke_end, boolean proto_is_xowa) {
int subs_len = lnke.Subs_len();
if (subs_len == 0) { // no text; auto-number; EX: "[1]"
if (lnke.Lnke_typ() == Xop_lnke_tkn.Lnke_typ_text)
bfr.Add_mid(src, lnke_bgn, lnke_end);
else
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_int_variable(ctx.Cur_page().Html_data().Lnke_autonumber_next()).Add_byte(Byte_ascii.Brack_end);
}
else { // text available
for (int i = 0; i < subs_len; i++)
html_wtr.Write_tkn(bfr, ctx, hctx, src, lnke, i, lnke.Subs_get(i));
}
}
private static final byte[]
A_lhs_end_external = Bry_.new_a7("\" class=\"external text\" rel=\"nofollow\">")
, A_lhs_end_internal = Bry_.new_a7("\">")
;
}

View 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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xoh_lnke_wtr_tst {
private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_(); fxt.Reset();}
@Test public void Basic() {fxt.Test_parse_page_wiki_str("[irc://a]" , "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">[1]</a>");}
@Test public void Autonumber() {fxt.Test_parse_page_wiki_str("[irc://a] [irc://b]" , "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">[1]</a> <a href=\"irc://b\" class=\"external text\" rel=\"nofollow\">[2]</a>");}
@Test public void Caption() {fxt.Test_parse_page_wiki_str("[irc://a b]" , "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">b</a>");}
@Test public void Caption_wtxt() {fxt.Test_parse_page_wiki_str("[irc://a ''b'']" , "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\"><i>b</i></a>");}
@Test public void Xowa_protocol() {
String img = "<img src=\"file:///mem/xowa/user/test_user/app/img/xowa/protocol.png\"/>";
fxt.Wiki().Sys_cfg().Xowa_proto_enabled_(true);
fxt.Test_parse_page_wiki_str("[xowa-cmd:\"a\" z]" , "<a href=\"xowa-cmd:a\">z" + img + "</a>");
fxt.Test_parse_page_wiki_str("[xowa-cmd:\"a.b('c_d');\" z]" , "<a href=\"xowa-cmd:a.b('c_d');\">z" + img + "</a>");
fxt.Test_parse_page_wiki_str("[xowa-cmd:*\"a\"b*c\"* z]" , "<a href=\"xowa-cmd:a%22b%2Ac\">z" + img + "</a>");
fxt.Wiki().Sys_cfg().Xowa_proto_enabled_(false);
fxt.Test_parse_page_wiki_str("[xowa-cmd:\"a\" b]" , "[xowa-cmd:&quot;a&quot; b]"); // protocol is disabled: literalize String (i.e.: don't make it an anchor)
}
}

View 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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import gplx.core.btries.*;
public class Xop_lnke_end_lxr implements Xop_lxr {//20111222
public byte Lxr_tid() {return Xop_lxr_.Tid_lnke_end;}
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Byte_ascii.Brack_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) {return ctx.Lnke().MakeTkn_end(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos);}
public static final Xop_lnke_end_lxr _ = new Xop_lnke_end_lxr(); Xop_lnke_end_lxr() {}
}

View File

@@ -0,0 +1,22 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
public class Xop_lnke_log {
private static final Gfo_msg_grp owner = Gfo_msg_grp_.new_(Xoa_app_.Nde, "lnke");
public static final Gfo_msg_itm Dangling = Gfo_msg_itm_.new_note_(owner, "dangling"); // NOTE: WP.BOT:YOBOT;PAGE:en.w:Pan_flute
}

View File

@@ -0,0 +1,44 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import gplx.core.btries.*; import gplx.xowa.net.*;
public class Xop_lnke_lxr implements Xop_lxr {
Xop_lnke_lxr(byte lnke_typ, byte[] protocol, byte tid) {this.lnke_typ = lnke_typ; this.protocol = protocol; this.tid = tid;} private byte lnke_typ; byte[] protocol; byte tid;
public byte Lxr_tid() {return Xop_lxr_.Tid_lnke_bgn;}
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {
Xoo_protocol_itm[] ary = Xoo_protocol_itm.Ary();
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
Xoo_protocol_itm itm = ary[i];
Ctor_lxr_add(core_trie, itm.Key_w_colon_bry(), itm.Tid());
}
core_trie.Add(Bry_relative_1, new Xop_lnke_lxr(Xop_lnke_tkn.Lnke_typ_brack, Xoa_consts.Url_relative_prefix, Xoo_protocol_itm.Tid_relative_1));
core_trie.Add(Bry_relative_2, new Xop_lnke_lxr(Xop_lnke_tkn.Lnke_typ_brack, Xoa_consts.Url_relative_prefix, Xoo_protocol_itm.Tid_relative_2));
Ctor_lxr_add(core_trie, Bry_.new_a7("xowa-cmd"), Xoo_protocol_itm.Tid_xowa);
} private static final byte[] Bry_relative_1 = Bry_.new_a7("[//"), Bry_relative_2 = Bry_.new_a7("[[//");
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
private void Ctor_lxr_add(Btrie_fast_mgr core_trie, byte[] protocol_bry, byte tid) {
core_trie.Add(protocol_bry , new Xop_lnke_lxr(Xop_lnke_tkn.Lnke_typ_text, protocol_bry, tid));
core_trie.Add(Bry_.Add(Byte_ascii.Brack_bgn, protocol_bry) , new Xop_lnke_lxr(Xop_lnke_tkn.Lnke_typ_brack, protocol_bry, tid));
}
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) {
if (this.tid == Xoo_protocol_itm.Tid_xowa && !ctx.Wiki().Sys_cfg().Xowa_proto_enabled()) return ctx.Lxr_make_txt_(cur_pos);
return ctx.Lnke().MakeTkn_bgn(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, protocol, tid, lnke_typ);
}
public static final Xop_lnke_lxr _ = new Xop_lnke_lxr(); Xop_lnke_lxr() {}
}

View 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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import gplx.xowa.parsers.lnkes.*;
public class Xop_lnke_tkn extends Xop_tkn_itm_base {//20111222
public static final byte Lnke_typ_null = 0, Lnke_typ_brack = 1, Lnke_typ_text = 2, Lnke_typ_brack_dangling = 3;
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_lnke;}
public boolean Lnke_relative() {return lnke_relative;} public Xop_lnke_tkn Lnke_relative_(boolean v) {lnke_relative = v; return this;} private boolean lnke_relative;
public byte Lnke_typ() {return lnke_typ;} public Xop_lnke_tkn Lnke_typ_(byte v) {lnke_typ = v; return this;} private byte lnke_typ = Lnke_typ_null;
public byte[] Lnke_site() {return lnke_site;} public Xop_lnke_tkn Lnke_site_(byte[] v) {lnke_site = v; return this;} private byte[] lnke_site;
public byte[] Lnke_xwiki_wiki() {return lnke_xwiki_wiki;} private byte[] lnke_xwiki_wiki;
public byte[] Lnke_xwiki_page() {return lnke_xwiki_page;} private byte[] lnke_xwiki_page;
public Gfo_url_arg[] Lnke_xwiki_qargs() {return lnke_xwiki_qargs;} Gfo_url_arg[] lnke_xwiki_qargs;
public void Lnke_xwiki_(byte[] wiki, byte[] page, Gfo_url_arg[] args) {this.lnke_xwiki_wiki = wiki; this.lnke_xwiki_page = page; this.lnke_xwiki_qargs = args;}
public int Lnke_bgn() {return lnke_bgn;} private int lnke_bgn;
public int Lnke_end() {return lnke_end;} private int lnke_end;
public Xop_lnke_tkn Lnke_rng_(int bgn, int end) {lnke_bgn = bgn; lnke_end = end; return this;}
public byte[] Protocol() {return protocol;} private byte[] protocol;
public byte Proto_tid() {return proto_tid;} private byte proto_tid;
public Xop_lnke_tkn Subs_add_ary(Xop_tkn_itm... ary) {for (Xop_tkn_itm itm : ary) super.Subs_add(itm); return this;}
public Xop_lnke_tkn(int bgn, int end, byte[] protocol, byte proto_tid, byte lnke_typ, int lnke_bgn, int lnke_end) {
this.Tkn_ini_pos(false, bgn, end); this.protocol = protocol; this.proto_tid = proto_tid; this.lnke_typ = lnke_typ; this.lnke_bgn = lnke_bgn; this.lnke_end = lnke_end;
} Xop_lnke_tkn() {}
}

View File

@@ -0,0 +1,306 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import gplx.xowa.apps.progs.*; import gplx.xowa.net.*; import gplx.xowa.wikis.xwikis.*;
public class Xop_lnke_wkr implements Xop_ctx_wkr {
public void Ctor_ctx(Xop_ctx ctx) {url_parser = ctx.App().Utl__url_parser().Url_parser();} Gfo_url_parser url_parser; Gfo_url_site_data site_data = new Gfo_url_site_data(); Xoa_url_parser xo_url_parser = new Xoa_url_parser(); Xoa_url xo_url_parser_url = Xoa_url.blank_();
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 boolean Dangling_goes_on_stack() {return dangling_goes_on_stack;} public void Dangling_goes_on_stack_(boolean v) {dangling_goes_on_stack = v;} private boolean dangling_goes_on_stack;
public void AutoClose(Xop_ctx ctx, byte[] src, int src_len, int bgn_pos, int cur_pos, Xop_tkn_itm tkn) {
// "[" but no "]"; EX: "[irc://a"; NOTE: lnkes that start with protocol will be ac'd in MakeTkn_bgn; EX: "http://a"
Xop_lnke_tkn bgn_tkn = (Xop_lnke_tkn)tkn;
bgn_tkn.Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack_dangling);
bgn_tkn.Src_end_(bgn_tkn.Lnke_end()); // NOTE: endPos is lnke_end, not cur_pos or src_len; EX: "[irc://a b", lnk ends at a, not b; NOTE: still bgns at [
ctx.Msg_log().Add_itm_none(Xop_lnke_log.Dangling, src, tkn.Src_bgn(), cur_pos);
}
public static final String Str_xowa_protocol = "xowa-cmd:";
public static final byte[] Bry_xowa_protocol = Bry_.new_a7(Str_xowa_protocol);
public int MakeTkn_bgn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, byte[] protocol, byte proto_tid, byte lnke_type) {
boolean lnke_type_brack = (lnke_type == Xop_lnke_tkn.Lnke_typ_brack);
if ( !lnke_type_brack // lnke doesn't have "["; EX: "ttl:"
&& !Valid_text_lnke(ctx, src, src_len, bgn_pos, cur_pos) // tkn is part of work; EX: " ttl:" vs "attl:"
)
return ctx.Lxr_make_txt_(cur_pos - 1); // -1 to ignore ":" in making text colon; needed to process ":" for list like "; attl: b" PAGE:de.w:Mord_(Deutschland)#Besonders_verwerfliche_Begehungsweise; DATE:2015-01-09
if (ctx.Stack_get_typ(Xop_tkn_itm_.Tid_lnke) != null) return ctx.Lxr_make_txt_(cur_pos); // no nested lnke; return cur lnke as text; EX: "[irc://a irc://b]" -> "<a href='irc:a'>irc:b</a>"
if (proto_tid == Xoo_protocol_itm.Tid_xowa) return Make_tkn_xowa(ctx, tkn_mkr, root, src, src_len, bgn_pos, cur_pos, protocol, proto_tid, lnke_type);
// HACK: need to disable lnke if enclosing type is lnki and (1) arg is "link=" or (2) in 1st arg; basically, only enable for caption tkns (and preferably, thumb only) (which should be neither 1 or 2)
if (ctx.Cur_tkn_tid() == Xop_tkn_itm_.Tid_lnki && lnke_type == Xop_lnke_tkn.Lnke_typ_text) {
byte mode = Lnki_linkMode_init;
int lnki_pipe_count = 0;
int tkn_idx = -1;
for (int i = root.Subs_len() - 1; i > -1; i--) {
Xop_tkn_itm link_tkn = root.Subs_get(i);
tkn_idx = i;
switch (link_tkn.Tkn_tid()) {
case Xop_tkn_itm_.Tid_pipe:
if (mode == Lnki_linkMode_text) {ctx.Lxr_make_(false); return bgn_pos + 1;} // +1 to position after lnke_hook; EX:[[File:A.png|link=http:b.org]] position at t in http so http hook won't be invoked.
else {i = -1; ++lnki_pipe_count;}
break;
case Xop_tkn_itm_.Tid_txt:
if (mode == Lnki_linkMode_eq) mode = Lnki_linkMode_text;
// else i = -1; // DELETE: do not be overly strict; need to handle pattern of link=http://a.org?b=http://c.org; DATE:2013-02-03
break;
case Xop_tkn_itm_.Tid_eq:
if (mode == Lnki_linkMode_init) mode = Lnki_linkMode_eq;
// else i = -1; // DELETE: do not be overly strict; need to handle pattern of link=http://a.org?b=http://c.org; DATE:2013-02-03
break;
case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab:
break;
}
}
if (lnki_pipe_count == 0) {
for (int i = tkn_idx; i > -1; i--) {
Xop_tkn_itm link_tkn = root.Subs_get(i);
tkn_idx = i;
switch (link_tkn.Tkn_tid()) {
// case Xop_tkn_itm_.Tid_txt: return cur_pos; // REMOVED:2012-11-12: was causing [[http://a.org a]] [[http://b.org b]] to fail; PAGE:en.w:Template:Infobox_country
case Xop_tkn_itm_.Tid_space: case Xop_tkn_itm_.Tid_tab: break;
}
}
}
}
int lnke_bgn = bgn_pos, lnke_end = -1, brack_end_pos = -1;
int lnke_end_tid = End_tid_null;
while (true) { // loop until lnke_end_tid char;
if (cur_pos == src_len) {lnke_end_tid = End_tid_eos; lnke_end = cur_pos; break;}
switch (src[cur_pos]) {
case Byte_ascii.Brack_end:
if (lnke_type_brack) { // NOTE: check that frame begins with [ in order to end with ]
lnke_end_tid = End_tid_brack; brack_end_pos = cur_pos + Xoa_prog_mgr.Adj_next_char;
}
else { // NOTE: frame does not begin with [ but ] encountered. mark "invalid" in order to force parser to stop before "]"
lnke_end_tid = End_tid_invalid;
}
break;
case Byte_ascii.Space: lnke_end_tid = End_tid_space; break;
case Byte_ascii.Nl: lnke_end_tid = End_tid_nl; break;
case Byte_ascii.Gt: case Byte_ascii.Lt:
lnke_end_tid = End_tid_invalid;
break;
case Byte_ascii.Apos:
if (cur_pos + 1 < src_len && src[cur_pos + 1] == Byte_ascii.Apos) // NOTE: '' breaks link, but not '; EX: [http://a.org''b'']]; DATE:2013-03-18
lnke_end_tid = End_tid_invalid;
break;
case Byte_ascii.Brack_bgn: // NOTE: always stop lnke at "[" regardless of brack_type; EX: [http:a.org[[B]]] and http:a.org[[B]]; DATE:2014-07-11
case Byte_ascii.Quote: // NOTE: quote should also stop lnke; DATE:2014-10-10
lnke_end_tid = End_tid_symbol;
break;
}
if (lnke_end_tid == End_tid_null) cur_pos++;
else {
lnke_end = cur_pos;
cur_pos++;
break;
}
}
if (lnke_type_brack) {
switch (lnke_end_tid) {
case End_tid_eos:
if (brack_end_pos == -1) { // eos but no ]; EX: "[irc://a"
if (dangling_goes_on_stack) { // added for Xow_popup_parser which needs to handle dangling lnke due to block_len; DATE:2014-06-20
ctx.Subs_add_and_stack(root, tkn_mkr.Txt(bgn_pos, src_len)); // note that tkn doesn't matter, as Xow_popup_parser only cares *if* something is on stack, not *what* is on stack
return src_len;
}
ctx.Subs_add(root, tkn_mkr.Txt(bgn_pos, bgn_pos + 1));// convert open brack to txt; // FUTURE: don't make brack_tkn; just flag
bgn_pos += 1;
brack_end_pos = cur_pos;
lnke_bgn = bgn_pos;
lnke_type = Xop_lnke_tkn.Lnke_typ_brack_dangling;
}
break;
case End_tid_nl:
lnke_type = Xop_lnke_tkn.Lnke_typ_brack_dangling;
return ctx.Lxr_make_txt_(lnke_end); // textify lnk; EX: [irc://a\n] textifies "[irc://a"
default:
lnke_bgn += proto_tid == Xoo_protocol_itm.Tid_relative_2 ? 2 : 1; // if Tid_relative_2, then starts with [[; adjust by 2; EX:"[[//en" should have lnke_bgn at "//en", not "[//en"
lnke_type = Xop_lnke_tkn.Lnke_typ_brack;
break;
}
}
else { // else, plain text
brack_end_pos = lnke_end;
lnke_type = Xop_lnke_tkn.Lnke_typ_text;
if (ctx.Cur_tkn_tid() == Xop_tkn_itm_.Tid_lnki) { // SEE:NOTE_1
Xop_tkn_itm prv_tkn = root.Subs_get(root.Subs_len() - 1); // get last tkn
if (prv_tkn.Tkn_tid() == Xop_tkn_itm_.Tid_lnki) { // is tkn lnki?
root.Subs_del_after(prv_tkn.Tkn_sub_idx()); // delete [[ tkn and replace with [ tkn
root.Subs_add(tkn_mkr.Txt(prv_tkn.Src_bgn(), prv_tkn.Src_bgn() + 1));
ctx.Stack_pop_last(); // don't forget to remove from stack
lnke_type = Xop_lnke_tkn.Lnke_typ_brack; // change lnke_typee to brack
--bgn_pos;
}
}
}
if (proto_tid == Xoo_protocol_itm.Tid_relative_2) // for "[[//", add "["; rest of code handles "[//" normally, but still want to include literal "["; DATE:2013-02-02
ctx.Subs_add(root, tkn_mkr.Txt(lnke_bgn - 1, lnke_bgn));
url_parser.Parse_site_fast(site_data, src, lnke_bgn, lnke_end);
int site_bgn = site_data.Site_bgn(), site_end = site_data.Site_end();
if (site_bgn == site_end) return ctx.Lxr_make_txt_(cur_pos); // empty proto should return text, not lnke; EX: "http:", "http://", "[http://]"; DATE:2014-10-09
int adj = Ignore_punctuation_at_end(src, site_bgn, lnke_end);
if (adj != 0) {
lnke_end -= adj;
brack_end_pos -= adj;
cur_pos -= adj;
}
Xop_lnke_tkn tkn = tkn_mkr.Lnke(bgn_pos, brack_end_pos, protocol, proto_tid, lnke_type, lnke_bgn, lnke_end);
tkn.Lnke_relative_(site_data.Rel());
Xow_xwiki_itm xwiki = ctx.App().Usere().Wiki().Xwiki_mgr().Get_by_mid(src, site_bgn, site_end); // NOTE: check User_wiki.Xwiki_mgr, not App.Wiki_mgr() b/c only it is guaranteed to know all wikis on system
if (xwiki != null) { // lnke is to an xwiki; EX: [http://en.wikipedia.org/A a]
Xowe_wiki wiki = ctx.Wiki();
Xoa_url_parser.Parse_url(xo_url_parser_url, ctx.App(), wiki, src, lnke_bgn, lnke_end, false);
byte[] xwiki_wiki = xo_url_parser_url.Wiki_bry();
byte[] xwiki_page = xo_url_parser_url.Page_bry();
byte[] ttl_bry = xo_url_parser_url.Page_bry();
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, ttl_bry);
if (ttl != null && ttl.Wik_itm() != null) {
xwiki_wiki = ttl.Wik_itm().Domain_bry();
xwiki_page = ttl.Page_url();
}
tkn.Lnke_xwiki_(xwiki_wiki, xwiki_page, xo_url_parser_url.Args());
}
ctx.Subs_add(root, tkn);
if (lnke_type == Xop_lnke_tkn.Lnke_typ_brack) {
if (lnke_end_tid == End_tid_brack) {
tkn.Src_end_(cur_pos);
tkn.Subs_move(root);
return cur_pos;
}
ctx.Stack_add(tkn);
if (lnke_end_tid == End_tid_invalid) {
return cur_pos - 1; // -1 to return before < or >
}
}
else {
switch (lnke_end_tid) {
case End_tid_space:
ctx.Subs_add(root, tkn_mkr.Space(root, cur_pos - 1, cur_pos));
break;
case End_tid_symbol:
case End_tid_nl:
case End_tid_invalid: // NOTE that cur_pos is set after <, must subtract 1 else </xnde> will be ignored; EX: <span>irc://a</span>
return cur_pos - 1;
}
}
return cur_pos;
}
private static int Ignore_punctuation_at_end(byte[] src, int proto_end, int lnke_end) { // DATE:2014-10-09
int rv = 0;
int pos = lnke_end - 1; // -1 b/c pos is after char; EX: "abc" has pos of 3; need --pos to start at src[2] = 'c'
byte paren_bgn_chk = Bool_.__byte;
while (pos >= proto_end) {
byte b = src[pos];
switch (b) { // REF.MW: $sep = ',;\.:!?';
case Byte_ascii.Comma: case Byte_ascii.Semic: case Byte_ascii.Backslash: case Byte_ascii.Dot:
case Byte_ascii.Bang: case Byte_ascii.Question:
break;
case Byte_ascii.Colon: // differentiate between "http:" (don't trim) and "http://a.org:" (trim)
if (pos == proto_end -1) return rv;
break;
case Byte_ascii.Paren_end: // differentiate between "(http://a.org)" (trim) and "http://a.org/b(c)" (don't trim)
if (paren_bgn_chk == Bool_.__byte) {
int paren_bgn_pos = Bry_finder.Find_fwd(src, Byte_ascii.Paren_bgn, proto_end, lnke_end);
paren_bgn_chk = paren_bgn_pos == Bry_finder.Not_found ? Bool_.N_byte : Bool_.Y_byte;
}
if (paren_bgn_chk == Bool_.Y_byte) // "(" found; do not ignore ")"
return rv;
else
break;
default:
return rv;
}
--pos;
++rv;
}
return rv;
}
private static final byte Lnki_linkMode_init = 0, Lnki_linkMode_eq = 1, Lnki_linkMode_text = 2;
private static final byte End_tid_null = 0, End_tid_eos = 1, End_tid_brack = 2, End_tid_space = 3, End_tid_nl = 4, End_tid_symbol = 5, End_tid_invalid = 6;
public int MakeTkn_end(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(); // BLOCK:invalid_ttl_check; // TODO: backout apos changes
// 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()) { // always invalid
// ctx.Stack_pop_last();
// return Xop_lnki_wkr_.Invalidate_lnki(ctx, src, root, lnki, bgn_pos);
// }
// }
int lnke_bgn_idx = ctx.Stack_idx_typ(Xop_tkn_itm_.Tid_lnke);
if (lnke_bgn_idx == -1) return ctx.Lxr_make_txt_(cur_pos); // no lnke_bgn tkn; occurs when just ]; EX: "a]b"
Xop_lnke_tkn bgnTkn = (Xop_lnke_tkn)ctx.Stack_pop_til(root, src, lnke_bgn_idx, false, bgn_pos, cur_pos, Xop_tkn_itm_.Tid_lnke);
bgnTkn.Src_end_(cur_pos);
bgnTkn.Subs_move(root);
return cur_pos;
}
private static boolean Valid_text_lnke(Xop_ctx ctx, byte[] src, int src_len, int bgn_pos, int cur_pos) {
if (bgn_pos == Xop_parser_.Doc_bgn_char_0) return true; // lnke starts at 0; always true
int prv_pos = bgn_pos - 1;
byte prv_byte = src[prv_pos];
switch (prv_byte) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e:
case Byte_ascii.Ltr_f: case Byte_ascii.Ltr_g: case Byte_ascii.Ltr_h: case Byte_ascii.Ltr_i: case Byte_ascii.Ltr_j:
case Byte_ascii.Ltr_k: case Byte_ascii.Ltr_l: case Byte_ascii.Ltr_m: case Byte_ascii.Ltr_n: case Byte_ascii.Ltr_o:
case Byte_ascii.Ltr_p: case Byte_ascii.Ltr_q: case Byte_ascii.Ltr_r: case Byte_ascii.Ltr_s: case Byte_ascii.Ltr_t:
case Byte_ascii.Ltr_u: case Byte_ascii.Ltr_v: case Byte_ascii.Ltr_w: case Byte_ascii.Ltr_x: case Byte_ascii.Ltr_y: case Byte_ascii.Ltr_z:
return false; // alpha-numerical is invalid; EX: "titel:" should not generate a lnke for "tel:"
}
if (prv_byte >= Byte_ascii.Ascii_min && prv_byte <= Byte_ascii.Ascii_max) return true; // consider all other ASCII chars as true; EX: \t\n !, etc;
prv_pos = gplx.intl.Utf8_.Get_pos0_of_char_bwd(src, prv_pos);
prv_byte = src[prv_pos];
boolean prv_char_is_letter = ctx.Lang().Case_mgr().Match_any_exists(prv_byte, src, prv_pos, bgn_pos);
return !prv_char_is_letter;
}
private int Make_tkn_xowa(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos, byte[] protocol, byte proto_tid, byte lnke_type) {
// NOTE: fmt is [xowa-cmd:^"app.setup_mgr.import_wiki('');"^ ]
if (lnke_type != Xop_lnke_tkn.Lnke_typ_brack) return ctx.Lxr_make_txt_(cur_pos); // NOTE: must check for [ or else C:\xowa\ will cause it to evaluate as lnke
int proto_end_pos = cur_pos + 1; // +1 to skip past :
int lhs_dlm_pos = Bry_finder.Find_fwd(src, Byte_ascii.Quote, proto_end_pos, src_len); if (lhs_dlm_pos == Bry_.NotFound) return ctx.Lxr_make_txt_(cur_pos);
int lnke_bgn_pos = lhs_dlm_pos + 1;
byte[] rhs_dlm_bry = Bry_quote;
if (lhs_dlm_pos - proto_end_pos > 0) {
Bry_bfr bfr = ctx.App().Utl__bfr_mkr().Get_k004();
rhs_dlm_bry = bfr.Add(Bry_quote).Add_mid(src, proto_end_pos, lhs_dlm_pos).Xto_bry_and_clear();
bfr.Mkr_rls();
}
int rhs_dlm_pos = Bry_finder.Find_fwd(src, rhs_dlm_bry, lnke_bgn_pos, src_len); if (rhs_dlm_pos == Bry_.NotFound) return ctx.Lxr_make_txt_(cur_pos);
int txt_bgn = Bry_finder.Find_fwd_while_space_or_tab(src, rhs_dlm_pos + rhs_dlm_bry.length, src_len); if (txt_bgn == Bry_.NotFound) return ctx.Lxr_make_txt_(cur_pos);
int txt_end = Bry_finder.Find_fwd(src, Byte_ascii.Brack_end, txt_bgn, src_len); if (txt_end == Bry_.NotFound) return ctx.Lxr_make_txt_(cur_pos);
int end_pos = txt_end + 1; // +1 to place after ]
Xop_lnke_tkn tkn = tkn_mkr.Lnke(bgn_pos, end_pos, protocol, proto_tid, lnke_type, lnke_bgn_pos, rhs_dlm_pos); // +1 to ignore [
ctx.Subs_add(root, tkn);
tkn.Subs_add(tkn_mkr.Txt(txt_bgn, txt_end));
return end_pos;
} private static final byte[] Bry_quote = new byte[] {Byte_ascii.Quote};
}
/*
NOTE_1
lnke takes precedence over lnki.
EX: [[irc://a b]]
pass: [<a href="irc://a">b</a>] i.e. [b] where b is a lnke with caption b and trg of irc://a
fail: <a href="irc://a">b</a> i.e. b where b is a lnki with caption b and trg of irc://a
*/

View File

@@ -0,0 +1,94 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xop_lnke_wkr_brack_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Brace_noText() {
fxt.Test_parse_page_wiki("[irc://a]", fxt.tkn_lnke_(0, 9).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack).Lnke_rng_(1, 8));
}
@Test public void Brace_eos() {
fxt.Test_parse_page_wiki("[irc://a", fxt.tkn_txt_(0, 1), fxt.tkn_lnke_(1, 8).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack_dangling).Lnke_rng_(1, 8));
}
@Test public void Brace_text() {
fxt.Test_parse_page_wiki("[irc://a b c]", fxt.tkn_lnke_(0, 13).Lnke_rng_(1, 8).Subs_(fxt.tkn_txt_(9, 10), fxt.tkn_space_(10, 11), fxt.tkn_txt_(11, 12)));
}
@Test public void Brace_lt() {
fxt.Init_log_(Xop_xnde_log.Eos_while_closing_tag).Test_parse_page_wiki("[irc://a<b c]", fxt.tkn_lnke_(0, 13).Lnke_rng_(1, 8).Subs_(fxt.tkn_txt_(8, 10), fxt.tkn_space_(10, 11), fxt.tkn_txt_(11, 12)));
}
@Test public void Brace_xnde_bgn() {// PURPOSE: occurred at ref of UK; a {{cite web|url=http://www.abc.gov/{{dead link|date=December 2011}}|title=UK}} b
fxt.Test_parse_page_wiki_str
( "[http://b.org<sup>c</sup>]"
, "<a href=\"http://b.org\" class=\"external text\" rel=\"nofollow\"><sup>c</sup></a>"
);
}
@Test public void Brace_newLine() {
fxt.Test_parse_page_wiki("[irc://a\n]", fxt.tkn_txt_(0, 8), fxt.tkn_nl_char_len1_(8), fxt.tkn_txt_(9, 10));
}
@Test public void Html_brack() {
fxt.Test_parse_page_wiki_str("[irc://a]", "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">[1]</a>");
}
@Test public void Apos() {
fxt.Test_parse_page_wiki_str("[http://www.a.org''b'']", "<a href=\"http://www.a.org\" class=\"external text\" rel=\"nofollow\"><i>b</i></a>");
fxt.Test_parse_page_wiki_str("[http://www.a.org'b]", "<a href=\"http://www.a.org'b\" class=\"external text\" rel=\"nofollow\">[1]</a>");
}
@Test public void Nowiki() {
fxt.Test_parse_page_all_str
( "<nowiki>http://a.org</nowiki>"
, "http://a.org"
);
}
@Test public void Lnki_one() { // PURPOSE: parallel test for "http://a.org[[B]]"; DATE:2014-07-11
fxt.Test_parse_page_wiki_str
( "[http://a.org b [[C]] d]"
,String_.Concat_lines_nl_skip_last
( "<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">b <a href=\"/wiki/C\">C</a> d</a>"
));
}
@Test public void Encode_xwiki() { // PURPOSE: href title and args should always be encoded; PAGE:en.w:List_of_Category_A_listed_buildings_in_West_Lothian DATE:2014-07-15
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("commons.wikimedia.org"), Bry_.new_u8("commons.wikimedia.org"));
fxt.Test_parse_page_wiki_str // encode page
( "[http://commons.wikimedia.org/%22%3E_A B]"
, "<a href=\"/site/commons.wikimedia.org/wiki/%22%3E_A\">B</a>" // '%22%3E' not '">'
);
fxt.Test_parse_page_wiki_str // encode args
( "[http://commons.wikimedia.org/A?b=%22%3E_C D]"
, "<a href=\"/site/commons.wikimedia.org/wiki/A?b=%22%3E_C\">D</a>" // '%22%3E' not '">'
);
}
@Test public void Encode_basic() { // PURPOSE: counterpart to Encode_xwiki; DATE:2014-07-15
fxt.Test_parse_page_wiki_str // encode page
( "[http://a.org/%22%3E_A B]"
, "<a href=\"http://a.org/%22%3E_A\" class=\"external text\" rel=\"nofollow\">B</a>" // '%22%3E' not '">'
);
fxt.Test_parse_page_wiki_str // encode args
( "[http://a.org/A?b=%22%3E_C D]"
, "<a href=\"http://a.org/A?b=%22%3E_C\" class=\"external text\" rel=\"nofollow\">D</a>" // '%22%3E' not '">'
);
}
@Test public void Encode_relative() { // PURPOSE: counterpart to Encode_xwiki; DATE:2014-07-15
fxt.Test_parse_page_wiki_str // encode page
( "[//a.org/%22%3E_A B]"
, "<a href=\"http://a.org/%22%3E_A\" class=\"external text\" rel=\"nofollow\">B</a>" // '%22%3E' not '">'
);
fxt.Test_parse_page_wiki_str // encode args
( "[//a.org/A?b=%22%3E_C D]"
, "<a href=\"http://a.org/A?b=%22%3E_C\" class=\"external text\" rel=\"nofollow\">D</a>" // '%22%3E' not '">'
);
}
}

View File

@@ -0,0 +1,39 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xop_lnke_wkr_dangling_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Dangling_eos() {
fxt.Test_parse_page_wiki("[irc://a b"
, fxt.tkn_lnke_(0, 8).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack_dangling)
, fxt.tkn_txt_(9, 10)
);
}
@Test public void Dangling_newLine() {
fxt.Test_parse_page_wiki("[irc://a b\nc]"
, fxt.tkn_lnke_(0, 8).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack_dangling)
, fxt.tkn_txt_(9, 10)
, fxt.tkn_nl_char_len1_(10)
, fxt.tkn_txt_(11, 13)
);
}
@Test public void Dangling_gt() {
fxt.Test_parse_page_wiki("[irc://a>b c]", fxt.tkn_lnke_(0, 13).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_brack).Subs_(fxt.tkn_txt_(8, 10), fxt.tkn_space_(10, 11), fxt.tkn_txt_(11, 12)));
}
}

View File

@@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xop_lnke_wkr_relative_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Relative_obj() {
fxt.Test_parse_page_wiki("[//a b]"
, fxt.tkn_lnke_(0, 7).Lnke_rng_(1, 4).Subs_(fxt.tkn_txt_(5, 6))
);
}
@Test public void Relative_external() {
fxt.Test_parse_page_wiki_str("[//www.a.org a]", "<a href=\"http://www.a.org\" class=\"external text\" rel=\"nofollow\">a</a>");
}
@Test public void Relative_internal() {
fxt.Init_xwiki_add_user_("en.wikipedia.org");
fxt.Test_parse_page_wiki_str("[//en.wikipedia.org/wiki Wikipedia]", "<a href=\"/site/en.wikipedia.org/wiki/\">Wikipedia</a>");
}
@Test public void Relative_w_category() { // EX: [//commons.wikimedia.org/wiki/Category:Diomedeidae A]
fxt.Init_xwiki_add_user_("en.wikipedia.org");
fxt.Test_parse_page_wiki_str("[//en.wikipedia.org/wiki/Category:A A]", "<a href=\"/site/en.wikipedia.org/wiki/Category:A\">A</a>");
}
@Test public void Relurl() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("en.wikipedia.org"), Bry_.new_u8("en.wikipedia.org"));
fxt.Test_parse_page_wiki_str("[[//en.wikipedia.org/ a]]", "[<a href=\"/site/en.wikipedia.org/wiki/\">a</a>]");
}
}

View File

@@ -0,0 +1,99 @@
/*
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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*; import gplx.xowa.langs.cases.*;
public class Xop_lnke_wkr_text_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Text_obj() {
fxt.Test_parse_page_wiki("irc://a", fxt.tkn_lnke_(0, 7).Lnke_typ_(Xop_lnke_tkn.Lnke_typ_text).Lnke_rng_(0, 7));
}
@Test public void Text_html() {
fxt.Test_parse_page_wiki_str("irc://a", "<a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">irc://a</a>");
}
@Test public void Text_after() {
fxt.Test_parse_page_wiki("irc://a b c", fxt.tkn_lnke_(0, 7).Lnke_rng_(0, 7), fxt.tkn_space_(7, 8), fxt.tkn_txt_(8, 9), fxt.tkn_space_(9, 10), fxt.tkn_txt_(10, 11));
}
@Test public void Text_before_ascii() { // PURPOSE: free form external urls should not match if preceded by letters; EX:de.w:Sylvie_und_Bruno; DATE:2014-05-11
fxt.Ctx().Lang().Case_mgr_utf8_();
String expd_lnke_html = "<a href=\"tel:a\" class=\"external text\" rel=\"nofollow\">tel:a</a>";
fxt.Test_parse_page_wiki_str("titel:a" , "titel:a");
fxt.Test_parse_page_wiki_str(" tel:a" , " " + expd_lnke_html);
fxt.Test_parse_page_wiki_str("!tel:a" , "!" + expd_lnke_html);
fxt.Test_parse_page_wiki_str("ätel:a" , "ätel:a");
fxt.Test_parse_page_wiki_str("€tel:a" , "" + expd_lnke_html);
}
@Test public void Invalid_lnki_and_list_dt_dd() { // PURPOSE: invalid lnke should still allow processing of ":" in list <dd>; PAGE:de.w:Mord_(Deutschland)#Besonders_verwerfliche_Begehungsweise DATE:2015-01-08
fxt.Test_parse_page_wiki_str("; atel: b" , String_.Concat_lines_nl_skip_last
( "<dl>"
, " <dt> atel"
, " </dt>"
, " <dd> b"
, " </dd>"
, "</dl>"
));
}
@Test public void Xnde() {// NOTE: compare to Brace_lt
fxt.Test_parse_page_wiki("<span>irc://a</span>"
, fxt.tkn_xnde_(0, 20).Subs_
( fxt.tkn_lnke_(6, 13)
)
);
}
@Test public void List() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "*irc://a"
, "*irc://b"
),String_.Concat_lines_nl_skip_last
( "<ul>"
, " <li><a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">irc://a</a>"
, " </li>"
, " <li><a href=\"irc://b\" class=\"external text\" rel=\"nofollow\">irc://b</a>"
, " </li>"
, "</ul>"
));
}
@Test public void Defect_reverse_caption_link() { // PURPOSE: bad lnke formatting (caption before link); ] should show up at end, but only [ shows up; PAGE:en.w:Paul Philippoteaux; [caption http://www.americanheritage.com]
fxt.Test_parse_page_wiki_str("[caption irc://a]", "[caption <a href=\"irc://a\" class=\"external text\" rel=\"nofollow\">irc://a</a>]");
}
@Test public void Lnki() { // PURPOSE: trailing lnki should not get absorbed into lnke; DATE:2014-07-11
fxt.Test_parse_page_wiki_str
( "http://a.org[[B]]" // NOTE: [[ should create another lnki
,String_.Concat_lines_nl_skip_last
( "<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">http://a.org</a><a href=\"/wiki/B\">B</a>"
));
}
@Test public void Protocol_only() { // PURPOSE: protocol only should return text; DATE:2014-10-09
fxt.Test_parse_page_wiki_str("http://" , "http://");
fxt.Test_parse_page_wiki_str("http:" , "http:");
fxt.Test_parse_page_wiki_str("[http://]" , "[http://]");
fxt.Test_parse_page_wiki_str("[http:]" , "[http:]");
}
@Test public void Ignore_punctuation_at_end() { // PURPOSE: ignore "," and related punctuation at end; DATE:2014-10-09
fxt.Test_parse_page_wiki_str("http://a.org," , "<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">http://a.org</a>,"); // basic
fxt.Test_parse_page_wiki_str("http://a.org,," , "<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">http://a.org</a>,,"); // many
fxt.Test_parse_page_wiki_str("http://a.org/b,c" , "<a href=\"http://a.org/b,c\" class=\"external text\" rel=\"nofollow\">http://a.org/b,c</a>"); // do not ignore if in middle
fxt.Test_parse_page_wiki_str("http://a.org:" , "<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">http://a.org</a>:"); // colon at end; compare to "http:"
}
@Test public void Ignore_punctuation_at_end__paren_end() { // PURPOSE: end parent has special rules; DATE:2014-10-10
fxt.Test_parse_page_wiki_str("(http://a.org)" , "(<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">http://a.org</a>)"); // trim=y
fxt.Test_parse_page_wiki_str("http://a.org/b(c)", "<a href=\"http://a.org/b(c)\" class=\"external text\" rel=\"nofollow\">http://a.org/b(c)</a>"); // trim=n
}
@Test public void Sym_quote() { // PURPOSE: quote should interrupt lnke; DATE:2014-10-10
fxt.Test_parse_page_wiki_str("http://a.org/b\"c", "<a href=\"http://a.org/b\" class=\"external text\" rel=\"nofollow\">http://a.org/b</a>&quot;c");
}
}

View 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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xop_lnke_wkr_uncommon_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Err_multiple() {
fxt.Test_parse_page_wiki("[irc://a][irc://b]"
, fxt.tkn_lnke_(0, 9)
, fxt.tkn_lnke_(9, 18)
);
}
@Test public void Err_txt_is_protocol() {
fxt.Test_parse_page_wiki("[irc://a irc://b]"
, fxt.tkn_lnke_(0, 17).Lnke_rng_(1, 8).Subs_(fxt.tkn_txt_(9, 16))
);
}
@Test public void Lnke_should_precede_lnki() { // PURPOSE: [[ should not be interpreted as lnki if [irc is available
fxt.Test_parse_page_wiki("[[irc://a/b c]]"
, fxt.tkn_txt_(0, 1)
, fxt.tkn_lnke_(1, 14).Subs_
( fxt.tkn_txt_(12, 13)
)
, fxt.tkn_txt_(14, 15)
);
}
@Test public void Defect_2nd_consecutive_lnke() { // PURPOSE: bad code that was causing lnkes to show up; PAGE:en.w:Template:Infobox_country;
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "[[http://a.org a]] [[http://b.org b]]"
), String_.Concat_lines_nl_skip_last
( "[<a href=\"http://a.org\" class=\"external text\" rel=\"nofollow\">a</a>] [<a href=\"http://b.org\" class=\"external text\" rel=\"nofollow\">b</a>]"
));
}
}

View 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.parsers.lnkes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xop_lnke_wkr_xwiki_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Xwiki() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("en.wikipedia.org"), Bry_.new_u8("en.wikipedia.org"));
fxt.Test_parse_page_wiki_str("[http://en.wikipedia.org/wiki/A a]", "<a href=\"/site/en.wikipedia.org/wiki/A\">a</a>");
}
@Test public void Xwiki_relative() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("en.wikipedia.org"), Bry_.new_u8("en.wikipedia.org"));
fxt.Test_parse_page_wiki_str("[//en.wikipedia.org/ a]", "<a href=\"/site/en.wikipedia.org/wiki/\">a</a>");
}
@Test public void Xwiki_qarg() {// DATE:2013-02-02
fxt.Init_xwiki_add_user_("en.wikipedia.org");
fxt.Test_parse_page_wiki_str("http://en.wikipedia.org/wiki/Special:Allpages?from=Earth", "<a href=\"/site/en.wikipedia.org/wiki/Special:Allpages?from=Earth\">http://en.wikipedia.org/wiki/Special:Allpages?from=Earth</a>");
}
@Test public void Lang_prefix() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("en.wikipedia.org"), Bry_.new_u8("en.wikipedia.org"));
fxt.Wiki().Xwiki_mgr().Add_full(Bry_.new_a7("fr"), Bry_.new_a7("fr.wikipedia.org"));
fxt.Test_parse_page_wiki_str("[http://en.wikipedia.org/wiki/fr:A a]", "<a href=\"/site/fr.wikipedia.org/wiki/A\">a</a>");
}
@Test public void Xwiki_query_arg() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_u8("en.wikipedia.org"), Bry_.new_u8("en.wikipedia.org"));
fxt.Test_parse_page_wiki_str("[http://en.wikipedia.org/wiki/A?action=edit a]", "<a href=\"/site/en.wikipedia.org/wiki/A?action=edit\">a</a>");
}
}