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 static byte[] Bld_fmtr_viewed(
     Bry_fmtr fmtr, Xoae_app app, Xowe_wiki wiki, Bry_bfr wrdx_bfr, Xoa_ttl ttl) {
   byte[] view_time_item = Bry_.Empty;
   gplx.xowa.users.history.Xou_history_itm history_itm =
       app.Usere().History_mgr().Get_or_null(wiki.Domain_bry(), ttl.Full_txt_w_ttl_case());
   if (history_itm != null)
     view_time_item =
         fmtr.Bld_bry_many(wrdx_bfr, history_itm.View_end().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss());
   return view_time_item;
 }
class Wdata_fmtr__json implements gplx.core.brys.Bfr_arg {
  private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
  private Xoapi_toggle_itm toggle_itm;
  private Wdata_toc_data toc_data;
  private Json_doc jdoc;

  public void Init_by_ctor(Wdata_toc_data toc_data, Xoapi_toggle_mgr toggle_mgr) {
    this.toc_data = toc_data.Itms_len_enable_n_();
    this.toggle_itm =
        toggle_mgr.Get_or_new("wikidatawiki-json")
            .Html_toggle_hdr_cls_(Bry_.new_a7("overflow:auto;"));
  }

  public void Init_by_lang(Wdata_hwtr_msgs msgs) {
    toc_data.Orig_(msgs.Json_div_hdr());
    toggle_itm.Init_msgs(msgs.Toggle_title_y(), msgs.Toggle_title_n());
  }

  public void Init_by_wdoc(Json_doc jdoc) {
    this.jdoc = jdoc;
    toc_data.Make(0);
  }

  public void Bfr_arg__add(Bry_bfr bfr) {
    if (jdoc == null) return; // TEST: wdoc doesn't have jdoc
    jdoc.Root_nde().Print_as_json(tmp_bfr, 0);
    fmtr.Bld_bfr_many(
        bfr,
        toc_data.Href(),
        toc_data.Text(),
        toggle_itm.Html_toggle_btn(),
        toggle_itm.Html_toggle_hdr(),
        tmp_bfr.To_bry_and_clear());
  }

  private final Bry_fmtr fmtr =
      Bry_fmtr.new_(
          String_.Concat_lines_nl_skip_last(
              "",
              "  <h2 class='wb-section-heading' id='~{hdr_href}'>~{hdr_text}~{toggle_btn}</h2>",
              "  <div class='visualClear'></div>",
              "  <pre~{toggle_hdr}>~{json}",
              "  </pre>",
              "  </div>"),
          "hdr_href",
          "hdr_text",
          "toggle_btn",
          "toggle_hdr",
          "json");
}
public class Wdata_itemByTitle_page implements Xows_page {
  private Xoa_url_arg_hash arg_hash = new Xoa_url_arg_hash();
  private static final byte[] Arg_site = Bry_.new_a7("site"), Arg_page = Bry_.new_a7("page");

  public Bry_fmtr Html_fmtr() {
    return html_fmtr;
  }

  private Wdata_itemByTitle_cfg cfg;

  public Xows_special_meta Special_meta() {
    return Xows_special_meta_.Itm__item_by_title;
  }

  public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
    if (cfg == null)
      cfg =
          (Wdata_itemByTitle_cfg) wiki.Appe().Special_mgr().Get_or_null(Wdata_itemByTitle_cfg.Key);
    // Special:ItemByTitle/enwiki/Earth -> www.wikidata.org/wiki/Q2
    Gfo_usr_dlg usr_dlg = wiki.Appe().Usr_dlg();
    byte[] site_bry = cfg.Site_default();
    byte[] page_bry = Bry_.Empty;
    byte[] raw_bry = ttl.Full_txt_wo_qarg(); // EX: enwiki/Earth
    int args_len = url.Args().length;
    if (args_len > 0) {
      arg_hash.Load(url);
      site_bry = arg_hash.Get_val_bry_or(Arg_site, Bry_.Empty);
      page_bry = arg_hash.Get_val_bry_or(Arg_page, Bry_.Empty);
    }
    int site_bgn = Bry_finder.Find_fwd(raw_bry, Xoa_ttl.Subpage_spr);
    if (site_bgn != Bry_.NotFound) { // leaf arg is available
      int page_bgn = Bry_finder.Find_fwd(raw_bry, Xoa_ttl.Subpage_spr, site_bgn + 1);
      int raw_bry_len = raw_bry.length;
      if (page_bgn != Bry_.NotFound
          && page_bgn < raw_bry_len) { // pipe is found and not last char (EX: "enwiki/" is invalid
        site_bry = Bry_.Mid(raw_bry, site_bgn + 1, page_bgn);
        page_bry = Bry_.Mid(raw_bry, page_bgn + 1, raw_bry_len);
      }
    }
    Xoae_app app = wiki.Appe();
    if (Bry_.Len_gt_0(site_bry) && Bry_.Len_gt_0(page_bry))
      if (Navigate(usr_dlg, app, app.Wiki_mgr().Wdata_mgr(), page, site_bry, page_bry)) return;
    Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_k004();
    html_fmtr.Bld_bfr_many(
        tmp_bfr,
        "Search for items by site and title",
        "Site",
        site_bry,
        "Page",
        page_bry,
        "Search");
    page.Data_raw_(tmp_bfr.To_bry_and_rls());
    page.Html_data().Html_restricted_n_(); // [[Special:]] pages allow all HTML
  }

  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 static Bry_fmtr html_fmtr =
      Bry_fmtr.new_(
          String_.Concat_lines_nl(
              "<div id=\"mw-content-text\">",
              "<form method=\"get\" action=\"//www.wikidata.org/wiki/Special:ItemByTitle\" name=\"itembytitle\" id=\"wb-itembytitle-form1\">",
              "<fieldset>",
              "<legend>~{legend}</legend>",
              "<label for=\"wb-itembytitle-sitename\">~{site_lbl}:</label>",
              "<input id=\"wb-itembytitle-sitename\" size=\"12\" name=\"site\" value=\"~{site_val}\" accesskey=\"s\" />",
              "",
              "<label for=\"pagename\">~{page_lbl}:</label>",
              "<input id=\"pagename\" size=\"36\" class=\"wb-input-text\" name=\"page\" value=\"~{page_val}\" accesskey=\"p\" />",
              "",
              "<input id=\"wb-itembytitle-submit\" class=\"wb-input-button\" type=\"submit\" value=\"~{search_lbl}\" name=\"submit\" />",
              "</fieldset>",
              "</form>",
              "</div>",
              "<br>To change the default site, see <a href='/site/home/wiki/Help:Options/Wikibase'>Help:Options/Wikibase</a>"),
          "legend",
          "site_lbl",
          "site_val",
          "page_lbl",
          "page_val",
          "search_lbl");
}
  private void Write_page_by_tid(
      Xop_ctx ctx,
      Xoh_wtr_ctx hctx,
      byte html_gen_tid,
      Bry_bfr bfr,
      Bry_fmtr fmtr,
      byte[] page_data) {
    // if custom_html, use it and exit; needed for Default_tab
    byte[] custom_html = page.Html_data().Custom_html();
    if (custom_html != null) {
      bfr.Add(custom_html);
      return;
    }
    // temp variables
    if (root_dir_bry == null) this.root_dir_bry = app.Fsys_mgr().Root_dir().To_http_file_bry();
    Xoa_ttl page_ttl = page.Ttl();
    int page_ns_id = page_ttl.Ns().Id();
    byte page_tid = Xow_page_tid.Identify(wiki.Domain_tid(), page_ns_id, page_ttl.Page_db());
    DateAdp modified_on = page.Db().Page().Modified_on();
    byte[] modified_on_msg =
        wiki.Msg_mgr()
            .Val_by_id_args(
                Xol_msg_itm_.Id_portal_lastmodified,
                modified_on.XtoStr_fmt_yyyy_MM_dd(),
                modified_on.XtoStr_fmt_HHmm());
    byte[] page_body_class = Xoh_page_body_cls.Calc(tmp_bfr, page_ttl, page_tid);
    byte[] html_content_editable =
        wiki.Gui_mgr().Cfg_browser().Content_editable() ? Content_editable_bry : Bry_.Empty;
    byte[] page_content_sub = Xoh_page_wtr_wkr_.Bld_page_content_sub(app, wiki, page, tmp_bfr);
    byte[] js_edit_toolbar_bry =
        html_gen_tid == Xopg_page_.Tid_edit
            ? wiki.Fragment_mgr().Html_js_edit_toolbar()
            : Bry_.Empty;
    Xol_vnt_mgr vnt_mgr = wiki.Lang().Vnt_mgr();
    if (vnt_mgr.Enabled()) {
      byte[] converted_title = vnt_mgr.Convert_lang().Converted_title(); // prefer converted title
      if (converted_title
          == null) // converted title does not exist; use regular page title and convert it
      converted_title = vnt_mgr.Convert_lang().Auto_convert(vnt_mgr.Cur_itm(), page_ttl.Page_txt());
      page_ttl = Xoa_ttl.Parse(wiki, page_ttl.Ns().Id(), converted_title);
    }
    byte[] page_name =
        Xoh_page_wtr_wkr_.Bld_page_name(
            tmp_bfr, page_ttl,
            null); // NOTE: page_name does not show display_title (<i>). always pass in null
    byte[] page_display_title =
        Xoh_page_wtr_wkr_.Bld_page_name(tmp_bfr, page_ttl, page.Html_data().Display_ttl());
    page.Html_data()
        .Custom_tab_name_(
            page_name); // set tab_name to page_name; note that if null, gui code will ignore and
                        // use Ttl.Page_txt; PAGE: zh.w:釣魚臺列嶼主權問題 DATE:2015-10-05
    Xow_portal_mgr portal_mgr = wiki.Html_mgr().Portal_mgr().Init_assert();
    fmtr.Bld_bfr_many(
        bfr,
        root_dir_bry,
        Xoa_app_.Version,
        Xoa_app_.Build_date,
        app.Tcp_server().Running_str(),
        page.Db().Page().Id(),
        page.Ttl().Full_db(),
        page_name,
        page.Html_data().Page_heading().Init(page.Html_data(), page_display_title),
        modified_on_msg,
        mgr.Css_common_bry(),
        mgr.Css_wiki_bry(),
        page.Html_data().Head_mgr().Init(app, wiki, page).Init_dflts(),
        page.Lang().Dir_ltr_bry(),
        page.Html_data().Indicators(),
        page_content_sub,
        wiki.Html_mgr().Portal_mgr().Div_jump_to(),
        wiki.Xtn_mgr().Xtn_pgbnr().Write_html(page, ctx, hctx),
        page_body_class,
        html_content_editable,
        page_data,
        wdata_lang_wtr

        // sidebar divs
        ,
        portal_mgr.Div_personal_bry(),
        portal_mgr.Div_ns_bry(wiki.Utl__bfr_mkr(), page_ttl, wiki.Ns_mgr()),
        portal_mgr.Div_view_bry(
            wiki.Utl__bfr_mkr(), html_gen_tid, page.Html_data().Xtn_search_text()),
        portal_mgr.Div_logo_bry(),
        portal_mgr.Div_home_bry(),
        new Xopg_xtn_skin_fmtr_arg(page, Xopg_xtn_skin_itm_tid.Tid_sidebar),
        portal_mgr.Div_sync_bry(
            tmp_bfr, app.Api_root().Addon().Bldr().Sync().Manual_enabled(), wiki, page),
        portal_mgr.Div_wikis_bry(wiki.Utl__bfr_mkr()),
        portal_mgr.Sidebar_mgr().Html_bry(),
        mgr.Edit_rename_div_bry(page_ttl),
        page.Html_data().Edit_preview_w_dbg(),
        js_edit_toolbar_bry);
    Xoh_page_wtr_wkr_.Bld_head_end(bfr, tmp_bfr, page); // add after </head>
    Xoh_page_wtr_wkr_.Bld_html_end(bfr, tmp_bfr, page); // add after </html>		
  }
public class Xol_duration_mgr {
  private Xol_msg_itm[] interval_msgs = null;
  private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
  private final Bry_fmtr tmp_fmtr = Bry_fmtr.New__tmp();

  public Xol_duration_mgr(Xol_lang_itm lang) {
    this.lang = lang;
  }

  private Xol_lang_itm lang;

  public Xol_interval_itm[] Get_duration_intervals(long seconds, Xol_duration_itm[] intervals) {
    if (intervals == null) intervals = Xol_duration_itm_.Ary_default;
    Array_.Sort(intervals, Xol_duration_itm_sorter.Instance);
    int intervals_len = intervals.length;
    long val = seconds;
    List_adp rv = List_adp_.New();
    for (int i = 0; i < intervals_len; i++) {
      Xol_duration_itm itm = intervals[i];
      long itm_seconds = itm.Seconds();
      val = seconds / itm_seconds;
      if (val > 0
          || (i == intervals_len - 1
              && rv.Count()
                  == 0) // always add one seg; EX: 40 seconds, but minutes requested -> 0 minutes;
                        // DATE:2014-05-10
      ) {
        seconds -= val * itm_seconds;
        rv.Add(new Xol_interval_itm(itm, val));
      }
    }
    return (Xol_interval_itm[]) rv.To_ary(Xol_interval_itm.class);
  }

  public byte[] Format_durations(Xop_ctx ctx, long seconds, Xol_duration_itm[] ary) {
    if (interval_msgs == null) Format_durations_init();
    Xol_interval_itm[] intervals = Get_duration_intervals(seconds, ary);
    int intervals_len = intervals.length;
    byte[][] msgs_ary = new byte[intervals_len][];
    for (int i = 0; i < intervals_len; i++) {
      Xol_interval_itm interval = intervals[i];
      Xol_msg_itm msg_itm = interval_msgs[interval.Duration_itm().Tid()];
      byte[] msg_bry = msg_itm.Fmt(tmp_bfr, tmp_fmtr, interval.Val());
      msg_bry = ctx.Wiki().Parser_mgr().Main().Parse_text_to_html(ctx, msg_bry);
      msgs_ary[i] = msg_bry;
    }
    return List_to_str(msgs_ary);
  }

  private byte[] Msg_and, Msg_word_separator, Msg_comma_separator;

  private void Format_durations_init() {
    Xol_msg_mgr msg_mgr = lang.Msg_mgr();
    int len = Xol_duration_itm_.Ary_default.length;
    interval_msgs = new Xol_msg_itm[len];
    for (int i = 0; i < len; i++) {
      Xol_duration_itm itm = Xol_duration_itm_.Ary_default[i];
      byte[] msg_key = Bry_.Add(Bry_duration, itm.Name_bry());
      interval_msgs[i] = msg_mgr.Itm_by_key_or_new(msg_key);
    }
  }

  private static final byte[] Bry_duration = Bry_.new_a7("duration-");

  private void List_to_str_init() {
    Xol_msg_mgr msg_mgr = lang.Msg_mgr();
    Msg_and = msg_mgr.Val_by_str_or_empty("and");
    Msg_word_separator = msg_mgr.Val_by_str_or_empty("word-separator");
    Msg_comma_separator = msg_mgr.Val_by_str_or_empty("comma-separator");
  }

  public byte[] List_to_str(byte[][] segs_ary) {
    int len = segs_ary.length;
    switch (len) {
      case 0:
        return Bry_.Empty;
      case 1:
        return segs_ary[0];
      default:
        if (Msg_and == null) List_to_str_init();
        int last_idx = len - 1;
        for (int i = 0; i < last_idx; i++) {
          if (i != 0) tmp_bfr.Add(Msg_comma_separator);
          tmp_bfr.Add(segs_ary[i]);
        }
        tmp_bfr.Add(Msg_and).Add(Msg_word_separator).Add(segs_ary[last_idx]);
        return tmp_bfr.To_bry_and_clear();
    }
  }
}
Beispiel #7
0
class Hiero_html_wtr {
  private Hiero_phoneme_mgr phoneme_mgr;
  private Bry_bfr temp_bfr = Bry_bfr.reset_(255);

  public Hiero_html_wtr(Hiero_html_mgr mgr, Hiero_phoneme_mgr phoneme_mgr) {
    this.phoneme_mgr = phoneme_mgr;
  }

  public void Init_for_write(Xoh_wtr_ctx hctx) {
    this.hiero_img_dir =
        hctx.Mode_is_hdump()
            ? gplx.xowa.html.hdumps.abrvs.Xohd_abrv_.Key_hiero_dir
            : Hiero_xtn_mgr.Img_src_dir;
  }

  private byte[] hiero_img_dir = null;

  public void Hr(Bry_bfr bfr) {
    bfr.Add(Html_tag_.Hr_inl).Add_byte_nl();
  }

  public void Tbl_eol(Bry_bfr bfr) {
    bfr.Add(Tbl_eol_bry);
  }

  public byte[] Td_height(int height) {
    return temp_bfr.Add(Option_bgn_bry)
        .Add_int_variable(height)
        .Add(Option_end_bry)
        .Xto_bry_and_clear();
  }

  private static final byte[] Option_bgn_bry = Bry_.new_a7("height: "),
      Option_end_bry = Bry_.new_a7("px;");

  public void Td(Bry_bfr bfr, byte[] glyph) {
    bfr.Add(Td_bgn_bry).Add(glyph).Add(Td_end_bry);
  }

  private static final byte[] Td_bgn_bry = Bry_.new_a7("\n          <td>"),
      Td_end_bry = Bry_.new_a7("\n          </td>");

  public void Cartouche_bgn(Bry_bfr bfr) {
    bfr.Add(Cartouche_bgn_lhs_bry)
        .Add_int_variable((Hiero_html_mgr.Cartouche_width * Hiero_html_mgr.scale) / 100)
        .Add(Cartouche_bgn_rhs_bry);
  }

  private static final String Tbl_bgn_str = "<table class=\"mw-hiero-table\">";
  private static final byte[]
      Cartouche_bgn_lhs_bry =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last(
                  "",
                  "          <td>",
                  "            " + Tbl_bgn_str,
                  "              <tr>",
                  "                <td class='mw-hiero-box' style='height: ")),
      Cartouche_bgn_rhs_bry =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last(
                  "px;'>",
                  "                </td>",
                  "              </tr>",
                  "              <tr>",
                  "                <td>",
                  "                  " + Tbl_bgn_str,
                  "                    <tr>"));

  public void Cartouche_end(Bry_bfr bfr) {
    bfr.Add(Cartouche_end_lhs_bry)
        .Add_int_variable((Hiero_html_mgr.Cartouche_width * Hiero_html_mgr.scale) / 100)
        .Add(Cartouche_end_rhs_bry);
  }

  private static final byte[]
      Cartouche_end_lhs_bry =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last(
                  "",
                  "                    </tr>",
                  "                  </table>",
                  "                </td>",
                  "              </tr>",
                  "              <tr>",
                  "                <td class='mw-hiero-box' style='height: ")),
      Cartouche_end_rhs_bry =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last(
                  "px;'>",
                  "                </td>",
                  "              </tr>",
                  "            </table>",
                  "          </td>"));

  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);
  }

  private static final Bry_fmtr cartouche_img_fmtr =
      Bry_fmtr.new_(
          String_.Concat(
              "\n            <img src='~{path}hiero_~{code}.png'",
              " height='~{height}' title='~{title}'",
              " alt='~{title}' />"),
          "path",
          "code",
          "height",
          "title");

  public void Tbl_inner(Bry_bfr html_bfr, Bry_bfr text_bfr) {
    html_bfr.Add(Tbl_inner_bgn)
        .Add_bfr_and_clear(text_bfr)
        .Add(Tbl_inner_end); // 	$html .= self::TABLE_START . "<tr>\n" . $tableContentHtml .
    // '</tr></table>';
  }

  private static final byte[]
      Tbl_inner_bgn =
          Bry_.new_u8(
              String_.Concat_lines_nl_skip_last(
                  "      <table class=\"mw-hiero-table\">", "        <tr>")),
      Tbl_inner_end =
          Bry_.new_u8(String_.Concat_lines_nl_skip_last("", "        </tr>", "      </table>"));

  public void Tbl_outer(Bry_bfr bfr, Bry_bfr html_bfr) {
    bfr.Add(Outer_tbl_bgn);
    bfr.Add_bfr_and_clear(html_bfr);
    bfr.Add(Outer_tbl_end);
  }

  private static final byte[]
      Outer_tbl_bgn =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last(
                  "<table class='mw-hiero-table mw-hiero-outer' dir='ltr'>",
                  "  <tr>",
                  "    <td>",
                  "")),
      Outer_tbl_end =
          Bry_.new_a7(
              String_.Concat_lines_nl_skip_last("", "    </td>", "  </tr>", "</table>", ""));

  public byte[] Img_phoneme(byte[] img_cls, byte[] td_height, byte[] glyph_esc, byte[] code) {
    byte[] code_esc = Html_utl.Escape_html_as_bry(temp_bfr, code);
    byte[] img_title =
        temp_bfr.Add(code_esc)
            .Add_byte_space()
            .Add_byte(Byte_ascii.Brack_bgn)
            .Add(glyph_esc)
            .Add_byte(Byte_ascii.Brack_end)
            .Xto_bry_and_clear(); // "~{code} [~{glyph}]"
    return Img(img_cls, td_height, glyph_esc, code_esc, img_title);
  }

  public byte[] Img_file(byte[] img_cls, byte[] td_height, byte[] glyph_esc) {
    return Img(img_cls, td_height, glyph_esc, glyph_esc, glyph_esc);
  }

  private byte[] Img(
      byte[] img_cls, byte[] td_height, byte[] glyph, byte[] img_src_name, byte[] img_title) {
    byte[] img_src = Bld_img_src(hiero_img_dir, img_src_name);
    return glyph_img_fmtr.Bld_bry_many(
        temp_bfr, img_cls, Hiero_html_mgr.Image_margin, td_height, img_src, img_title, glyph);
  }

  private static final byte[] Tbl_eol_bry =
      Bry_.new_a7(
          String_.Concat_lines_nl_skip_last(
              "", "        </tr>", "      </table>", "      " + Tbl_bgn_str, "        <tr>"));
  private static final Bry_fmtr glyph_img_fmtr =
      Bry_fmtr.new_(
          "\n            <img ~{img_cls}style='margin: ~{img_margin}px; ~{option}' src='~{img_src}' title='~{img_title}' alt='~{glyph}' />",
          "img_cls",
          "img_margin",
          "option",
          "img_src",
          "img_title",
          "glyph");

  public byte[] Void(boolean half) { // render void
    int width = Hiero_html_mgr.Max_height;
    if (half) width /= 2;
    return void_fmtr.Bld_bry_many(temp_bfr, width);
  }

  private static final Bry_fmtr void_fmtr =
      Bry_fmtr.new_(
          String_.Concat_lines_nl_skip_last(
              "",
              "            <table class=\"mw-hiero-table\" style=\"width: ~{width}px;\">",
              "              <tr>",
              "                <td>&#160;",
              "                </td>",
              "              </tr>",
              "            </table>"),
          "width");

  private static byte[] Bld_img_src(byte[] hiero_img_dir, byte[] name) {
    return Bry_.Add(hiero_img_dir, Img_src_prefix, name, Img_src_ext);
  }

  private static final byte[] Img_src_prefix = Bry_.new_a7("hiero_"),
      Img_src_ext = Bry_.new_a7(".png");
}
 public static byte[] Bld_fmtr_wiki(
     Bry_fmtr fmtr, Bry_bfr wrdx_bfr, byte[] wiki_domain, byte[] page_domain) {
   return Bry_.Eq(wiki_domain, page_domain)
       ? Bry_.Empty // same domain; return "";
       : fmtr.Bld_bry_many(wrdx_bfr, page_domain);
 }
public class Xow_popup_html_mkr {
  private Xoae_app app;
  private Xowe_wiki wiki;

  public Bry_fmtr Fmtr_popup() {
    return fmtr_popup;
  }

  private Bry_fmtr fmtr_popup = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_popup_keys);

  public Bry_fmtr Fmtr_viewed() {
    return fmtr_viewed;
  }

  private Bry_fmtr fmtr_viewed = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_viewed_keys);

  public Bry_fmtr Fmtr_wiki() {
    return fmtr_wiki;
  }

  private Bry_fmtr fmtr_wiki = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_wiki_keys);

  public Bry_fmtr Fmtr_next_sect() {
    return fmtr_next_sect;
  }

  private Bry_fmtr fmtr_next_sect = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_next_sect_keys);

  public void Output_js_clean_(boolean v) {
    output_js_clean = v;
  }

  private boolean output_js_clean = true;

  public void Output_tidy_(boolean v) {
    output_tidy = v;
  }

  private boolean output_tidy = true;

  public void Ctor(Xoae_app app, Xowe_wiki wiki) {
    this.wiki = wiki;
    this.app = app;
    wiki.Eval_mgr().Eval_mgr_(fmtr_popup, fmtr_viewed, fmtr_wiki, fmtr_next_sect);
  }

  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();
  }
}