v3.3.4 v3.6.4.1
gnosygnu 8 years ago
parent 8afc115176
commit b3c2d3bb5f

@ -24,6 +24,7 @@ public class Io_zip_compress_cmd__jre {
public Io_zip_compress_cmd__jre Make_new() {return new Io_zip_compress_cmd__jre();}
public byte Exec_hook(gplx.core.progs.Gfo_prog_ui prog_ui, Io_url[] src_urls, Io_url trg_url, String resume_name, long resume_file, long resume_item) {
OutputStream trg_out_stream;
Io_mgr.Instance.CreateDirIfAbsent(trg_url.OwnerDir());
try {trg_out_stream = new FileOutputStream(trg_url.Xto_api());}
catch (Exception e) {throw Err_.new_exc(e, "io", "trg open failed", "url", trg_url.Raw());}
ZipOutputStream trg_stream = new ZipOutputStream(trg_out_stream);

@ -37,6 +37,7 @@ public class Gftest {
throw Err_.new_wo_type(bfr.To_str_and_clear());
}
}
public static void Eq__str(String expd, byte[] actl) {Eq__str(expd, String_.new_u8(actl), null);}
public static void Eq__str(String expd, String actl) {Eq__str(expd, actl, null);}
public static void Eq__str(String expd, String actl, String msg_fmt, Object... msg_args) {
if (String_.Eq(expd, actl)) return;
@ -64,6 +65,16 @@ public class Gftest {
bfr.Add(Bry__line_end);
throw Err_.new_wo_type(bfr.To_str_and_clear());
}
public static void Eq__bool_y(boolean actl) {Eq__bool(Bool_.Y, actl, null);}
public static void Eq__bool(boolean expd, boolean actl) {Eq__bool(expd, actl, null);}
public static void Eq__bool(boolean expd, boolean actl, String msg_fmt, Object... msg_args) {
if (expd == actl) return;
Write_fail_head(bfr, msg_fmt, msg_args);
bfr.Add_str_a7("expd: ").Add_bool(expd).Add_byte_nl();
bfr.Add_str_a7("actl: ").Add_bool(actl).Add_byte_nl();
bfr.Add(Bry__line_end);
throw Err_.new_wo_type(bfr.To_str_and_clear());
}
public static void Eq__double(double expd, double actl) {Eq__double(expd, actl, null);}
public static void Eq__double(double expd, double actl, String msg_fmt, Object... msg_args) {
if (expd == actl) return;

@ -20,7 +20,7 @@ import java.io.*;
import java.net.*;
import gplx.core.progs.*;
public class Http_download_wkr__jre extends Http_download_wkr__base {
public Http_download_wkr Make_new() {return this;}
public Http_download_wkr Make_new() {return new Http_download_wkr__jre();}
@Override public byte Exec_hook(Gfo_prog_ui prog_ui, String src_url, Io_url trg_url, long downloaded) {
long prog_data_cur = downloaded;
boolean prog_resumed = prog_data_cur > 0;

@ -37,6 +37,11 @@ public class Gfh_tag_ {
, Id__br = 14
, Id__hr = 15
, Id__td = 16
, Id__pre = 17
, Id__small = 18
, Id__i = 19
, Id__b = 20
, Id__sup = 21
;
public static final byte[]
Bry__a = Bry_.new_a7("a")
@ -64,6 +69,11 @@ public class Gfh_tag_ {
.Add_str_int("li" , Id__li)
.Add_str_int("td" , Id__td)
.Add_str_int("p" , Id__p)
.Add_str_int("pre" , Id__pre)
.Add_str_int("small" , Id__small)
.Add_str_int("i" , Id__i)
.Add_str_int("b" , Id__b)
.Add_str_int("sup" , Id__sup)
;
public static String To_str(int tid) {
switch (tid) {
@ -86,6 +96,11 @@ public class Gfh_tag_ {
case Id__td: return "td";
case Id__ul: return "ul";
case Id__li: return "li";
case Id__pre: return "pre";
case Id__small: return "small";
case Id__i: return "i";
case Id__b: return "b";
case Id__sup: return "sup";
default: throw Err_.new_unhandled(tid);
}
}

@ -33,6 +33,9 @@ public class Gfh_tag_rdr {
tag__eos.Init(this, src, Bool_.N, Bool_.N, src_end, src_end, src_end, src_end, Gfh_tag_.Id__eos, Bry_.Empty);
err_wkr.Init_by_page(String_.new_u8(ctx_name), src);
}
public void Src_rng_(int src_bgn, int src_end) {
this.pos = src_bgn; this.src_end = src_end;
}
public int Pos() {return pos;} private int pos;
public void Pos_(int v) {this.pos = v;}
public void Atrs__make(Mwh_atr_wkr atr_wkr, int head_bgn, int head_end) {atr_parser.Parse(atr_wkr, -1, -1, src, head_bgn, head_end);}
@ -58,6 +61,11 @@ public class Gfh_tag_rdr {
while (tmp != stop_pos) {
if (src[tmp] == Byte_ascii.Angle_bgn) {
rv = Tag__extract(move, tail, match_name_id, tmp);
if (rv.Name_id() == Gfh_tag_.Id__comment) { // ignore comments DATE:2016-06-25
tmp = rv.Src_end();
rv = null; // null rv, else rv will still be comment and may get returned to caller
continue;
}
if (Tag__match(move, bwd, tail, match_name_id, tmp_depth, rv))
break;
else {
@ -82,12 +90,7 @@ public class Gfh_tag_rdr {
if ( tag_name_id != match_name_id // tag doesn't match requested
&& match_name_id != Gfh_tag_.Id__any // requested is not wildcard
) return false;
if (tag_name_id == Gfh_tag_.Id__comment) {
if (match_name_id == Gfh_tag_.Id__comment)
return true;
else
return false;
}
if (tag_name_id == Gfh_tag_.Id__comment) return true; // ignore comments
int depth = depth_obj.Val();
boolean tag_is_tail = tag.Tag_is_tail();
if (tail == tag_is_tail) {
@ -141,6 +144,7 @@ public class Gfh_tag_rdr {
atrs_end = name_end;
inline = true;
loop = false;
++tag_end; // move tag_end after >
}
else {
name_end = tag_end = -1;

@ -28,7 +28,6 @@ public class Gfh_tag_rdr_tst {
}
@Test public void Comment() {
fxt.Init("1<!--2-->3<!--4-->5<div id='1'>6</div>");
fxt.Test__move_fwd_head(Gfh_tag_.Id__comment , "<!--2-->") ; fxt.Test__pos("3");
fxt.Test__move_fwd_head(Gfh_tag_.Id__any , "<div id='1'>") ; fxt.Test__pos("6");
}
@Test public void Meta() {
@ -45,6 +44,10 @@ public class Gfh_tag_rdr_tst {
fxt.Test__move_fwd_head(Gfh_tag_.Id__div , "<div>") ; fxt.Test__pos("2");
fxt.Test__move_fwd_tail(Gfh_tag_.Id__div , "</div>") ; fxt.Test__pos("6");
}
@Test public void Inline() {
fxt.Init("1<br/>2");
fxt.Test__move_fwd_head(Gfh_tag_.Id__br , "<br/>") ; fxt.Test__pos("2");
}
}
class Gfh_tag_rdr_fxt {
private final Gfh_tag_rdr rdr = Gfh_tag_rdr.New__html();

@ -34,7 +34,7 @@ public class Xoa_app_ {
}
}
public static final String Name = "xowa";
public static final String Version = "3.6.3.4";
public static final String Version = "3.6.4.1";
public static String Build_date = "2012-12-30 00:00:00";
public static String Op_sys_str;
public static String User_agent = "";

@ -29,4 +29,6 @@ public interface Xoa_page {
Xoa_page__commons_mgr Commons_mgr();
void Xtn_gallery_packed_exists_y_();
boolean Xtn__timeline_exists();
boolean Xtn__gallery_exists();
}

@ -26,7 +26,7 @@ public class Xoae_page implements Xoa_page {
this.wiki = wiki; this.ttl = ttl;
this.lang = wiki.Lang(); // default to wiki.lang; can be override later by wikitext
hdr_mgr = new Xow_hdr_mgr(this);
redlink_list = new Xopg_lnki_list(ttl.Ns().Id_is_module());
redlink_list = new Xopg_lnki_list().Disabled_(ttl.Ns().Id_is_module());
Ttl_(ttl);
} Xoae_page() {} // called by Empty
public Xow_wiki Wiki() {return wiki;}
@ -35,6 +35,8 @@ public class Xoae_page implements Xoa_page {
public byte[] Url_bry_safe() {return url == null ? Bry_.Empty : url.Raw();}
public boolean Exists() {return !Missing();}
public void Xtn_gallery_packed_exists_y_() {html_data.Xtn_gallery_packed_exists_y_();}
public boolean Xtn__timeline_exists() {return false;} // drd always sets timeline
public boolean Xtn__gallery_exists() {return false;} // drd does not need to set gallery.style.css
public Xopg_revision_data Revision_data() {return revision_data;} private Xopg_revision_data revision_data = new Xopg_revision_data();
public Xopg_html_data Html_data() {return html_data;} private Xopg_html_data html_data = new Xopg_html_data();
public byte[] Redirect_to_ttl() {return redirect_to_ttl;} private byte[] redirect_to_ttl; public void Redirect_to_ttl_(byte[] v) {this.redirect_to_ttl = v;}

@ -17,10 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.centrals; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.xowa.specials.*; import gplx.xowa.htmls.bridges.*;
import gplx.xowa.addons.bldrs.infos.*;
public class Xobc_task_addon implements Xoax_addon_itm, Xoax_addon_itm__special, Xoax_addon_itm__json {
public Xow_special_page[] Special_pages() {
return new Xow_special_page[]
{ Xobc_task_special.Prototype
, Xobc_info_special.Prototype
};
}
public Bridge_cmd_itm[] Json_cmds() {

@ -19,9 +19,10 @@ package gplx.xowa.addons.bldrs.centrals; import gplx.*; import gplx.xowa.*; impo
import gplx.langs.jsons.*;
import gplx.xowa.addons.bldrs.centrals.cmds.*;
public class Xobc_task_bridge implements gplx.xowa.htmls.bridges.Bridge_cmd_itm {
public void Init_by_app(Xoa_app app) {}
private Xoa_app app;
public void Init_by_app(Xoa_app app) {this.app = app;}
public String Exec(Json_nde data) {
Xobc_task_mgr task_mgr = Xobc_task_special.Task_mgr;
Xobc_task_mgr task_mgr = Xobc_task_special.Task_mgr(app);
byte proc_id = proc_hash.Get_as_byte_or(data.Get_as_bry_or(Msg__proc, null), Byte_ascii.Max_7_bit);
Json_nde args = data.Get_kv(Msg__args).Val_as_nde();
switch (proc_id) {

@ -36,7 +36,6 @@ class Xobc_task_html extends Xow_special_wtr__base {
head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xobc.css")));
head_tags.Add(Xopg_tag_itm.New_htm_frag(addon_dir.GenSubFil_nest("bin", "xobc.row.mustache.html"), "xobc.row"));
head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.log.js")));
head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.ajax.listener.js")));
head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.app.js")));
head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", Get_app_js_file(app))));
head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.elem.js")));

@ -18,16 +18,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.addons.bldrs.centrals; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
public class Xobc_task_special implements Xow_special_page {
public static Xobc_task_mgr Task_mgr;
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
// init task_mgr
page.Html_data().Cbk_enabled_(true); // apply cbk_enabled early to capture logging statements
Xoa_app app = wiki.App();
if (Task_mgr == null) Task_mgr = New_task_mgr(app);
Task_mgr.Load_or_init();
if (task_mgr == null) task_mgr = New_task_mgr(app);
task_mgr.Load_or_init();
new Xobc_task_html().Bld_page_by_mustache(app, page, this);
}
public static Xobc_task_mgr Task_mgr(Xoa_app app) {
if (task_mgr == null) {
task_mgr = New_task_mgr(app);
}
return task_mgr;
} private static Xobc_task_mgr task_mgr;
private static Xobc_task_mgr New_task_mgr(Xoa_app app) {
Io_url data_db_url = app.Fsys_mgr().Bin_addon_dir().GenSubFil_nest("bldr", "central", "bldr_central.data_db.xowa");
app.User().User_db_mgr().Init_site_mgr();

@ -54,14 +54,4 @@ public class Xobc_data_db {
tbl__import_step.Delete(step_id);
}
}
private final gplx.core.lists.hashs.Hash_adp__int host_hash = new gplx.core.lists.hashs.Hash_adp__int();
public String Bld_src_http_url(gplx.core.brys.evals.Bry_eval_mgr eval_mgr, int host_id, String file_name) {
Xobc_host_regy_itm host_itm = (Xobc_host_regy_itm)host_hash.Get_by_or_null(host_id);
if (host_itm == null) {
host_itm = tbl__host_regy.Select(host_id);
host_hash.Add(host_id, host_itm);
}
String host_dir = String_.new_u8(eval_mgr.Eval(Bry_.new_u8(host_itm.Host_data_dir())));
return String_.Format("http://{0}/{1}/{2}", host_itm.Host_domain(), host_dir, file_name);
}
}

@ -68,6 +68,16 @@ public class Xobc_step_map_tbl implements Db_tbl {
} finally {rdr.Rls();}
throw Err_.new_("", "xobc:could not find next sort", "task_id", task_id);
}
public List_adp Select_all(int task_id) {
List_adp rv = List_adp_.New();
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_task_id).Crt_int(fld_task_id, task_id).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
rv.Add(rdr.Read_int("step_id"));
}
} finally {rdr.Rls();}
return rv;
}
public void Insert(int sm_id, int task_id, int step_id, int step_seqn) {
if (insert_stmt == null) insert_stmt = conn.Stmt_insert(tbl_name, flds);
insert_stmt.Clear().Val_int(fld_sm_id, sm_id).Val_int(fld_task_id, task_id).Val_int(fld_step_id, step_id).Val_int(fld_step_seqn, step_seqn)

@ -56,6 +56,11 @@ public class Xobc_task_regy_tbl implements Db_tbl {
try {return rdr.Move_next() ? rdr.Read_int(fld_task_id) : -1;}
finally {rdr.Rls();}
}
public String Select_key_by_id_or_null(int id) {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_task_id).Crt_int(fld_task_id, id).Exec_select__rls_auto();
try {return rdr.Move_next() ? rdr.Read_str(fld_task_key) : null;}
finally {rdr.Rls();}
}
public void Insert(int task_id, int task_seqn, int step_count, String task_key, String task_name) {
if (insert_stmt == null) insert_stmt = conn.Stmt_insert(tbl_name, flds);
insert_stmt.Clear().Val_int(fld_task_id, task_id).Val_int(fld_task_seqn, task_seqn).Val_int(fld_step_count, step_count)

@ -0,0 +1,46 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.centrals.hosts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*;
import gplx.core.brys.evals.*;
import gplx.xowa.wikis.domains.*;
public class Host_eval_itm {
private final Bry_eval_mgr mgr = Bry_eval_mgr.Dflt();
private final Host_eval_wkr wkr = new Host_eval_wkr();
private final Hash_adp host_hash = Hash_adp_.New();
public Host_eval_itm() {
mgr.Add_many(wkr);
}
public byte[] Eval_dir_name(Xow_domain_itm domain_itm) {
wkr.Domain_itm_(domain_itm);
return mgr.Eval(Bry_.new_u8("Xowa_~{host_regy|wiki_abrv}_latest"));
}
public String Eval_src_fil(Xobc_data_db data_db, int host_id, Xow_domain_itm domain, String file_name) {
return Eval_src_dir(data_db, host_id, domain) + file_name;
}
public String Eval_src_dir(Xobc_data_db data_db, int host_id, Xow_domain_itm domain) {
Xobc_host_regy_itm host_itm = (Xobc_host_regy_itm)host_hash.Get_by(host_id);
if (host_itm == null) {
host_itm = data_db.Tbl__host_regy().Select(host_id);
host_hash.Add(host_id, host_itm);
}
wkr.Domain_itm_(domain);
String host_dir = String_.new_u8(mgr.Eval(Bry_.new_u8(host_itm.Host_data_dir())));
return String_.Format("http://{0}/{1}/", host_itm.Host_domain(), host_dir);
}
}

@ -15,18 +15,23 @@ 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.addons.bldrs.centrals.utils; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
package gplx.xowa.addons.bldrs.centrals.hosts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
import gplx.core.brys.evals.*;
import gplx.xowa.wikis.domains.*;
public class Bry_eval_wkr__host_regy implements Bry_eval_wkr {
public class Host_eval_wkr implements Bry_eval_wkr {
private Xow_domain_itm domain_itm;
public String Key() {return "host_regy";}
public Bry_eval_wkr__host_regy Domain_itm_(Xow_domain_itm domain_itm) {this.domain_itm = domain_itm; return this;}
public Host_eval_wkr Domain_itm_(Xow_domain_itm domain_itm) {this.domain_itm = domain_itm; return this;}
public void Resolve(Bry_bfr rv, byte[] src, int args_bgn, int args_end) {
// EX: "~{host_regy|wiki_abrv}" -> "enwiki"
int type = hash.Get_as_byte_or(src, args_bgn, args_end, Byte_.Max_value_127);
switch (type) {
case Type__wiki_abrv: rv.Add(domain_itm.Abrv_wm()); break;
case Type__wiki_abrv:
byte[] lang_key = domain_itm.Lang_orig_key();
if (lang_key == Bry_.Empty) lang_key = Bry_.new_a7("en"); // handle species
rv.Add(lang_key);
rv.Add_str_a7("wiki");
break;
default: throw Err_.new_unhandled_default(type);
}
}

@ -0,0 +1,32 @@
/*
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.addons.bldrs.centrals.hosts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
import org.junit.*; import gplx.core.tests.*; import gplx.xowa.wikis.domains.*;
public class Host_eval_wkr__tst {
private final Host_eval_wkr__fxt fxt = new Host_eval_wkr__fxt();
@Test public void En_w() {fxt.Test__resolve_quick("en.wikipedia.org" , "Xowa_enwiki_latest");}
@Test public void Fr_d() {fxt.Test__resolve_quick("fr.wiktionary.org" , "Xowa_frwiki_latest");}
@Test public void Species() {fxt.Test__resolve_quick("species.wikimedia.org" , "Xowa_enwiki_latest");}
}
class Host_eval_wkr__fxt {
public void Test__resolve_quick(String domain_str, String expd) {
Host_eval_itm eval_itm = new Host_eval_itm();
Xow_domain_itm domain_itm = Xow_domain_itm_.parse(Bry_.new_u8(domain_str));
Gftest.Eq__bry(Bry_.new_u8(expd), eval_itm.Eval_dir_name(domain_itm));
}
}

@ -18,19 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.addons.bldrs.centrals.steps; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
import gplx.core.brys.evals.*; import gplx.core.primitives.*;
import gplx.xowa.addons.bldrs.centrals.tasks.*; import gplx.xowa.addons.bldrs.centrals.cmds.*; import gplx.xowa.addons.bldrs.centrals.steps.*; import gplx.xowa.addons.bldrs.centrals.utils.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*; import gplx.xowa.addons.bldrs.centrals.hosts.*;
import gplx.xowa.addons.bldrs.exports.merges.*;
import gplx.xowa.wikis.domains.*;
public class Xobc_step_factory {
private final Xobc_task_mgr task_mgr;
private final Xobc_data_db data_db;
private final Bry_eval_mgr eval_mgr = Bry_eval_mgr.Dflt(), eval_mgr__host_regy = Bry_eval_mgr.Dflt();
private final Bry_eval_wkr__host_regy eval_wkr__host_regy = new Bry_eval_wkr__host_regy();
private final Bry_eval_mgr eval_mgr = Bry_eval_mgr.Dflt(); private final Host_eval_itm host_eval = new Host_eval_itm();
private final Host_eval_wkr eval_wkr__host_regy = new Host_eval_wkr();
public Xobc_step_factory(Xobc_task_mgr task_mgr, Xobc_data_db data_db, Io_url wiki_dir) {
this.task_mgr = task_mgr;
this.data_db = data_db;
eval_mgr.Add_many(new Bry_eval_wkr__builder_central(wiki_dir));
eval_mgr__host_regy.Add_many(eval_wkr__host_regy);
}
public void Load(Xobc_task_itm task, int step_id, int cmd_idx) {
int step_type = data_db.Tbl__step_regy().Select_type(step_id);
@ -57,7 +56,7 @@ public class Xobc_step_factory {
String file_name = import_itm.Import_name;
step_name.Val_(file_name);
eval_wkr__host_regy.Domain_itm_(domain_itm);
String src_http_url = data_db.Bld_src_http_url(eval_mgr__host_regy, import_itm.Host_id, file_name);
String src_http_url = host_eval.Eval_src_fil(data_db, import_itm.Host_id, domain_itm, file_name);
Io_url zip_file_url = Eval_url(Bry_eval_wkr__builder_central.Make_str(Bry_eval_wkr__builder_central.Type__download_fil, wiki_domain, file_name));
Io_url unzip_dir_url = Eval_url(Bry_eval_wkr__builder_central.Make_str(Bry_eval_wkr__builder_central.Type__unzip_dir, wiki_domain, file_name));
Io_url wiki_dir_url = Eval_url(Bry_eval_wkr__builder_central.Make_str(Bry_eval_wkr__builder_central.Type__wiki_dir, wiki_domain, file_name));

@ -18,11 +18,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.addons.bldrs.exports.packs.files; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.exports.*; import gplx.xowa.addons.bldrs.exports.packs.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
public class Pack_file_bldr_cmd extends Xob_cmd__base {
private Io_url deploy_dir;
public Pack_file_bldr_cmd(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
@Override public void Cmd_run() {
new Pack_file_mgr().Exec(wiki);
new Pack_file_mgr().Exec(wiki, deploy_dir);
}
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk__deploy_dir_)) deploy_dir = m.ReadIoUrl("v");
else return super.Invk (ctx, ikey, k, m);
return this;
}
private static final String Invk__deploy_dir_ = "deploy_dir_";
public static final String BLDR_CMD_KEY = "bldr.export.pack.file";
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
public static final Xob_cmd Prototype = new Pack_file_bldr_cmd(null, null);

@ -18,9 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.addons.bldrs.exports.packs.files; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.exports.*; import gplx.xowa.addons.bldrs.exports.packs.*;
import gplx.core.progs.*; import gplx.core.ios.zips.*; import gplx.core.ios.streams.*; import gplx.core.security.*;
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.fsdb.*; import gplx.fsdb.meta.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*; import gplx.xowa.addons.bldrs.centrals.steps.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*; import gplx.xowa.addons.bldrs.centrals.steps.*; import gplx.xowa.addons.bldrs.centrals.hosts.*;
class Pack_file_mgr {
public void Exec(Xowe_wiki wiki) {
public void Exec(Xowe_wiki wiki, Io_url deploy_dir) {
// init
wiki.Init_assert();
Io_url wiki_dir = wiki.Fsys_mgr().Root_dir();
@ -53,6 +53,24 @@ class Pack_file_mgr {
Make_task(tmp_bfr, wiki, wiki_date, bc_db, hash, "html", Xobc_import_type.Tid__wiki__core, Xobc_import_type.Tid__wiki__srch, Xobc_import_type.Tid__wiki__html);
Make_task(tmp_bfr, wiki, wiki_date, bc_db, hash, "file", Xobc_import_type.Tid__file__core, Xobc_import_type.Tid__file__data);
bc_conn.Txn_end();
// deploy
if (deploy_dir != null) {
Host_eval_itm host_eval = new Host_eval_itm();
int len = hash.Len();
for (int i = 0; i < len; ++i) {
Pack_list list = (Pack_list)hash.Get_at(i);
int list_len = list.Len();
for (int j = 0; j < list_len; ++j) {
Pack_itm itm = (Pack_itm)list.Get_at(j);
byte[] owner_dir = host_eval.Eval_dir_name(wiki.Domain_itm());
Io_url src_url = itm.Zip_url();
Io_url trg_url = deploy_dir.GenSubFil_nest(String_.new_u8(owner_dir), src_url.NameAndExt());
Io_mgr.Instance.MoveFil_args(src_url, trg_url, true).Exec();
}
}
Io_mgr.Instance.Delete_dir_empty(pack_dir);
}
}
private static void Make_task(Bry_bfr tmp_bfr, Xow_wiki wiki, String wiki_date, Xobc_data_db bc_db, Pack_hash hash, String task_type, int... list_tids) {
// get packs
@ -86,7 +104,10 @@ class Pack_file_mgr {
}
}
public static String Build_task_name(Bry_bfr tmp_bfr, Xow_wiki wiki, String wiki_date, String task_type, long raw_len) {// Simple Wikipedia - Articles (2016-06) [420.31 MB]
byte[] lang_name = gplx.xowa.langs.Xol_lang_stub_.Get_by_key_or_null(wiki.Domain_itm().Lang_orig_key()).Canonical_name(); // EX: Deutsch
byte[] lang_key = wiki.Domain_itm().Lang_orig_key();
byte[] lang_name = Bry_.Len_eq_0(lang_key) // species.wikimedia.org and other wikimedia wikis have no lang;
? Bry_.Empty
: Bry_.Add(gplx.xowa.langs.Xol_lang_stub_.Get_by_key_or_null(lang_key).Canonical_name(), Byte_ascii.Space); // EX: "Deutsch "
byte[] wiki_name = wiki.Domain_itm().Domain_type().Display_bry(); // EX: Wikipedia
String type_name = String_.Eq(task_type, "html") ? "Articles" : "Images";
wiki_date = String_.Replace(wiki_date, ".", "-");

@ -0,0 +1,51 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.langs.mustaches.*;
class Xobc_info_doc implements Mustache_doc_itm {
private final byte[] wiki_domain, task_size;
private final String wiki_dir, torrent_fil;
private final Mustache_doc_itm[] urls;
public Xobc_info_doc(byte[] wiki_domain, String wiki_dir, byte[] task_size, String torrent_fil, Mustache_doc_itm[] urls) {
this.wiki_domain = wiki_domain; this.wiki_dir = wiki_dir; this.task_size = task_size; this.torrent_fil = torrent_fil; this.urls = urls;
}
public boolean Mustache__write(String key, Mustache_bfr bfr) {
if (String_.Eq(key, "wiki_domain")) bfr.Add_bry(wiki_domain);
else if (String_.Eq(key, "wiki_dir")) bfr.Add_str_u8(wiki_dir);
else if (String_.Eq(key, "task_size")) bfr.Add_bry(task_size);
else if (String_.Eq(key, "torrent_fil")) bfr.Add_str_u8(torrent_fil);
return false;
}
public Mustache_doc_itm[] Mustache__subs(String key) {
if (String_.Eq(key, "urls")) return urls;
return Mustache_doc_itm_.Ary__empty;
}
}
class Xobc_info_url implements Mustache_doc_itm {
private final String url; private final byte[] size;
public Xobc_info_url(String url, byte[] size) {
this.url = url; this.size = size;
}
public boolean Mustache__write(String key, Mustache_bfr bfr) {
if (String_.Eq(key, "url")) bfr.Add_str_u8(url);
else if (String_.Eq(key, "size")) bfr.Add_bry(size);
else return false;
return true;
}
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
}

@ -0,0 +1,89 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.xowa.specials.*; import gplx.langs.mustaches.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.tags.*;
import gplx.xowa.addons.bldrs.centrals.*; import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*; import gplx.xowa.addons.bldrs.centrals.hosts.*;
import gplx.xowa.wikis.domains.*; import gplx.core.ios.*;
class Xobc_info_html extends Xow_special_wtr__base {
private final Xobc_task_mgr task_mgr;
private final int task_id;
public Xobc_info_html(Xobc_task_mgr task_mgr, int task_id) {this.task_mgr = task_mgr; this.task_id = task_id;}
@Override protected Io_url Get_addon_dir(Xoa_app app) {return app.Fsys_mgr().Http_root().GenSubDir_nest("bin", "any", "xowa", "addon", "bldr", "info");}
@Override protected Io_url Get_mustache_fil(Io_url addon_dir) {return addon_dir.GenSubFil_nest("bin", "xobc_info.mustache.html");}
@Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) {
// get steps for task
Xobc_data_db data_db = task_mgr.Data_db();
List_adp list = data_db.Tbl__step_map().Select_all(task_id);
// get underlying files
Host_eval_itm host_eval = new Host_eval_itm();
int len = list.Len();
Xobc_info_url[] step_urls = new Xobc_info_url[len];
Xow_domain_itm wiki_domain = null;
int host_id = -1;
long total_size = 0;
Bry_bfr tmp_size_bfr = Bry_bfr_.New();
for (int i = 0; i < len; ++i) {
int step_id = (int)list.Get_at(i);
Xobc_import_step_itm step_itm = data_db.Tbl__import_step().Select_one(step_id);
if (i == 0) {
wiki_domain = Xow_abrv_xo_.To_itm(step_itm.Wiki_abrv()); // ASSUME: 1st step's wiki is same for all steps
host_id = step_itm.Host_id; // ASSUME: 1st step's host_id is same for all steps
}
String src_fil = host_eval.Eval_src_fil(data_db, host_id, wiki_domain, step_itm.Import_name);
Io_size_.To_bfr_new(tmp_size_bfr, step_itm.Import_size_zip, 2);
total_size += step_itm.Import_size_raw;
Xobc_info_url step_url = new Xobc_info_url(src_fil, tmp_size_bfr.To_bry_and_clear());
step_urls[i] = step_url;
}
// get wiki data, total_size
host_eval.Eval_dir_name(wiki_domain);
Io_url trg_dir = app.Fsys_mgr().Wiki_dir().GenSubDir(wiki_domain.Domain_str());
Io_size_.To_bfr_new(tmp_size_bfr, total_size, 2);
byte[] total_size_bry = tmp_size_bfr.To_bry_and_clear();
// get torrent
String torrent_fil = null;
String key = data_db.Tbl__task_regy().Select_key_by_id_or_null(task_id);
if (key == null) torrent_fil = "failed to get torrent for " + Int_.To_str(task_id);
else {// convert task_key to name; en.wikipedia.org|2016.06|html
String src_dir = host_eval.Eval_src_dir(data_db, host_id, wiki_domain);
String[] ary = String_.Split(key, "|");
ary[0] = String_.new_u8(wiki_domain.Abrv_wm());
torrent_fil = String_.Format("{0}/Xowa_{1}_{2}_{3}.torrent", src_dir, ary[0], ary[1], ary[2]); // EX: http://archive.org/download/Xowa_enwiki_latest/Xowa_enwiktionary_2016-06_core.zip
}
return new Xobc_info_doc
( wiki_domain.Domain_bry()
, trg_dir.Raw()
, total_size_bry
, torrent_fil
, step_urls
);
}
@Override protected void Bld_tags(Xoa_app app, Io_url addon_dir, Xopage_html_data page_data) {
Xopg_tag_mgr head_tags = page_data.Head_tags();
Xopg_tag_wtr_.Add__xocss (head_tags, app.Fsys_mgr().Http_root());
Xopg_tag_wtr_.Add__xohelp (head_tags, app.Fsys_mgr().Http_root());
head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xobc_info.css")));
}
@Override protected void Handle_invalid(Xoa_app app, Xoa_page page, Xow_special_page special) {
new Xopage_html_data(special.Special__meta().Display_ttl(), Bry_.new_u8("task has been deleted")).Apply(page);
}
}

@ -0,0 +1,35 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
import gplx.xowa.addons.bldrs.centrals.*;
public class Xobc_info_special implements Xow_special_page {
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
Gfo_qarg_mgr url_args = new Gfo_qarg_mgr().Init(url.Qargs_ary());
int task_id = url_args.Read_int_or("task_id", -1);
if (task_id == -1) return;
new Xobc_info_html(Xobc_task_special.Task_mgr(wiki.App()), task_id).Bld_page_by_mustache(wiki.App(), page, this);
}
Xobc_info_special(Xow_special_meta special__meta) {this.special__meta = special__meta;}
public Xow_special_meta Special__meta() {return special__meta;} private final Xow_special_meta special__meta;
public Xow_special_page Special__clone() {return this;}
public static final Xow_special_page Prototype = new Xobc_info_special(Xow_special_meta.New_xo("XowaDownloadCentralInfo", "Download Central Task Info"));
}

@ -16,34 +16,56 @@ 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.addons.servers.https; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.servers.*;
import gplx.core.envs.*;
public class Http_long_poll_cmd implements gplx.xowa.htmls.bridges.Bridge_cmd_itm {
private final List_adp msgs = List_adp_.New();
private long send_time_prv = 0;
public int Sleep_interval = 100;
public int Send_interval = 1000;
private boolean active;
public void Init_by_app(Xoa_app app) {
app.Gui__cbk_mgr().Reg(Xog_cbk_wkr__http.Instance);
}
public void Send_msg(String msg) {
synchronized (msgs) {
msgs.Add(msg);
}
}
public String Exec(gplx.langs.jsons.Json_nde data) {
// NOTE: this class is a singleton and only supports one user; need to track multiple requests by having http_server track incoming users
synchronized (msgs) {
if (active) return "polling";
}
// check if already active; if so, return;
while (true) {
if (msgs.Len() == 0) {
// get msgs in queue
int msgs_len = 0;
synchronized (msgs) {
active = true;
msgs_len = msgs.Len();
}
// no messages
if (msgs_len == 0) {
gplx.core.threads.Thread_adp_.Sleep(Sleep_interval);
continue;
}
else {
long send_time_cur = gplx.core.envs.Env_.TickCount();
if (send_time_cur - send_time_prv > Send_interval) {
send_time_prv = send_time_cur;
// message found; exit loop;
break;
}
// return commands
String[] rv = null;
synchronized (msgs) {
rv = msgs.To_str_ary_and_clear();
active = false;
}
}
return String_.Concat_lines_nl(msgs.To_str_ary_and_clear());
return String_.Concat_lines_nl(rv);
}
public byte[] Key() {return BRIDGE_KEY;} private static final byte[] BRIDGE_KEY = Bry_.new_a7("long_poll");
public static final Http_long_poll_cmd Instance = new Http_long_poll_cmd(); Http_long_poll_cmd() {}
private static final int
Sleep_interval = 100
;
}

@ -56,6 +56,7 @@ public class Xod_page_mgr {
// generate special
Xoh_page page = new Xoh_page();
page.Init(wiki, Xoa_url.new_(wiki.Domain_bry(), ttl.Page_db()), ttl, 1); // NOTE: init page to set url, ttl; DATE:2016-06-23
try {proto.Special__clone().Special__gen(wiki, page, url, ttl);}
catch (Exception e) {Gfo_log_.Instance.Warn("failed to generate special page", "url", url.To_str(), "err", Err_.Message_gplx_log(e)); return rv;}

@ -33,25 +33,6 @@ public class Load_page_wkr implements Gfo_thread_wkr {
// wait_for_popups; free mem check;
this.page = wiki.Page_mgr().Load_page(url, ttl, tab);
// DELETE:v3.6.4
// Xoa_app_.Usr_dlg().Log_many("", "", "page.load: url=~{0}", url.To_str());
// Wait_for_popups();
// Xowe_wiki_.Rls_mem_if_needed(wiki);
//
// // load page meta; wait_for_popups
// this.page = wiki.Data_mgr().Load_page_and_parse(url, ttl, wiki.Lang(), tab, false);
// boolean hdump_exists = page.Revision_data().Html_db_id() != -1 && wiki.Appe().Api_root().Wiki().Hdump().Read_preferred();
// page.Html_data().Hdump_exists_(hdump_exists);
// Wait_for_popups();
//
// // load page text
// boolean parse = true;
// if (hdump_exists) {
// wiki.Html__hdump_mgr().Load_mgr().Load_by_edit(page);
// parse = Bry_.Len_eq_0(page.Hdump_data().Body()); // NOTE: need to check if actually empty
// }
// if (parse)
// wiki.Parser_mgr().Parse(page, false);
// launch thread to show page
Gfo_invk_.Invk_by_val(tab.Cmd_sync(), Xog_tab_itm.Invk_show_url_loaded_swt, this);
@ -64,12 +45,6 @@ public class Load_page_wkr implements Gfo_thread_wkr {
Running_(false);
}
}
// DELETE:v3.6.4
// private static void Wait_for_popups() {// HACK: wait for popups to finish, else thread errors due to popups and loader mutating cached items
// int wait_count = 0;
// while (gplx.xowa.htmls.modules.popups.Xow_popup_mgr.Running() && ++wait_count < 100)
// Thread_adp_.Sleep(10);
// }
private static final Object thread_lock = new Object(); private static boolean running = false;
public static boolean Running() {
boolean rv = false;

@ -220,62 +220,6 @@ public class Xog_tab_itm implements Gfo_invk {
wkr.Wiki().Appe().Thread_mgr_old().Page_load_mgr().Resume();
}
}
// DELETE:v3.6.4
// public void Async() {
// if (page == null) return; // TEST: occurs during Xog_win_mgr_tst
// Xowe_wiki wiki = page.Wikie(); Xoae_app app = wiki.Appe(); Xog_win_itm win_itm = tab_mgr.Win(); Gfo_usr_dlg usr_dlg = win_itm.Usr_dlg();
// app.Usr_dlg().Log_many("", "", "page.async: url=~{0}", page.Url().To_str());
// if (page.Url().Anch_str() != null) html_itm.Scroll_page_by_id_gui(page.Url().Anch_str());
// if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;}
// int xfer_len = 0;
// xfer_len = page.File_queue().Count();
// String page_ttl_str = String_.new_u8(page.Ttl().Raw());
// if (xfer_len > 0){
// usr_dlg.Prog_one("", "", "downloading images: ~{0}", xfer_len);
// try {
// page.File_queue().Exec(wiki, page);
// if (page.Html_data().Xtn_gallery_packed_exists()) // packed_gallery exists; fire js once; PAGE:en.w:National_Sculpture_Museum_(Valladolid); DATE:2014-07-21
// html_itm.Html_gallery_packed_exec();
// if ( page.Html_data().Xtn_imap_exists() // imap exists; DATE:2014-08-07
// && page.Html_data().Head_mgr().Itm__popups().Enabled()
// )
// html_itm.Html_popups_bind_hover_to_doc(); // rebind all elements to popup
// }
// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.image: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));}
// }
// xfer_len = page.File_math().Count();
// if (xfer_len > 0){
// try {
// usr_dlg.Prog_one("", "", "generating math: ~{0}", xfer_len);
// for (int i = 0; i < xfer_len; i++) {
// if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;}
// gplx.xowa.xtns.math.Xof_math_itm itm = (gplx.xowa.xtns.math.Xof_math_itm)page.File_math().Get_at(i);
// String queue_msg = usr_dlg.Prog_many("", "", "generating math ~{0} of ~{1}: ~{2}", i + List_adp_.Base1, xfer_len, String_.new_u8(itm.Math()));
// app.File_mgr().Math_mgr().MakePng(itm.Math(), itm.Hash(), itm.Png_url(), queue_msg);
// gplx.gfui.SizeAdp size = app.File_mgr().Img_mgr().Wkr_query_img_size().Exec(itm.Png_url());
// html_itm.Html_img_update("xowa_math_img_" + itm.Id(), itm.Png_url().To_http_file_str(), size.Width(), size.Height());
// html_itm.Html_elem_delete("xowa_math_txt_" + itm.Id());
// }
// page.File_math().Clear();
// }
// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.math: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));}
// }
// if (page.Html_cmd_mgr().Count() > 0) {
// try {page.Html_cmd_mgr().Exec(app, page);}
// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cmds: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));}
// }
// try {
// if (page.Tab_data().Tab() != null) { // needed b/c Preview has page.Tab of null which causes null_ref error in redlinks
// Xopg_redlink_mgr redlinks_wkr = new Xopg_redlink_mgr(page, html_itm);
// Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_page_redlink, redlinks_wkr, gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Invk_run);
// usr_dlg.Prog_none("", "imgs.done", "");
// }
// } catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.redlinks: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));}
// try {app.File_mgr().Cache_mgr().Compress_check();}
// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cache: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));}
// app.Usere().User_db_mgr().Cache_mgr().Page_end(app.Wiki_mgr());
// app.Log_wtr().Queue_enabled_(false);
// }
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_show_url_loaded_swt)) this.Show_url_loaded((Load_page_wkr)m.ReadObj("v"));
else if (ctx.Match(k, Invk_show_url_failed_swt)) this.Show_url_failed((Load_page_wkr)m.ReadObj("v"));
@ -291,7 +235,6 @@ class Load_files_wkr implements Gfo_thread_wkr {
public boolean Thread__resume() {return true;}
public void Thread__exec() {
try {Xog_async_wkr.Async(tab);}
// try {tab.Async();} // DELETE:v3.6.4
catch (Exception e) {
tab.Tab_mgr().Win().App().Usr_dlg().Warn_many("error while running file wkr; page=~{0} err=~{1}", tab.Page().Url().To_str(), Err_.Message_gplx_full(e));
}

@ -68,7 +68,6 @@ public class Xog_win_itm implements Gfo_invk, Gfo_evt_itm {
else if (ctx.Match(k, Gfui_html.Evt_win_resized)) Refresh_win_size();
else if (ctx.Match(k, Invk_page_refresh)) Page__refresh();
else if (ctx.Match(k, Invk_page_async_exec)) Xog_async_wkr.Async(((Xog_tab_itm)m.ReadObj("v")));
// else if (ctx.Match(k, Invk_page_async_exec)) ((Xog_tab_itm)m.ReadObj("v")).Async(); // DELETE:v3.6.4
else if (ctx.Match(k, Invk_page_view_read)) Page__mode_(Xopg_page_.Tid_read);
else if (ctx.Match(k, Invk_page_view_edit)) Page__mode_(Xopg_page_.Tid_edit);
else if (ctx.Match(k, Invk_page_view_html)) Page__mode_(Xopg_page_.Tid_html);

@ -26,9 +26,11 @@ public class Xoh_img_mgr {
}
public int Len() {return list.Count();}
public Xof_fsdb_itm Get_at(int i) {return (Xof_fsdb_itm)list.Get_at(i);}
public Xof_fsdb_itm Make_img() {
public Xof_fsdb_itm Make_img(boolean img_is_gallery) {
Xof_fsdb_itm itm = new Xof_fsdb_itm();
itm.Init_at_hdoc(++uid_nxt, Xof_html_elem.Tid_img);
itm.Init_at_hdoc(++uid_nxt, img_is_gallery ? Xof_html_elem.Tid_gallery : Xof_html_elem.Tid_img);
if (img_is_gallery)
itm.Html_gallery_mgr_h_(gplx.xowa.xtns.gallery.Gallery_xnde.Default); // TODO:set to <gallery heights=val>; PAGE:en.w:National_Gallery_of_Art; DATE:2016-06-25
list.Add(itm);
return itm;
}

@ -40,12 +40,14 @@ public class Xoh_page implements Xoa_page {
public Ordered_hash Gallery_itms() {return gallery_itms;} private Ordered_hash gallery_itms = Ordered_hash_.New();
public Xopg_module_mgr Head_mgr() {return head_mgr;} private Xopg_module_mgr head_mgr = new Xopg_module_mgr();
public void Xtn_gallery_packed_exists_y_() {}
public boolean Xtn__timeline_exists() {return xtn__timeline_exists;} private boolean xtn__timeline_exists; public void Xtn__timeline_exists_y_() {xtn__timeline_exists = true;}
public boolean Xtn__gallery_exists() {return xtn__gallery_exists;} private boolean xtn__gallery_exists; public void Xtn__gallery_exists_y_() {xtn__gallery_exists = true;}
public Xopg_revision_data Revision_data() {return revision_data;} private Xopg_revision_data revision_data = new Xopg_revision_data();
public Xopg_html_data Html_data() {return html_data;} private Xopg_html_data html_data = new Xopg_html_data();
public byte[] Redirect_to_ttl() {return redirect_to_ttl;} private byte[] redirect_to_ttl; public void Redirect_to_ttl_(byte[] v) {this.redirect_to_ttl = v;}
// util
public Xopg_lnki_list Redlink_list() {return redlink_list;} private Xopg_lnki_list redlink_list;
public Xopg_lnki_list Redlink_list() {return redlink_list;} private Xopg_lnki_list redlink_list = new Xopg_lnki_list();
public Xoa_page__commons_mgr Commons_mgr() {return commons_mgr;} private final Xoa_page__commons_mgr commons_mgr = new Xoa_page__commons_mgr();
public int Exec_tid() {return exec_tid;} private int exec_tid = Xof_exec_tid.Tid_wiki_page;
public byte[] Html_head_xtn() {return html_head_xtn;} public void Html_head_xtn_(byte[] v) {html_head_xtn = v;} private byte[] html_head_xtn = Bry_.Empty; // drd:web_browser
@ -53,7 +55,7 @@ public class Xoh_page implements Xoa_page {
public void Init(Xow_wiki wiki, Xoa_url page_url, Xoa_ttl page_ttl, int page_id) {
this.wiki = wiki; this.page_url = page_url; this.page_ttl = page_ttl; this.page_id = page_id;
this.Clear();
this.redlink_list = new Xopg_lnki_list(page_ttl.Ns().Id_is_module());
redlink_list.Disabled_(page_ttl.Ns().Id_is_module()); // never redlink in Module ns; particularly since Lua has multi-line comments for [[ ]]
}
public void Ctor_by_db(int head_flag, byte[] display_ttl, byte[] content_sub, byte[] sidebar_div, int zip_tid, int hzip_tid, byte[] body) {
head_mgr.Flag_(head_flag);
@ -78,5 +80,6 @@ public class Xoh_page implements Xoa_page {
img_itms = Xohd_img_itm__base.Ary_empty;
head_mgr.Clear(); gallery_itms.Clear(); redlink_uids.Clear(); commons_mgr.Clear();
section_mgr.Clear(); img_mgr.Clear();
redlink_list.Clear();
}
}

@ -32,7 +32,7 @@ public class Bridge_cmd_mgr {
catch (Exception e) {throw Err_.new_exc(e, "bridge.cmds", "invalid json", "json", jdoc_bry);}
Json_nde msg = jdoc.Root_nde();
byte[] key_bry = msg.Get_bry(Key_cmd);
Bridge_cmd_itm cmd = (Bridge_cmd_itm)cmd_hash.Get_by_bry(key_bry); if (cmd == null) throw Err_.new_("bridge.cmds", "unknown cmd", "cmd", cmd);
Bridge_cmd_itm cmd = (Bridge_cmd_itm)cmd_hash.Get_by_bry(key_bry); if (cmd == null) throw Err_.new_("bridge.cmds", "unknown cmd", "key", key_bry);
try {return cmd.Exec(msg.Get(Key_data));}
catch (Exception e) {
Xoa_app_.Usr_dlg().Warn_many("", "", "exec json failed: ~{0}", "json", jdoc_bry);

@ -83,7 +83,8 @@ public class Xow_hdump_mgr__load {
wpg_head.Itm__popups().Bind_hover_area_ (hpg_head.Imap_exists());
wpg_head.Itm__gallery().Enabled_ (hpg_head.Gallery_packed_exists());
wpg_head.Itm__hiero().Enabled_ (hpg_head.Hiero_exists());
wpg_head.Itm__timeline().Enabled_ (true);
wpg_head.Itm__timeline().Enabled_ (hpg.Xtn__timeline_exists());
wpg_head.Itm__gallery_styles().Enabled_ (hpg.Xtn__gallery_exists());
// transfer images from Xoh_page to Xoae_page
Xoh_img_mgr src_imgs = hpg.Img_mgr();

@ -295,7 +295,7 @@ public class Xoh_html_wtr {
break;
}
case Xop_xnde_tag_.Tid__timeline: {
bfr.Add_str_a7("<pre class='xowa-timeline'>");
bfr.Add(gplx.xowa.htmls.core.wkrs.addons.timelines.Xoh_timeline_data.Hook_bry);
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_open_end(), xnde.Tag_close_bgn()); // NOTE: do not embed <timeline> tag inside pre, else timeline will render in black; EX:<pre><timeline>a</timeline></pre> will fail; DATE:2014-05-22
bfr.Add_str_a7("</pre>");
break;

@ -21,7 +21,9 @@ public class Xoh_hzip_dict_ {
public static final byte Escape = Byte_.By_int(27); // SERIALIZED: 27=escape byte
public static final byte[] Escape_bry = Bry_.New_by_ints(27); // SERIALIZED
public static final int
Tid__root = 0
Tid__timeline = -10
, Tid__gallery = -11
, Tid__root = 0
, Tid__escape = 1
, Tid__xnde = 2
, Tid__lnke = 3
@ -33,7 +35,9 @@ public class Xoh_hzip_dict_ {
, Tid__img_bare = 9
;
public static final String
Key__escape = "escape"
Key__timeline = "timeline"
, Key__gallery = "gallery"
, Key__escape = "escape"
, Key__hdr = "hdr"
, Key__lnke = "lnke"
, Key__lnki = "lnki"

@ -32,14 +32,13 @@ public class Xoh_hzip_mgr implements Xoh_hzip_wkr {
public byte[] Encode_as_bry(Xoh_hzip_bfr bfr, Xow_wiki wiki, Xoh_page hpg, byte[] src) {Encode(bfr, wiki, hpg, src); return bfr.To_bry_and_clear();}
public Gfo_poolable_itm Encode1(Xoh_hzip_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, boolean wkr_is_root, byte[] src, Object data_obj) {throw Err_.new_unimplemented();}
public void Encode(Xoh_hzip_bfr bfr, Xow_wiki wiki, Xoh_page hpg, byte[] src) {
hctx.Init_by_page(wiki, hpg.Url_bry_safe());
hctx.Init_by_page(wiki, hpg);
hdoc_parser.Parse(bfr, hpg, hctx, src);
}
public void Decode(Bry_bfr bfr, Xow_wiki wiki, Xoh_page hpg, byte[] src) {
byte[] page_url = hpg.Url_bry_safe(); int src_len = src.length;
hctx.Init_by_page(wiki, page_url);
rdr.Init_by_page(page_url, src, src_len);
Decode1(bfr, hdoc_wkr, hctx, hpg, rdr, src, 0, src_len, null);
hctx.Init_by_page(wiki, hpg);
rdr.Init_by_page(hpg.Url_bry_safe(), src, src.length);
Decode1(bfr, hdoc_wkr, hctx, hpg, rdr, src, 0, src.length, null);
}
public void Decode1(Bry_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, Bry_rdr rdr, byte[] src, int src_bgn, int src_end, Xoh_data_itm data_itm) {
int pos = src_bgn, txt_bgn = -1;

@ -19,15 +19,17 @@ package gplx.xowa.htmls.core.hzips; import gplx.*; import gplx.xowa.*; import gp
import gplx.core.btries.*; import gplx.core.threads.poolables.*;
import gplx.xowa.htmls.core.wkrs.escapes.*;
import gplx.xowa.htmls.core.wkrs.hdrs.*; import gplx.xowa.htmls.core.wkrs.lnkes.*; import gplx.xowa.htmls.core.wkrs.lnkis.*; import gplx.xowa.htmls.core.wkrs.xndes.*;
import gplx.xowa.htmls.core.wkrs.imgs.*; import gplx.xowa.htmls.core.wkrs.thms.*; import gplx.xowa.htmls.core.wkrs.glys.*;
import gplx.xowa.htmls.core.wkrs.imgs.*; import gplx.xowa.htmls.core.wkrs.thms.*;
import gplx.xowa.htmls.core.wkrs.addons.timelines.*; import gplx.xowa.htmls.core.wkrs.addons.gallerys.*;
public class Xoh_pool_mgr__data {
private final Gfo_poolable_mgr pool__hdr, pool__lnke, pool__img, pool__img_bare;//, pool__gly;
private final Gfo_poolable_mgr pool__hdr, pool__lnke, pool__img, pool__img_bare, pool__timeline, pool__gallery;
public Xoh_pool_mgr__data() {
pool__hdr = New_pool(new Xoh_hdr_data());
pool__lnke = New_pool(new Xoh_lnke_data());
pool__img = New_pool(new Xoh_img_data());
pool__img_bare = New_pool(new Xoh_img_bare_data());
// pool__gly = New_pool(new Xoh_gly_grp_data());
pool__timeline = New_pool(new Xoh_timeline_data());
pool__gallery = New_pool(new Xoh_gallery_data());
}
public Xoh_data_itm Get_by_tid(int tid) {
Gfo_poolable_mgr pool = null;
@ -36,7 +38,8 @@ public class Xoh_pool_mgr__data {
case Xoh_hzip_dict_.Tid__lnke: pool = pool__lnke; break;
case Xoh_hzip_dict_.Tid__img: pool = pool__img; break;
case Xoh_hzip_dict_.Tid__img_bare: pool = pool__img_bare; break;
// case Xoh_hzip_dict_.Tid__gly: pool = pool__gly; break;
case Xoh_hzip_dict_.Tid__timeline: pool = pool__timeline; break;
case Xoh_hzip_dict_.Tid__gallery: pool = pool__gallery; break;
default: return null;
}
return (Xoh_data_itm)pool.Get_fast();

@ -20,9 +20,10 @@ import gplx.core.btries.*; import gplx.core.threads.poolables.*;
import gplx.xowa.htmls.core.wkrs.escapes.*;
import gplx.xowa.htmls.core.wkrs.hdrs.*; import gplx.xowa.htmls.core.wkrs.lnkes.*; import gplx.xowa.htmls.core.wkrs.lnkis.*; import gplx.xowa.htmls.core.wkrs.xndes.*;
import gplx.xowa.htmls.core.wkrs.imgs.*; import gplx.xowa.htmls.core.wkrs.thms.*; import gplx.xowa.htmls.core.wkrs.glys.*;
import gplx.xowa.htmls.core.wkrs.addons.timelines.*; import gplx.xowa.htmls.core.wkrs.addons.gallerys.*;
public class Xoh_pool_mgr__hzip {
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
private Gfo_poolable_mgr mkr__escape, mkr__xnde, mkr__lnke, mkr__lnki, mkr__hdr, mkr__img, mkr__thm, mkr__gly, mkr__img_bare;
private Gfo_poolable_mgr mkr__escape, mkr__xnde, mkr__lnke, mkr__lnki, mkr__hdr, mkr__img, mkr__thm, mkr__gly, mkr__img_bare, mkr__gallery, mkr__timeline;
public Xoh_escape_hzip Mw__escape() {return (Xoh_escape_hzip) mkr__escape.Get_fast();}
public Xoh_xnde_hzip Mw__xnde() {return (Xoh_xnde_hzip) mkr__xnde.Get_fast();}
public Xoh_hdr_hzip Mw__hdr() {return (Xoh_hdr_hzip) mkr__hdr.Get_fast();}
@ -32,6 +33,8 @@ public class Xoh_pool_mgr__hzip {
public Xoh_img_bare_hzip Mw__img_bare() {return (Xoh_img_bare_hzip) mkr__img_bare.Get_fast();}
public Xoh_thm_hzip Mw__thm() {return (Xoh_thm_hzip) mkr__thm.Get_fast();}
public Xoh_gly_hzip Mw__gly() {return (Xoh_gly_hzip) mkr__gly.Get_fast();}
public Xoh_gallery_hzip Mw__gallery() {return (Xoh_gallery_hzip) mkr__gallery.Get_fast();}
public Xoh_timeline_hzip Mw__timeline() {return (Xoh_timeline_hzip) mkr__timeline.Get_fast();}
public void Init() {
this.Reg_all(false, Hook__core, Hook__html, Hook__mw);
}
@ -50,6 +53,8 @@ public class Xoh_pool_mgr__hzip {
mkr__thm = Reg(New_hook_len2(mode_is_b256, hook__mw , 5) , new Xoh_thm_hzip());
mkr__gly = Reg(New_hook_len2(mode_is_b256, hook__mw , 6) , new Xoh_gly_hzip());
mkr__img_bare = Reg(New_hook_len2(mode_is_b256, hook__mw , 7) , new Xoh_img_bare_hzip());
mkr__gallery = Reg(Xoh_gallery_data.Hook_bry , new Xoh_gallery_hzip());
mkr__timeline = Reg(Xoh_timeline_data.Hook_bry , new Xoh_timeline_hzip());
}
private Gfo_poolable_mgr Reg(byte[] hook, Gfo_poolable_itm proto) {
Gfo_poolable_mgr rv = Gfo_poolable_mgr_.New(1, 32, proto, Object_.Ary(hook));

@ -19,14 +19,17 @@ package gplx.xowa.htmls.core.hzips; import gplx.*; import gplx.xowa.*; import gp
import gplx.core.brys.*; import gplx.core.threads.poolables.*;
import gplx.xowa.htmls.core.wkrs.escapes.*;
import gplx.xowa.htmls.core.wkrs.hdrs.*; import gplx.xowa.htmls.core.wkrs.lnkes.*; import gplx.xowa.htmls.core.wkrs.lnkis.*; import gplx.xowa.htmls.core.wkrs.xndes.*;
import gplx.xowa.htmls.core.wkrs.imgs.*; import gplx.xowa.htmls.core.wkrs.thms.*; import gplx.xowa.htmls.core.wkrs.glys.*;
import gplx.xowa.htmls.core.wkrs.imgs.*; import gplx.xowa.htmls.core.wkrs.thms.*;
import gplx.xowa.htmls.core.wkrs.addons.timelines.*; import gplx.xowa.htmls.core.wkrs.addons.gallerys.*;
public class Xoh_pool_mgr__wtr {
private final Gfo_poolable_mgr pool__hdr, pool__lnke, pool__img, pool__img_bare;
private final Gfo_poolable_mgr pool__hdr, pool__lnke, pool__img, pool__img_bare, pool__timeline, pool__gallery;
public Xoh_pool_mgr__wtr() {
pool__hdr = New_pool(new Xoh_hdr_wtr());
pool__lnke = New_pool(new Xoh_lnke_wtr());
pool__img = New_pool(new Xoh_img_wtr());
pool__img_bare = New_pool(new Xoh_img_bare_wtr());
pool__timeline = New_pool(new Xoh_timeline_wtr());
pool__gallery = New_pool(new Xoh_gallery_wtr());
}
public Xoh_wtr_itm Get_by_tid(int tid) {
Gfo_poolable_mgr pool = null;
@ -35,6 +38,8 @@ public class Xoh_pool_mgr__wtr {
case Xoh_hzip_dict_.Tid__lnke: pool = pool__lnke; break;
case Xoh_hzip_dict_.Tid__img: pool = pool__img; break;
case Xoh_hzip_dict_.Tid__img_bare: pool = pool__img_bare; break;
case Xoh_hzip_dict_.Tid__timeline: pool = pool__timeline; break;
case Xoh_hzip_dict_.Tid__gallery: pool = pool__gallery; break;
default: return null;
}
return (Xoh_wtr_itm)pool.Get_fast();

@ -20,7 +20,7 @@ import gplx.xowa.htmls.core.wkrs.lnkes.*;
public class Xoh_stat_itm {
public void Clear() {
a_rhs = lnki_text_n = lnki_text_y = lnke__free = lnke__auto = lnke__text = 0;
hdr_1 = hdr_2 = hdr_3 = hdr_4 = hdr_5 = hdr_6 = 0;
hdr_1 = hdr_2 = hdr_3 = hdr_4 = hdr_5 = hdr_6 = timeline = gallery = 0;
img_full = 0;
space = 0;
Bry_.Clear(escape_bry);
@ -32,6 +32,8 @@ public class Xoh_stat_itm {
public int Lnke__auto() {return lnke__auto;} public void Lnke__auto__add() {++lnke__auto;} private int lnke__auto;
public int Lnke__text() {return lnke__text;} public void Lnke__text__add() {++lnke__text;} private int lnke__text;
public int Img_full() {return img_full;} public void Img_full_add() {++img_full;} private int img_full;
public int Timeline() {return timeline;} public void Timeline_add() {++timeline;} private int timeline;
public int Gallery() {return gallery;} public void Gallery_add() {++gallery;} private int gallery;
public int Hdr_1() {return hdr_1;} private int hdr_1;
public int Hdr_2() {return hdr_2;} private int hdr_2;
public int Hdr_3() {return hdr_3;} private int hdr_3;

@ -39,7 +39,7 @@ public class Xoh_make_mgr {
this.wiki_domain = wiki_domain;
}
public byte[] Parse(byte[] src, Xoh_page hpg, Xow_wiki wiki) {
hctx.Init_by_page(wiki, hpg.Url_bry_safe());
hctx.Init_by_page(wiki, hpg);
hpg.Section_mgr().Add(0, 2, Bry_.Empty, Bry_.Empty).Content_bgn_(0); // +1 to skip \n
make_parser.Parse(bfr, hpg, hctx, src);
hpg.Section_mgr().Set_content(hpg.Section_mgr().Len() - 1, src, src.length);

@ -31,7 +31,7 @@ public class Xoh_page_chkr {
return this;
}
public Xoh_page_chkr Imgs__add(String wiki_abrv, String lnki_ttl, byte lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page) {
Xof_fsdb_itm fsdb_itm = expd_img_mgr.Make_img();
Xof_fsdb_itm fsdb_itm = expd_img_mgr.Make_img(false);
fsdb_itm.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, Bry_.new_u8(wiki_abrv), Bry_.new_u8(lnki_ttl), lnki_type, lnki_upright, lnki_w, lnki_h, lnki_time, lnki_page, Xof_patch_upright_tid_.Tid_all);
return this;
}

@ -33,6 +33,7 @@ public class Xoh_hdoc_ctx {
public boolean Xwiki_mgr__missing(byte[] domain){return app.Xwiki_mgr__missing(domain);}
public Xou_cache_finder File__mgr() {return file__mgr;} private Xou_cache_finder file__mgr = Xou_cache_finder_.Noop;
public Xof_url_bldr File__url_bldr() {return file__url_bldr;} private final Xof_url_bldr file__url_bldr = new Xof_url_bldr();
public Xoa_page Page() {return page;} private Xoa_page page;
public byte[] Page__url() {return page__url;} private byte[] page__url;
public Xoh_pool_mgr__hzip Pool_mgr__hzip() {return pool_mgr__hzip;} private final Xoh_pool_mgr__hzip pool_mgr__hzip = new Xoh_pool_mgr__hzip();
public Xoh_pool_mgr__data Pool_mgr__data() {return pool_mgr__data;} private final Xoh_pool_mgr__data pool_mgr__data = new Xoh_pool_mgr__data();
@ -53,13 +54,14 @@ public class Xoh_hdoc_ctx {
if (cache_mgr != null) file__mgr = Xou_cache_finder_.New_db(cache_mgr); // NOTE: this effectively only loads the cache db in app mode (and not in test mode)
pool_mgr__hzip.Init();
}
public void Init_by_page(Xow_wiki wiki, byte[] page_url) {
public void Init_by_page(Xow_wiki wiki, Xoa_page page) {
if (fsys__root == null) Init_by_app(wiki.App()); // LAZY INIT
this.wiki__url_parser = wiki.Utl__url_parser();
this.wiki__ttl_parser = wiki;
this.wiki__domain_bry = wiki.Domain_bry();
this.fsys__file__wiki = Bry_.Add(fsys__file, wiki__domain_bry, Byte_ascii.Slash_bry);
this.page__url = page_url;
this.page = page;
this.page__url = page.Url_bry_safe();
this.Clear();
}
private void Clear() {

@ -33,6 +33,7 @@ public class Xoh_hzip_fxt {
hpg.Init(wiki, Xoa_url.blank(), parser_fxt.Wiki().Ttl_parse(Xoa_page_.Main_page_bry), 1);
}
public Xow_wiki Wiki() {return wiki;}
public Xoa_page Page() {return hpg;}
public Xoh_hzip_fxt Init_mode_is_b256_(boolean v) {bfr.Mode_is_b256_(v); mode_is_b256 = v; return this;}
public Xoh_hzip_fxt Init_mode_diff_y_() {hzip_mgr.Hctx().Mode_is_diff_(Bool_.Y); return this;}
public void Clear() {hpg.Clear();}
@ -85,7 +86,7 @@ public class Xoh_hzip_fxt {
Gfo_usr_dlg_.Test__show__term();
Tfds.Eq_str_lines(hzip, bfr.To_str_and_clear());
}
private void Test__decode__raw(String hzip, String html) {
public void Test__decode__raw(String hzip, String html) {
Gfo_usr_dlg_.Test__show__init();
hpg.Section_mgr().Clear();
hzip_mgr.Decode(bfr, parser_fxt.Wiki(), hpg, Bry_.new_u8(hzip));

@ -40,7 +40,8 @@ public abstract class Xoh_itm_parser_fxt {
}
public void Exec_parse(String src_str) {
this.src = Bry_.new_u8(src_str); this.src_len = src.length;
hctx.Init_by_page(wiki, Xoa_page_.Main_page_bry);
Xoh_page hpg = new Xoh_page(); // NOTE: no need to pass url and ttl now
hctx.Init_by_page(wiki, hpg);
err_wkr.Init_by_page(Xoa_page_.Main_page_str, src);
Exec_parse_hook(err_wkr, hctx, 0, src_len);
}

@ -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.htmls.core.wkrs.addons.gallerys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.threads.poolables.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*;
import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gallery_data implements Xoh_data_itm {// NOTE: some galleries fail hzip; use Hook_bry to catch them; PAGE:en.d:a; DATE:2016-06-24
public int Tid() {return Xoh_hzip_dict_.Tid__gallery;}
public int Src_bgn() {return src_bgn;} private int src_bgn;
public int Src_end() {return src_end;} private int src_end;
public void Clear() {
this.src_bgn = this.src_end = -1;
}
public boolean Init_by_parse(Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Gfh_tag_rdr tag_rdr, byte[] src, Gfh_tag gallery_lhs, Gfh_tag unused) {
this.Clear();
this.src_bgn = gallery_lhs.Src_bgn();
this.src_end = gallery_lhs.Src_end();
return true;
}
public void Init_by_decode(int src_bgn, int src_end) {
this.src_bgn = src_bgn;
this.src_end = src_end;
}
public static final byte[] Hook_bry = Bry_.new_a7(" class=\"gallery mw-gallery");
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_gallery_data rv = new Xoh_gallery_data(); rv.pool_mgr = mgr; rv.pool_idx = idx; return rv;}
}

@ -0,0 +1,50 @@
/*
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.htmls.core.wkrs.addons.gallerys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.brys.*; import gplx.core.threads.poolables.*; import gplx.xowa.wikis.ttls.*;
import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gallery_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
public int Tid() {return Xoh_hzip_dict_.Tid__gallery;}
public String Key() {return Xoh_hzip_dict_.Key__gallery;}
public byte[] Hook() {return hook;} private byte[] hook;
public Gfo_poolable_itm Encode1(Xoh_hzip_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, boolean wkr_is_root, byte[] src, Object data_obj) {
Xoh_gallery_data data = (Xoh_gallery_data)data_obj;
bfr.Add_mid(src, data.Src_bgn(), data.Src_end());
hctx.Hzip__stat().Gallery_add();
return this;
}
public void Decode1(Bry_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, Bry_rdr rdr, byte[] src, int src_bgn, int src_end, Xoh_data_itm data_itm) {
int gallery_bgn = src_bgn;
int gallery_end = Bry_find_.Find_fwd(src, Byte_ascii.Gt, src_bgn, src_end);
if (gallery_end == -1) {
Gfo_log_.Instance.Warn("hzip.gallery.end_not_found", "page", hpg.Url_bry_safe(), "src_bgn", src_bgn);
gallery_end = gallery_bgn;
}
else
++gallery_end;
Xoh_gallery_data data = (Xoh_gallery_data)data_itm;
data.Init_by_decode(gallery_bgn, gallery_end);
rdr.Move_to(gallery_end);
}
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_gallery_hzip rv = new Xoh_gallery_hzip(); rv.pool_mgr = mgr; rv.pool_idx = idx; rv.hook = (byte[])args[0]; return rv;}
}

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.htmls.core.wkrs.addons.gallerys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import org.junit.*; import gplx.core.tests.*; import gplx.xowa.htmls.core.makes.tests.*;
public class Xoh_gallery_hzip_tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Basic() {
fxt.Test__decode
( "<ul class=\"gallery mw-gallery-traditional style=\"max-width:489px; _width:489px;\">"
, "<ul class=\"gallery mw-gallery-traditional style=\"max-width:489px; _width:489px;\">"
);
Gftest.Eq__bool_y(fxt.Page().Xtn__gallery_exists());
}
}

@ -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.htmls.core.wkrs.addons.gallerys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.brys.fmtrs.*; import gplx.core.threads.poolables.*; import gplx.core.brys.args.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.core.wkrs.bfr_args.*;
import gplx.xowa.htmls.sections.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gallery_wtr implements gplx.core.brys.Bfr_arg, Xoh_wtr_itm {
private Xoh_page hpg;
private byte[] src; private int src_bgn, src_end;
public void Init_by_parse(Bry_bfr bfr, Xoh_page hpg, Xoh_hdoc_ctx hctx, byte[] src, Xoh_gallery_data data) {
Init_by_decode(hpg, hctx, src, data);
this.Bfr_arg__add(bfr);
}
public boolean Init_by_decode(Xoh_page hpg, Xoh_hdoc_ctx hctx, byte[] src, Xoh_data_itm data_itm) {
this.hpg = hpg; this.src = src;
Xoh_gallery_data data = (Xoh_gallery_data)data_itm;
this.src_bgn = data.Src_bgn();
this.src_end = data.Src_end();
return true;
}
public void Bfr_arg__add(Bry_bfr bfr) {
hpg.Xtn__gallery_exists_y_();
bfr.Add_mid(src, src_bgn, src_end);
}
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_gallery_wtr rv = new Xoh_gallery_wtr(); rv.pool_mgr = mgr; rv.pool_idx = idx; return rv;}
}

@ -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.htmls.core.wkrs.addons.timelines; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.threads.poolables.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*;
import gplx.xowa.htmls.core.hzips.*;
public class Xoh_timeline_data implements Xoh_data_itm {
public int Tid() {return Xoh_hzip_dict_.Tid__timeline;}
public int Src_bgn() {return src_bgn;} private int src_bgn;
public int Src_end() {return src_end;} private int src_end;
public void Clear() {
this.src_bgn = this.src_end = -1;
}
public boolean Init_by_parse(Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Gfh_tag_rdr tag_rdr, byte[] src, Gfh_tag timeline_lhs, Gfh_tag unused) {
this.Clear();
this.src_bgn = timeline_lhs.Src_bgn();
this.src_end = timeline_lhs.Src_end();
return true;
}
public void Init_by_decode(int src_bgn, int src_end) {
this.src_bgn = src_bgn;
this.src_end = src_end;
}
public static final byte[] Hook_bry = Bry_.new_a7("<pre class='xowa-timeline'>");
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_timeline_data rv = new Xoh_timeline_data(); rv.pool_mgr = mgr; rv.pool_idx = idx; return rv;}
}

@ -0,0 +1,50 @@
/*
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.htmls.core.wkrs.addons.timelines; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.brys.*; import gplx.core.threads.poolables.*; import gplx.xowa.wikis.ttls.*;
import gplx.xowa.htmls.core.hzips.*;
public class Xoh_timeline_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
public int Tid() {return Xoh_hzip_dict_.Tid__timeline;}
public String Key() {return Xoh_hzip_dict_.Key__timeline;}
public byte[] Hook() {return hook;} private byte[] hook;
public Gfo_poolable_itm Encode1(Xoh_hzip_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, boolean wkr_is_root, byte[] src, Object data_obj) {
Xoh_timeline_data data = (Xoh_timeline_data)data_obj;
// just add the entire thing; not worth trying to compress "<pre class='xowa-timeline'>"
bfr.Add_mid(src, data.Src_bgn(), data.Src_end());
hctx.Hzip__stat().Timeline_add();
return this;
}
public void Decode1(Bry_bfr bfr, Xoh_hdoc_wkr hdoc_wkr, Xoh_hdoc_ctx hctx, Xoh_page hpg, Bry_rdr rdr, byte[] src, int src_bgn, int src_end, Xoh_data_itm data_itm) {
int timeline_bgn = src_bgn;
int timeline_end = Bry_find_.Find_fwd(src, Byte_ascii.Gt, src_bgn, src_end);
if (timeline_end == -1) {
Gfo_log_.Instance.Warn("hzip.timeline.end_not_found", "page", hpg.Url_bry_safe(), "src_bgn", src_bgn);
timeline_end = timeline_bgn;
}
else
++timeline_end;
Xoh_timeline_data data = (Xoh_timeline_data)data_itm;
data.Init_by_decode(timeline_bgn, timeline_end);
}
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_timeline_hzip rv = new Xoh_timeline_hzip(); rv.pool_mgr = mgr; rv.pool_idx = idx; rv.hook = (byte[])args[0]; return rv;}
}

@ -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.htmls.core.wkrs.addons.timelines; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import org.junit.*; import gplx.core.tests.*; import gplx.xowa.htmls.core.makes.tests.*;
public class Xoh_timeline_hzip_tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Basic() { // EX: <timeline>code</timeline>
fxt.Test__decode__raw("<pre class='xowa-timeline'>abc</pre>", "<pre class='xowa-timeline'>abc</pre>");
Gftest.Eq__bool_y(fxt.Page().Xtn__timeline_exists());
}
}

@ -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.htmls.core.wkrs.addons.timelines; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.addons.*;
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.brys.fmtrs.*; import gplx.core.threads.poolables.*; import gplx.core.brys.args.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.core.wkrs.bfr_args.*;
import gplx.xowa.htmls.sections.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_timeline_wtr implements gplx.core.brys.Bfr_arg, Xoh_wtr_itm {
private Xoh_page hpg;
private byte[] src; private int src_bgn, src_end;
public void Init_by_parse(Bry_bfr bfr, Xoh_page hpg, Xoh_hdoc_ctx hctx, byte[] src, Xoh_timeline_data data) {
Init_by_decode(hpg, hctx, src, data);
this.Bfr_arg__add(bfr);
}
public boolean Init_by_decode(Xoh_page hpg, Xoh_hdoc_ctx hctx, byte[] src, Xoh_data_itm data_itm) {
this.hpg = hpg;
this.src = src;
Xoh_timeline_data data = (Xoh_timeline_data)data_itm;
this.src_bgn = data.Src_bgn();
this.src_end = data.Src_end();
return true;
}
public void Bfr_arg__add(Bry_bfr bfr) {
hpg.Xtn__timeline_exists_y_();
bfr.Add_mid(src, src_bgn, src_end);
}
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_timeline_wtr rv = new Xoh_timeline_wtr(); rv.pool_mgr = mgr; rv.pool_idx = idx; return rv;}
}

@ -20,7 +20,7 @@ import gplx.core.brys.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*; import gplx.langs.htmls.styles.*; import gplx.langs.htmls.clses.*;
import gplx.xowa.htmls.core.hzips.*;
import gplx.xowa.xtns.gallery.*;
public class Xoh_gly_grp_data implements Gfh_class_parser_wkr, Gfh_style_wkr {
public class Xoh_gly_grp_data implements Gfh_class_parser_wkr, Gfh_style_wkr { // FUTURE:add gallerycaption
private final List_adp itms_list = List_adp_.New();
public int Src_bgn() {return src_bgn;} private int src_bgn;
public int Src_end() {return src_end;} private int src_end;
@ -54,6 +54,11 @@ public class Xoh_gly_grp_data implements Gfh_class_parser_wkr, Gfh_style_wkr {
while (true) {
li_head = tag_rdr.Tag__peek_fwd_head();
if (li_head.Name_id() != Gfh_tag_.Id__li) break; // no more <li>; break;
// FUTURE: galleries with gallerycaption will cause gallery to write raw; instate code below, but would need to then serialize "gallerycaption"; PAGE:en.d:A DATE:2016-06-24
// if (li_head.Atrs__cls_has(Atr__cls__gallerycaption)) {// skip <li class='gallerycaption'>A</li>
// li_head = tag_rdr.Tag__move_fwd_head();
// li_head = tag_rdr.Tag__peek_fwd_head();
// }
if (!li_head.Atrs__cls_has(Atr__cls__gallerybox)) return false;
tag_rdr.Pos_(li_head.Src_end());
Xoh_gly_itm_data itm_parser = new Xoh_gly_itm_data();
@ -131,6 +136,7 @@ public class Xoh_gly_grp_data implements Gfh_class_parser_wkr, Gfh_style_wkr {
}
public static final byte[] Atr__cls__gallery = Bry_.new_a7("gallery");
private static final byte[] Atr__cls__mw_gallery = Bry_.new_a7("mw-gallery-"), Atr__cls__gallerybox = Bry_.new_a7("gallerybox")
// , Atr__cls__gallerycaption = Bry_.new_a7("gallerycaption")
, Style__max_width = Bry_.new_a7("max-width"), Style___width = Bry_.new_a7("_width")
;
}

@ -58,10 +58,12 @@ class Xoh_gly_itm_list_wtr implements Bfr_arg {
private Xoh_gly_itm_wtr[] ary; private int ary_len;
public void Init(Xoh_gly_itm_wtr[] ary) {
this.ary = ary; this.ary_len = ary.length;
}
public void Bfr_arg__clear() {
for (int i = 0; i < ary_len; ++i)
ary[i].Clear();
ary = null;
}
public void Bfr_arg__clear() {ary = null;}
public boolean Bfr_arg__missing() {return ary == null;}
public void Bfr_arg__add(Bry_bfr bfr) {
for (int i = 0; i < ary_len; ++i) {

@ -84,13 +84,15 @@ public class Xoh_gly_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
Xoh_data_itm img_data = hctx.Pool_mgr__data().Get_by_tid(Xoh_hzip_dict_.Tid__img);
Xoh_hzip_wkr img_hzip = hctx.Pool_mgr__hzip().Mw__img();
img_hzip.Decode1(bfr, hdoc_wkr, hctx, hpg, rdr, src, src_bgn, src_end, img_data);
itm_wtr.Init(true, uid, li_w, div_1_w, div_2_margin, capt_tid, capt_bry);
((gplx.xowa.htmls.core.wkrs.imgs.Xoh_img_data)img_data).Img_is_gallery_(true);
itm_wtr.Img_wtr().Init_by_decode(hpg, hctx, src, img_data);
itm_wtr.Init(hctx.Mode_is_diff(), itm_wtr.Img_wtr().Fsdb_itm().Html_uid(), li_w, div_1_w, div_2_margin, capt_tid, capt_bry);
img_data.Pool__rls();
img_hzip.Pool__rls();
}
grp_wtr.Init(hctx.Mode_is_diff(), uid, cls_bry, ul_style_max_w, ul_style_w, xtra_cls_bry, xtra_style_bry, xtra_atr_bry, itm_ary);
grp_wtr.Bfr_arg__add(bfr);
hpg.Xtn__gallery_exists_y_();
}
public void Pool__rls () {pool_mgr.Rls_fast(pool_idx);} private Gfo_poolable_mgr pool_mgr; private int pool_idx;
public Gfo_poolable_itm Pool__make (Gfo_poolable_mgr mgr, int idx, Object[] args) {Xoh_gly_hzip rv = new Xoh_gly_hzip(); rv.pool_mgr = mgr; rv.pool_idx = idx; rv.hook = (byte[])args[0]; return rv;}

@ -0,0 +1,157 @@
/*
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.htmls.core.wkrs.glys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gly_hzip__basic__tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Basic() {
fxt.Test__bicode("~'!{,L#{\"g{\"b0!A1~!1A.png~9\"D\"D{\"g{\"b0!B1~!1B.png~9\"D\"Dabc", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:B.png' class='image' xowa_title='B.png'><img data-xowa-title='B.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>B1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>abc"));
}
@Test public void Clear_state() { // page # wasn't being cleared between gallery itms; PAGE:en.w:Almagest; DATE:2016-01-05
fxt.Test__bicode("~'!{,L#{\"g{\"b0!A1~!1A.png~{\"d\"D\"D!#{\"g{\"b0!B1~!1B.png~{\"d\"D\"D!$abc", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|2' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:B.png' class='image' xowa_title='B.png'><img data-xowa-title='B.png' data-xoimg='0|120|120|-1|-1|3' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>B1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>abc"));
}
@Test public void Extra_cls() { // PURPOSE: handle extra cls; EX: <gallery class='abc'>
fxt.Test__bicode("~'1!cls1 cls2~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional cls1 cls2'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
// FUTURE: galleries with gallerycaption will cause gallery to write raw; instate code below, but would need to then serialize "gallerycaption"; PAGE:en.d:A DATE:2016-06-24
//@Test public void Caption() { // handle <li class='gallerycaption'>A</li>; PAGE:en.d:a; DATE:2016-06-24
// fxt.Test__bicode("~'!!\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
// ( "<ul class='gallery mw-gallery-traditional'>"
// , "<li class='gallerycaption'>A</li>"
// , "<li class='gallerybox' style='width:155px;'>"
// , "<div style='width:155px;'>"
// , "<div class='thumb' style='width:150px;'>"
// , "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
// , "</div>"
// , "<div class='gallerytext'>"
// , "<p>A1</p>"
// , "</div>"
// , "</div>"
// , "</li>"
// , "</ul>"));
//}
@Test public void Extra_cls__gallery() { // handle redundant gallery; EX: <gallery class='gallery'>; PAGE:en.w:Butuan; DATE:2016-01-05
fxt.Test__bicode("~'1!gallery~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional gallery'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Xtra_atr() { // PURPOSE: handle extra atr; EX: <gallery id='abc'>
fxt.Test__bicode("~'A! id=\"abc\"\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' id='abc'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Tidy__br_at_end() { // PURPOSE: handle inconsistent tidy behavior where <p> is put on one line ("<p>a</p>") unless it ends with <br> ("<p>a<br>\n</p>")
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0!A1<br>"
, "~!1A.png~9\"D\"D"
), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1<br>" // TIDY: <br> forces </p> to be on next line
, "</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Tidy__empty() { // PURPOSE: no items should place </ul> on same line
fxt.Test__bicode("~'!!!", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'></ul>")); // TIDY: <ul></ul> should be on same line if 0 items
}
}

@ -0,0 +1,124 @@
/*
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.htmls.core.wkrs.glys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gly_hzip__caption__tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Capt_is_empty() { // PURPOSE: handle empty caption
fxt.Test__bicode("~'!!#{\"g{\"b0#~!1A.png~9\"D\"D{\"g{\"b0#!1A.png9\"D\"D<p>abc</p>", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'></div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'></div>"
, "</div>"
, "</li>"
, "</ul><p>abc</p>"));
}
@Test public void Capt_is_br() { // PURPOSE: handle captions which have <br>, not <p>; PAGE:s.w:Sociology; DATE:2015-12-20
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0\"<b><i>A1</i></b>"
, "~!1A.png~9\"D\"D"), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'><br>"
, "<b><i>A1</i></b>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Capt_has_multiple_p() { // PURPOSE: handle captions with multiple <p>; PAGE:en.w:Wikipedia:Bot_requests/Archive_25; DATE:2016-01-12
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0!a<br>"
, "b</p>"
, "<p><br>"
, "~!1A.png~9\"D\"D"), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>a<br>"
, "b</p>"
, "<p><br>"
, "</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Capt_has_complicated_nl_behavior() {// handle complicated captions which force <div> on different line PAGE:en.w:Tamago_kake_gohan; DATE:2016-01-05
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b>\"<div class=\"center\"><a href=\"/wiki/B.png\" class=\"image\" xowa_title=\"B.png\"><img data-xowa-title=\"A.png\" data-xoimg=\"0|120|-1|-1|-1|-1\" src=\"\" width=\"0\" height=\"0\" alt=\"\"></a></div>"
, "abc~\"\\A.png~#9\"D\"D"
), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:29px auto;'><a href='/wiki/A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'><br>"
, "<div class='center'><a href='/wiki/B.png' class='image' xowa_title='B.png'><img data-xowa-title='A.png' data-xoimg='0|120|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "abc</div>" // NOTE: tidy forces </div> to be on same line instead of next
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Capt_has_hr() {// handle <hr> which causes <p> to end early; PAGE:de.v:Kurs:Photoshop_Einzell<6C>sungen/HighKey_mit_CS5; DATE:2016-06-24
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b>%a</p>"
, "<hr>"
, "b"
, "~\"\\A.png~#9\"D\"D")
, String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:29px auto;'><a href='/wiki/A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>a</p>" // NOTE: </p> placed before <hr>
, "<hr>"
, "b" // NOTE: no <p> for "b"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"
));
}
}

@ -0,0 +1,144 @@
/*
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.htmls.core.wkrs.glys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gly_hzip__style__tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Style__no_max_width() { // PURPOSE: if no perrow=# then no "style='max-width:###; _width:###;'"
fxt.Test__bicode("~'!!\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__no_width() { // PURPOSE: if "_width" omitted, do not add back; EX: style="max-width:648px; margin:auto; background:transparent;"; PAGE:en.w:Wikipedia:Village_pump_(technical)/Archive_86 DATE:2016-01-12
fxt.Test__bicode("~'i{,L! color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__max_width_duped() { // PURPOSE: if max-width duped, do not delete 2nd; EX: style="max-width:648px; color:blue; max-width:648px;"; PAGE:en.w:Wikipedia:Village_pump_(technical)/Archive_86 DATE:2016-01-12
fxt.Test__bicode("~'){(Z max-width:648px; color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:652px; _width:652px; max-width:648px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__append() { // PURPOSE: handle appended style; EX: <gallery perrow=4 style='color:blue; float:left;'>
fxt.Test__bicode("~'){,L color:blue; float:left;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px; color:blue; float:left;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__invalid_unclosed() { // handle broken styles; EX: <gallery style='center'>
fxt.Test__bicode("~'9!center~center~\"{\"g{\"bl!abc~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional center' style='center'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:75px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>abc</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Style__extra_colon() { // handle broken styles; EX: <gallery style='a:b:c:d;' PAGE:en.w:Bronze_Horseman DATE:2016-01-05
fxt.Test__bicode("~'9!center~color:red:float:right;~\"{\"g{\"bl!abc~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional center' style='color:red:float:right;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:75px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>abc</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Style__replace() { // PURPOSE: handle replaced style; EX: <gallery style='color:blue; float:left;'>
fxt.Test__bicode("~')!color:blue; float:left;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='color:blue; float:left;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__ws() { // PURPOSE: handle ws in style; EX: <gallery class="gallery mw-gallery-traditional" style="max-width:1115px; _width:1115px; color:blue;'>; PAGE:en.w:Anti-Serb_sentiment; DATE:2016-01-08
fxt.Test__bicode("~'){,L color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
}

@ -1,341 +0,0 @@
/*
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.htmls.core.wkrs.glys; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*;
public class Xoh_gly_hzip_tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Test public void Basic() {
fxt.Test__bicode("~'!{,L#{\"g{\"b0!A1~!1A.png~9\"D\"D{\"g{\"b0!B1~!1B.png~9\"D\"Dabc", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:B.png' class='image' xowa_title='B.png'><img data-xowa-title='B.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>B1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>abc"));
}
@Test public void Clear_state() { // page # wasn't being cleared between gallery itms; PAGE:en.w:Almagest; DATE:2016-01-05
fxt.Test__bicode("~'!{,L#{\"g{\"b0!A1~!1A.png~{\"d\"D\"D!#{\"g{\"b0!B1~!1B.png~{\"d\"D\"D!$abc", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|2' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:B.png' class='image' xowa_title='B.png'><img data-xowa-title='B.png' data-xoimg='0|120|120|-1|-1|3' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>B1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>abc"));
}
@Test public void Capt_is_empty() { // PURPOSE: handle empty caption
fxt.Test__bicode("~'!!#{\"g{\"b0#~!1A.png~9\"D\"D{\"g{\"b0#!1A.png9\"D\"D<p>abc</p>", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'></div>"
, "</div>"
, "</li>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'></div>"
, "</div>"
, "</li>"
, "</ul><p>abc</p>"));
}
@Test public void Capt_is_br() { // PURPOSE: handle captions which have <br>, not <p>; PAGE:s.w:Sociology; DATE:2015-12-20
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0\"<b><i>A1</i></b>"
, "~!1A.png~9\"D\"D"), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'><br>"
, "<b><i>A1</i></b>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Capt_has_multiple_p() { // PURPOSE: handle captions with multiple <p>; PAGE:en.w:Wikipedia:Bot_requests/Archive_25; DATE:2016-01-12
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0!a<br>"
, "b</p>"
, "<p><br>"
, "~!1A.png~9\"D\"D"), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>a<br>"
, "b</p>"
, "<p><br>"
, "</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Capt_has_complicated_nl_behavior() {// handle complicated captions which force <div> on different line PAGE:en.w:Tamago_kake_gohan; DATE:2016-01-05
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b>\"<div class=\"center\"><a href=\"/wiki/B.png\" class=\"image\" xowa_title=\"B.png\"><img data-xowa-title=\"A.png\" data-xoimg=\"0|120|-1|-1|-1|-1\" src=\"\" width=\"0\" height=\"0\" alt=\"\"></a></div>"
, "abc~\"\\A.png~#9\"D\"D"
), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:29px auto;'><a href='/wiki/A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'><br>"
, "<div class='center'><a href='/wiki/B.png' class='image' xowa_title='B.png'><img data-xowa-title='A.png' data-xoimg='0|120|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "abc</div>" // NOTE: tidy forces </div> to be on same line instead of next
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Style__no_max_width() { // PURPOSE: if no perrow=# then no "style='max-width:###; _width:###;'"
fxt.Test__bicode("~'!!\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__no_width() { // PURPOSE: if "_width" omitted, do not add back; EX: style="max-width:648px; margin:auto; background:transparent;"; PAGE:en.w:Wikipedia:Village_pump_(technical)/Archive_86 DATE:2016-01-12
fxt.Test__bicode("~'i{,L! color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__max_width_duped() { // PURPOSE: if max-width duped, do not delete 2nd; EX: style="max-width:648px; color:blue; max-width:648px;"; PAGE:en.w:Wikipedia:Village_pump_(technical)/Archive_86 DATE:2016-01-12
fxt.Test__bicode("~'){(Z max-width:648px; color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:652px; _width:652px; max-width:648px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__append() { // PURPOSE: handle appended style; EX: <gallery perrow=4 style='color:blue; float:left;'>
fxt.Test__bicode("~'){,L color:blue; float:left;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px; color:blue; float:left;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__invalid_unclosed() { // handle broken styles; EX: <gallery style='center'>
fxt.Test__bicode("~'9!center~center~\"{\"g{\"bl!abc~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional center' style='center'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:75px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>abc</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Style__extra_colon() { // handle broken styles; EX: <gallery style='a:b:c:d;' PAGE:en.w:Bronze_Horseman DATE:2016-01-05
fxt.Test__bicode("~'9!center~color:red:float:right;~\"{\"g{\"bl!abc~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional center' style='color:red:float:right;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:75px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>abc</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"
));
}
@Test public void Style__replace() { // PURPOSE: handle replaced style; EX: <gallery style='color:blue; float:left;'>
fxt.Test__bicode("~')!color:blue; float:left;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='color:blue; float:left;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Style__ws() { // PURPOSE: handle ws in style; EX: <gallery class="gallery mw-gallery-traditional" style="max-width:1115px; _width:1115px; color:blue;'>; PAGE:en.w:Anti-Serb_sentiment; DATE:2016-01-08
fxt.Test__bicode("~'){,L color:blue;~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' style='max-width:978px; _width:978px; color:blue;'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Extra_cls() { // PURPOSE: handle extra cls; EX: <gallery class='abc'>
fxt.Test__bicode("~'1!cls1 cls2~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional cls1 cls2'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Extra_cls__gallery() { // handle redundant gallery; EX: <gallery class='gallery'>; PAGE:en.w:Butuan; DATE:2016-01-05
fxt.Test__bicode("~'1!gallery~\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional gallery'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Xtra_atr() { // PURPOSE: handle extra atr; EX: <gallery id='abc'>
fxt.Test__bicode("~'A! id=\"abc\"\"{\"g{\"b0!A1~!1A.png~9\"D\"D", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional' id='abc'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Tidy__br_at_end() { // PURPOSE: handle inconsistent tidy behavior where <p> is put on one line ("<p>a</p>") unless it ends with <br> ("<p>a<br>\n</p>")
fxt.Test__bicode(String_.Concat_lines_nl_skip_last
( "~'!!\"{\"g{\"b0!A1<br>"
, "~!1A.png~9\"D\"D"
), String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'>"
, "<li class='gallerybox' style='width:155px;'>"
, "<div style='width:155px;'>"
, "<div class='thumb' style='width:150px;'>"
, "<div style='margin:15px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|120|120|-1|-1|-1' src='' width='0' height='0' alt=''></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>A1<br>" // TIDY: <br> forces </p> to be on next line
, "</p>"
, "</div>"
, "</div>"
, "</li>"
, "</ul>"));
}
@Test public void Tidy__empty() { // PURPOSE: no items should place </ul> on same line
fxt.Test__bicode("~'!!!", String_.Concat_lines_nl_skip_last
( "<ul class='gallery mw-gallery-traditional'></ul>")); // TIDY: <ul></ul> should be on same line if 0 items
}
}

@ -95,12 +95,14 @@ public class Xoh_gly_itm_data {
capt_end = div_tail.Src_bgn();
if (Bry_.Match(src, capt_end - 5, capt_end, Bry__p__rhs))
capt_end -= 5; // set capt_end to before </p>; 5 = "\n</p>";
else // no </p>; occurs when <hr> in middle; PAGE:fr.w:Forfry DATE:2016-06-24
capt_tid = Capt_tid__p_wo_rhs;
}
tag_rdr.Pos_(capt_tail_end);
return true;
}
private static final byte[] Atr__cls__gallerytext = Bry_.new_a7("gallerytext"), Bry__p__rhs = Bry_.new_a7("</p>\n");
public static final byte Capt_tid__p = 0, Capt_tid__br = 1, Capt_tid__empty = 2, Capt_tid__null = 3;
public static final byte Capt_tid__p = 0, Capt_tid__br = 1, Capt_tid__empty = 2, Capt_tid__null = 3, Capt_tid__p_wo_rhs = 4;
private static final Btrie_slim_mgr Capt_tid__trie = Btrie_slim_mgr.ci_a7()
.Add_bry_byte(Gfh_tag_.P_lhs , Capt_tid__p)
.Add_bry_byte(Gfh_tag_.Br_lhs , Capt_tid__br)

@ -21,7 +21,7 @@ import gplx.langs.htmls.*; import gplx.xowa.htmls.core.wkrs.bfr_args.*; import g
public class Xoh_gly_itm_wtr implements Bfr_arg {
private final Bfr_arg_clearable[] arg_ary;
private final Bfr_arg__hatr_id li_id = Bfr_arg__hatr_id.New_id("xogly_li_"), img_id = Bfr_arg__hatr_id.New_id(gplx.xowa.htmls.Xoh_img_mgr.Bry__html_uid)
, div_1_id = Bfr_arg__hatr_id.New_id("xogly_div1_"), div_2_id = Bfr_arg__hatr_id.New_id("xogly_div2_"), div_3_id = Bfr_arg__hatr_id.New_id("xogly_div3_");
, div_1_id = Bfr_arg__hatr_id.New_id("xowa_gallery_div1_"), div_2_id = Bfr_arg__hatr_id.New_id("xowa_gallery_div2_"), div_3_id = Bfr_arg__hatr_id.New_id("xowa_gallery_div3_");
private final Bfr_arg__itm_caption itm_caption_fmtr = new Bfr_arg__itm_caption();
private int li_w, div_1_w, div_2_margin;
public Xoh_gly_itm_wtr() {
@ -73,6 +73,7 @@ class Bfr_arg__itm_caption implements Bfr_arg {
case Xoh_gly_itm_data.Capt_tid__empty: return; // <div class='gallerytext'></div>
case Xoh_gly_itm_data.Capt_tid__p: bfr.Add_byte_nl().Add(Gfh_tag_.P_lhs); break; // <div class='gallerytext'><p>
case Xoh_gly_itm_data.Capt_tid__br: bfr.Add(Gfh_tag_.Br_lhs).Add_byte_nl(); break; // <div class='gallerytext'><br>
case Xoh_gly_itm_data.Capt_tid__p_wo_rhs: bfr.Add_byte_nl().Add(Gfh_tag_.P_lhs); break; // <div class='gallerytext'><br>
}
bfr.Add(capt_bry);
int itm_caption_len = capt_bry.length;

@ -25,9 +25,9 @@ public class Xoh_gly_itm_wtr_tst {
fxt.Test__write(String_.Concat_lines_nl_skip_last
( ""
, "<li id='xogly_li_0' class='gallerybox' style='width:155px;'>"
, "<div id='xogly_div1_0' style='width:155px;'>"
, "<div id='xogly_div2_0' class='thumb' style='width:150px;'>"
, "<div id='xogly_div3_0' style='margin:5px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img id='xoimg_0' data-xoimg='0|120|120|-1|-1|-1' width='0' height='0'></a></div>"
, "<div id='xowa_gallery_div1_0' style='width:155px;'>"
, "<div id='xowa_gallery_div2_0' class='thumb' style='width:150px;'>"
, "<div id='xowa_gallery_div3_0' style='margin:5px auto;'><a href='/wiki/File:A.png' class='image' xowa_title='A.png'><img id='xoimg_0' data-xoimg='0|120|120|-1|-1|-1' width='0' height='0'></a></div>"
, "</div>"
, "<div class='gallerytext'>"
, "<p>caption</p>"

@ -43,8 +43,9 @@ public class Xoh_img_data implements Xoh_data_itm {
public boolean Img_is_vid() {return img_is_vid;} private boolean img_is_vid;
public boolean Img_wo_anch() {return img_wo_anch;} private boolean img_wo_anch;
public int Img_imap_idx() {return img_imap_idx;} private int img_imap_idx;
public boolean Img_is_gallery() {return img_is_gallery;} private boolean img_is_gallery; public void Img_is_gallery_(boolean v) {this.img_is_gallery = v;}
public void Clear() {
this.img_alt__diff_anch_title = anch_rel_is_nofollow = img_is_vid = img_wo_anch = false;
this.img_alt__diff_anch_title = anch_rel_is_nofollow = img_is_vid = img_wo_anch = img_is_gallery = false;
this.src_bgn = src_end = anch_title_bgn = anch_title_end = img_w = img_h = img_alt_bgn = img_alt_end = -1;
this.img_imap_idx = -1;
anch_href.Clear(); anch_cls.Clear();

@ -28,4 +28,26 @@ public class Xoh_img_html__dump__tst {
@Test public void Empty_link() {
fxt.Test__html("[[File:A.png|220x110px|link=|abc]]", "<img data-xowa-title=\"A.png\" data-xoimg='0|220|110|-1|-1|-1' src='' width='0' height='0' alt='abc'/>");
}
@Test public void Lcase_img() {
Make_ns_case_sensitive(fxt.Parser_fxt().Wiki(), gplx.xowa.wikis.nss.Xow_ns_.Tid__file);
fxt.Test__html("[[File:a_b.png]]", "<a href=\"/wiki/File:a_b.png\" class=\"image\" xowa_title=\"a_b.png\"><img data-xowa-title=\"a_b.png\" data-xoimg=\"0|-1|-1|-1|-1|-1\" src=\"\" width=\"0\" height=\"0\" alt=\"\"/></a>");
}
@Test public void Lcase_video() {
Make_ns_case_sensitive(fxt.Parser_fxt().Wiki(), gplx.xowa.wikis.nss.Xow_ns_.Tid__file);
fxt.Test__html("[[File:a b.ogv]]"
, String_.Concat_lines_nl_skip_last
( " <div class=\"xowa_media_div\">"
, " <div><a href=\"/wiki/File:a_b.ogv\" class=\"image\" title=\"A_b.ogv\" xowa_title=\"a_b.ogv\"><img data-xowa-title=\"a_b.ogv\" data-xoimg=\"0|-1|-1|-1|-1|-1\" src=\"\" width=\"0\" height=\"0\" alt=\"\"/></a>"
, " </div>"
, "<div><a href=\"\" xowa_title=\"a_b.ogv\" class=\"xowa_media_play\" style=\"width:218px;max-width:220px;\" alt=\"Play sound\"></a></div>"
, " </div>"
)
);
}
private static void Make_ns_case_sensitive(Xow_wiki wiki, int ns_id) {
gplx.xowa.wikis.nss.Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
gplx.xowa.wikis.nss.Xow_ns ns = ns_mgr.Ids_get_or_null(ns_id);
ns.Case_match_(gplx.xowa.wikis.nss.Xow_ns_case_.Tid__all);
ns_mgr.Init();
}
}

@ -149,7 +149,7 @@ public class Xoh_img_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
if (anch__ns_id_needs_saving)
anch_href_ns = Xoh_lnki_dict_.Ns_decode(rdr);
byte[] ns_custom_bry = null;
if (anch__ns_is_custom) ns_custom_bry = rdr.Read_bry_to();
if (anch__ns_is_custom) ns_custom_bry = Xoa_ttl.Replace_spaces(rdr.Read_bry_to()); // NOTE: use unders not spaces; will be used directly below to generate href; else href="User talk:A"; PAGE:de.b:Wikibooks:Benutzersperrung/_InselFahrer DATE:2016-06-25
int img_w = -1, img_h = -1, file_time = -1, file_page = -1;
if (file__src_exists) {
img_w = rdr.Read_hzip_int(2) - Gfo_hzip_int_.Neg_1_adj;

@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.htmls.core.wkrs.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.wikis.nss.*;
public class Xoh_img_hzip__dump__tst {
public class Xoh_img_hzip__dump__basic__tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Before public void Clear() {fxt.Clear();}
@Test public void Basic() { // [[File:A.png|border|class=other|220px|abc]]
@ -83,80 +83,6 @@ public class Xoh_img_hzip__dump__tst {
);
ns_mgr.Ns_file().Name_bry_(Bry_.new_u8("File")); ns_mgr.Init_w_defaults();
}
@Test public void Link__cs() { // [[File:A.png|link=File:a.ogg|abc]]
fxt.Test__bicode
( "~%!Aa.ogg~A.png~)#Sabc~"
, "<a href='/wiki/File:a.ogg' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__anchor() { // [[File:A.png|link=A#B_C|abc]]; PAGE:en.w:Arabic; DATE:2016-01-06
fxt.Test__bicode
( "~%#'A#B_C~D.png~#9!I!I"
, "<a href='/wiki/A#B_C' class='image' xowa_title='D.png'><img data-xowa-title='D.png' data-xoimg='0|40|40|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Link__wm__n() { // [[File:A.png|link=http://a.org|abc]]
fxt.Test__bicode
( "~%!Dhttp://a.org~A.png~)#Sabc~"
, "<a href='http://a.org' rel='nofollow' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__wm__y() { // [[File:A.png|link=http://en.wikitionary.org/wiki/Special:Search/A|abc]]
fxt.Test__bicode
( "~%\"men.wiktionary.org|Search/A~A.png~\")#Sabc~"
, "<a href='/site/en.wiktionary.org/wiki/Special:Search/A' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__wm__n_2() { // [[File:A.png|link=creativecommons:by/2.5]]
fxt.Test__bicode
( "~%#(creativecommons.org|by/2.5/~CC-BY-icon-80x15.png~#)!q"
, "<a href='/site/creativecommons.org/wiki/by/2.5/' class='image' xowa_title='CC-BY-icon-80x15.png'><img data-xowa-title='CC-BY-icon-80x15.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Link__media() { // [[File:A.png|link=file:///C:/A.ogg]]
fxt.Test__bicode
( "~%!D~A.ogg~)!,B~"
, "<a href='' class='image' title='B' xowa_title='A.ogg'><img data-xowa-title='A.ogg' data-xoimg='0|11|-1|-1|-1|-1' src='' width='0' height='0' alt='B'></a>"
);
}
@Test public void Link__encoding() { // [[File:A.svg|24px|text-top|link=wikt:𬖾|𬖾]]; PAGE:en.w:Pho; DATE:2016-01-04
fxt.Test__bicode
( "~%#Xen.wiktionary.org|%F0%AC%96%BE~A.png~#)!,abc~B~"
, "<a href='/site/en.wiktionary.org/wiki/%F0%AC%96%BE' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|11|-1|-1|-1|-1' src='' width='0' height='0' alt='B'></a>"
);
}
@Test public void Link__invalid() { // handle invalid titles in link arg; EX:[[File:A.png|link=wikt:]]; PAGE:en.w:List_of_Saint_Petersburg_Metro_stations; DATE:2016-01-04
fxt.Test__bicode
( "~%\"mcommons.wikimedia.org|~A.png~1!Abc~"
, "<a href='/site/commons.wikimedia.org/wiki/Category:' class='image' title='Abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|-1|-1|-1|-1|-1' src='' width='0' height='0' alt='Abc'></a>"
);
}
@Test public void Link__empty() { // empty link should not create anchor; EX:[[File:A.png|link=|abc]]; PAGE:en.w:List_of_counties_in_New_York; DATE:2016-01-10
fxt.Test__bicode
( "~%|iVPA.png~#9#S\":abc~"
, "<img data-xowa-title='A.png' data-xoimg='0|220|110|-1|-1|-1' src='' width='0' height='0' alt='abc'>"
);
}
@Test public void Link__empty__tidy() {// <a><font><img> should not trigger empty link code; PAGE:en.w:Wikipedia:Reference_Desk_archive_unanswered_2005 ; DATE:2016-01-13
fxt.Test__bicode
( "<a href=\"/wiki/Image:A.png\" class=\"image\" title=\"\" xowa_title=\"A.png\"><font style=\"color:red\">~%|iVPA.png~#!abc~</font></a>"
, "<a href='/wiki/Image:A.png' class='image' title='' xowa_title='A.png'><font style='color:red'><img data-xowa-title='A.png' data-xoimg='0|-1|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></font></a>"
);
}
@Test public void Link__ns_alias() { // [[File:A.png|link=WP:MCB]]; PAGE:en.w:Wikipedia:WikiProject_Molecular_and_Cell_Biology; DATE:2016-01-11
fxt.Init__ns_alias__add("WP", Xow_ns_.Tid__project);
fxt.Test__bicode
( "~%/+MCB~A.png~'WP~)!q"
, "<a href='/wiki/WP:MCB' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
fxt.Init__ns_alias__del("WP");
}
@Test public void Link__xwiki_lc() { // [[File:A.png|link=wikt:Category:en:A]]; PAGE:en.w:Portal:Trucks/Wikimedia; DATE:2016-01-11
fxt.Test__bicode
( "~%#(en.wiktionary.org|en:A~A.png~1)!q"
, "<a href='/site/en.wiktionary.org/wiki/Category:en:A' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Missing() { // PURPOSE: bad dump shouldn't write corrupt data
fxt.Test__bicode
( "%|\"\\QA.png!!!!A"

@ -0,0 +1,105 @@
/*
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.htmls.core.wkrs.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.wkrs.*;
import org.junit.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.wikis.nss.*;
public class Xoh_img_hzip__dump__link__tst {
private final Xoh_hzip_fxt fxt = new Xoh_hzip_fxt().Init_mode_diff_y_();
@Before public void Clear() {fxt.Clear();}
@Test public void Link__cs() { // [[File:A.png|link=File:a.ogg|abc]]
fxt.Test__bicode
( "~%!Aa.ogg~A.png~)#Sabc~"
, "<a href='/wiki/File:a.ogg' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__anchor() { // [[File:A.png|link=A#B_C|abc]]; PAGE:en.w:Arabic; DATE:2016-01-06
fxt.Test__bicode
( "~%#'A#B_C~D.png~#9!I!I"
, "<a href='/wiki/A#B_C' class='image' xowa_title='D.png'><img data-xowa-title='D.png' data-xoimg='0|40|40|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Link__wm__n() { // [[File:A.png|link=http://a.org|abc]]
fxt.Test__bicode
( "~%!Dhttp://a.org~A.png~)#Sabc~"
, "<a href='http://a.org' rel='nofollow' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__wm__y() { // [[File:A.png|link=http://en.wikitionary.org/wiki/Special:Search/A|abc]]
fxt.Test__bicode
( "~%\"men.wiktionary.org|Search/A~A.png~\")#Sabc~"
, "<a href='/site/en.wiktionary.org/wiki/Special:Search/A' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|220|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></a>"
);
}
@Test public void Link__wm__n_2() { // [[File:A.png|link=creativecommons:by/2.5]]
fxt.Test__bicode
( "~%#(creativecommons.org|by/2.5/~CC-BY-icon-80x15.png~#)!q"
, "<a href='/site/creativecommons.org/wiki/by/2.5/' class='image' xowa_title='CC-BY-icon-80x15.png'><img data-xowa-title='CC-BY-icon-80x15.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Link__media() { // [[File:A.png|link=file:///C:/A.ogg]]
fxt.Test__bicode
( "~%!D~A.ogg~)!,B~"
, "<a href='' class='image' title='B' xowa_title='A.ogg'><img data-xowa-title='A.ogg' data-xoimg='0|11|-1|-1|-1|-1' src='' width='0' height='0' alt='B'></a>"
);
}
@Test public void Link__encoding() { // [[File:A.svg|24px|text-top|link=wikt:𬖾|𬖾]]; PAGE:en.w:Pho; DATE:2016-01-04
fxt.Test__bicode
( "~%#Xen.wiktionary.org|%F0%AC%96%BE~A.png~#)!,abc~B~"
, "<a href='/site/en.wiktionary.org/wiki/%F0%AC%96%BE' class='image' title='abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|11|-1|-1|-1|-1' src='' width='0' height='0' alt='B'></a>"
);
}
@Test public void Link__invalid() { // handle invalid titles in link arg; EX:[[File:A.png|link=wikt:]]; PAGE:en.w:List_of_Saint_Petersburg_Metro_stations; DATE:2016-01-04
fxt.Test__bicode
( "~%\"mcommons.wikimedia.org|~A.png~1!Abc~"
, "<a href='/site/commons.wikimedia.org/wiki/Category:' class='image' title='Abc' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|-1|-1|-1|-1|-1' src='' width='0' height='0' alt='Abc'></a>"
);
}
@Test public void Link__empty() { // empty link should not create anchor; EX:[[File:A.png|link=|abc]]; PAGE:en.w:List_of_counties_in_New_York; DATE:2016-01-10
fxt.Test__bicode
( "~%|iVPA.png~#9#S\":abc~"
, "<img data-xowa-title='A.png' data-xoimg='0|220|110|-1|-1|-1' src='' width='0' height='0' alt='abc'>"
);
}
@Test public void Link__empty__tidy() {// <a><font><img> should not trigger empty link code; PAGE:en.w:Wikipedia:Reference_Desk_archive_unanswered_2005 ; DATE:2016-01-13
fxt.Test__bicode
( "<a href=\"/wiki/Image:A.png\" class=\"image\" title=\"\" xowa_title=\"A.png\"><font style=\"color:red\">~%|iVPA.png~#!abc~</font></a>"
, "<a href='/wiki/Image:A.png' class='image' title='' xowa_title='A.png'><font style='color:red'><img data-xowa-title='A.png' data-xoimg='0|-1|-1|-1|-1|-1' src='' width='0' height='0' alt='abc'></font></a>"
);
}
@Test public void Link__ns_alias() { // [[File:A.png|link=WP:MCB]]; PAGE:en.w:Wikipedia:WikiProject_Molecular_and_Cell_Biology; DATE:2016-01-11
fxt.Init__ns_alias__add("WP", Xow_ns_.Tid__project);
fxt.Test__bicode
( "~%/+MCB~A.png~'WP~)!q"
, "<a href='/wiki/WP:MCB' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
fxt.Init__ns_alias__del("WP");
}
@Test public void Link__xwiki_lc() { // [[File:A.png|link=wikt:Category:en:A]]; PAGE:en.w:Portal:Trucks/Wikimedia; DATE:2016-01-11
fxt.Test__bicode
( "~%#(en.wiktionary.org|en:A~A.png~1)!q"
, "<a href='/site/en.wiktionary.org/wiki/Category:en:A' class='image' xowa_title='A.png'><img data-xowa-title='A.png' data-xoimg='0|80|-1|-1|-1|-1' src='' width='0' height='0' alt=''></a>"
);
}
@Test public void Link__xwiki_under() {// EX: [[File:A.png|link=User talk:B]]; PAGE:de.b:Wikibooks:Benutzersperrung/_InselFahrer DATE:2016-06-24
fxt.Test__bicode
( "~%/,meta.wikimedia.org|B~A.png~&User Talk~!", String_.Concat
( "<a href='/site/meta.wikimedia.org/wiki/User_Talk:B' class='image' xowa_title='A.png'>"
, "<img data-xowa-title='A.png' data-xoimg='0|-1|-1|-1|-1|-1' src='' width='0' height='0' alt=''>"
, "</a>"
));
}
}

@ -64,7 +64,7 @@ public class Xoh_img_wtr implements Bfr_arg, Xoh_wtr_itm {
this.Clear();
this.img_is_vid = data.Img_is_vid();
this.img_wo_anch = data.Img_wo_anch();
this.fsdb_itm = hpg.Img_mgr().Make_img();
this.fsdb_itm = hpg.Img_mgr().Make_img(data.Img_is_gallery());
byte[] file_ttl_bry = data.Img_src().File_ttl_bry();
byte[] lnki_ttl = Xoa_ttl.Replace_spaces(Gfo_url_encoder_.Href_quotes.Decode(file_ttl_bry)); // NOTE: must decode for fsdb.lnki_ttl as well as xowa_title; EX: A%C3%A9b -> A<>b
if (data.Img_xoimg().Val_dat_exists()) {

@ -23,7 +23,7 @@ public class Xoh_lnke_wtr implements gplx.core.brys.Bfr_arg, Xoh_wtr_itm {
private final Bfr_arg__bry anch_href = Bfr_arg__bry.New_empty(), anch_cls = Bfr_arg__bry.New_empty(), anch_content = Bfr_arg__bry.New_empty();
private final Bfr_arg__hatr_bry anch_title = new Bfr_arg__hatr_bry(Gfh_atr_.Bry__title);
public boolean Init_by_decode(Xoh_page hpg, Xoh_hdoc_ctx hctx, byte[] src, Xoh_data_itm data_itm) {
Bfr_arg_.Clear(anch_href, anch_cls,anch_content);
Bfr_arg_.Clear(anch_href, anch_cls, anch_content, anch_title);
Xoh_lnke_data data = (Xoh_lnke_data)data_itm;
anch_href.Set_by_mid(src, data.Href_bgn(), data.Href_end());
anch_cls.Set_by_val(Xoh_lnke_dict_.To_html_class(data.Lnke_tid()));

@ -91,6 +91,7 @@ public class Xoh_lnki_data {
Gfh_tag anch_tail = tag_rdr.Tag__move_fwd_tail(Gfh_tag_.Id__a); // </a>
this.capt_end = anch_tail.Src_bgn(); // get capt between "<a>" and "</a>
this.src_end = anch_tail.Src_end();
// skip ns in href / capt
if (href_ns_id != Xow_ns_.Tid__main) { // not main; try to remove template name;
int capt_bgn_wo_ns = capt_bgn + href_ns_name_len;
@ -100,6 +101,7 @@ public class Xoh_lnki_data {
capt_has_ns = true;
}
}
// get text splits
this.text_tid = href_itm.Tid() == Xoh_anch_href_data.Tid__anch
? Xoh_anch_capt_itm.Tid__diff

@ -106,7 +106,9 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
href_bry = Bry_.Empty;
}
else {
Xow_ns ns = hctx.Wiki__ttl_parser().Ns_mgr().Ids_get_or_null(ns_id); if (ns == null) rdr.Err_wkr().Fail("invalid ns_id", "ns_id", ns_id);
Xow_ns ns = hctx.Wiki__ttl_parser().Ns_mgr().Ids_get_or_null(ns_id);
if (ns == null)
rdr.Err_wkr().Fail("invalid ns_id", "ns_id", ns_id, "href_bry", href_bry); // add more args to troubleshoot random failure; DATE:2016-06-23
ns_bry = ns.Name_ui();
tmp_bfr.Add(ns.Name_db()).Add_byte_colon();
}
@ -124,12 +126,14 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm {
href_bry = tmp_bfr.To_bry_and_clear();
// generate stub for redlink
if ( !hctx.Mode_is_diff()) { // PERF: don't do redlinks during hzip_diff
try {
Xoa_ttl ttl = hpg.Wiki().Ttl_parse(Gfo_url_encoder_.Href.Decode(href_bry));
Xopg_lnki_itm__hdump lnki_itm = new Xopg_lnki_itm__hdump(ttl);
hpg.Redlink_list().Add(lnki_itm);
html_uid = lnki_itm.Html_uid();
} catch (Exception e) {Gfo_log_.Instance.Warn("failed to add lnki to redlinks", "page", hpg.Url_bry_safe(), "href_bry", href_bry, "e", Err_.Message_gplx_log(e));}
}
break;
}
byte[] capt_bry = Xoh_lnki_hzip_.Bld_capt(tmp_bfr, href_type, text_type, capt_has_ns, capt_cs0_tid, ns_bry, src, text_0_bgn, text_0_end, src, text_1_bgn, text_1_end);

@ -115,8 +115,8 @@ public class Xoh_anch_href_data implements Xoh_itm_parser {
if (ns.Id() != Xow_ns_.Tid__main) {
ttl_ns_id = ns.Id();
ttl_page_db = Bry_.Mid(ttl_full_txt, colon_pos + 1, ttl_full_len);
if (!Bry_.Match(ttl_full_txt, 0, colon_pos, ns.Name_ui()))
ttl_ns_custom = Bry_.Mid(ttl_full_txt, 0, colon_pos);
if (!Bry_.Match(ttl_full_txt, 0, colon_pos, ns.Name_ui())) // ns does not match expd name
ttl_ns_custom = Bry_.Mid(ttl_full_txt, 0, colon_pos); // mark as custom; NOTE: not using ttl_full_txt, b/c need to preserve underscores, else href="User_talk" -> "User talk"; PAGE:de.b:Wikibooks:Benutzersperrung/_InselFahrer DATE:2016-06-24
}
}
}

@ -58,9 +58,11 @@ public class Xoh_file_html_fmtr__base implements Xoh_file_img_wkr {
( "<img id=\"xoimg_~{uid}\" alt=\"~{img_alt}\"~{img_core}~{img_class} />"
, "uid", "img_core", "img_alt", "img_class"
);
public byte[] Html_thumb_part_img(Bry_bfr tmp_bfr, Xoh_wtr_ctx hctx, Xoae_page page, byte[] src, Xof_file_itm xfer_itm, int uid, byte[] a_href, byte[] img_src, byte[] img_alt) {
public byte[] Html_thumb_part_img(Bry_bfr tmp_bfr, Xoh_wtr_ctx hctx, Xoae_page page, byte[] src, Xof_file_itm xfer_itm, int uid, byte[] lnki_ttl, byte[] a_href, byte[] img_src, byte[] img_alt) {
byte[] a_title_atr = Gfh_atr_.Make(tmp_bfr, Gfh_atr_.Bry__title, xfer_itm.Lnki_ttl());
Html_full_img(tmp_bfr, hctx, page, src, xfer_itm, uid, a_href, Bool_.N, Xoh_lnki_consts.Tid_a_cls_image, Xoh_lnki_consts.Tid_a_rel_none, a_title_atr, Xoh_file_html_fmtr__base.Escape_xowa_title(xfer_itm.Lnki_ttl())
Html_full_img(tmp_bfr, hctx, page, src, xfer_itm, uid, a_href, Bool_.N, Xoh_lnki_consts.Tid_a_cls_image
, Xoh_lnki_consts.Tid_a_rel_none, a_title_atr
, Xoh_file_html_fmtr__base.Escape_xowa_title(lnki_ttl) // NOTE: must use lnki_ttl, not xfer_itm.Lnki_ttl(); 1st observes case-sensitivity; EX:"a.ogv"; PAGE:de.d:fappieren DATE:2016-06-23
, xfer_itm.Html_w(), xfer_itm.Html_h(), img_src, img_alt, Xoh_img_cls_.Tid__none, null);
return tmp_bfr.To_bry_and_clear();
}

@ -79,7 +79,7 @@ public class Xoh_file_wtr__basic {
)
) {
xfer_itm.Html_elem_tid_(Xof_html_elem.Tid_vid);
this.Write_file_video(bfr, ctx, hctx, src, lnki, uid, div_width, lnki_halign_bry, lnki_href, img_view_src, img_orig_src, img_alt, xfer_itm);
this.Write_file_video(bfr, ctx, hctx, src, lnki, uid, div_width, lnki_halign_bry, lnki_ttl, lnki_href, img_view_src, img_orig_src, img_alt, xfer_itm);
}
else if (orig_ext.Id_is_audio()) // audio
this.Write_file_audio(bfr, ctx, hctx, src, lnki, uid, div_width, lnki_halign_bry, lnki_href, img_orig_src, img_alt);
@ -100,10 +100,10 @@ public class Xoh_file_wtr__basic {
else
bfr.Add(content);
}
private void Write_file_video(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_lnki_tkn lnki, int uid, int div_width, byte[] lnki_halign_bry, byte[] lnki_href, byte[] img_view_src, byte[] img_orig_src, byte[] alt, Xof_file_itm xfer_itm) {
private void Write_file_video(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_lnki_tkn lnki, int uid, int div_width, byte[] lnki_halign_bry, byte[] lnki_ttl, byte[] lnki_href, byte[] img_view_src, byte[] img_orig_src, byte[] alt, Xof_file_itm xfer_itm) {
xfer_itm.Html_elem_tid_(Xof_html_elem.Tid_vid);
boolean video_is_thumb = Xop_lnki_type.Id_defaults_to_thumb(lnki.Lnki_type());
byte[] content = Arg_content_video(ctx, hctx, src, lnki, xfer_itm, uid, video_is_thumb, lnki_href, img_view_src, img_orig_src, alt);
byte[] content = Arg_content_video(ctx, hctx, src, lnki, xfer_itm, uid, video_is_thumb, lnki_ttl, lnki_href, img_view_src, img_orig_src, alt);
if (video_is_thumb)
html_fmtr.Html_thumb_core(bfr, hctx.Mode_is_hdump(), uid, lnki_halign_bry, div_width, content);
else
@ -178,7 +178,7 @@ public class Xoh_file_wtr__basic {
html_fmtr.Html_thumb_file_audio(scratch_bfr, Arg_caption_div(ctx, hctx, src, lnki, uid, img_orig_src, lnki_href), Arg_alt_html(ctx, hctx, src, lnki), Arg_play_btn(hctx.Mode_is_hdump(), uid, play_btn_width, Play_btn_max_width, img_orig_src, Xoh_file_html_fmtr__base.Escape_xowa_title(lnki.Ttl().Page_txt())), info_btn);
return scratch_bfr.To_bry_and_clear();
}
private byte[] Arg_content_video(Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_lnki_tkn lnki, Xof_file_itm xfer_itm, int uid, boolean lnki_thumb, byte[] a_href, byte[] view_src, byte[] orig_src, byte[] img_alt) {
private byte[] Arg_content_video(Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_lnki_tkn lnki, Xof_file_itm xfer_itm, int uid, boolean lnki_thumb, byte[] lnki_ttl, byte[] a_href, byte[] view_src, byte[] orig_src, byte[] img_alt) {
int thumb_w = xfer_itm.Html_w();
int play_btn_width = thumb_w; if (play_btn_width < 1) play_btn_width = wiki.Html_mgr().Img_thumb_width();
byte[] caption_html = Bry_.Empty, alt_html = Bry_.Empty;
@ -186,8 +186,9 @@ public class Xoh_file_wtr__basic {
caption_html = Arg_caption_div(ctx, hctx, src, lnki, uid, orig_src, a_href);
alt_html = Arg_alt_html(ctx, hctx, src, lnki);
}
html_fmtr.Html_thumb_file_video(scratch_bfr, Arg_play_btn(hctx.Mode_is_hdump(), uid, play_btn_width, play_btn_width, orig_src, Xoh_file_html_fmtr__base.Escape_xowa_title(lnki.Ttl().Page_txt()))
, html_fmtr.Html_thumb_part_img(scratch_bfr, hctx, page, src, xfer_itm, uid, a_href, view_src, img_alt)
html_fmtr.Html_thumb_file_video(scratch_bfr
, Arg_play_btn(hctx.Mode_is_hdump(), uid, play_btn_width, play_btn_width, orig_src, Xoh_file_html_fmtr__base.Escape_xowa_title(lnki.Ttl().Page_txt()))
, html_fmtr.Html_thumb_part_img(scratch_bfr, hctx, page, src, xfer_itm, uid, lnki_ttl, a_href, view_src, img_alt)
, caption_html, alt_html);
return scratch_bfr.To_bry_and_clear();
}

@ -80,13 +80,10 @@ public class Xoh_tag_parser implements Gfh_doc_wkr {
break;
case Gfh_tag_.Id__ul:
if (cur.Atrs__cls_has(Xoh_gly_grp_data.Atr__cls__gallery)) {
// rv = Parse_by_data(hdoc_wkr, hctx, tag_rdr, src, cur, null, Xoh_hzip_dict_.Tid__gly);
// rv = Parse_by_data(hdoc_wkr, hctx, tag_rdr, src, cur, null, Xoh_hzip_dict_.Tid__gly); // COMMENTED: wrote gallery hzip code, but doesn't seem worth enabling for low number of galleries
if (wkr__gly.Parse1(hdoc_wkr, hctx, src, tag_rdr, cur)) return wkr__gly.Src_end();
}
break;
// case Gfh_tag_.Id__td:
// if (wkr__xnde.Parse(hdoc_wkr, hctx, tag_rdr, src, cur)) return wkr__xnde.Src_end();
// break;
}
if (rv == -1) {
rv = cur_end;

@ -18,8 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.htmls.heads; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*;
public class Xoh_head_itm__timeline extends Xoh_head_itm__base {
@Override public byte[] Key() {return Xoh_head_itm_.Key__timeline;}
@Override public int Flags() {return Flag__css_include;}
@Override public void Write_css_include(Xoae_app app, Xowe_wiki wiki, Xoae_page page, Xoh_head_wtr wtr) {
@Override public int Flags() {return Flag__js_include;}
@Override public void Write_js_include(Xoae_app app, Xowe_wiki wiki, Xoae_page page, Xoh_head_wtr wtr) {
if (Url_js == null) Url_js = app.Fsys_mgr().Bin_any_dir().GenSubFil_nest("xowa", "html", "res", "src", "xowa", "timeline", "timeline.js").To_http_file_bry();
wtr.Write_js_include(Url_js);
}

@ -68,7 +68,10 @@ public class Xoh_head_mgr implements gplx.core.brys.Bfr_arg {
itm__globals.Enabled_y_(); // for now, always mark this and rest as exists; DATE:2014-06-09
itm__collapsible.Enabled_y_();
itm__navframe.Enabled_y_();
itm__popups.Enabled_(app.Api_root().Html().Modules().Popups().Enabled());
boolean popups_enabled
= !app.Mode().Tid_is_http() // do not enable if http_server, else js errors when calling xowa_exec; DATE:2016-06-22
&& app.Api_root().Html().Modules().Popups().Enabled(); // check user_cfg
itm__popups.Enabled_(popups_enabled);
return this;
}
public void Clear() {

@ -207,6 +207,7 @@ public class Xoh_head_wtr {
for (int i = 0; i < val_len; i++) {
byte b = val[i];
if (b == quote_byte) bfr.Add_byte_backslash(); // escape quote
else if (b == Byte_ascii.Backslash) bfr.Add_byte_backslash(); // escape backslash
bfr.Add_byte(b);
}
bfr.Add_byte(quote_byte);

@ -16,11 +16,105 @@ 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.htmls.tocs; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*;
class Xoh_toc_wtr {
private final Gfh_tag_rdr tag_rdr = Gfh_tag_rdr.New__html();
private byte[] page_name = Bry_.Empty;
private final Bry_bfr bfr = Bry_bfr_.New();
public void Clear() {
bfr.Clear();
}
public void Add(byte[] hdr_text) { // text within hdr; EX: <h2>Abc</h2> -> Abc
public void Page_name_(byte[] page_name) {this.page_name = page_name;}
public byte[] Convert(byte[] src) { // text within hdr; EX: <h2>Abc</h2> -> Abc
int end = src.length;
tag_rdr.Init(page_name, src, 0, end);
Convert_recurse(0, src, 0, end);
return bfr.To_bry_and_clear_and_trim();
}
private static void Add_wo_comment(Bry_bfr bfr, byte[] src, int bgn, int end) {
int pos = bgn;
while (true) {
int comm_bgn = Bry_find_.Find_fwd(src, Gfh_tag_.Comm_bgn, pos, end);
if (comm_bgn != -1) {
int tmp_pos = comm_bgn + Gfh_tag_.Comm_bgn_len;
int comm_end = Bry_find_.Find_fwd(src, Gfh_tag_.Comm_end, tmp_pos, end);
if (comm_end != -1) {
bfr.Add_mid(src, pos, comm_bgn);
pos = comm_end + Gfh_tag_.Comm_end_len;
continue;
}
}
bfr.Add_mid(src, pos, end);
break;
}
}
private void Convert_recurse(int depth, byte[] src, int pos, int end) {
tag_rdr.Src_rng_(pos, end);
while (pos < end) {
Gfh_tag lhs = tag_rdr.Tag__move_fwd_head();
int tag_id = lhs.Name_id();
// add any text before lhs;
int txt_end = lhs.Src_bgn();
switch (tag_id) {
case Gfh_tag_.Id__eos: txt_end = end; break; // eos; print everything until end
}
if (pos < txt_end) Add_wo_comment(bfr, src, pos, txt_end);
// set print_tag / recurse based on tag
boolean print_tag = false, recurse = true;
switch (tag_id) {
case Gfh_tag_.Id__eos: // eos; return;
return;
case Gfh_tag_.Id__i: // always print tag
case Gfh_tag_.Id__b:
print_tag = true;
break;
case Gfh_tag_.Id__small: // only print tag if not nested
case Gfh_tag_.Id__sup:
case Gfh_tag_.Id__any:
default: {
if (depth > 0)
print_tag = true;
break;
}
case Gfh_tag_.Id__comment: // never print tag
case Gfh_tag_.Id__img:
case Gfh_tag_.Id__br:
case Gfh_tag_.Id__hr:
print_tag = false;
recurse = false;
break;
case Gfh_tag_.Id__a: // a never prints tag; also, also, do not recurse if ref
print_tag = false;
byte[] href_val = lhs.Atrs__get_as_bry(Gfh_atr_.Bry__href);
if (Bry_.Has_at_bgn(href_val, gplx.xowa.xtns.cites.Ref_html_wtr_cfg.Note_href_bgn)) // do not print if href='#cite_note-...'; EX: <a href=\"#cite_note-0\">[1]</a>
recurse = false;
break;
}
// get lhs / rhs vars
int lhs_bgn = lhs.Src_bgn(), lhs_end = lhs.Src_end();
boolean lhs_is_pair = !lhs.Tag_is_inline();
int rhs_bgn = -1, rhs_end = -1, new_pos = lhs_end;
if (lhs_is_pair) { // get rhs unless inline
Gfh_tag rhs = tag_rdr.Tag__move_fwd_tail(tag_id);
rhs_bgn = rhs.Src_bgn(); rhs_end = rhs.Src_end();
new_pos = rhs_end;
}
// print "<tag></tag>"; also, recurse
if (print_tag) bfr.Add_mid(src, lhs_bgn, lhs_end);
if (recurse) {
Convert_recurse(depth + 1, src, lhs_end, rhs_bgn);
}
if (print_tag && lhs_is_pair)
bfr.Add_mid(src, rhs_bgn, rhs_end);
// set new_pos
pos = new_pos;
tag_rdr.Src_rng_(new_pos, end); // NOTE: must reinit pos and especially end
}
}
}

@ -16,54 +16,70 @@ 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.htmls.tocs; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*;
import org.junit.*;
import org.junit.*; import gplx.core.tests.*;
public class Xoh_toc_wtr_tst {
@Before public void init() {fxt.Clear();} private final Xoh_toc_wtr_fxt fxt = new Xoh_toc_wtr_fxt();
@Test public void Basic() {
fxt.Test__convert("a b c", "a b c");
}
@Test public void Ws() {
fxt.Test__add(" a b ", "a b");
fxt.Test__convert(" a b ", "a b");
}
@Test public void Apos__italic() {
fxt.Test__add("<i>a</i>", "<i>a</i>");
@Test public void Comment() {
fxt.Test__convert("<!--a-->", "");
}
@Test public void Xnde__small() {
fxt.Test__add("<small>a</small>", "a");
@Test public void Comment__many() {
fxt.Test__convert("1<!--2-->3<!--4-->5", "135");
}
@Test public void Xnde__nest__xnde() { // <sup> removed but not <small>
fxt.Test__add("a <sup>b<small>c</small>d</sup> e", "a b<small>c</small>d e");
@Test public void Comment__dangling() {
fxt.Test__convert("1<!--2-->3<!--4->5", "13<!--4->5");
}
@Test public void Xnde__nest__lnki() { // <small> and <a> removed
fxt.Test__add("<small><a href=\"/wiki/A\">b</a></small>", "b");
}
@Test public void Xnde__nest__inline() { // PURPOSE: do not render inline xndes; EX: Magnetic_resonance_imaging
fxt.Test__add("a<span id='b'>b<br/></span>", "ab");
@Test public void Apos__italic() {
fxt.Test__convert("<i>a</i>", "<i>a</i>");
}
@Test public void Lnki__caption() {
fxt.Test__add("<a href=\"/wiki/A\">b</a>", "b");
fxt.Test__convert("<a href=\"/wiki/A\">b</a>", "b");
}
@Test public void Lnki__caption__nest() {
fxt.Test__add("<a href=\"/wiki/A\">b<i>c</i>d</a>", "b<i>c</i>d");
fxt.Test__convert("<a href=\"/wiki/A\">b<i>c</i>d</a>", "b<i>c</i>d");
}
@Test public void Xnde__small() {
fxt.Test__convert("<small>a</small>", "a");
}
@Test public void Xnde__sup() {
fxt.Test__convert("<sup>a</sup>", "a");
}
@Test public void Xnde__nest__xnde() { // <sup> removed but not <small>
fxt.Test__convert("a <sup>b<small>c</small>d</sup> e", "a b<small>c</small>d e");
}
@Test public void Xnde__nest__lnki() { // <small> and <a> removed
fxt.Test__convert("<small><a href=\"/wiki/A\">b</a></small>", "b");
}
@Test public void Amp__ncr() {
fxt.Test__add("&#91;a&#93;", "&#91;a&#93;");
fxt.Test__convert("&#91;a&#93;", "&#91;a&#93;");
}
@Test public void Ref() { // PURPOSE: ref contents should not print in TOC; DATE:2013-07-23
fxt.Test__add("a<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>", "a");
fxt.Test__convert("a<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>", "a");
}
@Test public void Category__literal() { // PURPOSE: literal Category should show in in TOC; EX: de.w:1234; DATE:2014-01-21
fxt.Test__add("A<a href=\"/wiki/Category:B\">Category:B</a>", "ACategory:B");
fxt.Test__convert("A<a href=\"/wiki/Category:B\">Category:B</a>", "ACategory:B");
}
@Test public void File() { // PURPOSE: file should show in in TOC; EX: tr.w:D<>nya_Miraslari; DATE:2014-06-06
fxt.Test__add
fxt.Test__convert
( "<a href=\"/wiki/File:A.png\" class=\"image\" xowa_title=\"A.png\"><img id=\"xoimg_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/orig/7/0/A.png\" width=\"0\" height=\"0\" /></a> b"
, "b");
}
@Test public void Xnde__nest__inline() { // PURPOSE: do not render inline xndes; EX: Magnetic_resonance_imaging
fxt.Test__convert("a<span id='b'>b<br/></span>", "ab");
}
@Test public void Translate_w_comment() { // PURPOSE: <translate> is an xtn and parses its innerText separately; meanwhile, toc_mgr defaults to using the innerText to build toc; EX:Wikidata:Introduction; DATE:2013-07-16
fxt.Test__add("<translate><!--b-->ac</translate>", "ac");
fxt.Test__convert("<translate><!--b-->ac</translate>", "ac");
}
}
class Xoh_toc_wtr_fxt {
private final Xoh_toc_wtr wtr = new Xoh_toc_wtr();
public void Clear() {wtr.Clear();}
public void Test__add(String html, String expd_text) {
public void Test__convert(String html, String expd) {
Gftest.Eq__str(expd, wtr.Convert(Bry_.new_u8(html)));
}
}

@ -51,7 +51,7 @@ public class Xop_subst_tst {
@Test public void Urlencode_missing_ttl() { // PURPOSE: handle missing ttl inside {{does-template-exist}}; EX: en.d:Kazakhstan; DATE:2014-03-25
fxt.Init_defn_clear();
fxt.Init_defn_add("test", "{{safesubst:urlencode:{{safesubst:Template:{{{1}}}}}}}");
fxt.Test_parse_page_tmpl_str("{{test|xyz}}", "%5B%5B%3ATemplate%3AXyz%5D%5D"); // url-encoded version of [[:Template:xyz]]
fxt.Test_parse_page_tmpl_str("{{test|xyz}}", "%5B%5BTemplate%3Axyz%5D%5D"); // url-encoded version of [[:Template:xyz]]; NOTE: removed leading ":" from ":Template:" DATE:2016-06-24
}
@Test public void Urlencode_invalid_ttl() { // PURPOSE: handle invalid ttl inside does-template-exist; EX: en.d:peace; DATE:2014-03-31
fxt.Init_defn_clear();

@ -56,6 +56,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
int name_bgn = 0, name_ary_len = 0;
boolean subst_found = false;
boolean name_had_subst = false;
boolean template_prefix_found = false;
if (defn == Xot_defn_.Null) { // tmpl_name is not exact match; may be dynamic, subst, transclusion, etc..
if (name_key_tkn.Itm_static() == Bool_.N_byte) { // tmpl is dynamic; EX:{{{{{1}}}|a}}
Bry_bfr name_tkn_bfr = Bry_bfr_.New_w_size(name_tkn.Src_end() - name_tkn.Src_bgn());
@ -77,11 +78,10 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
return false;
}
if (name_ary[name_bgn] == Byte_ascii.Colon) { // check 1st letter for transclusion
return Transclude(ctx, wiki, bfr, name_ary, caller, src); // transclusion; EX: {{:Name of page}}
return Transclude(ctx, wiki, bfr, Bool_.N, name_ary, caller, src); // transclusion; EX: {{:Name of page}}
}
// ignore "{{Template:"; EX: {{Template:a}} is the same thing as {{a}}
boolean template_prefix_found = false;
int tmpl_ns_len = wiki.Ns_mgr().Tmpls_get_w_colon(name_ary, name_bgn, name_ary_len);
if (tmpl_ns_len != Bry_find_.Not_found) {
name_ary = Bry_.Mid(name_ary, name_bgn + tmpl_ns_len, name_ary_len);
@ -191,14 +191,6 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
bfr.Add(Xop_curly_end_lxr.Hook);
return false;
}
// DELETE:v3.6.4
// byte[] missing_ttl
// = subst_found || template_prefix_found // if "subst:" or "Template:" found, use orig name; DATE:2014-03-31
// ? name_ary_orig
// : name_ary
// ;
// bfr.Add(Xop_curly_bgn_lxr.Hook).Add(missing_ttl).Add(Xop_curly_end_lxr.Hook);
// return false;
}
else { // some templates produce null ttls; EX: "Citation needed{{subst"
defn = wiki.Cache_mgr().Defn_cache().Get_by_key(ttl.Page_db());
@ -242,8 +234,8 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
return SubEval(ctx, wiki, bfr, name_ary, caller, src);
}
if (subst_found)
return Transclude(ctx, wiki, bfr, name_ary, caller, src);
Print_not_found(bfr, wiki.Ns_mgr(), name_ary);
return Transclude(ctx, wiki, bfr, template_prefix_found, name_ary, caller, src);
Print_not_found__w_template(bfr, wiki.Ns_mgr(), name_ary);
return false;
}
break;
@ -351,7 +343,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
bfr.Add(nde.Val_tkn().Dat_ary());
}
}
private boolean Transclude(Xop_ctx ctx, Xowe_wiki wiki, Bry_bfr bfr, byte[] name_ary, Xot_invk caller, byte[] src) {
private boolean Transclude(Xop_ctx ctx, Xowe_wiki wiki, Bry_bfr bfr, boolean template_prefix_found, byte[] name_ary, Xot_invk caller, byte[] src) {
Xoa_ttl page_ttl = Xoa_ttl.parse(wiki, name_ary); if (page_ttl == null) return false; // ttl not valid; EX: {{:[[abc]]}}
byte[] transclude_src = null;
if (page_ttl.Ns().Id_is_tmpl()) { // ttl is template; check tmpl_regy first before going to data_mgr
@ -372,7 +364,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
return Eval_sub(ctx, transclude_tmpl, caller, src, bfr);
}
else {
Print_not_found(bfr, wiki.Ns_mgr(), page_ttl.Full_txt_w_ttl_case());
Print_not_found__by_transclude(bfr, wiki.Ns_mgr(), template_prefix_found, name_ary);
return false;
}
}
@ -402,9 +394,17 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
}
return rv;
}
public static void Print_not_found(Bry_bfr bfr, Xow_ns_mgr ns_mgr, byte[] name_ary) { // print missing as [[:Template:Missing]]; REF:MW: Parser.php|braceSubstitution|$text = "[[:$titleText]]"; EX:en.d:Kazakhstan; DATE:2014-03-25
byte[] template_ns_name = ns_mgr.Ns_template().Name_db();
bfr.Add(Xop_tkn_.Lnki_bgn).Add_byte(Byte_ascii.Colon).Add(template_ns_name).Add_byte(Byte_ascii.Colon).Add(name_ary).Add(Xop_tkn_.Lnki_end);
private static void Print_not_found__by_transclude(Bry_bfr bfr, Xow_ns_mgr ns_mgr, boolean name_has_template, byte[] name_ary) {// print missing as [[Missing]]; PAGE:en.d:a DATE:2016-06-24
bfr.Add(Xop_tkn_.Lnki_bgn);
if (name_has_template)
bfr.Add(ns_mgr.Ns_template().Name_db()).Add_byte(Byte_ascii.Colon);
bfr.Add(name_ary);
bfr.Add(Xop_tkn_.Lnki_end);
}
public static void Print_not_found__w_template(Bry_bfr bfr, Xow_ns_mgr ns_mgr, byte[] name_ary) { // print missing as [[:Template:Missing]]; REF:MW: Parser.php|braceSubstitution|$text = "[[:$titleText]]"; EX:en.d:Kazakhstan; DATE:2014-03-25
bfr.Add(Xop_tkn_.Lnki_bgn).Add_byte(Byte_ascii.Colon);
bfr.Add(ns_mgr.Ns_template().Name_db()).Add_byte(Byte_ascii.Colon);
bfr.Add(name_ary).Add(Xop_tkn_.Lnki_end);
}
private boolean SubEval(Xop_ctx ctx, Xowe_wiki wiki, Bry_bfr bfr, byte[] name_ary, Xot_invk caller, byte[] src_for_tkn) {
Xoa_ttl page_ttl = Xoa_ttl.parse(wiki, name_ary); if (page_ttl == null) return false; // ttl not valid; EX: {{:[[abc]]}}

@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*; import gplx.xowa.wikis.ttls.*; import gplx.xowa.wikis.nss.*;
public class Xot_invk_wkr_basic_tst {
public class Xot_invk_wkr__basic__tst {
private final Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic() {

@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xot_invk_wkr_prepend_nl_tst {
public class Xot_invk_wkr__prepend_nl__tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() { // PURPOSE: if {| : ; # *, auto add new_line REF.MW:Parser.php|braceSubstitution
fxt.Init_defn_clear();

@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xot_invk_wkr_raw_msg_tst {
public class Xot_invk_wkr__raw_msg__tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_defn_clear();}
@Test public void Raw() { // PURPOSE: {{raw:A}} is same as {{A}}; EX.WIKT:android; {{raw:ja/script}}

@ -17,10 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
import org.junit.*;
public class Xot_invk_wkr_transclude_tst {
public class Xot_invk_wkr__transclude__tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_defn_clear();}
@Test public void Template() { // PURPOSE: {{:Template:Test}} is same as {{Template:Test}}; EX.WIKT:android; japanese and {{:Template:ja/script}}
@Test public void Basic() { // PURPOSE: {{:Template:Test}} is same as {{Template:Test}}; EX.WIKT:android; japanese and {{:Template:ja/script}}
fxt.Init_defn_add("Test_1", "{{#if:|y|n}}"); // NOTE: must be of form "Test 1"; test_1 will fail
fxt.Test_parse_tmpl_str("{{:Template:Test 1}}", "n");
}
@ -33,8 +33,19 @@ public class Xot_invk_wkr_transclude_tst {
fxt.Init_page_create("Root", "<gallery>A.png|a{{/Leaf}}b</gallery>"); // NOTE: gallery neeeded for XOWA to fail; MW fails if just {{/Leaf}}
fxt.Test_parse_page("Root", "<gallery>A.png|a{{/Leaf}}b</gallery>");
}
@Test public void Missing() { // PURPOSE: transclusion of a missing page should create a link, not print an empty String; EX: it.u:Dipartimento:Design; DATE:2014-02-12
@Test public void Missing__sub_page() { // PURPOSE: transclusion of a missing page should create a link, not print an empty String; EX: it.u:Dipartimento:Design; DATE:2014-02-12
fxt.Page_ttl_("Test_Page");
fxt.Test_parse_tmpl_str("{{/Sub}}", "[[Test_Page/Sub]]");
}
@Test public void Missing__colon_prefix() {// PURPOSE: page with colon_prefix should not add Template: PAGE:en.d:a; DATE:2016-06-24
fxt.Test_parse_tmpl_str("{{:a}}", "[[:a]]"); // ":a", not "Template:A" or "A"
}
@Test public void Colon_by_safesubst() { // SUPPORT: page with colon_prefix should not add Template: PAGE:en.d:a; DATE:2016-06-24
fxt.Init_defn_add("Test_2", "{{safesubst:Template:{{{1}}}}}");
fxt.Test_parse_tmpl_str("{{Test 2|b}}", "[[Template:b]]");
}
@Test public void Colon_w_template() { // SUPPORT: page with colon_prefix should not add Template: PAGE:en.d:a; DATE:2016-06-24
fxt.Init_defn_add("Test_3", "{{:Template:{{{1}}}}}");
fxt.Test_parse_tmpl_str("{{Test 3|b}}", "[[:Template:b]]");
}
}

@ -23,6 +23,7 @@ public class Xow_abrv_xo__tst {
fxt.Test("en.wikipedia.org" , "en.w"); // multi.enwiki
fxt.Test("fr.wiktionary.org" , "fr.d"); // multi.frwiktionary
fxt.Test("commons.wikimedia.org" , "c"); // important.unique.commons
fxt.Test("species.wikimedia.org" , "species"); // important.unique.species
fxt.Test("www.wikidata.org" , "wd"); // important.unique.wikidata
fxt.Test("home" , "home"); // important.unique.xowa
fxt.Test("meta.wikimedia.org" , "meta"); // wikimedia.unique

@ -92,7 +92,7 @@ public class Xow_domain_tid_ {
, Itm__wikiversity = new_(Bool_.Y , Xow_domain_type_src_.Int__wmf , Int__wikiversity , Bry__wikiversity , "u" , ".wikiversity.org")
, Itm__wikinews = new_(Bool_.Y , Xow_domain_type_src_.Int__wmf , Int__wikinews , Bry__wikinews , "n" , ".wikinews.org")
, Itm__wikimedia = new_(Bool_.Y , Xow_domain_type_src_.Int__wmf , Int__wikimedia , Bry__wikimedia , "m" , ".wikimedia.org")
, Itm__species = new_(Bool_.Y , Xow_domain_type_src_.Int__wmf , Int__species , Bry__species , "species" , Xow_domain_itm_.Str__species)
, Itm__species = new_(Bool_.N , Xow_domain_type_src_.Int__wmf , Int__species , Bry__species , "species" , Xow_domain_itm_.Str__species)
, Itm__commons = new_(Bool_.N , Xow_domain_type_src_.Int__wmf , Int__commons , Bry__commons , "c" , Xow_domain_itm_.Str__commons)
, Itm__wikidata = new_(Bool_.N , Xow_domain_type_src_.Int__wmf , Int__wikidata , Bry__wikidata , "wd" , Xow_domain_itm_.Str__wikidata)
, Itm__mediawiki = new_(Bool_.N , Xow_domain_type_src_.Int__wmf , Int__mediawiki , Bry__mediawiki , "mw" , Xow_domain_itm_.Str__mediawiki)

@ -22,14 +22,14 @@ public class Xowe_page_mgr {
public Xowe_page_mgr(Xowe_wiki wiki) {this.wiki = wiki;}
public Xoae_page Load_page(Xoa_url url, Xoa_ttl ttl, Xog_tab_itm tab) {
Xoa_app_.Usr_dlg().Log_many("", "", "page.load: url=~{0}", url.To_str());
Wait_for_popups();
Wait_for_popups(wiki.App());
Xowe_wiki_.Rls_mem_if_needed(wiki);
// load page meta; wait_for_popups
Xoae_page page = wiki.Data_mgr().Load_page_and_parse(url, ttl, wiki.Lang(), tab, false);
boolean hdump_exists = page.Revision_data().Html_db_id() != -1 && wiki.Appe().Api_root().Wiki().Hdump().Read_preferred();
page.Html_data().Hdump_exists_(hdump_exists);
Wait_for_popups();
Wait_for_popups(wiki.App());
// load page text
boolean parse = true;
@ -41,7 +41,8 @@ public class Xowe_page_mgr {
wiki.Parser_mgr().Parse(page, false);
return page;
}
private static void Wait_for_popups() {// HACK: wait for popups to finish, else thread errors due to popups and loader mutating cached items
private static void Wait_for_popups(Xoa_app app) {// HACK: wait for popups to finish, else thread errors due to popups and loader mutating cached items
if (app.Mode().Tid_is_http()) return;
int wait_count = 0;
while (gplx.xowa.htmls.modules.popups.Xow_popup_mgr.Running() && ++wait_count < 100)
gplx.core.threads.Thread_adp_.Sleep(10);

@ -20,11 +20,10 @@ import gplx.xowa.wikis.nss.*; import gplx.xowa.parsers.lnkis.*;
public class Xopg_lnki_list {
private final List_adp list = List_adp_.New();
private int lnki_idx;
public Xopg_lnki_list(boolean ttl_is_module) { // never redlink in Module ns; particularly since Lua has multi-line comments for [[ ]]
this.disabled = ttl_is_module;
public Xopg_lnki_list() {
this.Clear();
}
public boolean Disabled() {return disabled;} private final boolean disabled;
public boolean Disabled() {return disabled;} private boolean disabled; public Xopg_lnki_list Disabled_(boolean v) {this.disabled = v; return this;}
public int Len() {return list.Len();}
public Xopg_lnki_itm Get_at(int i) {return (Xopg_lnki_itm)list.Get_at(i);}
public void Add_direct(Xopg_lnki_itm lnki) {list.Add(lnki);} // add lnki directly to list without changing html_uid; needed for hdumps which call "Fill_page" to transfer from Xoh_page to Xoae_page

@ -42,6 +42,7 @@ public class Ref_html_wtr_cfg {
}
public static final byte[] Msg_backlabels_err = Bry_.new_a7("cite_error_no_link_label_group");
private static final byte[] Msg_backlabels = Bry_.new_a7("cite_references_link_many_format_backlink_labels");
public static final byte[] Note_href_bgn = Bry_.new_a7("#cite_note-"); // for TOC
public static Ref_html_wtr_cfg new_() {
Ref_html_wtr_cfg rv = new Ref_html_wtr_cfg();
rv.Itm_html_ ("<sup id=\"cite_ref-~{itm_id}\" class=\"reference\"><a href=\"#cite_note-~{grp_id}\">[~{grp_key}]</a></sup>");

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

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

@ -0,0 +1,77 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
class Pfunc_tag_kvp_wtr {
private int key_bgn, key_end;
private int val_bgn, val_end;
public void Write_as_html_atr(Bry_bfr tmp, byte[] kvp_bry) {
Parse(kvp_bry);
// write as html
if (val_bgn == -1) return; // ignore atrs with empty vals: EX:{{#tag:ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич DATE:2014-07-03
if (key_bgn != -1)
tmp.Add(Bry_.Mid(kvp_bry, key_bgn, key_end));
if (val_bgn != -1) {
if (key_bgn != -1)
tmp.Add_byte(Byte_ascii.Eq);
tmp.Add_byte(Byte_ascii.Quote);
tmp.Add(Bry_.Mid(kvp_bry, val_bgn, val_end));
tmp.Add_byte(Byte_ascii.Quote);
}
}
private void Parse(byte[] src) {
this.key_bgn = this.key_end = this.val_bgn = this.val_end = -1; // NOTE: must clear; DATE:2014-07-20
int itm_bgn = -1, itm_end = -1, src_len = src.length;
byte quote_byte = Byte_ascii.Null;
boolean mode_is_key = true;
for (int i = 0; i < src_len; ++i) {
byte b = src[i];
switch (b) {
case Byte_ascii.Eq:
if (mode_is_key) {
mode_is_key = false;
if (itm_end == -1) itm_end = i;
this.key_bgn = itm_bgn;
this.key_end = itm_end;
itm_bgn = itm_end = -1;
}
break;
// quote-char encountered ...
// NOTE: quotes cannot be escaped; also, in case of multiple quotes (a="b"c") regx uses first two quotes; REF:MW:CoreParserFunctions.php|tagObj
case Byte_ascii.Quote:
case Byte_ascii.Apos:
if (itm_bgn == -1) { // ... quote hasn't started; start quote
itm_bgn = i + 1;
quote_byte = b;
}
else if (itm_end == -1 // ... quote has started and quote hasn't ended; note that this ends quote immediately; EX: 'id="a"b"' -> 'id=a' x> 'id=a"b'
&& b == quote_byte) // handle alternating quotes; EX: id="a'b" -> id=a'b x> id=a; PAGE:en.s:The_formative_period_in_Colby%27s_history; DATE:2016-06-23
itm_end = i;
break;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:// NOTE: do not need to handle ws, b/c argBldr will trim it EX: {{#tag|a| b = c }}; " b " and " c " are automatically trimmed
break;
default:
if (itm_bgn == -1) itm_bgn = i;
break;
}
}
if (itm_end == -1) itm_end = src_len;
this.val_bgn = itm_bgn;
this.val_end = itm_end;
}
}

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

@ -30,6 +30,6 @@ public class Pfunc_anchorencode_tst {
@Test public void Html_ncr() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a &#34; b}}" , "{{test}}" , "a_.22_b");}
@Test public void Html_ref() {fxt.Test_parse_tmpl_str_test("{{anchorencode:a &quot; b}}" , "{{test}}" , "a_.22_b");}
@Test public void Tmpl_missing_basic() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{a}}}}" , "{{test}}" , "Template:a");}
@Test public void Tmpl_missing_colon() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{:a}}}}" , "{{test}}" , "Template:A");}
@Test public void Tmpl_missing_colon() {fxt.Test_parse_tmpl_str_test("{{anchorencode:{{:a}}}}" , "{{test}}" , "a");} // NOTE: changed from "Template:A" to "a"; DATE:2016-06-24
@Test public void Lnki_literal() {fxt.Test_parse_tmpl_str_test("{{anchorencode:[[:a]]}}" , "{{test}}" , "a");}
}

Loading…
Cancel
Save