aboutsummaryrefslogtreecommitdiffstats
path: root/tiddlers
diff options
context:
space:
mode:
authorshu <nvcsadjkojf@outlook.com>2026-08-19 15:56:06 +0800
committershu <nvcsadjkojf@outlook.com>2026-08-19 15:56:06 +0800
commitca1a4a31706d0c03673fe4c414c645ed826b21c6 (patch)
treec412265a19dd4694c39aac65b6e1a8903a513978 /tiddlers
parent490d41f154615a52734f117d7d7bda5a9331e303 (diff)
精简 Wiki 构建与运行方式
将浏览器端工具整理为 utilities 插件,移除 Docker、Org GTD 和 files API,并补充单文件构建及 Node.js 运行入口。
Diffstat (limited to 'tiddlers')
-rw-r--r--tiddlers/$__StoryList.tid3
-rw-r--r--tiddlers/$__StoryList_2.tid0
-rw-r--r--tiddlers/$__config_org-gtd_extraKeys.json8
-rw-r--r--tiddlers/$__config_org-gtd_extraKeys.json.meta4
-rw-r--r--tiddlers/GTD Agenda.tid5
-rw-r--r--tiddlers/GTD Inbox.org5
-rw-r--r--tiddlers/GTD Inbox.org.meta4
-rw-r--r--tiddlers/Org GTD 使用说明.tid46
-rw-r--r--tiddlers/files API demo.tid51
-rw-r--r--tiddlers/files-list-api.tid.js.meta5
-rw-r--r--tiddlers/plugin-copy-codeblock-widget.tid72
-rw-r--r--tiddlers/plugin-current-tiddler-toc-sidebar.tid69
-rw-r--r--tiddlers/plugin-current-tiddler-toc-widget.tid284
-rw-r--r--tiddlers/plugin-files-api-route.tid132
-rw-r--r--tiddlers/plugin-highlight-caddyfile.tid65
-rw-r--r--tiddlers/plugin-highlight-json5.tid59
-rw-r--r--tiddlers/plugin-highlight-tiddlywiki.tid191
-rw-r--r--tiddlers/plugin-journal-calendar-widget.tid333
-rw-r--r--tiddlers/plugin-org-gtd-agenda-widget.tid229
-rw-r--r--tiddlers/plugin-org-gtd-codemirror.tid341
-rw-r--r--tiddlers/plugin-org-gtd-content-type.tid12
-rw-r--r--tiddlers/plugin-org-gtd-editor-mapping.tid2
-rw-r--r--tiddlers/plugin-org-gtd-library.tid141
-rw-r--r--tiddlers/plugin-org-gtd-parser.tid76
-rw-r--r--tiddlers/plugin-org-gtd-sidebar.tid13
-rw-r--r--tiddlers/plugin-org-gtd-styles.tid159
-rw-r--r--tiddlers/tiddlywiki.tid44
-rw-r--r--tiddlers/日历.tid77
28 files changed, 76 insertions, 2354 deletions
diff --git a/tiddlers/$__StoryList.tid b/tiddlers/$__StoryList.tid
index 1231352..e69de29 100644
--- a/tiddlers/$__StoryList.tid
+++ b/tiddlers/$__StoryList.tid
@@ -1,3 +0,0 @@
-list: tag 日历 tiddlywiki
-title: $:/StoryList
-type: text/vnd.tiddlywiki \ No newline at end of file
diff --git a/tiddlers/$__StoryList_2.tid b/tiddlers/$__StoryList_2.tid
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tiddlers/$__StoryList_2.tid
diff --git a/tiddlers/$__config_org-gtd_extraKeys.json b/tiddlers/$__config_org-gtd_extraKeys.json
deleted file mode 100644
index d79f694..0000000
--- a/tiddlers/$__config_org-gtd_extraKeys.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "Alt-T": "orgGtdCycleState",
- "Ctrl-Left": "orgGtdPromote",
- "Ctrl-Right": "orgGtdDemote",
- "Ctrl-Up": "orgGtdMoveUp",
- "Ctrl-Down": "orgGtdMoveDown",
- "Alt-Y": "orgGtdToggleFold"
-}
diff --git a/tiddlers/$__config_org-gtd_extraKeys.json.meta b/tiddlers/$__config_org-gtd_extraKeys.json.meta
deleted file mode 100644
index 2fb750a..0000000
--- a/tiddlers/$__config_org-gtd_extraKeys.json.meta
+++ /dev/null
@@ -1,4 +0,0 @@
-created: 20260728104833107
-modified: 20260728105401160
-title: $:/config/org-gtd/extraKeys
-type: application/json \ No newline at end of file
diff --git a/tiddlers/GTD Agenda.tid b/tiddlers/GTD Agenda.tid
deleted file mode 100644
index 69614ea..0000000
--- a/tiddlers/GTD Agenda.tid
+++ /dev/null
@@ -1,5 +0,0 @@
-created: 20260728000000000
-title: GTD Agenda
-type: text/vnd.tiddlywiki
-
-<$org-gtd-agenda days="7"/>
diff --git a/tiddlers/GTD Inbox.org b/tiddlers/GTD Inbox.org
deleted file mode 100644
index 742123e..0000000
--- a/tiddlers/GTD Inbox.org
+++ /dev/null
@@ -1,5 +0,0 @@
-* TODO 熟悉 Org GTD 插件 :gtd:
- SCHEDULED: <2026-07-28 Tue>
-** WAIT 根据实际工作流调整任务内容
-** NEXT 打开 GTD Agenda 查看任务
-* DONE 已安装 Org GTD 插件 \ No newline at end of file
diff --git a/tiddlers/GTD Inbox.org.meta b/tiddlers/GTD Inbox.org.meta
deleted file mode 100644
index 7855b61..0000000
--- a/tiddlers/GTD Inbox.org.meta
+++ /dev/null
@@ -1,4 +0,0 @@
-created: 20260728000000000
-modified: 20260728105340434
-title: GTD Inbox
-type: text/x-org \ No newline at end of file
diff --git a/tiddlers/Org GTD 使用说明.tid b/tiddlers/Org GTD 使用说明.tid
deleted file mode 100644
index 2a670ee..0000000
--- a/tiddlers/Org GTD 使用说明.tid
+++ /dev/null
@@ -1,46 +0,0 @@
-created: 20260728000000000
-modified: 20260728090815424
-tags: 🍀
-title: Org GTD 使用说明
-type: text/vnd.tiddlywiki
-
-!语法
-
-在 [[GTD Agenda]] 中点击“新建 Org 文档”,使用以下子集:
-
-```org
-* TODO 收集任务 :work:
- SCHEDULED: <2026-07-29 Wed>
- DEADLINE: <2026-07-31 Fri>
-** NEXT 下一步行动
-** WAIT 等待他人
-* DONE 已完成事项
-```
-
-!CodeMirror 快捷键
-
-插件默认不绑定快捷键,避免与浏览器、桌面环境和 TiddlyWiki 冲突。普通按键(包括 Tab)保持 CodeMirror 原有行为。
-
-需要快捷键时,编辑 [[$:/config/org-gtd/extraKeys]],按 CodeMirror 键名到命令名的格式填写 JSON。组合键内部使用连字符,例如 `Ctrl-Left`;空格表示连续按键,例如 `F8 T`。配置只在 Org 编辑器中生效;保存后重新打开编辑器。
-
-例如,将 `Ctrl-Left` 绑定为提升层级,并将 `F8` 后按 `T` 绑定为循环任务状态:
-
-```json
-{
- "Ctrl-Left": "orgGtdPromote",
- "F8 T": "orgGtdCycleState"
-}
-```
-
-可用命令:
-
-|命令 |操作 |h
-|orgGtdCycleState |循环 TODO → NEXT → WAIT → DONE |
-|orgGtdPromote / orgGtdDemote |提升 / 降低当前子树层级 |
-|orgGtdMoveUp / orgGtdMoveDown |向上 / 向下移动当前子树 |
-|orgGtdInsertSibling |新建同级 TODO 标题 |
-|orgGtdToggleFold |折叠 / 展开当前子树 |
-
-保持配置内容为 `{}` 即可禁用全部 Org GTD 快捷键。
-
-Agenda 显示逾期、今天、未来 7 天和无日期的 NEXT。点击 Agenda 事项会打开源 Org 文档并定位到对应标题。
diff --git a/tiddlers/files API demo.tid b/tiddlers/files API demo.tid
deleted file mode 100644
index dce6e46..0000000
--- a/tiddlers/files API demo.tid
+++ /dev/null
@@ -1,51 +0,0 @@
-created: 20260726073547121
-modified: 20260726085801292
-tags: tiddlywiki
-title: files API demo
-type: text/vnd.tiddlywiki
-
-\procedure store-file-list()
-<$action-setfield
- $tiddler="$:/temp/files-list"
- text=<<data>>
- type="application/json"
-/>
-\end
-
-<$button>
- <$action-sendmessage
- $message="tm-http-request"
- url="./api/files"
- method="GET"
- oncompletion=<<store-file-list>>
- />
- 刷新文件列表
-</$button>
-
-<pre><$text text={{$:/temp/files-list}}/></pre>
-
-[img[./files/photo_2026-07-26_11-10-12.jpg]]
-
-
-```caddyfile
-example.com {
- encode zstd gzip
-
- @api path /api/*
- reverse_proxy @api localhost:3000
-
- header {
- X-Content-Type-Options nosniff
- }
-}
-```
-
-```json5
-{
- // 支持注释
- unquoted: 'value',
- hexadecimal: 0xFF,
- infinity: Infinity,
- trailingComma: true,
-}
-``` \ No newline at end of file
diff --git a/tiddlers/files-list-api.tid.js.meta b/tiddlers/files-list-api.tid.js.meta
deleted file mode 100644
index 066c85b..0000000
--- a/tiddlers/files-list-api.tid.js.meta
+++ /dev/null
@@ -1,5 +0,0 @@
-created: 20260726082748103
-modified: 20260726082841751
-tags: tiddlywiki
-title: files-list-api.tid
-type: application/javascript \ No newline at end of file
diff --git a/tiddlers/plugin-copy-codeblock-widget.tid b/tiddlers/plugin-copy-codeblock-widget.tid
deleted file mode 100644
index 2251c62..0000000
--- a/tiddlers/plugin-copy-codeblock-widget.tid
+++ /dev/null
@@ -1,72 +0,0 @@
-title: $:/plugins/local/copy-codeblock/copy-codeblock.js
-type: application/javascript
-module-type: widget
-
-/*\
-title: $:/plugins/local/copy-codeblock/copy-codeblock.js
-type: application/javascript
-module-type: widget
-
-Adds a copy button to code blocks.
-\*/
-(function() {
-"use strict";
-
-var CodeBlockWidget = require("$:/core/modules/widgets/codeblock.js").codeblock;
-
-var CopyCodeBlockWidget = function(parseTreeNode,options) {
- this.initialise(parseTreeNode,options);
-};
-
-CopyCodeBlockWidget.prototype = new CodeBlockWidget();
-CopyCodeBlockWidget.prototype.constructor = CopyCodeBlockWidget;
-
-CopyCodeBlockWidget.prototype.postRender = function() {
- var self = this,
- preNode = this.domNodes[0],
- previousNode,
- button;
-
- // Preserve syntax highlighting supplied by the highlight plugin.
- if(CodeBlockWidget.prototype.postRender) {
- CodeBlockWidget.prototype.postRender.call(this);
- }
-
- if(!$tw.browser || !preNode || preNode.isTiddlyWikiFakeDom) {
- return;
- }
-
- // The system code view already renders its own copy button.
- previousNode = preNode.previousElementSibling;
- if(previousNode && previousNode.querySelector && previousNode.querySelector(".tc-image-copy-clipboard")) {
- return;
- }
-
- preNode.style.position = "relative";
- preNode.style.paddingRight = "5em";
-
- button = this.document.createElement("button");
- button.setAttribute("type","button");
- button.setAttribute("aria-label","Copy code");
- button.setAttribute("title","Copy code");
- button.className = "tc-btn-invisible tc-copy-codeblock-button";
- button.textContent = "Copy";
- button.style.position = "absolute";
- button.style.top = "0.5em";
- button.style.right = "0.5em";
- button.style.zIndex = "1";
- button.style.padding = "0.2em 0.45em";
- button.style.cursor = "pointer";
-
- button.addEventListener("click",function(event) {
- event.preventDefault();
- event.stopPropagation();
- $tw.utils.copyToClipboard(self.getAttribute("code",""));
- });
-
- preNode.appendChild(button);
-};
-
-exports.codeblock = CopyCodeBlockWidget;
-
-})();
diff --git a/tiddlers/plugin-current-tiddler-toc-sidebar.tid b/tiddlers/plugin-current-tiddler-toc-sidebar.tid
deleted file mode 100644
index 9d73d6d..0000000
--- a/tiddlers/plugin-current-tiddler-toc-sidebar.tid
+++ /dev/null
@@ -1,69 +0,0 @@
-title: $:/plugins/local/current-tiddler-toc/sidebar
-type: text/vnd.tiddlywiki
-tags: $:/tags/SideBar
-caption: 目录
-list-after: $:/core/ui/SideBar/More
-
-<style>
-.tc-current-tiddler-toc {
- font-size: 0.95em;
- overflow-y: auto;
- overscroll-behavior: contain;
- scrollbar-gutter: stable;
- padding-right: 0.25em;
-}
-
-.tc-current-tiddler-toc-group {
- margin: 0 0 1em;
-}
-
-.tc-current-tiddler-toc-title {
- display: block;
- width: 100%;
- font-weight: 600;
- margin: 0 0 0.35em;
- padding: 0.2em 0;
- text-align: left;
- overflow-wrap: anywhere;
-}
-
-.tc-current-tiddler-toc-list {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-.tc-current-tiddler-toc-item {
- margin: 0;
- padding-top: 0.2em;
- padding-bottom: 0.2em;
-}
-
-.tc-current-tiddler-toc-link {
- display: block;
- width: 100%;
- padding: 0.2em 0;
- text-align: left;
- line-height: 1.35;
- overflow-wrap: anywhere;
-}
-
-.tc-current-tiddler-toc-link:hover,
-.tc-current-tiddler-toc-link:focus {
- text-decoration: underline;
-}
-
-.tc-current-tiddler-toc-empty {
- color: <<colour muted-foreground>>;
- font-style: italic;
-}
-
-.tc-current-tiddler-toc-group-empty {
- padding-left: 1.1em;
- color: <<colour muted-foreground>>;
- font-size: 0.9em;
- font-style: italic;
-}
-</style>
-
-<$current-tiddler-toc/>
diff --git a/tiddlers/plugin-current-tiddler-toc-widget.tid b/tiddlers/plugin-current-tiddler-toc-widget.tid
deleted file mode 100644
index a68e449..0000000
--- a/tiddlers/plugin-current-tiddler-toc-widget.tid
+++ /dev/null
@@ -1,284 +0,0 @@
-title: $:/plugins/local/current-tiddler-toc/widget.js
-type: application/javascript
-module-type: widget
-
-/*\
-title: $:/plugins/local/current-tiddler-toc/widget.js
-type: application/javascript
-module-type: widget
-
-Displays a table of contents for the current story tiddler.
-\*/
-(function() {
-"use strict";
-
-var Widget = require("$:/core/modules/widgets/widget.js").widget;
-
-var CurrentTiddlerTocWidget = function(parseTreeNode,options) {
- this.initialise(parseTreeNode,options);
-};
-
-CurrentTiddlerTocWidget.prototype = new Widget();
-CurrentTiddlerTocWidget.prototype.constructor = CurrentTiddlerTocWidget;
-
-CurrentTiddlerTocWidget.prototype.render = function(parent,nextSibling) {
- this.parentDomNode = parent;
- this.computeAttributes();
- this.execute();
-
- var container = this.document.createElement("div");
- container.className = "tc-current-tiddler-toc";
-
- parent.insertBefore(container,nextSibling);
- this.domNodes.push(container);
- this.containerNode = container;
-
- if($tw.browser) {
- var self = this,
- windowObject = this.document.defaultView || window;
-
- this.windowObject = windowObject;
- this.resizeHandler = function() {
- self.updateMaxHeight();
- };
- windowObject.addEventListener("resize",this.resizeHandler);
- if(windowObject.visualViewport) {
- windowObject.visualViewport.addEventListener("resize",this.resizeHandler);
- }
- }
-
- this.scheduleBuild();
-};
-
-CurrentTiddlerTocWidget.prototype.execute = function() {
-};
-
-CurrentTiddlerTocWidget.prototype.getStoryTitles = function() {
- return this.wiki.getTiddlerList("$:/StoryList") || [];
-};
-
-CurrentTiddlerTocWidget.prototype.findTiddlerFrame = function(title) {
- var frames = this.document.querySelectorAll(".tc-tiddler-frame[data-tiddler-title]"),
- index;
-
- for(index = 0; index < frames.length; index++) {
- var frame = frames[index],
- frameTitle = frame.getAttribute("data-tiddler-title"),
- frameTiddler;
-
- if(frameTitle === title) {
- return frame;
- }
-
- frameTiddler = this.wiki.getTiddler(frameTitle);
-
- if(frameTiddler && (frameTiddler.fields["draft.of"] === title || frameTiddler.fields["draft.title"] === title)) {
- return frame;
- }
- }
-
- return null;
-};
-
-CurrentTiddlerTocWidget.prototype.clearContainer = function() {
- while(this.containerNode && this.containerNode.firstChild) {
- this.containerNode.removeChild(this.containerNode.firstChild);
- }
-};
-
-CurrentTiddlerTocWidget.prototype.showMessage = function(message) {
- var messageNode = this.document.createElement("div");
-
- messageNode.className = "tc-current-tiddler-toc-empty";
- messageNode.textContent = message;
- this.containerNode.appendChild(messageNode);
-};
-
-CurrentTiddlerTocWidget.prototype.updateMaxHeight = function() {
- if(!this.containerNode || !this.containerNode.parentNode || !this.windowObject) {
- return;
- }
-
- var viewport = this.windowObject.visualViewport,
- viewportHeight = viewport ? viewport.height : this.windowObject.innerHeight,
- top = this.containerNode.getBoundingClientRect().top,
- availableHeight = Math.max(160,Math.floor(viewportHeight - top - 16));
-
- this.containerNode.style.maxHeight = availableHeight + "px";
-};
-
-CurrentTiddlerTocWidget.prototype.getHeadings = function(frame) {
- var body = frame.querySelector(".tc-tiddler-body");
-
- if(!body) {
- body = frame.querySelector(".tc-tiddler-preview-preview");
- }
-
- if(!body) {
- return [];
- }
-
- var headingNodes = body.querySelectorAll("h1, h2, h3, h4, h5, h6"),
- headings = [],
- index;
-
- for(index = 0; index < headingNodes.length; index++) {
- var heading = headingNodes[index];
-
- // Ignore headings that belong to nested, independent tiddler frames.
- if(heading.closest && heading.closest(".tc-tiddler-frame") !== frame) {
- continue;
- }
-
- headings.push({
- node: heading,
- level: parseInt(heading.tagName.substring(1),10),
- text: heading.textContent.trim() || "未命名标题"
- });
- }
-
- return headings;
-};
-
-CurrentTiddlerTocWidget.prototype.addTiddlerGroup = function(title,frame) {
- var self = this,
- groupNode = this.document.createElement("section"),
- titleButton = this.document.createElement("button");
-
- groupNode.className = "tc-current-tiddler-toc-group";
- titleButton.setAttribute("type","button");
- titleButton.className = "tc-btn-invisible tc-current-tiddler-toc-title";
- titleButton.textContent = title;
- titleButton.title = "滚动到条目:" + title;
- titleButton.addEventListener("click",function(event) {
- event.preventDefault();
- frame.scrollIntoView({
- behavior: "smooth",
- block: "start"
- });
- });
- groupNode.appendChild(titleButton);
-
- var headings = this.getHeadings(frame);
-
- if(!headings.length) {
- var emptyNode = this.document.createElement("div");
- emptyNode.className = "tc-current-tiddler-toc-group-empty";
- emptyNode.textContent = "没有标题";
- groupNode.appendChild(emptyNode);
- this.containerNode.appendChild(groupNode);
- return;
- }
-
- var minimumLevel = headings.reduce(function(result,heading) {
- return Math.min(result,heading.level);
- },6),
- listNode = this.document.createElement("ol");
-
- listNode.className = "tc-current-tiddler-toc-list";
- groupNode.appendChild(listNode);
-
- headings.forEach(function(heading) {
- var itemNode = self.document.createElement("li"),
- buttonNode = self.document.createElement("button");
-
- itemNode.className = "tc-current-tiddler-toc-item";
- itemNode.style.paddingLeft = ((heading.level - minimumLevel) * 1.1) + "em";
-
- buttonNode.setAttribute("type","button");
- buttonNode.className = "tc-btn-invisible tc-current-tiddler-toc-link";
- buttonNode.textContent = heading.text;
- buttonNode.title = heading.text;
- buttonNode.addEventListener("click",function(event) {
- event.preventDefault();
- heading.node.scrollIntoView({
- behavior: "smooth",
- block: "start"
- });
- });
-
- itemNode.appendChild(buttonNode);
- listNode.appendChild(itemNode);
- });
-
- this.containerNode.appendChild(groupNode);
-};
-
-CurrentTiddlerTocWidget.prototype.build = function() {
- if(!this.containerNode || !this.containerNode.parentNode) {
- return;
- }
-
- this.clearContainer();
-
- var titles = this.getStoryTitles(),
- index,
- visibleCount = 0;
-
- if(!titles.length) {
- this.showMessage("当前没有打开的条目");
- this.updateMaxHeight();
- return;
- }
-
- for(index = 0; index < titles.length; index++) {
- var title = titles[index],
- frame = this.findTiddlerFrame(title);
-
- if(frame) {
- this.addTiddlerGroup(title,frame);
- visibleCount += 1;
- }
- }
-
- if(!visibleCount) {
- this.showMessage("打开的条目尚未显示");
- }
-
- this.updateMaxHeight();
-};
-
-CurrentTiddlerTocWidget.prototype.scheduleBuild = function() {
- var self = this;
-
- if(!$tw.browser) {
- return;
- }
-
- if(this.buildTimer) {
- clearTimeout(this.buildTimer);
- }
-
- // Wait until the story river has completed the current DOM update.
- this.buildTimer = setTimeout(function() {
- self.buildTimer = null;
- self.build();
- },0);
-};
-
-CurrentTiddlerTocWidget.prototype.refresh = function() {
- this.computeAttributes();
- this.scheduleBuild();
- return false;
-};
-
-CurrentTiddlerTocWidget.prototype.removeChildDomNodes = function() {
- if(this.buildTimer) {
- clearTimeout(this.buildTimer);
- this.buildTimer = null;
- }
- if(this.windowObject && this.resizeHandler) {
- this.windowObject.removeEventListener("resize",this.resizeHandler);
- if(this.windowObject.visualViewport) {
- this.windowObject.visualViewport.removeEventListener("resize",this.resizeHandler);
- }
- this.resizeHandler = null;
- this.windowObject = null;
- }
-
- Widget.prototype.removeChildDomNodes.call(this);
-};
-
-exports["current-tiddler-toc"] = CurrentTiddlerTocWidget;
-
-})();
diff --git a/tiddlers/plugin-files-api-route.tid b/tiddlers/plugin-files-api-route.tid
deleted file mode 100644
index 6236926..0000000
--- a/tiddlers/plugin-files-api-route.tid
+++ /dev/null
@@ -1,132 +0,0 @@
-title: $:/plugins/local/files-api/get-files.js
-type: application/javascript
-module-type: route
-
-/*\
-title: $:/plugins/local/files-api/get-files.js
-type: application/javascript
-module-type: route
-
-GET /api/files
-\*/
-"use strict";
-
-var fs = require("fs"),
- path = require("path");
-
-exports.methods = ["GET"];
-exports.path = /^\/api\/files\/?$/;
-
-exports.info = {
- priority: 100
-};
-
-function encodeFilePath(filename) {
- return filename
- .split(path.sep)
- .map(encodeURIComponent)
- .join("/");
-}
-
-async function scanDirectory(rootDirectory,directory,prefix) {
- var entries,
- files = [];
-
- try {
- entries = await fs.promises.readdir(directory,{
- withFileTypes: true
- });
- } catch(error) {
- if(error.code === "ENOENT") {
- return [];
- }
- throw error;
- }
-
- for(var index = 0; index < entries.length; index++) {
- var entry = entries[index];
-
- // 不公开隐藏文件。
- if(entry.name.charAt(0) === ".") {
- continue;
- }
-
- var absolutePath = path.join(directory,entry.name);
-
- // 忽略符号链接,避免扫描到 files/ 目录之外。
- if(entry.isDirectory()) {
- var childFiles = await scanDirectory(
- rootDirectory,
- absolutePath,
- path.join(prefix,entry.name)
- );
- files.push.apply(files,childFiles);
- continue;
- }
-
- if(!entry.isFile()) {
- continue;
- }
-
- var relativePath = path.join(prefix,entry.name),
- extension = path.extname(entry.name).toLowerCase(),
- extensionInfo = $tw.config.fileExtensionInfo[extension],
- stats;
-
- try {
- stats = await fs.promises.stat(absolutePath);
- } catch(error) {
- // 文件可能在扫描过程中被删除。
- continue;
- }
-
- files.push({
- name: entry.name,
- path: relativePath.split(path.sep).join("/"),
- url: (prefix === "" ? "" : "") +
- encodeFilePath(relativePath),
- type: extensionInfo ?
- extensionInfo.type :
- "application/octet-stream",
- size: stats.size,
- modified: stats.mtime.toISOString()
- });
- }
-
- return files;
-}
-
-exports.handler = function(request,response,state) {
- var rootDirectory = path.resolve(state.boot.wikiPath,"files"),
- pathPrefix = state.pathPrefix || "";
-
- scanDirectory(rootDirectory,rootDirectory,"")
- .then(function(files) {
- files.sort(function(left,right) {
- return left.path.localeCompare(right.path);
- });
-
- files.forEach(function(file) {
- file.url = pathPrefix + "/files/" + file.url;
- });
-
- state.sendResponse(
- 200,
- {"Content-Type": "application/json; charset=utf-8"},
- JSON.stringify(files),
- "utf8"
- );
- })
- .catch(function(error) {
- console.error("Unable to list files directory:",error);
-
- state.sendResponse(
- 500,
- {"Content-Type": "application/json; charset=utf-8"},
- JSON.stringify({
- error: "Unable to list files directory"
- }),
- "utf8"
- );
- });
-};
diff --git a/tiddlers/plugin-highlight-caddyfile.tid b/tiddlers/plugin-highlight-caddyfile.tid
deleted file mode 100644
index 8427c3f..0000000
--- a/tiddlers/plugin-highlight-caddyfile.tid
+++ /dev/null
@@ -1,65 +0,0 @@
-tiddlers/highlight-caddyfile.tid
-title: $:/plugins/local/highlight-languages/caddyfile.js
-type: application/javascript
-module-type: highlight
-
-/*\
-title: $:/plugins/local/highlight-languages/caddyfile.js
-type: application/javascript
-module-type: highlight
-
-Caddyfile language definition for highlight.js.
-\*/
-"use strict";
-
-hljs.registerLanguage("caddyfile",function(hljs) {
- return {
- name: "Caddyfile",
- aliases: ["caddy"],
- case_insensitive: true,
- contains: [
- {
- className: "comment",
- begin: /#/,
- end: /$/
- },
- {
- className: "section",
- begin: /^\s*(?=[^#\n{]*(?:[.:,]|\blocalhost\b))(?:https?:\/\/)?[^\s#{}]+(?:\s*,\s*[^\s#{}]+)*(?=\s*\{?\s*$)/,
- relevance: 10
- },
- {
- className: "keyword",
- begin: /^\s*[A-Za-z_][A-Za-z0-9_-]*(?=\s|$)/,
- relevance: 1
- },
- {
- className: "meta",
- match: /@[A-Za-z0-9_-]+/
- },
- {
- className: "variable",
- match: /\{\$?[A-Za-z_][A-Za-z0-9_.\-[\]*]*\}/
- },
- {
- className: "title",
- match: /\([A-Za-z_][A-Za-z0-9_-]*\)/
- },
- hljs.QUOTE_STRING_MODE,
- hljs.APOS_STRING_MODE,
- {
- className: "literal",
- match: /\b(?:true|false|on|off)\b/
- },
- {
- className: "number",
- match: /\b\d+(?:\.\d+)?(?:ns|us|ms|s|m|h|d|kb|mb|gb|tb)?\b/i,
- relevance: 0
- },
- {
- className: "punctuation",
- match: /[{}]/
- }
- ]
- };
-});
diff --git a/tiddlers/plugin-highlight-json5.tid b/tiddlers/plugin-highlight-json5.tid
deleted file mode 100644
index fae9bd4..0000000
--- a/tiddlers/plugin-highlight-json5.tid
+++ /dev/null
@@ -1,59 +0,0 @@
-title: $:/plugins/local/highlight-languages/json5.js
-type: application/javascript
-module-type: highlight
-
-/*\
-title: $:/plugins/local/highlight-languages/json5.js
-type: application/javascript
-module-type: highlight
-
-JSON5 language definition for highlight.js.
-\*/
-"use strict";
-
-hljs.registerLanguage("json5",function(hljs) {
- return {
- name: "JSON5",
- aliases: ["json5"],
- keywords: {
- literal: "true false null"
- },
- contains: [
- hljs.C_LINE_COMMENT_MODE,
- hljs.C_BLOCK_COMMENT_MODE,
- {
- className: "attr",
- match: /[A-Za-z_$][0-9A-Za-z_$]*(?=\s*:)/
- },
- {
- className: "attr",
- match: /"(?:\\.|[^"\\\r\n])*"(?=\s*:)/
- },
- {
- className: "attr",
- match: /'(?:\\.|[^'\\\r\n])*'(?=\s*:)/
- },
- hljs.QUOTE_STRING_MODE,
- hljs.APOS_STRING_MODE,
- {
- className: "number",
- variants: [
- {
- begin: /[+-]?(?:Infinity|NaN)\b/
- },
- {
- begin: /[+-]?0[xX][0-9a-fA-F]+\b/
- },
- {
- begin: /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/
- }
- ],
- relevance: 0
- },
- {
- className: "punctuation",
- match: /[{}\[\],:]/
- }
- ]
- };
-});
diff --git a/tiddlers/plugin-highlight-tiddlywiki.tid b/tiddlers/plugin-highlight-tiddlywiki.tid
deleted file mode 100644
index dd1a891..0000000
--- a/tiddlers/plugin-highlight-tiddlywiki.tid
+++ /dev/null
@@ -1,191 +0,0 @@
-title: $:/plugins/local/highlight-languages/tiddlywiki.js
-type: application/javascript
-module-type: highlight
-
-/*\
-title: $:/plugins/local/highlight-languages/tiddlywiki.js
-type: application/javascript
-module-type: highlight
-
-TiddlyWiki TID and WikiText language definition for highlight.js.
-\*/
-"use strict";
-
-hljs.registerLanguage("tiddlywiki",function(hljs) {
- var systemTiddler = {
- className: "symbol",
- match: /\$:\/[^\s\][\]<>{}"']+/
- },
- variable = {
- className: "variable",
- variants: [
- {
- begin: /<</,
- end: />>/
- },
- {
- match: /<[^<>\s]+>/
- }
- ]
- },
- transclusion = {
- className: "template-variable",
- variants: [
- {
- begin: /\{\{\{/,
- end: /\}\}\}/
- },
- {
- begin: /\{\{/,
- end: /\}\}/
- }
- ],
- contains: [
- systemTiddler,
- variable
- ]
- },
- link = {
- className: "link",
- variants: [
- {
- begin: /\[\[/,
- end: /\]\]/
- },
- {
- begin: /\[(?:img|ext)\[/,
- end: /\]\]/
- }
- ],
- contains: [
- systemTiddler
- ]
- },
- filter = {
- className: "selector",
- begin: /\[(?=[^\]\n]*[A-Za-z][A-Za-z0-9_-]*\[)/,
- end: /\]/,
- contains: [
- {
- className: "keyword",
- match: /[A-Za-z][A-Za-z0-9_.-]*(?=\[)/
- },
- {
- className: "string",
- begin: /\[/,
- end: /\]/,
- contains: [
- systemTiddler,
- variable
- ]
- },
- variable,
- systemTiddler
- ]
- };
-
- return {
- name: "TiddlyWiki",
- aliases: [
- "tid",
- "wikitext"
- ],
- contains: [
- {
- className: "comment",
- begin: /<!--/,
- end: /-->/
- },
- {
- className: "comment",
- begin: /\/%/,
- end: /%\//
- },
- {
- className: "meta",
- begin: /^\\(?:define|end|function|import|parameters|procedure|rules|whitespace|widget)\b/,
- end: /$/,
- contains: [
- variable,
- systemTiddler,
- hljs.QUOTE_STRING_MODE,
- hljs.APOS_STRING_MODE
- ]
- },
- {
- className: "attr",
- match: /^[A-Za-z0-9_.-]+(?=\s*:)/
- },
- {
- className: "section",
- begin: /^!{1,6}\s+/,
- end: /$/
- },
- {
- className: "bullet",
- match: /^[*#;:]+\s+/
- },
- {
- className: "quote",
- begin: /^>{1,3}\s+/,
- end: /$/
- },
- {
- className: "tag",
- begin: /<\/?\$?[A-Za-z][A-Za-z0-9_.:-]*/,
- end: /\/?>/,
- contains: [
- {
- className: "attr",
- match: /[A-Za-z_$][A-Za-z0-9_.:-]*(?=\s*=)/
- },
- hljs.QUOTE_STRING_MODE,
- hljs.APOS_STRING_MODE,
- transclusion,
- variable,
- filter,
- systemTiddler
- ]
- },
- {
- className: "template-tag",
- begin: /<</,
- end: />>/,
- contains: [
- hljs.QUOTE_STRING_MODE,
- hljs.APOS_STRING_MODE,
- systemTiddler
- ]
- },
- transclusion,
- link,
- filter,
- systemTiddler,
- {
- className: "code",
- begin: /`+/,
- end: /`+/
- },
- {
- className: "strong",
- begin: /''/,
- end: /''/
- },
- {
- className: "emphasis",
- begin: /\/\//,
- end: /\/\//
- },
- {
- className: "emphasis",
- begin: /__/,
- end: /__/
- },
- {
- className: "deletion",
- begin: /~~/,
- end: /~~/
- }
- ]
- };
-});
diff --git a/tiddlers/plugin-journal-calendar-widget.tid b/tiddlers/plugin-journal-calendar-widget.tid
deleted file mode 100644
index cd54724..0000000
--- a/tiddlers/plugin-journal-calendar-widget.tid
+++ /dev/null
@@ -1,333 +0,0 @@
-title: $:/plugins/local/journal-calendar/widget.js
-type: application/javascript
-module-type: widget
-
-/*\
-title: $:/plugins/local/journal-calendar/widget.js
-type: application/javascript
-module-type: widget
-
-Renders journal tiddlers as monthly calendars.
-\*/
-(function() {
-"use strict";
-
-var Widget = require("$:/core/modules/widgets/widget.js").widget,
- VIEW_STATE_TITLE = "$:/state/journal-calendar/view",
- MONTH_STATE_TITLE = "$:/state/journal-calendar/month";
-
-var JournalCalendarWidget = function(parseTreeNode,options) {
- this.initialise(parseTreeNode,options);
-};
-
-JournalCalendarWidget.prototype = new Widget();
-JournalCalendarWidget.prototype.constructor = JournalCalendarWidget;
-
-function pad(value) {
- return value < 10 ? "0" + value : "" + value;
-}
-
-function dateKey(year,month,day) {
- return year + "-" + pad(month) + "-" + pad(day);
-}
-
-function monthKey(year,month) {
- return year + "-" + pad(month);
-}
-
-function isValidMonth(value) {
- var match = /^(\d{4})-(\d{2})$/.exec(value || "");
- return !!match && Number(match[2]) >= 1 && Number(match[2]) <= 12;
-}
-
-function parseMonth(value) {
- var parts = value.split("-");
- return {
- year: Number(parts[0]),
- month: Number(parts[1])
- };
-}
-
-JournalCalendarWidget.prototype.render = function(parent,nextSibling) {
- this.parentDomNode = parent;
- this.computeAttributes();
- this.execute();
-
- var container = this.document.createElement("div");
- container.className = "tc-journal-calendar";
- parent.insertBefore(container,nextSibling);
- this.domNodes.push(container);
- this.containerNode = container;
-
- this.renderCalendar();
-};
-
-JournalCalendarWidget.prototype.execute = function() {
- this.tag = this.getAttribute("tag","日志");
- this.view = this.getAttribute("view","switchable");
- this.month = this.getAttribute("month","");
-};
-
-JournalCalendarWidget.prototype.getJournalDate = function(tiddler) {
- var titleMatch = /^(\d{4})年(\d{2})月(\d{2})日$/.exec(tiddler.fields.title),
- date;
-
- if(titleMatch) {
- date = new Date(Number(titleMatch[1]),Number(titleMatch[2]) - 1,Number(titleMatch[3]));
- if(date.getFullYear() === Number(titleMatch[1]) && date.getMonth() === Number(titleMatch[2]) - 1 && date.getDate() === Number(titleMatch[3])) {
- return date;
- }
- }
- return null;
-};
-
-JournalCalendarWidget.prototype.getJournalData = function() {
- var titles = this.wiki.getTiddlersWithTag(this.tag),
- byDate = Object.create(null),
- months = Object.create(null),
- self = this;
-
- titles.forEach(function(title) {
- var tiddler = self.wiki.getTiddler(title);
- if(!tiddler || tiddler.fields["draft.of"]) {
- return;
- }
-
- var date = self.getJournalDate(tiddler);
- if(!date) {
- return;
- }
-
- var day = dateKey(date.getFullYear(),date.getMonth() + 1,date.getDate()),
- month = day.substring(0,7);
- byDate[day] = {
- title: title,
- tags: (tiddler.fields.tags || []).filter(function(tag) {
- return tag !== self.tag;
- })
- };
- months[month] = true;
- });
-
- return {
- byDate: byDate,
- months: Object.keys(months).sort().reverse()
- };
-};
-
-JournalCalendarWidget.prototype.getCurrentMonth = function() {
- if(isValidMonth(this.month)) {
- return this.month;
- }
-
- var stateMonth = this.wiki.getTiddlerText(MONTH_STATE_TITLE,"");
- if(isValidMonth(stateMonth)) {
- return stateMonth;
- }
-
- var now = new Date();
- return monthKey(now.getFullYear(),now.getMonth() + 1);
-};
-
-JournalCalendarWidget.prototype.getCurrentView = function() {
- if(this.view === "month" || this.view === "all") {
- return this.view;
- }
- return this.wiki.getTiddlerText(VIEW_STATE_TITLE,"month") === "all" ? "all" : "month";
-};
-
-JournalCalendarWidget.prototype.setState = function(title,value) {
- this.wiki.addTiddler({
- title: title,
- text: value
- });
-};
-
-JournalCalendarWidget.prototype.createButton = function(label,className,handler) {
- var button = this.document.createElement("button");
- button.setAttribute("type","button");
- button.className = className;
- button.textContent = label;
- button.addEventListener("click",handler);
- return button;
-};
-
-JournalCalendarWidget.prototype.renderViewSwitcher = function(currentView) {
- if(this.view !== "switchable") {
- return;
- }
-
- var self = this,
- controls = this.document.createElement("div");
- controls.className = "tc-journal-calendar-view-switcher";
-
- controls.appendChild(this.createButton("单月视图","tc-btn-invisible tc-journal-calendar-switch" + (currentView === "month" ? " tc-selected" : ""),function() {
- self.setState(VIEW_STATE_TITLE,"month");
- }));
- controls.appendChild(this.createButton("全部月份","tc-btn-invisible tc-journal-calendar-switch" + (currentView === "all" ? " tc-selected" : ""),function() {
- self.setState(VIEW_STATE_TITLE,"all");
- }));
- this.containerNode.appendChild(controls);
-};
-
-JournalCalendarWidget.prototype.renderMonthControls = function(selectedMonth) {
- if(isValidMonth(this.month)) {
- return;
- }
-
- var self = this,
- selected = parseMonth(selectedMonth),
- controls = this.document.createElement("div");
- controls.className = "tc-journal-calendar-month-controls";
-
- function setOffset(offset) {
- var date = new Date(selected.year,selected.month - 1 + offset,1);
- self.setState(MONTH_STATE_TITLE,monthKey(date.getFullYear(),date.getMonth() + 1));
- }
-
- controls.appendChild(this.createButton("上个月","tc-btn-invisible tc-journal-calendar-nav",function() {
- setOffset(-1);
- }));
- controls.appendChild(this.createButton("本月","tc-btn-invisible tc-journal-calendar-nav",function() {
- var now = new Date();
- self.setState(MONTH_STATE_TITLE,monthKey(now.getFullYear(),now.getMonth() + 1));
- }));
- controls.appendChild(this.createButton("下个月","tc-btn-invisible tc-journal-calendar-nav",function() {
- setOffset(1);
- }));
- this.containerNode.appendChild(controls);
-};
-
-JournalCalendarWidget.prototype.navigateTo = function(title,node,event) {
- var bounds = node.getBoundingClientRect();
- this.dispatchEvent({
- type: "tm-navigate",
- navigateTo: title,
- navigateFromTitle: this.getVariable("storyTiddler"),
- navigateFromNode: this,
- navigateFromClientRect: {
- top: bounds.top,
- left: bounds.left,
- width: bounds.width,
- right: bounds.right,
- bottom: bounds.bottom,
- height: bounds.height
- },
- navigateSuppressNavigation: event.metaKey || event.ctrlKey || event.button === 1
- });
-};
-
-JournalCalendarWidget.prototype.renderMonth = function(value,byDate) {
- var self = this,
- selected = parseMonth(value),
- section = this.document.createElement("section"),
- heading = this.document.createElement("h2"),
- viewport = this.document.createElement("div"),
- grid = this.document.createElement("div"),
- weekdays = ["一","二","三","四","五","六","日"],
- firstWeekday = (new Date(selected.year,selected.month - 1,1).getDay() + 6) % 7,
- daysInMonth = new Date(selected.year,selected.month,0).getDate(),
- today = new Date(),
- index;
-
- section.className = "tc-journal-calendar-month";
- heading.className = "tc-journal-calendar-month-title";
- heading.textContent = selected.year + "年" + selected.month + "月";
- section.appendChild(heading);
- viewport.className = "tc-journal-calendar-viewport";
- grid.className = "tc-journal-calendar-grid";
-
- weekdays.forEach(function(weekday) {
- var weekdayNode = self.document.createElement("div");
- weekdayNode.className = "tc-journal-calendar-weekday";
- weekdayNode.textContent = weekday;
- grid.appendChild(weekdayNode);
- });
-
- for(index = 0; index < firstWeekday; index++) {
- var blank = this.document.createElement("div");
- blank.className = "tc-journal-calendar-day tc-journal-calendar-day-empty";
- grid.appendChild(blank);
- }
-
- for(var day = 1; day <= daysInMonth; day++) {
- var key = dateKey(selected.year,selected.month,day),
- journal = byDate[key],
- dayNode = this.document.createElement("div"),
- numberNode;
-
- dayNode.className = "tc-journal-calendar-day" + (journal ? " tc-journal-calendar-day-has-journal" : "");
- if(selected.year === today.getFullYear() && selected.month === today.getMonth() + 1 && day === today.getDate()) {
- dayNode.className += " tc-journal-calendar-day-today";
- }
-
- if(journal) {
- numberNode = this.createButton(day,"tc-btn-invisible tc-journal-calendar-day-number tc-journal-calendar-day-link",function(title) {
- return function(event) {
- self.navigateTo(title,event.currentTarget,event);
- };
- }(journal.title));
- numberNode.title = "打开日志:" + journal.title;
- numberNode.setAttribute("aria-label","打开日志:" + journal.title);
- } else {
- numberNode = this.document.createElement("div");
- numberNode.className = "tc-journal-calendar-day-number";
- numberNode.textContent = day;
- }
- dayNode.appendChild(numberNode);
-
- if(journal) {
- journal.tags.forEach(function(tag) {
- var tagButton = self.createButton(tag,"tc-btn-invisible tc-tag-label tc-journal-calendar-tag",function(event) {
- self.navigateTo(tag,event.currentTarget,event);
- });
- tagButton.title = "打开标签:" + tag;
- tagButton.setAttribute("aria-label","打开标签:" + tag);
- dayNode.appendChild(tagButton);
- });
- }
- grid.appendChild(dayNode);
- }
-
- viewport.appendChild(grid);
- section.appendChild(viewport);
- this.containerNode.appendChild(section);
-};
-
-JournalCalendarWidget.prototype.renderCalendar = function() {
- var data = this.getJournalData(),
- currentView = this.getCurrentView();
-
- this.renderViewSwitcher(currentView);
-
- if(currentView === "all") {
- if(!data.months.length) {
- var empty = this.document.createElement("div");
- empty.className = "tc-journal-calendar-empty";
- empty.textContent = "目前没有日志。";
- this.containerNode.appendChild(empty);
- return;
- }
- data.months.forEach(function(month) {
- this.renderMonth(month,data.byDate);
- },this);
- return;
- }
-
- var selectedMonth = this.getCurrentMonth();
- this.renderMonthControls(selectedMonth);
- this.renderMonth(selectedMonth,data.byDate);
-};
-
-JournalCalendarWidget.prototype.refresh = function(changedTiddlers) {
- var changedAttributes = this.computeAttributes();
- if(Object.keys(changedAttributes).length || Object.keys(changedTiddlers).length) {
- this.refreshSelf();
- return true;
- }
- return false;
-};
-
-exports["journal-calendar"] = JournalCalendarWidget;
-
-})();
diff --git a/tiddlers/plugin-org-gtd-agenda-widget.tid b/tiddlers/plugin-org-gtd-agenda-widget.tid
deleted file mode 100644
index 4749564..0000000
--- a/tiddlers/plugin-org-gtd-agenda-widget.tid
+++ /dev/null
@@ -1,229 +0,0 @@
-title: $:/plugins/local/org-gtd/agenda-widget.js
-type: application/javascript
-module-type: widget
-
-/*\
-title: $:/plugins/local/org-gtd/agenda-widget.js
-type: application/javascript
-module-type: widget
-\*/
-(function() {
-"use strict";
-
-var Widget = require("$:/core/modules/widgets/widget.js").widget,
- org = require("$:/plugins/local/org-gtd/library.js"),
- JUMP_STATE_TITLE = "$:/state/org-gtd/jump";
-
-var OrgGtdAgendaWidget = function(parseTreeNode,options) {
- this.initialise(parseTreeNode,options);
- this.parseCache = Object.create(null);
-};
-
-OrgGtdAgendaWidget.prototype = new Widget();
-OrgGtdAgendaWidget.prototype.constructor = OrgGtdAgendaWidget;
-
-function startOfDay(date) {
- return new Date(date.getFullYear(),date.getMonth(),date.getDate()).getTime();
-}
-
-function earliestDate(task) {
- var values = [task.scheduled,task.deadline].filter(function(value) {
- return !isNaN(org.dateToTime(value));
- });
- values.sort();
- return values[0] || "";
-}
-
-OrgGtdAgendaWidget.prototype.render = function(parent,nextSibling) {
- this.parentDomNode = parent;
- this.computeAttributes();
- this.execute();
-
- var container = this.document.createElement("div");
- container.className = "tc-org-agenda";
- parent.insertBefore(container,nextSibling);
- this.domNodes.push(container);
- this.containerNode = container;
- this.renderAgenda();
-};
-
-OrgGtdAgendaWidget.prototype.execute = function() {
- this.days = Math.max(1,Number(this.getAttribute("days","7")) || 7);
-};
-
-OrgGtdAgendaWidget.prototype.createButton = function(label,className,handler) {
- var button = this.document.createElement("button");
- button.type = "button";
- button.className = "tc-btn-invisible " + className;
- button.textContent = label;
- button.addEventListener("click",handler);
- return button;
-};
-
-OrgGtdAgendaWidget.prototype.getTasks = function() {
- var self = this,
- tasks = [],
- activeTitles = Object.create(null);
- this.wiki.allTitles().forEach(function(title) {
- var tiddler = self.wiki.getTiddler(title),
- text,
- cached,
- parsed;
- if(!tiddler || tiddler.fields.type !== "text/x-org" || tiddler.fields["draft.of"]) {
- return;
- }
- activeTitles[title] = true;
- text = tiddler.fields.text || "";
- cached = self.parseCache[title];
- parsed = cached && cached.text === text ? cached.parsed : org.parse(text);
- self.parseCache[title] = {text: text,parsed: parsed};
- parsed.headings.forEach(function(heading) {
- if(heading.state && heading.state !== "DONE" && heading.title) {
- tasks.push({
- tiddler: title,
- title: heading.title,
- state: heading.state,
- level: heading.level,
- line: heading.sourceLine,
- scheduled: heading.scheduled,
- deadline: heading.deadline,
- date: earliestDate(heading)
- });
- }
- });
- });
- Object.keys(this.parseCache).forEach(function(title) {
- if(!activeTitles[title]) {
- delete self.parseCache[title];
- }
- });
- return tasks;
-};
-
-OrgGtdAgendaWidget.prototype.openTask = function(task,event) {
- this.wiki.setText(JUMP_STATE_TITLE,"text",null,JSON.stringify({title: task.tiddler,line: task.line}));
- this.dispatchEvent({
- type: "tm-edit-tiddler",
- param: task.tiddler,
- tiddlerTitle: task.tiddler,
- navigateFromTitle: this.getVariable("storyTiddler"),
- event: event
- });
-};
-
-OrgGtdAgendaWidget.prototype.renderTask = function(parent,task) {
- var self = this,
- button = this.createButton(task.title,"tc-org-agenda-task",function(event) {
- self.openTask(task,event);
- }),
- state = this.document.createElement("span"),
- source = this.document.createElement("span"),
- meta = this.document.createElement("span"),
- row = this.document.createElement("div"),
- parts = [];
- row.className = "tc-org-agenda-row";
- state.className = "tc-org-state tc-org-state-" + task.state.toLowerCase();
- state.textContent = task.state;
- source.className = "tc-org-agenda-source";
- source.textContent = task.tiddler;
- if(task.scheduled) {
- parts.push("计划 " + task.scheduled);
- }
- if(task.deadline) {
- parts.push("截止 " + task.deadline);
- }
- meta.className = "tc-org-agenda-meta";
- meta.textContent = parts.join(" · ");
- row.appendChild(state);
- row.appendChild(button);
- row.appendChild(source);
- if(parts.length) {
- row.appendChild(meta);
- }
- parent.appendChild(row);
-};
-
-OrgGtdAgendaWidget.prototype.renderSection = function(title,tasks,className) {
- var self = this,
- section = this.document.createElement("section"),
- heading = this.document.createElement("h2"),
- count = this.document.createElement("span");
- section.className = "tc-org-agenda-section " + className;
- heading.className = "tc-org-agenda-section-title";
- heading.textContent = title;
- count.className = "tc-org-agenda-count";
- count.textContent = String(tasks.length);
- heading.appendChild(count);
- section.appendChild(heading);
- if(tasks.length) {
- tasks.forEach(function(task) {
- self.renderTask(section,task);
- });
- } else {
- var empty = this.document.createElement("p");
- empty.className = "tc-org-agenda-empty";
- empty.textContent = "没有事项";
- section.appendChild(empty);
- }
- this.containerNode.appendChild(section);
-};
-
-OrgGtdAgendaWidget.prototype.renderAgenda = function() {
- var self = this,
- today = startOfDay(new Date()),
- horizonDate = new Date(today),
- horizon,
- groups = {overdue: [],today: [],upcoming: [],next: []},
- toolbar = this.document.createElement("div"),
- newButton;
- horizonDate.setDate(horizonDate.getDate() + this.days);
- horizon = horizonDate.getTime();
- newButton = this.createButton("+ 新建 Org 文档","tc-org-agenda-new",function(event) {
- var title = self.wiki.generateNewTitle("GTD Inbox");
- self.dispatchEvent({
- type: "tm-new-tiddler",
- paramObject: {title: title,type: "text/x-org",text: "* TODO "},
- navigateFromTitle: self.getVariable("storyTiddler"),
- event: event
- });
- });
- toolbar.className = "tc-org-agenda-toolbar";
- toolbar.appendChild(newButton);
- this.containerNode.appendChild(toolbar);
- this.getTasks().forEach(function(task) {
- var time = org.dateToTime(task.date);
- if(!isNaN(time)) {
- if(time < today) {
- groups.overdue.push(task);
- } else if(time === today) {
- groups.today.push(task);
- } else if(time <= horizon) {
- groups.upcoming.push(task);
- }
- } else if(task.state === "NEXT") {
- groups.next.push(task);
- }
- });
- Object.keys(groups).forEach(function(key) {
- groups[key].sort(function(left,right) {
- return (left.date || "9999").localeCompare(right.date || "9999") || left.title.localeCompare(right.title,"zh-Hans");
- });
- });
- this.renderSection("逾期",groups.overdue,"tc-org-agenda-overdue");
- this.renderSection("今天",groups.today,"tc-org-agenda-today");
- this.renderSection("未来 " + this.days + " 天",groups.upcoming,"tc-org-agenda-upcoming");
- this.renderSection("无日期的下一步",groups.next,"tc-org-agenda-next");
-};
-
-OrgGtdAgendaWidget.prototype.refresh = function(changedTiddlers) {
- var changedAttributes = this.computeAttributes();
- if(Object.keys(changedAttributes).length || Object.keys(changedTiddlers).length) {
- this.refreshSelf();
- return true;
- }
- return false;
-};
-
-exports["org-gtd-agenda"] = OrgGtdAgendaWidget;
-
-})();
diff --git a/tiddlers/plugin-org-gtd-codemirror.tid b/tiddlers/plugin-org-gtd-codemirror.tid
deleted file mode 100644
index 09b3e6c..0000000
--- a/tiddlers/plugin-org-gtd-codemirror.tid
+++ /dev/null
@@ -1,341 +0,0 @@
-title: $:/plugins/local/org-gtd/codemirror.js
-type: application/javascript
-module-type: codemirror
-
-/*\
-title: $:/plugins/local/org-gtd/codemirror.js
-type: application/javascript
-module-type: codemirror
-\*/
-(function() {
-"use strict";
-
-var CodeMirror = require("$:/plugins/tiddlywiki/codemirror/lib/codemirror.js"),
- org = require("$:/plugins/local/org-gtd/library.js"),
- JUMP_STATE_TITLE = "$:/state/org-gtd/jump",
- KEY_MAP_TITLE = "$:/config/org-gtd/extraKeys";
-
-function isOrgEditor(cm) {
- return cm.getMode().name === "org-gtd";
-}
-
-function readOrgGtdKeyMap(cm) {
- var widget = cm.getOption("editWidget"),
- text,
- keyMap;
- if(!widget || !widget.wiki) {
- return null;
- }
- text = widget.wiki.getTiddlerText(KEY_MAP_TITLE,"{}");
- try {
- keyMap = JSON.parse(text);
- } catch(error) {
- console.error("Org GTD shortcut configuration is invalid JSON",error);
- return null;
- }
- if(!keyMap || typeof keyMap !== "object" || Array.isArray(keyMap) || Object.keys(keyMap).length === 0) {
- return null;
- }
- try {
- return CodeMirror.normalizeKeyMap(keyMap);
- } catch(error) {
- console.error("Org GTD shortcut configuration contains an invalid key name",error);
- return null;
- }
-}
-
-function syncOrgGtdKeyMap(cm) {
- var keyMap;
- if(cm.state.orgGtdKeyMap) {
- cm.removeKeyMap(cm.state.orgGtdKeyMap);
- cm.state.orgGtdKeyMap = null;
- }
- if(!isOrgEditor(cm)) {
- return;
- }
- keyMap = readOrgGtdKeyMap(cm);
- if(keyMap) {
- cm.addKeyMap(keyMap);
- cm.state.orgGtdKeyMap = keyMap;
- }
-}
-
-function clearFolds(cm) {
- var marks = cm.state.orgGtdFoldMarks || [];
- marks.forEach(function(mark) {
- if(mark.find()) {
- mark.clear();
- }
- });
- cm.state.orgGtdFoldMarks = [];
-}
-
-function replaceDocument(cm,lines,cursorLine,cursorCh) {
- var lastLine = cm.lastLine(),
- lastCh = cm.getLine(lastLine).length;
- clearFolds(cm);
- cm.operation(function() {
- cm.replaceRange(lines.join("\n"),CodeMirror.Pos(0,0),CodeMirror.Pos(lastLine,lastCh),"+org-gtd");
- cm.setCursor(CodeMirror.Pos(cursorLine,cursorCh || 0));
- });
-}
-
-function currentHeading(cm) {
- var parsed = org.parse(cm.getValue()),
- heading = org.headingAtLine(parsed,cm.getCursor().line);
- return {parsed: parsed,heading: heading};
-}
-
-CodeMirror.defineMode("org-gtd",function() {
- return {
- startState: function() {
- return {heading: false,planning: false};
- },
- token: function(stream,state) {
- if(stream.sol()) {
- state.heading = /^\*+\s+/.test(stream.string);
- state.planning = /^\s*(?:SCHEDULED|DEADLINE):/.test(stream.string);
- }
- if(state.heading) {
- if(stream.match(/^\*+\s+/)) {
- return "header";
- }
- if(stream.match(/^(?:TODO|NEXT|WAIT|DONE)\b/)) {
- return "keyword";
- }
- if(stream.match(/^\s+:[A-Za-z0-9_@#%+.-]+(?::[A-Za-z0-9_@#%+.-]+)*:\s*$/)) {
- return "tag";
- }
- }
- if(state.planning) {
- if(stream.match(/^\s*(?:SCHEDULED|DEADLINE):/)) {
- return "def";
- }
- if(stream.match(/^\s*<[0-9]{4}-[0-9]{2}-[0-9]{2}(?:\s+[^>]*)?>/)) {
- return "atom";
- }
- }
- if(stream.sol() && stream.match(/^\s*#.*$/)) {
- return "comment";
- }
- stream.next();
- return null;
- },
- lineComment: "# "
- };
-});
-
-CodeMirror.defineMIME("text/x-org","org-gtd");
-
-CodeMirror.commands.orgGtdCycleState = function(cm) {
- var cursor,
- line,
- result;
- if(!isOrgEditor(cm)) {
- return CodeMirror.Pass;
- }
- cursor = cm.getCursor();
- line = cm.getLine(cursor.line);
- result = org.cycleState(line);
- if(!result) {
- return CodeMirror.Pass;
- }
- cm.replaceRange(result.line,CodeMirror.Pos(cursor.line,0),CodeMirror.Pos(cursor.line,line.length),"+org-gtd");
- cm.setCursor(CodeMirror.Pos(cursor.line,Math.min(cursor.ch + (result.line.length - line.length),result.line.length)));
-};
-
-function changeLevel(cm,direction) {
- var context,
- lines;
- if(!isOrgEditor(cm)) {
- return CodeMirror.Pass;
- }
- context = currentHeading(cm);
- if(!context.heading || (direction < 0 && context.heading.level === 1)) {
- return CodeMirror.Pass;
- }
- lines = context.parsed.lines.slice(0);
- for(var index = context.heading.line; index <= context.heading.subtreeEndLine; index++) {
- if(/^\*+\s+/.test(lines[index])) {
- lines[index] = direction > 0 ? "*" + lines[index] : lines[index].substring(1);
- }
- }
- replaceDocument(cm,lines,context.heading.line,Math.max(0,cm.getCursor().ch + direction));
-}
-
-CodeMirror.commands.orgGtdPromote = function(cm) {
- return changeLevel(cm,-1);
-};
-
-CodeMirror.commands.orgGtdDemote = function(cm) {
- return changeLevel(cm,1);
-};
-
-function moveSubtree(cm,direction) {
- var context,
- heading,
- headings,
- index,
- other,
- lines,
- before,
- current,
- after,
- newLine;
- if(!isOrgEditor(cm)) {
- return CodeMirror.Pass;
- }
- context = currentHeading(cm);
- heading = context.heading;
- if(!heading) {
- return CodeMirror.Pass;
- }
- headings = context.parsed.headings;
- index = headings.indexOf(heading);
- if(direction < 0) {
- for(index = index - 1; index >= 0; index--) {
- if(headings[index].level < heading.level) {
- return CodeMirror.Pass;
- }
- if(headings[index].level === heading.level) {
- other = headings[index];
- break;
- }
- }
- if(!other) {
- return CodeMirror.Pass;
- }
- lines = context.parsed.lines;
- before = lines.slice(0,other.line);
- current = lines.slice(heading.line,heading.subtreeEndLine + 1);
- after = lines.slice(other.line,heading.line).concat(lines.slice(heading.subtreeEndLine + 1));
- newLine = other.line;
- replaceDocument(cm,before.concat(current,after),newLine,cm.getCursor().ch);
- } else {
- for(index = index + 1; index < headings.length; index++) {
- if(headings[index].line <= heading.subtreeEndLine) {
- continue;
- }
- if(headings[index].level < heading.level) {
- return CodeMirror.Pass;
- }
- if(headings[index].level === heading.level) {
- other = headings[index];
- break;
- }
- }
- if(!other) {
- return CodeMirror.Pass;
- }
- lines = context.parsed.lines;
- before = lines.slice(0,heading.line);
- current = lines.slice(heading.line,heading.subtreeEndLine + 1);
- after = lines.slice(other.line,other.subtreeEndLine + 1);
- newLine = heading.line + after.length;
- replaceDocument(cm,before.concat(after,current,lines.slice(other.subtreeEndLine + 1)),newLine,cm.getCursor().ch);
- }
-}
-
-CodeMirror.commands.orgGtdMoveUp = function(cm) {
- return moveSubtree(cm,-1);
-};
-
-CodeMirror.commands.orgGtdMoveDown = function(cm) {
- return moveSubtree(cm,1);
-};
-
-CodeMirror.commands.orgGtdToggleFold = function(cm) {
- var context,
- heading,
- marks,
- existing,
- marker,
- mark;
- if(!isOrgEditor(cm)) {
- return CodeMirror.Pass;
- }
- context = currentHeading(cm);
- heading = context.heading;
- if(!heading || cm.getCursor().line !== heading.line || heading.subtreeEndLine === heading.line) {
- return CodeMirror.Pass;
- }
- marks = cm.state.orgGtdFoldMarks = cm.state.orgGtdFoldMarks || [];
- existing = marks.filter(function(item) {
- var range = item.find();
- return range && range.from.line === heading.line;
- })[0];
- if(existing) {
- existing.clear();
- cm.state.orgGtdFoldMarks = marks.filter(function(item) {return item !== existing;});
- return;
- }
- marker = cm.getWrapperElement().ownerDocument.createElement("span");
- marker.className = "cm-org-gtd-fold-marker";
- marker.textContent = " ...";
- mark = cm.markText(
- CodeMirror.Pos(heading.line,cm.getLine(heading.line).length),
- CodeMirror.Pos(heading.subtreeEndLine,cm.getLine(heading.subtreeEndLine).length),
- {collapsed: true,replacedWith: marker,atomic: true}
- );
- marks.push(mark);
- marker.addEventListener("click",function() {
- mark.clear();
- cm.state.orgGtdFoldMarks = marks.filter(function(item) {return item !== mark;});
- });
-};
-
-CodeMirror.commands.orgGtdInsertSibling = function(cm) {
- var context,
- heading,
- lines,
- newLine;
- if(!isOrgEditor(cm)) {
- return CodeMirror.Pass;
- }
- context = currentHeading(cm);
- heading = context.heading;
- if(!heading) {
- return CodeMirror.Pass;
- }
- lines = context.parsed.lines.slice(0);
- newLine = heading.subtreeEndLine + 1;
- lines.splice(newLine,0,new Array(heading.level + 1).join("*") + " TODO ");
- replaceDocument(cm,lines,newLine,heading.level + 6);
-};
-
-CodeMirror.defineInitHook(function(cm) {
- var widget = cm.getOption("editWidget"),
- request,
- currentTitle,
- tiddler,
- originalTitle;
- syncOrgGtdKeyMap(cm);
- cm.on("optionChange",function(instance,option) {
- if(option === "mode") {
- syncOrgGtdKeyMap(instance);
- }
- });
- if(!widget || !widget.wiki) {
- return;
- }
- request = $tw.utils.parseJSONSafe(widget.wiki.getTiddlerText(JUMP_STATE_TITLE,""),null);
- if(!request) {
- return;
- }
- currentTitle = widget.editTitle || widget.getVariable("currentTiddler","");
- tiddler = widget.wiki.getTiddler(currentTitle);
- originalTitle = tiddler && tiddler.fields["draft.of"] ? tiddler.fields["draft.of"] : currentTitle;
- if(originalTitle !== request.title) {
- return;
- }
- setTimeout(function() {
- var line = Math.max(0,Math.min(Number(request.line || 1) - 1,cm.lastLine())),
- position = CodeMirror.Pos(line,0);
- cm.setCursor(position);
- cm.scrollIntoView(position,100);
- cm.focus();
- widget.wiki.deleteTiddler(JUMP_STATE_TITLE);
- },0);
-});
-
-})();
diff --git a/tiddlers/plugin-org-gtd-content-type.tid b/tiddlers/plugin-org-gtd-content-type.tid
deleted file mode 100644
index 64d2c76..0000000
--- a/tiddlers/plugin-org-gtd-content-type.tid
+++ /dev/null
@@ -1,12 +0,0 @@
-title: $:/plugins/local/org-gtd/content-type.js
-type: application/javascript
-module-type: config
-
-/*\
-title: $:/plugins/local/org-gtd/content-type.js
-type: application/javascript
-module-type: config
-\*/
-"use strict";
-
-$tw.utils.registerFileType("text/x-org","utf8",".org");
diff --git a/tiddlers/plugin-org-gtd-editor-mapping.tid b/tiddlers/plugin-org-gtd-editor-mapping.tid
deleted file mode 100644
index 251f966..0000000
--- a/tiddlers/plugin-org-gtd-editor-mapping.tid
+++ /dev/null
@@ -1,2 +0,0 @@
-title: $:/config/EditorTypeMappings/text/x-org
-text: codemirror
diff --git a/tiddlers/plugin-org-gtd-library.tid b/tiddlers/plugin-org-gtd-library.tid
deleted file mode 100644
index af41028..0000000
--- a/tiddlers/plugin-org-gtd-library.tid
+++ /dev/null
@@ -1,141 +0,0 @@
-title: $:/plugins/local/org-gtd/library.js
-type: application/javascript
-module-type: library
-
-/*\
-title: $:/plugins/local/org-gtd/library.js
-type: application/javascript
-module-type: library
-\*/
-(function() {
-"use strict";
-
-var TODO_STATES = ["TODO","NEXT","WAIT","DONE"],
- TODO_LOOKUP = Object.create(null),
- HEADING_PATTERN = /^(\*+)\s+(?:(TODO|NEXT|WAIT|DONE)\s+)?(.*)$/,
- TAG_PATTERN = /\s+:([A-Za-z0-9_@#%+.-]+(?::[A-Za-z0-9_@#%+.-]+)*):\s*$/,
- DATE_PATTERN = /\b(SCHEDULED|DEADLINE):\s*<([0-9]{4}-[0-9]{2}-[0-9]{2})(?:\s+[^>]*)?>/g;
-
-TODO_STATES.forEach(function(state) {
- TODO_LOOKUP[state] = true;
-});
-
-function parseHeading(line,lineIndex) {
- var match = HEADING_PATTERN.exec(line),
- tagMatch,
- title,
- tags = [];
- if(!match) {
- return null;
- }
- title = match[3];
- tagMatch = TAG_PATTERN.exec(title);
- if(tagMatch) {
- tags = tagMatch[1].split(":");
- title = title.substring(0,tagMatch.index).trim();
- }
- return {
- level: match[1].length,
- state: match[2] || "",
- title: title,
- tags: tags,
- line: lineIndex,
- sourceLine: lineIndex + 1,
- endLine: lineIndex,
- scheduled: "",
- deadline: ""
- };
-}
-
-function parse(text) {
- var lines = (text || "").split("\n"),
- headings = [],
- current = null;
- lines.forEach(function(line,index) {
- var heading = parseHeading(line,index),
- match;
- if(heading) {
- if(current) {
- current.endLine = index - 1;
- }
- headings.push(heading);
- current = heading;
- return;
- }
- if(current) {
- DATE_PATTERN.lastIndex = 0;
- while((match = DATE_PATTERN.exec(line)) !== null) {
- if(match[1] === "SCHEDULED") {
- current.scheduled = match[2];
- } else {
- current.deadline = match[2];
- }
- }
- }
- });
- if(current) {
- current.endLine = lines.length - 1;
- }
- for(var index = 0; index < headings.length; index++) {
- var heading = headings[index],
- nextIndex = index + 1;
- while(nextIndex < headings.length && headings[nextIndex].level > heading.level) {
- nextIndex++;
- }
- heading.subtreeEndLine = nextIndex < headings.length ? headings[nextIndex].line - 1 : lines.length - 1;
- }
- return {lines: lines,headings: headings};
-}
-
-function headingAtLine(parsed,line) {
- var result = null;
- parsed.headings.forEach(function(heading) {
- if(heading.line <= line && heading.subtreeEndLine >= line) {
- if(!result || heading.level >= result.level) {
- result = heading;
- }
- }
- });
- return result;
-}
-
-function cycleState(line) {
- var heading = parseHeading(line,0),
- stars,
- nextState,
- rest;
- if(!heading) {
- return null;
- }
- stars = new Array(heading.level + 1).join("*");
- if(heading.state) {
- nextState = TODO_STATES[(TODO_STATES.indexOf(heading.state) + 1) % TODO_STATES.length];
- rest = line.replace(/^(\*+)\s+(?:TODO|NEXT|WAIT|DONE)\s+/,"$1 " + nextState + " ");
- } else {
- rest = line.replace(/^(\*+)\s+/,"$1 TODO ");
- }
- return {line: rest,state: nextState || "TODO",level: stars.length};
-}
-
-function dateToTime(value) {
- var match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value || ""),
- date;
- if(!match) {
- return NaN;
- }
- date = new Date(Number(match[1]),Number(match[2]) - 1,Number(match[3]));
- if(date.getFullYear() !== Number(match[1]) || date.getMonth() !== Number(match[2]) - 1 || date.getDate() !== Number(match[3])) {
- return NaN;
- }
- return date.getTime();
-}
-
-exports.TODO_STATES = TODO_STATES;
-exports.TODO_LOOKUP = TODO_LOOKUP;
-exports.parseHeading = parseHeading;
-exports.parse = parse;
-exports.headingAtLine = headingAtLine;
-exports.cycleState = cycleState;
-exports.dateToTime = dateToTime;
-
-})();
diff --git a/tiddlers/plugin-org-gtd-parser.tid b/tiddlers/plugin-org-gtd-parser.tid
deleted file mode 100644
index 4aa4bd4..0000000
--- a/tiddlers/plugin-org-gtd-parser.tid
+++ /dev/null
@@ -1,76 +0,0 @@
-title: $:/plugins/local/org-gtd/parser.js
-type: application/javascript
-module-type: parser
-
-/*\
-title: $:/plugins/local/org-gtd/parser.js
-type: application/javascript
-module-type: parser
-\*/
-(function() {
-"use strict";
-
-var org = require("$:/plugins/local/org-gtd/library.js");
-
-function attr(value) {
- return {type: "string",value: String(value)};
-}
-
-function text(value) {
- return {type: "text",text: String(value)};
-}
-
-function element(tag,className,children,attributes) {
- var attrs = attributes || {};
- if(className) {
- attrs["class"] = attr(className);
- }
- return {
- type: "element",
- tag: tag,
- attributes: attrs,
- children: children || [],
- isBlock: tag !== "span"
- };
-}
-
-function headingNode(heading) {
- var children = [],
- level = Math.min(heading.level,6),
- classes = "tc-org-heading tc-org-level-" + heading.level;
- if(heading.state) {
- classes += " tc-org-heading-" + heading.state.toLowerCase();
- children.push(element("span","tc-org-state tc-org-state-" + heading.state.toLowerCase(),[text(heading.state)]));
- children.push(text(" "));
- }
- children.push(text(heading.title));
- if(heading.tags.length) {
- children.push(text(" "));
- children.push(element("span","tc-org-tags",[text(":" + heading.tags.join(":") + ":")]));
- }
- return element("h" + level,classes,children,{"data-org-line": attr(heading.sourceLine)});
-}
-
-function OrgParser(type,source,options) {
- var parsed = org.parse(source || ""),
- headingsByLine = Object.create(null),
- tree = [];
- parsed.headings.forEach(function(heading) {
- headingsByLine[heading.line] = heading;
- });
- parsed.lines.forEach(function(line,index) {
- var heading = headingsByLine[index];
- if(heading) {
- tree.push(headingNode(heading));
- } else if(/^\s*(?:SCHEDULED|DEADLINE):/.test(line)) {
- tree.push(element("div","tc-org-planning",[text(line.trim())]));
- } else if(line.trim()) {
- tree.push(element("div","tc-org-body-line",[text(line)]));
- }
- });
- this.tree = options.parseAsInline ? [text(source || "")] : [element("div","tc-org-document",tree)];
-}
-
-exports["text/x-org"] = OrgParser;
-
-})();
diff --git a/tiddlers/plugin-org-gtd-sidebar.tid b/tiddlers/plugin-org-gtd-sidebar.tid
deleted file mode 100644
index 467f946..0000000
--- a/tiddlers/plugin-org-gtd-sidebar.tid
+++ /dev/null
@@ -1,13 +0,0 @@
-caption: GTD
-list-after: 🍀
-tags: $:/tags/SideBar
-title: $:/plugins/local/org-gtd/sidebar
-type: text/vnd.tiddlywiki
-
-<div class="tc-sidebar-tab-open">
-<$link to="GTD Agenda">打开 Agenda</$link>
-
-<$list filter="[type[text/x-org]!has[draft.of]sort[title]]" emptyMessage="还没有 Org 文档。">
-<div class="tc-sidebar-tab-open-item"><$link/></div>
-</$list>
-</div>
diff --git a/tiddlers/plugin-org-gtd-styles.tid b/tiddlers/plugin-org-gtd-styles.tid
deleted file mode 100644
index 345a4ee..0000000
--- a/tiddlers/plugin-org-gtd-styles.tid
+++ /dev/null
@@ -1,159 +0,0 @@
-title: $:/plugins/local/org-gtd/styles
-tags: $:/tags/Stylesheet
-
-.tc-org-document {
- --org-todo: #c74b50;
- --org-next: <<colour primary>>;
- --org-wait: #b27b2f;
- --org-done: <<colour muted-foreground>>;
-}
-
-.tc-org-heading {
- margin: 1.15rem 0 0.45rem;
- line-height: 1.35;
-}
-
-.tc-org-heading-done {
- color: <<colour muted-foreground>>;
- text-decoration: line-through;
-}
-
-.tc-org-state {
- display: inline-block;
- padding: 0.1rem 0.4rem;
- font-size: 0.72rem;
- font-weight: 700;
- line-height: 1.25;
- letter-spacing: 0.03em;
- border: 1px solid currentColor;
- border-radius: 0.25rem;
-}
-
-.tc-org-state-todo { color: #c74b50; }
-.tc-org-state-next { color: <<colour primary>>; }
-.tc-org-state-wait { color: #b27b2f; }
-.tc-org-state-done { color: <<colour muted-foreground>>; }
-
-.tc-org-tags {
- color: <<colour muted-foreground>>;
- font-size: 0.78em;
- font-weight: 500;
-}
-
-.tc-org-planning {
- margin: 0.25rem 0 0.25rem 1rem;
- color: <<colour muted-foreground>>;
- font-family: monospace;
- font-size: 0.88em;
-}
-
-.tc-org-body-line {
- margin: 0.2rem 0;
- white-space: pre-wrap;
-}
-
-.cm-org-gtd-fold-marker {
- color: <<colour primary>>;
- cursor: pointer;
- font-weight: 700;
-}
-
-.tc-org-agenda-toolbar {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 1rem;
-}
-
-.tc-org-agenda-new {
- padding: 0.45rem 0.8rem;
- color: <<colour background>>;
- background: <<colour primary>>;
- border-radius: 0.35rem;
-}
-
-.tc-org-agenda-section {
- margin: 0 0 1.5rem;
- border-top: 2px solid <<colour tiddler-border>>;
-}
-
-.tc-org-agenda-overdue {
- border-top-color: #c74b50;
-}
-
-.tc-org-agenda-today {
- border-top-color: <<colour primary>>;
-}
-
-.tc-org-agenda-section-title {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- margin: 0;
- padding: 0.6rem 0 0.45rem;
- font-size: 1rem;
-}
-
-.tc-org-agenda-count {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 1.45rem;
- height: 1.45rem;
- padding: 0 0.35rem;
- color: <<colour muted-foreground>>;
- background: <<colour sidebar-tab-background>>;
- border-radius: 999px;
- font-size: 0.75rem;
-}
-
-.tc-org-agenda-row {
- display: grid;
- grid-template-columns: auto minmax(8rem,1fr) auto;
- align-items: center;
- gap: 0.45rem 0.7rem;
- padding: 0.5rem 0;
- border-bottom: 1px solid <<colour tiddler-border>>;
-}
-
-.tc-org-agenda-task {
- min-width: 0;
- color: <<colour foreground>>;
- font-weight: 600;
- text-align: left;
-}
-
-.tc-org-agenda-task:hover,
-.tc-org-agenda-task:focus {
- color: <<colour primary>>;
- text-decoration: underline;
-}
-
-.tc-org-agenda-source,
-.tc-org-agenda-meta,
-.tc-org-agenda-empty {
- color: <<colour muted-foreground>>;
- font-size: 0.82rem;
-}
-
-.tc-org-agenda-meta {
- grid-column: 2 / -1;
-}
-
-.tc-org-agenda-empty {
- margin: 0;
- padding: 0.6rem 0;
-}
-
-@media (max-width: 600px) {
- .tc-org-agenda-row {
- grid-template-columns: auto minmax(0,1fr);
- }
-
- .tc-org-agenda-source {
- grid-column: 2;
- }
-
- .tc-org-agenda-meta {
- grid-column: 2;
- }
-}
diff --git a/tiddlers/tiddlywiki.tid b/tiddlers/tiddlywiki.tid
index 9c209ee..8a108a6 100644
--- a/tiddlers/tiddlywiki.tid
+++ b/tiddlers/tiddlywiki.tid
@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
! 新增一个语法高亮
-增加一个 [[tiddlers/highlight-tiddlywiki.tid|$:/plugins/local/highlight-languages/tiddlywiki.js]] 文件,重启服务就可以了
+源码位于 [[plugins/utilities/highlight-tiddlywiki.tid|$:/plugins/local/highlight-languages/tiddlywiki.js]],由 `$:/plugins/local/utilities` 插件统一打包。
<details>
<summary>点击展开文件内容</summary>
@@ -60,7 +60,7 @@ list-after: $:/core/ui/SideBar/More
! 插件 - 代码复制
-在代码块右上角展示一个复制按钮,插件内容保存在 [[tiddlers/copy-codeblock.tid|$:/plugins/local/copy-codeblock/copy-codeblock.js]]
+在代码块右上角展示一个复制按钮,源码位于 [[plugins/utilities/copy-codeblock-widget.tid|$:/plugins/local/copy-codeblock/copy-codeblock.js]]。
<details>
<summary>点击展开文件内容</summary>
@@ -71,42 +71,6 @@ list-after: $:/core/ui/SideBar/More
! 资源文件管理
-图片文件可以和条目文件分开保存,可以和 html 分开加载
-
-资源文件可以放置在 files 文件夹中,通过 ./files/... 的方式引用
-
-资源文件的上传下载,用 webdav 好了
-
-增加索取所有文件的接口,写入到 tiddlers/files-list-api.tid 文件中
-
-<details>
-<summary>点击展开文件内容</summary>
-
-{{files-list-api.tid}}
-
-</details>
-
-在 wiki 中获取文件列表
-
-```tid
-\procedure store-file-list()
-<$action-setfield
- $tiddler="$:/temp/files-list"
- text=<<data>>
- type="application/json"
-/>
-\end
-
-<$button>
- <$action-sendmessage
- $message="tm-http-request"
- url="./api/files"
- method="GET"
- oncompletion=<<store-file-list>>
- />
- 刷新文件列表
-</$button>
-
-<pre><$text text={{$:/temp/files-list}}/></pre>
-```
+图片文件可以和条目文件分开保存,也可以和 HTML 分开加载。
+资源文件可以放在 `files/` 文件夹中,通过 `./files/...` 引用。
diff --git a/tiddlers/日历.tid b/tiddlers/日历.tid
index 0b11acb..ce84a8b 100644
--- a/tiddlers/日历.tid
+++ b/tiddlers/日历.tid
@@ -9,13 +9,44 @@ type: text/vnd.tiddlywiki
width: 100%;
}
+.tc-journal-calendar-toolbar {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.75rem 1rem;
+ margin-bottom: 1rem;
+}
+
+.tc-journal-calendar-month-summary {
+ display: flex;
+ flex-wrap: wrap;
+ flex: 1 1 auto;
+ align-items: center;
+ gap: 0.5rem 1rem;
+ min-width: 0;
+}
+
+.tc-journal-calendar-current-month {
+ margin: 0;
+ white-space: nowrap;
+}
+
.tc-journal-calendar-view-switcher,
.tc-journal-calendar-month-controls {
display: flex;
- flex-wrap: wrap;
- justify-content: center;
+ flex-wrap: nowrap;
gap: 0.5rem;
- margin-bottom: 1rem;
+}
+
+.tc-journal-calendar-view-switcher {
+ flex: 0 0 auto;
+ justify-content: flex-end;
+ margin-left: auto;
+}
+
+.tc-journal-calendar-month-controls {
+ justify-content: flex-start;
}
.tc-journal-calendar-switch,
@@ -34,9 +65,30 @@ type: text/vnd.tiddlywiki
margin-bottom: 2rem;
}
+.tc-journal-calendar-month-header {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem 1rem;
+ margin-bottom: 0.75rem;
+}
+
.tc-journal-calendar-month-title {
- margin: 0 0 0.75rem;
- text-align: center;
+ margin: 0;
+}
+
+.tc-journal-calendar-expand {
+ margin-left: auto;
+ padding: 0.35rem 0.8rem;
+ border: 1px solid <<colour tiddler-border>>;
+ border-radius: 999px;
+}
+
+.tc-journal-calendar-expand:hover,
+.tc-journal-calendar-expand:focus {
+ color: <<colour background>>;
+ background: <<colour primary>>;
}
.tc-journal-calendar-viewport {
@@ -101,6 +153,10 @@ type: text/vnd.tiddlywiki
color: <<colour primary>>;
}
+.tc-journal-calendar-day-today .tc-journal-calendar-day-link {
+ color: <<colour background>>;
+}
+
.tc-journal-calendar-day-number {
margin-bottom: 0.35rem;
font-weight: 600;
@@ -133,7 +189,14 @@ type: text/vnd.tiddlywiki
}
@media (max-width: 600px) {
+ .tc-journal-calendar-month-summary {
+ flex: 1 1 100%;
+ flex-wrap: wrap;
+ }
+
.tc-journal-calendar-view-switcher {
+ flex: 1 1 100%;
+ margin-left: 0;
display: grid;
grid-template-columns: repeat(2,minmax(0,1fr));
gap: 0.35rem;
@@ -159,6 +222,10 @@ type: text/vnd.tiddlywiki
font-size: 1.25rem;
}
+ .tc-journal-calendar-expand {
+ min-height: 2.75rem;
+ }
+
.tc-journal-calendar-viewport {
overflow-x: visible;
}