diff --git a/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java b/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java index 4cd780a4a..287097221 100644 --- a/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java +++ b/400_xowa/src/gplx/xowa/files/Xof_file_wkr__tst.java @@ -18,7 +18,7 @@ along with this program. If not, see . package gplx.xowa.files; import gplx.*; import gplx.xowa.*; import org.junit.*; public class Xof_file_wkr__tst { - private final Xof_file_wkr___fxt fxt = new Xof_file_wkr___fxt(); + private final Xof_file_wkr___fxt fxt = new Xof_file_wkr___fxt(); @Test public void Ttl_standardize() { fxt.Test__ttl_standardize("Abc.png" , "Abc.png"); // basic fxt.Test__ttl_standardize("A b.png" , "A_b.png"); // spaces -> unders diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java index c998234fd..ecc75b4c8 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java @@ -19,6 +19,12 @@ package gplx.xowa.mws; import gplx.*; import gplx.xowa.*; import gplx.core.btries.*; import gplx.xowa.mws.htmls.*; import gplx.xowa.mws.linkers.*; +/* TODO.XO + * titleFormatter->gePrefixedTex + * $html = HtmlArmor::getHtml($text); + * Get_link_url + * Get_link_classes +*/ public class Xomw_linker { private final Bry_bfr tmp = Bry_bfr_.New(); private final Linker_rel_splitter splitter = new Linker_rel_splitter(); diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java index b2869dd67..9368be160 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker__normalize_subpage_link__tst.java @@ -28,7 +28,7 @@ public class Xomw_linker__normalize_subpage_link__tst { @Test public void Dot2__trailing() {fxt.Test__normalize_subpage_link("A/B/C" , "../../Z/" , "" , "A/Z" , "Z");} } class Xomw_linker__normalize_subpage_link__fxt { - private final Xomw_linker mgr = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer()); + private final Xomw_linker mgr = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer(new Xomw_sanitizer())); private final Xowe_wiki wiki; private final Xomw_linker__normalize_subpage_link normalize_subpage_link = new Xomw_linker__normalize_subpage_link(); public Xomw_linker__normalize_subpage_link__fxt() { diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java index 33764246f..d539b4a32 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker__split_trail__tst.java @@ -23,7 +23,7 @@ public class Xomw_linker__split_trail__tst { @Test public void None() {fxt.Test__split_trail(" abc" , null , " abc");} } class Xomw_linker__split_trail__fxt { - private final Xomw_linker linker = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer()); + private final Xomw_linker linker = new Xomw_linker(new gplx.xowa.mws.linkers.Xomw_link_renderer(new Xomw_sanitizer())); private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs(); public Xomw_linker__split_trail__fxt() { String[] ary = new String[] {"a", "b", "c", "d", "e", "f"}; diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer.java b/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer.java index 9d3e1df99..04b87f1da 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer.java @@ -18,7 +18,7 @@ along with this program. If not, see . package gplx.xowa.mws; import gplx.*; import gplx.xowa.*; import gplx.core.brys.*; import gplx.core.btries.*; import gplx.core.encoders.*; import gplx.core.primitives.*; import gplx.langs.htmls.entitys.*; import gplx.xowa.parsers.htmls.*; -import gplx.xowa.mws.parsers.*; import gplx.langs.phps.utls.*; +import gplx.langs.htmls.*; import gplx.xowa.mws.htmls.*; import gplx.xowa.mws.parsers.*; import gplx.langs.phps.utls.*; public class Xomw_sanitizer { private final Mwh_doc_wkr__atr_bldr atr_bldr = new Mwh_doc_wkr__atr_bldr(); private final Mwh_atr_parser atr_parser = new Mwh_atr_parser(); @@ -91,6 +91,50 @@ public class Xomw_sanitizer { } } + // Merge two sets of HTML attributes. Conflicting items in the second set + // will override those in the first, except for 'class' attributes which + // will be combined (if they're both strings). + // XO.MW: XO does src += trg; MW does rv = src + trg; + public void Merge_attributes(Xomw_atr_mgr src, Xomw_atr_mgr trg) { + int trg_len = trg.Len(); + for (int i = 0; i < trg_len; i++) { + Xomw_atr_itm trg_atr = trg.Get_at(i); + // merge trg and src + byte[] atr_cls = Gfh_atr_.Bry__class; + if (Bry_.Eq(trg_atr.Key_bry(), atr_cls)) { + Xomw_atr_itm src_atr = src.Get_by_or_null(atr_cls); + if (src_atr != null) { + // NOTE: need byte[]-creation is unavoidable b/c src_atr and trg_atr are non-null + Merge_atrs_combine(tmp_bfr, src_atr.Val(), Byte_ascii.Space); + tmp_bfr.Add_byte_space(); + Merge_atrs_combine(tmp_bfr, trg_atr.Val(), Byte_ascii.Space); + src_atr.Val_(tmp_bfr.To_bry_and_clear()); + continue; + } + } + src.Add_or_set(trg_atr); + } + } + private void Merge_atrs_combine(Bry_bfr trg, byte[] src, byte sep) { + int src_len = src.length; + for (int i = 0; i < src_len; i++) { + byte b = src[i]; + if (b == sep) { + // gobble ws; EX: "a b" + int space_bgn = i; + int space_end = Bry_find_.Find_fwd_while(src, i, src_len, sep); + i = space_end - 1; // -1 b/c i++ above + + // ignore ws at BOS; EX: " a" + if (space_bgn == 0) + continue; + // ignore ws at EOS; EX: "a " + if (space_end == src_len) + break; + } + trg.Add_byte(b); + } + } public byte[] Clean_url(byte[] url) { // Normalize any HTML entities in input. They will be // re-escaped by makeExternalLink(). diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer__tst.java b/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer__tst.java index 3023c14c7..0cd02e015 100644 --- a/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer__tst.java +++ b/400_xowa/src/gplx/xowa/mws/Xomw_sanitizer__tst.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.mws; import gplx.*; import gplx.xowa.*; -import org.junit.*; import gplx.core.tests.*; import gplx.core.btries.*; +import org.junit.*; import gplx.core.tests.*; import gplx.core.btries.*; import gplx.xowa.mws.htmls.*; public class Xomw_sanitizer__tst { private final Xomw_sanitizer__fxt fxt = new Xomw_sanitizer__fxt(); @Test public void Normalize__text() {fxt.Test__normalize_char_references("abc" , "abc");} @@ -107,6 +107,22 @@ public class Xomw_sanitizer__tst { // ipv6_brack fxt.Test__clean_url("http://[0a.1b:12]:123/cd" , "http://[0a.1b:12]:123/cd"); } + @Test public void Merge_atrs() { + Xomw_atr_mgr src_atrs = new Xomw_atr_mgr(); + Xomw_atr_mgr trg_atrs = new Xomw_atr_mgr(); + Xomw_atr_mgr expd_atrs = new Xomw_atr_mgr(); + String cls = "class"; + // basic: k1 + k2 + fxt.Test__merge_attributes(src_atrs.Clear().Add_many("k1", "v1"), trg_atrs.Clear().Add_many("k2", "v2"), expd_atrs.Clear().Add_many("k1", "v1", "k2", "v2")); + // overwrite: k1 + k1 + fxt.Test__merge_attributes(src_atrs.Clear().Add_many("k1", "v1"), trg_atrs.Clear().Add_many("k1", "v1a"), expd_atrs.Clear().Add_many("k1", "v1a")); + // cls: many + fxt.Test__merge_attributes(src_atrs.Clear().Add_many(cls, "v1 v2"), trg_atrs.Clear().Add_many(cls, "v3 v4"), expd_atrs.Clear().Add_many(cls, "v1 v2 v3 v4")); + // cls: src.empty + fxt.Test__merge_attributes(src_atrs.Clear(), trg_atrs.Clear().Add_many(cls, "v1"), expd_atrs.Clear().Add_many(cls, "v1")); + // cls: ws + fxt.Test__merge_attributes(src_atrs.Clear().Add_many(cls, " v1 v2 "), trg_atrs.Clear().Add_many(cls, " v3 v4 "), expd_atrs.Clear().Add_many(cls, "v1 v2 v3 v4")); + } } class Xomw_sanitizer__fxt { private final Xomw_sanitizer sanitizer = new Xomw_sanitizer(); @@ -145,4 +161,8 @@ class Xomw_sanitizer__fxt { byte[] src_bry = Bry_.new_u8(src_str); Gftest.Eq__str(expd, sanitizer.Clean_url(src_bry)); } + public void Test__merge_attributes(Xomw_atr_mgr src, Xomw_atr_mgr trg, Xomw_atr_mgr expd) { + sanitizer.Merge_attributes(src, trg); + Gftest.Eq__ary__lines(expd.To_str(tmp), src.To_str(tmp), "merge_atrs"); + } } diff --git a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java index ad3f58396..81073cc03 100644 --- a/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java +++ b/400_xowa/src/gplx/xowa/mws/htmls/Xomw_atr_mgr.java @@ -17,17 +17,14 @@ along with this program. If not, see . */ package gplx.xowa.mws.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; public class Xomw_atr_mgr { - private final Ordered_hash hash = Ordered_hash_.New(); - public int Len() {return hash.Len();} - public Xomw_atr_itm Get_at(int i) {return (Xomw_atr_itm)hash.Get_at(i);} - public Xomw_atr_mgr Clear() {hash.Clear(); return this;} - public void Add(byte[] key, byte[] val) {hash.Add(key, new Xomw_atr_itm(-1, key, val));} - public void Add(Xomw_atr_itm itm) {hash.Add(itm.Key_bry(), itm);} - public void Del(byte[] key) {hash.Del(key);} - public void Set(byte[] key, byte[] val) { - Xomw_atr_itm atr = Get_by_or_make(key); - atr.Val_(val); - } + private final Ordered_hash hash = Ordered_hash_.New_bry(); + public int Len() {return hash.Len();} + public Xomw_atr_itm Get_at(int i) {return (Xomw_atr_itm)hash.Get_at(i);} + public Xomw_atr_itm Get_by_or_null(byte[] k) {return (Xomw_atr_itm)hash.Get_by(k);} + public Xomw_atr_mgr Clear() {hash.Clear(); return this;} + public void Del(byte[] key) {hash.Del(key);} + public void Add(Xomw_atr_itm itm) {hash.Add(itm.Key_bry(), itm);} + public void Add(byte[] key, byte[] val) {this.Add(new Xomw_atr_itm(-1, key, val));} public void Add_or_set(Xomw_atr_itm src) { Xomw_atr_itm trg = (Xomw_atr_itm)hash.Get_by(src.Key_bry()); if (trg == null) @@ -35,8 +32,9 @@ public class Xomw_atr_mgr { else trg.Val_(src.Val()); } - public Xomw_atr_itm Get_by_or_null(byte[] k) { - return (Xomw_atr_itm)hash.Get_by(k); + public void Set(byte[] key, byte[] val) { + Xomw_atr_itm atr = Get_by_or_make(key); + atr.Val_(val); } public Xomw_atr_itm Get_by_or_make(byte[] k) { Xomw_atr_itm rv = (Xomw_atr_itm)hash.Get_by(k); @@ -50,11 +48,22 @@ public class Xomw_atr_mgr { Xomw_atr_itm atr = (Xomw_atr_itm)hash.Get_by(k); return atr == null ? null : atr.Val(); } - public void Merge(Xomw_atr_mgr src) { - int src_len = src.Len(); - for (int i = 0; i < src_len; i++) { - Xomw_atr_itm src_atr = src.Get_at(i); - this.Add(src_atr); + public Xomw_atr_mgr Add_many(String... kvs) {// TEST + int len = kvs.length; + for (int i = 0; i < len; i += 2) { + byte[] key = Bry_.new_u8(kvs[i]); + byte[] val = Bry_.new_u8(kvs[i + 1]); + Add(key, val); + } + return this; + } + public String To_str(Bry_bfr tmp) { // TEST + int len = this.Len(); + for (int i = 0; i < len; i++) { + Xomw_atr_itm itm = this.Get_at(i); + tmp.Add(itm.Key_bry()).Add_byte_eq(); + tmp.Add(itm.Val()).Add_byte_nl(); } + return tmp.To_str_and_clear(); } } diff --git a/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java index 0fd471455..bf0530737 100644 --- a/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java +++ b/400_xowa/src/gplx/xowa/mws/linkers/Xomw_link_renderer.java @@ -19,18 +19,20 @@ package gplx.xowa.mws.linkers; import gplx.*; import gplx.xowa.*; import gplx.xo import gplx.langs.htmls.*; import gplx.xowa.mws.htmls.*; /* TODO.XO - * titleFormatter->gePrefixedTex - * $html = HtmlArmor::getHtml($text); - * Get_link_url - * Normalise_special_page - * Merge_attribs - * Get_link_classes + * P7: $html = HtmlArmor::getHtml($text); + * P3: Get_link_url [alternate urls? EX: mw/wiki/index.php/title?] + * P2: titleFormatter->getPrefixedText [depends on redlinks] + * P1: Get_link_classes [depends on redlinks] */ public class Xomw_link_renderer { private boolean expand_urls = false; private final Xomw_html_utl html_utl = new Xomw_html_utl(); private final Xomw_atr_mgr attribs = new Xomw_atr_mgr(); - + private final List_adp tmp_merge_deleted = List_adp_.New(); + private final Xomw_sanitizer sanitizer; + public Xomw_link_renderer(Xomw_sanitizer sanitizer) { + this.sanitizer = sanitizer; + } // XO.MW:SYNC:1.29; DATE:2017-01-31 public void Make_link(Bry_bfr bfr, Xoa_ttl target, byte[] text, byte[] classes, Xomw_atr_mgr extra_atrs, Xomw_qry_mgr query) { if (target.Is_known()) { @@ -57,7 +59,7 @@ public class Xomw_link_renderer { attribs.Add(Gfh_atr_.Bry__title, prefixed_text); } - attribs.Merge(extra_atrs); + Merge_attribs(attribs, extra_atrs); if (text == null) { text = this.Get_link_text(target); @@ -99,7 +101,7 @@ public class Xomw_link_renderer { attribs.Clear(); attribs.Add(Gfh_atr_.Bry__href, url); // $attribs = ['href' => $url,] + $this->mergeAttribs($attribs, $extraAttribs); attribs.Add(Gfh_atr_.Bry__class, Bry_.new_a7("new")); - attribs.Merge(extra_atrs); + Merge_attribs(attribs, extra_atrs); // $prefixedText = $this->titleFormatter->getPrefixedText($target); // if ($prefixedText !== '') { @@ -157,22 +159,35 @@ public class Xomw_link_renderer { private Xoa_ttl Normalize_target(Xoa_ttl target) { return Xomw_linker.Normalise_special_page(target); } -// private function mergeAttribs( $defaults, $attribs ) { -// if ( !$attribs ) { -// return $defaults; -// } -// // Merge the custom attribs with the default ones, and iterate -// // over that, deleting all "false" attributes. -// $ret = []; -// $merged = Sanitizer::mergeAttributes( $defaults, $attribs ); -// foreach ( $merged as $key => $val ) { -// # A false value suppresses the attribute -// if ( $val !== false ) { -// $ret[$key] = $val; -// } -// } -// return $ret; -// } + // XO.MW:SYNC:1.29; DATE:2017-02-01 + private void Merge_attribs(Xomw_atr_mgr src, Xomw_atr_mgr trg) { + // XO.MW: ignore; src is always non-null and empty; if trg exists, it will be merged below + // if (!$attribs) {return $defaults;} + + // Merge the custom attribs with the default ones, and iterate + // over that, deleting all "false" attributes. + sanitizer.Merge_attributes(src, trg); + + // XO.MW:MW removes "false" values; XO removes "null" values + boolean deleted = false; + int len = trg.Len(); + for (int i = 0; i < len; i++) { + Xomw_atr_itm trg_atr = trg.Get_at(i); + // A false value suppresses the attribute + if (trg_atr.Val() == null) { + tmp_merge_deleted.Add(trg_atr); + deleted = true; + } + } + if (deleted) { + len = tmp_merge_deleted.Len(); + for (int i = 0; i < len; i++) { + Xomw_atr_itm atr = (Xomw_atr_itm)trg.Get_at(i); + trg.Del(atr.Key_bry()); + } + tmp_merge_deleted.Clear(); + } + } public byte[] Get_link_classes(Xoa_ttl target) { // Make sure the target is in the cache // $id = $this->linkCache->addLinkObj($target); diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders__tst.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders__tst.java index c85278fb1..a3036291a 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders__tst.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_link_holders__tst.java @@ -26,7 +26,7 @@ public class Xomw_link_holders__tst { } } class Xomw_link_holders__fxt { - private final Xomw_link_holders holders = new Xomw_link_holders(new Xomw_link_renderer(), Bry_bfr_.New()); + private final Xomw_link_holders holders = new Xomw_link_holders(new Xomw_link_renderer(new Xomw_sanitizer()), Bry_bfr_.New()); private final Xomw_parser_bfr pbfr = new Xomw_parser_bfr(); private final Xowe_wiki wiki; private boolean apos = true; diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java index 548d23685..6912433e6 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser.java @@ -32,7 +32,7 @@ public class Xomw_parser { private final Xomw_heading_wkr heading_wkr = new Xomw_heading_wkr(); private final Xomw_magiclinks_wkr magiclinks_wkr; private final Xomw_doubleunder_wkr doubleunder_wkr = new Xomw_doubleunder_wkr(); - private final Xomw_link_renderer link_renderer = new Xomw_link_renderer(); + private final Xomw_link_renderer link_renderer; private final Xomw_link_holders holders; private final Xomw_heading_cbk__html heading_wkr_cbk; private final Btrie_slim_mgr protocols_trie; @@ -61,6 +61,7 @@ public class Xomw_parser { } } + this.link_renderer = new Xomw_link_renderer(sanitizer); this.linker = new Xomw_linker(link_renderer); this.protocols_trie = Xomw_parser.Protocols__dflt(); this.holders = new Xomw_link_holders(link_renderer, tmp); diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser__tst.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser__tst.java index 656b9e693..48719da41 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser__tst.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser__tst.java @@ -51,9 +51,9 @@ public class Xomw_parser__tst { , "" , "

italics" , "" - , "b" + , "b" , "abc" - , "https://c.org" + , "https://c.org" , "a »b«  !important c" , "

" )); diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr__tst.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr__tst.java index 28311b621..3b394034e 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr__tst.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkes/Xomw_lnke_wkr__tst.java @@ -19,7 +19,7 @@ package gplx.xowa.mws.parsers.lnkes; import gplx.*; import gplx.xowa.*; import g import org.junit.*; public class Xomw_lnke_wkr__tst { private final Xomw_lnke_wkr__fxt fxt = new Xomw_lnke_wkr__fxt(); - @Test public void Basic() {fxt.Test__parse("[https://a.org b]" , "b");} + @Test public void Basic() {fxt.Test__parse("[https://a.org b]" , "b");} @Test public void Invaild__protocol() {fxt.Test__parse("[httpz:a.org]" , "[httpz:a.org]");} @Test public void Invaild__protocol_slash() {fxt.Test__parse("[https:a.org]" , "[https:a.org]");} @Test public void Invaild__urlchars__0() {fxt.Test__parse("[https://]" , "[https://]");} @@ -33,9 +33,9 @@ public class Xomw_lnke_wkr__tst { , "g" ), String_.Concat_lines_nl_apos_skip_last ( "a" - , "c" + , "c" , "d" - , "f" + , "f" , "g" )); } diff --git a/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr__tst.java b/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr__tst.java index d84c24166..6fe61a747 100644 --- a/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr__tst.java +++ b/400_xowa/src/gplx/xowa/mws/parsers/magiclinks/Xomw_magiclinks_wkr__tst.java @@ -19,51 +19,51 @@ package gplx.xowa.mws.parsers.magiclinks; import gplx.*; import gplx.xowa.*; imp import org.junit.*; public class Xomw_magiclinks_wkr__tst { private final Xomw_magiclinks_wkr__fxt fxt = new Xomw_magiclinks_wkr__fxt(); - @Test public void Basic() {fxt.Test__parse("a https://b.org z", "a https://b.org z");} + @Test public void Basic() {fxt.Test__parse("a https://b.org z", "a https://b.org z");} @Test public void Invalid() {fxt.Test__parse("a _https://b.org z", "a _https://b.org z");} @Test public void Tag__anch() {fxt.Test__parse("a b z", "a b z");} @Test public void Tag__misc() {fxt.Test__parse("a
b
z", "a
b
z");} @Test public void Interrupt() { // ent - fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); + fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); // hex - fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); + fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); // dec - fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); + fxt.Test__parse("a https://b.org<z" , "a https://b.org<z"); // num_post_proto rule fxt.Test__parse("a https://< z" , "a https://< z"); } @Test public void Interrupt__hex_dec() {// implementation specific test for mixed hex / dec // dec-hex - fxt.Test__parse("a https://b.orgc;z" , "a https://b.org&#3c;z"); + fxt.Test__parse("a https://b.orgc;z" , "a https://b.org&#3c;z"); } @Test public void Separator() { // basic; ,;.:!? - fxt.Test__parse("a https://b.org,;.:!? z" , "a https://b.org,;.:!? z"); + fxt.Test__parse("a https://b.org,;.:!? z" , "a https://b.org,;.:!? z"); // ")" excluded - fxt.Test__parse("a https://b.org).:!? z" , "a https://b.org).:!? z"); + fxt.Test__parse("a https://b.org).:!? z" , "a https://b.org).:!? z"); // ")" included b/c "(" exists - fxt.Test__parse("a https://b.org().:!? z" , "a https://b.org().:!? z"); + fxt.Test__parse("a https://b.org().:!? z" , "a https://b.org().:!? z"); // ";" excluded - fxt.Test__parse("a https://b.org;.:!? z" , "a https://b.org;.:!? z"); + fxt.Test__parse("a https://b.org;.:!? z" , "a https://b.org;.:!? z"); // ";" included b/c of ent - fxt.Test__parse("a https://b.org&abc;.:!? z" , "a https://b.org&abc;.:!? z"); + fxt.Test__parse("a https://b.org&abc;.:!? z" , "a https://b.org&abc;.:!? z"); // ";" included b/c of hex; note that Clean_url changes "±" to "±" - fxt.Test__parse("a https://b.org±.:!? z", "a https://b.org±.:!? z"); + fxt.Test__parse("a https://b.org±.:!? z", "a https://b.org±.:!? z"); // ";" included b/c of dec; note that Clean_url changes "{" to "{" - fxt.Test__parse("a https://b.org{.:!? z", "a https://b.org{.:!? z"); + fxt.Test__parse("a https://b.org{.:!? z", "a https://b.org{.:!? z"); // ";" excluded b/c of invalid.ent - fxt.Test__parse("a https://b.org&a1b;.:!? z" , "a https://b.org&a1b;.:!? z"); + fxt.Test__parse("a https://b.org&a1b;.:!? z" , "a https://b.org&a1b;.:!? z"); // ";" excluded b/c of invalid.hex - fxt.Test__parse("a https://b.org&#x;.:!? z" , "a https://b.org&#x;.:!? z"); + fxt.Test__parse("a https://b.org&#x;.:!? z" , "a https://b.org&#x;.:!? z"); // ";" excluded b/c of invalid.dec - fxt.Test__parse("a https://b.org&#a;.:!? z" , "a https://b.org&#a;.:!? z"); + fxt.Test__parse("a https://b.org&#a;.:!? z" , "a https://b.org&#a;.:!? z"); // num_post_proto rule fxt.Test__parse("a https://.:!? z" , "a https://.:!? z"); } @Test public void Clean_url() { // basic - fxt.Test__parse("http://a᠆b.org/c᠆d" , "http://ab.org/c᠆d"); + fxt.Test__parse("http://a᠆b.org/c᠆d" , "http://ab.org/c᠆d"); } } class Xomw_magiclinks_wkr__fxt {