미디어위키:Gadget-dictionary.js

삼쩌모 (토론 | 기여)님의 2025년 6월 29일 (일) 03:58 판

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
/* ▣ Dictionary “검색 전용” 가젯 ▣
   위키문법을 서버 파서로 HTML 변환 후 출력
-------------------------------------------------- */
mw.loader.using(
  ['oojs-ui-core', 'oojs-ui.styles.icons-interactions', 'mediawiki.api'],
  function () {

    /* ─ 1. JSON → {소문자 단어: 정의(wikitext)} ─ */
    var jsonNode = document.getElementById('dictionary-json');
    if (!jsonNode) return;
    var raw  = JSON.parse(jsonNode.textContent);
    var dict = {};
    Object.keys(raw).forEach(k => dict[k.toLowerCase()] = raw[k]);

    /* ─ 2. 위키텍스트 → HTML 변환용 함수 (캐시 포함) ─ */
    const api   = new mw.Api();
    const cache = Object.create(null);      // wt → html

    function parseWT(wt) {
      if (cache[wt]) return $.Deferred().resolve(cache[wt]).promise();
      return api.get({
        action: 'parse',
        format: 'json',
        prop:   'text',
        text:   wt,
        contentmodel: 'wikitext',
        disablelimitreport: 1
      }).then(data => {
        const html = data?.parse?.text['*'] || mw.html.escape(wt);
        cache[wt] = html;
        return html;
      }, () => mw.html.escape(wt));         // 오류 시 그대로 출력
    }

    /* ─ 3. 한 번만 결과·버튼 CSS 삽입 ─ */
    if (!document.getElementById('dict-card-style')) {
      mw.util.addCSS(`
.oo-ui-inputWidget-input, .oo-ui-buttonElement-button{
  background:light-dark(#fff,rgb(30,30,30));color:var(--text);
  border:1px solid light-dark(#ccc,#555);height:36px}
.oo-ui-inputWidget-input{border-radius:5px 0 0 5px}
.oo-ui-buttonElement-button{border-radius:0 5px 5px 0;padding:6px 8px}
.dict-card{border:1px solid light-dark(#ccc,#555);border-radius:8px;
  background:light-dark(#f9f9f9,hsl(200,5%,17%));margin:8px 0;padding:12px 16px}
.dict-none{padding:8px;color:light-dark(#d33,hsl(0,71%,75%))}
      `).id = 'dict-card-style';
    }

    /* ─ 4. 검색 UI 주입 ─ */
    mw.hook('wikipage.content').add($c => {
      $c.find('.dictionary-container').each(function () {
        const $box = $(this);
        if ($box.children().length) return;   // 중복 방지

        /* 입력창 + 버튼 */
        const input  = new OO.ui.TextInputWidget({placeholder:'단어 입력…',icons:['search']});
        const button = new OO.ui.ButtonWidget({label:'검색',icon:'search',flags:['progressive']});
        const field  = new OO.ui.ActionFieldLayout(input,button,{align:'top'})
                         .$element.css('margin-bottom','10px');
        const $res   = $('<div class="dict-result"></div>');
        $box.append(field,$res);

        /* 검색 실행 */
        function run() {
          const q = input.getValue().trim();
          const key = q.toLowerCase();
          if (!q) return $res.empty();

          if (dict.hasOwnProperty(key)) {
            const wt = `'''${q}'''<br>${dict[key]}`;   // 카드 안에 단어+정의를 한 번에 파싱
            parseWT(wt).then(html => {
              $res.html(`<div class="dict-card">${html}</div>`);
            });
          } else {
            $res.html('<div class="dict-none">해당 단어가 없습니다.</div>');
          }
        }
        button.on('click',run);
        input.on('enter',run);
      });
    });
  }
);