mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
TemplateStyles: Apply wrapper to each class, not to top only [#712]
This commit is contained in:
parent
ecbcf1e707
commit
a4b5f5de5d
@ -35,14 +35,12 @@ public class XoCssMin {
|
||||
public static final int
|
||||
MODE_NODEJS = 1
|
||||
, MODE_YCSS_MIN = 2
|
||||
, MODE_XOWA = 4
|
||||
, MODE_ALL = MODE_NODEJS | MODE_YCSS_MIN | MODE_XOWA
|
||||
, MODE_ALL = MODE_NODEJS | MODE_YCSS_MIN
|
||||
;
|
||||
public void DataCollectorMgr_(GfoDataCollectorMgr v) {this.dataCollectorMgr = v;} private GfoDataCollectorMgr dataCollectorMgr;
|
||||
public String cssmin(String css, int linebreakpos) {return cssmin(css, linebreakpos, MODE_ALL);}
|
||||
public String cssmin(String css, int linebreakpos, int mode) {
|
||||
boolean isModeYcssMin = Bitmask_.Has_int(mode, MODE_YCSS_MIN);
|
||||
boolean isModeXowa = Bitmask_.Has_int(mode, MODE_XOWA);
|
||||
|
||||
int startIndex = 0,
|
||||
endIndex = 0,
|
||||
@ -288,17 +286,6 @@ public class XoCssMin {
|
||||
// Trim the final string (for any leading or trailing white spaces)
|
||||
css = JsString_.replace(css, patterns, "^\\s+|\\s+$", "");
|
||||
|
||||
if (isModeXowa) {
|
||||
// add the '.mw-parser-output ' selector
|
||||
css = JsString_.replace(css, patterns, "\\}([^@}].{2})", "}.mw-parser-output $1");
|
||||
css = JsString_.replace(css, patterns, "(@media[^\\{]*\\{)", "$1.mw-parser-output ");
|
||||
if (css.charAt(0) != '@')
|
||||
css = ".mw-parser-output " + css;
|
||||
|
||||
// change some url(...) entries
|
||||
css = css.replace("//upload.wikimedia.org", "//www.xowa.org/xowa/fsys/bin/any/xowa/upload.wikimedia.org");
|
||||
}
|
||||
|
||||
return css;
|
||||
}
|
||||
private String _extractDataUrls(String css, List<String> preservedTokens) {
|
||||
|
@ -27,7 +27,6 @@ import gplx.xowa.htmls.heads.Xoh_head_itm__css_dynamic;
|
||||
import gplx.xowa.htmls.hxtns.blobs.Hxtn_blob_tbl;
|
||||
import gplx.xowa.htmls.hxtns.pages.Hxtn_page_mgr;
|
||||
import gplx.xowa.htmls.hxtns.wikis.Hxtn_wiki_itm;
|
||||
import gplx.xowa.htmls.minifys.XoCssMin;
|
||||
import gplx.xowa.parsers.Xop_ctx;
|
||||
import gplx.xowa.parsers.Xop_root_tkn;
|
||||
import gplx.xowa.parsers.htmls.Mwh_atr_itm;
|
||||
@ -40,17 +39,17 @@ import gplx.xowa.xtns.Xox_xnde;
|
||||
import gplx.xowa.xtns.Xox_xnde_;
|
||||
public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 {
|
||||
private byte[] css_ttl_bry;
|
||||
private byte[] wrapper;
|
||||
private byte[] css_src;
|
||||
private boolean css_ignore;
|
||||
private int css_page_id;
|
||||
private Xoa_ttl css_ttl;
|
||||
private static XoCssMin cssMin = new XoCssMin();
|
||||
private String prepend = ".mw-parser-output";
|
||||
|
||||
public void Xatr__set(Xowe_wiki wiki, byte[] src, Mwh_atr_itm xatr, byte xatr_id) {
|
||||
switch (xatr_id) {
|
||||
case Xatr__src: css_ttl_bry = xatr.Val_as_bry(); break;
|
||||
case Xatr__wrapper:
|
||||
wrapper = Bry_.Add(xatr.Val_as_bry(), Byte_ascii.Space); // add trailing space for html_head.format
|
||||
prepend = prepend + " " + xatr.Val_as_str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -104,7 +103,12 @@ public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 {
|
||||
if (!css_ignore) {
|
||||
Bry_bfr tmp_bfr = ctx.Wiki().Utl__bfr_mkr().Get_b512();
|
||||
try {
|
||||
html_head.Bld_many(tmp_bfr, css_page_id, wrapper, Bry_.new_u8(cssMin.cssmin(String_.new_u8(css_src), -1)) );
|
||||
css_src = new XoCssTransformer(String_.new_u8(css_src))
|
||||
.Minify()
|
||||
.Prepend(prepend)
|
||||
.Url("upload.wikimedia.org", "www.xowa.org/xowa/fsys/bin/any/xowa/upload.wikimedia.org")
|
||||
.ToBry();
|
||||
html_head.Bld_many(tmp_bfr, css_page_id, 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());
|
||||
@ -130,7 +134,7 @@ public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 {
|
||||
.Add_str_byte("wrapper", Xatr__wrapper)
|
||||
;
|
||||
private static final Bry_fmt
|
||||
html_head = Bry_fmt.Auto("\n/*TemplateStyles:r~{id}*/\n~{wrapper}~{css}")
|
||||
html_head = Bry_fmt.Auto("\n/*TemplateStyles:r~{id}*/\n~{css}")
|
||||
, html_error = Bry_fmt.Auto("<strong class=\"error\">~{msg}</strong>")
|
||||
;
|
||||
}
|
||||
|
@ -26,108 +26,124 @@ public class Template_styles_nde_tst {
|
||||
fxt.Reset();
|
||||
}
|
||||
@Test public void Implicit_template() { // PURPOSE: default to template
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Template:Test.css", css);
|
||||
fxt.Test__parse
|
||||
String css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Template:Test.css", css);
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Test.css'/>"
|
||||
, ""
|
||||
, fxt.Make__style(0, css)
|
||||
, fxt.Make_style(0, css)
|
||||
);
|
||||
}
|
||||
@Test public void Force_main() { // PURPOSE: ":" forces main
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Test.css", css);
|
||||
fxt.Test__parse
|
||||
String css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Test.css", css);
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src=':Test.css'/>"
|
||||
, ""
|
||||
, fxt.Make__style(0, css)
|
||||
, fxt.Make_style(0, css)
|
||||
);
|
||||
}
|
||||
@Test public void Explicit() { // PURPOSE: explicit ns
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Module:Test.css", css);
|
||||
fxt.Test__parse
|
||||
String css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Module:Test.css", css);
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Module:Test.css'/>"
|
||||
, ""
|
||||
, fxt.Make__style(0, css)
|
||||
, 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 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
|
||||
( "<templatestyles src='Module:Test1.css'/>"
|
||||
, "<templatestyles src='Module:Test2.css'/>"
|
||||
)
|
||||
, ""
|
||||
, fxt.Make__style(0, css_red)
|
||||
+ fxt.Make__style(1, css_blue)
|
||||
, 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 css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Module:Test.css", css);
|
||||
fxt.Test_parse
|
||||
( String_.Concat_lines_nl
|
||||
( "<templatestyles src='Module:Test.css'/>"
|
||||
, "<templatestyles src='Module:Test.css'/>"
|
||||
)
|
||||
, ""
|
||||
, String_.Concat_lines_nl
|
||||
( fxt.Make__style(0, css))
|
||||
( fxt.Make_style(0, css))
|
||||
);
|
||||
}
|
||||
@Test public void Tag() { // PURPOSE: {{#tag}}
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Module:A/Test.css", css);
|
||||
fxt.Test__parse
|
||||
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'}}"
|
||||
, ""
|
||||
, fxt.Make__style(0, css)
|
||||
, fxt.Make_style(0, css)
|
||||
);
|
||||
}
|
||||
@Test public void Fix_single_word_paragraph() { // PURPOSE:make sure block is closed, else single-word paragraphs; ISSUE#:616; DATE:2019-11-18
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Template:Test.css", css);
|
||||
String css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Template:Test.css", css);
|
||||
fxt.Parser_fxt().Init_para_y_();
|
||||
fxt.Test__parse
|
||||
fxt.Test_parse
|
||||
( String_.Concat_lines_nl_skip_last("<templatestyles src='Test.css'/>", "a")
|
||||
, String_.Concat_lines_nl_skip_last("", "<p>a", "</p>")
|
||||
, fxt.Make__style(0, css)
|
||||
, fxt.Make_style(0, css)
|
||||
);
|
||||
fxt.Parser_fxt().Init_para_n_();
|
||||
}
|
||||
@Test public void Error__invalid_title() {
|
||||
fxt.Test__parse
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='A|b.css'/>"
|
||||
, "<strong class=\"error\">Invalid title for TemplateStyles src attribute.</strong>"
|
||||
, ""
|
||||
);
|
||||
}
|
||||
@Test public void Error__missing_page() {
|
||||
fxt.Test__parse
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Missing.css'/>"
|
||||
, "<strong class=\"error\">Page Missing.css has no content.</strong>"
|
||||
, ""
|
||||
);
|
||||
}
|
||||
@Test public void Error__missing_src() {
|
||||
fxt.Test__parse
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src{{=}}'Missing.css'/>"// PAGE:en.w:Switzerland; ISSUE#:416; DATE:2019-03-31
|
||||
, "<strong class=\"error\">Invalid title for TemplateStyles src attribute.</strong>"
|
||||
, ""
|
||||
);
|
||||
}
|
||||
@Test public void Wrapper() {
|
||||
String css = fxt.Make__css_color("red");
|
||||
fxt.Init__page("Template:Test.css", css);
|
||||
fxt.Test__parse
|
||||
String css = fxt.Make_css_color("red");
|
||||
fxt.Init_page("Template:Test.css", css);
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Test.css' wrapper='.wrapper_class' />"
|
||||
, ""
|
||||
, fxt.Make__style(0, ".wrapper_class", css)
|
||||
, fxt.Make_style(0, ".wrapper_class", css)
|
||||
);
|
||||
}
|
||||
@Test public void Url() {
|
||||
fxt.Init_page("Template:Test.css", fxt.Make_css_url("//upload.wikimedia.org/A.png"));
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Test.css' />"
|
||||
, ""
|
||||
, fxt.Make_style(0, fxt.Make_css_url("//www.xowa.org/xowa/fsys/bin/any/xowa/upload.wikimedia.org/A.png"))
|
||||
);
|
||||
}
|
||||
@Test public void Minify() {
|
||||
fxt.Init_page("Template:Test.css", fxt.Make_css_color("rgb (128,128,128)"));
|
||||
fxt.Test_parse
|
||||
( "<templatestyles src='Test.css' />"
|
||||
, ""
|
||||
, fxt.Make_style(0, fxt.Make_css_color("#808080"))
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -138,18 +154,21 @@ class Template_styles_nde_fxt {
|
||||
parser_fxt.Reset();
|
||||
parser_fxt.Wiki().Xtn_mgr().Init_by_wiki(parser_fxt.Wiki());
|
||||
}
|
||||
public void Init__page(String page, String text) {
|
||||
public void Init_page(String page, String text) {
|
||||
parser_fxt.Init_page_create(page, text);
|
||||
}
|
||||
public String Make__css_color(String color) {
|
||||
public String Make_css_color(String color) {
|
||||
return ".style0{color:" + color + "}";
|
||||
}
|
||||
public String Make__style(int id, String css) {return Make__style(id, null, css);}
|
||||
public String Make__style(int id, String wrapper, String css) {
|
||||
wrapper = wrapper == null ? "" : wrapper + " ";
|
||||
return "\n/*TemplateStyles:r" + id + "*/\n" + wrapper + ".mw-parser-output " + css; // .mw-parser-output needs to be added to all TemplateStyles CSS, else TS ids called "portal" will affect sidebar; ISSUE#:426; PAGE:en.w:Poland DATE:2020-04-10
|
||||
public String Make_css_url(String url) {
|
||||
return ".style1{url(" + url + "}";
|
||||
}
|
||||
public void Test__parse(String src, String expd_html, String expd_head) {
|
||||
public String Make_style(int id, String css) {return Make_style(id, null, css);}
|
||||
public String Make_style(int id, String wrapper, String css) {
|
||||
wrapper = wrapper == null ? "" : wrapper + " ";
|
||||
return "\n/*TemplateStyles:r" + id + "*/\n" + ".mw-parser-output " + wrapper + css; // .mw-parser-output needs to be added to all TemplateStyles CSS, else TS ids called "portal" will affect sidebar; ISSUE#:426; PAGE:en.w:Poland DATE:2020-04-10
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package gplx.xowa.xtns.template_styles;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.langs.javascripts.JsString_;
|
||||
import gplx.xowa.htmls.minifys.XoCssMin;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class XoCssTransformer {
|
||||
private final static ConcurrentHashMap<String, Pattern> patterns = new ConcurrentHashMap<>();
|
||||
private String css;
|
||||
public XoCssTransformer(String css) {
|
||||
this.css = css;
|
||||
}
|
||||
|
||||
public XoCssTransformer Minify() {
|
||||
XoCssMin minifier = new XoCssMin();
|
||||
this.css = minifier.cssmin(css, -1);
|
||||
return this;
|
||||
}
|
||||
public XoCssTransformer Prepend(String prepend) {
|
||||
// prepend any classes to all declarations; primarily for '.mw-parser-output ' selector
|
||||
css = JsString_.replace(css, patterns, "\\}([^@}].{2})", "} " + prepend + " $1");
|
||||
css = JsString_.replace(css, patterns, "(@media[^\\{]*\\{)", "$1" + prepend + " ");
|
||||
if (css.charAt(0) != '@')
|
||||
css = prepend + " " + css;
|
||||
return this;
|
||||
}
|
||||
public XoCssTransformer Url(String src, String trg) {
|
||||
// change some url(...) entries
|
||||
css = css.replace("//" + src, "//" + trg);
|
||||
return this;
|
||||
}
|
||||
public byte[] ToBry() {return Bry_.new_u8(css);}
|
||||
public String ToStr() {return css;}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package gplx.xowa.xtns.template_styles;
|
||||
|
||||
import gplx.core.tests.Gftest;
|
||||
import org.junit.Test;
|
||||
|
||||
public class XoCssTransformerTest {
|
||||
private final XoCssTranformerTstr tstr = new XoCssTranformerTstr();
|
||||
|
||||
@Test
|
||||
public void Minify() {
|
||||
tstr.Test_Minify("basic" ,"rgb (128,128,128)", "#808080");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Prepend() {
|
||||
tstr.Test_Prepend("cls.1.1" ,"x {}" , ".a" , ".a x {}");
|
||||
tstr.Test_Prepend("cls.n.1" ,"x {}y {}", ".a" , ".a x {} .a y {}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Url() {
|
||||
tstr.Test_Url("match.y" , "url(//site/a.png)", "site", "prepend/site", "url(//prepend/site/a.png)");
|
||||
tstr.Test_Url("match.y.any", "//site/abc" , "site", "prepend/site", "//prepend/site/abc"); // NOTE: matches any "//"
|
||||
tstr.Test_Url("match.n" , "url(/-site/a.png)", "site", "prepend/site", "url(/-site/a.png)");
|
||||
}
|
||||
}
|
||||
class XoCssTranformerTstr {
|
||||
public void Test_Url(String note, String css, String src, String trg, String expd) {
|
||||
XoCssTransformer transformer = new XoCssTransformer(css);
|
||||
String actl = transformer.Url(src, trg).ToStr();
|
||||
Gftest.Eq__str(expd, actl, note);
|
||||
}
|
||||
public void Test_Prepend(String note, String css, String prepend, String expd) {
|
||||
XoCssTransformer transformer = new XoCssTransformer(css);
|
||||
String actl = transformer.Prepend(prepend).ToStr();
|
||||
Gftest.Eq__str(expd, actl, note);
|
||||
}
|
||||
public void Test_Minify(String note, String css, String expd) {
|
||||
XoCssTransformer transformer = new XoCssTransformer(css);
|
||||
String actl = transformer.Minify().ToStr();
|
||||
Gftest.Eq__str(expd, actl, note);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user