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}