@Test public void Bidi() { fxt.Init_ttl("A" + String_.new_u8(Bry_.ints_(226, 128, 142)) + "B").Expd_page_txt("AB").Test(); fxt.Init_ttl("A" + String_.new_u8(Bry_.ints_(226, 128, 97)) + "B") .Expd_page_txt("A" + String_.new_u8(Bry_.ints_(226, 128, 97)) + "B") .Test(); }
public boolean Chk(Xowe_wiki wiki) { if (!wiki.App().App_type().Uid_is_gui()) return true; // NOTE: ignore during Server / Console modes; DATE:2015-04-01 if (in_progress_hash.Has(wiki.Domain_bry())) return true; // NOTE: ignore if currently building; different bldr commands call // wiki.Init_assert() which may lead to fals checks; Io_url url = url_(wiki); if (!Io_mgr.I.ExistsFil(url)) return true; Xoae_app app = wiki.Appe(); app.Usr_dlg().Log_many("", "", "import.marker: marker found: url=~{0}", url.Raw()); byte[] incompete_msg_bry = app.Usere() .Msg_mgr() .Val_by_key_args(Bry_.new_a7("api-xowa.import.core.incomplete"), wiki.Domain_str()); int rslt = app.Gui_mgr().Kit().Ask_yes_no_cancel("", "", String_.new_u8(incompete_msg_bry)); switch (rslt) { case Gfui_dlg_msg_.Btn_yes: Xob_cleanup_cmd.Delete_wiki_sql(wiki); End(wiki); return false; // delete wiki case Gfui_dlg_msg_.Btn_no: End(wiki); return true; // delete marker case Gfui_dlg_msg_.Btn_cancel: return true; // noop default: throw Err_.unhandled(rslt); } }
public Xowv_wiki(Xoav_app app, byte[] domain_bry, Io_url wiki_root_dir) { this.app = app; this.domain_bry = domain_bry; this.domain_str = String_.new_u8(domain_bry); this.domain_itm = Xow_domain_itm_.parse(domain_bry); this.domain_tid = domain_itm.Domain_type_id(); this.domain_abrv = Xow_abrv_wm_.To_abrv(Xow_domain_itm_.parse(domain_bry)); this.ns_mgr = Xow_ns_mgr_.default_(app.Utl_case_mgr()); this.lang = app.Lang_mgr() .Get_by_or_en( domain_itm .Lang_actl_key()); // NOTE: must not be null, or causes null ref exception on // redlinks in drd; DATE:2016-06-28 this.msg_mgr = new Xow_msg_mgr(this, lang); this.html__hdump_mgr = new Xow_hdump_mgr(this); this.special_mgr = new Xosp_special_mgr(this); this.fsys_mgr = new Xow_fsys_mgr(wiki_root_dir, app.Fsys_mgr().File_dir().GenSubDir(domain_str)); this.fsdb_mgr = new Xof_fsdb_mgr__sql(); this.url__parser = new Xow_url_parser(this); this.xwiki_mgr = new Xow_xwiki_mgr(this); this.stats = new Xow_site_stats_mgr(this); this.lnki_bldr = new Xoh_lnki_bldr(app, href_wtr); this.ctg_catpage_mgr = new Xoctg_catpage_mgr(this); }
public byte[] Bld(Xowe_wiki cur_wiki, Xoae_page page, Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) { if (output_js_clean) cur_wiki.Html_mgr().Js_cleaner().Clean_bfr(wiki, page.Ttl(), wrdx_bfr, 0); if (output_tidy) cur_wiki.Html_mgr().Tidy_mgr().Exec_tidy(wrdx_bfr, Bool_.Y, page.Url_bry_safe()); byte[] hdom_bry = wrdx_bfr.To_bry_and_clear(); String page_url = wrdx_bfr.Add(page.Wiki().Domain_bry()) .Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki) .Add( gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode( page.Ttl() .Full_db())) // NOTE: was page.Url().Raw(), but that doesn't work for // Special:Search; PAGE:en.w:Earth and "Quotations"; // DATE:2014-06-29 .To_str_and_clear(); fmtr_popup.Bld_bfr_many( wrdx_bfr, hdom_bry, wiki.Lang().Dir_ltr_bry(), page_url, String_.new_u8(page.Ttl().Full_txt_w_ttl_case()), popup_itm.Popup_id(), Xow_popup_html_bldr_.Bld_fmtr_wiki( fmtr_wiki, wrdx_bfr, cur_wiki.Domain_bry(), page.Wiki().Domain_bry()) // NOTE: use cur_wiki, not page_wiki; DATE:2014-06-28 , gplx.core.ios.Io_size_.To_str(page.Db().Text().Text_bry().length), page.Db().Page().Modified_on().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss(), Xow_popup_html_bldr_.Bld_fmtr_viewed(fmtr_viewed, app, wiki, wrdx_bfr, page.Ttl()), app.Fsys_mgr().Root_dir().To_http_file_bry()); return wrdx_bfr.To_bry_and_clear(); }
// public Io_url[] Src_fils() {return src_fils;} public Io_line_rdr_fxt Src_fils_(Io_url[] v) // {src_fils = v; return this;} Io_url[] src_fils; public Io_line_rdr_fxt tst_Match(String match, String expd) { rdr.Key_gen_(Io_line_rdr_key_gen_.first_pipe); boolean match_v = rdr.Match(Bry_.new_u8(match)); String actl = match_v ? String_.new_u8(rdr.Bfr(), rdr.Key_pos_bgn(), rdr.Key_pos_end()) : ""; Tfds.Eq(expd, actl); return this; }
Xof_repo_itm Ini_repo_add(Xof_file_mgr file_mgr, byte[] key, String root, String wiki, boolean trg) { Xof_repo_itm repo = file_mgr.Repo_mgr().Set(String_.new_u8(key), root, wiki).Ext_rules_(Xof_rule_grp.Grp_app_default).Dir_depth_(2); if (trg) { byte[][] ary = repo.Mode_names(); ary[0] = Bry_.new_a7("raw"); ary[1] = Bry_.new_a7("fit"); } return repo; }
public static Xopg_tag_itm New_js_file(Io_url src_url) { byte[] src = src_url.To_http_file_bry(); return new Xopg_tag_itm( Tid__js_file, Gfh_tag_.Bry__script, src, null, Tag__type_js, Keyval_.new_("src", String_.new_u8(src))); }
public Xow_search_tkn[] Scan(byte[] src) { this.src = src; this.src_len = src.length; tkns.Clear(); pos = 0; txt_bgn = -1; while (pos < src_len) { byte cur_b = src[pos]; Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len); if (cur_obj == null) { // text character if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it ++pos; } else { // AND, OR, (, ), -, \s, " int pos_end = trie.Match_pos(); byte cur_tid = ((Byte_obj_val) cur_obj).Val(); if (Cur_join_is_word(cur_tid, pos_end)) continue; // ignore words containing "and", "or"; EX: "random"; "for" if (txt_bgn != -1) { // pending word; create Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos); txt_bgn = -1; } switch (cur_tid) { case Xow_search_tkn.Tid_space: // discard spaces pos = Bry_finder.Find_fwd_while(src, pos, src_len, Byte_ascii.Space); break; case Xow_search_tkn.Tid_quote: // find end quote and add as word int quote_bgn = pos + 1; int quote_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len); if (quote_end == Bry_.NotFound) throw Err_.new_fmt_("could not find end quote: {0}", String_.new_u8(src)); Tkns_add_word(Xow_search_tkn.Tid_word_quoted, quote_bgn, quote_end); pos = quote_end + 1; // +1 to place after quote break; case Xow_search_tkn.Tid_not: Tkns_add_word(Xow_search_tkn.Tid_not, pos, pos_end); pos = pos_end; break; case Xow_search_tkn.Tid_paren_bgn: case Xow_search_tkn.Tid_paren_end: case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or: tkns.Add(new_tkn(cur_tid, pos, pos_end)); pos = pos_end; break; default: throw Err_.unhandled(cur_tid); } } } if (txt_bgn != -1) { // pending word; create Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos); txt_bgn = -1; } return (Xow_search_tkn[]) tkns.To_ary_and_clear(Xow_search_tkn.class); }
private static boolean Navigate( Gfo_usr_dlg usr_dlg, Xoae_app app, Wdata_wiki_mgr wdata_mgr, Xoae_page page, byte[] site_bry, byte[] page_bry) { page_bry = Xoa_app_.Utl__encoder_mgr() .Http_url() .Decode(page_bry); // NOTE: space is converted to + on postback to url; decode byte[] wiki_domain = Xow_wiki_alias.Parse_wmf_key(site_bry); if (wiki_domain == null) { usr_dlg.Warn_many("", "", "site_bry parse failed; site_bry:~{0}", String_.new_u8(site_bry)); return false; } Xowe_wiki wiki = app.Wiki_mgr().Get_by_key_or_make(wiki_domain); if (wiki == null) { usr_dlg.Warn_many( "", "", "wiki_domain does not exist; wiki_domain:~{0}", String_.new_u8(wiki_domain)); return false; } Xoa_ttl wdata_ttl = Xoa_ttl.parse_(wiki, page_bry); if (wdata_ttl == null) { usr_dlg.Warn_many("", "", "ttl is invalid; ttl:~{0}", String_.new_u8(page_bry)); return false; } Wdata_doc doc = wdata_mgr.Pages_get(wiki, wdata_ttl); if (doc == null) { usr_dlg.Warn_many( "", "", "ttl cannot be found in wikidata; ttl:~{0}", String_.new_u8(wdata_ttl.Raw())); return false; } byte[] qid_bry = doc.Qid(); Xoae_page qid_page = wdata_mgr.Wdata_wiki().Data_mgr().Redirect(page, qid_bry); if (qid_page.Missing()) { usr_dlg.Warn_many( "", "", "qid cannot be found in wikidata; qid:~{0}", String_.new_u8(qid_bry)); return false; } return true; }
private int Import_url_chk( byte[] rel_url_prefix, byte[] src, int src_len, int old_pos, int find_bgn, byte[] url_raw, Bry_bfr bfr) { if (find_bgn < Bry_import_len) return Bry_find_.Not_found; if (!Bry_.Match(src, find_bgn - Bry_import_len, find_bgn, Bry_import)) return Bry_find_.Not_found; byte[] css_url = url_raw; int css_url_len = css_url.length; if (css_url_len > 0 && css_url[0] == Byte_ascii .Slash) { // css_url starts with "/"; EX: "/page" or "//site/page" DATE:2014-02-03 if (css_url_len > 1 && css_url[1] != Byte_ascii.Slash) // skip if css_url starts with "//"; EX: "//site/page" css_url = Bry_.Add(rel_url_prefix, css_url); // "/w/a.css" -> "//en.wikipedia.org/w/a.css" } css_url = Bry_.Replace( css_url, Byte_ascii.Space, Byte_ascii .Underline); // NOTE: must replace spaces with underlines else download will fail; // EX:https://it.wikivoyage.org/w/index.php?title=MediaWiki:Container e // Infobox.css&action=raw&ctype=text/css; DATE:2015-03-08 byte[] css_src_bry = Import_url_build(stylesheet_prefix, rel_url_prefix, css_url); String css_src_str = String_.new_u8(css_src_bry); download_wkr.Download_xrg() .Prog_fmt_hdr_( usr_dlg.Log_many( GRP_KEY, "logo.download", "downloading import for '~{0}'", css_src_str)); byte[] css_trg_bry = download_wkr.Download_xrg().Exec_as_bry(css_src_str); if (css_trg_bry == null) { usr_dlg.Warn_many("", "", "could not import css: url=~{0}", css_src_str); return Bry_find_.Not_found; // css not found } bfr.Add_mid(src, old_pos, find_bgn - Bry_import_len).Add_byte_nl(); bfr.Add(Bry_comment_bgn).Add(css_url).Add(Bry_comment_end).Add_byte_nl(); if (Bry_find_.Find_fwd(css_url, Wikisource_dynimg_ttl) != -1) css_trg_bry = Bry_.Replace( css_trg_bry, Wikisource_dynimg_find, Wikisource_dynimg_repl); // FreedImg hack; // PAGE:en.s:Page:Notes_on_Osteology_of_Baptanodon._With_a_Description_of_a_New_Species.pdf/3 DATE:2014-09-06 bfr.Add(css_trg_bry).Add_byte_nl(); bfr.Add_byte_nl(); int semic_pos = Bry_find_.Find_fwd(src, Byte_ascii.Semic, find_bgn + url_raw.length, src_len); return semic_pos + Int_.Const_dlm_len; }
public Io_line_rdr_fxt tst_Read_til_lines(int count, String... expd) { lines.Clear(); for (int i = 0; i < expd.length; i++) expd[i] = expd[i] + Op_sys.Lnx.Nl_str(); for (int i = 0; i < count; i++) { if (rdr.Read_next()) lines.Add(String_.new_u8(rdr.Bfr(), rdr.Itm_pos_bgn(), rdr.Itm_pos_end())); else break; } Tfds.Eq_ary_str(expd, lines.To_str_ary()); return this; }
public static Xopg_tag_itm New_css_file(Io_url href_url) { byte[] href = href_url.To_http_file_bry(); return new Xopg_tag_itm( Tid__css_file, Gfh_tag_.Bry__link, href, null, Tag__type_css, Tag__rel_stylesheet, Keyval_.new_("href", String_.new_u8(href))); }
public byte[] Cartouche_img( Xoh_wtr_ctx hctx, boolean bgn, byte[] glyph) { // render open / close cartouche; note that MW has two branches, but they are // both the same int height = (int) ((Hiero_html_mgr.Max_height * Hiero_html_mgr.scale) / 100); Hiero_phoneme_itm phoneme_itm = phoneme_mgr.Get_by_key(glyph); if (phoneme_itm == null) throw Err_.new_fmt_("missing phoneme: {0}", String_.new_u8(glyph)); byte[] code = phoneme_itm.Gardiner_code(); byte[] title = bgn ? Html_entity_.Lt_bry : Html_entity_.Gt_bry; return cartouche_img_fmtr.Bld_bry_many(temp_bfr, hiero_img_dir, code, height, title); }
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_clear)) this.Clear(); else if (ctx.Match(k, Invk_separators)) return separators_mgr; else if (ctx.Match(k, Invk_digits)) { digits_translate = true; return digits_mgr; } // NOTE: only langes with a digit_transform_table will call digits; DATE:2014-05-28 else if (ctx.Match(k, Invk_digit_grouping_pattern)) return String_.new_u8(num_grp_fmtr.Digit_grouping_pattern()); else if (ctx.Match(k, Invk_digit_grouping_pattern_)) num_grp_fmtr.Digit_grouping_pattern_(m.ReadBry("v")); else return Gfo_invk_.Rv_unhandled; return this; }
public Btrie_fast_mgr Add(byte[] key, Object val) { if (val == null) throw Err_.new_("null objects cannot be registered").Add("key", String_.new_u8(key)); int key_len = key.length; int key_end = key_len - 1; ByteTrieItm_fast cur = root; for (int i = 0; i < key_len; i++) { byte b = key[i]; ByteTrieItm_fast nxt = cur.Ary_find(b); if (nxt == null) nxt = cur.Ary_add(b, null); if (i == key_end) nxt.Val_set(val); cur = nxt; } return this; }
public void Save_as() { if (this.Active_tab_is_null()) return; Xog_tab_itm tab = win.Tab_mgr().Active_tab(); String file_name = Xoa_app_.Utl__encoder_mgr() .Fsys_safe() .Encode_str(String_.new_u8(tab.Page().Ttl().Full_url())) + ".html"; String file_url = app.Gui_mgr() .Kit() .New_dlg_file(Gfui_kit_.File_dlg_type_save, "Select file to save to:") .Init_file_(file_name) .Ask(); if (String_.Len_eq_0(file_url)) return; Io_mgr.I.SaveFilStr(file_url, tab.Html_box().Text()); app.Usr_dlg().Prog_many("", "", "saved page: file=~{0}", file_url); }
public Mustache_tkn_base(int tid, byte[] key_bry) { this.tid = tid; this.key = String_.new_u8(key_bry); }
public static byte[] Write_wdata_links(List_adp slink_list, Xowe_wiki wiki, Xoa_ttl ttl, Wdata_external_lang_links_data external_links_mgr) { try { switch (wiki.Domain_tid()) { case Xow_domain_type_.Tid_home: // home will never be in wikidata case Xow_domain_type_.Tid_wikidata: // wikidata will never be in wikidata return Qid_null; } Wdata_wiki_mgr wdata_mgr = wiki.Appe().Wiki_mgr().Wdata_mgr(); Wdata_doc doc = wdata_mgr.Pages_get(wiki, ttl); if (doc == null) return Qid_null; // no links boolean external_links_mgr_enabled = external_links_mgr.Enabled(); Ordered_hash links = doc.Slink_list(); Bry_bfr tmp_bfr = wiki.Appe().Utl__bfr_mkr().Get_k004(); Xow_wiki_abrv wiki_abrv = new Xow_wiki_abrv(); int len = links.Count(); for (int i = 0; i < len; i++) { Wdata_sitelink_itm slink = (Wdata_sitelink_itm)links.Get_at(i); byte[] xwiki_key = slink.Site(); Xow_wiki_abrv_.parse_(wiki_abrv, xwiki_key, 0, xwiki_key.length); if (wiki_abrv.Domain_tid() == Xow_wiki_abrv_.Tid_null) { wiki.Appe().Usr_dlg().Warn_many("", "", "unknown wiki in wikidata: ttl=~{0} wiki=~{1}", ttl.Page_db_as_str(), String_.new_u8(xwiki_key)); continue; } if (wiki_abrv.Domain_tid() != wiki.Domain_tid()) continue; // ignore wikis in a different domain; EX: looking at enwiki:Earth, and wikidata has dewikiquote; ignore dewikiquote; DATE:2014-06-21 byte[] lang_key = wiki_abrv.Lang_itm().Key(); if (external_links_mgr_enabled && external_links_mgr.Langs_hide(lang_key, 0, lang_key.length)) continue; tmp_bfr.Add(lang_key); tmp_bfr.Add_byte(Byte_ascii.Colon); tmp_bfr.Add(slink.Name()); Xoa_ttl slink_ttl = Xoa_ttl.parse_(wiki, tmp_bfr.Xto_bry_and_clear()); if (slink_ttl == null) continue; // invalid ttl Xow_xwiki_itm xwiki_itm = slink_ttl.Wik_itm(); if ( xwiki_itm == null // not a known xwiki; EX: [[zzz:abc]] || Bry_.Eq(xwiki_itm.Domain_bry(), wiki.Domain_bry()) // skip if same as self; i.e.: do not include links to enwiki if already in enwiki ) continue; slink.Page_ttl_(slink_ttl); slink_list.Add(slink); } tmp_bfr.Mkr_rls(); if (external_links_mgr_enabled && external_links_mgr.Sort()) slink_list.Sort_by(Xoa_ttl_sorter._); return doc.Qid(); } catch (Exception e) {Err_.Noop(e); return Qid_null;} }
private static Keyval new_itm(Xol_lang_stub itm) { String key_str = String_.new_u8(itm.Key()); String name_str = String_.new_u8(itm.Canonical_name()); return Keyval_.new_(key_str, name_str + " [" + key_str + "]"); }
String Make_key(int ns_id, byte[] ttl) { return Int_.To_str(ns_id) + "|" + String_.new_u8(ttl); }
String Replace_invalid_chars_str(String raw_str) { return String_.new_u8(Replace_invalid_chars(Bry_.new_u8(raw_str))); }
public byte[] Convert_to_local_urls(byte[] rel_url_prefix, byte[] src, List_adp list) { try { int src_len = src.length; int prv_pos = 0; Bry_bfr bfr = Bry_bfr_.New_w_size(src_len); Hash_adp img_hash = Hash_adp_bry.cs(); while (true) { int url_pos = Bry_find_.Find_fwd(src, Bry_url, prv_pos); if (url_pos == Bry_find_.Not_found) { bfr.Add_mid(src, prv_pos, src_len); break; } // no more "url("; exit; int bgn_pos = url_pos + Bry_url_len; // set bgn_pos after "url(" byte bgn_byte = src[bgn_pos]; byte end_byte = Byte_ascii.Null; boolean quoted = true; switch (bgn_byte) { // find end_byte case Byte_ascii.Quote: case Byte_ascii.Apos: // quoted; end_byte is ' or " end_byte = bgn_byte; ++bgn_pos; break; default: // not quoted; end byte is ")" end_byte = Byte_ascii.Paren_end; quoted = false; break; } int end_pos = Bry_find_.Find_fwd(src, end_byte, bgn_pos, src_len); if (end_pos == Bry_find_.Not_found) { // unclosed "url("; exit since nothing else will be found usr_dlg.Warn_many( GRP_KEY, "parse.invalid_url.end_missing", "could not find end_sequence for 'url(': bgn='~{0}' end='~{1}'", prv_pos, String_.new_u8__by_len(src, prv_pos, prv_pos + 25)); bfr.Add_mid(src, prv_pos, src_len); break; } if (end_pos - bgn_pos == 0) { // empty; "url()"; ignore usr_dlg.Warn_many( GRP_KEY, "parse.invalid_url.empty", "'url(' is empty: bgn='~{0}' end='~{1}'", prv_pos, String_.new_u8__by_len(src, prv_pos, prv_pos + 25)); bfr.Add_mid(src, prv_pos, bgn_pos); prv_pos = bgn_pos; continue; } byte[] img_raw = Bry_.Mid(src, bgn_pos, end_pos); int img_raw_len = img_raw.length; if (Bry_.Has_at_bgn(img_raw, Bry_data_image, 0, img_raw_len)) { // base64 bfr.Add_mid(src, prv_pos, end_pos); // nothing to download; just add entire String prv_pos = end_pos; continue; } int import_url_end = Import_url_chk( rel_url_prefix, src, src_len, prv_pos, url_pos, img_raw, bfr); // check for embedded stylesheets via @import tag if (import_url_end != Bry_find_.Not_found) { prv_pos = import_url_end; continue; } byte[] img_cleaned = Xob_url_fixer.Fix(wiki_domain, img_raw, img_raw_len); if (img_cleaned == null) { // could not clean img usr_dlg.Warn_many( GRP_KEY, "parse.invalid_url.clean_failed", "could not extract valid http src: bgn='~{0}' end='~{1}'", prv_pos, String_.new_u8(img_raw)); bfr.Add_mid(src, prv_pos, bgn_pos); prv_pos = bgn_pos; continue; } if (!img_hash.Has(img_cleaned)) { // only add unique items for download; img_hash.Add_as_key_and_val(img_cleaned); list.Add(String_.new_u8(img_cleaned)); } img_cleaned = Replace_invalid_chars( Bry_.Copy( img_cleaned)); // NOTE: must call ByteAry.Copy else img_cleaned will change // *inside* hash bfr.Add_mid(src, prv_pos, bgn_pos); if (!quoted) bfr.Add_byte(Byte_ascii.Quote); bfr.Add(img_cleaned); if (!quoted) bfr.Add_byte(Byte_ascii.Quote); prv_pos = end_pos; } return bfr.To_bry_and_clear(); } catch (Exception e) { usr_dlg.Warn_many( "", "", "failed to convert local_urls: ~{0} ~{1}", String_.new_u8(rel_url_prefix), Err_.Message_gplx_full(e)); return src; } }
public int MakeTkn_end(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int lxr_bgn_pos, int lxr_cur_pos) { if (ctx.Cur_tkn_tid() == Xop_tkn_itm_.Tid_brack_bgn) // WORKAROUND: ignore }} if inside lnki; EX.CM:Template:Protected; {{#switch:a|b=[[a|ja=}}]]}} return ctx.Lxr_make_txt_(lxr_cur_pos); int lxr_end_pos = Bry_finder.Find_fwd_while(src, lxr_cur_pos, src_len, Byte_ascii.Curly_end); // NOTE: can be many consecutive }; EX: {{a|{{{1}}}}} int end_tkn_len = lxr_end_pos - lxr_bgn_pos; boolean vnt_enabled = ctx.Wiki().Lang().Vnt_mgr().Enabled(); while (end_tkn_len > 0) { int acs_pos = -1, acs_len = ctx.Stack_len(); for (int i = acs_len - 1; i > -1; i--) { // find auto-close pos Xop_tkn_itm stack_tkn = ctx.Stack_get(i); switch (stack_tkn.Tkn_tid()) { case Xop_tkn_itm_.Tid_tmpl_curly_bgn: // found curly_bgn; mark and exit acs_pos = i; i = -1; break; case Xop_tkn_itm_.Tid_brack_bgn: // found no curly_bgn, but found brack_bgn; note that extra }} should not close any frames beyond lnki; EX:w:Template:Cite wikisource; w:John Fletcher (playwright) i = -1; break; case Xop_tkn_itm_.Tid_xnde: // found xnde; ignore; handle {{template|<poem>}}</poem>}} DATE:2014-03-03 Xop_xnde_tkn stack_xnde = (Xop_xnde_tkn)stack_tkn; if (stack_xnde.Tag().Xtn()) i = -1; break; } } if (acs_pos == -1) { // "}}+" found but no "{{+" found; warn and output literal tkn ctx.Msg_log().Add_itm_none(Xop_curly_log.Bgn_not_found, src, lxr_bgn_pos, lxr_end_pos); ctx.Subs_add(root, tkn_mkr.Txt(lxr_bgn_pos, lxr_end_pos)); return lxr_end_pos; } Xop_curly_bgn_tkn bgn_tkn = (Xop_curly_bgn_tkn)ctx.Stack_pop_til(root, src, acs_pos, true, lxr_bgn_pos, lxr_end_pos, Xop_tkn_itm_.Tid_tmpl_curly_bgn); // NOTE: in theory, an unclosed [[ can be on stack; for now, ignore int bgn_tkn_len = bgn_tkn.Src_end() - bgn_tkn.Src_bgn(); int bgn_tkn_pos_bgn = bgn_tkn.Src_bgn();// save original pos_bgn boolean vnt_dash_adjust = false; if (vnt_enabled ) { int curly_bgn_dash = bgn_tkn.Src_bgn() - 1; if (curly_bgn_dash > -1 && src[curly_bgn_dash] == Byte_ascii.Dash) { // "-" exists before curlies; EX: "-{{" int curly_end_dash = lxr_end_pos; if (curly_end_dash < src_len && src[curly_end_dash] == Byte_ascii.Dash) { // "-" exists after curlies; EX: "}}-" if (bgn_tkn_len > 2 && end_tkn_len > 2) { // more than 3 curlies at bgn / end with flanking dashes; EX: "-{{{ }}}-"; NOTE: 3 is needed b/c 2 will never be reduced; EX: "-{{" will always be "-" and "{{", not "-{" and "{" int numeric_val = Bry_.Xto_int_or(src, bgn_tkn.Src_end(), lxr_bgn_pos, -1); if ( numeric_val != -1 // do not apply if numeric val; EX:"-{{{0}}}-" vs "-{{{#expr:0}}}-" sr.w:Template:Link_FA && bgn_tkn_len == 3 && end_tkn_len == 3 // exactly 3 tokens; assume param token; "-{{{" -> "-" + "{{{" x> -> "-{" + "{{"; if unbalanced (3,4 or 4,3) fall into code below ) { } // noop; PAGE:sr.w:ДНК; EX:<span id="interwiki-{{{1}}}-fa"></span> DATE:2014-07-03 else { --bgn_tkn_len; // reduce bgn curlies by 1; EX: "{{{" -> "{{" ++bgn_tkn_pos_bgn; // add one to bgn tkn_pos; --end_tkn_len; // reduce end curlies by 1; EX: "}}}" -> "}}" --lxr_end_pos; // reduce end by 1; this will "reprocess" the final "}" as a text tkn; EX: "}}}-" -> "}}" and position before "}-" vnt_dash_adjust = true; } } } } } int new_tkn_len = 0; if (bgn_tkn_len == end_tkn_len) // exact match; should be majority of cases new_tkn_len = bgn_tkn_len; else if (bgn_tkn_len > end_tkn_len) // more bgn than end; use end, and deduct bgn; EX: {{{{{1}}}|a}} new_tkn_len = end_tkn_len; else /*bgn_tkn_len < end_tkn_len*/ // more end than bgn; use bgn, and deduct end; EX: {{a|{{{1}}}}} new_tkn_len = bgn_tkn_len; int keep_curly_bgn = 0; /* NOTE: this is a semi-hack; if bgn_tkn > new_tkn, then pretend bgn_tkn fits new_tkn, give to bldr, and then adjust back later EX: {{{{{1}}}|a}} -> bgn_tkn_len=5,new_tkn_len=3 -> change bgn(0, 5) to bgn(2, 5) The "correct" way is to insert a new_bgn_tkn after cur_bgn_tkn on root, but this would have performance implications: array would have to be resized, and all subs will have to be reindexed NOTE: bgn curlies should also be preserved if new_tkn_len > 3; EX: {{{{{{1}}}}}}; note that bgn = end, but len > 3 */ if (bgn_tkn_len > new_tkn_len || new_tkn_len > 3) { bgn_tkn.Tkn_ini_pos(false, bgn_tkn.Src_end() - new_tkn_len, bgn_tkn.Src_end()); keep_curly_bgn = 1; // preserves {{ } switch (new_tkn_len) { case 0: // EXC_CASE: should not happen; warn; ctx.Msg_log().Add_itm_none(Xop_curly_log.Bgn_len_0, src, bgn_tkn.Src_bgn(), lxr_end_pos); break; // case 1: // EXC_CASE: SEE:NOTE_1; // break; case 2: // USE_CASE: make invk_tkn ctx.Invk().Make_tkn(ctx, root, src, lxr_bgn_pos, lxr_bgn_pos + new_tkn_len, bgn_tkn, keep_curly_bgn); break; default: // USE_CASE: make prm_tkn; NOTE: 3 or more new_tkn_len = 3; // gobble 3 at a time; EX: 6 -> 3 -> 0; EX: 7 -> 4 -> 1; prm_wkr.Make_tkn(ctx, tkn_mkr, root, src, src_len, lxr_bgn_pos, lxr_bgn_pos + new_tkn_len, bgn_tkn, keep_curly_bgn); break; } switch (bgn_tkn_len - new_tkn_len) { // continuation of semi-hack above; some bgn still left over; adjust and throw back on stack case 1: // 1 tkn; convert curly to generic text tkn bgn_tkn.Src_end_(bgn_tkn.Src_end() - 1); // NOTE: shorten end of bgn_tkn by 1; TEST ctx.Stack_add(tkn_mkr.Txt(bgn_tkn_pos_bgn, bgn_tkn.Src_end() - new_tkn_len)); break; case 0: // noop break; default: bgn_tkn.Tkn_ini_pos(false, bgn_tkn_pos_bgn, bgn_tkn.Src_end() - new_tkn_len); // bgn(2, 5) -> bgn (0, 2) ctx.Stack_add(bgn_tkn); break; } if (vnt_dash_adjust) { Xop_tkn_itm text_tkn = root.Subs_get_or_null(root.Subs_len() - 2); // -2 to get tkn before newly-created tmpl / prm if (text_tkn == null || text_tkn.Tkn_tid() != Xop_tkn_itm_.Tid_txt) ctx.Wiki().Appe().Usr_dlg().Warn_many("", "", "token before curly_bgn was not text tkn; src=~{0}", String_.new_u8(src, lxr_bgn_pos, lxr_end_pos)); else text_tkn.Src_end_(text_tkn.Src_end() + 1); // +1 to extend txt_tkn with dash be 1 to include curly; EX: "-" "{{{" -> "-{" "{{" } end_tkn_len -= new_tkn_len; lxr_bgn_pos += new_tkn_len; // move lxr_bgn_pos along if (end_tkn_len == 1) { // SEE:NOTE_1: ctx.Subs_add(root, tkn_mkr.Txt(lxr_bgn_pos, lxr_bgn_pos + 1)); end_tkn_len = 0; ++lxr_bgn_pos; } } return lxr_end_pos; }