[Manual] Add scripts and raw wiki

This commit is contained in:
2023-02-28 12:07:24 +01:00
parent d29725b74a
commit 5320dc75f0
1482 changed files with 27397 additions and 3932 deletions

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2023 Gk0Wk(nmg_wk@yeah.net)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,2 @@
title: $:/plugins/Gk0Wk/echarts/LICENSE
type: text/plain

View File

@ -0,0 +1,6 @@
caption: Add a new Graph Chart, "levels" (default to 1) controls how many levels will it reach from "focussedTiddler" (default to $:/temp/focussedTiddler); "graphTitle" decided the title of the chart
tags: $:/tags/TextEditor/Snippet
title: $:/plugins/Gk0Wk/echarts/Snippets/TheBrain
type: text/vnd.tiddlywiki
<$echarts $tiddler="$:/plugins/Gk0Wk/echarts/addons/TheBrain.js" aliasField="caption" levels=2 focussedTiddler="Index" graphTitle="Graph" />

View File

@ -0,0 +1 @@
"use strict";var __create=Object.create,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty,__export=(e,t)=>{for(var r in t)__defProp(e,r,{get:t[r],enumerable:!0})},__copyProps=(t,r,a,o)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let e of __getOwnPropNames(r))__hasOwnProp.call(t,e)||e===a||__defProp(t,e,{get:()=>r[e],enumerable:!(o=__getOwnPropDesc(r,e))||o.enumerable});return t},__toESM=(e,t,r)=>(r=null!=e?__create(__getProtoOf(e)):{},__copyProps(!t&&e&&e.__esModule?r:__defProp(r,"default",{value:e,enumerable:!0}),e)),__toCommonJS=e=>__copyProps(__defProp({},"__esModule",{value:!0}),e),GitHubHeatMap_exports={},ECharts=(__export(GitHubHeatMap_exports,{"default":()=>GitHubHeatMap_default}),module.exports=__toCommonJS(GitHubHeatMap_exports),__toESM(require("$:/plugins/Gk0Wk/echarts/echarts.min.js"))),getFilterByDate=(e,t)=>`[all[tiddlers]sameday:created[${e}]][all[tiddlers]sameday:modified[${e}]] +${t} +[sort[]]`,yearDates=new Map,dayTime=864e5,getData=(t,a)=>{if(!yearDates.has(t)){var r=ECharts.number.parseDate(t+"-01-01").getTime(),o=ECharts.number.parseDate(t+1+"-01-01").getTime(),l=[];for(let e=r;e<o;e+=dayTime){var i=ECharts.format.formatTime("yyyy-MM-dd",e),d=i.replace(/-/g,"");l.push([i,d])}yearDates.set(t,l)}let n=0;return[yearDates.get(t).map(([e,t])=>{var r=$tw.wiki.filterTiddlers(getFilterByDate(t,a)).length;return n+=r,[e,r]}),n]},getPlatteColor=e=>$tw.wiki.renderText("text/plain","text/vnd.tiddlywiki",`<$transclude tiddler={{$:/palette}} index="${e}"><$transclude tiddler="$:/palettes/Vanilla" index="${e}"><$transclude tiddler="$:/config/DefaultColourMappings/${e}"/></$transclude></$transclude>`,{}),checkIfChinese=()=>{var e;return!0===(null==(e=$tw.wiki.getTiddlerText("$:/language"))?void 0:e.includes("zh"))},checkIfDarkMode=()=>{var e;return"dark"===(null==(e=null==(e=$tw.wiki.getTiddler($tw.wiki.getTiddlerText("$:/palette")))?void 0:e.fields)?void 0:e["color-scheme"])},GitHubHeatMapAddon={shouldUpdate:(e,t)=>0<$tw.utils.count(t),onUpdate:(e,t,r)=>{var a=parseInt(r.year,10)||(new Date).getFullYear();const p=r.subfilter||"[!is[shadow]!prefix[$:/]]";var[o,l]=getData(a,p);let i="",d=0,n;e.setOption({title:{top:0,left:"center",text:checkIfChinese()?`今年产出 ${l} 篇文章`:`Produced ${l} tiddlers this year`},tooltip:{position:"top",formatter:({value:[e,t]})=>(e===i&&t===d&&n||(n=((e,t)=>{if(0===t)return checkIfChinese()?ECharts.format.formatTime("yyyy年M月d日",e)+" 无条目。":$tw.utils.formatDateString($tw.utils.parseDate(e.replace(/-/g,"")),"MMM DDD, YYYY")+" no tiddler.";var r=$tw.utils.domMaker("p",{text:checkIfChinese()?ECharts.format.formatTime("yyyy年M月d日",e)+` 共有 ${t} 篇:`:$tw.utils.formatDateString($tw.utils.parseDate(e.replace(/-/g,"")),"MMM DDD, YYYY")+` ${t} tiddler${1<t?"s":""}.`}),a=$tw.utils.domMaker("ul",{}),o=$tw.wiki.filterTiddlers(getFilterByDate(e.replace(/-/g,""),p)),l=o.length;for(let n=0;n<l;n++){const s=o[n];var i=$tw.utils.domMaker("li",{}),d=$tw.utils.domMaker("a",{text:s,"class":"tc-tiddlylink tc-tiddlylink-resolves tc-popup-handle tc-popup-absolute",style:{cursor:"pointer"}});d.addEventListener("click",()=>(new $tw.Story).navigateTiddler(s)),i.appendChild(d),a.appendChild(i)}return[r,a]})(e,t),i=e,d=t),n),triggerOn:"mousemove|click",enterable:!0,hideDelay:800,backgroundColor:getPlatteColor("page-background"),borderColor:getPlatteColor("very-muted-foreground")},visualMap:{type:"piecewise",orient:"horizontal",calculable:!0,showLabel:!1,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:a,itemStyle:{borderWidth:3,borderCap:"round",borderJoin:"round",borderColor:getPlatteColor("background")},splitLine:{show:!1},dayLabel:{show:!0,nameMap:checkIfChinese()?"ZH":"EN"},monthLabel:{show:!0,nameMap:checkIfChinese()?"ZH":"EN"},yearLabel:{show:!0,position:"bottom",margin:12,verticalAlign:"top"}},series:{type:"heatmap",coordinateSystem:"calendar",calendarIndex:0,data:o}})}},GitHubHeatMap_default=GitHubHeatMapAddon;

View File

@ -0,0 +1,5 @@
Modern.TiddlyDev#IncludeSource: true
Modern.TiddlyDev#Origin: addons/Gk0Wk/GitHubHeatMap.ts
module-type: echarts-component
title: $:/plugins/Gk0Wk/echarts/addons/GitHubHeatMap.js
type: application/javascript

View File

@ -0,0 +1,199 @@
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;

View File

@ -0,0 +1,3 @@
Modern.TiddlyDev#IncludeSource: true
title: $:/plugins/Gk0Wk/echarts/addons/GitHubHeatMap.ts
type: application/javascript

View File

@ -0,0 +1,58 @@
title: $:/plugins/Gk0Wk/echarts/addons/PluginsSize
type: text/vnd.tiddlywiki
`{
"tooltip": {
"trigger": "item"
},
"series": [
{
"type": "treemap",
"visibleMin": 300,
"name": "Plugin Size",
"leafDepth": 1,
"data": [
`
<$list filter="[!plugin-type[]!title[$:/core]!title[$:/temp/info-plugin]]" variable="pluginName" counter="counter1">
` {
"name": "`<$list filter="[<pluginName>has[name]]"><$text text={{{ [<pluginName>get[name]] }}}/></$list><$list filter="[<pluginName>!has[name]]"><$text text={{{ [<pluginName>has[name]else<pluginName>split[/]nth[4]] }}}/></$list>`",
"value": `<$text text={{{ [<pluginName>get[text]length[]else[0]] }}}/>`,
"children": [
`
<$list filter="[<pluginName>plugintiddlers[]]" variable="pluginShadow" counter="counter2">
` {
"name": "`<$text text={{{ [<pluginShadow>removeprefix<pluginName>removeprefix[/]else<pluginShadow>] }}}/>`",
"value": `<$text text={{{ [<pluginShadow>get[text]length[]else[0]] }}}/>`
}`<$list filter="[<counter2-last>match[no]]">`,`</$list>`
`
</$list>
` ]
}`<$list filter="[<counter1-last>match[no]]">`,`</$list>`
`
</$list>
`
],
"levels": [
{
"itemStyle": {
"borderColor": "#555",
"borderWidth": 4,
"gapWidth": 4
}
},
{
"colorSaturation": [0.3, 0.6],
"itemStyle": {
"borderColorSaturation": 0.7,
"gapWidth": 2,
"borderWidth": 2
}
}
],
"upperLabel": {
"show": true,
"height": 30
}
}
]
}`

View File

@ -0,0 +1,19 @@
{
"xAxis": {
"type": "category",
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
"yAxis": {
"type": "value"
},
"series": [
{
"data": [120, 200, 150, 80, 70, 110, 130],
"type": "bar",
"showBackground": true,
"backgroundStyle": {
"color": "rgba(180, 180, 180, 0.2)"
}
}
]
}

View File

@ -0,0 +1,2 @@
title: $:/plugins/Gk0Wk/echarts/addons/SimpleExample.json
type: application/json

View File

@ -0,0 +1 @@
"use strict";var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,__export=(t,e)=>{for(var o in e)__defProp(t,o,{get:e[o],enumerable:!0})},__copyProps=(e,o,r,a)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let t of __getOwnPropNames(o))__hasOwnProp.call(e,t)||t===r||__defProp(e,t,{get:()=>o[t],enumerable:!(a=__getOwnPropDesc(o,t))||a.enumerable});return e},__toCommonJS=t=>__copyProps(__defProp({},"__esModule",{value:!0}),t),TagCloud_exports={},getPlatteColor=(__export(TagCloud_exports,{"default":()=>TagCloud_default}),module.exports=__toCommonJS(TagCloud_exports),t=>$tw.wiki.renderText("text/plain","text/vnd.tiddlywiki",`<$transclude tiddler={{$:/palette}} index="${t}"><$transclude tiddler="$:/palettes/Vanilla" index="${t}"><$transclude tiddler="$:/config/DefaultColourMappings/${t}"/></$transclude></$transclude>`,{})),addon={shouldUpdate:(t,e)=>0<$tw.utils.count(e),onUpdate:t=>{const r=new Map;let e="",o;var a=t.getOption();const l=!0===a.darkMode;a=a.filter||"[tags[]!is[system]sort[title]]",l,l,r.clear(),a=$tw.wiki.filterTiddlers(a).map(t=>({name:t,value:Math.sqrt($tw.wiki.getTiddlersWithTag(t).length),textStyle:{color:(e=>{if(!r.get(e)){var o=[];for(let t=0;t<3;t++)o.push(l?255-Math.round(160*Math.random()):Math.round(160*Math.random()));r.set(e,`rgb(${o.join(",")})`)}return r.get(e)})(t)}}));t.setOption({series:[{type:"wordCloud",gridSize:4,shape:"pentagon",data:a,layoutAnimation:!0,textStyle:{fontFamily:"sans-serif",fontWeight:"bold"},emphasis:{focus:"self",textStyle:{textShadowBlur:10,textShadowColor:"#333"}}}],tooltip:{position:"top",formatter:({data:{name:t}})=>(t===e&&o||(o=(t=>{var e=$tw.utils.domMaker("ul",{}),o=$tw.wiki.getTiddlersWithTag(t),r=o.length;for(let d=0;d<r;d++){const n=o[d];var a=$tw.utils.domMaker("li",{}),l=$tw.utils.domMaker("a",{text:n,"class":"tc-tiddlylink tc-tiddlylink-resolves tc-popup-handle tc-popup-absolute",style:{cursor:"pointer"}});l.addEventListener("click",()=>(new $tw.Story).navigateTiddler(n)),a.appendChild(l),e.appendChild(a)}return[e]})(t),e=t),o),triggerOn:"mousemove|click",enterable:!0,hideDelay:800,textStyle:{color:"inherit",fontFamily:"inherit",fontSize:"inherit"},backgroundColor:getPlatteColor("page-background"),borderColor:getPlatteColor("very-muted-foreground")}})}},TagCloud_default=addon;

View File

@ -0,0 +1,5 @@
Modern.TiddlyDev#IncludeSource: true
Modern.TiddlyDev#Origin: addons/Gk0Wk/TagCloud.ts
module-type: echarts-component
title: $:/plugins/Gk0Wk/echarts/addons/TagCloud.js
type: application/javascript

View File

@ -0,0 +1,123 @@
import type { IScriptAddon } from '../../scriptAddon';
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 addon: IScriptAddon<any> = {
shouldUpdate: (_state, changedTiddlers) => {
return $tw.utils.count(changedTiddlers) > 0;
},
// See https://github.com/ecomfe/echarts-wordcloud
onUpdate: myChart => {
let previousDarkMode;
const colorCache = new Map();
const getColor = (tag: string) => {
if (!colorCache.get(tag)) {
const rgb = [];
for (let i = 0; i < 3; i++) {
rgb.push(
isDarkMode
? 255 - Math.round(Math.random() * 160)
: Math.round(Math.random() * 160),
);
}
colorCache.set(tag, `rgb(${rgb.join(',')})`);
}
return colorCache.get(tag);
};
const tooltipFormatter = (tag: string) => {
const ul = $tw.utils.domMaker('ul', {});
const tiddlers = $tw.wiki.getTiddlersWithTag(tag);
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 [ul];
};
let lastTag = '';
let cache: Element[] | string | undefined;
const cachedTooltipFormatter = ({
data: { name },
}: {
data: { name: string };
}) => {
if (name !== lastTag || !cache) {
cache = tooltipFormatter(name);
lastTag = name;
}
return cache;
};
const chartOptions = myChart.getOption();
const isDarkMode = (chartOptions as any).darkMode === true;
const filter =
(chartOptions as any).filter || '[tags[]!is[system]sort[title]]';
if (previousDarkMode !== isDarkMode) {
previousDarkMode = isDarkMode;
colorCache.clear();
}
const data = $tw.wiki.filterTiddlers(filter).map(tag => ({
name: tag,
value: Math.sqrt($tw.wiki.getTiddlersWithTag(tag).length),
textStyle: {
color: getColor(tag),
},
}));
myChart.setOption({
series: [
{
type: 'wordCloud',
gridSize: 4,
shape: 'pentagon',
data,
layoutAnimation: true,
textStyle: {
fontFamily: 'sans-serif',
fontWeight: 'bold',
},
emphasis: {
focus: 'self',
textStyle: {
textShadowBlur: 10,
textShadowColor: '#333',
},
},
},
],
tooltip: {
position: 'top',
formatter: cachedTooltipFormatter,
triggerOn: 'mousemove|click',
enterable: true,
hideDelay: 800,
textStyle: {
color: 'inherit',
fontFamily: 'inherit',
fontSize: 'inherit',
},
backgroundColor: getPlatteColor('page-background'),
borderColor: getPlatteColor('very-muted-foreground'),
},
} as any);
},
};
export default addon;

View File

@ -0,0 +1,3 @@
Modern.TiddlyDev#IncludeSource: true
title: $:/plugins/Gk0Wk/echarts/addons/TagCloud.ts
type: application/javascript

View File

@ -0,0 +1,23 @@
title: $:/plugins/Gk0Wk/echarts/addons/TagCloudTagView
<$set name="tagName" value={{$:/temp/Gk0Wk/echarts/addons/TagCloud/currentTag}}>
<$list filter="[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]" variable="lang">
<$list filter="[<lang>search[zh]]">
!! 包含 <$link to=<<tagName>>/> 标签的条目
</$list>
<$list filter="[<lang>!search[zh]]">
!! Tiddlers tagged with <$link to=<<tagName>>/>
</$list>
</$list>
<div class="tc-table-of-contents">
<$macrocall $name="toc" tag=<<tagName>> sort="sort[title]"/>
</div>
</$set>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
Modern.TiddlyDev#IncludeSource: true
Modern.TiddlyDev#Origin: addons/Gk0Wk/TheBrain.ts
module-type: echarts-component
title: $:/plugins/Gk0Wk/echarts/addons/TheBrain.js
type: application/javascript

View File

@ -0,0 +1,602 @@
/* eslint-disable max-lines */
import type { IParseTreeNode } from 'tiddlywiki';
import type { IScriptAddon } from '../../scriptAddon';
const colors = [
'#5470c6',
'#91cc75',
'#fac858',
'#ee6666',
'#73c0de',
'#3ba272',
'#fc8452',
'#9a60b4',
'#ea7ccc',
];
const CategoriesEn = [
'Focusing',
'History',
'Link To',
'Backlink From',
'Tag To',
'Tag By',
'Transclude',
].map((name, index) => ({
name,
itemStyle: { color: colors[index % colors.length] },
}));
const CategoriesZh = [
'聚焦',
'历史',
'链接',
'反链',
'标签',
'作为标签',
'嵌套',
].map((name, index) => ({
name,
itemStyle: { color: colors[index % colors.length] },
}));
const attributes = new Set<string>([
'focussedTiddler',
'levels',
'graphTitle',
'aliasField',
'excludeFilter',
'previewDelay',
]);
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 findIcon = (title: string) => {
const fields = $tw.wiki.getTiddler(title)?.fields;
if (!fields?.icon) {
return undefined;
}
const iconFields = $tw.wiki.getTiddler(fields.icon as string)?.fields;
if (!iconFields) {
if (/^https?:\/\//.test(fields.icon as string)) {
return `image://${fields.icon as string}`;
}
return undefined;
}
if (iconFields._canonical_uri) {
return `image://${iconFields._canonical_uri}`;
} else if (iconFields.title.startsWith('$:/core/images/')) {
return undefined;
} else {
return `image://data:${iconFields.type};base64,${iconFields.text}`;
}
};
const getAliasOrTitle = (
tiddlerTitle: string,
aliasField: string | undefined,
): [string, boolean] => {
if (aliasField === undefined || aliasField === 'title') {
return [tiddlerTitle, Boolean($tw.wiki.getTiddler(tiddlerTitle))];
}
const tiddler = $tw.wiki.getTiddler(tiddlerTitle);
if (tiddler) {
const aliasValue = tiddler.fields[aliasField];
return [
typeof aliasValue === 'string'
? $tw.wiki.renderText('text/plain', 'text/vnd.tiddlywiki', aliasValue, {
variables: { currentTiddler: tiddlerTitle },
})
: tiddlerTitle,
true,
];
} else {
return [tiddlerTitle, false];
}
};
interface ITheBrainState {
currentlyFocused?: string;
historyTiddlers: string[];
viewingTiddlers: Set<string>;
focusing?: string;
}
const TheBrainAddon: IScriptAddon<ITheBrainState> = {
onMount: (myChart, attributes) => {
myChart.on('click', { dataType: 'node' }, (event: any) => {
new $tw.Story().navigateTiddler(event.data.name);
});
return {
historyTiddlers: [],
viewingTiddlers: new Set(),
focusing: attributes.focussedTiddler,
};
},
shouldUpdate: (
{ viewingTiddlers, focusing, currentlyFocused },
changedTiddlers,
changedAttributes,
) => {
return (
Object.keys(changedTiddlers).some(title => viewingTiddlers.has(title)) ||
Object.keys(changedAttributes).some(attribute =>
attributes.has(attribute),
) ||
(focusing === undefined &&
$tw.wiki.getTiddlerText('$:/temp/focussedTiddler') !== currentlyFocused)
);
},
// eslint-disable-next-line complexity
onUpdate: (
myCharts,
state,
addonAttributes: {
focussedTiddler?: string;
levels?: number;
graphTitle?: string;
aliasField?: string;
excludeFilter?: string;
previewDelay?: string;
},
) => {
/** 参数focussedTiddler 是图的中央节点 */
let focussedTiddler =
addonAttributes.focussedTiddler ||
$tw.wiki.getTiddlerText('$:/temp/focussedTiddler')!;
state.viewingTiddlers.clear();
state.focusing = addonAttributes.focussedTiddler;
state.currentlyFocused = focussedTiddler;
if (!focussedTiddler) {
return;
}
state.viewingTiddlers.add(focussedTiddler);
if ($tw.wiki.getTiddler(focussedTiddler)?.fields['draft.of']) {
focussedTiddler = $tw.wiki.getTiddler(focussedTiddler)!.fields[
'draft.of'
] as string;
}
const nodes: any[] = [];
const edges: any[] = [];
const ifChinese =
$tw.wiki.getTiddlerText('$:/language')?.includes('zh') === true;
/** 参数levels 指定图向外展开几级 */
let levels = Number(addonAttributes.levels);
if (Number.isNaN(levels)) {
levels = 1;
}
levels = Math.max(levels, 0);
/** 参数graphTitle 指定右下角显示的标题 */
const graphTitle =
addonAttributes.graphTitle || (ifChinese ? '聚焦' : 'Focusing Map');
/** 参数aliasField 用于指定展示为节点标题的字段,例如 caption */
const aliasField =
addonAttributes.aliasField === ''
? undefined
: addonAttributes.aliasField;
/** 参数excludeFilter 用于排除部分节点 */
const excludeFilter =
addonAttributes.excludeFilter === ''
? undefined
: $tw.wiki.compileFilter(
addonAttributes.excludeFilter ?? '[prefix[$:/]]',
);
const nodeMap: Map<string, boolean> = new Map();
// 聚焦点
nodes.push({
name: focussedTiddler,
// fixed: true,
category: 0,
label: {
formatter: getAliasOrTitle(focussedTiddler, aliasField)[0],
fontWeight: 'bold',
fontSize: '15px',
},
symbol: findIcon(focussedTiddler),
symbolSize: 15,
select: {
disabled: true,
},
itemStyle: {
opacity: 1,
borderColor: `${colors[0]}66`,
borderWidth: 15,
},
isTag: false,
tooltip: {
show: false,
},
});
// 初始化:当前关注的 Tiddler
let tiddlerQueue = [focussedTiddler];
if (excludeFilter) {
const tiddlers = new Set<string>(tiddlerQueue);
for (const excluded of excludeFilter.call($tw.wiki, tiddlerQueue)) {
tiddlers.delete(excluded);
}
tiddlerQueue = Array.from(tiddlers);
}
nodeMap.set(focussedTiddler, true);
nodeMap.set('', false);
const tryPush = (
title: string,
node: (label: string, exist: boolean) => any,
edge: (exist: boolean) => any,
) => {
if (excludeFilter && excludeFilter.call($tw.wiki, [title]).length > 0) {
return false;
}
const nodeState = nodeMap.get(title);
const [label, exist] =
nodeState === undefined
? getAliasOrTitle(title, aliasField)
: ['', nodeState];
if (nodeState === undefined) {
nodes.push(node(label, exist));
nodeMap.set(title, exist);
if (exist) {
tiddlerQueue.push(title);
}
}
edges.push(edge(exist));
return exist;
};
// 广搜 levels 层
while (tiddlerQueue.length && levels-- > 0) {
const tiddlers = tiddlerQueue;
tiddlerQueue = [];
for (const tiddler of tiddlers) {
// 链接
for (const linksTo of $tw.wiki.getTiddlerLinks(tiddler)) {
tryPush(
linksTo,
(label, exist) => ({
name: linksTo,
label: { formatter: label },
itemStyle: { opacity: exist ? 1 : 0.65 },
symbol: findIcon(linksTo),
category: 2,
isTag: false,
}),
exist => ({
source: tiddler,
target: linksTo,
lineStyle: {
color: colors[2],
type: exist ? 'solid' : 'dashed',
},
}),
);
}
// 反链
for (const backlinksFrom of $tw.wiki.getTiddlerBacklinks(tiddler)) {
tryPush(
backlinksFrom,
(label, exist) => ({
name: backlinksFrom,
label: { formatter: label },
itemStyle: { opacity: exist ? 1 : 0.65 },
symbol: findIcon(backlinksFrom),
category: 3,
isTag: false,
}),
exist => ({
source: backlinksFrom,
target: tiddler,
lineStyle: {
color: colors[3],
type: exist ? 'solid' : 'dashed',
},
}),
);
}
// 标签
for (const tag of $tw.wiki.getTiddler(focussedTiddler)?.fields?.tags ??
[]) {
tryPush(
tag,
(label, exist) => ({
name: tag,
label: { formatter: label },
itemStyle: { opacity: exist ? 1 : 0.65 },
symbol: findIcon(tag),
category: 4,
isTag: true,
}),
exist => ({
source: tiddler,
target: tag,
lineStyle: {
color: colors[4],
type: exist ? 'solid' : 'dashed',
},
}),
);
}
// 作为标签
for (const tagBy of $tw.wiki.getTiddlersWithTag(tiddler)) {
tryPush(
tagBy,
(label, exist) => ({
name: tagBy,
label: { formatter: label },
itemStyle: { opacity: exist ? 1 : 0.65 },
symbol: findIcon(tagBy),
category: 5,
isTag: false,
}),
exist => ({
source: tagBy,
target: tiddler,
lineStyle: {
color: colors[5],
type: exist ? 'solid' : 'dashed',
},
}),
);
}
// 嵌入
const tiddler_ = $tw.wiki.getTiddler(tiddler);
if (tiddler_) {
const type = tiddler_.fields.type || 'text/vnd.tiddlywiki';
if (type === 'text/vnd.tiddlywiki' || type === 'text/x-markdown') {
const transcluded: Set<string> = new Set();
const findTransclude = (children: IParseTreeNode[]) => {
const { length } = children;
for (let i = 0; i < length; i++) {
const node = children[i];
if (node.type === 'tiddler') {
const title = node.attributes!.tiddler?.value as
| string
| undefined;
if (title) {
transcluded.add(title);
}
} else if (Array.isArray((node as any).children)) {
findTransclude((node as any).children);
}
}
};
findTransclude($tw.wiki.parseTiddler(tiddler).tree);
// eslint-disable-next-line max-depth
for (const transcludeTiddler of transcluded) {
tryPush(
transcludeTiddler,
(label, exist) => ({
name: transcludeTiddler,
label: { formatter: label },
itemStyle: { opacity: exist ? 1 : 0.65 },
symbol: findIcon(transcludeTiddler),
category: 6,
isTag: false,
}),
exist => ({
source: tiddler,
target: transcludeTiddler,
lineStyle: {
color: colors[6],
type: exist ? 'solid' : 'dashed',
},
}),
);
}
}
}
}
}
// 历史路径
let nextTiddler = focussedTiddler;
const historyMap: Set<string> = new Set();
for (let index = state.historyTiddlers.length - 2; index >= 0; index--) {
const tiddlerTitle = state.historyTiddlers[index];
if (
historyMap.has(tiddlerTitle) ||
tiddlerTitle === nextTiddler ||
tiddlerTitle.startsWith('$:/')
) {
continue;
}
tryPush(
tiddlerTitle,
(label, exist) => ({
name: tiddlerTitle,
label: { formatter: label, fontSize: '10px' },
category: 1,
symbol: findIcon(tiddlerTitle),
symbolSize: 3,
itemStyle: { opacity: exist ? 0.65 : 0.4 },
isTag: false,
}),
// eslint-disable-next-line @typescript-eslint/no-loop-func
exist => ({
source: tiddlerTitle,
target: nextTiddler,
lineStyle: {
color: colors[1],
type: exist ? 'dashed' : 'dotted',
opacity: 0.5,
},
}),
);
nextTiddler = tiddlerTitle;
}
// 更新历史
const historyIndex = state.historyTiddlers.indexOf(focussedTiddler);
if (historyIndex > -1) {
state.historyTiddlers.splice(historyIndex, 1);
}
state.historyTiddlers.push(focussedTiddler);
state.historyTiddlers.slice(-10);
let lastTitle = '';
let cache: Element[] | undefined;
const cachedTooltipFormatter = ({
data: { name, isTag },
dataType,
}: {
data: { name: string; isTag: boolean };
dataType: string;
}) => {
if (dataType !== 'node') {
return [];
}
if (name !== lastTitle || !cache) {
const container = $tw.utils.domMaker('div', {
style: {
maxWidth: '40vw',
maxHeight: '50vh',
overflowY: 'auto',
whiteSpace: 'normal',
},
class: 'gk0wk-echarts-thebrain-popuptiddler-container',
});
if (isTag) {
const ul = $tw.utils.domMaker('ul', {});
const tiddlers = $tw.wiki.getTiddlersWithTag(name);
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);
}
cache = [ul];
} else {
// 不可以直接 renderText, 那种是 headless 渲染
$tw.wiki
.makeWidget(
$tw.wiki.parseTiddler(
'$:/plugins/Gk0Wk/echarts/addons/TheBrainPopup',
),
{
document,
parseAsInline: true,
variables: { currentTiddler: name },
} as any,
)
.render(container, null);
cache = [
container,
$tw.utils.domMaker('style', {
innerHTML: `.gk0wk-echarts-thebrain-popuptiddler-container::-webkit-scrollbar {display: none;} .gk0wk-echarts-thebrain-popuptiddler-container .tc-tiddler-controls { display: none; }`,
}),
];
}
lastTitle = name;
}
return cache;
};
let previewDelay = Number(addonAttributes.previewDelay || '1000');
if (!Number.isSafeInteger(previewDelay)) {
previewDelay = -1;
}
myCharts.setOption({
backgroundColor: 'transparent',
legend: [
{
data: (ifChinese ? CategoriesZh : CategoriesEn).map(a => {
return a.name;
}),
icon: 'circle',
},
],
title: {
text: graphTitle,
show: true,
top: 'bottom',
left: 'right',
},
toolbox: {
show: true,
left: 0,
bottom: 0,
feature: {
restore: {},
saveAsImage: {},
},
},
tooltip: {
position: 'top',
formatter: cachedTooltipFormatter,
triggerOn: previewDelay >= 0 ? 'mousemove' : 'none',
enterable: true,
showDelay: Math.max(0, previewDelay),
hideDelay: 800,
confine: true,
textStyle: {
color: 'inherit',
fontFamily: 'inherit',
fontSize: 'inherit',
},
appendToBody: true,
backgroundColor: getPlatteColor('page-background'),
borderColor: getPlatteColor('very-muted-foreground'),
},
series: [
{
name: graphTitle,
type: 'graph',
layout: 'force',
top: 0,
bottom: 0,
left: 0,
right: 0,
height: '100%',
width: '100%',
nodes,
edges,
categories: ifChinese ? CategoriesZh : CategoriesEn,
roam: true,
draggable: true,
zoom: 4,
label: {
position: 'right',
show: true,
backgroundColor: 'transparent',
},
labelLayout: {
moveOverlap: true,
},
force: {
repulsion: 50,
},
cursor: 'pointer',
symbolSize: 6,
edgeSymbol: ['none', 'arrow'],
edgeSymbolSize: [0, 5],
lineStyle: {
width: 1,
opacity: 0.75,
curveness: 0.15,
},
itemStyle: {
opacity: 0.9,
},
},
],
} as any);
},
};
export default TheBrainAddon;
/* eslint-enable max-lines */

View File

@ -0,0 +1,3 @@
Modern.TiddlyDev#IncludeSource: true
title: $:/plugins/Gk0Wk/echarts/addons/TheBrain.ts
type: application/javascript

View File

@ -0,0 +1,3 @@
title: $:/plugins/Gk0Wk/echarts/addons/TheBrainPopup
<h1><$text text=<<currentTiddler>> /></h1><$list filter="[<currentTiddler>tags[]count[]match[0]]"><$transclude tiddler="$:/core/ui/ViewTemplate/tags" /></$list><$transclude tiddler="$:/core/ui/ViewTemplate/body" mode="inline" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,2 @@
title: $:/plugins/Gk0Wk/echarts/banner
type: image/jpeg

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
Modern.TiddlyDev#Minify: false
module-type: echarts-extension
title: $:/plugins/Gk0Wk/echarts/echarts-wordcloud.min.js
type: application/javascript
version: 2.1.0

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
Modern.TiddlyDev#Minify: false
module-type: library
title: $:/plugins/Gk0Wk/echarts/echarts.min.js
type: application/javascript
version: 5.4.1

View File

@ -0,0 +1,14 @@
tags: $:/tags/Macro
title: $:/plugins/Gk0Wk/echarts/macro
type: text/vnd.tiddlywiki
\define echarts(textortiddler,height:"300px",width:"100%",class:"gk0wk-echarts-body",theme:"auto",renderer:"canvas",fillSidebar:"true")
<$set name="textortiddler" value="""$textortiddler$""">
<$list filter="[<textortiddler>is[tiddler]] [<textortiddler>is[shadow]]">
<$echarts $tiddler=<<textortiddler>> $height="$height$" $width="$width$" $class="$class$" $theme="$theme$" $renderer="$renderer$" $fillSidebar="$fillSidebar$"/>
</$list>
<$list filter="[<textortiddler>!is[tiddler]!is[shadow]]">
<$echarts $text=<<textortiddler>> $height="$height$" $width="$width$" $class="$class$" $theme="$theme$" $renderer="$renderer$" $fillSidebar="$fillSidebar$"/>
</$list>
</$set>
\end

View File

@ -0,0 +1,25 @@
title: $:/plugins/Gk0Wk/echarts/readme
<$list filter="[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]" variable="lang">
<$list filter="[<lang>search[zh]]">
将强大的可视化工具 [[ECharts|https://echarts.apache.org/zh/index.html]] 以优雅的方式与 TiddlyWiki 相结合。
插件说明与使用教程较长,请参考 https://tiddly-gittly.github.io/tw-echarts/
> 本插件使用灵活而强大的 <$text text="TiddlyWiki" /> 开发框架 [[Tiddly.ModernDev|https://github.com/tiddly-gittly/Modern.TiddlyDev]]
</$list>
<$list filter="[<lang>!search[zh]]">
Combines the powerful visualization tool [[ECharts|https://echarts.apache.org/en/index.html]] with TiddlyWiki in an elegant way.
The plugin description and tutorial is long, please refer to https://tiddly-gittly.github.io/tw-echarts/
> This plugin uses the flexible and powerful <$text text="TiddlyWiki" /> development framework [[Tiddly.ModernDev|https://github.com/tiddly-gittly/Modern.TiddlyDev]]
</$list>
</$list>
[img[$:/plugins/Gk0Wk/echarts/banner]]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
Modern.TiddlyDev#Origin: widget.ts
module-type: widget
title: $:/plugins/Gk0Wk/echarts/widget.js
type: application/javascript

View File

@ -0,0 +1,13 @@
{
"version": "0.1.4",
"title": "$:/plugins/Gk0Wk/echarts",
"plugin-type": "plugin",
"name": "ECharts",
"list": "readme LICENSE",
"description": "ECharts for TiddlyWiki5",
"author": "Gk0Wk",
"source": "https://github.com/tiddly-gittly/tw-echarts/tree/master/plugins/Gk0Wk/echarts",
"dependents": "$:/plugins/Gk0Wk/focused-tiddler",
"Modern.TiddlyDev#SHA256-Hashed": "f5cbae57e5d060bfca14eaa6b8a5669a56e0139b0250e5c65d215cdcafb5a07e",
"core-version": ">=5.2.0"
}