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