mirror of
https://gitlab.com/octtspacc/OcttKB
synced 2025-02-15 10:50:43 +01:00
200 lines
6.2 KiB
JavaScript
200 lines
6.2 KiB
JavaScript
import { IScriptAddon } from '../../scriptAddon';
|
|
import * as ECharts from '$:/plugins/Gk0Wk/echarts/echarts.min.js';
|
|
|
|
const getFilterByDate = (date: string, subfilter: string) =>
|
|
`[all[tiddlers]sameday:created[${date}]][all[tiddlers]sameday:modified[${date}]] +${subfilter} +[sort[]]`;
|
|
const yearDates: Map<number, [string, string][]> = new Map();
|
|
const dayTime = 3600 * 24 * 1000;
|
|
const getData = (year: number, subfilter: string) => {
|
|
if (!yearDates.has(year)) {
|
|
const startDate = (ECharts as any).number
|
|
.parseDate(`${year}-01-01`)
|
|
.getTime();
|
|
const endDate = (ECharts as any).number
|
|
.parseDate(`${year + 1}-01-01`)
|
|
.getTime();
|
|
const dates: [string, string][] = [];
|
|
for (let time = startDate; time < endDate; time += dayTime) {
|
|
const timeFmt: string = (ECharts as any).format.formatTime(
|
|
'yyyy-MM-dd',
|
|
time,
|
|
);
|
|
const timeTW = timeFmt.replace(/-/g, '');
|
|
dates.push([timeFmt, timeTW]);
|
|
}
|
|
yearDates.set(year, dates);
|
|
}
|
|
let total = 0;
|
|
return [
|
|
yearDates.get(year)!.map(([timeFmt, timeTW]) => {
|
|
const count = $tw.wiki.filterTiddlers(
|
|
getFilterByDate(timeTW, subfilter),
|
|
).length;
|
|
total += count;
|
|
return [timeFmt, count];
|
|
}),
|
|
total,
|
|
] as [[string, number][], number];
|
|
};
|
|
|
|
const getPlatteColor = (name: string) =>
|
|
$tw.wiki.renderText(
|
|
'text/plain',
|
|
'text/vnd.tiddlywiki',
|
|
`<$transclude tiddler={{$:/palette}} index="${name}"><$transclude tiddler="$:/palettes/Vanilla" index="${name}"><$transclude tiddler="$:/config/DefaultColourMappings/${name}"/></$transclude></$transclude>`,
|
|
{},
|
|
);
|
|
|
|
const checkIfChinese = () =>
|
|
$tw.wiki.getTiddlerText('$:/language')?.includes('zh') === true;
|
|
|
|
const checkIfDarkMode = () =>
|
|
$tw.wiki.getTiddler($tw.wiki.getTiddlerText('$:/palette')!)?.fields?.[
|
|
'color-scheme'
|
|
] === 'dark';
|
|
|
|
const GitHubHeatMapAddon: IScriptAddon<any> = {
|
|
shouldUpdate: (_, changedTiddlers) => $tw.utils.count(changedTiddlers) > 0,
|
|
onUpdate: (myChart, _state, addonAttributes) => {
|
|
const year = parseInt(addonAttributes.year, 10) || new Date().getFullYear();
|
|
const subfilter = addonAttributes.subfilter || '[!is[shadow]!prefix[$:/]]';
|
|
const [data, total] = getData(year, subfilter);
|
|
const tooltipFormatter = (dateValue: string, count: number) => {
|
|
if (count === 0) {
|
|
return checkIfChinese()
|
|
? `${(ECharts as any).format.formatTime(
|
|
'yyyy年M月d日',
|
|
dateValue,
|
|
)} 无条目。`
|
|
: `${$tw.utils.formatDateString(
|
|
$tw.utils.parseDate(dateValue.replace(/-/g, ''))!,
|
|
'MMM DDD, YYYY',
|
|
)} no tiddler.`;
|
|
}
|
|
const p = $tw.utils.domMaker('p', {
|
|
text: checkIfChinese()
|
|
? `${(ECharts as any).format.formatTime(
|
|
'yyyy年M月d日',
|
|
dateValue,
|
|
)} 共有 ${count} 篇:`
|
|
: `${$tw.utils.formatDateString(
|
|
$tw.utils.parseDate(dateValue.replace(/-/g, ''))!,
|
|
'MMM DDD, YYYY',
|
|
)} ${count} tiddler${count > 1 ? 's' : ''}.`,
|
|
});
|
|
const ul = $tw.utils.domMaker('ul', {});
|
|
const tiddlers = $tw.wiki.filterTiddlers(
|
|
getFilterByDate(dateValue.replace(/-/g, ''), subfilter),
|
|
);
|
|
const len = tiddlers.length;
|
|
for (let i = 0; i < len; i++) {
|
|
const tiddler = tiddlers[i];
|
|
const li = $tw.utils.domMaker('li', {});
|
|
const a = $tw.utils.domMaker('a', {
|
|
text: tiddler,
|
|
class:
|
|
'tc-tiddlylink tc-tiddlylink-resolves tc-popup-handle tc-popup-absolute',
|
|
style: {
|
|
cursor: 'pointer',
|
|
},
|
|
});
|
|
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
a.addEventListener('click', () =>
|
|
new $tw.Story().navigateTiddler(tiddler),
|
|
);
|
|
li.appendChild(a);
|
|
ul.appendChild(li);
|
|
}
|
|
return [p, ul];
|
|
};
|
|
let lastDateValue = '';
|
|
let lastCount = 0;
|
|
let cache: Element[] | string | undefined;
|
|
const cachedTooltipFormatter = ({
|
|
value: [dateValue, count],
|
|
}: {
|
|
value: [string, number];
|
|
}) => {
|
|
if (dateValue !== lastDateValue || count !== lastCount || !cache) {
|
|
cache = tooltipFormatter(dateValue, count);
|
|
lastDateValue = dateValue;
|
|
lastCount = count;
|
|
}
|
|
return cache;
|
|
};
|
|
myChart.setOption({
|
|
title: {
|
|
top: 0,
|
|
left: 'center',
|
|
text: checkIfChinese()
|
|
? `今年产出 ${total} 篇文章`
|
|
: `Produced ${total} tiddlers this year`,
|
|
},
|
|
tooltip: {
|
|
position: 'top',
|
|
formatter: cachedTooltipFormatter,
|
|
triggerOn: 'mousemove|click',
|
|
enterable: true,
|
|
hideDelay: 800,
|
|
backgroundColor: getPlatteColor('page-background'),
|
|
borderColor: getPlatteColor('very-muted-foreground'),
|
|
},
|
|
visualMap: {
|
|
type: 'piecewise',
|
|
orient: 'horizontal',
|
|
calculable: true,
|
|
showLabel: false,
|
|
right: 0,
|
|
top: 175,
|
|
pieces: [
|
|
// 设置分段范围
|
|
{ lte: 0, color: checkIfDarkMode() ? '#161B22' : '#EBEDF0' },
|
|
{ gt: 0, lte: 3, color: '#0E4429' },
|
|
{ gt: 3, lte: 7, color: '#006D32' },
|
|
{ gt: 7, lte: 15, color: '#26A641' },
|
|
{ gt: 15, color: '#39D353' },
|
|
],
|
|
},
|
|
calendar: {
|
|
top: 60,
|
|
left: 0,
|
|
right: 0,
|
|
cellSize: 15,
|
|
orient: 'horizontal',
|
|
range: year,
|
|
itemStyle: {
|
|
borderWidth: 3,
|
|
borderCap: 'round',
|
|
borderJoin: 'round',
|
|
borderColor: getPlatteColor('background'),
|
|
},
|
|
splitLine: {
|
|
show: false,
|
|
},
|
|
dayLabel: {
|
|
show: true,
|
|
nameMap: checkIfChinese() ? 'ZH' : 'EN',
|
|
},
|
|
monthLabel: {
|
|
show: true,
|
|
nameMap: checkIfChinese() ? 'ZH' : 'EN',
|
|
},
|
|
yearLabel: {
|
|
show: true,
|
|
position: 'bottom',
|
|
margin: 12,
|
|
verticalAlign: 'top',
|
|
},
|
|
},
|
|
series: {
|
|
type: 'heatmap',
|
|
coordinateSystem: 'calendar',
|
|
calendarIndex: 0,
|
|
data,
|
|
},
|
|
} as any);
|
|
},
|
|
};
|
|
|
|
export default GitHubHeatMapAddon;
|