1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
import gplx.xowa.xtns.cite.*; import gplx.xowa.xtns.imaps.*; import gplx.xowa.xtns.relatedSites.*; import gplx.xowa.xtns.proofreadPage.*; import gplx.xowa.xtns.wdatas.*;
import gplx.xowa.xtns.insiders.*; import gplx.xowa.xtns.indicators.*;
public class Xow_xtn_mgr implements GfoInvkAble {
private Ordered_hash regy = Ordered_hash_.new_bry_();
public int Count() {return regy.Count();}
public Cite_xtn_mgr Xtn_cite() {return xtn_cite;} private Cite_xtn_mgr xtn_cite;
public Imap_xtn_mgr Xtn_imap() {return xtn_imap;} private Imap_xtn_mgr xtn_imap;
public Sites_xtn_mgr Xtn_sites() {return xtn_sites;} private Sites_xtn_mgr xtn_sites;
public Insider_xtn_mgr Xtn_insider() {return xtn_insider;} private Insider_xtn_mgr xtn_insider;
public Indicator_xtn_mgr Xtn_indicator() {return xtn_indicator;} private Indicator_xtn_mgr xtn_indicator;
public Pp_xtn_mgr Xtn_proofread() {return xtn_proofread;} private Pp_xtn_mgr xtn_proofread;
public Wdata_xtn_mgr Xtn_wikibase() {return xtn_wikibase;} private Wdata_xtn_mgr xtn_wikibase;
public Xow_xtn_mgr Ctor_by_app(Xoae_app app) { // NOTE: needed for options
Add(app, new Cite_xtn_mgr());
Add(app, new Imap_xtn_mgr());
Add(app, new Sites_xtn_mgr());
Add(app, new Insider_xtn_mgr());
Add(app, new Indicator_xtn_mgr());
Add(app, new Pp_xtn_mgr());
Add(app, new Wdata_xtn_mgr());
Add(app, new gplx.xowa.xtns.scribunto.Scrib_xtn_mgr());
Add(app, new gplx.xowa.xtns.gallery.Gallery_xtn_mgr());
Add(app, new gplx.xowa.xtns.poems.Poem_xtn_mgr());
Add(app, new gplx.xowa.xtns.hieros.Hiero_xtn_mgr());
Add(app, new gplx.xowa.xtns.scores.Score_xtn_mgr());
Add(app, new gplx.xowa.xtns.listings.Listing_xtn_mgr());
Add(app, new gplx.xowa.xtns.titleBlacklists.Blacklist_xtn_mgr());
Add(app, new gplx.xowa.xtns.pfuncs.scribunto.Pfunc_xtn_mgr());
return this;
}
public Xow_xtn_mgr Ctor_by_wiki(Xowe_wiki wiki) {
Xoae_app app = wiki.Appe();
Xow_xtn_mgr app_xtn_mgr = app.Xtn_mgr();
int regy_len = app_xtn_mgr.Count();
for (int i = 0; i < regy_len; i++) {
Xox_mgr proto = (Xox_mgr)app_xtn_mgr.Get_at(i);
Xox_mgr mgr = proto.Clone_new();
mgr.Xtn_ctor_by_wiki(wiki);
regy.Add(mgr.Xtn_key(), mgr);
Set_members(mgr);
}
return this;
}
public void Init_by_app(Xoae_app app) {
int regy_len = regy.Count();
for (int i = 0; i < regy_len; i++) {
Xox_mgr mgr = (Xox_mgr)regy.Get_at(i);
mgr.Xtn_init_by_app(app);
}
}
public Xow_xtn_mgr Init_by_wiki(Xowe_wiki wiki) {
int regy_len = regy.Count();
for (int i = 0; i < regy_len; i++) {
Xox_mgr mgr = (Xox_mgr)regy.Get_at(i);
mgr.Xtn_init_by_wiki(wiki);
}
return this;
}
public Xox_mgr Get_at(int i) {return (Xox_mgr)regy.Get_at(i);}
public Xox_mgr Get_or_fail(byte[] key) {Object rv = regy.Get_by(key); if (rv == null) throw Exc_.new_("unknown xtn", "key", String_.new_u8(key)); return (Xox_mgr)rv;}
private Xox_mgr Add(Xoae_app app, Xox_mgr xtn) {
xtn.Xtn_ctor_by_app(app);
regy.Add(xtn.Xtn_key(), xtn);
Set_members(xtn);
return xtn;
}
private void Set_members(Xox_mgr mgr) {
byte[] xtn_key = mgr.Xtn_key();
Object o = xtn_tid_trie.Match_exact(xtn_key, 0, xtn_key.length); if (o == null) return;
switch (((Byte_obj_val)o).Val()) {
case Tid_cite: xtn_cite = (Cite_xtn_mgr)mgr; break;
case Tid_sites: xtn_sites = (Sites_xtn_mgr)mgr; break;
case Tid_insider: xtn_insider = (Insider_xtn_mgr)mgr; break;
case Tid_indicator: xtn_indicator= (Indicator_xtn_mgr)mgr; break;
case Tid_imap: xtn_imap = (Imap_xtn_mgr)mgr; break;
case Tid_proofread: xtn_proofread = (Pp_xtn_mgr)mgr; break;
case Tid_wikibase: xtn_wikibase = (Wdata_xtn_mgr)mgr; break;
}
}
private static final byte Tid_cite = 0, Tid_sites = 1, Tid_insider = 2, Tid_imap = 3, Tid_proofread = 4, Tid_wikibase = 5, Tid_indicator = 6;
private static final Btrie_slim_mgr xtn_tid_trie = Btrie_slim_mgr.cs_()
.Add_bry_bval(Cite_xtn_mgr.XTN_KEY , Tid_cite)
.Add_bry_bval(Sites_xtn_mgr.XTN_KEY , Tid_sites)
.Add_bry_bval(Insider_xtn_mgr.XTN_KEY , Tid_insider)
.Add_bry_bval(Indicator_xtn_mgr.XTN_KEY , Tid_indicator)
.Add_bry_bval(Imap_xtn_mgr.XTN_KEY , Tid_imap)
.Add_bry_bval(Pp_xtn_mgr.XTN_KEY , Tid_proofread)
.Add_bry_bval(Wdata_xtn_mgr.XTN_KEY , Tid_wikibase)
;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_get)) return Get_or_fail(m.ReadBry("v"));
else return GfoInvkAble_.Rv_unhandled;
} private static final String Invk_get = "get";
}

View File

@@ -0,0 +1,26 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns; import gplx.*; import gplx.xowa.*;
public interface Xox_mgr extends GfoInvkAble {
byte[] Xtn_key();
void Xtn_ctor_by_app(Xoae_app app);
void Xtn_ctor_by_wiki(Xowe_wiki wiki);
void Xtn_init_by_app(Xoae_app app);
void Xtn_init_by_wiki(Xowe_wiki wiki);
Xox_mgr Clone_new();
}

View File

@@ -0,0 +1,68 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.xowa.bldrs.langs.*; import gplx.xowa.html.*;
public abstract class Xox_mgr_base implements Xox_mgr {
public Xox_mgr_base() {
this.enabled = Enabled_default();
}
public abstract byte[] Xtn_key();
public abstract Xox_mgr Clone_new();
public boolean Enabled() {return enabled;} private boolean enabled;
@gplx.Virtual public boolean Enabled_default() {return true;}
public void Enabled_y_() {enabled = true; enabled_manually = true;} public void Enabled_n_() {enabled = false; enabled_manually = true;} // TEST:
public void Enabled_(boolean v) {enabled = v;}
public boolean Enabled_manually() {return enabled_manually;} private boolean enabled_manually;
@gplx.Virtual public void Xtn_ctor_by_app(Xoae_app app) {}
@gplx.Virtual public void Xtn_ctor_by_wiki(Xowe_wiki wiki) {}
@gplx.Virtual public void Xtn_init_by_app(Xoae_app app) {}
@gplx.Virtual public void Xtn_init_by_wiki(Xowe_wiki wiki) {}
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_enabled)) return Yn.Xto_str(enabled);
else if (ctx.Match(k, Invk_enabled_)) {enabled = m.ReadYn("v"); enabled_manually = true;}
else return GfoInvkAble_.Rv_unhandled;
return this;
}
private static final String Invk_enabled = "enabled", Invk_enabled_ = "enabled_";
public static void Xtn_write_escape(Xoae_app app, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {Xtn_write_escape(app, bfr, src, xnde.Src_bgn(), xnde.Src_end());}
public static void Xtn_write_escape(Xoae_app app, Bry_bfr bfr, byte[] src) {Xtn_write_escape(app, bfr, src, 0, src.length);}
public static void Xtn_write_escape(Xoae_app app, Bry_bfr bfr, byte[] src, int bgn, int end) {Xoh_html_wtr_escaper.Escape(app.Parser_amp_mgr(), bfr, src, bgn, end, true, false);}
public static void Xtn_write_unsupported(Xoae_app app, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde, byte parse_content_tid) {
bfr.Add(Xowa_not_implemented);
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_open_bgn(), xnde.Tag_open_end());
if (xnde.CloseMode() != Xop_xnde_tkn.CloseMode_pair) return; // inline node
switch (parse_content_tid) {
case Parse_content_tid_escape:
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
break;
case Parse_content_tid_html:
bfr.Add(ctx.Wiki().Parser().Parse_text_to_html(ctx, Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn())));
break;
case Parse_content_tid_none: default:
break;
}
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_close_bgn(), xnde.Tag_close_end());
}
public static void Xtn_load_i18n(Xowe_wiki wiki, byte[] xtn_key) {
Xoae_app app = wiki.Appe();
Io_url url = app.Fsys_mgr().Bin_xtns_dir().GenSubFil_nest(String_.new_u8(xtn_key), "i18n", wiki.Lang().Key_str() + ".json");
Xob_i18n_parser.Load_msgs(false, wiki.Lang(), url);
}
private static final byte[] Xowa_not_implemented = Bry_.new_a7("XOWA does not support this extension: ");
public static final byte Parse_content_tid_none = 0, Parse_content_tid_escape = 1, Parse_content_tid_html = 2;
}

View File

@@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns; import gplx.*; import gplx.xowa.*;
import gplx.xowa.html.*;
public interface Xox_xnde {
void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde);
void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src);
}

View File

@@ -0,0 +1,24 @@
/*
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.categoryList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Xtn_categoryList_nde_tst {
// private Xop_fxt fxt = new Xop_fxt(); String raw_src;
@Test public void Basic() {
}
}

View File

@@ -0,0 +1,24 @@
/*
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.categoryList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*;
public class Xtn_categorylist_nde implements Xox_xnde, Xop_xnde_atr_parser {
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {}
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {}
}

View File

@@ -0,0 +1,31 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Cite_xtn_mgr extends Xox_mgr_base {
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("cite");
// public byte[] Group_default_name() {return group_default_name;} private byte[] group_default_name = Bry_.new_a7("lower-alpha");
public static byte[] Group_default_name() {return group_default_name;} private static byte[] group_default_name = Bry_.new_a7("lower-alpha");
@Override public Xox_mgr Clone_new() {return new Cite_xtn_mgr();}
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_group_default_name)) return String_.new_u8(group_default_name);
else if (ctx.Match(k, Invk_group_default_name_)) group_default_name = m.ReadBry("v");
else return super.Invk(ctx, ikey, k, m);
return this;
}
private static final String Invk_group_default_name = "group_default_name", Invk_group_default_name_ = "group_default_name_";
}

View File

@@ -0,0 +1,149 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*;
public class Ref_html_wtr {
public Ref_html_wtr(Xowe_wiki wiki) {
cfg = Ref_html_wtr_cfg.new_();
}
public void Xnde_ref(Xoh_wtr_ctx opts, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
Ref_nde itm = (Ref_nde)xnde.Xnde_xtn();
if (itm == null) return;
if (itm.Follow_y()) return; // NOTE: "follow" is always appended to preceding ref; will never generate its own ^ a
byte[] itm_group = itm.Group();
boolean itm_group_is_default = Bry_.Eq(itm_group, Bry_.Empty) || Bry_.Eq(itm_group, Cite_xtn_mgr.Group_default_name()); // do not show "lower-alpha"; PAGE:en.w:Moon; DATE:2014-07-21
cfg.Itm_html().Bld_bfr_many(bfr
, Itm_id(itm, true)
, Grp_id(itm)
, itm_group_is_default
? itm.Idx_major() + 1
: (Object)grp_key_fmtr.Atrs_(cfg.Itm_grp_text(), itm.Group(), itm.Idx_major() + 1)
);
} private Bry_fmtr_arg_fmtr_objs grp_key_fmtr = Bry_fmtr_arg_.fmtr_null_();
public Ref_html_wtr_cfg Cfg() {return cfg;} private Ref_html_wtr_cfg cfg;
public void Init_by_wiki(Xowe_wiki wiki) {
cfg.Init_by_wiki(wiki);
}
private Bry_fmtr_arg Itm_id(Ref_nde itm, boolean caller_is_ref) {
if (itm.Name() == Bry_.Empty)
return itm_id_fmtr.Atrs_(cfg.Itm_id_uid(), itm.Uid());
else {
if (caller_is_ref)
return itm_id_fmtr.Atrs_(cfg.Itm_id_key_one(), itm.Name(), itm.Idx_major(), itm.Idx_minor());
else
return itm_id_fmtr.Atrs_(cfg.Itm_id_key_many(), itm.Name(), itm.Idx_major());
}
} private Bry_fmtr_arg_fmtr_objs itm_id_fmtr = Bry_fmtr_arg_.fmtr_null_();
private Bry_fmtr_arg Grp_id(Ref_nde itm) {
return itm.Name() == Bry_.Empty // name is blank >>> uid
? grp_id_fmtr.Atrs_(cfg.Grp_id_uid(), itm.Uid())
: grp_id_fmtr.Atrs_(cfg.Grp_id_key(), itm.Name(), itm.Idx_major());
} private Bry_fmtr_arg_fmtr_objs grp_id_fmtr = Bry_fmtr_arg_.fmtr_null_();
private int List_len(Ref_nde itm) {
int len = itm.Related_len();
int rv = len;
for (int i = 0; i < len; i++) {
Ref_nde list_itm = itm.Related_get(i);
if (list_itm.Nested()) --rv;
}
return rv;
}
public void Xnde_references(Xoh_html_wtr wtr, Xop_ctx ctx, Xoh_wtr_ctx opts, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
References_nde references = (References_nde)xnde.Xnde_xtn();
Ref_itm_lst lst = ctx.Cur_page().Ref_mgr().Lst_get(references.Group(), references.List_idx()); // get group; EX: <references group="note"/>
if (lst == null) return; // NOTE: possible to have a grouped references without references; EX: Infobox planet; <references group=note> in sidebar, but no refs
if (lst.Itms_len() == 0) return;
bfr.Add(cfg.Grp_bgn());
int itms_len = lst.Itms_len();
for (int j = 0; j < itms_len; j++) { // iterate over itms in grp
Ref_nde head_itm = lst.Itms_get_at(j);
Bry_bfr tmp = Bry_bfr.new_();
int list_len = List_len(head_itm);
grp_list_fmtr.Init(ctx.Wiki(), cfg, head_itm);
Ref_nde text_itm = grp_list_fmtr.IdentifyTxt(); // find the item that has the text (there should only be 0 or 1)
if (text_itm.Body() != null)
wtr.Write_tkn(tmp, ctx, opts, text_itm.Body().Root_src(), null, Xoh_html_wtr.Sub_idx_null, text_itm.Body());
// add follows
int related_len = head_itm.Related_len();
for (int k = 0; k < related_len; k++) {
Ref_nde related_itm = head_itm.Related_get(k);
if (related_itm.Follow_y()) { // NOTE: both follow and related are in the related list; only add follow
tmp.Add_byte_space(); // always add space; REF.MW:Cite_body.php;$this->mRefs[$group][$follow]['text'] = $this->mRefs[$group][$follow]['text'] . ' ' . $str;
wtr.Write_tkn(tmp, ctx, opts, related_itm.Body().Root_src(), null, Xoh_html_wtr.Sub_idx_null, related_itm.Body());
}
}
if (list_len == 0) { // ref has 0 list_itms or 1 list_itm but nested; EX: "123 ^ text"
cfg.Grp_html_one().Bld_bfr_many(bfr
, Grp_id(head_itm) // NOTE: use head_itm for back ref to work (^ must link to same id)
, Itm_id(head_itm, true)
, tmp
);
}
else { // ref has 1+ itms; EX: "123 ^ a b c text"
cfg.Grp_html_many().Bld_bfr_many(bfr
, Itm_id(text_itm, false)
, grp_list_fmtr
, tmp
);
}
}
bfr.Add(cfg.Grp_end());
}
private static Xoh_ref_list_fmtr grp_list_fmtr = new Xoh_ref_list_fmtr();
}
class Xoh_ref_list_fmtr implements Bry_fmtr_arg {
public void Init(Xowe_wiki wiki, Ref_html_wtr_cfg cfg, Ref_nde itm) {
this.wiki = wiki; this.cfg = cfg; this.itm = itm;
} private Xowe_wiki wiki; private Ref_nde itm; private Ref_html_wtr_cfg cfg;
public Ref_nde IdentifyTxt() {
if (HasTxt(itm)) return itm;
int itm_related_len = itm.Related_len();
for (int i = 0; i < itm_related_len; i++) {
Ref_nde rel = itm.Related_get(i);
if (HasTxt(rel)) return rel;
}
return itm; // no itm has text; TODO:WARN
}
private boolean HasTxt(Ref_nde v) {return v.Body() != null && v.Body().Root_src().length > 0;}
public void XferAry(Bry_bfr trg, int idx) {
int related_len = itm.Related_len();
Bry_fmtr itm_fmtr = cfg.Grp_html_list();
Fmt(itm_fmtr, wiki, trg, itm);
for (int i = 0; i < related_len; i++) {
Ref_nde link_itm = itm.Related_get(i);
if (link_itm.Nested()) continue;
Fmt(itm_fmtr, wiki, trg, link_itm);
}
}
private void Fmt(Bry_fmtr itm_fmtr, Xowe_wiki wiki, Bry_bfr trg, Ref_nde itm) {
int itm_idx_minor = itm.Idx_minor();
if (itm_idx_minor < 0) return; // HACK: <ref follow created a negative index; ignore these references for now; de.wikisource.org/wiki/Seite:Die Trunksucht.pdf/63; DATE:2013-06-22
byte[] backlabel
= itm_idx_minor < cfg.Backlabels_len()
? cfg.Backlabels()[itm.Idx_minor()]
: wiki.Parser().Parse_text_to_html(wiki.Ctx(), wiki.Msg_mgr().Val_by_key_args(Ref_html_wtr_cfg.Msg_backlabels_err, itm.Idx_minor()))
;
itm_fmtr.Bld_bfr_many(trg
, fmtr.Atrs_(cfg.Itm_id_key_one(), itm.Name(), itm.Idx_major(), itm.Idx_minor())
, backlabel
);
}
private Bry_fmtr_arg_fmtr_objs fmtr = Bry_fmtr_arg_.fmtr_null_();
}

View File

@@ -0,0 +1,121 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Ref_html_wtr_cfg {
public Bry_fmtr Itm_html() {return itm_html;} private Bry_fmtr itm_html; public Ref_html_wtr_cfg Itm_html_(String v) {itm_html = Bry_fmtr.new_(v, "itm_id", "grp_id", "grp_key"); return this;}
public Bry_fmtr Itm_id_uid() {return itm_id_uid;} private Bry_fmtr itm_id_uid; public Ref_html_wtr_cfg Itm_id_uid_(String v) {itm_id_uid = Bry_fmtr.new_(v, "uid"); return this;}
public Bry_fmtr Itm_id_key_one() {return itm_id_key_one;} private Bry_fmtr itm_id_key_one; public Ref_html_wtr_cfg Itm_id_key_one_(String v) {itm_id_key_one = Bry_fmtr.new_(v, "itm_key", "uid", "minor"); return this;}
public Bry_fmtr Itm_id_key_many() {return itm_id_key_many;} private Bry_fmtr itm_id_key_many; public Ref_html_wtr_cfg Itm_id_key_many_(String v) {itm_id_key_many = Bry_fmtr.new_(v, "itm_key", "uid"); return this;}
public Bry_fmtr Itm_grp_text() {return itm_grp_text;} private Bry_fmtr itm_grp_text; public Ref_html_wtr_cfg Itm_grp_text_(String v) {itm_grp_text = Bry_fmtr.new_(v, "grp_key", "major"); return this;}
public Bry_fmtr Grp_html_one() {return grp_html_one;} private Bry_fmtr grp_html_one; public Ref_html_wtr_cfg Grp_html_one_(String v) {grp_html_one = Bry_fmtr.new_(v, "grp_id", "itm_id", "text"); return this;}
public Bry_fmtr Grp_html_many() {return grp_html_many;} private Bry_fmtr grp_html_many; public Ref_html_wtr_cfg Grp_html_many_(String v) {grp_html_many = Bry_fmtr.new_(v, "grp_id", "related_ids", "text"); return this;}
public Bry_fmtr Grp_html_list() {return grp_html_list;} private Bry_fmtr grp_html_list; public Ref_html_wtr_cfg Grp_html_list_(String v) {grp_html_list = Bry_fmtr.new_(v, "itm_id", "backlabel"); return this;}
public Bry_fmtr Grp_id_uid() {return grp_id_uid;} private Bry_fmtr grp_id_uid; public Ref_html_wtr_cfg Grp_id_uid_(String v) {grp_id_uid = Bry_fmtr.new_(v, "uid"); return this;}
public Bry_fmtr Grp_id_key() {return grp_id_key;} private Bry_fmtr grp_id_key; public Ref_html_wtr_cfg Grp_id_key_(String v) {grp_id_key = Bry_fmtr.new_(v, "itm_key", "major"); return this;}
public byte[][] Backlabels() {return backlabels;} private byte[][] backlabels;
public int Backlabels_len() {return backlabels_len;} private int backlabels_len;
public byte[] Grp_bgn() {return grp_bgn;} private byte[] grp_bgn;
public byte[] Grp_end() {return grp_end;} private byte[] grp_end;
public void Init_by_wiki(Xowe_wiki wiki) {
byte[] backlabels_bry = wiki.Msg_mgr().Val_by_key_obj(Msg_backlabels);
Backlabels_(Ref_backlabels_xby_bry(backlabels_bry));
}
public void Backlabels_(byte[][] v) {
backlabels = v;
backlabels_len = v.length;
}
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 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>");
rv.Itm_id_uid_ ("~{uid}");
rv.Itm_id_key_one_ ("~{itm_key}_~{uid}-~{minor}");
rv.Itm_id_key_many_ ("~{itm_key}-~{uid}");
rv.Itm_grp_text_ ("~{grp_key} ~{major}");
rv.Grp_html_one_ ("<li id=\"cite_note-~{grp_id}\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-~{itm_id}\">^</a></span> <span class=\"reference-text\">~{text}</span></li>\n");
rv.Grp_html_many_ ("<li id=\"cite_note-~{grp_id}\"><span class=\"mw-cite-backlink\">^~{related_ids}</span> <span class=\"reference-text\">~{text}</span></li>\n");
rv.Grp_html_list_ (" <sup><a href=\"#cite_ref-~{itm_id}\">~{backlabel}</a></sup>");
rv.Grp_id_uid_ ("~{uid}");
rv.Grp_id_key_ ("~{itm_key}-~{major}");
rv.grp_bgn = Bry_.new_a7("<ol class=\"references\">\n");
rv.grp_end = Bry_.new_a7("</ol>\n");
rv.Backlabels_ (Ref_backlabels_default);
return rv;
} Ref_html_wtr_cfg() {}
private static final byte[][] Ref_backlabels_default = Ref_backlabels_xby_str_ary(String_.Ary // TEST:default backlabels for test only; actual backlabels will be overrriden by MediaWiki:Cite_references_link_many_format_backlink_labels; DATE:2014-06-07
( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
, "aa", "ab", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq", "ar", "as", "at", "au", "av", "aw", "ax", "ay", "az"
, "ba", "bb", "bc", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bk", "bl", "bm", "bn", "bo", "bp", "bq", "br", "bs", "bt", "bu", "bv", "bw", "bx", "by", "bz"
, "ca", "cb", "cc", "cd", "ce", "cf", "cg", "ch", "ci", "cj", "ck", "cl", "cm", "cn", "co", "cp", "cq", "cr", "cs", "ct", "cu", "cv", "cw", "cx", "cy", "cz"
, "da", "db", "dc", "dd", "de", "df", "dg", "dh", "di", "dj", "dk", "dl", "dm", "dn", "do", "dp", "dq", "dr", "ds", "dt", "du", "dv", "dw", "dx", "dy", "dz"
, "ea", "eb", "ec", "ed", "ee", "ef", "eg", "eh", "ei", "ej", "ek", "el", "em", "en", "eo", "ep", "eq", "er", "es", "et", "eu", "ev", "ew", "ex", "ey", "ez"
, "fa", "fb", "fc", "fd", "fe", "ff", "fg", "fh", "fi", "fj", "fk", "fl", "fm", "fn", "fo", "fp", "fq", "fr", "fs", "ft", "fu", "fv", "fw", "fx", "fy", "fz"
, "ga", "gb", "gc", "gd", "ge", "gf", "gg", "gh", "gi", "gj", "gk", "gl", "gm", "gn", "go", "gp", "gq", "gr", "gs", "gt", "gu", "gv", "gw", "gx", "gy", "gz"
, "ha", "hb", "hc", "hd", "he", "hf", "hg", "hh", "hi", "hj", "hk", "hl", "hm", "hn", "ho", "hp", "hq", "hr", "hs", "ht", "hu", "hv", "hw", "hx", "hy", "hz"
, "ia", "ib", "ic", "id", "ie", "if", "ig", "ih", "ii", "ij", "ik", "il", "im", "in", "io", "ip", "iq", "ir", "is", "it", "iu", "iv", "iw", "ix", "iy", "iz"
, "ja", "jb", "jc", "jd", "je", "jf", "jg", "jh", "ji", "jj", "jk", "jl", "jm", "jn", "jo", "jp", "jq", "jr", "js", "jt", "ju", "jv", "jw", "jx", "jy", "jz"
, "ka", "kb", "kc", "kd", "ke", "kf", "kg", "kh", "ki", "kj", "kk", "kl", "km", "kn", "ko", "kp", "kq", "kr", "ks", "kt", "ku", "kv", "kw", "kx", "ky", "kz"
, "la", "lb", "lc", "ld", "le", "lf", "lg", "lh", "li", "lj", "lk", "ll", "lm", "ln", "lo", "lp", "lq", "lr", "ls", "lt", "lu", "lv", "lw", "lx", "ly", "lz"
, "ma", "mb", "mc", "md", "me", "mf", "mg", "mh", "mi", "mj", "mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz"
, "na", "nb", "nc", "nd", "ne", "nf", "ng", "nh", "ni", "nj", "nk", "nl", "nm", "nn", "no", "np", "nq", "nr", "ns", "nt", "nu", "nv", "nw", "nx", "ny", "nz"
, "oa", "ob", "oc", "od", "oe", "of", "og", "oh", "oi", "oj", "ok", "ol", "om", "on", "oo", "op", "oq", "or", "os", "ot", "ou", "ov", "ow", "ox", "oy", "oz"
, "pa", "pb", "pc", "pd", "pe", "pf", "pg", "ph", "pi", "pj", "pk", "pl", "pm", "pn", "po", "pp", "pq", "pr", "ps", "pt", "pu", "pv", "pw", "px", "py", "pz"
, "qa", "qb", "qc", "qd", "qe", "qf", "qg", "qh", "qi", "qj", "qk", "ql", "qm", "qn", "qo", "qp", "qq", "qr", "qs", "qt", "qu", "qv", "qw", "qx", "qy", "qz"
, "ra", "rb", "rc", "rd", "re", "rf", "rg", "rh", "ri", "rj", "rk", "rl", "rm", "rn", "ro", "rp", "rq", "rr", "rs", "rt", "ru", "rv", "rw", "rx", "ry", "rz"
, "sa", "sb", "sc", "sd", "se", "sf", "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sp", "sq", "sr", "ss", "st", "su", "sv", "sw", "sx", "sy", "sz"
, "ta", "tb", "tc", "td", "te", "tf", "tg", "th", "ti", "tj", "tk", "tl", "tm", "tn", "to", "tp", "tq", "tr", "ts", "tt", "tu", "tv", "tw", "tx", "ty", "tz"
, "ua", "ub", "uc", "ud", "ue", "uf", "ug", "uh", "ui", "uj", "uk", "ul", "um", "un", "uo", "up", "uq", "ur", "us", "ut", "uu", "uv", "uw", "ux", "uy", "uz"
, "va", "vb", "vc", "vd", "ve", "vf", "vg", "vh", "vi", "vj", "vk", "vl", "vm", "vn", "vo", "vp", "vq", "vr", "vs", "vt", "vu", "vv", "vw", "vx", "vy", "vz"
, "wa", "wb", "wc", "wd", "we", "wf", "wg", "wh", "wi", "wj", "wk", "wl", "wm", "wn", "wo", "wp", "wq", "wr", "ws", "wt", "wu", "wv", "ww", "wx", "wy", "wz"
, "xa", "xb", "xc", "xd", "xe", "xf", "xg", "xh", "xi", "xj", "xk", "xl", "xm", "xn", "xo", "xp", "xq", "xr", "xs", "xt", "xu", "xv", "xw", "xx", "xy", "xz"
, "ya", "yb", "yc", "yd", "ye", "yf", "yg", "yh", "yi", "yj", "yk", "yl", "ym", "yn", "yo", "yp", "yq", "yr", "ys", "yt", "yu", "yv", "yw", "yx", "yy", "yz"
, "za", "zb", "zc", "zd", "ze", "zf", "zg", "zh", "zi", "zj", "zk", "zl", "zm", "zn", "zo", "zp", "zq", "zr", "zs", "zt", "zu", "zv", "zw", "zx", "zy", "zz"
));
private static byte[][] Ref_backlabels_xby_str_ary(String[] ary) {
int ary_len = ary.length;
byte[][] rv = new byte[ary_len][];
for (int i = 0; i < ary_len; i++)
rv[i] = Bry_.new_a7(ary[i]);
return rv;
}
public static byte[][] Ref_backlabels_xby_bry(byte[] raw) {
if (raw == null) return Ref_backlabels_default;
List_adp list = List_adp_.new_();
int len = raw.length, pos = 0, bgn = -1;
while (true) {
boolean last = pos == len;
byte b = last ? Byte_ascii.Space : raw[pos];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Nl: case Byte_ascii.Tab:
if (bgn != -1) { // guard against leading ws, or multiple ws; EX: "bos\s\s" or "\s\s"
list.Add(Bry_.Mid(raw, bgn, pos));
bgn = -1;
}
break;
default:
if (bgn == -1)
bgn = pos;
break;
}
if (last) break;
++pos;
}
return (byte[][])list.To_ary_and_clear(byte[].class);
}
}

View File

@@ -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.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Ref_itm_grp {
private List_adp lsts = List_adp_.new_();
public Ref_itm_grp(byte[] grp_name) {this.grp_name = grp_name;}
public byte[] Grp_name() {return grp_name;} private byte[] grp_name;
public int Grp_seal() {
if (lst_idx == lsts.Count()) // NOTE: lst_idx == lsts.Count() if there are no itms in lst; need to add placeholder list anyway; <references> nodes has a List_index, which will call lsts.Get_at(); see Empty_group_before_ref
lsts.Add(new Ref_itm_lst(grp_name));
return lst_idx++;
} int lst_idx;
public int Lsts_len() {return lsts.Count();}
public Ref_itm_lst Lsts_get_at(int i) {return i < lsts.Count() ? (Ref_itm_lst)lsts.Get_at(i) : null;} // NOTE: null can be returned; see Infobox planet; w:Mars
public void Lsts_add(byte[] itm_name, byte[] follow, Ref_nde itm) {
Ref_itm_lst lst = null;
int lsts_len = lsts.Count();
if (lst_idx >= lsts_len) {
lst = new Ref_itm_lst(grp_name);
lsts.Add(lst);
}
else
lst = (Ref_itm_lst)lsts.Get_at(lsts_len - 1);
lst.Itms_add(itm_name, follow, itm);
}
public void Lsts_clear() {
int lsts_len = lsts.Count();
for (int i = 0; i < lsts_len; i++) {
Ref_itm_lst lst = (Ref_itm_lst)lsts.Get_at(i);
lst.Itms_clear();
}
lsts.Clear();
lst_idx = 0;
}
}

View File

@@ -0,0 +1,63 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Ref_itm_lst {
public Ref_itm_lst(byte[] grp_name) {this.grp_name = grp_name;}
byte[] grp_name; int idx_major_last = 0;
public int Itms_len() {return list.Count();}
public Ref_nde Itms_get_at(int i) {return (Ref_nde)list.Get_at(i);}
public void Itms_add(byte[] itm_name, byte[] follow, Ref_nde itm) {
if (itm_name == Bry_.Empty) {
if (follow == Bry_.Empty) {
itm.Idx_major_(idx_major_last++);
list.Add(itm);
}
else {
Object o = hash.Get_by(follow);
if (o == null) {// fail
}
else {
Ref_nde head = (Ref_nde)o;
head.Related_add(itm, Ref_nde.Idx_minor_follow);
itm.Idx_major_(head.Idx_major());
}
}
}
else {
Object o = hash.Get_by(itm_name);
if (o == null) {
hash.Add(itm_name, itm);
itm.Idx_major_(idx_major_last++);
list.Add(itm);
}
else {
Ref_nde head = (Ref_nde)o;
head.Related_add(itm, head.Related_len());
itm.Idx_major_(head.Idx_major());
itm.Idx_minor_(head.Related_len());
}
}
}
public void Itms_clear() {
hash.Clear();
list.Clear();
idx_major_last = 0;
}
Hash_adp hash = Hash_adp_bry.cs_(); List_adp list = List_adp_.new_();
}

View File

@@ -0,0 +1,53 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Ref_itm_mgr {
private Hash_adp_bry grps = Hash_adp_bry.cs_(); // CASE_MATCH:changed from ci; DATE:2014-07-07
private Ref_itm_grp grp_default = new Ref_itm_grp(Bry_.Empty);
private int uid_last;
public boolean References__recursing() {return references__recursing;} public void References__recursing_(boolean v) {references__recursing = v;} private boolean references__recursing;
public Ref_itm_lst Lst_get(byte[] grp_name, int lst_idx) {
return Bry_.Len_eq_0(grp_name) ? grp_default.Lsts_get_at(lst_idx) : ((Ref_itm_grp)grps.Get_by(grp_name)).Lsts_get_at(lst_idx); // NOTE: must be Bry_.Len_eq_0 else <references group=""/> not same as <references/>; DATE:2013-02-06
}
public void Grps_add(byte[] grp_name, byte[] itm_name, byte[] follow, Ref_nde itm) {
Ref_itm_grp grp = Grps_get(grp_name);
grp.Lsts_add(itm_name, follow, itm);
itm.Uid_(uid_last++);
}
public int Grps_seal(byte[] grp_name) {
Ref_itm_grp grp = Grps_get(grp_name);
return grp.Grp_seal();
}
public void Grps_clear() {
grps.Clear();
grp_default.Lsts_clear();
uid_last = 0;
references__recursing = false;
}
public Ref_itm_grp Grps_get(byte[] grp_name) {
if (Bry_.Len_eq_0(grp_name)) return grp_default;
Object o = grps.Get_by_bry(grp_name);
if (o == null) {
Ref_itm_grp grp = new Ref_itm_grp(grp_name);
grps.Add(grp_name, grp);
return grp;
}
else
return (Ref_itm_grp)o;
}
}

View File

@@ -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.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Ref_itm_mgr_cfg_tst {
@Before public void init() {fxt.Clear();} private Ref_itm_mgr_cfg_fxt fxt = new Ref_itm_mgr_cfg_fxt();
@Test public void Ref_backlabels_xby_bry() {
fxt.Test_Ref_backlabels_xby_bry("a b c" , "a", "b", "c"); // basic
fxt.Test_Ref_backlabels_xby_bry(" a b c" , "a", "b", "c"); // leading ws
fxt.Test_Ref_backlabels_xby_bry("a b c " , "a", "b", "c"); // trailing ws
fxt.Test_Ref_backlabels_xby_bry("a b c" , "a", "b", "c"); // redundant ws
}
}
class Ref_itm_mgr_cfg_fxt {
public void Clear() {}
public void Test_Ref_backlabels_xby_bry(String raw, String... expd) {
byte[][] actl = Ref_html_wtr_cfg.Ref_backlabels_xby_bry(Bry_.new_u8(raw));
Tfds.Eq_ary_str(expd, String_.Ary(actl));
}
}

View File

@@ -0,0 +1,83 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Ref_itm_mgr_tst {
Ref_itm_mgr_fxt fxt = new Ref_itm_mgr_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Basic() {fxt.run_Add("key_1", "key_2").tst(fxt.itm_("key_1", 0, 0), fxt.itm_("key_2", 1, 1));}
@Test public void Repeat() {fxt.run_Add("key_1", "key_2", "key_1").tst(fxt.itm_("key_1", 0).Related_(fxt.itm_uid_(2)), fxt.itm_("key_2", 1, 1));}
@Test public void Group() {fxt.run_Add_grp("grp_1", "key_1").run_Add("key_1").tst_grp("grp_1", fxt.itm_("key_1", 0, 0)).tst(fxt.itm_("key_1", 0, 1));}
@Test public void Follow() {fxt.run_Add("key_1").run_Add_follow("key_1").tst(fxt.itm_("key_1", 0, 0).Related_(fxt.itm_uid_(1).Idx_minor_follow_()));}
}
class Ref_itm_mgr_fxt {
private Ref_itm_mgr ref_mgr = new Ref_itm_mgr();
private Tst_mgr tst_mgr = new Tst_mgr();
public Xtn_ref_nde_chkr itm_uid_(int uid) {return itm_(null, -1, uid);}
public Xtn_ref_nde_chkr itm_(String key, int idx) {return itm_(key, idx, -1);}
public Xtn_ref_nde_chkr itm_(String key, int idx, int uid) {return new Xtn_ref_nde_chkr().Key_(key).Idx_major_(idx).Uid_(uid);}
public Ref_itm_mgr_fxt run_Add_follow(String follow) {return run_Add_grp(Bry_.Empty, Bry_.new_u8(follow), Bry_.Ary(Bry_.Empty));}
public Ref_itm_mgr_fxt run_Add(String... name_ary) {return run_Add_grp(Bry_.Empty, Bry_.Empty, Bry_.Ary(name_ary));}
public Ref_itm_mgr_fxt run_Add_grp(String grp, String... name_ary) {return run_Add_grp(Bry_.new_u8(grp), Bry_.Empty, Bry_.Ary(name_ary));}
public void Clear() {ref_mgr.Grps_clear();}
Ref_itm_mgr_fxt run_Add_grp(byte[] grp_name, byte[] follow, byte[]... name_ary) {
for (int i = 0; i < name_ary.length; i++) {
byte[] name = name_ary[i];
Ref_nde itm = new Ref_nde().Name_(name);
ref_mgr.Grps_add(grp_name, name, follow, itm);
}
return this;
}
public Ref_itm_mgr_fxt tst(Xtn_ref_nde_chkr... chkr_ary) {return tst_grp(ref_mgr.Lst_get(Bry_.Empty, 0), chkr_ary);}
public Ref_itm_mgr_fxt tst_grp(String grp_name, Xtn_ref_nde_chkr... chkr_ary) {return tst_grp(ref_mgr.Lst_get(Bry_.new_a7(grp_name), 0), chkr_ary);}
public Ref_itm_mgr_fxt tst_grp(Ref_itm_lst lst, Xtn_ref_nde_chkr... chkr_ary) {
int itms_len = lst.Itms_len();
Ref_nde[] actl = new Ref_nde[itms_len];
for (int i = 0; i < itms_len; i++)
actl[i] = lst.Itms_get_at(i);
tst_mgr.Tst_ary("", chkr_ary, actl);
return this;
} List_adp actl_list = List_adp_.new_();
}
class Xtn_ref_nde_chkr implements Tst_chkr {
public Class<?> TypeOf() {return Ref_nde.class;}
public String Key() {return key;} public Xtn_ref_nde_chkr Key_(String v) {key = v; return this;} private String key;
public int Idx_major() {return idx_major;} public Xtn_ref_nde_chkr Idx_major_(int v) {idx_major = v; return this;} private int idx_major = -1;
public int Idx_minor() {return idx_minor;} public Xtn_ref_nde_chkr Idx_minor_(int v) {idx_minor = v; return this;} private int idx_minor = -1;
public Xtn_ref_nde_chkr Idx_minor_follow_() {idx_minor = Ref_nde.Idx_minor_follow; return this;}
public int Uid() {return uid;} public Xtn_ref_nde_chkr Uid_(int v) {uid = v; return this;} private int uid = -1;
public Xtn_ref_nde_chkr[] Related() {return related;} public Xtn_ref_nde_chkr Related_(Xtn_ref_nde_chkr... v) {related = v; return this;} Xtn_ref_nde_chkr[] related;
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
Ref_nde actl = (Ref_nde)actl_obj;
int rv = 0;
rv += mgr.Tst_val(key == null, path, "key", key, String_.new_u8(actl.Name()));
rv += mgr.Tst_val(idx_major == -1, path, "idx_major", idx_major, actl.Idx_major());
rv += mgr.Tst_val(idx_minor == -1, path, "idx_minor", idx_minor, actl.Idx_minor());
rv += mgr.Tst_val(uid == -1, path, "uid", uid, actl.Uid());
if (related != null)
rv += mgr.Tst_sub_ary(related, Xto_bry(actl), "related", rv);
return rv;
}
Ref_nde[] Xto_bry(Ref_nde itm) {
int len = itm.Related_len();
Ref_nde[] rv = new Ref_nde[len];
for (int i = 0; i < len; i++)
rv[i] = itm.Related_get(i);
return rv;
}
}

View File

@@ -0,0 +1,81 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.xowa.html.*;
public class Ref_nde implements Xox_xnde, Xop_xnde_atr_parser {
public byte[] Name() {return name;} public Ref_nde Name_(byte[] v) {name = v; return this;} private byte[] name = Bry_.Empty;
public byte[] Group() {return group;} private byte[] group = Bry_.Empty;
public byte[] Follow() {return follow;} private byte[] follow = Bry_.Empty;
public boolean Follow_y() {return follow != Bry_.Empty;}
public int Uid() {return uid;} public Ref_nde Uid_(int v) {uid = v; return this;} private int uid;
public boolean Head() {return head;} private boolean head;
public boolean Nested() {return nested;} private boolean nested;
public int Idx_major() {return idx_major;} public Ref_nde Idx_major_(int v) {idx_major = v; return this;} private int idx_major;
public int Idx_minor() {return idx_minor;} public Ref_nde Idx_minor_(int v) {idx_minor = v; return this;} private int idx_minor;
public Xop_xnde_tkn Xnde() {return xnde;} private Xop_xnde_tkn xnde;
public Xop_root_tkn Body() {return body;} private Xop_root_tkn body;
public boolean Exists_in_lnki_title() {return exists_in_lnki_title;} public Ref_nde Exists_in_lnki_title_(boolean v) {exists_in_lnki_title = v; return this;} private boolean exists_in_lnki_title;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {
if (xatr_key_obj == null) return;
Byte_obj_val xatr_key = (Byte_obj_val)xatr_key_obj;
switch (xatr_key.Val()) {
case Xatr_id_name: name = wiki.Appe().Sanitizer().Escape_id(xatr.Val_as_bry(src)); break;
case Xatr_id_follow: follow = xatr.Val_as_bry(src); break;
case Xatr_id_group: group = xatr.Val_as_bry(src); break;
}
}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
if (ctx.Tid_is_popup()) return;
Xop_xatr_itm.Xatr_parse(wiki.Appe(), this, xatrs_hash, wiki, src, xnde);
if (xnde.CloseMode() == Xop_xnde_tkn.CloseMode_pair)
body = wiki.Parser().Parse_text_to_wdom_old_ctx(ctx, Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn()), false);
byte[] references_group = ctx.References_group(); // set by <references>
if (references_group != null) {
group = references_group; // override <ref group> with <references group>; note that MW throws an error if nested <ref> has different group than outer <references>; Cite error: <ref> tag in <references> has conflicting group attribute "a".
head = true;
nested = true; // refs nested in references don't show <a> entry in <references>
}
if (!ctx.Ref_ignore()) // sub_ctx may be marked to ignore <ref>; EX: <pages>,{{#lst}}; DATE:2014-04-24
ctx.Cur_page().Ref_mgr().Grps_add(group, name, follow, this);
this.xnde = xnde;
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
html_wtr.Ref_wtr().Xnde_ref(hctx, bfr, src, xnde);
}
private static final Ref_nde[] Ary_empty = new Ref_nde[0];
public Ref_nde[] Related() {return related;} Ref_nde[] related = Ary_empty;
public int Related_len() {return related_len;} private int related_len;
public Ref_nde Related_get(int i) {return related[i];}
public void Related_add(Ref_nde itm, int idx_minor) {
int new_len = related_len + 1;
int related_max = related.length;
if (new_len > related_max)
related = (Ref_nde[])Array_.Resize(related, related_max == 0 ? 1 : related_max * 2);
itm.Idx_minor_(idx_minor);
related[related_len] = itm;
related_len = new_len;
}
public static final byte Xatr_id_name = 0, Xatr_id_group = 1, Xatr_id_follow = 2;
public static final int Idx_minor_follow = -2;
private static final Hash_adp_bry xatrs_hash = Hash_adp_bry.ci_ascii_()
.Add_str_obj("name", Byte_obj_val.new_(Ref_nde.Xatr_id_name))
.Add_str_obj("group", Byte_obj_val.new_(Ref_nde.Xatr_id_group))
.Add_str_obj("follow", Byte_obj_val.new_(Ref_nde.Xatr_id_follow));
}

View File

@@ -0,0 +1,58 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.xowa.html.*;
public class References_nde implements Xox_xnde, Xop_xnde_atr_parser {
public byte[] Group() {return group;} public References_nde Group_(byte[] v) {group = v; return this;} private byte[] group = Bry_.Empty;
public int List_idx() {return list_idx;} public References_nde List_idx_(int v) {list_idx = v; return this;} private int list_idx;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {
if (xatr_key_obj == null) return;
Byte_obj_val xatr_key = (Byte_obj_val)xatr_key_obj;
switch (xatr_key.Val()) {
case Xatr_id_group: group = xatr.Val_as_bry(src); break;
}
}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
if (ctx.Tid_is_popup()) return;
Ref_itm_mgr ref_mgr = ctx.Cur_page().Ref_mgr();
if (ref_mgr.References__recursing()) return; // skip nested <references> else refs will be lost; EX:"<references><references/></references>"; PAGE:en.w:Hwair; DATE:2014-06-27
ctx.Para().Process_block__bgn_n__end_y(Xop_xnde_tag_.Tag_div); // xnde generates <block_node>; <references> -> <ol>; close any blocks; PAGE:fr.w:Heidi_(roman); DATE:2014-02-17
Xop_xatr_itm.Xatr_parse(wiki.Appe(), this, xatrs_hash, wiki, src, xnde);
if (xnde.CloseMode() == Xop_xnde_tkn.CloseMode_pair) { // "<references>", "</references>"; parse anything in between but only to pick up <ref> tags; discard everything else; DATE:2014-06-27
int itm_bgn = xnde.Tag_open_end(), itm_end = xnde.Tag_close_bgn();
Xop_ctx references_ctx = Xop_ctx.new_sub_page_(wiki, ctx, ctx.Lst_page_regy()).References_group_(group); // changed from following: "Xop_ctx references_ctx = Xop_ctx.new_sub_(wiki).References_group_(group);"; DATE:2015-05-16;
references_ctx.Para().Enabled_n_(); // disable para during <references> parsing
byte[] references_src = Bry_.Mid(src, itm_bgn, itm_end);
Xop_tkn_mkr tkn_mkr = ctx.Tkn_mkr();
Xop_root_tkn sub_root = tkn_mkr.Root(src);
boolean prv_recursing = ref_mgr.References__recursing();
ref_mgr.References__recursing_(true);
wiki.Parser().Parse_text_to_wdom(sub_root, references_ctx, tkn_mkr, references_src, Xop_parser_.Doc_bgn_char_0); // NOTE: parse inner contents, but root will be discarded; only picking up <ref> tags; DATE:2014-06-27
ref_mgr.References__recursing_(prv_recursing);
}
list_idx = ref_mgr.Grps_get(group).Grp_seal(); // NOTE: needs to be sealed at end; else inner refs will end up in new group; EX: <references><ref>don't seal prematurely</ref></references>
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
html_wtr.Ref_wtr().Xnde_references(html_wtr, ctx, hctx, bfr, src, xnde);
}
private static final byte Xatr_id_group = 0;
public static boolean Enabled = true;
private static final Hash_adp_bry xatrs_hash = Hash_adp_bry.ci_ascii_()
.Add_str_obj("group", Byte_obj_val.new_(References_nde.Xatr_id_group));
}

View File

@@ -0,0 +1,202 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class References_nde_basic_tst {
@Before public void init() {fxt.Clear_ref_mgr();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Basic() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>x</ref>"
, "<ref>y</ref>"
, "<ref>z</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[2]</a></sup>"
, "<sup id=\"cite_ref-2\" class=\"reference\"><a href=\"#cite_note-2\">[3]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">x</span></li>"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "<li id=\"cite_note-2\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-2\">^</a></span> <span class=\"reference-text\">z</span></li>"
, "</ol>"
, ""
));
}
@Test public void Name_dif() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name='r_x'>x</ref>"
, "<ref name='r_y'>y</ref>"
, "<ref name='r_z'>z</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-r_x_0-0\" class=\"reference\"><a href=\"#cite_note-r_x-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-r_y_1-0\" class=\"reference\"><a href=\"#cite_note-r_y-1\">[2]</a></sup>"
, "<sup id=\"cite_ref-r_z_2-0\" class=\"reference\"><a href=\"#cite_note-r_z-2\">[3]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-r_x-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-r_x_0-0\">^</a></span> <span class=\"reference-text\">x</span></li>"
, "<li id=\"cite_note-r_y-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-r_y_1-0\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "<li id=\"cite_note-r_z-2\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-r_z_2-0\">^</a></span> <span class=\"reference-text\">z</span></li>"
, "</ol>"
, ""
));
}
@Test public void Name_same() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name='r_x'>x</ref>"
, "<ref name='r_y'>y</ref>"
, "<ref name='r_x'>z</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-r_x_0-0\" class=\"reference\"><a href=\"#cite_note-r_x-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-r_y_1-0\" class=\"reference\"><a href=\"#cite_note-r_y-1\">[2]</a></sup>"
, "<sup id=\"cite_ref-r_x_0-1\" class=\"reference\"><a href=\"#cite_note-r_x-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-r_x-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-r_x_0-0\">a</a></sup> <sup><a href=\"#cite_ref-r_x_0-1\">b</a></sup></span> <span class=\"reference-text\">x</span></li>"
, "<li id=\"cite_note-r_y-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-r_y_1-0\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "</ol>"
, ""
));
}
@Test public void Name_same_text_in_last_ref() { // WP:Hundred Years' War
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name='ref_a'></ref>"
, "<ref name='ref_a'></ref>"
, "<ref name='ref_a'>x</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-ref_a_0-0\" class=\"reference\"><a href=\"#cite_note-ref_a-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-ref_a_0-1\" class=\"reference\"><a href=\"#cite_note-ref_a-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-ref_a_0-2\" class=\"reference\"><a href=\"#cite_note-ref_a-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-ref_a-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-ref_a_0-0\">a</a></sup> <sup><a href=\"#cite_ref-ref_a_0-1\">b</a></sup> <sup><a href=\"#cite_ref-ref_a_0-2\">c</a></sup></span> <span class=\"reference-text\">x</span></li>"
, "</ol>"
, ""
));
}
@Test public void List_ignored() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>*x</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">*x</span></li>"
, "</ol>"
, ""
));
}
@Test public void Name_mixed_case() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref NAME=A>x</ref>"
, "<ref Name=A>y</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-A_0-0\" class=\"reference\"><a href=\"#cite_note-A-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-A_0-1\" class=\"reference\"><a href=\"#cite_note-A-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-A-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-A_0-0\">a</a></sup> <sup><a href=\"#cite_ref-A_0-1\">b</a></sup></span> <span class=\"reference-text\">x</span></li>"
, "</ol>"
, ""
));
}
@Test public void Name2() { // PURPOSE: make sure inline tag matches open tag
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "a<ref name=name_0>b</ref>"
, "b<ref name=name_0/>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "a<sup id=\"cite_ref-name_0_0-0\" class=\"reference\"><a href=\"#cite_note-name_0-0\">[1]</a></sup>"
, "b<sup id=\"cite_ref-name_0_0-1\" class=\"reference\"><a href=\"#cite_note-name_0-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-name_0-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-name_0_0-0\">a</a></sup> <sup><a href=\"#cite_ref-name_0_0-1\">b</a></sup></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, ""
));
}
@Test public void References_refs() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "a<ref group=group_0 name=name_0/>"
, "<references group=group_0>"
, " <ref name=name_0>b</ref>"
, "</references>"
), String_.Concat_lines_nl_skip_last
( "a<sup id=\"cite_ref-name_0_0-0\" class=\"reference\"><a href=\"#cite_note-name_0-0\">[group_0 1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-name_0-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-name_0_0-0\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, ""
));
}
@Test public void Nested() { // PURPOSE: nested ref was creating 3rd [1]
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "a<ref name=r_x/>"
, "b<ref name=r_x/>"
, "<references>"
, "<ref name=r_x>c</ref>"
, "</references>"
), String_.Concat_lines_nl_skip_last
( "a<sup id=\"cite_ref-r_x_0-0\" class=\"reference\"><a href=\"#cite_note-r_x-0\">[1]</a></sup>"
, "b<sup id=\"cite_ref-r_x_0-1\" class=\"reference\"><a href=\"#cite_note-r_x-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-r_x-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-r_x_0-0\">a</a></sup> <sup><a href=\"#cite_ref-r_x_0-1\">b</a></sup></span> <span class=\"reference-text\">c</span></li>"
, "</ol>"
, ""
));
}
@Test public void Key_ignore_nl_tab() { // PURPOSE: \n in ref_name should be escaped to \s; PAGE:en.w:Self-Transcendence 3100 Mile Race
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name=\"name\na\">b</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-name_a_0-0\" class=\"reference\"><a href=\"#cite_note-name_a-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-name_a-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-name_a_0-0\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, ""
));
}
@Test public void Empty_group_before_ref() { // PURPOSE: empty grp before itm should not throw error; DATE:2013-02-18; EX: w:Help:External links and references; Johnstown,_Colorado
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl
( "<references/><references/>a<ref>test</ref>"
, "<references/>"
), String_.Concat_lines_nl
( "a<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">test</span></li>"
, "</ol>"
, ""
));
}
@Test public void Follow() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name='ref_a'>x</ref>"
, "<ref>y</ref>"
, "<ref follow='ref_a'>z</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-ref_a_0-0\" class=\"reference\"><a href=\"#cite_note-ref_a-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[2]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-ref_a-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-ref_a_0-0\">a</a></sup></span> <span class=\"reference-text\">x z</span></li>"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "</ol>"
, ""
));
}
}

View File

@@ -0,0 +1,122 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class References_nde_group_tst {
@Before public void init() {fxt.Clear_ref_mgr();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Basic() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>x</ref>"
, "<ref group='group_a'>y</ref>"
, "<ref>z</ref>"
, "<references group='group_a'/>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[group_a 1]</a></sup>"
, "<sup id=\"cite_ref-2\" class=\"reference\"><a href=\"#cite_note-2\">[2]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "</ol>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">x</span></li>"
, "<li id=\"cite_note-2\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-2\">^</a></span> <span class=\"reference-text\">z</span></li>"
, "</ol>"
, ""
));
}
@Test public void Lower_alpha_is_ignored() {
String expd =
String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>" // note:do not show lower-alpha; DATE:2014-07-21
, "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">x</span></li>"
, "</ol>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "</ol>"
, ""
);
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref group='lower-alpha'>x</ref>"
, "<ref>y</ref>"
, "<references group='lower-alpha'/>"
, "<references group=''/>"
), expd);
}
@Test public void Empty() { // PURPOSE: <references group=""/> is same as <references/>; DATE:2013-02-06
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>b</ref>"
, "<references group=\"\"/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, ""
));
}
@Test public void Val_less_defaults_to_key() { // PURPOSE: similar to above, except "group" is same as "group=group"; DATE:2014-07-03
String expd = String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[group 1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, "");
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref group='group'>b</ref>"
, "<references group/>"
), expd
);
fxt.Clear_ref_mgr();
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last // PURPOSE.FIX: similar to above, except "group />" was not same as "group/>"; SEE:xatr_parser and " a " test; DATE:2014-07-03
( "<ref group='group'>b</ref>"
, "<references group />"
), expd
);
}
@Test public void Empty_group() { // PURPOSE: group without items should be blank; should not throw error; DATE:2013-02-12
fxt.Test_parse_page_wiki_str("<references name='group_a'/>", "");
}
@Test public void Multiple_same_name_groups() { // PURPOSE: multiple groups with same name "clears" out references; DATE:2013-02-11
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>a</ref>"
, "<references/>"
, "<ref>b</ref>"
, "<references/>"
, "<ref>c</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">a</span></li>"
, "</ol>"
, "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
, "<sup id=\"cite_ref-2\" class=\"reference\"><a href=\"#cite_note-2\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-2\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-2\">^</a></span> <span class=\"reference-text\">c</span></li>"
, "</ol>"
, ""
));
}
}

View File

@@ -0,0 +1,67 @@
/*
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.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class References_nde_pre_tst {
@Before public void init() {fxt.Clear_ref_mgr();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Pre_ignored() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref> x</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\"> x</span></li>"
, "</ol>"
, ""
));
}
@Test public void Pre_ignored_2() { // PURPOSE: <ref> creates <li> which will effectively disable all pre; PAGE:en.w:Robert_Browning
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>x"
, " y"
, "</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">x"
, " y"
, "</span></li>"
, "</ol>"
, ""
));
}
@Test public void Pre_ignored_3() { // PURPOSE: " <references>" should not create pre; fr.w:Heidi_(roman); DATE:2014-02-17
fxt.Init_para_y_();
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>x</ref>"
, ""
, " <references/>"
), String_.Concat_lines_nl_skip_last
( "<p><sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "</p>"
, " <ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">x</span></li>"
, "</ol>"
, ""
));
fxt.Init_para_n_();
}
}

View File

@@ -0,0 +1,94 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.cite; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class References_nde_rare_tst {
@Before public void init() {fxt.Clear_ref_mgr(); fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@After public void term() {fxt.Init_para_n_();}
@Test public void Recursive() { // PURPOSE: handle recursive situations; EX: ja.w:Kソリューション ; ja.w:Template:cite web。; DATE:2014-03-05
fxt.Init_page_create("Template:Recursive", "<ref>{{Recursive}}</ref>");
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref>{{Recursive}}</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[2]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\"><span class=\"error\">Template loop detected:Recursive</span></span></li>"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\"><sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup></span></li>"
, "</ol>"
, ""
));
}
@Test public void Backlabel_out_of_range() { // PURPOSE: handle more backlabels than expected; PAGE:en.w:List_of_Russula_species; DATE:2014-06-07
Ref_html_wtr_cfg cfg = fxt.Wiki().Html_mgr().Html_wtr().Ref_wtr().Cfg();
byte[][] old = cfg.Backlabels();
cfg.Backlabels_(Bry_.Ary("a"));
fxt.Wiki().Msg_mgr().Get_or_make(Ref_html_wtr_cfg.Msg_backlabels_err).Atrs_set(Bry_.new_a7("Ran out of custom link labels for group ~{0}."), true, false);
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<ref name='ref_1'>a</ref><ref name='ref_1'>b</ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-ref_1_0-0\" class=\"reference\"><a href=\"#cite_note-ref_1-0\">[1]</a></sup><sup id=\"cite_ref-ref_1_0-1\" class=\"reference\"><a href=\"#cite_note-ref_1-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-ref_1-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-ref_1_0-0\">a</a></sup> <sup><a href=\"#cite_ref-ref_1_0-1\">Ran out of custom link labels for group 1.</a></sup></span> <span class=\"reference-text\">a</span></li>"
, "</ol>"
, ""
));
cfg.Backlabels_(old);
}
@Test public void Tag() { // PURPOSE: #tag can create nested refs; PAGE:en.w:Battle_of_Midway DATE:2014-06-27
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "{{#tag:ref|x<ref>y</ref>}}" //"<ref>x<ref>y</ref></ref>"
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[2]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">y</span></li>"
, "<li id=\"cite_note-1\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-1\">^</a></span> <span class=\"reference-text\">x<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup></span></li>"
, "</ol>"
, ""
));
}
@Test public void Tag_2() { // PURPOSE: more involved nested refs; PAGE:en.w:Battle_of_Midway DATE:2014-06-27
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "a<ref name='itm_0'/> b {{#tag:ref|c<ref name='itm_0'>d</ref>}}" // <ref>c<ref name='itm_0'>d</ref></ref>
, "<references/>"
), String_.Concat_lines_nl_skip_last
( "a<sup id=\"cite_ref-itm_0_0-0\" class=\"reference\"><a href=\"#cite_note-itm_0-0\">[1]</a></sup> b <sup id=\"cite_ref-2\" class=\"reference\"><a href=\"#cite_note-2\">[2]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-itm_0-0\"><span class=\"mw-cite-backlink\">^ <sup><a href=\"#cite_ref-itm_0_0-0\">a</a></sup> <sup><a href=\"#cite_ref-itm_0_0-1\">b</a></sup></span> <span class=\"reference-text\">d</span></li>"
, "<li id=\"cite_note-2\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-2\">^</a></span> <span class=\"reference-text\">c<sup id=\"cite_ref-itm_0_0-1\" class=\"reference\"><a href=\"#cite_note-itm_0-0\">[1]</a></sup></span></li>"
, "</ol>"
, ""
));
}
@Test public void Dangling_references__nested() { // PURPOSE: handle nested <references/>; PAGE:en.w:Hwair; DATE:2014-06-27
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<ref>a</ref>"
, "<references>"
, " <references/>" // must be ignored, else it will become owner for <ref>
, "</references>"
), String_.Concat_lines_nl_skip_last
( "<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup>"
, "<ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">a</span></li>"
, "</ol>"
, ""
));
}
}

View File

@@ -0,0 +1,55 @@
/*
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.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
class Dpl_html_data {
public byte Tid() {return tid;} private byte tid;
public byte[] Grp_bgn() {return grp_bgn;} private byte[] grp_bgn;
public byte[] Grp_end() {return grp_end;} private byte[] grp_end;
public byte[] Itm_bgn() {return itm_bgn;} private byte[] itm_bgn;
public byte[] Itm_end() {return itm_end;} private byte[] itm_end;
public static final byte Tid_null = 0, Tid_none = 1, Tid_list_ol = 2, Tid_list_ul = 3, Tid_gallery = 4, Tid_inline = 5;
public static final byte[]
Ul_bgn = Bry_.new_a7("<ul>"), Ul_end = Bry_.new_a7("</ul>")
, Ol_bgn = Bry_.new_a7("<ol>"), Ol_end = Bry_.new_a7("</ol>")
, Li_bgn = Bry_.new_a7("<li>"), Li_end = Bry_.new_a7("</li>")
, Br = Bry_.new_a7("<br />")
;
private static final Dpl_html_data
Itm_gallery = new_(Tid_gallery, null, null, null, null)
, Itm_inline = new_(Tid_inline, null, null, null, null)
, Itm_none = new_(Tid_none, null, null, null, Br)
, Itm_ordered = new_(Tid_list_ol, Ol_bgn, Ol_end, Li_bgn, Li_end)
, Itm_unordered = new_(Tid_list_ul, Ul_bgn, Ul_end, Li_bgn, Li_end)
;
private static Dpl_html_data new_(byte tid, byte[] grp_bgn, byte[] grp_end, byte[] itm_bgn, byte[] itm_end) {
Dpl_html_data rv = new Dpl_html_data();
rv.tid = tid; rv.grp_bgn = grp_bgn; rv.grp_end = grp_end; rv.itm_bgn = itm_bgn; rv.itm_end = itm_end;
return rv;
}
public static Dpl_html_data new_(byte key) {
switch (key) {
case Dpl_itm_keys.Key_gallery: return Itm_gallery;
case Dpl_itm_keys.Key_inline: return Itm_inline;
case Dpl_itm_keys.Key_none: return Itm_none;
case Dpl_itm_keys.Key_ordered: return Itm_ordered;
case Dpl_itm_keys.Key_unordered: return Itm_unordered;
default: throw Exc_.new_unhandled(key);
}
}
}

View File

@@ -0,0 +1,183 @@
/*
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.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.html.*; import gplx.xowa.html.*;
class Dpl_itm {
public List_adp Ctg_includes() {return ctg_includes;} private List_adp ctg_includes;
public List_adp Ctg_excludes() {return ctg_excludes;} private List_adp ctg_excludes;
public int Count() {return count;} private int count = Int_.MinValue;
public int Offset() {return offset;} private int offset = Int_.MinValue;
public boolean No_follow() {return no_follow;} private boolean no_follow;
public boolean Suppress_errors() {return suppress_errors;} private boolean suppress_errors;
public boolean Show_ns() {return show_ns;} private boolean show_ns;
public byte Sort_ascending() {return sort_ascending;} private byte sort_ascending = Bool_.__byte;
public int Ns_filter() {return ns_filter;} private int ns_filter = Ns_filter_null;
public boolean Gallery_filesize() {return gallery_filesize;} private boolean gallery_filesize;
public boolean Gallery_filename() {return gallery_filename;} private boolean gallery_filename;
public int Gallery_imgs_per_row() {return gallery_imgs_per_row;} private int gallery_imgs_per_row;
public int Gallery_img_w() {return gallery_img_w;} private int gallery_img_w;
public int Gallery_img_h() {return gallery_img_h;} private int gallery_img_h;
public byte[] Gallery_caption() {return gallery_caption;} private byte[] gallery_caption;
public byte Redirects_mode() {return redirects_mode;} private byte redirects_mode = Dpl_redirect.Tid_unknown;
public byte Sort_tid() {return sort_tid;} private byte sort_tid = Dpl_sort.Tid_categoryadd;
public byte Quality_pages() {return quality_pages;} private byte quality_pages;
public byte Stable_pages() {return stable_pages;} private byte stable_pages;
private Xop_ctx sub_ctx; private Xop_tkn_mkr sub_tkn_mkr; private Xop_root_tkn sub_root;
public void Parse(Xowe_wiki wiki, Xop_ctx ctx, byte[] page_ttl, byte[] src, Xop_xnde_tkn xnde) { // parse kvs in node; EX:<dpl>category=abc\nredirects=y\n</dpl>
sub_ctx = Xop_ctx.new_sub_(wiki);
sub_tkn_mkr = sub_ctx.Tkn_mkr();
sub_root = sub_tkn_mkr.Root(Bry_.Empty);
int content_bgn = xnde.Tag_open_end(), content_end = xnde.Tag_close_bgn();
int pos = content_bgn;
int fld_bgn = content_bgn;
byte key_id = 0;
Gfo_usr_dlg usr_dlg = wiki.Appe().Usr_dlg();
boolean ws_bgn_chk = true; int ws_bgn_idx = -1, ws_end_idx = -1;
boolean loop = true;
while (loop) { // iterate over content
boolean done = pos >= content_end;
byte b = done ? Dlm_row : src[pos]; // get cur byte
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab:
if (ws_bgn_chk) ws_bgn_idx = pos; // definite ws at bgn; set ws_bgn_idx, and keep setting until text reached; handles mixed sequence of \s\n\t where last tkn should be ws_bgn_idx
else {if (ws_end_idx == -1) ws_end_idx = pos;}; // possible ws at end; may be overriden later; see AdjustWsForTxtTkn
break;
case Dlm_fld: { // dlm is fld; EX: "=" in "category="
if (ws_bgn_idx != -1) fld_bgn = ws_bgn_idx + 1; // +1 to position after last known ws
int fld_end = ws_end_idx == -1 ? pos : ws_end_idx;
key_id = Dpl_itm_keys.Parse(src, fld_bgn, fld_end, Dpl_itm_keys.Key_null);
if (key_id == Dpl_itm_keys.Key_null) { // unknown key; warn and set pos to end of line; EX: "unknown=";
Parse_missing_key(usr_dlg, page_ttl, src, fld_bgn, fld_end);
fld_bgn = Bry_finder.Find_fwd(src, Byte_ascii.Nl, pos);
if (fld_bgn == Bry_.NotFound) loop = false;
}
else { // known key; set pos to val_bgn
fld_bgn = pos + Int_.Const_dlm_len;
}
ws_bgn_chk = true; ws_bgn_idx = ws_end_idx = -1;
break;
}
case Dlm_row: { // dlm is nl; EX: "\n" in "category=abc\n"
if (fld_bgn != pos) { // ignores blank lines
if (ws_bgn_idx != -1) fld_bgn = ws_bgn_idx + 1; // +1 to position after last known ws
int fld_end = ws_end_idx == -1 ? pos : ws_end_idx;
byte[] val = Bry_.Mid(src, fld_bgn, fld_end);
Parse_cmd(wiki, key_id, val);
}
fld_bgn = pos + Int_.Const_dlm_len;
ws_bgn_chk = true; ws_bgn_idx = ws_end_idx = -1;
break;
}
default: // text token
if (ws_bgn_chk) ws_bgn_chk = false; else ws_end_idx = -1; // INLINE: AdjustWsForTxtTkn
break;
}
if (done) break;
++pos;
}
}
private static final byte Dlm_fld = Byte_ascii.Eq, Dlm_row = Byte_ascii.Nl;
public void Parse_cmd(Xowe_wiki wiki, byte key_id, byte[] val) {
sub_root.Clear();
val = wiki.Parser().Parse_text_to_wtxt(sub_root, sub_ctx, sub_tkn_mkr, val);
switch (key_id) {
case Dpl_itm_keys.Key_category: if (ctg_includes == null) ctg_includes = List_adp_.new_(); ctg_includes.Add(Xoa_ttl.Replace_spaces(val)); break;
case Dpl_itm_keys.Key_notcategory: if (ctg_excludes == null) ctg_excludes = List_adp_.new_(); ctg_excludes.Add(Xoa_ttl.Replace_spaces(val)); break;
case Dpl_itm_keys.Key_ns: {Xow_ns ns = (Xow_ns)wiki.Ns_mgr().Names_get_or_null(val, 0, val.length); ns_filter = ns == null ? Xow_ns_.Id_main : ns.Id(); break;}
case Dpl_itm_keys.Key_order: sort_ascending = Dpl_sort.Parse_as_bool_byte(val); break;
case Dpl_itm_keys.Key_suppresserrors: suppress_errors = Dpl_itm_keys.Parse_as_bool(val, false); break;
case Dpl_itm_keys.Key_nofollow: no_follow = Dpl_itm_keys.Parse_as_bool(val, true); break; // NOTE: default to true; allows passing nofollow=nofollow; MW: if ('false' != $arg)
case Dpl_itm_keys.Key_shownamespace: show_ns = Dpl_itm_keys.Parse_as_bool(val, true); break; // NOTE: default to true;
case Dpl_itm_keys.Key_redirects: redirects_mode = Dpl_redirect.Parse(val); break;
case Dpl_itm_keys.Key_stablepages: stable_pages = Dpl_stable_tid.Parse(val); break;
case Dpl_itm_keys.Key_qualitypages: quality_pages = Dpl_redirect.Parse(val); break;
case Dpl_itm_keys.Key_addfirstcategorydate: Parse_ctg_date(val); break;
case Dpl_itm_keys.Key_count: count = Bry_.Xto_int_or(val, Int_.MinValue); break;
case Dpl_itm_keys.Key_offset: offset = Bry_.Xto_int_or(val, Int_.MinValue); break;
case Dpl_itm_keys.Key_imagesperow: gallery_imgs_per_row = Bry_.Xto_int_or(val, Int_.MinValue); break;
case Dpl_itm_keys.Key_imagewidth: gallery_img_w = Bry_.Xto_int_or(val, Int_.MinValue); break;
case Dpl_itm_keys.Key_imageheight: gallery_img_h = Bry_.Xto_int_or(val, Int_.MinValue); break;
case Dpl_itm_keys.Key_gallerycaption: gallery_caption = val; break; // FUTURE: parse for {{int:}}?
case Dpl_itm_keys.Key_galleryshowfilesize: gallery_filesize = Dpl_itm_keys.Parse_as_bool(val, true); break;
case Dpl_itm_keys.Key_galleryshowfilename: gallery_filename = Dpl_itm_keys.Parse_as_bool(val, true); break;
case Dpl_itm_keys.Key_ordermethod: sort_tid = Dpl_sort.Parse(val); break;
}
}
private void Parse_ctg_date(byte[] val) {
// byte val_key = Keys_get_or(val, Dpl_itm_keys.Key_false);
// if (val_key == Dpl_itm_keys.Key_true)
// ctg_date = true;
// else {
// if (val.length == 8) { // HACK: preg_match( '/^(?:[ymd]{2,3}|ISO 8601)$/'
// ctg_date = true;
// ctg_date_fmt = val;
// if (ctg_date_fmt.length == 2) {
// ctg_date_strip = true;
// ctg_date_fmt = Bry_.Add(ctg_date_fmt, new byte[] {Byte_ascii.Ltr_y});
// }
// }
// else
// ctg_date = false;
// }
}
private void Parse_missing_key(Gfo_usr_dlg usr_dlg, byte[] page_ttl, byte[] src, int fld_bgn, int fld_end) {
byte[] key_bry = Bry_.Mid(src, fld_bgn, fld_end);
boolean log =
( Known_invalid_keys.Get_by_mid(src, fld_bgn, fld_end) != null
|| Bry_.Has_at_bgn(key_bry, Html_tag_.Comm_bgn) // ignore comment-like keys; EX: <!--category=Ctg_0--> will have key of "<!--category="
);
String err_msg = String_.Format("dynamic_page_list:unknown_key: page={0} key={1}", String_.new_u8(page_ttl), String_.new_u8(key_bry));
if (log)
usr_dlg.Log_many("", "", err_msg);
else
usr_dlg.Warn_many("", "", err_msg);
}
private static final Hash_adp_bry Known_invalid_keys = Hash_adp_bry.ci_ascii_()
.Add_str_obj("orcer" , Bool_obj_val.True) // ignore as per http://en.wikinews.org/wiki/Template_talk:United_States; (Note it doesn't make a difference, as categoryadd is the default order method.)
.Add_str_obj("addcategorydatefirst" , Bool_obj_val.True)
.Add_str_obj("mainspace" , Bool_obj_val.True)
.Add_str_obj("showcurid" , Bool_obj_val.True)
.Add_str_obj("sort" , Bool_obj_val.True) // fr.n
.Add_str_obj("supresserror" , Bool_obj_val.True) // fr.n
.Add_str_obj("supresserrors" , Bool_obj_val.True) // frequency: 3 - 10
.Add_str_obj("addlasteditor" , Bool_obj_val.True)
.Add_str_obj("noresultsheader" , Bool_obj_val.True)
.Add_str_obj("catergory" , Bool_obj_val.True)
.Add_str_obj("catrgory" , Bool_obj_val.True)
.Add_str_obj("allrevisionssince" , Bool_obj_val.True) // frequency: 1
.Add_str_obj("limit" , Bool_obj_val.True)
.Add_str_obj("namespacename" , Bool_obj_val.True)
;
public static final int Ns_filter_null = Int_.MinValue;
// boolean ctg_date = false, ctg_date_strip = false;
// byte[] ns_include = null;
// byte[] ctg_date_fmt;
}
class Dpl_stable_tid {
public static final byte Tid_null = 0, Tid_include = 1, Tid_only = 2, Tid_exclude = 3;
public static byte Parse(byte[] bry) {
byte key = Dpl_itm_keys.Parse(bry, Dpl_redirect.Tid_exclude); // NOTE: exclude is default value.
switch (key) {
case Dpl_itm_keys.Key_exclude: return Tid_exclude;
case Dpl_itm_keys.Key_include: return Tid_include;
case Dpl_itm_keys.Key_only: return Tid_only;
default: throw Exc_.new_unhandled(key);
}
}
}

View File

@@ -0,0 +1,125 @@
/*
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.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
class Dpl_itm_keys {
public static byte Parse(byte[] src, int bgn, int end, byte or) {
Object o = keys.Get_by_mid(src, bgn, end);
return o == null ? or : ((Byte_obj_val)o).Val();
}
public static byte Parse(byte[] bry, byte or) {
Object o = keys.Get_by_bry(bry);
return o == null ? or : ((Byte_obj_val)o).Val();
}
public static boolean Parse_as_bool(byte[] bry, boolean or) {
byte key = Dpl_itm_keys.Parse(bry, Key_null);
switch (key) {
case Dpl_itm_keys.Key_false: return false;
case Dpl_itm_keys.Key_true: return true;
case Dpl_itm_keys.Key_null: return or;
default: throw Exc_.new_unhandled(String_.new_u8(bry)); // shouldn't happen; should always go to or;
}
}
public static final byte
Key_null = Byte_.Max_value_127
, Key_category = 1
, Key_notcategory = 2
, Key_ns = 3
, Key_count = 4
, Key_offset = 5
, Key_imagewidth = 6
, Key_imageheight = 7
, Key_imagesperow = 8
, Key_mode = 9
, Key_gallery = 10
, Key_none = 11
, Key_ordered = 12
, Key_unordered = 13
, Key_inline = 14
, Key_gallerycaption = 15
, Key_galleryshowfilesize = 16
, Key_galleryshowfilename = 17
, Key_order = 18
, Key_ordermethod = 19
, Key_lastedit = 20
, Key_length = 21
, Key_created = 22
, Key_sortkey = 23
, Key_categorysortkey = 24
, Key_popularity = 25
, Key_categoryadd = 26
, Key_redirects = 27
, Key_include = 28
, Key_only = 29
, Key_exclude = 30
, Key_stablepages = 31
, Key_qualitypages = 32
, Key_suppresserrors = 33
, Key_addfirstcategorydate = 34
, Key_shownamespace = 35
, Key_googlehack = 36
, Key_nofollow = 37
, Key_descending = 38
, Key_ascending = 39
, Key_false = 40
, Key_true = 41
;
private static final Hash_adp_bry keys = Hash_adp_bry.ci_ascii_()
.Add_str_byte("category", Dpl_itm_keys.Key_category)
.Add_str_byte("notcategory", Dpl_itm_keys.Key_notcategory)
.Add_str_byte("namespace", Dpl_itm_keys.Key_ns)
.Add_str_byte("count", Dpl_itm_keys.Key_count)
.Add_str_byte("offset", Dpl_itm_keys.Key_offset)
.Add_str_byte("imagewidth", Dpl_itm_keys.Key_imagewidth)
.Add_str_byte("imageheight", Dpl_itm_keys.Key_imageheight)
.Add_str_byte("imagesperow", Dpl_itm_keys.Key_imagesperow)
.Add_str_byte("mode", Dpl_itm_keys.Key_mode)
.Add_str_byte("gallery", Dpl_itm_keys.Key_gallery)
.Add_str_byte("none", Dpl_itm_keys.Key_none)
.Add_str_byte("ordered", Dpl_itm_keys.Key_ordered)
.Add_str_byte("unordered", Dpl_itm_keys.Key_unordered)
.Add_str_byte("inline", Dpl_itm_keys.Key_inline)
.Add_str_byte("gallerycaption", Dpl_itm_keys.Key_gallerycaption)
.Add_str_byte("galleryshowfilesize", Dpl_itm_keys.Key_galleryshowfilesize)
.Add_str_byte("galleryshowfilename", Dpl_itm_keys.Key_galleryshowfilename)
.Add_str_byte("order", Dpl_itm_keys.Key_order)
.Add_str_byte("ordermethod", Dpl_itm_keys.Key_ordermethod)
.Add_str_byte("lastedit", Dpl_itm_keys.Key_lastedit)
.Add_str_byte("length", Dpl_itm_keys.Key_length)
.Add_str_byte("created", Dpl_itm_keys.Key_created)
.Add_str_byte("sortkey", Dpl_itm_keys.Key_sortkey)
.Add_str_byte("categorysortkey", Dpl_itm_keys.Key_categorysortkey)
.Add_str_byte("popularity", Dpl_itm_keys.Key_popularity)
.Add_str_byte("categoryadd", Dpl_itm_keys.Key_categoryadd)
.Add_str_byte("redirects", Dpl_itm_keys.Key_redirects)
.Add_str_byte("include", Dpl_itm_keys.Key_include)
.Add_str_byte("only", Dpl_itm_keys.Key_only)
.Add_str_byte("exclude", Dpl_itm_keys.Key_exclude)
.Add_str_byte("stablepages", Dpl_itm_keys.Key_stablepages)
.Add_str_byte("qualitypages", Dpl_itm_keys.Key_qualitypages)
.Add_str_byte("suppresserrors", Dpl_itm_keys.Key_suppresserrors)
.Add_str_byte("addfirstcategorydate", Dpl_itm_keys.Key_addfirstcategorydate)
.Add_str_byte("shownamespace", Dpl_itm_keys.Key_shownamespace)
.Add_str_byte("googlehack", Dpl_itm_keys.Key_googlehack)
.Add_str_byte("nofollow", Dpl_itm_keys.Key_nofollow)
.Add_str_byte("descending", Dpl_itm_keys.Key_descending)
.Add_str_byte("ascending", Dpl_itm_keys.Key_ascending)
.Add_str_byte("false", Dpl_itm_keys.Key_false)
.Add_str_byte("true", Dpl_itm_keys.Key_true)
;
}

View File

@@ -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.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
// public class Dpl_page {
// public byte[] Ttl_bry() {return ttl_bry;} public Dpl_page Ttl_bry_(byte[] v) {ttl_bry = v; return this;} private byte[] ttl_bry;
// }
import gplx.xowa.wikis.data.tbls.*;
class Dpl_page_sorter implements gplx.lists.ComparerAble {
public Dpl_page_sorter(Dpl_itm itm) {this.itm = itm;} private Dpl_itm itm;
public int compare(Object lhsObj, Object rhsObj) {
Xowd_page_itm lhs = (Xowd_page_itm)lhsObj;
Xowd_page_itm rhs = (Xowd_page_itm)rhsObj;
int multiplier = itm.Sort_ascending() == Bool_.Y_byte ? 1 : -1;
switch (itm.Sort_tid()) {
case Dpl_sort.Tid_categorysortkey:
case Dpl_sort.Tid_categoryadd: return multiplier * Bry_.Compare(lhs.Ttl_page_db(), rhs.Ttl_page_db());
}
return CompareAble_.Same;
}
}

View File

@@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
class Dpl_redirect {
public static final byte Tid_exclude = 0, Tid_include = 1, Tid_only = 2, Tid_unknown = Byte_.Max_value_127;
public static byte Parse(byte[] bry) {
byte key = Dpl_itm_keys.Parse(bry, Dpl_redirect.Tid_exclude); // NOTE: exclude is default value.
switch (key) {
case Dpl_itm_keys.Key_exclude: return Tid_exclude;
case Dpl_itm_keys.Key_include: return Tid_include;
case Dpl_itm_keys.Key_only: return Tid_only;
default: throw Exc_.new_unhandled(key);
}
}
}

View File

@@ -0,0 +1,43 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
class Dpl_sort {
public static final byte Tid_null = 0, Tid_lastedit = 1, Tid_length = 2, Tid_created = 3, Tid_sortkey = 4, Tid_categorysortkey = 5, Tid_popularity = 6, Tid_categoryadd = 7;
public static byte Parse_as_bool_byte(byte[] bry) {
byte val = Dpl_itm_keys.Parse(bry, Dpl_itm_keys.Key_null);
switch (val) {
case Dpl_itm_keys.Key_ascending: return Bool_.Y_byte;
case Dpl_itm_keys.Key_descending: return Bool_.N_byte;
case Dpl_itm_keys.Key_null:
default: return Bool_.__byte;
}
}
public static byte Parse(byte[] bry) {
byte key = Dpl_itm_keys.Parse(bry, Dpl_itm_keys.Key_categoryadd);
switch (key) {
case Dpl_itm_keys.Key_lastedit: return Tid_lastedit;
case Dpl_itm_keys.Key_length: return Tid_length;
case Dpl_itm_keys.Key_created: return Tid_created;
case Dpl_itm_keys.Key_sortkey: return Tid_sortkey;
case Dpl_itm_keys.Key_categorysortkey: return Tid_categorysortkey;
case Dpl_itm_keys.Key_popularity: return Tid_popularity; // FUTURE: default to categoryadd if counters disabled
case Dpl_itm_keys.Key_categoryadd: return Tid_categoryadd;
default: throw Exc_.new_unhandled(key);
}
}
}

View File

@@ -0,0 +1,158 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.xowa.html.*;
import gplx.xowa.dbs.*; import gplx.xowa.ctgs.*; import gplx.xowa.wikis.data.tbls.*;
public class Dpl_xnde implements Xox_xnde, Xop_xnde_atr_parser {
private Dpl_itm itm = new Dpl_itm(); private List_adp pages = List_adp_.new_();
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {} // NOTE: <dynamicPageList> has no attributes
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
itm.Parse(wiki, ctx, ctx.Cur_page().Ttl().Full_txt(), src, xnde);
Dpl_page_finder.Find_pages(pages, wiki, itm);
if (itm.Sort_ascending() != Bool_.__byte)
pages.Sort_by(new Dpl_page_sorter(itm));
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
Xowe_wiki wiki = ctx.Wiki();
Dpl_html_data html_mode = Dpl_html_data.new_(Dpl_itm_keys.Key_unordered);
int itms_len = pages.Count();
if (itms_len == 0) {
if (!itm.Suppress_errors())
bfr.Add_str_a7("No pages meet these criteria.");
return;
}
int itms_bgn = 0;
if (itm.Offset() != Int_.MinValue) {
itms_bgn = itm.Offset();
}
if (itm.Count() != Int_.MinValue && itms_bgn + itm.Count() < itms_len) {
itms_len = itms_bgn + itm.Count();
}
boolean showns = itm.Show_ns();
bfr.Add(html_mode.Grp_bgn()).Add_byte_nl();
for (int i = itms_bgn; i < itms_len; i++) {
Xowd_page_itm page = (Xowd_page_itm)pages.Get_at(i);
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, page.Ns_id(), page.Ttl_page_db());
byte[] ttl_page_txt = showns ? ttl.Full_txt() : ttl.Page_txt();
if (ttl_page_txt == null) continue; // NOTE: apparently DynamicPageList allows null pages; DATE:2013-07-22
switch (html_mode.Tid()) {
case Dpl_html_data.Tid_list_ul:
case Dpl_html_data.Tid_list_ol:
bfr.Add(Xoh_consts.Space_2).Add(html_mode.Itm_bgn()).Add(Xoh_consts.A_bgn);
bfr.Add_str_a7("/wiki/").Add(ttl_page_txt);
bfr.Add(Xoh_consts.A_bgn_lnki_0).Add(ttl_page_txt).Add_byte(Byte_ascii.Quote);
if (itm.No_follow()) bfr.Add(Bry_nofollow);
bfr.Add_byte(Byte_ascii.Gt);
bfr.Add(ttl_page_txt);
bfr.Add(Xoh_consts.A_end).Add(html_mode.Itm_end()).Add_byte_nl();
break;
default:
break;
}
}
bfr.Add(html_mode.Grp_end()).Add_byte_nl();
}
private static byte[] Bry_nofollow = Bry_.new_a7(" rel=\"nofollow\"");
}
class Dpl_page_finder {
public static void Find_pages(List_adp rv, Xowe_wiki wiki, Dpl_itm itm) {
rv.Clear();
List_adp includes = itm.Ctg_includes(); if (includes == null) return;
int includes_len = includes.Count();
Ordered_hash old_regy = Ordered_hash_.new_(), new_regy = Ordered_hash_.new_(), cur_regy = Ordered_hash_.new_();
Xodb_load_mgr load_mgr = wiki.Db_mgr().Load_mgr();
Xowd_page_itm tmp_page = new Xowd_page_itm();
Int_obj_ref tmp_id = Int_obj_ref.zero_();
List_adp del_list = List_adp_.new_();
int ns_filter = itm.Ns_filter();
Ordered_hash exclude_pages = Ordered_hash_.new_();
Find_excludes(exclude_pages, load_mgr, tmp_page, tmp_id, itm.Ctg_excludes());
for (int i = 0; i < includes_len; i++) { // loop over includes
byte[] include = (byte[])includes.Get_at(i);
cur_regy.Clear(); del_list.Clear();
Find_pages_in_ctg(cur_regy, load_mgr, tmp_page, tmp_id, include);
Del_old_pages_not_in_cur(i, tmp_id, old_regy, cur_regy, del_list);
Add_cur_pages_also_in_old(i, tmp_id, old_regy, cur_regy, new_regy, exclude_pages, ns_filter);
old_regy = new_regy;
new_regy = Ordered_hash_.new_();
}
int pages_len = old_regy.Count();
for (int i = 0; i < pages_len; i++) { // loop over old and create pages
Int_obj_ref old_id = (Int_obj_ref)old_regy.Get_at(i);
rv.Add(new Xowd_page_itm().Id_(old_id.Val()));
}
wiki.Db_mgr().Load_mgr().Load_by_ids(Cancelable_.Never, rv, 0, pages_len);
rv.Sort_by(Xowd_page_itm_sorter.IdAsc);
}
private static void Find_excludes(Ordered_hash exclude_pages, Xodb_load_mgr load_mgr, Xowd_page_itm tmp_page, Int_obj_ref tmp_id, List_adp exclude_ctgs) {
if (exclude_ctgs == null) return;
int exclude_ctgs_len = exclude_ctgs.Count();
for (int i = 0; i < exclude_ctgs_len; i++) {
byte[] exclude_ctg = (byte[])exclude_ctgs.Get_at(i);
Find_pages_in_ctg(exclude_pages, load_mgr, tmp_page, tmp_id, exclude_ctg);
}
}
private static void Find_pages_in_ctg(Ordered_hash list, Xodb_load_mgr load_mgr, Xowd_page_itm tmp_page, Int_obj_ref tmp_id, byte[] ctg_ttl) {
Xoctg_view_ctg ctg = new Xoctg_view_ctg().Name_(ctg_ttl);
load_mgr.Load_ctg_v1(ctg, ctg_ttl);
for (byte ctg_tid = 0; ctg_tid < Xoa_ctg_mgr.Tid__max; ctg_tid++) {
Xoctg_view_grp ctg_mgr = ctg.Grp_by_tid(ctg_tid); if (ctg_mgr == null) continue;
int itms_len = ctg_mgr.Total();
for (int i = 0; i < itms_len; i++) {
Xoctg_view_itm ctg_itm = ctg_mgr.Itms()[i];
int ctg_itm_id = ctg_itm.Id();
if (list.Has(tmp_id.Val_(ctg_itm_id))) continue;
list.Add(Int_obj_ref.new_(ctg_itm_id), ctg_itm);
// if (ctg_tid == Xoa_ctg_mgr.Tid_subc) { // recurse subcategories
// load_mgr.Load_by_id(tmp_page, ctg_itm_id);
// Find_pages_in_ctg(list, load_mgr, tmp_page, tmp_id, tmp_page.Ttl_wo_ns());
// }
}
}
}
private static void Del_old_pages_not_in_cur(int i, Int_obj_ref tmp_id, Ordered_hash old_regy, Ordered_hash cur_regy, List_adp del_list) {
if (i == 0) return; // skip logic for first ctg (which doesn't have a predecessor)
int old_len = old_regy.Count();
for (int j = 0; j < old_len; j++) { // if cur is not in new, del it
Int_obj_ref old_id = (Int_obj_ref)old_regy.Get_at(j);
if (!cur_regy.Has(tmp_id.Val_(old_id.Val()))) // old_itm does not exist in cur_regy
del_list.Add(old_id); // remove; EX: (A,B) in old; B only in cur; old should now be (A) only
}
int del_len = del_list.Count();
for (int j = 0; j < del_len; j++) {
Int_obj_ref old_itm = (Int_obj_ref)del_list.Get_at(j);
old_regy.Del(tmp_id.Val_(old_itm.Val()));
}
}
private static void Add_cur_pages_also_in_old(int i, Int_obj_ref tmp_id, Ordered_hash old_regy, Ordered_hash cur_regy, Ordered_hash new_regy, Ordered_hash exclude_pages, int ns_filter) {
int found_len = cur_regy.Count();
for (int j = 0; j < found_len; j++) { // if new_page is in cur, add it
Xoctg_view_itm cur_itm = (Xoctg_view_itm)cur_regy.Get_at(j);
if (ns_filter != Dpl_itm.Ns_filter_null && ns_filter != cur_itm.Ttl().Ns().Id()) continue;
tmp_id.Val_(cur_itm.Id()); // set tmp_id, since it will be used at least once
if (exclude_pages.Has(tmp_id)) continue; // ignore excluded pages
if (i != 0) { // skip logic for first ctg (which doesn't have a predecessor)
if (!old_regy.Has(tmp_id)) continue; // cur_itm not in old_regy; ignore
}
new_regy.Add_as_key_and_val(Int_obj_ref.new_(cur_itm.Id()));
}
}
}

View File

@@ -0,0 +1,243 @@
/*
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.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.core.strings.*;
public class Dpl_xnde_tst {
private Dpl_xnde_fxt fxt = new Dpl_xnde_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Ctg() {
fxt.Ctg_create("Ctg_0", "B", "A");
fxt.Ul_pages("<DynamicPageList>category=Ctg_0</DynamicPageList>", fxt.Ul(Itm_html_null, "B", "A"));
}
@Test public void Ctg_multiple() {
fxt.Ctg_create_pages("Ctg_0", Dpl_page_mok.new_(101, "A"), Dpl_page_mok.new_(102, "B"));
fxt.Ctg_create_pages("Ctg_1", Dpl_page_mok.new_(101, "A"));
fxt.Ul_pages(String_.Concat_lines_nl
( "<DynamicPageList>"
, "category=Ctg_0"
, "category=Ctg_1"
, "</DynamicPageList>"
), fxt.Ul(Itm_html_null, "A"));
}
@Test public void Ctg_multiple_none() { // PURPOSE: page must be in both categories
fxt.Ctg_create("Ctg_0", "A");
fxt.Ctg_create("Ctg_1", "B");
fxt.Ul_pages(String_.Concat_lines_nl
( "<DynamicPageList>"
, "category=Ctg_0"
, "category=Ctg_1"
, "</DynamicPageList>"
), "No pages meet these criteria.");
}
@Test public void Notcategory() {
fxt.Ctg_create_pages("Ctg_0", Dpl_page_mok.new_(101, "A"), Dpl_page_mok.new_(102, "B"));
fxt.Ctg_create_pages("Ctg_1", Dpl_page_mok.new_(101, "A"));
fxt.Ul_pages(String_.Concat_lines_nl
( "<DynamicPageList>"
, "category=Ctg_0"
, "notcategory=Ctg_1"
, "</DynamicPageList>"
), fxt.Ul(Itm_html_null, "B"));
}
@Test public void Ctg_ascending() {
fxt.Ctg_create("Ctg_0", "B", "A");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "order=ascending"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A", "B"));
}
@Test public void Ctg_ws() {
fxt.Ctg_create("Ctg_0", "B", "A");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, " category = Ctg_0 "
, " order = ascending "
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A", "B"));
}
@Test public void Ctg_descending() {
fxt.Ctg_create("Ctg_0", "A", "B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "order=descending"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "B", "A"));
}
@Test public void Nofollow() {
fxt.Ctg_create("Ctg_0", "A", "B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "nofollow=true"
, "</DynamicPageList>"), fxt.Ul(" rel=\"nofollow\"", "A", "B"));
}
@Test public void Invalid_key() {
fxt.Ctg_create("Ctg_0", "A", "B");
fxt.Warns("dynamic_page_list:unknown_key: page=Test page key=invalid_key");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "invalid_key=invalid_val"
, "category=Ctg_0"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A", "B"));
}
@Test public void No_results() {
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "</DynamicPageList>"), "No pages meet these criteria.");
}
@Test public void Suppress_errors() {
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "suppresserrors=true"
, "</DynamicPageList>"), "");
}
@Test public void Count() {
fxt.Ctg_create("Ctg_0", "A", "B", "C");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "count=2"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A", "B"));
}
@Test public void Offset() {
fxt.Ctg_create("Ctg_0", "A", "B", "C");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "offset=2"
, "count=2"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "C"));
}
@Test public void Ns() {
fxt.Ctg_create("Ctg_0", "Talk:A", "B");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "namespace=Talk"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A"));
}
@Test public void Showns() {
fxt.Ctg_create("Ctg_0", "Talk:A");
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "shownamespace=true"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "Talk:A"));
fxt.Ul_pages(String_.Concat_lines_nl_skip_last
( "<DynamicPageList>"
, "category=Ctg_0"
, "shownamespace=false"
, "</DynamicPageList>"), fxt.Ul(Itm_html_null, "A"));
}
@Test public void Comment() { // PURPOSE: comment should be ignored; en.n:Portal:Federally_Administered_Tribal_Areas; DATE:2014-01-18
fxt.Ctg_create("Ctg_0", "B", "A");
fxt.Ul_pages(String_.Concat_lines_nl
( "<DynamicPageList>"
, "category=Ctg_0"
, "<!--category=Ctg_0-->"
, "</DynamicPageList>"
), fxt.Ul(Itm_html_null, "B", "A"));
}
@Test public void Error_skip_line() { // PURPOSE: error should skip rest of line; was failing with array out of bounds; en.n:Portal:Austria/Wikipedia; DATE:2014-01-18
fxt.Warns("dynamic_page_list:unknown_key: page=Test page key=Ctg_0 order"); // ignore warning message
fxt.Ul_pages("<DynamicPageList> category=Ctg_0 order=descending</DynamicPageList>", "No pages meet these criteria.");
}
@Test public void Atr_has_template() { // PURPOSE: attribute also has template; DATE:2014-01-31
fxt.Ctg_create("Test_page", "B", "A");
fxt.Ul_pages(String_.Concat_lines_nl
( "<DynamicPageList>"
, "category={{PAGENAME}}"
, "</DynamicPageList>"
), fxt.Ul(Itm_html_null, "B", "A"));
}
@Test public void Err_page_ns_doesnt_exist() {// PURPOSE: check that <dpl> is not enabled if wiki does not have Page / Index ns; PAGE:fr.w:Wikipedia:Le_Bistro/novembre_2006 DATE:2014-11-28
fxt.Wiki().Ns_mgr().Clear().Init(); // call .Clear() to remove ns for Page / Index
fxt.Wiki().Cfg_parser().Xtns().Itm_pages().Reset(); // must reset to clear cached valid ns_page from previous tests
fxt.Fxt().Test_parse_page_wiki_str("<dynamicpagelist>category=a</dynamicpagelist>", "No pages meet these criteria.");
fxt.Wiki().Cfg_parser().Xtns().Itm_pages().Reset(); // must reset to clear cached invalid ns_page for next tests
}
private static final String Itm_html_null = null;
}
class Dpl_page_mok {
public Dpl_page_mok(int id, String ttl) {this.id = id; this.ttl = ttl;}
public int Id() {return id;} private int id;
public String Ttl() {return ttl;} private String ttl;
public static Dpl_page_mok new_(int id, String ttl) {return new Dpl_page_mok(id, ttl);}
}
class Dpl_xnde_fxt {
private Xop_fxt fxt = new Xop_fxt();
private int next_id;
public void Clear() {
next_id = 100;
fxt.Reset();
warns = String_.Ary_empty;
fxt.App().Usr_dlg().Gui_wkr().Clear();
fxt.Wiki().Hive_mgr().Clear();
fxt.Wiki().Db_mgr().Save_mgr().Clear(); // NOTE: must clear to reset next_id to 0; Ctg_create assumes clean slate from 0
fxt.Wiki().Xtn_mgr().Xtn_proofread().Enabled_y_();
fxt.Wiki().Db_mgr().Load_mgr().Clear(); // must clear; otherwise fails b/c files get deleted, but wiki.data_mgr caches the Xowd_regy_mgr (the .reg file) in memory;
fxt.Wiki().Ns_mgr().Add_new(Xowc_xtn_pages.Ns_page_id_default, "Page").Add_new(Xowc_xtn_pages.Ns_index_id_default, "Index").Init();
Io_mgr.I.InitEngine_mem();
}
public Xowe_wiki Wiki() {return fxt.Wiki();}
public Xop_fxt Fxt() {return fxt;}
public void Warns(String... v) {warns = v;} private String[] warns;
public void Page_create(String page) {fxt.Init_page_create(page);}
public void Ctg_create(String ctg, String... ttls) {
int len = ttls.length;
Dpl_page_mok[] ary = new Dpl_page_mok[len];
for (int i = 0; i < len; i++)
ary[i] = Dpl_page_mok.new_(++next_id, ttls[i]);
Ctg_create_pages(ctg, ary);
}
public void Ctg_create_pages(String ctg, Dpl_page_mok... pages) {
int pages_len = pages.length;
int[] page_ids = new int[pages_len];
for (int i = 0; i < pages_len; i++) {
Dpl_page_mok page = pages[i];
int id = page.Id();
String ttl = page.Ttl();
Xoa_ttl page_ttl = Xoa_ttl.parse_(fxt.Wiki(), Bry_.new_u8(ttl));
Xoae_page page_obj = fxt.Wiki().Data_mgr().Get_page(page_ttl, false);
if (page_obj.Missing()) {
fxt.Init_page_create(ttl);
fxt.Init_id_create (id, 0, 0, false, 5, Xow_ns_.Id_main, ttl);
}
page_ids[i] = id;
}
fxt.Init_ctg_create(ctg, page_ids);
}
public String Ul(String itm_html, String... pages) {
bfr.Add("<ul>").Add_char_nl();
int pages_len = pages.length;
for (int i = 0; i < pages_len; i++) {
String page = pages[i];
bfr.Add(" <li><a href=\"/wiki/").Add(page).Add("\" title=\"").Add(page).Add("\"");
if (itm_html != null) bfr.Add(itm_html);
bfr.Add(">").Add(page).Add("</a></li>").Add_char_nl();
}
bfr.Add("</ul>").Add_char_nl();
return bfr.Xto_str_and_clear();
}
public void Ul_pages(String raw, String expd) {
fxt.Test_parse_page_wiki_str(raw, expd);
fxt.tst_Warn(warns);
} String_bldr bfr = String_bldr_.new_();
}

View File

@@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.flaggedRevs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*; import gplx.xowa.pages.skins.*; import gplx.xowa.xtns.pfuncs.*;
public class Pages_using_pending_changes_func extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_pagesUsingPendingChanges;}
@Override public Pf_func New(int id, byte[] name) {return new Pages_using_pending_changes_func().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
bfr.Add_int_fixed(0, 1);
}
public static final Pages_using_pending_changes_func _ = new Pages_using_pending_changes_func(); Pages_using_pending_changes_func() {}
}

View File

@@ -0,0 +1,25 @@
/*
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.flaggedRevs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.xowa.pages.skins.*;
public class Pages_using_pending_changes_func_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_html_full_str("{{PAGESUSINGPENDINGCHANGES}}", "0");
}
}

View File

@@ -0,0 +1,25 @@
/*
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.flaggedRevs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*; import gplx.xowa.pages.skins.*; import gplx.xowa.xtns.pfuncs.*;
public class Pending_change_level_func extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_pendingChangeLevel;}
@Override public Pf_func New(int id, byte[] name) {return new Pending_change_level_func().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {}// NOOP
public static final Pending_change_level_func _ = new Pending_change_level_func(); Pending_change_level_func() {}
}

View File

@@ -0,0 +1,25 @@
/*
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.flaggedRevs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.xowa.pages.skins.*;
public class Pending_change_level_func_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_html_full_str("{{PENDINGCHANGELEVEL}}", "");
}
}

View File

@@ -0,0 +1,63 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.html.hdumps.abrvs.*;
public interface Gallery_box_w_fmtr_arg extends Bry_fmtr_arg {
Gallery_box_w_fmtr_arg Init(int uid, int width);
}
class Gallery_box_w_fmtr_arg__basic implements Gallery_box_w_fmtr_arg {
private int width;
public Gallery_box_w_fmtr_arg Init(int uid, int width) {this.width = width; return this;}
public void XferAry(Bry_bfr bfr, int idx) {
bfr.Add(Style_bgn);
bfr.Add_int_variable(width);
bfr.Add(Style_end);
}
private static final byte[] Style_bgn = Bry_.new_a7("style=\"width: "), Style_end = Bry_.new_a7("px\"");
}
class Gallery_box_w_fmtr_arg__hdump implements Gallery_box_w_fmtr_arg {
private int uid;
public Gallery_box_w_fmtr_arg Init(int uid, int width) {this.uid = uid; return this;}
public void XferAry(Bry_bfr bfr, int idx) {
bfr.Add(Xohd_abrv_.Key_gallery_box_w);
bfr.Add_int_variable(uid);
bfr.Add_byte_apos();
}
}
interface Gallery_img_pad_fmtr_arg extends Bry_fmtr_arg {
Gallery_img_pad_fmtr_arg Init(int uid, int vpad);
}
class Gallery_img_pad_fmtr_arg__basic implements Gallery_img_pad_fmtr_arg {
private int vpad;
public Gallery_img_pad_fmtr_arg Init(int uid, int vpad) {this.vpad = vpad; return this;}
public void XferAry(Bry_bfr bfr, int idx) {
bfr.Add(Style_bgn);
bfr.Add_int_variable(vpad);
bfr.Add(Style_end);
}
private static final byte[] Style_bgn = Bry_.new_a7("style=\"margin:"), Style_end = Bry_.new_a7("px auto;\"");
}
class Gallery_img_pad_fmtr_arg__hdump implements Gallery_img_pad_fmtr_arg {
private int uid;
public Gallery_img_pad_fmtr_arg Init(int uid, int width) {this.uid = uid; return this;}
public void XferAry(Bry_bfr bfr, int idx) {
bfr.Add(Xohd_abrv_.Key_gallery_img_pad);
bfr.Add_int_variable(uid);
bfr.Add_byte_apos();
}
}

View File

@@ -0,0 +1,173 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.files.*; import gplx.xowa.html.*; import gplx.xowa.html.lnkis.*; import gplx.xowa.html.hdumps.core.*; import gplx.xowa.html.hdumps.pages.*;
public class Gallery_html_wtr {
private final Xoh_arg_img_core img_core_fmtr_basic = new Xoh_arg_img_core__basic(), img_core_fmtr_hdump = new Xoh_arg_img_core__hdump();
public void Write_html(Bry_bfr bfr, Xoae_app app, Xowe_wiki wiki, Xop_ctx ctx, Xoh_html_wtr wtr, Xoh_wtr_ctx hctx, Xoae_page page, Gallery_xnde mgr, byte[] src) {
int itm_div_w = Gallery_html_wtr_utl.Calc_itm_div_len(mgr.Itm_w_or_default());
int itm_div_h = Gallery_html_wtr_utl.Calc_itm_div_len(mgr.Itm_h_or_default());
int itm_box_w = Gallery_html_wtr_utl.Calc_itm_box_w(itm_div_w);
int itms_len = mgr.Itms_len();
int itms_per_row = mgr.Itms_per_row();
if (itms_per_row == Gallery_xnde.Null) itms_per_row = wiki.Cfg_gallery().Imgs_per_row();
int mgr_box_width_row = Gallery_html_wtr_utl.Calc_itm_pad_w(itm_box_w) * itms_per_row;
int row_multiplier; Bry_fmtr mgr_box_style;
if (itms_per_row == Gallery_xnde.Null) { // no "perrow" defined; default to total # of items;
row_multiplier = itms_len;
mgr_box_style = Gallery_html_wtr_.Mgr_box_style_none;
}
else {
row_multiplier = itms_per_row;
mgr_box_style = Gallery_html_wtr_.Mgr_box_style_max;
}
boolean mode_is_packed = Gallery_mgr_base_.Mode_is_packed(mgr.Mode());
byte[] mgr_box_cls; int mgr_box_width_all;
if (mode_is_packed) {
mgr_box_cls = Gallery_html_wtr_.Cls_packed;
mgr_box_width_all = 0;
}
else {
mgr_box_cls = Bry_.Empty;
mgr_box_width_all = Gallery_html_wtr_utl.Calc_itm_pad_w(itm_box_w) * row_multiplier; // 8=Gallery Box borders; REF.MW:ImageGallery.php|GB_BORDERS;
}
Bry_bfr itm_bfr = wiki.Utl__bfr_mkr().Get_k004(), tmp_bfr = wiki.Utl__bfr_mkr().Get_k004();
int mgr_elem_id = -1; int gallery_w_count = 0;
boolean hctx_is_hdump = hctx.Mode_is_hdump();
Xoh_arg_img_core img_core_fmtr = hctx_is_hdump ? img_core_fmtr_hdump : img_core_fmtr_basic;
Xopg_hdump_data hdump_imgs = page.Hdump_data();
for (int i = 0; i < itms_len; i++) {
Gallery_itm itm = mgr.Itms_get_at(i);
byte[] itm_caption = Gallery_html_wtr_.Bld_caption(wiki, ctx, wtr, hctx, itm);
Xoa_ttl itm_ttl = itm.Ttl();
if ( itm_ttl != null // ttl does not have invalid characters
&& itm_ttl.Ns().Id_file() // ttl is in file ns;
) {
Xop_lnki_tkn lnki = ctx.Tkn_mkr().Lnki(itm.Ttl_bgn(), itm.Ttl_end()).Ttl_(itm_ttl).W_(mgr.Itm_w()).H_(mgr.Itm_h());
Xof_file_itm xfer_itm = wtr.Lnki_wtr().File_wtr().Lnki_eval(Xof_exec_tid.Tid_wiki_page, ctx, page, lnki);
xfer_itm.Html_gallery_mgr_h_(mgr.Itm_h_or_default());
xfer_itm.Html_elem_tid_(Xof_html_elem.Tid_gallery);
if (mode_is_packed) {
if (gallery_w_count < itms_per_row) {
mgr_box_width_all += Gallery_html_wtr_utl.Calc_itm_pad_w(itm_box_w);
++gallery_w_count;
}
if (xfer_itm.Html_w() > 0) {
itm_div_w = Gallery_html_wtr_utl.Calc_itm_div_len(xfer_itm.Html_w());
itm_box_w = Gallery_html_wtr_utl.Calc_itm_box_w(itm_div_w); // NOTE: redefine itm_box_w for rest of loop
}
if (xfer_itm.Html_h() > 0)
itm_div_h = Gallery_html_wtr_utl.Calc_itm_div_len(xfer_itm.Html_h());
}
int itm_elem_id = xfer_itm.Html_uid();
if (mgr_elem_id == -1)
mgr_elem_id = itm_elem_id; // HACK: set mgr_elem_id to first itm_elem_id
int html_w = xfer_itm.Html_w();
int html_h = xfer_itm.Html_h();
byte[] html_src = xfer_itm.Html_view_url().To_http_file_bry();
if (html_src.length == 0) { // itm not found; use gallery defaults
html_w = mgr.Itm_w_or_default();
html_h = mgr.Itm_h_or_default();
}
byte[] lnki_ttl = lnki.Ttl().Page_txt();
Xoa_ttl lnki_link_ttl = itm_ttl; // default href to ttl
if ( itm.Link_bgn() != Bry_.NotFound // link is not -1; EX: "A.png" has no link specified
&& (itm.Link_end() - itm.Link_bgn()) > 0 // and link_end - link_bgn > 0; EX: "A.png|link="; DATE:2014-06-15
)
lnki_link_ttl = Xoa_ttl.parse_(wiki, Bry_.Mid(src, itm.Link_bgn(), itm.Link_end()));
byte[] lnki_href = app.Href_parser().Build_to_bry(wiki, lnki_link_ttl);
byte[] lnki_alt = itm.Alt_bgn() == Bry_.NotFound ? lnki_ttl : Xoh_html_wtr_escaper.Escape(app.Parser_amp_mgr(), tmp_bfr, Bry_.Mid(src, itm.Alt_bgn(), itm.Alt_end()));
img_core_fmtr.Init(itm_elem_id, html_src, html_w, html_h);
int itm_margin = Gallery_html_wtr_utl.Calc_vpad(mgr.Itm_h(), html_h);
Gallery_html_wtr_.Itm_img_fmtr.Bld_bfr_many(itm_bfr
, itm_box_w, itm_div_w, itm_margin
, itm_elem_id
, lnki_ttl
, lnki_href
, img_core_fmtr
, itm_caption
, lnki_alt
);
if (hctx_is_hdump)
hdump_imgs.Imgs_add_img(new Xohd_data_itm__gallery_itm().Data_init_gallery(itm_div_w, itm_box_w, itm_margin), xfer_itm, Xohd_data_itm__gallery_itm.Tid_gallery);
}
else {
Gallery_html_wtr_.Itm_txt_fmtr.Bld_bfr_many(itm_bfr
, itm_box_w, itm_div_h
, Bry_.Mid(src, itm.Ttl_bgn(), itm.Ttl_end())
, itm_caption
);
}
}
itm_bfr.Mkr_rls();
tmp_bfr.Mkr_rls();
int mgr_box_width_max = mgr_box_width_all < mgr_box_width_row ? mgr_box_width_row : mgr_box_width_all;
Gallery_html_wtr_.Mgr_all_fmtr.Bld_bfr_many(bfr, mgr_elem_id, mgr_box_cls, Bry_fmtr_arg_.fmtr_(mgr_box_style, Bry_fmtr_arg_.int_(mgr_box_width_max)), itm_bfr);
}
}
class Gallery_html_wtr_ {
public static final byte[] Cls_packed = Bry_.new_u8(" mw-gallery-packed");
public static final Bry_fmtr
Mgr_all_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( "<ul id=\"xowa_gallery_ul_~{gallery_id}\" class=\"gallery~{gallery_cls}\" style=\"~{gallery_style}\">~{itm_list}"
, "</ul>"
), "gallery_id", "gallery_cls", "gallery_style", "itm_list"
)
, Mgr_box_style_none = Bry_fmtr.new_()
, Mgr_box_style_max = Bry_fmtr.new_("max-width:~{gallery_width}px; _width:~{gallery_width}px;", "gallery_width")
, Itm_img_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <li id=\"xowa_gallery_li_~{img_id}\" class=\"gallerybox\" style=\"width:~{itm_box_width}px;\">"
, " <div id=\"xowa_gallery_div1_~{img_id}\" style=\"width:~{itm_box_width}px;\">"
, " <div id=\"xowa_gallery_div2_~{img_id}\" class=\"thumb\" style=\"width:~{itm_div_width}px;\">"
, " <div id=\"xowa_gallery_div3_~{img_id}\" style=\"margin:~{itm_margin}px auto;\">"
, " <a href=\"~{img_href}\" class=\"image\">"
, " <img id=\"xowa_file_img_~{img_id}\" alt=\"~{img_alt}\"~{img_core} />"
, " </a>"
, " </div>"
, " </div>"
, " <div class=\"gallerytext\">~{itm_caption}"
, " </div>"
, " </div>"
, " </li>"
), "itm_box_width", "itm_div_width", "itm_margin", "img_id", "img_ttl", "img_href", "img_core", "itm_caption", "img_alt"
)
, Itm_txt_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <li id=\"xowa_gallery_li_~{img_id}\" class=\"gallerybox\" style=\"width:~{itm_box_width};\">"
, " <div id=\"xowa_gallery_div1_~{img_id}\" style=\"width:~{itm_box_width};\">"
, " <div id=\"xowa_gallery_div2_~{img_id}\" style=\"~{itm_div_height}\">"
, " ~{itm_text}"
, " </div>"
, " <div class=\"gallerytext\">~{itm_caption}"
, " </div>"
, " </div>"
, " </li>"
), "itm_box_width", "itm_div_height", "itm_text", "itm_caption"
);
public static byte[] Bld_caption(Xowe_wiki wiki, Xop_ctx ctx, Xoh_html_wtr wtr, Xoh_wtr_ctx hctx, Gallery_itm itm) {
byte[] rv = itm.Caption_bry();
if (Bry_.Len_gt_0(rv)) {
Bry_bfr caption_bfr = wiki.Utl__bfr_mkr().Get_k004();
Xop_root_tkn caption_root = itm.Caption_tkn();
wtr.Write_tkn(caption_bfr, ctx, hctx, caption_root.Root_src(), caption_root, Xoh_html_wtr.Sub_idx_null, caption_root);
rv = caption_bfr.To_bry_and_rls();
}
return rv;
}
}

View File

@@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Gallery_html_wtr_utl {
public static int Calc_itm_div_len(int v) {return v + 30;} // 30=Thumb padding; REF.MW:ImageGallery.php|THUMB_PADDING
public static int Calc_itm_box_w(int v) {return v + 5;} // 5=Gallery Box padding; REF.MW:ImageGallery.php|GB_PADDING
public static int Calc_itm_pad_w(int v) {return v + 8;} // 8=Gallery Box borders; REF.MW:ImageGallery.php|GB_BORDERS
public static int Calc_vpad(int mgr_itm_height, int html_h) {
int min_thumb_height = html_h > 17 ? html_h : 17; // $minThumbHeight = $thumb->height > 17 ? $thumb->height : 17;
return (int)Math_.Floor((30 + mgr_itm_height - min_thumb_height) / 2); // $vpad = floor(( self::THUMB_PADDING + $this->mHeights - $minThumbHeight ) /2);
}
}

View File

@@ -0,0 +1,62 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.files.*; import gplx.xowa.files.gui.*; import gplx.xowa.gui.views.*; import gplx.xowa.html.*;
public class Gallery_itm implements Js_img_wkr {
private Gallery_xnde xnde; private Xof_file_itm xfer_itm; private Xowe_wiki wiki; private Xop_ctx ctx; private byte[] src; private byte[] gallery_li_id_bry; private int gallery_itm_idx;
public Xoa_ttl Ttl() {return ttl;} public Gallery_itm Ttl_(Xoa_ttl v) {ttl = v; return this;} private Xoa_ttl ttl;
public int Ttl_bgn() {return ttl_bgn;} public Gallery_itm Ttl_bgn_(int v) {ttl_bgn = v; return this;} private int ttl_bgn;
public int Ttl_end() {return ttl_end;} public Gallery_itm Ttl_end_(int v) {ttl_end = v; return this;} private int ttl_end;
public Xof_ext Ext() {return ext;} public Gallery_itm Ext_(Xof_ext v) {ext = v; return this;} private Xof_ext ext;
public byte[] Caption_bry() {return caption_bry;} public Gallery_itm Caption_bry_(byte[] v) {caption_bry = v; return this;} private byte[] caption_bry;
public Xop_root_tkn Caption_tkn() {return caption_tkn;} public Gallery_itm Caption_tkn_(Xop_root_tkn v) {caption_tkn = v; return this;} private Xop_root_tkn caption_tkn;
public int Alt_bgn() {return alt_bgn;} public Gallery_itm Alt_bgn_(int v) {alt_bgn = v; return this;} private int alt_bgn;
public int Alt_end() {return alt_end;} public Gallery_itm Alt_end_(int v) {alt_end = v; return this;} private int alt_end;
public int Link_bgn() {return link_bgn;} public Gallery_itm Link_bgn_(int v) {link_bgn = v; return this;} private int link_bgn;
public int Link_end() {return link_end;} public Gallery_itm Link_end_(int v) {link_end = v; return this;} private int link_end;
public int Page_bgn() {return page_bgn;} public Gallery_itm Page_bgn_(int v) {page_bgn = v; return this;} private int page_bgn;
public int Page_end() {return page_end;} public Gallery_itm Page_end_(int v) {page_end = v; return this;} private int page_end;
public Xop_lnki_tkn Lnki_tkn() {return lnki_tkn;} public Gallery_itm Lnki_tkn_(Xop_lnki_tkn v) {lnki_tkn = v; return this;} private Xop_lnki_tkn lnki_tkn;
public Gallery_itm Reset() {
ttl = null;
ttl_bgn = ttl_end = alt_bgn = alt_end = link_bgn = link_end = page_bgn = page_end = Bry_.NotFound;
caption_bry = null; // NOTE: use null instead of ""; more legible tests
caption_tkn = null;
ext = null;
return this;
}
public void Html_prepare(Xowe_wiki wiki, Xop_ctx ctx, byte[] src, Gallery_xnde xnde, Xof_file_itm xfer_itm, byte[] gallery_li_id_bry, int gallery_itm_idx) {
this.xnde = xnde; this.xfer_itm = xfer_itm;
this.wiki = wiki; this.ctx = ctx; this.src = src; this.gallery_li_id_bry = gallery_li_id_bry; this.gallery_itm_idx = gallery_itm_idx;
}
public void Html_update(Xoa_page page, Xog_js_wkr js_wkr, int html_uid, int html_w, int html_h, Io_url html_view_url, int orig_w, int orig_h, Io_url html_orig_url, byte[] lnki_ttl) {
Gallery_mgr_base gallery_mgr = xnde.Gallery_mgr();
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_k004(), tmp_bfr = wiki.Utl__bfr_mkr().Get_k004();
try {
xfer_itm.Init_at_gallery_end(html_w, html_h, html_view_url, html_orig_url);
gallery_mgr.Write_html_itm(bfr, tmp_bfr, wiki.Appe(), wiki, ctx.Cur_page(), ctx, wiki.Html_mgr().Html_wtr(), Xoh_wtr_ctx.Basic, src, xnde, Bry_.Empty, gallery_itm_idx, xfer_itm, false);
String itm_html = bfr.Xto_str_and_clear();
js_wkr.Html_elem_replace_html(String_.new_u8(gallery_li_id_bry), itm_html);
if (gallery_itm_idx == xnde.Itms_len() - 1 && Gallery_mgr_base_.Mode_is_packed(xnde.Mode()))
page.Xtn_gallery_packed_exists_y_(); // set flag for packed_gallery; don't fire multiple times; PAGE:en.w:National_Sculpture_Museum_(Valladolid); DATE:2014-07-21
}
finally {
bfr.Mkr_rls(); tmp_bfr.Mkr_rls();
}
}
}

View File

@@ -0,0 +1,251 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
import gplx.xowa.parsers.lnkis.redlinks.*;
import gplx.xowa.files.*;
public class Gallery_itm_parser {
private Xowe_wiki wiki; private Btrie_slim_mgr trie = Btrie_slim_mgr.ci_utf_8_();
private Gallery_itm cur_itm;
private byte[] src; private int end_pos;
private int cur_pos; private byte cur_byte;
private byte cur_fld;
private int itm_bgn;
private Bry_bfr caption_bfr = Bry_bfr.reset_(255); private int caption_bgn;
private Xop_ctx ctx;
public Gallery_itm_parser Init_by_wiki(Xowe_wiki wiki) {
this.wiki = wiki; Xol_lang lang = wiki.Lang();
this.ctx = wiki.Ctx();
trie.Clear();
Byte_obj_ref tmp_bref = Byte_obj_ref.zero_();
Init_keyword(tmp_bref, lang, Xol_kwd_grp_.Id_img_alt, Fld_alt); // NOTE: MW uses "gallery-@gplx.Internal protected-alt" which just maps to "img-alt"
Init_keyword(tmp_bref, lang, Xol_kwd_grp_.Id_img_link, Fld_link); // NOTE: MW uses "gallery-@gplx.Internal protected-link" which just maps to "img-link"
Init_keyword(tmp_bref, lang, Xol_kwd_grp_.Id_img_page, Fld_page);
return this;
}
public boolean Parse_in_progress() {return parse_in_progress;} public void Parse_in_progress_(boolean v) {parse_in_progress = v;} private boolean parse_in_progress;
public void Parse_all(List_adp rv, Gallery_mgr_base mgr, Gallery_xnde xnde, byte[] src, int content_bgn, int content_end) {
synchronized (trie) {parse_in_progress = true;}
this.src = src;
this.cur_pos = content_bgn; this.end_pos = content_end;
cur_itm = new Gallery_itm();
while (cur_pos < end_pos) {
cur_itm.Reset();
caption_bfr.Clear();
byte cur_mode = Parse_itm();
if (cur_itm.Ttl() != null) {
if (caption_bfr.Len() > 0)
cur_itm.Caption_bry_(caption_bfr.Xto_bry_and_clear_and_trim());
Make_lnki_tkn(mgr, xnde, src);
rv.Add(cur_itm);
cur_itm = new Gallery_itm();
}
if (cur_mode == Mode_nl)
++cur_pos;
}
synchronized (trie) {parse_in_progress = false;}
}
private void Make_lnki_tkn(Gallery_mgr_base mgr, Gallery_xnde xnde, byte[] src) {
Xop_lnki_tkn lnki_tkn = ctx.Tkn_mkr().Lnki(cur_itm.Ttl_bgn(), cur_itm.Ttl_end()).Ttl_(cur_itm.Ttl());
if (cur_itm.Link_bgn() != -1)
lnki_tkn.Link_tkn_(new Arg_nde_tkn_mock("link", String_.new_u8(src, cur_itm.Link_bgn(), cur_itm.Link_end()))); // NOTE: hackish, but add the link as arg_nde, since gallery link is not parsed like a regular lnki
cur_itm.Lnki_tkn_(lnki_tkn);
if (cur_itm.Page_bgn() != -1) {
int page_val = Bry_.Xto_int_or(src, cur_itm.Page_bgn(), cur_itm.Page_end(), -1);
if (page_val == -1) Xoa_app_.Usr_dlg().Warn_many("", "", "page is not an int: wiki=~{0} ttl=~{1} page=~{2}", wiki.Domain_str(), ctx.Cur_page().Ttl().Page_db(), String_.new_u8(src, cur_itm.Page_bgn(), cur_itm.Page_end()));
lnki_tkn.Page_(page_val);
}
byte[] lnki_caption = cur_itm.Caption_bry();
if (Bry_.Len_gt_0(lnki_caption)) {
Xop_root_tkn caption_tkn = wiki.Parser().Parse_text_to_wdom_old_ctx(ctx, lnki_caption, true);
cur_itm.Caption_tkn_(caption_tkn);
}
Xopg_redlink_logger file_wkr = ctx.Lnki().File_wkr(); // NOTE: do not set file_wkr ref early (as member var); parse_all sets late
ctx.Cur_page().Lnki_list().Add(lnki_tkn);
mgr.Get_thumb_size(lnki_tkn, cur_itm.Ext()); // NOTE: set thumb size, so that lnki.temp parse picks it up
if (file_wkr != null) file_wkr.Wkr_exec(ctx, src, lnki_tkn, gplx.xowa.bldrs.cmds.files.Xob_lnki_src_tid.Tid_gallery);
lnki_tkn.W_(-1).H_(-1); // NOTE: reset lnki back to defaults, else itm will show as large missing caption
}
private byte Parse_itm() {
int fld_count = 0;
itm_bgn = cur_pos;
while (cur_pos < end_pos) {
byte mode = Fld_bgn(fld_count);
if (mode == Mode_nl || mode == Mode_eos) return mode;
mode = Skip_to_fld_end();
Fld_end();
if (mode != Mode_pipe) return mode;
++cur_pos; // position after pipe
++fld_count;
}
return Mode_eos;
}
private byte Fld_bgn(int fld_count) {
cur_fld = Fld_null;
int bgn_pos = cur_pos;
byte mode = Skip_ws();
switch (mode) {
case Mode_nl:
case Mode_eos:
return mode;
}
Object o = trie.Match_bgn_w_byte(cur_byte, src, cur_pos, end_pos);
if (o != null) { // either "alt" or "link"
int old_pos = cur_pos;
cur_pos = trie.Match_pos();
Skip_ws();
if (cur_byte == Byte_ascii.Eq) { // "="
++cur_pos; // position after eq
Skip_ws();
cur_fld = ((Byte_obj_val)o).Val();
switch (cur_fld) {
case Fld_alt: cur_itm.Alt_bgn_(cur_pos); return Mode_text;
case Fld_link: cur_itm.Link_bgn_(cur_pos); return Mode_text;
case Fld_page:
if (cur_itm.Ext() != null && cur_itm.Ext().Id_supports_page()) { // NOTE: ext can be null with long multi-line captions; EX:<ref\n|page=1 />; DATE:2014-03-21
cur_itm.Page_bgn_(cur_pos);
return Mode_text;
}
else { // not a pdf / djvu; treat "page=" as caption
cur_fld = Fld_caption;
cur_pos = old_pos;
break; // NOTE: do not return Mode_text, so it reaches caption code below
}
}
}
else
cur_pos = old_pos;
}
if (fld_count == 0) {
cur_fld = Fld_ttl;
cur_itm.Ttl_bgn_(cur_pos);
}
else {
cur_fld = Fld_caption;
caption_bgn = caption_bfr.Len() == 0 ? cur_pos : bgn_pos; // if 1st caption, trim bgn; otherwise, enclose rest; EX: "File:A.png| a| b" -> "a| b"
}
return Mode_text;
}
private byte Skip_to_fld_end() {
while (cur_pos < end_pos) {
cur_byte = src[cur_pos];
switch (cur_byte) {
case Byte_ascii.Pipe: return Mode_pipe;
case Byte_ascii.Nl: return Mode_nl;
case Byte_ascii.Cr:
case Byte_ascii.Space:
case Byte_ascii.Tab:
++cur_pos;
continue;
default:
++cur_pos;
continue;
}
}
return Mode_eos;
}
private void Fld_end() {
int fld_end = cur_pos;
if (cur_fld != Fld_caption) {
int non_ws_pos = Bry_finder.Find_bwd_non_ws_or_not_found(src, cur_pos - 1, itm_bgn) + 1; // SEE:non_ws_pos
if (non_ws_pos != Bry_.NotFound + 1)
fld_end = non_ws_pos;
}
switch (cur_fld) {
case Fld_ttl:
cur_itm.Ttl_end_(fld_end);
byte[] ttl_bry = Bry_.Mid(src, cur_itm.Ttl_bgn(), fld_end);
ttl_bry = Xoa_app_.Utl__encoder_mgr().Http_url_ttl().Decode(ttl_bry); // NOTE: must decode url-encoded entries; EX: "A%28b%29.png" -> "A(b).png"; DATE:2014-01-01
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, ttl_bry);
if ( ttl == null // invalid ttl; EX: "<invalid>"
|| ttl.Anch_bgn() == 1 // anchor-only ttl; EX: "#invalid"; DATE:2014-03-18
)
cur_itm.Reset();
else {
if (!ttl.Ns().Id_file_or_media()) // ttl does not have "File:"; MW allows non-ns names; EX: "A.png" instead of "File:A.png"; DATE:2013-11-18
ttl = Xoa_ttl.parse_(wiki, Xow_ns_.Id_file, ttl_bry);
cur_itm.Ttl_(ttl);
cur_itm.Ext_(Xof_ext_.new_by_ttl_(ttl_bry));
}
break;
case Fld_caption:
if (caption_bfr.Len() != 0) caption_bfr.Add_byte_pipe(); // prepend | to all other captions; EX: File:A.png|a|b -> "a|b" (pipe not added to 1st, but added to 2nd)
caption_bfr.Add_mid(src, caption_bgn, fld_end);
break;
case Fld_alt:
if (fld_end < cur_itm.Alt_bgn())
cur_itm.Alt_bgn_(-1);
else
cur_itm.Alt_end_(fld_end);
break;
case Fld_link:
if (fld_end < cur_itm.Link_bgn())
cur_itm.Link_bgn_(-1);
else
cur_itm.Link_end_(fld_end);
break;
case Fld_page:
if (fld_end < cur_itm.Page_bgn())
cur_itm.Page_bgn_(-1);
else
cur_itm.Page_end_(fld_end);
break;
default: throw Exc_.new_unhandled(fld_end);
}
}
private byte Skip_ws() {
while (cur_pos < end_pos) {
cur_byte = src[cur_pos];
switch (cur_byte) {
case Byte_ascii.Cr:
case Byte_ascii.Space:
case Byte_ascii.Tab: ++cur_pos; continue; // ignore
case Byte_ascii.Pipe: return Mode_pipe;
case Byte_ascii.Nl: return Mode_nl;
default: return Mode_text;
}
}
return Mode_eos;
}
private static final byte Fld_null = 0, Fld_ttl = 1, Fld_caption = 2, Fld_alt = 3, Fld_link = 4, Fld_page = 5;
private static final byte Mode_eos = 1, Mode_nl = 2, Mode_pipe = 3, Mode_text = 4;
private void Init_keyword(Byte_obj_ref tmp_bref, Xol_lang lang, int kwd_id, byte trie_key) {
Xol_kwd_grp grp = lang.Kwd_mgr().Get_at(kwd_id);
if (grp == null) {Gfo_usr_dlg_.I.Warn_many("", "", "could not find gallery keyword: ~{0}", String_.new_u8(Xol_kwd_grp_.Bry_by_id(kwd_id))); return;}
Xol_kwd_itm[] itms = grp.Itms();
int len = itms.length;
Byte_obj_val trie_ref = Byte_obj_val.new_(trie_key);
for (int i = 0; i < len; i++) {
Xol_kwd_itm itm = itms[i];
byte[] itm_bry = Xol_kwd_parse_data.Strip(caption_bfr, itm.Val(), tmp_bref); // strip off =$1 for "alt=$1"
trie.Add_obj(itm_bry, trie_ref);
}
}
}
/*
SEE:non_ws_pos;
int non_ws_pos = Bry_finder.Find_bwd_non_ws(src, cur_pos - 1, itm_bgn) + 1;
. -1 to start before cur_pos (which is usually pipe);
. +1 to place after non_ws_char
EX: text="b c |"; cur_pos = 4;
. -1 to start at cur_pos = 3
. src[3] = ' '; ws; continue
. src[2] = c; return 2;
. + 1 to place after "c" -> 3
. fld_end = 3
*/

View File

@@ -0,0 +1,112 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Gallery_itm_parser_tst {
@Before public void init() {fxt.Init();} private Gallery_itm_parser_fxt fxt = new Gallery_itm_parser_fxt();
@Test public void All() {fxt.Test_parse("File:A.png|a|alt=b|link=c" , fxt.Expd("File:A.png", "a" , "b" , "c"));}
@Test public void Ttl_only() {fxt.Test_parse("File:A.png" , fxt.Expd("File:A.png", null, null, null));}
@Test public void Ttl_url_encoded() {fxt.Test_parse("File:A%28b%29.png" , fxt.Expd("File:A(b).png"));} // PURPOSE: handle url-encoded sequences; DATE:2014-01-01
@Test public void Caption_only() {fxt.Test_parse("File:A.png|a" , fxt.Expd("File:A.png", "a" , null, null));}
@Test public void Caption_many() {fxt.Test_parse("File:A.png|a|b" , fxt.Expd("File:A.png", "a|b"));} // NOTE: pipe becomes part of caption (i.e.: doesn't separate into caption / alt)
@Test public void Alt_only() {fxt.Test_parse("File:A.png|alt=a" , fxt.Expd("File:A.png", null, "a" , null));}
@Test public void Link_only() {fxt.Test_parse("File:A.png|link=a" , fxt.Expd("File:A.png", null, null, "a"));}
@Test public void Caption_alt() {fxt.Test_parse("File:A.png|a|alt=b" , fxt.Expd("File:A.png", "a" , "b"));}
@Test public void Alt_caption() {fxt.Test_parse("File:A.png|alt=a|b" , fxt.Expd("File:A.png", "b" , "a"));}
@Test public void Alt_blank() {fxt.Test_parse("File:A.png|alt=|b" , fxt.Expd("File:A.png", "b" , ""));}
@Test public void Alt_invalid() {fxt.Test_parse("File:A.png|alta=b" , fxt.Expd("File:A.png", "alta=b"));} // NOTE: invalid alt becomes caption
@Test public void Ws() {fxt.Test_parse("File:A.png| alt = b | c" , fxt.Expd("File:A.png", "c" , "b"));}
@Test public void Ws_caption_many() {fxt.Test_parse("File:A.png| a | b | c " , fxt.Expd("File:A.png", "a | b | c"));}
@Test public void Page_pdf() {fxt.Test_parse("File:A.pdf|page=1 " , fxt.Expd("File:A.pdf", null, null, null, 1));} // pdf parses page=1
@Test public void Page_png() {fxt.Test_parse("File:A.png|page=1 " , fxt.Expd("File:A.png", "page=1", null, null));} // non-pdf treats page=1 as caption
@Test public void Page_invalid() {fxt.Test_parse("|page=1");} // check that null title doesn't fail; DATE:2014-03-21
@Test public void Skip_blank() {fxt.Test_parse("");}
@Test public void Skip_empty() {fxt.Test_parse("|File:A.png");}
@Test public void Skip_ws() {fxt.Test_parse(" |File:A.png");}
@Test public void Skip_anchor() {fxt.Test_parse("#a");} // PURPOSE: anchor-like ttl should not render; ar.d:جَبَّارَة; DATE:2014-03-18
@Test public void Many() {
fxt.Test_parse("File:A.png\nFile:B.png" , fxt.Expd("File:A.png"), fxt.Expd("File:B.png"));
}
@Test public void Many_nl() {
fxt.Test_parse("File:A.png\n\n\nFile:B.png" , fxt.Expd("File:A.png"), fxt.Expd("File:B.png"));
}
@Test public void Many_nl_w_tab() {
fxt.Test_parse("File:A.png\n \t \nFile:B.png" , fxt.Expd("File:A.png"), fxt.Expd("File:B.png"));
}
@Test public void Many_invalid() {
fxt.Test_parse("File:A.png\n<invalid>\nFile:B.png" , fxt.Expd("File:A.png"), fxt.Expd("File:B.png"));
}
@Test public void Caption_complicated() {
fxt.Test_parse("File:A.png|alt=a|b[[c|d]]e ", fxt.Expd("File:A.png", "b[[c|d]]e", "a"));
}
@Test public void Alt_magic_word_has_arg() { // PURPOSE: img_alt magic_word is of form "alt=$1"; make sure =$1 is stripped for purpose of parser; DATE:2013-09-12
fxt.Init_kwd_set(Xol_kwd_grp_.Id_img_alt, "alt=$1");
fxt.Test_parse("File:A.png|alt=a|b", fxt.Expd("File:A.png", "b", "a"));
}
@Test public void Link_null() { // PURPOSE: null link causes page to fail; EX: ru.w:Гянджа; <gallery>Datei:A.png|link= |</gallery>; DATE:2014-04-11
fxt.Test_parse("File:A.png|link = |b", fxt.Expd("File:A.png", "b", null, null));
}
@Test public void Caption_empty() { // PURPOSE: check that empty ws doesn't break caption (based on Link_null); DATE:2014-04-11
fxt.Test_parse("File:A.png| | | ", fxt.Expd("File:A.png", null, null, null));
}
}
class Gallery_itm_parser_fxt {
private Xoae_app app; private Xowe_wiki wiki;
private Gallery_itm_parser parser;
public Gallery_itm_parser_fxt Init() {
this.app = Xoa_app_fxt.app_();
this.wiki = Xoa_app_fxt.wiki_tst_(app);
parser = new Gallery_itm_parser();
parser.Init_by_wiki(wiki);
return this;
}
public String[] Expd(String ttl) {return new String[] {ttl, null, null, null, null};}
public String[] Expd(String ttl, String caption) {return new String[] {ttl, caption, null, null, null};}
public String[] Expd(String ttl, String caption, String alt) {return new String[] {ttl, caption, alt, null, null};}
public String[] Expd(String ttl, String caption, String alt, String link) {return new String[] {ttl, caption, alt, link, null};}
public String[] Expd(String ttl, String caption, String alt, String link, int page) {return new String[] {ttl, caption, alt, link, Int_.Xto_str(page)};}
public void Init_kwd_set(int kwd_id, String kwd_val) {
wiki.Lang().Kwd_mgr().Get_or_new(kwd_id).Itms()[0].Val_(Bry_.new_a7(kwd_val));
parser.Init_by_wiki(wiki);
}
public void Test_parse(String raw, String[]... expd) {
List_adp actl = List_adp_.new_();
byte[] src = Bry_.new_a7(raw);
parser.Parse_all(actl, Gallery_mgr_base_.New_by_mode(Gallery_mgr_base_.Traditional_tid), new Gallery_xnde(), src, 0, src.length);
Tfds.Eq_ary(String_.Ary_flatten(expd), String_.Ary_flatten(Xto_str_ary(src, actl)));
}
private String[][] Xto_str_ary(byte[] src, List_adp list) {
int len = list.Count();
String[][] rv = new String[len][];
for (int i = 0; i < len; i++) {
Gallery_itm itm = (Gallery_itm)list.Get_at(i);
String[] ary = new String[5];
rv[i] = ary;
ary[0] = String_.new_u8(itm.Ttl().Full_txt());
ary[2] = Xto_str_ary_itm(src, itm.Alt_bgn(), itm.Alt_end());
ary[3] = Xto_str_ary_itm(src, itm.Link_bgn(), itm.Link_end());
ary[4] = Xto_str_ary_itm(src, itm.Page_bgn(), itm.Page_end());
byte[] caption = itm.Caption_bry();
ary[1] = caption == null ? null : String_.new_u8(caption);
}
return rv;
}
private String Xto_str_ary_itm(byte[] src, int bgn, int end) {
return bgn == Bry_.NotFound && end == Bry_.NotFound ? null : String_.new_u8(src, bgn, end);
}
}

View File

@@ -0,0 +1,226 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; import gplx.xowa.files.*; import gplx.xowa.html.hdumps.abrvs.*; import gplx.xowa.html.hdumps.core.*;
public abstract class Gallery_mgr_base {
private Gallery_box_w_fmtr_arg__basic box_w_fmtr__basic = new Gallery_box_w_fmtr_arg__basic(); private Gallery_box_w_fmtr_arg__hdump box_w_fmtr__hdump = new Gallery_box_w_fmtr_arg__hdump();
private Gallery_img_pad_fmtr_arg__basic img_pad_fmtr__basic = new Gallery_img_pad_fmtr_arg__basic(); private Gallery_img_pad_fmtr_arg__hdump img_pad_fmtr__hdump = new Gallery_img_pad_fmtr_arg__hdump();
public abstract byte Tid();
public abstract byte[] Tid_bry();
@gplx.Virtual public boolean Tid_is_packed() {return false;}
public int Itm_default_w() {return itm_default_w;} protected int itm_default_w;
public int Itm_default_h() {return itm_default_h;} protected int itm_default_h;
public int Itms_per_row() {return itms_per_row;} @gplx.Virtual public void Itms_per_row_(int v) {this.itms_per_row = v;} protected int itms_per_row;
@gplx.Virtual public int Get_thumb_padding() {return 30;} // REF.MW: getThumbPadding; How much padding such the thumb have between image and inner div that that contains the border. This is both for verical and horizontal padding. (However, it is cut in half in the vertical direction).
@gplx.Virtual public int Get_gb_padding() {return 5;} // REF.MW: getGBPadding; GB stands for gallerybox (as in the <li class="gallerybox"> element)
@gplx.Virtual public int Get_gb_borders() {return 8;} // REF.MW: getGBBorders; Get how much extra space the borders around the image takes up. For this mode, it is 2px borders on each side + 2px implied padding on each side from the stylesheet, giving us 2*2+2*2 = 8.
@gplx.Virtual public int Get_all_padding() {return this.Get_thumb_padding() + this.Get_gb_padding() + this.Get_gb_borders();} // REF.MW: getAllPadding; How many pixels of whitespace surround the thumbnail.
@gplx.Virtual public int Get_vpad(int itm_h, int thm_h) { // REF.MW: getVPad; Get vertical padding for a thumbnail; Generally this is the total height minus how high the thumb is.
return (this.Get_thumb_padding() + itm_h - thm_h) / 2;
}
@gplx.Virtual public int Get_thumb_div_width(int thm_w) { // REF.MW: getThumbDivWidth; Get the width of the inner div that contains the thumbnail in question. This is the div with the class of "thumb".
return itm_default_w + this.Get_thumb_padding();
}
@gplx.Virtual public int Get_gb_width(int thm_w, int thm_h) {// REF.MW: getGBWidth; Width of gallerybox <li>. Generally is the width of the image, plus padding on image plus padding on gallerybox.s
return itm_default_w + this.Get_thumb_padding() + this.Get_gb_padding();
}
@gplx.Virtual public void Get_modules(Xoae_page page) {} // REF.MW: getModules; Get a list of modules to include in the page.
@gplx.Virtual public void Init(int itms_per_row, int itm_default_w, int itm_default_h) {
this.itms_per_row = itms_per_row;
this.itm_default_w = itm_default_w;
this.itm_default_h = itm_default_h;
}
@gplx.Virtual public void Wrap_gallery_text(Bry_bfr bfr, byte[] gallery_text, int thm_w, int thm_h) {
bfr .Add(Wrap_gallery_text_bgn)
.Add(gallery_text)
.Add(Wrap_gallery_text_end)
;
}
public void Write_html(Bry_bfr bfr, Xowe_wiki wiki, Xoae_page page, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Gallery_xnde xnde) {
boolean hctx_is_hdump = hctx.Mode_is_hdump();
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
byte[] box_style = xnde.Atr_style();
int gallery_uid = page.Html_data().Xtn_gallery_next_id();
if (itms_per_row > 0) {
int max_width = itms_per_row * (itm_default_w + this.Get_all_padding());
box_style = Fmt_and_add(tmp_bfr, box_style_max_width_fmtr, box_style, max_width);
page.Hdump_data().Imgs_add(new Xohd_data_itm__gallery_mgr(gallery_uid, max_width));
}
byte[] box_cls = Fmt_and_add(tmp_bfr, box_cls_fmtr, xnde.Atr_cls(), this.Tid_bry());
byte[] gallery_ul_id = tmp_bfr.Add(box_id_prefix_bry).Add_int_variable(gallery_uid).Xto_bry_and_clear();
Box_hdr_write(bfr, wiki.Appe().Html_mgr().Whitelist_mgr(), src, gallery_ul_id, box_cls, box_style, xnde.Atrs_other(), hctx_is_hdump, gallery_uid);
byte[] box_caption = xnde.Atr_caption();
if (Bry_.Len_gt_0(box_caption)) box_caption_fmtr.Bld_bfr_many(bfr, box_caption);
Xoae_app app = wiki.Appe(); Xoh_html_wtr html_wtr = wiki.Html_mgr().Html_wtr();
int itm_len = xnde.Itms_len();
for (int i = 0; i < itm_len; i++) {
Write_html_itm(bfr, tmp_bfr, app, wiki, page, ctx, html_wtr, hctx, src, xnde, gallery_ul_id, i, null, hctx_is_hdump);
}
bfr.Add(box_html_end_bry);
tmp_bfr.Mkr_rls();
} private static final byte[] box_id_prefix_bry = Bry_.new_a7("xowa_gallery_ul_"), itm_id_prefix_bry = Bry_.new_a7("xowa_gallery_li_");
public static byte File_found_mode = Bool_.__byte;
public void Write_html_itm(Bry_bfr bfr, Bry_bfr tmp_bfr, Xoae_app app, Xowe_wiki wiki, Xoae_page page, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, byte[] src, Gallery_xnde xnde, byte[] gallery_ul_id, int i, Xof_file_itm xfer_itm, boolean hctx_is_hdump) {
Gallery_itm itm = (Gallery_itm)xnde.Itms_get_at(i);
Xoa_ttl ttl = itm.Ttl();
byte[] itm_caption = itm.Caption_bry(); if (itm_caption == null) itm_caption = Bry_.Empty;
Xop_lnki_tkn lnki = itm.Lnki_tkn();
int lnki_w_orig = lnki.W(), lnki_h_orig = lnki.H(); // store orig lnki_w / lnki_w
this.Get_thumb_size(lnki, itm.Ext()); // packed=expand by 1.5;
if (xfer_itm == null) { // will be null on 1st pass
xfer_itm = html_wtr.Lnki_wtr().File_wtr().Lnki_eval(Xof_exec_tid.Tid_wiki_page, ctx, page, lnki);
xfer_itm.Html_gallery_mgr_h_(xnde.Itm_h_or_default());
xfer_itm.Html_elem_tid_(Xof_html_elem.Tid_gallery_v2);
}
int img_uid = xfer_itm.Html_uid();
byte[] gallery_li_id = tmp_bfr.Add(itm_id_prefix_bry).Add_int_variable(img_uid).Xto_bry_and_clear();
byte[] itm_html = Bry_.Empty;
int html_w_expand = xfer_itm.Html_w();
int html_h_expand = xfer_itm.Html_h();
boolean file_found = xfer_itm.File_exists();
if (File_found_mode != Bool_.__byte)
file_found = File_found_mode == Bool_.Y_byte;
int vpad = -1, img_div_w = -1;
if ( !hctx_is_hdump // always write img if hdump; DATE:2015-04-27
&& ( !ttl.Ns().Id_file()
|| !file_found
)
) { // itm is not a file, or is not found; write text
itm_html = itm_missing_fmtr.Bld_bry_many(tmp_bfr, this.Get_thumb_padding() + itm_default_h, ttl.Page_txt());
itm.Html_prepare(wiki, ctx, src, xnde, xfer_itm, gallery_li_id, i);
xfer_itm.Html_img_wkr_(itm);
lnki.W_(lnki_w_orig).H_(lnki_h_orig);
html_w_expand = lnki_w_orig; html_h_expand = lnki_h_orig; // reset lnki_w_orig / lnki_h_orig else large captions
}
else {
byte[] alt = itm.Alt_bgn() == Bry_.NotFound && Bry_.Len_eq_0(itm_caption) // if ( $alt == '' && $text == '' ) $imageParameters['alt'] = $nt->getText();
? itm.Ttl().Page_txt()
: Xoh_html_wtr_escaper.Escape(app.Parser_amp_mgr(), tmp_bfr, Bry_.Mid(src, itm.Alt_bgn(), itm.Alt_end()))
;
Xoa_ttl href_ttl = itm.Link_bgn() == Bry_.NotFound
? ttl
: Xoa_ttl.parse_(wiki, Bry_.Mid(src, itm.Link_bgn(), itm.Link_end()))
;
if (href_ttl == null) href_ttl = ttl; // occurs when link is invalid; EX: A.png|link=<invalid>
this.Adjust_image_parameters(xfer_itm); // trad=noop; packed=reduce by 1.5
int html_w_normal = xfer_itm.Html_w();
int html_h_normal = xfer_itm.Html_h();
xfer_itm.Init_at_gallery_bgn(html_w_normal, html_h_normal, html_w_expand);// NOTE: file_w should be set to expanded width so js can resize if gallery
img_div_w = this.Get_thumb_div_width(html_w_expand);
itm_div0_fmtr.Bld_bfr_many(tmp_bfr, img_div_w);
Gallery_img_pad_fmtr_arg vpad_fmtr = hctx_is_hdump ? (Gallery_img_pad_fmtr_arg)img_pad_fmtr__hdump : (Gallery_img_pad_fmtr_arg)img_pad_fmtr__basic;
vpad = this.Get_vpad(itm_default_h, html_h_expand);
itm_div1_fmtr.Bld_bfr_many(tmp_bfr, vpad_fmtr.Init(img_uid, vpad)); // <div style="margin:~{vpad}px auto;">
wiki.Html_mgr().Html_wtr().Lnki_wtr().Write_file(tmp_bfr, ctx, hctx, src, lnki, xfer_itm, alt);
tmp_bfr.Add(itm_divs_end_bry);
itm_html = tmp_bfr.Xto_bry_and_clear();
}
byte[] show_filenames_link = Bry_.Empty;
if (xnde.Show_filename()) {
wiki.Html_mgr().Html_wtr().Lnki_wtr().Write_plain_by_bry
( tmp_bfr, src, lnki
, Bry_.Limit(ttl.Page_txt(), 25) // 25 is defined by captionLength in DefaultSettings.php
); // MW:passes know,noclasses which isn't relevant to XO
}
int itm_div_width = this.Get_gb_width(html_w_expand, html_h_expand);
Gallery_box_w_fmtr_arg box_w_fmtr_arg = hctx_is_hdump ? (Gallery_box_w_fmtr_arg)box_w_fmtr__hdump : (Gallery_box_w_fmtr_arg)box_w_fmtr__basic;
itm_li_bgn_fmtr.Bld_bfr_many(bfr, gallery_li_id, box_w_fmtr_arg.Init(img_uid, itm_div_width));
bfr.Add(itm_html);
wiki.Parser().Parse_text_to_html(tmp_bfr, page, true, itm_caption);
itm_caption = tmp_bfr.Xto_bry_and_clear();
itm_caption = tmp_bfr.Add(show_filenames_link).Add(itm_caption).Xto_bry_and_clear();
Wrap_gallery_text(bfr, itm_caption, html_w_expand, html_h_expand);
bfr.Add(itm_li_end_bry);
if (hctx_is_hdump)
page.Hdump_data().Imgs_add_img(new Xohd_data_itm__gallery_itm().Data_init_gallery(itm_div_width, img_div_w, vpad), xfer_itm, Xohd_data_itm__gallery_itm.Tid_gallery);
}
private static final byte[]
Wrap_gallery_text_bgn = Bry_.new_a7("\n <div class=\"gallerytext\">") // NOTE: The newline after <div class="gallerytext"> is needed to accommodate htmltidy
, Wrap_gallery_text_end = Bry_.new_a7("\n </div>") // NOTE: prepend "\n"; will cause extra \n when caption exists, but needed when caption doesn't exists; EX: "<div class='caption'> </div>"; \n puts
;
@gplx.Virtual public void Get_thumb_size(Xop_lnki_tkn lnki, Xof_ext ext) { // REF.MW: getThumbParams; Get the transform parameters for a thumbnail.
lnki.W_(itm_default_w);
lnki.H_(itm_default_h);
}
@gplx.Virtual public void Adjust_image_parameters(Xof_file_itm xfer_itm) {} // REF.MW: Adjust the image parameters for a thumbnail. Used by a subclass to insert extra high resolution images.
public static final Bry_fmtr
box_style_max_width_fmtr = Bry_fmtr.new_( "max-width:~{max_width}px;_width:~{max_width}px;", "max_width") // id=xowa_gallery_ul_1
, box_cls_fmtr = Bry_fmtr.new_( "gallery mw-gallery-~{mode}", "mode")
, box_caption_fmtr = Bry_fmtr.new_( "\n <li class='gallerycaption'>~{caption}</li>", "caption")
, itm_li_bgn_fmtr = Bry_fmtr.new_( "\n <li id=\"~{id}\" class=\"gallerybox\" ~{itm_box_w}>" // id=xowa_gallery_li_1
+ "\n <div ~{itm_box_w}>", "id", "itm_box_w")
, itm_div0_fmtr = Bry_fmtr.new_( "\n <div class=\"thumb\" style=\"width: ~{width}px;\">", "width")
, itm_missing_fmtr = Bry_fmtr.new_( "\n <div class=\"thumb\" style=\"height: ~{height}px;\">~{ttl_text}</div>", "height", "ttl_text")
, itm_div1_fmtr = Bry_fmtr.new_( "\n <div ~{vpad}>\n ", "vpad")
, hdump_box_w_fmtr = Bry_fmtr.new_( "width:~{width}px;", "width")
, hdump_img_pad_fmtr = Bry_fmtr.new_( "margin:~{width}px auto;", "width")
;
private static final byte[]
itm_li_end_bry = Bry_.new_a7 ( "\n </div>"
+ "\n </li>")
, box_html_end_bry = Bry_.new_a7 ( "\n</ul>")
, itm_divs_end_bry = Bry_.new_a7 ( "\n </div>\n </div>")
;
private static byte[] Fmt_and_add(Bry_bfr tmp_bfr, Bry_fmtr fmtr, byte[] trailer, Object... fmtr_args) {
fmtr.Bld_bfr_many(tmp_bfr, fmtr_args);
if (Bry_.Len_gt_0(trailer)) {
tmp_bfr.Add_byte_space();
tmp_bfr.Add(trailer);
}
return tmp_bfr.Xto_bry_and_clear();
}
private static void Box_hdr_write(Bry_bfr bfr, Xop_xatr_whitelist_mgr whitelist_mgr, byte[] src, byte[] gallery_ul_uid, byte[] cls, byte[] style, List_adp xatr_list, boolean hctx_is_hdump, int uid) {
bfr.Add_byte(Byte_ascii.Lt).Add(Html_tag_.Ul_name_bry);
Html_wtr.Write_atr_bry(bfr, Html_atr_.Id_bry, gallery_ul_uid);
Html_wtr.Write_atr_bry(bfr, Html_atr_.Cls_bry, cls);
if (hctx_is_hdump) {
bfr.Add_byte_space();
bfr.Add(Xohd_abrv_.Key_gallery_box_max);
bfr.Add_int_variable(uid);
bfr.Add_byte_apos();
}
else
Html_wtr.Write_atr_bry(bfr, Html_atr_.Style_bry, style);
if (xatr_list != null) {
int len = xatr_list.Count();
for (int i = 0; i < len; i++) {
Xop_xatr_itm xatr = (Xop_xatr_itm)xatr_list.Get_at(i);
if (!whitelist_mgr.Chk(Xop_xnde_tag_.Tid_ul, src, xatr)) continue;
byte[] key = xatr.Key_bry();
byte[] val = xatr.Val_as_bry(src);
Html_wtr.Write_atr_bry(bfr, key, val);
}
}
bfr.Add_byte(Byte_ascii.Gt);
}
}
class Gallery_mgr_traditional extends Gallery_mgr_base {
@Override public byte Tid() {return Gallery_mgr_base_.Traditional_tid;}
@Override public byte[] Tid_bry() {return Gallery_mgr_base_.Traditional_bry;}
}
class Gallery_mgr_nolines extends Gallery_mgr_base {
@Override public byte Tid() {return Gallery_mgr_base_.Nolines_tid;}
@Override public byte[] Tid_bry() {return Gallery_mgr_base_.Nolines_bry;}
@Override public int Get_thumb_padding() {return 0;}
@Override public int Get_gb_padding() {return 4;} // This accounts for extra space between <li> elements.
@Override public int Get_vpad(int itm_h, int thm_h) {return 0;}
}

View File

@@ -0,0 +1,64 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
class Gallery_mgr_base_ {
public static byte Get_or_traditional(byte[] bry) {
Byte_obj_val rv = (Byte_obj_val)Hash.Get_by(bry);
return rv == null ? Traditional_tid : rv.Val();
}
public static Gallery_mgr_base New_by_mode(byte mode) {
switch (mode) {
default:
case Traditional_tid: return new Gallery_mgr_traditional();
case Nolines_tid: return new Gallery_mgr_nolines();
case Packed_tid: return new Gallery_mgr_packed_base();
case Packed_hover_tid: return new Gallery_mgr_packed_hover();
case Packed_overlay_tid: return new Gallery_mgr_packed_overlay();
}
}
public static boolean Mode_is_packed(byte v) {
switch (v) {
case Packed_tid:
case Packed_hover_tid:
case Packed_overlay_tid: return true;
default: return false;
}
}
public static final byte
Traditional_tid = 0
, Nolines_tid = 1
, Packed_tid = 2
, Packed_hover_tid = 3
, Packed_overlay_tid = 4
;
public static final byte[]
Traditional_bry = Bry_.new_a7("traditional")
, Nolines_bry = Bry_.new_a7("nolines")
, Packed_bry = Bry_.new_a7("packed")
, Packed_hover_bry = Bry_.new_a7("packed-hover")
, Packed_overlay_bry = Bry_.new_a7("packed-overlay")
;
private static final Hash_adp_bry Hash = Hash_adp_bry.ci_ascii_()
.Add_bry_byte(Traditional_bry , Traditional_tid)
.Add_bry_byte(Nolines_bry , Nolines_tid)
.Add_bry_byte(Packed_bry , Packed_tid)
.Add_bry_byte(Packed_hover_bry , Packed_hover_tid)
.Add_bry_byte(Packed_overlay_bry , Packed_overlay_tid)
;
}

View File

@@ -0,0 +1,170 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
import gplx.xowa.html.*; import gplx.xowa.files.fsdb.*;
public class Gallery_mgr_base_basic_tst {
private Gallery_mgr_base_fxt fxt = new Gallery_mgr_base_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic() {
fxt.Test_html_str(String_.Concat_lines_nl_skip_last
( "<gallery widths=200px heights=300px>"
, "A.png|''a1''"
, "B.png|''b1''"
, "</gallery>"
), String_.Concat_lines_nl_skip_last
( "<ul id=\"xowa_gallery_ul_0\" class=\"gallery mw-gallery-traditional\">"
, " <li id=\"xowa_gallery_li_0\" class=\"gallerybox\" style=\"width: 235px\">"
, " <div style=\"width: 235px\">"
, " <div class=\"thumb\" style=\"width: 230px;\">"
, " <div style=\"margin:15px auto;\">"
, " <a href=\"/wiki/File:A.png\" class=\"image\" xowa_title=\"A.png\"><img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/200px.png\" width=\"200\" height=\"300\" /></a>"
, " </div>"
, " </div>"
, " <div class=\"gallerytext\"><p><i>a1</i>"
, "</p>"
, ""
, " </div>"
, " </div>"
, " </li>"
, " <li id=\"xowa_gallery_li_1\" class=\"gallerybox\" style=\"width: 235px\">"
, " <div style=\"width: 235px\">"
, " <div class=\"thumb\" style=\"width: 230px;\">"
, " <div style=\"margin:15px auto;\">"
, " <a href=\"/wiki/File:B.png\" class=\"image\" xowa_title=\"B.png\"><img id=\"xowa_file_img_1\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/5/7/B.png/200px.png\" width=\"200\" height=\"300\" /></a>"
, " </div>"
, " </div>"
, " <div class=\"gallerytext\"><p><i>b1</i>"
, "</p>"
, ""
, " </div>"
, " </div>"
, " </li>"
, "</ul>"
));
fxt.Test_html_modules_js("");
}
@Test public void Tmpl() {
fxt.Fxt().Init_defn_add("test_tmpl", "b");
fxt.Test_html_frag("<gallery>File:A.png|a{{test_tmpl}}c</gallery>", "<div class=\"gallerytext\"><p>abc\n</p>");
}
@Test public void Itm_defaults_to_120() {
fxt.Test_html_frag("<gallery>File:A.png|a</gallery>", "<img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/120px.png\" width=\"120\" height=\"120\" />");
}
@Test public void Height_fix() {
fxt.Fxt().Wiki().File_mgr().Cfg_set(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_gallery_fix_defaults, "y");
fxt.Test_html_frag("<gallery heights=250>File:A.png|a<br/>c</gallery>", " width=\"120\" height=\"250\"");
fxt.Fxt().Wiki().File_mgr().Cfg_set(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_gallery_fix_defaults, "n");
}
@Test public void Alt() {
fxt.Test_html_frag("<gallery>File:A.png|b|alt=c</gallery>"
, "<img id=\"xowa_file_img_0\" alt=\"c\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/120px.png\" width=\"120\" height=\"120\" />"
, "<div class=\"gallerytext\"><p>b\n</p>"
);
}
@Test public void Link() {
fxt.Test_html_frag("<gallery>File:A.png|b|link=c</gallery>", "<a href=\"/wiki/C\" class=\"image\"");
}
@Test public void Page() { // PURPOSE: page was not being set; PAGE:pt.s:Portal:Diccionario_geographico_do_Brazil; DATE:2015-04-16
fxt.Test_html_frag
( "<gallery>File:A.pdf|b|page=8</gallery>"
, "A.pdf/120px-8.jpg" // make sure page 8 shows up
);
}
@Test public void Alt_caption_multiple() {
fxt.Test_html_frag("<gallery>File:A.png|alt=b|c[[d|e]]f</gallery>", "<div class=\"gallerytext\"><p>c<a href=\"/wiki/D\">ef</a>\n</p>");
}
@Test public void Alt_escape_quote() {
fxt.Test_html_frag("<gallery>File:A.png|b|alt=c\"d'e</gallery>", "alt=\"c&quot;d'e\"");
}
@Test public void Caption_null() { // PURPOSE: null caption causes page to fail; EX: de.w:Lewis Caroll; <gallery>Datei:A.png</gallery>; DATE:2013-10-09
fxt.Test_html_frag("<gallery>File:A.png</gallery>", "<div class=\"gallerytext\">\n");
}
@Test public void Ttl_has_no_ns() { // PURPOSE: MW allows ttl to not have ns; DATE: 2013-11-18
fxt.Test_html_frag("<gallery>A.png|b</gallery>", "<img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/120px.png\" width=\"120\" height=\"120\" />"); // make sure image is generated
}
@Test public void Ref() { // PURPOSE: <ref> inside <gallery> was not showing up in <references>; DATE:2013-10-09
fxt.Test_html_frag("<gallery>File:A.png|<ref name='a'>b</ref></gallery><references/>"
, "<div class=\"gallerytext\"><p><sup id=\"cite_ref-a_0-0\" class=\"reference\"><a href=\"#cite_note-a-0\">[1]</a></sup>\n</p>"
, String_.Concat_lines_nl
( "</ul><ol class=\"references\">"
, "<li id=\"cite_note-a-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-a_0-0\">^</a></span> <span class=\"reference-text\">b</span></li>"
, "</ol>"
)
);
}
@Test public void Packed() {
fxt.Test_html_frag("<gallery mode=packed heights=300px>File:A.png|a</gallery>", "<ul id=\"xowa_gallery_ul_0\" class=\"gallery mw-gallery-packed\">");
fxt.Test_html_modules_js(String_.Concat_lines_nl_skip_last
( ""
, " <script type='text/javascript'>"
, " var xowa_global_values = {"
, " 'gallery-packed-enabled' : true,"
, " }"
, " </script>"
));
}
@Test public void Missing() {
fxt.Init_files_missing_y_();
fxt.Test_html_frag("<gallery>File:A.png|b</gallery>", "<div class=\"thumb\" style=\"height: 150px;\">A.png</div>");
}
@Test public void Multiple() { // PURPOSE.bug: multiple galleries should not use same gallery super; DATE:2014-04-13
fxt.Test_html_frag("<gallery>File:A.png|a</gallery><gallery widths=180px>File:B.png|b</gallery>"
, "src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/120px.png\" width=\"120\" height=\"120\" />" // should not be 180px from gallery #2
);
}
@Test public void Link_is_empty() { // PURPOSE: "link=" causes null pointer exception; DATE:2014-06-15
fxt.Test_html_frag("<gallery>File:A.png|link=</gallery>", "href=\"/wiki/File:A.png\"");
}
@Test public void Dangling_autcloses() { // PURPOSE: dangling gallery should auto-close, not escape; PAGE:en.w:Wikipedia:Featured_pictures_thumbs_43 DATE:2014-08-23
fxt.Test_html_frag("<gallery>File:A.png|b", "<ul id=\"xowa_gallery_ul_0\"");
}
@Test public void Nested() { // PURPOSE: handle gallery nested inside ref; PAGE: es.w:Arquitectura_medieval DATE:2015-07-10
fxt.Test_html_frag(String_.Concat_lines_nl_skip_last
( "<gallery>"
, "File:A.jpg|A1"
, "File:B.jpg|B1 <ref>B2 <gallery>File:B11.jpg|B123./gallery></ref>" // NOTE: nested gallery
, "File:C.jpg|C1"
, "</gallery>"
), "C1" // make sure that image after nested gallery appears
);
}
// @Test public void Ttl_caption() { // TODO: category entries get rendered with name only (no ns)
// fxt.Test_html_frag
// ( "<gallery>Category:A</gallery>"
// , "<li class='gallerycaption'>B</li>"
// );
// }
}
class Gallery_mgr_base_fxt {
public void Reset() {
fxt.Wiki().Xtn_mgr().Init_by_wiki(fxt.Wiki());
Gallery_mgr_base.File_found_mode = Bool_.Y_byte;
}
public Xop_fxt Fxt() {return fxt;} private Xop_fxt fxt = new Xop_fxt();
public void Init_files_missing_y_() {
Gallery_mgr_base.File_found_mode = Bool_.N_byte;
}
public void Test_html_str(String raw, String expd) {fxt.Test_html_full_str(raw, expd);}
public void Test_html_frag(String raw, String... expd_frags) {fxt.Test_html_full_frag(raw, expd_frags);} // TODO: change to wiki_str; currently uids do not get reset if wiki
public void Test_html_frag_n(String raw, String... expd_frags) {fxt.Test_html_full_frag_n(raw, expd_frags);}
public void Test_html_modules_js(String expd) {
fxt.Page().Html_data().Module_mgr().Itm__globals().Enabled_n_();
fxt.Test_html_modules_js(expd);
}
}

View File

@@ -0,0 +1,66 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
import gplx.xowa.html.*;
public class Gallery_mgr_base_xnde_atrs_tst {
private Gallery_mgr_base_fxt fxt = new Gallery_mgr_base_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Atr_misc() {// PURPOSE: add other atrs to end of ul
fxt.Test_html_frag
( "<gallery id=a>File:A.png</gallery>"
, "<ul id=\"xowa_gallery_ul_0\" class=\"gallery mw-gallery-traditional\" id=\"a\">"
);
}
@Test public void Atr_style() { // PURPOSE: combine style with itms_per_row
fxt.Test_html_frag
( "<gallery perrow=2 style='color:blue;'>File:A.png</gallery>"
, "<ul id=\"xowa_gallery_ul_0\" class=\"gallery mw-gallery-traditional\" style=\"max-width:326px;_width:326px; color:blue;\">"
);
}
@Test public void Atr_caption() { // PURPOSE: caption atr adds new element
fxt.Test_html_frag
( "<gallery caption=B>File:A.png</gallery>"
, "<li class='gallerycaption'>B</li>"
);
}
@Test public void Atr_caption_ignore() { // PURPOSE: blank caption should not create caption element; PAGE:fr.w:Chronologie_du_si<73>ge_de_Paris_(1870) DATE:2014-08-15
fxt.Test_html_frag_n
( "<gallery caption=>File:A.png</gallery>"
, "<li class='gallerycaption'>"
);
}
@Test public void Atr_show_filename() { // PURPOSE: show filename
fxt.Test_html_frag
( "<gallery showfilename=true>A.png</gallery>"
, "<div class=\"gallerytext\"><a href=\"/wiki/File:A.png\">File:A.png</a>"
);
}
@Test public void Atr_whitelist() { // PURPOSE: ignore atrs not in whitelist
fxt.Test_html_frag
( "<gallery onmouseover='alert();'>A.png</gallery>"
, "<ul id=\"xowa_gallery_ul_0\" class=\"gallery mw-gallery-traditional\">"
);
}
// @Test public void Ttl_caption() { // TODO: PURPOSE: category entries get rendered with name only (no ns)
// fxt.Test_html_frag
// ( "<gallery>Category:A</gallery>"
// , "<li class='gallerycaption'>B</li>"
// );
// }
}

View File

@@ -0,0 +1,84 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.files.*; import gplx.xowa.html.modules.*;
public class Gallery_mgr_packed_base extends Gallery_mgr_base {
@Override public byte Tid() {return Gallery_mgr_base_.Packed_tid;}
@Override public byte[] Tid_bry() {return Gallery_mgr_base_.Packed_bry;}
@Override public void Init(int itms_per_row, int itm_default_w, int itm_default_h) {
this.itms_per_row = 0; // Does not support per row option.
this.itm_default_w = itm_default_w;
this.itm_default_h = itm_default_h;
}
@Override public void Itms_per_row_(int v) {}
@Override public void Get_modules(Xoae_page page) {
page.Html_data().Module_mgr().Itm__gallery().Enabled_y_();
}
@Override public int Get_thumb_padding() {return 0;}
@Override public int Get_gb_padding() {return 2;}
@Override public int Get_vpad(int itm_h, int thm_h) {
return (int)((this.Get_thumb_padding() + itm_h - thm_h / Scale_factor) / 2);
}
@Override public int Get_thumb_div_width(int thm_w) {
if (thm_w < Scale_factor_x_60)
thm_w = Scale_factor_x_60; // Require at least 60px wide, so caption is wide enough to work.
return (int)(thm_w / Scale_factor) + this.Get_thumb_padding();
}
@Override public int Get_gb_width(int thm_w, int thm_h) {
int val = thm_w == -1 ? (int)(itm_default_w * Scale_factor) : thm_w;
return Get_thumb_div_width(val) + this.Get_gb_padding();
}
@Override public void Get_thumb_size(Xop_lnki_tkn lnki, Xof_ext ext) {
Get_thumb_size_static(lnki, ext, itm_default_w, itm_default_h);
}
@Override public void Adjust_image_parameters(Xof_file_itm xfer_itm) {
int w = (int)(xfer_itm.Html_w() / Scale_factor);
int h = (int)(xfer_itm.Html_h() / Scale_factor);
xfer_itm.Html_size_(w, h);
}
public static final double Scale_factor = 1.5d; // We artificially have 1.5 the resolution neccessary so that we can scale it up by that much on the client side, without worrying about requesting a new image.
private static final int Scale_factor_x_60 = (int)(Scale_factor * 60);
public static void Get_thumb_size_static(Xop_lnki_tkn lnki, Xof_ext ext, int itm_default_w, int itm_default_h) {
int w;
if (ext.Id_is_audio())
w = itm_default_w;
else
w = (itm_default_h) * 10 + 100; // We want the width not to be the constraining factor, so use random big number.
lnki.W_((int)(Scale_factor * w));
lnki.H_((int)(Scale_factor * itm_default_h));
}
}
class Gallery_mgr_packed_overlay extends Gallery_mgr_packed_base {
@Override public byte[] Tid_bry() {return Gallery_mgr_base_.Packed_overlay_bry;}
@Override public void Wrap_gallery_text(Bry_bfr bfr, byte[] gallery_text, int thm_w, int thm_h) {
if (gallery_text.length == 0) return; // If we have no text, do not output anything to avoid ugly white overlay.
int img_w = this.Get_gb_width(thm_w, thm_h) - this.Get_thumb_padding() - this.Get_gb_padding();
int caption_w = (img_w - 20);
bfr .Add(Wrap_gallery_text_0).Add_int_variable(caption_w)
.Add(Wrap_gallery_text_1).Add(gallery_text)
.Add(Wrap_gallery_text_2)
;
}
private static final byte[]
Wrap_gallery_text_0 = Bry_.new_a7("\n <div class=\"gallerytextwrapper\" style=\"width: ")
, Wrap_gallery_text_1 = Bry_.new_a7("px\"><div class=\"gallerytext\">\n") // NOTE: The newline after <div class="gallerytext"> is needed to accommodate htmltidy
, Wrap_gallery_text_2 = Bry_.new_a7("\n </div></div>") // NOTE: 2nd </div> is not part of MW, but needed to close div
;
}
class Gallery_mgr_packed_hover extends Gallery_mgr_packed_overlay { @Override public byte[] Tid_bry() {return Gallery_mgr_base_.Packed_hover_bry;}
}

View File

@@ -0,0 +1,129 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*; import gplx.dbs.cfgs.*;
import gplx.fsdb.meta.*;
import gplx.xowa.parsers.logs.*;
import gplx.xowa.html.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
public class Gallery_xnde implements Xox_xnde, Xop_xnde_atr_parser {
private Gallery_xtn_mgr xtn_mgr;
public byte Mode() {return mode;} private byte mode;
public int Itm_w() {return itm_w;} private int itm_w = Null;
public int Itm_h() {return itm_h;} private int itm_h = Null;
public int Itms_per_row() {return itms_per_row;} private int itms_per_row = Null;
public boolean Show_filename() {return show_filename;} private boolean show_filename = false;
public byte[] Atr_caption() {return atr_caption;} private byte[] atr_caption = Bry_.Empty;
public byte[] Atr_style() {return atr_style;} private byte[] atr_style = Bry_.Empty;
public byte[] Atr_cls() {return atr_cls;} private byte[] atr_cls = Bry_.Empty;
public List_adp Atrs_other() {return atrs_other;} private List_adp atrs_other;
public int Itm_w_or_default() {return itm_w == Null ? Default : itm_w;}
public int Itm_h_or_default() {return itm_h == Null ? Default : itm_h;}
public int Itms_len() {return itms.Count();} private List_adp itms = List_adp_.new_();
public Gallery_itm Itms_get_at(int i) {return (Gallery_itm)itms.Get_at(i);}
public Gallery_mgr_base Gallery_mgr() {return gallery_mgr;} private Gallery_mgr_base gallery_mgr;
private boolean html_wtr_v1 = false;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {
if (xatr_key_obj != null) {
Byte_obj_val xatr_key = (Byte_obj_val)xatr_key_obj;
switch (xatr_key.Val()) {
case Gallery_xnde_atrs.Mode_tid: mode = Gallery_mgr_base_.Get_or_traditional(xatr.Val_as_bry(src)); break;
case Gallery_xnde_atrs.Perrow_tid: itms_per_row = xatr.Val_as_int_or(src, Null); break;
case Gallery_xnde_atrs.Widths_tid: itm_w = xatr.Val_as_int_or(src, Null); break;
case Gallery_xnde_atrs.Heights_tid: itm_h = xatr.Val_as_int_or(src, Null); break;
case Gallery_xnde_atrs.Showfilename_tid: show_filename = xatr.Val_as_bool(src); break;
case Gallery_xnde_atrs.Caption_tid: if (!xatr.Tid_is_key_only()) atr_caption = xatr.Val_as_bry(src); break; // NOTE: do not create caption for key only; EX:<gallery caption=> PAGE:fr.w:Chronologie_du_si<73>ge_de_Paris_(1870); DATE:2014-08-15
case Gallery_xnde_atrs.Style_tid: atr_style = xatr.Val_as_bry(src); break;
case Gallery_xnde_atrs.Class_tid: atr_cls = xatr.Val_as_bry(src); break;
}
}
else {
if (atrs_other == null) atrs_other = List_adp_.new_();
atrs_other.Add(xatr);
}
}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
try {
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_bgn); // cancel pre for <gallery>; DATE:2014-03-11
Xop_xatr_itm.Xatr_parse(wiki.Appe(), this, Gallery_xnde_atrs.Key_hash, wiki, src, xnde);
xtn_mgr = (Gallery_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Gallery_xtn_mgr.XTN_KEY);
Init_atrs(wiki);
gallery_mgr.Get_modules(ctx.Cur_page());
Gallery_itm_parser parser = xtn_mgr.Parser();
if (parser.Parse_in_progress()) parser = new Gallery_itm_parser().Init_by_wiki(wiki); // handle nested galleries; EX: <gallery><ref><gallery>; PAGE:es.w:Arquitectura_medieval DATE:2015-07-10
parser.Parse_all(itms, gallery_mgr, this, src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
boolean log_wkr_enabled = Log_wkr != Xop_log_basic_wkr.Null; if (log_wkr_enabled) Log_wkr.Log_end_xnde(ctx.Cur_page(), Xop_log_basic_wkr.Tid_gallery, src, xnde);
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end); // cancel pre for <gallery>; DATE:2014-03-11
} catch (Exception exc) {
wiki.Appe().Usr_dlg().Warn_many("", "", "failed to write gallery; src=~{0} err=~{1}", String_.new_u8(src, xnde.Src_bgn(), xnde.Src_end()), Err_.Message_gplx(exc));
}
} public static Xop_log_basic_wkr Log_wkr = Xop_log_basic_wkr.Null;
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
Xowe_wiki wiki = ctx.Wiki();
try {
if (html_wtr_v1)
xtn_mgr.Html_wtr().Write_html(bfr, app, wiki, ctx, html_wtr, hctx, ctx.Cur_page(), this, src);
else {
gallery_mgr.Write_html(bfr, wiki, ctx.Cur_page(), ctx, hctx, src, this);
}
} catch (Exception exc) {
wiki.Appe().Usr_dlg().Warn_many("", "", "failed to write gallery; src=~{0} err=~{1}", String_.new_u8(src, xnde.Src_bgn(), xnde.Src_end()), Err_.Message_gplx(exc));
}
}
private void Init_atrs(Xowe_wiki wiki) {
Db_cfg_hash cfg_grp = wiki.File_mgr().Cfg_get(Xof_fsdb_mgr_cfg.Grp_xowa);
if (cfg_grp.Get(Xof_fsdb_mgr_cfg.Key_gallery_fix_defaults).To_yn_or_n()) {
if (itm_w == Gallery_xnde.Null && itm_h == Gallery_xnde.Null) // if no w/h specified, set both to default (just like v1)
itm_w = itm_h = Gallery_xnde.Default;
}
else {
if (itm_w == Gallery_xnde.Null) itm_w = Gallery_xnde.Default;
if (itm_h == Gallery_xnde.Null) itm_h = Gallery_xnde.Default;
}
gallery_mgr = Gallery_mgr_base_.New_by_mode(mode);
if ( !wiki.File_mgr().Version_1_y() // v2: fsdb
&& !cfg_grp.Get(Xof_fsdb_mgr_cfg.Key_gallery_packed).To_yn_or_n() // packed not supported
) {
gallery_mgr = Gallery_mgr_base_.New_by_mode(Gallery_mgr_base_.Traditional_tid); // always go to traditional
html_wtr_v1 = true;
}
gallery_mgr.Init(itms_per_row, this.Itm_w_or_default(), this.Itm_h_or_default());
}
public static final int Default = 120, Null = -1;
}
class Gallery_xnde_atrs {
public static final byte
Mode_tid = 0
, Perrow_tid = 1
, Widths_tid = 2
, Heights_tid = 3
, Caption_tid = 4
, Showfilename_tid = 5
, Style_tid = 6
, Class_tid = 7
;
public static Hash_adp_bry Key_hash = Hash_adp_bry.ci_ascii_()
.Add_str_byte("mode" , Mode_tid)
.Add_str_byte("perrow" , Perrow_tid)
.Add_str_byte("widths" , Widths_tid)
.Add_str_byte("heights" , Heights_tid)
.Add_str_byte("caption" , Caption_tid)
.Add_str_byte("showfilename" , Showfilename_tid)
.Add_str_byte("style" , Style_tid)
.Add_str_byte("class" , Class_tid)
;
}

View File

@@ -0,0 +1,182 @@
/*
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.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Gallery_xnde_tst {
private Xop_fxt fxt = new Xop_fxt(); String raw_src;
@Before public void init() {fxt.Reset(); fxt.Wiki().Xtn_mgr().Init_by_wiki(fxt.Wiki());}
@Test public void Lnki_no_caption() {
fxt.Test_parse_page_wiki("<gallery>File:A.png</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png")
)
));
}
@Test public void Lnki_1() {
fxt.Test_parse_page_wiki("<gallery>File:A.png|b</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png")
)
));
}
@Test public void Lnki_3() {
fxt.Test_parse_page_wiki("<gallery>File:A.png|a\nFile:B.png|b\nFile:C.png|c</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png")
, new_chkr_gallery_itm().Expd_lnki_("File:B.png")
, new_chkr_gallery_itm().Expd_lnki_("File:C.png")
)
));
}
@Test public void Ignore_newLines() {
fxt.Test_parse_page_wiki("<gallery>\n\n\nFile:A.png|a\n\n\nFile:B.png|b\n\n\n</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png")
, new_chkr_gallery_itm().Expd_lnki_("File:B.png")
)
));
}
@Test public void Only_first_pipe() {
fxt.Test_parse_page_wiki("<gallery>File:A.png|File:B.png|cc</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png")
)
));
}
@Test public void Invalid_lnki() {
fxt.Test_parse_page_wiki("<gallery>A.png|cc</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png") // NOTE: MW converts "A.png" to "File:A.png"
)
));
}
@Test public void File_only_trailing_nl() {
fxt.Test_parse_page_wiki("<gallery>File:A.png\n</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png").Expd_caption_(null)
)
));
}
@Test public void Invalid_curly() {
raw_src = "a\n";
fxt.Init_log_(Xop_ttl_log.Invalid_char).Test_parse_page_wiki("<gallery>File:A.png|" + raw_src + "}}</gallery>" // NOTE: }} is ignored since it is not a valid title
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png").Expd_caption_("a")
)
));
}
@Test public void Caption() {
raw_src = "a<br/>c";
fxt.Test_parse_page_wiki("<gallery>File:A.png|" + raw_src + "</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png").Expd_caption_(raw_src)
)
));
}
@Test public void Xnde_atr() {
raw_src = "<center>a<br/>b</center>";
fxt.Test_parse_page_wiki(String_.Concat_lines_nl_skip_last
( "<gallery perrow=3>"
, "File:A.jpg|" + raw_src
, "</gallery>"
) , fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.jpg").Expd_caption_(raw_src)
)
));
}
@Test public void Err_pre() { // PURPOSE: leading ws was failing; PAGE:en.w:Vlaardingen; "\nA.jpg| <center>Visbank</center>\n"
raw_src = " <center>a</center>";
fxt.Test_parse_page_wiki(String_.Concat_lines_nl_skip_last
( "<gallery>"
, "File:A.jpg|" + raw_src
, "</gallery>"
) , fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.jpg").Expd_caption_("<center>a</center>")
)
));
}
@Test public void Err_comment() { // PURPOSE: comment was being rendered; PAGE:en.w:Perpetual motion; <!-- removed A.jpg|bcde -->
raw_src = "b";
fxt.Init_log_(Xop_ttl_log.Comment_eos).Test_parse_page_wiki(String_.Concat_lines_nl_skip_last
( "<gallery>"
, "<!-- deleted A.jpg|" + raw_src
, "</gallery>"
) , fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_()
)
);
}
@Test public void Misc_atr() { // make sure misc attribute doesn't fail
raw_src = "b";
fxt.Test_parse_page_wiki("<gallery id=a>File:A.png|" + raw_src + "</gallery>"
, fxt.tkn_xnde_().Xnde_tagId_(Xop_xnde_tag_.Tid_gallery).Xnde_xtn_
( new_chkr_gallery_mgr().Expd_subs_
( new_chkr_gallery_itm().Expd_lnki_("File:A.png").Expd_caption_(raw_src)
)
));
}
private Gallery_mgr_data_chkr new_chkr_gallery_mgr() {return new Gallery_mgr_data_chkr();}
private Gallery_itm_chkr new_chkr_gallery_itm() {return new Gallery_itm_chkr();}
}
class Gallery_mgr_data_chkr implements Tst_chkr {
public Class<?> TypeOf() {return Gallery_xnde.class;}
public Gallery_itm_chkr[] Expd_subs() {return expd_subs;} public Gallery_mgr_data_chkr Expd_subs_(Gallery_itm_chkr... v) {expd_subs = v; return this;} Gallery_itm_chkr[] expd_subs = null;
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
Gallery_xnde actl = (Gallery_xnde)actl_obj;
int rv = 0;
rv += Chk_basic(mgr, path, actl, rv);
rv += Chk_subs(mgr, path, actl, rv);
return rv;
}
public int Chk_basic(Tst_mgr mgr, String path, Gallery_xnde actl, int err) {
return err;
}
public int Chk_subs(Tst_mgr mgr, String path, Gallery_xnde actl, int err) {
if (expd_subs != null) {
int actl_subs_len = actl.Itms_len();
Gallery_itm[] actl_subs = new Gallery_itm[actl_subs_len];
for (int i = 0; i < actl_subs_len; i++)
actl_subs[i] = actl.Itms_get_at(i);
return mgr.Tst_sub_ary(expd_subs, actl_subs, path, err);
}
return err;
}
}
class Gallery_itm_chkr implements Tst_chkr {
public Class<?> TypeOf() {return Gallery_itm.class;}
public Gallery_itm_chkr Expd_lnki_(String v) {expd_lnki = Xoa_ttl_chkr.new_(v); return this;} private Xoa_ttl_chkr expd_lnki;
public Gallery_itm_chkr Expd_caption_(String v) {expd_caption = v; return this;} private String expd_caption;
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
Gallery_itm actl = (Gallery_itm)actl_obj;
int err = 0;
err += mgr.Tst_sub_obj(expd_lnki, actl.Ttl(), path, err);
err += mgr.Tst_val(expd_caption == null, "", "caption", expd_caption, String_.new_u8(actl.Caption_bry()));
return err;
}
}

View File

@@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.modules.*;
public class Gallery_xtn_mgr extends Xox_mgr_base {
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("gallery");
@Override public Xox_mgr Clone_new() {return new Gallery_xtn_mgr();}
public Gallery_itm_parser Parser() {return parser;} private Gallery_itm_parser parser;
public Gallery_html_wtr Html_wtr() {return html_wtr;} private Gallery_html_wtr html_wtr;
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
parser = new Gallery_itm_parser();
parser.Init_by_wiki(wiki);
html_wtr = new Gallery_html_wtr();
}
}

View File

@@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.geoCrumbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.xtns.pfuncs.*;
public class Geoc_isin_func extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_geoCrumbs_isin;}
@Override public Pf_func New(int id, byte[] name) {return new Geoc_isin_func().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] ttl_bry = Eval_argx(ctx, src, caller, self);
Xowe_wiki wiki = ctx.Wiki();
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, ttl_bry); if (ttl == null) return;
byte[] lnki_ttl = Bry_.Add(Xop_tkn_.Lnki_bgn, ttl_bry, Xop_tkn_.Lnki_end); // make "[[ttl]]"
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b128();
wiki.Parser().Parse_text_to_html(tmp_bfr, ctx.Cur_page(), false, lnki_ttl);
ctx.Cur_page().Html_data().Content_sub_(tmp_bfr.To_bry_and_rls());
}
public static final Geoc_isin_func _ = new Geoc_isin_func();
}

View File

@@ -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.xtns.geoCrumbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Geoc_isin_func_tst {
@Before public void init() {fxt.Reset();} private Geoc_isin_func_fxt fxt = new Geoc_isin_func_fxt();
@Test public void Basic() {
fxt.Test_parse("{{#isin:A}}", "<a href=\"/wiki/A\">A</a>");
}
}
class Geoc_isin_func_fxt {
private Xop_fxt fxt = new Xop_fxt();
public void Reset() {
fxt.Reset();
}
public void Test_parse(String raw, String expd) {
fxt.Test_parse_tmpl_str_test(raw, "{{test}}" , "");
Tfds.Eq(expd, String_.new_u8(fxt.Page().Html_data().Content_sub()));
}
}

View File

@@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.geoCrumbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.dbs.*;
class Geoc_isin_mgr {
public void Reg(int page_id, byte[] page_ttl, byte[] owner_ttl) {
}
}
class Geoc_isin_itm {
public int Page_id() {return page_id;} private int page_id;
public byte[] Page_ttl() {return page_ttl;} private byte[] page_ttl;
public byte[] Owner_ttl() {return owner_ttl;} private byte[] owner_ttl;
public Db_cmd_mode Db_state() {return db_state;} private Db_cmd_mode db_state = Db_cmd_mode.Retrieved;
public void Init_by_make(int page_id, byte[] page_ttl, byte[] owner_ttl) {
this.page_id = page_id; this.page_ttl = page_ttl; this.owner_ttl = owner_ttl; db_state = Db_cmd_mode.Created;
}
}

View File

@@ -0,0 +1,25 @@
/*
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.geodata; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.xtns.pfuncs.*;
public class Geo_coordinates_func extends Pf_func_base {
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {} // NOOP: MW uses to save coordinates for API retrieval
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_geodata_coordinates;}
@Override public Pf_func New(int id, byte[] name) {return new Geo_coordinates_func().Name_(name);}
public static final Geo_coordinates_func _ = new Geo_coordinates_func(); Geo_coordinates_func() {}
}

View File

@@ -0,0 +1,24 @@
/*
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.geodata; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Geo_coordinates_func_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic() {fxt.Test_parse_tmpl_str_test("{{#coordinates:1|2}}" , "{{test}}" , "");}
}

View File

@@ -0,0 +1,66 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.srls.dsvs.*;
class Hiero_file_mgr implements GfoInvkAble {
private Ordered_hash hash = Ordered_hash_.new_bry_();
private Hiero_file_srl srl;
public Hiero_file_mgr() {srl = new Hiero_file_srl(this);}
public int Len() {return hash.Count();}
public Hiero_file_itm Get_at(int i) {return (Hiero_file_itm)hash.Get_at(i);}
public void Add(byte[] key, int file_w, int file_h) {hash.Add(key, new Hiero_file_itm(key, file_w, file_h));}
public void Clear() {hash.Clear();}
public Hiero_file_itm Get_by_key(byte[] key) {return (Hiero_file_itm)hash.Get_by(key);}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_srl)) return srl;
else return GfoInvkAble_.Rv_unhandled;
} private static final String Invk_srl = "srl";
}
class Hiero_file_itm {
public Hiero_file_itm(byte[] key, int file_w, int file_h) {this.key = key; this.file_w = file_w; this.file_h = file_h;}
public byte[] Key() {return key;} private byte[] key;
public int File_w() {return file_w;} private int file_w;
public int File_h() {return file_h;} private int file_h;
}
class Hiero_file_srl extends Dsv_wkr_base {
private Hiero_file_mgr mgr;
private byte[] key;
private int file_w = -1, file_h = -1;
public Hiero_file_srl(Hiero_file_mgr mgr) {this.mgr = mgr;}
@Override public Dsv_fld_parser[] Fld_parsers() {return new Dsv_fld_parser[] {Dsv_fld_parser_.Bry_parser, Dsv_fld_parser_.Int_parser, Dsv_fld_parser_.Int_parser};}
@Override public boolean Write_bry(Dsv_tbl_parser parser, int fld_idx, byte[] src, int bgn, int end) {
switch (fld_idx) {
case 0: key = Bry_.Mid(src, bgn, end); return true;
default: return false;
}
}
@Override public boolean Write_int(Dsv_tbl_parser parser, int fld_idx, int pos, int val_int) {
switch (fld_idx) {
case 1: file_w = val_int; return true;
case 2: file_h = val_int; return true;
default: return false;
}
}
@Override public void Commit_itm(Dsv_tbl_parser parser, int pos) {
if (key == null) throw parser.Err_row_bgn("file missing key", pos);
if (file_w == -1) throw parser.Err_row_bgn("file missing w", pos);
if (file_h == -1) throw parser.Err_row_bgn("file missing h", pos);
mgr.Add(key, file_w, file_h);
key = null; file_w = file_h = -1;
}
}

View File

@@ -0,0 +1,239 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.html.*;
class Hiero_html_mgr {
private Bry_bfr html_bfr = Bry_bfr.reset_(Io_mgr.Len_kb), content_bfr = Bry_bfr.reset_(255), tbl_content_bfr = Bry_bfr.reset_(Io_mgr.Len_kb), temp_bfr = Bry_bfr.reset_(255);
private Xoh_wtr_ctx hctx;
private boolean cartouche_opened = false;
public static int scale = 100;
private Hiero_prefab_mgr prefab_mgr; private Hiero_file_mgr file_mgr; private Hiero_phoneme_mgr phoneme_mgr;
private Hiero_html_wtr wtr;
public Hiero_html_mgr(Hiero_xtn_mgr xtn_mgr) {
prefab_mgr = xtn_mgr.Prefab_mgr();
file_mgr = xtn_mgr.File_mgr();
phoneme_mgr = xtn_mgr.Phoneme_mgr();
wtr = new Hiero_html_wtr(this, phoneme_mgr);
}
public void Render_blocks(Bry_bfr final_bfr, Xoh_wtr_ctx hctx, Hiero_block[] blocks, int scale, boolean hr_enabled) {
this.hctx = hctx; wtr.Init_for_write(hctx);
Hiero_html_mgr.scale = scale;
tbl_content_bfr.Clear(); content_bfr.Clear(); temp_bfr.Clear();
cartouche_opened = false;
if (hr_enabled)
wtr.Hr(html_bfr);
int blocks_len = blocks.length;
for (int i = 0; i < blocks_len; i++) {
Hiero_block block = blocks[i];
if (block.Len() == 1)
Render_block_single(content_bfr, hr_enabled, block);
else
Render_block_many(content_bfr, hr_enabled, block);
if (content_bfr.Len_gt_0())
tbl_content_bfr.Add_bfr_and_clear(content_bfr); // $tbl_content = $tbl + $content;
}
if (tbl_content_bfr.Len_gt_0())
wtr.Tbl_inner(html_bfr, tbl_content_bfr);
wtr.Tbl_outer(final_bfr, html_bfr);
}
private void Render_block_single(Bry_bfr content_bfr, boolean hr_enabled, Hiero_block block) {
byte[] code = block.Get_at(0); // block has only one code (hence the proc name: Render_block_single)
byte b_0 = code[0];
switch (b_0) {
case Byte_ascii.Bang: { // new_line
wtr.Tbl_eol(content_bfr);
if (hr_enabled)
wtr.Hr(content_bfr);
break;
}
case Byte_ascii.Lt: { // cartouche bgn
wtr.Td(content_bfr, Render_glyph(Tkn_lt));
cartouche_opened = true;
wtr.Cartouche_bgn(content_bfr);
break;
}
case Byte_ascii.Gt: { // cartouche end
wtr.Cartouche_end(content_bfr);
cartouche_opened = false;
wtr.Td(content_bfr, Render_glyph(Tkn_gt));
break;
}
default: { // glyph or '.'
byte[] td_height = wtr.Td_height(Resize_glyph(code, cartouche_opened));
wtr.Td(content_bfr, Render_glyph(code, td_height));
break;
}
}
}
private void Render_block_many(Bry_bfr content_bfr, boolean hr_enabled, Hiero_block block) {
temp_bfr.Clear(); // build prefab_bry: "convert all codes into '&' to test prefabs glyph"
int block_len = block.Len();
boolean amp = false;
for (int i = 0; i < block_len; i++) {
byte[] v = block.Get_at(i);
int v_len = v.length;
amp = false;
if (v_len == 1) {
switch (v[0]) {
case Byte_ascii.Brack_bgn: case Byte_ascii.Brack_end:
case Byte_ascii.Paren_bgn: case Byte_ascii.Paren_end:
case Byte_ascii.Star: case Byte_ascii.Colon: case Byte_ascii.Bang:
amp = true;
break;
}
}
if (amp)
temp_bfr.Add_byte(Byte_ascii.Amp);
else
temp_bfr.Add(v);
}
byte[] prefab_bry = temp_bfr.Xto_bry_and_clear();
Hiero_prefab_itm prefab_itm = prefab_mgr.Get_by_key(prefab_bry);
if (prefab_itm != null) {
byte[] td_height = wtr.Td_height(Resize_glyph(prefab_bry, cartouche_opened));
wtr.Td(content_bfr, Render_glyph(prefab_bry, td_height));
}
else {
int line_max = 0, total = 0, height = 0; // get block total height
byte[] glyph = null;
for (int i = 0; i < block_len; i++) {
byte[] v = block.Get_at(i);
int v_len = v.length;
if (v_len == 1) {
switch (v[0]) {
case Byte_ascii.Colon:
if (height > line_max)
line_max = height;
total += line_max;
line_max = 0;
continue;
case Byte_ascii.Star:
if (height > line_max)
line_max = height;
continue;
}
}
Hiero_phoneme_itm phoneme_itm = phoneme_mgr.Get_by_key(v);
if (phoneme_itm != null)
glyph = phoneme_itm.Gardiner_code();
else
glyph = v;
Hiero_file_itm file_itm = file_mgr.Get_by_key(glyph);
if (file_itm != null)
height = 2 + file_itm.File_h();
}
if (height > line_max)
line_max = height;
total += line_max;
// render all glyph into the block
for (int i = 0; i < block_len; i++) {
byte[] v = block.Get_at(i);
int v_len = v.length;
if (v_len == 1) {
switch (v[0]) {
case Byte_ascii.Colon:
temp_bfr.Add_str_a7("\n <br/>");
continue;
case Byte_ascii.Star:
temp_bfr.Add_byte_space();
continue;
}
}
// resize the glyph according to the block total height
byte[] td_height = wtr.Td_height(Resize_glyph(v, cartouche_opened, total));
temp_bfr.Add(Render_glyph(v, td_height));
}
wtr.Td(content_bfr, temp_bfr.Xto_bry_and_clear());
}
}
private byte[] Render_glyph(byte[] src) {return Render_glyph(src, Bry_.Empty);}
private byte[] Render_glyph(byte[] src, byte[] td_height) {
int src_len = src.length; if (src_len == 0) return src; // bounds check
byte byte_n = src[src_len - 1];
byte[] img_cls = byte_n == Byte_ascii.Backslash // REF.MW:isMirrored
? Bry_cls_mirrored // 'class="mw-mirrored" '
: Bry_.Empty
;
byte[] glyph = Extract_code(src, src_len); // trim backslashes from end; REF.MW:extractCode
if (Bry_.Eq(glyph, Tkn_dot_dot)) // render void block
return wtr.Void(Bool_.N);
else if (Bry_.Eq(glyph, Tkn_dot)) // render 1/2 width void block
return wtr.Void(Bool_.Y);
else if (Bry_.Eq(glyph, Tkn_lt))
return wtr.Cartouche_img(hctx, Bool_.Y, glyph);
else if (Bry_.Eq(glyph, Tkn_gt))
return wtr.Cartouche_img(hctx, Bool_.N, glyph);
Hiero_phoneme_itm phoneme_itm = phoneme_mgr.Get_by_key(glyph);
Hiero_file_itm file_itm = null;
byte[] glyph_esc = Html_utl.Escape_html_as_bry(glyph);
if (phoneme_itm != null) {
byte[] code = phoneme_itm.Gardiner_code();
file_itm = file_mgr.Get_by_key(code);
if (file_itm != null)
return wtr.Img_phoneme(img_cls, td_height, glyph_esc, code);
else
return glyph_esc;
}
file_itm = file_mgr.Get_by_key(glyph);
return file_itm != null
? wtr.Img_file(img_cls, td_height, glyph_esc)
: glyph_esc
;
}
private int Resize_glyph(byte[] item, boolean cartouche_opened) {return Resize_glyph(item, cartouche_opened, 0);}
private int Resize_glyph(byte[] item, boolean cartouche_opened, int total) {
item = Extract_code(item, item.length);
Hiero_phoneme_itm phoneme_itm = phoneme_mgr.Get_by_key(item);
byte[] glyph = phoneme_itm == null ? item : phoneme_itm.Gardiner_code();
int margin = 2 * Image_margin;
if (cartouche_opened)
margin += 2 * (int)((Cartouche_width * scale) / 100);
Hiero_file_itm file_itm = file_mgr.Get_by_key(glyph);
if (file_itm != null) {
int height = margin + file_itm.File_h();
if (total > 0) {
return total > Max_height
? (int)(((((height * Max_height) / total) - margin) * scale) / 100)
: (int)(((height - margin) * scale) / 100)
;
}
else {
return height > Max_height
? (int)(((((Max_height * Max_height) / height) - margin) * scale) / 100)
: (int)(((height - margin) * scale) / 100)
;
}
}
return (int)(((Max_height - margin) * scale) / 100);
}
private static byte[] Extract_code(byte[] src, int src_len) { // trim backslashes from end; REF.MW:extractCode
return Bry_.Trim_end(src, Byte_ascii.Backslash, src_len);
}
public static final int Image_margin = 1;
public static final int Cartouche_width = 2;
public static final int Max_height = 44;
private static final byte[] Bry_cls_mirrored = Bry_.new_a7("class=\"mw-mirrored\" ");
private static final byte[]
Tkn_lt = new byte[] {Byte_ascii.Lt}
, Tkn_gt = new byte[] {Byte_ascii.Gt}
, Tkn_dot = new byte[] {Byte_ascii.Dot}
, Tkn_dot_dot = new byte[] {Byte_ascii.Dot, Byte_ascii.Dot}
;
}

View File

@@ -0,0 +1,56 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Hiero_html_mgr_fxt {
private Hiero_xtn_mgr xtn_mgr;
public Hiero_html_mgr_fxt(Xop_fxt fxt) {this.fxt = fxt;}
public Xop_fxt Fxt() {return fxt;} private Xop_fxt fxt;
public void Reset() {
fxt.Reset();
xtn_mgr = new Hiero_xtn_mgr();
xtn_mgr.Xtn_init_by_app(fxt.App());
xtn_mgr.Clear();
}
public Hiero_html_mgr_fxt Init_hiero_A1_B1() {
this.Init_file("A1", 29, 38);
this.Init_file("B1", 23, 38);
return this;
}
public Hiero_html_mgr_fxt Init_hiero_cartouche() {
this.Init_phoneme("<", "Ca1");
this.Init_phoneme(">", "Ca2");
return this;
}
public Hiero_html_mgr_fxt Init_hiero_p_t() {
this.Init_phoneme("p", "Q3");
this.Init_phoneme("t", "X1");
this.Init_file("Q3", 12, 15);
this.Init_file("X1", 20, 11);
return this;
}
public Hiero_html_mgr_fxt Init_hiero_a_A1() {
this.Init_prefab("a&A1");
this.Init_file("a&A1", 37, 38);
return this;
}
public Hiero_html_mgr_fxt Init_prefab(String prefab) {xtn_mgr.Prefab_mgr().Add(Bry_.new_u8(prefab)); return this;}
public Hiero_html_mgr_fxt Init_file(String s, int w, int h) {xtn_mgr.File_mgr().Add(Bry_.new_u8(s), w, h); return this;}
public Hiero_html_mgr_fxt Init_phoneme(String phoneme, String code) {xtn_mgr.Phoneme_mgr().Add(Bry_.new_u8(phoneme), Bry_.new_u8(code)); return this;}
public void Test_html_full_str(String raw, String expd) {fxt.Test_html_full_str(raw, expd);}
public void Test_html_full_frag(String raw, String expd) {fxt.Test_html_full_frag(raw, expd);}
}

View File

@@ -0,0 +1,389 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Hiero_html_mgr_tst {
@Before public void init() {fxt.Reset();} private Hiero_html_mgr_fxt fxt = new Hiero_html_mgr_fxt(new Xop_fxt());
@Test public void Empty() {
fxt.Test_html_full_str
( "<hiero></hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, ""
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Glyph_1() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str
( "<hiero>A1</hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Mirrored() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str
( "<hiero>A1\\</hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img class=\"mw-mirrored\" style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Glyph_2() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str("<hiero>A1-B1</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Void_half() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str
( "<hiero>A1 . B1</hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " <td>"
, " <table class=\"mw-hiero-table\" style=\"width: 22px;\">"
, " <tr>"
, " <td>&#160;"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Void_full() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str
( "<hiero>A1 .. B1</hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " <td>"
, " <table class=\"mw-hiero-table\" style=\"width: 44px;\">"
, " <tr>"
, " <td>&#160;"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void New_line() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str
( "<hiero>A1 ! B1</hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Cartouche() {
fxt.Init_hiero_A1_B1().Init_hiero_cartouche();
fxt.Test_html_full_str
( "<hiero>< A1 ></hiero>"
, String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_Ca1.png' height='44' title='&lt;' alt='&lt;' />"
, " </td>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td class='mw-hiero-box' style='height: 2px;'>"
, " </td>"
, " </tr>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, " <tr>"
, " <td class='mw-hiero-box' style='height: 2px;'>"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " <td>"
, " <img src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_Ca2.png' height='44' title='&gt;' alt='&gt;' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Superposition_regular() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str("<hiero>A1:B1</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 20px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' />"
, " <br/>"
, " <img style='margin: 1px; height: 20px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Superposition_phoneme() {
fxt.Init_hiero_p_t();
fxt.Test_html_full_str("<hiero>t:p</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 11px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_X1.png' title='X1 [t]' alt='t' />"
, " <br/>"
, " <img style='margin: 1px; height: 15px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_Q3.png' title='Q3 [p]' alt='p' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Superposition_prefab() {
fxt.Init_hiero_a_A1();
fxt.Test_html_full_str("<hiero>a:A1</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_a&amp;A1.png' title='a&amp;A1' alt='a&amp;A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Juxtaposition_regular() {
fxt.Init_hiero_A1_B1();
fxt.Test_html_full_str("<hiero>A1*B1</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_A1.png' title='A1' alt='A1' /> "
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_B1.png' title='B1' alt='B1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Juxtaposition_phoneme() {
fxt.Init_hiero_p_t();
fxt.Test_html_full_str("<hiero>t*p</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 11px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_X1.png' title='X1 [t]' alt='t' /> "
, " <img style='margin: 1px; height: 15px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_Q3.png' title='Q3 [p]' alt='p' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Juxtaposition_prefab() {
fxt.Init_hiero_a_A1();
fxt.Test_html_full_str("<hiero>a*A1</hiero>", String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, " <table class=\"mw-hiero-table\">"
, " <tr>"
, " <td>"
, " <img style='margin: 1px; height: 38px;' src='file:///mem/xowa/bin/any/xowa/xtns/Wikihiero/img/hiero_a&amp;A1.png' title='a&amp;A1' alt='a&amp;A1' />"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, "</table>"
));
}
@Test public void Para_if_text() {// PURPOSE: check that paras are handled correctly; EX: w:Hieroglyphics; DATE:2014-04-23
fxt.Fxt().Init_para_y_();
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "a" // should always be in <p>
, ""
, "<hiero></hiero> b" // <hiero> should not be in <p> but "b" should be;
), String_.Concat_lines_nl_skip_last
( "<p>a"
, "</p>"
, "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, ""
, " </td>"
, " </tr>"
, "</table>"
, ""
, "<p> b" // NOTE: space seems wrong, but is "harmless"
, "</p>"
));
fxt.Fxt().Init_para_n_();
}
@Test public void Para_skip_if_list() {// PURPOSE: do not add para if in list; EX:de.d:Damascus; DATE:2014-06-06
fxt.Fxt().Init_para_y_();
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( ":<hiero></hiero> a" // a should not be in para
, ":b"
), String_.Concat_lines_nl_skip_last
( "<dl>"
, " <dd><table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, ""
, " </td>"
, " </tr>"
, "</table>"
, " a"
, " </dd>"
, " <dd>b"
, " </dd>"
, "</dl>"
));
fxt.Fxt().Init_para_n_();
}
}

View File

@@ -0,0 +1,172 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.html.*;
class Hiero_html_wtr {
private Hiero_phoneme_mgr phoneme_mgr;
private Bry_bfr temp_bfr = Bry_bfr.reset_(255);
public Hiero_html_wtr(Hiero_html_mgr mgr, Hiero_phoneme_mgr phoneme_mgr) {this.phoneme_mgr = phoneme_mgr;}
public void Init_for_write(Xoh_wtr_ctx hctx) {this.hiero_img_dir = hctx.Mode_is_hdump() ? gplx.xowa.html.hdumps.abrvs.Xohd_abrv_.Key_hiero_dir : Hiero_xtn_mgr.Img_src_dir;} private byte[] hiero_img_dir = null;
public void Hr(Bry_bfr bfr) {bfr.Add(Html_tag_.Hr_inl).Add_byte_nl();}
public void Tbl_eol(Bry_bfr bfr) {bfr.Add(Tbl_eol_bry);}
public byte[] Td_height(int height) {
return temp_bfr.Add(Option_bgn_bry).Add_int_variable(height).Add(Option_end_bry).Xto_bry_and_clear();
}
private static final byte[]
Option_bgn_bry = Bry_.new_a7("height: ")
, Option_end_bry = Bry_.new_a7("px;")
;
public void Td(Bry_bfr bfr, byte[] glyph) {
bfr.Add(Td_bgn_bry).Add(glyph).Add(Td_end_bry);
}
private static final byte[]
Td_bgn_bry = Bry_.new_a7("\n <td>")
, Td_end_bry = Bry_.new_a7("\n </td>")
;
public void Cartouche_bgn(Bry_bfr bfr) {
bfr.Add(Cartouche_bgn_lhs_bry).Add_int_variable((Hiero_html_mgr.Cartouche_width * Hiero_html_mgr.scale) / 100).Add(Cartouche_bgn_rhs_bry);
}
private static final String Tbl_bgn_str = "<table class=\"mw-hiero-table\">";
private static final byte[]
Cartouche_bgn_lhs_bry = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( ""
, " <td>"
, " " + Tbl_bgn_str
, " <tr>"
, " <td class='mw-hiero-box' style='height: "
))
, Cartouche_bgn_rhs_bry = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( "px;'>"
, " </td>"
, " </tr>"
, " <tr>"
, " <td>"
, " " + Tbl_bgn_str
, " <tr>"
))
;
public void Cartouche_end(Bry_bfr bfr) {
bfr.Add(Cartouche_end_lhs_bry).Add_int_variable((Hiero_html_mgr.Cartouche_width * Hiero_html_mgr.scale) / 100).Add(Cartouche_end_rhs_bry);
}
private static final byte[]
Cartouche_end_lhs_bry = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( ""
, " </tr>"
, " </table>"
, " </td>"
, " </tr>"
, " <tr>"
, " <td class='mw-hiero-box' style='height: "
))
, Cartouche_end_rhs_bry = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( "px;'>"
, " </td>"
, " </tr>"
, " </table>"
, " </td>"
));
public byte[] Cartouche_img(Xoh_wtr_ctx hctx, boolean bgn, byte[] glyph) { // render open / close cartouche; note that MW has two branches, but they are both the same
int height = (int)((Hiero_html_mgr.Max_height * Hiero_html_mgr.scale) / 100);
Hiero_phoneme_itm phoneme_itm = phoneme_mgr.Get_by_key(glyph); if (phoneme_itm == null) throw Exc_.new_("missing phoneme", "glyph", String_.new_u8(glyph));
byte[] code = phoneme_itm.Gardiner_code();
byte[] title = bgn ? Html_entity_.Lt_bry : Html_entity_.Gt_bry;
return cartouche_img_fmtr.Bld_bry_many(temp_bfr, hiero_img_dir, code, height, title);
}
private static final Bry_fmtr cartouche_img_fmtr = Bry_fmtr.new_(String_.Concat
( "\n <img src='~{path}hiero_~{code}.png'"
, " height='~{height}' title='~{title}'"
, " alt='~{title}' />"
)
, "path", "code", "height", "title");
public void Tbl_inner(Bry_bfr html_bfr, Bry_bfr text_bfr) {
html_bfr.Add(Tbl_inner_bgn).Add_bfr_and_clear(text_bfr).Add(Tbl_inner_end); // $html .= self::TABLE_START . "<tr>\n" . $tableContentHtml . '</tr></table>';
}
private static final byte[]
Tbl_inner_bgn = Bry_.new_u8(String_.Concat_lines_nl_skip_last
( " <table class=\"mw-hiero-table\">"
, " <tr>"
))
, Tbl_inner_end = Bry_.new_u8(String_.Concat_lines_nl_skip_last
( ""
, " </tr>"
, " </table>"
))
;
public void Tbl_outer(Bry_bfr bfr, Bry_bfr html_bfr) {
bfr.Add(Outer_tbl_bgn);
bfr.Add_bfr_and_clear(html_bfr);
bfr.Add(Outer_tbl_end);
}
private static final byte[]
Outer_tbl_bgn = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
, " <tr>"
, " <td>"
, ""
)
)
, Outer_tbl_end = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( ""
, " </td>"
, " </tr>"
, "</table>"
, ""
))
;
public byte[] Img_phoneme(byte[] img_cls, byte[] td_height, byte[] glyph_esc, byte[] code) {
byte[] code_esc = Html_utl.Escape_html_as_bry(temp_bfr, code);
byte[] img_title = temp_bfr.Add(code_esc).Add_byte_space().Add_byte(Byte_ascii.Brack_bgn).Add(glyph_esc).Add_byte(Byte_ascii.Brack_end).Xto_bry_and_clear(); // "~{code} [~{glyph}]"
return Img(img_cls, td_height, glyph_esc, code_esc, img_title);
}
public byte[] Img_file(byte[] img_cls, byte[] td_height, byte[] glyph_esc) {return Img(img_cls, td_height, glyph_esc, glyph_esc, glyph_esc);}
private byte[] Img(byte[] img_cls, byte[] td_height, byte[] glyph, byte[] img_src_name, byte[] img_title) {
byte[] img_src = Bld_img_src(hiero_img_dir, img_src_name);
return glyph_img_fmtr.Bld_bry_many(temp_bfr, img_cls, Hiero_html_mgr.Image_margin, td_height, img_src, img_title, glyph);
}
private static final byte[]
Tbl_eol_bry = Bry_.new_a7(String_.Concat_lines_nl_skip_last
( ""
, " </tr>"
, " </table>"
, " " + Tbl_bgn_str
, " <tr>"
));
private static final Bry_fmtr
glyph_img_fmtr = Bry_fmtr.new_
( "\n <img ~{img_cls}style='margin: ~{img_margin}px; ~{option}' src='~{img_src}' title='~{img_title}' alt='~{glyph}' />", "img_cls", "img_margin", "option", "img_src", "img_title", "glyph")
;
public byte[] Void(boolean half) { // render void
int width = Hiero_html_mgr.Max_height;
if (half) width /= 2;
return void_fmtr.Bld_bry_many(temp_bfr, width);
}
private static final Bry_fmtr void_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <table class=\"mw-hiero-table\" style=\"width: ~{width}px;\">"
, " <tr>"
, " <td>&#160;"
, " </td>"
, " </tr>"
, " </table>"
)
, "width");
private static byte[] Bld_img_src(byte[] hiero_img_dir, byte[] name) {
return Bry_.Add(hiero_img_dir, Img_src_prefix, name, Img_src_ext);
}
private static final byte[] Img_src_prefix = Bry_.new_a7("hiero_"), Img_src_ext = Bry_.new_a7(".png");
}

View File

@@ -0,0 +1,118 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.php.*; import gplx.srls.dsvs.*;
public class Hiero_mw_tables_parser {
private Php_parser parser = new Php_parser(); private Php_evaluator evaluator;
private Php_text_itm_parser quote_parser = new Php_text_itm_parser();
public Hiero_mw_tables_parser() {evaluator = new Php_evaluator(Gfo_msg_log.Test());}
public void Bld_all(Io_url load_fil, Io_url save_fil) {
Hiero_xtn_mgr xtn_mgr = new Hiero_xtn_mgr();
xtn_mgr.Clear(); // clear b/c members are actually static; else test will fail
Load_data(xtn_mgr, load_fil);
Save_data(xtn_mgr, save_fil); // prefabs.gfs (key only); files.gfs (key,size); phonemes (key, val)
}
public void Load_data(Hiero_xtn_mgr xtn_mgr, Io_url load_fil) {// NOTE: parsing tables.php instead of tables.ser b/c latter is too difficult to read / debug
evaluator.Clear();
parser.Parse_tkns(Io_mgr.I.LoadFilBry(load_fil), evaluator);
Php_line[] lines = (Php_line[])evaluator.List().To_ary(Php_line.class);
int lines_len = lines.length;
for (int i = 0; i < lines_len; i++) {
Php_line_assign line = (Php_line_assign)lines[i];
byte[] key = line.Key().Val_obj_bry();
Object o = Tid_hash.Get_by_bry(key);
if (o != null) {
Byte_obj_val stub = (Byte_obj_val)o;
switch (stub.Val()) {
case Tid_prefabs: Parse_prefabs(xtn_mgr.Prefab_mgr(), line); break;
case Tid_files: Parse_files(xtn_mgr.File_mgr(), line); break;
case Tid_phonemes: Parse_phonemes(xtn_mgr.Phoneme_mgr(), line); break;
}
}
}
}
private void Parse_prefabs(Hiero_prefab_mgr mgr, Php_line_assign line) { // $wh_prefabs = array(v, v ...);
Php_itm_ary ary = (Php_itm_ary)line.Val();
int subs_len = ary.Subs_len();
for (int i = 0; i < subs_len; i++) {
Php_itm itm = (Php_itm)ary.Subs_get(i);
mgr.Add(Php_itm_.Parse_bry(itm));
}
}
private void Parse_files(Hiero_file_mgr mgr, Php_line_assign line) { // $wh_files = array(k => array(w, h), k => array(w, h) ...);
Php_itm_ary ary = (Php_itm_ary)line.Val();
int subs_len = ary.Subs_len();
for (int i = 0; i < subs_len; i++) {
Php_itm_kv kv = (Php_itm_kv)ary.Subs_get(i);
byte[] key = Php_itm_.Parse_bry(kv.Key());
Php_itm_ary val_ary = (Php_itm_ary)kv.Val();
int w = Php_itm_.Parse_int_or(val_ary.Subs_get(0), -1);
int h = Php_itm_.Parse_int_or(val_ary.Subs_get(1), -1);
mgr.Add(key, w, h);
}
}
private void Parse_phonemes(Hiero_phoneme_mgr mgr, Php_line_assign line) { // $wh_phonemes = array(k => v, k => v ...);
List_adp tmp_list = List_adp_.new_(); Byte_obj_ref tmp_rslt = Byte_obj_ref.zero_(); Bry_bfr tmp_bfr = Bry_bfr.new_();
Php_itm_ary ary = (Php_itm_ary)line.Val();
int subs_len = ary.Subs_len();
for (int i = 0; i < subs_len; i++) {
Php_itm_kv kv = (Php_itm_kv)ary.Subs_get(i);
byte[] kv_key = quote_parser.Parse_as_bry(tmp_list, Php_itm_.Parse_bry(kv.Key()), tmp_rslt, tmp_bfr);
mgr.Add(kv_key, Php_itm_.Parse_bry(kv.Val()));
}
}
public void Save_data(Hiero_xtn_mgr xtn_mgr, Io_url save_fil) {
Gfs_bldr bldr = new Gfs_bldr();
int len = -1;
Hiero_prefab_mgr prefab_mgr = xtn_mgr.Prefab_mgr();
len = prefab_mgr.Len();
bldr.Add_proc_init_many(Hiero_xtn_mgr.Invk_prefabs, Hiero_phoneme_mgr.Invk_srl, Dsv_wkr_base.Invk_load_by_str).Add_quote_xtn_apos_bgn(); // prefabs.srl.load_by_str('\n
for (int i = 0; i < len; i++) {
Hiero_prefab_itm itm = prefab_mgr.Get_at(i);
bldr.Bfr().Add(itm.Key()).Add_byte_nl(); // NOTE: escape not needed
}
bldr.Add_quote_xtn_apos_end(); // ');\n
bldr.Add_nl();
Hiero_file_mgr file_mgr = xtn_mgr.File_mgr();
len = file_mgr.Len();
bldr.Add_proc_init_many(Hiero_xtn_mgr.Invk_files, Hiero_phoneme_mgr.Invk_srl, Dsv_wkr_base.Invk_load_by_str).Add_quote_xtn_apos_bgn(); // files.srl.load_by_str('\n
for (int i = 0; i < len; i++) {
Hiero_file_itm itm = file_mgr.Get_at(i);
bldr.Bfr().Add(itm.Key()).Add_byte_pipe().Add_int_variable(itm.File_w()).Add_byte_pipe().Add_int_variable(itm.File_h()).Add_byte_nl(); // NOTE: escape not needed
}
bldr.Add_quote_xtn_apos_end(); // ');\n
bldr.Add_nl();
Hiero_phoneme_mgr phoneme_mgr = xtn_mgr.Phoneme_mgr();
len = phoneme_mgr.Len();
bldr.Add_proc_init_many(Hiero_xtn_mgr.Invk_phonemes, Hiero_phoneme_mgr.Invk_srl, Dsv_wkr_base.Invk_load_by_str).Add_paren_bgn().Add_nl(); // phonemes.srl.load_by_str(
bldr.Add_quote_xtn_bgn();
for (int i = 0; i < len; i++) {
Hiero_phoneme_itm itm = phoneme_mgr.Get_at(i);
bldr.Bfr().Add(itm.Key()).Add_byte_pipe().Add(itm.Gardiner_code()).Add_byte_nl(); // NOTE: escape not needed
}
bldr.Add_quote_xtn_end();
bldr.Add_paren_end().Add_term_nl();
Io_mgr.I.SaveFilBfr(save_fil, bldr.Bfr());
}
private static final byte Tid_prefabs = 0, Tid_files = 1, Tid_phonemes = 2;
private static Hash_adp_bry Tid_hash = Hash_adp_bry.cs_().Add_str_byte("wh_prefabs", Tid_prefabs).Add_str_byte("wh_files", Tid_files).Add_str_byte("wh_phonemes", Tid_phonemes);
}

View File

@@ -0,0 +1,75 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
import gplx.intl.*;
public class Hiero_mw_tables_parser_tst {
@Before public void init() {fxt.Reset();} private Hiero_mw_tables_parser_fxt fxt = new Hiero_mw_tables_parser_fxt();
@Test public void Basic() {// DATE:2014-04-19
fxt.Test_bld_all
( String_.Concat_lines_nl_skip_last
( "$wh_prefabs = array("
, " \"a&A1\","
, " \"Z6&A1\","
, ");"
, ""
, "$wh_files = array("
, " \"a&A1\" => array( 37, 38 ),"
, " \"Z98A\" => array( 5, 15 ),"
, ");"
, ""
, "$wh_phonemes = array("
, " \"mSa\" => \"A12\","
, " \"\\\"]\" => \"\","
, ");"
)
, String_.Concat_lines_nl_skip_last
( "prefabs.srl.load_by_str('"
, "a&A1"
, "Z6&A1"
, "');"
, ""
, "files.srl.load_by_str('"
, "a&A1|37|38"
, "Z98A|5|15"
, "');"
, ""
, "phonemes.srl.load_by_str("
, "<:['"
, "mSa|A12"
, "\"]|"
, "']:>"
, ");"
)
);
}
}
class Hiero_mw_tables_parser_fxt {
private Hiero_mw_tables_parser parser = new Hiero_mw_tables_parser();
public void Reset() {}
public void Test_bld_all(String raw, String expd) {
Io_url load_url = Io_url_.mem_fil_("mem/hiero/load.php");
Io_url save_url = Io_url_.mem_fil_("mem/hiero/save.php");
Io_mgr.I.SaveFilStr(load_url, raw);
parser.Bld_all(load_url, save_url);
Tfds.Eq_str_lines(expd, Io_mgr.I.LoadFilStr(save_url));
}
public void Exec_bld_all(String load, String save) {
parser.Bld_all(Io_url_.new_fil_(load), Io_url_.new_fil_(save));
}
}

View File

@@ -0,0 +1,132 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*; import gplx.html.*; import gplx.xowa.html.*;
class Hiero_parser {
private Btrie_slim_mgr trie = Btrie_slim_mgr.cs_();
private List_adp blocks = List_adp_.new_();
private Hiero_block cur_block;
private Bry_bfr cur_tkn = Bry_bfr.reset_(16);
public Hiero_block[] Parse(byte[] src, int bgn, int end) {
blocks.Clear();
this.cur_block = new Hiero_block();
cur_tkn.Clear();
int pos = bgn;
while (true) {
if (pos == end) break;
byte b = src[pos];
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
if (o == null) {
New_char(b);
++pos;
}
else {
Hiero_parser_itm itm = (Hiero_parser_itm)o;
int new_pos = trie.Match_pos();
switch (itm.Tid()) {
case Hiero_parser_itm.Tid_comment:
int end_comm = Bry_finder.Find_fwd(src, Html_tag_.Comm_end, new_pos, end);
if (end_comm == Bry_finder.Not_found) // --> not found; for now, ignore <!--
pos = new_pos;
else
pos = end_comm + Html_tag_.Comm_end_len;
break;
case Hiero_parser_itm.Tid_block_spr:
New_block();
break;
case Hiero_parser_itm.Tid_single_char:
Single_char_block(itm);
break;
case Hiero_parser_itm.Tid_dot:
Dot();
break;
case Hiero_parser_itm.Tid_tkn_spr:
New_token(itm);
break;
default: throw Exc_.new_unhandled(itm.Tid()); // should never happen
}
pos = new_pos;
}
}
this.New_block();// flush remaining items
return (Hiero_block[])blocks.To_ary_and_clear(Hiero_block.class);
}
private void New_block() {
this.New_token(null);
if (cur_block.Len() > 0) {
blocks.Add(cur_block);
cur_block = new Hiero_block();
}
}
private void New_token(Hiero_parser_itm itm) {
if (cur_tkn.Len_gt_0())
cur_block.Add(cur_tkn.Xto_bry_and_clear());
if (itm != null)
cur_block.Add(itm.Key());
}
private void Single_char_block(Hiero_parser_itm itm) {
this.New_block();
cur_block.Add(itm.Key());
}
private void Dot() {
if (cur_tkn.Eq(Byte_ascii.Dot)) { // is "."
cur_tkn.Add_byte(Byte_ascii.Dot); // make ".."
this.New_block();
}
else {
this.New_block();
cur_tkn.Add_byte(Byte_ascii.Dot); // make "."; note that New_block clears tkn
}
}
private void New_char(byte b) {
if (b == Byte_ascii.Dot) { // is "."; NOTE: never occurs; should always hit dot block; transcribed literally from MW
this.New_block();
this.cur_tkn.Add_byte(b); // $this->token = $char;
}
else
this.cur_tkn.Add_byte(b); // $this->token .= $char;
}
public void Init() {
Init_itms(Hiero_parser_itm.Tid_block_spr, " ", "-", "\t", "\n", "\r");
Init_itms(Hiero_parser_itm.Tid_tkn_spr, "*", ":", "(", ")");
Init_itms(Hiero_parser_itm.Tid_dot, ".");
Init_itms(Hiero_parser_itm.Tid_single_char , "!");
Init_itms(Hiero_parser_itm.Tid_comment, Html_tag_.Comm_bgn_str);
}
private void Init_itms(byte tid, String... keys) {
int keys_len = keys.length;
for (int i = 0; i < keys_len; i++) {
String key_str = keys[i];
byte[] key_bry = Bry_.new_u8(key_str);
Hiero_parser_itm itm = new Hiero_parser_itm(tid, key_bry);
trie.Add_obj(key_bry, itm);
}
}
}
class Hiero_parser_itm {
public Hiero_parser_itm(byte tid, byte[] key) {this.tid = tid; this.key = key;}
public byte Tid() {return tid;} private byte tid;
public byte[] Key() {return key;} private byte[] key;
public static final byte Tid_block_spr = 1, Tid_tkn_spr = 2, Tid_single_char = 3, Tid_dot = 4, Tid_comment = 5;
}
class Hiero_block {
private List_adp list = List_adp_.new_();
public int Len() {return list.Count();}
public byte[] Get_at(int i) {return (byte[])list.Get_at(i);}
public void Add(byte[] v) {list.Add(v);}
}

View File

@@ -0,0 +1,59 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Hiero_parser_tst {
@Before public void init() {fxt.Reset();} private Hiero_parser_fxt fxt = new Hiero_parser_fxt();
@Test public void Separator() {
String[][] expd = new String[][] {fxt.block_("A1"), fxt.block_("B1")};
fxt.Test_parse("A1 B1" , expd); // space
fxt.Test_parse("A1-B1" , expd); // dash
fxt.Test_parse("A1\tB1" , expd); // tab
fxt.Test_parse("A1\nB1" , expd); // nl
fxt.Test_parse("A1\rB1" , expd); // cr
fxt.Test_parse("A1 B1" , expd); // many: space
fxt.Test_parse("A1 \t\nB1" , expd); // many: mixed
}
}
class Hiero_parser_fxt {
private Hiero_parser parser;
public void Reset() {
parser = new Hiero_parser();
parser.Init();
}
public String[] block_(String... v) {return v;}
public void Test_parse(String raw, String[]... expd) {
byte[] raw_bry = Bry_.new_a7(raw);
Hiero_block[] actl = parser.Parse(raw_bry, 0, raw_bry.length);
Tfds.Eq_ary(String_.Ary_flatten(expd), String_.Ary_flatten(Xto_str(actl)));
}
private String[][] Xto_str(Hiero_block[] ary) {
int len = ary.length;
String[][] rv = new String[len][];
for (int i = 0; i < len; i++) {
Hiero_block itm = ary[i];
int itm_len = itm.Len();
String[] rv_sub = new String[itm_len];
rv[i] = rv_sub;
for (int j = 0; j < itm_len; j++) {
rv_sub[j] = String_.new_u8(itm.Get_at(j));
}
}
return rv;
}
}

View File

@@ -0,0 +1,59 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.srls.dsvs.*;
class Hiero_phoneme_mgr implements GfoInvkAble {
private Ordered_hash hash = Ordered_hash_.new_bry_();
private Hiero_phoneme_srl srl;
public Hiero_phoneme_mgr() {srl = new Hiero_phoneme_srl(this);}
public int Len() {return hash.Count();}
public Hiero_phoneme_itm Get_at(int i) {return (Hiero_phoneme_itm)hash.Get_at(i);}
public void Add(byte[] key, byte[] val) {hash.Add(key, new Hiero_phoneme_itm(key, val));}
public void Clear() {hash.Clear();}
public Hiero_phoneme_itm Get_by_key(byte[] key) {return (Hiero_phoneme_itm)hash.Get_by(key);}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_srl)) return srl;
else return GfoInvkAble_.Rv_unhandled;
}
public static final String Invk_srl = "srl";
}
class Hiero_phoneme_itm {
public Hiero_phoneme_itm(byte[] key, byte[] gardiner_code) {this.key = key; this.gardiner_code = gardiner_code;}
public byte[] Key() {return key;} private byte[] key;
public byte[] Gardiner_code() {return gardiner_code;} private byte[] gardiner_code;
}
class Hiero_phoneme_srl extends Dsv_wkr_base {
private Hiero_phoneme_mgr mgr;
private byte[] key;
private byte[] val;
public Hiero_phoneme_srl(Hiero_phoneme_mgr mgr) {this.mgr = mgr;}
@Override public Dsv_fld_parser[] Fld_parsers() {return new Dsv_fld_parser[] {Dsv_fld_parser_.Bry_parser, Dsv_fld_parser_.Bry_parser};}
@Override public boolean Write_bry(Dsv_tbl_parser parser, int fld_idx, byte[] src, int bgn, int end) {
switch (fld_idx) {
case 0: key = Bry_.Mid(src, bgn, end); return true;
case 1: val = Bry_.Mid(src, bgn, end); return true;
default: return false;
}
}
@Override public void Commit_itm(Dsv_tbl_parser parser, int pos) {
if (key == null) throw parser.Err_row_bgn("phoneme missing key", pos);
if (val == null) throw parser.Err_row_bgn("phoneme missing val", pos);
mgr.Add(key, val);
key = val = null;
}
}

View File

@@ -0,0 +1,53 @@
/*
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.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.srls.dsvs.*;
class Hiero_prefab_mgr implements GfoInvkAble {
private Ordered_hash hash = Ordered_hash_.new_bry_();
private Hiero_prefab_srl srl;
public Hiero_prefab_mgr() {srl = new Hiero_prefab_srl(this);}
public int Len() {return hash.Count();}
public Hiero_prefab_itm Get_at(int i) {return (Hiero_prefab_itm)hash.Get_at(i);}
public Hiero_prefab_itm Get_by_key(byte[] key) {return (Hiero_prefab_itm)hash.Get_by(key);}
public void Add(byte[] key) {hash.Add(key, new Hiero_prefab_itm(key));}
public void Clear() {hash.Clear();}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_srl)) return srl;
else return GfoInvkAble_.Rv_unhandled;
} private static final String Invk_srl = "srl";
}
class Hiero_prefab_itm {
public Hiero_prefab_itm(byte[] key) {this.key = key;}
public byte[] Key() {return key;} private byte[] key;
}
class Hiero_prefab_srl extends Dsv_wkr_base {
private Hiero_prefab_mgr mgr;
private byte[] key;
public Hiero_prefab_srl(Hiero_prefab_mgr mgr) {this.mgr = mgr;}
@Override public Dsv_fld_parser[] Fld_parsers() {return new Dsv_fld_parser[] {Dsv_fld_parser_.Bry_parser};}
@Override public boolean Write_bry(Dsv_tbl_parser parser, int fld_idx, byte[] src, int bgn, int end) {
switch (fld_idx) {
case 0: key = Bry_.Mid(src, bgn, end); return true;
default: return false;
}
}
@Override public void Commit_itm(Dsv_tbl_parser parser, int pos) {
if (key == null) throw parser.Err_row_bgn("prefab missing key", pos);
mgr.Add(key);
}
}

View File

@@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.parsers.logs.*;
import gplx.xowa.html.*;
public class Hiero_xnde implements Xox_xnde, Xop_xnde_atr_parser {
private Hiero_xtn_mgr xtn_mgr;
private Hiero_block[] blocks;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_bgn);
xtn_mgr = (Hiero_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Hiero_xtn_mgr.Xtn_key_static);
xtn_mgr.Xtn_init_assert(wiki);
ctx.Cur_page().Html_data().Module_mgr().Itm__hiero().Enabled_y_();
blocks = xtn_mgr.Parser().Parse(src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
boolean log_wkr_enabled = Log_wkr != Xop_log_basic_wkr.Null; if (log_wkr_enabled) Log_wkr.Log_end_xnde(ctx.Cur_page(), Xop_log_basic_wkr.Tid_hiero, src, xnde);
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end);
switch (ctx.Cur_tkn_tid()) {
case Xop_tkn_itm_.Tid_list: // NOTE: if inside list, do not reenable para mode; questionable logic; PAGE:de.d:Damascus;DATE:2014-06-06
break;
default:
ctx.Para().Process_nl(ctx, root, src, xnde.Tag_close_end(), xnde.Tag_close_end()); // NOTE: this should create an extra stub "p" so that remaining text gets enclosed in <p>; EX:w:Hieroglyphics;
break;
}
} public static Xop_log_basic_wkr Log_wkr = Xop_log_basic_wkr.Null;
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
xtn_mgr.Html_wtr().Render_blocks(bfr, hctx, blocks, Hiero_html_mgr.scale, false);
}
}

View File

@@ -0,0 +1,57 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.hieros; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.wikis.*; import gplx.xowa.html.modules.*; import gplx.xowa.apps.fsys.*;
public class Hiero_xtn_mgr extends Xox_mgr_base implements GfoInvkAble {
@Override public boolean Enabled_default() {return true;}
@Override public byte[] Xtn_key() {return Xtn_key_static;} public static final byte[] Xtn_key_static = Bry_.new_a7("hiero");
@Override public Xox_mgr Clone_new() {return new Hiero_xtn_mgr();}
public static byte[] Img_src_dir;
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {}
private static boolean xtn_init_done = false;
public void Xtn_init_assert(Xowe_wiki wiki) {
if (xtn_init_done) return;
if (!Enabled()) return;
Xoae_app app = wiki.Appe();
Io_url ext_root_dir = Hiero_root_dir(app.Fsys_mgr());
Img_src_dir = Bry_.new_u8(ext_root_dir.GenSubDir("img").To_http_file_str());
app.Gfs_mgr().Run_url_for(this, ext_root_dir.GenSubFil_nest("data", "tables.gfs"));
html_wtr = new Hiero_html_mgr(this);
parser.Init();
xtn_init_done = true;
}
@gplx.Internal protected Hiero_parser Parser() {return parser;} private static final Hiero_parser parser = new Hiero_parser();
@gplx.Internal protected Hiero_prefab_mgr Prefab_mgr() {return prefab_mgr;} private static final Hiero_prefab_mgr prefab_mgr = new Hiero_prefab_mgr();
@gplx.Internal protected Hiero_file_mgr File_mgr() {return file_mgr;} private static final Hiero_file_mgr file_mgr = new Hiero_file_mgr();
@gplx.Internal protected Hiero_phoneme_mgr Phoneme_mgr() {return phoneme_mgr;} private static final Hiero_phoneme_mgr phoneme_mgr = new Hiero_phoneme_mgr();
@gplx.Internal protected Hiero_html_mgr Html_wtr() {return html_wtr;} private static Hiero_html_mgr html_wtr;
public void Clear() {
prefab_mgr.Clear();
file_mgr.Clear();
phoneme_mgr.Clear();
}
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_prefabs)) return prefab_mgr;
else if (ctx.Match(k, Invk_files)) return file_mgr;
else if (ctx.Match(k, Invk_phonemes)) return phoneme_mgr;
else return super.Invk(ctx, ikey, k, m);
}
public static final String Invk_prefabs = "prefabs", Invk_files = "files", Invk_phonemes = "phonemes";
public static void Hiero_root_dir_(Io_url v) {hiero_root_dir = v;} private static Io_url hiero_root_dir;
public static Io_url Hiero_root_dir(Xoa_fsys_mgr fsys_mgr) {return hiero_root_dir == null ? fsys_mgr.Bin_xtns_dir().GenSubDir("Wikihiero") : hiero_root_dir;}
}

View File

@@ -0,0 +1,71 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
class Imap_desc_tid {
public static final byte Tid_tr = 0, Tid_br = 1, Tid_bl = 2, Tid_tl = 3, Tid_none = 4, Tid_null = 5;
public static final byte[]
Key_tr = Bry_.new_a7("top-right")
, Key_br = Bry_.new_a7("bottom-right")
, Key_bl = Bry_.new_a7("bottom-left")
, Key_tl = Bry_.new_a7("top-left")
, Key_none = Bry_.new_a7("none")
;
public static Btrie_slim_mgr trie_(Xowe_wiki wiki) {
Btrie_slim_mgr rv = Btrie_slim_mgr.ci_utf_8_();
trie_add(rv, Key_tr, Key_br, Key_bl, Key_tl, Key_none);
byte[][] lang_types = Parse_lang_types(wiki);
if (lang_types != null)
trie_add(rv, lang_types);
return rv;
}
private static void trie_add(Btrie_slim_mgr trie, byte[]... ary) {
trie.Add_bry_bval(ary[0] ,Tid_tr);
trie.Add_bry_bval(ary[1] ,Tid_br);
trie.Add_bry_bval(ary[2] ,Tid_bl);
trie.Add_bry_bval(ary[3] ,Tid_tl);
trie.Add_bry_bval(ary[4] ,Tid_none);
}
private static byte[][] Parse_lang_types(Xowe_wiki wiki) {
byte[] val = wiki.Msg_mgr().Val_by_key_obj("imagemap_desc_types");
if (Bry_.Len_eq_0(val)) return null; // no msg in lang; return;
byte[][] ary = Bry_.Split(val, Byte_ascii.Comma); // msg is 5 words concatenated by comma: EX:top-right,bottom-right-bottom-left,top-left,none
int ary_len = ary.length;
if (ary_len != 5) wiki.Appe().Usr_dlg().Warn_many("", "", "imap_desc does not have 5 items; wiki=~{0} val=~{1}", wiki.Domain_bry(), val);
for (int i = 0; i < 5; ++i)
ary[i] = Bry_.Trim(ary[i]); // note that items will have trailing ws; EX: "top-right, bottom-right, bottom-left, top-left, none"
return ary;
}
public static byte parse_(Btrie_slim_mgr trie, byte[] src, int bgn, int end) {
Object rv = trie.Match_bgn(src, bgn, end);
return rv == null ? Tid_null : ((Byte_obj_val)rv).Val();
}
public static void Calc_desc_margins(Int_2_ref rv, byte tid, int html_w, int html_h) {
int margin_l
= tid == Tid_tl || tid == Tid_bl
? 0
: html_w - 20
;
int margin_t
= tid == Tid_tl || tid == Tid_tr
? -html_h + 1 // 1px hack for IE, to stop it poking out the top
: -20
;
rv.Val_all_(margin_l, margin_t);
}
}

View File

@@ -0,0 +1,65 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
class Imap_html_fmtrs {
public static final Bry_fmtr
All = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( "<div id='imap_div_~{imap_id}' class=\"noresize\"~{desc_style}>~{map}~{img}"
, " </div>"
), "imap_id", "desc_style", "map", "img"
)
, Map = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <map name=\"imageMap_1_~{imap_id}\">~{shapes}"
, " </map>"
), "imap_id", "shapes"
)
, Area = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( "\n <area href=\"~{href}\" shape=\"~{shape}\" coords=\"~{coords}\" alt=\"~{title}\" title=\"~{title}\"/>"
), "href", "shape", "coords", "title")
, Img_anchor_none = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <img id=\"xowa_file_img_~{img_elem_id}\" alt=\"~{img_alt}\"~{img_core}~{img_cls} usemap=\"#imageMap_1_~{imap_id}\"/>"
), "imap_id", "img_elem_id", "img_alt", "img_core", "img_cls", "anchor_href", "anchor_title"
)
, Img_anchor_lnki = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <a href=\"~{anchor_href}\" title=\"~{anchor_title}\">"
, " <img id=\"xowa_file_img_~{img_elem_id}\" alt=\"~{img_alt}\"~{img_core}~{img_cls} usemap=\"#imageMap_1_~{imap_id}\"/>"
, " </a>"
), "imap_id", "img_elem_id", "img_alt", "img_core", "img_cls", "anchor_href", "anchor_title"
)
, Img_anchor_lnke = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <a href=\"~{anchor_href}\" title=~{anchor_title} class=\"plainlinks\" rel=\"nofollow\">"
, " <img id=\"xowa_file_img_~{img_elem_id}\" alt=\"~{img_alt}\"~{img_core}~{img_cls} usemap=\"#imageMap_1_~{imap_id}\"/>"
, " </a>"
), "imap_id", "img_elem_id", "img_alt", "img_core", "img_cls", "anchor_href", "anchor_title"
)
, Desc_style = Bry_fmtr.new_(" style=\"height:~{div_h}px; width: ~{div_w}px;\"", "div_w", "div_h")
, Desc_main = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <div style=\"margin-left:~{margin_left}px; margin-top:~{margin_top}px; text-align:left;\">"
, " <a href=\"~{img_href}\" title=\"~{msg_desc}\">"
, " <img alt=\"~{msg_desc}\" src=\"~{icon_url}\" style=\"border: none;\" />"
, " </a>"
, " </div>"
), "margin_left", "margin_top", "img_href", "msg_desc", "icon_url"
)
;
}

View File

@@ -0,0 +1,52 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*; import gplx.xowa.html.lnkis.*;
class Imap_img_fmtr_arg implements Bry_fmtr_arg {
private Xoh_wtr_ctx hctx; private Imap_map map; private Imap_xtn_mgr xtn_mgr;
private int img_elem_id, img_w, img_h;
private byte[] img_alt, img_src, img_cls, img_href;
private Int_2_ref margin_calc = new Int_2_ref();
public void Init(Xoh_wtr_ctx hctx, Imap_xtn_mgr xtn_mgr, Imap_map map, int img_elem_id, byte[] img_alt, byte[] img_src, int img_w, int img_h, byte[] img_cls, byte[] img_href) {
this.hctx = hctx; this.map = map; this.xtn_mgr = xtn_mgr;
this.img_elem_id = img_elem_id; this.img_w = img_w; this.img_h = img_h;
this.img_alt = img_alt;
this.img_src = img_src;
this.img_cls = img_cls;
this.img_href = img_href;
}
public void XferAry(Bry_bfr bfr, int idx) {
Bry_fmtr fmtr = Imap_html_fmtrs.Img_anchor_none;
byte[] anchor_href = Bry_.Empty, anchor_text = Bry_.Empty;
Imap_itm_dflt itm_dflt = map.Dflt();
boolean hctx_is_hdump = hctx.Mode_is_hdump();
Xoh_arg_img_core img_core_fmtr = xtn_mgr.Img_core_fmtr(hctx_is_hdump);
img_core_fmtr.Init(img_elem_id, img_src, img_w, img_h);
if (itm_dflt != null) {
fmtr = itm_dflt.Link_tid() == Xop_tkn_itm_.Tid_lnki ? Imap_html_fmtrs.Img_anchor_lnki : Imap_html_fmtrs.Img_anchor_lnke;
anchor_href = itm_dflt.Link_href();
anchor_text = itm_dflt.Link_text();
}
fmtr.Bld_bfr_many(bfr, map.Id(), img_elem_id, img_alt, img_core_fmtr, img_cls, anchor_href, anchor_text);
Imap_itm_desc itm_desc = map.Desc();
if (itm_desc != null) {
Imap_desc_tid.Calc_desc_margins(margin_calc, itm_desc.Desc_tid(), img_w, img_h);
Imap_html_fmtrs.Desc_main.Bld_bfr_many(bfr, margin_calc.Val_0(), margin_calc.Val_1(), img_href, xtn_mgr.Desc_msg(), xtn_mgr.Desc_icon_url());
}
}
}

View File

@@ -0,0 +1,59 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
interface Imap_itm {
byte Itm_tid();
}
class Imap_itm_ {
public static final byte Tid_invalid = 0, Tid_img = 1, Tid_desc = 2, Tid_comment = 3, Tid_dflt = 4, Tid_shape_rect = 5, Tid_shape_circle = 6, Tid_shape_poly = 7;
public static final byte[]
Key_dflt = Bry_.new_a7("default")
, Key_shape_rect = Bry_.new_a7("rect")
, Key_shape_circle = Bry_.new_a7("circle")
, Key_shape_poly = Bry_.new_a7("poly")
;
public static byte[] Xto_key(byte v) {
switch (v) {
case Tid_shape_rect : return Key_shape_rect;
case Tid_shape_circle : return Key_shape_circle;
case Tid_shape_poly : return Key_shape_poly;
default : throw Exc_.new_unhandled(v);
}
}
}
class Imap_itm_img implements Imap_itm {
public Imap_itm_img(Xop_lnki_tkn img_link) {this.img_link = img_link;}
public byte Itm_tid() {return Imap_itm_.Tid_img;}
public Xop_lnki_tkn Img_link() {return img_link;} private Xop_lnki_tkn img_link;
}
class Imap_itm_desc implements Imap_itm {
public Imap_itm_desc(byte desc_tid) {this.desc_tid = desc_tid;}
public byte Itm_tid() {return Imap_itm_.Tid_desc;}
public byte Desc_tid() {return desc_tid;} private byte desc_tid;
}
class Imap_itm_dflt implements Imap_itm, Imap_link_owner {
public byte Itm_tid() {return Imap_itm_.Tid_dflt;}
public int Link_tid() {return link_tid;} public void Link_tid_(int v) {link_tid = v;} private int link_tid;
public byte[] Link_href() {return link_href;} public void Link_href_(byte[] v) {this.link_href = v;} private byte[] link_href;
public byte[] Link_text() {return link_text;} public void Link_text_(byte[] v) {this.link_text = v;} private byte[] link_text;
}
class Imap_err {
public Imap_err(int itm_idx, String err_key) {this.itm_idx = itm_idx; this.err_key = err_key;}
public int Itm_idx() {return itm_idx;} private int itm_idx;
public String Err_key() {return err_key;} private String err_key;
}

View File

@@ -0,0 +1,67 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.xowa.parsers.lnkes.*; import gplx.xowa.html.*; import gplx.xowa.net.*;
interface Imap_link_owner {
void Link_tid_(int v);
void Link_href_(byte[] v);
void Link_text_(byte[] v);
}
class Imap_link_owner_ {
public static void Init(Imap_link_owner link_owner, Xoae_app app, Xowe_wiki wiki, byte[] src, Xop_tkn_itm tkn) {
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
try {
int tkn_tid = tkn.Tkn_tid();
link_owner.Link_tid_(tkn_tid);
switch (tkn_tid) {
case Xop_tkn_itm_.Tid_lnki: {
Xop_lnki_tkn lnki_tkn = (Xop_lnki_tkn)tkn;
link_owner.Link_href_(app.Href_parser().Build_to_bry(wiki, lnki_tkn.Ttl()));
wiki.Html_mgr().Html_wtr().Lnki_wtr().Write_caption(bfr, Xoh_wtr_ctx.Alt, src, lnki_tkn, lnki_tkn.Ttl());
link_owner.Link_text_(bfr.Xto_bry_and_clear());
break;
}
case Xop_tkn_itm_.Tid_lnke: {
Xop_lnke_tkn lnke = (Xop_lnke_tkn)tkn;
Xop_ctx ctx = wiki.Ctx();
int lnke_bgn = lnke.Lnke_bgn(), lnke_end = lnke.Lnke_end(); boolean proto_is_xowa = lnke.Proto_tid() == Xoo_protocol_itm.Tid_xowa;
Xoh_lnke_wtr lnke_wtr = wiki.Html_mgr().Html_wtr().Lnke_wtr();
lnke_wtr.Write_href(bfr, ctx, src, lnke, lnke_bgn, lnke_end, proto_is_xowa);
link_owner.Link_href_(bfr.Xto_bry_and_clear());
lnke_wtr.Write_caption(bfr, wiki.Html_mgr().Html_wtr(), Xoh_wtr_ctx.Basic, ctx, src, lnke, lnke_bgn, lnke_end, proto_is_xowa);
link_owner.Link_text_(bfr.Xto_bry_and_clear());
break;
}
}
}
finally {bfr.Mkr_rls();} // release buffer in case of null error; PAGE:de.u:PPA/Raster/TK25/51/18/12/20; DATE:2015-02-02
}
}
class Imap_itm_shape implements Imap_itm, Imap_link_owner {
public Imap_itm_shape(byte shape_tid, Double_obj_val[] shape_pts) {
this.shape_tid = shape_tid;
this.shape_pts = shape_pts;
}
public byte Itm_tid() {return shape_tid;} private byte shape_tid;
public Double_obj_val[] Shape_pts() {return shape_pts;} private Double_obj_val[] shape_pts;
public int Link_tid() {return link_tid;} public void Link_tid_(int v) {link_tid = v;} private int link_tid;
public byte[] Link_href() {return link_href;} public void Link_href_(byte[] v) {this.link_href = v;} private byte[] link_href;
public byte[] Link_text() {return link_text;} public void Link_text_(byte[] v) {this.link_text = v;} private byte[] link_text;
public static final byte Tid_default = 0, Tid_rect = 4, Tid_circle = 3, Tid_poly = 5;
}

View File

@@ -0,0 +1,73 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.files.*; import gplx.xowa.html.*; import gplx.xowa.files.gui.*; import gplx.xowa.gui.views.*; import gplx.xowa.html.lnkis.*;
import gplx.xowa.html.hdumps.core.*;
public class Imap_map implements Xoh_file_img_wkr, Js_img_wkr {
private static final Imap_map_fmtr map_fmtr_arg = new Imap_map_fmtr();
public Imap_map(int id) {this.id = id;}
public Imap_xtn_mgr Xtn_mgr() {return xtn_mgr;} private Imap_xtn_mgr xtn_mgr;
@gplx.Internal protected void Init(Imap_xtn_mgr xtn_mgr, byte[] img_src, Imap_itm_img img, Imap_itm_dflt dflt, Imap_itm_desc desc, Imap_itm_shape[] shapes, Imap_err[] errs) {
this.xtn_mgr = xtn_mgr; this.img_src = img_src; this.img = img; this.dflt = dflt; this.desc = desc; this.shapes = shapes; this.errs = errs;
}
public boolean Invalid() {return img == null;} // invalid if missing image; PAGE:en.w:Wikipedia:WikiProject_Games/Advert EX: <imagemap>|thumb;</imagemap>; DATE:2014-08-12
public int Id() {return id;} private int id;
public byte[] Img_src() {return img_src;} private byte[] img_src;
@gplx.Internal protected Imap_itm_img Img() {return img;} private Imap_itm_img img;
@gplx.Internal protected Imap_itm_dflt Dflt() {return dflt;} private Imap_itm_dflt dflt;
@gplx.Internal protected Imap_itm_desc Desc() {return desc;} private Imap_itm_desc desc;
@gplx.Internal protected Imap_itm_shape[] Shapes() {return shapes;} private Imap_itm_shape[] shapes;
@gplx.Internal protected Imap_err[] Errs() {return errs;} private Imap_err[] errs;
private byte img_cls_tid;
private byte[] a_href, img_alt, img_cls_other;
public void Html_full_img(Bry_bfr tmp_bfr, Xoh_wtr_ctx hctx, Xoae_page page, Xof_file_itm xfer_itm, int uid
, byte[] a_href, byte a_cls, byte a_rel, byte[] a_title, byte[] a_xowa_title
, int img_w, int img_h, byte[] img_src, byte[] img_alt, byte img_cls, byte[] img_cls_other
) {
xfer_itm.Html_img_wkr_(this);
xfer_itm.Html_elem_tid_(Xof_html_elem.Tid_imap);
this.a_href = a_href; this.img_alt = img_alt; this.img_cls_tid = img_cls; this.img_cls_other = img_cls_other;
Write_imap_div(tmp_bfr, hctx, uid, img_w, img_h, img_src, xfer_itm.Orig_w(), xfer_itm.Orig_h());
if (hctx.Mode_is_hdump())
page.Hdump_data().Imgs_add_img(new Xohd_data_itm__img(), xfer_itm, Xohd_data_itm__gallery_itm.Tid_basic);
}
public void Html_update(Xoa_page page, Xog_js_wkr js_wkr, int html_uid, int html_w, int html_h, Io_url html_view_url, int orig_w, int orig_h, Io_url html_orig_url, byte[] lnki_ttl) {
Xowe_wiki wiki = xtn_mgr.Wiki();
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_k004();
Write_imap_div(tmp_bfr, Xoh_wtr_ctx.Basic, html_uid, html_w, html_h, html_view_url.To_http_file_bry(), orig_w, orig_h);
js_wkr.Html_elem_replace_html("imap_div_" + Int_.Xto_str(html_uid), tmp_bfr.To_str_and_rls());
}
private void Write_imap_div(Bry_bfr bfr, Xoh_wtr_ctx hctx, int html_uid, int html_w, int html_h, byte[] html_src, int orig_w, int orig_h) {
byte[] desc_style = Calc_desc_style(html_w, html_h);
map_fmtr_arg.Init(id, shapes, Calc_scale(orig_w, orig_h, html_w, html_h));
img_fmtr_arg.Init(hctx, xtn_mgr, this, html_uid, img_alt, html_src, html_w, html_h, Xoh_lnki_consts.Img_cls_to_bry(img_cls_tid, img_cls_other), a_href);
Imap_html_fmtrs.All.Bld_bfr_many(bfr, html_uid, desc_style, map_fmtr_arg, img_fmtr_arg);
}
private byte[] Calc_desc_style(int html_w, int html_h) {
if (desc == null) return Bry_.Empty;
Bry_bfr tmp_bfr = xtn_mgr.Wiki().Utl__bfr_mkr().Get_b128().Mkr_rls();
return Imap_html_fmtrs.Desc_style.Bld_bry_many(tmp_bfr, html_w, html_h);
}
private static final Imap_img_fmtr_arg img_fmtr_arg = new Imap_img_fmtr_arg();
private static double Calc_scale(int orig_w, int orig_h, int html_w, int html_h) {
int denominator = orig_w + orig_h;
int numerator = html_w + html_h;
if (denominator <= 0 || numerator <= 0) return 1; // return identity; note that MW does "return self::error( 'imagemap_invalid_image' );"
return (double)numerator / (double)denominator;
}
}

View File

@@ -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.xtns.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
class Imap_map_fmtr implements Bry_fmtr_arg {
private int imap_id;
public void Init(int imap_id, Imap_itm_shape[] shapes, double scale) {this.imap_id = imap_id; shapes_fmtr_arg.Init(shapes, scale);}
public Imap_pts_fmtr_arg Pts_fmtr() {return shapes_fmtr_arg.Pts_fmtr();}
public void XferAry(Bry_bfr bfr, int idx) {
Imap_html_fmtrs.Map.Bld_bfr_many(bfr, imap_id, shapes_fmtr_arg);
}
private static final Imap_shapes_fmtr shapes_fmtr_arg = new Imap_shapes_fmtr();
}
class Imap_shapes_fmtr implements Bry_fmtr_arg {
private Imap_itm_shape[] shapes;
public void Init(Imap_itm_shape[] shapes, double scale) {this.shapes = shapes; pts_fmtr_arg.Scale_(scale);}
public Imap_pts_fmtr_arg Pts_fmtr() {return pts_fmtr_arg;}
public void XferAry(Bry_bfr bfr, int idx) {
int shapes_len = shapes.length;
Bry_fmtr fmtr = Imap_html_fmtrs.Area;
for (int i = 0; i < shapes_len; ++i) {
Imap_itm_shape shape = shapes[i];
Fmt_shape(bfr, fmtr, pts_fmtr_arg, shape);
}
}
@gplx.Internal protected static void Fmt_shape(Bry_bfr bfr, Bry_fmtr fmtr, Imap_pts_fmtr_arg pts_fmtr, Imap_itm_shape shape) {
pts_fmtr_arg.Pts_(shape.Shape_pts());
fmtr.Bld_bfr_many(bfr
, shape.Link_href()
, Imap_itm_.Xto_key(shape.Itm_tid())
, pts_fmtr_arg
, shape.Link_text()
);
}
private static final Imap_pts_fmtr_arg pts_fmtr_arg = new Imap_pts_fmtr_arg();
}

View File

@@ -0,0 +1,234 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*; import gplx.core.primitives.*; import gplx.xowa.parsers.lnkis.redlinks.*;
class Imap_parser {
private Imap_xtn_mgr xtn_mgr; private Xoa_url page_url; private Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.I;
private byte[] imap_img_src;
private Imap_itm_img imap_img;
private Imap_itm_dflt imap_dflt;
private Imap_itm_desc imap_desc;
private List_adp shapes = List_adp_.new_(), pts = List_adp_.new_(), errs = List_adp_.new_();
private byte[] src;
private int itm_idx; private int itm_bgn, itm_end;
private Xoae_app app; private Xowe_wiki wiki; private Xop_ctx wiki_ctx, imap_ctx; private Xop_root_tkn imap_root;
public Imap_parser(Imap_xtn_mgr xtn_mgr) {this.xtn_mgr = xtn_mgr;}
public void Init(Xowe_wiki wiki, Xoa_url page_url, Gfo_usr_dlg usr_dlg) {
this.app = wiki.Appe(); this.wiki = wiki; this.page_url = page_url; this.usr_dlg = usr_dlg;
this.wiki_ctx = wiki.Ctx();
if (imap_ctx == null) {
imap_ctx = Xop_ctx.new_(wiki);
imap_root = app.Tkn_mkr().Root(Bry_.Empty);
}
}
public void Clear() {
this.itm_idx = 0;
imap_img = null; imap_img_src = null; imap_desc = null; imap_dflt = null;
shapes.Clear(); pts.Clear(); errs.Clear();
}
public Imap_map Parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
Imap_map rv = new Imap_map(ctx.Cur_page().Html_data().Xtn_imap_next_id());
Init(wiki, ctx.Cur_page().Url(), wiki.Appe().Usr_dlg());
this.Parse(rv, src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
return rv;
}
public void Parse(Imap_map rv, byte[] src, int src_bgn, int src_end) {
this.Clear();
this.src = src;
itm_bgn = src_bgn; itm_end = src_bgn - 1;
while (true) {
if (itm_end == src_end) break;
itm_bgn = Bry_finder.Trim_fwd_space_tab(src, itm_end + 1, src_end); // trim ws at start, and look for first char
if (itm_bgn == src_end) break; // line is entirely ws and terminated by eos; EX: "\n EOS"
itm_end = Bry_finder.Find_fwd_until(src, itm_bgn, src_end, Byte_ascii.Nl); // look for \n
if (itm_end == Bry_finder.Not_found) itm_end = src_end; // no \n; make EOS = \n
itm_end = Bry_finder.Trim_bwd_space_tab(src, itm_end, itm_bgn); // trim any ws at end
if (itm_end - itm_bgn == 0) continue; // line is entirely ws; continue;
byte b = src[itm_bgn];
if (b == Byte_ascii.Hash) {
Parse_comment(itm_bgn, itm_end);
continue;
}
try {
if (itm_idx == 0)
itm_end = Parse_img(rv, itm_bgn, itm_end, src_end);
else {
Object tid_obj = tid_trie.Match_bgn_w_byte(b, src, itm_bgn, itm_end);
byte tid_val = tid_obj == null ? Imap_itm_.Tid_invalid : ((Byte_obj_val)tid_obj).Val();
int tid_end_pos = tid_trie.Match_pos();
switch (tid_val) {
case Imap_itm_.Tid_desc: Parse_desc(tid_end_pos, itm_end); break;
case Imap_itm_.Tid_dflt: Parse_dflt(tid_end_pos, itm_end); break;
case Imap_itm_.Tid_shape_rect: Parse_shape(tid_val, tid_end_pos, itm_bgn, itm_end, 4); break;
case Imap_itm_.Tid_shape_poly: Parse_shape(tid_val, tid_end_pos, itm_bgn, itm_end, Reqd_poly); break;
case Imap_itm_.Tid_shape_circle: Parse_shape(tid_val, tid_end_pos, itm_bgn, itm_end, 3); break;
default:
case Imap_itm_.Tid_invalid: Parse_invalid(itm_bgn, itm_end); break;
}
}
} catch (Exception e) {usr_dlg.Warn_many("", "", "imap.parse:skipping line; page=~{0} line=~{1} err=~{2}", page_url.Xto_full_str_safe(), Bry_.Mid_safe(src, itm_bgn, itm_end), Err_.Message_gplx(e));}
++itm_idx;
}
rv.Init(xtn_mgr, imap_img_src, imap_img, imap_dflt, imap_desc, (Imap_itm_shape[])shapes.To_ary_and_clear(Imap_itm_shape.class), (Imap_err[])errs.To_ary_and_clear(Imap_err.class));
}
private void Parse_comment(int itm_bgn, int itm_end) {} // noop comments; EX: "# comment\n"
private void Parse_invalid(int itm_bgn, int itm_end) {usr_dlg.Warn_many("", "", "imap has invalid line: page=~{0} line=~{1}", page_url.Xto_full_str_safe(), String_.new_u8(src, itm_bgn, itm_end));}
private boolean Parse_desc(int itm_bgn, int itm_end) {
xtn_mgr.Desc_assert();
Btrie_slim_mgr trie = xtn_mgr.Desc_trie();
byte tid_desc = Imap_desc_tid.parse_(trie, src, Bry_finder.Trim_fwd_space_tab(src, itm_bgn, itm_end), Bry_finder.Trim_bwd_space_tab(src, itm_bgn, itm_end));
switch (tid_desc) {
case Imap_desc_tid.Tid_null: return Add_err(Bool_.N, itm_bgn, itm_end, "imagemap_invalid_coord");
case Imap_desc_tid.Tid_none: return true;
}
if (imap_img == null || imap_img.Img_link().Lnki_type() == Xop_lnki_type.Id_thumb) return true; // thumbs don't get desc
imap_desc = new Imap_itm_desc(tid_desc);
return true;
}
private void Parse_dflt(int itm_bgn, int itm_end) {
imap_dflt = new Imap_itm_dflt();
Init_link_owner(imap_dflt, src, itm_bgn, itm_end);
}
private boolean Parse_shape(byte shape_tid, int tid_end_pos, int itm_bgn, int itm_end, int reqd_pts) {
boolean shape_is_poly = shape_tid == Imap_itm_.Tid_shape_poly;
int pos = Bry_finder.Trim_fwd_space_tab(src, tid_end_pos, itm_end); // gobble any leading spaces
int grp_end = Bry_finder.Find_fwd(src, Byte_ascii.Brack_bgn, pos, itm_end); // find first "["; note that this is a lazy way of detecting start of lnki / lnke; MW has complicated regex, but hopefully this will be enough; DATE:2014-10-22
if (grp_end == -1) {return Add_err(Bool_.Y, itm_bgn, itm_end, "No valid link was found");}
int num_bgn = -1, comma_pos = -1, pts_len = 0;
while (true) {
boolean last = pos == grp_end;
byte b = last ? Byte_ascii.Space : src[pos];
switch (b) {
case Byte_ascii.Comma: if (comma_pos == -1) comma_pos = pos; break;
default: if (num_bgn == -1) num_bgn = pos; break;
case Byte_ascii.Space: case Byte_ascii.Tab:
if (num_bgn != -1) {
byte[] num_bry = comma_pos == -1 ? Bry_.Mid(src, num_bgn, pos) : Bry_.Mid(src, num_bgn, comma_pos); // if commas exist, treat first as decimal; echo(intval(round('1,2,3,4' * 1))) -> 1; PAGE:fr.w:Gouesnou; DATE:2014-08-12
double num = Bry_.Xto_double_or(num_bry, Double_.NaN);
if (Double_.IsNaN(num)) {
if (shape_is_poly) // poly code in ImageMap_body.php accepts invalid words and converts to 0; EX:"word1"; PAGE:uk.w:Стратосфера; DATE:2014-07-26
num = 0;
else
return Add_err(Bool_.Y, itm_bgn, itm_end, "imagemap_invalid_coord");
}
num_bgn = -1; comma_pos = -1;
pts.Add(Double_obj_val.new_(num));
++pts_len;
if (pts_len == reqd_pts) // NOTE: MW allows more points, but doesn't show them; EX: rect 1 2 3 4 5 -> rect 1 2 3 4; PAGE:en.w:Kilauea DATE:2014-07-28; EX:1 2 3 4 <!-- --> de.w:Wilhelm_Angele DATE:2014-10-30
last = true;
}
break;
}
if (last) break;
++pos;
}
if (reqd_pts == Reqd_poly) {
if (pts_len == 0) return Add_err(Bool_.Y, itm_bgn, itm_end, "imagemap_missing_coord");
else if (pts_len % 2 != 0) return Add_err(Bool_.Y, itm_bgn, itm_end, "imagemap_poly_odd");
}
else {
if (pts_len < reqd_pts) return Add_err(Bool_.Y, itm_bgn, itm_end, "imagemap_missing_coord");
}
pos = Bry_finder.Trim_fwd_space_tab(src, pos, itm_end);
Imap_itm_shape shape_itm = new Imap_itm_shape(shape_tid, (Double_obj_val[])pts.To_ary_and_clear(Double_obj_val.class));
Init_link_owner(shape_itm, src, pos, itm_end);
shapes.Add(shape_itm);
return true;
}
private boolean Add_err(boolean clear_pts, int bgn, int end, String err_key) {
usr_dlg.Warn_many("", "", err_key + ": page=~{0} line=~{1}", page_url.Xto_full_str_safe(), String_.new_u8(src, bgn, end));
errs.Add(new Imap_err(itm_idx, err_key));
if (clear_pts) pts.Clear();
return false;
}
private void Init_link_owner(Imap_link_owner link_owner, byte[] src, int bgn, int end) {
byte[] link_tkn_src = Bry_.Mid(src, bgn, end);
Xop_tkn_itm link_tkn = Parse_link(link_tkn_src);
if (link_tkn == null) {Add_err(Bool_.N, bgn, end, "imap.invalid link_owner"); return;} // exit early if invalid; PAGE:de.u:PPA/Raster/TK25/51/18/12/20; DATE:2015-02-02
link_tkn_src = imap_root.Data_mid(); // NOTE:must re-set link_tkn_src since link_tkn is expanded wikitext; i.e.: not "{{A}}" but "expanded"; PAGE:fr.w:Arrondissements_de_Lyon DATE:2014-08-12
Imap_link_owner_.Init(link_owner, app, wiki, link_tkn_src, link_tkn);
}
private Xop_tkn_itm Parse_link(byte[] raw) {
imap_root.Clear();
imap_ctx.Clear();
wiki.Parser().Parse_text_to_wdom(imap_root, imap_ctx, wiki.Appe().Tkn_mkr(), raw, 0);
int subs_len = imap_root.Subs_len();
for (int i = 0; i < subs_len; ++i) {
Xop_tkn_itm sub = imap_root.Subs_get(i);
switch (sub.Tkn_tid()) {
case Xop_tkn_itm_.Tid_lnki:
case Xop_tkn_itm_.Tid_lnke:
return sub;
}
}
return null;
}
private int Parse_img(Imap_map imap, int itm_bgn, int itm_end, int src_end) {
int img_bgn = Bry_finder.Trim_fwd_space_tab(src, itm_bgn, itm_end); // trim ws
int img_end = Parse_img__get_img_end(itm_end, src_end);
imap_img_src = Bry_.Add(Xop_tkn_.Lnki_bgn, Bry_.Mid(src, img_bgn, img_end), Xop_tkn_.Lnki_end);
Xop_tkn_itm tkn_itm = Parse_link(imap_img_src); // NOTE: need to parse before imap_root.Data_mid() below
imap_img_src = imap_root.Data_mid(); // need to re-set src to pick up templates; EX: <imagemap>File:A.png|thumb|{{Test_template}}\n</imagemap>; PAGE:en.w:Kilauea; DATE:2014-07-27
Xopg_redlink_logger file_wkr = wiki_ctx.Lnki().File_wkr(); // NOTE: do not do imap_ctx.Lnki(); imap_ctx is brand new
if ( tkn_itm == null // no lnki or lnke
|| tkn_itm.Tkn_tid() != Xop_tkn_itm_.Tid_lnki // no lnki; occurs with badly constructed maps; PAGE:en.w:Demography_of_the_United_Kingdom DATE:2015-01-22
)
imap_ctx.Wiki().Appe().Usr_dlg().Warn_many("", "", "image_map failed to find lnki; page=~{0} imageMap=~{1}", String_.new_u8(imap_ctx.Cur_page().Ttl().Full_txt()), String_.new_u8(imap_img_src));
else {
Xop_lnki_tkn lnki_tkn = (Xop_lnki_tkn)tkn_itm;
imap_img = new Imap_itm_img(lnki_tkn);
lnki_tkn.Lnki_file_wkr_(imap);
wiki_ctx.Cur_page().Lnki_list().Add(lnki_tkn);
if (file_wkr != null) file_wkr.Wkr_exec(wiki_ctx, src, lnki_tkn, gplx.xowa.bldrs.cmds.files.Xob_lnki_src_tid.Tid_imageMap);
}
return img_end;
}
private int Parse_img__get_img_end(int line_end, int src_end) { // heuristic to handle images that span more than one line via ref; en.w:Archaea DATE:2014-08-22
int rv = line_end;
int pos = line_end + 1;
while (pos < src_end) {
pos = Bry_finder.Trim_fwd_space_tab(src, pos, src_end); // trim ws
if (pos == src_end) break;
byte b = src[pos];
if (b == Byte_ascii.Nl) // new-line; end
break;
else {
Object tid_obj = tid_trie.Match_bgn_w_byte(b, src, pos, src_end);
if (tid_obj == null) { // not a known imap line; assume continuation of img line and skip to next line
imap_ctx.Wiki().Appe().Usr_dlg().Note_many("", "", "image_map extending image over multiple lines; page=~{0} imageMap=~{1}", String_.new_u8(imap_ctx.Cur_page().Ttl().Full_txt()), String_.new_u8(imap_img_src));
int next_line = Bry_finder.Find_fwd(src, Byte_ascii.Nl, pos);
if (next_line == Bry_finder.Not_found) next_line = src_end;
rv = next_line;
pos = rv + 1;
}
else // known imap line; stop
break;
}
}
return rv;
}
private static Btrie_slim_mgr tid_trie = Btrie_slim_mgr.ci_ascii_() // names are not i18n'd; // NOTE:ci.ascii:MW_const.en
.Add_str_byte("desc" , Imap_itm_.Tid_desc)
.Add_str_byte("#" , Imap_itm_.Tid_comment)
.Add_bry_bval(Imap_itm_.Key_dflt , Imap_itm_.Tid_dflt)
.Add_bry_bval(Imap_itm_.Key_shape_rect , Imap_itm_.Tid_shape_rect)
.Add_bry_bval(Imap_itm_.Key_shape_circle , Imap_itm_.Tid_shape_circle)
.Add_bry_bval(Imap_itm_.Key_shape_poly , Imap_itm_.Tid_shape_poly)
;
private static final int Reqd_poly = -1;
}

View File

@@ -0,0 +1,101 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.core.primitives.*;
public class Imap_parser_tst {
@Before public void init() {fxt.Reset();} private Imap_parser_fxt fxt = new Imap_parser_fxt();
@Test public void Rect_pass() {fxt.Test_shape("rect 1 2 3 4 [[A]]" , fxt.itm_rect_("[[A]]", 1, 2, 3, 4));}
@Test public void Rect_pass_many() {fxt.Test_shape("rect 1 2 3 4 5 6[[A]]" , fxt.itm_rect_("[[A]]", 1, 2, 3, 4));} // PURPOSE: MW allows extra points to be passed; PAGE:en.w:Kilauea DATE:2014-07-28
@Test public void Rect_pass_invalid() {fxt.Test_shape("rect 1 2 3 4 a b [[A]]" , fxt.itm_rect_("[[A]]", 1, 2, 3, 4));} // PURPOSE: MW only scans first 4 tokens for numbers; PAGE:de.w:Wilhelm_Angele DATE:2014-10-30
@Test public void Circle_pass() {fxt.Test_shape("circle 1 2 3 [[A]]" , fxt.itm_circle_("[[A]]", 1, 2, 3));}
@Test public void Poly_pass() {fxt.Test_shape("poly 1 2 3 4 5 6 [[A]]" , fxt.itm_poly_("[[A]]", 1, 2, 3, 4, 5, 6));}
@Test public void Poly_pass_chars() {fxt.Test_shape("poly a b [[A]]" , fxt.itm_poly_("[[A]]", 0, 0));} // PURPOSE: non-numeric should be converted to 0; PAGE:uk.w:Стратосфера; DATE:2014-07-26
@Test public void Poly_pass_chars_2() {fxt.Test_shape("poly 1a 2a [[A]]" , fxt.itm_poly_("[[A]]", 0, 0));} // PURPOSE: non-numeric should be converted to 0; PAGE:ru.w:Системный_блок; DATE:2014-10-22
@Test public void Poly_pass_dots() {fxt.Test_shape("poly 1.2 3.4 [[A]]" , fxt.itm_poly_("[[A]]", 1.2d, 3.4d));} // PURPOSE: make sure decimals are handled correctly
@Test public void Poly_pass_commas() {fxt.Test_shape("poly 1, 2, 3, 4 [[A]]" , fxt.itm_poly_("[[A]]", 1, 2, 3, 4));} // PURPOSE: commas should be ignored; PAGE:de.w:Kaimnitz; DATE:2014-08-05
@Test public void Poly_pass_commas_2() {fxt.Test_shape("poly 1,2 3,4 [[A]]" , fxt.itm_poly_("[[A]]", 1, 3));} // PURPOSE: commas should be ignored for purpose of parse; PAGE:fr.w:Gouesnou; DATE:2014-08-12
@Test public void Rect_fail() {fxt.Test_shape_err("rect 1 2 3 [[A]]" , "imagemap_missing_coord");}
@Test public void Circle_fail() {fxt.Test_shape_err("circle 1 2 [[A]]" , "imagemap_missing_coord");}
@Test public void Poly_fail_odd() {fxt.Test_shape_err("poly 1 2 3 [[A]]" , "imagemap_poly_odd");}
@Test public void Poly_fail_zero() {fxt.Test_shape_err("poly [[A]]" , "imagemap_missing_coord");}
@Test public void Circle_fail_invalid() {fxt.Test_shape_err("rect 1 2..3 4 [[A]]" , "imagemap_invalid_coord");}
}
class Imap_fxt_base {
protected Xoae_app app; protected Xowe_wiki wiki;
@gplx.Virtual public void Reset() {
app = Xoa_app_fxt.app_();
wiki = Xoa_app_fxt.wiki_tst_(app);
wiki.Ctx().Para().Enabled_n_();
}
public Imap_itm_shape itm_rect_(String link, double... pts_ary) {return itm_shape_(Imap_itm_.Tid_shape_rect, link, pts_ary);}
public Imap_itm_shape itm_circle_(String link, double... pts_ary) {return itm_shape_(Imap_itm_.Tid_shape_circle, link, pts_ary);}
public Imap_itm_shape itm_poly_(String link, double... pts_ary) {return itm_shape_(Imap_itm_.Tid_shape_poly, link, pts_ary);}
private Imap_itm_shape itm_shape_(byte tid, String link, double... pts_ary) {
int pts_len = pts_ary.length;
Double_obj_val[] pts_doubles = new Double_obj_val[pts_len];
for (int i = 0; i < pts_len; ++i)
pts_doubles[i] = Double_obj_val.new_(pts_ary[i]);
byte[] link_bry = Bry_.new_u8(link);
Imap_itm_shape rv = new Imap_itm_shape(tid, pts_doubles);
Imap_link_owner_.Init(rv, app, wiki, link_bry, Make_link_tkn(link_bry));
return rv;
}
private Xop_tkn_itm Make_link_tkn(byte[] src) {
Xop_root_tkn root_tkn = new Xop_root_tkn();
wiki.Parser().Parse_text_to_wdom(root_tkn, wiki.Ctx(), app.Tkn_mkr(), src, Xop_parser_.Doc_bgn_bos);
return root_tkn.Subs_get(0);
}
}
class Imap_parser_fxt extends Imap_fxt_base {
private Imap_parser parser;
private Imap_map imap;
@Override public void Reset() {
super.Reset();
Xoa_url url = Xoa_url.new_(wiki.Domain_bry(), Bry_.new_a7("Test_1"));
Imap_xtn_mgr xtn_mgr = new Imap_xtn_mgr();
parser = new Imap_parser(xtn_mgr);
parser.Init(wiki, url, Gfo_usr_dlg_.Noop);
parser.Clear();
imap = new Imap_map(1);
}
public void Test_shape(String raw_str, Imap_itm_shape expd) {
raw_str = "File:A.png\n" + raw_str;
byte[] raw = Bry_.new_u8(raw_str);
parser.Parse(imap, raw, 0, raw.length);
Imap_itm_shape[] actl_ary = imap.Shapes();
Imap_itm_shape actl = actl_ary == null | actl_ary.length != 1 ? null : (Imap_itm_shape)actl_ary[0];
if (actl == null && expd == null) {} // noop; test passed
else if (actl == null && expd != null) {Tfds.Fail("actl should not be null", raw);}
else if (actl != null && expd == null) {Tfds.Fail("actl should be null", raw);}
else {
Tfds.Eq(expd.Itm_tid(), actl.Itm_tid(), "tid");
Tfds.Eq_ary(expd.Shape_pts(), actl.Shape_pts(), "pts");
Tfds.Eq(String_.new_u8(expd.Link_href()), String_.new_u8(actl.Link_href()));
Tfds.Eq(String_.new_u8(expd.Link_text()), String_.new_u8(actl.Link_text()));
}
Tfds.Eq(0, imap.Errs().length, "expd 0 errors");
}
public void Test_shape_err(String raw_str, String expd_err) {
raw_str = "File:A.png\n" + raw_str;
byte[] raw = Bry_.new_u8(raw_str);
parser.Parse(imap, raw, 0, raw.length);
Imap_err[] err_ary = imap.Errs();
Tfds.Eq(1, err_ary.length, "expd 1 err");
Tfds.Eq(expd_err, err_ary[0].Err_key());
}
}

View File

@@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
class Imap_pts_fmtr_arg implements Bry_fmtr_arg {
private double scale = 1; private Double_obj_val[] pts;
public void Scale_(double v) {this.scale = v;}
public void Pts_(Double_obj_val[] v) {this.pts = v;}
public void XferAry(Bry_bfr bfr, int idx) {
int pts_len = pts.length;
for (int i = 0; i < pts_len; ++i) {
Double_obj_val pt = pts[i];
if (i != 0) bfr.Add_byte_comma();
int pt_int = (int)pt.Val();
pt_int = (int)Math_.Round(scale * pt_int, 0);
bfr.Add_int_variable(pt_int);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*; import gplx.xowa.parsers.logs.*;
public class Imap_xnde implements Xox_xnde {
private Imap_xtn_mgr xtn_mgr;
private Imap_map imap_data;
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
xtn_mgr = wiki.Xtn_mgr().Xtn_imap();
xtn_mgr.Xtn_assert();
Xoae_page page = ctx.Cur_page();
page.Html_data().Module_mgr().Itm__popups().Bind_hover_area_(true);
page.Html_data().Xtn_imap_exists_y_();
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end);
imap_data = xtn_mgr.Parser().Parse(wiki, ctx, root, src, xnde);
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end);
boolean log_wkr_enabled = Log_wkr != Xop_log_basic_wkr.Null; if (log_wkr_enabled) Log_wkr.Log_end_xnde(ctx.Cur_page(), Xop_log_basic_wkr.Tid_imageMap, src, xnde);
} public static Xop_log_basic_wkr Log_wkr = Xop_log_basic_wkr.Null;
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
if (imap_data.Invalid()) return;
html_wtr.Write_tkn(bfr, ctx, hctx, imap_data.Img_src(), xnde, Xoh_html_wtr.Sub_idx_null, imap_data.Img().Img_link());
}
}

View File

@@ -0,0 +1,228 @@
/*
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.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Imap_xnde_html_all_tst {
@Before public void init() {fxt.Reset();} private Imap_xnde_html_fxt fxt = new Imap_xnde_html_fxt();
@Test public void Basic() {
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|thumb|123px|a1"
, "circle 0 0 5 [[B|b1]]"
, "rect 0 0 4 8 [[C|c1]]"
, "desc none"
, "</imagemap>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"thumb tright\">"
, " <div id=\"xowa_file_div_0\" class=\"thumbinner\" style=\"width:220px;\">" // NOTE:220px is default w for "non-found" thumb; DATE:2014-09-24
, " <div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " <area href=\"/wiki/B\" shape=\"circle\" coords=\"0,0,5\" alt=\"b1\" title=\"b1\"/>"
, " <area href=\"/wiki/C\" shape=\"rect\" coords=\"0,0,4,8\" alt=\"c1\" title=\"c1\"/>"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " </div>"
, " <div class=\"thumbcaption\">"
, " <div class=\"magnify\">"
, " <a href=\"/wiki/File:A.png\" class=\"internal\" title=\"Enlarge\">"
, " <img src=\"file:///mem/xowa/user/test_user/app/img/file/magnify-clip.png\" width=\"15\" height=\"11\" alt=\"\" />"
, " </a>"
, " </div>"
, " a1"
, " </div>"
, " </div>"
, "</div>"
));
}
@Test public void Caption_xml() { // PURPOSE: xnde in caption was being escaped; PAGE:en.w:Council_of_Europe; DATE:2014-07-25
fxt.Test_html_full_frag("<imagemap>File:A.png|thumb|<b>c</b>\n</imagemap>", "<b>c</b>");
}
@Test public void Default() {
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|thumb|123px|a1"
, "default [[B|b1]]"
, "</imagemap>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"thumb tright\">"
, " <div id=\"xowa_file_div_0\" class=\"thumbinner\" style=\"width:220px;\">" // NOTE:220px is default w for "non-found" thumb; DATE:2014-09-24
, " <div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " </map>"
, " <a href=\"/wiki/B\" title=\"b1\">"
, " <img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " </a>"
, " </div>"
, " <div class=\"thumbcaption\">"
, " <div class=\"magnify\">"
, " <a href=\"/wiki/File:A.png\" class=\"internal\" title=\"Enlarge\">"
, " <img src=\"file:///mem/xowa/user/test_user/app/img/file/magnify-clip.png\" width=\"15\" height=\"11\" alt=\"\" />"
, " </a>"
, " </div>"
, " a1"
, " </div>"
, " </div>"
, "</div>"
));
}
@Test public void Desc() {
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|123px|a1"
, "desc top-left"
, "</imagemap>"
), String_.Concat_lines_nl_skip_last
( "<div id='imap_div_0' class=\"noresize\" style=\"height:0px; width: 123px;\">"
, " <map name=\"imageMap_1_1\">"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"a1\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " <div style=\"margin-left:0px; margin-top:1px; text-align:left;\">"
, " <a href=\"/wiki/File:A.png\" title=\"click here\">"
, " <img alt=\"click here\" src=\"file:///mem/xowa/bin/any/xowa/xtns/ImageMap/imgs/desc-20.png\" style=\"border: none;\" />"
, " </a>"
, " </div>"
, " </div>"
));
}
@Test public void Lnke() { // PURPOSE: handle shapes with lnke; PAGE:en.w:Cholesterolt DATE:2014-07-25
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|thumb|123px|a1"
, "circle 0 0 5 [[http://b.org b1]]"
, "desc none"
, "</imagemap>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"thumb tright\">"
, " <div id=\"xowa_file_div_0\" class=\"thumbinner\" style=\"width:220px;\">" // NOTE:220px is default w for "non-found" thumb; DATE:2014-09-24
, " <div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " <area href=\"http://b.org\" shape=\"circle\" coords=\"0,0,5\" alt=\"b1\" title=\"b1\"/>"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " </div>"
, " <div class=\"thumbcaption\">"
, " <div class=\"magnify\">"
, " <a href=\"/wiki/File:A.png\" class=\"internal\" title=\"Enlarge\">"
, " <img src=\"file:///mem/xowa/user/test_user/app/img/file/magnify-clip.png\" width=\"15\" height=\"11\" alt=\"\" />"
, " </a>"
, " </div>"
, " a1"
, " </div>"
, " </div>"
, "</div>"
));
}
@Test public void Err_trailing_ws() { // PURPOSE: empty 1st line causes failure
fxt.Test_html_full_frag(String_.Concat_lines_nl_skip_last
( "<imagemap> "
, "File:A.png|thumb|test_caption"
, "</imagemap>"
), "test_caption" // no error if test_caption appears;
);
}
@Test public void Para_omitted() { // PURPOSE: imagemap should not be automatically enclosed in para; PAGE:cs.w:Seznam_clenu_ctrn<72>ct<63>ho_Knesetu; DATE:2014-05-08;
fxt.Fxt().Init_para_y_();
fxt.Test_html_full_str("<imagemap>File:A.png</imagemap> a", fxt.Frag_html_full() + " a"); // NOTE: "a" no longer enclosed in <p>; DATE:2014-07-25
fxt.Fxt().Init_para_n_();
}
@Test public void Xnde_double_pipe() {// PURPOSE: if || is inside table and imagemap, treat as lnki; EX:w:United_States_presidential_election,_1992; DATE:2014-03-29; DATE:2014-05-06
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|-"
, "| z"
, "<imagemap>"
, "File:A.png||123px|b" // NOTE: "||" should not be tblw; also should not be pipe + text; if it is pipe + text, then caption will be "|123px" and width will be -1; DATE:2014-05-06
, "</imagemap>"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <tr>"
, " <td> z"
, "<div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"b\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>" // NOTE: width must be 123, not 0
, " </div>"
, " </td>"
, " </tr>"
, "</table>"
, ""
)
);
}
@Test public void Template_image() { // PURPOSE: handle templates in caption; PAGE:en.w:Kilauea; DATE:2014-07-27
fxt.Fxt().Init_page_create("Template:Test_template", "xyz");
fxt.Test_html_full_frag("<imagemap>File:A.png|thumb|{{Test_template}}\n</imagemap>", "xyz");
}
@Test public void Template_shape() { // PURPOSE: handle templates in shape; PAGE:fr.w:Arrondissements_de_Lyon DATE:2014-08-12
fxt.Fxt().Init_page_create("Template:B1", "<b>b1</b>"); // note that an xnde is a better example as it will throw ArrayOutOfBounds error
fxt.Test_html_full_str(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|thumb|123px|a1"
, "circle 0 0 5 [[B|{{b1}}]]"
, "desc none"
, "</imagemap>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"thumb tright\">"
, " <div id=\"xowa_file_div_0\" class=\"thumbinner\" style=\"width:220px;\">" // NOTE:220px is default w for "non-found" thumb; DATE:2014-09-24
, " <div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " <area href=\"/wiki/B\" shape=\"circle\" coords=\"0,0,5\" alt=\"b1\" title=\"b1\"/>"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/thumb/7/0/A.png/123px.png\" width=\"123\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " </div>"
, " <div class=\"thumbcaption\">"
, " <div class=\"magnify\">"
, " <a href=\"/wiki/File:A.png\" class=\"internal\" title=\"Enlarge\">"
, " <img src=\"file:///mem/xowa/user/test_user/app/img/file/magnify-clip.png\" width=\"15\" height=\"11\" alt=\"\" />"
, " </a>"
, " </div>"
, " a1"
, " </div>"
, " </div>"
, "</div>"
));
}
@Test public void Template_multi_line() { // PURPOSE: handle multiple-line captions; PAGE:en.w:Archaea; DATE:2014-08-22
fxt.Test_html_full_frag(String_.Concat_lines_nl_skip_last
( "<imagemap>"
, "File:A.png|thumb|<ref>text"
, "</ref>"
, "</imagemap>"
), "id=\"cite_ref-0\"");
}
}
class Imap_xnde_html_fxt {
public void Reset() {
fxt.Reset();
Xol_msg_itm msg = fxt.Wiki().Msg_mgr().Get_or_make(Bry_.new_a7("imagemap_description"));
msg.Atrs_set(Bry_.new_a7("click here"), false, false);
}
public Xop_fxt Fxt() {return fxt;} private Xop_fxt fxt = new Xop_fxt();
public void Test_html_full_str(String raw, String expd) {fxt.Test_html_full_str(raw, expd);}
public void Test_html_full_frag(String raw, String expd) {fxt.Test_html_full_frag(raw, expd);}
public String Frag_html_full() {
return String_.Concat_lines_nl_skip_last
( "<div id='imap_div_0' class=\"noresize\">"
, " <map name=\"imageMap_1_1\">"
, " </map>"
, " <img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/orig/7/0/A.png\" width=\"0\" height=\"0\" usemap=\"#imageMap_1_1\"/>"
, " </div>"
);
}
}

View File

@@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Imap_xnde_html_itm_tst {
@Before public void init() {fxt.Reset();} private Imap_html_bldr_fxt fxt = new Imap_html_bldr_fxt();
@Test public void Rect() {fxt.Test_shape_html(fxt.itm_rect_("[[A|b]]", 1, 2, 3, 4), "\n <area href=\"/wiki/A\" shape=\"rect\" coords=\"1,2,3,4\" alt=\"b\" title=\"b\"/>");}
@Test public void Circle() {fxt.Test_shape_html(fxt.itm_circle_("[[A|b]]", 1, 2, 3 ), "\n <area href=\"/wiki/A\" shape=\"circle\" coords=\"1,2,3\" alt=\"b\" title=\"b\"/>");}
@Test public void Poly() {fxt.Test_shape_html(fxt.itm_poly_("[[A|b]]", 1, 2, 3, 4), "\n <area href=\"/wiki/A\" shape=\"poly\" coords=\"1,2,3,4\" alt=\"b\" title=\"b\"/>");}
}
class Imap_html_bldr_fxt extends Imap_fxt_base {
private Bry_bfr bfr = Bry_bfr.new_();
private Imap_pts_fmtr_arg pts_fmtr_arg = new Imap_pts_fmtr_arg();
public void Test_shape_html(Imap_itm_shape shape, String expd) {
Imap_shapes_fmtr.Fmt_shape(bfr, Imap_html_fmtrs.Area, pts_fmtr_arg, shape);
Tfds.Eq(expd, bfr.Xto_str_and_clear());
}
}

View File

@@ -0,0 +1,48 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.imaps; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*; import gplx.xowa.wikis.*; import gplx.xowa.html.*; import gplx.xowa.html.lnkis.*;
public class Imap_xtn_mgr extends Xox_mgr_base implements GfoInvkAble {
private boolean init;
@Override public boolean Enabled_default() {return true;}
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("imageMap");
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki;
@gplx.Internal protected Imap_parser Parser() {return parser;} private Imap_parser parser;
public void Desc_assert() {
if (desc_trie != null) return;
desc_trie = Imap_desc_tid.trie_(wiki);
desc_msg = wiki.Msg_mgr().Val_by_key_obj("imagemap_description");
desc_icon_url = wiki.Appe().Fsys_mgr().Bin_xtns_dir().GenSubFil_nest("ImageMap", "imgs", "desc-20.png").To_http_file_bry();
}
public Btrie_slim_mgr Desc_trie() {return desc_trie;} private Btrie_slim_mgr desc_trie;
public byte[] Desc_msg() {return desc_msg;} private byte[] desc_msg;
public byte[] Desc_icon_url() {return desc_icon_url;} private byte[] desc_icon_url;
public Xoh_arg_img_core Img_core_fmtr(boolean hctx_is_hdump) {return hctx_is_hdump ? img_core_hdump : img_core_basic;}
private final Xoh_arg_img_core img_core_basic = new Xoh_arg_img_core__basic(), img_core_hdump = new Xoh_arg_img_core__hdump();
@Override public Xox_mgr Clone_new() {return new Imap_xtn_mgr();}
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
this.wiki = wiki;
}
public void Xtn_assert() {
if (init) return;
parser = new Imap_parser(this);
init = true;
}
public void Clear() {
}
}

View File

@@ -0,0 +1,62 @@
/*
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.indicators; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Indicator_html_bldr implements Bry_fmtr_arg {
private Indicator_html_bldr_itm bldr_itm = new Indicator_html_bldr_itm();
private Ordered_hash list = Ordered_hash_.new_();
public void Enabled_(boolean v) {enabled = v;} private boolean enabled = Bool_.Y;
public void Clear() {
enabled = Bool_.Y;
list.Clear();
}
public int Count() {return list.Count();}
public boolean Has(String key) {return list.Has(key);}
public void Add(Indicator_xnde xnde) {
if (!enabled) return; // do not add if disabled; called from <page>; PAGE:en.s:The_Parochial_System_(Wilberforce,_1838); DATE:2015-04-29
list.Add_if_dupe_use_nth(xnde.Name(), xnde); // Add_if_dupe_use_nth: 2nd indicator overwrites 1st; DATE:2015-04-29
}
public void XferAry(Bry_bfr bfr, int idx) {
if (list.Count() == 0) return; // do not build html if no items; DATE:2015-04-29
bldr_itm.Init(list);
fmtr_grp.Bld_bfr_many(bfr, bldr_itm);
}
private static final Bry_fmtr
fmtr_grp = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <div class='mw-indicators'>~{itms}"
, " </div>"
), "itms")
;
}
class Indicator_html_bldr_itm implements Bry_fmtr_arg {
private Ordered_hash list;
public void Init(Ordered_hash list) {this.list = list;}
public void XferAry(Bry_bfr bfr, int idx) {
int list_len = list.Count();
for (int i = list_len - 1; i > -1; --i) { // reverse order
Indicator_xnde xnde = (Indicator_xnde)list.Get_at(i);
fmtr_itm.Bld_bfr_many(bfr, xnde.Name(), xnde.Html());
}
}
private static final Bry_fmtr
fmtr_itm = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( ""
, " <div id='mw-indicator-~{name}' class='mw-indicator'>~{html}</div>"
), "name", "html")
;
}

View File

@@ -0,0 +1,66 @@
/*
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.indicators; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*; import gplx.xowa.xtns.indicators.*;
public class Indicator_html_bldr_tst {
@Before public void init() {fxt.Clear();} private Indicator_html_bldr_fxt fxt = new Indicator_html_bldr_fxt();
@Test public void Basic() {
fxt.Init_indicator("a", "a1");
fxt.Init_indicator("b", "b1");
fxt.Test_bld(String_.Concat_lines_nl_skip_last
( ""
, " <div class='mw-indicators'>"
, " <div id='mw-indicator-b' class='mw-indicator'>b1</div>" // reverse-order
, " <div id='mw-indicator-a' class='mw-indicator'>a1</div>"
, " </div>"
));
}
@Test public void Multiple_ignore() {
fxt.Init_indicator("a", "a1");
fxt.Init_indicator("a", "a2");
fxt.Test_bld(String_.Concat_lines_nl_skip_last
( ""
, " <div class='mw-indicators'>"
, " <div id='mw-indicator-a' class='mw-indicator'>a2</div>" // 2nd overwrites 1st
, " </div>"
));
}
}
class Indicator_html_bldr_fxt {
private Xoae_app app; private Xowe_wiki wiki; private Xoae_page page;
private Indicator_xtn_mgr xtn_mgr;
public void Clear() {
this.app = Xoa_app_fxt.app_();
this.wiki = Xoa_app_fxt.wiki_tst_(app);
this.xtn_mgr = wiki.Xtn_mgr().Xtn_indicator();
xtn_mgr.Enabled_y_();
xtn_mgr.Xtn_init_by_wiki(wiki);
this.page = wiki.Ctx().Cur_page();
}
public void Init_indicator(String name, String html) {
Indicator_xnde xnde = new Indicator_xnde();
xnde.Init_for_test(name, Bry_.new_u8(html));
Indicator_html_bldr indicators = page.Html_data().Indicators();
indicators.Add(xnde);
}
public void Test_bld(String expd) {
Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
page.Html_data().Indicators().XferAry(tmp_bfr, 0);
Tfds.Eq_str_lines(expd, tmp_bfr.Xto_str_and_clear());
}
}

View File

@@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.indicators; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*; import gplx.xowa.html.*; import gplx.xowa.pages.skins.*;
public class Indicator_xnde implements Xox_xnde, Xop_xnde_atr_parser {
public String Name() {return name;} private String name;
public byte[] Html() {return html;} private byte[] html;
public void Init_for_test(String name, byte[] html) {this.name = name; this.html = html;} // TEST
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {
if (xatr_key_obj == null) return;
Byte_obj_val xatr_key = (Byte_obj_val)xatr_key_obj;
switch (xatr_key.Val()) {
case Xatr_name: this.name = xatr.Val_as_str(src); break;
}
}
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
Xop_xatr_itm.Xatr_parse(wiki.Appe(), this, xatrs_hash, wiki, src, xnde);
this.html = Xop_parser_.Parse_text_to_html(wiki, ctx.Cur_page(), ctx.Cur_page().Ttl(), Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn()), false);
Indicator_html_bldr html_bldr = ctx.Cur_page().Html_data().Indicators();
html_bldr.Add(this);
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
}
private static final byte Xatr_name = 0;
private static final Hash_adp_bry xatrs_hash = Hash_adp_bry.ci_ascii_()
.Add_str_obj("name", Byte_obj_val.new_(Xatr_name));
}

View File

@@ -0,0 +1,25 @@
/*
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.indicators; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Indicator_xnde_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_parse_page_all_str("<indicator name='a'>test</indicator>", "");
}
}

View File

@@ -0,0 +1,26 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.indicators; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.wikis.*;
public class Indicator_xtn_mgr extends Xox_mgr_base {
public Indicator_xtn_mgr() {
}
@Override public boolean Enabled_default() {return false;}
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("Indicator");
@Override public Xox_mgr Clone_new() {return new Indicator_xtn_mgr();}
}

View File

@@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.inputBox; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*;
public class Xtn_inputbox_nde implements Xox_xnde {
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {} // FUTURE: noop for now so it doesn't show (since it's useless)
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {}
}

View File

@@ -0,0 +1,25 @@
/*
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.inputBox; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Xtn_inputbox_nde_tst {
private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic() {
fxt.Test_parse_page_wiki_str("a<inputbox>b</inputbox>c", "ac");
}
}

View File

@@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.insiders; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.xtns.pfuncs.*; import gplx.xowa.pages.skins.*;
public class Insider_func extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_insider;}
@Override public Pf_func New(int id, byte[] name) {return new Insider_func().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] val = Eval_argx(ctx, src, caller, self);
Xopg_xtn_skin_mgr skin_mgr = ctx.Cur_page().Html_data().Xtn_skin_mgr();
Insider_xtn_skin_itm skin_itm = (Insider_xtn_skin_itm)skin_mgr.Get_or_null(Insider_xtn_skin_itm.KEY);
if (skin_itm == null) {
skin_itm = new Insider_xtn_skin_itm(ctx.Wiki().Xtn_mgr().Xtn_insider().Html_bldr());
skin_mgr.Add(skin_itm);
}
skin_itm.Add(val);
}
public static final Insider_func _ = new Insider_func(); Insider_func() {}
}

View File

@@ -0,0 +1,38 @@
/*
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.insiders; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Insider_func_tst {
@Before public void init() {fxt.Reset();} private Insider_func_fxt fxt = new Insider_func_fxt();
@Test public void Basic() {
fxt.Test_parse("{{#insider:A}}x{{#insider:B}}", "x", "A", "B");
}
}
class Insider_func_fxt {
private Xop_fxt fxt = new Xop_fxt();
public void Reset() {
fxt.Reset();
}
public void Test_parse(String raw, String expd, String... insiders) {
fxt.Test_parse_tmpl_str_test(raw, "{{test}}", expd);
Insider_xtn_skin_itm skin_itm = (Insider_xtn_skin_itm)fxt.Page().Html_data().Xtn_skin_mgr().Get_or_null(Insider_xtn_skin_itm.KEY);
List_adp list = skin_itm.Itms();
byte[][] brys = (byte[][])list.To_ary(byte[].class);
Tfds.Eq_ary_str(insiders, String_.Ary(brys));
}
}

View File

@@ -0,0 +1,74 @@
/*
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.insiders; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.wikis.*; import gplx.xowa.wikis.xwikis.*; import gplx.xowa.pages.skins.*;
import gplx.xowa.html.hrefs.*;
class Insider_xtn_skin_itm implements Xopg_xtn_skin_itm {
private List_adp itms = List_adp_.new_();
private Insider_html_bldr html_bldr;
public Insider_xtn_skin_itm(Insider_html_bldr html_bldr) {this.html_bldr = html_bldr;}
public byte Tid() {return Xopg_xtn_skin_itm_tid.Tid_sidebar;}
public byte[] Key() {return KEY;} public static final byte[] KEY = Bry_.new_u8("Insider");
public List_adp Itms() {return itms;}
public void Add(byte[] itm) {itms.Add(itm);}
public void Write(Bry_bfr bfr, Xoae_page page) {
html_bldr.Bld_all(bfr, page, itms);
}
}
public class Insider_html_bldr implements Bry_fmtr_arg {
private Insider_xtn_mgr xtn_mgr;
private Bry_bfr tmp_ttl = Bry_bfr.reset_(255);
private List_adp list; private int list_len;
private Hash_adp_bry hash = Hash_adp_bry.cs_();
public Insider_html_bldr(Insider_xtn_mgr xtn_mgr) {this.xtn_mgr = xtn_mgr;}
public void Bld_all(Bry_bfr bfr, Xoae_page page, List_adp list) {
this.list = list; this.list_len = list.Count();
hash.Clear();
fmtr_grp.Bld_bfr_many(bfr, xtn_mgr.Msg_sidebar_ttl(), xtn_mgr.Msg_about_page(), xtn_mgr.Msg_about_ttl(), this);
}
public void XferAry(Bry_bfr bfr, int idx) {
Xowe_wiki wiki = xtn_mgr.Wiki();
Xoh_href_parser href_parser = wiki.Appe().Href_parser();
for (int i = 0; i < list_len; ++i) {
byte[] itm = (byte[])list.Get_at(i);
Xoa_ttl user_ttl = Xoa_ttl.parse_(wiki, Xow_ns_.Id_user, itm);
if (user_ttl == null) continue;
byte[] user_ttl_bry = user_ttl.Full_db();
if (hash.Has(user_ttl_bry)) continue;
hash.Add(user_ttl_bry, user_ttl_bry);
href_parser.Encoder().Encode(tmp_ttl, user_ttl_bry);
user_ttl_bry = tmp_ttl.Xto_bry_and_clear();
fmtr_itm.Bld_bfr(bfr, user_ttl_bry, user_ttl.Page_txt());
}
}
private static final Bry_fmtr
fmtr_grp = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( "<div id='p-insiders' class='portal' role='navigation'>"
, " <h3>~{hdr}</h3>"
, " <div class='body'>"
, " <ul>~{itms}"
, " <li class='interwiki-insider'><a class='xowa-hover-off' href='/wiki/~{about_href}'>~{about_text}</a></li>"
, " </ul>"
, " </div>"
, "</div>"
), "hdr", "about_href", "about_text", "itms")
, fmtr_itm = Bry_fmtr.new_
( "\n <li class='interwiki-insider'><a class='xowa-hover-off' href='/wiki/~{href}'>~{name}</a></li>"
, "href", "name")
;
}

View File

@@ -0,0 +1,62 @@
/*
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.insiders; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Insider_html_bldr_tst {
@Before public void init() {fxt.Clear();} private Insider_html_bldr_fxt fxt = new Insider_html_bldr_fxt();
@Test public void Basic() {
fxt.Init_insider("A_1");
fxt.Test_bld(String_.Concat_lines_nl_skip_last
( "<div id='p-insiders' class='portal' role='navigation'>"
, " <h3>Docent</h3>"
, " <div class='body'>"
, " <ul>"
, " <li class='interwiki-insider'><a class='xowa-hover-off' href='/wiki/User:A_1'>A 1</a></li>"
, " <li class='interwiki-insider'><a class='xowa-hover-off' href='/wiki/Docent_page'>About Docents</a></li>"
, " </ul>"
, " </div>"
, "</div>"
));
}
}
class Insider_html_bldr_fxt {
private Xoae_app app; private Xowe_wiki wiki; private Xoae_page page;
private Insider_xtn_mgr xtn_mgr;
private Insider_xtn_skin_itm skin_itm;
public void Clear() {
this.app = Xoa_app_fxt.app_();
this.wiki = Xoa_app_fxt.wiki_tst_(app);
Xop_fxt.Init_msg(wiki, "insider-title", "Docent");
Xop_fxt.Init_msg(wiki, "insider-about", "About Docents");
Xop_fxt.Init_msg(wiki, "insider-about-page", "Docent_page");
this.xtn_mgr = wiki.Xtn_mgr().Xtn_insider();
xtn_mgr.Enabled_y_();
xtn_mgr.Xtn_init_by_wiki(wiki);
this.page = wiki.Ctx().Cur_page();
skin_itm = new Insider_xtn_skin_itm(xtn_mgr.Html_bldr());
page.Html_data().Xtn_skin_mgr().Add(skin_itm);
}
public void Init_insider(String lnki_ttl) {
skin_itm.Add(Bry_.new_u8(lnki_ttl));
}
public void Test_bld(String expd) {
Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
skin_itm.Write(tmp_bfr, page);
Tfds.Eq_str_lines(expd, tmp_bfr.Xto_str_and_clear());
}
}

View File

@@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.insiders; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*; import gplx.xowa.wikis.*;
public class Insider_xtn_mgr extends Xox_mgr_base {
public Insider_xtn_mgr() {
html_bldr = new Insider_html_bldr(this);
}
@Override public boolean Enabled_default() {return false;}
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("Insider");
@Override public Xox_mgr Clone_new() {return new Insider_xtn_mgr();}
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
this.wiki = wiki;
if (!Enabled()) return;
Xox_mgr_base.Xtn_load_i18n(wiki, XTN_KEY);
msg_sidebar_ttl = wiki.Msg_mgr().Val_by_key_obj("insider-title");
msg_about_ttl = wiki.Msg_mgr().Val_by_key_obj("insider-about");
msg_about_page = wiki.Msg_mgr().Val_by_key_obj("insider-about-page");
}
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki;
public Insider_html_bldr Html_bldr() {return html_bldr;} private Insider_html_bldr html_bldr;
public byte[] Msg_sidebar_ttl() {return msg_sidebar_ttl;} private byte[] msg_sidebar_ttl;
public byte[] Msg_about_ttl() {return msg_about_ttl;} private byte[] msg_about_ttl;
public byte[] Msg_about_page() {return msg_about_page;} private byte[] msg_about_page;
}

View File

@@ -0,0 +1,265 @@
/*
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.listings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.html.*; import gplx.xowa.html.*;
public class Listing_xnde implements Xox_xnde, Xop_xnde_atr_parser {
public Listing_xnde(int tag_id) {}
private byte[] xatr_name, xatr_alt, xatr_address, xatr_directions, xatr_phone, xatr_tollfree, xatr_email, xatr_fax, xatr_url, xatr_hours, xatr_price, xatr_checkin, xatr_checkout;
private int xatr_lat = Xatr_meridian_null, xatr_long = Xatr_meridian_null;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_obj) {
if (xatr_obj == null) return;
byte xatr_tid = ((Byte_obj_val)xatr_obj).Val();
switch (xatr_tid) {
case Listing_xatrs.Tid_name: xatr_name = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_alt: xatr_alt = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_address: xatr_address = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_directions: xatr_directions = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_phone: xatr_phone = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_tollfree: xatr_tollfree = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_email: xatr_email = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_fax: xatr_fax = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_url: xatr_url = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_hours: xatr_hours = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_price: xatr_price = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_checkin: xatr_checkin = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_checkout: xatr_checkout = xatr.Val_as_bry__blank_to_null(src); break;
case Listing_xatrs.Tid_lat: xatr_lat = xatr.Val_as_int_or(src, Xatr_meridian_null); break;
case Listing_xatrs.Tid_long: xatr_long = xatr.Val_as_int_or(src, Xatr_meridian_null); break;
}
}
private void Init_args() {
if (xatr_name == null) {
xatr_name = msg_mgr.Itm_by_key_or_new(Bry_.new_a7("listings-unknown")).Val();
}
xatr_alt = Parse_wikitext(xatr_alt);
xatr_address = Parse_wikitext(xatr_address);
xatr_directions = Parse_wikitext(xatr_directions);
}
private Xowe_wiki wiki; private Xop_parser parser; private Xop_ctx sub_ctx; private Xol_msg_mgr msg_mgr;
private void Init_sub_ctx() {
sub_ctx = Xop_ctx.new_sub_(wiki);
}
private byte[] Parse_wikitext(byte[] v) {
if (Bry_.Len_eq_0(v)) return v; // ignore null, ""
if (sub_ctx == null) Init_sub_ctx();
return parser.Parse_text_to_html(sub_ctx, v);
}
private Listing_xtn_mgr xtn_mgr;
private byte[] html_output = Bry_.Empty;
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
this.wiki = wiki; this.parser = wiki.Parser(); this.msg_mgr = wiki.Lang().Msg_mgr();
xtn_mgr = (Listing_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Listing_xtn_mgr.Xtn_key_static);
if (xtn_mgr == null || !xtn_mgr.Enabled()) return;
Xoae_app app = wiki.Appe();
Xop_xatr_itm[] atrs = Xop_xatr_itm.Xatr_parse(app, this, Listing_xatrs.Key_hash, wiki, src, xnde);
Init_args();
Html_wtr hwtr = xtn_mgr.Hwtr();
if (!Bld_by_template(xnde, atrs, src)) {
Bld_by_args(xtn_mgr, hwtr, xnde, src);
html_output = hwtr.Xto_bry_and_clear();
}
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
if (xtn_mgr == null || !xtn_mgr.Enabled())
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde);
else
bfr.Add(html_output);
}
private boolean Bld_by_template(Xop_xnde_tkn xnde, Xop_xatr_itm[] atrs, byte[] src) {
byte[] listings_template = xtn_mgr.Listings_template();
if (listings_template == null) return false;
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
bfr.Add(Xoa_consts.Invk_bgn); // "{{"
bfr.Add(listings_template); // name
int atrs_len = atrs.length;
for (int i = 0; i < atrs_len; i++) {
Xop_xatr_itm atr = atrs[i];
bfr.Add_byte_pipe(); // "|"
byte[] atr_key = atr.Key_bry(); if (atr_key == null) continue; // skip keyless atrs; PAGE:nl.v:Rome;EX:<sleep phone='' "abc"/> DATE:2014-06-04
bfr.Add(atr_key); // key
bfr.Add_byte(Byte_ascii.Eq); // "="
bfr.Add(atr.Val_as_bry(src)); // val; NOTE: must use Val_as_bry(src), not Val_bry, else int or "" will not be captured; DATE:2014-05-21
}
if (xnde.CloseMode() == Xop_xnde_tkn.CloseMode_pair) {
bfr.Add_byte_pipe(); // "|"
bfr.Add_mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
}
bfr.Add(Xoa_consts.Invk_end); // "}}"
Xop_ctx sub_ctx = Xop_ctx.new_sub_(wiki);
html_output = wiki.Parser().Parse_text_to_html(sub_ctx, bfr.To_bry_and_rls());
return true;
}
private void Bld_by_args(Listing_xtn_mgr xtn_mgr, Html_wtr wtr, Xop_xnde_tkn xnde, byte[] src) {
wtr.Nde_full(Tag_strong, xatr_name); // <strong>name</strong>
if (xatr_url != null)
wtr.Nde_full_atrs(Tag_a, wtr.Xto_bry_and_clear(), false
, Atr_a_href , xatr_url
, Atr_a_class , Atr_a_class_external_text
, Atr_a_rel , Atr_a_rel_nofollow
, Atr_a_title , xatr_name
);
if (xatr_alt != null) {
wtr.Txt(Txt_space_paren); // " ("
wtr.Nde_full_atrs(Tag_em, xatr_alt, false); // alt
wtr.Txt_byte(Byte_ascii.Paren_end); // ")"
}
byte[] position = Bld_position();
if (xatr_address != null || xatr_directions != null || position != null) {
if (xatr_address != null)
wtr.Txt(Txt_comma_space).Txt(xatr_address); // , address
if (xatr_directions != null || position != null) {
wtr.Txt(Txt_space_paren); // " ("
wtr.Nde_bgn_hdr(Tag_em).Txt(xatr_directions); // <em>directions
if (xatr_directions != null && position != null)
wtr.Txt(Txt_comma_space); // ,
wtr.Txt(position); // position
wtr.Nde_end(); // </em>
wtr.Txt_byte(Byte_ascii.Paren_end); // ")"
}
}
if (xatr_phone != null || xatr_tollfree != null) {
wtr .Txt(Txt_comma_space)
.Txt_raw(xtn_mgr.Phone_symbol())
.Txt_byte(Byte_ascii.Space)
.Txt(xatr_phone)
;
if (xatr_tollfree != null) {
wtr .Txt(Txt_space_paren)
.Txt_raw(xtn_mgr.Tollfree_symbol())
.Txt(Txt_colon_space)
.Txt(xatr_tollfree)
.Txt_byte(Byte_ascii.Paren_end)
;
}
}
if (xatr_fax != null) {
wtr .Txt(Txt_comma_space)
.Txt_raw(xtn_mgr.Fax_symbol())
.Txt(Txt_colon_space)
.Txt(xatr_fax)
;
}
if (xatr_email != null) {
wtr .Txt(Txt_comma_space)
.Txt_raw(xtn_mgr.Email_symbol())
.Txt(Txt_colon_space)
;
wtr .Nde_full_atrs(Tag_a, xatr_email, true
, Atr_a_class , Atr_a_class_email
, Atr_a_href , Bry_.Add(Txt_mailto, xatr_email)
);
}
wtr.Txt(Txt_dot_space);
if (xatr_hours != null)
wtr.Txt(xatr_hours).Txt(Txt_dot_space);
if (xatr_checkin != null || xatr_checkout != null) {
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b128();
if (xatr_checkin != null) {
byte[] checkin_val = xtn_mgr.Checkin_msg().Fmt(tmp_bfr, xatr_checkin);
wtr.Txt_raw(checkin_val);
if (xatr_checkout != null)
wtr.Txt(Txt_comma_space);
}
if (xatr_checkout != null) {
byte[] checkout_val = xtn_mgr.Checkout_msg().Fmt(tmp_bfr, xatr_checkout);
wtr.Txt_raw(checkout_val);
}
wtr.Txt(Txt_dot_space);
tmp_bfr.Mkr_rls();
}
if (xatr_price != null)
wtr.Txt(xatr_price).Txt(Txt_dot_space);
if (xnde.CloseMode() == Xop_xnde_tkn.CloseMode_pair)
wtr.Txt(Bry_.Trim(Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn())));
}
private byte[] Bld_position() {
if (xatr_lat >= Xatr_meridian_null || xatr_long >= Xatr_meridian_null) return null; // check that lat and long are valid
Xol_msg_itm position_template = xtn_mgr.Position_template();
if (position_template == null) return null;
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b128().Mkr_rls();
byte[] rv = position_template.Fmt(tmp_bfr, xatr_lat, xatr_long);
tmp_bfr.Add(Xoa_consts.Invk_bgn); // "{{"
tmp_bfr.Add(rv); // rv is not message, but actually template precursor
tmp_bfr.Add(Xoa_consts.Invk_end); // "}}"
Xop_ctx sub_ctx = Xop_ctx.new_sub_(wiki);
rv = wiki.Parser().Parse_text_to_html(sub_ctx, tmp_bfr.Xto_bry_and_clear());
Xol_msg_itm position_text = xtn_mgr.Position_text();
if (Bry_.Len_eq_0(position_text.Val())) return rv;
return position_text.Fmt(tmp_bfr, rv);
}
private static final int Xatr_meridian_null = 361;
public static final byte[]
Tag_strong = Bry_.new_a7("strong")
, Tag_a = Bry_.new_a7("a")
, Tag_em = Bry_.new_a7("em")
, Tag_abbr = Bry_.new_a7("abbr")
, Atr_a_href = Bry_.new_a7("href")
, Atr_a_class = Bry_.new_a7("class")
, Atr_a_class_external_text = Bry_.new_a7("external text")
, Atr_a_class_email = Bry_.new_a7("email")
, Atr_a_rel = Bry_.new_a7("rel")
, Atr_a_rel_nofollow = Bry_.new_a7("nofollow")
, Atr_a_title = Bry_.new_a7("title")
, Txt_comma_space = Bry_.new_a7(", ")
, Txt_space_paren = Bry_.new_a7(" (")
, Txt_colon_space = Bry_.new_a7(": ")
, Txt_dot_space = Bry_.new_a7(". ")
, Txt_mailto = Bry_.new_a7("mailto:")
;
}
class Listing_xatrs {
public static final byte Tid_name = 0, Tid_alt = 1, Tid_address = 2, Tid_directions = 3, Tid_phone = 4, Tid_tollfree = 5, Tid_email = 6, Tid_fax = 7, Tid_url = 8
, Tid_hours = 9, Tid_price = 10, Tid_checkin = 11, Tid_checkout = 12, Tid_lat = 13, Tid_long = 14
;
public static Hash_adp_bry Key_hash = Hash_adp_bry.cs_()
.Add_str_byte("name" , Tid_name)
.Add_str_byte("alt" , Tid_alt)
.Add_str_byte("address" , Tid_address)
.Add_str_byte("directions" , Tid_directions)
.Add_str_byte("phone" , Tid_phone)
.Add_str_byte("tollfree" , Tid_tollfree)
.Add_str_byte("email" , Tid_email)
.Add_str_byte("fax" , Tid_fax)
.Add_str_byte("url" , Tid_url)
.Add_str_byte("hours" , Tid_hours)
.Add_str_byte("price" , Tid_price)
.Add_str_byte("checkin" , Tid_checkin)
.Add_str_byte("checkout" , Tid_checkout)
.Add_str_byte("lat" , Tid_lat)
.Add_str_byte("long" , Tid_long)
;
public static Xop_xnde_tag Tag_by_tid(int tid) {
Xop_xnde_tag rv = null;
switch (tid) {
case Xop_xnde_tag_.Tid_listing_buy: rv = Xop_xnde_tag_.Tag_listing_buy; break;
case Xop_xnde_tag_.Tid_listing_do: rv = Xop_xnde_tag_.Tag_listing_do; break;
case Xop_xnde_tag_.Tid_listing_drink: rv = Xop_xnde_tag_.Tag_listing_drink; break;
case Xop_xnde_tag_.Tid_listing_eat: rv = Xop_xnde_tag_.Tag_listing_eat; break;
case Xop_xnde_tag_.Tid_listing_listing: rv = Xop_xnde_tag_.Tag_listing_listing; break;
case Xop_xnde_tag_.Tid_listing_see: rv = Xop_xnde_tag_.Tag_listing_see; break;
case Xop_xnde_tag_.Tid_listing_sleep: rv = Xop_xnde_tag_.Tag_listing_sleep; break;
default: throw Exc_.new_unhandled(tid);
}
return rv;
}
}

View File

@@ -0,0 +1,108 @@
/*
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.listings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Listing_xnde_basic_tst {
private Xop_fxt fxt = new Xop_fxt();
private Listing_xtn_mgr listings_xtn_mgr;
@Before public void init() {
fxt.Reset_for_msgs();
Listing_xnde_basic_tst.Add_listing_msgs(fxt.Wiki());
listings_xtn_mgr = (Listing_xtn_mgr)fxt.Wiki().Xtn_mgr().Get_or_fail(Listing_xtn_mgr.Xtn_key_static);
listings_xtn_mgr.Enabled_y_();
listings_xtn_mgr.Xtn_init_by_wiki(fxt.Wiki());
}
@Test public void Url() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' url='http://site.org'/>"
, "<a href=\"http://site.org\" class=\"external text\" rel=\"nofollow\" title=\"name_0\"><strong>name_0</strong></a>. "
);
}
@Test public void Alt() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' alt=\"''alt_0''\"/>"
, "<strong>name_0</strong> (<em><i>alt_0</i></em>). "
);
}
@Test public void Address_directions() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' address='address_0' directions='directions_0'/>"
, "<strong>name_0</strong>, address_0 (<em>directions_0</em>). "
);
}
@Test public void Phone_tollfree() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' phone='phone_0' tollfree='tollfree_0'/>"
, "<strong>name_0</strong>, <abbr title=\"phone\">☎</abbr> phone_0 (toll-free: tollfree_0). "
);
}
@Test public void Fax() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' fax='fax_0'/>"
, "<strong>name_0</strong>, fax: fax_0. "
);
}
@Test public void Email() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' email='email_0'/>"
, "<strong>name_0</strong>, email: <a class=\"email\" href=\"mailto:email_0\">email_0</a>. "
);
}
@Test public void Hours() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' hours='hours_0'/>"
, "<strong>name_0</strong>. hours_0. "
);
}
@Test public void Checkin_checkout() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' checkin='checkin_0' checkout='checkout_0'/>"
, "<strong>name_0</strong>. Check-in: checkin_0, check-out: checkout_0. "
);
}
@Test public void Price() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0' price='price_0'/>"
, "<strong>name_0</strong>. price_0. "
);
}
@Test public void Content() {
fxt.Test_parse_page_all_str
( "<sleep name='name_0'>content_0</sleep>"
, "<strong>name_0</strong>. content_0"
);
}
public static void Add_listing_msgs(Xowe_wiki wiki) {
Xol_msg_mgr msg_mgr = wiki.Lang().Msg_mgr();
msg_mgr.Itm_by_key_or_new("listings-unknown", "Unknown destination");
msg_mgr.Itm_by_key_or_new("listings-desc", "Add tags for listing locations");
msg_mgr.Itm_by_key_or_new("listings-phone", "phone");
msg_mgr.Itm_by_key_or_new("listings-phone-symbol", "");
msg_mgr.Itm_by_key_or_new("listings-fax", "fax");
msg_mgr.Itm_by_key_or_new("listings-fax-symbol", "");
msg_mgr.Itm_by_key_or_new("listings-email", "email");
msg_mgr.Itm_by_key_or_new("listings-email-symbol", "");
msg_mgr.Itm_by_key_or_new("listings-tollfree", "toll-free");
msg_mgr.Itm_by_key_or_new("listings-tollfree-symbol", "");
msg_mgr.Itm_by_key_or_new("listings-checkin", "Check-in: ~{0}", true);
msg_mgr.Itm_by_key_or_new("listings-checkout", "check-out: ~{0}");
msg_mgr.Itm_by_key_or_new("listings-desc", "Add tags for listing locations");
msg_mgr.Itm_by_key_or_new("listings-position", "position: ~{0}");
msg_mgr.Itm_by_key_or_new("listings-position-template", "");
}
}

View File

@@ -0,0 +1,143 @@
/*
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.listings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Listing_xnde_template_tst {
private Xop_fxt fxt = new Xop_fxt();
private Listing_xtn_mgr listings_xtn_mgr;
@Before public void init() {
fxt.Reset_for_msgs();
Listing_xnde_basic_tst.Add_listing_msgs(fxt.Wiki());
listings_xtn_mgr = (Listing_xtn_mgr)fxt.Wiki().Xtn_mgr().Get_or_fail(Listing_xtn_mgr.Xtn_key_static);
listings_xtn_mgr.Clear();
listings_xtn_mgr.Enabled_y_();
}
private void Init_xtn_mgr() {listings_xtn_mgr.Xtn_init_by_wiki(fxt.Wiki());}
@Test public void Disabled() {
listings_xtn_mgr.Enabled_n_();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' address='address_0'>content_0</sleep>"
, "&lt;sleep name='name_0' address='address_0'&gt;content_0&lt;/sleep&gt;"
);
}
@Test public void Ignore_empty() {
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' alt='' address='' directions='' phone='' url='' checkin='' checkout='' price='' lat='' long=''> </sleep>"
, "<strong>name_0</strong>. "
);
}
@Test public void Ignore_invalid() { // PURPOSE: invalid atrs were causing null reference exception; PAGE:nl.v:Rome;EX:<sleep phone='' "abc"/> DATE:2014-06-04
fxt.Init_page_create("Template:ListingsSample", "{{{name|nil_name}}};{{{address|nil_address}}};{{{1|nil_content}}}");
fxt.Init_page_create("MediaWiki:listings-template", "ListingsSample");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' 'invalid'></sleep>"
, "name_0;nil_address;"
);
}
@Test public void Template() {
fxt.Init_page_create("Template:ListingsSample", "{{{name|nil_name}}};{{{address|nil_address}}};{{{1|nil_content}}}");
fxt.Init_page_create("MediaWiki:listings-template", "ListingsSample");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' address='address_0'>content_0</sleep>"
, "name_0;address_0;content_0"
);
}
@Test public void Template_lat() { // PURPOSE: lat / long was not being set for listings sample; PAGE:fr.v:Marrakech; DATE:2014-05-21
fxt.Init_page_create("Template:ListingsSample2", "{{{name|nil_name}}};{{{lat|nil_lat}}};{{{long|nil_long}}}");
fxt.Init_page_create("MediaWiki:listings-template", "ListingsSample2");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' lat='12' long=''></sleep>"
, "name_0;12;"
);
}
@Test public void Position_template_as_text() {
fxt.Init_page_create("MediaWiki:listings-position-template" , "position_template|$1|$2");
fxt.Init_page_create("Template:position_template" , "tmpl:lat={{{1}}} long={{{2}}}");
fxt.Init_page_create("MediaWiki:listings-position" , "msg: $1");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' lat='100' long='200'></sleep>"
, "<strong>name_0</strong> (<em>msg: tmpl:lat=100 long=200</em>). "
);
}
@Test public void Phone__text() {
fxt.Init_page_create("MediaWiki:listings-phone" , "phone");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' phone='0'></sleep>"
, "<strong>name_0</strong>, <abbr title=\"phone\">☎</abbr> 0. "
);
}
@Test public void Phone__text_and_symbol() {
fxt.Init_page_create("MediaWiki:listings-phone" , "phone");
fxt.Init_page_create("MediaWiki:listings-phone-symbol" , "P");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' phone='0'></sleep>"
, "<strong>name_0</strong>, <abbr title=\"phone\">P</abbr> 0. "
);
}
@Test public void Tollfree__text_and_symbol() {
fxt.Init_page_create("MediaWiki:listings-tollfree" , "tollfree");
fxt.Init_page_create("MediaWiki:listings-tollfree-symbol" , "tf");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' tollfree='0'></sleep>"
, "<strong>name_0</strong>, <abbr title=\"phone\">☎</abbr> (<abbr title=\"tollfree\">tf</abbr>: 0). "
);
}
@Test public void Fax__text_and_symbol() {
fxt.Init_page_create("MediaWiki:listings-fax" , "fax");
fxt.Init_page_create("MediaWiki:listings-fax-symbol" , "f");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' fax='0'></sleep>"
, "<strong>name_0</strong>, <abbr title=\"fax\">f</abbr>: 0. "
);
}
@Test public void Email__text_and_symbol() {
fxt.Init_page_create("MediaWiki:listings-email" , "email");
fxt.Init_page_create("MediaWiki:listings-email-symbol" , "e");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' email='a@b.org'></sleep>"
, "<strong>name_0</strong>, <abbr title=\"email\">e</abbr>: <a class=\"email\" href=\"mailto:a@b.org\">a@b.org</a>. "
);
}
@Test public void Checkin__template() {
fxt.Init_page_create("MediaWiki:listings-checkin" , "checkin: $1");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' checkin='checkin_0'></sleep>"
, "<strong>name_0</strong>. checkin: checkin_0. "
);
}
@Test public void Checkout__template() {
fxt.Init_page_create("MediaWiki:listings-checkout" , "checkout: $1");
Init_xtn_mgr();
fxt.Test_parse_page_all_str
( "<sleep name='name_0' checkout='checkout_0'></sleep>"
, "<strong>name_0</strong>. checkout: checkout_0. "
);
}
}

View File

@@ -0,0 +1,80 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.listings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.html.*;
import gplx.xowa.wikis.*;
public class Listing_xtn_mgr extends Xox_mgr_base {
@Override public boolean Enabled_default() {return false;}
@Override public byte[] Xtn_key() {return Xtn_key_static;} public static final byte[] Xtn_key_static = Bry_.new_a7("Listings");
@Override public Xox_mgr Clone_new() {return new Listing_xtn_mgr();}
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
if (!Enabled()) return;
this.Reset(wiki);
}
@gplx.Internal protected Html_wtr Hwtr() {return hwtr;} private Html_wtr hwtr;
public void Clear() {
listings_template = phone_symbol = tollfree_symbol = fax_symbol = email_symbol = null;
checkin_msg = checkout_msg = position_template = position_text = null;
}
private void Reset(Xowe_wiki wiki) {
hwtr = new Html_wtr();
Xop_ctx sub_ctx = Xop_ctx.new_sub_(wiki);
listings_template = Load_txt(wiki, sub_ctx, "listings-template");
phone_symbol = Load_txt(wiki, sub_ctx, "listings-phone-symbol", "listings-phone");
tollfree_symbol = Load_txt(wiki, sub_ctx, "listings-tollfree-symbol", "listings-tollfree");
fax_symbol = Load_txt(wiki, sub_ctx, "listings-fax-symbol", "listings-fax");
email_symbol = Load_txt(wiki, sub_ctx, "listings-email-symbol", "listings-email");
checkin_msg = Load_msg(wiki, sub_ctx, "listings-checkin");
checkout_msg = Load_msg(wiki, sub_ctx, "listings-checkout");
position_template = Load_msg(wiki, sub_ctx, "listings-position-template"); // EX: formats 11 12 to "template_name|11|12"
position_text = Load_msg(wiki, sub_ctx, "listings-position"); // EX: formats output of "{{template_name|11|12}}" to "message $output"
}
public byte[] Listings_template() {return listings_template;} private byte[] listings_template;
public byte[] Phone_symbol() {return phone_symbol;} private byte[] phone_symbol;
public byte[] Tollfree_symbol() {return tollfree_symbol;} private byte[] tollfree_symbol;
public byte[] Fax_symbol() {return fax_symbol;} private byte[] fax_symbol;
public byte[] Email_symbol() {return email_symbol;} private byte[] email_symbol;
public Xol_msg_itm Checkin_msg() {return checkin_msg;} private Xol_msg_itm checkin_msg;
public Xol_msg_itm Checkout_msg() {return checkout_msg;} private Xol_msg_itm checkout_msg;
public Xol_msg_itm Position_template() {return position_template;} private Xol_msg_itm position_template;
public Xol_msg_itm Position_text() {return position_text;} private Xol_msg_itm position_text;
private byte[] Load_txt(Xowe_wiki wiki, Xop_ctx sub_ctx, String symbol_ttl, String template_ttl) {
byte[] symbol_text = Load_txt(wiki, sub_ctx, symbol_ttl);
byte[] template_text = Load_txt(wiki, sub_ctx, template_ttl);
byte[] rv = null;
if (symbol_text != null) {
hwtr.Nde_full_atrs(Listing_xnde.Tag_abbr, symbol_text, true
, Listing_xnde.Atr_a_title, Html_utl.Escape_html_as_bry(template_text)
);
rv = hwtr.Xto_bry_and_clear();
}
else {
rv = template_text;
}
return rv;
}
private byte[] Load_txt(Xowe_wiki wiki, Xop_ctx sub_ctx, String ttl) {
byte[] rv = wiki.Msg_mgr().Val_by_key_obj(Bry_.new_u8(ttl)); if (Bry_.Len_eq_0(rv)) return null; // ttl does not exist; note that msg_mgr returns "" for missing values
rv = wiki.Parser().Parse_text_to_html(sub_ctx, rv);
rv = Html_utl.Escape_html_as_bry(rv);
return rv;
}
private Xol_msg_itm Load_msg(Xowe_wiki wiki, Xop_ctx sub_ctx, String ttl) {
return wiki.Msg_mgr().Find_or_null(Bry_.new_u8(ttl));
}
}

View File

@@ -0,0 +1,31 @@
/*
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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.xtns.pfuncs.*;
public class Lst_pfunc_lst extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_lst;}
@Override public Pf_func New(int id, byte[] name) {return new Lst_pfunc_lst().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] src_ttl_bry = Eval_argx(ctx, src, caller, self); if (Bry_.Len_eq_0(src_ttl_bry)) return; // {{#lst:}} -> ""
int args_len = self.Args_len();
byte[] sect_bgn = Pf_func_.Eval_arg_or(ctx, src, caller, self, args_len, 0, Lst_pfunc_wkr.Null_arg);
byte[] sect_end = Pf_func_.Eval_arg_or(ctx, src, caller, self, args_len, 1, Lst_pfunc_wkr.Null_arg);
new Lst_pfunc_wkr().Init_include(src_ttl_bry, sect_bgn, sect_end).Exec(bfr, ctx);
}
public static final Lst_pfunc_lst _ = new Lst_pfunc_lst(); Lst_pfunc_lst() {}
}

View File

@@ -0,0 +1,101 @@
/*
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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Lst_pfunc_lst_tst {
@Before public void init() {fxt.Clear();} private Lst_pfunc_lst_fxt fxt = new Lst_pfunc_lst_fxt();
@Test public void Bgn_only() {
fxt.Clear().Page_txt_("a<section begin=key0/>val0<section end=key0/> b").Test_lst("{{#lst:section_test|key0}}", "val0");
}
@Test public void Multiple() {
fxt.Clear().Page_txt_("a<section begin=key0/>val00<section end=key0/> b<section begin=key0/> val01<section end=key0/> c").Test_lst("{{#lst:section_test|key0}}", "val00 val01");
}
@Test public void Range() {
fxt.Clear().Page_txt_("a<section begin=key0/>val0<section end=key0/> b<section begin=key1/> val1<section end=key1/> c<section begin=key2/> val2<section end=key2/> d")
.Test_lst("{{#lst:section_test|key0|key2}}", "val0 b val1 c val2");
}
@Test public void Nest() {
fxt.Clear().Page_txt_("<section begin=key0/>val0<section begin=key00/> val00<section end=key00/><section end=key0/>").Test_lst("{{#lst:section_test|key0}}", "val0 val00");
}
@Test public void Wikitext() { // PURPOSE: assert section is expanded to html
fxt.Clear().Page_txt_("a<section begin=key0/>''val0''<section end=key0/> b").Test_lst("{{#lst:section_test|key0}}", "<i>val0</i>");
}
@Test public void Refs_ignored() { // PURPOSE: assert that nearby refs are ignored
fxt.Clear().Page_txt_("a<section begin=key0/>val0<ref>ref1</ref><section end=key0/> b <ref>ref2</ref>").Test_lst("{{#lst:section_test|key0}}<references/>", String_.Concat_lines_nl
( "val0<sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup><ol class=\"references\">"
, "<li id=\"cite_note-0\"><span class=\"mw-cite-backlink\"><a href=\"#cite_ref-0\">^</a></span> <span class=\"reference-text\">ref1</span></li>"
, "</ol>"
));
}
@Test public void Missing_bgn_end() {
fxt.Page_txt_("a<section bgn=key0/> b<section end=key0/> c");
fxt.Clear().Test_lst("{{#lst:section_test}}", "a b c");
}
@Test public void Missing_bgn() {
fxt.Page_txt_("a<section bgn=key0/> b<section end=key0/> c");
fxt.Clear().Test_lst("{{#lst:section_test||key0}}", "a b");
}
@Test public void Missing_end() {
fxt.Page_txt_("a <section begin=key0/>val0<section end=key1/> b");
fxt.Clear().Test_lst("{{#lst:section_test|key0}}", "val0 b"); // end is missing; read to end;
}
@Test public void Missing_end_noinclude() { // EX: de.wikisource.org/wiki/Versuch_einer_mokscha-mordwinischen_Grammatik/Mokscha-Texte; Seite:Ahlqvist_Forschungen_auf_dem_Gebiete_der_ural-altaischen_Sprachen_I.pdf/111
fxt.Page_txt_("a <section begin=key0/>val0<section end=key1/> b<noinclude>c</noinclude>");
fxt.Clear().Test_lst("{{#lst:section_test|key0}}", "val0 b"); // end is missing; ignore noinclude
}
@Test public void Missing_bgn_dupe() {
fxt.Page_txt_("a <section begin=key0/>val0<section end=key0/> b<section begin=key1/>val1<section end=key0/>");
fxt.Clear().Test_lst("{{#lst:section_test|key0}}", "val0");
}
@Test public void Nowiki() { // PURPOSE.fix: <nowiki> was creating incorrect sections; DATE:2013-07-11
fxt.Clear().Page_txt_("a<nowiki>''c''</nowiki><section begin=key0/>val0<section end=key0/> b").Test_lst("{{#lst:section_test|key0}}", "val0");
}
@Test public void Fullpagename() { // PURPOSE.fix: lst creates its own ctx; make sure ctx has same page_name of calling page (Test page) not default (Main page); DATE:2013-07-11
fxt.Clear().Page_txt_("a <section begin=key0/>{{FULLPAGENAME}}<section end=key0/> b").Test_lst("{{#lst:section_test|key0}}", "Test page");
}
@Test public void Nested_forbid_recursion() { // PURPOSE: forbid recursive calls; DATE:2014-02-09
fxt.Fxt().Init_page_create("Sub_0", "<section begin=key_0 />a<section end=key_0 />{{#lst:Sub_0|key_0}}"); // NOTE: recursive call to self
fxt.Fxt().Test_parse_page_all_str("{{#lst:Sub_0|key_0}}", "a");
}
@Test public void Nested_allow() { // PURPOSE: allow nested calls; DATE:2014-02-09
fxt.Fxt().Init_page_create("Template:Sub_1", "<section begin=key_1 />b<section end=key_1 />");
fxt.Fxt().Init_page_create("Sub_0", "<section begin=key_0 />a{{Sub_1}}<section end=key_0 />");
fxt.Fxt().Test_parse_page_all_str("{{#lst:Sub_0|key_0}}", "ab");
}
@Test public void Nested_recursion() { // PURPOSE: allow nested calls; it.s:Main_Page; DATE:2014-02-09
fxt.Fxt().Init_page_create("Sub_1", "<section begin=key_0 />b<section end=key_0 />");
fxt.Fxt().Init_page_create("Template:Sub_1", "{{#section:Sub_1|key_0}}");
fxt.Fxt().Init_page_create("Sub_0", "<section begin=key_0 />a{{Sub_1}}<section end=key_0 />");
fxt.Fxt().Test_parse_page_all_str("{{#section:Sub_0|key_0}}", "ab");
}
}
class Lst_pfunc_lst_fxt {
public Lst_pfunc_lst_fxt Clear() {
if (fxt == null) fxt = new Xop_fxt();
fxt.Reset();
fxt.Wiki().Cache_mgr().Free_mem_all();
Io_mgr.I.InitEngine_mem();
return this;
}
public Xop_fxt Fxt() {return fxt;} private Xop_fxt fxt;
public Lst_pfunc_lst_fxt Page_txt_(String v) {page_txt = v; return this;} private String page_txt;
public void Test_lst(String func, String expd) {
fxt.Init_page_create("section_test", page_txt);
fxt.Test_parse_page_all_str(func, expd);
}
}

View File

@@ -0,0 +1,31 @@
/*
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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.xtns.pfuncs.*;
public class Lst_pfunc_lstx extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_lstx;}
@Override public Pf_func New(int id, byte[] name) {return new Lst_pfunc_lstx().Name_(name);}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] src_ttl_bry = Eval_argx(ctx, src, caller, self); if (Bry_.Len_eq_0(src_ttl_bry)) return; // {{#lst:}} -> ""
int args_len = self.Args_len();
byte[] sect_exclude = Pf_func_.Eval_arg_or(ctx, src, caller, self, args_len, 0, Lst_pfunc_wkr.Null_arg);
byte[] sect_replace = Pf_func_.Eval_arg_or(ctx, src, caller, self, args_len, 1, Lst_pfunc_wkr.Null_arg);
new Lst_pfunc_wkr().Init_exclude(src_ttl_bry, sect_exclude, sect_replace).Exec(bfr, ctx);
}
public static final Lst_pfunc_lstx _ = new Lst_pfunc_lstx(); Lst_pfunc_lstx() {}
}

View File

@@ -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.xtns.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Lst_pfunc_lstx_tst {
private Lst_pfunc_lst_fxt fxt = new Lst_pfunc_lst_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Basic() {
fxt.Page_txt_("a<section begin=key0/> val0<section end=key0/> b<section begin=key1/> val1<section end=key1/> c").Test_lst("{{#lstx:section_test|key0}}", "a b val1 c");
}
@Test public void Replace() {
fxt.Page_txt_("a<section begin=key0/> val0<section end=key0/> b<section begin=key1/> val1<section end=key1/> c").Test_lst("{{#lstx:section_test|key0|val3}}", "aval3 b val1 c");
}
@Test public void Section_is_empty() {
fxt.Page_txt_("a<section begin=key0/> val0<section end=key0/> b<section begin=key1/> val1<section end=key1/> c").Test_lst("{{#lstx:section_test|}}", "a val0 b val1 c");
}
@Test public void Missing_bgn_end() {
fxt.Page_txt_("a<section begin=key0/> b<section end=key0/> c").Test_lst("{{#lstx:section_test}}", "a b c");
}
}

View File

@@ -0,0 +1,139 @@
/*
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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
public class Lst_pfunc_wkr {
private boolean mode_include = true;
private byte[] src_ttl_bry;
private byte[] sect_bgn, sect_end;
private byte[] sect_exclude, sect_replace;
public Lst_pfunc_wkr Init_include(byte[] src_ttl_bry, byte[] sect_bgn, byte[] sect_end) {
this.mode_include = Bool_.Y; this.src_ttl_bry = src_ttl_bry; this.sect_bgn = sect_bgn; this.sect_end = sect_end; return this;
}
public Lst_pfunc_wkr Init_exclude(byte[] src_ttl_bry, byte[] sect_exclude, byte[] sect_replace) {
this.mode_include = Bool_.N; this.src_ttl_bry = src_ttl_bry; this.sect_exclude = sect_exclude; this.sect_replace = sect_replace; return this;
}
public void Exec(Bry_bfr bfr, Xop_ctx ctx) {
Xowe_wiki wiki = ctx.Wiki();
Xoa_ttl src_ttl = Xoa_ttl.parse_(wiki, src_ttl_bry); if (src_ttl == null) return; // {{#lst:<>}} -> ""
Xot_defn_tmpl defn_tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Lst_cache().Get_by_key(src_ttl_bry);
Xop_ctx sub_ctx = null;
byte[] src = null;
if (defn_tmpl == null) { // cache transclusions to prevent multiple parsings; DATE:2014-02-22
sub_ctx = Xop_ctx.new_sub_(wiki).Ref_ignore_(true);
byte[] src_page_bry = wiki.Cache_mgr().Page_cache().Get_or_load_as_src(src_ttl);
if (src_page_bry == null) return; // {{#lst:missing}} -> ""
Xoae_page page = ctx.Cur_page();
if (!page.Tmpl_stack_add(src_ttl.Full_db())) return;
defn_tmpl = wiki.Parser().Parse_text_to_defn_obj(sub_ctx, sub_ctx.Tkn_mkr(), src_ttl.Ns(), src_ttl_bry, src_page_bry); // NOTE: parse as tmpl to ignore <noinclude>
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
page.Tmpl_stack_del(); // take template off stack; evaluate will never recurse, and will fail if ttl is still on stack; DATE:2014-03-10
defn_tmpl.Tmpl_evaluate(sub_ctx, Xot_invk_temp.Page_is_caller, tmp_bfr);
src = tmp_bfr.To_bry_and_rls();
if (!page.Tmpl_stack_add(src_ttl.Full_db())) return; // put template back on stack;
Xop_root_tkn root = wiki.Parser().Parse_text_to_wdom(sub_ctx, src, true); // NOTE: pass sub_ctx as old_ctx b/c entire document will be parsed, and references outside the section should be ignored;
src = root.Data_mid(); // NOTE: must set src to root.Data_mid() which is result of parse; else <nowiki> will break text; DATE:2013-07-11
wiki.Cache_mgr().Lst_cache().Add(defn_tmpl, Xow_ns_case_.Id_all);
page.Tmpl_stack_del();
defn_tmpl.Data_mid_(src);
defn_tmpl.Ctx_(sub_ctx);
}
else {
src = defn_tmpl.Data_mid();
sub_ctx = defn_tmpl.Ctx();
}
if (mode_include) Write_include(bfr, sub_ctx, src, sect_bgn, sect_end);
else Write_exclude(bfr, sub_ctx, src, sect_exclude, sect_replace);
}
private static final byte Include_between = 0, Include_to_eos = 1, Include_to_bos = 2;
private static void Write_include(Bry_bfr bfr, Xop_ctx sub_ctx, byte[] src, byte[] lst_bgn, byte[] lst_end) {
if (lst_end == Null_arg) { // no end arg; EX: {{#lst:page|bgn}}; NOTE: different than {{#lst:page|bgn|}}
if (lst_bgn == Null_arg) { // no bgn arg; EX: {{#lst:page}}
bfr.Add(src); // write all and exit
return;
}
else // bgn exists; set end to bgn; EX: {{#lst:page|bgn}} is same as {{#lst:page|bgn|bgn}}; NOTE: {{#lst:page|bgn|}} means write from bgn to eos
lst_end = lst_bgn;
}
byte include_mode = Include_between;
if (Bry_.Len_eq_0(lst_end))
include_mode = Include_to_eos;
else if (Bry_.Len_eq_0(lst_bgn))
include_mode = Include_to_bos;
int bgn_pos = 0; boolean bgn_found = false; int src_page_bry_len = src.length;
Lst_section_nde_mgr section_mgr = sub_ctx.Lst_section_mgr(); // get section_mgr from Parse
int sections_len = section_mgr.Count();
for (int i = 0; i < sections_len; i++) {
Lst_section_nde section = section_mgr.Get_at(i);
byte section_tid = section.Name_tid();
byte[] section_key = section.Section_name();
if (section_tid == Lst_section_nde.Xatr_bgn && Bry_.Eq(section_key, lst_bgn)) {
int sect_bgn_rhs = section.Xnde().Tag_close_end();
if (include_mode == Include_to_eos) { // write from cur to eos; EX: {{#lst:page|bgn|}}
bfr.Add_mid(src, sect_bgn_rhs, src_page_bry_len);
return;
}
else { // bgn and end
if (!bgn_found) { // NOTE: !bgn_found to prevent "resetting" of dupe; EX: <s begin=key0/>a<s begin=key0/>b; should start from a not b
bgn_pos = sect_bgn_rhs;
bgn_found = true;
}
}
}
else if (section_tid == Lst_section_nde.Xatr_end && Bry_.Eq(section_key, lst_end)) {
int sect_end_lhs = section.Xnde().Tag_open_bgn();
if (include_mode == Include_to_bos) { // write from bos to cur; EX: {{#lst:page||end}}
bfr.Add_mid(src, 0, sect_end_lhs);
return;
}
else {
if (bgn_found) { // NOTE: bgn_found to prevent writing from bos; EX: a<s end=key0/>b should not write anything
bfr.Add_mid(src, bgn_pos, sect_end_lhs);
bgn_found = false;
}
}
}
}
if (bgn_found) // bgn_found, but no end; write to end of page; EX: "a <section begin=key/> b" -> " b"
bfr.Add_mid(src, bgn_pos, src_page_bry_len);
}
private static void Write_exclude(Bry_bfr bfr, Xop_ctx sub_ctx, byte[] src, byte[] sect_exclude, byte[] sect_replace) {
if (Bry_.Len_eq_0(sect_exclude)) { // no exclude arg; EX: {{#lstx:page}} or {{#lstx:page}}
bfr.Add(src); // write all and exit
return;
}
Lst_section_nde_mgr section_mgr = sub_ctx.Lst_section_mgr(); // get section_mgr from Parse
int sections_len = section_mgr.Count();
int bgn_pos = 0;
for (int i = 0; i < sections_len; i++) {
Lst_section_nde section = section_mgr.Get_at(i);
byte section_tid = section.Name_tid();
byte[] section_key = section.Section_name();
if (section_tid == Lst_section_nde.Xatr_bgn && Bry_.Eq(section_key, sect_exclude)) { // exclude section found
bfr.Add_mid(src, bgn_pos, section.Xnde().Tag_open_bgn()); // write everything from bgn_pos up to exclude
}
else if (section_tid == Lst_section_nde.Xatr_end && Bry_.Eq(section_key, sect_exclude)) { // exclude end found
if (sect_replace != null)
bfr.Add(sect_replace); // write replacement
bgn_pos = section.Xnde().Tag_close_end(); // reset bgn_pos
}
}
bfr.Add_mid(src, bgn_pos, src.length);
}
public static final byte[] Null_arg = null;
}

View File

@@ -0,0 +1,57 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*;
import gplx.xowa.langs.*; import gplx.xowa.html.*;
public class Lst_section_nde implements Xox_xnde, Xop_xnde_atr_parser {
public byte[] Section_name() {return section_name;} private byte[] section_name;
public void Xatr_parse(Xowe_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_obj) {
if (xatr_obj == null) return;
byte xatr_tid = ((Byte_obj_val)xatr_obj).Val();
switch (xatr_tid) {
case Xatr_name: case Xatr_bgn: case Xatr_end:
section_name = xatr.Val_as_bry(src); name_tid = xatr_tid; break;
}
}
public Xop_xnde_tkn Xnde() {return xnde;} private Xop_xnde_tkn xnde;
public byte Name_tid() {return name_tid;} private byte name_tid;
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
Xoae_app app = ctx.App();
Xop_xatr_itm[] atrs = Xop_xatr_itm.Xatr_parse(app, this, wiki.Lang().Xatrs_section(), wiki, src, xnde);
this.xnde = xnde;
xnde.Atrs_ary_(atrs);
ctx.Lst_section_mgr().Add(this);
}
public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {} // NOTE: write nothing; <section> is just a bookmark
public static final byte Xatr_name = 0, Xatr_bgn = 1, Xatr_end = 2;
public static Hash_adp_bry new_xatrs_(Xol_lang lang) {
Hash_adp_bry rv = Hash_adp_bry.ci_utf8_(lang.Case_mgr()); // UTF8:see xatrs below
rv.Add_str_byte("name", Lst_section_nde.Xatr_name);
Xatrs_add(rv, "begin", "end");
switch (lang.Lang_id()) { // NOTE: as of v315572b, i18n is done directly in code, not in magic.php; am wary of adding keywords for general words like begin/end, so adding them manually per language; DATE:2013-02-09
case Xol_lang_itm_.Id_de: Xatrs_add(rv, "Anfang", "Ende"); break;
case Xol_lang_itm_.Id_he: Xatrs_add(rv, "התחלה", "סוף"); break;
case Xol_lang_itm_.Id_pt: Xatrs_add(rv, "começo", "fim"); break;
}
return rv;
}
private static void Xatrs_add(Hash_adp_bry hash, String key_begin, String key_end) {
hash.Add_str_byte(key_begin , Lst_section_nde.Xatr_bgn);
hash.Add_str_byte(key_end , Lst_section_nde.Xatr_end);
}
}

Some files were not shown because too many files have changed in this diff Show More