mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v1.6.5.1
This commit is contained in:
72
400_xowa/src/gplx/xowa/xtns/Xow_xtn_mgr.java
Normal file
72
400_xowa/src/gplx/xowa/xtns/Xow_xtn_mgr.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
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.xtns.gallery.*; import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.poems.*; import gplx.xowa.xtns.hiero.*;
|
||||
import gplx.xowa.xtns.scores.*; import gplx.xowa.xtns.listings.*; import gplx.xowa.xtns.titleBlacklists.*;
|
||||
public class Xow_xtn_mgr implements GfoInvkAble {
|
||||
private OrderedHash regy = OrderedHash_.new_bry_();
|
||||
public int Count() {return regy.Count();}
|
||||
public Xow_xtn_mgr Ctor_by_app(Xoa_app app) { // NOTE: needed for options
|
||||
Add(app, new Scrib_xtn_mgr());
|
||||
Add(app, new Gallery_xtn_mgr());
|
||||
Add(app, new Poem_xtn_mgr());
|
||||
Add(app, new Hiero_xtn_mgr());
|
||||
Add(app, new Score_xtn_mgr());
|
||||
Add(app, new Listing_xtn_mgr());
|
||||
Add(app, new Blacklist_xtn_mgr());
|
||||
return this;
|
||||
}
|
||||
public Xow_xtn_mgr Ctor_by_wiki(Xow_wiki wiki) {
|
||||
Xoa_app app = wiki.App();
|
||||
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);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Init_by_app(Xoa_app app) {
|
||||
int regy_len = regy.Count();
|
||||
for (int i = 0; i < regy_len; i++) {
|
||||
Xox_mgr mgr = (Xox_mgr)regy.FetchAt(i);
|
||||
mgr.Xtn_init_by_app(app);
|
||||
}
|
||||
}
|
||||
public Xow_xtn_mgr Init_by_wiki(Xow_wiki wiki) {
|
||||
int regy_len = regy.Count();
|
||||
for (int i = 0; i < regy_len; i++) {
|
||||
Xox_mgr mgr = (Xox_mgr)regy.FetchAt(i);
|
||||
mgr.Xtn_init_by_wiki(wiki);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Xox_mgr Get_at(int i) {return (Xox_mgr)regy.FetchAt(i);}
|
||||
public Xox_mgr Get_or_fail(byte[] key) {Object rv = regy.Fetch(key); if (rv == null) throw Err_.new_fmt_("unknown xtn: {0}", String_.new_utf8_(key)); return (Xox_mgr)rv;}
|
||||
private Xox_mgr Add(Xoa_app app, Xox_mgr xtn) {
|
||||
xtn.Xtn_ctor_by_app(app);
|
||||
regy.Add(xtn.Xtn_key(), xtn);
|
||||
return xtn;
|
||||
}
|
||||
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";
|
||||
}
|
||||
26
400_xowa/src/gplx/xowa/xtns/Xox_mgr.java
Normal file
26
400_xowa/src/gplx/xowa/xtns/Xox_mgr.java
Normal 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(Xoa_app app);
|
||||
void Xtn_ctor_by_wiki(Xow_wiki wiki);
|
||||
void Xtn_init_by_app(Xoa_app app);
|
||||
void Xtn_init_by_wiki(Xow_wiki wiki);
|
||||
Xox_mgr Clone_new();
|
||||
}
|
||||
54
400_xowa/src/gplx/xowa/xtns/Xox_mgr_base.java
Normal file
54
400_xowa/src/gplx/xowa/xtns/Xox_mgr_base.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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 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;} public void Enabled_n_() {enabled = false;} // TEST:
|
||||
@gplx.Virtual public void Xtn_ctor_by_app(Xoa_app app) {}
|
||||
@gplx.Virtual public void Xtn_ctor_by_wiki(Xow_wiki wiki) {}
|
||||
@gplx.Virtual public void Xtn_init_by_app(Xoa_app app) {}
|
||||
@gplx.Virtual public void Xtn_init_by_wiki(Xow_wiki wiki) {}
|
||||
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_enabled)) return Yn.X_to_str(enabled);
|
||||
else if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk_enabled = "enabled", Invk_enabled_ = "enabled_";
|
||||
public static void Xtn_write_escape(Xoa_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(Xoa_app app, Bry_bfr bfr, byte[] src) {Xtn_write_escape(app, bfr, src, 0, src.length);}
|
||||
public static void Xtn_write_escape(Xoa_app app, Bry_bfr bfr, byte[] src, int bgn, int end) {Xoh_html_wtr_escaper.Escape(app, bfr, src, bgn, end, true, false);}
|
||||
public static void Xtn_write_unsupported(Xoa_app app, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde, boolean parse_content) {
|
||||
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
|
||||
if (parse_content)
|
||||
bfr.Add(ctx.Wiki().Parser().Parse_text_to_html(ctx, Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn())));
|
||||
else
|
||||
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
|
||||
Xox_mgr_base.Xtn_write_escape(app, bfr, src, xnde.Tag_close_bgn(), xnde.Tag_close_end());
|
||||
}
|
||||
private static final byte[] Xowa_not_implemented = Bry_.new_ascii_("XOWA does not support this extension: ");
|
||||
}
|
||||
23
400_xowa/src/gplx/xowa/xtns/Xox_xnde.java
Normal file
23
400_xowa/src/gplx/xowa/xtns/Xox_xnde.java
Normal 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(Xow_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde);
|
||||
void Xtn_write(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde);
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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(Xow_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {}
|
||||
public void Xatr_parse(Xow_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {}
|
||||
public void Xtn_write(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {}
|
||||
}
|
||||
@@ -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_ascii_("<ul>"), Ul_end = Bry_.new_ascii_("</ul>")
|
||||
, Ol_bgn = Bry_.new_ascii_("<ol>"), Ol_end = Bry_.new_ascii_("</ol>")
|
||||
, Li_bgn = Bry_.new_ascii_("<li>"), Li_end = Bry_.new_ascii_("</li>")
|
||||
, Br = Bry_.new_ascii_("<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 Err_mgr._.unhandled_(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
183
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_itm.java
Normal file
183
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_itm.java
Normal 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.html.*;
|
||||
import gplx.xowa.html.*;
|
||||
class Dpl_itm {
|
||||
public ListAdp Ctg_includes() {return ctg_includes;} private ListAdp ctg_includes;
|
||||
public ListAdp Ctg_excludes() {return ctg_excludes;} private ListAdp 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(Xow_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.App().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.NewLine, 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.NewLine;
|
||||
public void Parse_cmd(Xow_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 = ListAdp_.new_(); ctg_includes.Add(Xoa_ttl.Replace_spaces(val)); break;
|
||||
case Dpl_itm_keys.Key_notcategory: if (ctg_excludes == null) ctg_excludes = ListAdp_.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_.X_to_int_or(val, Int_.MinValue); break;
|
||||
case Dpl_itm_keys.Key_offset: offset = Bry_.X_to_int_or(val, Int_.MinValue); break;
|
||||
case Dpl_itm_keys.Key_imagesperow: gallery_imgs_per_row = Bry_.X_to_int_or(val, Int_.MinValue); break;
|
||||
case Dpl_itm_keys.Key_imagewidth: gallery_img_w = Bry_.X_to_int_or(val, Int_.MinValue); break;
|
||||
case Dpl_itm_keys.Key_imageheight: gallery_img_h = Bry_.X_to_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_.HasAtBgn(key_bry, Html_consts.Comm_bgn) // ignore comment-like keys; EX: <!--category=Ctg_0--> will have key of "<!--category="
|
||||
);
|
||||
String err_msg = String_.Format("unknown_key: page={0} key={1}", String_.new_utf8_(page_ttl), String_.new_utf8_(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_()
|
||||
.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 Err_mgr._.unhandled_(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
124
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_itm_keys.java
Normal file
124
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_itm_keys.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
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 Err_mgr._.unhandled_(String_.new_utf8_(bry)); // shouldn't happen; should always go to or;
|
||||
}
|
||||
}
|
||||
public static final byte
|
||||
Key_null = Byte_.MaxValue_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_()
|
||||
.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)
|
||||
;
|
||||
}
|
||||
34
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_page.java
Normal file
34
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_page.java
Normal 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.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;
|
||||
// }
|
||||
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) {
|
||||
Xodb_page lhs = (Xodb_page)lhsObj;
|
||||
Xodb_page rhs = (Xodb_page)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_wo_ns(), rhs.Ttl_wo_ns());
|
||||
}
|
||||
return CompareAble_.Same;
|
||||
}
|
||||
}
|
||||
@@ -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_.MaxValue_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 Err_mgr._.unhandled_(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_sort.java
Normal file
43
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_sort.java
Normal 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 Err_mgr._.unhandled_(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
157
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java
Normal file
157
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.dynamicPageList; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.html.*;
|
||||
import gplx.xowa.dbs.*; import gplx.xowa.ctgs.*;
|
||||
public class Dpl_xnde implements Xox_xnde, Xop_xnde_atr_parser {
|
||||
private Dpl_itm itm = new Dpl_itm(); private ListAdp pages = ListAdp_.new_();
|
||||
public void Xatr_parse(Xow_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {} // NOTE: <dynamicPageList> has no attributes
|
||||
public void Xtn_parse(Xow_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.SortBy(new Dpl_page_sorter(itm));
|
||||
}
|
||||
public void Xtn_write(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
Xow_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("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++) {
|
||||
Xodb_page page = (Xodb_page)pages.FetchAt(i);
|
||||
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, page.Ns_id(), page.Ttl_wo_ns());
|
||||
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("/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_ascii_(" rel=\"nofollow\"");
|
||||
}
|
||||
class Dpl_page_finder {
|
||||
public static void Find_pages(ListAdp rv, Xow_wiki wiki, Dpl_itm itm) {
|
||||
rv.Clear();
|
||||
ListAdp includes = itm.Ctg_includes(); if (includes == null) return;
|
||||
int includes_len = includes.Count();
|
||||
OrderedHash old_regy = OrderedHash_.new_(), new_regy = OrderedHash_.new_(), cur_regy = OrderedHash_.new_();
|
||||
Xodb_load_mgr load_mgr = wiki.Db_mgr().Load_mgr();
|
||||
Xodb_page tmp_page = new Xodb_page();
|
||||
Int_obj_ref tmp_id = Int_obj_ref.zero_();
|
||||
ListAdp del_list = ListAdp_.new_();
|
||||
int ns_filter = itm.Ns_filter();
|
||||
OrderedHash exclude_pages = OrderedHash_.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.FetchAt(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 = OrderedHash_.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.FetchAt(i);
|
||||
rv.Add(new Xodb_page().Id_(old_id.Val()));
|
||||
}
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(Cancelable_.Never, rv, 0, pages_len);
|
||||
rv.SortBy(Xodb_page_sorter.IdAsc);
|
||||
}
|
||||
private static void Find_excludes(OrderedHash exclude_pages, Xodb_load_mgr load_mgr, Xodb_page tmp_page, Int_obj_ref tmp_id, ListAdp 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.FetchAt(i);
|
||||
Find_pages_in_ctg(exclude_pages, load_mgr, tmp_page, tmp_id, exclude_ctg);
|
||||
}
|
||||
}
|
||||
private static void Find_pages_in_ctg(OrderedHash list, Xodb_load_mgr load_mgr, Xodb_page 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, OrderedHash old_regy, OrderedHash cur_regy, ListAdp 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.FetchAt(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.FetchAt(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, OrderedHash old_regy, OrderedHash cur_regy, OrderedHash new_regy, OrderedHash 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.FetchAt(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.AddKeyVal(Int_obj_ref.new_(cur_itm.Id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
232
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java
Normal file
232
400_xowa/src/gplx/xowa/xtns/dynamicPageList/Dpl_xnde_tst.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
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.*;
|
||||
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("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("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"));
|
||||
}
|
||||
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().Ui_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
|
||||
Io_mgr._.InitEngine_mem();
|
||||
}
|
||||
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_utf8_(ttl));
|
||||
Xoa_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.XtoStrAndClear();
|
||||
}
|
||||
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_();
|
||||
}
|
||||
179
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_html_wtr.java
Normal file
179
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_html_wtr.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
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.*;
|
||||
public class Gallery_html_wtr {
|
||||
private int itms_per_row, itms_len; private boolean mode_is_packed;
|
||||
public int Itm_div_w() {return itm_div_w;} private int itm_div_w;
|
||||
public int Itm_div_h() {return itm_div_h;} private int itm_div_h;
|
||||
public int Itm_box_w() {return itm_box_w;} private int itm_box_w;
|
||||
public int Mgr_box_width_row() {return mgr_box_width_row;} private int mgr_box_width_row;
|
||||
public int Mgr_box_width_all() {return mgr_box_width_all;} private int mgr_box_width_all;
|
||||
public byte[] Mgr_box_cls() {return mgr_box_cls;} private byte[] mgr_box_cls;
|
||||
public Bry_fmtr Mgr_box_style() {return mgr_box_style;} private Bry_fmtr mgr_box_style;
|
||||
public int Gallery_multiplier() {return gallery_multiplier;} private int gallery_multiplier;
|
||||
public void Write_html(Xoa_app app, Xow_wiki wiki, Xop_ctx ctx, Xoa_page page, Xoh_html_wtr wtr, Xoh_html_wtr_ctx hctx, Bry_bfr bfr, byte[] src, Gallery_xnde mgr) {
|
||||
itms_per_row = mgr.Itms_per_row();
|
||||
if (itms_per_row == Gallery_xnde.Null) itms_per_row = wiki.Cfg_gallery().Imgs_per_row();
|
||||
itms_len = mgr.Itms_len();
|
||||
itm_div_w = Gallery_html_wtr_utl.Calc_itm_div_len(mgr.Itm_w_or_default());
|
||||
itm_div_h = Gallery_html_wtr_utl.Calc_itm_div_len(mgr.Itm_h_or_default());
|
||||
itm_box_w = Gallery_html_wtr_utl.Calc_itm_box_w(itm_div_w);
|
||||
if (itms_per_row == Gallery_xnde.Null) { // no "perrow" defined; default to total # of items;
|
||||
gallery_multiplier = itms_len;
|
||||
mgr_box_style = fmtr_mgr_box_style_none;
|
||||
}
|
||||
else {
|
||||
gallery_multiplier = itms_per_row;
|
||||
mgr_box_style = fmtr_mgr_box_style_per_row;
|
||||
}
|
||||
mode_is_packed = Gallery_mgr_base_.Mode_is_packed(mgr.Mode());
|
||||
int gallery_w_count = 0;
|
||||
if (mode_is_packed) {
|
||||
mgr_box_cls = Gallery_box_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) * gallery_multiplier; // 8=Gallery Box borders; REF.MW:ImageGallery.php|GB_BORDERS;
|
||||
}
|
||||
mgr_box_width_row = Gallery_html_wtr_utl.Calc_itm_pad_w(itm_box_w) * itms_per_row;
|
||||
int itm_box_w_tmp = itm_box_w;
|
||||
Bry_bfr tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_k004();
|
||||
Bry_bfr itm_bfr = wiki.Utl_bry_bfr_mkr().Get_k004();
|
||||
int mgr_elem_id = -1;
|
||||
for (int i = 0; i < itms_len; i++) {
|
||||
Gallery_itm itm = mgr.Itms_get_at(i);
|
||||
byte[] itm_caption = Bld_caption(wiki, wtr, ctx, 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).Lnki_w_(mgr.Itm_w()).Lnki_h_(mgr.Itm_h());
|
||||
Xof_xfer_itm xfer_itm = wtr.Lnki_wtr().File_wtr().Lnki_eval(ctx, page, lnki, wtr.Queue_add_ref())
|
||||
.Gallery_mgr_h_(mgr.Itm_h_or_default())
|
||||
.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_tmp);
|
||||
++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_tmp = Gallery_html_wtr_utl.Calc_itm_box_w(itm_div_w);
|
||||
}
|
||||
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_src();
|
||||
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();
|
||||
}
|
||||
int v_pad = Gallery_html_wtr_utl.Calc_vpad(mgr.Itm_h(), html_h);
|
||||
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, tmp_bfr, Bry_.Mid(src, itm.Alt_bgn(), itm.Alt_end()));
|
||||
fmtr_gallery_itm_img.Bld_bfr_many(itm_bfr
|
||||
, itm_box_w_tmp, itm_div_w
|
||||
, v_pad
|
||||
, itm_elem_id
|
||||
, lnki_ttl
|
||||
, lnki_href
|
||||
, html_src
|
||||
, html_w, html_h
|
||||
, itm_caption
|
||||
, lnki_alt
|
||||
);
|
||||
}
|
||||
else {
|
||||
fmtr_gallery_itm_txt.Bld_bfr_many(itm_bfr
|
||||
, itm_box_w_tmp, 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;
|
||||
fmtr_mgr_box.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);
|
||||
}
|
||||
private static byte[] Bld_caption(Xow_wiki wiki, Xoh_html_wtr wtr, Xop_ctx ctx, Xoh_html_wtr_ctx hctx, Gallery_itm itm) {
|
||||
byte[] rv = itm.Caption_bry();
|
||||
if (Bry_.Len_gt_0(rv)) {
|
||||
Bry_bfr caption_bfr = wiki.Utl_bry_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.Mkr_rls().XtoAryAndClear();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static final byte[] Gallery_box_cls_packed = Bry_.new_utf8_(" mw-gallery-packed");
|
||||
private Bry_fmtr
|
||||
fmtr_mgr_box = 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"
|
||||
)
|
||||
, fmtr_gallery_itm_img = 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}\" src=\"~{html_src}\" width=\"~{img_width}\" height=\"~{img_height}\" />"
|
||||
, " </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", "html_src", "img_width", "img_height", "itm_caption", "img_alt"
|
||||
)
|
||||
, fmtr_gallery_itm_txt = 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"
|
||||
)
|
||||
, fmtr_mgr_box_style_none = Bry_fmtr.new_()
|
||||
, fmtr_mgr_box_style_per_row = Bry_fmtr.new_("max-width:~{gallery_width}px; _width:~{gallery_width}px;", "gallery_width")
|
||||
;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
61
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm.java
Normal file
61
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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.*;
|
||||
public class Gallery_itm implements Js_img_wkr {
|
||||
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(Xow_wiki wiki, Xop_ctx ctx, byte[] src, Gallery_xnde xnde, Xof_xfer_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;
|
||||
} private Gallery_xnde xnde; private Xof_xfer_itm xfer_itm; private Xow_wiki wiki; private Xop_ctx ctx; private byte[] src; private byte[] gallery_li_id_bry; private int gallery_itm_idx;
|
||||
public void Html_update(Xog_html_itm html_itm, int w, int h, String view_src, String orig_src) {
|
||||
Gallery_mgr_base gallery_mgr = xnde.Gallery_mgr();
|
||||
Bry_bfr bfr = wiki.Utl_bry_bfr_mkr().Get_k004(), tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_k004();
|
||||
try {
|
||||
xfer_itm.Init_xfer_by_gallery_update(w, h, view_src, orig_src);
|
||||
gallery_mgr.Write_html_itm(bfr, tmp_bfr, wiki.App(), wiki, ctx.Cur_page(), ctx, wiki.Html_mgr().Html_wtr(), src, xnde, Bry_.Empty, gallery_itm_idx, xfer_itm);
|
||||
String itm_html = bfr.XtoStrAndClear();
|
||||
html_itm.Html_elem_replace_html(String_.new_utf8_(gallery_li_id_bry), itm_html);
|
||||
if (gallery_itm_idx == xnde.Itms_len() - 1 && Gallery_mgr_base_.Mode_is_packed(xnde.Mode()))
|
||||
html_itm.Html_gallery_packed_exec();
|
||||
}
|
||||
finally {
|
||||
bfr.Mkr_rls(); tmp_bfr.Mkr_rls();
|
||||
}
|
||||
}
|
||||
}
|
||||
242
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm_parser.java
Normal file
242
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm_parser.java
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
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.parsers.lnkis.redlinks.*;
|
||||
import gplx.xowa.files.*;
|
||||
public class Gallery_itm_parser {
|
||||
private Xow_wiki wiki; private ByteTrieMgr_slim trie = ByteTrieMgr_slim.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(Xow_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 void Parse_all(ListAdp rv, Gallery_mgr_base mgr, Gallery_xnde xnde, byte[] src, int content_bgn, int content_end) {
|
||||
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.XtoAryAndClearAndTrim());
|
||||
Make_lnki_tkn(mgr, xnde, src);
|
||||
rv.Add(cur_itm);
|
||||
cur_itm = new Gallery_itm();
|
||||
}
|
||||
if (cur_mode == Mode_nl)
|
||||
++cur_pos;
|
||||
}
|
||||
}
|
||||
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_utf8_(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);
|
||||
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);
|
||||
}
|
||||
Xop_lnki_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.files.Xob_lnki_src_tid.Tid_gallery);
|
||||
lnki_tkn.Lnki_w_(-1).Lnki_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(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.NewLine: return Mode_nl;
|
||||
case Byte_ascii.CarriageReturn:
|
||||
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(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 = ctx.App().Url_converter_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 Err_.unhandled(fld_end);
|
||||
}
|
||||
}
|
||||
private byte Skip_ws() {
|
||||
while (cur_pos < end_pos) {
|
||||
cur_byte = src[cur_pos];
|
||||
switch (cur_byte) {
|
||||
case Byte_ascii.CarriageReturn:
|
||||
case Byte_ascii.Space:
|
||||
case Byte_ascii.Tab: ++cur_pos; continue; // ignore
|
||||
case Byte_ascii.Pipe: return Mode_pipe;
|
||||
case Byte_ascii.NewLine: 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) {lang.App().Usr_dlg().Warn_many("", "", "could not find gallery keyword: ~{0}", String_.new_utf8_(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(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
|
||||
*/
|
||||
112
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm_parser_tst.java
Normal file
112
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_itm_parser_tst.java
Normal 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 Xoa_app app; private Xow_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_.XtoStr(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_ascii_(kwd_val));
|
||||
parser.Init_by_wiki(wiki);
|
||||
}
|
||||
public void Test_parse(String raw, String[]... expd) {
|
||||
ListAdp actl = ListAdp_.new_();
|
||||
byte[] src = Bry_.new_ascii_(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(X_to_str_ary(src, actl)));
|
||||
}
|
||||
private String[][] X_to_str_ary(byte[] src, ListAdp list) {
|
||||
int len = list.Count();
|
||||
String[][] rv = new String[len][];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gallery_itm itm = (Gallery_itm)list.FetchAt(i);
|
||||
String[] ary = new String[5];
|
||||
rv[i] = ary;
|
||||
ary[0] = String_.new_utf8_(itm.Ttl().Full_txt());
|
||||
ary[2] = X_to_str_ary_itm(src, itm.Alt_bgn(), itm.Alt_end());
|
||||
ary[3] = X_to_str_ary_itm(src, itm.Link_bgn(), itm.Link_end());
|
||||
ary[4] = X_to_str_ary_itm(src, itm.Page_bgn(), itm.Page_end());
|
||||
byte[] caption = itm.Caption_bry();
|
||||
ary[1] = caption == null ? null : String_.new_utf8_(caption);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private String X_to_str_ary_itm(byte[] src, int bgn, int end) {
|
||||
return bgn == Bry_.NotFound && end == Bry_.NotFound ? null : String_.new_utf8_(src, bgn, end);
|
||||
}
|
||||
}
|
||||
206
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_mgr_base.java
Normal file
206
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_mgr_base.java
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
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.*;
|
||||
public abstract class Gallery_mgr_base {
|
||||
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(Xoa_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, Xow_wiki wiki, Xoa_page page, Xop_ctx ctx, byte[] src, Gallery_xnde xnde) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_b512();
|
||||
byte[] box_style = xnde.Atr_style();
|
||||
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);
|
||||
}
|
||||
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(page.File_queue().Elem_id().Val_add()).XtoAryAndClear();
|
||||
Box_hdr_write(bfr, wiki.App().Html_mgr().Whitelist_mgr(), src, gallery_ul_id, box_cls, box_style, xnde.Atrs_other());
|
||||
byte[] box_caption = xnde.Atr_caption();
|
||||
if (box_caption != Gallery_xnde.Null_bry)
|
||||
box_caption_fmtr.Bld_bfr_many(bfr, box_caption);
|
||||
|
||||
Xoa_app app = wiki.App(); 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, src, xnde, gallery_ul_id, i, null) ;
|
||||
}
|
||||
bfr.Add(box_html_end_bry);
|
||||
tmp_bfr.Mkr_rls();
|
||||
} private static final byte[] box_id_prefix_bry = Bry_.new_ascii_("xowa_gallery_ul_"), itm_id_prefix_bry = Bry_.new_ascii_("xowa_gallery_li_");
|
||||
public static byte File_found_mode = Bool_.__byte;
|
||||
public void Write_html_itm(Bry_bfr bfr, Bry_bfr tmp_bfr, Xoa_app app, Xow_wiki wiki, Xoa_page page, Xop_ctx ctx, Xoh_html_wtr html_wtr, byte[] src, Gallery_xnde xnde, byte[] gallery_ul_id, int i, Xof_xfer_itm xfer_itm) {
|
||||
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.Lnki_w(), lnki_h_orig = lnki.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(ctx, page, lnki, html_wtr.Queue_add_ref())
|
||||
.Gallery_mgr_h_(xnde.Itm_h_or_default())
|
||||
.Html_elem_tid_(Xof_html_elem.Tid_gallery_v2)
|
||||
;
|
||||
}
|
||||
byte[] gallery_li_id = tmp_bfr.Add(itm_id_prefix_bry).Add_int_variable(xfer_itm.Html_uid()).XtoAryAndClear();
|
||||
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_found();
|
||||
if (File_found_mode != Bool_.__byte)
|
||||
file_found = File_found_mode == Bool_.Y_byte;
|
||||
if ( !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.Lnki_w_(lnki_w_orig).Lnki_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, 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_xfer_for_gallery(html_w_normal, html_h_normal, html_w_expand);// NOTE: file_w should be set to expanded width so js can resize if gallery
|
||||
itm_div0_fmtr.Bld_bfr_many(tmp_bfr, this.Get_thumb_div_width(html_w_expand));
|
||||
itm_div1_fmtr.Bld_bfr_many(tmp_bfr, this.Get_vpad(itm_default_h, html_h_expand)); // <div style="margin:~{vpad}px auto;">
|
||||
wiki.Html_mgr().Html_wtr().Lnki_wtr().Write_file(tmp_bfr, ctx, Xoh_html_wtr_ctx.Basic, src, lnki, xfer_itm, alt);
|
||||
tmp_bfr.Add(itm_divs_end_bry);
|
||||
itm_html = tmp_bfr.XtoAryAndClear();
|
||||
}
|
||||
|
||||
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);
|
||||
itm_li_bgn_fmtr.Bld_bfr_many(bfr, gallery_li_id, itm_div_width);
|
||||
bfr.Add(itm_html);
|
||||
wiki.Parser().Parse_text_to_html(tmp_bfr, page, true, itm_caption);
|
||||
itm_caption = tmp_bfr.XtoAryAndClear();
|
||||
itm_caption = tmp_bfr.Add(show_filenames_link).Add(itm_caption).XtoAryAndClear();
|
||||
Wrap_gallery_text(bfr, itm_caption, html_w_expand, html_h_expand);
|
||||
bfr.Add(itm_li_end_bry);
|
||||
}
|
||||
private static final byte[]
|
||||
Wrap_gallery_text_bgn = Bry_.new_ascii_("\n <div class=\"gallerytext\">") // NOTE: The newline after <div class="gallerytext"> is needed to accommodate htmltidy
|
||||
, Wrap_gallery_text_end = Bry_.new_ascii_("\n </div>")
|
||||
;
|
||||
@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.Lnki_w_(itm_default_w);
|
||||
lnki.Lnki_h_(itm_default_h);
|
||||
}
|
||||
@gplx.Virtual public void Adjust_image_parameters(Xof_xfer_itm xfer_itm) { // REF.MW: Adjust the image parameters for a thumbnail. Used by a subclass to insert extra high resolution images.
|
||||
}
|
||||
private 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\" style=\"width: ~{width}px\">" // id=xowa_gallery_li_1
|
||||
+ "\n <div style=\"width: ~{width}px\">", "id", "width")
|
||||
, 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 style=\"margin:~{vpad}px auto;\">\n ", "vpad")
|
||||
;
|
||||
|
||||
private static final byte[]
|
||||
itm_li_end_bry = Bry_.new_ascii_ ( "\n </div>"
|
||||
+ "\n </li>")
|
||||
, box_html_end_bry = Bry_.new_ascii_ ( "\n</ul>")
|
||||
, itm_divs_end_bry = Bry_.new_ascii_ ( "\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.XtoAryAndClear();
|
||||
}
|
||||
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, ListAdp xatr_list) {
|
||||
bfr.Add_byte(Byte_ascii.Lt).Add(Html_consts.Ul_tag_bry);
|
||||
Html_wtr.Write_atr(bfr, Html_atrs.Id_bry, gallery_ul_uid);
|
||||
Html_wtr.Write_atr(bfr, Html_atrs.Cls_bry, cls);
|
||||
Html_wtr.Write_atr(bfr, Html_atrs.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.FetchAt(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(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;}
|
||||
}
|
||||
63
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_mgr_base_.java
Normal file
63
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_mgr_base_.java
Normal 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.*;
|
||||
class Gallery_mgr_base_ {
|
||||
public static byte Get_or_traditional(byte[] bry) {
|
||||
Byte_obj_val rv = (Byte_obj_val)Hash.Fetch(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_ascii_("traditional")
|
||||
, Nolines_bry = Bry_.new_ascii_("nolines")
|
||||
, Packed_bry = Bry_.new_ascii_("packed")
|
||||
, Packed_hover_bry = Bry_.new_ascii_("packed-hover")
|
||||
, Packed_overlay_bry = Bry_.new_ascii_("packed-overlay")
|
||||
;
|
||||
private static final Hash_adp_bry Hash = Hash_adp_bry.ci_()
|
||||
.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)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
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_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:A.png\" class=\"image\" xowa_title=\"A.png\"><img id=\"xowa_file_img_1\" 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_2\" 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_2\" 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_1\" 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_1\" 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 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"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_1\" 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 Ttl_caption() { // PURPOSE: 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());
|
||||
fxt.Wiki().Html_mgr().Html_wtr().Lnki_wtr().Init_by_page(fxt.Ctx(), fxt.Ctx().Cur_page());
|
||||
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_modules_js(String expd) {
|
||||
fxt.Page().Html_data().Module_mgr().Itm_globals().Enabled_n_();
|
||||
fxt.Test_html_modules_js(expd);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
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_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() { // PURPOSE: category entries get rendered with name only (no ns)
|
||||
// fxt.Test_html_frag
|
||||
// ( "<gallery>Category:A</gallery>"
|
||||
// , "<li class='gallerycaption'>B</li>"
|
||||
// );
|
||||
// }
|
||||
}
|
||||
@@ -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(Xoa_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_xfer_itm xfer_itm) {
|
||||
int w = (int)(xfer_itm.Html_w() / Scale_factor);
|
||||
int h = (int)(xfer_itm.Html_h() / Scale_factor);
|
||||
xfer_itm.Init_xfer_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.Lnki_w_((int)(Scale_factor * w));
|
||||
lnki.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_ascii_("\n <div class=\"gallerytextwrapper\" style=\"width: ")
|
||||
, Wrap_gallery_text_1 = Bry_.new_ascii_("px\"><div class=\"gallerytext\">\n") // NOTE: The newline after <div class="gallerytext"> is needed to accommodate htmltidy
|
||||
, Wrap_gallery_text_2 = Bry_.new_ascii_("\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;}
|
||||
}
|
||||
127
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xnde.java
Normal file
127
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xnde.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.gallery; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.fsdb.*;
|
||||
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 = Null_bry;
|
||||
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 ListAdp Atrs_other() {return atrs_other;} private ListAdp 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 ListAdp itms = ListAdp_.new_();
|
||||
public Gallery_itm Itms_get_at(int i) {return (Gallery_itm)itms.FetchAt(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(Xow_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: atr_caption = xatr.Val_as_bry(src); break;
|
||||
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 = ListAdp_.new_();
|
||||
atrs_other.Add(xatr);
|
||||
}
|
||||
}
|
||||
public void Xtn_parse(Xow_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.App(), 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());
|
||||
xtn_mgr.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.App().Usr_dlg().Warn_many("", "", "failed to write gallery; src=~{0} err=~{1}", String_.new_utf8_(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(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
Xow_wiki wiki = ctx.Wiki();
|
||||
try {
|
||||
if (html_wtr_v1)
|
||||
xtn_mgr.Html_wtr().Write_html(app, wiki, ctx, ctx.Cur_page(), html_wtr, opts, bfr, src, this);
|
||||
else {
|
||||
gallery_mgr.Write_html(bfr, wiki, ctx.Cur_page(), ctx, src, this);
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
wiki.App().Usr_dlg().Warn_many("", "", "failed to write gallery; src=~{0} err=~{1}", String_.new_utf8_(src, xnde.Src_bgn(), xnde.Src_end()), Err_.Message_gplx(exc));
|
||||
}
|
||||
}
|
||||
private void Init_atrs(Xow_wiki wiki) {
|
||||
Fsdb_cfg_grp cfg_grp = wiki.File_mgr().Cfg_get(Xof_fsdb_mgr_cfg.Grp_xowa);
|
||||
if (cfg_grp.Get_yn_or_n(Xof_fsdb_mgr_cfg.Key_gallery_fix_defaults)) {
|
||||
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_yn_or_n(Xof_fsdb_mgr_cfg.Key_gallery_packed) // 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;
|
||||
public static final byte[] Null_bry = null;
|
||||
}
|
||||
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_()
|
||||
.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)
|
||||
;
|
||||
}
|
||||
182
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xnde_tst.java
Normal file
182
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xnde_tst.java
Normal 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; EX.WP: 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; EX.WP: 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_utf8_(actl.Caption_bry()));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
30
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xtn_mgr.java
Normal file
30
400_xowa/src/gplx/xowa/xtns/gallery/Gallery_xtn_mgr.java
Normal 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_ascii_("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(Xow_wiki wiki) {
|
||||
parser = new Gallery_itm_parser();
|
||||
parser.Init_by_wiki(wiki);
|
||||
html_wtr = new Gallery_html_wtr();
|
||||
}
|
||||
}
|
||||
32
400_xowa/src/gplx/xowa/xtns/geoCrumbs/Geoc_isin_func.java
Normal file
32
400_xowa/src/gplx/xowa/xtns/geoCrumbs/Geoc_isin_func.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.geoCrumbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
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);
|
||||
Xow_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_bry_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.Mkr_rls().XtoAryAndClear());
|
||||
}
|
||||
public static final Geoc_isin_func _ = new Geoc_isin_func();
|
||||
}
|
||||
@@ -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_utf8_(fxt.Page().Html_data().Content_sub()));
|
||||
}
|
||||
}
|
||||
33
400_xowa/src/gplx/xowa/xtns/geoCrumbs/Geoc_isin_mgr.java
Normal file
33
400_xowa/src/gplx/xowa/xtns/geoCrumbs/Geoc_isin_mgr.java
Normal 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_obj_state Db_state() {return db_state;} private Db_obj_state db_state = Db_obj_state.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_obj_state.Created;
|
||||
}
|
||||
}
|
||||
@@ -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.*;
|
||||
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() {}
|
||||
}
|
||||
@@ -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}}" , "");}
|
||||
}
|
||||
66
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_file_mgr.java
Normal file
66
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_file_mgr.java
Normal 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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.srls.dsvs.*;
|
||||
class Hiero_file_mgr implements GfoInvkAble {
|
||||
private OrderedHash hash = OrderedHash_.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.FetchAt(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.Fetch(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;
|
||||
}
|
||||
}
|
||||
391
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_html_mgr.java
Normal file
391
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_html_mgr.java
Normal file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.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 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, Hiero_block[] blocks, int scale, boolean hr_enabled) {
|
||||
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.Asterisk: 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.XtoAryAndClear();
|
||||
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.Asterisk:
|
||||
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("\n <br/>");
|
||||
continue;
|
||||
case Byte_ascii.Asterisk:
|
||||
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.XtoAryAndClear());
|
||||
}
|
||||
}
|
||||
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(Bool_.Y, glyph);
|
||||
else if (Bry_.Eq(glyph, Tkn_gt))
|
||||
return wtr.Cartouche_img(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_ascii_("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}
|
||||
;
|
||||
}
|
||||
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 Hr(Bry_bfr bfr) {bfr.Add(Html_consts.Hr_bry).Add_byte_nl();}
|
||||
public void Tbl_eol(Bry_bfr bfr) {bfr.Add(Tbl_eol_bry);}
|
||||
private static final String
|
||||
Tbl_bgn_str = "<table class=\"mw-hiero-table\">"
|
||||
;
|
||||
private static final byte[]
|
||||
Tbl_eol_bry = Bry_.new_ascii_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " " + Tbl_bgn_str
|
||||
, " <tr>"
|
||||
));
|
||||
public byte[] Td_height(int height) {
|
||||
return temp_bfr.Add(Option_bgn_bry).Add_int_variable(height).Add(Option_end_bry).XtoAryAndClear();
|
||||
}
|
||||
private static final byte[]
|
||||
Option_bgn_bry = Bry_.new_ascii_("height: ")
|
||||
, Option_end_bry = Bry_.new_ascii_("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_ascii_("\n <td>")
|
||||
, Td_end_bry = Bry_.new_ascii_("\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 byte[]
|
||||
Cartouche_bgn_lhs_bry = Bry_.new_ascii_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <td>"
|
||||
, " " + Tbl_bgn_str
|
||||
, " <tr>"
|
||||
, " <td class='mw-hiero-box' style='height: "
|
||||
))
|
||||
, Cartouche_bgn_rhs_bry = Bry_.new_ascii_(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_ascii_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td class='mw-hiero-box' style='height: "
|
||||
))
|
||||
, Cartouche_end_rhs_bry = Bry_.new_ascii_(String_.Concat_lines_nl_skip_last
|
||||
( "px;'>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
));
|
||||
public byte[] Cartouche_img(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 Err_.new_fmt_("missing phoneme: {0}", String_.new_utf8_(glyph));
|
||||
byte[] code = phoneme_itm.Gardiner_code();
|
||||
byte[] title = bgn ? Html_consts.Lt : Html_consts.Gt;
|
||||
return cartouche_img_fmtr.Bld_bry_many(temp_bfr, Hiero_xtn_mgr.Img_src_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_utf8_(String_.Concat_lines_nl_skip_last
|
||||
( " <table class=\"mw-hiero-table\">"
|
||||
, " <tr>"
|
||||
))
|
||||
, Tbl_inner_end = Bry_.new_utf8_(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_ascii_(String_.Concat_lines_nl_skip_last
|
||||
( "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>"
|
||||
, " <tr>"
|
||||
, " <td>"
|
||||
, ""
|
||||
)
|
||||
)
|
||||
, Outer_tbl_end = Bry_.new_ascii_(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).XtoAryAndClear(); // "~{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(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 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> "
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
)
|
||||
, "width");
|
||||
private static byte[] Bld_img_src(byte[] name) {
|
||||
return Bry_.Add(Hiero_xtn_mgr.Img_src_dir, Img_src_prefix, name, Img_src_ext);
|
||||
}
|
||||
private static final byte[] Img_src_prefix = Bry_.new_ascii_("hiero_"), Img_src_ext = Bry_.new_ascii_(".png");
|
||||
}
|
||||
425
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_html_mgr_tst.java
Normal file
425
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_html_mgr_tst.java
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
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.hiero; 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();
|
||||
@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> "
|
||||
, " </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> "
|
||||
, " </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='<' alt='<' />"
|
||||
, " </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='>' alt='>' />"
|
||||
, " </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&A1.png' title='a&A1' alt='a&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&A1.png' title='a&A1' alt='a&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_();
|
||||
}
|
||||
}
|
||||
class Hiero_html_mgr_fxt {
|
||||
private Hiero_xtn_mgr xtn_mgr;
|
||||
public Xop_fxt Fxt() {return fxt;} private Xop_fxt fxt = new Xop_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_utf8_(prefab)); return this;}
|
||||
public Hiero_html_mgr_fxt Init_file(String s, int w, int h) {xtn_mgr.File_mgr().Add(Bry_.new_utf8_(s), w, h); return this;}
|
||||
public Hiero_html_mgr_fxt Init_phoneme(String phoneme, String code) {xtn_mgr.Phoneme_mgr().Add(Bry_.new_utf8_(phoneme), Bry_.new_utf8_(code)); return this;}
|
||||
public void Test_html_full_str(String raw, String expd) {fxt.Test_html_full_str(raw, expd);}
|
||||
}
|
||||
117
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_mw_tables_parser.java
Normal file
117
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_mw_tables_parser.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
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._.LoadFilBry(load_fil), evaluator);
|
||||
Php_line[] lines = (Php_line[])evaluator.List().XtoAry(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 ...);
|
||||
ListAdp tmp_list = ListAdp_.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._.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);
|
||||
}
|
||||
@@ -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.hiero; 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._.SaveFilStr(load_url, raw);
|
||||
parser.Bld_all(load_url, save_url);
|
||||
Tfds.Eq_str_lines(expd, Io_mgr._.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));
|
||||
}
|
||||
}
|
||||
132
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_parser.java
Normal file
132
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_parser.java
Normal 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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.html.*; import gplx.xowa.html.*;
|
||||
class Hiero_parser {
|
||||
private ByteTrieMgr_slim trie = ByteTrieMgr_slim.cs_();
|
||||
private ListAdp blocks = ListAdp_.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(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_consts.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_consts.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 Err_.unhandled(itm.Tid()); // should never happen
|
||||
}
|
||||
pos = new_pos;
|
||||
}
|
||||
}
|
||||
this.New_block();// flush remaining items
|
||||
return (Hiero_block[])blocks.XtoAryAndClear(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.XtoAryAndClear());
|
||||
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_consts.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_utf8_(key_str);
|
||||
Hiero_parser_itm itm = new Hiero_parser_itm(tid, key_bry);
|
||||
trie.Add(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 ListAdp list = ListAdp_.new_();
|
||||
public int Len() {return list.Count();}
|
||||
public byte[] Get_at(int i) {return (byte[])list.FetchAt(i);}
|
||||
public void Add(byte[] v) {list.Add(v);}
|
||||
}
|
||||
59
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_parser_tst.java
Normal file
59
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_parser_tst.java
Normal 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.hiero; 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_ascii_safe_null_(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_utf8_(itm.Get_at(j));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
59
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_phoneme_mgr.java
Normal file
59
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_phoneme_mgr.java
Normal 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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.srls.dsvs.*;
|
||||
class Hiero_phoneme_mgr implements GfoInvkAble {
|
||||
private OrderedHash hash = OrderedHash_.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.FetchAt(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.Fetch(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;
|
||||
}
|
||||
}
|
||||
53
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_prefab_mgr.java
Normal file
53
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_prefab_mgr.java
Normal 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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.srls.dsvs.*;
|
||||
class Hiero_prefab_mgr implements GfoInvkAble {
|
||||
private OrderedHash hash = OrderedHash_.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.FetchAt(i);}
|
||||
public Hiero_prefab_itm Get_by_key(byte[] key) {return (Hiero_prefab_itm)hash.Fetch(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);
|
||||
}
|
||||
}
|
||||
44
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_xnde.java
Normal file
44
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_xnde.java
Normal 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.hiero; 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(Xow_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_key_obj) {}
|
||||
public void Xtn_parse(Xow_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(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
xtn_mgr.Html_wtr().Render_blocks(bfr, blocks, Hiero_html_mgr.scale, false);
|
||||
}
|
||||
}
|
||||
58
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_xtn_mgr.java
Normal file
58
400_xowa/src/gplx/xowa/xtns/hiero/Hiero_xtn_mgr.java
Normal 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.hiero; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.html.modules.*;
|
||||
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_ascii_("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(Xow_wiki wiki) {
|
||||
}
|
||||
private static boolean xtn_init_done = false;
|
||||
public void Xtn_init_assert(Xow_wiki wiki) {
|
||||
if (xtn_init_done) return;
|
||||
if (!Enabled()) return;
|
||||
Xoa_app app = wiki.App();
|
||||
Io_url ext_root_dir = app.Fsys_mgr().Bin_extensions_dir().GenSubDir("Wikihiero");
|
||||
Img_src_dir = Bry_.new_utf8_(ext_root_dir.GenSubDir("img").To_http_file_str());
|
||||
// Module_css = new Xoh_module_itm("wikihiero.css").Css_mgr_init(ext_root_dir.GenSubFil_nest("modules", "ext.wikihiero.css"));
|
||||
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 Xoh_module_itm Module_css;
|
||||
}
|
||||
144
400_xowa/src/gplx/xowa/xtns/imageMap/Xop_imageMap_xnde.java
Normal file
144
400_xowa/src/gplx/xowa/xtns/imageMap/Xop_imageMap_xnde.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.imageMap; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.html.*;
|
||||
import gplx.xowa.parsers.lnkis.redlinks.*; import gplx.xowa.parsers.logs.*;
|
||||
public class Xop_imageMap_xnde implements Xox_xnde {
|
||||
private boolean first = true;
|
||||
public byte[] Xtn_src() {return lnki_src;} private byte[] lnki_src;
|
||||
private Xop_root_tkn xtn_root;
|
||||
public ListAdp Shape_list() {return shape_list;} ListAdp shape_list = ListAdp_.new_();
|
||||
public void Xtn_parse(Xow_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_end);
|
||||
int content_bgn = xnde.Tag_open_end(), content_end = xnde.Tag_close_bgn();
|
||||
int nl_0_pos = Bry_finder.Find_fwd_while_not_ws(src, content_bgn, content_end);
|
||||
int cur_pos = nl_0_pos, nl_1_pos = -1;//, ws_pos_bgn = -1;
|
||||
int src_len = src.length;
|
||||
Xop_ctx imageMap_ctx = Xop_ctx.new_sub_(wiki).Tid_is_image_map_(true);
|
||||
imageMap_ctx.Para().Enabled_n_();
|
||||
Xop_tkn_mkr tkn_mkr = ctx.Tkn_mkr();
|
||||
while (true) {
|
||||
boolean last = cur_pos == content_end;
|
||||
if (last) nl_1_pos = cur_pos;
|
||||
if (nl_1_pos != -1 || last) {
|
||||
Object typeId_obj = TypeTrie.MatchAtCur(src, nl_0_pos, nl_1_pos);
|
||||
if (typeId_obj == null) { // flag itm
|
||||
if (!first && nl_1_pos - nl_0_pos > 0)
|
||||
ctx.Msg_log().Add_itm_none(Xtn_imageMap_msg.Line_type_unknown, src, nl_0_pos, nl_1_pos);
|
||||
}
|
||||
else {
|
||||
byte typeId = ((Byte_obj_val)typeId_obj).Val();
|
||||
switch (typeId) {
|
||||
case TypeId_comment: break; // NOOP
|
||||
case TypeId_desc: break; // FUTURE: flag; TODO: desc show info icon; top-right, bottom-right, bottom-left, top-left, none
|
||||
case TypeId_default:
|
||||
case TypeId_rect:
|
||||
case TypeId_circle:
|
||||
case TypeId_poly:
|
||||
// GfoLogWkr logWkr = new GfoLogWkr();
|
||||
// logWkr.Add_args(Xtn_imageMap_msg.Coords_count_invalid, TypeName[typeId], TypeCoords[typeId], coords.length);
|
||||
Xtn_imageMap_shape shape = Xtn_imageMap_shape.parse_(typeId, src, nl_0_pos + TypeTrie.Match_pos(), nl_1_pos);
|
||||
shape_list.Add(shape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//int bgn = ws_pos_bgn = -1 ? nl_0_pos : ws
|
||||
ParseLine(ctx, imageMap_ctx, wiki, tkn_mkr, root, src, src_len, xnde, nl_0_pos, nl_1_pos);
|
||||
nl_0_pos = nl_1_pos + 1;
|
||||
nl_1_pos = -1;
|
||||
}
|
||||
if (last) break;
|
||||
byte b = src[cur_pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Space:
|
||||
case Byte_ascii.Tab:
|
||||
break;
|
||||
case Byte_ascii.NewLine:
|
||||
nl_1_pos = cur_pos;
|
||||
break;
|
||||
default:
|
||||
// ws_pos_bgn = cur_pos;;
|
||||
break;
|
||||
}
|
||||
++cur_pos;
|
||||
}
|
||||
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_end);
|
||||
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>; DATE:2014-05-08
|
||||
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(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
html_wtr.Write_tkn(bfr, ctx, opts, xtn_root.Root_src(), xnde, Xoh_html_wtr.Sub_idx_null, xtn_root);
|
||||
}
|
||||
private void ParseLine(Xop_ctx orig_ctx, Xop_ctx image_map_ctx, Xow_wiki wiki, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, Xop_xnde_tkn xnde, int nl_0_pos, int nl_1_pos) {
|
||||
int line_len = nl_1_pos - nl_0_pos;
|
||||
if (line_len == 0 || src[nl_0_pos + 1] == Byte_ascii.Hash) return;
|
||||
if (first) {
|
||||
byte[] lnki_raw = Bry_.Add(Xop_tkn_.Lnki_bgn, Bry_.Mid(src, nl_0_pos, nl_1_pos), Xop_tkn_.Lnki_end);
|
||||
xtn_root = tkn_mkr.Root(lnki_src);
|
||||
image_map_ctx.Wiki().Parser().Parse_text_to_wdom(xtn_root, image_map_ctx, tkn_mkr, lnki_raw, 0);
|
||||
lnki_src = xtn_root.Root_src(); // NOTE: html_wtr will write based on parsed mid (not raw)
|
||||
xtn_root.Root_src_(lnki_src); // HACK: Xoh_html_wtr uses raw (instead of mid); put data in raw in order to conform to other xtns
|
||||
Xop_lnki_logger file_wkr = orig_ctx.Lnki().File_wkr(); // NOTE: do not do image_map_ctx.Lnki(); image_map_ctx is brand new
|
||||
Xop_lnki_tkn lnki_tkn = null;
|
||||
int subs_len = xtn_root.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Xop_tkn_itm sub_tkn = xtn_root.Subs_get(i);
|
||||
if (sub_tkn.Tkn_tid() == Xop_tkn_itm_.Tid_lnki) {
|
||||
lnki_tkn = (Xop_lnki_tkn)sub_tkn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lnki_tkn == null) {
|
||||
image_map_ctx.Wiki().App().Usr_dlg().Warn_many("", "", "image_map failed to find lnki; page=~{0} imageMap=~{1}", String_.new_utf8_(image_map_ctx.Cur_page().Ttl().Full_txt()), String_.new_utf8_(lnki_raw));
|
||||
}
|
||||
else {
|
||||
orig_ctx.Cur_page().Lnki_list().Add(lnki_tkn);
|
||||
if (file_wkr != null) file_wkr.Wkr_exec(orig_ctx, src, lnki_tkn, gplx.xowa.bldrs.files.Xob_lnki_src_tid.Tid_imageMap);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
public static final byte TypeId_default = 0, TypeId_rect = 4, TypeId_circle = 3, TypeId_poly = 5, TypeId_desc = 6, TypeId_comment = 7;
|
||||
public static ByteTrieMgr_slim TypeTrie = ByteTrieMgr_slim.ci_ascii_() // NOTE: names are not i18n'd; // NOTE:ci.ascii:MW_const.en
|
||||
.Add("default" , Byte_obj_val.new_(TypeId_default))
|
||||
.Add("rect" , Byte_obj_val.new_(TypeId_rect))
|
||||
.Add("circle" , Byte_obj_val.new_(TypeId_circle))
|
||||
.Add("poly" , Byte_obj_val.new_(TypeId_poly))
|
||||
.Add("desc" , Byte_obj_val.new_(TypeId_desc))
|
||||
.Add("#" , Byte_obj_val.new_(TypeId_comment))
|
||||
;
|
||||
}
|
||||
class Xtn_imageMap_shape {
|
||||
public byte TypeId() {return typeId;} private byte typeId;
|
||||
public int[] Coord_ary() {return coord_ary;} private int[] coord_ary = null;
|
||||
public Xop_lnki_tkn Lnki_tkn() {return lnki_tkn;} private Xop_lnki_tkn lnki_tkn = null;
|
||||
public static Xtn_imageMap_shape parse_(byte typeId, byte[] src, int bgn, int end) {
|
||||
Xtn_imageMap_shape rv = new Xtn_imageMap_shape();
|
||||
rv.typeId = typeId;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xtn_imageMap_msg {
|
||||
public static final Gfo_msg_grp Nde = Gfo_msg_grp_.new_(Xoa_app_.Nde, "image_map");
|
||||
public static final Gfo_msg_itm
|
||||
Line_type_unknown = Gfo_msg_itm_.new_warn_(Nde, "line_type_unknown", "Line type is unknown")
|
||||
, Coords_count_invalid = Gfo_msg_itm_.new_warn_(Nde, "coords_count_invalid", "Coordinate counts are invalid for shape: shape=~{0} expd=~{1} actl=~{2}")
|
||||
;
|
||||
}
|
||||
@@ -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.imageMap; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Xop_imageMap_xnde_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_page_wiki_str("<imagemap>File:A.png</imagemap>", html_img_none("File:A.png", ""));
|
||||
}
|
||||
@Test public void Caption() {
|
||||
fxt.Test_parse_page_wiki_str("<imagemap>File:A.png|thumb|bcde</imagemap>", String_.Concat_lines_nl_skip_last
|
||||
( Xop_para_wkr_basic_tst.File_html("File", "A.png", "7/0", "bcde")
|
||||
, ""
|
||||
));
|
||||
}
|
||||
@Test public void Err_trailing_ws() { // PURPOSE: empty 1st line causes failure
|
||||
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
|
||||
( "<imagemap> "
|
||||
, "File:A.png"
|
||||
, "</imagemap>"
|
||||
), html_img_none("File:A.png", ""));
|
||||
}
|
||||
@Test public void Coords_one() {
|
||||
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
|
||||
( "<imagemap>"
|
||||
, "File:A.png"
|
||||
, "circle 1 3 5 [[b|c]]"
|
||||
// , "rect 2 4 6 8"
|
||||
// , "poly 1 2 3 4 5"
|
||||
, "</imagemap>"
|
||||
), html_img_none("File:A.png", ""));
|
||||
}
|
||||
@Test public void Para_omitted() { // PURPOSE: imagemap should not be automatically enclosed in para; cs.w:Seznam_clenu_ctrn<72>ct<63>ho_Knesetu; DATE:2014-05-08
|
||||
fxt.Init_para_y_();
|
||||
fxt.Test_parse_page_wiki_str("<imagemap>File:A.png</imagemap> a", html_img_none("File:A.png", "") + String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, ""
|
||||
, "<p> a"
|
||||
, "</p>"
|
||||
));
|
||||
fxt.Init_para_n_();
|
||||
}
|
||||
private static String html_img_none(String trg, String alt) {
|
||||
return String_.Format("<a href=\"/wiki/{0}\" class=\"image\" xowa_title=\"A.png\"><img id=\"xowa_file_img_0\" alt=\"\" src=\"file:///mem/wiki/repo/trg/orig/7/0/A.png\" width=\"0\" height=\"0\" /></a>", trg, alt);
|
||||
}
|
||||
}
|
||||
23
400_xowa/src/gplx/xowa/xtns/inputBox/Xtn_inputbox_nde.java
Normal file
23
400_xowa/src/gplx/xowa/xtns/inputBox/Xtn_inputbox_nde.java
Normal 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(Xow_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(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
265
400_xowa/src/gplx/xowa/xtns/listings/Listing_xnde.java
Normal file
265
400_xowa/src/gplx/xowa/xtns/listings/Listing_xnde.java
Normal 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.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(Xow_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_ascii_("listings-unknown")).Val();
|
||||
}
|
||||
xatr_alt = Parse_wikitext(xatr_alt);
|
||||
xatr_address = Parse_wikitext(xatr_address);
|
||||
xatr_directions = Parse_wikitext(xatr_directions);
|
||||
}
|
||||
private Xow_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(Xow_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;
|
||||
Xoa_app app = wiki.App();
|
||||
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.X_to_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public void Xtn_write(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
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_bry_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.Mkr_rls().XtoAryAndClear());
|
||||
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.X_to_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_bry_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_bry_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.XtoAryAndClear());
|
||||
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_ascii_("strong")
|
||||
, Tag_a = Bry_.new_ascii_("a")
|
||||
, Tag_em = Bry_.new_ascii_("em")
|
||||
, Tag_abbr = Bry_.new_ascii_("abbr")
|
||||
, Atr_a_href = Bry_.new_ascii_("href")
|
||||
, Atr_a_class = Bry_.new_ascii_("class")
|
||||
, Atr_a_class_external_text = Bry_.new_ascii_("external text")
|
||||
, Atr_a_class_email = Bry_.new_ascii_("email")
|
||||
, Atr_a_rel = Bry_.new_ascii_("rel")
|
||||
, Atr_a_rel_nofollow = Bry_.new_ascii_("nofollow")
|
||||
, Atr_a_title = Bry_.new_ascii_("title")
|
||||
, Txt_comma_space = Bry_.new_ascii_(", ")
|
||||
, Txt_space_paren = Bry_.new_ascii_(" (")
|
||||
, Txt_colon_space = Bry_.new_ascii_(": ")
|
||||
, Txt_dot_space = Bry_.new_ascii_(". ")
|
||||
, Txt_mailto = Bry_.new_ascii_("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 Err_.unhandled(tid);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
108
400_xowa/src/gplx/xowa/xtns/listings/Listing_xnde_basic_tst.java
Normal file
108
400_xowa/src/gplx/xowa/xtns/listings/Listing_xnde_basic_tst.java
Normal 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(Xow_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", "");
|
||||
}
|
||||
}
|
||||
@@ -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>"
|
||||
, "<sleep name='name_0' address='address_0'>content_0</sleep>"
|
||||
);
|
||||
}
|
||||
@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. "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
81
400_xowa/src/gplx/xowa/xtns/listings/Listing_xtn_mgr.java
Normal file
81
400_xowa/src/gplx/xowa/xtns/listings/Listing_xtn_mgr.java
Normal 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.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_ascii_("listings");
|
||||
@Override public Xox_mgr Clone_new() {return new Listing_xtn_mgr();}
|
||||
@Override public void Xtn_init_by_wiki(Xow_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(Xow_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(Xow_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.X_to_bry_and_clear();
|
||||
}
|
||||
else {
|
||||
rv = template_text;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private byte[] Load_txt(Xow_wiki wiki, Xop_ctx sub_ctx, String ttl) {
|
||||
byte[] rv = wiki.Msg_mgr().Val_by_key_obj(Bry_.new_utf8_(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(Xow_wiki wiki, Xop_ctx sub_ctx, String ttl) {
|
||||
return wiki.Msg_mgr().Find_or_null(Bry_.new_utf8_(ttl));
|
||||
}
|
||||
public static void Create_msgs() {}
|
||||
}
|
||||
45
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lst.java
Normal file
45
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lst.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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_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() {}
|
||||
public static Hash_adp_bry new_xatrs_(Xol_lang lang) {
|
||||
Hash_adp_bry rv = Hash_adp_bry.ci_();
|
||||
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);
|
||||
}
|
||||
}
|
||||
101
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lst_tst.java
Normal file
101
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lst_tst.java
Normal 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._.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);
|
||||
}
|
||||
}
|
||||
30
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lstx.java
Normal file
30
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lstx.java
Normal 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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
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() {}
|
||||
}
|
||||
35
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lstx_tst.java
Normal file
35
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_lstx_tst.java
Normal 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");
|
||||
}
|
||||
}
|
||||
139
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_wkr.java
Normal file
139
400_xowa/src/gplx/xowa/xtns/lst/Lst_pfunc_wkr.java
Normal 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) {
|
||||
Xow_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}} -> ""
|
||||
Xoa_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_bry_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.PageIsCaller, tmp_bfr);
|
||||
src = tmp_bfr.Mkr_rls().XtoAryAndClear();
|
||||
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;
|
||||
}
|
||||
41
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde.java
Normal file
41
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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.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(Xow_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(Xow_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
|
||||
Xoa_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(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx opts, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {} // NOTE: write nothing; <section> is just a bookmark
|
||||
public static final byte Xatr_name = 0, Xatr_bgn = 1, Xatr_end = 2;
|
||||
}
|
||||
24
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde_mgr.java
Normal file
24
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde_mgr.java
Normal 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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Lst_section_nde_mgr {
|
||||
public int Count() {return list.Count();} private ListAdp list = ListAdp_.new_();
|
||||
public Lst_section_nde Get_at(int i) {return (Lst_section_nde)list.FetchAt(i);}
|
||||
public void Add(Lst_section_nde xnde) {list.Add(xnde);}
|
||||
public void Clear() {list.Clear();}
|
||||
}
|
||||
25
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde_tst.java
Normal file
25
400_xowa/src/gplx/xowa/xtns/lst/Lst_section_nde_tst.java
Normal 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.lst; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Lst_section_nde_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_page_all_str("a<section name=\"b\">c</section>d", "ad");
|
||||
}
|
||||
}
|
||||
55
400_xowa/src/gplx/xowa/xtns/mapSources/Map_dd2dms_func.java
Normal file
55
400_xowa/src/gplx/xowa/xtns/mapSources/Map_dd2dms_func.java
Normal 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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Map_dd2dms_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_mapSources_dd2dms;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Map_dd2dms_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] coord = Eval_argx(ctx, src, caller, self);
|
||||
int args_len = self.Args_len();
|
||||
Bry_bfr tmp_bfr = ctx.Wiki().Utl_bry_bfr_mkr().Get_b128();
|
||||
byte[] plus = Bry_.Empty, minus = Bry_.Empty;
|
||||
int prec = 4;
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn arg = self.Args_get_by_idx(i);
|
||||
byte[] key = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Key_tkn());
|
||||
Object key_tid_obj = Key_hash.Fetch(key);
|
||||
if (key_tid_obj != null) {
|
||||
byte[] val = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Val_tkn());
|
||||
switch (((Byte_obj_val)key_tid_obj).Val()) {
|
||||
case Key_tid_plus: plus = val; break;
|
||||
case Key_tid_minus: minus = val; break;
|
||||
case Key_tid_precision: prec = Bry_.X_to_int_or(val, prec); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp_bfr.Mkr_rls();
|
||||
Map_math map_math = Map_math._;
|
||||
if (map_math.Ctor(coord, prec, Bry_.Empty, 2))
|
||||
bfr.Add(map_math.Get_dms(plus, minus));
|
||||
else
|
||||
map_math.Fail(ctx, src, self, bfr, this.Name());
|
||||
}
|
||||
public static final Map_dd2dms_func _ = new Map_dd2dms_func(); Map_dd2dms_func() {}
|
||||
private static final byte Key_tid_plus = 1, Key_tid_minus = 2, Key_tid_precision = 3;
|
||||
private static final Hash_adp_bry Key_hash = Hash_adp_bry.cs_()
|
||||
.Add_str_byte("plus" , Key_tid_plus)
|
||||
.Add_str_byte("minus" , Key_tid_minus)
|
||||
.Add_str_byte("precision" , Key_tid_precision)
|
||||
;
|
||||
}
|
||||
@@ -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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Map_dd2dms_func_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Example() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4}}" , "{{test}}" , "14° 34' 48"");}
|
||||
@Test public void Plus() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4|plus=pos}}" , "{{test}}" , "14° 34' 48" pos");}
|
||||
@Test public void Ws() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58| precision = 4 | plus = pos }}" , "{{test}}" , "14° 34' 48" pos");}
|
||||
}
|
||||
33
400_xowa/src/gplx/xowa/xtns/mapSources/Map_deg2dd_func.java
Normal file
33
400_xowa/src/gplx/xowa/xtns/mapSources/Map_deg2dd_func.java
Normal 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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Map_deg2dd_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_mapSources_deg2dd;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Map_deg2dd_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] coord = Eval_argx(ctx, src, caller, self);
|
||||
byte[] precision_bry = Pf_func_.Eval_val_or(ctx, src, caller, self, self.Args_len(), 0, null);
|
||||
int prec = precision_bry == null ? -1 : Bry_.X_to_int_or(precision_bry, -1);
|
||||
Map_math map_math = Map_math._;
|
||||
if (map_math.Ctor(coord, prec, Bry_.Empty, 2))
|
||||
bfr.Add_double(map_math.Coord_dec());
|
||||
else
|
||||
map_math.Fail(ctx, src, self, bfr, this.Name());
|
||||
}
|
||||
public static final Map_deg2dd_func _ = new Map_deg2dd_func(); Map_deg2dd_func() {}
|
||||
}
|
||||
@@ -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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Map_deg2dd_func_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Prec_basic() {fxt.Test_parse_tmpl_str_test("{{#deg2dd: 1.2345|2}}" , "{{test}}" , "1.23");}
|
||||
@Test public void Prec_round() {fxt.Test_parse_tmpl_str_test("{{#deg2dd: 1.2345|3}}" , "{{test}}" , "1.235");}
|
||||
@Test public void Example() {fxt.Test_parse_tmpl_str_test("{{#deg2dd: 14° 23' 45'' S|precision=3}}" , "{{test}}" , "-14.396");}
|
||||
@Test public void Example_N() {fxt.Test_parse_tmpl_str_test("{{#deg2dd: 14° 23' 45'' N|precision=3}}" , "{{test}}" , "14.396");}
|
||||
}
|
||||
106
400_xowa/src/gplx/xowa/xtns/mapSources/Map_geolink_func.java
Normal file
106
400_xowa/src/gplx/xowa/xtns/mapSources/Map_geolink_func.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Map_geolink_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_mapSources_geoLink;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Map_geolink_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] mer_x_val = null, mer_y_val = null, mer_x_pos = null, mer_x_neg = null, mer_y_pos = null, mer_y_neg = null;
|
||||
int prec = 4;
|
||||
int args_len = self.Args_len();
|
||||
Bry_bfr tmp_bfr = ctx.Wiki().Utl_bry_bfr_mkr().Get_b128();
|
||||
try {
|
||||
byte[] pattern = Eval_argx(ctx, src, caller, self);
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Arg_nde_tkn arg = self.Args_get_by_idx(i);
|
||||
byte[] key = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Key_tkn());
|
||||
Object key_tid_obj = Key_hash.Fetch(key);
|
||||
if (key_tid_obj != null) {
|
||||
byte[] val = Pf_func_.Eval_tkn(tmp_bfr, ctx, src, caller, arg.Val_tkn());
|
||||
switch (((Byte_obj_val)key_tid_obj).Val()) {
|
||||
case Key_tid_lat_val: mer_x_val = val; break;
|
||||
case Key_tid_long_val: mer_y_val = val; break;
|
||||
case Key_tid_lat_pos: mer_x_pos = val; break;
|
||||
case Key_tid_lat_neg: mer_x_neg = val; break;
|
||||
case Key_tid_long_pos: mer_y_pos = val; break;
|
||||
case Key_tid_long_min: mer_y_neg = val; break;
|
||||
case Key_tid_prec: prec = Bry_.X_to_int_or(val, prec); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Map_math mer_x_math = new Map_math();
|
||||
Map_math mer_y_math = new Map_math();
|
||||
boolean mer_x_pass = mer_x_math.Ctor(mer_x_val, prec, Map_math.Dir_lat_bry, 2);
|
||||
boolean mer_y_pass = mer_y_math.Ctor(mer_y_val, prec, Map_math.Dir_long_bry, 2);
|
||||
if (!mer_x_pass) {
|
||||
mer_x_math.Fail(ctx, src, self, bfr, this.Name());
|
||||
return;
|
||||
}
|
||||
if (!mer_y_pass) {
|
||||
mer_y_math.Fail(ctx, src, self, bfr, this.Name());
|
||||
return;
|
||||
}
|
||||
Object[] args = new Object[6];
|
||||
args[0] = X_to_coord(tmp_bfr, mer_x_math, mer_x_pass, mer_x_math.Coord_dir_ns(), Bry_arg_0_fail);
|
||||
args[1] = X_to_coord(tmp_bfr, mer_y_math, mer_y_pass, mer_y_math.Coord_dir_ew(), Bry_arg_1_fail);
|
||||
args[2] = X_to_dms(mer_x_math, mer_x_pass, mer_x_pos, mer_x_neg);
|
||||
args[3] = X_to_dms(mer_y_math, mer_y_pass, mer_y_pos, mer_y_neg);
|
||||
args[4] = X_to_dec(tmp_bfr, mer_x_math, mer_x_pass);
|
||||
args[5] = X_to_dec(tmp_bfr, mer_y_math, mer_y_pass);
|
||||
bfr.Add(Xol_msg_itm_.eval_(tmp_bfr, tmp_msg_itm, pattern, args));
|
||||
} finally {tmp_bfr.Mkr_rls();}
|
||||
}
|
||||
private static final Xol_msg_itm tmp_msg_itm = new Xol_msg_itm(-1, Bry_.Empty);
|
||||
private static byte[] X_to_coord(Bry_bfr bfr, Map_math math, boolean pass, byte[] dir, byte[] or) {
|
||||
return pass
|
||||
? bfr.Add_double(Math_.Abs_double(math.Dec())).Add_byte(Byte_ascii.Underline).Add(dir).XtoAryAndClear()
|
||||
: or
|
||||
;
|
||||
}
|
||||
private static byte[] X_to_dms(Map_math math, boolean pass, byte[] pos, byte[] neg) {
|
||||
return pass
|
||||
? math.Get_dms(pos, neg)
|
||||
: Bry_.Empty // mapsources-math-incorrect-input
|
||||
;
|
||||
}
|
||||
private static byte[] X_to_dec(Bry_bfr bfr, Map_math math, boolean pass) {
|
||||
return pass
|
||||
? bfr.Add_double(math.Dec()).XtoAryAndClear()
|
||||
: Bry_arg_5_fail
|
||||
;
|
||||
}
|
||||
private static final byte[]
|
||||
Bry_arg_0_fail = Bry_.new_ascii_("0_N")
|
||||
, Bry_arg_1_fail = Bry_.new_ascii_("0_E")
|
||||
, Bry_arg_5_fail = Bry_.new_ascii_("0")
|
||||
;
|
||||
/*
|
||||
return wfMsgReplaceArgs( $pattern, $args );
|
||||
*/
|
||||
public static final Map_geolink_func _ = new Map_geolink_func(); Map_geolink_func() {}
|
||||
private static final byte Key_tid_lat_val = 1, Key_tid_long_val = 2, Key_tid_lat_pos = 3, Key_tid_lat_neg = 4, Key_tid_long_pos = 5, Key_tid_long_min = 6, Key_tid_prec = 7;
|
||||
private static final Hash_adp_bry Key_hash = Hash_adp_bry.cs_()
|
||||
.Add_str_byte("lat" , Key_tid_lat_val)
|
||||
.Add_str_byte("long" , Key_tid_long_val)
|
||||
.Add_str_byte("plusLat" , Key_tid_lat_pos)
|
||||
.Add_str_byte("minusLat" , Key_tid_lat_neg)
|
||||
.Add_str_byte("plusLong" , Key_tid_long_pos)
|
||||
.Add_str_byte("minusLong" , Key_tid_long_min)
|
||||
.Add_str_byte("precision" , Key_tid_prec)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Map_geolink_func_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Example() {
|
||||
fxt.Test_parse_tmpl_str_test
|
||||
( "{{#geoLink: $1 $2 $3 $4 $5 $6|lat=10.5|long=20.5|plusLat=N|plusLong=E|minusLat=S|minusLong=W|precision=decimal places}}", "{{test}}"
|
||||
, "10.5_N 20.5_E 10° 30' 0" N 20° 30' 0" E 10.5 20.5")
|
||||
;
|
||||
}
|
||||
}
|
||||
307
400_xowa/src/gplx/xowa/xtns/mapSources/Map_math.java
Normal file
307
400_xowa/src/gplx/xowa/xtns/mapSources/Map_math.java
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
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.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
class Map_math {// REF.MW:MapSources_math.php
|
||||
private int word_idx_nsew;
|
||||
private double[] rv = new double[4];
|
||||
private byte dir_id;
|
||||
private int prec;
|
||||
private int step;
|
||||
public double Dec() {return dec;} private double dec;
|
||||
public int Error() {return error;} private int error;
|
||||
public double Coord_dec() {return coord_dec;} private double coord_dec;
|
||||
public double Coord_deg() {return coord_deg;} private double coord_deg;
|
||||
public double Coord_min() {return coord_min;} private double coord_min;
|
||||
public double Coord_sec() {return coord_sec;} private double coord_sec;
|
||||
public byte[] Coord_dir_ns() {return coord_dir_ns;} private byte[] coord_dir_ns;
|
||||
public byte[] Coord_dir_ew() {return coord_dir_ew;} private byte[] coord_dir_ew;
|
||||
public boolean Ctor(byte[] input, int prec, byte[] dir, int until_step) {
|
||||
try {
|
||||
New_coord(input, dir, prec);
|
||||
if (until_step > 1 && error == 0)
|
||||
Set_coord();
|
||||
} catch (Exception e) {
|
||||
Err_.Noop(e);
|
||||
error = -128;
|
||||
}
|
||||
return error == 0;
|
||||
}
|
||||
public void Fail(Xop_ctx ctx, byte[] src, Xot_invk self, Bry_bfr bfr, byte[] pfunc_name) {
|
||||
byte[] self_src = Bry_.Mid(src, self.Src_bgn(), self.Src_end());
|
||||
if (error != -1) // -1 indicates empty coord; don't log, b/c it.v: often omits; it.v:Sami; DATE:2014-03-02
|
||||
ctx.App().Usr_dlg().Warn_many("", "", "mapSources failed: page=~{0} src=~{1} err=~{2}", String_.new_utf8_(ctx.Cur_page().Ttl().Full_db()), String_.new_utf8_(self_src), error);
|
||||
bfr.Add(pfunc_name).Add(Bry_failed);
|
||||
return;
|
||||
} private static final byte[] Bry_failed = Bry_.new_ascii_(" failed.");
|
||||
private void New_coord(byte[] input, byte[] dir, int prec) { // REF.MW:newCoord
|
||||
this.error = 0; this.word_idx_nsew = -1;
|
||||
coord_dec = coord_deg = coord_min = coord_sec = 0;
|
||||
rv[0] = rv[1] = rv[2] = 0; rv[3] = 1;
|
||||
this.dir_id = Parse_dir(dir);
|
||||
this.prec = Parse_precision(prec);
|
||||
this.dec = 0;
|
||||
this.step = 0;
|
||||
Parse_input(input);
|
||||
}
|
||||
private void Set_coord() { // REF.MW:setCoord
|
||||
if (step > 1) return;
|
||||
if (prec < 9)
|
||||
dec = Math_.Round(dec, prec);
|
||||
int sign = dec < 0 ? -1 : 1;
|
||||
double angle = Math_.Abs_double(dec);
|
||||
double deg = Math_.Floor(angle);
|
||||
double min = (angle - deg) * 60;
|
||||
double sec = prec > 0
|
||||
? Math_.Round((min - Math_.Floor(min)) * 60, prec - 4)
|
||||
: Math_.Round((min - Math_.Floor(min)) * 60, 0)
|
||||
;
|
||||
min = Math_.Floor(min);
|
||||
if (sec >= 60) {
|
||||
sec -= 60;
|
||||
min++;
|
||||
}
|
||||
if (prec < 3 && sec >= 30)
|
||||
min++;
|
||||
if (prec < 3)
|
||||
sec = 0;
|
||||
if (min >= 60) {
|
||||
min -= 60;
|
||||
deg++;
|
||||
}
|
||||
if (prec < 1 && min >= 30) {
|
||||
deg++;
|
||||
}
|
||||
if (prec < 1)
|
||||
min = 0;
|
||||
coord_dec = Math_.Round(dec, prec);
|
||||
coord_deg = deg * sign;
|
||||
coord_min = min;
|
||||
coord_sec = sec;
|
||||
if (sign > 0) {
|
||||
coord_dir_ns = Compass_N;
|
||||
coord_dir_ew = Compass_E;
|
||||
}
|
||||
else {
|
||||
coord_dir_ns = Compass_S;
|
||||
coord_dir_ew = Compass_W;
|
||||
}
|
||||
step = 2;
|
||||
}
|
||||
private static final byte[] Bry_deg = Bry_.new_utf8_("°"), Bry_quot = Bry_.new_ascii_(""");
|
||||
public byte[] Get_dms(byte[] plus, byte[] minus) { // REF.MW: getDMSString
|
||||
if (step < 2) Set_coord();
|
||||
double deg = coord_deg;
|
||||
if ( dec < 0
|
||||
&& (Bry_.Len_gt_0(plus) || Bry_.Len_gt_0(minus))) {
|
||||
deg = Math_.Abs_double(deg);
|
||||
}
|
||||
tmp_bfr.Add_double(deg).Add(Bry_deg);
|
||||
if (prec > 0)
|
||||
tmp_bfr.Add_byte_space().Add_double(coord_min).Add_byte(Byte_ascii.Apos);
|
||||
if (prec > 2)
|
||||
tmp_bfr.Add_byte_space().Add_double(coord_sec).Add(Bry_quot);
|
||||
byte[] letter = null;
|
||||
if (dir_id == Dir_lat_id)
|
||||
letter = coord_dir_ns;
|
||||
if (dir_id == Dir_long_id)
|
||||
letter = coord_dir_ew;
|
||||
if (dec > 0 && Bry_.Len_gt_0(plus))
|
||||
letter = plus;
|
||||
if (dec < 0 && Bry_.Len_gt_0(minus))
|
||||
letter = minus;
|
||||
if (letter != null)
|
||||
tmp_bfr.Add_byte_space().Add(letter);
|
||||
return tmp_bfr.XtoAryAndClear();
|
||||
}
|
||||
private void Parse_input(byte[] src) { // REF.MW: toDec
|
||||
src = Parse_input_normalize(tmp_bfr, src);
|
||||
if (src == null) {error = -1; return;}
|
||||
int src_len = src.length;
|
||||
int word_idx = -1, word_bgn = 0, words_len = 0;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
boolean is_last = i == src_len;
|
||||
byte b = is_last ? Byte_ascii.Space : src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Space:
|
||||
Parse_input_word(rv, src, ++word_idx, word_bgn, i);
|
||||
++words_len;
|
||||
i = Bry_finder.Find_fwd_while_space_or_tab(src, i, src_len);
|
||||
word_bgn = i;
|
||||
break;
|
||||
}
|
||||
if (is_last) break;
|
||||
i++;
|
||||
}
|
||||
if (word_idx_nsew != -1 && word_idx_nsew != words_len - 1) {error = -10; return;}
|
||||
if (words_len < 1 || words_len > 4) {error = -2; return;}
|
||||
if (rv[0] >= 0)
|
||||
dec = (rv[0] + rv[1] / 60 + rv[2] / 3600 ) * rv[3];
|
||||
else
|
||||
dec = (rv[0] - rv[1] / 60 - rv[2] / 3600 ) * rv[3];
|
||||
this.step = 1;
|
||||
}
|
||||
private boolean Parse_input_word_is_compass(byte v) {
|
||||
switch (v) {
|
||||
case Byte_ascii.Ltr_N:
|
||||
case Byte_ascii.Ltr_E:
|
||||
case Byte_ascii.Ltr_S:
|
||||
case Byte_ascii.Ltr_W:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private void Parse_input_word(double[] rv, byte[] input, int word_idx, int word_bgn, int word_end) {
|
||||
if (word_idx >= Input_units_len) return;
|
||||
byte unit_dlm = Input_units[word_idx];
|
||||
int pos = Bry_finder.Find_fwd(input, unit_dlm, word_bgn, word_end);
|
||||
if (pos != Bry_.NotFound) // remove dlms from end of bry; EX: "123'" -> "123"
|
||||
word_end = pos;
|
||||
if (!Parse_input_word_is_compass(input[word_bgn])) { // if ( is_numeric( $v ) ) {
|
||||
double word_val = Bry_.XtoDoubleByPosOr(input, word_bgn, word_end, Double_.NaN);
|
||||
if (word_val != Double_.NaN) {
|
||||
if (word_idx > 2) {error = -4; return;}
|
||||
switch (word_idx) {
|
||||
case 0:
|
||||
if (word_val <= -180 || word_val > 180) {error = -5; return;}
|
||||
rv[0] = word_val;
|
||||
break;
|
||||
case 1:
|
||||
if (word_val < 0 || word_val >= 60) {error = -6; return;}
|
||||
if (rv[0] != (int)(rv[0])) {error = -7; return;}
|
||||
rv[1] = word_val;
|
||||
break;
|
||||
case 2:
|
||||
if (word_val < 0 || word_val >= 60) {error = -8; return;}
|
||||
if (rv[1] != (int)(rv[1])) {error = -9; return;}
|
||||
rv[2] = word_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {error = -3; return;}
|
||||
}
|
||||
else { // 'NSEW'
|
||||
word_idx_nsew = word_idx;
|
||||
byte word_byte = input[word_bgn];
|
||||
if (rv[0] < 0) {error = -11; return;}
|
||||
if (word_end - word_bgn != 1) {error = -3; return;}
|
||||
switch (dir_id) {
|
||||
case Dir_long_id:
|
||||
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) {error = -12; return;}
|
||||
break;
|
||||
case Dir_lat_id:
|
||||
if (word_byte == Byte_ascii.Ltr_E || word_byte == Byte_ascii.Ltr_W) {error = -12; return;}
|
||||
break;
|
||||
case Dir_unknown_id:
|
||||
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) this.dir_id = Dir_lat_id;
|
||||
else this.dir_id = Dir_long_id;
|
||||
break;
|
||||
}
|
||||
if (this.dir_id == Dir_lat_id) {
|
||||
double rv_0 = rv[0];
|
||||
if (rv_0 < -90 || rv_0 > 90) {error = -13; return;}
|
||||
}
|
||||
if (word_byte == Byte_ascii.Ltr_S || word_byte == Byte_ascii.Ltr_W)
|
||||
rv[3] = -1;
|
||||
}
|
||||
}
|
||||
private static byte Parse_dir(byte[] dir) {
|
||||
if (Bry_.Len_eq_0(dir)) return Dir_unknown_id;
|
||||
Object dir_obj = Dir_trie.MatchAtCur(dir, 0, dir.length);
|
||||
return dir_obj == null ? Dir_unknown_id : ((Byte_obj_val)dir_obj).Val();
|
||||
}
|
||||
private static int Parse_precision(int val) { // REF.MW: MapSourcesMath.php|newCoord
|
||||
if (val > -1 && val < 10) return val;
|
||||
else if (val == -1) return 9;
|
||||
else return 4;
|
||||
}
|
||||
private Bry_bfr tmp_bfr = Bry_bfr.reset_(32);
|
||||
private static byte[] Parse_input_normalize(Bry_bfr bfr, byte[] input) {
|
||||
int input_end = input.length; if (input_end == 0) return null;
|
||||
int i = 0;
|
||||
while (i < input_end) {
|
||||
byte b = input[i];
|
||||
Object o = Input_trie.Match(b, input, i, input_end);
|
||||
if (o == null) {
|
||||
bfr.Add_byte(b);
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
byte tid = ((Byte_obj_val)o).Val();
|
||||
switch (tid) {
|
||||
case Input_tid_apos: bfr.Add_byte(Byte_ascii.Apos).Add_byte_space(); break; // EX: "'" -> "' "
|
||||
case Input_tid_quote: bfr.Add_byte(Byte_ascii.Quote).Add_byte_space(); break; // EX: '"' -> '" '
|
||||
case Input_tid_dash: bfr.Add_byte(Byte_ascii.Dash); break;
|
||||
case Input_tid_space: bfr.Add_byte_space(); break;
|
||||
case Input_tid_degree: bfr.Add_byte(Byte_ascii.Slash); bfr.Add_byte_space(); break; // EX: "°" -> "° "
|
||||
case Input_tid_compass: bfr.Add_byte_space(); bfr.Add_byte(Byte_ascii.Case_upper(b)); break; // NOTE: always single-char ASCII; EX: N,E,S,W,n,e,s,w
|
||||
}
|
||||
i = Input_trie.Match_pos();
|
||||
}
|
||||
}
|
||||
return bfr.XtoAryAndClearAndTrim();
|
||||
}
|
||||
private static final byte Dir_unknown_id = 0, Dir_lat_id = 1, Dir_long_id = 2;
|
||||
public static final byte[] Dir_lat_bry = Bry_.new_ascii_("lat"), Dir_long_bry = Bry_.new_ascii_("long");
|
||||
private static final ByteTrieMgr_slim Dir_trie = ByteTrieMgr_slim.ci_ascii_() // NOTE:ci.ascii:MW_const.en
|
||||
.Add_bry_bval(Dir_lat_bry , Dir_lat_id)
|
||||
.Add_bry_bval(Dir_long_bry , Dir_long_id)
|
||||
;
|
||||
private static final byte[]
|
||||
Compass_N = new byte[] {Byte_ascii.Ltr_N}
|
||||
, Compass_E = new byte[] {Byte_ascii.Ltr_E}
|
||||
, Compass_S = new byte[] {Byte_ascii.Ltr_S}
|
||||
, Compass_W = new byte[] {Byte_ascii.Ltr_W}
|
||||
;
|
||||
private static final byte Input_tid_apos = 1, Input_tid_quote = 2, Input_tid_dash = 3, Input_tid_space = 4, Input_tid_degree = 5, Input_tid_compass = 6;
|
||||
private static final byte Input_byte_degree = Byte_ascii.Slash; // NOTE: ugly cheat to avoid using multi-byte char; note that all "/" are swapped out to " ", so any remaining "/" was added by the normalizer; EX: "123° 4/5" -> "123/ 4 5"
|
||||
private static final byte[] Input_units = new byte[] {Input_byte_degree, Byte_ascii.Apos, Byte_ascii.Quote, Byte_ascii.Space};
|
||||
private static final int Input_units_len = Input_units.length;
|
||||
private static final byte[] Input_bry_degree = Bry_.new_utf8_("°");
|
||||
private static final ByteTrieMgr_slim Input_trie = ByteTrieMgr_slim.cs_()
|
||||
.Add_str_byte("'" , Input_tid_apos) // NOTE: must add ' so that "'" -> "' "
|
||||
.Add_str_byte("‘" , Input_tid_apos)
|
||||
.Add_str_byte("’" , Input_tid_apos)
|
||||
.Add_str_byte("′" , Input_tid_apos)
|
||||
.Add_str_byte("\"" , Input_tid_quote) // NOTE: must add " so that '"' -> '" '
|
||||
.Add_str_byte("''" , Input_tid_quote)
|
||||
.Add_str_byte("“" , Input_tid_quote)
|
||||
.Add_str_byte("”" , Input_tid_quote)
|
||||
.Add_str_byte("″" , Input_tid_quote)
|
||||
.Add_str_byte("-" , Input_tid_dash)
|
||||
.Add_str_byte("−" , Input_tid_dash)
|
||||
.Add_str_byte(" " , Input_tid_space)
|
||||
.Add_str_byte("_" , Input_tid_space)
|
||||
.Add_str_byte("/" , Input_tid_space)
|
||||
.Add_str_byte("\t" , Input_tid_space)
|
||||
.Add_str_byte("\n" , Input_tid_space)
|
||||
.Add_str_byte("\r" , Input_tid_space)
|
||||
.Add_bry_bval(Input_bry_degree , Input_tid_degree)
|
||||
.Add_str_byte("N" , Input_tid_compass)
|
||||
.Add_str_byte("S" , Input_tid_compass)
|
||||
.Add_str_byte("E" , Input_tid_compass)
|
||||
.Add_str_byte("W" , Input_tid_compass)
|
||||
.Add_str_byte("n" , Input_tid_compass)
|
||||
.Add_str_byte("s" , Input_tid_compass)
|
||||
.Add_str_byte("e" , Input_tid_compass)
|
||||
.Add_str_byte("w" , Input_tid_compass)
|
||||
;
|
||||
public static final Map_math _ = new Map_math();
|
||||
}
|
||||
@@ -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.massMessage; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Message_target_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_massMessage_target;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Message_target_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] argx = Eval_argx(ctx, src, caller, self); if (argx == null) return;
|
||||
bfr.Add(Xop_tkn_.Lnki_bgn).Add(argx).Add(Xop_tkn_.Lnki_end); // TODO: evaluate 2nd arg; {{#target:A|en.wikipedia.org}}
|
||||
}
|
||||
public static final Message_target_func _ = new Message_target_func(); Message_target_func() {}
|
||||
}
|
||||
@@ -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.massMessage; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Message_target_func_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_page_all_str("{{#target:A}}", "<a href=\"/wiki/A\">A</a>");
|
||||
}
|
||||
}
|
||||
31
400_xowa/src/gplx/xowa/xtns/math/Math_nde.java
Normal file
31
400_xowa/src/gplx/xowa/xtns/math/Math_nde.java
Normal 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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.html.*;
|
||||
public class Math_nde implements Xox_xnde, Xop_xnde_atr_parser {
|
||||
public Xop_xnde_tkn Xnde() {throw Err_.not_implemented_();}
|
||||
public void Xatr_parse(Xow_wiki wiki, byte[] src, Xop_xatr_itm xatr, Object xatr_obj) {}
|
||||
public void Xtn_parse(Xow_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
|
||||
Xof_math_mgr math_mgr = wiki.App().File_mgr().Math_mgr();
|
||||
if (math_mgr.Enabled() && math_mgr.Renderer_is_mathjax())
|
||||
ctx.Cur_page().Html_data().Module_mgr().Itm_mathjax().Enabled_y_();
|
||||
}
|
||||
public void Xtn_write(Xoa_app app, Xoh_html_wtr html_wtr, Xoh_html_wtr_ctx hctx, Xop_ctx ctx, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
app.File_mgr().Math_mgr().Html_wtr().Write(html_wtr, ctx, hctx, bfr, src, xnde);
|
||||
}
|
||||
}
|
||||
85
400_xowa/src/gplx/xowa/xtns/math/Xof_math_html_wtr.java
Normal file
85
400_xowa/src/gplx/xowa/xtns/math/Xof_math_html_wtr.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.html.*;
|
||||
public class Xof_math_html_wtr {
|
||||
private Xof_math_itm tmp_math_itm = new Xof_math_itm();
|
||||
private Bry_fmtr math_fmtr_latex = Bry_fmtr.new_("<img id='xowa_math_img_~{math_idx}' src='' width='' height=''/><span id='xowa_math_txt_~{math_idx}'>~{math_text}</span>", "math_idx", "math_text");
|
||||
private Bry_fmtr math_fmtr_mathjax = Bry_fmtr.new_("<span id='xowa_math_txt_~{math_idx}'>~{math_text}</span>", "math_idx", "math_text");
|
||||
public void Write(Xoh_html_wtr wtr, Xop_ctx ctx, Xoh_html_wtr_ctx opts, Bry_bfr bfr, byte[] src, Xop_xnde_tkn xnde) {
|
||||
Xoa_app app = ctx.App(); Xow_wiki wiki = ctx.Wiki(); Xoa_page page = ctx.Cur_page();
|
||||
boolean renderer_is_latex = !app.File_mgr().Math_mgr().Renderer_is_mathjax();
|
||||
byte[] math_bry = Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn());
|
||||
Bry_bfr tmp_bfr = app.Utl_bry_bfr_mkr().Get_b512().Mkr_rls();
|
||||
math_bry = Escape_tex(tmp_bfr, !renderer_is_latex, math_bry);
|
||||
byte[] math_bry_clean = app.Html_mgr().Js_cleaner().Clean(wiki, math_bry, 0, math_bry.length); // check for js;
|
||||
if (math_bry_clean != null) math_bry = math_bry_clean; // js found; use clean version; DATE:2013-08-26
|
||||
boolean enabled = app.File_mgr().Math_mgr().Enabled();
|
||||
if (renderer_is_latex && app.File_mgr().Math_mgr().Find_itm(tmp_math_itm, page.Wiki().Domain_str(), math_bry)) {
|
||||
bfr.Add(Xoh_consts.Img_bgn);
|
||||
bfr.Add_str(tmp_math_itm.Png_url().To_http_file_str());
|
||||
bfr.Add(Xoh_consts.__inline_quote);
|
||||
}
|
||||
else {
|
||||
int id = page.File_math().Count();
|
||||
Xof_math_itm new_math_itm = tmp_math_itm.Clone().Id_(id);
|
||||
Bry_fmtr math_fmtr = renderer_is_latex ? math_fmtr_latex : math_fmtr_mathjax;
|
||||
math_fmtr.Bld_bfr_many(tmp_bfr, id, math_bry);
|
||||
bfr.Add_bfr_and_clear(tmp_bfr);
|
||||
if (enabled && renderer_is_latex) // NOTE: only generate images if math is enabled; otherwise "downloading" prints at bottom of screen, but no action (also a lot of file IO)
|
||||
page.File_math().Add(new_math_itm);
|
||||
}
|
||||
}
|
||||
private static byte[] Escape_tex(Bry_bfr tmp_bfr, boolean mathjax, byte[] bry) {return Escape_tex(false, tmp_bfr, mathjax, bry, 0, bry.length);}
|
||||
private static byte[] Escape_tex(boolean write_to_bfr, Bry_bfr bfr, boolean mathjax, byte[] bry, int bgn, int end) {
|
||||
if (bry == null) return null;
|
||||
boolean dirty = write_to_bfr ? true : false; // if write_to_bfr, then mark true, else bfr.Add_mid(bry, 0, i); will write whole bry again
|
||||
byte[] escaped = null;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = bry[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Lt: if (mathjax) escaped = gplx.html.Html_consts.Lt; break;
|
||||
case Byte_ascii.Gt: if (mathjax) escaped = gplx.html.Html_consts.Gt; break;
|
||||
case Byte_ascii.Amp: escaped = Const_amp; break;
|
||||
case Byte_ascii.Quote: if (mathjax) escaped = gplx.html.Html_consts.Quote; break;
|
||||
default:
|
||||
if (dirty || write_to_bfr)
|
||||
bfr.Add_byte(b);
|
||||
continue;
|
||||
}
|
||||
// handle lt, gt, amp, quote; everything else handled by default: continue above
|
||||
if (escaped == null) { // handle do-not-escape calls; EX: Escape(y, y, n, y);
|
||||
if (dirty || write_to_bfr)
|
||||
bfr.Add_byte(b);
|
||||
}
|
||||
else {
|
||||
if (!dirty) {
|
||||
bfr.Add_mid(bry, 0, i);
|
||||
dirty = true;
|
||||
}
|
||||
bfr.Add(escaped);
|
||||
escaped = null;
|
||||
}
|
||||
}
|
||||
if (write_to_bfr)
|
||||
return null;
|
||||
else
|
||||
return dirty ? bfr.XtoAryAndClear() : bry;
|
||||
}
|
||||
private static final byte[] Const_amp = Bry_.new_ascii_("\\&");
|
||||
}
|
||||
28
400_xowa/src/gplx/xowa/xtns/math/Xof_math_itm.java
Normal file
28
400_xowa/src/gplx/xowa/xtns/math/Xof_math_itm.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.gfui.*;
|
||||
import gplx.xowa.apps.*;
|
||||
public class Xof_math_itm {
|
||||
public Xof_math_itm Ctor(byte[] math, String hash, Io_url png_url) {this.math = math; this.hash = hash; this.png_url = png_url; return this;}
|
||||
public int Id() {return id;} public Xof_math_itm Id_(int v) {id = v; return this;} private int id;
|
||||
public String Hash() {return hash;} private String hash;
|
||||
public byte[] Math() {return math;} private byte[] math;
|
||||
public Io_url Png_url() {return png_url;} Io_url png_url;
|
||||
public Xof_math_itm Clone() {return new Xof_math_itm().Ctor(math, hash, png_url);}
|
||||
}
|
||||
105
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr.java
Normal file
105
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.xowa.apps.fsys.*;
|
||||
public class Xof_math_mgr implements GfoInvkAble {
|
||||
public Xof_math_mgr(Xoa_app app) {this.app = app; html_wtr = new Xof_math_html_wtr();} private Xoa_app app;
|
||||
public ProcessAdp Cmd_convert_tex_to_dvi() {return cmd_convert_tex_to_dvi;} private ProcessAdp cmd_convert_tex_to_dvi = new ProcessAdp();
|
||||
public ProcessAdp Cmd_convert_dvi_to_png() {return cmd_convert_dvi_to_png;} private ProcessAdp cmd_convert_dvi_to_png = new ProcessAdp();
|
||||
public void Init(Xoa_app app) {
|
||||
Launcher_app_mgr app_mgr = app.Fsys_mgr().App_mgr();
|
||||
cmd_convert_tex_to_dvi = app_mgr.App_convert_tex_to_dvi();
|
||||
cmd_convert_dvi_to_png = app_mgr.App_convert_dvi_to_png();
|
||||
}
|
||||
private Io_url Make_math_dir(String wiki_key) {return app.Fsys_mgr().Root_dir().GenSubDir_nest("file", wiki_key, "math");}
|
||||
public Xof_math_html_wtr Html_wtr() {return html_wtr;} private Xof_math_html_wtr html_wtr;
|
||||
public void Make_itm(Xof_math_itm rv, String wiki_key, byte[] math_bry) {
|
||||
Io_url math_dir = Make_math_dir(wiki_key);
|
||||
math_bry = app.Math_subst_regy().Subst(math_bry);
|
||||
String md5 = gplx.security.HashAlgo_.Md5.CalcHash(ConsoleDlg_.Null, gplx.ios.IoStream_.ary_(math_bry));
|
||||
Io_url png_fil = Make_png_fil(math_dir, md5);
|
||||
rv.Ctor(math_bry, md5, png_fil);
|
||||
}
|
||||
public boolean Find_itm(Xof_math_itm rv, String wiki_key, byte[] math_bry) {
|
||||
Make_itm(rv, wiki_key, math_bry);
|
||||
return Io_mgr._.ExistsFil(rv.Png_url());
|
||||
}
|
||||
public boolean Renderer_is_mathjax() {return renderer_is_mathjax;} public void Renderer_is_mathjax_(boolean v) {renderer_is_mathjax = v;} private boolean renderer_is_mathjax = true;
|
||||
private Io_url Make_png_fil(Io_url math_dir, String hash) {
|
||||
String Math_dir_spr = math_dir.Info().DirSpr();
|
||||
tmp_sb.Clear().Add(math_dir.Raw())
|
||||
.Add(String_.CharAt(hash, 0)).Add(Math_dir_spr)
|
||||
.Add(String_.CharAt(hash, 1)).Add(Math_dir_spr)
|
||||
.Add(String_.CharAt(hash, 2)).Add(Math_dir_spr)
|
||||
.Add(hash).Add(".png")
|
||||
;
|
||||
return Io_url_.new_fil_(tmp_sb.XtoStrAndClear());
|
||||
}
|
||||
public boolean MakePng(byte[] math, String hash, Io_url png_url, String prog_fmt) {
|
||||
if (!enabled) return false;
|
||||
Io_url tmp_dir = app.Fsys_mgr().Temp_dir().GenSubDir("math"); // cmd_convert_tex_to_dvi.Tmp_dir();
|
||||
Io_url tex_url = tmp_dir.GenSubFil("xowa_math_temp.tex");
|
||||
String latex = Latex_wrap(math);
|
||||
prog_fmt = String_.Replace(prog_fmt, "~", "~~"); // double-up ~ or else will break in progress bar
|
||||
Io_mgr._.SaveFilStr(tex_url, latex);
|
||||
cmd_convert_tex_to_dvi.Prog_fmt_(prog_fmt + " tex_to_dvi: ~{process_seconds} second(s); ~{process_exe_name} ~{process_exe_args}");
|
||||
boolean pass = cmd_convert_tex_to_dvi.Run(tex_url.Raw(), tmp_dir.Xto_api()).Exit_code_pass();
|
||||
if (!pass) {
|
||||
app.Gui_wtr().Warn_many(GRP_KEY, "tex_to_dvi.fail", "fail: tex_to_dvi: error=~{0} latex=~{1}", cmd_convert_tex_to_dvi.Rslt_out(), latex);
|
||||
}
|
||||
// NOTE: latex sometimes throws errors, but will generate .dvi; for sake of simplicity; always try to run dvipng
|
||||
Io_mgr._.CreateDirIfAbsent(png_url.OwnerDir());
|
||||
cmd_convert_dvi_to_png.Prog_fmt_(prog_fmt + " dvi_to_png: ~{process_seconds} second(s); ~{process_exe_name} ~{process_exe_args}");
|
||||
pass = cmd_convert_dvi_to_png.Run(tex_url.GenNewExt(".dvi"), png_url, tmp_dir.Xto_api()).Exit_code_pass();
|
||||
if (!pass) {
|
||||
app.Gui_wtr().Warn_many(GRP_KEY, "dvi_to_png.fail", "fail: dvi_to_png: error=~{0} latex=~{1}", cmd_convert_tex_to_dvi.Rslt_out(), latex);
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
private String_bldr tmp_sb = String_bldr_.new_();
|
||||
private String Latex_wrap(byte[] math) {return Latex_doc_fmtr.Bld_str_many(String_.Replace(String_.new_utf8_(math), "\n\n", "\n"));} // NOTE: remove lines that are completely blank; not sure if this is right; EX.WP: Standard Model (mathematical formulation); <math>(\mathbf{1},\mathbf\n\n{1},0)</math>
|
||||
private static Bry_fmtr Latex_doc_fmtr = new Bry_fmtr()
|
||||
.Fmt_(String_.Concat_lines_nl_skip_last
|
||||
( "\\documentclass{article}"
|
||||
, "\\usepackage{amsmath}"
|
||||
, "\\usepackage{amsfonts}"
|
||||
, "\\usepackage{amssymb}"
|
||||
, "\\usepackage{color}"
|
||||
, "\\usepackage[landscape]{geometry}"
|
||||
, "\\pagestyle{empty}"
|
||||
, "\\begin{document}"
|
||||
, "\\begin{Large}"
|
||||
, "\\nonumber"
|
||||
, "$\\displaystyle"
|
||||
, "~{0}"
|
||||
, "$\\end{Large}"
|
||||
, "\\end{document}"
|
||||
));
|
||||
public boolean Enabled() {return enabled;} public Xof_math_mgr Enabled_(boolean v) {enabled = v; return this;} private boolean enabled = true;
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_enabled)) return Yn.X_to_str(enabled);
|
||||
else if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_renderer)) return renderer_is_mathjax ? "mathjax" : "latex";
|
||||
else if (ctx.Match(k, Invk_renderer_)) renderer_is_mathjax = String_.Eq(m.ReadStr("v"), "mathjax");
|
||||
else if (ctx.Match(k, Invk_renderer_list)) return Options_renderer_list;
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_renderer = "renderer", Invk_renderer_ = "renderer_", Invk_renderer_list = "renderer_list";
|
||||
private static KeyVal[] Options_renderer_list = KeyVal_.Ary(KeyVal_.new_("mathjax", "MathJax"), KeyVal_.new_("latex", "LaTeX"));
|
||||
private static final String GRP_KEY = "xowa.math.mgr";
|
||||
}
|
||||
30
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr_html_tst.java
Normal file
30
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr_html_tst.java
Normal 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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Xof_math_mgr_html_tst {
|
||||
@Before public void init() {} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Escape_mathjax() { // PURPOSE: escape <>&"; EX:de.w:Vergleich_(Zahlen); DATE:2014-05-10
|
||||
fxt.Test_html_full_str("<math>a<>&\"b</math>", "<span id='xowa_math_txt_0'>a<>\\&"b</span>");
|
||||
}
|
||||
@Test public void Escape_latex() {
|
||||
fxt.App().File_mgr().Math_mgr().Renderer_is_mathjax_(false);
|
||||
fxt.Test_html_full_str("<math>a<>&\"b</math>", "<img id='xowa_math_img_0' src='' width='' height=''/><span id='xowa_math_txt_0'>a<>\\&\"b</span>");
|
||||
fxt.App().File_mgr().Math_mgr().Renderer_is_mathjax_(true);
|
||||
}
|
||||
}
|
||||
27
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr_tst.java
Normal file
27
400_xowa/src/gplx/xowa/xtns/math/Xof_math_mgr_tst.java
Normal 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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*;
|
||||
public class Xof_math_mgr_tst {
|
||||
@Before public void init() {} Xof_math_subst_regy subst_regy = new Xof_math_subst_regy().Init();
|
||||
@Test public void Basic() {tst("a\\plusmn b" , "a\\pm b");}
|
||||
@Test public void Match_fails() {tst("a\\plusmna b" , "a\\plusmna b");}
|
||||
@Test public void Part() {tst("a\\part_t b" , "a\\partial_t b");} // EX.WP: Faraday's law of induction
|
||||
@Test public void Partial() {tst("a\\partial_{x_i}" , "a\\partial_{x_i}");} // DEFECT: partial -> partialial
|
||||
private void tst(String src, String expd) {Tfds.Eq(expd, String_.new_utf8_(subst_regy.Subst(Bry_.new_utf8_(src))));}
|
||||
}
|
||||
175
400_xowa/src/gplx/xowa/xtns/math/Xof_math_subst_regy.java
Normal file
175
400_xowa/src/gplx/xowa/xtns/math/Xof_math_subst_regy.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
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.math; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
public class Xof_math_subst_regy {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
public byte[] Subst(byte[] src) {
|
||||
if (!init) Init();
|
||||
int src_len = src.length;
|
||||
int dollarSignCount = 0;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
byte b = src[i];
|
||||
Object o = trie.Match(b, src, i, src_len);
|
||||
if (o == null)
|
||||
bfr.Add_byte(b);
|
||||
else {
|
||||
Xof_math_subst_itm itm = (Xof_math_subst_itm)o;
|
||||
int itm_src_len = itm.SrcLen();
|
||||
int nxt = i + itm_src_len;
|
||||
if (nxt < src_len) {
|
||||
switch (src[nxt]) { // NOTE: for now, manually list characters that are viable word end characters; NOTE: my knowledge of TeX is nil
|
||||
case Byte_ascii.Space:
|
||||
case Byte_ascii.Curly_end:
|
||||
case Byte_ascii.Brack_end:
|
||||
case Byte_ascii.Underline:
|
||||
case Byte_ascii.NewLine: // NOTE: needed for \begin\n
|
||||
break;
|
||||
default:
|
||||
if (itm.WholeWord()) {
|
||||
bfr.Add_byte(b); // itm does not match; ignore; EX: \alpha is itm, but cur text is \alpham
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
bfr.Add(itm.Trg());
|
||||
if (itm.DollarSign()) ++dollarSignCount;
|
||||
i += itm_src_len - 1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dollarSignCount; i++)
|
||||
bfr.Add_byte(Byte_ascii.Dollar);
|
||||
return bfr.XtoAryAndClearAndTrim();
|
||||
} boolean init = false;
|
||||
public Xof_math_subst_regy Init() {
|
||||
if (init) return this;
|
||||
init = true;
|
||||
Reg("\\Alpha", "\\mathrm{A}");
|
||||
Reg("\\Beta", "\\mathrm{B}");
|
||||
Reg("\\Epsilon", "\\mathrm{E}");
|
||||
Reg("\\Zeta", "\\mathrm{Z}");
|
||||
Reg("\\Eta", "\\mathrm{H}");
|
||||
Reg("\\thetasym", "\\vartheta");
|
||||
Reg("\\Iota", "\\mathrm{I}");
|
||||
Reg("\\Kappa", "\\mathrm{K}");
|
||||
Reg("\\Mu", "\\mathrm{M}");
|
||||
Reg("\\Nu", "\\mathrm{N}");
|
||||
Reg("\\omicron", "\\mathrm{o}");
|
||||
Reg("\\Omicron", "\\mathrm{O}");
|
||||
Reg("\\Rho", "\\mathrm{P}");
|
||||
Reg("\\Tau", "\\mathrm{T}");
|
||||
Reg("\\Chi", "\\mathrm{X}");
|
||||
Reg("\\alef", "\\aleph");
|
||||
Reg("\\alefsym", "\\aleph");
|
||||
Reg("\\larr", "\\leftarrow");
|
||||
Reg("\\rarr", "\\rightarrow");
|
||||
Reg("\\Larr", "\\Leftarrow");
|
||||
Reg("\\lArr", "\\Leftarrow");
|
||||
Reg("\\Rarr", "\\Rightarrow");
|
||||
Reg("\\rArr", "\\Rightarrow");
|
||||
Reg("\\uarr", "\\uparrow");
|
||||
Reg("\\uArr", "\\Uparrow");
|
||||
Reg("\\Uarr", "\\Uparrow");
|
||||
Reg("\\darr", "\\downarrow");
|
||||
Reg("\\dArr", "\\Downarrow");
|
||||
Reg("\\Darr", "\\Downarrow");
|
||||
Reg("\\lrarr", "\\leftrightarrow");
|
||||
Reg("\\harr", "\\leftrightarrow");
|
||||
Reg("\\Lrarr", "\\Leftrightarrow");
|
||||
Reg("\\Harr", "\\Leftrightarrow");
|
||||
Reg("\\lrArr", "\\Leftrightarrow");
|
||||
Reg("\\hAar", "\\Leftrightarrow");
|
||||
Reg("\\bull", "\\bullet");
|
||||
Reg("\\Dagger", "\\ddagger");
|
||||
Reg("\\weierp", "\\wp");
|
||||
Reg("\\and", "\\land");
|
||||
Reg("\\or", "\\lor");
|
||||
Reg("\\sub", "\\subset");
|
||||
Reg("\\supe", "\\supseteq");
|
||||
Reg("\\sube", "\\subseteq");
|
||||
Reg("\\infin", "\\infty");
|
||||
Reg("\\isin", "\\in");
|
||||
Reg("\\exist", "\\exists");
|
||||
Reg("\\ne", "\\neq");
|
||||
Reg("\\real", "\\Re");
|
||||
Reg("\\image", "\\Im");
|
||||
Reg("\\plusmn", "\\pm");
|
||||
Reg("\\sdot", "\\cdot");
|
||||
Reg("\\empty", "\\emptyset");
|
||||
Reg("\\O", "\\emptyset");
|
||||
Reg("\\sect", "\\S");
|
||||
Reg("\\ge", "\\geq");
|
||||
Reg("\\le", "\\leq");
|
||||
Reg("\\ang", "\\angle");
|
||||
Reg("\\part", "\\partial", false, true);
|
||||
Reg("\\lang", "\\langle");
|
||||
Reg("\\rang", "\\rangle");
|
||||
Reg("\\lbrack", "[");
|
||||
Reg("\\rbrack", "]");
|
||||
Reg("\\clubs", "\\clubsuit");
|
||||
Reg("\\spades", "\\spadesuit");
|
||||
Reg("\\hearts", "\\heartsuit");
|
||||
Reg("\\diamonds", "\\diamondsuit");
|
||||
Reg("\\euro", "\\mbox{\\euro}");
|
||||
Reg("\\geneuro", "\\mbox{\\geneuro}");
|
||||
Reg("\\geneuronarrow", "\\mbox{\\geneuronarrow}");
|
||||
Reg("\\geneurowide", "\\mbox{\\geneurowide}");
|
||||
Reg("\\officialeuro", "\\mbox{\\officialeuro}");
|
||||
Reg("\\Coppa", "\\mbox{\\Coppa}");
|
||||
Reg("\\coppa", "\\mbox{\\coppa}");
|
||||
Reg("\\varcoppa", "\\mbox{\\coppa}");
|
||||
Reg("\\Digamma", "\\mbox{\\Digamma}");
|
||||
Reg("\\Koppa", "\\mbox{\\Koppa}");
|
||||
Reg("\\koppa", "\\mbox{\\koppa}");
|
||||
Reg("\\Sampi", "\\mbox{\\Sampi}");
|
||||
Reg("\\sampi", "\\mbox{\\sampi}");
|
||||
Reg("\\Stigma", "\\mbox{\\Stigma}");
|
||||
Reg("\\stigma", "\\mbox{\\stigma}");
|
||||
Reg("\\varstigma", "\\mbox{\\varstigma}");
|
||||
Reg("\\reals", "\\mathbb{R}");
|
||||
Reg("\\Reals", "\\mathbb{R}");
|
||||
Reg("\\R", "\\mathbb{R}");
|
||||
Reg("\\C", "\\mathbb{C}");
|
||||
Reg("\\cnums", "\\mathbb{C}");
|
||||
Reg("\\Complex", "\\mathbb{C}");
|
||||
Reg("\\Z", "\\mathbb{Z}");
|
||||
Reg("\\natnums", "\\mathbb{N}");
|
||||
Reg("\\N", "\\mathbb{N}");
|
||||
Reg("\\Q", "\\mathbb{Q}");
|
||||
Reg("\\H", "\\mathbb{H}");
|
||||
Reg("\\restriction", "\\upharpoonright");
|
||||
Reg("\\begin{align}", "\n$\\begin{align}", true, true); // HACK: \begin{align} needs to have preceding blank line else "\begin{align} allowed only in paragraph mode." and no dvi produced
|
||||
return this;
|
||||
}
|
||||
private void Reg(String src_str, String trg_str) {Reg(src_str, trg_str, false, true);}
|
||||
private void Reg(String src_str, String trg_str, boolean dollarSign, boolean wholeWord) {
|
||||
byte[] src_bry = Bry_.new_ascii_(src_str);
|
||||
Xof_math_subst_itm itm = new Xof_math_subst_itm(src_bry, Bry_.new_ascii_(trg_str), dollarSign, wholeWord);
|
||||
trie.Add(src_bry, itm);
|
||||
}
|
||||
ByteTrieMgr_slim trie = ByteTrieMgr_slim.cs_();
|
||||
}
|
||||
class Xof_math_subst_itm {
|
||||
public int SrcLen() {return src_len;} private int src_len;
|
||||
public byte[] Src() {return src;} private byte[] src;
|
||||
public byte[] Trg() {return trg;} private byte[] trg;
|
||||
public boolean DollarSign() {return dollarSign;} private boolean dollarSign;
|
||||
public boolean WholeWord() {return wholeWord;} private boolean wholeWord;
|
||||
public Xof_math_subst_itm(byte[] src, byte[] trg, boolean dollarSign, boolean wholeWord) {this.src = src; src_len = src.length; this.trg = trg; this.dollarSign = dollarSign; this.wholeWord = wholeWord;}
|
||||
}
|
||||
39
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr.java
Normal file
39
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.exprs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_expr extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self); if (val_dat_ary == Bry_.Empty) return;
|
||||
DecimalAdp rslt = shunter.Evaluate(ctx, val_dat_ary); // NOTE: php uses "float" but really is a double; http://www.php.net/manual/en/language.types.float.php
|
||||
if (rslt == Pfunc_expr_shunter.Null_rslt) {
|
||||
bb.Add_bfr(shunter.Err());
|
||||
// ctx.Msg_log().Add_args(src, self.Src_bgn(), self.Src_end(), Pfunc_expr_msg.Unknown);
|
||||
shunter.Err().Clear();
|
||||
}
|
||||
else
|
||||
bb.Add_str(rslt.XtoStr());
|
||||
}
|
||||
Pfunc_expr_shunter shunter = Pfunc_expr_shunter._;
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_expr;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_expr().Name_(name);}
|
||||
}
|
||||
class Pfunc_expr_msg {
|
||||
public static final Gfo_msg_grp Nde = Gfo_msg_grp_.new_(Xoa_app_.Nde, "expr");
|
||||
public static final Gfo_msg_itm Unknown = Gfo_msg_itm_.new_warn_(Nde, "unknown", "unknown");
|
||||
}
|
||||
540
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_ops.java
Normal file
540
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_ops.java
Normal file
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.exprs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
interface Expr_tkn {
|
||||
int Tid();
|
||||
byte[] Val_ary();
|
||||
String Val_str();
|
||||
}
|
||||
class Expr_tkn_ {
|
||||
public static final int Tid_operator = 1, Tid_paren_lhs = 5, Tid_paren_rhs = 6, Tid_space = 7, Tid_number = 8;
|
||||
}
|
||||
interface Func_tkn extends Expr_tkn {
|
||||
boolean Func_is_const();
|
||||
int ArgCount();
|
||||
int Precedence();
|
||||
Func_tkn GetAlt();
|
||||
boolean Calc(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack);
|
||||
}
|
||||
class Ws_tkn implements Expr_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_space;}
|
||||
public byte[] Val_ary() {return val_ary;} private byte[] val_ary;
|
||||
public String Val_str() {return val_str;} private String val_str;
|
||||
public Ws_tkn(byte b) {this.val_ary = new byte[] {b}; this.val_str = Char_.XtoStr(Char_.XbyInt(b));}
|
||||
}
|
||||
class Paren_bgn_tkn implements Expr_tkn, Func_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_paren_lhs;}
|
||||
public boolean Func_is_const() {return false;}
|
||||
public byte[] Val_ary() {return val_ary;} private byte[] val_ary = Bry_.new_utf8_(val_str);
|
||||
public String Val_str() {return val_str;} static final String val_str = "(";
|
||||
public int ArgCount() {return 0;}
|
||||
public int Precedence() {return -1;}
|
||||
public Func_tkn GetAlt() {return this;}
|
||||
public boolean Calc(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {throw Err_.not_implemented_();}
|
||||
public static Paren_bgn_tkn _ = new Paren_bgn_tkn(); Paren_bgn_tkn() {}
|
||||
}
|
||||
class Paren_end_tkn implements Expr_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_paren_rhs;}
|
||||
public byte[] Val_ary() {return val_ary;} private byte[] val_ary = Bry_.new_utf8_(val_str);
|
||||
public String Val_str() {return val_str;} static final String val_str = ")";
|
||||
public static Paren_end_tkn _ = new Paren_end_tkn(); Paren_end_tkn() {}
|
||||
}
|
||||
class Num_tkn implements Expr_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_number;}
|
||||
public byte[] Val_ary() {return val_ary;} private byte[] val_ary;
|
||||
public String Val_str() {return String_.new_utf8_(val_ary);}
|
||||
public Num_tkn(int val_int) {
|
||||
this.val_int = val_int;
|
||||
this.val_ary = new byte[] {Byte_.int_(val_int + Byte_ascii.Num_0)};
|
||||
} int val_int;
|
||||
}
|
||||
class Dot_tkn implements Expr_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_number;}
|
||||
public byte[] Val_ary() {return Val_Ary;} static final byte[] Val_Ary = new byte[] {Byte_ascii.Dot};
|
||||
public String Val_str() {return String_.new_utf8_(Val_Ary);}
|
||||
public Dot_tkn() {}
|
||||
}
|
||||
class Val_stack {
|
||||
public void Clear() {stack_len = 0;}
|
||||
public int Len() {return stack_len;}
|
||||
public DecimalAdp Pop() {
|
||||
int stack_len_new = stack_len - 1;
|
||||
DecimalAdp rv = stack[stack_len_new];
|
||||
stack_len = stack_len_new;
|
||||
return rv;
|
||||
}
|
||||
public void Push(DecimalAdp v) {
|
||||
int stack_len_new = stack_len + 1;
|
||||
if (stack_len_new > stack_max) {
|
||||
stack_max = stack_len_new * 2;
|
||||
stack = (DecimalAdp[])Array_.Resize(stack, stack_max);
|
||||
}
|
||||
stack[stack_len] = v;
|
||||
stack_len = stack_len_new;
|
||||
}
|
||||
DecimalAdp[] stack = new DecimalAdp[0]; int stack_len = 0, stack_max = 0;
|
||||
}
|
||||
class Func_tkn_stack {
|
||||
public void Clear() {stack_len = 0;}
|
||||
public int Len() {return stack_len;}
|
||||
public Func_tkn GetLast() {return stack_len == 0 ? null : stack[stack_len - 1];}
|
||||
public Func_tkn Pop() {
|
||||
int stack_len_new = stack_len - 1;
|
||||
Func_tkn rv = stack[stack_len_new];
|
||||
stack_len = stack_len_new;
|
||||
return rv;
|
||||
}
|
||||
public void Push(Func_tkn v) {
|
||||
int stack_len_new = stack_len + 1;
|
||||
if (stack_len_new > stack_max) {
|
||||
stack_max = stack_len_new * 2;
|
||||
stack = (Func_tkn[])Array_.Resize(stack, stack_max);
|
||||
}
|
||||
stack[stack_len] = v;
|
||||
stack_len = stack_len_new;
|
||||
}
|
||||
Func_tkn[] stack = new Func_tkn[0]; int stack_len = 0, stack_max = 0;
|
||||
}
|
||||
abstract class Func_tkn_base implements Func_tkn {
|
||||
public int Tid() {return Expr_tkn_.Tid_operator;}
|
||||
public abstract int Precedence();
|
||||
public abstract int ArgCount();
|
||||
@gplx.Virtual public boolean Func_is_const() {return false;}
|
||||
public void Ctor(String v) {val_ary = Bry_.new_utf8_(v);}
|
||||
public byte[] Val_ary() {return val_ary;} private byte[] val_ary;
|
||||
public String Val_str() {return String_.new_utf8_(Val_ary());}
|
||||
@gplx.Virtual public Func_tkn GetAlt() {return this;}
|
||||
public boolean Calc(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
if (val_stack.Len() < this.ArgCount()) {shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_missing_operand, Val_ary()); return false;}
|
||||
return Calc_hook(ctx, shunter, val_stack);
|
||||
}
|
||||
public abstract boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack);
|
||||
}
|
||||
class Func_tkn_plus extends Func_tkn_base {
|
||||
public Func_tkn_plus(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 6;}
|
||||
@Override public Func_tkn GetAlt() {return Func_tkn_plus_positive._;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Op_add(rhs));
|
||||
return true;
|
||||
}
|
||||
public static final Func_tkn_plus _ = new Func_tkn_plus(); Func_tkn_plus() {}
|
||||
}
|
||||
class Func_tkn_plus_positive extends Func_tkn_base {
|
||||
Func_tkn_plus_positive(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 10;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {return true;}// effectively a noop
|
||||
public static final Func_tkn_plus_positive _ = new Func_tkn_plus_positive("+");
|
||||
}
|
||||
class Func_tkn_minus extends Func_tkn_base {
|
||||
public Func_tkn_minus(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 6;}
|
||||
@Override public Func_tkn GetAlt() {return Func_tkn_minus_negative._;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Op_subtract(rhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_minus_negative extends Func_tkn_base {
|
||||
public Func_tkn_minus_negative(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 10;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(val.Op_mult(DecimalAdp_.Neg1));
|
||||
return true;
|
||||
}
|
||||
public static final Func_tkn_minus_negative _ = new Func_tkn_minus_negative("-");
|
||||
}
|
||||
class Func_tkn_divide extends Func_tkn_base {
|
||||
public Func_tkn_divide(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 7;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
if (rhs.Eq(0)) {
|
||||
shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_division_by_zero);
|
||||
return false;
|
||||
}
|
||||
val_stack.Push(lhs.Op_divide(rhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_times extends Func_tkn_base {
|
||||
public Func_tkn_times(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 7;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Op_mult(rhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_pow extends Func_tkn_base {
|
||||
public Func_tkn_pow(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 8;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
int rhs_int = rhs.XtoInt();
|
||||
if ((double)rhs_int == rhs.XtoDouble()) // exponent is integer; use decimal pow which does less casts to double
|
||||
val_stack.Push(lhs.Op_pow(rhs_int));
|
||||
else {
|
||||
double rslt = Math_.Pow(lhs.XtoDouble(), rhs.XtoDouble());
|
||||
if (Double_.IsNaN(rslt)) {
|
||||
shunter.Rslt_set(Double_.NaN_bry);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
val_stack.Push(DecimalAdp_.double_thru_str_(rslt));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_e_op extends Func_tkn_base {
|
||||
public Func_tkn_e_op(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 9;} // NOTE: needs to be < than - sign
|
||||
@Override public Func_tkn GetAlt() {return Func_tkn_e_const._;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
int rhs_int = rhs.XtoInt();
|
||||
double rhs_double = rhs.XtoDouble();
|
||||
if ((double)rhs_int == rhs_double) // exponent is integer; use pow_10 which does less casts to double
|
||||
val_stack.Push(lhs.Op_mult(DecimalAdp_.pow_10_(rhs_int)));
|
||||
else
|
||||
val_stack.Push(lhs.Op_mult(DecimalAdp_.double_thru_str_(Math_.Pow(10d, rhs_double))));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_mod extends Func_tkn_base {
|
||||
public Func_tkn_mod(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 7;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
// must convert to int else issues with {{#expr:0.00999999mod10}} and {{USCensusPop|1960=763956|1970=756510}}; REF: http://php.net/manual/en/language.operators.arithmetic.php: "Operands of modulus are converted to integers (by stripping the decimal part) before processing"
|
||||
// must convert to long else issues with (39052000900/1) mod 100 which should be 0, not 47; JAVA does not fail int conversion, and instead converts to Int_.MaxValue; EX: de.w:Quijano_(Pi<50>lagos)
|
||||
long rhs = ((DecimalAdp)val_stack.Pop()).XtoLong();
|
||||
long lhs = ((DecimalAdp)val_stack.Pop()).XtoLong();
|
||||
if (rhs == 0) {
|
||||
shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_division_by_zero);
|
||||
return false;
|
||||
}
|
||||
val_stack.Push(DecimalAdp_.long_(lhs % rhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_eq extends Func_tkn_base {
|
||||
public Func_tkn_eq(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Eq(rhs) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_neq extends Func_tkn_base {
|
||||
public Func_tkn_neq(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Eq(rhs) ? DecimalAdp_.Zero : DecimalAdp_.One);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_gt extends Func_tkn_base {
|
||||
public Func_tkn_gt(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Comp_gt(rhs) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_lt extends Func_tkn_base {
|
||||
public Func_tkn_lt(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Comp_lt(rhs) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_gte extends Func_tkn_base {
|
||||
public Func_tkn_gte(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Comp_gte(rhs) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_lte extends Func_tkn_base {
|
||||
public Func_tkn_lte(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 4;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(lhs.Comp_lte(rhs) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_and extends Func_tkn_base {
|
||||
public Func_tkn_and(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 3;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(!lhs.Eq(0) && !rhs.Eq(0) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_or extends Func_tkn_base {
|
||||
public Func_tkn_or(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 2;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
val_stack.Push(!lhs.Eq(0) || !rhs.Eq(0) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_not extends Func_tkn_base {
|
||||
public Func_tkn_not(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(val.Eq(0) ? DecimalAdp_.One : DecimalAdp_.Zero);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_e_const extends Func_tkn_base {
|
||||
public Func_tkn_e_const(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 0;}
|
||||
@Override public int Precedence() {return 0;}
|
||||
@Override public boolean Func_is_const() {return true;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
val_stack.Push(DecimalAdp_.Const_e);
|
||||
return true;
|
||||
}
|
||||
public static final Func_tkn_e_const _ = new Func_tkn_e_const("e");
|
||||
}
|
||||
class Func_tkn_pi extends Func_tkn_base {
|
||||
public Func_tkn_pi(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 0;}
|
||||
@Override public int Precedence() {return 0;}
|
||||
@Override public boolean Func_is_const() {return true;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
val_stack.Push(DecimalAdp_.Const_pi);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_ceil extends Func_tkn_base {
|
||||
public Func_tkn_ceil(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Ceil(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_trunc extends Func_tkn_base {
|
||||
public Func_tkn_trunc(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Trunc(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_floor extends Func_tkn_base {
|
||||
public Func_tkn_floor(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Floor(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_abs extends Func_tkn_base {
|
||||
public Func_tkn_abs(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(val.Op_abs());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_exp extends Func_tkn_base {
|
||||
public Func_tkn_exp(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Exp(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_ln extends Func_tkn_base {
|
||||
public Func_tkn_ln(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
if (val.Comp_lte(0)) {shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_invalid_argument_ln); return false;}
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Log(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_sin extends Func_tkn_base {
|
||||
public Func_tkn_sin(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Sin(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_cos extends Func_tkn_base {
|
||||
public Func_tkn_cos(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Cos(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_tan extends Func_tkn_base {
|
||||
public Func_tkn_tan(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Tan(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_asin extends Func_tkn_base {
|
||||
public Func_tkn_asin(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
if (val.Comp_lt(-1) || val.Comp_gt(1)) {shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_invalid_argument, this.Val_ary()); return false;}
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Asin(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_acos extends Func_tkn_base {
|
||||
public Func_tkn_acos(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
if (val.Comp_lt(-1) || val.Comp_gt(1)) {shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_invalid_argument, this.Val_ary()); return false;}
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Acos(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_atan extends Func_tkn_base {
|
||||
public Func_tkn_atan(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(DecimalAdp_.double_(Math_.Atan(val.XtoDouble())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_round extends Func_tkn_base {
|
||||
public Func_tkn_round(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 5;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = val_stack.Pop();
|
||||
DecimalAdp lhs = val_stack.Pop();
|
||||
if (rhs.Comp_gt(16)) {
|
||||
rhs = DecimalAdp_.int_(16);
|
||||
}
|
||||
else if (rhs.Comp_lt(-16)) {
|
||||
rhs = DecimalAdp_.int_(-16);
|
||||
}
|
||||
DecimalAdp val = lhs.Op_round(rhs.XtoInt());
|
||||
if (val.XtoDouble() == 0) // NOTE: must explicitly check for zero, else "0.0" will be pushed onto stack; EXE: {{#expr: 0 round 1}}; DATE:2013-11-09
|
||||
val_stack.Push(DecimalAdp_.Zero);
|
||||
else
|
||||
val_stack.Push(val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_fmod extends Func_tkn_base {
|
||||
public Func_tkn_fmod(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 2;}
|
||||
@Override public int Precedence() {return 7;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp rhs = (DecimalAdp)val_stack.Pop();
|
||||
DecimalAdp lhs = (DecimalAdp)val_stack.Pop();
|
||||
if (rhs.XtoDouble() == 0) {
|
||||
shunter.Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_division_by_zero);
|
||||
return false;
|
||||
}
|
||||
val_stack.Push(lhs.Op_mod(rhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class Func_tkn_sqrt extends Func_tkn_base {
|
||||
public Func_tkn_sqrt(String v) {this.Ctor(v);}
|
||||
@Override public int ArgCount() {return 1;}
|
||||
@Override public int Precedence() {return 9;}
|
||||
@Override public boolean Calc_hook(Xop_ctx ctx, Pfunc_expr_shunter shunter, Val_stack val_stack) {
|
||||
DecimalAdp val = val_stack.Pop();
|
||||
val_stack.Push(val.Op_sqrt());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
219
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_shunter.java
Normal file
219
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_shunter.java
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.exprs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_expr_shunter {
|
||||
ByteTrieMgr_fast trie = expression_();
|
||||
Val_stack val_stack = new Val_stack();
|
||||
Func_tkn_stack prc_stack = new Func_tkn_stack();
|
||||
public static final DecimalAdp Null_rslt = null;
|
||||
public Bry_bfr Err() {return err_bfr;} Bry_bfr err_bfr = Bry_bfr.new_();
|
||||
public DecimalAdp Err_set(Xop_ctx ctx, int msgId) {return Err_set(ctx, msgId, Bry_.Empty);}
|
||||
public DecimalAdp Err_set(Xop_ctx ctx, int msg_id, byte[] arg) {
|
||||
byte[] msg_val = ctx.Wiki().Msg_mgr().Val_by_id(msg_id);
|
||||
err_bfr.Clear().Add(Err_bgn_ary);
|
||||
tmp_fmtr.Fmt_(msg_val).Bld_bfr_one(err_bfr, arg);
|
||||
err_bfr.Add(Err_end_ary);
|
||||
return Null_rslt;
|
||||
} static final byte[] Err_bgn_ary = Bry_.new_ascii_("<strong class=\"error\">"), Err_end_ary = Bry_.new_ascii_("</strong>"); Bry_fmtr tmp_fmtr = Bry_fmtr.tmp_();
|
||||
public void Rslt_set(byte[] bry) {
|
||||
err_bfr.Add(bry);
|
||||
}
|
||||
public DecimalAdp Evaluate(Xop_ctx ctx, byte[] src) { // REF.MW: Expr.php
|
||||
int src_len = src.length; if (src_len == 0) return Null_rslt;
|
||||
int cur_pos = 0; byte cur_byt = src[0];
|
||||
boolean mode_expr = true; Func_tkn prv_prc = null;
|
||||
val_stack.Clear(); prc_stack.Clear();
|
||||
while (true) {
|
||||
// can't think of a way for this to happen; note that operators will automatically push values/operators off stack that are lower; can't get up to 100
|
||||
// if (val_stack.Len() > 100 || prc_stack.Len() > 100) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_err__stack_exhausted);
|
||||
Object o = trie.Match(cur_byt, src, cur_pos, src_len);
|
||||
int bgn_pos = cur_pos;
|
||||
if (o == null) { // letter or unknown symbol
|
||||
while (cur_pos < src_len) {
|
||||
byte b = src[cur_pos++];
|
||||
if (Byte_ascii.Is_ltr(b))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, cur_pos));
|
||||
}
|
||||
else {
|
||||
Expr_tkn t = (Expr_tkn)o;
|
||||
cur_pos = trie.Match_pos();
|
||||
switch (t.Tid()) {
|
||||
case Expr_tkn_.Tid_space: break;
|
||||
case Expr_tkn_.Tid_number:
|
||||
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
|
||||
int numBgn = cur_pos - 1;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (cur_pos == src_len) break;
|
||||
switch (src[cur_pos]) {
|
||||
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
|
||||
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
|
||||
case Byte_ascii.Dot:
|
||||
++cur_pos;
|
||||
break;
|
||||
default: loop = false; break;
|
||||
}
|
||||
}
|
||||
DecimalAdp num = Null_rslt;
|
||||
try {num = Bry_.XtoDecimalByPos(src, numBgn, cur_pos);}
|
||||
catch (Exception exc) {
|
||||
// NOTE: PATCH.PHP: 65.5.5 can evaluate to 65.5; EX "{{Geological eras|-600|height=2|border=none}}" eventually does "|10-to={{#ifexpr:{{{1|-4567}}}<-65.5|-65.5|{{{1}}}}}.5" which is 65.5.5
|
||||
Err_.Noop(exc);
|
||||
int dot_count = 0;
|
||||
for (int i = numBgn; i < cur_pos; i++) {
|
||||
if (src[i] == Byte_ascii.Dot) {
|
||||
switch (dot_count) {
|
||||
case 0: dot_count = 1; break;
|
||||
case 1:
|
||||
try {
|
||||
num = Bry_.XtoDecimalByPos(src, numBgn, i);
|
||||
}
|
||||
catch (Exception exc_inner) {Err_.Noop(exc_inner);}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num == null) return Null_rslt;
|
||||
}
|
||||
val_stack.Push(num);
|
||||
mode_expr = false;
|
||||
break;
|
||||
case Expr_tkn_.Tid_paren_lhs:
|
||||
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_operator, Bry_.new_ascii_("("));
|
||||
prc_stack.Push((Func_tkn)t);
|
||||
break;
|
||||
case Expr_tkn_.Tid_operator:
|
||||
Func_tkn cur_prc = (Func_tkn)t;
|
||||
if (Byte_ascii.Is_ltr(cur_byt)) {
|
||||
int nxt_pos = Bry_finder.Find_fwd_while_letter(src, cur_pos, src_len);
|
||||
if (nxt_pos > cur_pos)
|
||||
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, nxt_pos));
|
||||
}
|
||||
if (cur_prc.Func_is_const()) { // func is "pi" or "e"; DATE:2014-03-01
|
||||
if (mode_expr) { // number expected; just call Calc (which will place value on stack)
|
||||
cur_prc.Calc(ctx, this, val_stack);
|
||||
break;
|
||||
}
|
||||
else // operator expected; fail b/c pi / e is not an operator;
|
||||
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
|
||||
}
|
||||
if (mode_expr) { // NOTE: all the GetAlts have higher precedence; "break;" need to skip evaluation below else will fail for --1
|
||||
Func_tkn alt_prc = cur_prc.GetAlt();
|
||||
prc_stack.Push(alt_prc);
|
||||
break;
|
||||
}
|
||||
prv_prc = prc_stack.GetLast();
|
||||
while (prv_prc != null && (cur_prc.Precedence() <= prv_prc.Precedence())) {
|
||||
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
|
||||
prc_stack.Pop();
|
||||
prv_prc = prc_stack.GetLast();
|
||||
}
|
||||
prc_stack.Push(cur_prc);
|
||||
mode_expr = true;
|
||||
break;
|
||||
case Expr_tkn_.Tid_paren_rhs: {
|
||||
prv_prc = prc_stack.GetLast();
|
||||
while (prv_prc != null && prv_prc.Tid() != Expr_tkn_.Tid_paren_lhs) {
|
||||
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
|
||||
prc_stack.Pop();
|
||||
prv_prc = prc_stack.GetLast();
|
||||
}
|
||||
if (prv_prc == Paren_bgn_tkn._)
|
||||
prc_stack.Pop();
|
||||
else
|
||||
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_closing_bracket);
|
||||
mode_expr = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur_pos == src_len) break;
|
||||
cur_byt = src[cur_pos];
|
||||
}
|
||||
while (prc_stack.Len() > 0) {
|
||||
Func_tkn cur_prc = prc_stack.Pop();
|
||||
if (cur_prc.Tid() == Expr_tkn_.Tid_paren_lhs) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unclosed_bracket);
|
||||
if (!cur_prc.Calc(ctx, this, val_stack)) return Null_rslt;
|
||||
}
|
||||
return val_stack.Len() == 0 ? Null_rslt : val_stack.Pop(); // HACK: for [[List of Premiers of South Australia by time in office]] and {{#expr:\n{{age in days
|
||||
}
|
||||
private static ByteTrieMgr_fast expression_() {
|
||||
ByteTrieMgr_fast rv = ByteTrieMgr_fast.ci_ascii_(); // NOTE:ci.ascii:MW_const.en; math and expressions
|
||||
Trie_add(rv, new Ws_tkn(Byte_ascii.Space));
|
||||
Trie_add(rv, new Ws_tkn(Byte_ascii.Tab));
|
||||
Trie_add(rv, new Ws_tkn(Byte_ascii.NewLine));
|
||||
Trie_add(rv, Paren_bgn_tkn._);
|
||||
Trie_add(rv, Paren_end_tkn._);
|
||||
Trie_add(rv, new Func_tkn_plus("+"));
|
||||
Trie_add(rv, new Func_tkn_minus("-"));
|
||||
Trie_add(rv, new Func_tkn_minus(Char_.XtoStr((char)8722)));
|
||||
Trie_add(rv, new Func_tkn_times("*"));
|
||||
Trie_add(rv, new Func_tkn_divide("/"));
|
||||
Trie_add(rv, new Func_tkn_divide("div"));
|
||||
Trie_add(rv, new Func_tkn_pow("^"));
|
||||
Trie_add(rv, new Func_tkn_mod("mod"));
|
||||
Trie_add(rv, new Func_tkn_eq("="));
|
||||
Trie_add(rv, new Func_tkn_neq("<>"));
|
||||
Trie_add(rv, new Func_tkn_neq("!="));
|
||||
Trie_add(rv, new Func_tkn_gt(">"));
|
||||
Trie_add(rv, new Func_tkn_lt("<"));
|
||||
Trie_add(rv, new Func_tkn_gte(">="));
|
||||
Trie_add(rv, new Func_tkn_lte("<="));
|
||||
Trie_add(rv, new Func_tkn_and("and"));
|
||||
Trie_add(rv, new Func_tkn_or("or"));
|
||||
Trie_add(rv, new Func_tkn_not("not"));
|
||||
Trie_add(rv, new Func_tkn_e_op("e"));
|
||||
Trie_add(rv, new Func_tkn_pi("pi"));
|
||||
Trie_add(rv, new Func_tkn_ceil("ceil"));
|
||||
Trie_add(rv, new Func_tkn_trunc("trunc"));
|
||||
Trie_add(rv, new Func_tkn_floor("floor"));
|
||||
Trie_add(rv, new Func_tkn_abs("abs"));
|
||||
Trie_add(rv, new Func_tkn_exp("exp"));
|
||||
Trie_add(rv, new Func_tkn_ln("ln"));
|
||||
Trie_add(rv, new Func_tkn_sin("sin"));
|
||||
Trie_add(rv, new Func_tkn_cos("cos"));
|
||||
Trie_add(rv, new Func_tkn_tan("tan"));
|
||||
Trie_add(rv, new Func_tkn_asin("asin"));
|
||||
Trie_add(rv, new Func_tkn_acos("acos"));
|
||||
Trie_add(rv, new Func_tkn_atan("atan"));
|
||||
Trie_add(rv, new Func_tkn_round("round"));
|
||||
Trie_add(rv, new Func_tkn_fmod("fmod"));
|
||||
Trie_add(rv, new Func_tkn_sqrt("sqrt"));
|
||||
Trie_add(rv, new Num_tkn(0));
|
||||
Trie_add(rv, new Num_tkn(1));
|
||||
Trie_add(rv, new Num_tkn(2));
|
||||
Trie_add(rv, new Num_tkn(3));
|
||||
Trie_add(rv, new Num_tkn(4));
|
||||
Trie_add(rv, new Num_tkn(5));
|
||||
Trie_add(rv, new Num_tkn(6));
|
||||
Trie_add(rv, new Num_tkn(7));
|
||||
Trie_add(rv, new Num_tkn(8));
|
||||
Trie_add(rv, new Num_tkn(9));
|
||||
Trie_add(rv, new Dot_tkn());
|
||||
Trie_add(rv, new Func_tkn_gt(">"));
|
||||
Trie_add(rv, new Func_tkn_lt("<"));
|
||||
Trie_add(rv, new Func_tkn_minus("−"));
|
||||
return rv;
|
||||
}
|
||||
private static void Trie_add(ByteTrieMgr_fast trie, Expr_tkn tkn) {trie.Add(tkn.Val_ary(), tkn);}
|
||||
public static final Pfunc_expr_shunter _ = new Pfunc_expr_shunter(); Pfunc_expr_shunter() {}
|
||||
}
|
||||
112
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_tst.java
Normal file
112
400_xowa/src/gplx/xowa/xtns/pfuncs/exprs/Pfunc_expr_tst.java
Normal 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.pfuncs.exprs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_expr_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Null() {fxt.Test_parse_tmpl_str_test("{{#expr:}}" , "{{test}}" , "");}
|
||||
@Test public void Num_len1() {fxt.Test_parse_tmpl_str_test("{{#expr:1}}" , "{{test}}" , "1");}
|
||||
@Test public void Num_len3() {fxt.Test_parse_tmpl_str_test("{{#expr:123}}" , "{{test}}" , "123");}
|
||||
@Test public void Num_decimal() {fxt.Test_parse_tmpl_str_test("{{#expr:1.2}}" , "{{test}}" , "1.2");}
|
||||
@Test public void Num_decimal_lead() {fxt.Test_parse_tmpl_str_test("{{#expr:.12}}" , "{{test}}" , "0.12");}
|
||||
@Test public void Num_decimal_lax() {fxt.Test_parse_tmpl_str_test("{{#expr:1.2.3}}" , "{{test}}" , "1.2");} // PURPOSE: PHP allows 1.2.3 to be 1.2
|
||||
@Test public void Num_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:-1}}" , "{{test}}" , "-1");}
|
||||
@Test public void Num_neg_double() {fxt.Test_parse_tmpl_str_test("{{#expr:--1}}" , "{{test}}" , "1");}
|
||||
@Test public void Ws() {fxt.Test_parse_tmpl_str_test("{{#expr: 123\t\n }}" , "{{test}}" , "123");}
|
||||
@Test public void Plus_op() {fxt.Test_parse_tmpl_str_test("{{#expr:1 + 2}}" , "{{test}}" , "3");}
|
||||
@Test public void Minus_op() {fxt.Test_parse_tmpl_str_test("{{#expr:3 - 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Mult() {fxt.Test_parse_tmpl_str_test("{{#expr:3 * 2}}" , "{{test}}" , "6");}
|
||||
@Test public void Div_sym() {fxt.Test_parse_tmpl_str_test("{{#expr:6 / 3}}" , "{{test}}" , "2");}
|
||||
@Test public void Div_word() {fxt.Test_parse_tmpl_str_test("{{#expr:6 div 3}}" , "{{test}}" , "2");}
|
||||
@Test public void Plus_sign() {fxt.Test_parse_tmpl_str_test("{{#expr:1 + + 2}}" , "{{test}}" , "3");}
|
||||
@Test public void Minus_sign() {fxt.Test_parse_tmpl_str_test("{{#expr:3 + - 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Paren_1() {fxt.Test_parse_tmpl_str_test("{{#expr:(1 + 2) * 3}}" , "{{test}}" , "9");}
|
||||
@Test public void Paren_2() {fxt.Test_parse_tmpl_str_test("{{#expr:((1 + 2) * 3) * 4}}" , "{{test}}" , "36");}
|
||||
@Test public void Pow() {fxt.Test_parse_tmpl_str_test("{{#expr:2 ^ 4}}" , "{{test}}" , "16");}
|
||||
@Test public void Eq_y() {fxt.Test_parse_tmpl_str_test("{{#expr:2 = 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Eq_n() {fxt.Test_parse_tmpl_str_test("{{#expr:2 = 3}}" , "{{test}}" , "0");}
|
||||
@Test public void Neq_1() {fxt.Test_parse_tmpl_str_test("{{#expr:2 != 3}}" , "{{test}}" , "1");}
|
||||
@Test public void Neq_2() {fxt.Test_parse_tmpl_str_test("{{#expr:2 <> 3}}" , "{{test}}" , "1");}
|
||||
@Test public void Gt() {fxt.Test_parse_tmpl_str_test("{{#expr:3 > 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Lt() {fxt.Test_parse_tmpl_str_test("{{#expr:2 < 3}}" , "{{test}}" , "1");}
|
||||
@Test public void Gte() {fxt.Test_parse_tmpl_str_test("{{#expr:2 >= 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Lte() {fxt.Test_parse_tmpl_str_test("{{#expr:2 <= 2}}" , "{{test}}" , "1");}
|
||||
@Test public void Mod() {fxt.Test_parse_tmpl_str_test("{{#expr:3 mod 2}}" , "{{test}}" , "1");}
|
||||
@Test public void And_1() {fxt.Test_parse_tmpl_str_test("{{#expr:1 and -1}}" , "{{test}}" , "1");}
|
||||
@Test public void And_0() {fxt.Test_parse_tmpl_str_test("{{#expr:1 and 0}}" , "{{test}}" , "0");}
|
||||
@Test public void Or_0() {fxt.Test_parse_tmpl_str_test("{{#expr:1 or 0}}" , "{{test}}" , "1");}
|
||||
@Test public void Not_y() {fxt.Test_parse_tmpl_str_test("{{#expr:not 0}}" , "{{test}}" , "1");}
|
||||
@Test public void Not_n() {fxt.Test_parse_tmpl_str_test("{{#expr:not 1}}" , "{{test}}" , "0");}
|
||||
@Test public void Minus_op_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:2 - 3}}" , "{{test}}" , "-1");}
|
||||
@Test public void E_num() {fxt.Test_parse_tmpl_str_test("{{#expr:e}}" , "{{test}}" , "2.71828182845904");}
|
||||
@Test public void Pi_num() {fxt.Test_parse_tmpl_str_test("{{#expr:pi}}" , "{{test}}" , "3.14159265358979");}
|
||||
@Test public void Pi_mult() {fxt.Test_parse_tmpl_str_test("{{#expr:pi*1}}" , "{{test}}" , "3.14159265358979");}
|
||||
@Test public void E_op_pos() {fxt.Test_parse_tmpl_str_test("{{#expr:1.2 e 2}}" , "{{test}}" , "120");}
|
||||
@Test public void E_op_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:1.2 e -2}}" , "{{test}}" , "0.012");}
|
||||
@Test public void Ceil_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:ceil(-1.2)}}" , "{{test}}" , "-1");}
|
||||
@Test public void Trunc_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:trunc(-1.2)}}" , "{{test}}" , "-1");}
|
||||
@Test public void Floor_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:floor(-1.2)}}" , "{{test}}" , "-2");}
|
||||
@Test public void Ceil_pos() {fxt.Test_parse_tmpl_str_test("{{#expr:ceil(1.2)}}" , "{{test}}" , "2");}
|
||||
@Test public void Trunc_pos() {fxt.Test_parse_tmpl_str_test("{{#expr:trunc(1.2)}}" , "{{test}}" , "1");}
|
||||
@Test public void Floor_pos() {fxt.Test_parse_tmpl_str_test("{{#expr:floor(1.2)}}" , "{{test}}" , "1");}
|
||||
@Test public void Abs_pos() {fxt.Test_parse_tmpl_str_test("{{#expr:abs(1)}}" , "{{test}}" , "1");}
|
||||
@Test public void Abs_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:abs(-1)}}" , "{{test}}" , "1");}
|
||||
@Test public void Exp() {fxt.Test_parse_tmpl_str_test("{{#expr:exp(10)}}" , "{{test}}" , "22026.46579480671789");} // NOTE: MW returns 4807, not 480671789;
|
||||
@Test public void Ln() {fxt.Test_parse_tmpl_str_test("{{#expr:ln(22026.4657948067)}}" , "{{test}}" , "10");}
|
||||
@Test public void Sin() {fxt.Test_parse_tmpl_str_test("{{#expr:sin(1.5707963267949)}}" , "{{test}}" , "1");}
|
||||
@Test public void Cos() {fxt.Test_parse_tmpl_str_test("{{#expr:cos(0)}}" , "{{test}}" , "1");}
|
||||
@Test public void Tan() {fxt.Test_parse_tmpl_str_test("{{#expr:tan(45)}}" , "{{test}}" , "1.61977519054386");}
|
||||
@Test public void Asin() {fxt.Test_parse_tmpl_str_test("{{#expr:asin(0)}}" , "{{test}}" , "0");}
|
||||
@Test public void Acos() {fxt.Test_parse_tmpl_str_test("{{#expr:acos(0)}}" , "{{test}}" , "1.57079632679489");} // NOTE: MW (and C#) returns 49, not 489
|
||||
@Test public void Atan() {fxt.Test_parse_tmpl_str_test("{{#expr:atan(0)}}" , "{{test}}" , "0");}
|
||||
@Test public void Round() {fxt.Test_parse_tmpl_str_test("{{#expr:1.5 round 0}}" , "{{test}}" , "2");}
|
||||
@Test public void Round_0() {fxt.Test_parse_tmpl_str_test("{{#expr:0 round 1}}" , "{{test}}" , "0");} // PURPOSE: 0 round 1 should be 0, not 0.0; DATE:2013-11-09
|
||||
@Test public void Round_ex_1() {fxt.Test_parse_tmpl_str_test("{{#expr:(0.03937007874015)round(3)}}" , "{{test}}" , "0.039");} // PURPOSE: rounding results in excessive decimal places; EX.WP:Milky Way (light year conversions)
|
||||
@Test public void Mod_frac() {fxt.Test_parse_tmpl_str_test("{{#expr:0.00999999mod10}}" , "{{test}}" , "0");}
|
||||
@Test public void Mod_large() {fxt.Test_parse_tmpl_str_test("{{#expr:39052000900mod100}}" , "{{test}}" , "0");} // PURPOSE: JAVA was failing in converting to int and converted to Int_.MaxValue instead; DATE:2013-01-26
|
||||
@Test public void Fmod() {fxt.Test_parse_tmpl_str_test("{{#expr:1.25 fmod .5}}" , "{{test}}" , "0.25");}
|
||||
@Test public void Sqrt() {fxt.Test_parse_tmpl_str_test("{{#expr:sqrt 4}}" , "{{test}}" , "2");}
|
||||
@Test public void Sqrt_frac() {fxt.Test_parse_tmpl_str_test("{{#expr:sqrt 2}}" , "{{test}}" , "1.41421356237309");} // NOTE: MW (and C#) returns 31, not 309
|
||||
@Test public void Esc_xml_entRef() {fxt.Test_parse_tmpl_str_test("{{#expr:−1 < 5}}" , "{{test}}" , "1");}
|
||||
@Test public void Ex_1() {fxt.Test_parse_tmpl_str_test("{{#expr:1e2round0}}" , "{{test}}" , "100");} // PURPOSE: used in Convert
|
||||
@Test public void Floating() {fxt.Test_parse_tmpl_str_test("{{#expr:27.321582}}" , "{{test}}" , "27.321582");}
|
||||
@Test public void Floating_2() {fxt.Test_parse_tmpl_str_test("{{#expr:0.1*41}}" , "{{test}}" , "4.1");} // PURPOSE: division results in expanded floating-point; EX.WP:Wikipedia
|
||||
@Test public void Floating_3() {fxt.Test_parse_tmpl_str_test("{{#expr:111/10^(-1)}}" , "{{test}}" , "1110");} // PURPOSE: division by pow; EX.WP:Wikipedia:Featured articles
|
||||
@Test public void Floating_4() {fxt.Test_parse_tmpl_str_test("{{#expr:abs(-73.9023)}}" , "{{test}}" , "73.9023");} // PURPOSE: Abs;
|
||||
@Test public void Unicode_8722() {fxt.Test_parse_tmpl_str_test("{{#expr:2−1}}" , "{{test}}" , "1");} // PURPOSE: handle alternate minus; EX.WP: Australian krill
|
||||
@Test public void Exp_large_neg() {fxt.Test_parse_tmpl_str_test("{{#expr:418400000000000000000000E-23}}" , "{{test}}" , "4.184");} // PURPOSE: handle large neg; EX: w:Chicxulub_crater; {{convert|100|TtonTNT|J|lk=on}}
|
||||
@Test public void Exp_large_neg2() {fxt.Test_parse_tmpl_str_test("{{#expr:210000000000000000E-17}}" , "{{test}}" , "2.1");} // PURPOSE: handle large neg2; EX: w:Chicxulub_crater; {{convert|50|MtonTNT|J|lk=on}}
|
||||
@Test public void Fix_transclusion() {fxt.Test_parse_tmpl_str_test("{{#expr:{{#if:||1}}/.2}}" , "{{test}}" , "5");} // PURPOSE: /. was invoking transclusion; DATE:2013-04-26
|
||||
@Test public void Exc_unrecognised_word() {fxt.Test_parse_tmpl_str_test("{{#expr:abc}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"abc\"</strong>");}
|
||||
@Test public void Exc_division_by_zero() {fxt.Test_parse_tmpl_str_test("{{#expr:1/0}}" , "{{test}}" , "<strong class=\"error\">Division by zero</strong>");}
|
||||
@Test public void Exc_division_by_zero_mod() {fxt.Test_parse_tmpl_str_test("{{#expr:1 mod 0}}" , "{{test}}" , "<strong class=\"error\">Division by zero</strong>");}
|
||||
@Test public void Exc_unexpected_number() {fxt.Test_parse_tmpl_str_test("{{#expr:0 1}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unexpected number</strong>");}
|
||||
@Test public void Exc_unexpected_closing_bracket() {fxt.Test_parse_tmpl_str_test("{{#expr:5 + 1)}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unexpected closing bracket</strong>");}
|
||||
@Test public void Exc_unclosed_bracket() {fxt.Test_parse_tmpl_str_test("{{#expr:(5 + 1}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unclosed bracket</strong>");}
|
||||
@Test public void Exc_unexpected_operator_paren_end() {fxt.Test_parse_tmpl_str_test("{{#expr:5 ( 1}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unexpected ( operator</strong>");}
|
||||
@Test public void Exc_unexpected_number_pi() {fxt.Test_parse_tmpl_str_test("{{#expr:5 pi}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unexpected number</strong>");}
|
||||
@Test public void Exc_missing_operand() {fxt.Test_parse_tmpl_str_test("{{#expr:5 *}}" , "{{test}}" , "<strong class=\"error\">Expression error: Missing operand for *</strong>");}
|
||||
@Test public void Exc_invalid_argument_asin() {fxt.Test_parse_tmpl_str_test("{{#expr:asin(2)}}" , "{{test}}" , "<strong class=\"error\">Invalid argument for asin: < -1 or > 1</strong>");}
|
||||
@Test public void Exc_invalid_argument_acos() {fxt.Test_parse_tmpl_str_test("{{#expr:acos(2)}}" , "{{test}}" , "<strong class=\"error\">Invalid argument for acos: < -1 or > 1</strong>");}
|
||||
@Test public void Exc_invalid_argument_ln() {fxt.Test_parse_tmpl_str_test("{{#expr:ln(-1)}}" , "{{test}}" , "<strong class=\"error\">Invalid argument for ln: <= 0</strong>");}
|
||||
@Test public void Exc_pow_nan() {fxt.Test_parse_tmpl_str_test("{{#expr:(-2)^1.2}}" , "{{test}}" , "NaN");} // PURPOSE: handle nan; EX: w:Help:Calculation
|
||||
@Test public void Exc_unrecognized_word_ornot() {fxt.Test_parse_tmpl_str_test("{{#expr:0ornot0}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"ornot\"</strong>");} // PURPOSE: handle nan; EX: w:Help:Calculation
|
||||
@Test public void Exc_unrecognized_word_notnot() {fxt.Test_parse_tmpl_str_test("{{#expr:notnot0}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"notnot\"</strong>");} // PURPOSE: handle nan; EX: w:Help:Calculation
|
||||
@Test public void Exc_unrecognized_word_sinln() {fxt.Test_parse_tmpl_str_test("{{#expr:sinln1.1}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"sinln\"</strong>");} // PURPOSE: handle nan; EX: w:Help:Calculation
|
||||
}
|
||||
37
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_if.java
Normal file
37
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_if.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_if extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@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);
|
||||
boolean val_is_empty = true; int val_len = val.length;
|
||||
for (int i = 0; i < val_len; i++) {
|
||||
switch (val[i]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.NewLine: case Byte_ascii.Tab: break; // ws; continue
|
||||
default: val_is_empty = false; i = val_len; break; // non-ws; break loop
|
||||
}
|
||||
}
|
||||
if (val_is_empty)
|
||||
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 1));
|
||||
else
|
||||
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 0));
|
||||
}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_if;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_if().Name_(name);}
|
||||
}
|
||||
45
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_if_tst.java
Normal file
45
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_if_tst.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_if_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void If_y() {fxt.Test_parse_tmpl_str_test("{{#if:1|a|b}}" , "{{test}}" , "a");}
|
||||
@Test public void If_n() {fxt.Test_parse_tmpl_str_test("{{#if:|a|b}}" , "{{test}}" , "b");}
|
||||
@Test public void If_n_ws() {fxt.Test_parse_tmpl_str_test("{{#if: |a|b}}" , "{{test}}" , "b");}
|
||||
@Test public void If_y_ws() {fxt.Test_parse_tmpl_str_test("{{#if: |a|b \n}}" , "{{test}}" , "b");}
|
||||
@Test public void If_y_ws1() {fxt.Test_parse_tmpl_str_test("{{#if: |a|{{#if: |a|b}}\n}}" , "{{test}}" , "b");}
|
||||
@Test public void If_prm_n() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{{1}}}|b}}" , "{{test}}" , "b");}
|
||||
@Test public void If_prm_y() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{{1}}}|b}}" , "{{test|a}}" , "a");}
|
||||
@Test public void If_prm_n_dflt_ws() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1| }}}|a|b}}" , "{{test}}" , "b");}
|
||||
@Test public void If_prm_nest_0() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test}}" , "c");}
|
||||
@Test public void If_prm_nest_1() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test|1}}" , "b");}
|
||||
@Test public void If_prm_nest_2() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test|1|2}}" , "a");}
|
||||
@Test public void If_ignore_key() {fxt.Test_parse_tmpl_str_test("{{#if:|<i id=1|<i id=2}}" , "{{test}}" , "<i id=2");}
|
||||
@Test public void If_newline() { // PURPOSE: new_line in comments; WP:[[redirect-distinguish|a|b]]
|
||||
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
|
||||
( "{{#if:1<!--"
|
||||
, "-->|a<!--"
|
||||
, "-->|b<!--"
|
||||
, "-->}}"
|
||||
)
|
||||
, "{{test}}", "a");
|
||||
}
|
||||
@Test public void If_rel2abs() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1}}}|y}}" , "{{test|http://a.org/c/}}" , "y");} // PURPOSE.fix: trailing slash should not trigger rel2abs code; DATE:2013-04-06
|
||||
}
|
||||
32
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifeq.java
Normal file
32
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifeq.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_ifeq extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
int self_args_len = self.Args_len(); if (self_args_len < 2) return; // no equal/not_equal clauses defined; return; EX: {{#if:a}} {{#if:a|b}}
|
||||
byte[] lhs = Eval_argx(ctx, src, caller, self);
|
||||
byte[] rhs = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
|
||||
if (Pf_func_.Eq_(lhs, rhs))
|
||||
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
|
||||
else
|
||||
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 2));
|
||||
}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_ifeq;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifeq().Name_(name);}
|
||||
}
|
||||
48
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifeq_tst.java
Normal file
48
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifeq_tst.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_ifeq_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
|
||||
@Test public void Ifeq_y() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1|a|b}}" , "{{test}}" , "a");}
|
||||
@Test public void Ifeq_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|2|a|b}}" , "{{test}}" , "b");}
|
||||
@Test public void Ifeq_prm_arg() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{{1}}}|1|a|b}}" , "{{test|1}}" , "a");}
|
||||
@Test public void Ifeq_prm_arg_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{{1}}}|1|a|b}}" , "{{test|2}}" , "b");}
|
||||
@Test public void Ifeq_prm_blank_y() {fxt.Test_parse_tmpl_str_test("{{#ifeq:||a|b}}" , "{{test}}" , "a");}
|
||||
@Test public void Ifeq_prm_blank_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:|1|a|b}}" , "{{test}}" , "b");}
|
||||
@Test public void Ifeq_numeric() {fxt.Test_parse_tmpl_str_test("{{#ifeq:003|3.0|y|n}}" , "{{test}}" , "y");}
|
||||
@Test public void Ifeq_numeric_neg() {fxt.Test_parse_tmpl_str_test("{{#ifeq:-1.0|-1|y|n}}" , "{{test}}" , "y");}
|
||||
@Test public void Ifeq_prm_arg0() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|{{{1}}}|a|b}}" , "{{test|1}}" , "a");}
|
||||
@Test public void Ifeq_expr_err() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{#expr:a}}|0|y|n}}" , "{{test}}" , "n");}
|
||||
@Test public void Ifeq_blank() {fxt.Test_parse_tmpl_str_test("{{#ifeq:0||y|n}}" , "{{test}}" , "n");}
|
||||
|
||||
@Test public void Ifeq_exc_args_0() {fxt.Test_parse_tmpl_str_test("{{#ifeq:}}" , "{{test}}" , "");}
|
||||
@Test public void Ifeq_exc_args_1() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1}}" , "{{test}}" , "");}
|
||||
@Test public void Ifeq_exc_args_2() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1|a}}" , "{{test}}" , "a");}
|
||||
@Test public void Ifeq_exp() {fxt.Test_parse_tmpl_str_test("{{#ifeq:0.006|+6.0E-3|y|n}}" , "{{test}}" , "y");}
|
||||
@Test public void Ifeq_plus_minus() {fxt.Test_parse_tmpl_str_test("{{#ifeq:+|-|y}}" , "{{test}}" , "");} // PURPOSE: was evaluating to y; EX.WP:Permian-Triassic extinction
|
||||
@Test public void Tab_ent() { // PURPOSE: hack; tabs are materialized as "	" which causes trimming problems; EX.WP: Template:Cretaceous_graphical_timeline and "|period11= Campanian\s\t"
|
||||
fxt.Test_parse_page_all_str("{{#ifeq:a|a 	|y|n}}", "y"); // note that "|a\s\t" gets trimmed to "a"
|
||||
}
|
||||
@Test public void Ifeq_hex() {fxt.Test_parse_tmpl_str_test("{{#ifeq:44|0X002C|y|n}}" , "{{test}}" , "y");} // PURPOSE: hex compares to int; EX:w:Comma
|
||||
@Test public void Colon_2() { // PURPOSE: 2nd colon causes error b/c of bad whitespace evaluation; EX.WP:de.wiktionary.org/wiki/glitschig; DATE:2013-12-10
|
||||
fxt.Test_parse_tmpl_str_test("{{#ifeq: :|a|b|c}}" , "{{test}}" , "c");
|
||||
}
|
||||
}
|
||||
122
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_iferror.java
Normal file
122
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_iferror.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_iferror extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
|
||||
if (val_dat_ary == null) return;
|
||||
if (Error_exists(val_dat_ary))
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0));
|
||||
else {
|
||||
if (self_args_len < 2) // pass clause absent; add original
|
||||
bb.Add(val_dat_ary);
|
||||
else
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
|
||||
}
|
||||
}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_iferror;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_iferror().Name_(name);}
|
||||
boolean Error_exists(byte[] src) {
|
||||
// NOTE: approximation of MW code. basically checking for <tag class=error; REF.MW: ParserFunctions_body.php|iferror
|
||||
// /<(?:strong|span|p|div)\s(?:[^\s>]*\s+)*?class="(?:[^"\s>]*\s+)*?error(?:\s[^">]*)?"/
|
||||
int src_len = src.length;
|
||||
byte state = State_null;
|
||||
int pos = 0;
|
||||
boolean valid = false;
|
||||
while (true) {
|
||||
if (pos == src_len) break;
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match(b, src, pos, src_len);
|
||||
if (o == null)
|
||||
++pos;
|
||||
else {
|
||||
Byte_obj_val bv = (Byte_obj_val)o;
|
||||
int pos_nxt = trie.Match_pos();
|
||||
if (pos_nxt == src_len) return false; // each of the three states requires at least one character afterwards
|
||||
switch (bv.Val()) {
|
||||
case State_close: // >: reset state
|
||||
state = State_null;
|
||||
break;
|
||||
case State_nde: // <(?:strong|span|p|div)\s
|
||||
switch (src[pos_nxt]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine:
|
||||
state = State_nde;
|
||||
++pos_nxt;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case State_class:
|
||||
if (state == State_nde) {
|
||||
valid = true;
|
||||
switch (src[pos - 1]) {
|
||||
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine:
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (valid) {
|
||||
state = State_class;
|
||||
++pos_nxt;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State_error:
|
||||
if (state == State_class) {
|
||||
valid = true;
|
||||
switch (src[pos - 1]) {
|
||||
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine:
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
switch (src[pos_nxt]) {
|
||||
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine:
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (valid)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pos = pos_nxt;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static final ByteTrieMgr_slim trie = trie_();
|
||||
static final byte State_null = 0, State_nde = 1, State_class = 2, State_error = 3, State_close = 4;
|
||||
private static ByteTrieMgr_slim trie_() {
|
||||
ByteTrieMgr_slim rv = ByteTrieMgr_slim.ci_ascii_(); // NOTE:ci.ascii:MW_const.en
|
||||
trie_init(rv, State_nde , "<strong");
|
||||
trie_init(rv, State_nde , "<span");
|
||||
trie_init(rv, State_nde , "<p");
|
||||
trie_init(rv, State_nde , "<div");
|
||||
trie_init(rv, State_class, "class=");
|
||||
trie_init(rv, State_error, "error");
|
||||
trie_init(rv, State_close, ">");
|
||||
return rv;
|
||||
}
|
||||
private static void trie_init(ByteTrieMgr_slim trie, byte b, String s) {trie.Add(s, Byte_obj_val.new_(b));}
|
||||
}
|
||||
@@ -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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_iferror_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Basic_pass() {fxt.Test_parse_tmpl_str_test("{{#iferror: {{#expr: 1 + 2 }} | error | ok }}" , "{{test}}" , "ok");}
|
||||
@Test public void Basic_fail() {fxt.Test_parse_tmpl_str_test("{{#iferror: {{#expr: 1 + X }} | error | ok }}" , "{{test}}" , "error");}
|
||||
@Test public void Basic_omit() {fxt.Test_parse_tmpl_str_test("{{#iferror: ok | error}}" , "{{test}}" , "ok");}
|
||||
@Test public void NoMatch_0() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong>error</strong> | error | ok }}" , "{{test}}" , "ok");}
|
||||
@Test public void NoMatch_1() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong test=\"error\"></strong> | error | ok }}" , "{{test}}" , "ok");}
|
||||
@Test public void NoMatch_2() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong class=\"errora\"></strong> | error | ok }}" , "{{test}}" , "ok");}
|
||||
//@Test public void NoMatch_3() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong class=\"error a| error | ok }}" , "{{test}}" , "ok");} // FUTURE: match for ">
|
||||
}
|
||||
62
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexist.java
Normal file
62
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexist.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_ifexist extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
|
||||
if (Exists(tmp_db_page, ctx, val_dat_ary))
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0));
|
||||
else
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
|
||||
} private static final Xodb_page tmp_db_page = Xodb_page.tmp_();
|
||||
public static int Count = 0;
|
||||
public static boolean Exists(Xodb_page rv, Xop_ctx ctx, byte[] val_dat_ary) {
|
||||
rv.Clear();
|
||||
if (val_dat_ary.length == 0) return false;
|
||||
if (val_dat_ary[0] == Byte_ascii.Brack_bgn) return false; // HACK: values like [[Commune (socialism)|Commune]] in [[Template:Infobox Former Country]] for Paris Commune
|
||||
Xow_wiki wiki = ctx.Wiki();
|
||||
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, val_dat_ary);
|
||||
if (ttl == null) return false; // not a valid title; TODO: logme; see [[Dinosaur]]; Template:Taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{{taxonomy/{Placeholder <strong class=\"error\">error message</strong>.\n}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
|
||||
byte[] page_ttl = ttl.Page_db(); // NOTE: must use Page_db; EX: {{#ifexist:File:Peter & Paul fortress in SPB 03.jpg|y|n}}
|
||||
if (ttl.Ns().Id() < 0) {
|
||||
rv.Exists_(true);
|
||||
return true; // HACK: -2 Media namespace returned for Heart normal.svg in Superficial_temporal_artery
|
||||
}
|
||||
Object exists_val = ctx.Wiki().If_exists_regy().Fetch(val_dat_ary);
|
||||
if (exists_val != null) {
|
||||
boolean exists = ((Bool_obj_val)exists_val).Val();
|
||||
rv.Exists_(exists);
|
||||
return exists;
|
||||
}
|
||||
boolean found = wiki.Db_mgr().Load_mgr().Load_by_ttl(rv, ttl.Ns(), page_ttl);
|
||||
if ( !found
|
||||
&& wiki.Lang().Vnt_mgr().Enabled()) {
|
||||
Xodb_page page = wiki.Lang().Vnt_mgr().Convert_ttl(wiki, ttl.Ns(), page_ttl);
|
||||
if (page != Xodb_page.Null)
|
||||
found = page.Exists();
|
||||
}
|
||||
rv.Exists_(found);
|
||||
++Count;
|
||||
ctx.Wiki().If_exists_regy().Add(val_dat_ary, found ? Bool_obj_val.True : Bool_obj_val.False);
|
||||
return found;
|
||||
}
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_iferror;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifexist().Name_(name);}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_ifexist_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Basic_pass() {fxt.Test_parse_tmpl_str_test("{{#ifexist: Abc | exists | doesn't exist }}" , "{{test}}" , "doesn't exist");}
|
||||
@Test public void Empty() {fxt.Test_parse_tmpl_str_test("{{#ifexist:|y|n}}" , "{{test}}" , "n");} // NOTE: {{autolink}} can pass in ""
|
||||
@Test public void Db_key() { // PURPOSE: test that (1) & is encoded; (2) " " becomes "_"; EX: {{#ifexist:File:Peter & Paul fortress in SPB 03.jpg|y|n}}
|
||||
fxt.Init_page_create("A_&_b", "");
|
||||
fxt.Test_parse_tmpl_str_test("{{#ifexist:A & b|y|n}}", "{{test}}", "y");
|
||||
}
|
||||
}
|
||||
42
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexpr.java
Normal file
42
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexpr.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.xtns.pfuncs.exprs.*;
|
||||
public class Pfunc_ifexpr extends Pf_func_base {
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
|
||||
if (val_dat_ary == null) return;
|
||||
DecimalAdp result = shunter.Evaluate(ctx, val_dat_ary);
|
||||
boolean is_nan = result == Pfunc_expr_shunter.Null_rslt;
|
||||
if (is_nan && shunter.Err().Len() > 0) {
|
||||
bb.Add_bfr(shunter.Err());
|
||||
shunter.Err().Clear();
|
||||
}
|
||||
else {
|
||||
if (is_nan || result.XtoInt() == 0)
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
|
||||
else
|
||||
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0));
|
||||
}
|
||||
}
|
||||
Pfunc_expr_shunter shunter = Pfunc_expr_shunter._;
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_ifexpr;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifexpr().Name_(name);}
|
||||
}
|
||||
31
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexpr_tst.java
Normal file
31
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_ifexpr_tst.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_ifexpr_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Basic_y() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 > 0 |y|n}}" , "{{test}}" , "y");}
|
||||
@Test public void Basic_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 < 0 |y|n}}" , "{{test}}" , "n");}
|
||||
@Test public void Blank_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: |y|n}}" , "{{test}}" , "n");}
|
||||
@Test public void Args_0_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 > 0}}" , "{{test}}" , "");}
|
||||
@Test public void Args_0_y() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 0 > 1}}" , "{{test}}" , "");}
|
||||
@Test public void Err() {fxt.Test_parse_tmpl_str_test("{{#ifexpr:20abc >1|y|n}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"abc \"</strong>");} // HACK: shouldn't be "abc "
|
||||
}
|
||||
/*
|
||||
*/
|
||||
88
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_switch.java
Normal file
88
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_switch.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pfunc_switch extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_switch;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_switch().Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {// REF.MW:ParserFunctions_body.php
|
||||
int self_args_len = self.Args_len(); if (self_args_len == 0) return; // no cases; return; effectively "empty"
|
||||
byte[] argx = Eval_argx(ctx, src, caller, self);
|
||||
boolean fall_thru_found = false;
|
||||
byte[] match = null;
|
||||
Arg_itm_tkn dflt_val_tkn = null; byte[] dflt_val_bry = null;
|
||||
Arg_nde_tkn last_keyless_arg = null;
|
||||
Bry_bfr tmp = ctx.Wiki().Utl_bry_bfr_mkr().Get_b512();
|
||||
for (int i = 0; i < self_args_len; i++) {
|
||||
Arg_nde_tkn arg = self.Args_get_by_idx(i);
|
||||
if (arg.KeyTkn_exists()) { // = exists; EX: "|a=1|"
|
||||
last_keyless_arg = null; // set last_keyless_arg to null
|
||||
byte[] case_key = Get_or_eval(ctx, src, caller, self, bfr, arg.Key_tkn(), tmp);
|
||||
if ( fall_thru_found // fall-thru found earlier; take cur value; EX: {{#switch:a|a|b=1|c=2}} -> 1
|
||||
|| Pf_func_.Eq_(case_key, argx) // case_key matches argx; EX: {{#switch:a|a=1}}
|
||||
) {
|
||||
match = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
|
||||
break; // stop iterating; explicit match found;
|
||||
}
|
||||
else if (Bry_.HasAtBgn(case_key, Dflt_keyword)){// case_key is #default; EX: {{#switch:a|#default=1}}; note that "#defaultabc" is also allowed;
|
||||
dflt_val_tkn = arg.Val_tkn(); // set dflt_val_tkn; note that there is no "break" b/c multiple #defaults will use last one; EX: {{#switch:a|#default=1|#default=2}} -> 2
|
||||
dflt_val_bry = null; // set dflt_val_bry to null; EX:{{#switch:a|#defaultabc|#default=2}} -> 2
|
||||
}
|
||||
else {} // case_key != argx; continue
|
||||
}
|
||||
else { // = missing; EX: "|a|", "|#default|"
|
||||
last_keyless_arg = arg;
|
||||
byte[] case_val = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
|
||||
if (Pf_func_.Eq_(case_val, argx)) // argx matches case_val; EX: case_val="|a|" and argx="a"
|
||||
fall_thru_found = true; // set as fall-thru; note that fall-thrus will have "val" in next keyed arg, so need to continue iterating; EX: {{#switch:a|a|b=1|c=2}} "a" is fall-thru, but "b" is next keyed arg with a val
|
||||
else if (Bry_.HasAtBgn(case_val, Dflt_keyword)){// case_val starts with #default; EX: "|#default|" or "|#defaultabc|"
|
||||
last_keyless_arg = null; // unflag last keyless arg else |#defaultabc| will be treated as last_keyless_arg and generate "#defaultabc"; DATE:2014-05-29
|
||||
dflt_val_tkn = null; // unflag dflt_val_tkn; EX: {{#switch:a|b|#default=1|#default}} -> "" x> "1"
|
||||
int case_val_len = case_val.length;
|
||||
dflt_val_bry
|
||||
= case_val_len == Dflt_keyword_len // PERF: check if case_val = "|#default|"
|
||||
? null // PERF: set to null; don't create Bry_.Empty
|
||||
: Bry_.Mid(case_val, Dflt_keyword_len, case_val_len) // chop off "#default"; EX: {{#switch:a|b|#defaultabc}} -> "abc"
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match == null) { // no match; will either use last_keyless arg or #default
|
||||
if (last_keyless_arg != null) // always prefer last_keyless_arg; EX: {{#switch:a|#default=1|2}} -> 2
|
||||
match = Get_or_eval(ctx, src, caller, self, bfr, last_keyless_arg.Val_tkn(), tmp);
|
||||
else if (dflt_val_bry != null) // "|#defaultabc|" found; use it
|
||||
match = dflt_val_bry;
|
||||
else if (dflt_val_tkn != null) // "|#default=val|" found; use it
|
||||
match = Get_or_eval(ctx, src, caller, self, bfr, dflt_val_tkn, tmp);
|
||||
else {} // nothing found; noop; match will remain null
|
||||
}
|
||||
if (match != null)
|
||||
bfr.Add(match);
|
||||
tmp.Mkr_rls();
|
||||
}
|
||||
private byte[] Get_or_eval(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb, Arg_itm_tkn itm, Bry_bfr tmp) {
|
||||
if (itm.Itm_static() == Bool_.Y_byte)
|
||||
return Bry_.Trim(src, itm.Dat_bgn(), itm.Dat_end());
|
||||
else {
|
||||
itm.Tmpl_evaluate(ctx, src, caller, tmp);
|
||||
return tmp.XtoAryAndClearAndTrim();
|
||||
}
|
||||
}
|
||||
public static final byte[] Dflt_keyword = Bry_.new_utf8_("#default"); // NOTE: technically should pull from messages, but would need to cache Dflt_keyword on wiki level; checked all Messages files, and no one overrides it; DATE:2014-05-29
|
||||
private static int Dflt_keyword_len = Dflt_keyword.length;
|
||||
}
|
||||
81
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_switch_tst.java
Normal file
81
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Pfunc_switch_tst.java
Normal 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.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_switch_tst {
|
||||
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Basic_a() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a=1|b=2|3}}" , "{{test}}" , "1");}
|
||||
@Test public void Basic_b() {fxt.Test_parse_tmpl_str_test("{{#switch:b|a=1|b=2|3}}" , "{{test}}" , "2");}
|
||||
@Test public void Basic_dflt() {fxt.Test_parse_tmpl_str_test("{{#switch:z|a=1|b=2|3}}" , "{{test}}" , "3");}
|
||||
@Test public void FallThru_a() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
|
||||
@Test public void FallThru_b() {fxt.Test_parse_tmpl_str_test("{{#switch:b|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
|
||||
@Test public void FallThru_c() {fxt.Test_parse_tmpl_str_test("{{#switch:c|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
|
||||
@Test public void FallThru_d() {fxt.Test_parse_tmpl_str_test("{{#switch:d|a|b|c=1|d=2|3}}" , "{{test}}" , "2");}
|
||||
@Test public void FallThru_dflt() {fxt.Test_parse_tmpl_str_test("{{#switch:z|a|b|c=1|d=2|3}}" , "{{test}}" , "3");}
|
||||
@Test public void Dflt_named() {fxt.Test_parse_tmpl_str_test("{{#switch:z|b=2|#default=3|a=1}}" , "{{test}}" , "3");}
|
||||
@Test public void Dflt_last_idx_wins() // even if there is a named default, if last arg is un-keyd, then use it as default
|
||||
{fxt.Test_parse_tmpl_str_test("{{#switch:z|#default=3|9}}" , "{{test}}" , "9");}
|
||||
@Test public void Dflt_last_named_wins() // last named default wins
|
||||
{fxt.Test_parse_tmpl_str_test("{{#switch:z|#default=3|#default=4}}" , "{{test}}" , "4");}
|
||||
@Test public void Numeric() {fxt.Test_parse_tmpl_str_test("{{#switch:003|3.0=y|n}}" , "{{test}}" , "y");} //{{#switch:{{CURRENTMONTH}}|03=y|n}}
|
||||
@Test public void NoKeys() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a|b|c|d}}" , "{{test}}" , "d");}// d wins b/c it is default
|
||||
@Test public void Prm_val() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a=1|b=2|3}}" , "{{test|b}}" , "2");}
|
||||
@Test public void Prm_case1v() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a={{{1}}}|b=2|3}}" , "{{test|a}}" , "a");}
|
||||
@Test public void Prm_case1k() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|{{{1}}}=1|b=2|3}}" , "{{test|a}}" , "1");}
|
||||
@Test public void Null_x() {fxt.Test_parse_tmpl_str_test("{{#switch:|a=1|b=2|3}}" , "{{test|b}}" , "3");}
|
||||
@Test public void Exc_no_cases() {fxt.Test_parse_tmpl_str_test("{{#switch:a}}" , "{{test}}" , "");}
|
||||
@Test public void Exc_brace() {fxt.Test_parse_tmpl_str_test("{{#switch:a|{{{1}}}}=y|n}}" , "{{test|a}}" , "n");}// NOTE: deliberate 4th } brace
|
||||
@Test public void Ex_1() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|off=none|def=off|{{{1|off}}}}}", "{{test|b}}" , "b");}
|
||||
@Test public void Ex_2() {
|
||||
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
|
||||
( "{{#switch:{{{{{|safesubst:}}}NAMESPACE:Category:Foo}}"
|
||||
, "|{{ns:0}}"
|
||||
, "|{{ns:Category}}=yes"
|
||||
, "|no"
|
||||
, "}}"
|
||||
)
|
||||
, "{{test}}"
|
||||
, "yes");
|
||||
}
|
||||
@Test public void Ws() {
|
||||
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
|
||||
( "{{#switch: | {{ns:0}}"
|
||||
, "|{{ns:2}} = yes"
|
||||
, "|no"
|
||||
, "}}"
|
||||
)
|
||||
, "{{test}}"
|
||||
, "yes");
|
||||
}
|
||||
@Test public void Do_not_call_val_unless_needed() {
|
||||
fxt.Init_defn_clear();
|
||||
Xop_xowa_dbg.Argx_list.Clear();
|
||||
fxt.Init_defn_add("fail", "{{#xowa_dbg:Fail}}");
|
||||
fxt.Init_defn_add("pass", "{{#xowa_dbg:Pass}}");
|
||||
fxt.Init_defn_add("dflt", "{{#xowa_dbg:Dflt}}");
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a={{fail}}|#default={{dflt}}|b={{pass}}}}", "{{test|b}}", "Pass");
|
||||
Tfds.Eq(1, Xop_xowa_dbg.Argx_list.Count());
|
||||
}
|
||||
@Test public void Dflt_empty() { // PURPOSE: empty default should return "" not "#default"; PAGE:de.v:M<>nchen/Sehensw<73>rdigkeiten; DATE:2014-05-29
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:z|b=1|#default}}" , "{{test}}" , "");
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:z|b=1|#defaultabc}}" , "{{test}}" , "abc"); // chop off "#default"
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:a|#default|#default=1}}" , "{{test}}" , "1"); // override "|#default|" with "|#default=2|"
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:b|#default|1}}" , "{{test}}" , "1"); // override "|#default|" with "|2|"
|
||||
fxt.Test_parse_tmpl_str_test("{{#switch:b|#defaultabc=1}}" , "{{test}}" , "1"); // this is also supported by MW
|
||||
}
|
||||
}
|
||||
28
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Xop_xowa_dbg.java
Normal file
28
400_xowa/src/gplx/xowa/xtns/pfuncs/ifs/Xop_xowa_dbg.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Xop_xowa_dbg extends Pf_func_base {
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
byte[] argx = Eval_argx(ctx, src, caller, self);
|
||||
bfr.Add(argx);
|
||||
Argx_list.Add(argx);
|
||||
}
|
||||
public static final ListAdp Argx_list = ListAdp_.new_();
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xowa_dbg;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Xop_xowa_dbg().Name_(name);}
|
||||
}
|
||||
43
400_xowa/src/gplx/xowa/xtns/pfuncs/numbers/Pf_formatnum.java
Normal file
43
400_xowa/src/gplx/xowa/xtns/pfuncs/numbers/Pf_formatnum.java
Normal 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.pfuncs.numbers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.intl.*; import gplx.xowa.langs.numbers.*;
|
||||
public class Pf_formatnum extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_str_formatnum;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pf_formatnum().Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
Xol_lang lang = ctx.Wiki().Lang();
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] argx = Eval_argx(ctx, src, caller, self);
|
||||
byte[] arg1 = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
|
||||
bfr.Add(Format_num(lang, argx, arg1));
|
||||
}
|
||||
public static byte[] Format_num(Xol_lang lang, byte[] num, byte[] arg1) {
|
||||
ByteTrieMgr_slim trie_raw = lang.Kwd_mgr().Trie_raw();
|
||||
ByteTrieMgr_slim trie_nosep = lang.Kwd_mgr().Trie_nosep();
|
||||
int arg1_len = arg1.length;
|
||||
if (Bry_.Len_gt_0(arg1)) { // argument specified
|
||||
if (trie_raw .MatchAtCurExact(arg1, 0, arg1_len) != null)
|
||||
return lang.Num_mgr().Raw(num);
|
||||
else if (trie_nosep .MatchAtCurExact(arg1, 0, arg1_len) != null)
|
||||
return lang.Num_mgr().Format_num_no_separators(num);
|
||||
}
|
||||
return lang.Num_mgr().Format_num(num);
|
||||
}
|
||||
}
|
||||
@@ -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.pfuncs.numbers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
import gplx.intl.*; import gplx.xowa.langs.numbers.*;
|
||||
public class Pf_formatnum_de_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Reset();
|
||||
fxt.Init_lang_numbers_separators(".", ",");
|
||||
}
|
||||
@After public void term() {
|
||||
fxt.Init_lang_numbers_separators_en();
|
||||
}
|
||||
@Test public void Fmt__plain() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234,56}}" , "{{test}}" , "1.234.56");} // NOTE: double "." looks strange, but matches MW; DATE:2013-10-24
|
||||
@Test public void Fmt__grp_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1.234,56}}" , "{{test}}" , "1,234.56");}
|
||||
@Test public void Fmt__dec_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234.56}}" , "{{test}}" , "1.234,56");} // NOTE: "." should be treated as decimal separator, but replaced with ","; DATE:2013-10-21
|
||||
@Test public void Raw__grp_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1.234,56|R}}" , "{{test}}" , "1234.56");}
|
||||
@Test public void Raw__plain() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234,56|R}}" , "{{test}}" , "1234.56");}
|
||||
@Test public void Raw__dec_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:12,34|R}}" , "{{test}}" , "12.34");} // NOTE: dec_dlm is always ".
|
||||
@Test public void Nosep__plain() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234,56|NOSEP}}" , "{{test}}" , "1234,56");}
|
||||
@Test public void Nosep__grp_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1.234,56|NOSEP}}" , "{{test}}" , "1.234,56");}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.numbers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
import gplx.intl.*;
|
||||
public class Pf_formatnum_en_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Len_4() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234}}" , "{{test}}" , "1,234");}
|
||||
@Test public void Len_7() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234567}}" , "{{test}}" , "1,234,567");}
|
||||
@Test public void Len_2() {fxt.Test_parse_tmpl_str_test("{{formatnum:12}}" , "{{test}}" , "12");}
|
||||
@Test public void Len_10() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234567890}}" , "{{test}}" , "1,234,567,890");}
|
||||
@Test public void Neg() {fxt.Test_parse_tmpl_str_test("{{formatnum:-1234}}" , "{{test}}" , "-1,234");}
|
||||
@Test public void Decimal() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234.5678}}" , "{{test}}" , "1,234.5678");}
|
||||
@Test public void Mixed() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234abc5678}}" , "{{test}}" , "1,234abc5,678");}
|
||||
@Test public void Zeros() {fxt.Test_parse_tmpl_str_test("{{formatnum:0000000}}" , "{{test}}" , "0,000,000");}
|
||||
@Test public void Raw__grp_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1,234.56|R}}" , "{{test}}" , "1234.56");}
|
||||
@Test public void Raw__plain() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234.56|R}}" , "{{test}}" , "1234.56");}
|
||||
@Test public void Nosep__plain() {fxt.Test_parse_tmpl_str_test("{{formatnum:1234.56|NOSEP}}" , "{{test}}" , "1234.56");}
|
||||
@Test public void Nosep__grp_dlm() {fxt.Test_parse_tmpl_str_test("{{formatnum:1,234.56|NOSEP}}" , "{{test}}" , "1,234.56");}
|
||||
@Test public void Cs() {fxt.Test_parse_tmpl_str_test("{{FORMATNUM:1234}}" , "{{test}}" , "1,234");}
|
||||
@Test public void Exc_ws() { // PURPOSE: EX: {{rnd|122835.3|(-3)}}
|
||||
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
|
||||
( "{{formatnum:"
|
||||
, " {{#expr:2}}"
|
||||
, "}}"
|
||||
)
|
||||
, "{{test}}"
|
||||
, "2"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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.pfuncs.numbers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
import gplx.intl.*; import gplx.xowa.langs.numbers.*;
|
||||
public class Pf_formatnum_es_tst {
|
||||
private Xop_fxt fxt;
|
||||
@Before public void init() {
|
||||
Xoa_app app = Xoa_app_fxt.app_();
|
||||
Xol_lang lang = new Xol_lang(app, Bry_.new_ascii_("es")).Init_by_load_assert();
|
||||
Xow_wiki wiki = Xoa_app_fxt.wiki_(app, "es.wikipedia.org", lang);
|
||||
fxt = new Xop_fxt(app, wiki);
|
||||
}
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:1234.56}}" , "{{test}}", "1234.56"); // fmt.n;
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:1234}}" , "{{test}}", "1234"); // fmt.n; decimal
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:-1234.56}}" , "{{test}}", "-1234.56"); // fmt.n; neg
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:12345.90}}" , "{{test}}", "12,345.90"); // fmt.y; 5
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:123456.90}}" , "{{test}}", "123,456.90"); // fmt.y; 6
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:1234.}}" , "{{test}}", "1,234."); // stress; decimal at end
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:123456a}}" , "{{test}}", "123,456a"); // stress; letters
|
||||
}
|
||||
}
|
||||
@@ -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.pfuncs.numbers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
import gplx.intl.*; import gplx.xowa.langs.numbers.*;
|
||||
public class Pf_formatnum_fa_tst {
|
||||
private Xop_fxt fxt;
|
||||
@Before public void init() {
|
||||
Xoa_app app = Xoa_app_fxt.app_();
|
||||
Xol_lang lang = new Xol_lang(app, Bry_.new_ascii_("fa")).Init_by_load_assert();
|
||||
String gfs = String_.Concat_lines_nl
|
||||
( "numbers {"
|
||||
, " digits {"
|
||||
, " clear;"
|
||||
, " set('0', '۰');"
|
||||
, " set('1', '۱');"
|
||||
, " set('2', '۲');"
|
||||
, " set('3', '۳');"
|
||||
, " set('4', '۴');"
|
||||
, " set('5', '۵');"
|
||||
, " set('6', '۶');"
|
||||
, " set('7', '۷');"
|
||||
, " set('8', '۸');"
|
||||
, " set('9', '۹');"
|
||||
, " set('%', '٪');"
|
||||
, " set('.', '٫');"
|
||||
, " set(',', '٬');"
|
||||
, " }"
|
||||
, "}"
|
||||
);
|
||||
app.Gfs_mgr().Run_str_for(lang, gfs);
|
||||
Xow_wiki wiki = Xoa_app_fxt.wiki_(app, "fa.wikipedia.org", lang);
|
||||
fxt = new Xop_fxt(app, wiki);
|
||||
}
|
||||
@Test public void Basic() {
|
||||
fxt.Test_parse_tmpl_str_test("{{formatnum:۱۵۰|R}}" , "{{test}}", "150");
|
||||
}
|
||||
}
|
||||
22
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm.java
Normal file
22
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public interface Pft_fmt_itm {
|
||||
int TypeId();
|
||||
void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr);
|
||||
}
|
||||
166
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm_.java
Normal file
166
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm_.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pft_fmt_itm_ {
|
||||
public static final int
|
||||
Tid_seg_int = 1
|
||||
, Tid_hour_base12 = 2
|
||||
, Tid_dow_base0 = 3
|
||||
, Tid_seg_str = 4
|
||||
, Tid_year_isLeap = 5
|
||||
, Tid_timestamp_unix = 6
|
||||
, Tid_raw_ary = 7
|
||||
, Tid_raw_byt = 8
|
||||
, Tid_dayOfYear = 9
|
||||
, Tid_daysInMonth = 10
|
||||
, Tid_AmPm = 11
|
||||
, Tid_roman = 12
|
||||
, Tid_iso_fmt = 13
|
||||
, Tid_rfc_5322 = 14
|
||||
, Tid_raw = 15
|
||||
, Tid_timezone_offset = 16
|
||||
, Tid_thai = 17
|
||||
, Tid_minguo = 18
|
||||
;
|
||||
public static final Pft_fmt_itm
|
||||
Year_len4 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_year , 4, Bool_.Y)
|
||||
, Year_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_year , 2, Bool_.Y)
|
||||
, Month_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_month , 2, Bool_.Y)
|
||||
, Month_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_month , 2, Bool_.N)
|
||||
, Day_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_day , 2, Bool_.Y)
|
||||
, Day_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_day , 2, Bool_.N)
|
||||
, Hour_base24_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_hour , 2, Bool_.Y)
|
||||
, Hour_base24 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_hour , 2, Bool_.N)
|
||||
, Hour_base12_len2 = new Pft_fmt_itm_hour_base12(Bool_.Y)
|
||||
, Hour_base12 = new Pft_fmt_itm_hour_base12(Bool_.N)
|
||||
, Minute_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_minute , 2, Bool_.Y)
|
||||
, Second_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_second , 2, Bool_.Y)
|
||||
, Dow_base1_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_dayOfWeek , 1, Bool_.Y)
|
||||
, Dow_base0_int = new Pft_fmt_itm_dow_base0()
|
||||
, WeekOfYear_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_weekOfYear , 2, Bool_.N)
|
||||
, WeekOfYear_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_weekOfYear , 2, Bool_.Y)
|
||||
, Month_abrv = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_abrv_jan - Int_.Base1) // Jan
|
||||
, Month_name = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_name_january - Int_.Base1) // January
|
||||
, Month_gen = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_gen_january - Int_.Base1) // January
|
||||
, Dow_abrv = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_dayOfWeek, Xol_msg_itm_.Id_dte_dow_abrv_sun) // Sun
|
||||
, Dow_name = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_dayOfWeek, Xol_msg_itm_.Id_dte_dow_name_sunday) // Sunday
|
||||
, Year_isLeap = new Pft_fmt_itm_year_isLeap()
|
||||
, Timestamp_unix = new Pft_fmt_itm_timestamp_unix()
|
||||
, Byte_space = new Pft_fmt_itm_raw_byt(Byte_ascii.Space)
|
||||
, Byte_comma = new Pft_fmt_itm_raw_byt(Byte_ascii.Comma)
|
||||
, Byte_dash = new Pft_fmt_itm_raw_byt(Byte_ascii.Dash)
|
||||
, DayOfYear_int = new Pft_fmt_itm_dayOfYear()
|
||||
, DaysInMonth_int = new Pft_fmt_itm_daysInMonth()
|
||||
, AmPm_lower = new Pft_fmt_itm_AmPm(true)
|
||||
, AmPm_upper = new Pft_fmt_itm_AmPm(false)
|
||||
, Roman = new Pft_fmt_itm_roman()
|
||||
, Thai = new Pft_fmt_itm_thai()
|
||||
, Minguo = new Pft_fmt_itm_minguo()
|
||||
, Raw = new Pft_fmt_itm_raw()
|
||||
, Iso_fmt = new Pft_fmt_itm_iso_fmt()
|
||||
, Rfc_5322 = new Pft_fmt_itm_rfc_5322()
|
||||
, Timezone_offset = new Pft_fmt_itm_timezone_offset()
|
||||
;
|
||||
public static final ByteTrieMgr_fast Regy = ByteTrieMgr_fast.cs_()
|
||||
.Add(Byte_ascii.Ltr_Y , Pft_fmt_itm_.Year_len4) // 2012
|
||||
.Add(Byte_ascii.Ltr_y , Pft_fmt_itm_.Year_len2) // 12
|
||||
.Add(Byte_ascii.Ltr_L , Pft_fmt_itm_.Year_isLeap) // 1,0
|
||||
.Add(Byte_ascii.Ltr_o , Pft_fmt_itm_.Year_len4) // 2012: ISO-8601; don't know why it's different vs Ltr_Y
|
||||
.Add(Byte_ascii.Ltr_n , Pft_fmt_itm_.Month_int) // 1
|
||||
.Add(Byte_ascii.Ltr_m , Pft_fmt_itm_.Month_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_M , Pft_fmt_itm_.Month_abrv) // Jan
|
||||
.Add(Byte_ascii.Ltr_F , Pft_fmt_itm_.Month_name) // January
|
||||
.Add("xg" , Pft_fmt_itm_.Month_gen) // January
|
||||
.Add(Byte_ascii.Ltr_W , Pft_fmt_itm_.WeekOfYear_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_j , Pft_fmt_itm_.Day_int) // 1
|
||||
.Add(Byte_ascii.Ltr_d , Pft_fmt_itm_.Day_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_z , Pft_fmt_itm_.DayOfYear_int) // 0
|
||||
.Add(Byte_ascii.Ltr_D , Pft_fmt_itm_.Dow_abrv) // Sun
|
||||
.Add(Byte_ascii.Ltr_l , Pft_fmt_itm_.Dow_name) // Sunday
|
||||
.Add(Byte_ascii.Ltr_N , Pft_fmt_itm_.Dow_base0_int) // 1; Sunday=7
|
||||
.Add(Byte_ascii.Ltr_w , Pft_fmt_itm_.Dow_base1_int) // 1; Sunday=0
|
||||
.Add(Byte_ascii.Ltr_a , Pft_fmt_itm_.AmPm_lower) // am/pm
|
||||
.Add(Byte_ascii.Ltr_A , Pft_fmt_itm_.AmPm_upper) // AM/PM
|
||||
.Add(Byte_ascii.Ltr_g , Pft_fmt_itm_.Hour_base12) // 1; Base12
|
||||
.Add(Byte_ascii.Ltr_h , Pft_fmt_itm_.Hour_base12_len2) // 01; Base12; pad2
|
||||
.Add(Byte_ascii.Ltr_G , Pft_fmt_itm_.Hour_base24) // 13; Base24;
|
||||
.Add(Byte_ascii.Ltr_H , Pft_fmt_itm_.Hour_base24_len2) // 13; Base24; pad2
|
||||
.Add(Byte_ascii.Ltr_i , Pft_fmt_itm_.Minute_int_len2) // 04
|
||||
.Add(Byte_ascii.Ltr_s , Pft_fmt_itm_.Second_int_len2) // 05
|
||||
.Add(Byte_ascii.Ltr_t , Pft_fmt_itm_.DaysInMonth_int) // 31
|
||||
.Add(Byte_ascii.Ltr_U , Pft_fmt_itm_.Timestamp_unix) // 1343865600
|
||||
.Add(Byte_ascii.Ltr_Z , Pft_fmt_itm_.Timezone_offset) // timezone offset in seconds
|
||||
.Add(Byte_ascii.Ltr_c , Pft_fmt_itm_.Iso_fmt) // 2012-01-02T03:04:05+00:00
|
||||
.Add(Byte_ascii.Ltr_r , Pft_fmt_itm_.Rfc_5322) // Mon 02 Jan 2012 08:04:05 +0000
|
||||
.Add("xr" , Pft_fmt_itm_.Roman) // MCXI
|
||||
.Add("xkY" , Pft_fmt_itm_.Thai) // Year += 543
|
||||
.Add("xoY" , Pft_fmt_itm_.Minguo) // Year -= 1911
|
||||
.Add("xn" , Pft_fmt_itm_.Raw) // NOTE: really does nothing; REF.MW: Language.php|sprintfdate does $s .= $num; DATE:2013-12-31
|
||||
.Add("xN" , Pft_fmt_itm_.Raw)
|
||||
// TODO: foreign; space; "
|
||||
;
|
||||
public static Pft_fmt_itm[] Parse(Xop_ctx ctx, byte[] fmt) {
|
||||
ByteTrieMgr_fast trie = Pft_fmt_itm_.Regy;
|
||||
int i = 0, fmt_len = fmt.length;
|
||||
fmt_itms.Clear(); int raw_bgn = String_.Pos_neg1; byte raw_byt = Byte_.Zero;
|
||||
while (i < fmt_len) {
|
||||
byte b = fmt[i];
|
||||
Object o = trie.Match(b, fmt, i, fmt_len);
|
||||
if (o != null) {
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
fmt_itms.Add((Pft_fmt_itm)o);
|
||||
i = trie.Match_pos();
|
||||
}
|
||||
else {
|
||||
switch (b) {
|
||||
case Byte_ascii.Backslash:
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
++i; // peek next char
|
||||
if (i == fmt_len) // trailing backslash; add one; EX: "b\" -> "b\" not "b"
|
||||
fmt_itms.Add(new Pft_fmt_itm_raw_byt(Byte_ascii.Backslash));
|
||||
else
|
||||
fmt_itms.Add(new Pft_fmt_itm_raw_byt(fmt[i]));
|
||||
++i;
|
||||
break;
|
||||
case Byte_ascii.Quote:
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
++i; // skip quote_bgn
|
||||
raw_bgn = i;
|
||||
while (i < fmt_len) {
|
||||
b = fmt[i];
|
||||
if (b == Byte_ascii.Quote) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
fmt_itms.Add(i - raw_bgn == 0 ? new Pft_fmt_itm_raw_byt(Byte_ascii.Quote) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i));
|
||||
raw_bgn = String_.Pos_neg1;
|
||||
++i; // skip quote_end
|
||||
break;
|
||||
default:
|
||||
if (raw_bgn == String_.Pos_neg1) {raw_bgn = i; raw_byt = b;}
|
||||
i += gplx.intl.Utf8_.Len_of_char_by_1st_byte(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(fmt_len - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(fmt[fmt_len - 1]) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, fmt_len)); raw_bgn = String_.Pos_neg1;}
|
||||
return (Pft_fmt_itm[])fmt_itms.XtoAry(Pft_fmt_itm.class);
|
||||
} private static ListAdp fmt_itms = ListAdp_.new_();
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pft_fmt_itm_seg_int implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_seg_int(int segIdx, int len, boolean fixed_len) {this.segIdx = segIdx; this.fixed_len = fixed_len; this.len = len;} private int segIdx, len; boolean fixed_len;
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_seg_int;}
|
||||
public int SegIdx() {return segIdx;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int val = date.Segment(segIdx);
|
||||
if (fixed_len) bfr.Add_int_fixed(val, len);
|
||||
else bfr.Add_int_variable(val);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_raw implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
// TODO: should flag .Raw() on bldr to skip transliterating numerals in foreign languages; DATE:2013-12-31
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_seg_str implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_seg_str(int segIdx, int type) {this.segIdx = segIdx; this.type = type;} private int segIdx, type;
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_seg_str;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
DateAdpTranslator_xapp.Translate(wiki, lang, type, date.Segment(segIdx), bfr);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_year_isLeap implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_year_isLeap;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_fixed(DateAdp_.IsLeapYear(date.Year()) ? 1 : 0, 1);}
|
||||
}
|
||||
class Pft_fmt_itm_hour_base12 implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hour_base12;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int val = date.Hour();
|
||||
switch (val) {
|
||||
case 0: val = 12; break;
|
||||
case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: val -= 12; break;
|
||||
default: break;
|
||||
}
|
||||
if (fixed_len) bfr.Add_int_fixed(val, 2);
|
||||
else bfr.Add_int_variable(val);
|
||||
}
|
||||
public Pft_fmt_itm_hour_base12(boolean fixed_len) {this.fixed_len = fixed_len;} private boolean fixed_len;
|
||||
}
|
||||
class Pft_fmt_itm_timestamp_unix implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_timestamp_unix;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_long_variable(date.Timestamp_unix());}
|
||||
}
|
||||
class Pft_fmt_itm_raw_ary implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw_ary;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_mid(src, bgn, end);}
|
||||
public Pft_fmt_itm_raw_ary(byte[] src, int bgn, int end) {this.src = src; this.bgn = bgn; this.end = end;} private byte[] src; int bgn; int end;
|
||||
}
|
||||
class Pft_fmt_itm_raw_byt implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw_byt;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_byte(b);}
|
||||
public Pft_fmt_itm_raw_byt(byte b) {this.b = b;} private byte b;
|
||||
}
|
||||
class Pft_fmt_itm_daysInMonth implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_daysInMonth;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_variable(DateAdp_.DaysInMonth(date));}
|
||||
}
|
||||
class Pft_fmt_itm_dayOfYear implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_dayOfYear;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_variable(date.DayOfYear() - Int_.Base1);} // php is base1; .net/java is base0
|
||||
}
|
||||
class Pft_fmt_itm_AmPm implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_AmPm;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
boolean am = date.Hour() < 13;
|
||||
byte[] val = null;
|
||||
if ( am && lower) val = Ary_am_lower;
|
||||
else if ( am && !lower) val = Ary_am_upper;
|
||||
else if (!am && lower) val = Ary_pm_lower;
|
||||
else if (!am && !lower) val = Ary_pm_upper;
|
||||
bfr.Add(val);
|
||||
} static final byte[] Ary_am_upper = Bry_.new_ascii_("AM"), Ary_pm_upper = Bry_.new_ascii_("PM"), Ary_am_lower = Bry_.new_ascii_("am"), Ary_pm_lower = Bry_.new_ascii_("pm");
|
||||
public Pft_fmt_itm_AmPm(boolean lower) {this.lower = lower;} private boolean lower;
|
||||
}
|
||||
class Pft_fmt_itm_dow_base0 implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_dow_base0;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int dow = date.DayOfWeek();
|
||||
if (dow == 0) dow = 7;
|
||||
bfr.Add_int_fixed(dow, 1);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_roman implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_roman;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int nxt_idx = bldr.Idx_cur() + 1;
|
||||
Pft_fmt_itm[] ary = bldr.Fmt_itms();
|
||||
if (nxt_idx < ary.length) {
|
||||
Pft_fmt_itm itm = (Pft_fmt_itm)ary[nxt_idx];
|
||||
if (itm.TypeId() == Pft_fmt_itm_.Tid_seg_int) {
|
||||
Pft_fmt_itm_seg_int nxt_int = (Pft_fmt_itm_seg_int)ary[nxt_idx]; // FUTURE: should check tkn type
|
||||
int v = date.Segment(nxt_int.SegIdx());
|
||||
Pfxtp_roman.ToRoman(v, bfr);
|
||||
bldr.Idx_nxt_(nxt_idx + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
bfr.Add_str("xf");
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_thai implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_thai;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Year() + 543);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_minguo implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_minguo;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Year() - 1911);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_iso_fmt implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_iso_fmt() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_iso_fmt;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_str(date.XtoStr_fmt("yyyy-MM-dd"));
|
||||
bfr.Add_byte(Byte_ascii.Ltr_T);
|
||||
bfr.Add_str(date.XtoStr_fmt("HH:mm:ss"));
|
||||
bfr.Add_str(date.XtoStr_tz());
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_rfc_5322 implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_rfc_5322() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_rfc_5322;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {// Mon, 02 Jan 2012 10:15:01 +0000
|
||||
int dow = date.DayOfWeek();
|
||||
DateAdpTranslator_xapp.Translate(wiki, lang, DateAdp_.SegIdx_dayOfWeek, dow, bfr);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
bfr.Add_str(date.XtoStr_fmt("dd MMM yyyy HH:mm:ss")); // NOTE: always UTC time
|
||||
bfr.Add(CONST_timezone); // NOTE: always UTC time zone
|
||||
} static final byte[] CONST_timezone = Bry_.new_ascii_(" +0000");
|
||||
}
|
||||
class Pft_fmt_itm_timezone_offset implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_timezone_offset() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_timezone_offset;}
|
||||
public void Fmt(Bry_bfr bfr, Xow_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Timezone_offset());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user