mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
Skin: Change to mustache-backed Skin.Vector (temporary commit) [#797]
This commit is contained in:
parent
5c3d6a173b
commit
2f4693ac47
@ -1,40 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.jsons; import gplx.*; import gplx.langs.*;
|
||||
public class Json_doc_bldr {
|
||||
public Json_nde Nde(Json_doc jdoc) {return factory.Nde(jdoc, -1);}
|
||||
public Json_nde Nde(Json_doc jdoc, Json_grp owner) {
|
||||
Json_nde rv = factory.Nde(jdoc, -1);
|
||||
owner.Add(rv);
|
||||
return rv;
|
||||
}
|
||||
public Json_itm Str(byte[] v) {return Str(String_.new_u8(v));}
|
||||
public Json_itm Str(String v) {return Json_itm_tmp.new_str_(v);}
|
||||
public Json_itm Int(int v) {return Json_itm_tmp.new_int_(v);}
|
||||
public Json_kv Kv_int(Json_grp owner, String key, int val) {Json_kv rv = factory.Kv(Json_itm_tmp.new_str_(key), Json_itm_tmp.new_int_(val)); owner.Add(rv); return rv;}
|
||||
public Json_kv Kv_str(Json_grp owner, String key, String val) {Json_kv rv = factory.Kv(Json_itm_tmp.new_str_(key), Json_itm_tmp.new_str_(val)); owner.Add(rv); return rv;}
|
||||
public Json_ary Kv_ary(Json_grp owner, String key, Json_itm... subs) {
|
||||
Json_itm key_itm = Json_itm_tmp.new_str_(key);
|
||||
Json_ary val_ary = factory.Ary(-1, -1);
|
||||
Json_kv kv = factory.Kv(key_itm, val_ary);
|
||||
owner.Add(kv);
|
||||
int len = subs.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
val_ary.Add(subs[i]);
|
||||
return val_ary;
|
||||
}
|
||||
Json_doc doc = new Json_doc(); Json_factory factory = new Json_factory();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,9 +13,20 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.jsons; import gplx.*; import gplx.langs.*;
|
||||
import gplx.objects.strings.unicodes.*;
|
||||
import gplx.core.encoders.*;
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Double_;
|
||||
import gplx.Object_;
|
||||
import gplx.String_;
|
||||
import gplx.core.encoders.Hex_utl_;
|
||||
import gplx.objects.strings.unicodes.Ustring;
|
||||
import gplx.objects.strings.unicodes.Ustring_;
|
||||
|
||||
public class Json_doc_wtr {
|
||||
private int indent = -2;
|
||||
private Bry_bfr bfr = Bry_bfr_.Reset(255);
|
||||
@ -96,6 +107,7 @@ public class Json_doc_wtr {
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv(boolean comma, String key, byte[] val) {return Kv(comma, Bry_.new_u8(key), val);}
|
||||
public Json_doc_wtr Kv(boolean comma, byte[] key, byte[] val) {
|
||||
Key_internal(comma, key);
|
||||
Str(val);
|
||||
@ -108,12 +120,15 @@ public class Json_doc_wtr {
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv(boolean comma, String key, int v) {return Kv(comma, Bry_.new_u8(key), v);}
|
||||
public Json_doc_wtr Kv(boolean comma, byte[] key, int v) {
|
||||
Key_internal(comma, key);
|
||||
Int(v);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv(boolean comma, String key, double v) {return Kv(comma, Bry_.new_u8(key), Bry_.new_u8(Double_.To_str(v)));}
|
||||
public Json_doc_wtr Kv(boolean comma, String key, boolean v) {return Kv(comma, Bry_.new_u8(key), v ? Bool_.Y_bry : Bool_.N_bry);}
|
||||
public Json_doc_wtr Key(boolean comma, String key) {return Key(comma, Bry_.new_u8(key));}
|
||||
public Json_doc_wtr Key(boolean comma, byte[] key) {
|
||||
Key_internal(comma, key);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,11 +13,27 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.jsons; import gplx.*; import gplx.langs.*;
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
|
||||
public class Json_itm_int extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private byte[] data_bry; private int data; private boolean data_is_null = true;
|
||||
public Json_itm_int(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;}
|
||||
private byte[] data_bry;
|
||||
private int data;
|
||||
private boolean data_is_null = true;
|
||||
|
||||
public Json_itm_int(Json_doc doc, int src_bgn, int src_end) {
|
||||
this.Ctor(src_bgn, src_end);
|
||||
this.doc = doc;
|
||||
}
|
||||
public Json_itm_int(int val) {
|
||||
this.Ctor(-1, -1);
|
||||
this.doc = null;
|
||||
this.data = val;
|
||||
this.data_is_null = false;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__int;}
|
||||
public int Data_as_int() {
|
||||
if (data_is_null) {
|
||||
@ -27,7 +43,16 @@ public class Json_itm_int extends Json_itm_base {
|
||||
return data;
|
||||
}
|
||||
@Override public Object Data() {return Data_as_int();}
|
||||
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); return data_bry;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null)
|
||||
data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end());
|
||||
return data_bry;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (doc != null && this.Src_bgn() >= 0)
|
||||
bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());
|
||||
else
|
||||
bfr.Add_int_variable(data);
|
||||
}
|
||||
public static Json_itm_int cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__int ? null : (Json_itm_int)v;}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,19 +13,53 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.jsons; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.intls.*;
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.String_;
|
||||
import gplx.core.intls.Utf16_;
|
||||
|
||||
public class Json_itm_str extends Json_itm_base {
|
||||
private final boolean exact; private final Json_doc doc;
|
||||
private String data_str; private byte[] data_bry = null;
|
||||
public Json_itm_str(Json_doc doc, int src_bgn, int src_end, boolean exact) {this.Ctor(src_bgn + 1, src_end - 1); this.doc = doc; this.exact = exact;}
|
||||
private final boolean exact;
|
||||
private final Json_doc doc;
|
||||
private String data_str;
|
||||
private byte[] data_bry = null;
|
||||
private byte[] src = null;
|
||||
|
||||
public Json_itm_str(Json_doc doc, int src_bgn, int src_end, boolean exact) {
|
||||
this.Ctor(src_bgn + 1, src_end - 1);
|
||||
this.doc = doc;
|
||||
this.exact = exact;
|
||||
}
|
||||
public Json_itm_str(byte[] src, boolean exact) {
|
||||
this.doc = null;
|
||||
this.src = src;
|
||||
this.exact = exact;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__str;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
gplx.langs.htmls.Gfh_utl.Escape_html_to_bfr(bfr, doc.Src(), this.Src_bgn(), this.Src_end(), true, true, true, true, false); // false to apos for backwards compatibility
|
||||
byte[] src_doc;
|
||||
int bgn;
|
||||
int end;
|
||||
if (src == null) {
|
||||
src_doc = doc.Src();
|
||||
bgn = this.Src_bgn();
|
||||
end = this.Src_end();
|
||||
}
|
||||
else {
|
||||
src_doc = src;
|
||||
bgn = 0;
|
||||
end = src.length;
|
||||
}
|
||||
gplx.langs.htmls.Gfh_utl.Escape_html_to_bfr(bfr, src_doc, bgn, end, true, true, true, true, false); // false to apos for backwards compatibility
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
@Override public Object Data() {return this.Data_as_str();}
|
||||
public void Overwrite_bry(byte[] v) {data_bry = v;} //needed by MapLink/MapFrame
|
||||
public String Data_as_str() {
|
||||
if (data_str == null) {
|
||||
if (data_bry == null)
|
||||
@ -41,15 +75,32 @@ public class Json_itm_str extends Json_itm_base {
|
||||
return Bry_.Match(data_bry, comp);
|
||||
}
|
||||
private byte[] Data_make_bry() {
|
||||
byte[] src = doc.Src(); int bgn = this.Src_bgn(), end = this.Src_end();
|
||||
if (exact) return Bry_.Mid(src, bgn, end);
|
||||
Bry_bfr bfr = doc.Bfr();
|
||||
byte[] utf8_bry = doc.Tmp_u8_bry();
|
||||
byte[] src_doc;
|
||||
int bgn;
|
||||
int end;
|
||||
Bry_bfr bfr;
|
||||
byte[] utf8_bry;
|
||||
if (src == null) {
|
||||
src_doc = doc.Src();
|
||||
bgn = this.Src_bgn();
|
||||
end = this.Src_end();
|
||||
if (exact) return Bry_.Mid(src_doc, bgn, end);
|
||||
bfr = doc.Bfr();
|
||||
utf8_bry = doc.Tmp_u8_bry();
|
||||
}
|
||||
else {
|
||||
if (exact) return src;
|
||||
src_doc = src;
|
||||
bgn = 0;
|
||||
end = src.length;
|
||||
bfr = Bry_bfr_.New();
|
||||
utf8_bry = new byte[6];
|
||||
}
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
byte b = src_doc[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Backslash:
|
||||
b = src[++i];
|
||||
b = src_doc[++i];
|
||||
switch (b) { // NOTE: must properly unescape chars; EX:wd.q:2; DATE:2014-04-23
|
||||
case Byte_ascii.Ltr_t: bfr.Add_byte(Byte_ascii.Tab); break;
|
||||
case Byte_ascii.Ltr_n: bfr.Add_byte(Byte_ascii.Nl); break;
|
||||
@ -58,16 +109,16 @@ public class Json_itm_str extends Json_itm_base {
|
||||
case Byte_ascii.Ltr_f: bfr.Add_byte(Byte_ascii.Formfeed); break;
|
||||
case Byte_ascii.Ltr_u:
|
||||
i += 1; // +1 to skip "u"
|
||||
int utf8_val = gplx.core.encoders.Hex_utl_.Parse_or(src, i, i + 4, -1);
|
||||
int utf8_val = gplx.core.encoders.Hex_utl_.Parse_or(src_doc, i, i + 4, -1);
|
||||
// check for UTF surrogate-pairs; ISSUE#:487; DATE:2019-06-02
|
||||
// hi: 0xD800-0xDBFF; 55,296-56,319
|
||||
if (utf8_val >= Utf16_.Surrogate_hi_bgn && utf8_val <= Utf16_.Surrogate_hi_end) {
|
||||
int lo_bgn = i + 4; // +4 to skip 4 hex-dec chars
|
||||
if (lo_bgn + 6 <= end // +6 to handle encoded String; EX: '\u0022'
|
||||
&& src[lo_bgn] == Byte_ascii.Backslash
|
||||
&& src[lo_bgn + 1] == Byte_ascii.Ltr_u) {
|
||||
&& src_doc[lo_bgn] == Byte_ascii.Backslash
|
||||
&& src_doc[lo_bgn + 1] == Byte_ascii.Ltr_u) {
|
||||
lo_bgn = lo_bgn + 2; // +2 to skip '\' and 'u'
|
||||
int lo = gplx.core.encoders.Hex_utl_.Parse_or(src, lo_bgn, lo_bgn + 4, -1);
|
||||
int lo = gplx.core.encoders.Hex_utl_.Parse_or(src_doc, lo_bgn, lo_bgn + 4, -1);
|
||||
// lo: 0xDC00-0xDFFF; 56,320-57,343
|
||||
if (lo >= Utf16_.Surrogate_lo_bgn && lo <= Utf16_.Surrogate_lo_end) {
|
||||
utf8_val = Utf16_.Surrogate_merge(utf8_val, lo);
|
||||
|
62
400_xowa/src/gplx/langs/jsons/Json_mustache.java
Normal file
62
400_xowa/src/gplx/langs/jsons/Json_mustache.java
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
|
||||
public class Json_mustache {
|
||||
|
||||
public static Json_kv Add_text(String keystr, byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
Json_itm_str val = new Json_itm_str(bytes, false);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
|
||||
public static Json_kv Add_int(String keystr, int intval) {
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
Json_itm_int val = new Json_itm_int(intval);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
|
||||
public static Json_kv Add_double(String keystr, double doubleval) {
|
||||
// eek
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
byte[] bytes = bfr.Add_double(doubleval).To_bry();
|
||||
Json_itm_str val = new Json_itm_str(bytes, true);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
|
||||
public static Json_kv Add_bool(String keystr, boolean bool) {
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
Json_itm_bool val = new Json_itm_bool(bool);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
|
||||
public static Json_kv Add_nde(String keystr, Json_nde nde) {
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
return new Json_kv(key, nde);
|
||||
}
|
||||
|
||||
public static Json_kv Add_ary(String keystr, Json_ary ary) {
|
||||
if (ary == null) return null;
|
||||
Json_itm_str key = new Json_itm_str(Bry_.new_a7(keystr), true);
|
||||
return new Json_kv(key, ary);
|
||||
}
|
||||
}
|
@ -119,7 +119,7 @@ public class Json_nde extends Json_itm_base implements Json_grp {
|
||||
public Json_itm Get_itm(byte[] key) {
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Json_itm itm = subs[i];
|
||||
if (itm.Tid() == Json_itm_.Tid__kv) {
|
||||
if (itm != null && itm.Tid() == Json_itm_.Tid__kv) {
|
||||
Json_kv itm_as_kv = (Json_kv)itm;
|
||||
if (Bry_.Eq(key, itm_as_kv.Key().Data_bry()))
|
||||
return itm;
|
||||
|
@ -14,9 +14,11 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*;
|
||||
import gplx.langs.jsons.*;
|
||||
public class Mustache_render_ctx {
|
||||
private final List_adp stack = List_adp_.New();
|
||||
private Mustache_doc_itm cur;
|
||||
private Json_itm nde; private Json_ary subary;
|
||||
private Mustache_doc_itm[] subs; private int subs_idx, subs_len; private byte cur_is_bool;
|
||||
public Mustache_render_ctx Init(Mustache_doc_itm cur) {
|
||||
this.cur = cur;
|
||||
@ -24,9 +26,53 @@ public class Mustache_render_ctx {
|
||||
this.subs_idx = subs_len = 0; this.cur_is_bool = Bool_.__byte;
|
||||
return this;
|
||||
}
|
||||
public Mustache_render_ctx Init(Json_nde nde) {
|
||||
this.cur = null;
|
||||
this.nde = nde;
|
||||
this.subs = null;
|
||||
this.subs_idx = subs_len = 0; this.cur_is_bool = Bool_.__byte;
|
||||
return this;
|
||||
}
|
||||
// partial implementation of {{.}}
|
||||
public boolean Render_variable(Mustache_bfr bfr, String key) {
|
||||
boolean rv = false;
|
||||
int stack_pos = stack.Len();
|
||||
if (cur == null) {
|
||||
Json_itm itm = nde;
|
||||
while (itm != null) {
|
||||
if (itm instanceof Json_nde) {
|
||||
Json_nde n = (Json_nde)itm;
|
||||
Json_kv kv = (Json_kv)n.Get_itm(Bry_.new_u8(key));
|
||||
if (kv == null)
|
||||
return rv;
|
||||
Json_itm jitm = kv.Val();
|
||||
if (jitm instanceof Json_itm_str) {
|
||||
Json_itm_str s = (Json_itm_str)jitm;
|
||||
bfr.Add_bry(s.Data_bry());
|
||||
return true;
|
||||
}
|
||||
else if (jitm instanceof Json_itm_int) {
|
||||
Json_itm_int s = (Json_itm_int)jitm;
|
||||
bfr.Bfr().Add_int_variable(s.Data_as_int());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
int a = 1/0;
|
||||
}
|
||||
}
|
||||
else if (key.equals(".") && itm instanceof Json_itm_str) {
|
||||
Json_itm_str s = (Json_itm_str)itm;
|
||||
bfr.Add_bry(s.Data_bry());
|
||||
return true;
|
||||
}
|
||||
--stack_pos;
|
||||
if (stack_pos == -1) // nothing else in stack
|
||||
break;
|
||||
else
|
||||
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).nde;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mustache_doc_itm itm = cur;
|
||||
while (itm != Mustache_doc_itm_.Null_itm) {
|
||||
boolean resolved = itm.Mustache__write(key, bfr);
|
||||
@ -42,16 +88,73 @@ public class Mustache_render_ctx {
|
||||
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Section_bgn(String key) {
|
||||
if (cur == null) {
|
||||
Mustache_stack_itm stack_itm = new Mustache_stack_itm(nde, subs, subs_idx, subs_len, cur_is_bool); // note that cur is "owner" since subs_idx == 0
|
||||
stack.Add(stack_itm);
|
||||
Json_nde n = null;
|
||||
Json_itm itm = nde;
|
||||
int stack_pos = stack.Len();
|
||||
while (stack_pos >= 0) {
|
||||
if (itm instanceof Json_nde) {
|
||||
n = (Json_nde)itm;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
stack_pos--;
|
||||
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).nde;
|
||||
}
|
||||
}
|
||||
Json_kv kv = null;
|
||||
if (n != null)
|
||||
kv = (Json_kv)n.Get_itm(Bry_.new_u8(key));
|
||||
if (kv == null)
|
||||
nde = null;
|
||||
else {
|
||||
nde = kv.Val();
|
||||
if (nde instanceof Json_ary) {
|
||||
subary = (Json_ary)nde;
|
||||
subs_len = subary.Len();
|
||||
}
|
||||
else
|
||||
subs_len = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mustache_stack_itm stack_itm = new Mustache_stack_itm(cur, subs, subs_idx, subs_len, cur_is_bool); // note that cur is "owner" since subs_idx == 0
|
||||
stack.Add(stack_itm);
|
||||
subs = cur.Mustache__subs(key); if (subs == null) subs = Mustache_doc_itm_.Ary__empty; // subs == null if property does not exist; EX: "folder{{#files}}file{{/files}}" and folder = new Folder(File[0]);
|
||||
subs_len = subs.length;
|
||||
}
|
||||
subs_idx = -1;
|
||||
}
|
||||
public boolean Section_do(boolean inverted) {
|
||||
if (cur == null) {
|
||||
if (++subs_idx >= subs_len) return false;
|
||||
if (nde == null) return false;
|
||||
if (nde instanceof Json_itm_bool) {
|
||||
Json_itm_bool b = (Json_itm_bool)nde;
|
||||
if (b.Data_as_bool() == false) {
|
||||
boolean rv = Bool_.N;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
boolean rv = Bool_.Y;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
else if (subary != null) {
|
||||
nde = subary.Get_at(subs_idx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++subs_idx >= subs_len) return false;
|
||||
Mustache_doc_itm sub = subs[subs_idx];
|
||||
if (subs_idx == 0) { // special logic to handle 1st item; note that there always be at least one item
|
||||
@ -71,25 +174,42 @@ public class Mustache_render_ctx {
|
||||
cur_is_bool = Bool_.__byte;
|
||||
}
|
||||
cur = sub;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public void Section_end() {
|
||||
Mustache_stack_itm itm = (Mustache_stack_itm)List_adp_.Pop(stack);
|
||||
if (cur == null) {
|
||||
nde = itm.nde;
|
||||
subary = null;
|
||||
}
|
||||
else {
|
||||
cur = itm.cur;
|
||||
}
|
||||
subs = itm.subs;
|
||||
subs_len = itm.subs_len;
|
||||
subs_idx = itm.subs_idx;
|
||||
cur = itm.cur;
|
||||
cur_is_bool = itm.cur_is_bool;
|
||||
}
|
||||
}
|
||||
class Mustache_stack_itm {
|
||||
public Mustache_stack_itm(Mustache_doc_itm cur, Mustache_doc_itm[] subs, int subs_idx, int subs_len, byte cur_is_bool) {
|
||||
this.cur = cur;
|
||||
this.nde = null;
|
||||
this.cur_is_bool = cur_is_bool;
|
||||
this.subs = subs;
|
||||
this.subs_idx = subs_idx;
|
||||
this.subs_len = subs_len;
|
||||
}
|
||||
public Mustache_stack_itm(Json_itm nde, Mustache_doc_itm[] subs, int subs_idx, int subs_len, byte cur_is_bool) {
|
||||
this.cur = null;
|
||||
this.nde = nde;
|
||||
this.cur_is_bool = cur_is_bool;
|
||||
this.subs = subs;
|
||||
this.subs_idx = subs_idx;
|
||||
this.subs_len = subs_len;
|
||||
}
|
||||
public final Json_itm nde;
|
||||
public final Mustache_doc_itm cur;
|
||||
public final byte cur_is_bool;
|
||||
public final Mustache_doc_itm[] subs;
|
||||
|
@ -31,7 +31,7 @@ class Mustache_tkn_def {
|
||||
, Grp_end = Byte_ascii.Slash // {{/section}}
|
||||
, Inverted = Byte_ascii.Pow // {{^inverted}}
|
||||
, Comment = Byte_ascii.Bang // {{!comment}}
|
||||
, Partial = Byte_ascii.Angle_bgn // {{>partial}}
|
||||
, Partial = Byte_ascii.Angle_end // {{>partial}}
|
||||
, Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}}
|
||||
, Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}}
|
||||
;
|
||||
|
@ -103,7 +103,21 @@ class Mustache_tkn_inverted extends Mustache_tkn_base { // EX: {{^section}}missi
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {Mustache_tkn_section.Render_static(Bool_.Y, this, bfr, ctx);}
|
||||
}
|
||||
class Mustache_tkn_partial extends Mustache_tkn_base { // EX: {{>a}} -> abc (deferred eval)
|
||||
public Mustache_tkn_partial(byte[] key) {super(Mustache_tkn_itm_.Tid__partial, key);}
|
||||
private Mustache_tkn_itm template_root;
|
||||
public Mustache_tkn_partial(byte[] key, Io_url dir) {
|
||||
super(Mustache_tkn_itm_.Tid__partial, key);
|
||||
int key_len = key.length;
|
||||
int i;
|
||||
for (i = 0; i < key_len; i++) {
|
||||
if (key[i] != ' ')
|
||||
break;
|
||||
}
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser(dir);
|
||||
template_root = parser.Parse(String_.new_a7(Bry_.Mid(key, i, key_len)));
|
||||
}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
template_root.Render(bfr, ctx);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_delimiter extends Mustache_tkn_base {// EX: {{=<% %>=}} -> <% variable %>
|
||||
public Mustache_tkn_delimiter(byte[] key) {super(Mustache_tkn_itm_.Tid__delimiter, key);}
|
||||
|
@ -16,7 +16,18 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*;
|
||||
public class Mustache_tkn_parser {
|
||||
private byte[] src; private int src_end;
|
||||
private Io_url template_root;
|
||||
private final Mustache_tkn_def tkn_def = new Mustache_tkn_def();
|
||||
public Mustache_tkn_parser() {
|
||||
}
|
||||
public Mustache_tkn_parser(Io_url template_root) {
|
||||
this.template_root = template_root;
|
||||
}
|
||||
public Mustache_tkn_itm Parse(String template) { return Parse(template, Bry_.Empty); }
|
||||
public Mustache_tkn_itm Parse(String template, byte[] default_text) {
|
||||
byte[] template_data = Io_mgr.Instance.LoadFilBryOr(template_root.GenSubFil_nest(template + ".mustache"), default_text);
|
||||
return Parse(template_data, 0, template_data.length);
|
||||
}
|
||||
public Mustache_tkn_itm Parse(byte[] src) {return Parse(src, 0, src.length);}
|
||||
public Mustache_tkn_itm Parse(byte[] src, int src_bgn, int src_end) {
|
||||
this.src = src; this.src_end = src_end;
|
||||
@ -80,7 +91,7 @@ public class Mustache_tkn_parser {
|
||||
default: throw Err_.new_unhandled(tkn_data.tid);
|
||||
case Mustache_tkn_def.Variable: tkn = new Mustache_tkn_variable(val_bry); break;
|
||||
case Mustache_tkn_def.Comment: tkn = new Mustache_tkn_comment(); break;
|
||||
case Mustache_tkn_def.Partial: tkn = new Mustache_tkn_partial(val_bry); break;
|
||||
case Mustache_tkn_def.Partial: tkn = new Mustache_tkn_partial(val_bry, template_root); break;
|
||||
case Mustache_tkn_def.Delimiter_bgn: tkn = new Mustache_tkn_delimiter(val_bry); break; // TODO_OLD: implement delimiter; EX: {{=<% %>=}}
|
||||
case Mustache_tkn_def.Escape_bgn: tkn = new Mustache_tkn_escape(val_bry); break;
|
||||
case Mustache_tkn_def.Section: tkn = new Mustache_tkn_section(val_bry); break;
|
||||
|
292
400_xowa/src/gplx/xowa/Db_Nav_template.java
Normal file
292
400_xowa/src/gplx/xowa/Db_Nav_template.java
Normal file
@ -0,0 +1,292 @@
|
||||
package gplx.xowa;
|
||||
import gplx.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
//import gplx.langs.mustaches.Mustache_tkn_itm;
|
||||
//import gplx.langs.mustaches.Mustache_tkn_parser;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.jsons.Json_mustache;
|
||||
import gplx.xowa.langs.msgs.Xol_msg_mgr;
|
||||
|
||||
public class Db_Nav_template {
|
||||
public Mustache_tkn_itm Navigation_root() {return navigation_root;} private Mustache_tkn_itm navigation_root;
|
||||
private Xol_msg_mgr msg_mgr;
|
||||
private Json_nde msgdata;
|
||||
private Xowe_wiki wiki;
|
||||
|
||||
private static boolean once = true;
|
||||
private static Mustache_tkn_itm menu_root;
|
||||
public static void Build_Sidebar(Xowe_wiki wiki, Bry_bfr bfr, byte[] id, byte[] text, byte[] itms) {
|
||||
if (once) {
|
||||
once = false;
|
||||
Io_url template_root = wiki.Appe().Fsys_mgr().Bin_any_dir().GenSubDir_nest("xowa", "xtns", "Skin-Vector", "templates");
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser(template_root);
|
||||
menu_root = parser.Parse("Menu");
|
||||
}
|
||||
Json_nde data = s_getMenuData(wiki,
|
||||
text,
|
||||
itms,
|
||||
MENU_TYPE_PORTAL
|
||||
);
|
||||
|
||||
//Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
Mustache_render_ctx mctx = new Mustache_render_ctx().Init(data);
|
||||
Mustache_bfr mbfr = Mustache_bfr.New_bfr(bfr);
|
||||
menu_root.Render(mbfr, mctx);
|
||||
// byte[] result = mbfr.To_bry_and_clear();
|
||||
//System.out.println(String_.new_u8(result));
|
||||
}
|
||||
public void Init(Xowe_wiki wiki) {
|
||||
Io_url template_root = wiki.Appe().Fsys_mgr().Bin_any_dir().GenSubDir_nest("xowa", "xtns", "Skin-Vector", "templates");
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser(template_root);
|
||||
navigation_root = parser.Parse("Navigation");
|
||||
this.wiki = wiki;
|
||||
|
||||
msg_mgr = wiki.Lang().Msg_mgr();
|
||||
build_msg();
|
||||
|
||||
Test();
|
||||
}
|
||||
|
||||
private String[] msgs = new String[] {
|
||||
"vector-opt-out-tooltip",
|
||||
"vector-opt-out",
|
||||
"navigation-heading",
|
||||
"vector-action-toggle-sidebar",
|
||||
"vector-jumptonavigation",
|
||||
"vector-jumptosearch",
|
||||
"vector-jumptocontent",
|
||||
"sitesubtitle",
|
||||
"sitetitle",
|
||||
"tagline"
|
||||
};
|
||||
|
||||
//all thes messages should be preprocessed (per language) as $data["msg-{$message}"] = $this->msg( $message )->text();
|
||||
private void build_msg() {
|
||||
int msg_len = msgs.length;
|
||||
msgdata = new Json_nde(null, -1);
|
||||
for (int i = 0; i < msg_len; i++) {
|
||||
String msg = msgs[i];
|
||||
msgdata.Add( Json_mustache.Add_text("msg-" + msg, msg_mgr.Val_by_str_or_empty(msg)));
|
||||
}
|
||||
}
|
||||
private void Test() {
|
||||
Json_nde namespaces = new Json_nde(null, -1);
|
||||
Json_nde jnde = new Json_nde(null, -1);
|
||||
jnde.Add_many(
|
||||
Json_mustache.Add_text("class", Bry_.new_a7("CLASS"))
|
||||
,Json_mustache.Add_text("text", Bry_.new_a7("TEXT"))
|
||||
,Json_mustache.Add_text("href", Bry_.new_a7("URL_str"))
|
||||
,Json_mustache.Add_bool("exists", true)
|
||||
,Json_mustache.Add_bool("primary", true)
|
||||
,Json_mustache.Add_text("link-class", Bry_.Empty)
|
||||
);
|
||||
jnde.Add(Json_mustache.Add_text("context", Bry_.new_a7("subject")));
|
||||
|
||||
namespaces.Add(Json_mustache.Add_nde("subject", jnde));
|
||||
|
||||
//Json_nde data_namespaces = new Json_nde(null, -1);
|
||||
msgdata.Add(Json_mustache.Add_nde("data-namespace-tabs", getMenuData(
|
||||
Bry_.new_a7("namespaces"),
|
||||
namespaces,
|
||||
MENU_TYPE_TABS
|
||||
)));
|
||||
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
Mustache_render_ctx mctx = new Mustache_render_ctx().Init(msgdata);
|
||||
Mustache_bfr mbfr = Mustache_bfr.New_bfr(tmp_bfr);
|
||||
navigation_root.Render(mbfr, mctx);
|
||||
byte[] result = mbfr.To_bry_and_clear();
|
||||
System.out.println(String_.new_u8(result));
|
||||
}
|
||||
|
||||
/* Vector/SkinVector.php */
|
||||
private static int MENU_TYPE_DROPDOWN = 0, MENU_TYPE_TABS = 1, MENU_TYPE_PORTAL = 2, MENU_TYPE_DEFAULT = 3;
|
||||
private static byte[][] extraClasses = new byte[][] {
|
||||
Bry_.new_a7("vector-menu vector-menu-dropdown vectorMenu"),
|
||||
Bry_.new_a7("vector-menu vector-menu-tabs vectorTabs"),
|
||||
Bry_.new_a7("vector-menu vector-menu-portal portal"),
|
||||
Bry_.new_a7("vector-menu")
|
||||
};
|
||||
private Json_nde getMenuData(byte[] label, Json_nde urls, int type) { return getMenuData(label, urls, type, false); }
|
||||
private Json_nde getMenuData(byte[] label, Json_nde urls, int type, boolean setLabelToSelected) {
|
||||
/*
|
||||
private function getMenuData(
|
||||
string $label,
|
||||
array $urls = [],
|
||||
int $type = self::MENU_TYPE_DEFAULT,
|
||||
bool $setLabelToSelected = false
|
||||
) : array {
|
||||
$skin = $this->getSkin();
|
||||
$extraClasses = [
|
||||
self::MENU_TYPE_DROPDOWN => 'vector-menu vector-menu-dropdown vectorMenu',
|
||||
self::MENU_TYPE_TABS => 'vector-menu vector-menu-tabs vectorTabs',
|
||||
self::MENU_TYPE_PORTAL => 'vector-menu vector-menu-portal portal',
|
||||
self::MENU_TYPE_DEFAULT => 'vector-menu',
|
||||
];
|
||||
// A list of classes to apply the list element and override the default behavior.
|
||||
$listClasses = [
|
||||
// `.menu` is on the portal for historic reasons.
|
||||
// It should not be applied elsewhere per T253329.
|
||||
self::MENU_TYPE_DROPDOWN => 'menu vector-menu-content-list',
|
||||
];
|
||||
$isPortal = $type === self::MENU_TYPE_PORTAL;
|
||||
*/
|
||||
boolean isPortal = type == MENU_TYPE_PORTAL;
|
||||
/*
|
||||
|
||||
// For some menu items, there is no language key corresponding with its menu key.
|
||||
// These inconsitencies are captured in MENU_LABEL_KEYS
|
||||
$msgObj = $skin->msg( self::MENU_LABEL_KEYS[ $label ] ?? $label );
|
||||
|
||||
$props = [
|
||||
'id' => "p-$label",
|
||||
*/
|
||||
|
||||
byte[] listClasses;
|
||||
byte[] msg = label; // for now
|
||||
byte[] linkertooltip = Bry_.Empty;
|
||||
if (type == MENU_TYPE_DROPDOWN)
|
||||
listClasses = Bry_.new_a7("menu vector-menu-content-list");
|
||||
else
|
||||
listClasses = Bry_.new_a7("vector-menu-content-list");
|
||||
|
||||
byte[] plabel = Bry_.Add(Bry_.new_a7("p-"), label);
|
||||
Json_nde props = new Json_nde(null, -1);
|
||||
props.Add_many(
|
||||
Json_mustache.Add_text("id", plabel)
|
||||
/*
|
||||
'label-id' => "p-{$label}-label",
|
||||
*/
|
||||
,Json_mustache.Add_text("label-id", Bry_.Add(plabel, Bry_.new_a7("-label")))
|
||||
/*
|
||||
// If no message exists fallback to plain text (T252727)
|
||||
'label' => $msgObj->exists() ? $msgObj->text() : $label,
|
||||
*/
|
||||
,Json_mustache.Add_text("label", msg)
|
||||
/*
|
||||
'list-classes' => $listClasses[$type] ?? 'vector-menu-content-list',
|
||||
*/
|
||||
,Json_mustache.Add_text("list-classes", listClasses)
|
||||
/*
|
||||
'html-items' => '',
|
||||
'is-dropdown' => $type === self::MENU_TYPE_DROPDOWN,
|
||||
*/
|
||||
,Json_mustache.Add_bool("is-dropdown", type == MENU_TYPE_DROPDOWN)
|
||||
,Json_mustache.Add_text("html-tooltip", wiki.Msg_mgr().Val_html_accesskey_and_title(plabel))
|
||||
/*
|
||||
'html-tooltip' => Linker::tooltip( 'p-' . $label ),
|
||||
];
|
||||
*/
|
||||
,Json_mustache.Add_text("html-tooltip", linkertooltip)
|
||||
);
|
||||
/*
|
||||
foreach ( $urls as $key => $item ) {
|
||||
$props['html-items'] .= $this->getSkin()->makeListItem( $key, $item );
|
||||
// Check the class of the item for a `selected` class and if so, propagate the items
|
||||
// label to the main label.
|
||||
if ( $setLabelToSelected ) {
|
||||
if ( isset( $item['class'] ) && stripos( $item['class'], 'selected' ) !== false ) {
|
||||
$props['label'] = $item['text'];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
props.Add(Json_mustache.Add_text("html-items", Bry_.new_u8("<li id=\"ca-nstab-main\" class=\"selected\"><a href=\"/wiki/Main_Page\" title=\"View the content page [c]\" accesskey=\"c\">Main Page</a></li>")));
|
||||
|
||||
/*
|
||||
$afterPortal = '';
|
||||
if ( $isPortal ) {
|
||||
// The BaseTemplate::getAfterPortlet method ran the SkinAfterPortlet
|
||||
// hook and if content is added appends it to the html-after-portal method.
|
||||
// This replicates that historic behaviour.
|
||||
// This code should eventually be upstreamed to SkinMustache in core.
|
||||
// Currently in production this supports the Wikibase 'edit' link.
|
||||
$content = $this->getAfterPortlet( $label );
|
||||
if ( $content !== '' ) {
|
||||
$afterPortal = Html::rawElement(
|
||||
'div',
|
||||
[ 'class' => [ 'after-portlet', 'after-portlet-' . $label ] ],
|
||||
$content
|
||||
);
|
||||
}
|
||||
}
|
||||
$props['html-after-portal'] = $afterPortal;
|
||||
|
||||
// Mark the portal as empty if it has no content
|
||||
$class = ( count( $urls ) == 0 && !$props['html-after-portal'] )
|
||||
? 'vector-menu-empty emptyPortlet' : '';
|
||||
$props['class'] = trim( "$class $extraClasses[$type]" );
|
||||
return $props;
|
||||
*/
|
||||
props.Add(Json_mustache.Add_text("class", extraClasses[type]));
|
||||
return props;
|
||||
}
|
||||
|
||||
private static Json_nde s_getMenuData(Xowe_wiki wiki, byte[] label, byte[] urls, int type) { return s_getMenuData(wiki, label, urls, type, false); }
|
||||
private static Json_nde s_getMenuData(Xowe_wiki wiki, byte[] label, byte[] urls, int type, boolean setLabelToSelected) {
|
||||
boolean isPortal = type == MENU_TYPE_PORTAL;
|
||||
|
||||
byte[] listClasses;
|
||||
byte[] msg = label; // for now
|
||||
byte[] linkertooltip = Bry_.Empty;
|
||||
if (type == MENU_TYPE_DROPDOWN)
|
||||
listClasses = Bry_.new_a7("menu vector-menu-content-list");
|
||||
else
|
||||
listClasses = Bry_.new_a7("vector-menu-content-list");
|
||||
|
||||
byte[] plabel = Bry_.Add(Bry_.new_a7("p-"), label);
|
||||
Json_nde props = new Json_nde(null, -1);
|
||||
props.Add_many(
|
||||
Json_mustache.Add_text("id", plabel)
|
||||
,Json_mustache.Add_text("label-id", Bry_.Add(plabel, Bry_.new_a7("-label")))
|
||||
,Json_mustache.Add_text("label", msg)
|
||||
,Json_mustache.Add_text("list-classes", listClasses)
|
||||
,Json_mustache.Add_bool("is-dropdown", type == MENU_TYPE_DROPDOWN)
|
||||
,Json_mustache.Add_text("html-tooltip", wiki.Msg_mgr().Val_html_accesskey_and_title(plabel))
|
||||
,Json_mustache.Add_text("html-tooltip", linkertooltip)
|
||||
);
|
||||
/*
|
||||
foreach ( $urls as $key => $item ) {
|
||||
$props['html-items'] .= $this->getSkin()->makeListItem( $key, $item );
|
||||
// Check the class of the item for a `selected` class and if so, propagate the items
|
||||
// label to the main label.
|
||||
if ( $setLabelToSelected ) {
|
||||
if ( isset( $item['class'] ) && stripos( $item['class'], 'selected' ) !== false ) {
|
||||
$props['label'] = $item['text'];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
props.Add(Json_mustache.Add_text("html-items", urls));
|
||||
|
||||
/*
|
||||
$afterPortal = '';
|
||||
if ( $isPortal ) {
|
||||
// The BaseTemplate::getAfterPortlet method ran the SkinAfterPortlet
|
||||
// hook and if content is added appends it to the html-after-portal method.
|
||||
// This replicates that historic behaviour.
|
||||
// This code should eventually be upstreamed to SkinMustache in core.
|
||||
// Currently in production this supports the Wikibase 'edit' link.
|
||||
$content = $this->getAfterPortlet( $label );
|
||||
if ( $content !== '' ) {
|
||||
$afterPortal = Html::rawElement(
|
||||
'div',
|
||||
[ 'class' => [ 'after-portlet', 'after-portlet-' . $label ] ],
|
||||
$content
|
||||
);
|
||||
}
|
||||
}
|
||||
$props['html-after-portal'] = $afterPortal;
|
||||
|
||||
// Mark the portal as empty if it has no content
|
||||
$class = ( count( $urls ) == 0 && !$props['html-after-portal'] )
|
||||
? 'vector-menu-empty emptyPortlet' : '';
|
||||
$props['class'] = trim( "$class $extraClasses[$type]" );
|
||||
return $props;
|
||||
*/
|
||||
props.Add(Json_mustache.Add_text("class", extraClasses[type]));
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
400
400_xowa/src/gplx/xowa/Db_Section_list.java
Normal file
400
400_xowa/src/gplx/xowa/Db_Section_list.java
Normal file
@ -0,0 +1,400 @@
|
||||
/* search for '</?section' then find fwd '>'
|
||||
any </section ignore
|
||||
|
||||
within bgn to end need to dig out 'begin' or 'end' or the language sensitivities
|
||||
also the key value
|
||||
|
||||
store
|
||||
name of section, start or end
|
||||
if start position after close >
|
||||
if end position before <
|
||||
*/
|
||||
package gplx.xowa;
|
||||
import gplx.Bry_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
|
||||
import gplx.xowa.parsers.Xop_ctx;
|
||||
import gplx.xowa.parsers.Xop_root_tkn;
|
||||
import gplx.xowa.parsers.Xop_parser;
|
||||
import gplx.xowa.parsers.Xop_parser_;
|
||||
import gplx.xowa.parsers.Xop_parser_tid_;
|
||||
import gplx.xowa.parsers.Xop_tkn_mkr;
|
||||
import gplx.xowa.parsers.tmpls.Xot_invk_temp;
|
||||
import gplx.xowa.parsers.lnkis.files.Xop_file_logger_;
|
||||
import gplx.xowa.parsers.tmpls.Xot_defn_tmpl;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bool_;
|
||||
import gplx.Hash_adp_bry;
|
||||
import gplx.xowa.xtns.lst.Lst_pfunc_itm;
|
||||
public class Db_Section_list {
|
||||
private List_adp sects;
|
||||
private List_adp heads;
|
||||
private byte[] src;
|
||||
private Xop_ctx ctx;
|
||||
private Xop_ctx sub_ctx;
|
||||
private Xowe_wiki wiki;
|
||||
private Xoa_ttl ttl;
|
||||
private byte[] ttl_bry;
|
||||
private static final byte Include_between = 0, Include_to_eos = 1, Include_to_bos = 2;
|
||||
public Db_Section_list(byte[] src, int langid, Xop_ctx ctx, Xop_ctx sub_ctx, Xoa_ttl ttl, byte[] ttl_bry) {
|
||||
byte b;
|
||||
this.src = src;
|
||||
this.ctx = ctx;
|
||||
this.wiki = ctx.Wiki();
|
||||
this.sub_ctx = sub_ctx;
|
||||
this.ttl = ttl;
|
||||
this.ttl_bry = ttl_bry;
|
||||
int src_len = src.length;
|
||||
int pos = 0;
|
||||
int bgn, end, atr;
|
||||
sects = List_adp_.New();
|
||||
begin_end keyword;
|
||||
switch (langid) {
|
||||
case 1: // german!!!
|
||||
keyword = new DE_begin_end();
|
||||
break;
|
||||
default:
|
||||
keyword = new EN_begin_end();
|
||||
break;
|
||||
}
|
||||
while (pos < src_len) {
|
||||
b = src[pos++];
|
||||
if (b == '<') {
|
||||
if (pos + 10 < src_len && (src[pos] | 32) == 's' && (src[pos+1] | 32) == 'e' && (src[pos+2] | 32) == 'c' && (src[pos+3] | 32) == 't' && (src[pos+4] | 32) == 'i' && (src[pos+5] | 32) == 'o' && (src[pos+6] | 32) == 'n' && src[pos+7] == ' ') {
|
||||
bgn = pos - 1;
|
||||
pos += 8;
|
||||
atr = pos;
|
||||
while (pos < src_len) {
|
||||
b = src[pos++];
|
||||
if (b == '>')
|
||||
break;
|
||||
}
|
||||
if (pos == src_len) // no end found
|
||||
break;
|
||||
end = pos;
|
||||
// now find a keyword
|
||||
begin_end_result bg = keyword.Find(src, atr, end);
|
||||
if (bg != null) {
|
||||
sects.Add(new Section(src, bg.start, bg.type, bgn, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (b == '\n') { // check for headers
|
||||
if (pos + 10 < src_len && src[pos] == '=') {
|
||||
int count = 1;
|
||||
pos++;
|
||||
while (pos < src_len) {
|
||||
b = src[pos++];
|
||||
if (b != '=')
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
// now find the next <nl>
|
||||
if (b != '\n') {
|
||||
int npos = pos;
|
||||
while (npos < src_len) {
|
||||
b = src[npos++];
|
||||
if (b == '\n')
|
||||
break;
|
||||
}
|
||||
if (b == '\n') {
|
||||
// now count any '=' backwards
|
||||
int ncount = 0;
|
||||
while (npos > pos) {
|
||||
b = src[--npos];
|
||||
if (b == '=')
|
||||
ncount++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (ncount == count) { // we have a header
|
||||
heads.Add(new Header(src, pos, npos, count));
|
||||
pos = npos + count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public byte[] Include(byte[] from, byte[] to) {
|
||||
if (to == Lst_pfunc_itm.Null_arg) { // no end arg; EX: {{#lst:page|bgn}}; NOTE: different than {{#lst:page|bgn|}}
|
||||
if (from == Lst_pfunc_itm.Null_arg) { // no bgn arg; EX: {{#lst:page}}
|
||||
return Compile3(src);
|
||||
}
|
||||
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
|
||||
to = from;
|
||||
}
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
byte include_mode = Include_between;
|
||||
if (Bry_.Len_eq_0(to))
|
||||
include_mode = Include_to_eos;
|
||||
else if (Bry_.Len_eq_0(from))
|
||||
include_mode = Include_to_bos;
|
||||
int bgn_pos = 0; boolean bgn_found = false; int src_page_bry_len = src.length;
|
||||
int sections_len = sects.Count();
|
||||
for (int i = 0; i < sections_len; i++) {
|
||||
Section sect = (Section)sects.Get_at(i);
|
||||
byte section_tid = (byte)sect.type;
|
||||
if (section_tid == begin_end_result.BEGIN && Matchkey(sect, from)) {
|
||||
int sect_bgn_rhs = sect.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);
|
||||
bgn_found = false;
|
||||
break;
|
||||
}
|
||||
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 == begin_end_result.END && Matchkey(sect, to)) {
|
||||
int sect_end_lhs = sect.bgn;
|
||||
if (include_mode == Include_to_bos) { // write from bos to cur; EX: {{#lst:page||end}}
|
||||
bfr.Add_mid(src, 0, sect_end_lhs);
|
||||
bgn_found = false;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
return Compile3(bfr.To_bry());
|
||||
}
|
||||
public byte[] Exclude(byte[] sect_exclude, byte[] sect_replace) {
|
||||
if (Bry_.Len_eq_0(sect_exclude)) { // no exclude arg; EX: {{#lstx:page}} or {{#lstx:page}}
|
||||
return Compile3(src); // write all and exit
|
||||
}
|
||||
int sections_len = sects.Count();
|
||||
int bgn_pos = 0;
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
for (int i = 0; i < sections_len; i++) {
|
||||
Section sect = (Section)sects.Get_at(i);
|
||||
byte section_tid = (byte)sect.type;
|
||||
if (section_tid == begin_end_result.BEGIN && Matchkey(sect, sect_exclude)) {
|
||||
bfr.Add_mid(src, bgn_pos, sect.bgn); // write everything from bgn_pos up to exclude
|
||||
}
|
||||
else if (section_tid == begin_end_result.END && Matchkey(sect, sect_exclude)) { // exclude end found
|
||||
if (sect_replace != null)
|
||||
bfr.Add(sect_replace); // write replacement
|
||||
bgn_pos = sect.end; // reset bgn_pos
|
||||
}
|
||||
}
|
||||
bfr.Add_mid(src, bgn_pos, src.length);
|
||||
return Compile3(bfr.To_bry());
|
||||
}
|
||||
public byte[] Header(byte[] lhs_hdr, byte[] rhs_hdr) {
|
||||
return Bry_.Empty;
|
||||
}
|
||||
private boolean Matchkey(Section sect, byte[] find) {
|
||||
if (find == Lst_pfunc_itm.Null_arg) return false;
|
||||
int pos = sect.keybgn;
|
||||
int keylen = sect.keyend - pos;
|
||||
int find_end = find.length;
|
||||
if (find_end != keylen) return false;
|
||||
for (int i = 0; i < find_end; i++) {
|
||||
if (src[pos + i] != find[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// need ctx hence wiki and page
|
||||
private byte[] Compile(byte[] page_bry) {
|
||||
Xop_root_tkn xtn_root = null;
|
||||
// set recursing flag
|
||||
Xoae_page page = ctx.Page();
|
||||
Bry_bfr full_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
try {
|
||||
wiki.Parser_mgr().Lst__recursing_(true);
|
||||
Hash_adp_bry lst_page_regy = ctx.Lst_page_regy(); if (lst_page_regy == null) lst_page_regy = Hash_adp_bry.cs(); // SEE:NOTE:page_regy; DATE:2014-01-01
|
||||
page.Html_data().Indicators().Enabled_(Bool_.N); // disable <indicator> b/c <page> should not add to current page; PAGE:en.s:The_Parochial_System_(Wilberforce,_1838); DATE:2015-04-29
|
||||
xtn_root = Bld_root_nde(full_bfr, lst_page_regy, page_bry); // NOTE: this effectively reparses page twice; needed b/c of "if {| : ; # *, auto add new_line" which can build different tokens
|
||||
} finally {
|
||||
wiki.Parser_mgr().Lst__recursing_(false);
|
||||
full_bfr.Mkr_rls();
|
||||
}
|
||||
page.Html_data().Indicators().Enabled_(Bool_.Y);
|
||||
if (xtn_root == null) return null;
|
||||
//html_wtr.Write_tkn_to_html(bfr, ctx, hctx, xtn_root.Root_src(), xnde, Xoh_html_wtr.Sub_idx_null, xtn_root);
|
||||
return null;
|
||||
}
|
||||
private byte[] Compile2(byte[] msg_val) {
|
||||
Xowe_wiki wikie = (Xowe_wiki)wiki;
|
||||
Xop_ctx sub_ctx = Xop_ctx.New__sub__reuse_page(wikie.Parser_mgr().Ctx());
|
||||
sub_ctx.Parse_tid_(Xop_parser_tid_.Tid__wtxt);
|
||||
Xop_tkn_mkr tkn_mkr = sub_ctx.Tkn_mkr();
|
||||
Xop_root_tkn sub_root = tkn_mkr.Root(msg_val);
|
||||
return wikie.Parser_mgr().Main().Expand_tmpl(sub_root, sub_ctx, tkn_mkr, msg_val);
|
||||
}
|
||||
private byte[] Compile3(byte[] sub_src) {
|
||||
// parse page; note adding to stack to prevent circular recursions
|
||||
if (!wiki.Parser_mgr().Tmpl_stack_add(ttl.Full_db())) return null;
|
||||
Xot_defn_tmpl tmpl = wiki.Parser_mgr().Main().Parse_text_to_defn_obj(sub_ctx, sub_ctx.Tkn_mkr(), ttl.Ns(), ttl_bry, sub_src); // NOTE: parse as tmpl to ignore <noinclude>
|
||||
wiki.Parser_mgr().Tmpl_stack_del(); // take template off stack; evaluate will never recurse, but will fail if ttl is still on stack; DATE:2014-03-10
|
||||
|
||||
// eval tmpl
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
try {
|
||||
tmpl.Tmpl_evaluate(sub_ctx, Xot_invk_temp.New_root(ttl.Page_txt()), tmp_bfr);
|
||||
sub_src = tmp_bfr.To_bry_and_clear();
|
||||
} finally {
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
return sub_src;
|
||||
}
|
||||
private Xop_root_tkn Bld_root_nde(Bry_bfr page_bfr, Hash_adp_bry lst_page_regy, byte[] wikitext) {
|
||||
Xop_ctx tmp_ctx = Xop_ctx.New__sub__reuse_lst(wiki, ctx, lst_page_regy);
|
||||
tmp_ctx.Page().Ttl_(ctx.Page().Ttl()); // NOTE: must set tmp_ctx.Ttl to ctx.Ttl; EX: Flatland and First World; DATE:2013-04-29
|
||||
tmp_ctx.Lnki().File_logger_(Xop_file_logger_.Noop); // NOTE: set file_wkr to null, else items will be double-counted
|
||||
tmp_ctx.Parse_tid_(Xop_parser_tid_.Tid__defn);
|
||||
Xop_parser tmp_parser = Xop_parser.new_(wiki, wiki.Parser_mgr().Main().Tmpl_lxr_mgr(), wiki.Parser_mgr().Main().Wtxt_lxr_mgr());
|
||||
Xop_root_tkn rv = tmp_ctx.Tkn_mkr().Root(wikitext);
|
||||
tmp_parser.Parse_text_to_wdom(rv, tmp_ctx, tmp_ctx.Tkn_mkr(), wikitext, Xop_parser_.Doc_bgn_bos);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
class Section {
|
||||
public int keybgn;
|
||||
public int keyend;
|
||||
public int type;
|
||||
public int bgn;
|
||||
public int end;
|
||||
Section(byte[] src, int keybgn, int type, int bgn, int end) {
|
||||
this.type = type;
|
||||
this.bgn = bgn;
|
||||
this.end = end;
|
||||
byte b = src[keybgn];
|
||||
if (b == '\'' || b == '"')
|
||||
keybgn++;
|
||||
keyend = end - 2;
|
||||
while (keyend > bgn) {
|
||||
b = src[keyend - 1];
|
||||
if (b != ' ' && b != '\t' && b != '\n')
|
||||
break;
|
||||
keyend--;
|
||||
}
|
||||
if (b == '\'' || b == '"')
|
||||
keyend--;
|
||||
this.keybgn = keybgn;
|
||||
}
|
||||
}
|
||||
class Header {
|
||||
public int bgn;
|
||||
public int end;
|
||||
public int level;
|
||||
Header(byte[] src, int bgn, int end, int level) {
|
||||
this.level = level;
|
||||
byte b;
|
||||
while (bgn < end) {
|
||||
b = src[bgn];
|
||||
if (b == ' ' || b == '\t')
|
||||
bgn++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
this.bgn = bgn;
|
||||
while (end > bgn) {
|
||||
b = src[end - 1];
|
||||
if (b == ' ' || b == '\t')
|
||||
bgn--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
interface begin_end {
|
||||
begin_end_result Find(byte[] src, int bgn, int end);
|
||||
}
|
||||
|
||||
class EN_begin_end implements begin_end {
|
||||
public begin_end_result Find(byte[] src, int bgn, int end) {
|
||||
while (bgn < end) {
|
||||
byte b = src[bgn++];
|
||||
switch (b) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
if ((src[bgn] | 32) == 'e' && (src[bgn+1] | 32) == 'g' && (src[bgn+2] | 32) == 'i' && (src[bgn+3] | 32) == 'n' && src[bgn+4] == '=') {
|
||||
bgn += 5;
|
||||
b = src[bgn];
|
||||
return new begin_end_result(begin_end_result.BEGIN, bgn);
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
if ((src[bgn] | 32) == 'n' && (src[bgn+1] | 32) == 'd' && src[bgn+2] == '=') {
|
||||
bgn += 3;
|
||||
b = src[bgn];
|
||||
return new begin_end_result(begin_end_result.END, bgn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
class DE_begin_end implements begin_end {
|
||||
public begin_end_result Find(byte[] src, int bgn, int end) {
|
||||
while (bgn < end) {
|
||||
byte b = src[bgn++];
|
||||
switch (b) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
if ((src[bgn] | 32) == 'e' && (src[bgn+1] | 32) == 'g' && (src[bgn+2] | 32) == 'i' && (src[bgn+3] | 32) == 'n' && src[bgn+4] == '=') {
|
||||
bgn += 5;
|
||||
b = src[bgn];
|
||||
return new begin_end_result(begin_end_result.BEGIN, bgn);
|
||||
}
|
||||
break;
|
||||
// End
|
||||
// Ende
|
||||
case 'e':
|
||||
case 'E':
|
||||
if ((src[bgn] | 32) == 'n' && (src[bgn+1] | 32) == 'd') {
|
||||
if (src[bgn+2] == '=') {
|
||||
bgn += 3;
|
||||
}
|
||||
else if ((src[bgn+2] | 32) == 'e' && src[bgn+3] == '=') {
|
||||
bgn += 4;
|
||||
}
|
||||
else
|
||||
break;
|
||||
b = src[bgn];
|
||||
return new begin_end_result(begin_end_result.END, bgn);
|
||||
}
|
||||
break;
|
||||
// Anfang
|
||||
case 'a':
|
||||
case 'A':
|
||||
if ((src[bgn] | 32) == 'n' && (src[bgn+1] | 32) == 'f' && (src[bgn+2] | 32) == 'a' && (src[bgn+3] | 32) == 'n' && (src[bgn+4] | 32) == 'g' && src[bgn+5] == '=') {
|
||||
bgn += 6;
|
||||
b = src[bgn];
|
||||
return new begin_end_result(begin_end_result.END, bgn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
class begin_end_result {
|
||||
public static int BEGIN = 1;
|
||||
public static int END = 2;
|
||||
public int type;
|
||||
public int start;
|
||||
begin_end_result(int type, int start) {
|
||||
this.type = type;
|
||||
this.start = start;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,8 +13,16 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
|
||||
import gplx.core.brys.*; import gplx.core.brys.fmts.*;
|
||||
package gplx.xowa.addons.htmls.sidebars;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bry_fmt;
|
||||
import gplx.List_adp;
|
||||
import gplx.core.brys.Bfr_arg;
|
||||
import gplx.xowa.Db_Nav_template;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
|
||||
class Xoh_sidebar_htmlr {
|
||||
public static byte[] To_html(Bry_bfr bfr, Xowe_wiki wiki, List_adp grps) {
|
||||
Xoh_sidebar_itms_fmtr itms_fmtr = new Xoh_sidebar_itms_fmtr();
|
||||
@ -23,15 +31,28 @@ class Xoh_sidebar_htmlr {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoh_sidebar_itm grp = (Xoh_sidebar_itm)grps.Get_at(i);
|
||||
itms_fmtr.Init_by_grp(popups_enabled, grp);
|
||||
fmt.Bld_many(bfr, grp.Id(), grp.Text(), itms_fmtr);
|
||||
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
itms_fmtr.Bfr_arg__add(tmp_bfr);
|
||||
Db_Nav_template.Build_Sidebar(wiki, bfr, grp.Id(), grp.Text(), tmp_bfr.To_bry());
|
||||
|
||||
//itms_fmtr.Init_by_grp(popups_enabled, grp);
|
||||
//fmt.Bld_many(bfr, grp.Id(), grp.Text(), itms_fmtr);
|
||||
}
|
||||
// dummy toolbox
|
||||
// id="p-tb" used by some js
|
||||
bfr.Add_str_a7("<div class=\"portal\" id=\"p-tb\"></div>");
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
private static final Bry_fmt fmt = Bry_fmt.Auto_nl_skip_last
|
||||
( "<div class=\"portal\" id=\"~{grp_id}\">"
|
||||
, " <h3>~{grp_text}</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>~{itms}"
|
||||
, " <h3 id=\"p-navigation-label\">"
|
||||
, " <span>~{grp_text}</span>"
|
||||
, " </h3>"
|
||||
, " <!-- Please do not use the .body class, it is deprecated. -->"
|
||||
, " <div class=\"body vector-menu-content\">"
|
||||
, " <!-- Please do not use the .menu class, it is deprecated. -->"
|
||||
, " <ul class=\"vector-menu-content-list\">~{itms}"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,11 +13,28 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
|
||||
import org.junit.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
|
||||
package gplx.xowa.addons.htmls.sidebars;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.List_adp;
|
||||
import gplx.String_;
|
||||
import gplx.Tfds;
|
||||
import gplx.xowa.Xoa_app_fxt;
|
||||
import gplx.xowa.Xoae_app;
|
||||
import gplx.xowa.Xop_fxt;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.langs.msgs.Xol_msg_itm;
|
||||
import gplx.xowa.langs.msgs.Xol_msg_mgr;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Xoh_sidebar_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private final Xoh_sidebar_mgr_fxt fxt = new Xoh_sidebar_mgr_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
private final Xoh_sidebar_mgr_fxt fxt = new Xoh_sidebar_mgr_fxt();
|
||||
@Test public void Grp() {
|
||||
fxt.Init__msg__grp("key", "text", "title");
|
||||
fxt.Exec__make("* key");
|
||||
@ -71,7 +88,39 @@ public class Xoh_sidebar_mgr_tst {
|
||||
fxt.Exec__make("** href_key<!--a-->|main_key<!--b-->");
|
||||
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
|
||||
}
|
||||
@Test public void Smoke() {
|
||||
@Test public void Itm_template_msg() {
|
||||
fxt.Init__msg__itm("href", "main", null, null, null, "{{ns:Special}}:Random");
|
||||
fxt.Exec__make("** href|main");
|
||||
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
|
||||
}
|
||||
@Test public void Itm_template_key() {
|
||||
fxt.Exec__make("** {{ns:Special}}:Random|main");
|
||||
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
|
||||
}
|
||||
// @Test
|
||||
public void Popups() {
|
||||
fxt.Init__popups_enabled(true);
|
||||
fxt.Exec__make
|
||||
( "* navigation"
|
||||
, "** mainpage|mainpage-description"
|
||||
);
|
||||
fxt.Test__objs
|
||||
( fxt.Make__grp("navigation", "").Subs__add
|
||||
( fxt.Make__itm("mainpage-description", Null_str, Null_str, "/wiki/Mainpage")
|
||||
));
|
||||
fxt.Test__html
|
||||
( "<div class=\"portal\" id=\"n-navigation\">"
|
||||
, " <h3>navigation</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Mainpage\" class='xowa-hover-off' title=\"\">mainpage-description</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
);
|
||||
}
|
||||
// @Test
|
||||
public void Smoke() {
|
||||
fxt.Init__msg__grp("navigation", "Grp_0_text", "Grp_0_title");
|
||||
fxt.Init__msg__itm("mainpage", "mainpage-description", "Itm_0_text", "Itm_0_title [a]", "a", "Itm_0_href");
|
||||
fxt.Init__msg__itm("Portal:Contents", "contents", "Itm_1_text", Null_str, Null_str, Null_str);
|
||||
@ -114,36 +163,6 @@ public class Xoh_sidebar_mgr_tst {
|
||||
, "</div>"
|
||||
);
|
||||
}
|
||||
@Test public void Itm_template_msg() {
|
||||
fxt.Init__msg__itm("href", "main", null, null, null, "{{ns:Special}}:Random");
|
||||
fxt.Exec__make("** href|main");
|
||||
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
|
||||
}
|
||||
@Test public void Itm_template_key() {
|
||||
fxt.Exec__make("** {{ns:Special}}:Random|main");
|
||||
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
|
||||
}
|
||||
@Test public void Popups() {
|
||||
fxt.Init__popups_enabled(true);
|
||||
fxt.Exec__make
|
||||
( "* navigation"
|
||||
, "** mainpage|mainpage-description"
|
||||
);
|
||||
fxt.Test__objs
|
||||
( fxt.Make__grp("navigation", "").Subs__add
|
||||
( fxt.Make__itm("mainpage-description", Null_str, Null_str, "/wiki/Mainpage")
|
||||
));
|
||||
fxt.Test__html
|
||||
( "<div class=\"portal\" id=\"n-navigation\">"
|
||||
, " <h3>navigation</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Mainpage\" class='xowa-hover-off' title=\"\">mainpage-description</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
);
|
||||
}
|
||||
private static final String Null_str = "";
|
||||
}
|
||||
class Xoh_sidebar_mgr_fxt {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,41 +13,12 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.parsers.tmpls;
|
||||
|
||||
import gplx.Array_;
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bry_find_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Err_;
|
||||
import gplx.Gfo_usr_dlg_;
|
||||
import gplx.Hash_adp_bry;
|
||||
import gplx.String_;
|
||||
import gplx.core.envs.Env_;
|
||||
import gplx.xowa.Xoa_ttl;
|
||||
import gplx.xowa.Xoae_page;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.langs.Xol_lang_itm;
|
||||
import gplx.xowa.langs.funcs.Xol_func_itm;
|
||||
import gplx.xowa.langs.kwds.Xol_kwd_grp;
|
||||
import gplx.xowa.langs.kwds.Xol_kwd_grp_;
|
||||
import gplx.xowa.langs.kwds.Xol_kwd_itm;
|
||||
import gplx.xowa.langs.kwds.Xol_kwd_mgr;
|
||||
import gplx.xowa.parsers.Xop_ctx;
|
||||
import gplx.xowa.parsers.Xop_tkn_itm;
|
||||
import gplx.xowa.parsers.Xop_tkn_itm_;
|
||||
import gplx.xowa.parsers.Xop_tkn_itm_base;
|
||||
import gplx.xowa.wikis.caches.Xow_page_cache_itm;
|
||||
import gplx.xowa.wikis.data.tbls.Xowd_page_itm;
|
||||
import gplx.xowa.wikis.nss.Xow_ns;
|
||||
import gplx.xowa.wikis.nss.Xow_ns_;
|
||||
import gplx.xowa.wikis.nss.Xow_ns_mgr_name_itm;
|
||||
import gplx.xowa.wikis.pages.Xopg_tmpl_prepend_mgr;
|
||||
import gplx.xowa.xtns.pfuncs.ttls.Pfunc_rel2abs;
|
||||
|
||||
package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||
import gplx.core.envs.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*; import gplx.xowa.langs.funcs.*;
|
||||
import gplx.xowa.xtns.pfuncs.*; import gplx.xowa.xtns.pfuncs.ttls.*;
|
||||
import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.nss.*; import gplx.xowa.wikis.caches.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.wikis.domains.Xow_domain_tid_;
|
||||
public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
public Xot_invk_tkn(int bgn, int end) {this.Tkn_ini_pos(false, bgn, end);}
|
||||
@Override public byte Tkn_tid() {return typeId;} private byte typeId = Xop_tkn_itm_.Tid_tmpl_invk;
|
||||
@ -95,6 +66,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
boolean subst_found = false;
|
||||
boolean name_had_subst = false;
|
||||
boolean template_prefix_found = false;
|
||||
// byte tmpl_case_match = wiki.Ns_mgr().Ns_template().Case_match();
|
||||
|
||||
// tmpl_name does not exist in db; may be dynamic, subst, transclusion, etc..
|
||||
if (defn == Xot_defn_.Null) {
|
||||
@ -285,6 +257,29 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
break;
|
||||
case Xot_defn_.Tid_func:
|
||||
try {
|
||||
/* System.out.println(String_.new_a7(caller.Frame_ttl()));
|
||||
if (true) {//(caller.Frame_ttl().length == 22 && caller.Frame_ttl()[21] == 't') {
|
||||
int alen = caller.Args_len();
|
||||
String s = "";
|
||||
for (int i = 0; i < alen; i++) {
|
||||
Arg_nde_tkn atkn = caller.Args_get_by_idx(i);
|
||||
if (atkn.KeyTkn_exists()) {
|
||||
Arg_itm_tkn argtkn = atkn.Key_tkn();
|
||||
s += String_.new_a7(argtkn.Dat_ary()) + ":";
|
||||
}
|
||||
else
|
||||
s += String.valueOf(i);
|
||||
s += String_.new_a7(atkn.Val_tkn().Dat_ary()) + "\n";
|
||||
}
|
||||
System.out.println(s);
|
||||
int a=1;
|
||||
}
|
||||
*/
|
||||
if (Bry_.Eq(caller.Frame_ttl(), Bry_.new_a7("Template:BookCat/core"))) {
|
||||
return true;
|
||||
//int a=1;
|
||||
}
|
||||
//System.out.println(String_.new_u8(caller.Frame_ttl()));
|
||||
Xot_invk_tkn_.Eval_func(ctx, src, caller, this, bfr, defn, argx_ary);
|
||||
rv = true;
|
||||
} catch (Exception e) {
|
||||
@ -306,10 +301,12 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
Bry_bfr rslt_bfr = wiki.Utl__bfr_mkr().Get_k004();
|
||||
try {
|
||||
Xopg_tmpl_prepend_mgr prepend_mgr = ctx.Page().Tmpl_prepend_mgr().Bgn(bfr);
|
||||
rv = defn_tmpl.Tmpl_evaluate(Xop_ctx.New__sub(wiki, ctx, ctx.Page()), invk_tmpl, rslt_bfr); // create new ctx so __NOTOC__ only applies to template, not page; PAGE:de.w:13._Jahrhundert DATE:2017-06-17
|
||||
//rv = defn_tmpl.Tmpl_evaluate(Xop_ctx.New__sub(wiki, ctx, ctx.Page()), invk_tmpl, rslt_bfr); // create new ctx so __NOTOC__ only applies to template, not page; PAGE:de.w:13._Jahrhundert DATE:2017-06-17
|
||||
rv = defn_tmpl.Tmpl_evaluate(ctx, invk_tmpl, rslt_bfr);
|
||||
prepend_mgr.End(ctx, bfr, rslt_bfr.Bfr(), rslt_bfr.Len(), Bool_.Y);
|
||||
if (name_had_subst) { // current invk had "subst:"; parse incoming invk again to remove effects of subst; PAGE:pt.w:Argentina DATE:2014-09-24
|
||||
byte[] tmp_src = rslt_bfr.To_bry_and_clear();
|
||||
if (tmp_src.length != 0)
|
||||
rslt_bfr.Add(wiki.Parser_mgr().Main().Expand_tmpl(tmp_src)); // this could be cleaner / more optimized
|
||||
}
|
||||
bfr.Add_bfr_and_clear(rslt_bfr);
|
||||
@ -341,7 +338,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
Xoa_ttl page_ttl = Xoa_ttl.Parse(wiki, name_ary); if (page_ttl == null) return false; // ttl not valid; EX: {{:[[abc]]}}
|
||||
byte[] transclude_src = null;
|
||||
if (page_ttl.Ns().Id_is_tmpl()) { // ttl is template; check tmpl_regy first before going to data_mgr
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db());
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db(), wiki.Ns_mgr().Ns_template().Case_match());
|
||||
if (tmpl != null) transclude_src = tmpl.Data_raw();
|
||||
}
|
||||
if (transclude_src == null && ctx.Tmpl_load_enabled()) { // ttl is template not in cache, or some other ns; do load
|
||||
@ -378,7 +375,7 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
Xot_defn_tmpl transclude_tmpl = null;
|
||||
switch (page_ttl.Ns().Id()) {
|
||||
case Xow_ns_.Tid__template: // ttl is template not in cache, or some other ns; do load
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db());
|
||||
Xot_defn_tmpl tmpl = (Xot_defn_tmpl)wiki.Cache_mgr().Defn_cache().Get_by_key(page_ttl.Page_db(), wiki.Ns_mgr().Ns_template().Case_match());
|
||||
if (tmpl != null) {
|
||||
if (tmpl.Root() == null) tmpl.Parse_tmpl(ctx);
|
||||
transclude_tmpl = tmpl;
|
||||
@ -389,6 +386,12 @@ public class Xot_invk_tkn extends Xop_tkn_itm_base implements Xot_invk {
|
||||
return true;
|
||||
}
|
||||
if (transclude_tmpl == null && ctx.Tmpl_load_enabled()) { // ttl is template not in cache, or some other ns; do load
|
||||
// if (page_ttl.Ns().Id() == wiki.Ns_mgr().Ns_page_id())
|
||||
// System.out.println("Transclude " + page_ttl.Full_db_as_str());
|
||||
|
||||
// if (wiki.Domain_tid() == Xow_domain_tid_.Tid__wikisource && page_ttl.Ns().Id() == wiki.Ns_mgr().Ns_page_id())
|
||||
// ctx.Page().Html_data().Quality_tots().Check_quality(page_ttl, wiki);
|
||||
|
||||
Xow_page_cache_itm cache_itm = wiki.Cache_mgr().Page_cache().Get_itm_else_load_or_null(page_ttl);
|
||||
if ( cache_itm != null) {
|
||||
if (!Bry_.Eq(cache_itm.Ttl().Full_db(), ctx.Page().Ttl().Full_db())) { // make sure that transcluded item is not same as page_ttl; DATE:2014-01-10
|
||||
|
@ -24,6 +24,11 @@ public class Xow_defn_cache { // stores compiled Xot_defn
|
||||
private final Gfo_cache_mgr cache = new Gfo_cache_mgr().Max_size_(64 * 1024 * 1024).Reduce_by_(32 * 1024 * 1024);
|
||||
public Xow_defn_cache(Xol_lang_itm lang) {this.lang = lang;}
|
||||
public Xot_defn Get_by_key(byte[] name) {return (Xot_defn)cache.Get_by_key(name);}
|
||||
public Xot_defn Get_by_key(byte[] name, byte case_match) {
|
||||
if (case_match == Xow_ns_case_.Tid__1st)
|
||||
name = lang.Case_mgr().Case_build_1st_upper(upper_1st_bfr, name, 0, name.length);
|
||||
return (Xot_defn)cache.Get_by_key(name);
|
||||
}
|
||||
public void Free_mem_all() {cache.Clear();}
|
||||
public void Add(Xot_defn defn, byte case_match) {
|
||||
byte[] name = defn.Name();
|
||||
|
@ -167,6 +167,7 @@ public class Pgbnr_func extends Pf_func_base {
|
||||
}
|
||||
itm.Init_from_html(max_width, banner_file, banner_url, srcset, cfg.enable_heading_override, toc_html, isPanorama);
|
||||
|
||||
// Mustache_render_ctx mctx = new Mustache_render_ctx().Init(itm.Mustache__json());
|
||||
Mustache_render_ctx mctx = new Mustache_render_ctx().Init(itm);
|
||||
Mustache_bfr mbfr = Mustache_bfr.New_bfr(tmp_bfr);
|
||||
wiki.Xtn_mgr().Xtn_pgbnr().Template_root().Render(mbfr, mctx);
|
||||
|
@ -81,7 +81,7 @@ class Pgbnr_func_fxt {
|
||||
fxt.Init__orig(wiki_is_commons, orig_ttl, orig_w, orig_h);
|
||||
}
|
||||
public void Test__parse(boolean hdump, String raw, String expd) {
|
||||
fxt.Exec_parse_page_all_as_str(raw);
|
||||
String test = fxt.Exec_parse_page_all_as_str(raw);
|
||||
Xoh_wtr_ctx hctx = hdump ? Xoh_wtr_ctx.Hdump : Xoh_wtr_ctx.Basic;
|
||||
Bfr_arg arg = fxt.Wiki().Xtn_mgr().Xtn_pgbnr().Write_html(fxt.Page(), fxt.Ctx(), hctx);
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
|
@ -17,19 +17,22 @@ package gplx.xowa.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gp
|
||||
import gplx.langs.mustaches.*; import gplx.xowa.parsers.lnkis.*;
|
||||
import gplx.xowa.files.*;
|
||||
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*; import gplx.xowa.htmls.core.wkrs.imgs.atrs.*; import gplx.xowa.htmls.core.wkrs.lnkis.htmls.*; import gplx.langs.htmls.encoders.*;
|
||||
import gplx.langs.jsons.*;
|
||||
public class Pgbnr_itm implements Mustache_doc_itm {
|
||||
public Xoa_ttl banner_ttl;
|
||||
public byte[] banner_img_src;
|
||||
public byte[] toc;
|
||||
public Xof_file_itm banner_file_itm;
|
||||
private byte[] banner_anch_title, banner_hdr_text, originx, banner_anch_href, srcset;
|
||||
private byte[] banner_anch_title, banner_hdr_text, originx, srcset;
|
||||
private double data_pos_x, data_pos_y;
|
||||
private int max_width;
|
||||
private boolean bottomtoc, isHeadingOverrideEnabled;
|
||||
public /**/ int max_width;
|
||||
public /**/ byte[] banner_anch_href;
|
||||
private boolean bottomtoc;
|
||||
public /**/ boolean isHeadingOverrideEnabled;
|
||||
private byte[] file_ttl;
|
||||
private Pgbnr_icon[] icons;
|
||||
private byte[] img_id_atr, img_xottl_atr, img_xoimg_atr;
|
||||
private boolean isPanorama;
|
||||
public /**/ boolean isPanorama;
|
||||
private boolean enable_toc = true;
|
||||
private boolean hasPosition = false;
|
||||
|
||||
@ -42,6 +45,15 @@ public class Pgbnr_itm implements Mustache_doc_itm {
|
||||
public double Data_pos_y() {return data_pos_y;}
|
||||
public boolean Show_toc_in_html() {return show_toc_in_html;} private boolean show_toc_in_html = false; // default to false so that TOC does not show up in both PageBanner and HTML body; DATE:2019-11-17
|
||||
|
||||
// hdump serialised info
|
||||
public boolean Precoded() {return precoded;} private boolean precoded = false;
|
||||
public byte[] Pgbnr_bry() {return pgbnr_bry;} private byte[] pgbnr_bry;
|
||||
public void Pgbnr_bry_(byte[] v) {
|
||||
if (v == null) return;
|
||||
pgbnr_bry = v;
|
||||
precoded = true;
|
||||
}
|
||||
|
||||
public void Clear_by_hdump() {
|
||||
this.exists = false;
|
||||
this.srcset = style = null;
|
||||
@ -63,11 +75,18 @@ public class Pgbnr_itm implements Mustache_doc_itm {
|
||||
}
|
||||
public void Init_from_wtxt(Xoa_ttl banner_ttl, Xof_file_itm banner_file_itm, byte[] banner_anch_title, byte[] banner_hdr_text, boolean bottomtoc
|
||||
, byte[] toc, double data_pos_x, double data_pos_y, byte[] originx, Pgbnr_icon[] icons) {
|
||||
Init_from_wtxt(banner_ttl, banner_file_itm, banner_anch_title, banner_hdr_text, bottomtoc
|
||||
, toc, data_pos_x, data_pos_y, originx, icons, false);
|
||||
}
|
||||
public void Init_from_wtxt(Xoa_ttl banner_ttl, Xof_file_itm banner_file_itm, byte[] banner_anch_title, byte[] banner_hdr_text, boolean bottomtoc
|
||||
, byte[] toc, double data_pos_x, double data_pos_y, byte[] originx, Pgbnr_icon[] icons, boolean enable_toc) {
|
||||
this.banner_ttl = banner_ttl; this.banner_file_itm = banner_file_itm;
|
||||
this.banner_anch_title = banner_anch_title; this.banner_hdr_text = banner_hdr_text; this.bottomtoc = bottomtoc; this.toc = toc; this.icons = icons;
|
||||
this.data_pos_x = data_pos_x; this.data_pos_y = data_pos_y; this.originx = originx;
|
||||
this.banner_img_src = banner_file_itm.Html_view_url().To_http_file_bry();
|
||||
this.file_ttl = Gfo_url_encoder_.Href_quotes.Encode(banner_file_itm.Lnki_ttl()); // NOTE: Encode(Lnki_ttl) not Orig_ttl; else "%27s" instead of "'s" PAGE:en.v:'s-Hertogenbosch; DATE:2016-07-12
|
||||
this.enable_toc = enable_toc;
|
||||
show_toc_in_html = !enable_toc;
|
||||
}
|
||||
public void Init_from_html(int max_width, byte[] banner_anch_href, byte[] banner_img_src, byte[] srcset, boolean isHeadingOverrideEnabled, byte[] toc, boolean isPanorama) {
|
||||
this.max_width = max_width;
|
||||
@ -126,4 +145,112 @@ public class Pgbnr_itm implements Mustache_doc_itm {
|
||||
, Atr_key__data_pos_y = Bry_.new_a7("data-pos-y")
|
||||
, Atr_val__style_dflt = Bry_.new_a7("max-width:-1px")
|
||||
;
|
||||
public Json_nde Mustache__json() {
|
||||
return buildargs();
|
||||
}
|
||||
private Json_nde buildargs() {
|
||||
Json_ary ary = null;
|
||||
if (json_icon_list != null) {
|
||||
ary = new Json_ary(-1, -1);
|
||||
int iconlen = json_icon_list.Len();
|
||||
for (int i = 0; i < iconlen; i++) {
|
||||
Json_nde inde = (Json_nde)json_icon_list.Get_at(i);
|
||||
ary.Add(inde);
|
||||
}
|
||||
}
|
||||
|
||||
Json_doc_wtr wtr = new Json_doc_wtr();
|
||||
wtr.Nde_bgn();
|
||||
wtr.Kv(Bool_.N, "title", banner_hdr_text);
|
||||
wtr.Kv(Bool_.Y, "tooltip", banner_anch_title);
|
||||
wtr.Kv(Bool_.Y, "bannerfile", banner_anch_href);
|
||||
wtr.Kv(Bool_.Y, "banner", banner_img_src);
|
||||
wtr.Kv(Bool_.Y, "srcset", srcset == null ? Bry_.Empty : Bry_.Empty);
|
||||
wtr.Kv(Bool_.Y, "originx", originx);
|
||||
wtr.Kv(Bool_.Y, "toc", toc);
|
||||
wtr.Kv(Bool_.Y, "img_id_atr", img_id_atr);
|
||||
wtr.Kv(Bool_.Y, "img_xottl", img_xottl_atr);
|
||||
wtr.Kv(Bool_.Y, "img_xoimg", img_xoimg_atr);
|
||||
wtr.Kv(Bool_.Y, "file_ttl", file_ttl);
|
||||
wtr.Kv(Bool_.Y, "data-pos-x", data_pos_x);
|
||||
wtr.Kv(Bool_.Y, "data-pos-y", data_pos_y);
|
||||
wtr.Kv(Bool_.Y, "maxWidth", max_width);
|
||||
wtr.Kv(Bool_.Y, "hasIcons", icons.length > 0);
|
||||
wtr.Kv(Bool_.Y, "bottomtoc", bottomtoc);
|
||||
wtr.Kv(Bool_.Y, "isHeadingOverrideEnabled", isHeadingOverrideEnabled);
|
||||
wtr.Kv(Bool_.Y, "isPanorama", isPanorama);
|
||||
wtr.Kv(Bool_.Y, "enable-toc", enable_toc);
|
||||
wtr.Kv(Bool_.Y, "hasPosition", hasPosition);
|
||||
if (json_icon_list != null) {
|
||||
wtr.Key(Bool_.N, "icons");
|
||||
wtr.Ary_bgn();
|
||||
for (int i = 0; i < json_icon_list.Len(); i++) {
|
||||
Json_nde inde = (Json_nde)json_icon_list.Get_at(i);
|
||||
for (int j = 0; j < inde.Len(); j++) {
|
||||
Json_kv kv = inde.Get_at_as_kv(j);
|
||||
wtr.Kv(i == 0, kv.Key_as_bry(), kv.Val_as_bry());
|
||||
}
|
||||
}
|
||||
wtr.Ary_end();
|
||||
}
|
||||
wtr.Nde_end();
|
||||
String jsonStr = wtr.Bld_as_str();
|
||||
return Json_parser.ParseToJdoc(jsonStr).Root_nde();
|
||||
/*
|
||||
Json_nde jnde = new Json_nde(null, -1);
|
||||
jnde.Add_many(
|
||||
Json_mustache.Add_text("title", banner_hdr_text)
|
||||
,Json_mustache.Add_text("tooltip", banner_anch_title)
|
||||
,Json_mustache.Add_text("bannerfile", banner_anch_href)
|
||||
,Json_mustache.Add_text("banner", banner_img_src)
|
||||
,Json_mustache.Add_text("srcset", srcset == null ? Bry_.Empty : Bry_.Empty)
|
||||
,Json_mustache.Add_text("originx", originx)
|
||||
,Json_mustache.Add_text("toc", toc)
|
||||
,Json_mustache.Add_text("img_id_atr", img_id_atr)
|
||||
,Json_mustache.Add_text("img_xottl", img_xottl_atr)
|
||||
,Json_mustache.Add_text("img_xoimg", img_xoimg_atr)
|
||||
,Json_mustache.Add_text("file_ttl", file_ttl)
|
||||
,Json_mustache.Add_double("data-pos-x", data_pos_x)
|
||||
,Json_mustache.Add_double("data-pos-y", data_pos_y)
|
||||
,Json_mustache.Add_int("maxWidth", max_width)
|
||||
,Json_mustache.Add_bool("hasIcons", icons.length > 0)
|
||||
,Json_mustache.Add_bool("bottomtoc", bottomtoc)
|
||||
,Json_mustache.Add_bool("isHeadingOverrideEnabled", isHeadingOverrideEnabled)
|
||||
,Json_mustache.Add_bool("isPanorama", isPanorama)
|
||||
,Json_mustache.Add_bool("enable-toc", enable_toc)
|
||||
,Json_mustache.Add_bool("hasPosition", hasPosition)
|
||||
,Json_mustache.Add_ary("icons", ary)
|
||||
);
|
||||
//Bry_bfr bfr = Bry_bfr_.New();
|
||||
//jnde.Print_as_json(bfr, 0);
|
||||
//System.out.println(String_.new_u8(bfr.To_bry()));
|
||||
return jnde;
|
||||
*/
|
||||
}
|
||||
|
||||
private List_adp json_icon_list;
|
||||
public void Add_new_icon(Bry_bfr tmp_bfr, byte[] name, byte[] title, byte[] href) {
|
||||
if (json_icon_list == null) json_icon_list = List_adp_.New();
|
||||
json_icon_list.Add(Pgbnr_iconx(tmp_bfr, name, title, href));
|
||||
}
|
||||
|
||||
private Json_nde Pgbnr_iconx(Bry_bfr tmp_bfr, byte[] name, byte[] title, byte[] href) {
|
||||
|
||||
fmt.Bld_many(tmp_bfr, name, title);
|
||||
byte[] html = tmp_bfr.To_bry_and_clear();
|
||||
|
||||
Json_nde jnde = new Json_nde(null, -1);
|
||||
jnde.Add_many(
|
||||
Json_mustache.Add_text("name", name)
|
||||
,Json_mustache.Add_text("title", title)
|
||||
,Json_mustache.Add_text("url", href)
|
||||
,Json_mustache.Add_text("html", html)
|
||||
);
|
||||
return jnde;
|
||||
}
|
||||
|
||||
public static final Bry_fmt fmt = Bry_fmt.New
|
||||
( Bry_.New_u8_nl_apos("<span aria-disabled=\"false\" title=\"~{title}\" class=\"oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-~{name} oo-ui-iconElement oo-ui-iconWidget\"></span>")
|
||||
, "name", "title"
|
||||
);
|
||||
}
|
||||
|
@ -86,9 +86,11 @@ public class Pgbnr_xtn_mgr extends Xox_mgr_base implements Bfr_arg {
|
||||
|
||||
if (!enabled) return;
|
||||
// load template file;
|
||||
byte[] template_data = Io_mgr.Instance.LoadFilBryOr(wiki.Appe().Fsys_mgr().Bin_any_dir().GenSubDir_nest("xowa", "xtns", "WikidataPageBanner", "templates", "banner.mustache"), Template_dflt);
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser();
|
||||
template_root = parser.Parse(template_data, 0, template_data.length);
|
||||
//byte[] template_data = Io_mgr.Instance.LoadFilBryOr(wiki.Appe().Fsys_mgr().Bin_any_dir().GenSubDir_nest("xowa", "xtns", "WikidataPageBanner", "templates", "banner.mustache"), Template_dflt);
|
||||
//Mustache_tkn_parser parser = new Mustache_tkn_parser();
|
||||
//template_root = parser.Parse(template_data, 0, template_data.length);
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser(wiki.Appe().Fsys_mgr().Bin_any_dir().GenSubDir_nest("xowa", "xtns", "WikidataPageBanner", "templates"));
|
||||
template_root = parser.Parse("banner", Template_dflt);
|
||||
}
|
||||
public Bfr_arg Write_html(Xoae_page wpg, Xop_ctx pctx, Xoh_wtr_ctx hctx) {
|
||||
this.wpg = wpg; this.pctx = pctx; this.hctx = hctx;
|
||||
|
@ -140,10 +140,15 @@ app.wikis.get('~{wiki_key}') {
|
||||
app.wikis.get('~{wiki_key}').html.portal {
|
||||
div_personal =
|
||||
<:["
|
||||
<div id="p-personal" class="">
|
||||
<h3>~{<>msgs.get('personaltools');<>}</h3>
|
||||
<nav id="p-personal" class="vector-menu" aria-labelledby="p-personal-label" role="navigation"
|
||||
>
|
||||
<h3 id="p-personal-label">
|
||||
<span>~{<>app.user.msgs.get('personaltools');<>}</span>
|
||||
</h3>
|
||||
<div class="body vector-menu-content">
|
||||
~{portal_indicators_pagesource}
|
||||
</div>
|
||||
</nav>
|
||||
"]:>
|
||||
;
|
||||
div_ns =
|
||||
@ -228,13 +233,16 @@ app.wikis.get('~{wiki_key}').html.portal {
|
||||
;
|
||||
div_wikis =
|
||||
<:["
|
||||
<div id="xowa-portal-wikis" class="portal">
|
||||
<h3>~{toggle_btn}</h3>
|
||||
<div class="body">
|
||||
<nav id="xowa-portal-wikis" class="vector-menu vector-menu-portal portal" aria-labelledby="xowa-portal-wikis" role="navigation"
|
||||
>
|
||||
<h3 id="p-wiki">
|
||||
<span>~{toggle_btn}</span>
|
||||
</h3>
|
||||
<div class="body vector-menu-content">
|
||||
<ul~{toggle_hdr}>~{<>app.gui.html.portal.wikis.itms_as_html;<>}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
"]:>
|
||||
;
|
||||
}
|
||||
@ -472,9 +480,14 @@ app.wikis.scripts.set
|
||||
app.wikis.get('~{wiki_key}').html.portal
|
||||
.div_personal_(
|
||||
<:["
|
||||
<div id="p-personal" class="">
|
||||
<h3>~{<>app.user.msgs.get('personaltools');<>}</h3>
|
||||
<nav id="p-personal" class="vector-menu" aria-labelledby="p-personal-label" role="navigation"
|
||||
>
|
||||
<h3 id="p-personal-label">
|
||||
<span>~{<>app.user.msgs.get('personaltools');<>}</span>
|
||||
</h3>
|
||||
<div class="body vector-menu-content">
|
||||
</div>
|
||||
</nav>
|
||||
"]:>
|
||||
)
|
||||
;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -104,6 +104,18 @@ if (!window.xowa) {
|
||||
},
|
||||
remove: function () {},
|
||||
fire: function () {}
|
||||
} : name === 'wikipage.collapsibleContent' ? {
|
||||
add: function (f) {
|
||||
//fc = f;
|
||||
f(mw.collapsibleContent);
|
||||
// f(window.jQuery ? $collapsible.find( '> .mw-collapsible-content' ) : null);
|
||||
},
|
||||
remove: function () {},
|
||||
fire: function (t) {
|
||||
// different order!!!! wrong order HACK
|
||||
mw.collapsibleContent = t;
|
||||
//fc(t);
|
||||
}
|
||||
} : {
|
||||
add: function () {},
|
||||
remove: function () {},
|
||||
|
22
res/bin/any/xowa/xtns/Skin-Vector/templates/Menu.mustache
Normal file
22
res/bin/any/xowa/xtns/Skin-Vector/templates/Menu.mustache
Normal file
@ -0,0 +1,22 @@
|
||||
{{!
|
||||
See @typedef MenuDefinition
|
||||
}}
|
||||
{{! `role` is unnecessary but kept to support selectors in any gadgets or user styles. }}
|
||||
<!-- Please do not use role attribute as CSS selector, it is deprecated. -->
|
||||
<nav id="{{id}}" {{#class}}class="{{.}}"{{/class}} aria-labelledby="{{label-id}}" role="navigation" {{{html-tooltip}}}
|
||||
{{{html-user-language-attributes}}}>
|
||||
{{#is-dropdown}}
|
||||
<input type="checkbox" class="vector-menu-checkbox vectorMenuCheckbox" aria-labelledby="{{label-id}}" />
|
||||
{{/is-dropdown}}
|
||||
<h3 id="{{label-id}}">
|
||||
<span>{{label}}</span>
|
||||
</h3>
|
||||
{{! `body` class for backwards compatibility but let editors know not to use
|
||||
it via HTML comment below: }}
|
||||
<!-- Please do not use the .body class, it is deprecated. -->
|
||||
<div class="body vector-menu-content">
|
||||
<!-- Please do not use the .menu class, it is deprecated. -->
|
||||
<ul class="{{list-classes}}">{{{html-items}}}</ul>
|
||||
{{{html-after-portal}}}
|
||||
</div>
|
||||
</nav>
|
@ -0,0 +1,16 @@
|
||||
<div id="mw-navigation">
|
||||
<h2>{{msg-navigation-heading}}</h2>
|
||||
<div id="mw-head">
|
||||
{{#data-personal-menu}}{{>Menu}}{{/data-personal-menu}}
|
||||
<div id="left-navigation">
|
||||
{{#data-namespace-tabs}}{{>Menu}}{{/data-namespace-tabs}}
|
||||
{{#data-variants}}{{>Menu}}{{/data-variants}}
|
||||
</div>
|
||||
<div id="right-navigation">
|
||||
{{#data-page-actions}}{{>Menu}}{{/data-page-actions}}
|
||||
{{#data-page-actions-more}}{{>Menu}}{{/data-page-actions-more}}
|
||||
{{#data-search-box}}{{>SearchBox}}{{/data-search-box}}
|
||||
</div>
|
||||
</div>
|
||||
{{#data-sidebar}}{{>legacy/Sidebar}}{{/data-sidebar}}
|
||||
</div>
|
@ -0,0 +1,13 @@
|
||||
{{!
|
||||
See @typedef SidebarData
|
||||
string html-logo-attributes for site logo. Must be used inside tag e.g. `class="logo" lang="en-gb"`
|
||||
}}
|
||||
|
||||
<div id="mw-panel">
|
||||
<div id="p-logo" role="banner">
|
||||
<a {{{html-logo-attributes}}}></a>
|
||||
</div>
|
||||
{{#data-portals-first}}{{>Menu}}{{/data-portals-first}}
|
||||
{{#array-portals-rest}}{{>Menu}}{{/array-portals-rest}}
|
||||
{{#data-portals-languages}}{{>Menu}}{{/data-portals-languages}}
|
||||
</div>
|
@ -0,0 +1,69 @@
|
||||
{{!
|
||||
string|null html-site-notice the contents of a banner defined in MediaWiki:Sitenotice.
|
||||
Also used by CentralNotice to inject banners into Vector.
|
||||
Indicator[] array-indicators wiki-defined badges such as "good article",
|
||||
"featured article". An empty array if none are defined.
|
||||
string page-langcode the content language of the article. Assumed to be escaped HTML.
|
||||
string html-title
|
||||
bool page-isarticle
|
||||
string msg-tagline
|
||||
string html-subtitle
|
||||
string html-undelete-link
|
||||
string html-newtalk
|
||||
string msg-vector-jumptonavigation
|
||||
string msg-vector-jumptosearch
|
||||
string html-body-content
|
||||
string html-categories
|
||||
string html-after-content
|
||||
string msg-navigation-heading heading for entire navigation that is
|
||||
usually hidden to screen readers
|
||||
MenuDefinition data-personal-menu
|
||||
MenuDefinition data-namespace-tabs
|
||||
MenuDefinition data-variants
|
||||
MenuDefinition data-page-actions
|
||||
MenuDefinition data-page-actions-more
|
||||
object data-search-box. See SearchBox.mustache for documentation.
|
||||
object data-sidebar. See Sidebar.mustache for documentation.
|
||||
object data-footer for footer template partial. see Footer.mustache for documentation.
|
||||
}}
|
||||
<div id="mw-page-base" class="noprint"></div>
|
||||
<div id="mw-head-base" class="noprint"></div>
|
||||
<div id="content" class="mw-body" role="main">
|
||||
<a id="top"></a>
|
||||
<div id="siteNotice" class="mw-body-content">{{{html-site-notice}}}</div>
|
||||
{{>Indicators}}
|
||||
<h1 id="firstHeading" class="firstHeading" lang="{{page-langcode}}">{{{html-title}}}</h1>
|
||||
<div id="bodyContent" class="mw-body-content">
|
||||
{{#page-isarticle}}<div id="siteSub" class="noprint">{{msg-tagline}}</div>{{/page-isarticle}}
|
||||
<div id="contentSub"{{{html-user-language-attributes}}}>{{{html-subtitle}}}</div>
|
||||
<div id="contentSub2">{{{html-undelete-link}}}</div>
|
||||
{{{html-newtalk}}}
|
||||
{{!
|
||||
Keep this empty `div` for compatibility with gadgets and user scripts
|
||||
using this place to insert extra elements before.
|
||||
}}
|
||||
<div id="jump-to-nav"></div>
|
||||
<a class="mw-jump-link" href="#mw-head">{{msg-vector-jumptonavigation}}</a>
|
||||
<a class="mw-jump-link" href="#searchInput">{{msg-vector-jumptosearch}}</a>
|
||||
{{{html-body-content}}}
|
||||
{{{html-categories}}}
|
||||
</div>
|
||||
</div>
|
||||
{{{html-after-content}}}
|
||||
<div id="mw-navigation">
|
||||
<h2>{{msg-navigation-heading}}</h2>
|
||||
<div id="mw-head">
|
||||
{{#data-personal-menu}}{{>Menu}}{{/data-personal-menu}}
|
||||
<div id="left-navigation">
|
||||
{{#data-namespace-tabs}}{{>Menu}}{{/data-namespace-tabs}}
|
||||
{{#data-variants}}{{>Menu}}{{/data-variants}}
|
||||
</div>
|
||||
<div id="right-navigation">
|
||||
{{#data-page-actions}}{{>Menu}}{{/data-page-actions}}
|
||||
{{#data-page-actions-more}}{{>Menu}}{{/data-page-actions-more}}
|
||||
{{#data-search-box}}{{>SearchBox}}{{/data-search-box}}
|
||||
</div>
|
||||
</div>
|
||||
{{#data-sidebar}}{{>legacy/Sidebar}}{{/data-sidebar}}
|
||||
</div>
|
||||
{{#data-footer}}{{>Footer}}{{/data-footer}}
|
@ -1,7 +1,7 @@
|
||||
<div class="ext-wpb-pagebanner pre-content">
|
||||
<div class="ext-wpb-pagebanner">
|
||||
<div class="{{#isPanorama}}wpb-banner-image-panorama {{/isPanorama}}wpb-topbanner{{extraClass}}">
|
||||
{{#isHeadingOverrideEnabled}}<h1 class="wpb-name">{{title}}</h1>{{/isHeadingOverrideEnabled}}
|
||||
<a class="image" dir="ltr" title="{{tooltip}}" href="{{bannerfile}}" xowa_title="{{file_ttl}}"><img{{{img_id_atr}}}{{{img_xottl}}}{{{img_xoimg}}} src="{{banner}}" srcset="{{srcset}}" class="wpb-banner-image"{{#hasPosition}} data-pos-x="{{data-pos-x}}" data-pos-y="{{data-pos-y}}" {{/hasPosition}} style="max-width:{{maxWidth}}px"></a>
|
||||
<a class="image" dir="ltr" title="{{tooltip}}" href="{{bannerfile}}" xowa_title="{{file_ttl}}"><img{{{img_id_atr}}}{{{img_xottl}}}{{{img_xoimg}}} src="{{banner}}" srcset="{{srcset}}" class="wpb-banner-image"{{#hasPosition}} data-pos-x="{{data-pos-x}}" data-pos-y="{{data-pos-y}}"{{/hasPosition}}></a>
|
||||
{{#hasIcons}}
|
||||
<div class="wpb-iconbox">
|
||||
{{#icons}}
|
||||
|
Loading…
Reference in New Issue
Block a user