From 49e18a2255246056232b04e73375eb13c22a114f Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Tue, 9 Jun 2020 08:38:26 -0400 Subject: [PATCH] Css: Prepend '.mw-parser-output' to all nested classes [#741] --- .../template_styles/XoCssTransformer.java | 76 +++++++++++++++++-- .../template_styles/XoCssTransformerTest.java | 36 +++++++-- 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/400_xowa/src/gplx/xowa/xtns/template_styles/XoCssTransformer.java b/400_xowa/src/gplx/xowa/xtns/template_styles/XoCssTransformer.java index 952a07c99..4e3054879 100644 --- a/400_xowa/src/gplx/xowa/xtns/template_styles/XoCssTransformer.java +++ b/400_xowa/src/gplx/xowa/xtns/template_styles/XoCssTransformer.java @@ -1,10 +1,13 @@ package gplx.xowa.xtns.template_styles; import gplx.Bry_; +import gplx.String_; import gplx.langs.javascripts.JsString_; +import gplx.langs.javascripts.util.regex.JsPattern_; import gplx.xowa.htmls.minifys.XoCssMin; import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; import java.util.regex.Pattern; public class XoCssTransformer { @@ -19,19 +22,76 @@ public class XoCssTransformer { 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 XoCssTransformer Prepend(String selector) { + // prepend any classes to all declarations; primarily for '.mw-parser-output ' selector + // regex means match anything before `{` which is not `}{` + css = PrependSelector(css, "([^\\}\\{]*)\\{", selector); + return this; + } public byte[] ToBry() {return Bry_.new_u8(css);} public String ToStr() {return css;} + + private String PrependSelector(String orig, String regx, String selector) { + // init regex + Pattern pattern = JsPattern_.getOrCompile(patterns, regx); + Matcher matcher = pattern.matcher(orig); + + // init temp variables for replacements + StringBuffer sb = null; + int previous = 0; + + // find "match" which is everything before `{` + while (matcher.find()) { + // lazy-instantiate buffer + if (sb == null) sb = new StringBuffer(); + + // add everything between previousPosition and match.start + sb.append(orig, previous, matcher.start(1)); + + // get match, as well as trimmed version; need `.Trim()` to check for things like "\s@media" + String match = matcher.group(1); + String matchTrimmed = match.trim(); + if (matchTrimmed.length() > 0) { // should not happen b/c CSS shouldn't have "empty" class (`}{}`) but check anyway b/c of `match.charAt(0)` + if (matchTrimmed.charAt(0) != '@') { // ignore any css conditional group rules (`@`) rules like @media, @supports, etc + // split match by nested class selectors; EX: "a,b" -> ["a", "b"] + String[] items = match.split(","); + for (int i = 0; i < items.length; i++) { + // put `,` back between items, unless it's the first + if (i > 0) + sb.append(","); + + // prepend the selector + sb.append(selector); + + // for pretty-printing, only add `\s` if item doesn't start with space + String item = items[i]; + if (item.length() > 0 && !Character.isWhitespace(item.charAt(0))) { + sb.append(' '); + } + + // put back the item + sb.append(item); + } + } + else { + // EX: `@media` + sb.append(match); + } + } + previous = matcher.end(1); + } + + // finish generating string, or return orig + if (sb != null) { + sb.append(orig, previous, orig.length()); + return sb.toString(); + } + else + return orig; + } } diff --git a/400_xowa/tst/gplx/xowa/xtns/template_styles/XoCssTransformerTest.java b/400_xowa/tst/gplx/xowa/xtns/template_styles/XoCssTransformerTest.java index 63670fe8b..221f7779b 100644 --- a/400_xowa/tst/gplx/xowa/xtns/template_styles/XoCssTransformerTest.java +++ b/400_xowa/tst/gplx/xowa/xtns/template_styles/XoCssTransformerTest.java @@ -12,9 +12,33 @@ public class XoCssTransformerTest { } @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 {}"); + public void PrependBasic() { + tstr.Test_Prepend("x {}", "a", "a x {}"); + } + + @Test + public void PrependManyClasses() { + tstr.Test_Prepend("x,y,z {}", "a", "a x,a y,a z {}"); + } + + @Test + public void PrependManyNodes() { + tstr.Test_Prepend("x {} y {} z {}", "a", "a x {}a y {}a z {}"); + } + + @Test + public void PrependEmpty() { + tstr.Test_Prepend("x {}{}", "a", "a x {}{}"); + } + + @Test + public void PrependMediaAtBos() { + tstr.Test_Prepend("@media {} x {}", "a", "@media {}a x {}"); + } + + @Test + public void PrependMediaAtMid() { + tstr.Test_Prepend("x {} @media {} y {}", "a", "a x {} @media {}a y {}"); } @Test @@ -30,10 +54,10 @@ class XoCssTranformerTstr { 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) { + public void Test_Prepend(String css, String selector, String expd) { XoCssTransformer transformer = new XoCssTransformer(css); - String actl = transformer.Prepend(prepend).ToStr(); - Gftest.Eq__str(expd, actl, note); + String actl = transformer.Prepend(selector).ToStr(); + Gftest.Eq__str(expd, actl); } public void Test_Minify(String note, String css, String expd) { XoCssTransformer transformer = new XoCssTransformer(css);