diff --git a/400_xowa/src/gplx/xowa/Xoae_page.java b/400_xowa/src/gplx/xowa/Xoae_page.java index 806a17439..67a4ee1e1 100644 --- a/400_xowa/src/gplx/xowa/Xoae_page.java +++ b/400_xowa/src/gplx/xowa/Xoae_page.java @@ -17,6 +17,7 @@ package gplx.xowa; import gplx.*; import gplx.xowa.langs.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.guis.*; import gplx.xowa.guis.views.*; import gplx.xowa.files.*; import gplx.xowa.files.xfers.*; +import gplx.xowa.apps.kvs.*; import gplx.xowa.parsers.*; import gplx.xowa.wikis.pages.lnkis.*; import gplx.xowa.xtns.cites.*; import gplx.xowa.xtns.wbases.*; import gplx.xowa.xtns.wbases.pfuncs.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.*; import gplx.xowa.addons.htmls.tocs.*; import gplx.xowa.htmls.modules.popups.*; import gplx.xowa.wikis.pages.wtxts.*; import gplx.xowa.wikis.pages.dbs.*; import gplx.xowa.wikis.pages.redirects.*; import gplx.xowa.wikis.pages.hdumps.*; import gplx.xowa.wikis.pages.htmls.*; @@ -47,6 +48,7 @@ public class Xoae_page implements Xoa_page { public void Xtn_gallery_packed_exists_y_() {html.Xtn_gallery_packed_exists_y_();} public boolean Xtn__timeline_exists() {return false;} // drd always sets timeline public boolean Xtn__gallery_exists() {return false;} // drd does not need to set gallery.style.css + public Xoa_kv_hash Kv_data() {return kv_data;} private final Xoa_kv_hash kv_data = new Xoa_kv_hash(); private Guid_adp page_guid; public Guid_adp Page_guid() { if (page_guid == null) { @@ -80,6 +82,7 @@ public class Xoae_page implements Xoa_page { html.Clear(); hdump.Clear(); wtxt.Clear(); + kv_data.Clear(); lnki_list.Clear(); file_math.Clear(); diff --git a/400_xowa/src/gplx/xowa/Xop_fxt.java b/400_xowa/src/gplx/xowa/Xop_fxt.java index b53b4b5de..ba33a5e4e 100644 --- a/400_xowa/src/gplx/xowa/Xop_fxt.java +++ b/400_xowa/src/gplx/xowa/Xop_fxt.java @@ -65,6 +65,7 @@ public class Xop_fxt { ctx.Page().Clear_all(); wiki.File_mgr().Clear_for_tests(); wiki.Db_mgr().Load_mgr().Clear(); + wiki.Db_mgr().Save_mgr().Clear(); app.Wiki_mgr().Clear(); Io_mgr.Instance.InitEngine_mem(); // clear created pages wiki.Cfg_parser().Display_title_restrict_(false); // default to false, as a small number of tests assume restrict = false; diff --git a/400_xowa/src/gplx/xowa/addons/bldrs/mass_parses/parses/utls/Xomp_tmpl_cache_bldr.java b/400_xowa/src/gplx/xowa/addons/bldrs/mass_parses/parses/utls/Xomp_tmpl_cache_bldr.java index 9a408d825..2cfe3eaeb 100644 --- a/400_xowa/src/gplx/xowa/addons/bldrs/mass_parses/parses/utls/Xomp_tmpl_cache_bldr.java +++ b/400_xowa/src/gplx/xowa/addons/bldrs/mass_parses/parses/utls/Xomp_tmpl_cache_bldr.java @@ -48,8 +48,8 @@ public class Xomp_tmpl_cache_bldr { // add to text_db_loader int page_id = rdr.Read_int("page_id"); int page_redirect_id = rdr.Read_int("page_redirect_id"); - Xow_page_cache_itm itm = new Xow_page_cache_itm(true, page_ttl, null, null); // NOTE: "null, null;" b/c GetContent in Scrib_title checks specifically for null, not empty String; DATE:2016-10-19 - itm.Set_page_ids(page_id, page_redirect_id); + Xow_page_cache_itm itm = new Xow_page_cache_itm(true, page_id, page_ttl, null, null); // NOTE: "null, null;" b/c GetContent in Scrib_title checks specifically for null, not empty String; DATE:2016-10-19 + itm.Redirect_id_(page_redirect_id); text_db_loader.Add(rdr.Read_int("page_text_db_id"), itm); // ignore duplicate page_titles in cache; EX:ru.n:Модуль:Weather/data DATE:2017-03-16 diff --git a/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_hash.java b/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_hash.java new file mode 100644 index 000000000..5d6c29d7c --- /dev/null +++ b/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_hash.java @@ -0,0 +1,31 @@ +/* +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.apps.kvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; +public class Xoa_kv_hash { + private final Hash_adp hash = Hash_adp_.New(); + public Object Get_or_make(Xoa_kv_itm itm) { + String key = itm.Kv__key(); + Object val = hash.Get_by(key); + if (val == null) { + val = itm.Kv__val_make(); + hash.Add(key, val); + } + return val; + } + public void Clear() { + hash.Clear(); + } +} diff --git a/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_itm.java b/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_itm.java new file mode 100644 index 000000000..c764edfcd --- /dev/null +++ b/400_xowa/src/gplx/xowa/apps/kvs/Xoa_kv_itm.java @@ -0,0 +1,20 @@ +/* +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.apps.kvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; +public interface Xoa_kv_itm { + String Kv__key(); + Object Kv__val_make(); +} diff --git a/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java b/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java index 5be115b50..6b39451a0 100644 --- a/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java +++ b/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java @@ -48,19 +48,11 @@ public class Xoh_page_wtr_wkr { } Bry_bfr page_bfr = wiki.Utl__bfr_mkr().Get_m001(); // NOTE: get separate page rv to output page; do not reuse tmp_bfr b/c it will be used inside Fmt_do Xoh_wtr_ctx hctx = null; - if (page_mode == Xopg_page_.Tid_html && wiki.Html__hdump_mgr().Load_mgr().Html_mode().Tid_is_custom()) { - byte[] html_bry = null; - - // get html from html dump - if (wiki.Html__hdump_mgr().Load_mgr().Html_mode().Tid() == Xow_hdump_mode.Hdump_save.Tid()) { - hctx = Xoh_wtr_ctx.Hdump; - Write_body(page_bfr, ctx, hctx, page); - html_bry = page_bfr.To_bry_and_clear(); - } - // get from swt browser - else { - html_bry = page_html_source.Get_page_html(); - } + if (page_mode == Xopg_page_.Tid_html + && wiki.Html__hdump_mgr().Load_mgr().Html_mode().Tid() == Xow_hdump_mode.Hdump_save.Tid()) { + hctx = Xoh_wtr_ctx.Hdump; + Write_body(page_bfr, ctx, hctx, page); + byte[] html_bry = page_bfr.To_bry_and_clear(); Write_page_by_tid(ctx, hctx, page_mode, rv, mgr.Page_html_fmtr(), Gfh_utl.Escape_html_as_bry(html_bry)); } else { diff --git a/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr.java b/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr.java index 13d61e9ce..ee5c21cc4 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr.java +++ b/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr.java @@ -59,7 +59,7 @@ public class Xow_tidy_mgr implements Gfo_invk, Xow_tidy_mgr_interface { find = Bry_find_.Find_bwd(bfr_bry, Gfh_tag_.Body_rhs, bfr.Len()); if (find == Bry_find_.Not_found) return false; bfr.Delete_rng_to_end(find); return true; - } + } private static final byte[] // MW:includes/parser/Tidy.php|getWrapped Wrap_bgn = Bry_.new_a7 ( "" diff --git a/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xoh_tidy_mgr_tst.java b/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr_tst.java similarity index 83% rename from 400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xoh_tidy_mgr_tst.java rename to 400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr_tst.java index dd19390c5..000e4a8c1 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xoh_tidy_mgr_tst.java +++ b/400_xowa/src/gplx/xowa/htmls/core/htmls/tidy/Xow_tidy_mgr_tst.java @@ -15,10 +15,10 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.xowa.htmls.core.htmls.tidy; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.core.htmls.*; import org.junit.*; -public class Xoh_tidy_mgr_tst { - @Before public void init() {fxt.Clear();} private Xoh_tidy_mgr_fxt fxt = new Xoh_tidy_mgr_fxt(); +public class Xow_tidy_mgr_tst { + @Before public void init() {fxt.Clear();} private final Xoh_tidy_mgr_fxt fxt = new Xoh_tidy_mgr_fxt(); @Test public void Wrap() { - fxt.Test_wrap("a" + fxt.Test__wrap("a" , "" + "" + "" @@ -30,7 +30,7 @@ public class Xoh_tidy_mgr_tst { ); } @Test public void Unwrap_pass() { - fxt.Test_unwrap + fxt.Test__unwrap ( "" + "" + "" @@ -43,7 +43,7 @@ public class Xoh_tidy_mgr_tst { ); } @Test public void Unwrap_fail_bgn() { - fxt.Test_unwrap + fxt.Test__unwrap ( "" + "" + "" @@ -56,7 +56,7 @@ public class Xoh_tidy_mgr_tst { ); } @Test public void Unwrap_fail_end() { - fxt.Test_unwrap + fxt.Test__unwrap ( "" + "" + "" @@ -70,16 +70,16 @@ public class Xoh_tidy_mgr_tst { } } class Xoh_tidy_mgr_fxt { - private Bry_bfr bfr = Bry_bfr_.Reset(255); + private final Bry_bfr bfr = Bry_bfr_.Reset(255); public void Clear() { bfr.Clear(); } - public void Test_wrap(String val, String expd) { + public void Test__wrap(String val, String expd) { bfr.Add_str_u8(val); Xow_tidy_mgr.Tidy_wrap(bfr); Tfds.Eq(expd, bfr.To_str_and_clear()); } - public void Test_unwrap(String val, boolean expd_pass, String expd) { + public void Test__unwrap(String val, boolean expd_pass, String expd) { bfr.Add_str_u8(val); boolean actl_pass = Xow_tidy_mgr.Tidy_unwrap(bfr); if (actl_pass != expd_pass) Tfds.Fail("expd={0} actl={1}", expd_pass, actl_pass); diff --git a/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm_.java b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm_.java index 2df6b93cb..5e66dca2a 100644 --- a/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm_.java +++ b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm_.java @@ -38,5 +38,6 @@ public class Xoh_head_itm_ { , Key__tabber = Bry_.new_a7("tabber") , Key__xo_elem = Bry_.new_a7("xo.elem") , Key__page_cfg = Bry_.new_a7("page_cfg") + , Key__css_dynamic = Bry_.new_a7("css_dynamic") ; } diff --git a/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm__css_dynamic.java b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm__css_dynamic.java new file mode 100644 index 000000000..0a3c4631f --- /dev/null +++ b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_itm__css_dynamic.java @@ -0,0 +1,28 @@ +/* +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.htmls.heads; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; +import gplx.xowa.guis.*; +import gplx.xowa.apps.apis.xowa.html.modules.*; +public class Xoh_head_itm__css_dynamic extends Xoh_head_itm__base { + private final Bry_bfr bfr = Bry_bfr_.New(); + @Override public byte[] Key() {return Xoh_head_itm_.Key__css_dynamic;} + @Override public int Flags() {return Flag__css_text;} + public byte[] Get_and_clear() {return bfr.To_bry_and_clear();} // TEST: + public void Add(byte[] v) {bfr.Add(v);} + @Override public void Write_css_text(Xoae_app app, Xowe_wiki wiki, Xoae_page page, Xoh_head_wtr wtr) { + wtr.Write(bfr.To_bry_and_clear()); + } +} diff --git a/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_mgr.java b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_mgr.java index 1e2514a06..5920d7272 100644 --- a/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_mgr.java +++ b/400_xowa/src/gplx/xowa/htmls/heads/Xoh_head_mgr.java @@ -32,7 +32,7 @@ public class Xoh_head_mgr implements gplx.core.brys.Bfr_arg { public Xoh_head_mgr() { Itms_add(itm__css, itm__globals, itm__xo_elem, itm__server, itm__popups, itm__toc, itm__collapsible, itm__navframe, itm__gallery, itm__gallery_styles , itm__mathjax, itm__graph, itm__hiero, itm__top_icon, itm__title_rewrite, itm__search_suggest, itm__timeline - , itm__dbui, itm__pgbnr, itm__tabber, itm__page_cfg + , itm__dbui, itm__pgbnr, itm__tabber, itm__page_cfg, itm__css_dynamic ); } public Xoh_head_itm__css Itm__css() {return itm__css;} private final Xoh_head_itm__css itm__css = new Xoh_head_itm__css(); @@ -56,6 +56,7 @@ public class Xoh_head_mgr implements gplx.core.brys.Bfr_arg { public Xoh_head_itm__pgbnr Itm__pgbnr() {return itm__pgbnr;} private final Xoh_head_itm__pgbnr itm__pgbnr = new Xoh_head_itm__pgbnr(); public Xoh_head_itm__tabber Itm__tabber() {return itm__tabber;} private final Xoh_head_itm__tabber itm__tabber = new Xoh_head_itm__tabber(); public Xoh_head_itm__page_cfg Itm__page_cfg() {return itm__page_cfg;} private final Xoh_head_itm__page_cfg itm__page_cfg = new Xoh_head_itm__page_cfg(); + public Xoh_head_itm__css_dynamic Itm__css_dynamic() {return itm__css_dynamic;} private final Xoh_head_itm__css_dynamic itm__css_dynamic = new Xoh_head_itm__css_dynamic(); public Xoh_head_mgr Init(Xoae_app app, Xowe_wiki wiki, Xoae_page page) { this.app = app; this.wiki = wiki; this.page = page; return this; diff --git a/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache.java b/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache.java index 0f95b8569..9365f650a 100644 --- a/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache.java +++ b/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache.java @@ -56,6 +56,7 @@ public class Xow_page_cache { boolean page_exists = false; byte[] page_text = null; byte[] page_redirect_from = null; + int page_id = -1; // gplx.core.consoles.Console_adp__sys.Instance.Write_str("page_cache:" + String_.new_u8(ttl_full_db)); if (load_wkr != null) { page_text = load_wkr.Get_page_or_null(ttl_full_db); @@ -67,9 +68,10 @@ public class Xow_page_cache { page_text = page.Db().Text().Text_bry(); page_exists = page.Db().Page().Exists(); page_redirect_from = page.Redirect_trail().Itms__get_wtxt_at_0th_or_null(); + page_id = page.Db().Page().Id(); } if (page_exists) { - rv = new Xow_page_cache_itm(false, page_ttl, page_text, page_redirect_from); + rv = new Xow_page_cache_itm(false, page_id, page_ttl, page_text, page_redirect_from); Add_safe(ttl_full_db, rv); } else { @@ -86,7 +88,7 @@ public class Xow_page_cache { Xoae_page page = wiki.Data_mgr().Load_page_by_ttl(ttl); // NOTE: do not call Db_mgr.Load_page; need to handle redirects if ( page.Db().Page().Exists() // page exists || page.Redirect_trail().Itms__len() > 0 ) { // page redirects to missing page; note that page.Missing == true and page.Redirected_src() != null; PAGE: en.w:Shah_Rukh_Khan; DATE:2016-05-02 - rv = new Xow_page_cache_itm(false, page.Ttl(), page.Db().Text().Text_bry(), page.Redirect_trail().Itms__get_wtxt_at_0th_or_null()); + rv = new Xow_page_cache_itm(false, page.Db().Page().Id(), page.Ttl(), page.Db().Text().Text_bry(), page.Redirect_trail().Itms__get_wtxt_at_0th_or_null()); Add_safe(ttl_full_db, rv); } else { diff --git a/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache_itm.java b/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache_itm.java index b893b2a15..525feaa13 100644 --- a/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache_itm.java +++ b/400_xowa/src/gplx/xowa/wikis/caches/Xow_page_cache_itm.java @@ -16,9 +16,9 @@ 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.xowa.wikis.data.tbls.*; public class Xow_page_cache_itm implements Xowd_text_bry_owner { - public Xow_page_cache_itm(boolean cache_permanently, Xoa_ttl ttl, byte[] wtxt__direct, byte[] wtxt__redirect) { + public Xow_page_cache_itm(boolean cache_permanently, int page_id, Xoa_ttl ttl, byte[] wtxt__direct, byte[] wtxt__redirect) { this.cache_permanently = cache_permanently; - this.ttl = ttl; this.wtxt__direct = wtxt__direct; this.wtxt__redirect = wtxt__redirect; + this.page_id = page_id; this.ttl = ttl; this.wtxt__direct = wtxt__direct; this.wtxt__redirect = wtxt__redirect; } public Xoa_ttl Ttl() {return ttl;} private Xoa_ttl ttl; public byte[] Wtxt__direct() {return wtxt__direct;} private byte[] wtxt__direct; @@ -32,7 +32,7 @@ public class Xow_page_cache_itm implements Xowd_text_bry_owner { public int Page_id() {return page_id;} private int page_id; public int Redirect_id() {return redirect_id;} private int redirect_id; public void Set_text_bry_by_db(byte[] v) {this.wtxt__direct = v;} - public void Set_page_ids(int page_id, int redirect_id) {this.page_id = page_id; this.redirect_id = redirect_id;} + public void Redirect_id_(int v) {this.redirect_id = v;} public void Set_redirect(Xoa_ttl ttl, byte[] trg_wtxt) { this.ttl = ttl; this.wtxt__redirect = wtxt__direct; @@ -40,5 +40,5 @@ public class Xow_page_cache_itm implements Xowd_text_bry_owner { } public static final Xow_page_cache_itm Null = null; - public static final Xow_page_cache_itm Missing = new Xow_page_cache_itm(false, null, null, null); + public static final Xow_page_cache_itm Missing = new Xow_page_cache_itm(false, -1, null, null, null); } diff --git a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java index d7cc8f466..9a20d9db6 100644 --- a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java +++ b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java @@ -14,13 +14,16 @@ 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.template_styles; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; +import gplx.core.primitives.*; import gplx.xowa.wikis.caches.*; -import gplx.xowa.htmls.core.htmls.*; import gplx.xowa.parsers.htmls.*; +import gplx.xowa.htmls.core.htmls.*; import gplx.xowa.parsers.htmls.*; import gplx.xowa.htmls.heads.*; import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.wikis.nss.*; public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 { private byte[] css_ttl_bry; private byte[] css_src; + private boolean css_ignore; + private Int_obj_val css_page_id; private Xoa_ttl css_ttl; public void Xatr__set(Xowe_wiki wiki, byte[] src, Mwh_atr_itm xatr, byte xatr_id) { switch (xatr_id) { @@ -45,31 +48,60 @@ public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 { // get page Xow_page_cache_itm page_itm = wiki.Cache_mgr().Page_cache().Get_or_load_as_itm_2(css_ttl); - css_src = page_itm == null ? null : page_itm.Wtxt__direct(); + if (page_itm != null) { + css_src = page_itm.Wtxt__direct(); + css_page_id = new Int_obj_val(page_itm.Page_id()); + + // update css_page_ids + Hash_adp css_page_ids = (Hash_adp)ctx.Page().Kv_data().Get_or_make(Template_styles_kv_itm.Instance); + if (css_page_ids.Has(css_page_id)) { + css_ignore = true; + } + else { + css_page_ids.Add_as_key_and_val(css_page_id); + } + + } if (css_src == null) { Gfo_usr_dlg_.Instance.Warn_many("", "", "Template_styles_nde.page_not_found: wiki=~{0} page=~{1} css_ttl=~{2}", wiki.Domain_bry(), ctx.Page().Url_bry_safe(), css_ttl_bry); - } + } + } public void Xtn_write(Bry_bfr bfr, Xoae_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xoae_page wpg, Xop_xnde_tkn xnde, byte[] src) { if (css_ttl == null) { bfr.Add_str_a7(formatTagError("Invalid title for TemplateStyles src attribute.")); + return; } - else if (css_src == null) { + if (css_src == null) { bfr.Add_str_a7(formatTagError("Page " + String_.new_u8(css_ttl_bry) + " has no content.")); + return; } - else { - bfr.Add_str_a7(""); + + if (!css_ignore) { + Bry_bfr tmp_bfr = ctx.Wiki().Utl__bfr_mkr().Get_b512(); + try { + html_head.Bld_many(tmp_bfr, css_page_id.Val(), css_src); + Xoh_head_itm__css_dynamic css_dynamic = ctx.Page().Html_data().Head_mgr().Itm__css_dynamic(); + css_dynamic.Enabled_y_(); + css_dynamic.Add(tmp_bfr.To_bry_and_clear()); + } finally {tmp_bfr.Mkr_rls();} } } private static String formatTagError(String msg) { // $parser->addTrackingCategory( 'templatestyles-page-error-category' ); - return "" - // + call_user_func_array( 'wfMessage', $msg )->inContentLanguage()->parse() - + msg - + ""; + // + call_user_func_array( 'wfMessage', $msg )->inContentLanguage()->parse() + return html_error.Bld_many_to_str_auto_bfr(msg); } + public static final byte Xatr__src = 0; private static final Hash_adp_bry xatrs_hash = Hash_adp_bry.ci_a7().Add_str_byte("src", Xatr__src); + private static final Bry_fmt + html_head = Bry_fmt.Auto("\n/*TemplateStyles:r~{id}*/\n~{css}") + , html_error = Bry_fmt.Auto("~{msg}") + ; +} +class Template_styles_kv_itm implements gplx.xowa.apps.kvs.Xoa_kv_itm { + public String Kv__key() {return "TemplateStyles";} + public Object Kv__val_make() {return Hash_adp_.New();} + public static final Template_styles_kv_itm Instance = new Template_styles_kv_itm(); Template_styles_kv_itm() {} } diff --git a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java index b0e4b3a48..75e656d5b 100644 --- a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java +++ b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java @@ -14,52 +14,88 @@ 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.template_styles; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; -import org.junit.*; +import org.junit.*; import gplx.core.tests.*; public class Template_styles_nde_tst { private final Template_styles_nde_fxt fxt = new Template_styles_nde_fxt(); @Before public void init() { fxt.Reset(); } - private static final String Css_red = ".red{color:red;}"; - private static final String Style_red = ""; @Test public void Implicit_template() { // PURPOSE: default to template - fxt.Init__page("Template:Test.css", Css_red); + String css = fxt.Make__css_color("red"); + fxt.Init__page("Template:Test.css", css); fxt.Test__parse ( "" - , Style_red + , "" + , fxt.Make__style(0, css) ); } @Test public void Force_main() { // PURPOSE: ":" forces main - fxt.Init__page("Test.css", Css_red); + String css = fxt.Make__css_color("red"); + fxt.Init__page("Test.css", css); fxt.Test__parse ( "" - , Style_red + , "" + , fxt.Make__style(0, css) ); } @Test public void Explicit() { // PURPOSE: explicit ns - fxt.Init__page("Module:Test.css", Css_red); + String css = fxt.Make__css_color("red"); + fxt.Init__page("Module:Test.css", css); fxt.Test__parse ( "" - , Style_red + , "" + , fxt.Make__style(0, css) + ); + } + @Test public void Multiple() { // PURPOSE: multiple calls to diff page should output diff styles; DATE:2018-12-30 + String css_red = fxt.Make__css_color("red"); + String css_blue = fxt.Make__css_color("blue"); + fxt.Init__page("Module:Test1.css", css_red); + fxt.Init__page("Module:Test2.css", css_blue); + fxt.Test__parse + ( String_.Concat_lines_nl + ( "" + , "" + ) + , "" + , fxt.Make__style(0, css_red) + + fxt.Make__style(1, css_blue) + ); + } + @Test public void Dedupe() { // PURPOSE: multiple calls to same page should output link; DATE:2018-12-30 + String css = fxt.Make__css_color("red"); + fxt.Init__page("Module:Test.css", css); + fxt.Test__parse + ( String_.Concat_lines_nl + ( "" + , "" + ) + , "" + , String_.Concat_lines_nl + ( fxt.Make__style(0, css)) ); } @Test public void Tag() { // PURPOSE: {{#tag}} - fxt.Init__page("Module:A/Test.css", Css_red); + String css = fxt.Make__css_color("red"); + fxt.Init__page("Module:A/Test.css", css); fxt.Test__parse ( "{{#tag:templatestyles||src='Module:A/Test.css'}}" - , Style_red + , "" + , fxt.Make__style(0, css) ); } @Test public void Error__invalid_title() { fxt.Test__parse ( "" , "Invalid title for TemplateStyles src attribute." + , "" ); } @Test public void Error__missing_page() { fxt.Test__parse ( "" , "Page Missing.css has no content." + , "" ); } } @@ -72,7 +108,14 @@ class Template_styles_nde_fxt { public void Init__page(String page, String text) { parser_fxt.Init_page_create(page, text); } - public void Test__parse(String src, String expd) { - parser_fxt.Test__parse__tmpl_to_html(src, expd); + public String Make__css_color(String color) { + return ".style0{color:" + color + ";}"; + } + public String Make__style(int id, String css) { + return "\n/*TemplateStyles:r" + id + "*/\n" + css; + } + public void Test__parse(String src, String expd_html, String expd_head) { + parser_fxt.Test__parse__tmpl_to_html(src, expd_html); + Gftest.Eq__ary__lines(expd_head, parser_fxt.Page().Html_data().Head_mgr().Itm__css_dynamic().Get_and_clear()); } }