[
    {
        "author": "Gk0Wk",
        "dependents": "",
        "description": "Use tiddler's H1~H6 headers to generate navigable TOC for tiddler",
        "list": "readme LICENSE",
        "name": "Page TOC",
        "plugin-type": "plugin",
        "source": "https://github.com/Gk0Wk/TiddlySeq/tree/master/plugins/Gk0Wk/page-toc",
        "text": "{\"tiddlers\":{\"$:/plugins/Gk0Wk/page-toc/CurrentTiddlerTOC\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/CurrentTiddlerTOC\",\"text\":\"<$list filter=\\\"[[$:/temp/focussedTiddler]is[tiddler]get[text]]\\\" variable=\\\"tiddler\\\">\\n\\nTOC of <$text text=<<tiddler>>/>:\\n<$page-toc tiddler=<<tiddler>> emptyMessage=\\\"Empty TOC\\\"/>\\n\\n</$list>\\n\"},\"$:/plugins/Gk0Wk/page-toc/LICENSE\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/LICENSE\",\"text\":\"MIT License\\n\\nCopyright (c) 2021 Ke Wang (Gk0Wk in GitHub)\\n\\nPermission is hereby granted, free of charge, to any person obtaining a copy\\nof this software and associated documentation files (the \\\"Software\\\"), to deal\\nin the Software without restriction, including without limitation the rights\\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\\ncopies of the Software, and to permit persons to whom the Software is\\nfurnished to do so, subject to the following conditions:\\n\\nThe above copyright notice and this permission notice shall be included in all\\ncopies or substantial portions of the Software.\\n\\nTHE SOFTWARE IS PROVIDED \\\"AS IS\\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\\nSOFTWARE.\\n\",\"type\":\"text/plain\"},\"$:/plugins/Gk0Wk/page-toc/PageTOCButton\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/PageTOCButton\",\"list-after\":\"$:/core/ui/Buttons/info\",\"tags\":\"$:/tags/ViewToolbar\",\"caption\":\"{{$:/core/images/list-bullet}} {{$:/plugins/Gk0Wk/page-toc/PageTOCButton!!hint}}\",\"description\":\"Show TOC of this tiddler\",\"hint\":\"Page TOC\",\"text\":\"\\\\whitespace trim\\n<$set value={{{ [<currentTiddler>addprefix[$:/temp/Gk0Wk/page-toc/PageTOCButton/]] }}} name=\\\"stateTiddler\\\">\\n<$button popup=<<stateTiddler>> tooltip={{$:/plugins/Gk0Wk/page-toc/PageTOCButton!!description}} aria-label={{$:/plugins/Gk0Wk/page-toc/PageTOCButton!!hint}} class=<<tv-config-toolbar-class>>>\\n<$list filter=\\\"[<tv-config-toolbar-icons>match[yes]]\\\">{{$:/core/images/list-bullet}}</$list>\\n<$list filter=\\\"[<tv-config-toolbar-text>match[yes]]\\\"><span class=\\\"tc-btn-text\\\">{{$:/plugins/Gk0Wk/page-toc/PageTOCButton!!hint}}</span></$list>\\n</$button>\\n<$reveal type=\\\"popup\\\" state=<<stateTiddler>> position=\\\"belowleft\\\" tag=\\\"div\\\" class=\\\"tc-popup-keep\\\">\\n<$page-toc tiddler=<<currentTiddler>> emptyMessage=\\\"Empty TOC\\\" class=\\\"gk0wk-tiddlertoc-viewbuttonpopup\\\" headerClassPrefix=\\\"gk0wk-tiddlertoc-viewbuttonpopup-\\\" />\\n</$reveal>\\n</$set>\\n\"},\"$:/plugins/Gk0Wk/page-toc/readme\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/readme\",\"text\":\"<$list filter=\\\"[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]\\\" variable=\\\"lang\\\">\\n<$list filter=\\\"[<lang>search[zh]]\\\">\\n\\n利用条目的H1~H6标题为条目生成可导航的目录。没错，就是对单个条目生成的标题目录。而且目录是点击可导航的，就是说会滚动到标题所在的位置！\\n\\n虽然TiddlyWiki的组织逻辑不推荐编写过长的条目，但总会有碰到阅读长条目的时候。相信所有有类似经历的用户都曾想过：如果能为单个长条目生成阅读目录就好了，毕竟迷失在长文中是一件很痛苦的事情。我也是这其中的一员。\\n\\n本插件提供了一个能够对某个条目生成目录的空间`<$page-toc>`，参数如下：\\n\\n|!参数 |!解释 |\\n|tiddler |要生成目录的条目的标题，默认是当前条目(`currentTiddler`) |\\n|tag |为目录外层容器提供一个可选的HTML标签，用于代替默认的`div` |\\n|headerTag |为目录内层标题提供一个可选的HTML标签，用于代替默认的`p` |\\n|class |为目录外层容器指定类名，默认是`gk0wk-tiddlertoc-container` |\\n|headerClassPrefix |为目录内层标题指定类前缀(后面是`h1`~`h6`或`empty`)，默认是`gk0wk-tiddlertoc-` |\\n|emptyMessage |目录为空、条目不存在或者条目不是文章时显示的文字 |\\n|scrollMode |滚动到标题的模式，`center`(默认)是将标题滚动到窗口中央，`start`和`end`是滚动到窗口的顶部和底部，`nearest`是根据相对位置选择滚动到顶部或者底部 |\\n|h1, h2, ..., h6 |是否将某一级标题包含在内，默认均为`yes` |\\n\\n例如：\\n\\n```\\n<$page-toc tiddler=<<currentTiddler>> emptyMessage=\\\"Empty TOC\\\"/>\\n```\\n\\n同时，我利用这个控件编写了两个小的组件，可以直接使用这两个组件，也可以学习这两个组件的用法做自己的DIY：\\n\\n* [[CurrentTiddlerTOC|$:/plugins/Gk0Wk/page-toc/CurrentTiddlerTOC]] 可以显示当前所阅读的条目的名称并生成目录，但是需要[[Hotzone插件|https://tw-cpl.netlify.app/#felixhayashi%2Fhotzone]]的支持。\\n* [[PageTOCButton|$:/plugins/Gk0Wk/page-toc/PageTOCButton]] 为每个条目的工具栏增加以一个 {{$:/core/images/list-bullet}} 按钮，点击即可显示目录。\\n\\n如有任何使用问题，欢迎向我提[[Issue|https://github.com/Gk0Wk/TiddlySeq/issues]]！\\n\\n> 本插件使用灵活而强大的 <$text text=\\\"TiddlyWiki\\\" /> 开发框架 [[Tiddly.ModernDev|https://github.com/tiddly-gittly/Modern.TiddlyDev]]\\n\\n</$list>\\n\\n<$list filter=\\\"[<lang>!search[zh]]\\\">\\n\\nGenerate a navigable table of contents for tiddlers using the H1~H6 headings of the tiddlers. That's right, it's a headline table of contents generated for a single tiddler. And the table of contents is navigable by clicking on it, meaning it will scroll to where the title is!\\n\\nAlthough TiddlyWiki's organizational logic does not recommend writing excessively long tiddlers, there will always be times when you read long tiddlers. I'm sure all users who have had similar experiences have wondered if it would be nice to have a table of contents for individual long tiddlers, after all, it's a pain to get lost in long articles. I am also one of them.\\n\\nThis plugin provides a widget `<$page-toc>` that can generate a table of contents for a tiddler with the following parameters.\\n\\n|!Attribute |!Description |\\n|tiddler |Title of the tiddler to generate the TOC, default is the current tiddler (`currentTiddler`) |\\n|tag |Provide an optional HTML tag for the outer container of the TOC to replace the default `div` |\\n|headerTag |Provide an optional HTML tag for the inner TOC header to replace the default `p` |\\n|class |Specify the class name for the outer container of the TOC, the default is `gk0wk-tiddlertoc-container` |\\n|headerClassPrefix |Specify the class prefix (followed by `h1`~`h6` or `empty`) for the TOC inner level title, default is `gk0wk-tiddlertoc-` |\\n|emptyMessage |The text displayed when the table of contents is empty, the tiddler does not exist, or the tiddler is not an article |\\n|scrollMode |Scroll to header mode, `center` (default) is to scroll the header to the center of the window, `start` and `end` are to scroll to the top and bottom of the window, and `nearest` is to scroll to the top or bottom depending on the relative position |\\n|h1, h2, ..., h6 |Whether to include a certain level of title, default is `yes` |\\n\\nFor instance:\\n\\n```\\n<$page-toc tiddler=<<currentTiddler>> emptyMessage=\\\"Empty TOC\\\"/>\\n```\\n\\nAt the same time, I have written two small components using this widget, which can be used directly or you can learn the usage of these two components to do your own DIY:\\n\\n* [[CurrentTiddlerTOC|$:/plugins/Gk0Wk/page-toc/CurrentTiddlerTOC]] You can display the name of the currently read tiddler and generate a table of contents, but it requires the support of [[Hotzone Plugin|https://tw-cpl.netlify.app/#felixhayashi%2Fhotzone]].\\n* [[PageTOCButton|$:/plugins/Gk0Wk/page-toc/PageTOCButton]] Add a {{$:/core/images/list-bullet}} button to the toolbar for each tiddler and click it to display the table of contents.\\n\\nFeel free to make me an [[Issue|https://github.com/Gk0Wk/TiddlySeq/issues]] if you have any usage problems!\\n\\n> This plugin uses the flexible and powerful <$text text=\\\"TiddlyWiki\\\" /> development framework [[Tiddly.ModernDev|https://github.com/tiddly-gittly/Modern.TiddlyDev]]\\n\\n</$list>\\n</$list>\\n\"},\"$:/plugins/Gk0Wk/page-toc/style.css\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/style.css\",\"text\":\".gk0wk-tiddlertoc-h1 {\\n  padding-left: 0;\\n}\\n.gk0wk-tiddlertoc-h2 {\\n  padding-left: 1em;\\n}\\n.gk0wk-tiddlertoc-h3 {\\n  padding-left: 2em;\\n}\\n.gk0wk-tiddlertoc-h4 {\\n  padding-left: 3em;\\n}\\n.gk0wk-tiddlertoc-h5 {\\n  padding-left: 4em;\\n}\\n.gk0wk-tiddlertoc-h6 {\\n  padding-left: 5em;\\n}\\n\\n.gk0wk-tiddlertoc-empty {\\n  color: <<colour very-muted-foreground>>;\\n  user-select: none;\\n}\\n\\n.gk0wk-tiddlertoc-h1,\\n.gk0wk-tiddlertoc-h2,\\n.gk0wk-tiddlertoc-h3,\\n.gk0wk-tiddlertoc-h4,\\n.gk0wk-tiddlertoc-h5,\\n.gk0wk-tiddlertoc-h6 {\\n  user-select: none;\\n  cursor: pointer;\\n  transition: all {{$:/config/AnimationDuration}}ms;\\n}\\n\\n.gk0wk-tiddlertoc-h1:hover,\\n.gk0wk-tiddlertoc-h2:hover,\\n.gk0wk-tiddlertoc-h3:hover,\\n.gk0wk-tiddlertoc-h4:hover,\\n.gk0wk-tiddlertoc-h5:hover,\\n.gk0wk-tiddlertoc-h6:hover {\\n  color: <<colour foreground>>;\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup {\\n  border-radius: 3px;\\n  background: <<colour page-background>>;\\n  width: min(90vw, 300px);\\n  <<box-shadow \\\"#00000070 0 2px 6px\\\">>\\n  filter: contrast(90%);\\n  padding: 0;\\n  overflow-y: auto;\\n  max-height: 80vh;\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h1 {\\n  padding-left: 16px;\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h2 {\\n  padding-left: calc(16px + 1em);\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h3 {\\n  padding-left: calc(16px + 2em);\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h4 {\\n  padding-left: calc(16px + 3em);\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h5 {\\n  padding-left: calc(16px + 4em);\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h6 {\\n  padding-left: calc(16px + 5em);\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-empty {\\n  color: <<colour very-muted-foreground>>;\\n  user-select: none;\\n  font-size: 24px;\\n  line-height: 1em;\\n  padding: 20px;\\n  text-align: center;\\n  margin: 0 !important;\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h1,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h2,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h3,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h4,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h5,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h6 {\\n  font-size: 16px;\\n  font-weight: 700;\\n  line-height: 1em;\\n  margin: 0 !important;\\n  padding-top: 10px;\\n  padding-bottom: 10px;\\n  padding-right: 6px;\\n  user-select: none;\\n  cursor: pointer;\\n  background: transparent;\\n  opacity: 0.7;\\n  white-space: nowrap;\\n  text-overflow: ellipsis;\\n  overflow: hidden;\\n  transition: all {{$:/config/AnimationDuration}}ms;\\n}\\n\\n.gk0wk-tiddlertoc-viewbuttonpopup-h1:hover,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h2:hover,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h3:hover,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h4:hover,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h5:hover,\\n.gk0wk-tiddlertoc-viewbuttonpopup-h6:hover {\\n  opacity: 1;\\n  background: <<colour background>>;\\n  color: <<colour foreground>>;\\n}\\n\",\"tags\":\"$:/tags/Stylesheet\",\"type\":\"text/vnd.tiddlywiki\"},\"$:/plugins/Gk0Wk/page-toc/PageTOCWidget.js\":{\"title\":\"$:/plugins/Gk0Wk/page-toc/PageTOCWidget.js\",\"module-type\":\"widget\",\"type\":\"application/javascript\",\"Modern.TiddlyDev#Origin\":\"PageTOCWidget.ts\",\"text\":\"\\\"use strict\\\";var import_widget=require(\\\"$:/core/modules/widgets/widget.js\\\"),PageTOCWidget=class extends import_widget.widget{constructor(){super(...arguments),this.tocNodeTag=\\\"div\\\",this.tocHeaderNodeTag=\\\"p\\\",this.tocNodeClass=\\\"gk0wk-tiddlertoc-container\\\",this.tocHeaderNodeClassPrefix=\\\"gk0wk-tiddlertoc-\\\",this.tocTitle=\\\"\\\",this.emptyMessage=\\\"\\\",this.scrollMode=\\\"center\\\",this.includeHeaderMap={h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0}}initialise(e,t){super.initialise(e,t),this.computeAttributes()}execute(){this.tocTitle=this.getAttribute(\\\"tiddler\\\",this.getVariable(\\\"currentTiddler\\\")),this.tocNodeTag=this.getAttribute(\\\"tag\\\",\\\"div\\\"),$tw.config.htmlUnsafeElements.includes(this.tocNodeTag)&&(this.tocNodeTag=\\\"div\\\"),this.tocHeaderNodeTag=this.getAttribute(\\\"headerTag\\\",\\\"p\\\"),$tw.config.htmlUnsafeElements.includes(this.tocHeaderNodeTag)&&(this.tocHeaderNodeTag=\\\"p\\\"),this.tocNodeClass=this.getAttribute(\\\"class\\\",\\\"gk0wk-tiddlertoc-container\\\"),this.tocHeaderNodeClassPrefix=this.getAttribute(\\\"headerClassPrefix\\\",\\\"gk0wk-tiddlertoc-\\\"),this.emptyMessage=this.getAttribute(\\\"emptyMessage\\\",\\\"\\\"),this.includeHeaderMap.h1=\\\"yes\\\"===this.getAttribute(\\\"h1\\\",\\\"yes\\\"),this.includeHeaderMap.h2=\\\"yes\\\"===this.getAttribute(\\\"h2\\\",\\\"yes\\\"),this.includeHeaderMap.h3=\\\"yes\\\"===this.getAttribute(\\\"h3\\\",\\\"yes\\\"),this.includeHeaderMap.h4=\\\"yes\\\"===this.getAttribute(\\\"h4\\\",\\\"yes\\\"),this.includeHeaderMap.h5=\\\"yes\\\"===this.getAttribute(\\\"h5\\\",\\\"yes\\\"),this.includeHeaderMap.h6=\\\"yes\\\"===this.getAttribute(\\\"h6\\\",\\\"yes\\\"),this.scrollMode=this.getAttribute(\\\"scrollMode\\\",\\\"center\\\"),[\\\"start\\\",\\\"center\\\",\\\"end\\\",\\\"nearest\\\"].includes(this.scrollMode)||(this.scrollMode=\\\"center\\\")}render(e,i){if(this.parentDomNode=e,this.execute(),this.parentWidget.hasVariable(\\\"page-toc-recursion-detection\\\",\\\"yes\\\"))this.domNodes.push(e.appendChild(this.document.createTextNode(\\\"[Page TOC]\\\")));else{this.setVariable(\\\"page-toc-recursion-detection\\\",\\\"yes\\\");var s=$tw.utils.domMaker(this.tocNodeTag,{\\\"class\\\":this.tocNodeClass});this.domNodes.push(s);try{const o=this.getTOCInfo();if(o&&0!==o.headers.length)for(let e=0,t=o.headers.length;e<t;e++){const{tag:d,text:l,count:a}=o.headers[e];var r=$tw.utils.domMaker(this.tocHeaderNodeTag,{\\\"class\\\":\\\"\\\"+this.tocHeaderNodeClassPrefix+d,text:l});$tw.browser&&r.addEventListener(\\\"click\\\",()=>{var e,t,i=null==(t=null==(e=null==(t=document.querySelector(`.tc-tiddler-frame[data-tiddler-title=\\\"${o.title.replace('\\\"','\\\\\\\\\\\"')}\\\"]`))?void 0:t.querySelectorAll)?void 0:e.call(t,\\\".tc-tiddler-body \\\"+d))?void 0:t[a];if(i)switch(this.scrollMode){case\\\"center\\\":case\\\"nearest\\\":i.scrollIntoView({behavior:\\\"smooth\\\",block:this.scrollMode});break;default:i.scrollIntoView({behavior:\\\"auto\\\",block:this.scrollMode}),\\\"end\\\"===this.scrollMode?(document.body.scrollTop+=100,document.scrollingElement&&(document.scrollingElement.scrollTop+=100)):(document.body.scrollTop-=100,document.scrollingElement&&(document.scrollingElement.scrollTop-=100))}}),s.appendChild(r)}else s.insertBefore($tw.utils.domMaker(this.tocHeaderNodeTag,{\\\"class\\\":this.tocHeaderNodeClassPrefix+\\\"empty\\\",text:this.emptyMessage}),i)}catch(t){console.error(t),s.textContent=String(t)}e.insertBefore(s,i)}}refresh(e){var t=this.computeAttributes();return 0<$tw.utils.count(t)||Object.hasOwnProperty.call(t,this.tocTitle)?(this.refreshSelf(),this.refreshChildren(e),!0):this.refreshChildren(e)}getTOCInfo(){if(\\\"\\\"!==this.tocTitle){var e=$tw.wiki.getTiddler(this.tocTitle);if(e){var e=e.fields.type||\\\"text/vnd.tiddlywiki\\\",t=(null==(t=$tw.config.contentTypeInfo[e])?void 0:t.deserializerType)||e;if(\\\"text/vnd.tiddlywiki\\\"===t||\\\"text/x-markdown\\\"===t){for(var i=[],s={h1:0,h2:0,h3:0,h4:0,h5:0,h6:0},e=$tw.wiki.parseTiddler(this.tocTitle).tree,t=$tw.wiki.makeWidget({tree:e}),e=$tw.fakeDocument.createElement(\\\"div\\\"),r=(t.render(e,null),[e]);0<r.length;){var o=r.pop();if(/^h[1-6]$/.test(o.tagName)&&(console.log(o),i.push({tag:o.tagName,count:s[o.tagName]++,text:o.textContent||\\\"\\\"})),Array.isArray(o.children))for(let e=o.children.length-1;0<=e;e--)r.push(o.children[e])}return{title:this.tocTitle,headers:i}}}}}};exports[\\\"page-toc\\\"]=PageTOCWidget;\"}}}",
        "title": "$:/plugins/Gk0Wk/page-toc",
        "type": "application/json",
        "version": "0.0.5",
        "Modern.TiddlyDev#SHA256-Hashed": "6f71bcc34f5a179510ae8d550a86821fd3ae698002a035fae23623ad24f32b12"
    }
]