master
  1import dayjs from 'dayjs';
  2import 'dayjs/locale/en';
  3import 'dayjs/locale/zh-cn';
  4import 'dayjs/locale/zh-tw';
  5import relativeTime from 'dayjs/plugin/relativeTime';
  6
  7dayjs.extend(relativeTime);
  8
  9export function getReadingProgress(bottomHeight: number): number {
 10  const docEl = document.documentElement;
 11  const bodyEl = document.body;
 12  const totalHeight = Math.max(
 13    bodyEl.clientHeight,
 14    bodyEl.scrollHeight,
 15    bodyEl.offsetHeight,
 16    docEl.clientHeight,
 17    docEl.scrollHeight,
 18    docEl.offsetHeight
 19  );
 20  const mainHeight = Math.min(totalHeight, bottomHeight) - window.innerHeight;
 21  const scrollY = window.scrollY;
 22  return Math.round((scrollY / mainHeight) * 100);
 23}
 24
 25export async function getRandomPost() {
 26  // Use rss.xml to get random post
 27  // 使用 rss.xml 获取随机文章
 28  const site = import.meta.env.SITE;
 29  try {
 30    const response = await fetch('/rss.xml');
 31    const text = await response.text();
 32    const parser = new DOMParser();
 33    const xml = parser.parseFromString(text, 'text/xml');
 34    const items = xml.querySelectorAll('item link');
 35    const links = Array.from(items).map((item) => item.textContent || '');
 36
 37    if (links.length > 0) {
 38      const randomLink = links[Math.floor(Math.random() * links.length)].replace(site, '/');
 39      window.swup?.navigate(randomLink);
 40    }
 41  } catch (error) {
 42    console.error('Failed to get random post:', error);
 43  }
 44}
 45
 46export function convertTimeToRelative(): void {
 47  // 获取页面语言
 48  const lang = document.documentElement.lang || 'en';
 49  // 设置 dayjs 语言
 50  const localeMap: { [key: string]: string } = {
 51    'zh-CN': 'zh-cn',
 52    'zh-TW': 'zh-tw',
 53    en: 'en',
 54  };
 55  dayjs.locale(localeMap[lang] || 'en');
 56
 57  // 获取所有 time 标签
 58  const timeElements = document.getElementsByTagName('time');
 59  const now = dayjs();
 60  const sevenDaysAgo = now.subtract(7, 'day');
 61
 62  Array.from(timeElements).forEach((timeElement) => {
 63    const datetime = timeElement.getAttribute('datetime');
 64    if (!datetime) return;
 65
 66    if (!timeElement.title)
 67      timeElement.title = timeElement.textContent || dayjs(datetime).format('llll');
 68
 69    // 检查是否禁用相对时间转换
 70    if (timeElement.dataset.noRelative) return;
 71
 72    const date = dayjs(datetime);
 73    // 检查是否在7天内
 74    if (date.isAfter(sevenDaysAgo) || timeElement.dataset.forceRelative) {
 75      // 转换为相对时间
 76      timeElement.textContent = date.fromNow(timeElement.dataset.noAgo === 'true');
 77    }
 78  });
 79}
 80
 81export function loadScript(url: string): Promise<void> {
 82  return new Promise((resolve, reject) => {
 83    const script = document.createElement('script');
 84    script.src = url;
 85    script.onload = () => resolve();
 86    script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
 87    document.head.appendChild(script);
 88  });
 89}
 90
 91export function loadStylesheet(url: string): Promise<void> {
 92  return new Promise((resolve, reject) => {
 93    const link = document.createElement('link');
 94    link.rel = 'stylesheet';
 95    link.href = url;
 96    link.onload = () => resolve();
 97    link.onerror = () => reject(new Error(`Failed to load stylesheet: ${url}`));
 98    document.head.appendChild(link);
 99  });
100}