Greasy Fork

Greasy Fork is available in English.

NGA Filter

troll must die

当前为 2020-02-02 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        NGA Filter
// @namespace   http://greasyfork.icu/users/263018
// @version     1.0.1
// @author      snyssss
// @description troll must die

// @match       *bbs.nga.cn/thread.php?fid=*
// @match       *bbs.nga.cn/read.php?tid=*
// @match       *bbs.nga.cn/nuke.php?*
// @match       *ngabbs.com/thread.php?fid=*
// @match       *ngabbs.com/read.php?tid=*
// @match       *ngabbs.com/nuke.php?*

// @grant       GM_addStyle
// @grant       GM_setValue
// @grant       GM_getValue

// @noframes
// ==/UserScript==

(n => {
  "use strict";

  if (n === undefined) return;

  const key = "NGAFilter";

  // 数据
  const data = (() => {
    const d = {
      tags: {},
      users: {},
      options: {
        filterMode: 0,
        keyword: ""
      }
    };
    const v = GM_getValue(key);
    if (typeof v !== "object") {
      return d;
    }
    return Object.assign(d, v);
  })();

  // 保存数据
  const saveData = () => {
    GM_setValue(key, data);
  };

  // 增加标记
  const addTag = name => {
    const tag = Object.values(data.tags).find(item => item.name === name);

    if (tag) return tag.id;

    const id =
      Math.max(...Object.values(data.tags).map(item => item.id), 0) + 1;

    const hash = (() => {
      let h = 5381;
      for (var i = 0; i < name.length; i++) {
        h = ((h << 5) + h + name.charCodeAt(i)) & 0xffffffff;
      }
      return h;
    })();

    const hex = Math.abs(hash).toString(16) + "000000";

    const hsv = [
      `0x${hex.substr(2, 2)}` / 255,
      `0x${hex.substr(2, 2)}` / 255 / 2 + 0.25,
      `0x${hex.substr(4, 2)}` / 255 / 2 + 0.25
    ];

    const rgb = n.hsvToRgb(hsv[0], hsv[1], hsv[2]);

    const color = ["#", ...rgb].reduce((a, b) => {
      return a + ("0" + b.toString(16)).slice(-2);
    });

    data.tags[id] = {
      id,
      name,
      color,
      enabled: true
    };

    saveData();

    return id;
  };

  // 增加用户
  const addUser = (id, name = null, tags = [], isEnabled = true) => {
    if (data.users[id]) return data.users[id];

    data.users[id] = {
      id,
      name,
      tags,
      enabled: isEnabled
    };

    saveData();

    return data.users[id];
  };

  // 旧版本数据迁移
  {
    const dataKey = "troll_data";
    const modeKey = "troll_mode";
    const keywordKey = "troll_keyword";

    if (localStorage.getItem(dataKey)) {
      let trollMap = (function() {
        try {
          return JSON.parse(localStorage.getItem(dataKey)) || {};
        } catch (e) {}

        return {};
      })();

      let filterMode = ~~localStorage.getItem(modeKey);

      let filterKeyword = localStorage.getItem(keywordKey) || "";

      // 整理标签
      [...new Set(Object.values(trollMap).flat())].forEach(item =>
        addTag(item)
      );

      // 整理用户
      Object.keys(trollMap).forEach(item => {
        addUser(
          item,
          null,
          trollMap[item].map(tag => addTag(tag))
        );
      });

      data.options.filterMode = filterMode ? 0 : 1;
      data.options.keyword = filterKeyword;

      localStorage.removeItem(dataKey);
      localStorage.removeItem(modeKey);
      localStorage.removeItem(keywordKey);

      saveData();
    }
  }

  // 编辑用户标记
  const editUser = (() => {
    let window;
    return (uid, name, callback) => {
      if (window === undefined) {
        window = n.createCommmonWindow();
      }

      const user = data.users[uid];

      const content = document.createElement("div");

      content.className = "w100";
      content.innerHTML = `
        <table class="filter-table" style="min-width: 400px;">
            <tbody>
                ${Object.values(data.tags)
                  .map(
                    tag => `
                        <tr>
                            <td>
                                <b class="block_txt nobr" style="background:${
                                  tag.color
                                }; color:#fff; margin: 0.1em 0.2em;">${
                      tag.name
                    }</b>
                            </td>
                            <td>
                                <input type="checkbox" value="${
                                  tag.id
                                }" ${user &&
                      user.tags.find(item => item === tag.id) &&
                      "checked"}/>
                            </td>
                        </tr>
                    `
                  )
                  .join("")}
            </tbody>
            <tfoot>
                <tr>
                <td colspan="2">
                    <input placeholder="一次性添加多个标记用&quot;|&quot;隔开,不会添加重名标记" style="width: -webkit-fill-available;" />
                </td>
                </tr>
            </tfoot>
        </table>
        <div style="margin: 10px 0;">
            <button>${user && user.enabled === false ? "启用" : "禁用"}</button>
            <div class="right_">
                <button>删除</button>
                <button>保存</button>
            </div>
        </div>
    `;

      const actions = content.getElementsByTagName("button");

      actions[0].onclick = () => {
        actions[0].innerText =
          actions[0].innerText === "禁用" ? "启用" : "禁用";
      };

      actions[1].onclick = () => {
        if (confirm("是否确认?")) {
          delete data.users[uid];

          saveData();

          callback && callback();

          window._.hide();
        }
      };

      actions[2].onclick = () => {
        if (confirm("是否确认?")) {
          const values = [...content.getElementsByTagName("input")];
          const newTags = values[values.length - 1].value
            .split("|")
            .filter(item => item.length)
            .map(item => addTag(item));
          const tags = [
            ...new Set(
              values
                .filter(item => item.type === "checkbox" && item.checked)
                .map(item => ~~item.value)
                .concat(newTags)
            )
          ].sort();

          if (user) {
            user.tags = tags;
            user.enabled = actions[0].innerText === "禁用";
          } else {
            addUser(uid, name, tags, actions[0].innerText === "禁用");
          }

          saveData();

          callback && callback();

          window._.hide();
        }
      };

      if (user === undefined) {
        actions[1].style = "display: none;";
      }

      window._.addContent(null);
      window._.addTitle(`编辑标记 - ${name ? name : "#" + uid}`);
      window._.addContent(content);
      window._.show();
    };
  })();

  // 过滤
  const reFilter = (() => {
    const tPage = location.pathname === "/thread.php";
    const pPage = location.pathname === "/read.php";
    const uPage = location.pathname === "/nuke.php";

    const func = (() => {
      if (tPage) {
        return () => {
          const tData = n.topicArg.data;

          Object.values(tData).forEach(item => {
            const uid =
              item[2].search.match(/uid=(\S+)/).length &&
              item[2].search.match(/uid=(\S+)/)[1];

            const user = data.users[uid];

            const tags = user ? user.tags.map(tag => data.tags[tag]) : [];

            const isBlock =
              user &&
              user.enabled &&
              (tags.length === 0 || tags.filter(tag => tag.enabled).length);

            item.contentC = item[1];

            item.contentB = item.contentB || item.contentC.innerHTML;

            item.containerC =
              item.containerC || item.contentC.parentNode.parentNode;

            item.containerC.style =
              isBlock && data.options.filterMode === 0 ? "display: none;" : "";

            item.contentC.style =
              isBlock && data.options.filterMode === 1
                ? "text-decoration: line-through;"
                : "";
          });
        };
      } else if (pPage) {
        return () => {
          const pData = n.postArg.data;

          Object.values(pData).forEach(item => {
            if (typeof item.i === "number") {
              item.actionC =
                item.actionC ||
                (() => {
                  const ele = item.uInfoC.firstElementChild.lastElementChild;

                  ele.onclick = null;

                  return ele;
                })();

              item.tagC =
                item.tagC ||
                (() => {
                  const tc = document.createElement("div");

                  tc.className = "filter-tags";

                  item.uInfoC.appendChild(tc);

                  return tc;
                })();
            }

            item.pName =
              item.pName ||
              item.uInfoC.getElementsByClassName("author")[0].innerText;

            item.reFilter =
              item.reFilter ||
              (() => {
                const user = data.users[item.pAid];

                const tags = user ? user.tags.map(tag => data.tags[tag]) : [];

                const isBlock =
                  user &&
                  user.enabled &&
                  (tags.length === 0 || tags.filter(tag => tag.enabled).length);

                item.avatarC =
                  item.avatarC ||
                  (() => {
                    const tc = document.createElement("div");

                    const avatar = document.getElementById(
                      `posteravatar${item.i}`
                    );

                    if (avatar) {
                      avatar.parentNode.insertBefore(tc, avatar.nextSibling);

                      tc.appendChild(avatar);
                    }

                    return tc;
                  })();

                item.contentB = item.contentB || item.contentC.innerHTML;

                item.containerC =
                  item.containerC ||
                  (() => {
                    let temp = item.contentC;

                    while (
                      temp.className !== "forumbox postbox" &&
                      temp.className !== "comment_c left"
                    ) {
                      temp = temp.parentNode;
                    }

                    return temp;
                  })();

                item.containerC.style.display =
                  isBlock && data.options.filterMode === 0 ? "none" : "";

                item.contentC.innerHTML =
                  isBlock && data.options.filterMode === 1
                    ? `
                    <div class="lessernuke" style="background: #81C7D4; border-color: #66BAB7;">
                        <span class="crimson">Troll must die.</span>
                        <a href="javascript:void(0)" onclick="[...document.getElementsByName('troll_${user.id}')].forEach(item => item.style.display = '')">点击查看</a>
                        <div style="display: none;" name="troll_${user.id}">
                            ${item.contentB}
                        </div>
                    </div>`
                    : item.contentB;

                item.avatarC.style.display = isBlock ? "none" : "";

                if (item.actionC) {
                  item.actionC.style =
                    user && user.enabled
                      ? "background: #cb4042;"
                      : "background: #aaa;";
                }

                if (item.tagC) {
                  item.tagC.style.display = tags.length ? "" : "none";
                  item.tagC.innerHTML = tags
                    .map(
                      tag =>
                        `<b class="block_txt nobr" style="background:${tag.color}; color:#fff; margin: 0.1em 0.2em;">${tag.name}</b>`
                    )
                    .join("");
                }
              });

            if (item.actionC) {
              item.actionC.onclick =
                item.actionC.onclick ||
                (e => {
                  if (item.pAid < 0) return;

                  const user = data.users[item.pAid];

                  if (e.ctrlKey) {
                    editUser(item.pAid, item.pName, item.reFilter);
                  } else {
                    if (user) {
                      if (user.tags.length) {
                        user.enabled = !user.enabled;
                        user.name = item.pName;
                      } else {
                        delete data.users[user.id];
                      }
                    } else {
                      addUser(item.pAid, item.pName);
                    }

                    saveData();
                    item.reFilter();
                  }
                });
            }

            item.reFilter();
          });
        };
      } else if (uPage) {
        return () => {
          const container = document.getElementById("ucp_block");

          if (container.firstChild) {
            const uid = container.innerText.match(/用户ID\s*:\s*(\S+)/)[1];

            const name = container.innerText.match(/用户名\s*:\s*(\S+)/)[1];

            container.tagC =
              container.tagC ||
              (() => {
                const c = document.createElement("span");

                c.innerHTML = `
                    <h2 class="catetitle">:: ${name} 的标记 ::</h2>
                    <div class="cateblock" style="text-align: left; line-height: 1.8em;">
                        <div class="contentBlock" style="padding: 5px 10px;">
                            <span>
                                <ul class="actions" style="padding: 0px; margin: 0px;">
                                    <li style="padding-right: 5px;">
                                        <span>
                                            <a href="javascript: void(0);">[编辑 ${name} 的标记]</a>
                                        </span>
                                    </li>
                                    <div class="clear"></div>
                                </ul>
                            </span>
                            <div class="filter-tags"></div>
                            <div class="clear"></div>
                        </div>
                    </div>
                `;

                c.getElementsByTagName("a")[0].onclick = () => {
                  editUser(uid, name, container.refresh);
                };

                container.firstChild.insertBefore(
                  c,
                  container.firstChild.childNodes[1]
                );

                return c.getElementsByClassName("filter-tags")[0];
              })();

            container.refresh = () => {
              container.tagC.innerHTML = data.users[uid].tags
                .map(
                  tag =>
                    `<b class="block_txt nobr" style="background:${data.tags[tag].color}; color:#fff; margin: 0.1em 0.2em;">${data.tags[tag].name}</b>`
                )
                .join("");
            };

            container.refresh();
          }
        };
      }

      return () => {};
    })();

    const observer = new MutationObserver(mutations => {
      if (mutations.find(mutation => mutation.addedNodes.length)) {
        func();
      }
    });

    if (tPage) {
      observer.observe(document.getElementById("topicrows"), {
        childList: true
      });
    } else if (pPage) {
      observer.observe(document.getElementById("m_posts_c"), {
        childList: true
      });
    } else if (uPage) {
      observer.observe(document.getElementById("ucp_block"), {
        childList: true
      });
    }

    func();

    return func;
  })();

  // STYLE
  GM_addStyle(`
    .filter-tags {
        margin: 2px -0.2em 0;
        text-align: left;
    }
    .filter-table {
        border: 1px solid #ead5bc;
        border-left: none;
        border-bottom: none;
        width: 99.95%;
    }
    .filter-table thead {
        background-color: #591804;
        color: #fff8e7;
    }
    .filter-table tbody tr {
        background-color: #fff0cd;
    }
    .filter-table tbody tr:nth-of-type(odd) {
        background-color: #fff8e7;
    }
    .filter-table td {
        border: 1px solid #ead5bc;
        border-top: none;
        border-right: none;
        padding: 6px;
    }
  `);

  // UI
  const u = (() => {
    const modules = {};

    const tabContainer = (() => {
      const c = document.createElement("div");

      c.className = "w100";
      c.innerHTML = `
          <div class="right_" style="margin-bottom: 5px;">
              <table class="stdbtn" cellspacing="0">
                  <tbody>
                      <tr></tr>
                  </tbody>
              </table>
          </div>
          <div class="clear"></div>
          `;

      return c;
    })();

    const tabPanelContainer = (() => {
      const c = document.createElement("div");

      c.style =
        "min-width: 20vw; max-width: 80vw; max-height: 80vh; overflow: auto;";
      c.innerHTML = `
            `;

      return c;
    })();

    const content = (() => {
      const c = document.createElement("div");

      c.append(tabContainer);
      c.append(tabPanelContainer);

      return c;
    })();

    const addModule = (() => {
      const tc = tabContainer.getElementsByTagName("tr")[0];
      const cc = tabPanelContainer;

      return module => {
        const tabBox = document.createElement("td");

        tabBox.innerHTML = `<a href="javascript:void(0)" class="nobr silver">${module.name}</a>`;

        const tab = tabBox.childNodes[0];

        const toggle = () => {
          Object.values(modules).forEach(item => {
            if (item.tab === tab) {
              item.tab.className = "nobr";
              item.content.style = "display: block";
              item.refresh();
            } else {
              item.tab.className = "nobr silver";
              item.content.style = "display: none";
            }
          });
        };

        tc.append(tabBox);
        cc.append(module.content);

        tab.onclick = toggle;

        modules[module.name] = {
          ...module,
          tab,
          toggle
        };

        return modules[module.name];
      };
    })();

    return {
      content,
      modules,
      addModule
    };
  })();

  // 屏蔽列表
  const blockModule = (() => {
    const content = (() => {
      const c = document.createElement("div");

      c.style = "display: none";
      c.innerHTML = `
        <table class="filter-table">
            <thead>
                <tr>
                    <td>
                        <b style="margin: 0.1em 0.2em;">昵称</b>
                    </td>
                    <td>
                        <b style="margin: 0.1em 0.2em;">标记</b>
                    </td>
                    <td>
                        <b style="margin: 0.1em 0.2em;">操作</b>
                    </td>
                </tr>
            </thead>
            <tbody></tbody>
        </table>
            `;

      return c;
    })();

    const refresh = (() => {
      const container = content.getElementsByTagName("tbody")[0];

      const func = () => {
        container.innerHTML = "";

        Object.values(data.users).forEach(item => {
          const tc = document.createElement("tr");

          tc.refresh = () => {
            if (data.users[item.id]) {
              tc.innerHTML = `
                <tr>
                    <td>
                        <a href="/nuke.php?func=ucp&uid=${
                          item.id
                        }" class="b nobr">[${
                item.name ? "@" + item.name : "#" + item.id
              }]</a>
                    </td>
                    <td>
                        ${item.tags
                          .map(tag => {
                            if (data.tags[tag]) {
                              return `<b class="block_txt nobr" style="background:${data.tags[tag].color}; color:#fff; margin: 0.1em 0.2em;">${data.tags[tag].name}</b>`;
                            }
                          })
                          .join("")}
                    </td>
                    <td class="nobr">
                        <button>编辑</button>
                        <button>${item.enabled ? "禁用" : "启用"}</button>
                        <button>删除</button>
                    </td>
                </tr>
                `;

              const actions = tc.getElementsByTagName("button");

              actions[0].onclick = () => {
                editUser(item.id, item.name, tc.refresh);
              };

              actions[1].onclick = () => {
                data.users[item.id].enabled = !data.users[item.id].enabled;
                actions[1].innerHTML = data.users[item.id].enabled
                  ? "禁用"
                  : "启用";

                saveData();
                reFilter();
              };

              actions[2].onclick = () => {
                if (confirm("是否确认?")) {
                  delete data.users[item.id];
                  container.removeChild(tc);

                  saveData();
                  reFilter();
                }
              };
            } else {
              tc.remove();
            }
          };

          tc.refresh();

          container.appendChild(tc);
        });
      };

      return func;
    })();

    return {
      name: "屏蔽列表",
      content,
      refresh
    };
  })();

  // 标记设置
  const tagModule = (() => {
    const content = (() => {
      const c = document.createElement("div");

      c.style = "display: none";
      c.innerHTML = `
        <table class="filter-table">
            <thead>
                <tr>
                    <td>
                        <b style="margin: 0.1em 0.2em;">标记</b>
                    </td>
                    <td>
                        <b style="margin: 0.1em 0.2em;">列表</b>
                    </td>
                    <td>
                        <b style="margin: 0.1em 0.2em;">操作</b>
                    </td>
                </tr>
            </thead>
            <tbody></tbody>
        </table>
            `;

      return c;
    })();

    const refresh = (() => {
      const container = content.getElementsByTagName("tbody")[0];

      const func = () => {
        container.innerHTML = "";

        Object.values(data.tags).forEach(item => {
          const tc = document.createElement("tr");

          tc.innerHTML = `
            <tr>
                <td>
                    <b class="block_txt nobr" style="background:${
                      item.color
                    }; color:#fff; margin: 0.1em 0.2em;">${item.name}</b>
                </td>
                <td>
                    <button>${
                      Object.values(data.users).filter(user =>
                        user.tags.find(tag => tag === item.id)
                      ).length
                    }
                    </button>
                    <div style="display: none;">
                        ${Object.values(data.users)
                          .filter(user =>
                            user.tags.find(tag => tag === item.id)
                          )
                          .map(
                            user =>
                              `<a href="/nuke.php?func=ucp&uid=${
                                user.id
                              }" class="b nobr">[${
                                user.name ? "@" + user.name : "#" + user.id
                              }]</a>`
                          )
                          .join("")}
                    </div>
                </td>
                <td class="nobr">
                    <button>${item.enabled ? "禁用" : "启用"}</button>
                    <button>删除</button>
                </td>
            </tr>
            `;

          const actions = tc.getElementsByTagName("button");

          actions[0].onclick = (() => {
            let hide = true;
            return () => {
              hide = !hide;
              actions[0].nextElementSibling.style = `display: ${
                hide ? "none" : "block"
              };`;
            };
          })();

          actions[1].onclick = () => {
            data.tags[item.id].enabled = !data.tags[item.id].enabled;
            actions[1].innerHTML = data.tags[item.id].enabled ? "禁用" : "启用";

            saveData();
            reFilter();
          };

          actions[2].onclick = () => {
            if (confirm("是否确认?")) {
              delete data.tags[item.id];

              Object.values(data.users).forEach(user => {
                const index = user.tags.findIndex(tag => tag === item.id);
                if (index >= 0) {
                  user.tags.splice(index, 1);
                }
              });

              container.removeChild(tc);

              saveData();
              reFilter();
            }
          };

          container.appendChild(tc);
        });
      };

      return func;
    })();

    return {
      name: "标记设置",
      content,
      refresh
    };
  })();

  // 通用设置
  const commonModule = (() => {
    const content = (() => {
      const c = document.createElement("div");

      c.style = "display: none";

      return c;
    })();

    const refresh = (() => {
      const container = content;

      const func = () => {
        container.innerHTML = "";

        // 屏蔽关键词
        {
          const tc = document.createElement("div");

          tc.innerHTML += `
            <div>过滤关键词,用"|"隔开</div>
            <div>
                <input value="${data.options.keyword}"/>
                <button>确认</button>
            </div>
          `;

          const actions = tc.getElementsByTagName("button");

          actions[0].onclick = () => {
            const v = actions[0].previousElementSibling.value;

            data.options.keyword = v;

            saveData();
            reFilter();
          };

          container.appendChild(tc);
        }

        // 过滤方式
        {
          const tc = document.createElement("div");

          tc.innerHTML += `
            <br/>
            <div>过滤方式</div>
            <div>
                <input type="radio" name="filterType" ${data.options
                  .filterMode === 0 && "checked"}>
                <span>隐藏</span>
                <input type="radio" name="filterType" ${data.options
                  .filterMode === 1 && "checked"}>
                <span>标记</span>
                <button>确认</button>
            </div>
          `;

          const actions = tc.getElementsByTagName("button");

          actions[0].onclick = () => {
            const values = document.getElementsByName("filterType");

            for (let i = 0, length = values.length; i < length; i++) {
              if (values[i].checked) {
                data.options.filterMode = i;
                break;
              }
            }

            saveData();
            reFilter();
          };

          container.appendChild(tc);
        }

        // 删除没有标记的用户
        {
          const tc = document.createElement("div");

          tc.innerHTML += `
            <br/>
            <div>
                <button>删除没有标记的用户</button>
            </div>
          `;

          const actions = tc.getElementsByTagName("button");

          actions[0].onclick = () => {
            if (confirm("是否确认?")) {
              Object.values(data.users).forEach(item => {
                if (item.tags.length === 0) {
                  delete data.users[item.id];
                }
              });

              saveData();
              reFilter();
            }
          };

          container.appendChild(tc);
        }

        // 删除没有用户的标记
        {
          const tc = document.createElement("div");

          tc.innerHTML += `
            <br/>
            <div>
                <button>删除没有用户的标记</button>
            </div>
          `;

          const actions = tc.getElementsByTagName("button");

          actions[0].onclick = () => {
            if (confirm("是否确认?")) {
              Object.values(data.tags).forEach(item => {
                if (
                  Object.values(data.users).filter(user =>
                    user.tags.find(tag => tag === item.id)
                  ).length === 0
                ) {
                  delete data.tags[item.id];
                }
              });

              saveData();
              reFilter();
            }
          };

          container.appendChild(tc);
        }
      };

      return func;
    })();

    return {
      name: "通用设置",
      content,
      refresh
    };
  })();

  u.addModule(blockModule).toggle();
  u.addModule(tagModule);
  u.addModule(commonModule);

  // 增加菜单项
  (() => {
    const title = "屏蔽/标记";
    let window;

    n.mainMenu.addItemOnTheFly(title, null, () => {
      if (window === undefined) {
        window = n.createCommmonWindow();
      }

      window._.addContent(null);
      window._.addTitle(title);
      window._.addContent(u.content);
      window._.show();
    });
  })();
})(commonui);

// commonui.postArg
// commonui.topicArg