From ca1a4a31706d0c03673fe4c414c645ed826b21c6 Mon Sep 17 00:00:00 2001 From: shu Date: Wed, 19 Aug 2026 15:56:06 +0800 Subject: 精简 Wiki 构建与运行方式 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将浏览器端工具整理为 utilities 插件,移除 Docker、Org GTD 和 files API,并补充单文件构建及 Node.js 运行入口。 --- tiddlers/$__StoryList.tid | 3 - tiddlers/$__StoryList_2.tid | 0 tiddlers/$__config_org-gtd_extraKeys.json | 8 - tiddlers/$__config_org-gtd_extraKeys.json.meta | 4 - tiddlers/GTD Agenda.tid | 5 - tiddlers/GTD Inbox.org | 5 - tiddlers/GTD Inbox.org.meta | 4 - ...75\277\347\224\250\350\257\264\346\230\216.tid" | 46 --- tiddlers/files API demo.tid | 51 --- tiddlers/files-list-api.tid.js.meta | 5 - tiddlers/plugin-copy-codeblock-widget.tid | 72 ----- tiddlers/plugin-current-tiddler-toc-sidebar.tid | 69 ----- tiddlers/plugin-current-tiddler-toc-widget.tid | 284 ----------------- tiddlers/plugin-files-api-route.tid | 132 -------- tiddlers/plugin-highlight-caddyfile.tid | 65 ---- tiddlers/plugin-highlight-json5.tid | 59 ---- tiddlers/plugin-highlight-tiddlywiki.tid | 191 ------------ tiddlers/plugin-journal-calendar-widget.tid | 333 -------------------- tiddlers/plugin-org-gtd-agenda-widget.tid | 229 -------------- tiddlers/plugin-org-gtd-codemirror.tid | 341 --------------------- tiddlers/plugin-org-gtd-content-type.tid | 12 - tiddlers/plugin-org-gtd-editor-mapping.tid | 2 - tiddlers/plugin-org-gtd-library.tid | 141 --------- tiddlers/plugin-org-gtd-parser.tid | 76 ----- tiddlers/plugin-org-gtd-sidebar.tid | 13 - tiddlers/plugin-org-gtd-styles.tid | 159 ---------- tiddlers/tiddlywiki.tid | 44 +-- "tiddlers/\346\227\245\345\216\206.tid" | 77 ++++- 28 files changed, 76 insertions(+), 2354 deletions(-) create mode 100644 tiddlers/$__StoryList_2.tid delete mode 100644 tiddlers/$__config_org-gtd_extraKeys.json delete mode 100644 tiddlers/$__config_org-gtd_extraKeys.json.meta delete mode 100644 tiddlers/GTD Agenda.tid delete mode 100644 tiddlers/GTD Inbox.org delete mode 100644 tiddlers/GTD Inbox.org.meta delete mode 100644 "tiddlers/Org GTD \344\275\277\347\224\250\350\257\264\346\230\216.tid" delete mode 100644 tiddlers/files API demo.tid delete mode 100644 tiddlers/files-list-api.tid.js.meta delete mode 100644 tiddlers/plugin-copy-codeblock-widget.tid delete mode 100644 tiddlers/plugin-current-tiddler-toc-sidebar.tid delete mode 100644 tiddlers/plugin-current-tiddler-toc-widget.tid delete mode 100644 tiddlers/plugin-files-api-route.tid delete mode 100644 tiddlers/plugin-highlight-caddyfile.tid delete mode 100644 tiddlers/plugin-highlight-json5.tid delete mode 100644 tiddlers/plugin-highlight-tiddlywiki.tid delete mode 100644 tiddlers/plugin-journal-calendar-widget.tid delete mode 100644 tiddlers/plugin-org-gtd-agenda-widget.tid delete mode 100644 tiddlers/plugin-org-gtd-codemirror.tid delete mode 100644 tiddlers/plugin-org-gtd-content-type.tid delete mode 100644 tiddlers/plugin-org-gtd-editor-mapping.tid delete mode 100644 tiddlers/plugin-org-gtd-library.tid delete mode 100644 tiddlers/plugin-org-gtd-parser.tid delete mode 100644 tiddlers/plugin-org-gtd-sidebar.tid delete mode 100644 tiddlers/plugin-org-gtd-styles.tid (limited to 'tiddlers') 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 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 \344\275\277\347\224\250\350\257\264\346\230\216.tid" "b/tiddlers/Org GTD \344\275\277\347\224\250\350\257\264\346\230\216.tid" deleted file mode 100644 index 2a670ee..0000000 --- "a/tiddlers/Org GTD \344\275\277\347\224\250\350\257\264\346\230\216.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=<> - type="application/json" -/> -\end - -<$button> - <$action-sendmessage - $message="tm-http-request" - url="./api/files" - method="GET" - oncompletion=<> - /> - 刷新文件列表 - - -
<$text text={{$:/temp/files-list}}/>
- -[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 - - - -<$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: /<>/ - }, - { - 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: // - }, - { - 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: /<>/, - 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 - -
-<$link to="GTD Agenda">打开 Agenda - -<$list filter="[type[text/x-org]!has[draft.of]sort[title]]" emptyMessage="还没有 Org 文档。"> -
<$link/>
- -
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: <>; - --org-wait: #b27b2f; - --org-done: <>; -} - -.tc-org-heading { - margin: 1.15rem 0 0.45rem; - line-height: 1.35; -} - -.tc-org-heading-done { - color: <>; - 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: <>; } -.tc-org-state-wait { color: #b27b2f; } -.tc-org-state-done { color: <>; } - -.tc-org-tags { - color: <>; - font-size: 0.78em; - font-weight: 500; -} - -.tc-org-planning { - margin: 0.25rem 0 0.25rem 1rem; - color: <>; - 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: <>; - 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: <>; - background: <>; - border-radius: 0.35rem; -} - -.tc-org-agenda-section { - margin: 0 0 1.5rem; - border-top: 2px solid <>; -} - -.tc-org-agenda-overdue { - border-top-color: #c74b50; -} - -.tc-org-agenda-today { - border-top-color: <>; -} - -.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: <>; - 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 <>; -} - -.tc-org-agenda-task { - min-width: 0; - color: <>; - font-weight: 600; - text-align: left; -} - -.tc-org-agenda-task:hover, -.tc-org-agenda-task:focus { - color: <>; - text-decoration: underline; -} - -.tc-org-agenda-source, -.tc-org-agenda-meta, -.tc-org-agenda-empty { - color: <>; - 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` 插件统一打包。
点击展开文件内容 @@ -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]]。
点击展开文件内容 @@ -71,42 +71,6 @@ list-after: $:/core/ui/SideBar/More ! 资源文件管理 -图片文件可以和条目文件分开保存,可以和 html 分开加载 - -资源文件可以放置在 files 文件夹中,通过 ./files/... 的方式引用 - -资源文件的上传下载,用 webdav 好了 - -增加索取所有文件的接口,写入到 tiddlers/files-list-api.tid 文件中 - -
-点击展开文件内容 - -{{files-list-api.tid}} - -
- -在 wiki 中获取文件列表 - -```tid -\procedure store-file-list() -<$action-setfield - $tiddler="$:/temp/files-list" - text=<> - type="application/json" -/> -\end - -<$button> - <$action-sendmessage - $message="tm-http-request" - url="./api/files" - method="GET" - oncompletion=<> - /> - 刷新文件列表 - - -
<$text text={{$:/temp/files-list}}/>
-``` +图片文件可以和条目文件分开保存,也可以和 HTML 分开加载。 +资源文件可以放在 `files/` 文件夹中,通过 `./files/...` 引用。 diff --git "a/tiddlers/\346\227\245\345\216\206.tid" "b/tiddlers/\346\227\245\345\216\206.tid" index 0b11acb..ce84a8b 100644 --- "a/tiddlers/\346\227\245\345\216\206.tid" +++ "b/tiddlers/\346\227\245\345\216\206.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 <>; + border-radius: 999px; +} + +.tc-journal-calendar-expand:hover, +.tc-journal-calendar-expand:focus { + color: <>; + background: <>; } .tc-journal-calendar-viewport { @@ -101,6 +153,10 @@ type: text/vnd.tiddlywiki color: <>; } +.tc-journal-calendar-day-today .tc-journal-calendar-day-link { + color: <>; +} + .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; } -- cgit v1.2.3