مدیاویکی:Common.js: تفاوت میان نسخه‌ها

بدون خلاصۀ ویرایش
برچسب: برگردانده‌شده
بدون خلاصۀ ویرایش
برچسب: واگردانی دستی
خط ۶۸۹: خط ۶۸۹:
});
});
</script>
</script>
=========================================================================
(function () {
  function tokenize(html) {
    // فقط <br>, <br/>, <br /> را توکن جداگانه می‌کنیم؛ بقیه را کاراکتری تایپ می‌کنیم
    const out = [];
    const re = /<br\s*\/?>/ig;
    let last = 0, m;
    while ((m = re.exec(html)) !== null) {
      const chunk = html.slice(last, m.index);
      for (const ch of chunk) out.push(ch);
      out.push('<br>');
      last = re.lastIndex;
    }
    const tail = html.slice(last);
    for (const ch of tail) out.push(ch);
    return out;
  }
  function runTypewriter(root) {
    const nodes = root.querySelectorAll('.sj-type[data-sj-typewriter]');
    nodes.forEach((el) => {
      if (el.dataset.sjTyped === '1') return; // جلوگیری از اجرای دوباره
      el.dataset.sjTyped = '1';
      const original = (el.innerHTML || '').trim();
      const tokens = tokenize(original);
      el.innerHTML = '';
      el.style.visibility = 'visible';
      let i = 0;
      const base = Number(el.dataset.speed || 55);  // سرعت پایه
      const jitter = Number(el.dataset.jitter || 45); // نوسان
      function step() {
        if (i >= tokens.length) {
          setTimeout(() => el.classList.add('is-done'), 700);
          return;
        }
        const t = tokens[i++];
        if (t === '<br>') el.insertAdjacentHTML('beforeend', '<br>');
        else el.appendChild(document.createTextNode(t));
        let delay = base + Math.random() * jitter;
        if (t === '<br>') delay = 320; // مکث روی رفتن به خط بعد
        setTimeout(step, delay);
      }
      const startDelay = Number(el.dataset.delay || 300);
      setTimeout(step, startDelay);
    });
  }
  // اجرا روی محتوای هر صفحه
  mw.hook('wikipage.content').add(function ($content) {
    runTypewriter($content[0]);
  });
})();
========================================================================