mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
Skin: Change to mustache-backed Skin.Vector [#797]
This commit is contained in:
parent
5c3d6a173b
commit
19a315b8cd
File diff suppressed because it is too large
Load Diff
@ -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,295 +13,309 @@ 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;
|
||||
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.tests.*;
|
||||
public class Bry__tst {
|
||||
private final Bry__fxt fxt = new Bry__fxt();
|
||||
@Test public void new_ascii_() {
|
||||
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_a7("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_a7("" , Bry_.Empty); // none
|
||||
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ?
|
||||
}
|
||||
@Test public void new_u8() {
|
||||
fxt.Test_new_u8("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_u8("¢" , Bry_.New_by_ints(194, 162)); // bry_len=2; cent
|
||||
fxt.Test_new_u8("€" , Bry_.New_by_ints(226, 130, 172)); // bry_len=3; euro
|
||||
fxt.Test_new_u8("𤭢" , Bry_.New_by_ints(240, 164, 173, 162)); // bry_len=4; example from en.w:UTF-8
|
||||
}
|
||||
@Test public void Add__bry_plus_byte() {
|
||||
fxt.Test_add("a" , Byte_ascii.Pipe , "a|"); // basic
|
||||
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String
|
||||
}
|
||||
@Test public void Add__byte_plus_bry() {
|
||||
fxt.Test_add(Byte_ascii.Pipe , "a" , "|a"); // basic
|
||||
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String
|
||||
}
|
||||
@Test public void Add_w_dlm() {
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
|
||||
}
|
||||
@Test public void Add_w_dlm_bry() {
|
||||
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
|
||||
}
|
||||
@Test public void MidByPos() {
|
||||
tst_MidByPos("abcba", 0, 1, "a");
|
||||
tst_MidByPos("abcba", 0, 2, "ab");
|
||||
tst_MidByPos("abcba", 1, 4, "bcb");
|
||||
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Mid(Bry_.new_u8(src), bgn, end)));}
|
||||
@Test public void Replace_one() {
|
||||
tst_ReplaceOne("a" , "b" , "c" , "a");
|
||||
tst_ReplaceOne("b" , "b" , "c" , "c");
|
||||
tst_ReplaceOne("bb" , "b" , "c" , "cb");
|
||||
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
|
||||
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
|
||||
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Replace_one(Bry_.new_u8(src), Bry_.new_u8(find), Bry_.new_u8(repl))));}
|
||||
@Test public void XtoStrBytesByInt() {
|
||||
tst_XtoStrBytesByInt(0, 0);
|
||||
tst_XtoStrBytesByInt(9, 9);
|
||||
tst_XtoStrBytesByInt(10, 1, 0);
|
||||
tst_XtoStrBytesByInt(321, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(Int_.Max_value, 2,1,4,7,4,8,3,6,4,7);
|
||||
}
|
||||
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
|
||||
byte[] expd = new byte[expdAryAsInt.length];
|
||||
for (int i = 0; i < expd.length; i++) {
|
||||
int expdInt = expdAryAsInt[i];
|
||||
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Byte_ascii.To_a7_str(expdAryAsInt[i]);
|
||||
}
|
||||
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
|
||||
}
|
||||
@Test public void Has_at_end() {
|
||||
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
|
||||
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
|
||||
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
|
||||
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
|
||||
tst_HasAtEnd("abc", "bc", true); // y
|
||||
tst_HasAtEnd("abc", "bd", false); // n
|
||||
tst_HasAtEnd("a", "ab", false); // exceeds_len
|
||||
}
|
||||
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end));}
|
||||
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find)));}
|
||||
@Test public void Has_at_bgn() {
|
||||
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
|
||||
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
|
||||
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
|
||||
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
|
||||
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_bgn(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end), tst);}
|
||||
@Test public void Match() {
|
||||
tst_Match("abc", 0, "abc", true);
|
||||
tst_Match("abc", 2, "c", true);
|
||||
tst_Match("abc", 0, "cde", false);
|
||||
tst_Match("abc", 2, "abc", false); // bounds check
|
||||
tst_Match("abc", 0, "abcd", false);
|
||||
tst_Match("a" , 0, "", false);
|
||||
tst_Match("" , 0, "a", false);
|
||||
tst_Match("" , 0, "", true);
|
||||
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
|
||||
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_u8(src), srcPos, Bry_.new_u8(find)));}
|
||||
@Test public void ReadCsvStr() {
|
||||
tst_ReadCsvStr("a|" , "a");
|
||||
tst_ReadCsvStr("|a|", 1 , "a");
|
||||
Int_obj_ref bgn = Int_obj_ref.New_zero(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
|
||||
tst_ReadCsvStr("|", "");
|
||||
tst_ReadCsvStr_err("a");
|
||||
|
||||
tst_ReadCsvStr("'a'|" , "a");
|
||||
tst_ReadCsvStr("'a''b'|" , "a'b");
|
||||
tst_ReadCsvStr("'a|b'|" , "a|b");
|
||||
tst_ReadCsvStr("''|", "");
|
||||
tst_ReadCsvStr_err("''");
|
||||
tst_ReadCsvStr_err("'a'b'");
|
||||
tst_ReadCsvStr_err("'a");
|
||||
tst_ReadCsvStr_err("'a|");
|
||||
tst_ReadCsvStr_err("'a'");
|
||||
}
|
||||
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
|
||||
tst_XtoIntBy4Bytes(32, (byte)32); // space
|
||||
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // ∃
|
||||
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
|
||||
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
|
||||
}
|
||||
@Test public void XtoInt() {
|
||||
tst_XtoInt("1", 1);
|
||||
tst_XtoInt("123", 123);
|
||||
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("-1", Int_.Min_value, -1);
|
||||
tst_XtoInt("-123", Int_.Min_value, -123);
|
||||
tst_XtoInt("123-1", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("+123", Int_.Min_value, 123);
|
||||
tst_XtoInt("", -1);
|
||||
}
|
||||
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
|
||||
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.To_int_or(Bry_.new_u8(val), or));}
|
||||
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.To_int_by_a7(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.new_by_int(expd), "XbyInt");}
|
||||
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New_zero() , expd);}
|
||||
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New(bgn), expd);}
|
||||
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
|
||||
int bgn = bgnRef.Val();
|
||||
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
|
||||
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
|
||||
Tfds.Eq(expd, actl, "rv");
|
||||
if (rawHasQuotes) {
|
||||
int quoteAdj = String_.Count(actl, "'");
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
|
||||
}
|
||||
else
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
|
||||
}
|
||||
void tst_ReadCsvStr_err(String raw) {
|
||||
try {Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), Int_obj_ref.New_zero(), (byte)'|');}
|
||||
catch (Exception e) {Err_.Noop(e); return;}
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
@Test public void ReadCsvDte() {
|
||||
tst_ReadCsvDte("20110801 221435.987");
|
||||
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void ReadCsvInt() {
|
||||
tst_ReadCsvInt("1234567890");
|
||||
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.Parse(raw), Bry_.ReadCsvInt(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void Trim() {
|
||||
Trim_tst("a b c", 1, 4, "b");
|
||||
Trim_tst("a c", 1, 3, "");
|
||||
Trim_tst(" ", 0, 2, "");
|
||||
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Trim(Bry_.new_u8(raw), bgn, end)));}
|
||||
@Test public void Xto_int_lax() {
|
||||
tst_Xto_int_lax("12a", 12);
|
||||
tst_Xto_int_lax("1", 1);
|
||||
tst_Xto_int_lax("123", 123);
|
||||
tst_Xto_int_lax("a", 0);
|
||||
tst_Xto_int_lax("-1", -1);
|
||||
}
|
||||
private void tst_Xto_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__lax(Bry_.new_u8(val), 0, String_.Len(val), 0));}
|
||||
@Test public void To_int_or__trim_ws() {
|
||||
tst_Xto_int_trim("123 " , 123);
|
||||
tst_Xto_int_trim(" 123" , 123);
|
||||
tst_Xto_int_trim(" 123 " , 123);
|
||||
tst_Xto_int_trim(" 1 3 " , -1);
|
||||
}
|
||||
private void tst_Xto_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__trim_ws(Bry_.new_u8(val), 0, String_.Len(val), -1));}
|
||||
@Test public void Compare() {
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
|
||||
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_u8(lhs), lhs_bgn, lhs_end, Bry_.new_u8(rhs), rhs_bgn, rhs_end));}
|
||||
@Test public void Increment_last() {
|
||||
tst_IncrementLast(ary_(0), ary_(1));
|
||||
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
|
||||
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
|
||||
}
|
||||
byte[] ary_(int... ary) {
|
||||
byte[] rv = new byte[ary.length];
|
||||
for (int i = 0; i < ary.length; i++)
|
||||
rv[i] = Byte_.By_int(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
|
||||
@Test public void Replace_between() {
|
||||
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
|
||||
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
|
||||
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
|
||||
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_a7(Bry_.Replace_between(Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(end), Bry_.new_a7(repl))));}
|
||||
@Test public void Replace() {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
|
||||
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
|
||||
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
|
||||
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
|
||||
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
|
||||
}
|
||||
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
|
||||
Tfds.Eq(expd, String_.new_a7(Bry_.Replace(tmp_bfr, Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(repl))));
|
||||
}
|
||||
@Test public void Split_bry() {
|
||||
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
|
||||
Split_bry_tst("a|" , "|" , String_.Ary("a"));
|
||||
}
|
||||
void Split_bry_tst(String src, String dlm, String[] expd) {
|
||||
String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
}
|
||||
@Test public void Split_lines() {
|
||||
Tst_split_lines("a\nb" , "a", "b"); // basic
|
||||
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
|
||||
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
|
||||
Tst_split_lines("a\rb" , "a", "b"); // cr only
|
||||
}
|
||||
void Tst_split_lines(String src, String... expd) {
|
||||
Tfds.Eq_ary(expd, New_ary(Bry_split_.Split_lines(Bry_.new_a7(src))));
|
||||
}
|
||||
String[] New_ary(byte[][] lines) {
|
||||
int len = lines.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = String_.new_u8(lines[i]);
|
||||
return rv;
|
||||
}
|
||||
@Test public void Match_bwd_any() {
|
||||
Tst_match_bwd_any("abc", 2, 0, "c", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "b", false);
|
||||
Tst_match_bwd_any("abc", 2, 0, "bc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "abc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
|
||||
Tst_match_bwd_any("abc", 1, 0, "ab", true);
|
||||
}
|
||||
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
|
||||
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
|
||||
}
|
||||
@Test public void Trim_end() {
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.one
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many
|
||||
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@Test public void Mid_w_trim() {
|
||||
fxt.Test_Mid_w_trim("abc", "abc"); // no ws
|
||||
fxt.Test_Mid_w_trim(" a b c ", "a b c"); // ws at bgn and end
|
||||
fxt.Test_Mid_w_trim("\r\n\t a\r\n\t b \r\n\t ", "a\r\n\t b"); // space at bgn and end
|
||||
fxt.Test_Mid_w_trim("", ""); // handle 0 bytes
|
||||
fxt.Test_Mid_w_trim(" ", ""); // handle all ws
|
||||
}
|
||||
@Test public void New_u8_nl_apos() {
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a"), "a");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b'c", "d"), "a\nb\"c\nd");
|
||||
}
|
||||
@Test public void Repeat_bry() {
|
||||
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
|
||||
}
|
||||
@Test public void Xcase__build__all() {
|
||||
fxt.Test__xcase__build__all(Bool_.N, "abc", "abc");
|
||||
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
|
||||
}
|
||||
}
|
||||
class Bry__fxt {
|
||||
private final Bry_bfr tmp = Bry_bfr_.New();
|
||||
public void Test_trim_end(String raw, byte trim, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_end(raw_bry, trim, raw_bry.length)));
|
||||
}
|
||||
public void Test_new_u8(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_u8(raw));}
|
||||
public void Test_new_a7(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_a7(raw));}
|
||||
public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));}
|
||||
public void Test_add(byte b, String s, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(b, Bry_.new_u8(s))));}
|
||||
public void Test_add_w_dlm(String dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(Bry_.new_u8(dlm), Bry_.Ary(itms))));}
|
||||
public void Test_add_w_dlm(byte dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(dlm, Bry_.Ary(itms))));}
|
||||
public void Test_Mid_w_trim(String src, String expd) {byte[] bry = Bry_.new_u8(src); Tfds.Eq(expd, String_.new_u8(Bry_.Mid_w_trim(bry, 0, bry.length)));}
|
||||
public void Test__new_u8_nl_apos(String[] ary, String expd) {
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(Bry_.New_u8_nl_apos(ary)));
|
||||
}
|
||||
public void Test__repeat_bry(String s, int count, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Repeat_bry(Bry_.new_u8(s), count));
|
||||
}
|
||||
public void Test__xcase__build__all(boolean upper, String src, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Xcase__build__all(tmp, upper, Bry_.new_u8(src)));
|
||||
}
|
||||
}
|
||||
package gplx;
|
||||
|
||||
import gplx.core.primitives.Int_obj_ref;
|
||||
import gplx.core.tests.Gftest;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Bry__tst {
|
||||
private final Bry__fxt fxt = new Bry__fxt();
|
||||
@Test public void new_ascii_() {
|
||||
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_a7("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_a7("" , Bry_.Empty); // none
|
||||
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ?
|
||||
}
|
||||
@Test public void new_u8() {
|
||||
fxt.Test_new_u8("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_u8("¢" , Bry_.New_by_ints(194, 162)); // bry_len=2; cent
|
||||
fxt.Test_new_u8("€" , Bry_.New_by_ints(226, 130, 172)); // bry_len=3; euro
|
||||
fxt.Test_new_u8("𤭢" , Bry_.New_by_ints(240, 164, 173, 162)); // bry_len=4; example from en.w:UTF-8
|
||||
}
|
||||
@Test public void Add__bry_plus_byte() {
|
||||
fxt.Test_add("a" , Byte_ascii.Pipe , "a|"); // basic
|
||||
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String
|
||||
}
|
||||
@Test public void Add__byte_plus_bry() {
|
||||
fxt.Test_add(Byte_ascii.Pipe , "a" , "|a"); // basic
|
||||
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String
|
||||
}
|
||||
@Test public void Add_w_dlm() {
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
|
||||
}
|
||||
@Test public void Add_w_dlm_bry() {
|
||||
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
|
||||
}
|
||||
@Test public void MidByPos() {
|
||||
tst_MidByPos("abcba", 0, 1, "a");
|
||||
tst_MidByPos("abcba", 0, 2, "ab");
|
||||
tst_MidByPos("abcba", 1, 4, "bcb");
|
||||
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Mid(Bry_.new_u8(src), bgn, end)));}
|
||||
@Test public void Replace_one() {
|
||||
tst_ReplaceOne("a" , "b" , "c" , "a");
|
||||
tst_ReplaceOne("b" , "b" , "c" , "c");
|
||||
tst_ReplaceOne("bb" , "b" , "c" , "cb");
|
||||
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
|
||||
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
|
||||
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Replace_one(Bry_.new_u8(src), Bry_.new_u8(find), Bry_.new_u8(repl))));}
|
||||
@Test public void XtoStrBytesByInt() {
|
||||
tst_XtoStrBytesByInt(0, 0);
|
||||
tst_XtoStrBytesByInt(9, 9);
|
||||
tst_XtoStrBytesByInt(10, 1, 0);
|
||||
tst_XtoStrBytesByInt(321, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(Int_.Max_value, 2,1,4,7,4,8,3,6,4,7);
|
||||
}
|
||||
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
|
||||
byte[] expd = new byte[expdAryAsInt.length];
|
||||
for (int i = 0; i < expd.length; i++) {
|
||||
int expdInt = expdAryAsInt[i];
|
||||
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Byte_ascii.To_a7_str(expdAryAsInt[i]);
|
||||
}
|
||||
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
|
||||
}
|
||||
@Test public void Has_at_end() {
|
||||
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
|
||||
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
|
||||
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
|
||||
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
|
||||
tst_HasAtEnd("abc", "bc", true); // y
|
||||
tst_HasAtEnd("abc", "bd", false); // n
|
||||
tst_HasAtEnd("a", "ab", false); // exceeds_len
|
||||
}
|
||||
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end));}
|
||||
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find)));}
|
||||
@Test public void Has_at_bgn() {
|
||||
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
|
||||
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
|
||||
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
|
||||
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
|
||||
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_bgn(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end), tst);}
|
||||
@Test public void Match() {
|
||||
tst_Match("abc", 0, "abc", true);
|
||||
tst_Match("abc", 2, "c", true);
|
||||
tst_Match("abc", 0, "cde", false);
|
||||
tst_Match("abc", 2, "abc", false); // bounds check
|
||||
tst_Match("abc", 0, "abcd", false);
|
||||
tst_Match("a" , 0, "", false);
|
||||
tst_Match("" , 0, "a", false);
|
||||
tst_Match("" , 0, "", true);
|
||||
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
|
||||
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_u8(src), srcPos, Bry_.new_u8(find)));}
|
||||
@Test public void ReadCsvStr() {
|
||||
tst_ReadCsvStr("a|" , "a");
|
||||
tst_ReadCsvStr("|a|", 1 , "a");
|
||||
Int_obj_ref bgn = Int_obj_ref.New_zero(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
|
||||
tst_ReadCsvStr("|", "");
|
||||
tst_ReadCsvStr_err("a");
|
||||
|
||||
tst_ReadCsvStr("'a'|" , "a");
|
||||
tst_ReadCsvStr("'a''b'|" , "a'b");
|
||||
tst_ReadCsvStr("'a|b'|" , "a|b");
|
||||
tst_ReadCsvStr("''|", "");
|
||||
tst_ReadCsvStr_err("''");
|
||||
tst_ReadCsvStr_err("'a'b'");
|
||||
tst_ReadCsvStr_err("'a");
|
||||
tst_ReadCsvStr_err("'a|");
|
||||
tst_ReadCsvStr_err("'a'");
|
||||
}
|
||||
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
|
||||
tst_XtoIntBy4Bytes(32, (byte)32); // space
|
||||
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // ∃
|
||||
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
|
||||
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
|
||||
}
|
||||
@Test public void XtoInt() {
|
||||
tst_XtoInt("1", 1);
|
||||
tst_XtoInt("123", 123);
|
||||
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("-1", Int_.Min_value, -1);
|
||||
tst_XtoInt("-123", Int_.Min_value, -123);
|
||||
tst_XtoInt("123-1", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("+123", Int_.Min_value, 123);
|
||||
tst_XtoInt("", -1);
|
||||
}
|
||||
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
|
||||
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.To_int_or(Bry_.new_u8(val), or));}
|
||||
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.To_int_by_a7(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.new_by_int(expd), "XbyInt");}
|
||||
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New_zero() , expd);}
|
||||
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New(bgn), expd);}
|
||||
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
|
||||
int bgn = bgnRef.Val();
|
||||
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
|
||||
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
|
||||
Tfds.Eq(expd, actl, "rv");
|
||||
if (rawHasQuotes) {
|
||||
int quoteAdj = String_.Count(actl, "'");
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
|
||||
}
|
||||
else
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
|
||||
}
|
||||
void tst_ReadCsvStr_err(String raw) {
|
||||
try {Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), Int_obj_ref.New_zero(), (byte)'|');}
|
||||
catch (Exception e) {Err_.Noop(e); return;}
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
@Test public void ReadCsvDte() {
|
||||
tst_ReadCsvDte("20110801 221435.987");
|
||||
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void ReadCsvInt() {
|
||||
tst_ReadCsvInt("1234567890");
|
||||
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.Parse(raw), Bry_.ReadCsvInt(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void Trim() {
|
||||
Trim_tst("a b c", 1, 4, "b");
|
||||
Trim_tst("a c", 1, 3, "");
|
||||
Trim_tst(" ", 0, 2, "");
|
||||
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Trim(Bry_.new_u8(raw), bgn, end)));}
|
||||
@Test public void Xto_int_lax() {
|
||||
tst_Xto_int_lax("12a", 12);
|
||||
tst_Xto_int_lax("1", 1);
|
||||
tst_Xto_int_lax("123", 123);
|
||||
tst_Xto_int_lax("a", 0);
|
||||
tst_Xto_int_lax("-1", -1);
|
||||
}
|
||||
private void tst_Xto_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__lax(Bry_.new_u8(val), 0, String_.Len(val), 0));}
|
||||
@Test public void To_int_or__trim_ws() {
|
||||
tst_Xto_int_trim("123 " , 123);
|
||||
tst_Xto_int_trim(" 123" , 123);
|
||||
tst_Xto_int_trim(" 123 " , 123);
|
||||
tst_Xto_int_trim(" 1 3 " , -1);
|
||||
}
|
||||
private void tst_Xto_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__trim_ws(Bry_.new_u8(val), 0, String_.Len(val), -1));}
|
||||
@Test public void Compare() {
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
|
||||
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_u8(lhs), lhs_bgn, lhs_end, Bry_.new_u8(rhs), rhs_bgn, rhs_end));}
|
||||
@Test public void Increment_last() {
|
||||
tst_IncrementLast(ary_(0), ary_(1));
|
||||
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
|
||||
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
|
||||
}
|
||||
byte[] ary_(int... ary) {
|
||||
byte[] rv = new byte[ary.length];
|
||||
for (int i = 0; i < ary.length; i++)
|
||||
rv[i] = Byte_.By_int(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
|
||||
@Test public void Replace_between() {
|
||||
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
|
||||
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
|
||||
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
|
||||
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_a7(Bry_.Replace_between(Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(end), Bry_.new_a7(repl))));}
|
||||
@Test public void Replace() {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
|
||||
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
|
||||
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
|
||||
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
|
||||
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
|
||||
}
|
||||
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
|
||||
Tfds.Eq(expd, String_.new_a7(Bry_.Replace(tmp_bfr, Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(repl))));
|
||||
}
|
||||
@Test public void Split_bry() {
|
||||
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
|
||||
Split_bry_tst("a|" , "|" , String_.Ary("a"));
|
||||
}
|
||||
void Split_bry_tst(String src, String dlm, String[] expd) {
|
||||
String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
}
|
||||
@Test public void Split_lines() {
|
||||
Tst_split_lines("a\nb" , "a", "b"); // basic
|
||||
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
|
||||
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
|
||||
Tst_split_lines("a\rb" , "a", "b"); // cr only
|
||||
}
|
||||
void Tst_split_lines(String src, String... expd) {
|
||||
Tfds.Eq_ary(expd, New_ary(Bry_split_.Split_lines(Bry_.new_a7(src))));
|
||||
}
|
||||
String[] New_ary(byte[][] lines) {
|
||||
int len = lines.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = String_.new_u8(lines[i]);
|
||||
return rv;
|
||||
}
|
||||
@Test public void Match_bwd_any() {
|
||||
Tst_match_bwd_any("abc", 2, 0, "c", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "b", false);
|
||||
Tst_match_bwd_any("abc", 2, 0, "bc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "abc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
|
||||
Tst_match_bwd_any("abc", 1, 0, "ab", true);
|
||||
}
|
||||
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
|
||||
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
|
||||
}
|
||||
@Test public void Trim_bgn() {
|
||||
fxt.Test_trim_bgn(" a" , Byte_ascii.Space, "a"); // trim.one
|
||||
fxt.Test_trim_bgn(" a" , Byte_ascii.Space, "a"); // trim.many
|
||||
fxt.Test_trim_bgn("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_bgn("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@Test public void Trim_end() {
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.one
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many
|
||||
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@Test public void Mid_w_trim() {
|
||||
fxt.Test_Mid_w_trim("abc", "abc"); // no ws
|
||||
fxt.Test_Mid_w_trim(" a b c ", "a b c"); // ws at bgn and end
|
||||
fxt.Test_Mid_w_trim("\r\n\t a\r\n\t b \r\n\t ", "a\r\n\t b"); // space at bgn and end
|
||||
fxt.Test_Mid_w_trim("", ""); // handle 0 bytes
|
||||
fxt.Test_Mid_w_trim(" ", ""); // handle all ws
|
||||
}
|
||||
@Test public void New_u8_nl_apos() {
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a"), "a");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b'c", "d"), "a\nb\"c\nd");
|
||||
}
|
||||
@Test public void Repeat_bry() {
|
||||
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
|
||||
}
|
||||
@Test public void Xcase__build__all() {
|
||||
fxt.Test__xcase__build__all(Bool_.N, "abc", "abc");
|
||||
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
|
||||
}
|
||||
}
|
||||
class Bry__fxt {
|
||||
private final Bry_bfr tmp = Bry_bfr_.New();
|
||||
public void Test_trim_end(String raw, byte trim, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_end(raw_bry, trim, raw_bry.length)));
|
||||
}
|
||||
public void Test_trim_bgn(String raw, byte trim, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_bgn(raw_bry, trim, 0)));
|
||||
}
|
||||
public void Test_new_u8(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_u8(raw));}
|
||||
public void Test_new_a7(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_a7(raw));}
|
||||
public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));}
|
||||
public void Test_add(byte b, String s, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(b, Bry_.new_u8(s))));}
|
||||
public void Test_add_w_dlm(String dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(Bry_.new_u8(dlm), Bry_.Ary(itms))));}
|
||||
public void Test_add_w_dlm(byte dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(dlm, Bry_.Ary(itms))));}
|
||||
public void Test_Mid_w_trim(String src, String expd) {byte[] bry = Bry_.new_u8(src); Tfds.Eq(expd, String_.new_u8(Bry_.Mid_w_trim(bry, 0, bry.length)));}
|
||||
public void Test__new_u8_nl_apos(String[] ary, String expd) {
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(Bry_.New_u8_nl_apos(ary)));
|
||||
}
|
||||
public void Test__repeat_bry(String s, int count, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Repeat_bry(Bry_.new_u8(s), count));
|
||||
}
|
||||
public void Test__xcase__build__all(boolean upper, String src, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Xcase__build__all(tmp, upper, Bry_.new_u8(src)));
|
||||
}
|
||||
}
|
||||
|
@ -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,78 +13,94 @@ 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.core.gfobjs; import gplx.*; import gplx.core.*;
|
||||
import gplx.langs.jsons.*;
|
||||
public class Gfobj_rdr__json {
|
||||
private final Json_parser parser = new Json_parser();
|
||||
public Gfobj_grp Load(Io_url url) {
|
||||
byte[] src = Io_mgr.Instance.LoadFilBryOrNull(url); if (src == null) return null;
|
||||
return this.Parse(src);
|
||||
}
|
||||
public Gfobj_grp Parse(byte[] src) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
if (jdoc.Root_grp().Tid() == Json_itm_.Tid__nde) {
|
||||
Gfobj_nde rv_nde = Gfobj_nde.New();
|
||||
Parse_nde((Json_nde)jdoc.Root_grp(), rv_nde);
|
||||
return rv_nde;
|
||||
}
|
||||
else {
|
||||
Gfobj_ary rv_ary = new Gfobj_ary(null);
|
||||
Parse_ary((Json_ary)jdoc.Root_grp(), rv_ary);
|
||||
return rv_ary;
|
||||
}
|
||||
}
|
||||
private void Parse_nde(Json_nde jnde, Gfobj_nde gnde) {
|
||||
int len = jnde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv kv = jnde.Get_at_as_kv(i);
|
||||
String key_str = kv.Key_as_str();
|
||||
Json_itm val = kv.Val();
|
||||
byte val_tid = val.Tid();
|
||||
switch (val_tid) {
|
||||
case Json_itm_.Tid__str: gnde.Add_str (key_str, ((Json_itm_str)val).Data_as_str()); break;
|
||||
case Json_itm_.Tid__bool: gnde.Add_bool (key_str, ((Json_itm_bool)val).Data_as_bool()); break;
|
||||
case Json_itm_.Tid__int: gnde.Add_int (key_str, ((Json_itm_int)val).Data_as_int()); break;
|
||||
case Json_itm_.Tid__long: gnde.Add_long (key_str, ((Json_itm_long)val).Data_as_long()); break;
|
||||
case Json_itm_.Tid__decimal: gnde.Add_double (key_str, ((Json_itm_decimal)val).Data_as_decimal().To_double()); break;
|
||||
case Json_itm_.Tid__null: gnde.Add_str (key_str, null); break;
|
||||
case Json_itm_.Tid__ary:
|
||||
Gfobj_ary sub_ary = new Gfobj_ary(null);
|
||||
gnde.Add_ary(key_str, sub_ary);
|
||||
Parse_ary(Json_ary.cast(val), sub_ary);
|
||||
break;
|
||||
case Json_itm_.Tid__nde:
|
||||
Gfobj_nde sub_gnde = Gfobj_nde.New();
|
||||
gnde.Add_nde(key_str, sub_gnde);
|
||||
Parse_nde(Json_nde.cast(val), sub_gnde);
|
||||
break;
|
||||
default: throw Err_.new_unhandled_default(val_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Parse_ary(Json_ary jry, Gfobj_ary gry) {
|
||||
int len = jry.Len();
|
||||
Object[] ary = new Object[len];
|
||||
gry.Ary_(ary);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm jsub = jry.Get_at(i);
|
||||
switch (jsub.Tid()) {
|
||||
case Json_itm_.Tid__ary: {
|
||||
Gfobj_ary sub_ary = new Gfobj_ary(null);
|
||||
Parse_ary(Json_ary.cast(jsub), sub_ary);
|
||||
ary[i] = sub_ary;
|
||||
break;
|
||||
}
|
||||
case Json_itm_.Tid__nde: {
|
||||
Gfobj_nde sub_ary = Gfobj_nde.New();
|
||||
Parse_nde(Json_nde.cast(jsub), sub_ary);
|
||||
ary[i] = sub_ary;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ary[i] = jsub.Data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package gplx.core.gfobjs;
|
||||
|
||||
import gplx.Err_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.Io_url;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_itm_;
|
||||
import gplx.langs.jsons.Json_itm_bool;
|
||||
import gplx.langs.jsons.Json_itm_decimal;
|
||||
import gplx.langs.jsons.Json_itm_int;
|
||||
import gplx.langs.jsons.Json_itm_long;
|
||||
import gplx.langs.jsons.Json_itm_str;
|
||||
import gplx.langs.jsons.Json_kv;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.jsons.Json_parser;
|
||||
|
||||
public class Gfobj_rdr__json {
|
||||
private final Json_parser parser = new Json_parser();
|
||||
public Gfobj_grp Load(Io_url url) {
|
||||
byte[] src = Io_mgr.Instance.LoadFilBryOrNull(url); if (src == null) return null;
|
||||
return this.Parse(src);
|
||||
}
|
||||
public Gfobj_grp Parse(byte[] src) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
if (jdoc.Root_grp().Tid() == Json_itm_.Tid__nde) {
|
||||
Gfobj_nde rv_nde = Gfobj_nde.New();
|
||||
Parse_nde((Json_nde)jdoc.Root_grp(), rv_nde);
|
||||
return rv_nde;
|
||||
}
|
||||
else {
|
||||
Gfobj_ary rv_ary = new Gfobj_ary(null);
|
||||
Parse_ary((Json_ary)jdoc.Root_grp(), rv_ary);
|
||||
return rv_ary;
|
||||
}
|
||||
}
|
||||
private void Parse_nde(Json_nde jnde, Gfobj_nde gnde) {
|
||||
int len = jnde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv kv = jnde.Get_at_as_kv(i);
|
||||
String key_str = kv.Key_as_str();
|
||||
Json_itm val = kv.Val();
|
||||
byte val_tid = val.Tid();
|
||||
switch (val_tid) {
|
||||
case Json_itm_.Tid__str: gnde.Add_str (key_str, ((Json_itm_str)val).Data_as_str()); break;
|
||||
case Json_itm_.Tid__bool: gnde.Add_bool (key_str, ((Json_itm_bool)val).Data_as_bool()); break;
|
||||
case Json_itm_.Tid__int: gnde.Add_int (key_str, ((Json_itm_int)val).Data_as_int()); break;
|
||||
case Json_itm_.Tid__long: gnde.Add_long (key_str, ((Json_itm_long)val).Data_as_long()); break;
|
||||
case Json_itm_.Tid__decimal: gnde.Add_double (key_str, ((Json_itm_decimal)val).Data_as_decimal().To_double()); break;
|
||||
case Json_itm_.Tid__null: gnde.Add_str (key_str, null); break;
|
||||
case Json_itm_.Tid__ary:
|
||||
Gfobj_ary sub_ary = new Gfobj_ary(null);
|
||||
gnde.Add_ary(key_str, sub_ary);
|
||||
Parse_ary(Json_ary.cast(val), sub_ary);
|
||||
break;
|
||||
case Json_itm_.Tid__nde:
|
||||
Gfobj_nde sub_gnde = Gfobj_nde.New();
|
||||
gnde.Add_nde(key_str, sub_gnde);
|
||||
Parse_nde(Json_nde.Cast(val), sub_gnde);
|
||||
break;
|
||||
default: throw Err_.new_unhandled_default(val_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Parse_ary(Json_ary jry, Gfobj_ary gry) {
|
||||
int len = jry.Len();
|
||||
Object[] ary = new Object[len];
|
||||
gry.Ary_(ary);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm jsub = jry.Get_at(i);
|
||||
switch (jsub.Tid()) {
|
||||
case Json_itm_.Tid__ary: {
|
||||
Gfobj_ary sub_ary = new Gfobj_ary(null);
|
||||
Parse_ary(Json_ary.cast(jsub), sub_ary);
|
||||
ary[i] = sub_ary;
|
||||
break;
|
||||
}
|
||||
case Json_itm_.Tid__nde: {
|
||||
Gfobj_nde sub_ary = Gfobj_nde.New();
|
||||
Parse_nde(Json_nde.Cast(jsub), sub_ary);
|
||||
ary[i] = sub_ary;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ary[i] = jsub.Data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
400_xowa/src/gplx/langs/jsons/JsonDocBldr.java
Normal file
69
400_xowa/src/gplx/langs/jsons/JsonDocBldr.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
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.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.String_;
|
||||
|
||||
public class JsonDocBldr {
|
||||
private final List_adp stack = List_adp_.New();
|
||||
private final Json_doc doc = new Json_doc();
|
||||
private Json_grp root;
|
||||
private Json_grp cur;
|
||||
JsonDocBldr() {}
|
||||
public JsonDocBldr Clear(boolean isRootNode) {
|
||||
this.root = isRootNode ? Json_nde.NewByDoc(doc, 0) : Json_ary.NewByDoc(doc, 0, 0);
|
||||
doc.Ctor(Bry_.Empty, root);
|
||||
this.cur = root;
|
||||
stack.Clear();
|
||||
return this;
|
||||
}
|
||||
public JsonDocBldr NdeBgn(String key) {
|
||||
Json_nde nde = Json_nde.NewByDoc(doc, 1);
|
||||
if (cur.Tid() == Json_itm_.Tid__nde) {
|
||||
Json_kv kv = new Json_kv(Json_itm_str.NewByVal(key), nde);
|
||||
cur.Add(kv);
|
||||
}
|
||||
else {
|
||||
cur.Add(nde);
|
||||
}
|
||||
stack.Add(cur);
|
||||
cur = nde;
|
||||
return this;
|
||||
}
|
||||
public JsonDocBldr NdeEnd() {
|
||||
this.cur = (Json_grp)List_adp_.Pop_last(stack);
|
||||
return this;
|
||||
}
|
||||
public JsonDocBldr KvBool(String key, boolean val) {return Kv(key, Json_itm_bool.Get(val));}
|
||||
public JsonDocBldr KvInt(String key, int val) {return Kv(key, Json_itm_int.NewByVal(val));}
|
||||
public JsonDocBldr KvStr(String key, byte[] val) {return Kv(key, Json_itm_str.NewByVal(String_.new_u8(val)));}
|
||||
public JsonDocBldr KvStr(String key, String val) {return Kv(key, Json_itm_str.NewByVal(val));}
|
||||
private JsonDocBldr Kv(String key, Json_itm val) {
|
||||
Json_kv rv = new Json_kv(Json_itm_str.NewByVal(key), val);
|
||||
cur.Add(rv);
|
||||
return this;
|
||||
}
|
||||
public Json_doc ToDoc() {
|
||||
return doc;
|
||||
}
|
||||
public Json_nde ToRootNde() {
|
||||
return doc.Root_nde();
|
||||
}
|
||||
public static JsonDocBldr NewRootNde() {return new JsonDocBldr().Clear(true);}
|
||||
}
|
@ -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,66 +13,75 @@ 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_ary extends Json_itm_base implements Json_grp {
|
||||
public Json_ary(int src_bgn, int src_end) {this.Ctor(src_bgn, src_end);}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__ary;}
|
||||
public void Src_end_(int v) {this.src_end = v;}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
public int Len() {return subs_len;} private int subs_len = 0, subs_max = 0;
|
||||
public Json_nde Get_at_as_nde(int i) {
|
||||
Json_itm rv = subs[i]; if (rv.Tid() != Json_itm_.Tid__nde) throw Err_.new_("json", "itm is not nde", "type", rv.Tid(), "i", i);
|
||||
return (Json_nde)rv;
|
||||
}
|
||||
public Json_itm Get_at(int i) {return subs[i];}
|
||||
public Json_nde Get_as_nde(int i) {return Json_nde.cast(subs[i]);}
|
||||
public Json_ary Add_many(Json_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public void Add(Json_itm itm) {
|
||||
int new_len = subs_len + 1;
|
||||
if (new_len > subs_max) { // ary too small >>> expand
|
||||
subs_max = new_len * 2;
|
||||
Json_itm[] new_subs = new Json_itm[subs_max];
|
||||
Array_.Copy_to(subs, 0, new_subs, 0, subs_len);
|
||||
subs = new_subs;
|
||||
}
|
||||
subs[subs_len] = itm;
|
||||
subs_len = new_len;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (subs_len == 0) { // empty grp; print on one line (rather than printing across 3)
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Brack_end);
|
||||
return;
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Space);
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
if (i != 0) {
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
}
|
||||
subs[i].Print_as_json(bfr, depth + 1);
|
||||
}
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Brack_end).Add_byte_nl();
|
||||
}
|
||||
public byte[][] Xto_bry_ary() {
|
||||
if (subs_len == 0) return Bry_.Ary_empty;
|
||||
byte[][] rv = new byte[subs_len][];
|
||||
for (int i = 0; i < subs_len; ++i)
|
||||
rv[i] = subs[i].Data_bry();
|
||||
return rv;
|
||||
}
|
||||
private Json_itm[] subs = Json_itm_.Ary_empty;
|
||||
public static Json_ary cast_or_null(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__ary ? null : (Json_ary)v;}
|
||||
public static Json_ary cast(Json_itm v) {
|
||||
if (v == null || v.Tid() != Json_itm_.Tid__ary) throw Err_.new_("json", "itm is not array");
|
||||
return (Json_ary)v;
|
||||
}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Array_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Err_;
|
||||
|
||||
public class Json_ary extends Json_itm_base implements Json_grp {
|
||||
private Json_ary() {}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__ary;}
|
||||
public void Src_end_(int v) {}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
public int Len() {return subs_len;} private int subs_len = 0, subs_max = 0;
|
||||
public Json_nde Get_at_as_nde(int i) {
|
||||
Json_itm rv = subs[i]; if (rv.Tid() != Json_itm_.Tid__nde) throw Err_.new_("json", "itm is not nde", "type", rv.Tid(), "i", i);
|
||||
return (Json_nde)rv;
|
||||
}
|
||||
public Json_itm Get_at(int i) {return subs[i];}
|
||||
public Json_nde Get_as_nde(int i) {return Json_nde.Cast(subs[i]);}
|
||||
public Json_ary Add_many(Json_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public void Add(Json_itm itm) {
|
||||
int new_len = subs_len + 1;
|
||||
if (new_len > subs_max) { // ary too small >>> expand
|
||||
subs_max = new_len * 2;
|
||||
Json_itm[] new_subs = new Json_itm[subs_max];
|
||||
Array_.Copy_to(subs, 0, new_subs, 0, subs_len);
|
||||
subs = new_subs;
|
||||
}
|
||||
subs[subs_len] = itm;
|
||||
subs_len = new_len;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (subs_len == 0) { // empty grp; print on one line (rather than printing across 3)
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Brack_end);
|
||||
return;
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Space);
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
if (i != 0) {
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
}
|
||||
subs[i].Print_as_json(bfr, depth + 1);
|
||||
}
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Brack_end).Add_byte_nl();
|
||||
}
|
||||
public byte[][] Xto_bry_ary() {
|
||||
if (subs_len == 0) return Bry_.Ary_empty;
|
||||
byte[][] rv = new byte[subs_len][];
|
||||
for (int i = 0; i < subs_len; ++i)
|
||||
rv[i] = subs[i].Data_bry();
|
||||
return rv;
|
||||
}
|
||||
private Json_itm[] subs = Json_itm_.Ary_empty;
|
||||
public static Json_ary cast_or_null(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__ary ? null : (Json_ary)v;}
|
||||
public static Json_ary cast(Json_itm v) {
|
||||
if (v == null || v.Tid() != Json_itm_.Tid__ary) throw Err_.new_("json", "itm is not array");
|
||||
return (Json_ary)v;
|
||||
}
|
||||
public static Json_ary NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_ary();}
|
||||
public static Json_ary NewByVal() {return new Json_ary();}
|
||||
}
|
||||
|
@ -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,75 +13,82 @@ 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.primitives.*;
|
||||
public class Json_doc {
|
||||
private final byte[][] tmp_qry_bry = new byte[1][];
|
||||
public void Ctor(byte[] src, Json_grp new_root) {
|
||||
this.src = src;
|
||||
this.root_grp = new_root;
|
||||
switch (root_grp.Tid()) {
|
||||
case Json_itm_.Tid__nde: this.root_ary = null; this.root_nde = (Json_nde)root_grp; break;
|
||||
case Json_itm_.Tid__ary: this.root_nde = null; this.root_ary = (Json_ary)root_grp; break;
|
||||
default: throw Err_.new_unhandled(root_grp.Tid());
|
||||
}
|
||||
}
|
||||
public byte[] Src() {return src;} private byte[] src;
|
||||
public Json_grp Root_grp() {return root_grp;} private Json_grp root_grp;
|
||||
public Json_nde Root_nde() {return root_nde;} private Json_nde root_nde;
|
||||
public Json_ary Root_ary() {return root_ary;} private Json_ary root_ary;
|
||||
public Bry_bfr Bfr() {return bfr;} private final Bry_bfr bfr = Bry_bfr_.New();
|
||||
public Gfo_number_parser Utl_num_parser() {return utl_num_parser;} private final Gfo_number_parser utl_num_parser = new Gfo_number_parser();
|
||||
public byte[] Tmp_u8_bry() {return tmp_u8_bry;} private final byte[] tmp_u8_bry = new byte[6]; // tmp bry[] for decoding sequences like \u0008
|
||||
public byte[] Get_val_as_bry_or(byte[] qry_bry, byte[] or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_bry_or(tmp_qry_bry, or);}
|
||||
public byte[] Get_val_as_bry_or(byte[][] qry_bry, byte[] or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : nde.Data_bry();
|
||||
}
|
||||
public String Get_val_as_str_or(byte[] qry_bry, String or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_str_or(tmp_qry_bry, or);}
|
||||
public String Get_val_as_str_or(byte[][] qry_bry, String or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : (String)nde.Data();
|
||||
}
|
||||
public int Get_val_as_int_or(byte[] qry_bry, int or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_int_or(tmp_qry_bry, or);}
|
||||
public int Get_val_as_int_or(byte[][] qry_bry, int or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__int ? or : Bry_.To_int(nde.Data_bry());
|
||||
}
|
||||
public Json_grp Get_grp(byte[] qry_bry) {
|
||||
tmp_qry_bry[0] = qry_bry;
|
||||
Json_itm rv = Find_nde(root_nde, tmp_qry_bry, 0, 0); if (rv == null) return null;
|
||||
return (Json_grp)rv;
|
||||
}
|
||||
public Json_grp Get_grp_many(String... qry_ary) {return Get_grp_many(Bry_.Ary(qry_ary));}
|
||||
public Json_grp Get_grp_many(byte[]... qry_bry) {
|
||||
Json_itm rv = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0); if (rv == null) return null;
|
||||
return (Json_grp)rv;
|
||||
}
|
||||
public Json_itm Find_nde(byte[] key) {
|
||||
tmp_qry_bry[0] = key;
|
||||
return Find_nde(root_nde, tmp_qry_bry, 0, 0);
|
||||
}
|
||||
private Json_itm Find_nde(Json_nde owner, byte[][] paths, int paths_last, int paths_idx) {
|
||||
byte[] path = paths[paths_idx];
|
||||
int subs_len = owner.Len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Json_kv itm = Json_kv.cast(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes
|
||||
if (!itm.Key_eq(path)) continue;
|
||||
if (paths_idx == paths_last) return itm.Val();
|
||||
Json_nde sub_nde = Json_nde.cast(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit
|
||||
return Find_nde(sub_nde, paths, paths_last, paths_idx + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static String Make_str_by_apos(String... ary) {return String_.Replace(String_.Concat_lines_nl_skip_last(ary), "'", "\"");}
|
||||
public static String[] Make_str_ary_by_apos(String... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
if (String_.Has(itm, "'"))
|
||||
ary[i] = String_.Replace(itm, "'", "\"");
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Err_;
|
||||
import gplx.String_;
|
||||
import gplx.core.primitives.Gfo_number_parser;
|
||||
|
||||
public class Json_doc {
|
||||
private final byte[][] tmp_qry_bry = new byte[1][];
|
||||
public void Ctor(byte[] src, Json_grp new_root) {
|
||||
this.src = src;
|
||||
this.root_grp = new_root;
|
||||
switch (root_grp.Tid()) {
|
||||
case Json_itm_.Tid__nde: this.root_ary = null; this.root_nde = (Json_nde)root_grp; break;
|
||||
case Json_itm_.Tid__ary: this.root_nde = null; this.root_ary = (Json_ary)root_grp; break;
|
||||
default: throw Err_.new_unhandled(root_grp.Tid());
|
||||
}
|
||||
}
|
||||
public byte[] Src() {return src;} private byte[] src;
|
||||
public Json_grp Root_grp() {return root_grp;} private Json_grp root_grp;
|
||||
public Json_nde Root_nde() {return root_nde;} private Json_nde root_nde;
|
||||
public Json_ary Root_ary() {return root_ary;} private Json_ary root_ary;
|
||||
public Bry_bfr Bfr() {return bfr;} private final Bry_bfr bfr = Bry_bfr_.New();
|
||||
public Gfo_number_parser Utl_num_parser() {return utl_num_parser;} private final Gfo_number_parser utl_num_parser = new Gfo_number_parser();
|
||||
public byte[] Tmp_u8_bry() {return tmp_u8_bry;} private final byte[] tmp_u8_bry = new byte[6]; // tmp bry[] for decoding sequences like \u0008
|
||||
public byte[] Get_val_as_bry_or(byte[] qry_bry, byte[] or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_bry_or(tmp_qry_bry, or);}
|
||||
public byte[] Get_val_as_bry_or(byte[][] qry_bry, byte[] or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : nde.Data_bry();
|
||||
}
|
||||
public String Get_val_as_str_or(byte[] qry_bry, String or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_str_or(tmp_qry_bry, or);}
|
||||
public String Get_val_as_str_or(byte[][] qry_bry, String or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : (String)nde.Data();
|
||||
}
|
||||
public int Get_val_as_int_or(byte[] qry_bry, int or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_int_or(tmp_qry_bry, or);}
|
||||
public int Get_val_as_int_or(byte[][] qry_bry, int or) {
|
||||
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
|
||||
return nde == null || nde.Tid() != Json_itm_.Tid__int ? or : Bry_.To_int(nde.Data_bry());
|
||||
}
|
||||
public Json_grp Get_grp(byte[] qry_bry) {
|
||||
tmp_qry_bry[0] = qry_bry;
|
||||
Json_itm rv = Find_nde(root_nde, tmp_qry_bry, 0, 0); if (rv == null) return null;
|
||||
return (Json_grp)rv;
|
||||
}
|
||||
public Json_grp Get_grp_many(String... qry_ary) {return Get_grp_many(Bry_.Ary(qry_ary));}
|
||||
public Json_grp Get_grp_many(byte[]... qry_bry) {
|
||||
Json_itm rv = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0); if (rv == null) return null;
|
||||
return (Json_grp)rv;
|
||||
}
|
||||
public Json_itm Find_nde(byte[] key) {
|
||||
tmp_qry_bry[0] = key;
|
||||
return Find_nde(root_nde, tmp_qry_bry, 0, 0);
|
||||
}
|
||||
private Json_itm Find_nde(Json_nde owner, byte[][] paths, int paths_last, int paths_idx) {
|
||||
byte[] path = paths[paths_idx];
|
||||
int subs_len = owner.Len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Json_kv itm = Json_kv.Cast(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes
|
||||
if (!itm.Key_eq(path)) continue;
|
||||
if (paths_idx == paths_last) return itm.Val();
|
||||
Json_nde sub_nde = Json_nde.Cast(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit
|
||||
return Find_nde(sub_nde, paths, paths_last, paths_idx + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static String Make_str_by_apos(String... ary) {return String_.Replace(String_.Concat_lines_nl_skip_last(ary), "'", "\"");}
|
||||
public static String[] Make_str_ary_by_apos(String... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
if (String_.Has(itm, "'"))
|
||||
ary[i] = String_.Replace(itm, "'", "\"");
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
}
|
||||
|
@ -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,140 +13,155 @@ 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.*;
|
||||
public class Json_doc_wtr {
|
||||
private int indent = -2;
|
||||
private Bry_bfr bfr = Bry_bfr_.Reset(255);
|
||||
public void Opt_unicode_y_() {opt_unicode = true;} private boolean opt_unicode;
|
||||
public Json_doc_wtr Indent() {return Indent(indent);}
|
||||
private Json_doc_wtr Indent(int v) {if (v > 0) bfr.Add_byte_repeat(Byte_ascii.Space, v); return this;}
|
||||
public Json_doc_wtr Indent_add() {indent += 2; return this;}
|
||||
public Json_doc_wtr Indent_del() {indent -= 2; return this;}
|
||||
public Json_doc_wtr Nde_bgn() {Indent_add(); Indent(); bfr.Add_byte(Byte_ascii.Curly_bgn).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Nde_end() { Indent(); bfr.Add_byte(Byte_ascii.Curly_end).Add_byte_nl(); Indent_del(); return this;}
|
||||
public Json_doc_wtr Ary_bgn() {Indent_add(); Indent(); bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Ary_end() { Indent(); bfr.Add_byte(Byte_ascii.Brack_end).Add_byte_nl(); Indent_del(); return this;}
|
||||
public Json_doc_wtr New_line() {bfr.Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Str(byte[] v) {
|
||||
if (v == null)
|
||||
bfr.Add(Object_.Bry__null);
|
||||
else {
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
if (opt_unicode) {
|
||||
Ustring ustr = Ustring_.New_codepoints(String_.new_u8(v));
|
||||
int ustr_len = ustr.Len_in_data();
|
||||
for (int i = 0; i < ustr_len; i++) {
|
||||
int cp = ustr.Get_data(i);
|
||||
Write_str_codepoint(bfr, cp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bfr.Add_bry_escape(Byte_ascii.Quote, Escaped__quote, v, 0, v.length);
|
||||
}
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private void Write_str_codepoint(Bry_bfr bfr, int val) {
|
||||
switch (val) { // REF: https://www.json.org/
|
||||
case Byte_ascii.Quote:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Quote);
|
||||
break;
|
||||
case Byte_ascii.Backslash:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Backslash);
|
||||
break;
|
||||
case Byte_ascii.Backfeed:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_b);
|
||||
break;
|
||||
case Byte_ascii.Formfeed:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_f);
|
||||
break;
|
||||
case Byte_ascii.Nl:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_n);
|
||||
break;
|
||||
case Byte_ascii.Cr:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_r);
|
||||
break;
|
||||
case Byte_ascii.Tab:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_t);
|
||||
break;
|
||||
default:
|
||||
if ( val < Byte_ascii.Space // control characters
|
||||
|| val == 160 // nbsp
|
||||
|| val == 8206 // left to right
|
||||
|| val == 8207 // right to left
|
||||
) {
|
||||
// convert to \u1234
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_u).Add_str_a7(Hex_utl_.To_str(val, 4));
|
||||
}
|
||||
else {
|
||||
bfr.Add_u8_int(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
public Json_doc_wtr Int(int v) {bfr.Add_int_variable(v); return this;}
|
||||
public Json_doc_wtr Double(double v) {bfr.Add_double(v); return this;}
|
||||
public Json_doc_wtr Comma() {Indent(); bfr.Add_byte(Byte_ascii.Comma).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Kv_ary_empty(boolean comma, byte[] key) {
|
||||
Key_internal(comma, key);
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Brack_end);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv(boolean comma, byte[] key, byte[] val) {
|
||||
Key_internal(comma, key);
|
||||
Str(val);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv_double(boolean comma, byte[] key, double v) {
|
||||
Key_internal(comma, key);
|
||||
Double(v);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
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 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);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Val(boolean comma, int v) {
|
||||
Val_internal(comma);
|
||||
Int(v);
|
||||
New_line();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Val(boolean comma, byte[] v) {
|
||||
Val_internal(comma);
|
||||
Str(v);
|
||||
New_line();
|
||||
return this;
|
||||
}
|
||||
Json_doc_wtr Val_internal(boolean comma) {
|
||||
Indent();
|
||||
bfr.Add_byte(comma ? Byte_ascii.Comma : Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Space);
|
||||
return this;
|
||||
}
|
||||
Json_doc_wtr Key_internal(boolean comma, byte[] key) {
|
||||
Indent();
|
||||
bfr.Add_byte(comma ? Byte_ascii.Comma : Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Space);
|
||||
Str(key);
|
||||
bfr.Add_byte(Byte_ascii.Colon);
|
||||
return this;
|
||||
}
|
||||
public byte[] Bld() {return bfr.To_bry_and_clear();}
|
||||
public String Bld_as_str() {return bfr.To_str_and_clear();}
|
||||
private static final byte[] Escaped__quote = Bry_.new_a7("\\\"");
|
||||
}
|
||||
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);
|
||||
public void Opt_unicode_y_() {opt_unicode = true;} private boolean opt_unicode;
|
||||
public Json_doc_wtr Indent() {return Indent(indent);}
|
||||
private Json_doc_wtr Indent(int v) {if (v > 0) bfr.Add_byte_repeat(Byte_ascii.Space, v); return this;}
|
||||
public Json_doc_wtr Indent_add() {indent += 2; return this;}
|
||||
public Json_doc_wtr Indent_del() {indent -= 2; return this;}
|
||||
public Json_doc_wtr Nde_bgn() {Indent_add(); Indent(); bfr.Add_byte(Byte_ascii.Curly_bgn).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Nde_end() { Indent(); bfr.Add_byte(Byte_ascii.Curly_end).Add_byte_nl(); Indent_del(); return this;}
|
||||
public Json_doc_wtr Ary_bgn() {Indent_add(); Indent(); bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Ary_end() { Indent(); bfr.Add_byte(Byte_ascii.Brack_end).Add_byte_nl(); Indent_del(); return this;}
|
||||
public Json_doc_wtr New_line() {bfr.Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Str(byte[] v) {
|
||||
if (v == null)
|
||||
bfr.Add(Object_.Bry__null);
|
||||
else {
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
if (opt_unicode) {
|
||||
Ustring ustr = Ustring_.New_codepoints(String_.new_u8(v));
|
||||
int ustr_len = ustr.Len_in_data();
|
||||
for (int i = 0; i < ustr_len; i++) {
|
||||
int cp = ustr.Get_data(i);
|
||||
Write_str_codepoint(bfr, cp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bfr.Add_bry_escape(Byte_ascii.Quote, Escaped__quote, v, 0, v.length);
|
||||
}
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private void Write_str_codepoint(Bry_bfr bfr, int val) {
|
||||
switch (val) { // REF: https://www.json.org/
|
||||
case Byte_ascii.Quote:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Quote);
|
||||
break;
|
||||
case Byte_ascii.Backslash:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Backslash);
|
||||
break;
|
||||
case Byte_ascii.Backfeed:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_b);
|
||||
break;
|
||||
case Byte_ascii.Formfeed:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_f);
|
||||
break;
|
||||
case Byte_ascii.Nl:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_n);
|
||||
break;
|
||||
case Byte_ascii.Cr:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_r);
|
||||
break;
|
||||
case Byte_ascii.Tab:
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_t);
|
||||
break;
|
||||
default:
|
||||
if ( val < Byte_ascii.Space // control characters
|
||||
|| val == 160 // nbsp
|
||||
|| val == 8206 // left to right
|
||||
|| val == 8207 // right to left
|
||||
) {
|
||||
// convert to \u1234
|
||||
bfr.Add_byte_backslash().Add_byte(Byte_ascii.Ltr_u).Add_str_a7(Hex_utl_.To_str(val, 4));
|
||||
}
|
||||
else {
|
||||
bfr.Add_u8_int(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
public Json_doc_wtr Int(int v) {bfr.Add_int_variable(v); return this;}
|
||||
public Json_doc_wtr Double(double v) {bfr.Add_double(v); return this;}
|
||||
public Json_doc_wtr Comma() {Indent(); bfr.Add_byte(Byte_ascii.Comma).Add_byte_nl(); return this;}
|
||||
public Json_doc_wtr Kv_ary_empty(boolean comma, byte[] key) {
|
||||
Key_internal(comma, key);
|
||||
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Brack_end);
|
||||
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);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Kv_double(boolean comma, byte[] key, double v) {
|
||||
Key_internal(comma, key);
|
||||
Double(v);
|
||||
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);
|
||||
bfr.Add_byte_nl();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Val(boolean comma, int v) {
|
||||
Val_internal(comma);
|
||||
Int(v);
|
||||
New_line();
|
||||
return this;
|
||||
}
|
||||
public Json_doc_wtr Val(boolean comma, byte[] v) {
|
||||
Val_internal(comma);
|
||||
Str(v);
|
||||
New_line();
|
||||
return this;
|
||||
}
|
||||
Json_doc_wtr Val_internal(boolean comma) {
|
||||
Indent();
|
||||
bfr.Add_byte(comma ? Byte_ascii.Comma : Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Space);
|
||||
return this;
|
||||
}
|
||||
Json_doc_wtr Key_internal(boolean comma, byte[] key) {
|
||||
Indent();
|
||||
bfr.Add_byte(comma ? Byte_ascii.Comma : Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Space);
|
||||
Str(key);
|
||||
bfr.Add_byte(Byte_ascii.Colon);
|
||||
return this;
|
||||
}
|
||||
public byte[] Bld() {return bfr.To_bry_and_clear();}
|
||||
public String Bld_as_str() {return bfr.To_str_and_clear();}
|
||||
private static final byte[] Escaped__quote = Bry_.new_a7("\\\"");
|
||||
}
|
||||
|
@ -1,28 +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_factory {
|
||||
public Json_itm Null() {return Json_itm_null.Null;}
|
||||
public Json_itm Bool_n() {return Json_itm_bool.Bool_n;}
|
||||
public Json_itm Bool_y() {return Json_itm_bool.Bool_y;}
|
||||
public Json_itm_int Int(Json_doc doc, int bgn, int end) {return new Json_itm_int(doc, bgn, end);}
|
||||
public Json_itm_long Long(Json_doc doc, int bgn, int end) {return new Json_itm_long(doc, bgn, end);}
|
||||
public Json_itm Decimal(Json_doc doc, int bgn, int end) {return new Json_itm_decimal(doc, bgn, end);}
|
||||
public Json_itm Str(Json_doc doc, int bgn, int end, boolean exact) {return new Json_itm_str(doc, bgn, end, exact);}
|
||||
public Json_kv Kv(Json_itm key, Json_itm val) {return new Json_kv(key, val);}
|
||||
public Json_ary Ary(int bgn, int end) {return new Json_ary(bgn, end);}
|
||||
public Json_nde Nde(Json_doc doc, int bgn) {return new Json_nde(doc, bgn);}
|
||||
}
|
@ -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,21 +13,23 @@ 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 interface Json_itm {
|
||||
byte Tid();
|
||||
int Src_bgn();
|
||||
int Src_end();
|
||||
Object Data();
|
||||
byte[] Data_bry();
|
||||
void Print_as_json(Bry_bfr bfr, int depth);
|
||||
boolean Data_eq(byte[] comp);
|
||||
}
|
||||
class Json_itm_null extends Json_itm_base {
|
||||
Json_itm_null() {this.Ctor(-1, -1);}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__null;}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Object_.Bry__null);}
|
||||
@Override public byte[] Data_bry() {return Object_.Bry__null;}
|
||||
public static final Json_itm_null Null = new Json_itm_null();
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Object_;
|
||||
|
||||
public interface Json_itm {
|
||||
byte Tid();
|
||||
Object Data();
|
||||
byte[] Data_bry();
|
||||
boolean Data_eq(byte[] comp);
|
||||
void Print_as_json(Bry_bfr bfr, int depth);
|
||||
}
|
||||
class Json_itm_null extends Json_itm_base {
|
||||
Json_itm_null() {}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__null;}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Object_.Bry__null);}
|
||||
@Override public byte[] Data_bry() {return Object_.Bry__null;}
|
||||
public static final Json_itm_null Null = new Json_itm_null();
|
||||
}
|
||||
|
@ -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,15 +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.*;
|
||||
public abstract class Json_itm_base implements Json_itm {
|
||||
public abstract byte Tid();
|
||||
public void Ctor(int src_bgn, int src_end) {this.src_bgn = src_bgn; this.src_end = src_end;}
|
||||
public int Src_bgn() {return src_bgn;} private int src_bgn;
|
||||
public int Src_end() {return src_end;} protected int src_end;
|
||||
public abstract Object Data();
|
||||
public abstract byte[] Data_bry();
|
||||
public String Print_as_json() {Bry_bfr bfr = Bry_bfr_.New(); Print_as_json(bfr, 0); return bfr.To_str_and_clear();}
|
||||
public abstract void Print_as_json(Bry_bfr bfr, int depth);
|
||||
@gplx.Virtual public boolean Data_eq(byte[] comp) {return false;}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
|
||||
public abstract class Json_itm_base implements Json_itm {
|
||||
public abstract byte Tid();
|
||||
public abstract Object Data();
|
||||
public abstract byte[] Data_bry();
|
||||
public String Print_as_json() {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
Print_as_json(bfr, 0);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
public abstract void Print_as_json(Bry_bfr bfr, int depth);
|
||||
@gplx.Virtual public boolean Data_eq(byte[] comp) {return false;}
|
||||
}
|
||||
|
@ -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,14 +13,22 @@ 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_itm_bool extends Json_itm_base {
|
||||
private boolean data;
|
||||
public Json_itm_bool(boolean data) {this.data = data; this.Ctor(-1, -1);}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__bool;}
|
||||
public boolean Data_as_bool() {return data;}
|
||||
@Override public Object Data() {return data;}
|
||||
@Override public byte[] Data_bry() {return data ? Json_itm_.Bry__true : Json_itm_.Bry__false;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Bry__true: Json_itm_.Bry__false);}
|
||||
public static final Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
|
||||
public class Json_itm_bool extends Json_itm_base {
|
||||
private boolean data;
|
||||
private Json_itm_bool(boolean data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override public byte Tid() {return Json_itm_.Tid__bool;}
|
||||
public boolean Data_as_bool() {return data;}
|
||||
@Override public Object Data() {return data;}
|
||||
@Override public byte[] Data_bry() {return data ? Json_itm_.Bry__true : Json_itm_.Bry__false;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Bry__true: Json_itm_.Bry__false);}
|
||||
|
||||
public static final Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
|
||||
public static final Json_itm_bool Get(boolean v) {return v ? Bool_y : Bool_n;}
|
||||
}
|
||||
|
@ -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,23 +13,54 @@ 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_itm_decimal extends Json_itm_base {
|
||||
private final Json_doc doc; private Decimal_adp data; private byte[] data_bry;
|
||||
public Json_itm_decimal(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__decimal;}
|
||||
@Override public Object Data() {return this.Data_as_decimal();}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end());
|
||||
return data_bry;
|
||||
}
|
||||
public Decimal_adp Data_as_decimal() {
|
||||
if (data == null) {
|
||||
String s = String_.new_a7(this.Data_bry());
|
||||
s = String_.Replace(s, "e", "E"); // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
|
||||
data = Decimal_adp_.parse(s);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Decimal_adp;
|
||||
import gplx.Decimal_adp_;
|
||||
import gplx.Double_;
|
||||
import gplx.String_;
|
||||
|
||||
public class Json_itm_decimal extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private final int src_bgn, src_end;
|
||||
private Decimal_adp data;
|
||||
private byte[] data_bry;
|
||||
|
||||
private Json_itm_decimal(Json_doc doc, int src_bgn, int src_end, Decimal_adp data) {
|
||||
this.doc = doc;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
this.data = data;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__decimal;}
|
||||
@Override public Object Data() {return this.Data_as_decimal();}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null) {
|
||||
data_bry = data == null
|
||||
? Bry_.Mid(doc.Src(), src_bgn, src_end)
|
||||
: Bry_.new_u8(Double_.To_str_loose(data.To_double()));
|
||||
}
|
||||
return data_bry;
|
||||
}
|
||||
public Decimal_adp Data_as_decimal() {
|
||||
if (data == null) {
|
||||
String s = String_.new_a7(this.Data_bry());
|
||||
s = String_.Replace(s, "e", "E"); // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
|
||||
data = Decimal_adp_.parse(s);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (doc == null) {
|
||||
bfr.Add_str_a7(Double_.To_str_loose(data.To_double()));
|
||||
}
|
||||
else {
|
||||
bfr.Add_mid(doc.Src(), src_bgn, src_end);
|
||||
}
|
||||
}
|
||||
|
||||
public static Json_itm_decimal NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_decimal(doc, src_bgn, src_end, null);}
|
||||
public static Json_itm_decimal NewByVal(Decimal_adp val) {return new Json_itm_decimal(null, -1, -1, val);}
|
||||
}
|
||||
|
@ -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,21 +13,52 @@ 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_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;}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__int;}
|
||||
public int Data_as_int() {
|
||||
if (data_is_null) {
|
||||
data = doc.Utl_num_parser().Parse(doc.Src(), Src_bgn(), Src_end()).Rv_as_int();
|
||||
data_is_null = false;
|
||||
}
|
||||
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());}
|
||||
public static Json_itm_int cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__int ? null : (Json_itm_int)v;}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Int_;
|
||||
|
||||
public class Json_itm_int extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private final int src_bgn, src_end;
|
||||
private byte[] data_bry;
|
||||
private int data;
|
||||
private boolean data_needs_making;
|
||||
|
||||
private Json_itm_int(Json_doc doc, int src_bgn, int src_end, boolean data_needs_making, int data) {
|
||||
this.doc = doc;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
this.data_needs_making = data_needs_making;
|
||||
if (!data_needs_making)
|
||||
this.data = data;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__int;}
|
||||
@Override public Object Data() {return Data_as_int();}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null) {
|
||||
data_bry = doc == null
|
||||
? Int_.To_bry(data)
|
||||
: Bry_.Mid(doc.Src(), src_bgn, src_end);
|
||||
}
|
||||
return data_bry;
|
||||
}
|
||||
public int Data_as_int() {
|
||||
if (data_needs_making) {
|
||||
data = doc.Utl_num_parser().Parse(doc.Src(), src_bgn, src_end).Rv_as_int();
|
||||
data_needs_making = false;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (doc == null)
|
||||
bfr.Add_int_variable(data);
|
||||
else
|
||||
bfr.Add_mid(doc.Src(), src_bgn, src_end);
|
||||
}
|
||||
|
||||
public static Json_itm_int NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_int(doc, src_bgn, src_end, true, -1);}
|
||||
public static Json_itm_int NewByVal(int val) {return new Json_itm_int(null, -1, -1, false, val);}
|
||||
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,21 +13,51 @@ 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_itm_long extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private byte[] data_bry; private long data; private boolean data_is_null = true;
|
||||
public Json_itm_long(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__long;}
|
||||
public long Data_as_long() {
|
||||
if (data_is_null) {
|
||||
data = doc.Utl_num_parser().Parse(doc.Src(), Src_bgn(), Src_end()).Rv_as_long();
|
||||
data_is_null = false;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@Override public Object Data() {return Data_as_long();}
|
||||
@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());}
|
||||
public static Json_itm_long cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__long ? null : (Json_itm_long)v;}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Long_;
|
||||
|
||||
public class Json_itm_long extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private final int src_bgn, src_end;
|
||||
private byte[] data_bry;
|
||||
private long data;
|
||||
private boolean data_needs_making = true;
|
||||
private Json_itm_long(Json_doc doc, int src_bgn, int src_end, boolean data_needs_making, long data) {
|
||||
this.doc = doc;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
this.data_needs_making = data_needs_making;
|
||||
if (!data_needs_making)
|
||||
this.data = data;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__long;}
|
||||
@Override public Object Data() {return Data_as_long();}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null) {
|
||||
data_bry = doc == null
|
||||
? Bry_.new_u8(Long_.To_str(data))
|
||||
: Bry_.Mid(doc.Src(), src_bgn, src_end);
|
||||
}
|
||||
return data_bry;
|
||||
}
|
||||
public long Data_as_long() {
|
||||
if (data_needs_making) {
|
||||
data = doc.Utl_num_parser().Parse(doc.Src(), src_bgn, src_end).Rv_as_long();
|
||||
data_needs_making = false;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (doc == null)
|
||||
bfr.Add_long_variable(data);
|
||||
else
|
||||
bfr.Add_mid(doc.Src(), src_bgn, src_end);
|
||||
}
|
||||
|
||||
public static Json_itm_long NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_long(doc, src_bgn, src_end, true, -1);}
|
||||
public static Json_itm_long NewByVal(long val) {return new Json_itm_long(null, -1, -1, false, val);}
|
||||
public static Json_itm_long Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__long ? null : (Json_itm_long)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,83 +13,153 @@ 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.*;
|
||||
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;}
|
||||
@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
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
@Override public Object Data() {return this.Data_as_str();}
|
||||
public String Data_as_str() {
|
||||
if (data_str == null) {
|
||||
if (data_bry == null)
|
||||
data_bry = Data_make_bry();
|
||||
data_str = String_.new_u8(data_bry);
|
||||
}
|
||||
return data_str;
|
||||
}
|
||||
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Data_make_bry(); return data_bry;}
|
||||
@Override public boolean Data_eq(byte[] comp) {
|
||||
if (exact) return Bry_.Eq(doc.Src(), this.Src_bgn(), this.Src_end(), comp);
|
||||
if (data_bry == null) data_bry = Data_make_bry();
|
||||
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();
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Backslash:
|
||||
b = src[++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;
|
||||
case Byte_ascii.Ltr_r: bfr.Add_byte(Byte_ascii.Cr); break;
|
||||
case Byte_ascii.Ltr_b: bfr.Add_byte(Byte_ascii.Backfeed); break;
|
||||
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);
|
||||
// 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) {
|
||||
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);
|
||||
// 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);
|
||||
i += 6; // +6 to skip entire lo-String; EX: '\u0022'
|
||||
}
|
||||
}
|
||||
}
|
||||
int len = gplx.core.intls.Utf16_.Encode_int(utf8_val, utf8_bry, 0);
|
||||
bfr.Add_mid(utf8_bry, 0, len);
|
||||
i += 3; // +3 b/c for-loop will do another +1 to bring total to 4; EX: '0022'
|
||||
break;
|
||||
case Byte_ascii.Backslash:
|
||||
case Byte_ascii.Slash:
|
||||
default:
|
||||
bfr.Add_byte(b); break; // \? " \ / b f n r t
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bfr.Add_byte(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
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_;
|
||||
import gplx.langs.htmls.Gfh_utl;
|
||||
|
||||
public class Json_itm_str extends Json_itm_base {
|
||||
private final Json_doc doc;
|
||||
private final int src_bgn, src_end;
|
||||
private String data_str;
|
||||
private byte[] data_bry;
|
||||
private boolean data_needs_making;
|
||||
private boolean escaped;
|
||||
|
||||
private Json_itm_str(Json_doc doc, int src_bgn, int src_end, String data_str, boolean escaped) {
|
||||
this.doc = doc;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
this.data_str = data_str;
|
||||
this.data_bry = null;
|
||||
this.data_needs_making = true;
|
||||
this.escaped = escaped;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__str;}
|
||||
@Override public Object Data() {return this.Data_as_str();}
|
||||
public void Overwrite_bry(byte[] v) {
|
||||
this.data_bry = v; //needed by MapLink/MapFrame
|
||||
this.data_needs_making = false;
|
||||
}
|
||||
@Override public byte[] Data_bry() {
|
||||
if (data_bry == null) {
|
||||
data_bry = Data_make_bry();
|
||||
}
|
||||
return data_bry;
|
||||
}
|
||||
public String Data_as_str() {
|
||||
if (data_str == null) {
|
||||
data_bry = Data_make_bry();
|
||||
data_str = String_.new_u8(data_bry);
|
||||
}
|
||||
return data_str;
|
||||
}
|
||||
@Override public boolean Data_eq(byte[] comp) {
|
||||
return Bry_.Match(this.Data_bry(), comp);
|
||||
}
|
||||
private byte[] Data_make_bry() {
|
||||
// data already made; return it;
|
||||
if (!data_needs_making)
|
||||
return data_bry;
|
||||
|
||||
// mark data as made
|
||||
this.data_needs_making = false;
|
||||
|
||||
// get src, bgn, end, depending on whether or not itm is from jdoc or standalone
|
||||
byte[] src;
|
||||
int bgn;
|
||||
int end;
|
||||
if (doc == null) {
|
||||
src = Bry_.new_u8_safe(this.data_str);
|
||||
bgn = 0;
|
||||
end = src == null ? 0 : src.length;
|
||||
}
|
||||
else {
|
||||
src = doc.Src();
|
||||
bgn = src_bgn;
|
||||
end = src_end;
|
||||
}
|
||||
|
||||
// not escaped -> return the src
|
||||
if (!escaped) {
|
||||
this.data_bry = Bry_.Mid(src, bgn, end);
|
||||
return data_bry;
|
||||
}
|
||||
|
||||
// escaped; get some temp vars
|
||||
Bry_bfr bfr;
|
||||
byte[] utf8_bry;
|
||||
if (doc == null) {
|
||||
bfr = Bry_bfr_.New();
|
||||
utf8_bry = new byte[6];
|
||||
}
|
||||
else { // PERF:reuse bfr / bry on jdoc itself
|
||||
bfr = doc.Bfr();
|
||||
utf8_bry = doc.Tmp_u8_bry();
|
||||
}
|
||||
|
||||
// loop and unescape
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Backslash:
|
||||
b = src[++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;
|
||||
case Byte_ascii.Ltr_r: bfr.Add_byte(Byte_ascii.Cr); break;
|
||||
case Byte_ascii.Ltr_b: bfr.Add_byte(Byte_ascii.Backfeed); break;
|
||||
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);
|
||||
// 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) {
|
||||
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);
|
||||
// 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);
|
||||
i += 6; // +6 to skip entire lo-String; EX: '\u0022'
|
||||
}
|
||||
}
|
||||
}
|
||||
int len = gplx.core.intls.Utf16_.Encode_int(utf8_val, utf8_bry, 0);
|
||||
bfr.Add_mid(utf8_bry, 0, len);
|
||||
i += 3; // +3 b/c for-loop will do another +1 to bring total to 4; EX: '0022'
|
||||
break;
|
||||
case Byte_ascii.Backslash:
|
||||
case Byte_ascii.Slash:
|
||||
default:
|
||||
bfr.Add_byte(b); break; // \? " \ / b f n r t
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bfr.Add_byte(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.data_bry = bfr.To_bry_and_clear();
|
||||
return data_bry;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
byte[] data_bry = this.Data_bry();
|
||||
int data_len = data_bry.length;
|
||||
Gfh_utl.Escape_html_to_bfr(bfr, data_bry, 0, data_len, true, true, true, true, false); // false to apos for backwards compatibility
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
|
||||
public static Json_itm_str NewByDoc(Json_doc doc, int src_bgn, int src_end, boolean escaped) {return new Json_itm_str(doc, src_bgn + 1, src_end - 1, null, escaped);}
|
||||
public static Json_itm_str NewByVal(String val) {return new Json_itm_str(null, -1, -1, val, false);}
|
||||
}
|
@ -1,29 +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_itm_tmp implements Json_itm { // TEST:
|
||||
public Json_itm_tmp(byte tid, String data) {this.tid = tid; this.data = data;}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
public byte[] Data_bry() {return Bry_.new_u8(Object_.Xto_str_strict_or_empty(data));}
|
||||
public int Src_bgn() {return -1;}
|
||||
public int Src_end() {return -1;}
|
||||
public Object Data() {return data;} private String data;
|
||||
public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_str_u8(data);}
|
||||
public boolean Data_eq(byte[] comp) {return false;}
|
||||
public void Clear() {}
|
||||
public static Json_itm new_str_(String v) {return new Json_itm_tmp(Json_itm_.Tid__str, "\"" + v + "\"");}
|
||||
public static Json_itm new_int_(int v) {return new Json_itm_tmp(Json_itm_.Tid__int, Int_.To_str(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,25 +13,29 @@ 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_kv extends Json_itm_base {
|
||||
public Json_kv(Json_itm key, Json_itm val) {this.key = key; this.val = val;}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__kv;}
|
||||
public Json_itm Key() {return key;} private final Json_itm key;
|
||||
public Json_itm Val() {return val;} private final Json_itm val;
|
||||
public byte[] Key_as_bry() {return key.Data_bry();}
|
||||
public String Key_as_str() {return (String)key.Data();}
|
||||
public byte[] Val_as_bry() {return val.Data_bry();}
|
||||
public Json_nde Val_as_nde() {return Json_nde.cast(val);}
|
||||
public Json_ary Val_as_ary() {return Json_ary.cast(val);}
|
||||
public boolean Key_eq(byte[] comp) {return ((Json_itm_str)key).Data_eq(comp);}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
key.Print_as_json(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Colon);
|
||||
val.Print_as_json(bfr, depth);
|
||||
}
|
||||
public static final Json_kv[] Ary_empty = new Json_kv[0];
|
||||
public static Json_kv cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__kv ? null : (Json_kv)v;}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Byte_ascii;
|
||||
|
||||
public class Json_kv extends Json_itm_base {
|
||||
public Json_kv(Json_itm key, Json_itm val) {this.key = key; this.val = val;}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__kv;}
|
||||
public Json_itm Key() {return key;} private final Json_itm key;
|
||||
public Json_itm Val() {return val;} private final Json_itm val;
|
||||
public byte[] Key_as_bry() {return key.Data_bry();}
|
||||
public String Key_as_str() {return (String)key.Data();}
|
||||
public byte[] Val_as_bry() {return val.Data_bry();}
|
||||
public Json_nde Val_as_nde() {return Json_nde.Cast(val);}
|
||||
public Json_ary Val_as_ary() {return Json_ary.cast(val);}
|
||||
public boolean Key_eq(byte[] comp) {return ((Json_itm_str)key).Data_eq(comp);}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
key.Print_as_json(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Colon);
|
||||
val.Print_as_json(bfr, depth);
|
||||
}
|
||||
public static final Json_kv[] Ary_empty = new Json_kv[0];
|
||||
public static Json_kv Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__kv ? null : (Json_kv)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,37 +13,42 @@ 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 org.junit.*;
|
||||
public class Json_kv_ary_srl_tst {
|
||||
@Before public void init() {fxt.Clear();} private Json_kv_ary_srl_fxt fxt = new Json_kv_ary_srl_fxt();
|
||||
@Test public void Null() {fxt.Test_parse("{'k0':null}" , fxt.ary_(fxt.kv_str_("k0", null)));}
|
||||
@Test public void Bool_n() {fxt.Test_parse("{'k0':false}" , fxt.ary_(fxt.kv_bool_("k0", false)));}
|
||||
@Test public void Num() {fxt.Test_parse("{'k0':123}" , fxt.ary_(fxt.kv_int_("k0", 123)));}
|
||||
@Test public void Num_exp() {fxt.Test_parse("{'k0':1.23e2}" , fxt.ary_(fxt.kv_int_("k0", 123)));} // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
|
||||
@Test public void Str() {fxt.Test_parse("{'k0':'v0'}" , fxt.ary_(fxt.kv_str_("k0", "v0")));}
|
||||
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.kv_dec_("k0", Decimal_adp_.parse("1.23"))));}
|
||||
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("1", 1), fxt.kv_int_("2", 2), fxt.kv_int_("3", 3)))));}
|
||||
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_())));}
|
||||
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1,'k01':2}}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("k00", 1), fxt.kv_int_("k01", 2)))));}
|
||||
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_())));}
|
||||
}
|
||||
class Json_kv_ary_srl_fxt {
|
||||
public void Clear() {
|
||||
if (parser == null) {
|
||||
parser = new Json_parser();
|
||||
}
|
||||
} private Json_parser parser;
|
||||
public void Test_parse(String raw_str, Keyval[] expd) {
|
||||
byte[] raw_bry = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
|
||||
Json_doc doc = parser.Parse(raw_bry);
|
||||
Keyval[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root_nde());
|
||||
Tfds.Eq_str_lines(Keyval_.Ary_to_str(expd), Keyval_.Ary_to_str(actl));
|
||||
}
|
||||
public Keyval[] ary_(Keyval... ary) {return ary;}
|
||||
public Keyval kv_obj_(String key, Object val) {return Keyval_.new_(key, val);}
|
||||
public Keyval kv_str_(String key, String val) {return Keyval_.new_(key, val);}
|
||||
public Keyval kv_int_(String key, int val) {return Keyval_.new_(key, val);}
|
||||
public Keyval kv_bool_(String key, boolean val) {return Keyval_.new_(key, Bool_.To_str_lower(val));}
|
||||
public Keyval kv_dec_(String key, Decimal_adp val) {return Keyval_.new_(key, val.To_str());}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Decimal_adp;
|
||||
import gplx.Decimal_adp_;
|
||||
import gplx.Keyval;
|
||||
import gplx.Keyval_;
|
||||
import gplx.Tfds;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Json_kv_ary_srl_tst {
|
||||
private final Json_kv_ary_srl_fxt fxt = new Json_kv_ary_srl_fxt();
|
||||
@Test public void Null() {fxt.Test_parse("{'k0':null}" , fxt.ary_(fxt.New_kv_str("k0", null)));}
|
||||
@Test public void Bool_n() {fxt.Test_parse("{'k0':false}" , fxt.ary_(fxt.New_kv_bool("k0", false)));}
|
||||
@Test public void Num() {fxt.Test_parse("{'k0':123}" , fxt.ary_(fxt.New_kv_int("k0", 123)));}
|
||||
@Test public void Num_exp() {fxt.Test_parse("{'k0':1.23e2}" , fxt.ary_(fxt.New_kv_int("k0", 123)));} // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
|
||||
@Test public void Str() {fxt.Test_parse("{'k0':'v0'}" , fxt.ary_(fxt.New_kv_str("k0", "v0")));}
|
||||
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.New_kv_dec("k0", Decimal_adp_.parse("1.23"))));}
|
||||
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_(fxt.New_kv_int("1", 1), fxt.New_kv_int("2", 2), fxt.New_kv_int("3", 3)))));}
|
||||
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_())));}
|
||||
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1,'k01':2}}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_(fxt.New_kv_int("k00", 1), fxt.New_kv_int("k01", 2)))));}
|
||||
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_())));}
|
||||
}
|
||||
class Json_kv_ary_srl_fxt {
|
||||
private final Json_parser parser = new Json_parser();
|
||||
public void Test_parse(String raw_str, Keyval[] expd) {
|
||||
byte[] raw_bry = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
|
||||
Json_doc doc = parser.Parse(raw_bry);
|
||||
Keyval[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root_nde());
|
||||
Tfds.Eq_str_lines(Keyval_.Ary_to_str(expd), Keyval_.Ary_to_str(actl));
|
||||
}
|
||||
public Keyval[] ary_(Keyval... ary) {return ary;}
|
||||
public Keyval New_kv_obj(String key, Object val) {return Keyval_.new_(key, val);}
|
||||
public Keyval New_kv_str(String key, String val) {return Keyval_.new_(key, val);}
|
||||
public Keyval New_kv_int(String key, int val) {return Keyval_.new_(key, val);}
|
||||
public Keyval New_kv_bool(String key, boolean val) {return Keyval_.new_(key, Bool_.To_str_lower(val));}
|
||||
public Keyval New_kv_dec(String key, Decimal_adp val) {return Keyval_.new_(key, val.To_str());}
|
||||
}
|
||||
|
@ -1,191 +1,217 @@
|
||||
/*
|
||||
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.Array_;
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.DateAdp;
|
||||
import gplx.DateAdp_;
|
||||
import gplx.Err_;
|
||||
import gplx.Hash_adp_bry;
|
||||
import gplx.Int_;
|
||||
import gplx.Long_;
|
||||
import gplx.String_;
|
||||
|
||||
public class Json_nde extends Json_itm_base implements Json_grp {
|
||||
private Json_itm[] subs = Json_itm_.Ary_empty; private int subs_len = 0, subs_max = 0;
|
||||
private Hash_adp_bry subs_hash;
|
||||
public Json_nde(Json_doc jdoc, int src_bgn) {this.jdoc = jdoc; this.Ctor(src_bgn, -1);}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__nde;}
|
||||
public Json_doc Doc() {return jdoc;} private final Json_doc jdoc;
|
||||
public void Src_end_(int v) {this.src_end = v;}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
public int Len() {return subs_len;}
|
||||
public Json_itm Get_at(int i) {return subs[i];}
|
||||
public Json_itm Get_as_itm_or_null(String key) {return Get_as_itm_or_null(Bry_.new_u8(key));}
|
||||
public Json_itm Get_as_itm_or_null(byte[] key) {if (subs_hash == null) subs_hash = subs_hash_init(); return (Json_itm)subs_hash.Get_by_bry(key);}
|
||||
public Json_ary Get_as_ary(int idx) {return Json_ary.cast(Get_at(idx));}
|
||||
public Json_nde Get_as_nde(String key) {return Json_nde.cast(Get_as_itm_or_null(Bry_.new_u8(key)));}
|
||||
public Json_nde Get_as_nde(int idx) {return Json_nde.cast(Get_at(idx));}
|
||||
public Json_ary Get_as_ary(String key) {return Get_as_ary(Bry_.new_u8(key));}
|
||||
public Json_ary Get_as_ary(byte[] key) {
|
||||
Json_itm rv = Get_as_itm_or_null(key); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return Json_ary.cast(rv);
|
||||
}
|
||||
public Json_ary Get_as_ary_or_null(String key) {return Get_as_ary_or_null(Bry_.new_u8(key));}
|
||||
public Json_ary Get_as_ary_or_null(byte[] key) {
|
||||
Json_itm rv = Get_as_itm_or_null(key);
|
||||
return rv == null
|
||||
? null
|
||||
: Json_ary.cast(rv);
|
||||
}
|
||||
public byte[] Get_as_bry(String key) {
|
||||
byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Get_as_bry_or(byte[] key, byte[] or) {
|
||||
Json_itm rv = Get_as_itm_or_null(key);
|
||||
return rv == null ? or : rv.Data_bry();
|
||||
}
|
||||
public String Get_as_str(String key) {
|
||||
String rv = Get_as_str_or(key, null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public String Get_as_str_or(String key, String or) {return Get_as_str_or(Bry_.new_u8(key), or);}
|
||||
public String Get_as_str_or(byte[] key, String or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : String_.new_u8(rv);
|
||||
}
|
||||
public int Get_as_int(String key) {
|
||||
int rv = Get_as_int_or(key, Int_.Min_value); if (rv == Int_.Min_value) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public int Get_as_int_or(String key, int or) {return Get_as_int_or(Bry_.new_u8(key), or);}
|
||||
public int Get_as_int_or(byte[] key, int or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.To_int(rv);
|
||||
}
|
||||
public long Get_as_long(String key) {
|
||||
long rv = Get_as_long_or(key, Long_.Min_value); if (rv == Long_.Min_value) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public long Get_as_long_or(String key, long or) {return Get_as_long_or(Bry_.new_u8(key), or);}
|
||||
public long Get_as_long_or(byte[] key, long or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.To_long_or(rv, or);
|
||||
}
|
||||
public boolean Get_as_bool_or(String key, boolean or) {return Get_as_bool_or(Bry_.new_u8(key), or);}
|
||||
public boolean Get_as_bool_or(byte[] key, boolean or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.Eq(rv, Bool_.True_bry);
|
||||
}
|
||||
public DateAdp Get_as_date_by_utc(String key) {
|
||||
byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return DateAdp_.parse_gplx(String_.new_u8(rv));
|
||||
}
|
||||
|
||||
// to convert
|
||||
public boolean Has(byte[] key) {return Get_bry(key, null) != null;}
|
||||
public Json_kv Get_at_as_kv(int i) {
|
||||
Json_itm rv_itm = Get_at(i);
|
||||
Json_kv rv = Json_kv.cast(rv_itm); if (rv == null) throw Err_.new_("json", "sub is not kv", "i", i, "src", Bry_.Mid(jdoc.Src(), this.Src_bgn(), src_end));
|
||||
return rv;
|
||||
}
|
||||
|
||||
public Json_kv Get_kv(byte[] key) {return Json_kv.cast(Get_itm(key));}
|
||||
public Json_nde Get(String key) {return Get(Bry_.new_u8(key));}
|
||||
public Json_nde Get(byte[] key) {
|
||||
Json_kv kv = Json_kv.cast(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key);
|
||||
Json_nde rv = Json_nde.cast(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key);
|
||||
return rv;
|
||||
}
|
||||
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) {
|
||||
Json_kv itm_as_kv = (Json_kv)itm;
|
||||
if (Bry_.Eq(key, itm_as_kv.Key().Data_bry()))
|
||||
return itm;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Json_ary Get_ary(String key) {return Get_ary(Bry_.new_u8(key));}
|
||||
public Json_ary Get_ary(byte[] key) {return Json_ary.cast(Get_kv(key).Val_as_ary());}
|
||||
public String Get_str(String key) {return String_.new_u8(Get_bry(Bry_.new_u8(key)));}
|
||||
public byte[] Get_bry(byte[] key) {
|
||||
byte[] rv = Get_bry(key, null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Get_bry_or_null(String key) {return Get_bry(Bry_.new_u8(key), null);}
|
||||
public byte[] Get_bry_or_null(byte[] key) {return Get_bry(key, null);}
|
||||
public byte[] Get_bry(byte[] key, byte[] or) {
|
||||
Json_itm kv_obj = Get_itm(key);
|
||||
if (kv_obj == null) return or; // key not found;
|
||||
if (kv_obj.Tid() != Json_itm_.Tid__kv) return or; // key is not a key_val
|
||||
Json_kv kv = (Json_kv)kv_obj;
|
||||
Json_itm val = kv.Val();
|
||||
return (val == null) ? or : val.Data_bry();
|
||||
}
|
||||
public Json_nde Add_many(Json_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public void Add(Json_itm itm) {
|
||||
int new_len = subs_len + 1;
|
||||
if (new_len > subs_max) { // ary too small >>> expand
|
||||
subs_max = new_len * 2;
|
||||
Json_itm[] new_subs = new Json_itm[subs_max];
|
||||
Array_.Copy_to(subs, 0, new_subs, 0, subs_len);
|
||||
subs = new_subs;
|
||||
}
|
||||
subs[subs_len] = (Json_itm)itm;
|
||||
subs_len = new_len;
|
||||
subs_hash = null;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (bfr.Len() != 0) bfr.Add_byte_nl();
|
||||
Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Curly_bgn).Add_byte(Byte_ascii.Space);
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
if (i != 0) {
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
}
|
||||
subs[i].Print_as_json(bfr, depth + 1);
|
||||
}
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Curly_end).Add_byte_nl();
|
||||
}
|
||||
private Hash_adp_bry subs_hash_init() {
|
||||
Hash_adp_bry rv = Hash_adp_bry.cs();
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Json_itm itm = subs[i];
|
||||
if (itm.Tid() == Json_itm_.Tid__kv) {
|
||||
Json_kv itm_as_kv = (Json_kv)itm;
|
||||
rv.Add(itm_as_kv.Key().Data_bry(), itm_as_kv.Val());
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static Json_nde cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__nde ? null : (Json_nde)v;}
|
||||
}
|
||||
/*
|
||||
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.Array_;
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.DateAdp;
|
||||
import gplx.DateAdp_;
|
||||
import gplx.Decimal_adp_;
|
||||
import gplx.Err_;
|
||||
import gplx.Hash_adp_bry;
|
||||
import gplx.Int_;
|
||||
import gplx.Long_;
|
||||
import gplx.String_;
|
||||
|
||||
public class Json_nde extends Json_itm_base implements Json_grp {
|
||||
private final int src_bgn;
|
||||
private int src_end;
|
||||
private Json_itm[] subs = Json_itm_.Ary_empty;
|
||||
private int subs_len = 0, subs_max = 0;
|
||||
private Hash_adp_bry subs_hash;
|
||||
|
||||
private Json_nde(Json_doc jdoc, int src_bgn) {
|
||||
this.jdoc = jdoc;
|
||||
this.src_bgn = src_bgn;
|
||||
}
|
||||
@Override public byte Tid() {return Json_itm_.Tid__nde;}
|
||||
public Json_doc Doc() {return jdoc;} private final Json_doc jdoc;
|
||||
public void Src_end_(int v) {this.src_end = v;}
|
||||
@Override public Object Data() {return null;}
|
||||
@Override public byte[] Data_bry() {return null;}
|
||||
public int Len() {return subs_len;}
|
||||
public Json_itm Get_at(int i) {return subs[i];}
|
||||
public Json_itm Get_as_itm_or_null(String key) {return Get_as_itm_or_null(Bry_.new_u8(key));}
|
||||
public Json_itm Get_as_itm_or_null(byte[] key) {if (subs_hash == null) subs_hash = subs_hash_init(); return (Json_itm)subs_hash.Get_by_bry(key);}
|
||||
public Json_ary Get_as_ary(int idx) {return Json_ary.cast(Get_at(idx));}
|
||||
public Json_nde Get_as_nde(String key) {return Json_nde.Cast(Get_as_itm_or_null(Bry_.new_u8(key)));}
|
||||
public Json_nde Get_as_nde(int idx) {return Json_nde.Cast(Get_at(idx));}
|
||||
public Json_ary Get_as_ary(String key) {return Get_as_ary(Bry_.new_u8(key));}
|
||||
public Json_ary Get_as_ary(byte[] key) {
|
||||
Json_itm rv = Get_as_itm_or_null(key); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return Json_ary.cast(rv);
|
||||
}
|
||||
public Json_ary Get_as_ary_or_null(String key) {return Get_as_ary_or_null(Bry_.new_u8(key));}
|
||||
public Json_ary Get_as_ary_or_null(byte[] key) {
|
||||
Json_itm rv = Get_as_itm_or_null(key);
|
||||
return rv == null
|
||||
? null
|
||||
: Json_ary.cast(rv);
|
||||
}
|
||||
public byte[] Get_as_bry(String key) {
|
||||
byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Get_as_bry_or(byte[] key, byte[] or) {
|
||||
Json_itm rv = Get_as_itm_or_null(key);
|
||||
return rv == null ? or : rv.Data_bry();
|
||||
}
|
||||
public String Get_as_str(String key) {
|
||||
String rv = Get_as_str_or(key, null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public String Get_as_str_or(String key, String or) {return Get_as_str_or(Bry_.new_u8(key), or);}
|
||||
public String Get_as_str_or(byte[] key, String or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : String_.new_u8(rv);
|
||||
}
|
||||
public int Get_as_int(String key) {
|
||||
int rv = Get_as_int_or(key, Int_.Min_value); if (rv == Int_.Min_value) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public int Get_as_int_or(String key, int or) {return Get_as_int_or(Bry_.new_u8(key), or);}
|
||||
public int Get_as_int_or(byte[] key, int or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.To_int(rv);
|
||||
}
|
||||
public long Get_as_long(String key) {
|
||||
long rv = Get_as_long_or(key, Long_.Min_value); if (rv == Long_.Min_value) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public long Get_as_long_or(String key, long or) {return Get_as_long_or(Bry_.new_u8(key), or);}
|
||||
public long Get_as_long_or(byte[] key, long or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.To_long_or(rv, or);
|
||||
}
|
||||
public boolean Get_as_bool_or(String key, boolean or) {return Get_as_bool_or(Bry_.new_u8(key), or);}
|
||||
public boolean Get_as_bool_or(byte[] key, boolean or) {
|
||||
byte[] rv = Get_as_bry_or(key, null);
|
||||
return rv == null ? or : Bry_.Eq(rv, Bool_.True_bry);
|
||||
}
|
||||
public DateAdp Get_as_date_by_utc(String key) {
|
||||
byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return DateAdp_.parse_gplx(String_.new_u8(rv));
|
||||
}
|
||||
|
||||
// to convert
|
||||
public boolean Has(byte[] key) {return Get_bry(key, null) != null;}
|
||||
public Json_kv Get_at_as_kv(int i) {
|
||||
Json_itm rv_itm = Get_at(i);
|
||||
Json_kv rv = Json_kv.Cast(rv_itm);
|
||||
if (rv == null) {
|
||||
byte[] snip = jdoc == null ? Bry_.new_a7("no source") : Bry_.Mid(jdoc.Src(), src_bgn, src_end);
|
||||
throw Err_.new_("json", "sub is not kv", "i", i, "src", snip);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public Json_kv Get_kv(byte[] key) {return Json_kv.Cast(Get_itm(key));}
|
||||
public Json_nde Get(String key) {return Get(Bry_.new_u8(key));}
|
||||
public Json_nde Get(byte[] key) {
|
||||
Json_kv kv = Json_kv.Cast(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key);
|
||||
Json_nde rv = Json_nde.Cast(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public Json_itm Get_itm(byte[] key) {
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Json_itm itm = subs[i];
|
||||
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;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Json_ary Get_ary(String key) {return Get_ary(Bry_.new_u8(key));}
|
||||
public Json_ary Get_ary(byte[] key) {return Json_ary.cast(Get_kv(key).Val_as_ary());}
|
||||
public String Get_str(String key) {return String_.new_u8(Get_bry(Bry_.new_u8(key)));}
|
||||
public byte[] Get_bry(byte[] key) {
|
||||
byte[] rv = Get_bry(key, null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Get_bry_or_null(String key) {return Get_bry(Bry_.new_u8(key), null);}
|
||||
public byte[] Get_bry_or_null(byte[] key) {return Get_bry(key, null);}
|
||||
public byte[] Get_bry(byte[] key, byte[] or) {
|
||||
Json_itm kv_obj = Get_itm(key);
|
||||
if (kv_obj == null) return or; // key not found;
|
||||
if (kv_obj.Tid() != Json_itm_.Tid__kv) return or; // key is not a key_val
|
||||
Json_kv kv = (Json_kv)kv_obj;
|
||||
Json_itm val = kv.Val();
|
||||
return (val == null) ? or : val.Data_bry();
|
||||
}
|
||||
public void AddKvBool(String key, boolean val) {AddKv(key, Json_itm_bool.Get(val));}
|
||||
public void AddKvInt(String key, int val) {AddKv(key, Json_itm_int.NewByVal(val));}
|
||||
public void AddKvDouble(String key, double val) {AddKv(key, Json_itm_decimal.NewByVal(Decimal_adp_.double_(val)));}
|
||||
public void AddKvStr(String key, byte[] val) {AddKv(key, Json_itm_str.NewByVal(String_.new_u8(val)));}
|
||||
public void AddKvStr(String key, String val) {AddKv(key, Json_itm_str.NewByVal(val));}
|
||||
public void AddKvNde(String key, Json_nde val) {AddKv(key, val);}
|
||||
public void AddKvAry(String key, Json_ary val) {AddKv(key, val);}
|
||||
private void AddKv(String key, Json_itm val) {
|
||||
Json_kv rv = new Json_kv(Json_itm_str.NewByVal(key), val);
|
||||
Add(rv);
|
||||
}
|
||||
public Json_nde Add_many(Json_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public void Add(Json_itm itm) {
|
||||
int new_len = subs_len + 1;
|
||||
if (new_len > subs_max) { // ary too small >>> expand
|
||||
subs_max = new_len * 2;
|
||||
Json_itm[] new_subs = new Json_itm[subs_max];
|
||||
Array_.Copy_to(subs, 0, new_subs, 0, subs_len);
|
||||
subs = new_subs;
|
||||
}
|
||||
subs[subs_len] = (Json_itm)itm;
|
||||
subs_len = new_len;
|
||||
subs_hash = null;
|
||||
}
|
||||
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
|
||||
if (bfr.Len() != 0) bfr.Add_byte_nl();
|
||||
Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Curly_bgn).Add_byte(Byte_ascii.Space);
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
if (i != 0) {
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
}
|
||||
subs[i].Print_as_json(bfr, depth + 1);
|
||||
}
|
||||
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
|
||||
bfr.Add_byte(Byte_ascii.Curly_end).Add_byte_nl();
|
||||
}
|
||||
private Hash_adp_bry subs_hash_init() {
|
||||
Hash_adp_bry rv = Hash_adp_bry.cs();
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Json_itm itm = subs[i];
|
||||
if (itm.Tid() == Json_itm_.Tid__kv) {
|
||||
Json_kv itm_as_kv = (Json_kv)itm;
|
||||
rv.Add(itm_as_kv.Key().Data_bry(), itm_as_kv.Val());
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static Json_nde NewByDoc(Json_doc doc, int src_bgn) {return new Json_nde(doc, src_bgn);}
|
||||
public static Json_nde NewByVal() {return new Json_nde(null, -1);}
|
||||
public static Json_nde Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__nde ? null : (Json_nde)v;}
|
||||
}
|
||||
|
@ -1,198 +1,197 @@
|
||||
/*
|
||||
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.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Char_;
|
||||
import gplx.Err;
|
||||
import gplx.Err_;
|
||||
import gplx.Int_;
|
||||
import gplx.String_;
|
||||
import gplx.core.primitives.Gfo_number_parser;
|
||||
|
||||
public class Json_parser {
|
||||
private byte[] src; private int src_len, pos; private final Gfo_number_parser num_parser = new Gfo_number_parser();
|
||||
public Json_factory Factory() {return factory;} private final Json_factory factory = new Json_factory();
|
||||
public Json_doc Parse_by_apos_ary(String... ary) {return Parse_by_apos(String_.Concat_lines_nl(ary));}
|
||||
public Json_doc Parse_by_apos(String s) {return Parse(Bry_.Replace(Bry_.new_u8(s), Byte_ascii.Apos, Byte_ascii.Quote));}
|
||||
public Json_doc Parse(String src) {return Parse(Bry_.new_u8(src));}
|
||||
public Json_doc Parse(byte[] src) {
|
||||
synchronized (factory) {
|
||||
this.src = src; if (src == null) return null;
|
||||
this.src_len = src.length; if (src_len == 0) return null;
|
||||
this.pos = 0;
|
||||
Skip_ws();
|
||||
boolean root_is_nde = true;
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Curly_bgn: root_is_nde = Bool_.Y; break;
|
||||
case Byte_ascii.Brack_bgn: root_is_nde = Bool_.N; break;
|
||||
default: return null;
|
||||
}
|
||||
Skip_ws();
|
||||
Json_doc doc = new Json_doc();
|
||||
Json_grp root = null;
|
||||
if (root_is_nde)
|
||||
root = Make_nde(doc);
|
||||
else
|
||||
root = Make_ary(doc);
|
||||
doc.Ctor(src, root);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
private Json_nde Make_nde(Json_doc doc) {
|
||||
++pos; // brack_bgn
|
||||
Json_nde nde = new Json_nde(doc, pos);
|
||||
while (pos < src_len) {
|
||||
Skip_ws();
|
||||
if (src[pos] == Byte_ascii.Curly_end) {++pos; return nde;}
|
||||
else nde.Add(Make_kv(doc));
|
||||
Skip_ws();
|
||||
switch (src[pos++]) {
|
||||
case Byte_ascii.Comma: break;
|
||||
case Byte_ascii.Curly_end: return nde;
|
||||
default: throw Err_.new_unhandled(src[pos - 1]);
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos inside nde");
|
||||
}
|
||||
private Json_itm Make_kv(Json_doc doc) {
|
||||
Json_itm key = Make_string(doc);
|
||||
Skip_ws();
|
||||
Chk(Byte_ascii.Colon);
|
||||
Skip_ws();
|
||||
Json_itm val = Make_val(doc);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
private Json_itm Make_val(Json_doc doc) {
|
||||
while (pos < src_len) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Ltr_n: return Make_literal(Bry_null_ull , 3, factory.Null());
|
||||
case Byte_ascii.Ltr_f: return Make_literal(Bry_bool_alse , 4, factory.Bool_n());
|
||||
case Byte_ascii.Ltr_t: return Make_literal(Bry_bool_rue , 3, factory.Bool_y());
|
||||
case Byte_ascii.Quote: return Make_string(doc);
|
||||
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.Dash: return Make_num(doc);
|
||||
case Byte_ascii.Brack_bgn: return Make_ary(doc);
|
||||
case Byte_ascii.Curly_bgn: return Make_nde(doc);
|
||||
}
|
||||
throw Err_.new_unhandled(Char_.To_str(b));
|
||||
}
|
||||
throw Err_.new_wo_type("eos reached in val");
|
||||
}
|
||||
private Json_itm Make_literal(byte[] remainder, int remainder_len, Json_itm singleton) {
|
||||
++pos; // 1st char
|
||||
int literal_end = pos + remainder_len;
|
||||
if (Bry_.Eq(src, pos, literal_end, remainder)) {
|
||||
pos = literal_end;
|
||||
return singleton;
|
||||
}
|
||||
throw Err_.new_("json.parser", "invalid literal", "excerpt", Bry_.Mid_by_len_safe(src, pos - 1, 16));
|
||||
}
|
||||
private Json_itm Make_string(Json_doc doc) {
|
||||
int bgn = pos++; // ++: quote_bgn
|
||||
boolean exact = true;
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Backslash:
|
||||
++pos; // backslash
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Ltr_u: pos += 5; break; // \uFFFF 1 u + 4 hex-dec; ISSUE#:486; DATE:2019-06-02
|
||||
default: ++pos; break; // \? " \ / b f n r t
|
||||
}
|
||||
exact = false;
|
||||
break;
|
||||
case Byte_ascii.Quote:
|
||||
return factory.Str(doc, bgn, ++pos, exact); // ++: quote_end
|
||||
default:
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos reached inside quote");
|
||||
}
|
||||
private Json_itm Make_num(Json_doc doc) {
|
||||
int num_bgn = pos;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (pos == src_len) throw Err_.new_wo_type("eos reached inside num");
|
||||
switch (src[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:
|
||||
++pos;
|
||||
break;
|
||||
case Byte_ascii.Dot:
|
||||
case Byte_ascii.Dash: case Byte_ascii.Plus:
|
||||
case Byte_ascii.Ltr_E: case Byte_ascii.Ltr_e: // e e+ e- E E+ E-
|
||||
++pos;
|
||||
break;
|
||||
default:
|
||||
loop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num_parser.Parse(src, num_bgn, pos);
|
||||
if (num_parser.Has_frac())
|
||||
return factory.Decimal(doc, num_bgn, pos);
|
||||
else {
|
||||
if (num_parser.Is_int())
|
||||
return factory.Int(doc, num_bgn, pos);
|
||||
else
|
||||
return factory.Long(doc, num_bgn, pos);
|
||||
}
|
||||
}
|
||||
private Json_ary Make_ary(Json_doc doc) {
|
||||
Json_ary rv = factory.Ary(pos++, pos); // brack_bgn
|
||||
while (pos < src_len) {
|
||||
Skip_ws();
|
||||
if (src[pos] == Byte_ascii.Brack_end) {++pos; return rv;}
|
||||
else rv.Add(Make_val(doc));
|
||||
Skip_ws();
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Comma: ++pos; break;
|
||||
case Byte_ascii.Brack_end: ++pos; return rv;
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos inside ary");
|
||||
}
|
||||
private void Skip_ws() {
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Nl: case Byte_ascii.Tab: case Byte_ascii.Cr: ++pos; break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Chk(byte expd) {
|
||||
if (src[pos] == expd)
|
||||
++pos;
|
||||
else
|
||||
throw err_(src, pos, "expected '{0}' but got '{1}'", Char_.To_str(expd), Char_.To_str(src[pos]));
|
||||
}
|
||||
private Err err_(byte[] src, int bgn, String fmt, Object... args) {return err_(src, bgn, src.length, fmt, args);}
|
||||
private Err err_(byte[] src, int bgn, int src_len, String fmt, Object... args) {
|
||||
String msg = String_.Format(fmt, args) + " " + Int_.To_str(bgn) + " " + String_.new_u8__by_len(src, bgn, 20);
|
||||
return Err_.new_wo_type(msg);
|
||||
}
|
||||
private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull");
|
||||
public static Json_doc ParseToJdoc(String src) {
|
||||
Json_parser parser = new Json_parser();
|
||||
return parser.Parse(src);
|
||||
}
|
||||
}
|
||||
/*
|
||||
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.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Char_;
|
||||
import gplx.Err;
|
||||
import gplx.Err_;
|
||||
import gplx.Int_;
|
||||
import gplx.String_;
|
||||
import gplx.core.primitives.Gfo_number_parser;
|
||||
|
||||
public class Json_parser {
|
||||
private byte[] src;
|
||||
private int src_len, pos;
|
||||
private final Gfo_number_parser num_parser = new Gfo_number_parser();
|
||||
public Json_doc Parse_by_apos_ary(String... ary) {return Parse_by_apos(String_.Concat_lines_nl(ary));}
|
||||
public Json_doc Parse_by_apos(String s) {return Parse(Bry_.Replace(Bry_.new_u8(s), Byte_ascii.Apos, Byte_ascii.Quote));}
|
||||
public Json_doc Parse(String src) {return Parse(Bry_.new_u8(src));}
|
||||
public Json_doc Parse(byte[] src) {
|
||||
this.src = src; if (src == null) return null;
|
||||
this.src_len = src.length; if (src_len == 0) return null;
|
||||
this.pos = 0;
|
||||
Skip_ws();
|
||||
boolean root_is_nde = true;
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Curly_bgn: root_is_nde = Bool_.Y; break;
|
||||
case Byte_ascii.Brack_bgn: root_is_nde = Bool_.N; break;
|
||||
default: return null;
|
||||
}
|
||||
Skip_ws();
|
||||
Json_doc doc = new Json_doc();
|
||||
Json_grp root = null;
|
||||
if (root_is_nde)
|
||||
root = Make_nde(doc);
|
||||
else
|
||||
root = Make_ary(doc);
|
||||
doc.Ctor(src, root);
|
||||
return doc;
|
||||
}
|
||||
private Json_nde Make_nde(Json_doc doc) {
|
||||
++pos; // brack_bgn
|
||||
Json_nde nde = Json_nde.NewByDoc(doc, pos);
|
||||
while (pos < src_len) {
|
||||
Skip_ws();
|
||||
if (src[pos] == Byte_ascii.Curly_end) {++pos; return nde;}
|
||||
else nde.Add(Make_kv(doc));
|
||||
Skip_ws();
|
||||
switch (src[pos++]) {
|
||||
case Byte_ascii.Comma: break;
|
||||
case Byte_ascii.Curly_end: return nde;
|
||||
default: throw Err_.new_unhandled(src[pos - 1]);
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos inside nde");
|
||||
}
|
||||
private Json_itm Make_kv(Json_doc doc) {
|
||||
Json_itm key = Make_string(doc);
|
||||
Skip_ws();
|
||||
Chk(Byte_ascii.Colon);
|
||||
Skip_ws();
|
||||
Json_itm val = Make_val(doc);
|
||||
return new Json_kv(key, val);
|
||||
}
|
||||
private Json_itm Make_val(Json_doc doc) {
|
||||
while (pos < src_len) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Ltr_n: return Make_literal(Bry_null_ull , 3, Json_itm_null.Null);
|
||||
case Byte_ascii.Ltr_f: return Make_literal(Bry_bool_alse , 4, Json_itm_bool.Bool_n);
|
||||
case Byte_ascii.Ltr_t: return Make_literal(Bry_bool_rue , 3, Json_itm_bool.Bool_y);
|
||||
case Byte_ascii.Quote: return Make_string(doc);
|
||||
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.Dash: return Make_num(doc);
|
||||
case Byte_ascii.Brack_bgn: return Make_ary(doc);
|
||||
case Byte_ascii.Curly_bgn: return Make_nde(doc);
|
||||
}
|
||||
throw Err_.new_unhandled(Char_.To_str(b));
|
||||
}
|
||||
throw Err_.new_wo_type("eos reached in val");
|
||||
}
|
||||
private Json_itm Make_literal(byte[] remainder, int remainder_len, Json_itm singleton) {
|
||||
++pos; // 1st char
|
||||
int literal_end = pos + remainder_len;
|
||||
if (Bry_.Eq(src, pos, literal_end, remainder)) {
|
||||
pos = literal_end;
|
||||
return singleton;
|
||||
}
|
||||
throw Err_.new_("json.parser", "invalid literal", "excerpt", Bry_.Mid_by_len_safe(src, pos - 1, 16));
|
||||
}
|
||||
private Json_itm Make_string(Json_doc doc) {
|
||||
int bgn = pos++; // ++: quote_bgn
|
||||
boolean escaped = false;
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Backslash:
|
||||
++pos; // backslash
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Ltr_u: pos += 5; break; // \uFFFF 1 u + 4 hex-dec; ISSUE#:486; DATE:2019-06-02
|
||||
default: ++pos; break; // \? " \ / b f n r t
|
||||
}
|
||||
escaped = true;
|
||||
break;
|
||||
case Byte_ascii.Quote:
|
||||
return Json_itm_str.NewByDoc(doc, bgn, ++pos, escaped); // ++: quote_end
|
||||
default:
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos reached inside quote");
|
||||
}
|
||||
private Json_itm Make_num(Json_doc doc) {
|
||||
int num_bgn = pos;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (pos == src_len) throw Err_.new_wo_type("eos reached inside num");
|
||||
switch (src[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:
|
||||
++pos;
|
||||
break;
|
||||
case Byte_ascii.Dot:
|
||||
case Byte_ascii.Dash: case Byte_ascii.Plus:
|
||||
case Byte_ascii.Ltr_E: case Byte_ascii.Ltr_e: // e e+ e- E E+ E-
|
||||
++pos;
|
||||
break;
|
||||
default:
|
||||
loop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num_parser.Parse(src, num_bgn, pos);
|
||||
if (num_parser.Has_frac())
|
||||
return Json_itm_decimal.NewByDoc(doc, num_bgn, pos);
|
||||
else {
|
||||
if (num_parser.Is_int())
|
||||
return Json_itm_int.NewByDoc(doc, num_bgn, pos);
|
||||
else
|
||||
return Json_itm_long.NewByDoc(doc, num_bgn, pos);
|
||||
}
|
||||
}
|
||||
private Json_ary Make_ary(Json_doc doc) {
|
||||
Json_ary rv = Json_ary.NewByDoc(doc, pos++, pos); // brack_bgn
|
||||
while (pos < src_len) {
|
||||
Skip_ws();
|
||||
if (src[pos] == Byte_ascii.Brack_end) {++pos; return rv;}
|
||||
else rv.Add(Make_val(doc));
|
||||
Skip_ws();
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Comma: ++pos; break;
|
||||
case Byte_ascii.Brack_end: ++pos; return rv;
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("eos inside ary");
|
||||
}
|
||||
private void Skip_ws() {
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Nl: case Byte_ascii.Tab: case Byte_ascii.Cr: ++pos; break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Chk(byte expd) {
|
||||
if (src[pos] == expd)
|
||||
++pos;
|
||||
else
|
||||
throw err_(src, pos, "expected '{0}' but got '{1}'", Char_.To_str(expd), Char_.To_str(src[pos]));
|
||||
}
|
||||
private Err err_(byte[] src, int bgn, String fmt, Object... args) {return err_(src, bgn, src.length, fmt, args);}
|
||||
private Err err_(byte[] src, int bgn, int src_len, String fmt, Object... args) {
|
||||
String msg = String_.Format(fmt, args) + " " + Int_.To_str(bgn) + " " + String_.new_u8__by_len(src, bgn, 20);
|
||||
return Err_.new_wo_type(msg);
|
||||
}
|
||||
private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull");
|
||||
public static Json_doc ParseToJdoc(String src) {
|
||||
Json_parser parser = new Json_parser();
|
||||
return parser.Parse(src);
|
||||
}
|
||||
}
|
||||
|
@ -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,56 +13,61 @@ 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.primitives.*;
|
||||
public class Json_parser__list_nde__base extends Json_parser__itm__base {
|
||||
public void Parse_grp(String context, Json_grp grp) {
|
||||
this.context = context;
|
||||
int len = grp.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde sub = null;
|
||||
if (grp.Tid() == Json_itm_.Tid__nde) {
|
||||
Json_kv kv = Json_nde.cast(grp).Get_at_as_kv(i);
|
||||
sub = kv.Val_as_nde();
|
||||
}
|
||||
else {
|
||||
sub = Json_nde.cast(grp.Get_at(i));
|
||||
}
|
||||
Parse_nde(context, sub);
|
||||
}
|
||||
}
|
||||
public void Parse_nde(String context, Json_nde nde) {
|
||||
this.cur_itm = nde;
|
||||
for (int j = 0; j < keys_len; ++j)
|
||||
atrs[j] = null;
|
||||
int atr_len = nde.Len();
|
||||
for (int j = 0; j < atr_len; ++j) {
|
||||
Json_kv atr = nde.Get_at_as_kv(j);
|
||||
Object idx_obj = hash.Get_by_bry(atr.Key_as_bry());
|
||||
if (idx_obj == null) {Warn("unknown json parser key", atr); continue;}
|
||||
int idx_int = ((Int_obj_val)idx_obj).Val();
|
||||
atrs[idx_int] = atr;
|
||||
}
|
||||
Parse_hook_nde(nde, atrs);
|
||||
}
|
||||
public void Parse_to_list_as_bry(String context, Json_ary ary, Ordered_hash list) {
|
||||
this.cur_itm = ary;
|
||||
int len = ary.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] val = ary.Get_at(i).Data_bry();
|
||||
list.Add(val, val);
|
||||
}
|
||||
}
|
||||
public void Parse_to_list_as_kv(String context, Json_nde nde, Ordered_hash list) {
|
||||
this.cur_itm = nde;
|
||||
int len = nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = nde.Get_at_as_kv(i);
|
||||
byte[] key = sub.Key_as_bry();
|
||||
byte[] val = Parse_to_list_as_kv__get_val(sub, key);
|
||||
list.Add(key, Keyval_.new_(String_.new_u8(key), String_.new_u8(val)));
|
||||
}
|
||||
}
|
||||
@gplx.Virtual protected byte[] Parse_to_list_as_kv__get_val(Json_kv sub, byte[] key) {return sub.Val_as_bry();}
|
||||
@Override protected void Parse_hook_nde(Json_nde sub, Json_kv[] atrs) {}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Keyval_;
|
||||
import gplx.Ordered_hash;
|
||||
import gplx.String_;
|
||||
import gplx.core.primitives.Int_obj_val;
|
||||
|
||||
public class Json_parser__list_nde__base extends Json_parser__itm__base {
|
||||
public void Parse_grp(String context, Json_grp grp) {
|
||||
this.context = context;
|
||||
int len = grp.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde sub = null;
|
||||
if (grp.Tid() == Json_itm_.Tid__nde) {
|
||||
Json_kv kv = Json_nde.Cast(grp).Get_at_as_kv(i);
|
||||
sub = kv.Val_as_nde();
|
||||
}
|
||||
else {
|
||||
sub = Json_nde.Cast(grp.Get_at(i));
|
||||
}
|
||||
Parse_nde(context, sub);
|
||||
}
|
||||
}
|
||||
public void Parse_nde(String context, Json_nde nde) {
|
||||
this.cur_itm = nde;
|
||||
for (int j = 0; j < keys_len; ++j)
|
||||
atrs[j] = null;
|
||||
int atr_len = nde.Len();
|
||||
for (int j = 0; j < atr_len; ++j) {
|
||||
Json_kv atr = nde.Get_at_as_kv(j);
|
||||
Object idx_obj = hash.Get_by_bry(atr.Key_as_bry());
|
||||
if (idx_obj == null) {Warn("unknown json parser key", atr); continue;}
|
||||
int idx_int = ((Int_obj_val)idx_obj).Val();
|
||||
atrs[idx_int] = atr;
|
||||
}
|
||||
Parse_hook_nde(nde, atrs);
|
||||
}
|
||||
public void Parse_to_list_as_bry(String context, Json_ary ary, Ordered_hash list) {
|
||||
this.cur_itm = ary;
|
||||
int len = ary.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] val = ary.Get_at(i).Data_bry();
|
||||
list.Add(val, val);
|
||||
}
|
||||
}
|
||||
public void Parse_to_list_as_kv(String context, Json_nde nde, Ordered_hash list) {
|
||||
this.cur_itm = nde;
|
||||
int len = nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = nde.Get_at_as_kv(i);
|
||||
byte[] key = sub.Key_as_bry();
|
||||
byte[] val = Parse_to_list_as_kv__get_val(sub, key);
|
||||
list.Add(key, Keyval_.new_(String_.new_u8(key), String_.new_u8(val)));
|
||||
}
|
||||
}
|
||||
@gplx.Virtual protected byte[] Parse_to_list_as_kv__get_val(Json_kv sub, byte[] key) {return sub.Val_as_bry();}
|
||||
@Override protected void Parse_hook_nde(Json_nde sub, Json_kv[] atrs) {}
|
||||
}
|
||||
|
@ -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,87 +13,96 @@ 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 org.junit.*;
|
||||
public class Json_parser_tst {
|
||||
private final Json_parser_fxt fxt = new Json_parser_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
@Test public void Null() {fxt.Test_parse_val0("{'k0':null}" , null);}
|
||||
@Test public void Bool_n() {fxt.Test_parse_val0("{'k0':false}" , false);}
|
||||
@Test public void Bool_y() {fxt.Test_parse_val0("{'k0':true}" , true);}
|
||||
@Test public void Num() {fxt.Test_parse_val0("{'k0':123}" , 123);}
|
||||
@Test public void Num_neg() {fxt.Test_parse_val0("{'k0':-123}" , -123);}
|
||||
@Test public void Str() {fxt.Test_parse_val0("{'k0':'v0'}" , "v0");}
|
||||
@Test public void Str_esc_quote() {fxt.Test_parse_val0("{'k0':'a\\\"b'}" , "a\"b");}
|
||||
@Test public void Str_encoded_basic() {fxt.Test_parse_val0("{'k0':'a\\u0021b'}" , "a!b");}
|
||||
@Test public void Str_encoded_surrogate() {fxt.Test_parse_val0("{'k0':'a\\ud83c\\udf0eb'}", "a🌎b");} // check for UTF surrogate-pairs; symbol is earth globe americas (U+1F30E); ISSUE#:487; DATE:2019-06-02
|
||||
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "1.23")));}
|
||||
@Test public void Num_exp() {fxt.Test_parse("{'k0':1e+2}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "1e+2")));}
|
||||
@Test public void Num_mix() {fxt.Test_parse("{'k0':-1.23e-1}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "-1.23e-1")));}
|
||||
@Test public void Str_many() {fxt.Test_parse("{'k0':'v0','k1':'v1','k2':'v2'}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", "v0"), fxt.itm_kv_("k1", "v1"), fxt.itm_kv_("k2", "v2")));}
|
||||
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0")));}
|
||||
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0", 1, 2, 3)));}
|
||||
@Test public void Ary_str() {fxt.Test_parse("{'k0':['a','b','c']}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_str_("k0", "a", "b", "c")));}
|
||||
@Test public void Ary_ws() {fxt.Test_parse("{'k0': [ 1 , 2 , 3 ] }", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0", 1, 2, 3)));}
|
||||
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1}}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_().Add_many(fxt.itm_kv_("k00", 1)))));}
|
||||
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_())));}
|
||||
@Test public void Subs_ws() {fxt.Test_parse("{'k0': { 'k00' : 1 } }", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_().Add_many(fxt.itm_kv_("k00", 1)))));}
|
||||
@Test public void Ws() {fxt.Test_parse(" { 'k0' : 'v0' } ", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", "v0")));}
|
||||
@Test public void Root_is_ary() {fxt.Test_parse("[ 1 , 2 , 3 ]", fxt.itm_ary_().Add_many(fxt.itm_int_(1), fxt.itm_int_(2), fxt.itm_int_(3)));}
|
||||
public static String Replace_apos_as_str(String v) {return String_.new_u8(Replace_apos(Bry_.new_u8(v)));}
|
||||
public static byte[] Replace_apos(byte[] v) {return Bry_.Replace(v, Byte_ascii.Apos, Byte_ascii.Quote);}
|
||||
}
|
||||
class Json_parser_fxt {
|
||||
public void Clear() {
|
||||
if (parser == null) {
|
||||
parser = new Json_parser();
|
||||
factory = parser.Factory();
|
||||
}
|
||||
} Json_parser parser; Json_factory factory; Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
|
||||
public Json_itm itm_int_(int v) {return Json_itm_tmp.new_int_(v);}
|
||||
Json_itm itm_str_(String v) {return Json_itm_tmp.new_str_(v);}
|
||||
public Json_ary itm_ary_() {return factory.Ary(-1, -1);}
|
||||
public Json_nde itm_nde_() {return factory.Nde(null, -1);}
|
||||
public Json_kv itm_kv_null_(String k) {return factory.Kv(itm_str_(k), factory.Null());}
|
||||
public Json_kv itm_kv_(String k, String v) {return factory.Kv(itm_str_(k), itm_str_(v));}
|
||||
public Json_kv itm_kv_(String k, int v) {return factory.Kv(itm_str_(k), itm_int_(v));}
|
||||
public Json_kv itm_kv_(String k, boolean v) {return factory.Kv(itm_str_(k), v ? factory.Bool_y() : factory.Bool_n());}
|
||||
public Json_kv itm_kv_dec_(String k, String v) {return factory.Kv(itm_str_(k), new Json_itm_tmp(Json_itm_.Tid__decimal, v));}
|
||||
public Json_kv itm_kv_(String k, Json_nde v) {return factory.Kv(itm_str_(k), v);}
|
||||
public Json_kv itm_kv_ary_int_(String k, int... v) {
|
||||
Json_ary ary = factory.Ary(-1, -1);
|
||||
int len = v.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
ary.Add(itm_int_(v[i]));
|
||||
return factory.Kv(itm_str_(k), ary);
|
||||
}
|
||||
public Json_kv itm_kv_ary_str_(String k, String... v) {
|
||||
Json_ary ary = factory.Ary(-1, -1);
|
||||
int len = v.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
ary.Add(itm_str_(v[i]));
|
||||
return factory.Kv(itm_str_(k), ary);
|
||||
}
|
||||
public void Test_parse(String raw_str, Json_itm... expd_ary) {
|
||||
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
|
||||
Json_doc doc = parser.Parse(raw);
|
||||
doc.Root_grp().Print_as_json(tmp_bfr, 0);
|
||||
String actl = tmp_bfr.To_str_and_clear();
|
||||
String expd = Xto_str(raw, doc, expd_ary, 0, expd_ary.length);
|
||||
Tfds.Eq_str_lines(expd, actl, actl);
|
||||
}
|
||||
public void Test_parse_val0(String raw_str, Object expd) {
|
||||
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
|
||||
Json_doc doc = parser.Parse(raw);
|
||||
Json_kv kv = Json_kv.cast(doc.Root_nde().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
|
||||
Object actl = kv.Val().Data(); // NOTE: Data_bry is escaped val; EX: a\"b has DataBry of a"b
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
String Xto_str(byte[] raw, Json_doc doc, Json_itm[] ary, int bgn, int end) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
Json_itm itm = ary[i];
|
||||
itm.Print_as_json(tmp_bfr, 0);
|
||||
}
|
||||
return tmp_bfr.To_str_and_clear();
|
||||
}
|
||||
}
|
||||
package gplx.langs.jsons;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Decimal_adp;
|
||||
import gplx.Decimal_adp_;
|
||||
import gplx.Tfds;
|
||||
import gplx.core.tests.Gftest;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Json_parser_tst {
|
||||
private final Json_parser_fxt fxt = new Json_parser_fxt();
|
||||
@Test public void Null() {fxt.Test_parse_obj("{'k0':null}" , null);}
|
||||
@Test public void Bool_n() {fxt.Test_parse_obj("{'k0':false}" , false);}
|
||||
@Test public void Bool_y() {fxt.Test_parse_obj("{'k0':true}" , true);}
|
||||
@Test public void Num() {fxt.Test_parse_obj("{'k0':123}" , 123);}
|
||||
@Test public void Num_neg() {fxt.Test_parse_obj("{'k0':-123}" , -123);}
|
||||
@Test public void Str() {fxt.Test_parse_obj("{'k0':'v0'}" , "v0");}
|
||||
@Test public void Str_esc_quote() {fxt.Test_parse_obj("{'k0':'a\\\"b'}" , "a\"b");}
|
||||
@Test public void Str_encoded_basic() {fxt.Test_parse_obj("{'k0':'a\\u0021b'}" , "a!b");}
|
||||
@Test public void Str_encoded_surrogate() {fxt.Test_parse_obj("{'k0':'a\\ud83c\\udf0eb'}", "a🌎b");} // check for UTF surrogate-pairs; symbol is earth globe americas (U+1F30E); ISSUE#:487; DATE:2019-06-02
|
||||
@Test public void Num_dec() {fxt.Test_parse_dec("{'k0':1.23}" , Decimal_adp_.parse("1.23"));}
|
||||
@Test public void Num_exp() {fxt.Test_parse_obj("{'k0':1e+2}" , 100);}
|
||||
@Test public void Num_mix() {fxt.Test_parse_dec("{'k0':-1.23e-1}" , Decimal_adp_.parse("-1.23e-1"));}
|
||||
@Test public void Str_many() {fxt.Test_parse("{'k0':'v0','k1':'v1','k2':'v2'}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", "v0"), fxt.Init_kv("k1", "v1"), fxt.Init_kv("k2", "v2")));}
|
||||
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0")));}
|
||||
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0", 1, 2, 3)));}
|
||||
@Test public void Ary_str() {fxt.Test_parse("{'k0':['a','b','c']}" , fxt.Init_nde().Add_many(fxt.Init_kvary_str_("k0", "a", "b", "c")));}
|
||||
@Test public void Ary_ws() {fxt.Test_parse("{'k0': [ 1 , 2 , 3 ] }" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0", 1, 2, 3)));}
|
||||
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1}}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde().Add_many(fxt.Init_kv("k00", 1)))));}
|
||||
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde())));}
|
||||
@Test public void Subs_ws() {fxt.Test_parse("{'k0': { 'k00' : 1 } }" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde().Add_many(fxt.Init_kv("k00", 1)))));}
|
||||
@Test public void Ws() {fxt.Test_parse(" { 'k0' : 'v0' } " , fxt.Init_nde().Add_many(fxt.Init_kv("k0", "v0")));}
|
||||
@Test public void Root_is_ary() {fxt.Test_parse("[1,2,3]" , fxt.Init_ary().Add_many(fxt.Init_int(1), fxt.Init_int(2), fxt.Init_int(3)));}
|
||||
}
|
||||
class Json_parser_fxt {
|
||||
private final Json_parser parser = new Json_parser();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
|
||||
public Json_itm Init_int(int v) {return Json_itm_int.NewByVal(v);}
|
||||
public Json_itm Init_str(String v) {return Json_itm_str.NewByVal(v);}
|
||||
public Json_ary Init_ary() {return Json_ary.NewByVal();}
|
||||
public Json_nde Init_nde() {return Json_nde.NewByVal();}
|
||||
public Json_kv Init_kv_null(String k) {return new Json_kv(Init_str(k), Json_itm_null.Null);}
|
||||
public Json_kv Init_kv(String k, String v) {return new Json_kv(Init_str(k), Init_str(v));}
|
||||
public Json_kv Init_kv(String k, int v) {return new Json_kv(Init_str(k), Init_int(v));}
|
||||
public Json_kv Init_kv(String k, boolean v) {return new Json_kv(Init_str(k), v ? Json_itm_bool.Bool_y : Json_itm_bool.Bool_n);}
|
||||
public Json_kv Init_kv(String k, Json_nde v) {return new Json_kv(Init_str(k), v);}
|
||||
public Json_kv Init_kv_ary_int(String k, int... v) {
|
||||
Json_ary ary = Json_ary.NewByVal();
|
||||
int len = v.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
ary.Add(Init_int(v[i]));
|
||||
return new Json_kv(Init_str(k), ary);
|
||||
}
|
||||
public Json_kv Init_kvary_str_(String k, String... v) {
|
||||
Json_ary ary = Json_ary.NewByVal();
|
||||
int len = v.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
ary.Add(Init_str(v[i]));
|
||||
return new Json_kv(Init_str(k), ary);
|
||||
}
|
||||
public void Test_parse(String raw_str, Json_itm... expd_ary) {
|
||||
byte[] raw = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
|
||||
Json_doc doc = parser.Parse(raw);
|
||||
doc.Root_grp().Print_as_json(tmp_bfr, 0);
|
||||
String actl = tmp_bfr.To_str_and_clear();
|
||||
String expd = Xto_str(raw, doc, expd_ary, 0, expd_ary.length);
|
||||
Tfds.Eq_str_lines(expd, actl, actl);
|
||||
}
|
||||
public void Test_parse_obj(String raw_str, Object expd) {
|
||||
Json_kv kv = Parse_and_get_kv0(raw_str);
|
||||
Object actl = kv.Val().Data(); // NOTE: Data_bry is escaped val; EX: a\"b has DataBry of a"b
|
||||
Gftest.Eq__obj_or_null(expd, actl);
|
||||
}
|
||||
public void Test_parse_dec(String raw_str, Decimal_adp expd) {
|
||||
Json_kv kv = Parse_and_get_kv0(raw_str);
|
||||
Json_itm_decimal decimal_itm = (Json_itm_decimal)kv.Val();
|
||||
Gftest.Eq__bool(true, decimal_itm.Data_as_decimal().Eq(expd));
|
||||
}
|
||||
private Json_kv Parse_and_get_kv0(String raw_str) {
|
||||
byte[] raw = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
|
||||
Json_doc doc = parser.Parse(raw);
|
||||
return Json_kv.Cast(doc.Root_nde().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
|
||||
}
|
||||
private String Xto_str(byte[] raw, Json_doc doc, Json_itm[] ary, int bgn, int end) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
Json_itm itm = ary[i];
|
||||
itm.Print_as_json(tmp_bfr, 0);
|
||||
}
|
||||
return tmp_bfr.To_str_and_clear();
|
||||
}
|
||||
}
|
||||
|
112
400_xowa/src/gplx/langs/mustaches/JsonMustacheNde.java
Normal file
112
400_xowa/src/gplx/langs/mustaches/JsonMustacheNde.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
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.mustaches;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.String_;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_itm_;
|
||||
import gplx.langs.jsons.Json_kv;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.objects.Object_;
|
||||
|
||||
public class JsonMustacheNde implements Mustache_doc_itm {
|
||||
private final Json_nde nde;
|
||||
public JsonMustacheNde(Json_nde nde) {this.nde = nde;}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
Json_itm itm = nde.Get_itm(Bry_.new_u8(key));
|
||||
if (itm == null) { // mustacheKey does not exist in current jsonNde
|
||||
return false;
|
||||
}
|
||||
else { // mustacheKey exists
|
||||
switch (itm.Tid()) {
|
||||
// array / bool node -> ignore; EX: `{{#person}}Never shown{{/person}}`
|
||||
case Json_itm_.Tid__bool:
|
||||
case Json_itm_.Tid__ary:
|
||||
case Json_itm_.Tid__nde:
|
||||
return false;
|
||||
// item node -> render it; EX: `Hello {{name}}`
|
||||
default:
|
||||
bfr.Add_bry(Json_kv.Cast(itm).Val_as_bry());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
Json_itm itm = nde.Get_itm(Bry_.new_u8(key));
|
||||
if (itm == null) { // mustacheKey does not exist in current jsonNde
|
||||
return Mustache_doc_itm_.Ary__bool__n;
|
||||
}
|
||||
else { // mustacheKey exists
|
||||
if (itm.Tid() == Json_itm_.Tid__kv) {
|
||||
Json_kv kv = Json_kv.Cast(itm);
|
||||
switch (kv.Val().Tid()) {
|
||||
// bool node -> render; EX: `{{#person}}Never shown{{/person}}`
|
||||
case Json_itm_.Tid__bool:
|
||||
boolean dataVal = Bool_.Cast(kv.Val().Data());
|
||||
return dataVal ? Mustache_doc_itm_.Ary__bool__y : Mustache_doc_itm_.Ary__bool__n;
|
||||
// array node -> render; EX: `{{#repo}} <b>{{name}}</b>{{/repo}}`
|
||||
case Json_itm_.Tid__ary:
|
||||
return ToJsonMustachNdeAry(itm);
|
||||
// item node -> render only if key matchers
|
||||
default:
|
||||
return new Mustache_doc_itm[] {new JsonMustacheVal(true, key, kv.Val().Data())};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Mustache_doc_itm_.Ary__bool__n;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Mustache_doc_itm[] ToJsonMustachNdeAry(Json_itm itm) {
|
||||
Json_ary dataAry = Json_ary.cast_or_null(Json_kv.Cast(itm).Val());
|
||||
int subs_len = dataAry.Len();
|
||||
Mustache_doc_itm[] rv = new Mustache_doc_itm[subs_len];
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Json_itm sub = dataAry.Get_at(i);
|
||||
if (sub.Tid() == Json_itm_.Tid__nde) {
|
||||
rv[i] = new JsonMustacheNde((Json_nde)sub);
|
||||
}
|
||||
else {
|
||||
rv[i] = new JsonMustacheVal(false, Mustache_tkn_def.ItemString, sub.Data());
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class JsonMustacheVal implements Mustache_doc_itm {
|
||||
private final boolean fromArray;
|
||||
private final String jsonKey;
|
||||
private final Object jsonVal;
|
||||
public JsonMustacheVal(boolean fromArray, String jsonKey, Object jsonVal) {
|
||||
this.fromArray = fromArray;
|
||||
this.jsonKey = jsonKey;
|
||||
this.jsonVal = jsonVal;
|
||||
}
|
||||
public boolean Mustache__write(String mustacheKey, Mustache_bfr bfr) {
|
||||
if ( (String_.Eq(mustacheKey, jsonKey)) // print if `{{match}}`; EX: `{{#prop}}{{prop}}{{/prop}}`
|
||||
|| (String_.Eq(mustacheKey, Mustache_tkn_def.ItemString) && fromArray)) { // print if `{{.}}` and from array; EX: `{{#array}}{{.}}{{/array}}`
|
||||
bfr.Add_bry(Bry_.new_u8(Object_.To_str(jsonVal)));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
}
|
@ -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,9 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
import gplx.langs.jsons.*;
|
||||
public interface Mustache_doc_itm {
|
||||
boolean Mustache__write(String key, Mustache_bfr bfr);
|
||||
Mustache_doc_itm[] Mustache__subs(String key);
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
public interface Mustache_doc_itm {
|
||||
boolean Mustache__write(String key, Mustache_bfr bfr);
|
||||
Mustache_doc_itm[] Mustache__subs(String 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,150 +13,177 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.primitives.*;
|
||||
public class Mustache_itm_render_tst {
|
||||
private final Mustache_itm_render_fxt fxt = new Mustache_itm_render_fxt();
|
||||
@Test public void Text() {
|
||||
fxt.Test__parse("a b c", "a b c");
|
||||
}
|
||||
@Test public void Variable() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "1").Add_prop("prop2", "2"));
|
||||
fxt.Test__parse("{{prop1}}", "1");
|
||||
fxt.Test__parse("a{{prop1}}b{{prop2}}c", "a1b2c");
|
||||
}
|
||||
@Test public void Escape() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "<"));
|
||||
fxt.Test__parse("{{{prop1}}}", "<");
|
||||
fxt.Test__parse("{{prop1}}", "<");
|
||||
}
|
||||
@Test public void Section_bool() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
|
||||
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c", "abc");
|
||||
fxt.Test__parse("a{{#bool_n}}b{{/bool_n}}c", "ac");
|
||||
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c{{#bool_n}}d{{/bool_n}}e", "abce");
|
||||
}
|
||||
@Test public void Section_not() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
|
||||
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c", "ac");
|
||||
fxt.Test__parse("a{{^bool_n}}b{{/bool_n}}c", "abc");
|
||||
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c{{^bool_n}}d{{/bool_n}}e", "acde");
|
||||
}
|
||||
@Test public void Section_ws() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y"));
|
||||
fxt.Test__parse("a\n {{#bool_y}} \nb\n {{/bool_y}} \nc", "a\nb\nc");
|
||||
}
|
||||
@Test public void Section_subs_flat() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "1").Add_subs("subs2")
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "2").Add_subs("subs2")
|
||||
));
|
||||
fxt.Test__parse("a{{#subs1}}({{prop1}}){{/subs1}}d", "a(1)(2)d");
|
||||
}
|
||||
@Test public void Section_subs_nest_1() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2"))
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{/subs1}}"
|
||||
, "a12"
|
||||
);
|
||||
}
|
||||
@Test public void Section_subs_nest_2() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2")
|
||||
)
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "b")
|
||||
)
|
||||
);
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{/subs1}}"
|
||||
, "a12b"
|
||||
);
|
||||
}
|
||||
@Test public void Section_subs_nest_3() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2")
|
||||
)
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "b").Add_subs("subs2"
|
||||
, fxt.Make_mock(21).Add_prop("prop2", "3")
|
||||
, fxt.Make_mock(22).Add_prop("prop2", "4")
|
||||
)
|
||||
)
|
||||
);
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{prop1}}{{/subs1}}"
|
||||
, "a12ab34b"
|
||||
);
|
||||
}
|
||||
@Test public void Section_bool_subs() { // handle prop written after boolean; should not pick up inner prop
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_bool_y("bool1").Add_prop("prop2", "2").Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "11")
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "12")
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "a{{#bool1}}b{{#subs1}}c{{prop1}}d{{/subs1}}e{{/bool1}}f{{prop2}}g"
|
||||
, "abc11dc12def2g"
|
||||
);
|
||||
}
|
||||
@Test public void Section_owner() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
)
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{#subs2}}{{prop1}}{{prop2}}{{/subs2}}{{/subs1}}" // prop1 is cited in subs2, but value belongs to subs1
|
||||
, "a1"
|
||||
);
|
||||
}
|
||||
}
|
||||
class Mustache_itm_render_fxt {
|
||||
private final Mustache_tkn_parser parser = new Mustache_tkn_parser();
|
||||
private final Mustache_render_ctx ctx = new Mustache_render_ctx();
|
||||
private final Mustache_bfr bfr = Mustache_bfr.New();
|
||||
private Mustache_doc_itm__mock root;
|
||||
public Mustache_doc_itm__mock Make_mock(int id) {return new Mustache_doc_itm__mock(id);}
|
||||
public void Init__root(Mustache_doc_itm__mock v) {this.root = v;}
|
||||
public void Test__parse(String src_str, String expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Mustache_tkn_itm actl_itm = parser.Parse(src_bry, 0, src_bry.length);
|
||||
ctx.Init(root);
|
||||
actl_itm.Render(bfr, ctx);
|
||||
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
class Mustache_doc_itm__mock implements Mustache_doc_itm {
|
||||
private final Hash_adp hash_prop = Hash_adp_.New(), hash_bool = Hash_adp_.New(), hash_subs = Hash_adp_.New();
|
||||
public Mustache_doc_itm__mock(int id) {this.id = id;}
|
||||
public int id;
|
||||
public Mustache_doc_itm__mock Add_prop(String key, String val) {hash_prop.Add(key, Bry_.new_u8(val)); return this;}
|
||||
public Mustache_doc_itm__mock Add_bool_y(String key) {hash_bool.Add(key, Bool_obj_ref.y_()); return this;}
|
||||
public Mustache_doc_itm__mock Add_bool_n(String key) {hash_bool.Add(key, Bool_obj_ref.n_()); return this;}
|
||||
public Mustache_doc_itm__mock Add_subs(String key, Mustache_doc_itm__mock... ary) {hash_subs.Add(key, ary); return this;}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
byte[] rv = (byte[])hash_prop.Get_by(key);
|
||||
if (rv == null) return false;
|
||||
bfr.Add_bry(rv);
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
Object rv = hash_bool.Get_by(key);
|
||||
if (rv != null) {
|
||||
boolean bool_val = ((Bool_obj_ref)rv).Val();
|
||||
return bool_val ? Mustache_doc_itm_.Ary__bool__y : Mustache_doc_itm_.Ary__bool__n;
|
||||
}
|
||||
return (Mustache_doc_itm__mock[])hash_subs.Get_by(key);
|
||||
}
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Hash_adp;
|
||||
import gplx.Hash_adp_;
|
||||
import gplx.Tfds;
|
||||
import gplx.core.primitives.Bool_obj_ref;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.jsons.Json_parser;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Mustache_itm_render_tst {
|
||||
private final Mustache_itm_render_fxt fxt = new Mustache_itm_render_fxt();
|
||||
@Test public void Text() {
|
||||
fxt.Test__parse("a b c", "a b c");
|
||||
}
|
||||
@Test public void Variable() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "1").Add_prop("prop2", "2"));
|
||||
fxt.Test__parse("{{prop1}}", "1");
|
||||
fxt.Test__parse("a{{prop1}}b{{prop2}}c", "a1b2c");
|
||||
}
|
||||
@Test public void Escape() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "<"));
|
||||
fxt.Test__parse("{{{prop1}}}", "<");
|
||||
fxt.Test__parse("{{prop1}}", "<");
|
||||
}
|
||||
@Test public void Section_bool() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
|
||||
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c", "abc");
|
||||
fxt.Test__parse("a{{#bool_n}}b{{/bool_n}}c", "ac");
|
||||
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c{{#bool_n}}d{{/bool_n}}e", "abce");
|
||||
}
|
||||
@Test public void Section_not() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
|
||||
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c", "ac");
|
||||
fxt.Test__parse("a{{^bool_n}}b{{/bool_n}}c", "abc");
|
||||
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c{{^bool_n}}d{{/bool_n}}e", "acde");
|
||||
}
|
||||
@Test public void Section_ws() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y"));
|
||||
fxt.Test__parse("a\n {{#bool_y}} \nb\n {{/bool_y}} \nc", "a\nb\nc");
|
||||
}
|
||||
@Test public void Section_subs_flat() {
|
||||
fxt.Init__root(fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "1").Add_subs("subs2")
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "2").Add_subs("subs2")
|
||||
));
|
||||
fxt.Test__parse("a{{#subs1}}({{prop1}}){{/subs1}}d", "a(1)(2)d");
|
||||
}
|
||||
@Test public void Section_subs_nest_1() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2"))
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{/subs1}}"
|
||||
, "a12"
|
||||
);
|
||||
}
|
||||
@Test public void Section_subs_nest_2() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2")
|
||||
)
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "b")
|
||||
)
|
||||
);
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{/subs1}}"
|
||||
, "a12b"
|
||||
);
|
||||
}
|
||||
@Test public void Section_subs_nest_3() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
, fxt.Make_mock(12).Add_prop("prop2", "2")
|
||||
)
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "b").Add_subs("subs2"
|
||||
, fxt.Make_mock(21).Add_prop("prop2", "3")
|
||||
, fxt.Make_mock(22).Add_prop("prop2", "4")
|
||||
)
|
||||
)
|
||||
);
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{prop1}}{{#subs2}}{{prop2}}{{/subs2}}{{prop1}}{{/subs1}}"
|
||||
, "a12ab34b"
|
||||
);
|
||||
}
|
||||
@Test public void Section_bool_subs() { // handle prop written after boolean; should not pick up inner prop
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_bool_y("bool1").Add_prop("prop2", "2").Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "11")
|
||||
, fxt.Make_mock(2).Add_prop("prop1", "12")
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "a{{#bool1}}b{{#subs1}}c{{prop1}}d{{/subs1}}e{{/bool1}}f{{prop2}}g"
|
||||
, "abc11dc12def2g"
|
||||
);
|
||||
}
|
||||
@Test public void Section_owner() {
|
||||
fxt.Init__root
|
||||
( fxt.Make_mock(0).Add_subs("subs1"
|
||||
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
|
||||
, fxt.Make_mock(11).Add_prop("prop2", "1")
|
||||
)
|
||||
));
|
||||
fxt.Test__parse
|
||||
( "{{#subs1}}{{#subs2}}{{prop1}}{{prop2}}{{/subs2}}{{/subs1}}" // prop1 is cited in subs2, but value belongs to subs1
|
||||
, "a1"
|
||||
);
|
||||
}
|
||||
@Test public void Dot() {
|
||||
fxt.Test__parse
|
||||
( "{'subs':['a', 'b', 'c', 'd']}"
|
||||
, "{{#subs}}{{.}},{{/subs}}"
|
||||
, "a,b,c,d,"
|
||||
);
|
||||
}
|
||||
}
|
||||
class Mustache_itm_render_fxt {
|
||||
private final Mustache_tkn_parser parser = new Mustache_tkn_parser();
|
||||
private final Mustache_render_ctx ctx = new Mustache_render_ctx();
|
||||
private final Mustache_bfr bfr = Mustache_bfr.New();
|
||||
private Mustache_doc_itm__mock root;
|
||||
public Mustache_doc_itm__mock Make_mock(int id) {return new Mustache_doc_itm__mock(id);}
|
||||
public void Init__root(Mustache_doc_itm__mock v) {this.root = v;}
|
||||
public void Test__parse(String src_str, String expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Mustache_tkn_itm actl_itm = parser.Parse(src_bry, 0, src_bry.length);
|
||||
ctx.Init(root);
|
||||
actl_itm.Render(bfr, ctx);
|
||||
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
public void Test__parse(String jdoc, String src_str, String expd) {
|
||||
Json_nde jnde = Json_parser.ParseToJdoc(Json_doc.Make_str_by_apos(jdoc)).Root_nde();
|
||||
JsonMustacheNde nde = new JsonMustacheNde(jnde);
|
||||
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Mustache_tkn_itm actl_itm = parser.Parse(src_bry, 0, src_bry.length);
|
||||
ctx.Init(nde);
|
||||
actl_itm.Render(bfr, ctx);
|
||||
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
class Mustache_doc_itm__mock implements Mustache_doc_itm {
|
||||
private final Hash_adp hash_prop = Hash_adp_.New(), hash_bool = Hash_adp_.New(), hash_subs = Hash_adp_.New();
|
||||
public Mustache_doc_itm__mock(int id) {this.id = id;}
|
||||
public int id;
|
||||
public Mustache_doc_itm__mock Add_prop(String key, String val) {hash_prop.Add(key, Bry_.new_u8(val)); return this;}
|
||||
public Mustache_doc_itm__mock Add_bool_y(String key) {hash_bool.Add(key, Bool_obj_ref.y_()); return this;}
|
||||
public Mustache_doc_itm__mock Add_bool_n(String key) {hash_bool.Add(key, Bool_obj_ref.n_()); return this;}
|
||||
public Mustache_doc_itm__mock Add_subs(String key, Mustache_doc_itm__mock... ary) {hash_subs.Add(key, ary); return this;}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
byte[] rv = (byte[])hash_prop.Get_by(key);
|
||||
if (rv == null) return false;
|
||||
bfr.Add_bry(rv);
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
Object rv = hash_bool.Get_by(key);
|
||||
if (rv != null) {
|
||||
boolean bool_val = ((Bool_obj_ref)rv).Val();
|
||||
return bool_val ? Mustache_doc_itm_.Ary__bool__y : Mustache_doc_itm_.Ary__bool__n;
|
||||
}
|
||||
return (Mustache_doc_itm__mock[])hash_subs.Get_by(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,86 +13,100 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
public class Mustache_render_ctx {
|
||||
private final List_adp stack = List_adp_.New();
|
||||
private Mustache_doc_itm cur;
|
||||
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;
|
||||
this.subs = null;
|
||||
this.subs_idx = subs_len = 0; this.cur_is_bool = Bool_.__byte;
|
||||
return this;
|
||||
}
|
||||
public boolean Render_variable(Mustache_bfr bfr, String key) {
|
||||
boolean rv = false;
|
||||
int stack_pos = stack.Len();
|
||||
Mustache_doc_itm itm = cur;
|
||||
while (itm != Mustache_doc_itm_.Null_itm) {
|
||||
boolean resolved = itm.Mustache__write(key, bfr);
|
||||
if (resolved) {
|
||||
rv = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
--stack_pos;
|
||||
if (stack_pos == -1) // nothing else in stack
|
||||
break;
|
||||
else
|
||||
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).cur;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Section_bgn(String key) {
|
||||
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 (++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
|
||||
if (sub == Mustache_doc_itm_.Itm__bool__n) {
|
||||
boolean rv = Bool_.N;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
else if (sub == Mustache_doc_itm_.Itm__bool__y) {
|
||||
boolean rv = Bool_.Y;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
cur_is_bool = Bool_.__byte;
|
||||
}
|
||||
cur = sub;
|
||||
return true;
|
||||
}
|
||||
public void Section_end() {
|
||||
Mustache_stack_itm itm = (Mustache_stack_itm)List_adp_.Pop(stack);
|
||||
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.cur_is_bool = cur_is_bool;
|
||||
this.subs = subs;
|
||||
this.subs_idx = subs_idx;
|
||||
this.subs_len = subs_len;
|
||||
}
|
||||
public final Mustache_doc_itm cur;
|
||||
public final byte cur_is_bool;
|
||||
public final Mustache_doc_itm[] subs;
|
||||
public final int subs_idx;
|
||||
public final int subs_len;
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
|
||||
public class Mustache_render_ctx {
|
||||
private final List_adp stack = List_adp_.New();
|
||||
private Mustache_doc_itm cur;
|
||||
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;
|
||||
this.subs = null;
|
||||
this.subs_idx = subs_len = 0;
|
||||
this.cur_is_bool = Bool_.__byte;
|
||||
return this;
|
||||
}
|
||||
public boolean Render_variable(Mustache_bfr bfr, String key) {
|
||||
boolean rv = false;
|
||||
int stack_pos = stack.Len();
|
||||
Mustache_doc_itm itm = cur;
|
||||
while (itm != Mustache_doc_itm_.Null_itm) {
|
||||
boolean resolved = itm.Mustache__write(key, bfr);
|
||||
// current itm handles key -> exit
|
||||
if (resolved) {
|
||||
rv = true;
|
||||
break;
|
||||
}
|
||||
// current itm does not handle key -> go up stack
|
||||
else {
|
||||
--stack_pos;
|
||||
if (stack_pos == -1) // nothing else in stack
|
||||
break;
|
||||
else
|
||||
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).cur;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Section_bgn(String key) {
|
||||
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 == null if property does not exist; EX: "folder{{#files}}file{{/files}}" and folder = new Folder(File[0]);
|
||||
subs = Mustache_doc_itm_.Ary__empty;
|
||||
subs_len = subs.length;
|
||||
subs_idx = -1;
|
||||
}
|
||||
public boolean Section_do(boolean inverted) {
|
||||
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
|
||||
if (sub == Mustache_doc_itm_.Itm__bool__n) {
|
||||
boolean rv = Bool_.N;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
else if (sub == Mustache_doc_itm_.Itm__bool__y) {
|
||||
boolean rv = Bool_.Y;
|
||||
if (inverted) rv = !rv;
|
||||
cur_is_bool = Bool_.To_byte(rv);
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
cur_is_bool = Bool_.__byte;
|
||||
}
|
||||
cur = sub;
|
||||
return true;
|
||||
}
|
||||
public void Section_end() {
|
||||
Mustache_stack_itm itm = (Mustache_stack_itm)List_adp_.Pop(stack);
|
||||
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.cur_is_bool = cur_is_bool;
|
||||
this.subs = subs;
|
||||
this.subs_idx = subs_idx;
|
||||
this.subs_len = subs_len;
|
||||
}
|
||||
public final Mustache_doc_itm cur;
|
||||
public final byte cur_is_bool;
|
||||
public final Mustache_doc_itm[] subs;
|
||||
public final int subs_idx;
|
||||
public final int subs_len;
|
||||
}
|
||||
|
@ -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,30 +13,40 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
class Mustache_tkn_def {
|
||||
public byte[] Variable_lhs = Dflt_variable_lhs;
|
||||
public byte[] Variable_rhs = Dflt_variable_rhs;
|
||||
public int Variable_lhs_len;
|
||||
public int Variable_rhs_len;
|
||||
public static final byte[]
|
||||
Dflt_variable_lhs = Bry_.new_a7("{{")
|
||||
, Dflt_variable_rhs = Bry_.new_a7("}}")
|
||||
;
|
||||
public static final byte
|
||||
Variable = Byte_ascii.Curly_end // {{=<% %>=}}
|
||||
, Escape_bgn = Byte_ascii.Curly_bgn // {{{escape}}}
|
||||
, Escape_end = Byte_ascii.Curly_end // {{{escape}}}
|
||||
, Section = Byte_ascii.Hash // {{#section}}
|
||||
, Grp_end = Byte_ascii.Slash // {{/section}}
|
||||
, Inverted = Byte_ascii.Pow // {{^inverted}}
|
||||
, Comment = Byte_ascii.Bang // {{!comment}}
|
||||
, Partial = Byte_ascii.Angle_bgn // {{>partial}}
|
||||
, Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}}
|
||||
, Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}}
|
||||
;
|
||||
public Mustache_tkn_def() {
|
||||
Variable_lhs_len = Variable_lhs.length;
|
||||
Variable_rhs_len = Variable_rhs.length;
|
||||
}
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.String_;
|
||||
|
||||
class Mustache_tkn_def {
|
||||
public byte[] Variable_lhs = Dflt_variable_lhs;
|
||||
public byte[] Variable_rhs = Dflt_variable_rhs;
|
||||
public int Variable_lhs_len;
|
||||
public int Variable_rhs_len;
|
||||
public static final byte[]
|
||||
Dflt_variable_lhs = Bry_.new_a7("{{")
|
||||
, Dflt_variable_rhs = Bry_.new_a7("}}")
|
||||
;
|
||||
public static final byte
|
||||
Variable = Byte_ascii.Curly_end // {{=<% %>=}}
|
||||
, Escape_bgn = Byte_ascii.Curly_bgn // {{{escape}}}
|
||||
, Escape_end = Byte_ascii.Curly_end // {{{escape}}}
|
||||
, Section = Byte_ascii.Hash // {{#section}}
|
||||
, Grp_end = Byte_ascii.Slash // {{/section}}
|
||||
, Inverted = Byte_ascii.Pow // {{^inverted}}
|
||||
, Comment = Byte_ascii.Bang // {{!comment}}
|
||||
, Partial = Byte_ascii.Angle_end // {{>partial}}
|
||||
, Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}}
|
||||
, Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}}
|
||||
, Item = Byte_ascii.Dot // {{.}}
|
||||
;
|
||||
public static final String
|
||||
ItemString = String_.new_u8(Byte_.To_bry(Item))
|
||||
;
|
||||
public Mustache_tkn_def() {
|
||||
Variable_lhs_len = Variable_lhs.length;
|
||||
Variable_rhs_len = Variable_rhs.length;
|
||||
}
|
||||
}
|
||||
|
@ -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,98 +13,114 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
public interface Mustache_tkn_itm {
|
||||
int Tid();
|
||||
String Key();
|
||||
Mustache_tkn_itm[] Subs_ary();
|
||||
void Subs_ary_(Mustache_tkn_itm[] v);
|
||||
void Render(Mustache_bfr bfr, Mustache_render_ctx ctx);
|
||||
}
|
||||
class Mustache_tkn_itm_ {// for types, see http://mustache.github.io/mustache.5.html
|
||||
public static final int Tid__root = 0, Tid__text = 1, Tid__variable = 2, Tid__escape = 3, Tid__section = 4, Tid__inverted = 5, Tid__comment = 6, Tid__partial = 7, Tid__delimiter = 8;
|
||||
public static final Mustache_tkn_itm[] Ary_empty = new Mustache_tkn_itm[0];
|
||||
}
|
||||
abstract class Mustache_tkn_base implements Mustache_tkn_itm {
|
||||
public Mustache_tkn_base(int tid, byte[] key_bry) {this.tid = tid; this.key = String_.new_u8(key_bry);}
|
||||
public int Tid() {return tid;} private final int tid;
|
||||
public String Key() {return key;} private final String key;
|
||||
@gplx.Virtual public Mustache_tkn_itm[] Subs_ary() {return Mustache_tkn_itm_.Ary_empty;}
|
||||
@gplx.Virtual public void Subs_ary_(Mustache_tkn_itm[] v) {throw Err_.new_unsupported();} // fail if trying to set and not overridden
|
||||
@gplx.Virtual public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {throw Err_.new_unsupported();} // should be abstract
|
||||
}
|
||||
class Mustache_tkn_root extends Mustache_tkn_base { // EX: {{variable}} -> <a>
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_root() {super(Mustache_tkn_itm_.Tid__root, Bry_.Empty);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
int subs_len = subs_ary.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Mustache_tkn_itm sub = subs_ary[i];
|
||||
sub.Render(bfr, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_text extends Mustache_tkn_base { // EX: text -> text
|
||||
private final byte[] src; private final int src_bgn, src_end;
|
||||
public Mustache_tkn_text(byte[] src, int src_bgn, int src_end) {super(Mustache_tkn_itm_.Tid__text, Bry_.Empty);
|
||||
this.src = src;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
bfr.Add_mid(src, src_bgn, src_end);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_comment extends Mustache_tkn_base { // EX: {{!section}}comment{{/section}} ->
|
||||
public Mustache_tkn_comment() {super(Mustache_tkn_itm_.Tid__comment, Bry_.Empty);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {}
|
||||
}
|
||||
class Mustache_tkn_variable extends Mustache_tkn_base { // EX: {{variable}} -> <a>
|
||||
public Mustache_tkn_variable(byte[] key) {super(Mustache_tkn_itm_.Tid__variable, key);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = this.Key();
|
||||
ctx.Render_variable(bfr.Escape_(Bool_.Y), key);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_escape extends Mustache_tkn_base { // EX: {{{variable}}} -> <a>
|
||||
public Mustache_tkn_escape(byte[] key) {super(Mustache_tkn_itm_.Tid__escape, key);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = this.Key();
|
||||
ctx.Render_variable(bfr.Escape_(Bool_.N), key);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_section extends Mustache_tkn_base { // EX: {{#section}}val{{/section}} -> val (if boolean) or valvalval (if list)
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_section(byte[] key) {super(Mustache_tkn_itm_.Tid__section, key);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {Render_static(Bool_.N, this, bfr, ctx);}
|
||||
public static void Render_static(boolean inverted, Mustache_tkn_base tkn, Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = tkn.Key();
|
||||
Mustache_tkn_itm[] subs_ary = tkn.Subs_ary();
|
||||
ctx.Section_bgn(key);
|
||||
while (ctx.Section_do(inverted)) {
|
||||
int subs_len = subs_ary.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Mustache_tkn_itm sub = subs_ary[i];
|
||||
sub.Render(bfr, ctx);
|
||||
}
|
||||
}
|
||||
ctx.Section_end();
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_inverted extends Mustache_tkn_base { // EX: {{^section}}missing{{/section}} -> missing
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_inverted(byte[] key) {super(Mustache_tkn_itm_.Tid__inverted, key);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@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);}
|
||||
}
|
||||
class Mustache_tkn_delimiter extends Mustache_tkn_base {// EX: {{=<% %>=}} -> <% variable %>
|
||||
public Mustache_tkn_delimiter(byte[] key) {super(Mustache_tkn_itm_.Tid__delimiter, key);}
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Err_;
|
||||
import gplx.Io_url;
|
||||
import gplx.String_;
|
||||
|
||||
public interface Mustache_tkn_itm {
|
||||
int Tid();
|
||||
String Key();
|
||||
Mustache_tkn_itm[] Subs_ary();
|
||||
void Subs_ary_(Mustache_tkn_itm[] v);
|
||||
void Render(Mustache_bfr bfr, Mustache_render_ctx ctx);
|
||||
}
|
||||
class Mustache_tkn_itm_ {// for types, see http://mustache.github.io/mustache.5.html
|
||||
public static final int Tid__root = 0, Tid__text = 1, Tid__variable = 2, Tid__escape = 3, Tid__section = 4, Tid__inverted = 5, Tid__comment = 6, Tid__partial = 7, Tid__delimiter = 8;
|
||||
public static final Mustache_tkn_itm[] Ary_empty = new Mustache_tkn_itm[0];
|
||||
}
|
||||
abstract class Mustache_tkn_base implements Mustache_tkn_itm {
|
||||
public Mustache_tkn_base(int tid, byte[] key_bry) {this.tid = tid; this.key = String_.new_u8(key_bry);}
|
||||
public int Tid() {return tid;} private final int tid;
|
||||
public String Key() {return key;} private final String key;
|
||||
@gplx.Virtual public Mustache_tkn_itm[] Subs_ary() {return Mustache_tkn_itm_.Ary_empty;}
|
||||
@gplx.Virtual public void Subs_ary_(Mustache_tkn_itm[] v) {throw Err_.new_unsupported();} // fail if trying to set and not overridden
|
||||
@gplx.Virtual public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {throw Err_.new_unsupported();} // should be abstract
|
||||
}
|
||||
class Mustache_tkn_root extends Mustache_tkn_base { // EX: {{variable}} -> <a>
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_root() {super(Mustache_tkn_itm_.Tid__root, Bry_.Empty);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
int subs_len = subs_ary.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Mustache_tkn_itm sub = subs_ary[i];
|
||||
sub.Render(bfr, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_text extends Mustache_tkn_base { // EX: text -> text
|
||||
private final byte[] src; private final int src_bgn, src_end;
|
||||
public Mustache_tkn_text(byte[] src, int src_bgn, int src_end) {super(Mustache_tkn_itm_.Tid__text, Bry_.Empty);
|
||||
this.src = src;
|
||||
this.src_bgn = src_bgn;
|
||||
this.src_end = src_end;
|
||||
}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
bfr.Add_mid(src, src_bgn, src_end);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_comment extends Mustache_tkn_base { // EX: {{!section}}comment{{/section}} ->
|
||||
public Mustache_tkn_comment() {super(Mustache_tkn_itm_.Tid__comment, Bry_.Empty);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {}
|
||||
}
|
||||
class Mustache_tkn_variable extends Mustache_tkn_base { // EX: {{variable}} -> <a>
|
||||
public Mustache_tkn_variable(byte[] key) {super(Mustache_tkn_itm_.Tid__variable, key);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = this.Key();
|
||||
ctx.Render_variable(bfr.Escape_(Bool_.Y), key);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_escape extends Mustache_tkn_base { // EX: {{{variable}}} -> <a>
|
||||
public Mustache_tkn_escape(byte[] key) {super(Mustache_tkn_itm_.Tid__escape, key);}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = this.Key();
|
||||
ctx.Render_variable(bfr.Escape_(Bool_.N), key);
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_section extends Mustache_tkn_base { // EX: {{#section}}val{{/section}} -> val (if boolean) or valvalval (if list)
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_section(byte[] key) {super(Mustache_tkn_itm_.Tid__section, key);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {Render_static(Bool_.N, this, bfr, ctx);}
|
||||
public static void Render_static(boolean inverted, Mustache_tkn_base tkn, Mustache_bfr bfr, Mustache_render_ctx ctx) {
|
||||
String key = tkn.Key();
|
||||
Mustache_tkn_itm[] subs_ary = tkn.Subs_ary();
|
||||
ctx.Section_bgn(key);
|
||||
while (ctx.Section_do(inverted)) {
|
||||
int subs_len = subs_ary.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Mustache_tkn_itm sub = subs_ary[i];
|
||||
sub.Render(bfr, ctx);
|
||||
}
|
||||
}
|
||||
ctx.Section_end();
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_inverted extends Mustache_tkn_base { // EX: {{^section}}missing{{/section}} -> missing
|
||||
private Mustache_tkn_itm[] subs_ary;
|
||||
public Mustache_tkn_inverted(byte[] key) {super(Mustache_tkn_itm_.Tid__inverted, key);}
|
||||
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
|
||||
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
|
||||
@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)
|
||||
private Mustache_tkn_itm template_root;
|
||||
public Mustache_tkn_partial(byte[] key, Io_url dir) {
|
||||
super(Mustache_tkn_itm_.Tid__partial, key);
|
||||
Mustache_tkn_parser parser = new Mustache_tkn_parser(dir);
|
||||
template_root = parser.Parse(String_.new_a7(Bry_.Trim_bgn(key, Byte_ascii.Space, 0)));
|
||||
}
|
||||
@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);}
|
||||
}
|
||||
|
@ -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,140 +13,162 @@ 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.mustaches; import gplx.*; import gplx.langs.*;
|
||||
public class Mustache_tkn_parser {
|
||||
private byte[] src; private int src_end;
|
||||
private final Mustache_tkn_def tkn_def = new Mustache_tkn_def();
|
||||
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;
|
||||
Mustache_tkn_root root = new Mustache_tkn_root();
|
||||
Parse_grp(root, src_bgn);
|
||||
return root;
|
||||
}
|
||||
private int Parse_grp(Mustache_tkn_itm owner, int src_bgn) {
|
||||
List_adp subs_list = List_adp_.New();
|
||||
int txt_bgn = src_bgn;
|
||||
boolean end_grp = false;
|
||||
while (true) {// loop for "{{"
|
||||
int lhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_lhs, txt_bgn, src_end); // next "{{"
|
||||
if (lhs_bgn == Bry_find_.Not_found) { // no more "{{"
|
||||
subs_list.Add(new Mustache_tkn_text(src, txt_bgn, src_end)); // add everything between prv "}}" and cur "{{"
|
||||
break;
|
||||
}
|
||||
int lhs_end = lhs_bgn + tkn_def.Variable_lhs_len;
|
||||
|
||||
Mustache_tkn_data tkn_data = new Mustache_tkn_data(src[lhs_end]); // preview tkn
|
||||
lhs_end += tkn_data.lhs_end_adj;
|
||||
|
||||
int rhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_rhs, lhs_end, src_end); // next "}}"
|
||||
if (rhs_bgn == Bry_find_.Not_found) throw Fail(lhs_bgn, "unclosed tag"); // fail if no "}}"
|
||||
int rhs_end = rhs_bgn + tkn_def.Variable_rhs_len;
|
||||
if (tkn_data.rhs_bgn_chk != Byte_ascii.Null) {
|
||||
if (src[rhs_bgn] != tkn_data.rhs_bgn_chk) throw Fail(lhs_end, "invalid check byte");
|
||||
++rhs_end; // skip the chk_byte; note that bottom of function will skip "}}" by adding +2
|
||||
}
|
||||
|
||||
|
||||
int txt_end = lhs_bgn; // get text tkn
|
||||
if (tkn_data.ws_ignore) {
|
||||
int new_txt_bgn = Trim_bwd_to_nl(src, txt_bgn, txt_end);
|
||||
if (new_txt_bgn != -1) {
|
||||
int new_txt_end = Trim_fwd_to_nl(src, rhs_end, src_end);
|
||||
if (new_txt_end != -1) {
|
||||
txt_end = new_txt_bgn;
|
||||
rhs_end = new_txt_end == src_end ? src_end : new_txt_end + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_end > txt_bgn) // ignore 0-byte text tkns; occurs when consecutive tkns; EX: {{v1}}{{v2}} will try to create text tkn between "}}{{"
|
||||
subs_list.Add(new Mustache_tkn_text(src, txt_bgn, txt_end)); // add everything between prv "}}" and cur "{{"
|
||||
|
||||
txt_bgn = Parse_itm(tkn_data, subs_list, lhs_end, rhs_bgn, rhs_end); // do parse
|
||||
if (txt_bgn < 0) { // NOTE: txt_bgn < 0 means end grp
|
||||
txt_bgn *= -1;
|
||||
end_grp = true;
|
||||
}
|
||||
if (end_grp) break;
|
||||
}
|
||||
if (subs_list.Count() > 0) // don't create subs if no members
|
||||
owner.Subs_ary_((Mustache_tkn_itm[])subs_list.To_ary_and_clear(Mustache_tkn_itm.class));
|
||||
return txt_bgn;
|
||||
}
|
||||
private int Parse_itm(Mustache_tkn_data tkn_data, List_adp subs_list, int lhs_end, int rhs_bgn, int rhs_end) {
|
||||
byte[] val_bry = Bry_.Mid(src, lhs_end, rhs_bgn);
|
||||
Mustache_tkn_base tkn = null;
|
||||
switch (tkn_data.tid) {
|
||||
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.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;
|
||||
case Mustache_tkn_def.Inverted: tkn = new Mustache_tkn_inverted(val_bry); break;
|
||||
case Mustache_tkn_def.Grp_end: {
|
||||
return -(rhs_end); // pop the stack
|
||||
}
|
||||
}
|
||||
subs_list.Add(tkn);
|
||||
if (tkn_data.parse_grp) {
|
||||
return Parse_grp(tkn, rhs_end);
|
||||
}
|
||||
else
|
||||
return rhs_end;
|
||||
}
|
||||
private Err Fail(int pos, String fmt, Object... args) {
|
||||
return Err_.new_("mustache", fmt, "excerpt", Bry_.Mid_by_len_safe(src, pos, 32));
|
||||
}
|
||||
private static int Trim_bwd_to_nl(byte[] src, int txt_bgn, int txt_end) {
|
||||
int stop = txt_bgn - 1;
|
||||
int pos = txt_end - 1;
|
||||
while (pos > stop) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab:
|
||||
case Byte_ascii.Space: --pos; break;
|
||||
case Byte_ascii.Nl: return pos + 1; // 1 char after \n
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private static int Trim_fwd_to_nl(byte[] src, int txt_bgn, int txt_end) {
|
||||
int pos = txt_bgn;
|
||||
while (pos < txt_end) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab:
|
||||
case Byte_ascii.Space: ++pos; break;
|
||||
case Byte_ascii.Nl: return pos;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_data {
|
||||
public int tid;
|
||||
public int lhs_end_adj;
|
||||
public byte rhs_bgn_chk;
|
||||
public boolean parse_grp;
|
||||
public boolean ws_ignore;
|
||||
public Mustache_tkn_data(byte b) {
|
||||
tid = b;
|
||||
parse_grp = ws_ignore = false;
|
||||
lhs_end_adj = 1;
|
||||
rhs_bgn_chk = Byte_ascii.Null;
|
||||
switch (b) {
|
||||
default: lhs_end_adj = 0; tid = Mustache_tkn_def.Variable; break;
|
||||
case Mustache_tkn_def.Comment:
|
||||
case Mustache_tkn_def.Partial:
|
||||
case Mustache_tkn_def.Grp_end: ws_ignore = true; break;
|
||||
case Mustache_tkn_def.Delimiter_bgn: rhs_bgn_chk = Mustache_tkn_def.Delimiter_end; break; // check for "=}}"; TODO_OLD: implement delimiter; EX: {{=<% %>=}}
|
||||
case Mustache_tkn_def.Escape_bgn: rhs_bgn_chk = Mustache_tkn_def.Escape_end; break; // check for ""
|
||||
case Mustache_tkn_def.Section:
|
||||
case Mustache_tkn_def.Inverted: ws_ignore = true; parse_grp = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
package gplx.langs.mustaches;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_find_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Err;
|
||||
import gplx.Err_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.Io_url;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
|
||||
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;
|
||||
Mustache_tkn_root root = new Mustache_tkn_root();
|
||||
Parse_grp(root, src_bgn);
|
||||
return root;
|
||||
}
|
||||
private int Parse_grp(Mustache_tkn_itm owner, int src_bgn) {
|
||||
List_adp subs_list = List_adp_.New();
|
||||
int txt_bgn = src_bgn;
|
||||
boolean end_grp = false;
|
||||
while (true) {// loop for "{{"
|
||||
int lhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_lhs, txt_bgn, src_end); // next "{{"
|
||||
if (lhs_bgn == Bry_find_.Not_found) { // no more "{{"
|
||||
subs_list.Add(new Mustache_tkn_text(src, txt_bgn, src_end)); // add everything between prv "}}" and cur "{{"
|
||||
break;
|
||||
}
|
||||
int lhs_end = lhs_bgn + tkn_def.Variable_lhs_len;
|
||||
|
||||
Mustache_tkn_data tkn_data = new Mustache_tkn_data(src[lhs_end]); // preview tkn
|
||||
lhs_end += tkn_data.lhs_end_adj;
|
||||
|
||||
int rhs_bgn = Bry_find_.Find_fwd(src, tkn_def.Variable_rhs, lhs_end, src_end); // next "}}"
|
||||
if (rhs_bgn == Bry_find_.Not_found) throw Fail(lhs_bgn, "unclosed tag"); // fail if no "}}"
|
||||
int rhs_end = rhs_bgn + tkn_def.Variable_rhs_len;
|
||||
if (tkn_data.rhs_bgn_chk != Byte_ascii.Null) {
|
||||
if (src[rhs_bgn] != tkn_data.rhs_bgn_chk) throw Fail(lhs_end, "invalid check byte");
|
||||
++rhs_end; // skip the chk_byte; note that bottom of function will skip "}}" by adding +2
|
||||
}
|
||||
|
||||
|
||||
int txt_end = lhs_bgn; // get text tkn
|
||||
if (tkn_data.ws_ignore) {
|
||||
int new_txt_bgn = Trim_bwd_to_nl(src, txt_bgn, txt_end);
|
||||
if (new_txt_bgn != -1) {
|
||||
int new_txt_end = Trim_fwd_to_nl(src, rhs_end, src_end);
|
||||
if (new_txt_end != -1) {
|
||||
txt_end = new_txt_bgn;
|
||||
rhs_end = new_txt_end == src_end ? src_end : new_txt_end + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_end > txt_bgn) // ignore 0-byte text tkns; occurs when consecutive tkns; EX: {{v1}}{{v2}} will try to create text tkn between "}}{{"
|
||||
subs_list.Add(new Mustache_tkn_text(src, txt_bgn, txt_end)); // add everything between prv "}}" and cur "{{"
|
||||
|
||||
txt_bgn = Parse_itm(tkn_data, subs_list, lhs_end, rhs_bgn, rhs_end); // do parse
|
||||
if (txt_bgn < 0) { // NOTE: txt_bgn < 0 means end grp
|
||||
txt_bgn *= -1;
|
||||
end_grp = true;
|
||||
}
|
||||
if (end_grp) break;
|
||||
}
|
||||
if (subs_list.Count() > 0) // don't create subs if no members
|
||||
owner.Subs_ary_((Mustache_tkn_itm[])subs_list.To_ary_and_clear(Mustache_tkn_itm.class));
|
||||
return txt_bgn;
|
||||
}
|
||||
private int Parse_itm(Mustache_tkn_data tkn_data, List_adp subs_list, int lhs_end, int rhs_bgn, int rhs_end) {
|
||||
byte[] val_bry = Bry_.Mid(src, lhs_end, rhs_bgn);
|
||||
Mustache_tkn_base tkn = null;
|
||||
switch (tkn_data.tid) {
|
||||
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, 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;
|
||||
case Mustache_tkn_def.Inverted: tkn = new Mustache_tkn_inverted(val_bry); break;
|
||||
case Mustache_tkn_def.Grp_end: {
|
||||
return -(rhs_end); // pop the stack
|
||||
}
|
||||
}
|
||||
subs_list.Add(tkn);
|
||||
if (tkn_data.parse_grp) {
|
||||
return Parse_grp(tkn, rhs_end);
|
||||
}
|
||||
else
|
||||
return rhs_end;
|
||||
}
|
||||
private Err Fail(int pos, String fmt, Object... args) {
|
||||
return Err_.new_("mustache", fmt, "excerpt", Bry_.Mid_by_len_safe(src, pos, 32));
|
||||
}
|
||||
private static int Trim_bwd_to_nl(byte[] src, int txt_bgn, int txt_end) {
|
||||
int stop = txt_bgn - 1;
|
||||
int pos = txt_end - 1;
|
||||
while (pos > stop) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab:
|
||||
case Byte_ascii.Space: --pos; break;
|
||||
case Byte_ascii.Nl: return pos + 1; // 1 char after \n
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private static int Trim_fwd_to_nl(byte[] src, int txt_bgn, int txt_end) {
|
||||
int pos = txt_bgn;
|
||||
while (pos < txt_end) {
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab:
|
||||
case Byte_ascii.Space: ++pos; break;
|
||||
case Byte_ascii.Nl: return pos;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
class Mustache_tkn_data {
|
||||
public int tid;
|
||||
public int lhs_end_adj;
|
||||
public byte rhs_bgn_chk;
|
||||
public boolean parse_grp;
|
||||
public boolean ws_ignore;
|
||||
public Mustache_tkn_data(byte b) {
|
||||
tid = b;
|
||||
parse_grp = ws_ignore = false;
|
||||
lhs_end_adj = 1;
|
||||
rhs_bgn_chk = Byte_ascii.Null;
|
||||
switch (b) {
|
||||
default: lhs_end_adj = 0; tid = Mustache_tkn_def.Variable; break;
|
||||
case Mustache_tkn_def.Comment:
|
||||
case Mustache_tkn_def.Partial:
|
||||
case Mustache_tkn_def.Grp_end: ws_ignore = true; break;
|
||||
case Mustache_tkn_def.Delimiter_bgn: rhs_bgn_chk = Mustache_tkn_def.Delimiter_end; break; // check for "=}}"; TODO_OLD: implement delimiter; EX: {{=<% %>=}}
|
||||
case Mustache_tkn_def.Escape_bgn: rhs_bgn_chk = Mustache_tkn_def.Escape_end; break; // check for ""
|
||||
case Mustache_tkn_def.Section:
|
||||
case Mustache_tkn_def.Inverted: ws_ignore = true; parse_grp = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,275 @@
|
||||
package gplx.xowa.addons.htmls.sidebars;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Io_url;
|
||||
import gplx.String_;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.mustaches.JsonMustacheNde;
|
||||
import gplx.langs.mustaches.Mustache_bfr;
|
||||
import gplx.langs.mustaches.Mustache_render_ctx;
|
||||
import gplx.langs.mustaches.Mustache_tkn_itm;
|
||||
import gplx.langs.mustaches.Mustache_tkn_parser;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
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(new JsonMustacheNde(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 = Json_nde.NewByVal();
|
||||
for (int i = 0; i < msg_len; i++) {
|
||||
String msg = msgs[i];
|
||||
msgdata.AddKvStr("msg-" + msg, msg_mgr.Val_by_str_or_empty(msg));
|
||||
}
|
||||
}
|
||||
private void Test() {
|
||||
Json_nde jnde = Json_nde.NewByVal();
|
||||
jnde.AddKvStr("class", "CLASS");
|
||||
jnde.AddKvStr("text", "TEXT");
|
||||
jnde.AddKvStr("href", "URL_str");
|
||||
jnde.AddKvBool("exists", true);
|
||||
jnde.AddKvBool("primary", true);
|
||||
jnde.AddKvStr("link-class", String_.Empty);
|
||||
jnde.AddKvStr("context", "subject");
|
||||
|
||||
Json_nde namespaces = Json_nde.NewByVal();
|
||||
namespaces.AddKvNde("subject", jnde);
|
||||
|
||||
//Json_nde data_namespaces = new Json_nde(null, -1);
|
||||
msgdata.AddKvNde("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(new JsonMustacheNde(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_bry, 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",
|
||||
|
||||
String label = String_.new_u8(label_bry);
|
||||
String msg = label; // for now
|
||||
String linkertooltip = String_.Empty;
|
||||
String listClasses = type == MENU_TYPE_DROPDOWN
|
||||
? "menu vector-menu-content-list"
|
||||
: "vector-menu-content-list";
|
||||
String plabel = "p-" + label;
|
||||
|
||||
Json_nde props = Json_nde.NewByVal();
|
||||
props.AddKvStr("id", plabel);
|
||||
|
||||
// 'label-id' => "p-{$label}-label",
|
||||
props.AddKvStr("label-id", plabel +"-label");
|
||||
|
||||
// If no message exists fallback to plain text (T252727)
|
||||
// 'label' => $msgObj->exists() ? $msgObj->text() : $label,
|
||||
props.AddKvStr("label", msg);
|
||||
|
||||
// 'list-classes' => $listClasses[$type] ?? 'vector-menu-content-list',
|
||||
props.AddKvStr("list-classes", listClasses);
|
||||
|
||||
// 'html-items' => '',
|
||||
|
||||
// 'is-dropdown' => $type === self::MENU_TYPE_DROPDOWN,
|
||||
props.AddKvBool("is-dropdown", type == MENU_TYPE_DROPDOWN);
|
||||
props.AddKvStr("html-tooltip", wiki.Msg_mgr().Val_html_accesskey_and_title(plabel));
|
||||
|
||||
// 'html-tooltip' => Linker::tooltip( 'p-' . $label ),
|
||||
props.AddKvStr("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.AddKvStr("html-items", "<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.AddKvStr("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_bry, byte[] urls, int type, boolean setLabelToSelected) {
|
||||
boolean isPortal = type == MENU_TYPE_PORTAL;
|
||||
|
||||
String label = String_.new_u8(label_bry);
|
||||
String msg = label; // for now
|
||||
String linkertooltip = String_.Empty;
|
||||
String listClasses = type == MENU_TYPE_DROPDOWN
|
||||
? "menu vector-menu-content-list"
|
||||
: "vector-menu-content-list";
|
||||
String plabel = "p-" + label;
|
||||
|
||||
Json_nde props = Json_nde.NewByVal();
|
||||
props.AddKvStr("id", plabel);
|
||||
props.AddKvStr("label-id", plabel +"-label");
|
||||
props.AddKvStr("label", msg);
|
||||
props.AddKvStr("list-classes", listClasses);
|
||||
props.AddKvBool("is-dropdown", type == MENU_TYPE_DROPDOWN);
|
||||
props.AddKvStr("html-tooltip", wiki.Msg_mgr().Val_html_accesskey_and_title(plabel));
|
||||
props.AddKvStr("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.AddKvStr("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.AddKvStr("class", extraClasses[type]);
|
||||
return props;
|
||||
}
|
||||
}
|
@ -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,44 +13,60 @@ 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.*;
|
||||
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();
|
||||
int len = grps.Count();
|
||||
boolean popups_enabled = wiki.Html_mgr().Head_mgr().Popup_mgr().Enabled();
|
||||
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);
|
||||
}
|
||||
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}"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
, ""
|
||||
);
|
||||
}
|
||||
class Xoh_sidebar_itms_fmtr implements Bfr_arg {
|
||||
private boolean popups_enabled; private Xoh_sidebar_itm grp;
|
||||
public void Init_by_grp(boolean popups_enabled, Xoh_sidebar_itm grp) {this.popups_enabled = popups_enabled; this.grp = grp;}
|
||||
public void Bfr_arg__add(Bry_bfr bfr) {
|
||||
String itm_cls = popups_enabled ? " class='xowa-hover-off'" : "";
|
||||
int len = grp.Subs__len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoh_sidebar_itm itm = grp.Subs__get_at(i);
|
||||
fmt.Bld_many(bfr, itm.Id(), itm.Href(), itm_cls, itm.Atr_accesskey_and_title(), itm.Text());
|
||||
}
|
||||
}
|
||||
private final Bry_fmt fmt = Bry_fmt.Auto_nl_skip_last
|
||||
( ""
|
||||
, " <li id=\"~{itm_id}\"><a href=\"~{itm_href}\"~{itm_cls}~{itm_accesskey_and_title}>~{itm_text}</a></li>"
|
||||
);
|
||||
}
|
||||
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.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();
|
||||
int len = grps.Count();
|
||||
boolean popups_enabled = wiki.Html_mgr().Head_mgr().Popup_mgr().Enabled();
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
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);
|
||||
itms_fmtr.Bfr_arg__add(tmp_bfr);
|
||||
Db_Nav_template.Build_Sidebar(wiki, bfr, grp.Id(), grp.Text(), tmp_bfr.To_bry_and_clear());
|
||||
}
|
||||
// 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 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>"
|
||||
, ""
|
||||
);
|
||||
}
|
||||
class Xoh_sidebar_itms_fmtr implements Bfr_arg {
|
||||
private boolean popups_enabled; private Xoh_sidebar_itm grp;
|
||||
public void Init_by_grp(boolean popups_enabled, Xoh_sidebar_itm grp) {this.popups_enabled = popups_enabled; this.grp = grp;}
|
||||
public void Bfr_arg__add(Bry_bfr bfr) {
|
||||
String itm_cls = popups_enabled ? " class='xowa-hover-off'" : "";
|
||||
int len = grp.Subs__len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoh_sidebar_itm itm = grp.Subs__get_at(i);
|
||||
fmt.Bld_many(bfr, itm.Id(), itm.Href(), itm_cls, itm.Atr_accesskey_and_title(), itm.Text());
|
||||
}
|
||||
}
|
||||
private final Bry_fmt fmt = Bry_fmt.Auto_nl_skip_last
|
||||
( ""
|
||||
, " <li id=\"~{itm_id}\"><a href=\"~{itm_href}\"~{itm_cls}~{itm_accesskey_and_title}>~{itm_text}</a></li>"
|
||||
);
|
||||
}
|
||||
|
@ -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,223 +13,242 @@ 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.*;
|
||||
public class Xoh_sidebar_mgr_tst {
|
||||
@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");
|
||||
fxt.Test__objs(fxt.Make__grp("text", "title"));
|
||||
}
|
||||
@Test public void Grp_missing_msg() {
|
||||
fxt.Exec__make("* key");
|
||||
fxt.Test__objs(fxt.Make__grp("key", Null_str));
|
||||
}
|
||||
@Test public void Itm() {
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
|
||||
}
|
||||
@Test public void Itm_missing_msg() {
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Href_key"));
|
||||
}
|
||||
@Test public void Itm_text() { // PURPOSE: only text msg exists; EX: ** Portal:Contents|contents; no href, accesskey, title
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", Null_str, Null_str, Null_str); // only define msg for text
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("text", Null_str, Null_str, "/wiki/Href_key"));
|
||||
}
|
||||
@Test public void Itm_href_absolute() {
|
||||
fxt.Exec__make("** http://a.org|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "http://a.org"));
|
||||
}
|
||||
@Test public void Itm_href_manual() {
|
||||
fxt.Exec__make("** Help:Contents|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Help:Contents"));
|
||||
}
|
||||
@Test public void Itm_href_xwiki() {
|
||||
Xop_fxt.Reg_xwiki_alias(fxt.Wiki(), "c", "commons.wikimedia.org");
|
||||
fxt.Exec__make("** c:Help:Contents|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/site/commons.wikimedia.org/wiki/Help:Contents"));
|
||||
}
|
||||
@Test public void Itm_err_missing_key() {
|
||||
fxt.Exec__make("** no_main_key");
|
||||
fxt.Test__objs();
|
||||
}
|
||||
@Test public void Itm_ignore() { // PURPOSE: ignore SEARCH, TOOLBOX, LANGUAGES
|
||||
fxt.Exec__make
|
||||
( "** SEARCH"
|
||||
, "** TOOLBOX"
|
||||
, "** LANGUAGES"
|
||||
);
|
||||
fxt.Test__objs();
|
||||
}
|
||||
@Test public void Itm_comment() { // PURPOSE: ignore comment; EX:de.v:MediaWiki:Sidebar; DATE:2014-03-08
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
|
||||
fxt.Exec__make("** href_key<!--a-->|main_key<!--b-->");
|
||||
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
|
||||
}
|
||||
@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);
|
||||
fxt.Exec__make
|
||||
( "* navigation"
|
||||
, "** mainpage|mainpage-description"
|
||||
, "** Portal:Contents|contents"
|
||||
, "* SEARCH"
|
||||
, "* interaction"
|
||||
, "** helppage|help"
|
||||
, "* TOOLBOX"
|
||||
, "** TOOLBOXEND"
|
||||
, "* LANGUAGES"
|
||||
);
|
||||
fxt.Test__objs
|
||||
( fxt.Make__grp("Grp_0_text", "Grp_0_title").Subs__add
|
||||
( fxt.Make__itm("Itm_0_text", "Itm_0_title [a]", "a", "/wiki/Itm_0_href")
|
||||
, fxt.Make__itm("Itm_1_text", Null_str, Null_str, "/wiki/Portal:Contents")
|
||||
)
|
||||
, fxt.Make__grp("interaction", Null_str).Subs__add
|
||||
( fxt.Make__itm("help", Null_str, Null_str, "/wiki/Helppage")
|
||||
));
|
||||
fxt.Test__html
|
||||
( "<div class=\"portal\" id=\"n-navigation\">"
|
||||
, " <h3>Grp_0_text</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Itm_0_href\" accesskey=\"a\" title=\"Itm_0_title [a] [a]\">Itm_0_text</a></li>"
|
||||
, " <li id=\"n-contents\"><a href=\"/wiki/Portal:Contents\" title=\"\">Itm_1_text</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
, "<div class=\"portal\" id=\"n-interaction\">"
|
||||
, " <h3>interaction</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-help\"><a href=\"/wiki/Helppage\" title=\"\">help</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</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 {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Xoh_sidebar_mgr sidebar_mgr; private Bry_bfr bfr;
|
||||
public Xoh_sidebar_mgr_fxt Clear() {
|
||||
app = Xoa_app_fxt.Make__app__edit();
|
||||
wiki = Xoa_app_fxt.Make__wiki__edit(app);
|
||||
sidebar_mgr = wiki.Html_mgr().Portal_mgr().Sidebar_mgr();
|
||||
bfr = Bry_bfr_.Reset(Io_mgr.Len_kb);
|
||||
Init__popups_enabled(false);
|
||||
return this;
|
||||
}
|
||||
public Xowe_wiki Wiki() {return wiki;}
|
||||
public Xoh_sidebar_itm Make__grp(String text, String title, Xoh_sidebar_itm... itms) {
|
||||
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.N, Bry_.new_a7(text), Bry_.new_a7(text), null);
|
||||
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), null, null);
|
||||
return rv;
|
||||
}
|
||||
public Xoh_sidebar_itm Make__itm(String text, String title, String accesskey, String href) {
|
||||
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.Y, Bry_.new_a7(text), Bry_.new_a7(text), Bry_.new_a7(href));
|
||||
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), Bry_.new_a7(accesskey), null);
|
||||
return rv;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__popups_enabled(boolean v) {
|
||||
wiki.Html_mgr().Head_mgr().Popup_mgr().Enabled_(v);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__msg__grp(String key, String text, String title) {
|
||||
Init_msg(key, text);
|
||||
Init_msg("tooltip-n-" + key, title);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__msg__itm(String href_key, String main_key, String text, String title, String accesskey, String href) {
|
||||
if (text != null) Init_msg(main_key, text);
|
||||
if (href != null) Init_msg(href_key, href);
|
||||
if (title != null) Init_msg("tooltip-n-" + main_key, title);
|
||||
if (accesskey != null) Init_msg("accesskey-n-" + main_key, accesskey);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init_msg(String key, String val) {
|
||||
Xol_msg_mgr msg_mgr = wiki.Lang().Msg_mgr();
|
||||
Xol_msg_itm msg_itm = msg_mgr.Itm_by_key_or_new(Bry_.new_a7(key));
|
||||
msg_itm.Atrs_set(Bry_.new_a7(val), false, String_.Has(val, "{{"));
|
||||
return this;
|
||||
}
|
||||
public void Exec__make(String... raw) {
|
||||
sidebar_mgr.Make(bfr, Bry_.new_u8(String_.Concat_lines_nl_skip_last(raw)));
|
||||
}
|
||||
public void Test__objs(Xoh_sidebar_itm... expd) {
|
||||
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
|
||||
}
|
||||
public void Test__objs(String raw, Xoh_sidebar_itm... expd) {
|
||||
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
|
||||
}
|
||||
public void Test__html(String... expd) {
|
||||
Tfds.Eq_str_lines(String_.Concat_lines_nl_skip_last(expd), String_.new_u8(sidebar_mgr.Html_bry()));
|
||||
}
|
||||
private static String To_str_by_mgr(Xoh_sidebar_mgr mgr) {
|
||||
List_adp grps = mgr.Grps();
|
||||
int len = grps.Len();
|
||||
Xoh_sidebar_itm[] ary = new Xoh_sidebar_itm[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
ary[i] = (Xoh_sidebar_itm)grps.Get_at(i);
|
||||
return To_str_by_itms(ary);
|
||||
}
|
||||
|
||||
private static String To_str_by_itms(Xoh_sidebar_itm[] ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++)
|
||||
To_str_by_itm(bfr, ary[i]);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
private static void To_str_by_itm(Bry_bfr bfr, Xoh_sidebar_itm cur) {
|
||||
boolean tid_is_itm = cur.Tid_is_itm();
|
||||
bfr.Add_str_a7(tid_is_itm ? "itm|" : "grp|");
|
||||
bfr.Add(cur.Text()).Add_byte_pipe();
|
||||
bfr.Add(cur.Title()).Add_byte_pipe();
|
||||
if (tid_is_itm) {
|
||||
bfr.Add(cur.Accesskey()).Add_byte_pipe();
|
||||
bfr.Add(cur.Href()).Add_byte_pipe();
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
|
||||
int len = cur.Subs__len();
|
||||
for (int i = 0; i< len; ++i)
|
||||
To_str_by_itm(bfr, cur.Subs__get_at(i));
|
||||
}
|
||||
}
|
||||
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();
|
||||
@Test public void Grp() {
|
||||
fxt.Init__msg__grp("key", "text", "title");
|
||||
fxt.Exec__make("* key");
|
||||
fxt.Test__objs(fxt.Make__grp("text", "title"));
|
||||
}
|
||||
@Test public void Grp_missing_msg() {
|
||||
fxt.Exec__make("* key");
|
||||
fxt.Test__objs(fxt.Make__grp("key", Null_str));
|
||||
}
|
||||
@Test public void Itm() {
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
|
||||
}
|
||||
@Test public void Itm_missing_msg() {
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Href_key"));
|
||||
}
|
||||
@Test public void Itm_text() { // PURPOSE: only text msg exists; EX: ** Portal:Contents|contents; no href, accesskey, title
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", Null_str, Null_str, Null_str); // only define msg for text
|
||||
fxt.Exec__make("** href_key|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("text", Null_str, Null_str, "/wiki/Href_key"));
|
||||
}
|
||||
@Test public void Itm_href_absolute() {
|
||||
fxt.Exec__make("** http://a.org|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "http://a.org"));
|
||||
}
|
||||
@Test public void Itm_href_manual() {
|
||||
fxt.Exec__make("** Help:Contents|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Help:Contents"));
|
||||
}
|
||||
@Test public void Itm_href_xwiki() {
|
||||
Xop_fxt.Reg_xwiki_alias(fxt.Wiki(), "c", "commons.wikimedia.org");
|
||||
fxt.Exec__make("** c:Help:Contents|main_key");
|
||||
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/site/commons.wikimedia.org/wiki/Help:Contents"));
|
||||
}
|
||||
@Test public void Itm_err_missing_key() {
|
||||
fxt.Exec__make("** no_main_key");
|
||||
fxt.Test__objs();
|
||||
}
|
||||
@Test public void Itm_ignore() { // PURPOSE: ignore SEARCH, TOOLBOX, LANGUAGES
|
||||
fxt.Exec__make
|
||||
( "** SEARCH"
|
||||
, "** TOOLBOX"
|
||||
, "** LANGUAGES"
|
||||
);
|
||||
fxt.Test__objs();
|
||||
}
|
||||
@Test public void Itm_comment() { // PURPOSE: ignore comment; EX:de.v:MediaWiki:Sidebar; DATE:2014-03-08
|
||||
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
|
||||
fxt.Exec__make("** href_key<!--a-->|main_key<!--b-->");
|
||||
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
|
||||
}
|
||||
@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);
|
||||
fxt.Exec__make
|
||||
( "* navigation"
|
||||
, "** mainpage|mainpage-description"
|
||||
, "** Portal:Contents|contents"
|
||||
, "* SEARCH"
|
||||
, "* interaction"
|
||||
, "** helppage|help"
|
||||
, "* TOOLBOX"
|
||||
, "** TOOLBOXEND"
|
||||
, "* LANGUAGES"
|
||||
);
|
||||
fxt.Test__objs
|
||||
( fxt.Make__grp("Grp_0_text", "Grp_0_title").Subs__add
|
||||
( fxt.Make__itm("Itm_0_text", "Itm_0_title [a]", "a", "/wiki/Itm_0_href")
|
||||
, fxt.Make__itm("Itm_1_text", Null_str, Null_str, "/wiki/Portal:Contents")
|
||||
)
|
||||
, fxt.Make__grp("interaction", Null_str).Subs__add
|
||||
( fxt.Make__itm("help", Null_str, Null_str, "/wiki/Helppage")
|
||||
));
|
||||
fxt.Test__html
|
||||
( "<div class=\"portal\" id=\"n-navigation\">"
|
||||
, " <h3>Grp_0_text</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Itm_0_href\" accesskey=\"a\" title=\"Itm_0_title [a] [a]\">Itm_0_text</a></li>"
|
||||
, " <li id=\"n-contents\"><a href=\"/wiki/Portal:Contents\" title=\"\">Itm_1_text</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
, "<div class=\"portal\" id=\"n-interaction\">"
|
||||
, " <h3>interaction</h3>"
|
||||
, " <div class=\"body\">"
|
||||
, " <ul>"
|
||||
, " <li id=\"n-help\"><a href=\"/wiki/Helppage\" title=\"\">help</a></li>"
|
||||
, " </ul>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
);
|
||||
}
|
||||
private static final String Null_str = "";
|
||||
}
|
||||
class Xoh_sidebar_mgr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Xoh_sidebar_mgr sidebar_mgr; private Bry_bfr bfr;
|
||||
public Xoh_sidebar_mgr_fxt Clear() {
|
||||
app = Xoa_app_fxt.Make__app__edit();
|
||||
wiki = Xoa_app_fxt.Make__wiki__edit(app);
|
||||
sidebar_mgr = wiki.Html_mgr().Portal_mgr().Sidebar_mgr();
|
||||
bfr = Bry_bfr_.Reset(Io_mgr.Len_kb);
|
||||
Init__popups_enabled(false);
|
||||
return this;
|
||||
}
|
||||
public Xowe_wiki Wiki() {return wiki;}
|
||||
public Xoh_sidebar_itm Make__grp(String text, String title, Xoh_sidebar_itm... itms) {
|
||||
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.N, Bry_.new_a7(text), Bry_.new_a7(text), null);
|
||||
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), null, null);
|
||||
return rv;
|
||||
}
|
||||
public Xoh_sidebar_itm Make__itm(String text, String title, String accesskey, String href) {
|
||||
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.Y, Bry_.new_a7(text), Bry_.new_a7(text), Bry_.new_a7(href));
|
||||
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), Bry_.new_a7(accesskey), null);
|
||||
return rv;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__popups_enabled(boolean v) {
|
||||
wiki.Html_mgr().Head_mgr().Popup_mgr().Enabled_(v);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__msg__grp(String key, String text, String title) {
|
||||
Init_msg(key, text);
|
||||
Init_msg("tooltip-n-" + key, title);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init__msg__itm(String href_key, String main_key, String text, String title, String accesskey, String href) {
|
||||
if (text != null) Init_msg(main_key, text);
|
||||
if (href != null) Init_msg(href_key, href);
|
||||
if (title != null) Init_msg("tooltip-n-" + main_key, title);
|
||||
if (accesskey != null) Init_msg("accesskey-n-" + main_key, accesskey);
|
||||
return this;
|
||||
}
|
||||
public Xoh_sidebar_mgr_fxt Init_msg(String key, String val) {
|
||||
Xol_msg_mgr msg_mgr = wiki.Lang().Msg_mgr();
|
||||
Xol_msg_itm msg_itm = msg_mgr.Itm_by_key_or_new(Bry_.new_a7(key));
|
||||
msg_itm.Atrs_set(Bry_.new_a7(val), false, String_.Has(val, "{{"));
|
||||
return this;
|
||||
}
|
||||
public void Exec__make(String... raw) {
|
||||
sidebar_mgr.Make(bfr, Bry_.new_u8(String_.Concat_lines_nl_skip_last(raw)));
|
||||
}
|
||||
public void Test__objs(Xoh_sidebar_itm... expd) {
|
||||
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
|
||||
}
|
||||
public void Test__objs(String raw, Xoh_sidebar_itm... expd) {
|
||||
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
|
||||
}
|
||||
public void Test__html(String... expd) {
|
||||
Tfds.Eq_str_lines(String_.Concat_lines_nl_skip_last(expd), String_.new_u8(sidebar_mgr.Html_bry()));
|
||||
}
|
||||
private static String To_str_by_mgr(Xoh_sidebar_mgr mgr) {
|
||||
List_adp grps = mgr.Grps();
|
||||
int len = grps.Len();
|
||||
Xoh_sidebar_itm[] ary = new Xoh_sidebar_itm[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
ary[i] = (Xoh_sidebar_itm)grps.Get_at(i);
|
||||
return To_str_by_itms(ary);
|
||||
}
|
||||
|
||||
private static String To_str_by_itms(Xoh_sidebar_itm[] ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++)
|
||||
To_str_by_itm(bfr, ary[i]);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
private static void To_str_by_itm(Bry_bfr bfr, Xoh_sidebar_itm cur) {
|
||||
boolean tid_is_itm = cur.Tid_is_itm();
|
||||
bfr.Add_str_a7(tid_is_itm ? "itm|" : "grp|");
|
||||
bfr.Add(cur.Text()).Add_byte_pipe();
|
||||
bfr.Add(cur.Title()).Add_byte_pipe();
|
||||
if (tid_is_itm) {
|
||||
bfr.Add(cur.Accesskey()).Add_byte_pipe();
|
||||
bfr.Add(cur.Href()).Add_byte_pipe();
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
|
||||
int len = cur.Subs__len();
|
||||
for (int i = 0; i< len; ++i)
|
||||
To_str_by_itm(bfr, cur.Subs__get_at(i));
|
||||
}
|
||||
}
|
||||
|
@ -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,114 +13,129 @@ 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.apps.site_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*;
|
||||
import gplx.core.net.*; import gplx.langs.jsons.*; import gplx.xowa.apps.gfs.*;
|
||||
import gplx.xowa.langs.*;
|
||||
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.xwikis.*;
|
||||
class Xoa_site_cfg_itm__interwikimap extends Xoa_site_cfg_itm__base {
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
private final Gfo_url_parser url_parser = new Gfo_url_parser();
|
||||
public Xoa_site_cfg_itm__interwikimap() {this.Ctor(Xoa_site_cfg_loader__inet.Qarg__interwikimap);}
|
||||
@Override public void Parse_json_ary_itm(Bry_bfr bfr, Xow_wiki wiki, int i, Json_itm itm) {
|
||||
Json_nde nde = Json_nde.cast(itm);
|
||||
if (i != 0) bfr.Add_byte_nl();
|
||||
byte[] iw_key = nde.Get_bry_or_null("prefix"); if (iw_key == null) throw Err_.new_("site_meta", "invalid interwiki", "key", iw_key);
|
||||
byte[] iw_url = nde.Get_bry_or_null("url"); if (iw_url == null) throw Err_.new_("site_meta", "invalid interwiki", "url", iw_key);
|
||||
bfr.Add(iw_key).Add_byte_pipe().Add(Gfs_php_converter.To_gfs(tmp_bfr, iw_url));
|
||||
}
|
||||
@Override public void Exec_csv(Xow_wiki wiki, int loader_tid, byte[] dsv_bry) {
|
||||
if (loader_tid == Xoa_site_cfg_loader_.Tid__fallback)
|
||||
Exec_csv__fallback(wiki);
|
||||
else {
|
||||
byte[][] lines = Bry_split_.Split_lines(dsv_bry);
|
||||
int lines_len = lines.length;
|
||||
for (int i = 0; i < lines_len; ++i) {
|
||||
byte[] line = lines[i]; if (Bry_.Len_eq_0(line)) continue; // ignore blank lines
|
||||
byte[][] flds = Bry_split_.Split(line, Byte_ascii.Pipe);
|
||||
byte[] url_fmt = flds[1];
|
||||
byte[] domain_bry = Xow_xwiki_mgr.Get_domain_from_url(url_parser, url_fmt);
|
||||
wiki.Xwiki_mgr().Add_by_site_interwikimap
|
||||
( flds[0], domain_bry, url_fmt
|
||||
, Bry_.Replace(url_fmt, Arg0_xo, Arg0_wm) // NOTE: interwiki items are stored in wiki.core.xowa_cfg as https://en.wikipedia.org/wiki/~{0}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Exec_csv__fallback(Xow_wiki wiki) {
|
||||
Xow_xwiki_mgr xwiki_mgr = wiki.Xwiki_mgr();
|
||||
int domain_tid = wiki.Domain_tid();
|
||||
xwiki_mgr.Add_by_csv(Csv__manual); // adds manual xwikis that should exist in all wikis; EX: 'commons', 'wikidata', 'oldwikisource', 'wmf'
|
||||
switch (domain_tid) {
|
||||
case Xow_domain_tid_.Tid__wikipedia: case Xow_domain_tid_.Tid__wiktionary: case Xow_domain_tid_.Tid__wikisource: case Xow_domain_tid_.Tid__wikivoyage:
|
||||
case Xow_domain_tid_.Tid__wikiquote: case Xow_domain_tid_.Tid__wikibooks: case Xow_domain_tid_.Tid__wikiversity: case Xow_domain_tid_.Tid__wikinews:
|
||||
xwiki_mgr.Add_by_sitelink_mgr(); // lang: EX: [[fr:]] -> fr.wikipedia.org
|
||||
xwiki_mgr.Add_by_csv(Csv__peers__lang); // peer: EX: [[wikt]] -> en.wiktionary.org
|
||||
break;
|
||||
case Xow_domain_tid_.Tid__commons: case Xow_domain_tid_.Tid__wikidata:
|
||||
case Xow_domain_tid_.Tid__wikimedia: case Xow_domain_tid_.Tid__species: case Xow_domain_tid_.Tid__meta:
|
||||
case Xow_domain_tid_.Tid__incubator: case Xow_domain_tid_.Tid__wikimania: case Xow_domain_tid_.Tid__wikisource_org:
|
||||
case Xow_domain_tid_.Tid__mediawiki: case Xow_domain_tid_.Tid__wmfblog:
|
||||
case Xow_domain_tid_.Tid__home: case Xow_domain_tid_.Tid__other:
|
||||
xwiki_mgr.Add_by_sitelink_mgr(Xow_domain_tid_.Tid__wikipedia); // lang: hardcode to wikipedia; EX: "[[en:]] -> "en.wikipedia.org"
|
||||
xwiki_mgr.Add_by_csv(Csv__peers__english); // peer: hardcode to english
|
||||
break;
|
||||
}
|
||||
|
||||
// wikivoyage
|
||||
switch (domain_tid) {
|
||||
case Xow_domain_tid_.Tid__wikivoyage: case Xow_domain_tid_.Tid__home: // NOTE: home needed for diagnostic; DATE:2015-10-13
|
||||
xwiki_mgr.Add_by_csv(Csv__wikivoyage);
|
||||
break;
|
||||
}
|
||||
|
||||
// if simplewiki, add "w" -> "enwiki"
|
||||
if (Bry_.Eq(wiki.Domain_bry(), Xow_domain_itm_.Bry__simplewiki))
|
||||
xwiki_mgr.Add_by_csv(Csv__enwiki);
|
||||
}
|
||||
private static final byte[]
|
||||
Csv__manual = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "1|commons;c|commons.wikimedia.org|Commons"
|
||||
, "1|m;metawikipedia|meta.wikipedia.org"
|
||||
, "1|species;wikispecies|species.wikimedia.org"
|
||||
, "1|d;wikidata|www.wikidata.org"
|
||||
, "1|mw;mediawikiwiki|www.mediawiki.org"
|
||||
, "1|wmf;wikimedia;foundation|foundation.wikimedia.org"
|
||||
, "1|incubator|incubator.wikimedia.org"
|
||||
, "1|wikimania|wikimania.wikimedia.org"
|
||||
, "1|sourceswiki|wikisource.org"
|
||||
, "0|oldwikisource|https://wikisource.org/wiki/~{0}|Old Wikisoure"
|
||||
, "0|mail|https://lists.wikimedia.org/mailman/listinfo/~{0}|Wikitech Mailing List"
|
||||
))
|
||||
, Csv__peers__lang = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "2|w;wikipedia|wikipedia"
|
||||
, "2|wikt;wiktionary|wiktionary"
|
||||
, "2|s;wikisource|wikisource"
|
||||
, "2|b;wikibooks|wikibooks"
|
||||
, "2|v;wikiversity|wikiversity"
|
||||
, "2|q;wikiquote|wikiquote"
|
||||
, "2|n;wikinews|wikinews"
|
||||
, "2|voy;wikivoyage|wikivoyage"
|
||||
))
|
||||
, Csv__peers__english = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "1|w|en.wikipedia.org"
|
||||
, "1|wikt|en.wiktionary.org"
|
||||
, "1|s|en.wikisource.org"
|
||||
, "1|b|en.wikibooks.org"
|
||||
, "1|v|en.wikiversity.org"
|
||||
, "1|q|en.wikiquote.org"
|
||||
, "1|n|en.wikinews.org"
|
||||
, "1|voy|en.wikivoyage.org"
|
||||
))
|
||||
, Csv__wikivoyage = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "0|commons|commons.wikimedia.org|Wikimedia Commons"
|
||||
, "2|wikipedia|wikipedia|Wikipedia"
|
||||
, "0|dmoz|http://www.dmoz.org/~{0}|DMOZ"
|
||||
))
|
||||
, Csv__enwiki = Bry_.new_a7("2|w|wikipedia")
|
||||
;
|
||||
private static final byte[]
|
||||
Arg0_xo = Bry_.new_a7("~{0}")
|
||||
, Arg0_wm = Bry_.new_a7("$1")
|
||||
;
|
||||
}
|
||||
|
||||
package gplx.xowa.apps.site_cfgs;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bry_split_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Err_;
|
||||
import gplx.String_;
|
||||
import gplx.core.net.Gfo_url_parser;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.xowa.Xow_wiki;
|
||||
import gplx.xowa.apps.gfs.Gfs_php_converter;
|
||||
import gplx.xowa.wikis.domains.Xow_domain_itm_;
|
||||
import gplx.xowa.wikis.domains.Xow_domain_tid_;
|
||||
import gplx.xowa.wikis.xwikis.Xow_xwiki_mgr;
|
||||
|
||||
class Xoa_site_cfg_itm__interwikimap extends Xoa_site_cfg_itm__base {
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
private final Gfo_url_parser url_parser = new Gfo_url_parser();
|
||||
public Xoa_site_cfg_itm__interwikimap() {
|
||||
this.Ctor(Xoa_site_cfg_loader__inet.Qarg__interwikimap);
|
||||
}
|
||||
@Override public void Parse_json_ary_itm(Bry_bfr bfr, Xow_wiki wiki, int i, Json_itm itm) {
|
||||
Json_nde nde = Json_nde.Cast(itm);
|
||||
if (i != 0) bfr.Add_byte_nl();
|
||||
byte[] iw_key = nde.Get_bry_or_null("prefix"); if (iw_key == null) throw Err_.new_("site_meta", "invalid interwiki", "key", iw_key);
|
||||
byte[] iw_url = nde.Get_bry_or_null("url"); if (iw_url == null) throw Err_.new_("site_meta", "invalid interwiki", "url", iw_key);
|
||||
bfr.Add(iw_key).Add_byte_pipe().Add(Gfs_php_converter.To_gfs(tmp_bfr, iw_url));
|
||||
}
|
||||
@Override public void Exec_csv(Xow_wiki wiki, int loader_tid, byte[] dsv_bry) {
|
||||
if (loader_tid == Xoa_site_cfg_loader_.Tid__fallback)
|
||||
Exec_csv__fallback(wiki);
|
||||
else {
|
||||
byte[][] lines = Bry_split_.Split_lines(dsv_bry);
|
||||
int lines_len = lines.length;
|
||||
for (int i = 0; i < lines_len; ++i) {
|
||||
byte[] line = lines[i]; if (Bry_.Len_eq_0(line)) continue; // ignore blank lines
|
||||
byte[][] flds = Bry_split_.Split(line, Byte_ascii.Pipe);
|
||||
byte[] url_fmt = flds[1];
|
||||
byte[] domain_bry = Xow_xwiki_mgr.Get_domain_from_url(url_parser, url_fmt);
|
||||
wiki.Xwiki_mgr().Add_by_site_interwikimap
|
||||
( flds[0], domain_bry, url_fmt
|
||||
, Bry_.Replace(url_fmt, Arg0_xo, Arg0_wm) // NOTE: interwiki items are stored in wiki.core.xowa_cfg as https://en.wikipedia.org/wiki/~{0}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Exec_csv__fallback(Xow_wiki wiki) {
|
||||
Xow_xwiki_mgr xwiki_mgr = wiki.Xwiki_mgr();
|
||||
int domain_tid = wiki.Domain_tid();
|
||||
xwiki_mgr.Add_by_csv(Csv__manual); // adds manual xwikis that should exist in all wikis; EX: 'commons', 'wikidata', 'oldwikisource', 'wmf'
|
||||
switch (domain_tid) {
|
||||
case Xow_domain_tid_.Tid__wikipedia: case Xow_domain_tid_.Tid__wiktionary: case Xow_domain_tid_.Tid__wikisource: case Xow_domain_tid_.Tid__wikivoyage:
|
||||
case Xow_domain_tid_.Tid__wikiquote: case Xow_domain_tid_.Tid__wikibooks: case Xow_domain_tid_.Tid__wikiversity: case Xow_domain_tid_.Tid__wikinews:
|
||||
xwiki_mgr.Add_by_sitelink_mgr(); // lang: EX: [[fr:]] -> fr.wikipedia.org
|
||||
xwiki_mgr.Add_by_csv(Csv__peers__lang); // peer: EX: [[wikt]] -> en.wiktionary.org
|
||||
break;
|
||||
case Xow_domain_tid_.Tid__commons: case Xow_domain_tid_.Tid__wikidata:
|
||||
case Xow_domain_tid_.Tid__wikimedia: case Xow_domain_tid_.Tid__species: case Xow_domain_tid_.Tid__meta:
|
||||
case Xow_domain_tid_.Tid__incubator: case Xow_domain_tid_.Tid__wikimania: case Xow_domain_tid_.Tid__wikisource_org:
|
||||
case Xow_domain_tid_.Tid__mediawiki: case Xow_domain_tid_.Tid__wmfblog:
|
||||
case Xow_domain_tid_.Tid__home: case Xow_domain_tid_.Tid__other:
|
||||
xwiki_mgr.Add_by_sitelink_mgr(Xow_domain_tid_.Tid__wikipedia); // lang: hardcode to wikipedia; EX: "[[en:]] -> "en.wikipedia.org"
|
||||
xwiki_mgr.Add_by_csv(Csv__peers__english); // peer: hardcode to english
|
||||
break;
|
||||
}
|
||||
|
||||
// wikivoyage
|
||||
switch (domain_tid) {
|
||||
case Xow_domain_tid_.Tid__wikivoyage: case Xow_domain_tid_.Tid__home: // NOTE: home needed for diagnostic; DATE:2015-10-13
|
||||
xwiki_mgr.Add_by_csv(Csv__wikivoyage);
|
||||
break;
|
||||
}
|
||||
|
||||
// if simplewiki, add "w" -> "enwiki"
|
||||
if (Bry_.Eq(wiki.Domain_bry(), Xow_domain_itm_.Bry__simplewiki))
|
||||
xwiki_mgr.Add_by_csv(Csv__enwiki);
|
||||
}
|
||||
private static final byte[]
|
||||
Csv__manual = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "1|commons;c|commons.wikimedia.org|Commons"
|
||||
, "1|m;metawikipedia|meta.wikipedia.org"
|
||||
, "1|species;wikispecies|species.wikimedia.org"
|
||||
, "1|d;wikidata|www.wikidata.org"
|
||||
, "1|mw;mediawikiwiki|www.mediawiki.org"
|
||||
, "1|wmf;wikimedia;foundation|foundation.wikimedia.org"
|
||||
, "1|incubator|incubator.wikimedia.org"
|
||||
, "1|wikimania|wikimania.wikimedia.org"
|
||||
, "1|sourceswiki|wikisource.org"
|
||||
, "0|oldwikisource|https://wikisource.org/wiki/~{0}|Old Wikisoure"
|
||||
, "0|mail|https://lists.wikimedia.org/mailman/listinfo/~{0}|Wikitech Mailing List"
|
||||
))
|
||||
, Csv__peers__lang = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "2|w;wikipedia|wikipedia"
|
||||
, "2|wikt;wiktionary|wiktionary"
|
||||
, "2|s;wikisource|wikisource"
|
||||
, "2|b;wikibooks|wikibooks"
|
||||
, "2|v;wikiversity|wikiversity"
|
||||
, "2|q;wikiquote|wikiquote"
|
||||
, "2|n;wikinews|wikinews"
|
||||
, "2|voy;wikivoyage|wikivoyage"
|
||||
))
|
||||
, Csv__peers__english = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "1|w|en.wikipedia.org"
|
||||
, "1|wikt|en.wiktionary.org"
|
||||
, "1|s|en.wikisource.org"
|
||||
, "1|b|en.wikibooks.org"
|
||||
, "1|v|en.wikiversity.org"
|
||||
, "1|q|en.wikiquote.org"
|
||||
, "1|n|en.wikinews.org"
|
||||
, "1|voy|en.wikivoyage.org"
|
||||
))
|
||||
, Csv__wikivoyage = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "0|commons|commons.wikimedia.org|Wikimedia Commons"
|
||||
, "2|wikipedia|wikipedia|Wikipedia"
|
||||
, "0|dmoz|http://www.dmoz.org/~{0}|DMOZ"
|
||||
))
|
||||
, Csv__enwiki = Bry_.new_a7("2|w|wikipedia")
|
||||
;
|
||||
private static final byte[]
|
||||
Arg0_xo = Bry_.new_a7("~{0}")
|
||||
, Arg0_wm = Bry_.new_a7("$1")
|
||||
;
|
||||
}
|
||||
|
@ -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,41 +13,52 @@ 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.bldrs.wms.revs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wms.*;
|
||||
import gplx.langs.jsons.*; import gplx.core.net.*;
|
||||
class Xowm_rev_wkr__meta__wm implements Xowm_rev_wkr__meta {
|
||||
private final Json_parser json_parser = new Json_parser();
|
||||
private final Xowm_json_parser__page json_page_parser = new Xowm_json_parser__page();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(255);
|
||||
private final Wmapi_itm__pge tmp_pge = new Wmapi_itm__pge();
|
||||
public Xowm_rev_wkr__meta__wm() {
|
||||
tmp_pge.Rvn_ary_(new Wmapi_itm__rvn());
|
||||
}
|
||||
public Gfo_inet_conn Inet_conn() {return inet_conn;} public void Inet_conn_(Gfo_inet_conn v) {this.inet_conn = v;} private Gfo_inet_conn inet_conn;
|
||||
public void Fetch_meta(String domain_str, Ordered_hash hash, int bgn, int end) {
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
Wmapi_itm__pge itm = (Wmapi_itm__pge)hash.Get_at(i);
|
||||
if (i != bgn) tmp_bfr.Add_byte(Byte_ascii.Pipe);
|
||||
tmp_bfr.Add(itm.Page_ttl());
|
||||
}
|
||||
byte[] json = inet_conn.Download_as_bytes_or_null(Xowm_api_mgr.Bld_api_url(domain_str, "action=query&prop=revisions&rvprop=size|ids|timestamp|user|comment&format=json&rawcontinue=titles=" + tmp_bfr.To_str_and_clear()));
|
||||
Parse_doc(hash, json);
|
||||
}
|
||||
private void Parse_doc(Ordered_hash hash, byte[] json) {
|
||||
Json_doc jdoc = json_parser.Parse(json);
|
||||
Json_nde pages_nde = Json_nde.cast(jdoc.Get_grp_many(Jpath__query_pages));
|
||||
int len = pages_nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Parse_page(hash, pages_nde.Get_at_as_kv(i).Val_as_nde());
|
||||
}
|
||||
}
|
||||
private void Parse_page(Ordered_hash hash, Json_nde page_nde) {
|
||||
json_page_parser.Parse("update", tmp_pge, page_nde); // have to pass tmp_pge, b/c don't know which itm is in hash
|
||||
Wmapi_itm__pge hash_itm = (Wmapi_itm__pge)hash.Get_by(tmp_pge.Page_ttl()); if (hash_itm == null) return;
|
||||
hash_itm.Init_id(tmp_pge.Page_id());
|
||||
Wmapi_itm__rvn tmp_rvn = tmp_pge.Rvn_itm_last();
|
||||
hash_itm.Rvn_ary_(new Wmapi_itm__rvn());
|
||||
hash_itm.Rvn_itm_last().Init(tmp_rvn.Rvn_id(), tmp_rvn.Rvn_len(), tmp_rvn.Rvn_time(), tmp_rvn.Rvn_user(), tmp_rvn.Rvn_note());
|
||||
}
|
||||
private static final byte[][] Jpath__query_pages = Bry_.Ary("query", "pages");
|
||||
}
|
||||
package gplx.xowa.bldrs.wms.revs;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Ordered_hash;
|
||||
import gplx.core.net.Gfo_inet_conn;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.jsons.Json_parser;
|
||||
import gplx.xowa.bldrs.wms.Xowm_api_mgr;
|
||||
|
||||
class Xowm_rev_wkr__meta__wm implements Xowm_rev_wkr__meta {
|
||||
private final Json_parser json_parser = new Json_parser();
|
||||
private final Xowm_json_parser__page json_page_parser = new Xowm_json_parser__page();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(255);
|
||||
private final Wmapi_itm__pge tmp_pge = new Wmapi_itm__pge();
|
||||
public Xowm_rev_wkr__meta__wm() {
|
||||
tmp_pge.Rvn_ary_(new Wmapi_itm__rvn());
|
||||
}
|
||||
public Gfo_inet_conn Inet_conn() {return inet_conn;} public void Inet_conn_(Gfo_inet_conn v) {this.inet_conn = v;} private Gfo_inet_conn inet_conn;
|
||||
public void Fetch_meta(String domain_str, Ordered_hash hash, int bgn, int end) {
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
Wmapi_itm__pge itm = (Wmapi_itm__pge)hash.Get_at(i);
|
||||
if (i != bgn) tmp_bfr.Add_byte(Byte_ascii.Pipe);
|
||||
tmp_bfr.Add(itm.Page_ttl());
|
||||
}
|
||||
byte[] json = inet_conn.Download_as_bytes_or_null(Xowm_api_mgr.Bld_api_url(domain_str, "action=query&prop=revisions&rvprop=size|ids|timestamp|user|comment&format=json&rawcontinue=titles=" + tmp_bfr.To_str_and_clear()));
|
||||
Parse_doc(hash, json);
|
||||
}
|
||||
private void Parse_doc(Ordered_hash hash, byte[] json) {
|
||||
Json_doc jdoc = json_parser.Parse(json);
|
||||
Json_nde pages_nde = Json_nde.Cast(jdoc.Get_grp_many(Jpath__query_pages));
|
||||
int len = pages_nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Parse_page(hash, pages_nde.Get_at_as_kv(i).Val_as_nde());
|
||||
}
|
||||
}
|
||||
private void Parse_page(Ordered_hash hash, Json_nde page_nde) {
|
||||
json_page_parser.Parse("update", tmp_pge, page_nde); // have to pass tmp_pge, b/c don't know which itm is in hash
|
||||
Wmapi_itm__pge hash_itm = (Wmapi_itm__pge)hash.Get_by(tmp_pge.Page_ttl()); if (hash_itm == null) return;
|
||||
hash_itm.Init_id(tmp_pge.Page_id());
|
||||
Wmapi_itm__rvn tmp_rvn = tmp_pge.Rvn_itm_last();
|
||||
hash_itm.Rvn_ary_(new Wmapi_itm__rvn());
|
||||
hash_itm.Rvn_itm_last().Init(tmp_rvn.Rvn_id(), tmp_rvn.Rvn_len(), tmp_rvn.Rvn_time(), tmp_rvn.Rvn_user(), tmp_rvn.Rvn_note());
|
||||
}
|
||||
private static final byte[][] Jpath__query_pages = Bry_.Ary("query", "pages");
|
||||
}
|
||||
|
@ -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,108 +13,122 @@ 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.langs.msgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.langs.*;
|
||||
import gplx.core.brys.fmtrs.*;
|
||||
import gplx.xowa.addons.htmls.sidebars.*;
|
||||
public class Xow_msg_mgr implements Gfo_invk {
|
||||
private final Xow_wiki wiki; private Xol_lang_itm lang; private final Xol_msg_mgr msg_mgr;
|
||||
private final Bry_fmtr tmp_fmtr = Bry_fmtr.New__tmp();
|
||||
public Xow_msg_mgr(Xow_wiki wiki, Xol_lang_itm lang) {
|
||||
this.wiki = wiki;
|
||||
this.lang = lang;
|
||||
this.msg_mgr = new Xol_msg_mgr(wiki, false);
|
||||
}
|
||||
public void Clear() {msg_mgr.Clear();}
|
||||
public void Lang_(Xol_lang_itm v) {
|
||||
this.lang = v;
|
||||
this.Clear();
|
||||
}
|
||||
public byte[] Val_by_id_args(int id, Object... args) {return Val_by_id_priv(id, args);}
|
||||
public byte[] Val_by_id(int id) {return Val_by_id_priv(id, null);}
|
||||
private byte[] Val_by_id_priv(int id, Object[] args) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_id_or_null(id);
|
||||
if (itm == null)
|
||||
itm = lang.Msg_mgr().Itm_by_id_or_null(id);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
byte[] rv = Val_by_itm(tmp_bfr, itm, args);
|
||||
tmp_bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public Xol_msg_itm Get_or_make(byte[] key) {return msg_mgr.Itm_by_key_or_new(key);}
|
||||
public Xol_msg_itm Get_or_null(byte[] key) {return msg_mgr.Itm_by_key_or_null(key);}
|
||||
public Xol_msg_itm Find_or_null(byte[] key) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_key_or_null(key);
|
||||
if (itm == null) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
itm = Xol_msg_mgr_.Get_msg_itm(tmp_bfr, wiki, lang, key);
|
||||
if (itm.Defined_in_none()) itm = null;
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
return itm;
|
||||
}
|
||||
public byte[] Val_by_key_args(byte[] key, Object... args) {return Val_by_key(key, args);}
|
||||
public byte[] Val_by_key_obj(String key) {return Val_by_key(Bry_.new_u8(key), null);}
|
||||
public byte[] Val_by_key_obj(byte[] key) {return Val_by_key(key, null);}
|
||||
private byte[] Val_by_key(byte[] key, Object[] args) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_key_or_null(key);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
if (itm == null)
|
||||
itm = Xol_msg_mgr_.Get_msg_itm(tmp_bfr, wiki, lang, key);
|
||||
if (itm.Defined_in_none()) {
|
||||
tmp_bfr.Mkr_rls();
|
||||
return Bry_.Empty;
|
||||
}
|
||||
byte[] rv = Val_by_itm(tmp_bfr, itm, args);
|
||||
tmp_bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_by_itm(Bry_bfr tmp_bfr, Xol_msg_itm itm, Object[] args) {
|
||||
byte[] rv = itm.Val();
|
||||
if (args != null) rv = itm.Fmt_tmp(tmp_bfr, tmp_fmtr, rv, args);
|
||||
if (itm.Has_tmpl_txt()) rv = wiki.Wtxt__expand_tmpl(rv);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_html_accesskey_and_title(byte[] id) {
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
byte[] rv = Val_html_accesskey_and_title(id, bfr, null);
|
||||
bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_html_accesskey_and_title(byte[] id, Bry_bfr bfr, Xoh_sidebar_itm itm) {
|
||||
byte[] tooltip_key = Bry_.Add(CONST_prefix_tooltip, id);
|
||||
byte[] tooltip_val = Val_by_key_obj(tooltip_key);
|
||||
boolean tooltip_found = Bry_.Len_gt_0(tooltip_val);
|
||||
byte[] accesskey_key = Bry_.Empty, accesskey_val = Bry_.Empty;
|
||||
boolean accesskey_found = false;
|
||||
if (tooltip_found) {
|
||||
accesskey_key = Bry_.Add(CONST_prefix_accesskey, id);
|
||||
accesskey_val = Val_by_key_obj(accesskey_key);
|
||||
accesskey_found = Bry_.Len_gt_0(accesskey_val);
|
||||
}
|
||||
if (accesskey_found)
|
||||
bfr.Add(CONST_atr_accesskey).Add(accesskey_val).Add_byte(Byte_ascii.Quote);
|
||||
bfr.Add(CONST_atr_title).Add(tooltip_found ? tooltip_val : Bry_.Empty); // NOTE: if tooltip not found, make blank; don't bother showing tooltip_key
|
||||
if (accesskey_found)
|
||||
bfr.Add_byte(Byte_ascii.Space).Add_byte(Byte_ascii.Brack_bgn).Add(accesskey_val).Add_byte(Byte_ascii.Brack_end);
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
byte[] rv = bfr.To_bry_and_clear();
|
||||
if (itm == null)
|
||||
return rv;
|
||||
else {
|
||||
itm.Init_by_title_and_accesskey(tooltip_val, accesskey_val, rv);
|
||||
return null;
|
||||
}
|
||||
} private static final byte[] CONST_prefix_tooltip = Bry_.new_a7("tooltip-"), CONST_prefix_accesskey = Bry_.new_a7("accesskey-"), CONST_atr_title = Bry_.new_a7(" title=\""), CONST_atr_accesskey = Bry_.new_a7(" accesskey=\"");
|
||||
public Xol_msg_itm Set(String key_str, String val_str) { // TEST
|
||||
Xol_msg_itm msg_itm = this.Get_or_make(Bry_.new_u8(key_str));
|
||||
msg_itm.Atrs_set(Bry_.new_u8(val_str), false, false);
|
||||
msg_itm.Defined_in_(Xol_msg_itm.Defined_in__lang);
|
||||
return msg_itm;
|
||||
}
|
||||
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_get)) return this.Val_by_key_obj(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_get_html_accesskey_and_title)) return this.Val_html_accesskey_and_title(m.ReadBry("v"));
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
} private static final String Invk_get = "get", Invk_get_html_accesskey_and_title = "get_html_accesskey_and_title";
|
||||
}
|
||||
package gplx.xowa.langs.msgs;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.GfoMsg;
|
||||
import gplx.Gfo_invk;
|
||||
import gplx.Gfo_invk_;
|
||||
import gplx.GfsCtx;
|
||||
import gplx.core.brys.fmtrs.Bry_fmtr;
|
||||
import gplx.xowa.Xow_wiki;
|
||||
import gplx.xowa.addons.htmls.sidebars.Xoh_sidebar_itm;
|
||||
import gplx.xowa.langs.Xol_lang_itm;
|
||||
|
||||
public class Xow_msg_mgr implements Gfo_invk {
|
||||
private final Xow_wiki wiki;
|
||||
private final Xol_msg_mgr msg_mgr;
|
||||
private Xol_lang_itm lang;
|
||||
private final Bry_fmtr tmp_fmtr = Bry_fmtr.New__tmp();
|
||||
public Xow_msg_mgr(Xow_wiki wiki, Xol_lang_itm lang) {
|
||||
this.wiki = wiki;
|
||||
this.lang = lang;
|
||||
this.msg_mgr = new Xol_msg_mgr(wiki, false);
|
||||
}
|
||||
public void Clear() {msg_mgr.Clear();}
|
||||
public void Lang_(Xol_lang_itm v) {
|
||||
this.lang = v;
|
||||
this.Clear();
|
||||
}
|
||||
public byte[] Val_by_id_args(int id, Object... args) {return Val_by_id_priv(id, args);}
|
||||
public byte[] Val_by_id(int id) {return Val_by_id_priv(id, null);}
|
||||
private byte[] Val_by_id_priv(int id, Object[] args) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_id_or_null(id);
|
||||
if (itm == null)
|
||||
itm = lang.Msg_mgr().Itm_by_id_or_null(id);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
byte[] rv = Val_by_itm(tmp_bfr, itm, args);
|
||||
tmp_bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public Xol_msg_itm Get_or_make(byte[] key) {return msg_mgr.Itm_by_key_or_new(key);}
|
||||
public Xol_msg_itm Get_or_null(byte[] key) {return msg_mgr.Itm_by_key_or_null(key);}
|
||||
public Xol_msg_itm Find_or_null(byte[] key) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_key_or_null(key);
|
||||
if (itm == null) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
itm = Xol_msg_mgr_.Get_msg_itm(tmp_bfr, wiki, lang, key);
|
||||
if (itm.Defined_in_none()) itm = null;
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
return itm;
|
||||
}
|
||||
public byte[] Val_by_key_args(byte[] key, Object... args) {return Val_by_key(key, args);}
|
||||
public byte[] Val_by_key_obj(String key) {return Val_by_key(Bry_.new_u8(key), null);}
|
||||
public byte[] Val_by_key_obj(byte[] key) {return Val_by_key(key, null);}
|
||||
private byte[] Val_by_key(byte[] key, Object[] args) {
|
||||
Xol_msg_itm itm = msg_mgr.Itm_by_key_or_null(key);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
if (itm == null)
|
||||
itm = Xol_msg_mgr_.Get_msg_itm(tmp_bfr, wiki, lang, key);
|
||||
if (itm.Defined_in_none()) {
|
||||
tmp_bfr.Mkr_rls();
|
||||
return Bry_.Empty;
|
||||
}
|
||||
byte[] rv = Val_by_itm(tmp_bfr, itm, args);
|
||||
tmp_bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_by_itm(Bry_bfr tmp_bfr, Xol_msg_itm itm, Object[] args) {
|
||||
byte[] rv = itm.Val();
|
||||
if (args != null) rv = itm.Fmt_tmp(tmp_bfr, tmp_fmtr, rv, args);
|
||||
if (itm.Has_tmpl_txt()) rv = wiki.Wtxt__expand_tmpl(rv);
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_html_accesskey_and_title(String id) {return Val_html_accesskey_and_title(Bry_.new_u8(id));}
|
||||
public byte[] Val_html_accesskey_and_title(byte[] id) {
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
byte[] rv = Val_html_accesskey_and_title(id, bfr, null);
|
||||
bfr.Mkr_rls();
|
||||
return rv;
|
||||
}
|
||||
public byte[] Val_html_accesskey_and_title(byte[] id, Bry_bfr bfr, Xoh_sidebar_itm itm) {
|
||||
byte[] tooltip_key = Bry_.Add(CONST_prefix_tooltip, id);
|
||||
byte[] tooltip_val = Val_by_key_obj(tooltip_key);
|
||||
boolean tooltip_found = Bry_.Len_gt_0(tooltip_val);
|
||||
byte[] accesskey_key = Bry_.Empty, accesskey_val = Bry_.Empty;
|
||||
boolean accesskey_found = false;
|
||||
if (tooltip_found) {
|
||||
accesskey_key = Bry_.Add(CONST_prefix_accesskey, id);
|
||||
accesskey_val = Val_by_key_obj(accesskey_key);
|
||||
accesskey_found = Bry_.Len_gt_0(accesskey_val);
|
||||
}
|
||||
if (accesskey_found)
|
||||
bfr.Add(CONST_atr_accesskey).Add(accesskey_val).Add_byte(Byte_ascii.Quote);
|
||||
bfr.Add(CONST_atr_title).Add(tooltip_found ? tooltip_val : Bry_.Empty); // NOTE: if tooltip not found, make blank; don't bother showing tooltip_key
|
||||
if (accesskey_found)
|
||||
bfr.Add_byte(Byte_ascii.Space).Add_byte(Byte_ascii.Brack_bgn).Add(accesskey_val).Add_byte(Byte_ascii.Brack_end);
|
||||
bfr.Add_byte(Byte_ascii.Quote);
|
||||
byte[] rv = bfr.To_bry_and_clear();
|
||||
if (itm == null)
|
||||
return rv;
|
||||
else {
|
||||
itm.Init_by_title_and_accesskey(tooltip_val, accesskey_val, rv);
|
||||
return null;
|
||||
}
|
||||
} private static final byte[] CONST_prefix_tooltip = Bry_.new_a7("tooltip-"), CONST_prefix_accesskey = Bry_.new_a7("accesskey-"), CONST_atr_title = Bry_.new_a7(" title=\""), CONST_atr_accesskey = Bry_.new_a7(" accesskey=\"");
|
||||
public Xol_msg_itm Set(String key_str, String val_str) { // TEST
|
||||
Xol_msg_itm msg_itm = this.Get_or_make(Bry_.new_u8(key_str));
|
||||
msg_itm.Atrs_set(Bry_.new_u8(val_str), false, false);
|
||||
msg_itm.Defined_in_(Xol_msg_itm.Defined_in__lang);
|
||||
return msg_itm;
|
||||
}
|
||||
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_get)) return this.Val_by_key_obj(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_get_html_accesskey_and_title)) return this.Val_html_accesskey_and_title(m.ReadBry("v"));
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
} private static final String Invk_get = "get", Invk_get_html_accesskey_and_title = "get_html_accesskey_and_title";
|
||||
}
|
||||
|
@ -95,6 +95,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 +286,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,11 +330,13 @@ 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();
|
||||
rslt_bfr.Add(wiki.Parser_mgr().Main().Expand_tmpl(tmp_src)); // this could be cleaner / more optimized
|
||||
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);
|
||||
trace.Trace_end(trg_bgn, bfr);
|
||||
@ -341,7 +367,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 +404,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;
|
||||
|
@ -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,24 +13,33 @@ 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.wikis.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
|
||||
import gplx.core.intls.*; import gplx.core.caches.*;
|
||||
import gplx.xowa.langs.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
import gplx.xowa.parsers.tmpls.*;
|
||||
public class Xow_defn_cache { // stores compiled Xot_defn
|
||||
private final Xol_lang_itm lang; // needed to lowercase names;
|
||||
private final Bry_bfr upper_1st_bfr = Bry_bfr_.Reset(255);
|
||||
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 void Free_mem_all() {cache.Clear();}
|
||||
public void Add(Xot_defn defn, byte case_match) {
|
||||
byte[] name = defn.Name();
|
||||
cache.Add_replace(name, defn, defn.Cache_size());
|
||||
if (case_match == Xow_ns_case_.Tid__1st) {
|
||||
name = lang.Case_mgr().Case_build_1st_upper(upper_1st_bfr, name, 0, name.length);
|
||||
cache.Add_replace(name, defn, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
package gplx.xowa.wikis.caches;
|
||||
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.core.caches.Gfo_cache_mgr;
|
||||
import gplx.xowa.langs.Xol_lang_itm;
|
||||
import gplx.xowa.parsers.tmpls.Xot_defn;
|
||||
import gplx.xowa.wikis.nss.Xow_ns_case_;
|
||||
|
||||
public class Xow_defn_cache {
|
||||
private final Xol_lang_itm lang; // needed to lowercase names;
|
||||
private final Bry_bfr upper_1st_bfr = Bry_bfr_.Reset(255);
|
||||
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();
|
||||
cache.Add_replace(name, defn, defn.Cache_size());
|
||||
if (case_match == Xow_ns_case_.Tid__1st) {
|
||||
name = lang.Case_mgr().Case_build_1st_upper(upper_1st_bfr, name, 0, name.length);
|
||||
cache.Add_replace(name, defn, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
403
400_xowa/src/gplx/xowa/xtns/lst/Db_Section_list.java
Normal file
403
400_xowa/src/gplx/xowa/xtns/lst/Db_Section_list.java
Normal file
@ -0,0 +1,403 @@
|
||||
/* 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.xtns.lst;
|
||||
import gplx.Bry_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
|
||||
import gplx.xowa.Xoa_ttl;
|
||||
import gplx.xowa.Xoae_page;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
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;
|
||||
|
||||
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,201 +13,235 @@ 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.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.core.btries.*; import gplx.langs.mustaches.*;
|
||||
import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*; import gplx.xowa.xtns.pfuncs.*; import gplx.xowa.langs.kwds.*; import gplx.xowa.parsers.utils.*; import gplx.xowa.parsers.lnkis.*; import gplx.xowa.parsers.lnkis.files.*;
|
||||
import gplx.xowa.files.*;
|
||||
import gplx.xowa.htmls.core.htmls.*; import gplx.langs.htmls.encoders.*;
|
||||
// REF.MW:https://github.com/wikimedia/mediawiki-extensions-WikidataPageBanner/blob/master/includes/WikidataPageBannerFunctions.php
|
||||
// TODO.DATE:2019-11-11: calculate enableToc and hasPosition;
|
||||
public class Pgbnr_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_pagebanner;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pgbnr_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { // {{PAGEBANNER}} appears on page; WikidataPageBanner.hooks.php|addCustomBanner
|
||||
Xowe_wiki wiki = ctx.Wiki(); Xoae_page page = ctx.Page();
|
||||
Pgbnr_xtn_mgr xtn_mgr = wiki.Xtn_mgr().Xtn_pgbnr();
|
||||
Pgbnr_cfg cfg = xtn_mgr.Cfg();
|
||||
Xoa_ttl ttl = page.Ttl();
|
||||
if (!cfg.Chk_pgbnr_allowed(ttl, wiki)) return;
|
||||
byte[] tooltip = ttl.Page_txt(), title = ttl.Page_txt(), toc = Bry_.Empty, origin_x = Bry_.Empty;
|
||||
boolean bottomtoc = false;;
|
||||
double data_pos_x = 0, data_pos_y = 0;
|
||||
List_adp icons_list = null;
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
int args_len = self.Args_len();
|
||||
Xop_func_arg_itm func_arg = new Xop_func_arg_itm();
|
||||
for (int i = 0; i < args_len; ++i) {
|
||||
Arg_nde_tkn arg = self.Args_get_by_idx(i);
|
||||
func_arg.Set(tmp_bfr, ctx, src, caller, self, arg);
|
||||
byte[] key = func_arg.key;
|
||||
byte[] val = func_arg.val;
|
||||
if (key == Bry_.Empty) continue; // ignore blank args; EX:{{PAGEBANNER:A.png|\n|toc=yes}}
|
||||
int tid = arg_hash.Get_as_int_or(key, -1);
|
||||
if (tid == Arg__pgname)
|
||||
tooltip = title = val;
|
||||
if (tid == Arg__tooltip) // note that this overrides pgname above
|
||||
tooltip = val;
|
||||
if (tid == Arg__bottomtoc && Bry_.Eq(val, Bry__yes))
|
||||
bottomtoc = true;
|
||||
if (tid == Arg__toc && Bry_.Eq(val, Bry__yes)) // REF.MW:addToc
|
||||
toc = Bry_.Empty; // note that "" will be overwritten later by actual toc html
|
||||
if ( tid == -1 // note that "icon-*" won't have a tid
|
||||
&& Bry_.Has_at_bgn(key, Bry__icon) // if (substr($key, 0, 5) === 'icon-')
|
||||
&& Bry_.Len(key) > 5 // if ( !isset( $iconname) )
|
||||
&& Bry_.Len_gt_0(val) // if ( !isset( $$value ) )
|
||||
) { // REF.MW:addIcons
|
||||
tid = Arg__icon;
|
||||
if (icons_list == null) icons_list = List_adp_.New();
|
||||
byte[] icon_key = Bry_.Mid(key, 5);
|
||||
byte[] icon_name = Xop_sanitizer.Escape_cls(icon_key);
|
||||
byte[] icon_title = icon_name;
|
||||
Xoa_ttl icon_ttl = wiki.Ttl_parse(val);
|
||||
byte[] icon_href = Bry__icon_href_dflt;
|
||||
if (icon_ttl != null) {
|
||||
icon_href = Bry_.Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki, icon_ttl.Page_db());
|
||||
icon_title = icon_ttl.Page_txt();
|
||||
}
|
||||
icons_list.Add(new Pgbnr_icon(tmp_bfr, icon_name, icon_title, icon_href));
|
||||
}
|
||||
if (tid == Arg__origin) { // REF.MW:addFocus
|
||||
double tmp_data_pos_x = Double_.NaN, tmp_data_pos_y = Double_.NaN;
|
||||
int comma_pos = Bry_find_.Find_fwd(val, Byte_ascii.Comma);
|
||||
if (comma_pos != Bry_find_.Not_found) {
|
||||
tmp_data_pos_x = Bry_.To_double_or(val, 0, comma_pos, Double_.NaN);
|
||||
if (!Double_.IsNaN(tmp_data_pos_x)) {
|
||||
if (tmp_data_pos_x >= -1 && tmp_data_pos_x <= 1) {
|
||||
data_pos_x = tmp_data_pos_x;
|
||||
origin_x = tmp_data_pos_x <= .25d ? Bry__origin_x__left : Bry__origin_x__right;
|
||||
}
|
||||
}
|
||||
if (!Double_.IsNaN(tmp_data_pos_y)) {
|
||||
if (tmp_data_pos_y >= -1 && tmp_data_pos_y <= 1)
|
||||
data_pos_y = tmp_data_pos_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tid == -1) Gfo_usr_dlg_.Instance.Warn_many("", "", "unknown arg type; page=~{0} key=~{1} val=~{2}", page.Ttl().Full_db(), key, val);
|
||||
}
|
||||
|
||||
byte[] banner_name = Eval_argx(ctx, src, caller, self);
|
||||
Xoa_ttl banner_ttl = wiki.Ttl_parse(banner_name); // NOTE: MW also creates title to auto-register page and image in imagelinks
|
||||
if (banner_ttl == null) // if ttl is invalid, get it from wikidata; PAGE:en.v:Diving_the_Cape_Peninsula_and_False_Bay/Whale_Rock; DATE:2016-07-12
|
||||
banner_ttl = Get_wikidata_banner(wiki.Appe(), wiki, wiki.Xtn_mgr().Xtn_pgbnr().Cfg(), page.Ttl());
|
||||
if (banner_ttl == null) { // if ttl is still invalid, exit now else will fail with nullref below; PAGE:en.v:Peterborough (New Hampshire); DATE:2016-07-12
|
||||
Gfo_usr_dlg_.Instance.Warn_many("", "", "banner file is invalid; page=~{0} banner=~{1}", page.Url_bry_safe(), banner_name);
|
||||
return;
|
||||
}
|
||||
Xof_file_itm banner_file_itm = File__make_tkn(ctx, Xop_file_logger_.Tid__pgbnr_main, banner_ttl, Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null);
|
||||
|
||||
Pgbnr_itm itm = new Pgbnr_itm();
|
||||
itm.Init_from_wtxt(banner_ttl, banner_file_itm, tooltip, title, bottomtoc, toc, data_pos_x, data_pos_y, origin_x, icons_list == null ? Pgbnr_icon.Ary_empty : (Pgbnr_icon[])icons_list.To_ary_and_clear(Pgbnr_icon.class));
|
||||
page.Html_data().Xtn_pgbnr_(itm);
|
||||
page.Html_data().Head_mgr().Itm__pgbnr().Enabled_y_(); // register css / js during parse stage
|
||||
page.Wtxt().Toc().Flag__toc_(true); // NOTE: must mark toc_manual else will show 2nd TOC in edit mode; DATE:2016-07-10
|
||||
}
|
||||
public static void Add_banner(Bry_bfr bfr, Xoae_page wpg, Xop_ctx ctx, Xoh_wtr_ctx hctx, Pgbnr_itm itm) {
|
||||
Xowe_wiki wiki = ctx.Wiki(); Xoae_app app = wiki.Appe();
|
||||
Pgbnr_cfg cfg = wiki.Xtn_mgr().Xtn_pgbnr().Cfg(); if (!cfg.enabled) return;
|
||||
Xoa_ttl ttl = wpg.Ttl();
|
||||
Xoa_ttl banner_ttl = null; byte[] banner_html = null;
|
||||
if (itm != null) { // {{PAGEBANNER}} exists in wikitext
|
||||
itm.Init_hdump(hctx.Mode_is_hdump());
|
||||
banner_ttl = itm.banner_ttl;
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
if (banner_html == null) { // no banner; try again using title from wikidata; note that this should only happen if no banner_ttl or banner_ttl is invalid; EX:{{PAGEBANNER:|toc=yes}}
|
||||
banner_ttl = Get_wikidata_banner(app, wiki, cfg, ttl);
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
}
|
||||
}
|
||||
else if ( ttl.Ns().Id_is_main() // {{PAGEBANNER}} missing, but wiki is marked as enable_default_banner
|
||||
&& cfg.enable_default_banner
|
||||
&& cfg.Chk_pgbnr_allowed(ttl, wiki)
|
||||
) {
|
||||
banner_ttl = Get_wikidata_banner(app, wiki, cfg, ttl);
|
||||
if (banner_ttl == null)
|
||||
banner_ttl = wiki.Ttl_parse(cfg.dflt_img_title);
|
||||
Xof_file_itm banner_file_itm = File__make_tkn(ctx, Xop_file_logger_.Tid__pgbnr_main, banner_ttl, Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null);
|
||||
itm = new Pgbnr_itm();
|
||||
itm.Init_from_wtxt(banner_ttl, banner_file_itm, Bry_.Empty, Bry_.Empty, false, Bry_.Empty, 0, 0, Bry_.Empty, Pgbnr_icon.Ary_empty);
|
||||
itm.Init_hdump(hctx.Mode_is_hdump());
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
}
|
||||
if (banner_html != null) {
|
||||
bfr.Add(banner_html);
|
||||
}
|
||||
}
|
||||
public static byte[] Get_banner_html(Xowe_wiki wiki, Xop_ctx ctx, Xoh_wtr_ctx hctx, Pgbnr_cfg cfg, Xoa_ttl banner_ttl, Pgbnr_itm itm) {
|
||||
byte[][] urls = Get_standard_size_urls(wiki, cfg, banner_ttl); if (urls == null) return null;
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
int urls_len = urls.length;
|
||||
int[] sizes = cfg.standard_sizes;
|
||||
for (int i = 0; i < urls_len; ++i) {
|
||||
int size = sizes[i];
|
||||
if (i != 0) tmp_bfr.Add_byte_comma();
|
||||
tmp_bfr.Add(urls[i]).Add_byte_space().Add_int_variable(size).Add_byte(Byte_ascii.Ltr_w); // REF.MW: $srcset[] = "$url {$size}w";
|
||||
}
|
||||
byte[] srcset = tmp_bfr.To_bry_and_clear();
|
||||
byte[] banner_url = itm.banner_img_src != null ? itm.banner_img_src : urls.length == 0 ? Bry_.Empty : urls[urls_len - 1]; // gets largest url
|
||||
Xof_file_itm banner_file_itm = itm.banner_file_itm;
|
||||
int max_width = banner_file_itm.Orig_w(); // $file = wfFindFile( banner_file ); $options['max_width'] = $file->getWidth();
|
||||
// Provide information to the logic-less template about whether it is a panorama or not.
|
||||
boolean isPanorama = banner_file_itm.Orig_w() > (banner_file_itm.Orig_h() * 2);
|
||||
byte[] banner_file = null; // $bannerfile->getLocalUrl();
|
||||
|
||||
byte[] toc_html = null;
|
||||
if (hctx.Mode_is_hdump()) {
|
||||
gplx.xowa.htmls.core.wkrs.tocs.Xoh_toc_wtr.Write_tag(tmp_bfr, true);
|
||||
toc_html = tmp_bfr.To_bry_and_clear();
|
||||
banner_file = Bry_.Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki, gplx.xowa.wikis.nss.Xow_ns_.Bry__file, Byte_ascii.Colon_bry
|
||||
, Gfo_url_encoder_.Href.Encode(banner_ttl.Full_db())); // NOTE: must encode so "'" becomes "%27", not "'"; PAGE:en.v:'s-Hertogenbosch; DATE:2016-07-12
|
||||
}
|
||||
else {
|
||||
ctx.Page().Html_data().Toc_mgr().To_html(tmp_bfr, Xoh_wtr_ctx.Basic, true);
|
||||
toc_html = tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
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_bfr mbfr = Mustache_bfr.New_bfr(tmp_bfr);
|
||||
wiki.Xtn_mgr().Xtn_pgbnr().Template_root().Render(mbfr, mctx);
|
||||
return mbfr.To_bry_and_clear();
|
||||
}
|
||||
private static byte[][] Get_standard_size_urls(Xow_wiki wiki, Pgbnr_cfg cfg, Xoa_ttl banner_ttl) {
|
||||
Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
int[] sizes = cfg.standard_sizes;
|
||||
int sizes_len = sizes.length;
|
||||
for (int i = 0; i < sizes_len; ++i) {
|
||||
byte[] url = Get_image_url(wiki, banner_ttl, sizes[i]);
|
||||
if (url != null)
|
||||
hash.Add_if_dupe_use_1st(url, url);
|
||||
}
|
||||
return (byte[][])hash.To_ary_and_clear(byte[].class);
|
||||
}
|
||||
private static byte[] Get_image_url(Xow_wiki wiki, Xoa_ttl banner_ttl, int width) {
|
||||
// Object file = new Object(); // $file = wfFindFile( file_ttl );
|
||||
// if (file == null) return null;
|
||||
if (width >= 0 && width <= 3000) {
|
||||
// $mto = $file->transform( array( 'width' => $imagewidth ) );
|
||||
byte[] url = new byte[0]; // $url = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT );
|
||||
return url;
|
||||
}
|
||||
else
|
||||
return new byte[0]; // $file->getFullUrl();
|
||||
}
|
||||
private static Xoa_ttl Get_wikidata_banner(Xoae_app app, Xow_wiki wiki, Pgbnr_cfg cfg, Xoa_ttl ttl) {
|
||||
byte[] rv = app.Wiki_mgr().Wdata_mgr().Get_claim_or(wiki.Domain_itm(), ttl, cfg.dflt_img_wdata_prop, null); // don't log misses; wikivoyage pages will default to show pagebanner, and many pages may not have wikidata definitions
|
||||
if (rv == null) return null;
|
||||
return wiki.Ttl_parse(rv);
|
||||
}
|
||||
private static Xof_file_itm File__make_tkn(Xop_ctx ctx, byte tid, Xoa_ttl file_ttl, int file_w, int file_h) {
|
||||
Xop_lnki_tkn lnki = ctx.Tkn_mkr().Lnki(file_w, file_h).Ttl_(file_ttl);
|
||||
ctx.Page().Lnki_list().Add(lnki);
|
||||
ctx.Lnki().File_logger().Log_file(tid, ctx, lnki); // NOTE: do not set file_wkr ref early (as member var); parse_all sets late
|
||||
Xof_file_itm file_itm = ctx.Wiki().Html_mgr().Html_wtr().Lnki_wtr().File_wtr().Lnki_eval(Xof_exec_tid.Tid_wiki_page, ctx, ctx.Page(), lnki);
|
||||
return file_itm;
|
||||
}
|
||||
private static final byte[] Bry__yes = Bry_.new_a7("yes"), Bry__icon = Bry_.new_a7("icon-"), Bry__icon_href_dflt = Bry_.new_a7("#"), Bry__origin_x__left = Bry_.new_a7("wpb-left"), Bry__origin_x__right = Bry_.new_a7("wpb-right");
|
||||
private static final int Arg__pgname = 0, Arg__tooltip = 1, Arg__bottomtoc = 2, Arg__toc = 3, Arg__icon = 4, Arg__origin = 5;
|
||||
private static final Hash_adp_bry arg_hash = Hash_adp_bry.cs().Add_str_int("pgname", Arg__pgname)
|
||||
.Add_str_int("tooltip", Arg__tooltip).Add_str_int("bottomtoc", Arg__bottomtoc).Add_str_int("toc", Arg__toc).Add_str_int("origin", Arg__origin);
|
||||
}
|
||||
package gplx.xowa.xtns.pagebanners;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bry_find_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Double_;
|
||||
import gplx.Gfo_usr_dlg_;
|
||||
import gplx.Hash_adp_bry;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.Ordered_hash;
|
||||
import gplx.Ordered_hash_;
|
||||
import gplx.langs.htmls.encoders.Gfo_url_encoder_;
|
||||
import gplx.langs.mustaches.JsonMustacheNde;
|
||||
import gplx.langs.mustaches.Mustache_bfr;
|
||||
import gplx.langs.mustaches.Mustache_render_ctx;
|
||||
import gplx.xowa.Xoa_ttl;
|
||||
import gplx.xowa.Xoae_app;
|
||||
import gplx.xowa.Xoae_page;
|
||||
import gplx.xowa.Xow_wiki;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.files.Xof_exec_tid;
|
||||
import gplx.xowa.files.Xof_file_itm;
|
||||
import gplx.xowa.htmls.core.htmls.Xoh_wtr_ctx;
|
||||
import gplx.xowa.langs.kwds.Xol_kwd_grp_;
|
||||
import gplx.xowa.parsers.Xop_ctx;
|
||||
import gplx.xowa.parsers.lnkis.Xop_lnki_tkn;
|
||||
import gplx.xowa.parsers.lnkis.files.Xop_file_logger_;
|
||||
import gplx.xowa.parsers.tmpls.Arg_nde_tkn;
|
||||
import gplx.xowa.parsers.tmpls.Xop_func_arg_itm;
|
||||
import gplx.xowa.parsers.tmpls.Xot_invk;
|
||||
import gplx.xowa.parsers.utils.Xop_sanitizer;
|
||||
import gplx.xowa.xtns.pfuncs.Pf_func;
|
||||
import gplx.xowa.xtns.pfuncs.Pf_func_base;
|
||||
|
||||
// REF.MW:https://github.com/wikimedia/mediawiki-extensions-WikidataPageBanner/blob/master/includes/WikidataPageBannerFunctions.php
|
||||
// TODO.DATE:2019-11-11: calculate enableToc and hasPosition;
|
||||
public class Pgbnr_func extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_pagebanner;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pgbnr_func().Name_(name);}
|
||||
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { // {{PAGEBANNER}} appears on page; WikidataPageBanner.hooks.php|addCustomBanner
|
||||
Xowe_wiki wiki = ctx.Wiki(); Xoae_page page = ctx.Page();
|
||||
Pgbnr_xtn_mgr xtn_mgr = wiki.Xtn_mgr().Xtn_pgbnr();
|
||||
Pgbnr_cfg cfg = xtn_mgr.Cfg();
|
||||
Xoa_ttl ttl = page.Ttl();
|
||||
if (!cfg.Chk_pgbnr_allowed(ttl, wiki)) return;
|
||||
byte[] tooltip = ttl.Page_txt(), title = ttl.Page_txt(), toc = Bry_.Empty, origin_x = Bry_.Empty;
|
||||
boolean bottomtoc = false;;
|
||||
double data_pos_x = 0, data_pos_y = 0;
|
||||
List_adp icons_list = null;
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
int args_len = self.Args_len();
|
||||
Xop_func_arg_itm func_arg = new Xop_func_arg_itm();
|
||||
for (int i = 0; i < args_len; ++i) {
|
||||
Arg_nde_tkn arg = self.Args_get_by_idx(i);
|
||||
func_arg.Set(tmp_bfr, ctx, src, caller, self, arg);
|
||||
byte[] key = func_arg.key;
|
||||
byte[] val = func_arg.val;
|
||||
if (key == Bry_.Empty) continue; // ignore blank args; EX:{{PAGEBANNER:A.png|\n|toc=yes}}
|
||||
int tid = arg_hash.Get_as_int_or(key, -1);
|
||||
if (tid == Arg__pgname)
|
||||
tooltip = title = val;
|
||||
if (tid == Arg__tooltip) // note that this overrides pgname above
|
||||
tooltip = val;
|
||||
if (tid == Arg__bottomtoc && Bry_.Eq(val, Bry__yes))
|
||||
bottomtoc = true;
|
||||
if (tid == Arg__toc && Bry_.Eq(val, Bry__yes)) // REF.MW:addToc
|
||||
toc = Bry_.Empty; // note that "" will be overwritten later by actual toc html
|
||||
if ( tid == -1 // note that "icon-*" won't have a tid
|
||||
&& Bry_.Has_at_bgn(key, Bry__icon) // if (substr($key, 0, 5) === 'icon-')
|
||||
&& Bry_.Len(key) > 5 // if ( !isset( $iconname) )
|
||||
&& Bry_.Len_gt_0(val) // if ( !isset( $$value ) )
|
||||
) { // REF.MW:addIcons
|
||||
tid = Arg__icon;
|
||||
if (icons_list == null) icons_list = List_adp_.New();
|
||||
byte[] icon_key = Bry_.Mid(key, 5);
|
||||
byte[] icon_name = Xop_sanitizer.Escape_cls(icon_key);
|
||||
byte[] icon_title = icon_name;
|
||||
Xoa_ttl icon_ttl = wiki.Ttl_parse(val);
|
||||
byte[] icon_href = Bry__icon_href_dflt;
|
||||
if (icon_ttl != null) {
|
||||
icon_href = Bry_.Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki, icon_ttl.Page_db());
|
||||
icon_title = icon_ttl.Page_txt();
|
||||
}
|
||||
icons_list.Add(new Pgbnr_icon(tmp_bfr, icon_name, icon_title, icon_href));
|
||||
// itm.Add_new_icon(tmp_bfr, icon_name, icon_title, icon_href);
|
||||
}
|
||||
if (tid == Arg__origin) { // REF.MW:addFocus
|
||||
double tmp_data_pos_x = Double_.NaN, tmp_data_pos_y = Double_.NaN;
|
||||
int comma_pos = Bry_find_.Find_fwd(val, Byte_ascii.Comma);
|
||||
if (comma_pos != Bry_find_.Not_found) {
|
||||
tmp_data_pos_x = Bry_.To_double_or(val, 0, comma_pos, Double_.NaN);
|
||||
if (!Double_.IsNaN(tmp_data_pos_x)) {
|
||||
if (tmp_data_pos_x >= -1 && tmp_data_pos_x <= 1) {
|
||||
data_pos_x = tmp_data_pos_x;
|
||||
origin_x = tmp_data_pos_x <= .25d ? Bry__origin_x__left : Bry__origin_x__right;
|
||||
}
|
||||
}
|
||||
if (!Double_.IsNaN(tmp_data_pos_y)) {
|
||||
if (tmp_data_pos_y >= -1 && tmp_data_pos_y <= 1)
|
||||
data_pos_y = tmp_data_pos_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tid == -1) Gfo_usr_dlg_.Instance.Warn_many("", "", "unknown arg type; page=~{0} key=~{1} val=~{2}", page.Ttl().Full_db(), key, val);
|
||||
}
|
||||
|
||||
byte[] banner_name = Eval_argx(ctx, src, caller, self);
|
||||
Xoa_ttl banner_ttl = wiki.Ttl_parse(banner_name); // NOTE: MW also creates title to auto-register page and image in imagelinks
|
||||
if (banner_ttl == null) // if ttl is invalid, get it from wikidata; PAGE:en.v:Diving_the_Cape_Peninsula_and_False_Bay/Whale_Rock; DATE:2016-07-12
|
||||
banner_ttl = Get_wikidata_banner(wiki.Appe(), wiki, wiki.Xtn_mgr().Xtn_pgbnr().Cfg(), page.Ttl());
|
||||
if (banner_ttl == null) { // if ttl is still invalid, exit now else will fail with nullref below; PAGE:en.v:Peterborough (New Hampshire); DATE:2016-07-12
|
||||
Gfo_usr_dlg_.Instance.Warn_many("", "", "banner file is invalid; page=~{0} banner=~{1}", page.Url_bry_safe(), banner_name);
|
||||
return;
|
||||
}
|
||||
Xof_file_itm banner_file_itm = File__make_tkn(ctx, Xop_file_logger_.Tid__pgbnr_main, banner_ttl, Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null);
|
||||
|
||||
Pgbnr_itm itm = new Pgbnr_itm();
|
||||
itm.Init_from_wtxt(banner_ttl, banner_file_itm, tooltip, title, bottomtoc, toc, data_pos_x, data_pos_y, origin_x, icons_list == null ? Pgbnr_icon.Ary_empty : (Pgbnr_icon[])icons_list.To_ary_and_clear(Pgbnr_icon.class));
|
||||
page.Html_data().Xtn_pgbnr_(itm);
|
||||
page.Html_data().Head_mgr().Itm__pgbnr().Enabled_y_(); // register css / js during parse stage
|
||||
page.Wtxt().Toc().Flag__toc_(true); // NOTE: must mark toc_manual else will show 2nd TOC in edit mode; DATE:2016-07-10
|
||||
}
|
||||
public static void Add_banner(Bry_bfr bfr, Xoae_page wpg, Xop_ctx ctx, Xoh_wtr_ctx hctx, Pgbnr_itm itm) {
|
||||
Xowe_wiki wiki = ctx.Wiki(); Xoae_app app = wiki.Appe();
|
||||
Pgbnr_cfg cfg = wiki.Xtn_mgr().Xtn_pgbnr().Cfg(); if (!cfg.enabled) return;
|
||||
Xoa_ttl ttl = wpg.Ttl();
|
||||
Xoa_ttl banner_ttl = null; byte[] banner_html = null;
|
||||
if (itm != null) { // {{PAGEBANNER}} exists in wikitext
|
||||
itm.Init_hdump(hctx.Mode_is_hdump());
|
||||
banner_ttl = itm.banner_ttl;
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
if (banner_html == null) { // no banner; try again using title from wikidata; note that this should only happen if no banner_ttl or banner_ttl is invalid; EX:{{PAGEBANNER:|toc=yes}}
|
||||
banner_ttl = Get_wikidata_banner(app, wiki, cfg, ttl);
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
}
|
||||
}
|
||||
else if ( ttl.Ns().Id_is_main() // {{PAGEBANNER}} missing, but wiki is marked as enable_default_banner
|
||||
&& cfg.enable_default_banner
|
||||
&& cfg.Chk_pgbnr_allowed(ttl, wiki)
|
||||
) {
|
||||
banner_ttl = Get_wikidata_banner(app, wiki, cfg, ttl);
|
||||
if (banner_ttl == null)
|
||||
banner_ttl = wiki.Ttl_parse(cfg.dflt_img_title);
|
||||
Xof_file_itm banner_file_itm = File__make_tkn(ctx, Xop_file_logger_.Tid__pgbnr_main, banner_ttl, Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null);
|
||||
itm = new Pgbnr_itm();
|
||||
itm.Init_from_wtxt(banner_ttl, banner_file_itm, Bry_.Empty, Bry_.Empty, false, Bry_.Empty, 0, 0, Bry_.Empty, Pgbnr_icon.Ary_empty);
|
||||
itm.Init_hdump(hctx.Mode_is_hdump());
|
||||
banner_html = Get_banner_html(wiki, ctx, hctx, cfg, banner_ttl, itm);
|
||||
}
|
||||
if (banner_html != null) {
|
||||
bfr.Add(banner_html);
|
||||
}
|
||||
}
|
||||
public static byte[] Get_banner_html(Xowe_wiki wiki, Xop_ctx ctx, Xoh_wtr_ctx hctx, Pgbnr_cfg cfg, Xoa_ttl banner_ttl, Pgbnr_itm itm) {
|
||||
byte[][] urls = Get_standard_size_urls(wiki, cfg, banner_ttl); if (urls == null) return null;
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
int urls_len = urls.length;
|
||||
int[] sizes = cfg.standard_sizes;
|
||||
for (int i = 0; i < urls_len; ++i) {
|
||||
int size = sizes[i];
|
||||
if (i != 0) tmp_bfr.Add_byte_comma();
|
||||
tmp_bfr.Add(urls[i]).Add_byte_space().Add_int_variable(size).Add_byte(Byte_ascii.Ltr_w); // REF.MW: $srcset[] = "$url {$size}w";
|
||||
}
|
||||
byte[] srcset = tmp_bfr.To_bry_and_clear();
|
||||
byte[] banner_url = itm.banner_img_src != null ? itm.banner_img_src : urls.length == 0 ? Bry_.Empty : urls[urls_len - 1]; // gets largest url
|
||||
Xof_file_itm banner_file_itm = itm.banner_file_itm;
|
||||
int max_width = banner_file_itm.Orig_w(); // $file = wfFindFile( banner_file ); $options['max_width'] = $file->getWidth();
|
||||
// Provide information to the logic-less template about whether it is a panorama or not.
|
||||
boolean isPanorama = banner_file_itm.Orig_w() > (banner_file_itm.Orig_h() * 2);
|
||||
byte[] banner_file = null; // $bannerfile->getLocalUrl();
|
||||
|
||||
byte[] toc_html = null;
|
||||
if (hctx.Mode_is_hdump()) {
|
||||
gplx.xowa.htmls.core.wkrs.tocs.Xoh_toc_wtr.Write_tag(tmp_bfr, true);
|
||||
toc_html = tmp_bfr.To_bry_and_clear();
|
||||
banner_file = Bry_.Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki, gplx.xowa.wikis.nss.Xow_ns_.Bry__file, Byte_ascii.Colon_bry
|
||||
, Gfo_url_encoder_.Href.Encode(banner_ttl.Full_db())); // NOTE: must encode so "'" becomes "%27", not "'"; PAGE:en.v:'s-Hertogenbosch; DATE:2016-07-12
|
||||
}
|
||||
else {
|
||||
ctx.Page().Html_data().Toc_mgr().To_html(tmp_bfr, Xoh_wtr_ctx.Basic, true);
|
||||
toc_html = tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
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(new JsonMustacheNde(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);
|
||||
return mbfr.To_bry_and_clear();
|
||||
}
|
||||
private static byte[][] Get_standard_size_urls(Xow_wiki wiki, Pgbnr_cfg cfg, Xoa_ttl banner_ttl) {
|
||||
Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
int[] sizes = cfg.standard_sizes;
|
||||
int sizes_len = sizes.length;
|
||||
for (int i = 0; i < sizes_len; ++i) {
|
||||
byte[] url = Get_image_url(wiki, banner_ttl, sizes[i]);
|
||||
if (url != null)
|
||||
hash.Add_if_dupe_use_1st(url, url);
|
||||
}
|
||||
return (byte[][])hash.To_ary_and_clear(byte[].class);
|
||||
}
|
||||
private static byte[] Get_image_url(Xow_wiki wiki, Xoa_ttl banner_ttl, int width) {
|
||||
// Object file = new Object(); // $file = wfFindFile( file_ttl );
|
||||
// if (file == null) return null;
|
||||
if (width >= 0 && width <= 3000) {
|
||||
// $mto = $file->transform( array( 'width' => $imagewidth ) );
|
||||
byte[] url = new byte[0]; // $url = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT );
|
||||
return url;
|
||||
}
|
||||
else
|
||||
return new byte[0]; // $file->getFullUrl();
|
||||
}
|
||||
private static Xoa_ttl Get_wikidata_banner(Xoae_app app, Xow_wiki wiki, Pgbnr_cfg cfg, Xoa_ttl ttl) {
|
||||
byte[] rv = app.Wiki_mgr().Wdata_mgr().Get_claim_or(wiki.Domain_itm(), ttl, cfg.dflt_img_wdata_prop, null); // don't log misses; wikivoyage pages will default to show pagebanner, and many pages may not have wikidata definitions
|
||||
if (rv == null) return null;
|
||||
return wiki.Ttl_parse(rv);
|
||||
}
|
||||
private static Xof_file_itm File__make_tkn(Xop_ctx ctx, byte tid, Xoa_ttl file_ttl, int file_w, int file_h) {
|
||||
Xop_lnki_tkn lnki = ctx.Tkn_mkr().Lnki(file_w, file_h).Ttl_(file_ttl);
|
||||
ctx.Page().Lnki_list().Add(lnki);
|
||||
ctx.Lnki().File_logger().Log_file(tid, ctx, lnki); // NOTE: do not set file_wkr ref early (as member var); parse_all sets late
|
||||
Xof_file_itm file_itm = ctx.Wiki().Html_mgr().Html_wtr().Lnki_wtr().File_wtr().Lnki_eval(Xof_exec_tid.Tid_wiki_page, ctx, ctx.Page(), lnki);
|
||||
return file_itm;
|
||||
}
|
||||
private static final byte[] Bry__yes = Bry_.new_a7("yes"), Bry__icon = Bry_.new_a7("icon-"), Bry__icon_href_dflt = Bry_.new_a7("#"), Bry__origin_x__left = Bry_.new_a7("wpb-left"), Bry__origin_x__right = Bry_.new_a7("wpb-right");
|
||||
private static final int Arg__pgname = 0, Arg__tooltip = 1, Arg__bottomtoc = 2, Arg__toc = 3, Arg__icon = 4, Arg__origin = 5;
|
||||
private static final Hash_adp_bry arg_hash = Hash_adp_bry.cs().Add_str_int("pgname", Arg__pgname)
|
||||
.Add_str_int("tooltip", Arg__tooltip).Add_str_int("bottomtoc", Arg__bottomtoc).Add_str_int("toc", Arg__toc).Add_str_int("origin", Arg__origin);
|
||||
}
|
||||
|
@ -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,79 +13,92 @@ 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.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import org.junit.*; import gplx.core.brys.*; import gplx.xowa.wikis.pages.skins.*;
|
||||
import gplx.xowa.htmls.core.htmls.*;
|
||||
public class Pgbnr_func_tst {
|
||||
private final Pgbnr_func_fxt fxt = new Pgbnr_func_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
@Test public void Basic() {
|
||||
fxt.Init__orig(true, "A.png", 500, 200); // 500 > 200 * 2 for pageBanner;
|
||||
fxt.Test__parse(Bool_.N, "{{PAGEBANNER:A.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-banner-image-panorama wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='' class='image' title='Test page' xowa_title='A.png'><img id='xoimg_0' src='file:///mem/wiki/repo/src/orig/7/0/A.png' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:500px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div>"
|
||||
, " <div id=\"toctitle\" class=\"toctitle\">"
|
||||
, " <h2>Contents</h2>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
, "</div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Hdump__basic() {
|
||||
fxt.Test__parse(Bool_.Y, "{{PAGEBANNER:A.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='/wiki/File:A.png' class='image' title='Test page' xowa_title='A.png'>"
|
||||
+ "<img data-xowa-title=\"A.png\" data-xoimg=\"1|-1|-1|-1|-1|-1\" src='' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:0px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div class=\"xo-toc\" data-toc-mode=\"1\"></div></div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Hdump__quote() { // PAGE:en.v:Europe; DATE:2016-07-12
|
||||
fxt.Test__parse(Bool_.Y, "{{PAGEBANNER:A\"b.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='/wiki/File:A%22b.png' class='image' title='Test page' xowa_title='A%22b.png'><img data-xowa-title=\"A%22b.png\" data-xoimg=\"1|-1|-1|-1|-1|-1\" src='' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:0px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div class=\"xo-toc\" data-toc-mode=\"1\"></div></div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Pgbnr_func_fxt {
|
||||
private Xop_fxt fxt;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.Make__app__edit();
|
||||
Xowe_wiki wiki = Xoa_app_fxt.Make__wiki__edit(app, "en.wikivoyage.org");
|
||||
fxt = new Xop_fxt(app, wiki);
|
||||
fxt.Init__file_find_mgr();
|
||||
}
|
||||
public void Init__orig(boolean wiki_is_commons, String orig_ttl, int orig_w, int orig_h) {
|
||||
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);
|
||||
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();
|
||||
arg.Bfr_arg__add(bfr);
|
||||
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
package gplx.xowa.xtns.pagebanners;
|
||||
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.String_;
|
||||
import gplx.Tfds;
|
||||
import gplx.core.brys.Bfr_arg;
|
||||
import gplx.xowa.Xoa_app_fxt;
|
||||
import gplx.xowa.Xoae_app;
|
||||
import gplx.xowa.Xop_fxt;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.htmls.core.htmls.Xoh_wtr_ctx;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Pgbnr_func_tst {
|
||||
private final Pgbnr_func_fxt fxt = new Pgbnr_func_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
@Test public void Basic() {
|
||||
fxt.Init__orig(true, "A.png", 500, 200); // 500 > 200 * 2 for pageBanner;
|
||||
fxt.Test__parse(Bool_.N, "{{PAGEBANNER:A.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-banner-image-panorama wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='' class='image' title='Test page' xowa_title='A.png'><img id='xoimg_0' src='file:///mem/wiki/repo/src/orig/7/0/A.png' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:500px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div>"
|
||||
, " <div id=\"toctitle\" class=\"toctitle\">"
|
||||
, " <h2>Contents</h2>"
|
||||
, " </div>"
|
||||
, "</div>"
|
||||
, "</div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Hdump__basic() {
|
||||
fxt.Test__parse(Bool_.Y, "{{PAGEBANNER:A.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='/wiki/File:A.png' class='image' title='Test page' xowa_title='A.png'>"
|
||||
+ "<img data-xowa-title=\"A.png\" data-xoimg=\"1|-1|-1|-1|-1|-1\" src='' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:0px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div class=\"xo-toc\" data-toc-mode=\"1\"></div></div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Hdump__quote() { // PAGE:en.v:Europe; DATE:2016-07-12
|
||||
fxt.Test__parse(Bool_.Y, "{{PAGEBANNER:A\"b.png|icon-star=Star_article}}", String_.Concat_lines_nl_apos_skip_last
|
||||
( "<div class='ext-wpb-pagebanner pre-content'>"
|
||||
, " <div class='wpb-topbanner'>"
|
||||
, " <h1 class='wpb-name'>Test page</h1>"
|
||||
, " <a href='/wiki/File:A%22b.png' class='image' title='Test page' xowa_title='A%22b.png'><img data-xowa-title=\"A%22b.png\" data-xoimg=\"1|-1|-1|-1|-1|-1\" src='' width='0' height='0' class='wpb-banner-image ' alt='' srcset='' data-pos-x='0' data-pos-y='0' style='max-width:0px'></a>"
|
||||
, " <div class='wpb-iconbox'>"
|
||||
, " <a href='/wiki/Star_article'><span aria-disabled='false' title='Star article' class='oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement-icon oo-ui-icon-star oo-ui-iconElement oo-ui-iconWidget'></span></a>"
|
||||
, " </div>"
|
||||
, " </div>"
|
||||
, " <div class='wpb-topbanner-toc'><div class='wpb-banner-toc'><div class=\"xo-toc\" data-toc-mode=\"1\"></div></div></div>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Pgbnr_func_fxt {
|
||||
private Xop_fxt fxt;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.Make__app__edit();
|
||||
Xowe_wiki wiki = Xoa_app_fxt.Make__wiki__edit(app, "en.wikivoyage.org");
|
||||
fxt = new Xop_fxt(app, wiki);
|
||||
fxt.Init__file_find_mgr();
|
||||
}
|
||||
public void Init__orig(boolean wiki_is_commons, String orig_ttl, int orig_w, int orig_h) {
|
||||
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);
|
||||
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();
|
||||
arg.Bfr_arg__add(bfr);
|
||||
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
|
@ -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,28 +13,39 @@ 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.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.core.brys.fmtrs.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
public class Pgbnr_icon implements Mustache_doc_itm {
|
||||
private final byte[] name, title, href, html;
|
||||
public Pgbnr_icon(Bry_bfr tmp_bfr, byte[] name, byte[] title, byte[] href) {
|
||||
this.name = name; this.title = title; this.href = href;
|
||||
fmt.Bld_many(tmp_bfr, name, title);
|
||||
this.html = tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "name")) bfr.Add_bry(name);
|
||||
else if (String_.Eq(key, "title")) bfr.Add_bry(title);
|
||||
else if (String_.Eq(key, "url")) bfr.Add_bry(href);
|
||||
else if (String_.Eq(key, "html")) bfr.Add_bry(html);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
public static final Pgbnr_icon[] Ary_empty = new Pgbnr_icon[0];
|
||||
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"
|
||||
);
|
||||
}
|
||||
package gplx.xowa.xtns.pagebanners;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_fmt;
|
||||
import gplx.String_;
|
||||
import gplx.langs.mustaches.Mustache_bfr;
|
||||
import gplx.langs.mustaches.Mustache_doc_itm;
|
||||
import gplx.langs.mustaches.Mustache_doc_itm_;
|
||||
|
||||
public class Pgbnr_icon implements Mustache_doc_itm {
|
||||
private final byte[] name, title, href, html;
|
||||
public Pgbnr_icon(Bry_bfr tmp_bfr, byte[] name, byte[] title, byte[] href) {
|
||||
this.name = name; this.title = title; this.href = href;
|
||||
fmt.Bld_many(tmp_bfr, name, title);
|
||||
this.html = tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
public byte[] Name() {return name;}
|
||||
public byte[] Title() {return title;}
|
||||
public byte[] Href() {return href;}
|
||||
public byte[] Html() {return html;}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "name")) bfr.Add_bry(name);
|
||||
else if (String_.Eq(key, "title")) bfr.Add_bry(title);
|
||||
else if (String_.Eq(key, "url")) bfr.Add_bry(href);
|
||||
else if (String_.Eq(key, "html")) bfr.Add_bry(html);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
public static final Pgbnr_icon[] Ary_empty = new Pgbnr_icon[0];
|
||||
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"
|
||||
);
|
||||
}
|
||||
|
@ -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,117 +13,224 @@ 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.xtns.pagebanners; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
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.*;
|
||||
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 double data_pos_x, data_pos_y;
|
||||
private int max_width;
|
||||
private boolean bottomtoc, isHeadingOverrideEnabled;
|
||||
private byte[] file_ttl;
|
||||
private Pgbnr_icon[] icons;
|
||||
private byte[] img_id_atr, img_xottl_atr, img_xoimg_atr;
|
||||
private boolean isPanorama;
|
||||
private boolean enable_toc = true;
|
||||
private boolean hasPosition = false;
|
||||
|
||||
// NOTE: used by hdump
|
||||
public boolean Exists() {return exists;} private boolean exists;
|
||||
public byte[] Srcset() {return srcset;}
|
||||
public byte[] Style_if_not_dflt() {return Bry_.Eq(style, Atr_val__style_dflt) ? Bry_.Empty : style;}
|
||||
public byte[] Style() {return style;} private byte[] style;
|
||||
public double Data_pos_x() {return data_pos_x;}
|
||||
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
|
||||
|
||||
public void Clear_by_hdump() {
|
||||
this.exists = false;
|
||||
this.srcset = style = null;
|
||||
this.data_pos_x = this.data_pos_y = 0;
|
||||
}
|
||||
public void Init_by_parse(Gfh_tag tag) {
|
||||
this.exists = true;
|
||||
this.srcset = tag.Atrs__get_as_bry(Atr_key__srcset);
|
||||
this.style = tag.Atrs__get_as_bry(Gfh_atr_.Bry__style);
|
||||
this.data_pos_x = tag.Atrs__get_as_double_or(Atr_key__data_pos_x, 0);
|
||||
this.data_pos_y = tag.Atrs__get_as_double_or(Atr_key__data_pos_y, 0);
|
||||
}
|
||||
public void Init_by_decode(double data_pos_x, double data_pos_y, byte[] srcset, byte[] style_if_not_dflt) {
|
||||
this.data_pos_x = data_pos_x;
|
||||
this.data_pos_y = data_pos_y;
|
||||
this.srcset = srcset;
|
||||
this.style = Bry_.Eq(style_if_not_dflt, Bry_.Empty) ? Atr_val__style_dflt : style_if_not_dflt;
|
||||
this.exists = true;
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
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;
|
||||
this.banner_anch_href = banner_anch_href;
|
||||
this.banner_img_src = banner_img_src;
|
||||
this.srcset = srcset;
|
||||
this.isHeadingOverrideEnabled = isHeadingOverrideEnabled;
|
||||
this.toc = toc;
|
||||
this.isPanorama = isPanorama;
|
||||
}
|
||||
public void Init_hdump(boolean mode_is_hdump) {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
if (mode_is_hdump) {
|
||||
this.img_id_atr = Bry_.Empty;
|
||||
this.img_xottl_atr = Gfh_atr_.Add_to_bry(tmp_bfr, Xoh_img_xoimg_data.Bry__data_xowa_title, file_ttl);
|
||||
this.img_xoimg_atr = Gfh_atr_.Add_to_bry(tmp_bfr, Xoh_img_xoimg_data.Bry__data_xowa_image, Xoh_img_xoimg_data.Bry__data_xowa_image__full);
|
||||
this.banner_img_src = Bry_.Empty; // do not write img_src else hzip_diff will complain for every image; DATE:2016-10-18
|
||||
}
|
||||
else {
|
||||
this.img_id_atr = tmp_bfr.Add(Bry__anch_atr_id).Add_int_variable(banner_file_itm.Html_uid()).Add_byte_quote().To_bry_and_clear();
|
||||
this.img_xottl_atr = this.img_xoimg_atr = Bry_.Empty;
|
||||
}
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "title")) bfr.Add_bry(banner_hdr_text);
|
||||
else if (String_.Eq(key, "tooltip")) bfr.Add_bry(banner_anch_title);
|
||||
else if (String_.Eq(key, "bannerfile")) bfr.Add_bry(banner_anch_href);
|
||||
else if (String_.Eq(key, "banner")) bfr.Add_bry(banner_img_src);
|
||||
else if (String_.Eq(key, "srcset")) bfr.Add_bry(srcset == null ? Bry_.Empty : Bry_.Empty);
|
||||
else if (String_.Eq(key, "originx")) bfr.Add_bry(originx);
|
||||
else if (String_.Eq(key, "data-pos-x")) bfr.Add_double(data_pos_x);
|
||||
else if (String_.Eq(key, "data-pos-y")) bfr.Add_double(data_pos_y);
|
||||
else if (String_.Eq(key, "maxWidth")) bfr.Add_int(max_width);
|
||||
else if (String_.Eq(key, "toc")) bfr.Add_bry(toc);
|
||||
else if (String_.Eq(key, "img_id_atr")) bfr.Add_bry(img_id_atr);
|
||||
else if (String_.Eq(key, "img_xottl")) bfr.Add_bry(img_xottl_atr);
|
||||
else if (String_.Eq(key, "img_xoimg")) bfr.Add_bry(img_xoimg_atr);
|
||||
else if (String_.Eq(key, "file_ttl")) bfr.Add_bry(file_ttl);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "icons")) return icons;
|
||||
else if (String_.Eq(key, "hasIcons")) return Mustache_doc_itm_.Ary__bool(icons.length > 0);
|
||||
else if (String_.Eq(key, "bottomtoc")) return Mustache_doc_itm_.Ary__bool(bottomtoc);
|
||||
else if (String_.Eq(key, "isHeadingOverrideEnabled")) return Mustache_doc_itm_.Ary__bool(isHeadingOverrideEnabled);
|
||||
else if (String_.Eq(key, "isPanorama")) return Mustache_doc_itm_.Ary__bool(isPanorama);
|
||||
else if (String_.Eq(key, "enable-toc")) return Mustache_doc_itm_.Ary__bool(enable_toc);
|
||||
else if (String_.Eq(key, "hasPosition")) return Mustache_doc_itm_.Ary__bool(hasPosition);
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
private static final byte[] Bry__anch_atr_id = Bry_.new_a7(" id=\"xoimg_");
|
||||
public static final byte[]
|
||||
Atr_key__srcset = Bry_.new_a7("srcset")
|
||||
, Atr_key__data_pos_x = Bry_.new_a7("data-pos-x")
|
||||
, Atr_key__data_pos_y = Bry_.new_a7("data-pos-y")
|
||||
, Atr_val__style_dflt = Bry_.new_a7("max-width:-1px")
|
||||
;
|
||||
}
|
||||
package gplx.xowa.xtns.pagebanners;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Bry_fmt;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.String_;
|
||||
import gplx.langs.htmls.Gfh_atr_;
|
||||
import gplx.langs.htmls.docs.Gfh_tag;
|
||||
import gplx.langs.htmls.encoders.Gfo_url_encoder_;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.mustaches.Mustache_bfr;
|
||||
import gplx.langs.mustaches.Mustache_doc_itm;
|
||||
import gplx.langs.mustaches.Mustache_doc_itm_;
|
||||
import gplx.xowa.Xoa_ttl;
|
||||
import gplx.xowa.files.Xof_file_itm;
|
||||
import gplx.xowa.htmls.core.wkrs.imgs.atrs.Xoh_img_xoimg_data;
|
||||
|
||||
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, srcset;
|
||||
private double data_pos_x, data_pos_y;
|
||||
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;
|
||||
public /**/ boolean isPanorama;
|
||||
private boolean enable_toc = true;
|
||||
private boolean hasPosition = false;
|
||||
|
||||
// NOTE: used by hdump
|
||||
public boolean Exists() {return exists;} private boolean exists;
|
||||
public byte[] Srcset() {return srcset;}
|
||||
public byte[] Style_if_not_dflt() {return Bry_.Eq(style, Atr_val__style_dflt) ? Bry_.Empty : style;}
|
||||
public byte[] Style() {return style;} private byte[] style;
|
||||
public double Data_pos_x() {return data_pos_x;}
|
||||
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;
|
||||
this.data_pos_x = this.data_pos_y = 0;
|
||||
}
|
||||
public void Init_by_parse(Gfh_tag tag) {
|
||||
this.exists = true;
|
||||
this.srcset = tag.Atrs__get_as_bry(Atr_key__srcset);
|
||||
this.style = tag.Atrs__get_as_bry(Gfh_atr_.Bry__style);
|
||||
this.data_pos_x = tag.Atrs__get_as_double_or(Atr_key__data_pos_x, 0);
|
||||
this.data_pos_y = tag.Atrs__get_as_double_or(Atr_key__data_pos_y, 0);
|
||||
}
|
||||
public void Init_by_decode(double data_pos_x, double data_pos_y, byte[] srcset, byte[] style_if_not_dflt) {
|
||||
this.data_pos_x = data_pos_x;
|
||||
this.data_pos_y = data_pos_y;
|
||||
this.srcset = srcset;
|
||||
this.style = Bry_.Eq(style_if_not_dflt, Bry_.Empty) ? Atr_val__style_dflt : style_if_not_dflt;
|
||||
this.exists = true;
|
||||
}
|
||||
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;
|
||||
this.banner_anch_href = banner_anch_href;
|
||||
this.banner_img_src = banner_img_src;
|
||||
this.srcset = srcset;
|
||||
this.isHeadingOverrideEnabled = isHeadingOverrideEnabled;
|
||||
this.toc = toc;
|
||||
this.isPanorama = isPanorama;
|
||||
}
|
||||
public void Init_hdump(boolean mode_is_hdump) {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
if (mode_is_hdump) {
|
||||
this.img_id_atr = Bry_.Empty;
|
||||
this.img_xottl_atr = Gfh_atr_.Add_to_bry(tmp_bfr, Xoh_img_xoimg_data.Bry__data_xowa_title, file_ttl);
|
||||
this.img_xoimg_atr = Gfh_atr_.Add_to_bry(tmp_bfr, Xoh_img_xoimg_data.Bry__data_xowa_image, Xoh_img_xoimg_data.Bry__data_xowa_image__full);
|
||||
this.banner_img_src = Bry_.Empty; // do not write img_src else hzip_diff will complain for every image; DATE:2016-10-18
|
||||
}
|
||||
else {
|
||||
this.img_id_atr = tmp_bfr.Add(Bry__anch_atr_id).Add_int_variable(banner_file_itm.Html_uid()).Add_byte_quote().To_bry_and_clear();
|
||||
this.img_xottl_atr = this.img_xoimg_atr = Bry_.Empty;
|
||||
}
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "title")) bfr.Add_bry(banner_hdr_text);
|
||||
else if (String_.Eq(key, "tooltip")) bfr.Add_bry(banner_anch_title);
|
||||
else if (String_.Eq(key, "bannerfile")) bfr.Add_bry(banner_anch_href);
|
||||
else if (String_.Eq(key, "banner")) bfr.Add_bry(banner_img_src);
|
||||
else if (String_.Eq(key, "srcset")) bfr.Add_bry(srcset == null ? Bry_.Empty : Bry_.Empty);
|
||||
else if (String_.Eq(key, "originx")) bfr.Add_bry(originx);
|
||||
else if (String_.Eq(key, "data-pos-x")) bfr.Add_double(data_pos_x);
|
||||
else if (String_.Eq(key, "data-pos-y")) bfr.Add_double(data_pos_y);
|
||||
else if (String_.Eq(key, "maxWidth")) bfr.Add_int(max_width);
|
||||
else if (String_.Eq(key, "toc")) bfr.Add_bry(toc);
|
||||
else if (String_.Eq(key, "img_id_atr")) bfr.Add_bry(img_id_atr);
|
||||
else if (String_.Eq(key, "img_xottl")) bfr.Add_bry(img_xottl_atr);
|
||||
else if (String_.Eq(key, "img_xoimg")) bfr.Add_bry(img_xoimg_atr);
|
||||
else if (String_.Eq(key, "file_ttl")) bfr.Add_bry(file_ttl);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "icons")) return icons;
|
||||
else if (String_.Eq(key, "hasIcons")) return Mustache_doc_itm_.Ary__bool(icons.length > 0);
|
||||
else if (String_.Eq(key, "bottomtoc")) return Mustache_doc_itm_.Ary__bool(bottomtoc);
|
||||
else if (String_.Eq(key, "isHeadingOverrideEnabled")) return Mustache_doc_itm_.Ary__bool(isHeadingOverrideEnabled);
|
||||
else if (String_.Eq(key, "isPanorama")) return Mustache_doc_itm_.Ary__bool(isPanorama);
|
||||
else if (String_.Eq(key, "enable-toc")) return Mustache_doc_itm_.Ary__bool(enable_toc);
|
||||
else if (String_.Eq(key, "hasPosition")) return Mustache_doc_itm_.Ary__bool(hasPosition);
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
private static final byte[] Bry__anch_atr_id = Bry_.new_a7(" id=\"xoimg_");
|
||||
public static final byte[]
|
||||
Atr_key__srcset = Bry_.new_a7("srcset")
|
||||
, Atr_key__data_pos_x = Bry_.new_a7("data-pos-x")
|
||||
, 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_nde jnde = Json_nde.NewByVal();
|
||||
jnde.AddKvStr("title", banner_hdr_text);
|
||||
jnde.AddKvStr("tooltip", banner_anch_title);
|
||||
jnde.AddKvStr("bannerfile", banner_anch_href);
|
||||
jnde.AddKvStr("banner", banner_img_src);
|
||||
jnde.AddKvStr("srcset", srcset == null ? Bry_.Empty : Bry_.Empty);
|
||||
jnde.AddKvStr("originx", originx);
|
||||
jnde.AddKvStr("toc", toc);
|
||||
jnde.AddKvStr("img_id_atr", img_id_atr);
|
||||
jnde.AddKvStr("img_xottl", img_xottl_atr);
|
||||
jnde.AddKvStr("img_xoimg", img_xoimg_atr);
|
||||
jnde.AddKvStr("file_ttl", file_ttl);
|
||||
jnde.AddKvDouble("data-pos-x", data_pos_x);
|
||||
jnde.AddKvDouble("data-pos-y", data_pos_y);
|
||||
jnde.AddKvInt("maxWidth", max_width);
|
||||
jnde.AddKvBool("hasIcons", icons.length > 0);
|
||||
jnde.AddKvBool("bottomtoc", bottomtoc);
|
||||
jnde.AddKvBool("isHeadingOverrideEnabled", isHeadingOverrideEnabled);
|
||||
jnde.AddKvBool("isPanorama", isPanorama);
|
||||
jnde.AddKvBool("enable-toc", enable_toc);
|
||||
jnde.AddKvBool("hasPosition", hasPosition);
|
||||
Json_ary ary = null;
|
||||
if (json_icon_list != null) {
|
||||
ary = Json_ary.NewByVal();
|
||||
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);
|
||||
}
|
||||
if (iconlen > 0) {
|
||||
jnde.AddKvAry("icons", ary);
|
||||
}
|
||||
}
|
||||
int iconLen = icons.length;
|
||||
if (iconLen > 0) {
|
||||
ary = Json_ary.NewByVal();
|
||||
Bry_bfr tmpBfr = Bry_bfr_.New();
|
||||
for (int i = 0; i < iconLen; i++) {
|
||||
Pgbnr_icon icon = icons[i];
|
||||
Json_nde iconNde = Pgbnr_iconx(tmpBfr, icon.Name(), icon.Title(), icon.Href());
|
||||
ary.Add(iconNde);
|
||||
}
|
||||
jnde.AddKvAry("icons", ary);
|
||||
}
|
||||
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 = Json_nde.NewByVal();
|
||||
jnde.AddKvStr("name", name);
|
||||
jnde.AddKvStr("title", title);
|
||||
jnde.AddKvStr("url", href);
|
||||
jnde.AddKvStr("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"
|
||||
);
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package gplx.xowa.xtns.pagebanners;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Int_ary_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.core.brys.Bfr_arg;
|
||||
import gplx.langs.mustaches.Mustache_tkn_itm;
|
||||
import gplx.langs.mustaches.Mustache_tkn_parser;
|
||||
@ -86,9 +85,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;
|
||||
|
@ -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,225 +13,248 @@ 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.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||
import gplx.langs.jsons.*;
|
||||
public class Scrib_lib_text__json_util {
|
||||
private final Json_wtr wtr = new Json_wtr();
|
||||
public void Reindex_arrays(Scrib_lib_text__reindex_data rv, Keyval[] kv_ary, boolean is_encoding) {
|
||||
int next = 0;
|
||||
if (is_encoding) {
|
||||
Array_.Sort(kv_ary, KeyVal__sorter__key_is_numeric.Instance);
|
||||
next = 1;
|
||||
}
|
||||
boolean is_sequence = true;
|
||||
int len = kv_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval kv = kv_ary[i];
|
||||
Object kv_val = kv.Val();
|
||||
if (kv_val != null && Type_.Eq(kv_val.getClass(), Keyval[].class)) {
|
||||
Reindex_arrays(rv, (Keyval[])kv_val, is_encoding);
|
||||
if (!rv.Rv_is_kvy())
|
||||
kv.Val_(rv.Rv_as_ary());
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (kv.Key_tid() == Type_ids_.Id__int) {
|
||||
int kv_key_as_int = Int_.Cast(kv.Key_as_obj());
|
||||
is_sequence = next++ == kv_key_as_int;
|
||||
}
|
||||
else {
|
||||
int kv_key_to_int = Bry_.To_int_or__strict(Bry_.new_a7(kv.Key()), -1); // NOTE: a7 b/c proc is only checking for digits; none a7 bytes will be replaced by ?
|
||||
if (is_encoding && kv_key_to_int != -1) {
|
||||
is_sequence = next == kv_key_to_int;
|
||||
++next;
|
||||
}
|
||||
else
|
||||
is_sequence = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (is_encoding) {
|
||||
Object rv_as_ary = To_array_values(kv_ary);
|
||||
rv.Init(Bool_.N, null, rv_as_ary);
|
||||
return;
|
||||
} else {
|
||||
Convert_to_base1(kv_ary); // PHP: return $arr ? array_combine( range( 1, count( $arr ) ), $arr ) : $arr;
|
||||
}
|
||||
}
|
||||
rv.Init(Bool_.Y, kv_ary, null);
|
||||
}
|
||||
private static Object[] To_array_values(Keyval[] ary) {
|
||||
int len = ary.length;
|
||||
Object[] rv = new Object[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval itm = ary[i];
|
||||
rv[i] = itm.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void Convert_to_base1(Keyval[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval itm = ary[i];
|
||||
itm.Key_(i + 1);
|
||||
}
|
||||
}
|
||||
public Keyval[] Decode_rslt_as_nde() {return decode_rslt_as_nde;} private Keyval[] decode_rslt_as_nde;
|
||||
public Keyval[] Decode_rslt_as_ary() {return decode_rslt_as_ary;} private Keyval[] decode_rslt_as_ary;
|
||||
public byte Decode(Json_parser parser, byte[] src, int flag) {
|
||||
synchronized (wtr) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
if (jdoc.Root_grp().Tid() == Json_itm_.Tid__ary) {
|
||||
this.decode_rslt_as_ary = Decode_ary_top(jdoc.Root_ary());
|
||||
return Bool_.N_byte;
|
||||
}
|
||||
else {
|
||||
Json_nde root = (Json_nde)jdoc.Root_grp();
|
||||
int len = root.Len();
|
||||
this.decode_rslt_as_nde = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv json_kv = root.Get_at_as_kv(i);
|
||||
String kv_str = json_kv.Key_as_str();
|
||||
Object kv_val = Decode_obj(json_kv.Val());
|
||||
int kv_int = Int_.Parse_or(kv_str, Int_.Min_value);
|
||||
decode_rslt_as_nde[i] = kv_int == Int_.Min_value ? Keyval_.new_(kv_str, kv_val) : Keyval_.int_(kv_int, kv_val); // use int_key if applicable; PAGE:it.s:Il_Re_Cervo; DATE:2015-12-06
|
||||
}
|
||||
return Bool_.Y_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
private Object Decode_obj(Json_itm itm) {
|
||||
int itm_tid = itm.Tid();
|
||||
switch (itm_tid) {
|
||||
case Json_itm_.Tid__ary: return Decode_ary_sub(Json_ary.cast(itm));
|
||||
case Json_itm_.Tid__nde: return Decode_nde(Json_nde.cast(itm));
|
||||
default: return itm.Data();
|
||||
}
|
||||
}
|
||||
private Keyval[] Decode_ary_top(Json_ary ary) { // NOTE: top-level arrays must be returned as numbered nodes; EX: [{1:a}, {2:b}, {3:c}] not [a, b, c]; DATE:2016-08-01
|
||||
int len = ary.Len();
|
||||
Keyval[] rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Keyval_.int_(i + List_adp_.Base1, Decode_obj(itm));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Object Decode_ary_sub(Json_ary ary) {
|
||||
boolean subs_are_primitive = true;
|
||||
|
||||
// if ary has sub_ary / sub_nde, then unflag subs_are_primitive
|
||||
int len = ary.Len();
|
||||
if (len > 0) {
|
||||
Json_itm sub = ary.Get_at(0);
|
||||
switch (sub.Tid()) {
|
||||
case Json_itm_.Tid__nde:
|
||||
case Json_itm_.Tid__ary:
|
||||
subs_are_primitive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// generate array
|
||||
Object[] rv = null;
|
||||
// if subs_are_primitive, then just generate an Object[]
|
||||
if (subs_are_primitive) {
|
||||
rv = new Object[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Decode_obj(itm);
|
||||
}
|
||||
}
|
||||
// else generate a Keyval where val is ary / nde
|
||||
else {
|
||||
rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Keyval_.int_(i, Decode_obj(itm));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Keyval[] Decode_nde(Json_nde nde) {
|
||||
int len = nde.Len();
|
||||
Keyval[] rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv itm = nde.Get_at_as_kv(i);
|
||||
String kv_str = itm.Key_as_str();
|
||||
int kv_int = Int_.Parse_or(kv_str, Int_.Min_value);
|
||||
Object kv_val = Decode_obj(itm.Val());
|
||||
rv[i] = kv_int == Int_.Min_value ? Keyval_.new_(kv_str, kv_val) : Keyval_.int_(kv_int, kv_val); // use int_key if applicable; PAGE:it.s:Il_Re_Cervo; DATE:2015-12-06
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public byte[] Encode_as_nde(Keyval[] itm, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_nde_bgn();
|
||||
Encode_kv_ary(itm);
|
||||
return wtr.Doc_nde_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Encode_as_ary(Object ary, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_ary_bgn();
|
||||
Encode_ary(ary);
|
||||
return wtr.Doc_ary_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
private void Encode_kv_ary(Keyval[] kv_ary) {
|
||||
int len = kv_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval kv = kv_ary[i];
|
||||
Encode_kv(kv);
|
||||
}
|
||||
}
|
||||
private void Encode_kv(Keyval kv) {
|
||||
Object kv_val = kv.Val();
|
||||
Class<?> type = Type_.Type_by_obj(kv_val);
|
||||
if (Type_.Eq(type, Keyval[].class)) {
|
||||
wtr.Nde_bgn(kv.Key());
|
||||
Encode_kv_ary((Keyval[])kv_val);
|
||||
wtr.Nde_end();
|
||||
}
|
||||
else if (Type_.Is_array(type)) { // encode as array
|
||||
wtr.Ary_bgn(kv.Key());
|
||||
Encode_ary(kv_val);
|
||||
wtr.Ary_end();
|
||||
}
|
||||
else if (Type_.Eq(type, Int_.Cls_ref_type)) wtr.Kv_int(kv.Key(), Int_.Cast(kv_val));
|
||||
else if (Type_.Eq(type, Long_.Cls_ref_type)) wtr.Kv_long(kv.Key(), Long_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Float_.Cls_ref_type)) wtr.Kv_float(kv.Key(), Float_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Double_.Cls_ref_type)) wtr.Kv_double(kv.Key(), Double_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Bool_.Cls_ref_type)) wtr.Kv_bool(kv.Key(), Bool_.Cast(kv_val));
|
||||
else wtr.Kv_str(kv.Key(), Object_.Xto_str_strict_or_null(kv_val));
|
||||
}
|
||||
private void Encode_ary(Object ary) {
|
||||
int ary_len = Array_.Len(ary);
|
||||
for (int j = 0; j < ary_len; ++j)
|
||||
wtr.Ary_itm_obj(Array_.Get_at(ary, j));
|
||||
}
|
||||
public static final int
|
||||
Flag__none = 0
|
||||
, Flag__preserve_keys = 1
|
||||
, Flag__try_fixing = 2
|
||||
, Flag__pretty = 4
|
||||
;
|
||||
public static final int
|
||||
Skip__utf8 = 1
|
||||
, Skip__xml = 2
|
||||
, Skip__all = 3
|
||||
;
|
||||
public static final int
|
||||
Opt__force_assoc = 1
|
||||
;
|
||||
}
|
||||
class KeyVal__sorter__key_is_numeric implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Keyval lhs_itm = (Keyval)lhsObj;
|
||||
Keyval rhs_itm = (Keyval)rhsObj;
|
||||
int lhs_int = Int_.Parse_or(lhs_itm.Key(), Int_.Min_value);
|
||||
int rhs_int = Int_.Parse_or(rhs_itm.Key(), Int_.Min_value);
|
||||
return CompareAble_.Compare(lhs_int, rhs_int);
|
||||
}
|
||||
public static final KeyVal__sorter__key_is_numeric Instance = new KeyVal__sorter__key_is_numeric(); KeyVal__sorter__key_is_numeric() {}
|
||||
}
|
||||
package gplx.xowa.xtns.scribunto.libs;
|
||||
|
||||
import gplx.Array_;
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.CompareAble_;
|
||||
import gplx.Double_;
|
||||
import gplx.Float_;
|
||||
import gplx.Int_;
|
||||
import gplx.Keyval;
|
||||
import gplx.Keyval_;
|
||||
import gplx.List_adp_;
|
||||
import gplx.Long_;
|
||||
import gplx.Object_;
|
||||
import gplx.Type_;
|
||||
import gplx.Type_ids_;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_itm_;
|
||||
import gplx.langs.jsons.Json_kv;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.langs.jsons.Json_parser;
|
||||
import gplx.langs.jsons.Json_wtr;
|
||||
|
||||
public class Scrib_lib_text__json_util {
|
||||
private final Json_wtr wtr = new Json_wtr();
|
||||
public void Reindex_arrays(Scrib_lib_text__reindex_data rv, Keyval[] kv_ary, boolean is_encoding) {
|
||||
int next = 0;
|
||||
if (is_encoding) {
|
||||
Array_.Sort(kv_ary, KeyVal__sorter__key_is_numeric.Instance);
|
||||
next = 1;
|
||||
}
|
||||
boolean is_sequence = true;
|
||||
int len = kv_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval kv = kv_ary[i];
|
||||
Object kv_val = kv.Val();
|
||||
if (kv_val != null && Type_.Eq(kv_val.getClass(), Keyval[].class)) {
|
||||
Reindex_arrays(rv, (Keyval[])kv_val, is_encoding);
|
||||
if (!rv.Rv_is_kvy())
|
||||
kv.Val_(rv.Rv_as_ary());
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (kv.Key_tid() == Type_ids_.Id__int) {
|
||||
int kv_key_as_int = Int_.Cast(kv.Key_as_obj());
|
||||
is_sequence = next++ == kv_key_as_int;
|
||||
}
|
||||
else {
|
||||
int kv_key_to_int = Bry_.To_int_or__strict(Bry_.new_a7(kv.Key()), -1); // NOTE: a7 b/c proc is only checking for digits; none a7 bytes will be replaced by ?
|
||||
if (is_encoding && kv_key_to_int != -1) {
|
||||
is_sequence = next == kv_key_to_int;
|
||||
++next;
|
||||
}
|
||||
else
|
||||
is_sequence = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (is_encoding) {
|
||||
Object rv_as_ary = To_array_values(kv_ary);
|
||||
rv.Init(Bool_.N, null, rv_as_ary);
|
||||
return;
|
||||
} else {
|
||||
Convert_to_base1(kv_ary); // PHP: return $arr ? array_combine( range( 1, count( $arr ) ), $arr ) : $arr;
|
||||
}
|
||||
}
|
||||
rv.Init(Bool_.Y, kv_ary, null);
|
||||
}
|
||||
private static Object[] To_array_values(Keyval[] ary) {
|
||||
int len = ary.length;
|
||||
Object[] rv = new Object[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval itm = ary[i];
|
||||
rv[i] = itm.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void Convert_to_base1(Keyval[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval itm = ary[i];
|
||||
itm.Key_(i + 1);
|
||||
}
|
||||
}
|
||||
public Keyval[] Decode_rslt_as_nde() {return decode_rslt_as_nde;} private Keyval[] decode_rslt_as_nde;
|
||||
public Keyval[] Decode_rslt_as_ary() {return decode_rslt_as_ary;} private Keyval[] decode_rslt_as_ary;
|
||||
public byte Decode(Json_parser parser, byte[] src, int flag) {
|
||||
synchronized (wtr) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
if (jdoc.Root_grp().Tid() == Json_itm_.Tid__ary) {
|
||||
this.decode_rslt_as_ary = Decode_ary_top(jdoc.Root_ary());
|
||||
return Bool_.N_byte;
|
||||
}
|
||||
else {
|
||||
Json_nde root = (Json_nde)jdoc.Root_grp();
|
||||
int len = root.Len();
|
||||
this.decode_rslt_as_nde = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv json_kv = root.Get_at_as_kv(i);
|
||||
String kv_str = json_kv.Key_as_str();
|
||||
Object kv_val = Decode_obj(json_kv.Val());
|
||||
int kv_int = Int_.Parse_or(kv_str, Int_.Min_value);
|
||||
decode_rslt_as_nde[i] = kv_int == Int_.Min_value ? Keyval_.new_(kv_str, kv_val) : Keyval_.int_(kv_int, kv_val); // use int_key if applicable; PAGE:it.s:Il_Re_Cervo; DATE:2015-12-06
|
||||
}
|
||||
return Bool_.Y_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
private Object Decode_obj(Json_itm itm) {
|
||||
int itm_tid = itm.Tid();
|
||||
switch (itm_tid) {
|
||||
case Json_itm_.Tid__ary: return Decode_ary_sub(Json_ary.cast(itm));
|
||||
case Json_itm_.Tid__nde: return Decode_nde(Json_nde.Cast(itm));
|
||||
default: return itm.Data();
|
||||
}
|
||||
}
|
||||
private Keyval[] Decode_ary_top(Json_ary ary) { // NOTE: top-level arrays must be returned as numbered nodes; EX: [{1:a}, {2:b}, {3:c}] not [a, b, c]; DATE:2016-08-01
|
||||
int len = ary.Len();
|
||||
Keyval[] rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Keyval_.int_(i + List_adp_.Base1, Decode_obj(itm));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Object Decode_ary_sub(Json_ary ary) {
|
||||
boolean subs_are_primitive = true;
|
||||
|
||||
// if ary has sub_ary / sub_nde, then unflag subs_are_primitive
|
||||
int len = ary.Len();
|
||||
if (len > 0) {
|
||||
Json_itm sub = ary.Get_at(0);
|
||||
switch (sub.Tid()) {
|
||||
case Json_itm_.Tid__nde:
|
||||
case Json_itm_.Tid__ary:
|
||||
subs_are_primitive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// generate array
|
||||
Object[] rv = null;
|
||||
// if subs_are_primitive, then just generate an Object[]
|
||||
if (subs_are_primitive) {
|
||||
rv = new Object[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Decode_obj(itm);
|
||||
}
|
||||
}
|
||||
// else generate a Keyval where val is ary / nde
|
||||
else {
|
||||
rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
rv[i] = Keyval_.int_(i, Decode_obj(itm));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Keyval[] Decode_nde(Json_nde nde) {
|
||||
int len = nde.Len();
|
||||
Keyval[] rv = new Keyval[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv itm = nde.Get_at_as_kv(i);
|
||||
String kv_str = itm.Key_as_str();
|
||||
int kv_int = Int_.Parse_or(kv_str, Int_.Min_value);
|
||||
Object kv_val = Decode_obj(itm.Val());
|
||||
rv[i] = kv_int == Int_.Min_value ? Keyval_.new_(kv_str, kv_val) : Keyval_.int_(kv_int, kv_val); // use int_key if applicable; PAGE:it.s:Il_Re_Cervo; DATE:2015-12-06
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public byte[] Encode_as_nde(Keyval[] itm, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_nde_bgn();
|
||||
Encode_kv_ary(itm);
|
||||
return wtr.Doc_nde_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Encode_as_ary(Object ary, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_ary_bgn();
|
||||
Encode_ary(ary);
|
||||
return wtr.Doc_ary_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
private void Encode_kv_ary(Keyval[] kv_ary) {
|
||||
int len = kv_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Keyval kv = kv_ary[i];
|
||||
Encode_kv(kv);
|
||||
}
|
||||
}
|
||||
private void Encode_kv(Keyval kv) {
|
||||
Object kv_val = kv.Val();
|
||||
Class<?> type = Type_.Type_by_obj(kv_val);
|
||||
if (Type_.Eq(type, Keyval[].class)) {
|
||||
wtr.Nde_bgn(kv.Key());
|
||||
Encode_kv_ary((Keyval[])kv_val);
|
||||
wtr.Nde_end();
|
||||
}
|
||||
else if (Type_.Is_array(type)) { // encode as array
|
||||
wtr.Ary_bgn(kv.Key());
|
||||
Encode_ary(kv_val);
|
||||
wtr.Ary_end();
|
||||
}
|
||||
else if (Type_.Eq(type, Int_.Cls_ref_type)) wtr.Kv_int(kv.Key(), Int_.Cast(kv_val));
|
||||
else if (Type_.Eq(type, Long_.Cls_ref_type)) wtr.Kv_long(kv.Key(), Long_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Float_.Cls_ref_type)) wtr.Kv_float(kv.Key(), Float_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Double_.Cls_ref_type)) wtr.Kv_double(kv.Key(), Double_.cast(kv_val));
|
||||
else if (Type_.Eq(type, Bool_.Cls_ref_type)) wtr.Kv_bool(kv.Key(), Bool_.Cast(kv_val));
|
||||
else wtr.Kv_str(kv.Key(), Object_.Xto_str_strict_or_null(kv_val));
|
||||
}
|
||||
private void Encode_ary(Object ary) {
|
||||
int ary_len = Array_.Len(ary);
|
||||
for (int j = 0; j < ary_len; ++j)
|
||||
wtr.Ary_itm_obj(Array_.Get_at(ary, j));
|
||||
}
|
||||
public static final int
|
||||
Flag__none = 0
|
||||
, Flag__preserve_keys = 1
|
||||
, Flag__try_fixing = 2
|
||||
, Flag__pretty = 4
|
||||
;
|
||||
public static final int
|
||||
Skip__utf8 = 1
|
||||
, Skip__xml = 2
|
||||
, Skip__all = 3
|
||||
;
|
||||
public static final int
|
||||
Opt__force_assoc = 1
|
||||
;
|
||||
}
|
||||
class KeyVal__sorter__key_is_numeric implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Keyval lhs_itm = (Keyval)lhsObj;
|
||||
Keyval rhs_itm = (Keyval)rhsObj;
|
||||
int lhs_int = Int_.Parse_or(lhs_itm.Key(), Int_.Min_value);
|
||||
int rhs_int = Int_.Parse_or(rhs_itm.Key(), Int_.Min_value);
|
||||
return CompareAble_.Compare((Integer)lhs_int, (Integer)rhs_int);
|
||||
}
|
||||
public static final KeyVal__sorter__key_is_numeric Instance = new KeyVal__sorter__key_is_numeric(); KeyVal__sorter__key_is_numeric() {}
|
||||
}
|
||||
|
@ -63,11 +63,11 @@ import gplx.xowa.xtns.wbases.stores.Wbase_prop_mgr_loader_;
|
||||
import gplx.xowa.xtns.wbases.stores.Wbase_qid_mgr;
|
||||
|
||||
public class Wdata_wiki_mgr implements Gfo_evt_itm, Gfo_invk {
|
||||
private final Xoae_app app;
|
||||
private final Wdata_prop_val_visitor prop_val_visitor;
|
||||
private final Wdata_doc_parser wdoc_parser_v1 = new Wdata_doc_parser_v1(), wdoc_parser_v2 = new Wdata_doc_parser_v2();
|
||||
private final Object thread_lock = new Object();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(32);
|
||||
private final Xoae_app app;
|
||||
private final Wdata_prop_val_visitor prop_val_visitor;
|
||||
private final Wdata_doc_parser wdoc_parser_v1 = new Wdata_doc_parser_v1(), wdoc_parser_v2 = new Wdata_doc_parser_v2();
|
||||
private final Object thread_lock = new Object();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(32);
|
||||
public Wdata_wiki_mgr(Xoae_app app) {
|
||||
this.app = app;
|
||||
this.evt_mgr = new Gfo_evt_mgr(this);
|
||||
@ -78,11 +78,11 @@ public class Wdata_wiki_mgr implements Gfo_evt_itm, Gfo_invk {
|
||||
this.prop_val_visitor = new Wdata_prop_val_visitor(app, this);
|
||||
this.Enabled_(true);
|
||||
}
|
||||
public Gfo_evt_mgr Evt_mgr() {return evt_mgr;} private final Gfo_evt_mgr evt_mgr;
|
||||
public final Wbase_qid_mgr Qid_mgr;
|
||||
public final Wbase_pid_mgr Pid_mgr;
|
||||
public final Wbase_doc_mgr Doc_mgr;
|
||||
public Wbase_prop_mgr Prop_mgr() {return prop_mgr;} private final Wbase_prop_mgr prop_mgr;
|
||||
public Gfo_evt_mgr Evt_mgr() {return evt_mgr;} private final Gfo_evt_mgr evt_mgr;
|
||||
public final Wbase_qid_mgr Qid_mgr;
|
||||
public final Wbase_pid_mgr Pid_mgr;
|
||||
public final Wbase_doc_mgr Doc_mgr;
|
||||
public Wbase_prop_mgr Prop_mgr() {return prop_mgr;} private final Wbase_prop_mgr prop_mgr;
|
||||
public boolean Enabled() {return enabled;} private boolean enabled;
|
||||
public void Enabled_(boolean v) {
|
||||
this.enabled = v;
|
||||
@ -109,7 +109,7 @@ public class Wdata_wiki_mgr implements Gfo_evt_itm, Gfo_invk {
|
||||
public Json_parser Jdoc_parser() {return jdoc_parser;} private Json_parser jdoc_parser = new Json_parser();
|
||||
public void Init_by_app() {}
|
||||
public Wdata_doc_parser Wdoc_parser(Json_doc jdoc) {
|
||||
Json_kv itm_0 = Json_kv.cast(jdoc.Root_nde().Get_at(0)); // get 1st node
|
||||
Json_kv itm_0 = Json_kv.Cast(jdoc.Root_nde().Get_at(0)); // get 1st node
|
||||
return Bry_.Eq(itm_0.Key().Data_bry(), Wdata_doc_parser_v2.Bry_type)
|
||||
|| Bry_.Eq(itm_0.Key().Data_bry(), Wdata_doc_parser_v2.Bry_id)
|
||||
? wdoc_parser_v2 : wdoc_parser_v1; // if "type", must be v2
|
||||
@ -224,7 +224,7 @@ public class Wdata_wiki_mgr implements Gfo_evt_itm, Gfo_invk {
|
||||
public static final String Ns_lexeme_name = "Lexeme";
|
||||
public static final byte[] Ns_lexeme_name_bry = Bry_.new_a7(Ns_lexeme_name);
|
||||
|
||||
public static final byte[] Html_json_id = Bry_.new_a7("xowa-wikidata-json");
|
||||
public static final byte[] Html_json_id = Bry_.new_a7("xowa-wikidata-json");
|
||||
public static boolean Wiki_page_is_json(int wiki_tid, int ns_id) {
|
||||
switch (wiki_tid) {
|
||||
case Xow_domain_tid_.Tid__wikidata:
|
||||
|
@ -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,193 +13,234 @@ 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.xtns.wbases; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.core.primitives.*; import gplx.langs.jsons.*;
|
||||
import gplx.xowa.wikis.nss.*; import gplx.xowa.wikis.domains.*;
|
||||
import gplx.xowa.xtns.wbases.core.*; import gplx.xowa.xtns.wbases.pfuncs.*; import gplx.xowa.xtns.wbases.claims.*; import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*; import gplx.xowa.xtns.wbases.stores.*;
|
||||
public class Wdata_wiki_mgr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Wdata_doc_bldr wdoc_bldr;
|
||||
private final Wdata_xwiki_link_wtr wdata_lang_wtr = new Wdata_xwiki_link_wtr();
|
||||
private final Bry_bfr tmp_time_bfr = Bry_bfr_.New();
|
||||
public Xowe_wiki Wiki() {return parser_fxt.Wiki();}
|
||||
public Wdata_wiki_mgr_fxt Init() {return Init(new Xop_fxt(), true);}
|
||||
public Wdata_wiki_mgr_fxt Init(Xop_fxt parser_fxt, boolean reset) {
|
||||
this.parser_fxt = parser_fxt;
|
||||
this.wiki = parser_fxt.Wiki();
|
||||
app = wiki.Appe();
|
||||
app.Xwiki_mgr__sitelink_mgr().Init_by_app();
|
||||
wdoc_bldr = new Wdata_doc_bldr();
|
||||
wdata_mgr = app.Wiki_mgr().Wdata_mgr();
|
||||
wdata_mgr.Prop_mgr().Loader_(Wbase_prop_mgr_loader_.New_mock());
|
||||
wdata_mgr.Clear();
|
||||
if (reset) {
|
||||
Io_mgr.Instance.InitEngine_mem();
|
||||
parser_fxt.Reset();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Xoae_app App() {return app;}
|
||||
public Wdata_wiki_mgr Wdata_mgr() {return wdata_mgr;} private Wdata_wiki_mgr wdata_mgr;
|
||||
public Xop_fxt Parser_fxt() {return parser_fxt;} private Xop_fxt parser_fxt;
|
||||
public Wdata_doc_bldr Wdoc_bldr(String qid) {return wdoc_bldr.Qid_(qid);}
|
||||
public Json_doc Make_json(String src) {return app.Utl__json_parser().Parse_by_apos(src);}
|
||||
|
||||
public Wbase_claim_base Make_claim_novalue(int pid) {return Wbase_claim_value.New_novalue(pid);}
|
||||
public Wbase_claim_base Make_claim_somevalue(int pid) {return Wbase_claim_value.New_somevalue(pid);}
|
||||
public Wbase_claim_base Make_claim_string(int pid, String val) {return Make_claim_string(pid, Bry_.new_u8(val));}
|
||||
public Wbase_claim_base Make_claim_string(int pid, byte[] val) {return new Wbase_claim_string(pid, Wbase_claim_value_type_.Tid__value, val);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val) {return Make_claim_time(pid, val, Bry_.Empty, Bry_.Empty);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val, int precision) {return Make_claim_time(pid, val, Int_.To_bry(precision), Bry_.Empty);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val, byte[] precision, byte[] calendar) {
|
||||
return new Wbase_claim_time(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_time_.To_bry(tmp_time_bfr, val), Bry_.Empty, Bry_.Empty, Bry_.Empty, precision, calendar);
|
||||
}
|
||||
public Wbase_claim_base Make_claim_monolingual(int pid, String lang, String text) {return new Wbase_claim_monolingualtext(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_u8(lang), Bry_.new_u8(text));}
|
||||
public Wbase_claim_base Make_claim_quantity(int pid, String amount, String unit, String ubound, String lbound) {return new Wbase_claim_quantity(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_a7(amount), Bry_.new_a7(unit), Bry_.new_a7(ubound), Bry_.new_a7(lbound));}
|
||||
public Wbase_claim_base Make_claim_entity_qid(int pid, int val) {return new Wbase_claim_entity(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_entity_type_.Tid__item, Int_.To_bry(val));}
|
||||
public Wbase_claim_base Make_claim_entity_pid(int pid, int val) {return new Wbase_claim_entity(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_entity_type_.Tid__property, Int_.To_bry(val));}
|
||||
public Wbase_claim_base Make_claim_geo(int pid, String lon, String lat) {return Make_claim_geo(pid, lon, lat, ".00001", null, "http://www.wikidata.org/entity/Q2");}
|
||||
public Wbase_claim_base Make_claim_geo(int pid, String lon, String lat, String prc, String alt, String glb) {
|
||||
return new Wbase_claim_globecoordinate(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_a7(lat), Bry_.new_a7(lon), Bry_.new_a7(alt), Bry_.new_a7(prc), Bry_.new_a7(glb));
|
||||
}
|
||||
public Wbase_claim_grp Make_qualifiers_grp(int pid, Wbase_claim_base... ary) {return new Wbase_claim_grp(Int_obj_ref.New(pid), ary);}
|
||||
public Wbase_claim_grp_list Make_qualifiers(Wbase_claim_grp... ary) {
|
||||
Wbase_claim_grp_list rv = new Wbase_claim_grp_list();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
rv.Add(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
public Wbase_references_grp[] Make_references(Wbase_references_grp... ary) {
|
||||
return ary;
|
||||
}
|
||||
public Wbase_references_grp Make_reference_grp(String hash, int[] snaks_order, Wbase_claim_grp... snaks) {
|
||||
Wbase_claim_grp_list list = new Wbase_claim_grp_list();
|
||||
for (Wbase_claim_grp itm : snaks)
|
||||
list.Add(itm);
|
||||
return new Wbase_references_grp(Bry_.new_u8(hash), list, snaks_order);
|
||||
}
|
||||
public Wbase_claim_grp Make_reference_itm(int id, Wbase_claim_base... itms) {
|
||||
return new Wbase_claim_grp(Int_obj_ref.New(id), itms);
|
||||
}
|
||||
|
||||
public Wdata_doc_bldr Wdoc(String qid) {return wdoc_bldr.Qid_(qid);}
|
||||
public Wdata_doc doc_(String qid, Wbase_claim_base... props) {return wdoc_bldr.Qid_(qid).Add_claims(props).Xto_wdoc();}
|
||||
|
||||
public void Init_pids_add(String lang_key, String pid_name, int pid) {wdata_mgr.Pid_mgr.Add(Bry_.new_u8(lang_key + "|" + pid_name), pid);}
|
||||
public void Init_qids_add(String lang_key, int wiki_tid, String ttl, String qid) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
wdata_mgr.Qid_mgr.Add(tmp_bfr, Bry_.new_a7(lang_key), wiki_tid, Bry_.new_a7("000"), Bry_.new_a7(ttl), Bry_.new_a7(qid));
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
public void Init_lang_fallbacks(String... fallbacks) {wiki.Lang().Fallback_bry_(Bry_.new_a7(String_.Concat_with_str(",", fallbacks)));}
|
||||
public void Init_xwikis_add(String... prefixes) {
|
||||
int len = prefixes.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String prefix = prefixes[i];
|
||||
wiki.Xwiki_mgr().Add_by_atrs(prefix, prefix + ".wikipedia.org");
|
||||
}
|
||||
}
|
||||
public void Init_external_links_mgr_clear() {wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links().Reset();}
|
||||
public void Init_external_links_mgr_add(String... langs) {
|
||||
Wdata_external_lang_links_data external_lang_links = wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links();
|
||||
external_lang_links.Enabled_(true);
|
||||
int len = langs.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String lang = langs[i];
|
||||
if (String_.Eq(lang, "*"))
|
||||
external_lang_links.Sort_(true);
|
||||
else
|
||||
external_lang_links.Langs_add(Bry_.new_a7(lang));
|
||||
}
|
||||
}
|
||||
|
||||
public void Init__docs__add(Wdata_doc_bldr bldr) {Init__docs__add(bldr.Xto_wdoc());}
|
||||
public void Init__docs__add(Wdata_doc wdoc) {
|
||||
wdata_mgr.Doc_mgr.Add(wdoc.Qid(), wdoc);
|
||||
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
Wbase_qid_mgr qid_mgr = wdata_mgr.Qid_mgr;
|
||||
Ordered_hash slinks = wdoc.Slink_list();
|
||||
int slinks_len = slinks.Len();
|
||||
for (int i = 0; i < slinks_len; i++) {
|
||||
Wdata_sitelink_itm slink = (Wdata_sitelink_itm)slinks.Get_at(i);
|
||||
Xow_domain_itm domain = Xow_abrv_wm_.Parse_to_domain_itm(slink.Site());
|
||||
Xoa_ttl page_ttl = wiki.Ttl_parse(slink.Name());
|
||||
qid_mgr.Add(tmp_bfr, domain.Lang_actl_key(), domain.Domain_type_id(), page_ttl.Ns().Num_bry(), page_ttl.Page_db(), wdoc.Qid());
|
||||
}
|
||||
}
|
||||
|
||||
public void Test_link(String ttl_str, String expd) {Test_link(Xoa_ttl.Parse(wiki, Xow_ns_.Tid__main, Bry_.new_u8(ttl_str)), expd);}
|
||||
public void Test_link(Xoa_ttl ttl, String expd) {
|
||||
byte[] qid_ttl = wdata_mgr.Qid_mgr.Get_qid_or_null(wiki, ttl);
|
||||
Tfds.Eq(expd, String_.new_u8(qid_ttl));
|
||||
}
|
||||
public void Test_parse_pid_null(String val) {Test_parse_pid(val, Wbase_pid.Id_null);}
|
||||
public void Test_parse_pid(String val, int expd) {Tfds.Eq(expd, Wbase_statement_mgr_.Parse_pid(num_parser, Bry_.new_a7(val)));} private Gfo_number_parser num_parser = new Gfo_number_parser();
|
||||
public void Test_parse(String raw, String expd) {
|
||||
parser_fxt.Test_parse_page_tmpl_str(raw, expd);
|
||||
}
|
||||
public void Test_parse_langs(String raw, String expd) {
|
||||
// setup langs
|
||||
Xoae_page page = wiki.Parser_mgr().Ctx().Page();
|
||||
app.Xwiki_mgr__sitelink_mgr().Parse(Bry_.new_u8(String_.Concat_lines_nl
|
||||
( "0|grp1"
|
||||
, "1|en|English"
|
||||
, "1|fr|French"
|
||||
, "1|de|German"
|
||||
, "1|pl|Polish"
|
||||
)));
|
||||
wiki.Xwiki_mgr().Add_by_sitelink_mgr();
|
||||
wiki.Appe().Usere().Wiki().Xwiki_mgr().Add_by_csv(Bry_.new_a7(String_.Concat_lines_nl
|
||||
( "1|en.wikipedia.org|en.wikipedia.org"
|
||||
, "1|fr.wikipedia.org|fr.wikipedia.org"
|
||||
, "1|de.wikipedia.org|de.wikipedia.org"
|
||||
, "1|pl.wikipedia.org|pl.wikipedia.org"
|
||||
)));
|
||||
|
||||
parser_fxt.Page_ttl_("Q1_en");
|
||||
parser_fxt.Exec_parse_page_all_as_str(raw);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
|
||||
wdata_lang_wtr.Page_(page).Bfr_arg__add(tmp_bfr);
|
||||
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_rls());
|
||||
}
|
||||
public void Test_xwiki_links(String ttl, String... expd) {
|
||||
tmp_langs.Clear();
|
||||
Wdata_xwiki_link_wtr.Write_wdata_links(tmp_langs, wiki, Xoa_ttl.Parse(wiki, Bry_.new_u8(ttl)), wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links());
|
||||
Tfds.Eq_ary_str(expd, Test_xwiki_links_xto_str_ary(tmp_langs));
|
||||
} private List_adp tmp_langs = List_adp_.New();
|
||||
String[] Test_xwiki_links_xto_str_ary(List_adp list) {
|
||||
int len = list.Count();
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Wdata_sitelink_itm itm = (Wdata_sitelink_itm)list.Get_at(i);
|
||||
rv[i] = String_.new_a7(itm.Page_ttl().Page_db());
|
||||
}
|
||||
tmp_langs.Clear();
|
||||
return rv;
|
||||
}
|
||||
public void Test_write_json_as_html(String raw_str, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw_str);
|
||||
raw_bry = gplx.langs.jsons.Json_parser_tst.Replace_apos(raw_bry);
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
Wdata_wiki_mgr.Write_json_as_html(wdata_mgr.Jdoc_parser(), bfr, raw_bry);
|
||||
Tfds.Eq(expd, bfr.To_str_and_rls());
|
||||
}
|
||||
public static String New_json(String entity_id, String grp_key, String[] grp_vals) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
bfr.Add_str_a7("{ 'entity':'").Add_str_u8(entity_id).Add_byte(Byte_ascii.Apos).Add_byte_nl();
|
||||
bfr.Add_str_a7(", 'datatype':'commonsMedia'\n");
|
||||
bfr.Add_str_a7(", '").Add_str_u8(grp_key).Add_str_a7("':").Add_byte_nl();
|
||||
int len = grp_vals.length;
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, 2);
|
||||
bfr.Add_byte(i == 0 ? Byte_ascii.Curly_bgn : Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Apos).Add_str_u8(grp_vals[i ]).Add_byte(Byte_ascii.Apos).Add_byte(Byte_ascii.Colon);
|
||||
bfr.Add_byte(Byte_ascii.Apos).Add_str_u8(grp_vals[i + 1]).Add_byte(Byte_ascii.Apos).Add_byte_nl();
|
||||
}
|
||||
bfr.Add_str_a7(" }").Add_byte_nl();
|
||||
bfr.Add_str_a7("}").Add_byte_nl();
|
||||
return String_.Replace(bfr.To_str_and_clear(), "'", "\"");
|
||||
}
|
||||
}
|
||||
package gplx.xowa.xtns.wbases;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.Byte_ascii;
|
||||
import gplx.Int_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.Ordered_hash;
|
||||
import gplx.String_;
|
||||
import gplx.Tfds;
|
||||
import gplx.core.primitives.Gfo_number_parser;
|
||||
import gplx.core.primitives.Int_obj_ref;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.xowa.Xoa_ttl;
|
||||
import gplx.xowa.Xoae_app;
|
||||
import gplx.xowa.Xoae_page;
|
||||
import gplx.xowa.Xop_fxt;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.wikis.domains.Xow_abrv_wm_;
|
||||
import gplx.xowa.wikis.domains.Xow_domain_itm;
|
||||
import gplx.xowa.wikis.nss.Xow_ns_;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp_list;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_references_grp;
|
||||
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_entity_type_;
|
||||
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_value_type_;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_base;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_entity;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_globecoordinate;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_monolingualtext;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_quantity;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_string;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_time;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_time_;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_value;
|
||||
import gplx.xowa.xtns.wbases.core.Wbase_pid;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_sitelink_itm;
|
||||
import gplx.xowa.xtns.wbases.pfuncs.Wbase_statement_mgr_;
|
||||
import gplx.xowa.xtns.wbases.pfuncs.Wdata_external_lang_links_data;
|
||||
import gplx.xowa.xtns.wbases.stores.Wbase_prop_mgr_loader_;
|
||||
import gplx.xowa.xtns.wbases.stores.Wbase_qid_mgr;
|
||||
|
||||
public class Wdata_wiki_mgr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Wdata_doc_bldr wdoc_bldr;
|
||||
private final Wdata_xwiki_link_wtr wdata_lang_wtr = new Wdata_xwiki_link_wtr();
|
||||
private final Bry_bfr tmp_time_bfr = Bry_bfr_.New();
|
||||
public Xowe_wiki Wiki() {return parser_fxt.Wiki();}
|
||||
public Wdata_wiki_mgr_fxt Init() {return Init(new Xop_fxt(), true);}
|
||||
public Wdata_wiki_mgr_fxt Init(Xop_fxt parser_fxt, boolean reset) {
|
||||
this.parser_fxt = parser_fxt;
|
||||
this.wiki = parser_fxt.Wiki();
|
||||
app = wiki.Appe();
|
||||
app.Xwiki_mgr__sitelink_mgr().Init_by_app();
|
||||
wdoc_bldr = new Wdata_doc_bldr();
|
||||
wdata_mgr = app.Wiki_mgr().Wdata_mgr();
|
||||
wdata_mgr.Prop_mgr().Loader_(Wbase_prop_mgr_loader_.New_mock());
|
||||
wdata_mgr.Clear();
|
||||
if (reset) {
|
||||
Io_mgr.Instance.InitEngine_mem();
|
||||
parser_fxt.Reset();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Xoae_app App() {return app;}
|
||||
public Wdata_wiki_mgr Wdata_mgr() {return wdata_mgr;} private Wdata_wiki_mgr wdata_mgr;
|
||||
public Xop_fxt Parser_fxt() {return parser_fxt;} private Xop_fxt parser_fxt;
|
||||
public Wdata_doc_bldr Wdoc_bldr(String qid) {return wdoc_bldr.Qid_(qid);}
|
||||
public Json_doc Make_json(String src) {return app.Utl__json_parser().Parse_by_apos(src);}
|
||||
|
||||
public Wbase_claim_base Make_claim_novalue(int pid) {return Wbase_claim_value.New_novalue(pid);}
|
||||
public Wbase_claim_base Make_claim_somevalue(int pid) {return Wbase_claim_value.New_somevalue(pid);}
|
||||
public Wbase_claim_base Make_claim_string(int pid, String val) {return Make_claim_string(pid, Bry_.new_u8(val));}
|
||||
public Wbase_claim_base Make_claim_string(int pid, byte[] val) {return new Wbase_claim_string(pid, Wbase_claim_value_type_.Tid__value, val);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val) {return Make_claim_time(pid, val, Bry_.Empty, Bry_.Empty);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val, int precision) {return Make_claim_time(pid, val, Int_.To_bry(precision), Bry_.Empty);}
|
||||
public Wbase_claim_base Make_claim_time(int pid, String val, byte[] precision, byte[] calendar) {
|
||||
return new Wbase_claim_time(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_time_.To_bry(tmp_time_bfr, val), Bry_.Empty, Bry_.Empty, Bry_.Empty, precision, calendar);
|
||||
}
|
||||
public Wbase_claim_base Make_claim_monolingual(int pid, String lang, String text) {return new Wbase_claim_monolingualtext(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_u8(lang), Bry_.new_u8(text));}
|
||||
public Wbase_claim_base Make_claim_quantity(int pid, String amount, String unit, String ubound, String lbound) {return new Wbase_claim_quantity(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_a7(amount), Bry_.new_a7(unit), Bry_.new_a7(ubound), Bry_.new_a7(lbound));}
|
||||
public Wbase_claim_base Make_claim_entity_qid(int pid, int val) {return new Wbase_claim_entity(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_entity_type_.Tid__item, Int_.To_bry(val));}
|
||||
public Wbase_claim_base Make_claim_entity_pid(int pid, int val) {return new Wbase_claim_entity(pid, Wbase_claim_value_type_.Tid__value, Wbase_claim_entity_type_.Tid__property, Int_.To_bry(val));}
|
||||
public Wbase_claim_base Make_claim_geo(int pid, String lon, String lat) {return Make_claim_geo(pid, lon, lat, ".00001", null, "http://www.wikidata.org/entity/Q2");}
|
||||
public Wbase_claim_base Make_claim_geo(int pid, String lon, String lat, String prc, String alt, String glb) {
|
||||
return new Wbase_claim_globecoordinate(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_a7(lat), Bry_.new_a7(lon), Bry_.new_a7(alt), Bry_.new_a7(prc), Bry_.new_a7(glb));
|
||||
}
|
||||
public Wbase_claim_grp Make_qualifiers_grp(int pid, Wbase_claim_base... ary) {return new Wbase_claim_grp(Int_obj_ref.New(pid), ary);}
|
||||
public Wbase_claim_grp_list Make_qualifiers(Wbase_claim_grp... ary) {
|
||||
Wbase_claim_grp_list rv = new Wbase_claim_grp_list();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
rv.Add(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
public Wbase_references_grp[] Make_references(Wbase_references_grp... ary) {
|
||||
return ary;
|
||||
}
|
||||
public Wbase_references_grp Make_reference_grp(String hash, int[] snaks_order, Wbase_claim_grp... snaks) {
|
||||
Wbase_claim_grp_list list = new Wbase_claim_grp_list();
|
||||
for (Wbase_claim_grp itm : snaks)
|
||||
list.Add(itm);
|
||||
return new Wbase_references_grp(Bry_.new_u8(hash), list, snaks_order);
|
||||
}
|
||||
public Wbase_claim_grp Make_reference_itm(int id, Wbase_claim_base... itms) {
|
||||
return new Wbase_claim_grp(Int_obj_ref.New(id), itms);
|
||||
}
|
||||
|
||||
public Wdata_doc_bldr Wdoc(String qid) {return wdoc_bldr.Qid_(qid);}
|
||||
public Wdata_doc doc_(String qid, Wbase_claim_base... props) {return wdoc_bldr.Qid_(qid).Add_claims(props).Xto_wdoc();}
|
||||
|
||||
public void Init_pids_add(String lang_key, String pid_name, int pid) {wdata_mgr.Pid_mgr.Add(Bry_.new_u8(lang_key + "|" + pid_name), pid);}
|
||||
public void Init_qids_add(String lang_key, int wiki_tid, String ttl, String qid) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
wdata_mgr.Qid_mgr.Add(tmp_bfr, Bry_.new_a7(lang_key), wiki_tid, Bry_.new_a7("000"), Bry_.new_a7(ttl), Bry_.new_a7(qid));
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
public void Init_lang_fallbacks(String... fallbacks) {wiki.Lang().Fallback_bry_(Bry_.new_a7(String_.Concat_with_str(",", fallbacks)));}
|
||||
public void Init_xwikis_add(String... prefixes) {
|
||||
int len = prefixes.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String prefix = prefixes[i];
|
||||
wiki.Xwiki_mgr().Add_by_atrs(prefix, prefix + ".wikipedia.org");
|
||||
}
|
||||
}
|
||||
public void Init_external_links_mgr_clear() {wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links().Reset();}
|
||||
public void Init_external_links_mgr_add(String... langs) {
|
||||
Wdata_external_lang_links_data external_lang_links = wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links();
|
||||
external_lang_links.Enabled_(true);
|
||||
int len = langs.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String lang = langs[i];
|
||||
if (String_.Eq(lang, "*"))
|
||||
external_lang_links.Sort_(true);
|
||||
else
|
||||
external_lang_links.Langs_add(Bry_.new_a7(lang));
|
||||
}
|
||||
}
|
||||
|
||||
public void Init__docs__add(Wdata_doc_bldr bldr) {Init__docs__add(bldr.Xto_wdoc());}
|
||||
public void Init__docs__add(Wdata_doc wdoc) {
|
||||
wdata_mgr.Doc_mgr.Add(wdoc.Qid(), wdoc);
|
||||
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
Wbase_qid_mgr qid_mgr = wdata_mgr.Qid_mgr;
|
||||
Ordered_hash slinks = wdoc.Slink_list();
|
||||
int slinks_len = slinks.Len();
|
||||
for (int i = 0; i < slinks_len; i++) {
|
||||
Wdata_sitelink_itm slink = (Wdata_sitelink_itm)slinks.Get_at(i);
|
||||
Xow_domain_itm domain = Xow_abrv_wm_.Parse_to_domain_itm(slink.Site());
|
||||
Xoa_ttl page_ttl = wiki.Ttl_parse(slink.Name());
|
||||
qid_mgr.Add(tmp_bfr, domain.Lang_actl_key(), domain.Domain_type_id(), page_ttl.Ns().Num_bry(), page_ttl.Page_db(), wdoc.Qid());
|
||||
}
|
||||
}
|
||||
|
||||
public void Test_link(String ttl_str, String expd) {Test_link(Xoa_ttl.Parse(wiki, Xow_ns_.Tid__main, Bry_.new_u8(ttl_str)), expd);}
|
||||
public void Test_link(Xoa_ttl ttl, String expd) {
|
||||
byte[] qid_ttl = wdata_mgr.Qid_mgr.Get_qid_or_null(wiki, ttl);
|
||||
Tfds.Eq(expd, String_.new_u8(qid_ttl));
|
||||
}
|
||||
public void Test_parse_pid_null(String val) {Test_parse_pid(val, Wbase_pid.Id_null);}
|
||||
public void Test_parse_pid(String val, int expd) {Tfds.Eq(expd, Wbase_statement_mgr_.Parse_pid(num_parser, Bry_.new_a7(val)));} private Gfo_number_parser num_parser = new Gfo_number_parser();
|
||||
public void Test_parse(String raw, String expd) {
|
||||
parser_fxt.Test_parse_page_tmpl_str(raw, expd);
|
||||
}
|
||||
public void Test_parse_langs(String raw, String expd) {
|
||||
// setup langs
|
||||
Xoae_page page = wiki.Parser_mgr().Ctx().Page();
|
||||
app.Xwiki_mgr__sitelink_mgr().Parse(Bry_.new_u8(String_.Concat_lines_nl
|
||||
( "0|grp1"
|
||||
, "1|en|English"
|
||||
, "1|fr|French"
|
||||
, "1|de|German"
|
||||
, "1|pl|Polish"
|
||||
)));
|
||||
wiki.Xwiki_mgr().Add_by_sitelink_mgr();
|
||||
wiki.Appe().Usere().Wiki().Xwiki_mgr().Add_by_csv(Bry_.new_a7(String_.Concat_lines_nl
|
||||
( "1|en.wikipedia.org|en.wikipedia.org"
|
||||
, "1|fr.wikipedia.org|fr.wikipedia.org"
|
||||
, "1|de.wikipedia.org|de.wikipedia.org"
|
||||
, "1|pl.wikipedia.org|pl.wikipedia.org"
|
||||
)));
|
||||
|
||||
parser_fxt.Page_ttl_("Q1_en");
|
||||
parser_fxt.Exec_parse_page_all_as_str(raw);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
|
||||
wdata_lang_wtr.Page_(page).Bfr_arg__add(tmp_bfr);
|
||||
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_rls());
|
||||
}
|
||||
public void Test_xwiki_links(String ttl, String... expd) {
|
||||
tmp_langs.Clear();
|
||||
Wdata_xwiki_link_wtr.Write_wdata_links(tmp_langs, wiki, Xoa_ttl.Parse(wiki, Bry_.new_u8(ttl)), wiki.Parser_mgr().Ctx().Page().Wdata_external_lang_links());
|
||||
Tfds.Eq_ary_str(expd, Test_xwiki_links_xto_str_ary(tmp_langs));
|
||||
} private List_adp tmp_langs = List_adp_.New();
|
||||
String[] Test_xwiki_links_xto_str_ary(List_adp list) {
|
||||
int len = list.Count();
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Wdata_sitelink_itm itm = (Wdata_sitelink_itm)list.Get_at(i);
|
||||
rv[i] = String_.new_a7(itm.Page_ttl().Page_db());
|
||||
}
|
||||
tmp_langs.Clear();
|
||||
return rv;
|
||||
}
|
||||
public void Test_write_json_as_html(String raw_str, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw_str);
|
||||
raw_bry = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
Wdata_wiki_mgr.Write_json_as_html(wdata_mgr.Jdoc_parser(), bfr, raw_bry);
|
||||
Tfds.Eq(expd, bfr.To_str_and_rls());
|
||||
}
|
||||
public static String New_json(String entity_id, String grp_key, String[] grp_vals) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
bfr.Add_str_a7("{ 'entity':'").Add_str_u8(entity_id).Add_byte(Byte_ascii.Apos).Add_byte_nl();
|
||||
bfr.Add_str_a7(", 'datatype':'commonsMedia'\n");
|
||||
bfr.Add_str_a7(", '").Add_str_u8(grp_key).Add_str_a7("':").Add_byte_nl();
|
||||
int len = grp_vals.length;
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, 2);
|
||||
bfr.Add_byte(i == 0 ? Byte_ascii.Curly_bgn : Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
bfr.Add_byte(Byte_ascii.Apos).Add_str_u8(grp_vals[i ]).Add_byte(Byte_ascii.Apos).Add_byte(Byte_ascii.Colon);
|
||||
bfr.Add_byte(Byte_ascii.Apos).Add_str_u8(grp_vals[i + 1]).Add_byte(Byte_ascii.Apos).Add_byte_nl();
|
||||
}
|
||||
bfr.Add_str_a7(" }").Add_byte_nl();
|
||||
bfr.Add_str_a7("}").Add_byte_nl();
|
||||
return String_.Replace(bfr.To_str_and_clear(), "'", "\"");
|
||||
}
|
||||
}
|
||||
|
@ -39,11 +39,11 @@ public class Wbase_claim_factory {
|
||||
public Wbase_claim_base Parse(byte[] qid, int pid, byte snak_tid, Json_nde nde, byte value_tid, Json_itm value_itm) {
|
||||
switch (value_tid) {
|
||||
case Wbase_claim_type_.Tid__string: return new Wbase_claim_string(pid, snak_tid, value_itm.Data_bry());
|
||||
case Wbase_claim_type_.Tid__entity: return Parse_datavalue_entity (qid, pid, snak_tid, Json_nde.cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__time: return Parse_datavalue_time (qid, pid, snak_tid, Json_nde.cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__quantity: return Parse_datavalue_quantity (qid, pid, snak_tid, Json_nde.cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__globecoordinate: return Parse_datavalue_globecoordinate (qid, pid, snak_tid, Json_nde.cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__monolingualtext: return Parse_datavalue_monolingualtext (qid, pid, snak_tid, Json_nde.cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__entity: return Parse_datavalue_entity (qid, pid, snak_tid, Json_nde.Cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__time: return Parse_datavalue_time (qid, pid, snak_tid, Json_nde.Cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__quantity: return Parse_datavalue_quantity (qid, pid, snak_tid, Json_nde.Cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__globecoordinate: return Parse_datavalue_globecoordinate (qid, pid, snak_tid, Json_nde.Cast(value_itm));
|
||||
case Wbase_claim_type_.Tid__monolingualtext: return Parse_datavalue_monolingualtext (qid, pid, snak_tid, Json_nde.Cast(value_itm));
|
||||
default: throw Err_.new_unhandled_default(value_tid);
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ public class Wbase_claim_factory {
|
||||
byte[] numericId = null;
|
||||
byte[] id = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wbase_claim_entity_.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
byte[] subValBry = sub.Val().Data_bry();
|
||||
switch (tid) {
|
||||
@ -70,7 +70,7 @@ public class Wbase_claim_factory {
|
||||
int len = nde.Len();
|
||||
byte[] lang = null, text = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wbase_claim_monolingualtext_.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
byte[] sub_val_bry = sub.Val().Data_bry();
|
||||
switch (tid) {
|
||||
@ -85,7 +85,7 @@ public class Wbase_claim_factory {
|
||||
int len = nde.Len();
|
||||
byte[] lat = null, lng = null, alt = null, prc = null, glb = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wbase_claim_globecoordinate_.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
byte[] sub_val_bry = sub.Val().Data_bry();
|
||||
switch (tid) {
|
||||
@ -103,7 +103,7 @@ public class Wbase_claim_factory {
|
||||
int len = nde.Len();
|
||||
byte[] amount = null, unit = null, ubound = null, lbound = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wbase_claim_quantity_.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
byte[] sub_val_bry = sub.Val().Data_bry();
|
||||
switch (tid) {
|
||||
@ -120,7 +120,7 @@ public class Wbase_claim_factory {
|
||||
int len = nde.Len();
|
||||
byte[] time = null, timezone = null, before = null, after = null, precision = null, calendarmodel = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wbase_claim_time_.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
byte[] sub_val_bry = sub.Val().Data_bry();
|
||||
switch (tid) {
|
||||
|
@ -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,135 +13,158 @@ 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.xtns.wbases.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.langs.jsons.*; import gplx.xowa.xtns.wbases.core.*; import gplx.xowa.xtns.wbases.claims.*; import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*;
|
||||
class Wdata_claims_parser_v2 {
|
||||
private final Wbase_claim_factory factory = new Wbase_claim_factory();
|
||||
public void Make_claim_itms(byte[] qid, List_adp claim_itms_list, byte[] src, Json_kv claim_grp) {
|
||||
Json_ary claim_itms_ary = Json_ary.cast_or_null(claim_grp.Val());
|
||||
int claim_itms_len = claim_itms_ary.Len();
|
||||
int pid = Parse_pid(claim_grp.Key().Data_bry());
|
||||
for (int i = 0; i < claim_itms_len; ++i) {
|
||||
Json_nde claim_itm_nde = Json_nde.cast(claim_itms_ary.Get_at(i));
|
||||
Wbase_claim_base itm = Parse_claim_itm(qid, claim_itm_nde, pid);
|
||||
if (itm != null) // HACK: itm can be null if value is "somevalue"; DATE:2014-09-20
|
||||
claim_itms_list.Add(itm);
|
||||
}
|
||||
}
|
||||
private Wbase_claim_base Parse_claim_itm(byte[] qid, Json_nde nde, int pid) {
|
||||
int len = nde.Len();
|
||||
byte rank_tid = Wbase_claim_rank_.Tid__unknown;
|
||||
Wbase_claim_base claim_itm = null; Wbase_claim_grp_list qualifiers = null; int[] qualifiers_order = null; Wbase_references_grp[] snaks_grp = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_claim.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_claim.Tid__mainsnak: claim_itm = Parse_mainsnak(qid, Json_nde.cast(sub.Val()), pid); break;
|
||||
case Wdata_dict_claim.Tid__rank: rank_tid = Wbase_claim_rank_.Reg.Get_tid_or(sub.Val().Data_bry(), Wbase_claim_rank_.Tid__unknown); break;
|
||||
case Wdata_dict_claim.Tid__references: snaks_grp = Parse_references(qid, Json_ary.cast_or_null(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__qualifiers: qualifiers = Parse_qualifiers(qid, Json_nde.cast(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__qualifiers_order: qualifiers_order = Parse_pid_order(Json_ary.cast_or_null(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__type: break; // ignore: "statement"
|
||||
case Wdata_dict_claim.Tid__id: break; // ignore: "Q2$F909BD1C-D34D-423F-9ED2-3493663321AF"
|
||||
}
|
||||
}
|
||||
if (claim_itm != null) {
|
||||
claim_itm.Rank_tid_(rank_tid);
|
||||
if (qualifiers != null) claim_itm.Qualifiers_(qualifiers);
|
||||
if (qualifiers_order != null) claim_itm.Qualifiers_order_(qualifiers_order);
|
||||
if (snaks_grp != null) claim_itm.References_(snaks_grp);
|
||||
}
|
||||
return claim_itm;
|
||||
}
|
||||
public Wbase_references_grp[] Parse_references(byte[] qid, Json_ary owner) {
|
||||
int len = owner.Len();
|
||||
Wbase_references_grp[] rv = new Wbase_references_grp[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde grp_nde = Json_nde.cast(owner.Get_at(i));
|
||||
rv[i] = Parse_references_grp(qid, grp_nde);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Wbase_references_grp Parse_references_grp(byte[] qid, Json_nde owner) {
|
||||
byte[] hash = null;
|
||||
Wbase_claim_grp_list snaks = null;
|
||||
int[] snaks_order = null;
|
||||
int len = owner.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(owner.Get_at(i));
|
||||
byte tid = Wdata_dict_reference.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_reference.Tid__hash: hash = sub.Val_as_bry(); break;
|
||||
case Wdata_dict_reference.Tid__snaks: snaks = Parse_qualifiers(qid, Json_nde.cast(sub.Val())); break;
|
||||
case Wdata_dict_reference.Tid__snaks_order: snaks_order = Parse_pid_order(Json_ary.cast_or_null(sub.Val())); break;
|
||||
}
|
||||
}
|
||||
return new Wbase_references_grp(hash, snaks, snaks_order);
|
||||
}
|
||||
public Wbase_claim_grp_list Parse_qualifiers(byte[] qid, Json_nde qualifiers_nde) {
|
||||
Wbase_claim_grp_list rv = new Wbase_claim_grp_list();
|
||||
if (qualifiers_nde == null) return rv; // NOTE:sometimes references can have 0 snaks; return back an empty Wbase_claim_grp_list, not null; PAGE:Птичкин,_Евгений_Николаевич; DATE:2015-02-16
|
||||
int len = qualifiers_nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv qualifier_kv = Json_kv.cast(qualifiers_nde.Get_at(i));
|
||||
int pid = Parse_pid(qualifier_kv.Key().Data_bry());
|
||||
Wbase_claim_grp claims_grp = Parse_props_grp(qid, pid, Json_ary.cast_or_null(qualifier_kv.Val()));
|
||||
rv.Add(claims_grp);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public int[] Parse_pid_order(Json_ary ary) {
|
||||
int len = ary.Len();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm pid_itm = ary.Get_at(i);
|
||||
rv[i] = Parse_pid(pid_itm.Data_bry());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Wbase_claim_grp Parse_props_grp(byte[] qid, int pid, Json_ary props_ary) {
|
||||
List_adp list = List_adp_.New();
|
||||
int len = props_ary.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde qualifier_nde = Json_nde.cast(props_ary.Get_at(i));
|
||||
Wbase_claim_base qualifier_itm = Parse_mainsnak(qid, qualifier_nde, pid);
|
||||
list.Add(qualifier_itm);
|
||||
}
|
||||
return new Wbase_claim_grp(Int_obj_ref.New(pid), (Wbase_claim_base[])list.To_ary_and_clear(Wbase_claim_base.class));
|
||||
}
|
||||
public Wbase_claim_base Parse_mainsnak(byte[] qid, Json_nde nde, int pid) {
|
||||
int len = nde.Len();
|
||||
byte snak_tid = Byte_.Max_value_127;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_mainsnak.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_mainsnak.Tid__snaktype: snak_tid = Wbase_claim_value_type_.Reg.Get_tid_or_fail(sub.Val().Data_bry()); break;
|
||||
case Wdata_dict_mainsnak.Tid__datavalue: return Parse_datavalue(qid, pid, snak_tid, Json_nde.cast(sub.Val()));
|
||||
case Wdata_dict_mainsnak.Tid__datatype: break; // ignore: has values like "wikibase-property"; EX: www.wikidata.org/wiki/Property:P397; DATE:2015-06-12
|
||||
case Wdata_dict_mainsnak.Tid__property: break; // ignore: pid already available above
|
||||
case Wdata_dict_mainsnak.Tid__hash: break; // ignore: "84487fc3f93b4f74ab1cc5a47d78f596f0b49390"
|
||||
}
|
||||
}
|
||||
return new Wbase_claim_value(pid, Wbase_claim_type_.Tid__unknown, snak_tid); // NOTE: mainsnak can be null, especially for qualifiers; PAGE:Q2!P576; DATE:2014-09-20
|
||||
}
|
||||
public Wbase_claim_base Parse_datavalue(byte[] qid, int pid, byte snak_tid, Json_nde nde) {
|
||||
int len = nde.Len();
|
||||
Json_itm value_itm = null; byte value_tid = Wbase_claim_type_.Tid__unknown;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_datavalue.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_datavalue.Tid__type: value_tid = Wbase_claim_type_.Get_tid_or_unknown(sub.Val().Data_bry()); break;
|
||||
case Wdata_dict_datavalue.Tid__value: value_itm = sub.Val(); break;
|
||||
case Wdata_dict_datavalue.Tid__error: break; // ignore: "Can only construct GlobeCoordinateValue with a String globe parameter"
|
||||
}
|
||||
}
|
||||
return factory.Parse(qid, pid, snak_tid, nde, value_tid, value_itm);
|
||||
}
|
||||
private static int Parse_pid(byte[] pid_bry) {
|
||||
int rv = Bry_.To_int_or(pid_bry, 1, pid_bry.length, -1); if (rv == -1) throw Err_.new_wo_type("invalid pid", "pid", String_.new_u8(pid_bry));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
package gplx.xowa.xtns.wbases.parsers;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_;
|
||||
import gplx.Err_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.String_;
|
||||
import gplx.core.primitives.Int_obj_ref;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_kv;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp_list;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_references_grp;
|
||||
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_rank_;
|
||||
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_type_;
|
||||
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_value_type_;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_base;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_value;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_claim;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_datavalue;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_mainsnak;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_reference;
|
||||
|
||||
class Wdata_claims_parser_v2 {
|
||||
private final Wbase_claim_factory factory = new Wbase_claim_factory();
|
||||
public void Make_claim_itms(byte[] qid, List_adp claim_itms_list, byte[] src, Json_kv claim_grp) {
|
||||
Json_ary claim_itms_ary = Json_ary.cast_or_null(claim_grp.Val());
|
||||
int claim_itms_len = claim_itms_ary.Len();
|
||||
int pid = Parse_pid(claim_grp.Key().Data_bry());
|
||||
for (int i = 0; i < claim_itms_len; ++i) {
|
||||
Json_nde claim_itm_nde = Json_nde.Cast(claim_itms_ary.Get_at(i));
|
||||
Wbase_claim_base itm = Parse_claim_itm(qid, claim_itm_nde, pid);
|
||||
if (itm != null) // HACK: itm can be null if value is "somevalue"; DATE:2014-09-20
|
||||
claim_itms_list.Add(itm);
|
||||
}
|
||||
}
|
||||
private Wbase_claim_base Parse_claim_itm(byte[] qid, Json_nde nde, int pid) {
|
||||
int len = nde.Len();
|
||||
byte rank_tid = Wbase_claim_rank_.Tid__unknown;
|
||||
Wbase_claim_base claim_itm = null; Wbase_claim_grp_list qualifiers = null; int[] qualifiers_order = null; Wbase_references_grp[] snaks_grp = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_claim.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_claim.Tid__mainsnak: claim_itm = Parse_mainsnak(qid, Json_nde.Cast(sub.Val()), pid); break;
|
||||
case Wdata_dict_claim.Tid__rank: rank_tid = Wbase_claim_rank_.Reg.Get_tid_or(sub.Val().Data_bry(), Wbase_claim_rank_.Tid__unknown); break;
|
||||
case Wdata_dict_claim.Tid__references: snaks_grp = Parse_references(qid, Json_ary.cast_or_null(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__qualifiers: qualifiers = Parse_qualifiers(qid, Json_nde.Cast(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__qualifiers_order: qualifiers_order = Parse_pid_order(Json_ary.cast_or_null(sub.Val())); break;
|
||||
case Wdata_dict_claim.Tid__type: break; // ignore: "statement"
|
||||
case Wdata_dict_claim.Tid__id: break; // ignore: "Q2$F909BD1C-D34D-423F-9ED2-3493663321AF"
|
||||
}
|
||||
}
|
||||
if (claim_itm != null) {
|
||||
claim_itm.Rank_tid_(rank_tid);
|
||||
if (qualifiers != null) claim_itm.Qualifiers_(qualifiers);
|
||||
if (qualifiers_order != null) claim_itm.Qualifiers_order_(qualifiers_order);
|
||||
if (snaks_grp != null) claim_itm.References_(snaks_grp);
|
||||
}
|
||||
return claim_itm;
|
||||
}
|
||||
public Wbase_references_grp[] Parse_references(byte[] qid, Json_ary owner) {
|
||||
int len = owner.Len();
|
||||
Wbase_references_grp[] rv = new Wbase_references_grp[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde grp_nde = Json_nde.Cast(owner.Get_at(i));
|
||||
rv[i] = Parse_references_grp(qid, grp_nde);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Wbase_references_grp Parse_references_grp(byte[] qid, Json_nde owner) {
|
||||
byte[] hash = null;
|
||||
Wbase_claim_grp_list snaks = null;
|
||||
int[] snaks_order = null;
|
||||
int len = owner.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.Cast(owner.Get_at(i));
|
||||
byte tid = Wdata_dict_reference.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_reference.Tid__hash: hash = sub.Val_as_bry(); break;
|
||||
case Wdata_dict_reference.Tid__snaks: snaks = Parse_qualifiers(qid, Json_nde.Cast(sub.Val())); break;
|
||||
case Wdata_dict_reference.Tid__snaks_order: snaks_order = Parse_pid_order(Json_ary.cast_or_null(sub.Val())); break;
|
||||
}
|
||||
}
|
||||
return new Wbase_references_grp(hash, snaks, snaks_order);
|
||||
}
|
||||
public Wbase_claim_grp_list Parse_qualifiers(byte[] qid, Json_nde qualifiers_nde) {
|
||||
Wbase_claim_grp_list rv = new Wbase_claim_grp_list();
|
||||
if (qualifiers_nde == null) return rv; // NOTE:sometimes references can have 0 snaks; return back an empty Wbase_claim_grp_list, not null; PAGE:Птичкин,_Евгений_Николаевич; DATE:2015-02-16
|
||||
int len = qualifiers_nde.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv qualifier_kv = Json_kv.Cast(qualifiers_nde.Get_at(i));
|
||||
int pid = Parse_pid(qualifier_kv.Key().Data_bry());
|
||||
Wbase_claim_grp claims_grp = Parse_props_grp(qid, pid, Json_ary.cast_or_null(qualifier_kv.Val()));
|
||||
rv.Add(claims_grp);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public int[] Parse_pid_order(Json_ary ary) {
|
||||
int len = ary.Len();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm pid_itm = ary.Get_at(i);
|
||||
rv[i] = Parse_pid(pid_itm.Data_bry());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private Wbase_claim_grp Parse_props_grp(byte[] qid, int pid, Json_ary props_ary) {
|
||||
List_adp list = List_adp_.New();
|
||||
int len = props_ary.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_nde qualifier_nde = Json_nde.Cast(props_ary.Get_at(i));
|
||||
Wbase_claim_base qualifier_itm = Parse_mainsnak(qid, qualifier_nde, pid);
|
||||
list.Add(qualifier_itm);
|
||||
}
|
||||
return new Wbase_claim_grp(Int_obj_ref.New(pid), (Wbase_claim_base[])list.To_ary_and_clear(Wbase_claim_base.class));
|
||||
}
|
||||
public Wbase_claim_base Parse_mainsnak(byte[] qid, Json_nde nde, int pid) {
|
||||
int len = nde.Len();
|
||||
byte snak_tid = Byte_.Max_value_127;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_mainsnak.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_mainsnak.Tid__snaktype: snak_tid = Wbase_claim_value_type_.Reg.Get_tid_or_fail(sub.Val().Data_bry()); break;
|
||||
case Wdata_dict_mainsnak.Tid__datavalue: return Parse_datavalue(qid, pid, snak_tid, Json_nde.Cast(sub.Val()));
|
||||
case Wdata_dict_mainsnak.Tid__datatype: break; // ignore: has values like "wikibase-property"; EX: www.wikidata.org/wiki/Property:P397; DATE:2015-06-12
|
||||
case Wdata_dict_mainsnak.Tid__property: break; // ignore: pid already available above
|
||||
case Wdata_dict_mainsnak.Tid__hash: break; // ignore: "84487fc3f93b4f74ab1cc5a47d78f596f0b49390"
|
||||
}
|
||||
}
|
||||
return new Wbase_claim_value(pid, Wbase_claim_type_.Tid__unknown, snak_tid); // NOTE: mainsnak can be null, especially for qualifiers; PAGE:Q2!P576; DATE:2014-09-20
|
||||
}
|
||||
public Wbase_claim_base Parse_datavalue(byte[] qid, int pid, byte snak_tid, Json_nde nde) {
|
||||
int len = nde.Len();
|
||||
Json_itm value_itm = null; byte value_tid = Wbase_claim_type_.Tid__unknown;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv sub = Json_kv.Cast(nde.Get_at(i));
|
||||
byte tid = Wdata_dict_datavalue.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_datavalue.Tid__type: value_tid = Wbase_claim_type_.Get_tid_or_unknown(sub.Val().Data_bry()); break;
|
||||
case Wdata_dict_datavalue.Tid__value: value_itm = sub.Val(); break;
|
||||
case Wdata_dict_datavalue.Tid__error: break; // ignore: "Can only construct GlobeCoordinateValue with a String globe parameter"
|
||||
}
|
||||
}
|
||||
return factory.Parse(qid, pid, snak_tid, nde, value_tid, value_itm);
|
||||
}
|
||||
private static int Parse_pid(byte[] pid_bry) {
|
||||
int rv = Bry_.To_int_or(pid_bry, 1, pid_bry.length, -1); if (rv == -1) throw Err_.new_wo_type("invalid pid", "pid", String_.new_u8(pid_bry));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ import gplx.xowa.xtns.wbases.core.Wdata_sitelink_itm;
|
||||
|
||||
abstract class Wdata_doc_parser_fxt_base {
|
||||
protected Wdata_doc_parser wdoc_parser;
|
||||
private final Json_parser json_parser = new Json_parser();
|
||||
private final Bry_bfr tmp_time_bfr = Bry_bfr_.New();
|
||||
private final Json_parser json_parser = new Json_parser();
|
||||
private final Bry_bfr tmp_time_bfr = Bry_bfr_.New();
|
||||
public void Init() {
|
||||
if (wdoc_parser == null) wdoc_parser = Make_parser();
|
||||
}
|
||||
@ -100,13 +100,13 @@ abstract class Wdata_doc_parser_fxt_base {
|
||||
}
|
||||
public void Test_qualifiers(String raw, Wbase_claim_base... expd_itms) {
|
||||
Json_doc jdoc = json_parser.Parse_by_apos(raw);
|
||||
Json_nde qualifiers_nde = Json_nde.cast(Json_kv.cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
Json_nde qualifiers_nde = Json_nde.Cast(Json_kv.Cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
Wbase_claim_grp_list actl = wdoc_parser.Parse_qualifiers(Q1_bry, qualifiers_nde);
|
||||
Tfds.Eq_ary_str(expd_itms, To_ary(actl));
|
||||
}
|
||||
public void Test_references(String raw, int[] expd_order, Wbase_claim_base... expd_itms) {
|
||||
Json_doc jdoc = json_parser.Parse_by_apos(raw);
|
||||
Json_ary owner = Json_ary.cast_or_null(Json_kv.cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
Json_ary owner = Json_ary.cast_or_null(Json_kv.Cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
Wbase_references_grp[] actl = wdoc_parser.Parse_references(Q1_bry, owner);
|
||||
Wbase_references_grp actl_grp = actl[0];
|
||||
Tfds.Eq_ary(expd_order, actl_grp.Snaks_order());
|
||||
@ -114,7 +114,7 @@ abstract class Wdata_doc_parser_fxt_base {
|
||||
}
|
||||
public void Test_pid_order(String raw, int... expd) {
|
||||
Json_doc jdoc = json_parser.Parse_by_apos(raw);
|
||||
Json_ary nde = Json_ary.cast_or_null(Json_kv.cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
Json_ary nde = Json_ary.cast_or_null(Json_kv.Cast(jdoc.Root_nde().Get_at(0)).Val());
|
||||
int[] actl = wdoc_parser.Parse_pid_order(Q1_bry, nde);
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
}
|
||||
@ -131,7 +131,7 @@ abstract class Wdata_doc_parser_fxt_base {
|
||||
}
|
||||
return (Wbase_claim_base[])rv.To_ary_and_clear(Wbase_claim_base.class);
|
||||
}
|
||||
private static final byte[] Q1_bry = Bry_.new_a7("Q1");
|
||||
private static final byte[] Q1_bry = Bry_.new_a7("Q1");
|
||||
}
|
||||
class Wdata_doc_parser_v2_fxt extends Wdata_doc_parser_fxt_base {
|
||||
@Override public Wdata_doc_parser Make_parser() {return new Wdata_doc_parser_v2();}
|
||||
|
@ -1,19 +1,19 @@
|
||||
/*
|
||||
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.xowa.xtns.wbases.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
||||
/*
|
||||
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.xowa.xtns.wbases.parsers; import gplx.*;
|
||||
import gplx.core.primitives.*; import gplx.langs.jsons.*;
|
||||
import gplx.xowa.xtns.wbases.core.*; import gplx.xowa.xtns.wbases.claims.*; import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*;
|
||||
public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
@ -36,18 +36,18 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
}
|
||||
public Ordered_hash Parse_sitelinks(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(Bry_links)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(Bry_links)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv wiki_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_kv wiki_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
byte[] site_bry = wiki_kv.Key().Data_bry();
|
||||
byte[] title_bry = null; byte[][] badges_bry_ary = null;
|
||||
if (wiki_kv.Val().Tid() == Json_itm_.Tid__nde) { // v1.2: "enwiki":{name:"Earth", badges:[]}
|
||||
Json_nde val_nde = Json_nde.cast(wiki_kv.Val());
|
||||
Json_kv name_kv = Json_kv.cast(val_nde.Get_at(0));
|
||||
Json_nde val_nde = Json_nde.Cast(wiki_kv.Val());
|
||||
Json_kv name_kv = Json_kv.Cast(val_nde.Get_at(0));
|
||||
title_bry = name_kv.Val().Data_bry();
|
||||
Json_kv badges_kv = Json_kv.cast(val_nde.Get_at(1));
|
||||
Json_kv badges_kv = Json_kv.Cast(val_nde.Get_at(1));
|
||||
if (badges_kv != null) {// TEST:some tests do not define a badges nde; ignore if null; DATE:2014-09-19
|
||||
Json_ary badges_ary = Json_ary.cast_or_null(badges_kv.Val());
|
||||
badges_bry_ary = badges_ary.Xto_bry_ary();
|
||||
@ -65,11 +65,11 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
public Ordered_hash Parse_langvals(byte[] qid, Json_doc doc, boolean label_or_description) {
|
||||
try {
|
||||
byte[] langval_key = label_or_description ? Bry_label : Bry_description;
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(langval_key)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(langval_key)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_kv data_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
Wdata_langtext_itm itm = new Wdata_langtext_itm(lang_bry, data_kv.Val().Data_bry());
|
||||
rv.Add(lang_bry, itm);
|
||||
@ -79,11 +79,11 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
}
|
||||
public Ordered_hash Parse_aliases(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(Bry_aliases)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(Bry_aliases)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_kv data_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
byte[][] vals_bry_ary = null;
|
||||
Json_itm data_val = data_kv.Val();
|
||||
@ -93,11 +93,11 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
vals_bry_ary = vals_ary.Xto_bry_ary();
|
||||
break;
|
||||
case Json_itm_.Tid__nde: // EX: 'en':{'0:en_val_1','1:en_val_2'}; PAGE:wd.q:621080 DATE:2014-09-21
|
||||
Json_nde vals_nde = Json_nde.cast(data_val);
|
||||
Json_nde vals_nde = Json_nde.Cast(data_val);
|
||||
int vals_len = vals_nde.Len();
|
||||
vals_bry_ary = new byte[vals_len][];
|
||||
for (int j = 0; j < vals_len; ++j) {
|
||||
Json_kv vals_sub_kv = Json_kv.cast(vals_nde.Get_at(j));
|
||||
Json_kv vals_sub_kv = Json_kv.Cast(vals_nde.Get_at(j));
|
||||
vals_bry_ary[j] = vals_sub_kv.Val().Data_bry();
|
||||
}
|
||||
break;
|
||||
@ -116,7 +116,7 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
byte[] src = doc.Src();
|
||||
int len = list_nde.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json_nde claim_nde = Json_nde.cast(list_nde.Get_at(i));
|
||||
Json_nde claim_nde = Json_nde.Cast(list_nde.Get_at(i));
|
||||
Wbase_claim_base claim_itm = Make_claim_itm(src, claim_nde);
|
||||
temp_list.Add(claim_itm);
|
||||
}
|
||||
@ -150,10 +150,10 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
int len = prop_nde.Len(); // should have 5 (m, q, g, rank, refs), but don't enforce (can rely on keys)
|
||||
Wbase_claim_base rv = null;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json_kv kv = Json_kv.cast(prop_nde.Get_at(i));
|
||||
Json_kv kv = Json_kv.Cast(prop_nde.Get_at(i));
|
||||
Json_itm kv_key = kv.Key();
|
||||
Byte_obj_val bv = (Byte_obj_val)Prop_key_hash.Get_by_mid(src, kv_key.Src_bgn(), kv_key.Src_end());
|
||||
if (bv == null) {Warn("invalid prop node: ~{0}", String_.new_u8(src, kv_key.Src_bgn(), kv_key.Src_end())); return null;}
|
||||
Byte_obj_val bv = (Byte_obj_val)Prop_key_hash.Get_by_bry(kv_key.Data_bry());
|
||||
if (bv == null) {Warn("invalid prop node: ~{0}", String_.new_u8(kv_key.Data_bry())); return null;}
|
||||
switch (bv.Val()) {
|
||||
case Prop_tid_m:
|
||||
rv = New_prop_by_m(src, Json_ary.cast_or_null(kv.Val()));
|
||||
@ -176,13 +176,13 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
}
|
||||
private Wbase_claim_base New_prop_by_m(byte[] src, Json_ary ary) {
|
||||
byte snak_tid = Wbase_claim_value_type_.Reg.Get_tid_or_fail(ary.Get_at(0).Data_bry());
|
||||
int pid = Json_itm_int.cast(ary.Get_at(1)).Data_as_int();
|
||||
int pid = Json_itm_int.Cast(ary.Get_at(1)).Data_as_int();
|
||||
switch (snak_tid) {
|
||||
case Wbase_claim_value_type_.Tid__novalue : return Wbase_claim_value.New_novalue(pid);
|
||||
case Wbase_claim_value_type_.Tid__somevalue : return Wbase_claim_value.New_somevalue(pid);
|
||||
}
|
||||
Json_itm val_tid_itm = ary.Get_at(2);
|
||||
byte val_tid = Wbase_claim_type_.Get_tid_or_unknown(src, val_tid_itm.Src_bgn(), val_tid_itm.Src_end());
|
||||
byte val_tid = Wbase_claim_type_.Get_tid_or_unknown(val_tid_itm.Data_bry());
|
||||
return Make_itm(pid, snak_tid, val_tid, ary);
|
||||
}
|
||||
private Wbase_claim_base Make_itm(int pid, byte snak_tid, byte val_tid, Json_ary ary) {
|
||||
@ -190,31 +190,31 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
case Wbase_claim_type_.Tid__string:
|
||||
return new Wbase_claim_string(pid, snak_tid, ary.Get_at(3).Data_bry());
|
||||
case Wbase_claim_type_.Tid__entity: {
|
||||
Json_nde sub_nde = Json_nde.cast(ary.Get_at(3));
|
||||
Json_kv entity_kv = Json_kv.cast(sub_nde.Get_at(1));
|
||||
Json_nde sub_nde = Json_nde.Cast(ary.Get_at(3));
|
||||
Json_kv entity_kv = Json_kv.Cast(sub_nde.Get_at(1));
|
||||
return new Wbase_claim_entity(pid, snak_tid, Wbase_claim_entity_type_.Tid__item, entity_kv.Val().Data_bry());
|
||||
}
|
||||
case Wbase_claim_type_.Tid__time: {
|
||||
Json_nde sub_nde = Json_nde.cast(ary.Get_at(3));
|
||||
Json_nde sub_nde = Json_nde.Cast(ary.Get_at(3));
|
||||
return new Wbase_claim_time(pid, snak_tid, Get_val(sub_nde, 0), Get_val(sub_nde, 1), Get_val(sub_nde, 2), Get_val(sub_nde, 3), Get_val(sub_nde, 4), Get_val(sub_nde, 5));
|
||||
}
|
||||
case Wbase_claim_type_.Tid__globecoordinate: case Wbase_claim_type_.Tid__bad: {
|
||||
Json_nde sub_nde = Json_nde.cast(ary.Get_at(3));
|
||||
Json_nde sub_nde = Json_nde.Cast(ary.Get_at(3));
|
||||
return new Wbase_claim_globecoordinate(pid, snak_tid, Get_val(sub_nde, 0), Get_val(sub_nde, 1), Get_val(sub_nde, 2), Get_val(sub_nde, 3), Get_val(sub_nde, 4));
|
||||
}
|
||||
case Wbase_claim_type_.Tid__quantity: {
|
||||
Json_nde sub_nde = Json_nde.cast(ary.Get_at(3));
|
||||
Json_nde sub_nde = Json_nde.Cast(ary.Get_at(3));
|
||||
return new Wbase_claim_quantity(pid, snak_tid, Get_val(sub_nde, 0), Get_val(sub_nde, 1), Get_val(sub_nde, 2), Get_val(sub_nde, 3));
|
||||
}
|
||||
case Wbase_claim_type_.Tid__monolingualtext: {
|
||||
Json_nde sub_nde = Json_nde.cast(ary.Get_at(3));
|
||||
Json_nde sub_nde = Json_nde.Cast(ary.Get_at(3));
|
||||
return new Wbase_claim_monolingualtext(pid, snak_tid, Get_val(sub_nde, 1), Get_val(sub_nde, 0));
|
||||
}
|
||||
default: {throw Err_.new_unhandled(val_tid);}
|
||||
}
|
||||
}
|
||||
private static byte[] Get_val(Json_nde sub_nde, int i) {
|
||||
Json_kv kv = Json_kv.cast(sub_nde.Get_at(i));
|
||||
Json_kv kv = Json_kv.Cast(sub_nde.Get_at(i));
|
||||
return kv.Val().Data_bry();
|
||||
}
|
||||
private void Warn(String fmt, Object... args) {usr_dlg.Warn_many("", "", fmt, args);}
|
||||
@ -227,11 +227,11 @@ public class Wdata_doc_parser_v1 implements Wdata_doc_parser {
|
||||
.Add_bry_byte(Wdata_dict_claim_v1.Bry_rank , Prop_tid_rank)
|
||||
.Add_bry_byte(Wdata_dict_claim_v1.Bry_refs , Prop_tid_refs);
|
||||
Ordered_hash Bld_hash(Json_doc doc, byte[] key) {
|
||||
Json_nde nde = Json_nde.cast(doc.Get_grp(key)); if (nde == null) return Empty_ordered_hash_bry;
|
||||
Json_nde nde = Json_nde.Cast(doc.Get_grp(key)); if (nde == null) return Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int len = nde.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json_kv kv = Json_kv.cast(nde.Get_at(i));
|
||||
Json_kv kv = Json_kv.Cast(nde.Get_at(i));
|
||||
byte[] kv_key = kv.Key().Data_bry();
|
||||
rv.Add(kv_key, kv);
|
||||
}
|
||||
|
@ -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,133 +13,154 @@ 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.xtns.wbases.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
||||
import gplx.langs.jsons.*; import gplx.core.btries.*;
|
||||
import gplx.xowa.xtns.wbases.core.*; import gplx.xowa.xtns.wbases.claims.*; import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*;
|
||||
public class Wdata_doc_parser_v2 implements Wdata_doc_parser {
|
||||
private Wdata_claims_parser_v2 claims_parser = new Wdata_claims_parser_v2();
|
||||
public byte[] Parse_qid(Json_doc doc) {
|
||||
try {
|
||||
Json_itm itm = doc.Find_nde(Bry_id);
|
||||
return Bry_.Lcase__1st(itm.Data_bry()); // standardize on "q" instead of "Q" for compatibility with v1
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse qid", "src", String_.new_u8(doc.Src()));}
|
||||
}
|
||||
public Ordered_hash Parse_sitelinks(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(Bry_sitelinks)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_nde data_nde = Json_nde.cast(data_kv.Val());
|
||||
int data_nde_len = data_nde.Len();
|
||||
Json_kv site_kv = null, name_kv = null; Json_ary badges_ary = null;
|
||||
for (int j = 0; j < data_nde_len; ++j) {
|
||||
Json_kv sub = Json_kv.cast(data_nde.Get_at(j));
|
||||
byte tid = Wdata_dict_sitelink.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_sitelink.Tid__site: site_kv = Json_kv.cast(sub); break;
|
||||
case Wdata_dict_sitelink.Tid__title: name_kv = Json_kv.cast(sub); break;
|
||||
case Wdata_dict_sitelink.Tid__badges: badges_ary = Json_ary.cast_or_null(Json_kv.cast(sub).Val()); break;
|
||||
}
|
||||
}
|
||||
byte[] site_bry = site_kv.Val().Data_bry();
|
||||
Wdata_sitelink_itm itm = new Wdata_sitelink_itm(site_bry, name_kv.Val().Data_bry(), badges_ary.Xto_bry_ary());
|
||||
rv.Add(site_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse sitelinks", "qid", String_.new_u8(qid));}
|
||||
}
|
||||
public Ordered_hash Parse_langvals(byte[] qid, Json_doc doc, boolean label_or_description) {
|
||||
try {
|
||||
byte[] langval_key = label_or_description ? Bry_labels : Bry_descriptions;
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(langval_key)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_nde data_nde = Json_nde.cast(data_kv.Val());
|
||||
Json_kv text_kv = null;
|
||||
int data_nde_len = data_nde.Len();
|
||||
for (int j = 0; j < data_nde_len; ++j) {
|
||||
Json_kv sub = Json_kv.cast(data_nde.Get_at(j));
|
||||
byte tid = Wdata_dict_langtext.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_langtext.Tid__language: break;
|
||||
case Wdata_dict_langtext.Tid__value: text_kv = Json_kv.cast(sub); break;
|
||||
}
|
||||
}
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
Wdata_langtext_itm itm = new Wdata_langtext_itm(lang_bry, text_kv.Val().Data_bry());
|
||||
rv.Add(lang_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse langvals", "qid", String_.new_u8(qid), "langval_tid", label_or_description);}
|
||||
}
|
||||
public Ordered_hash Parse_aliases(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(Bry_aliases)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.cast(list_nde.Get_at(i));
|
||||
Json_ary vals_ary = Json_ary.cast_or_null(data_kv.Val());
|
||||
int vals_len = vals_ary.Len();
|
||||
byte[][] vals = new byte[vals_len][];
|
||||
for (int j = 0; j < vals_len; ++j) {
|
||||
Json_nde lang_nde = Json_nde.cast(vals_ary.Get_at(j));
|
||||
int k_len = lang_nde.Len();
|
||||
for (int k = 0; k < k_len; ++k) {
|
||||
Json_kv sub = Json_kv.cast(lang_nde.Get_at(k));
|
||||
byte tid = Wdata_dict_langtext.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_langtext.Tid__language: break;
|
||||
case Wdata_dict_langtext.Tid__value: vals[j] = sub.Val().Data_bry(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
Wdata_alias_itm itm = new Wdata_alias_itm(lang_bry, vals);
|
||||
rv.Add(lang_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse sitelinks", "qid", String_.new_u8(qid));}
|
||||
}
|
||||
public Ordered_hash Parse_claims(byte[] qid, Json_doc doc) {
|
||||
synchronized (this) {// TS; DATE:2016-07-06
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.cast(doc.Get_grp(Bry_claims)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_generic;
|
||||
List_adp temp_list = List_adp_.New();
|
||||
byte[] src = doc.Src();
|
||||
int len = list_nde.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json_kv claim_nde = Json_kv.cast(list_nde.Get_at(i));
|
||||
claims_parser.Make_claim_itms(qid, temp_list, src, claim_nde);
|
||||
}
|
||||
return Wdata_doc_parser_v1.Claims_list_to_hash(temp_list);
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse claims", "qid", String_.new_u8(doc.Src()));}
|
||||
}
|
||||
}
|
||||
public Wbase_claim_base Parse_claims_data(byte[] qid, int pid, byte snak_tid, Json_nde nde) {return claims_parser.Parse_datavalue(qid, pid, snak_tid, nde);}
|
||||
public Wbase_claim_grp_list Parse_qualifiers(byte[] qid, Json_nde nde) {return claims_parser.Parse_qualifiers(qid, nde);}
|
||||
public Wbase_references_grp[] Parse_references(byte[] qid, Json_ary owner) {return claims_parser.Parse_references(qid, owner);}
|
||||
public int[] Parse_pid_order(byte[] qid, Json_ary ary) {return claims_parser.Parse_pid_order(ary);}
|
||||
public static final String
|
||||
Str_id = "id"
|
||||
, Str_sitelinks = "sitelinks"
|
||||
, Str_labels = "labels"
|
||||
, Str_descriptions = "descriptions"
|
||||
, Str_aliases = "aliases"
|
||||
, Str_claims = "claims"
|
||||
, Str_type = "type"
|
||||
;
|
||||
public static final byte[]
|
||||
Bry_id = Bry_.new_a7(Str_id)
|
||||
, Bry_sitelinks = Bry_.new_a7(Str_sitelinks)
|
||||
, Bry_labels = Bry_.new_a7(Str_labels)
|
||||
, Bry_descriptions = Bry_.new_a7(Str_descriptions)
|
||||
, Bry_aliases = Bry_.new_a7(Str_aliases)
|
||||
, Bry_claims = Bry_.new_a7(Str_claims)
|
||||
, Bry_type = Bry_.new_a7(Str_type)
|
||||
;
|
||||
}
|
||||
package gplx.xowa.xtns.wbases.parsers;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Byte_;
|
||||
import gplx.Err_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.Ordered_hash;
|
||||
import gplx.Ordered_hash_;
|
||||
import gplx.String_;
|
||||
import gplx.langs.jsons.Json_ary;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_itm;
|
||||
import gplx.langs.jsons.Json_kv;
|
||||
import gplx.langs.jsons.Json_nde;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp_list;
|
||||
import gplx.xowa.xtns.wbases.claims.Wbase_references_grp;
|
||||
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_base;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_alias_itm;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_langtext;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_dict_sitelink;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_langtext_itm;
|
||||
import gplx.xowa.xtns.wbases.core.Wdata_sitelink_itm;
|
||||
|
||||
public class Wdata_doc_parser_v2 implements Wdata_doc_parser {
|
||||
private Wdata_claims_parser_v2 claims_parser = new Wdata_claims_parser_v2();
|
||||
public byte[] Parse_qid(Json_doc doc) {
|
||||
try {
|
||||
Json_itm itm = doc.Find_nde(Bry_id);
|
||||
return Bry_.Lcase__1st(itm.Data_bry()); // standardize on "q" instead of "Q" for compatibility with v1
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse qid", "src", String_.new_u8(doc.Src()));}
|
||||
}
|
||||
public Ordered_hash Parse_sitelinks(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(Bry_sitelinks)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
Json_nde data_nde = Json_nde.Cast(data_kv.Val());
|
||||
int data_nde_len = data_nde.Len();
|
||||
Json_kv site_kv = null, name_kv = null; Json_ary badges_ary = null;
|
||||
for (int j = 0; j < data_nde_len; ++j) {
|
||||
Json_kv sub = Json_kv.Cast(data_nde.Get_at(j));
|
||||
byte tid = Wdata_dict_sitelink.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_sitelink.Tid__site: site_kv = Json_kv.Cast(sub); break;
|
||||
case Wdata_dict_sitelink.Tid__title: name_kv = Json_kv.Cast(sub); break;
|
||||
case Wdata_dict_sitelink.Tid__badges: badges_ary = Json_ary.cast_or_null(Json_kv.Cast(sub).Val()); break;
|
||||
}
|
||||
}
|
||||
byte[] site_bry = site_kv.Val().Data_bry();
|
||||
Wdata_sitelink_itm itm = new Wdata_sitelink_itm(site_bry, name_kv.Val().Data_bry(), badges_ary.Xto_bry_ary());
|
||||
rv.Add(site_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse sitelinks", "qid", String_.new_u8(qid));}
|
||||
}
|
||||
public Ordered_hash Parse_langvals(byte[] qid, Json_doc doc, boolean label_or_description) {
|
||||
try {
|
||||
byte[] langval_key = label_or_description ? Bry_labels : Bry_descriptions;
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(langval_key)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
Json_nde data_nde = Json_nde.Cast(data_kv.Val());
|
||||
Json_kv text_kv = null;
|
||||
int data_nde_len = data_nde.Len();
|
||||
for (int j = 0; j < data_nde_len; ++j) {
|
||||
Json_kv sub = Json_kv.Cast(data_nde.Get_at(j));
|
||||
byte tid = Wdata_dict_langtext.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_langtext.Tid__language: break;
|
||||
case Wdata_dict_langtext.Tid__value: text_kv = Json_kv.Cast(sub); break;
|
||||
}
|
||||
}
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
Wdata_langtext_itm itm = new Wdata_langtext_itm(lang_bry, text_kv.Val().Data_bry());
|
||||
rv.Add(lang_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse langvals", "qid", String_.new_u8(qid), "langval_tid", label_or_description);}
|
||||
}
|
||||
public Ordered_hash Parse_aliases(byte[] qid, Json_doc doc) {
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(Bry_aliases)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_bry;
|
||||
Ordered_hash rv = Ordered_hash_.New_bry();
|
||||
int list_len = list_nde.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Json_kv data_kv = Json_kv.Cast(list_nde.Get_at(i));
|
||||
Json_ary vals_ary = Json_ary.cast_or_null(data_kv.Val());
|
||||
int vals_len = vals_ary.Len();
|
||||
byte[][] vals = new byte[vals_len][];
|
||||
for (int j = 0; j < vals_len; ++j) {
|
||||
Json_nde lang_nde = Json_nde.Cast(vals_ary.Get_at(j));
|
||||
int k_len = lang_nde.Len();
|
||||
for (int k = 0; k < k_len; ++k) {
|
||||
Json_kv sub = Json_kv.Cast(lang_nde.Get_at(k));
|
||||
byte tid = Wdata_dict_langtext.Reg.Get_tid_or_max_and_log(qid, sub.Key().Data_bry()); if (tid == Byte_.Max_value_127) continue;
|
||||
switch (tid) {
|
||||
case Wdata_dict_langtext.Tid__language: break;
|
||||
case Wdata_dict_langtext.Tid__value: vals[j] = sub.Val().Data_bry(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] lang_bry = data_kv.Key().Data_bry();
|
||||
Wdata_alias_itm itm = new Wdata_alias_itm(lang_bry, vals);
|
||||
rv.Add(lang_bry, itm);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse sitelinks", "qid", String_.new_u8(qid));}
|
||||
}
|
||||
public Ordered_hash Parse_claims(byte[] qid, Json_doc doc) {
|
||||
synchronized (this) {// TS; DATE:2016-07-06
|
||||
try {
|
||||
Json_nde list_nde = Json_nde.Cast(doc.Get_grp(Bry_claims)); if (list_nde == null) return Wdata_doc_parser_v1.Empty_ordered_hash_generic;
|
||||
List_adp temp_list = List_adp_.New();
|
||||
byte[] src = doc.Src();
|
||||
int len = list_nde.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json_kv claim_nde = Json_kv.Cast(list_nde.Get_at(i));
|
||||
claims_parser.Make_claim_itms(qid, temp_list, src, claim_nde);
|
||||
}
|
||||
return Wdata_doc_parser_v1.Claims_list_to_hash(temp_list);
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to parse claims", "qid", String_.new_u8(doc.Src()));}
|
||||
}
|
||||
}
|
||||
public Wbase_claim_base Parse_claims_data(byte[] qid, int pid, byte snak_tid, Json_nde nde) {return claims_parser.Parse_datavalue(qid, pid, snak_tid, nde);}
|
||||
public Wbase_claim_grp_list Parse_qualifiers(byte[] qid, Json_nde nde) {return claims_parser.Parse_qualifiers(qid, nde);}
|
||||
public Wbase_references_grp[] Parse_references(byte[] qid, Json_ary owner) {return claims_parser.Parse_references(qid, owner);}
|
||||
public int[] Parse_pid_order(byte[] qid, Json_ary ary) {return claims_parser.Parse_pid_order(ary);}
|
||||
public static final String
|
||||
Str_id = "id"
|
||||
, Str_sitelinks = "sitelinks"
|
||||
, Str_labels = "labels"
|
||||
, Str_descriptions = "descriptions"
|
||||
, Str_aliases = "aliases"
|
||||
, Str_claims = "claims"
|
||||
, Str_type = "type"
|
||||
;
|
||||
public static final byte[]
|
||||
Bry_id = Bry_.new_a7(Str_id)
|
||||
, Bry_sitelinks = Bry_.new_a7(Str_sitelinks)
|
||||
, Bry_labels = Bry_.new_a7(Str_labels)
|
||||
, Bry_descriptions = Bry_.new_a7(Str_descriptions)
|
||||
, Bry_aliases = Bry_.new_a7(Str_aliases)
|
||||
, Bry_claims = Bry_.new_a7(Str_claims)
|
||||
, Bry_type = Bry_.new_a7(Str_type)
|
||||
;
|
||||
}
|
||||
|
47
400_xowa/tst/gplx/langs/jsons/JsonDocBldrTest.java
Normal file
47
400_xowa/tst/gplx/langs/jsons/JsonDocBldrTest.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
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_bfr;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.core.tests.Gftest;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JsonDocBldrTest {
|
||||
private JsonDocBldrTestUtil util = new JsonDocBldrTestUtil();
|
||||
@Test public void Basic() {
|
||||
JsonDocBldr bldr = JsonDocBldr.NewRootNde();
|
||||
bldr.NdeBgn("nde")
|
||||
.KvBool("bool", true)
|
||||
.KvInt("int", 123)
|
||||
.KvStr("str", "abc")
|
||||
.NdeEnd();
|
||||
util.Test(bldr
|
||||
, "{ 'nde':"
|
||||
, " { 'bool':true"
|
||||
, " , 'int':123"
|
||||
, " , 'str':'abc'"
|
||||
, " }"
|
||||
, "}");
|
||||
}
|
||||
}
|
||||
class JsonDocBldrTestUtil {
|
||||
public void Test(JsonDocBldr bldr, String... ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
bldr.ToDoc().Root_grp().Print_as_json(bfr, 0);
|
||||
Gftest.Eq__ary__lines(Json_doc.Make_str_by_apos(ary), bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
71
400_xowa/tst/gplx/langs/mustaches/JsonMustacheNdeTest.java
Normal file
71
400_xowa/tst/gplx/langs/mustaches/JsonMustacheNdeTest.java
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
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.mustaches;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr_;
|
||||
import gplx.core.tests.Gftest;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.langs.jsons.Json_parser;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JsonMustacheNdeTest {
|
||||
private JsonMustacheNdeTestUtil util = new JsonMustacheNdeTestUtil();
|
||||
|
||||
@Test public void Str() {
|
||||
util.TestWrite("[{{key}}]", "{'key':'abc'}", "[abc]");
|
||||
}
|
||||
@Test public void Bool() {
|
||||
String mustache = "[{{#key}}y{{/key}}]";
|
||||
util.TestWrite(mustache, "{'key':true}", "[y]");
|
||||
util.TestWrite(mustache, "{'key':false}", "[]");
|
||||
}
|
||||
@Test public void Ary() {
|
||||
String mustache = "[{{#group}}{{key}} {{/group}}]";
|
||||
util.TestWrite(mustache, "{'group':[{'key':'a'}, {'key':'b'}, {'key':'c'}]}", "[a b c ]");
|
||||
}
|
||||
@Test public void SectionPropWithDot() {
|
||||
String mustache = "[{{#key}}{{.}}{{/key}}]";
|
||||
util.TestWrite(mustache, "{'key':'test'}", "[test]");
|
||||
util.TestWrite(mustache, "{'key1':'test'}", "[]");
|
||||
}
|
||||
@Test public void SectionPropWithoutDot() {
|
||||
String mustache = "[{{#prop}}{{propx}}{{/prop}}]";
|
||||
util.TestWrite(mustache, "{'prop':'test'}", "[]");
|
||||
util.TestWrite(mustache, "{'propx':'test'}", "[]");
|
||||
}
|
||||
@Test public void Dot() {// NOTE: online demo gives `([object Object])`; https://mustache.github.io/#demo
|
||||
String mustache = "({{.}})";
|
||||
util.TestWrite(mustache, "{'key':'test'}", "()");
|
||||
}
|
||||
}
|
||||
class JsonMustacheNdeTestUtil {
|
||||
public void TestWrite(String mustache, String json, String expd) {
|
||||
// parse JSON to mustache itm
|
||||
Json_doc jdoc = Json_parser.ParseToJdoc(Json_doc.Make_str_by_apos(json));
|
||||
JsonMustacheNde nde = new JsonMustacheNde(jdoc.Root_nde());
|
||||
|
||||
// parse template
|
||||
Mustache_tkn_itm actl_itm = new Mustache_tkn_parser().Parse(Bry_.new_u8(mustache));
|
||||
|
||||
// render
|
||||
Mustache_bfr bfr = new Mustache_bfr(Bry_bfr_.New());
|
||||
actl_itm.Render(bfr, new Mustache_render_ctx().Init(nde));
|
||||
|
||||
// test
|
||||
Gftest.Eq__ary__lines(expd, bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
@ -140,10 +140,14 @@ 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>
|
||||
</div>
|
||||
</nav>
|
||||
"]:>
|
||||
;
|
||||
div_ns =
|
||||
@ -178,7 +182,7 @@ app.wikis.get('~{wiki_key}').html.portal {
|
||||
<input type="search" name="search" placeholder="~{<>msgs.get('searchbutton');<>} ~{sitename}" id="searchInput"~{<>msgs.get_html_accesskey_and_title('search');<>} value="~{search_text}" autocomplete="off">
|
||||
<input type="hidden" name="fulltext" value="y">
|
||||
<input type="submit"~{<>msgs.get_html_accesskey_and_title('search');<>} id="mw-searchButton" class="searchButton mw-fallbackSearchButton" />
|
||||
<input type="submit" name="go" value="~{<>msgs.get('go');<>}" title="~{<>msgs.get('tooltip-search-go');<>}" id="searchButton" class="searchButton" />
|
||||
<input type="submit" name="go" value="~{<>msgs.get('go');<>}" title="~{<>msgs.get('tooltip-search-go');<>}" id="searchButton" class="searchButton" />
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
@ -195,8 +199,10 @@ app.wikis.get('~{wiki_key}').html.portal {
|
||||
;
|
||||
div_home =
|
||||
<:["
|
||||
<div class="portal" id='xowa-portal-home'>
|
||||
<h3>XOWA</h3>
|
||||
<nav id="xowa-portal-home" class="vector-menu vector-menu-portal portal" aria-labelledby="xowa-portal-home" role="navigation">
|
||||
<h3>
|
||||
<span>XOWA</span>
|
||||
</h3>
|
||||
<div class="body">
|
||||
<ul>
|
||||
<li><a href="/site/home/wiki/Main_Page" class='xowa-hover-off'>~{<>app.user.msgs.get('mainpage-description');<>}</a></li>
|
||||
@ -209,32 +215,36 @@ app.wikis.get('~{wiki_key}').html.portal {
|
||||
<li><a href="/site/home/wiki/Special:XowaCfg" class='xowa-hover-off'~{<>app.user.msgs.get_html_accesskey_and_title('xowa-portal-options');<>}>~{<>app.user.msgs.get('xowa-portal-options');<>}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
"]:>
|
||||
;
|
||||
div_sync =
|
||||
<:["
|
||||
<div id="xowa-portal-sync" class="portal">
|
||||
<h3>~{<>app.user.msgs.get('xowa-portal-sync');<>}</h3>
|
||||
<nav id="xowa-portal-sync" class="vector-menu vector-menu-portal portal" aria-labelledby="xowa-portal-sync" role="navigation">
|
||||
<h3>
|
||||
<span>~{<>app.user.msgs.get('xowa-portal-sync');<>}</span>
|
||||
</h3>
|
||||
<div class="body">
|
||||
<ul>
|
||||
<li><a href="/wiki/Special:XowaSyncHtml?page=~{page_url}" class='xowa-hover-off'~{<>app.user.msgs.get_html_accesskey_and_title('xowa-portal-sync_html');<>}>~{<>app.user.msgs.get('xowa-portal-sync_html');<>}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!--
|
||||
-->
|
||||
"]:>
|
||||
;
|
||||
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>
|
||||
"]:>
|
||||
;
|
||||
}
|
||||
@ -254,12 +264,12 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
<link rel="stylesheet" href="~{app_root_dir}bin/any/xowa/html/res/src/xowa/find/xowa_find_html.css" type="text/css">
|
||||
<script src="~{app_root_dir}bin/any/xowa/html/res/src/xowa/find/xowa_find_html.js" type='text/javascript'></script>
|
||||
<style type="text/css">
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #mw-searchButton {
|
||||
~{<>lang.x_axis_end;<>}: 0;
|
||||
direction: ~{<>lang.dir_str;<>};
|
||||
z-index:initial; /* reset z-index, else will show in front of popup; DATE:2015-07-31 */
|
||||
}
|
||||
}
|
||||
.new {!important; color:green;}
|
||||
</style>
|
||||
</head>
|
||||
@ -267,7 +277,7 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
<div id="mw-page-base" class="noprint"></div>
|
||||
<div id="mw-head-base" class="noprint"></div>
|
||||
<div id="content" class="mw-body">~{page_indicators}~{page_pgbnr}
|
||||
<div id='xowa_err_div' class='xowa_err' style='display:none; color:red; white-space:pre; display:block; unicode-bidi:embed;'></div>~{page_heading}
|
||||
<div id='xowa_err_div' class='xowa_err' style='display:none; color:red; white-space:pre; display:block; unicode-bidi:embed;'></div>~{page_heading}
|
||||
<div id="bodyContent" class="mw-body-content">
|
||||
<div id="siteSub">From XOWA: the free, open-source, offline wiki application</div>
|
||||
<div id="contentSub" class="visible">
|
||||
@ -321,7 +331,7 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
~{html_css_night_tag}<!--XOWA.SCRIPT.HEAD.TOP-->~{xowa_head}<!--XOWA.SCRIPT.HEAD.BOT-->
|
||||
<script src="~{app_root_dir}bin/any/xowa/html/res/src/xowa/edit-toolbar/edit-toolbar.js" type='text/javascript'></script>
|
||||
<style type="text/css">
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #mw-searchButton {
|
||||
~{<>lang.x_axis_end;<>}: 0;
|
||||
direction: ~{<>lang.dir_str;<>};
|
||||
@ -347,7 +357,7 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
<div id="mw-page-base" class="noprint"></div>
|
||||
<div id="mw-head-base" class="noprint"></div>
|
||||
<div id="content" class="mw-body">~{page_indicators}~{page_pgbnr}
|
||||
<div id='xowa_err_div' class='xowa_err'></div>~{page_heading}
|
||||
<div id='xowa_err_div' class='xowa_err'></div>~{page_heading}
|
||||
<div id="bodyContent" class="mw-body-content">
|
||||
<div id="siteSub">From XOWA: the free, open-source, offline wiki application</div>
|
||||
<div id="contentSub" class="visible">~{page_content_sub}</div>
|
||||
@ -362,7 +372,7 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
<a href="/wiki/Special:XowaPageDelete?delete=~{page_ttl_full}" onclick="return confirm('Please confirm you wish to delete this page.')" class="xowa_anchor_button" style="width:100px;max-width:1024px;">Delete page</a>
|
||||
<a href="/wiki/~{page_ttl_full}" class="xowa_anchor_button" style="width:100px;max-width:1024px;">~{<>msgs.get('cancel');<>}</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -407,7 +417,7 @@ app.wikis.get('~{wiki_key}').html.article {
|
||||
<link rel="stylesheet" href="~{html_css_wiki_path}" type="text/css">
|
||||
~{html_css_night_tag}<!--XOWA.SCRIPT.HEAD.TOP-->~{xowa_head}<!--XOWA.SCRIPT.HEAD.BOT-->
|
||||
<style type="text/css">
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #searchButton,
|
||||
div#simpleSearch #mw-searchButton {
|
||||
~{<>lang.x_axis_end;<>}: 0;
|
||||
direction: ~{<>lang.dir_str;<>};
|
||||
@ -472,9 +482,13 @@ 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>
|
||||
</div>
|
||||
<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