├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── gh-pages.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── dprint.json ├── package.json ├── pnpm-lock.yaml ├── src ├── auto-switch-language │ ├── plugin.info │ ├── readme.tid │ └── startup-action.tid ├── open-in-external-app │ ├── ViewToolbarButtons │ │ ├── OpenInExternalApp.tid │ │ ├── OpenInFolder.tid │ │ ├── button-caption-open-in-external-app.tid │ │ └── button-caption-open-in-folder.tid │ ├── icons │ │ ├── open-in-app.tid │ │ └── open-in-folder.tid │ ├── listener.ts │ ├── listener.ts.meta │ ├── plugin.info │ ├── readme.tid │ └── tree.tid ├── preview-glass │ ├── config.tid │ ├── defaults.multids │ ├── keyboard.js │ ├── keyboard.js.meta │ ├── link.js │ ├── link.js.meta │ ├── motivation.tid │ ├── plugin.info │ ├── popups.tid │ ├── preview-template.css │ ├── preview-template.css.meta │ ├── readme.tid │ ├── template.tid │ └── tree.tid ├── source-control-management │ ├── SideBarSCMTab.tid │ ├── git-pull-request.svg │ ├── git-pull-request.svg.meta │ ├── plugin.info │ ├── readme.tid │ ├── style.css │ ├── tab.ts │ ├── tab.ts.meta │ └── tree.tid └── type.ts ├── tailwind.config.js ├── tsconfig.eslint.json ├── tsconfig.json └── wiki ├── tiddlers ├── $__DefaultTiddlers.tid ├── $__Modern.TiddlyDev_Startup.tid ├── $__SiteSubtitle.tid ├── $__SiteTitle.tid ├── $__favicon.ico ├── $__favicon.ico.meta ├── $__palette.tid ├── $__plugins_Gk0Wk_CPL-Repo.json ├── $__plugins_Gk0Wk_CPL-Repo.json.meta ├── $__plugins_Modern.TiddlyDev_doc.json ├── $__plugins_linonetwo_prevent-edit.json ├── $__plugins_linonetwo_prevent-edit.json.meta ├── $__themes_tiddlywiki_vanilla_options_sidebarlayout.tid ├── LanguageSwitcher.tid └── tests │ └── example │ ├── filters.js │ └── filters.js.meta └── tiddlywiki.info /.eslintignore: -------------------------------------------------------------------------------- 1 | resources/ 2 | settings-dev/ 3 | out/ 4 | logs/ 5 | dist/ 6 | wiki/ 7 | template/ 8 | .webpack/ 9 | node_modules/ 10 | localization/ 11 | build-resources/ 12 | .vscode/ 13 | .github/ 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const tsEslintConfig = require('./tsconfig.eslint.json'); 2 | 3 | module.exports = { 4 | root: true, 5 | ignorePatterns: tsEslintConfig.exclude, 6 | parserOptions: { 7 | project: './tsconfig.eslint.json', 8 | tsconfigRootDir: __dirname, 9 | }, 10 | extends: ['eslint-config-tidgi'], 11 | rules: { 12 | 'unicorn/prefer-dom-node-text-content': 'off', 13 | 'unicorn/prefer-modern-dom-apis': 'off', 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Tiddlywiki To Github Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | paths-ignore: 9 | # Readme.md should not trigger wiki deploy 10 | - '*.md' 11 | 12 | jobs: 13 | deploy: 14 | permissions: 15 | contents: write 16 | pages: write 17 | id-token: write 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | 23 | - name: Install Node.js 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: lts/* 27 | 28 | - name: Setup pnpm 29 | uses: pnpm/action-setup@v4 30 | with: 31 | version: 'latest' 32 | run_install: false 33 | 34 | - name: Cache dependencies 35 | uses: actions/cache@v4 36 | with: 37 | path: | 38 | **/node_modules 39 | ~/.pnpm-store 40 | ~/.npm 41 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 42 | restore-keys: | 43 | ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 44 | ${{ runner.os }}-node- 45 | 46 | - name: Install Dependencies 47 | run: pnpm install 48 | 49 | - name: Build Library and static website 50 | run: pnpm run publish 51 | 52 | - name: Upload artifact 53 | uses: actions/upload-pages-artifact@v3 54 | with: 55 | # Upload entire repository 56 | path: ./dist 57 | - name: Deploy to GitHub Pages 58 | id: deployment 59 | uses: actions/deploy-pages@v4 60 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Plugins 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | paths-ignore: 8 | - 'README.md' 9 | - 'wiki/**' 10 | - 'public/**' 11 | - 'scripts/**' 12 | - '.vscode' 13 | - '.idea' 14 | pull_request: 15 | branches: 16 | - master 17 | - main 18 | paths-ignore: 19 | - 'README.md' 20 | - 'wiki/**' 21 | - 'public/**' 22 | - '.scripts/**' 23 | - '.vscode' 24 | - '.idea' 25 | 26 | concurrency: 27 | group: release-ci-group 28 | cancel-in-progress: true 29 | 30 | jobs: 31 | Plugins: 32 | permissions: 33 | contents: write 34 | pages: write 35 | id-token: write 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v4 40 | 41 | - name: Install Node.js 42 | uses: actions/setup-node@v4 43 | with: 44 | node-version: lts/* 45 | 46 | - name: Setup pnpm 47 | uses: pnpm/action-setup@v4 48 | with: 49 | version: 'latest' 50 | run_install: false 51 | 52 | - name: Cache dependencies 53 | uses: actions/cache@v3 54 | with: 55 | path: | 56 | **/node_modules 57 | ~/.pnpm-store 58 | ~/.npm 59 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 60 | restore-keys: | 61 | ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 62 | ${{ runner.os }}-node- 63 | 64 | - name: Install Dependencies 65 | run: pnpm install 66 | 67 | - name: Run tests 68 | run: pnpm run test 69 | 70 | - name: Build Plugins 71 | run: pnpm run build 72 | 73 | - name: Create Release 74 | uses: softprops/action-gh-release@v1 75 | if: startsWith(github.ref, 'refs/tags/') 76 | with: 77 | files: | 78 | dist/*.json 79 | env: 80 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # For IDE 4 | .vscode/**/* 5 | !.vscode/settings.json 6 | !.vscode/extensions.json 7 | .idea/ 8 | 9 | # Logs 10 | logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | lerna-debug.log* 16 | .pnp 17 | .pnp.js 18 | .history 19 | *.report 20 | 21 | # Diagnostic reports (https://nodejs.org/api/report.html) 22 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 23 | 24 | # Runtime data 25 | pids 26 | *.seed 27 | *.pid 28 | *.pid.lock 29 | 30 | # Directory for instrumented libs generated by jscoverage/JSCover 31 | lib-cov 32 | 33 | # Coverage directory used by tools like istanbul 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | .nyc_output 39 | 40 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 41 | .grunt 42 | 43 | # Bower dependency directory (https://bower.io/) 44 | bower_components 45 | 46 | # node-waf configuration 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | build/Release 51 | 52 | # Dependency directories 53 | node_modules/ 54 | jspm_packages/ 55 | .pnpm-store/ 56 | 57 | .changeset/pre.json 58 | 59 | # TypeScript v1 declaration files 60 | typings/ 61 | 62 | # TypeScript cache 63 | *.tsbuildinfo 64 | 65 | # Optional npm cache directory 66 | .npm 67 | 68 | # Optional eslint cache 69 | .eslintcache 70 | 71 | .sonarlint 72 | 73 | # Microbundle cache 74 | .rpt2_cache/ 75 | .rts2_cache_cjs/ 76 | .rts2_cache_es/ 77 | .rts2_cache_umd/ 78 | 79 | # Optional REPL history 80 | .node_repl_history 81 | 82 | # Output of 'npm pack' 83 | *.tgz 84 | 85 | # Yarn Integrity file 86 | .yarn-integrity 87 | 88 | # dotenv environment variables file 89 | .env 90 | .env.test 91 | .env.local 92 | .env.*.local 93 | 94 | # parcel-bundler cache (https://parceljs.org/) 95 | .cache 96 | 97 | # Next.js build output 98 | .next 99 | 100 | # Nuxt.js build / generate output 101 | .nuxt 102 | dist/ 103 | release/ 104 | output/ 105 | output_resource/ 106 | 107 | # Gatsby files 108 | .cache/ 109 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 110 | # https://nextjs.org/blog/next-9-1#public-directory-support 111 | public-dist 112 | 113 | # vuepress build output 114 | .vuepress/dist 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | **/*/typings/auto-generated 129 | 130 | # for TiddlyWiki 131 | dist/ 132 | output/ 133 | wiki/tiddlers/$__language.tid 134 | wiki/tiddlers/$__StoryList.tid 135 | wiki/tiddlers/$__StoryList_*.tid 136 | wiki/tiddlers/$__keepstate_* 137 | wiki/tiddlers/$__Import.tid 138 | wiki/tiddlers/$__UpgradeLibrary 139 | wiki/tiddlers/$__UpgradeLibrary_List 140 | wiki/tiddlers/$__temp_* 141 | wiki/tiddlers/$__view.tid 142 | wiki/tiddlers/$__config_Navigation_openLinkFromInsideRiver.tid 143 | wiki/tiddlers/$__config_Navigation_openLinkFromOutsideRiver.tid 144 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "arrowParens": "avoid" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 lin onetwo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plugins 2 | 3 | Plugins developed for a better [TidGi Desktop](https://github.com/tiddly-gittly/TidGi-Desktop). 4 | 5 | Release can be download at [Community Plugin Library](https://github.com/tiddly-gittly/TiddlyWiki-CPL). 6 | 7 | ## About 8 | 9 | ### Watch-FS 10 | 11 | "linonetwo/watch-fs" 12 | 13 | This plugin enables TiddlyWiki to watch the change in your disk, solves [pick up changes made by outside agencies #1530](https://github.com/Jermolene/TiddlyWiki5/issues/1530), and if you edit one of your tiddler using editor likes VSCode and save it on the disk, the change will immediately reflected in the browser. 14 | 15 | This by default monitor `./tiddlers` folder, if you have a different setup like my [linonetwo/wiki](https://github.com/linonetwo/wiki), add a `watchFolder` config to your `tiddlywiki.info`: 16 | 17 | ```json 18 | { 19 | ... 20 | "themes": [ 21 | "tiddlywiki/vanilla", 22 | "linonetwo/itonnote" 23 | ], 24 | ... 25 | "config": { 26 | "watchFolder": "./Meme-of-LinOnetwo/tiddlers" 27 | }, 28 | ``` 29 | 30 | See [Jermolene/TiddlyWiki5/issues/3060](https://github.com/Jermolene/TiddlyWiki5/issues/3060) for related discussions. 31 | 32 | Server side only. But also change the `SyncPollingInterval.tid` in the client side. 33 | 34 | ### Prevent-Edit 35 | 36 | "linonetwo/prevent-edit" 37 | 38 | Prevent `This page is asking you to confirm that you want to leave - data you have entered may not be saved` to popup. 39 | 40 | Client side only. 41 | 42 | ### Service-Worker 43 | 44 | "linonetwo/service-worker" 45 | 46 | Needs additional setup, see plugin folder for details, only use it if you are an experienced web developer... 47 | 48 | Client side only. 49 | 50 | ### Copy On Select 51 | 52 | "linonetwo/copy-on-select" 53 | 54 | When you select a string in your wiki, it will be copied automatically! 55 | 56 | Client side only. 57 | 58 | ### Inverse Link And Folder 59 | 60 | "linonetwo/inverse-link-and-folder" 61 | 62 | Yet another bidirectional-link plugin. 63 | 64 | ![Inverse Link And Folder Screenshot](./docs/img/inverse-link-and-folder.png) 65 | 66 | Client side only. 67 | 68 | ### Opened Tiddlers Bar 69 | 70 | "linonetwo/opened-tiddlers-bar" 71 | 72 | A VSCode style "opened tiddler" bar on the top of the wiki. 73 | 74 | ![Opened Tiddlers Bar Screenshot](./docs/img/opened-tiddlers-bar.png) 75 | 76 | Client side only. 77 | 78 | ### SCM 79 | 80 | "linonetwo/source-control-management" 81 | 82 | Allow you view modified tiddlers in your git-backup-ed nodejs wiki, inside TiddlyGit-Desktop. 83 | 84 | Note this plugin uses git api provided by TiddlyGit-Desktop, you can't use it alone. 85 | 86 | ![SCM Screenshot](./docs/img/scm.png) 87 | 88 | ### Github External Images 89 | 90 | "linonetwo/github-external-image" 91 | 92 | Allow extract your images, and load image from github raw image file. 93 | 94 | Need some simple setup, see readme for detail. 95 | 96 | ## How to use 97 | 98 | Place the plugin like this: 99 | 100 | ![Folder Structure](./docs/img/folder-structure.png) 101 | 102 | And update your `tiddlywiki.info`, pick what you need: 103 | 104 | ```json 105 | { 106 | "description": ".....", 107 | "plugins": [ 108 | "linonetwo/service-worker", 109 | "linonetwo/opened-tiddlers-bar", 110 | "linonetwo/inverse-link-and-folder", 111 | "linonetwo/copy-on-select", 112 | "linonetwo/prevent-edit", 113 | "linonetwo/watch-fs" 114 | ], 115 | "themes": ["tiddlywiki/vanilla", "linonetwo/itonnote"], 116 | "languages": ["zh-Hans"] 117 | } 118 | ``` 119 | -------------------------------------------------------------------------------- /dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "lineWidth": 180, 3 | "typescript": { 4 | "quoteProps": "asNeeded", 5 | "quoteStyle": "preferSingle", 6 | "binaryExpression.operatorPosition": "sameLine" 7 | }, 8 | "json": {}, 9 | "markdown": {}, 10 | "includes": [ 11 | "**/*.{ts,tsx,js,jsx,cjs,mjs,json,md}", 12 | "./*.json", 13 | "./*.js", 14 | "packages/*/.*.js" 15 | ], 16 | "excludes": ["**/node_modules", "**/*-lock.json"], 17 | "plugins": [ 18 | "https://plugins.dprint.dev/typescript-0.93.4.wasm", 19 | "https://plugins.dprint.dev/json-0.19.4.wasm", 20 | "https://plugins.dprint.dev/markdown-0.17.8.wasm" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://tiddly-gittly.github.io/Modern.TiddlyDev/", 3 | "license": "MIT", 4 | "version": "0.0.2", 5 | "scripts": { 6 | "dev": "tiddlywiki-plugin-dev dev", 7 | "dev:lan": "tiddlywiki-plugin-dev dev --lan", 8 | "dev:wiki": "tiddlywiki-plugin-dev dev --write-wiki", 9 | "test": "tiddlywiki-plugin-dev test", 10 | "build": "npm run clean && tiddlywiki-plugin-dev build", 11 | "publish": "npm run clean && tiddlywiki-plugin-dev publish", 12 | "reset": "rimraf ./**/node_modules", 13 | "clean": "rimraf dist", 14 | "prepare": "husky install", 15 | "update": "npm-check-updates -u && dprint config update", 16 | "new": "tiddlywiki-plugin-dev new", 17 | "build:library": "npm run clean && tiddlywiki-plugin-dev build --library --output dist/library", 18 | "publish:offline": "npm run clean && tiddlywiki-plugin-dev publish --offline" 19 | }, 20 | "engines": { 21 | "node": ">=20" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "lint-staged" 26 | } 27 | }, 28 | "lint-staged": { 29 | "*.{ts,tsx}": [ 30 | "node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet" 31 | ], 32 | "*.{js,jsx,mjs,mjsx,cjs,cjsx}": [ 33 | "node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet" 34 | ] 35 | }, 36 | "devDependencies": { 37 | "@modern-js/tsconfig": "^2.65.1", 38 | "@types/jasmine": "^5.1.7", 39 | "@types/node": "^22.13.5", 40 | "dprint": "^0.49.0", 41 | "eslint-config-tidgi": "^1.2.3", 42 | "husky": "^9.1.7", 43 | "lint-staged": "^15.4.3", 44 | "postcss": "^8.5.3", 45 | "rimraf": "^6.0.1", 46 | "ts-node": "^10.9.2", 47 | "tw5-typed": "^0.5.14", 48 | "typescript": "^5.7.3" 49 | }, 50 | "dependencies": { 51 | "npm-check-updates": "^17.1.15", 52 | "tiddlywiki": "^5.3.6", 53 | "tiddlywiki-plugin-dev": "^0.3.2" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/auto-switch-language/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/plugins/linonetwo/auto-switch-language", 3 | "name": "auto-switch-language", 4 | "author": "linonetwo", 5 | "description": "Use browser info to auto switch language", 6 | "plugin-type": "plugin", 7 | "version": "0.0.1", 8 | "list": "readme" 9 | } -------------------------------------------------------------------------------- /src/auto-switch-language/readme.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/auto-switch-language/readme 2 | type: text/vnd.tiddlywiki 3 | 4 | ! auto-switch-language 5 | 6 | Use browser info to auto switch language 7 | 8 | Copy from https://github.com/tiddly-gittly/Modern.TiddlyDev/blob/2d784fa1da0fc197ad31f61f87d9a0f3dfb7413b/wiki/tiddlers/%24__Modern.TiddlyDev_Startup.tid 9 | 10 | Only support zh-Hans and en-GB now. PR is welcome. 11 | -------------------------------------------------------------------------------- /src/auto-switch-language/startup-action.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/auto-switch-language/readme 2 | tags: $:/tags/StartupAction/Browser 3 | 4 | 5 | <$action-setfield $tiddler="$:/language" text={{{ [{$:/info/browser/language}search:title[zh]then[zh-Hans]else[en-GB]addprefix[$:/languages/]] }}}/> -------------------------------------------------------------------------------- /src/open-in-external-app/ViewToolbarButtons/OpenInExternalApp.tid: -------------------------------------------------------------------------------- 1 | tags: $:/tags/ViewToolbar 2 | title: $:/plugins/linonetwo/open-in-external-app/ViewToolbarButton/OpenInExternalApp 3 | type: text/vnd.tiddlywiki 4 | list-before: $:/core/ui/Buttons/close 5 | caption: {{$:/plugins/linonetwo/open-in-external-app/icons/open-in-app}} {{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-external-app}} 6 | short-caption: {{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-external-app}} 7 | description: Open tiddler in external app 8 | 9 | \whitespace trim 10 | <$button tooltip={{!!description}} aria-label={{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-external-app}} class=<>> 11 | <% if [has[_canonical_uri]] %> 12 | <$action-sendmessage $message="tm-open-in-external-app" filePath={{{[get[_canonical_uri]]}}} /> 13 | <% else %> 14 | <$action-sendmessage $message="tm-open-in-external-app" title=<> /> 15 | <% endif %> 16 | <$list filter="[match[yes]]"> 17 | {{$:/plugins/linonetwo/open-in-external-app/icons/open-in-app}} 18 | 19 | <$list filter="[match[yes]]"> 20 | 21 | <$text text={{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-external-app}}/> 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/open-in-external-app/ViewToolbarButtons/OpenInFolder.tid: -------------------------------------------------------------------------------- 1 | tags: $:/tags/ViewToolbar 2 | title: $:/plugins/linonetwo/open-in-external-app/ViewToolbarButton/OpenInFolder 3 | type: text/vnd.tiddlywiki 4 | list-before: $:/core/ui/Buttons/close 5 | caption: {{$:/plugins/linonetwo/open-in-external-app/icons/open-in-folder}} {{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-folder}} 6 | short-caption: {{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-folder}} 7 | description: Open tiddler in folder 8 | 9 | \whitespace trim 10 | <$button tooltip={{!!description}} aria-label={{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-folder}} class=<>> 11 | <% if [has[_canonical_uri]] %> 12 | <$action-sendmessage $message="tm-open-in-folder" filePath={{{[get[_canonical_uri]]}}} /> 13 | <% else %> 14 | <$action-sendmessage $message="tm-open-in-folder" title=<> /> 15 | <% endif %> 16 | <$list filter="[match[yes]]"> 17 | {{$:/plugins/linonetwo/open-in-external-app/icons/open-in-folder}} 18 | 19 | <$list filter="[match[yes]]"> 20 | 21 | <$text text={{$:/plugins/linonetwo/open-in-external-app/button-caption-open-in-folder}}/> 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/open-in-external-app/ViewToolbarButtons/button-caption-open-in-external-app.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/button-caption-open-in-external-app 2 | type: text/vnd.tiddlywiki 3 | 4 | Open External -------------------------------------------------------------------------------- /src/open-in-external-app/ViewToolbarButtons/button-caption-open-in-folder.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/button-caption-open-in-folder 2 | type: text/vnd.tiddlywiki 3 | 4 | Open in Folder -------------------------------------------------------------------------------- /src/open-in-external-app/icons/open-in-app.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/icons/open-in-app 2 | 3 | -------------------------------------------------------------------------------- /src/open-in-external-app/icons/open-in-folder.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/icons/open-in-folder 2 | 3 | -------------------------------------------------------------------------------- /src/open-in-external-app/listener.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/strict-boolean-expressions, no-var */ 2 | import { IWidgetEvent } from 'tiddlywiki'; 3 | 4 | declare var exports: { 5 | startup: () => void; 6 | }; 7 | 8 | async function getFilePath(event: IWidgetEvent): Promise { 9 | let title = ''; 10 | let filePath: string | undefined; 11 | if (typeof event.param === 'string') { 12 | // for button usage 13 | title = event.param; 14 | } else if (typeof event.paramObject === 'object') { 15 | // Get the specified additional fields, for message usage 16 | const additionalFields = event.paramObject as { filePath?: string; title?: string }; 17 | if (additionalFields?.title) { 18 | title = additionalFields.title; 19 | } 20 | if (additionalFields?.filePath) { 21 | filePath = additionalFields.filePath; 22 | } 23 | } 24 | if (title) { 25 | filePath = await window?.service?.wiki?.getTiddlerFilePath?.(title); 26 | } 27 | if (!filePath) return; 28 | // Check if filePath is a relative path (i.e., not starting with a drive letter or "/" for Mac/Linux) and prepend wikiFolderLocation 29 | const isRelativePath = !/^(?:[A-Za-z]:[/\\]|\/)/.test(filePath); 30 | if (isRelativePath) { 31 | const workspaceID = window?.meta?.()?.workspaceID; 32 | if (!workspaceID) return; 33 | const workspace = await window?.service?.workspace?.get(workspaceID); 34 | const wikiFolderLocation = workspace?.wikiFolderLocation; 35 | if (!wikiFolderLocation) return; 36 | filePath = decodeURI(`${wikiFolderLocation}/${filePath}`); 37 | } 38 | return filePath; 39 | } 40 | 41 | // Listen for the tm-home message 42 | exports.startup = () => { 43 | if (!$tw.browser) { 44 | return; 45 | } 46 | $tw.rootWidget.addEventListener('tm-open-in-external-app', async (event) => { 47 | const filePath = await getFilePath(event); 48 | if (filePath !== undefined) { 49 | await window?.service?.native?.openPath?.(filePath); 50 | } 51 | }); 52 | $tw.rootWidget.addEventListener('tm-open-in-folder', async (event) => { 53 | const filePath = await getFilePath(event); 54 | if (filePath !== undefined) { 55 | await window?.service?.native?.openPath?.(filePath, true); 56 | } 57 | }); 58 | 59 | $tw.rootWidget.addEventListener('tm-open-path', async (event) => { 60 | let filePath = ''; 61 | if (typeof event.param === 'string') { 62 | // for button usage 63 | filePath = event.param; 64 | } else if (typeof event.paramObject === 'object') { 65 | // Get the specified additional fields, for message usage 66 | const additionalFields = event.paramObject as { filePath?: string }; 67 | if (additionalFields?.filePath) { 68 | filePath = additionalFields.filePath; 69 | } 70 | } 71 | await window?.service?.native?.openPath?.(filePath); 72 | }); 73 | }; 74 | -------------------------------------------------------------------------------- /src/open-in-external-app/listener.ts.meta: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/listener 2 | type: application/javascript 3 | module-type: startup -------------------------------------------------------------------------------- /src/open-in-external-app/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/plugins/linonetwo/open-in-external-app", 3 | "name": "Open In External App", 4 | "description": "(Requires TidGi) A toolbar button to open PDF tiddler in os default reader, or open in folder.", 5 | "author": "LinOnetwo", 6 | "core-version": ">=5.1.22", 7 | "plugin-type": "plugin", 8 | "stability": "STABILITY_1_EXPERIMENTAL", 9 | "version": "0.2.0", 10 | "dependents": [], 11 | "list": "readme tree" 12 | } 13 | -------------------------------------------------------------------------------- /src/open-in-external-app/readme.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/readme 2 | type: text/vnd.tiddlywiki 3 | 4 | !! Basic Usage 5 | 6 | After you import a PDF or image file into your wiki, you can open that tiddler, and click on the button to open that file in external PDF viewer or image reader. 7 | 8 | Note that if you use this to open a `.tid` or `.md` file, and edit it, things won't change in the wiki, because the tiddlywiki currently doesn't reload changed files from the disk. 9 | 10 | !! Message usage 11 | 12 | You can use `param` or `$param` to passing the parameter. Or use `title` in `tm-open-in-external-app` and `filePath` in `tm-open-path`. 13 | 14 | !!! tm-open-in-external-app 15 | 16 | ```tw5 17 | <$button message="tm-open-in-external-app" param="SomePDFTiddlerTitle">Open that PDF 18 | ``` 19 | 20 | ```tw5 21 | <$button> 22 | <$action-sendmessage $message="tm-open-in-external-app" title="SomePDFTiddlerTitle" /> 23 | Open that PDF with tiddler title 24 | 25 | ``` 26 | 27 | !!! tm-open-path 28 | 29 | You can use absolute path: 30 | 31 | ```tw5 32 | <$button message="tm-open-path" param="SomePDF/File/Absolute/Path">Open that PDF 33 | ``` 34 | 35 | Or use relative path from the current wiki folder (that contains the `tiddlers` folder and `tiddler.info` file). 36 | 37 | ```tw5 38 | <$button> 39 | <$action-sendmessage $message="tm-open-path" filePath="tiddlers/File/relative/Path/from/Wiki/Folder" /> 40 | Open that PDF with filePath 41 | 42 | ``` 43 | 44 | Try this to open the info file: 45 | 46 | <$button> 47 | <$action-sendmessage $message="tm-open-path" filePath="tiddlywiki.info" /> 48 | Open tiddlywiki.info 49 | 50 | -------------------------------------------------------------------------------- /src/open-in-external-app/tree.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/open-in-external-app/tree 2 | type: text/vnd.tiddlywiki 3 | 4 | <> -------------------------------------------------------------------------------- /src/preview-glass/config.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/preview-glass/config 2 | 3 | \define default() 4 |
$(defaults)$$(option)$
5 |
6 | //{{$:/plugins/linonetwo/preview-glass/lingo/$(option)$}}<$list 7 | filter="[[$(option)$]prefix[template]]"> 8 | {{$(defaults)$$(option)$}}://
9 | <$edit-text tag=input tiddler="$(defaults)$$(option)$"/> 10 |
11 | \end 12 | 13 |
14 | <$vars defaults="$:/plugins/linonetwo/preview-glass/defaults/"> 15 | <$list filter="[all[tiddlers+shadows]removeprefixsort[title]]" variable="option"> 16 | <> 17 | 18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /src/preview-glass/defaults.multids: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/preview-glass/ 2 | 3 | lingo/keys: modifier keys to trigger popup directly on-hover (ctrl, alt+shift, meta, etc...) 4 | defaults/keys: CTRL 5 | 6 | lingo/delay: delay popup for this many milliseconds 7 | defaults/delay: 150 8 | 9 | lingo/class: css classes applied to the popup 10 | defaults/class: hover-popup-preview-container 11 | 12 | lingo/not: no preview for links inside elements with these classes 13 | defaults/not: tc-drop-down tc-search-drop-down tc-sidebar-scrollable tc-topbar tc-tiddler-title 14 | 15 | lingo/exclude: no preview for links to tiddlers matching this filter 16 | defaults/exclude: [is[system]] [all[shadows]] [!has[text]] 17 | 18 | lingo/template: the preview template 19 | defaults/template: $:/plugins/linonetwo/preview-glass/template 20 | 21 | lingo/open: view at ''<>'' -------------------------------------------------------------------------------- /src/preview-glass/keyboard.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/tobibeer/preview/keyboard.js 3 | type: application/javascript 4 | module-type: utils 5 | Fixes $:/core/modules/utils/dom/keyboard.js by providing an alternative. 6 | Do not use as an API, let's fix the core. 7 | @preserve 8 | \*/ 9 | (function(){ 10 | 11 | /*jslint node: true, browser: true */ 12 | /*global $tw: false */ 13 | "use strict"; 14 | 15 | var namedKeys = { 16 | "BACKSPACE": 8, 17 | "TAB": 9, 18 | "ENTER": 13, 19 | "ESCAPE": 27, 20 | "PAGEUP": 33, 21 | "PAGEDOWN": 34, 22 | "END": 35, 23 | "HOME": 36, 24 | "LEFT": 37, 25 | "UP": 38, 26 | "RIGHT": 39, 27 | "DOWN": 40, 28 | "INSERT": 45, 29 | "DELETE": 46 30 | }; 31 | 32 | /* 33 | Parses a key descriptor into the structure: 34 | { 35 | keyCode: numeric keycode 36 | shiftKey: boolean 37 | altKey: boolean 38 | ctrlKey: boolean 39 | } 40 | Key descriptors have the following format: 41 | ctrl+enter 42 | ctrl+shift+alt+A 43 | */ 44 | exports.parseKeyDescriptorTB = function(keyDescriptor) { 45 | var neg,s,t, 46 | components = keyDescriptor.toUpperCase().split("+"), 47 | info = { 48 | keyCode: null, 49 | shiftKey: false, 50 | altKey: false, 51 | ctrlKey: false 52 | }; 53 | for(t=0; t= 0) { 121 | // Then don't display 122 | doShow = 0; 123 | } 124 | } 125 | // Return what we got 126 | return doShow; 127 | }; 128 | // Turn delay to integer 129 | delay = delay !== undefined ? parseInt(delay) : null; 130 | // Not a number? 131 | if (delay !== null && isNaN(delay)) { 132 | // No delay 133 | delay = 0; 134 | } 135 | // Target tiddler exists? 136 | if (to) { 137 | // Add handle class 138 | $tw.utils.addClass(el, 'tc-popup-handle'); 139 | // Add absolute positioning class 140 | $tw.utils.addClass(el, 'tc-popup-absolute'); 141 | // Loop new event handlers 142 | ['mouseover', 'mouseout'].forEach(function (e) { 143 | // Create event listener 144 | el.addEventListener(e, function (event) { 145 | // Ref to event 146 | var ev = event || window.event; 147 | // On mouseover 148 | if (e === 'mouseover') { 149 | // Actually showing anything? 150 | if (show()) { 151 | // No keycode? 152 | if (!ev.keyCode) { 153 | // Set to 0, for whatever reason the core expects one 154 | ev.keyCode = 0; 155 | } 156 | // Modifier keys say we show directly? 157 | if ($tw.utils.checkKeyDescriptorTB(ev, keys)) { 158 | // Not yet blocking mousover madness? 159 | if (!block) { 160 | // Block further firing of mouseover events 161 | block = 1; 162 | // Then show 163 | showPopup(); 164 | } 165 | // Modifiers don't match but we got a delay? 166 | } else if (delay !== null) { 167 | // No more blocking of mouseover events 168 | block = 0; 169 | // Set timeout and wait to show popup 170 | self.previewTimeout = setTimeout(showPopup, delay); 171 | } 172 | } 173 | // Mouseout 174 | } else { 175 | // No more blocking of mouseover events 176 | block = 0; 177 | // No more waiting for the popup 178 | clearTimeout(self.previewTimeout); 179 | // close popup 180 | // if next object to move mouse to is not a popup 181 | if(!event.relatedTarget || !event.relatedTarget.classList.contains('tc-preview-tiddler')) { 182 | // then close popup 183 | $tw.popup.cancel(Math.max(0, getInfo(el).popupLevel)); 184 | } 185 | } 186 | }); 187 | }); 188 | } 189 | }; 190 | 191 | // Hijack click handler 192 | CoreLink.prototype.handleClickEvent = function () { 193 | // Run core handler 194 | clickCore.apply(this, arguments); 195 | // Abort popup delay timeout 196 | clearTimeout(this.previewTimeout); 197 | // Close popups 198 | $tw.popup.cancel(Math.max(0, $tw.popup.popupInfo(this.domNodes[0]).popupLevel)); 199 | }; 200 | })(); -------------------------------------------------------------------------------- /src/preview-glass/link.js.meta: -------------------------------------------------------------------------------- 1 | created: 20200530032342272 2 | modified: 20200530033801090 3 | module-type: startup 4 | title: $:/plugins/linonetwo/preview-glass/link.js 5 | type: application/javascript 6 | -------------------------------------------------------------------------------- /src/preview-glass/motivation.tid: -------------------------------------------------------------------------------- 1 | created: 20200413015135813 2 | modified: 20200530032358118 3 | title: $:/plugins/linonetwo/preview-glass/motivation 4 | type: text/vnd.tiddlywiki 5 | 6 | [[Preview|http://tobibeer.github.io/tw5-plugins/#preview]] 鼠标悬浮链接查看预览,只展示内部链接,因为外部链接可能也是个 TiddlyWiki 而非常硕大。 7 | 8 | 我在展示时使用了自己的模板,不展示具体内容,只展示 tag 和相关笔记,不然内容实在是太多了。真要看具体内容直接点击链接看不就好了。 9 | 10 | [[我还修改了原版的 JS|https://github.com/tobibeer/tw5-preview/issues/1]] ,从而让预览窗口在鼠标移开链接后就自动关闭,以免影响操作。 11 | 12 | ```js 13 | // Mouseout 14 | } else { 15 | // No more blocking of mouseover events 16 | block = 0; 17 | // No more waiting for the popup 18 | const popupID = Math.max(0, getInfo(el).popupLevel); 19 | clearTimeout(self.previewTimeout); 20 | // close popup 21 | $tw.popup.cancel(popupID); 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /src/preview-glass/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/plugins/linonetwo/preview-glass", 3 | "description": "Glassify Modification to the tobibeer/preview plugin, add inverse links, and make it auto-close", 4 | "author": "LinOnetwo", 5 | "version": "0.6.0", 6 | "core-version": ">=5.1.22", 7 | "list": "readme tree config motivation", 8 | "source": "https://github.com/tobibeer/tw5-preview", 9 | "documentation": "https://tobibeer.github.io/tw5-preview", 10 | "plugin-type": "plugin", 11 | "dependents": [ 12 | "$:/plugins/tobibeer/appear", 13 | "$:/plugins/ooktech/dynamic-tables", 14 | "$:/plugins/linonetwo/inverse-link-and-folder" 15 | ], 16 | "plugin-priority": "1" 17 | } 18 | -------------------------------------------------------------------------------- /src/preview-glass/popups.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/preview-glass/popups 2 | tags: $:/tags/PageTemplate 3 | 4 | \define state(num) 5 | $:/temp/tobibeer/preview-$num$ 6 | \end 7 | 8 | \define classes(num) 9 | tc-popup appear appear-block appear-reveal tc-preview-tiddler tc-preview-tiddler-$num$ $(default-classes)$ 10 | \end 11 | 12 | \define level(num) 13 | <$reveal tag="div" type="popup" state=<> class=<>> 14 | <$tiddler tiddler={{$:/temp/tobibeer/preview-$num$-tiddler}}> 15 | <$transclude tiddler={{$:/plugins/linonetwo/preview-glass/defaults/template}} mode="block"/> 16 | 17 | 18 | \end 19 | 20 | <$vars default-classes={{$:/plugins/linonetwo/preview-glass/defaults/class}}> 21 | <$list filter="1 2 3 4 5 6 7 8 9"> 22 | <$macrocall $name="level" num={{!!title}}/> 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/preview-glass/preview-template.css: -------------------------------------------------------------------------------- 1 | .hover-popup-preview-container { 2 | backdrop-filter: blur(10px); 3 | background: rgba(255, 255, 255, 0.3) !important; 4 | transform: translateY(0px); 5 | } 6 | 7 | /** 8 | Try added a triangle to it, but it seems work not so good with the backdrop-filter glass effect 9 | */ 10 | 11 | /** 12 | .hover-popup-preview-container::before { 13 | content: ""; 14 | width: 0px; 15 | height: 0px; 16 | position: absolute; 17 | border-left: 10px solid transparent; 18 | border-right: 10px solid transparent; 19 | border-top: 10px solid transparent; 20 | border-bottom: 10px solid rgba(255, 255, 255, 0.5); 21 | right: 95%; 22 | top: -20.5px; 23 | } 24 | */ -------------------------------------------------------------------------------- /src/preview-glass/preview-template.css.meta: -------------------------------------------------------------------------------- 1 | created: 20200415090452849 2 | modified: 20200530033507747 3 | tags: $:/tags/Stylesheet 4 | title: $:/plugins/linonetwo/preview-glass/preview-template.css 5 | type: text/css 6 | -------------------------------------------------------------------------------- /src/preview-glass/readme.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/preview-glass/readme 2 | created: 20200414135748497 3 | modified: 20200602062349232 4 | type: text/vnd.tiddlywiki 5 | 6 | !! About 7 | 8 | Modification to the [[tobibeer/preview plugin|https://tobibeer.github.io/tw5-plugins/#preview]], make it auto close if mouse move out of the link (as discussed in the [[issue#1|https://github.com/tobibeer/tw5-preview/issues/1]]), and add custom style, make it like a glass. 9 | 10 | !! Prerequisit 11 | 12 | This plugin has three dependencies: 13 | 14 | # [[tobibeer/appear|http://tobibeer.github.io/tw5-plugins/#appear]] to make popup work 15 | # [[$:/plugins/ooktech/dynamic-tables]] to make fields table in the popup template 16 | # [[$:/plugins/linonetwo/inverse-link-and-folder]] to make bi-directional links in the popup template 17 | 18 | !! This Plugin is a Forked version 19 | 20 | Original source is located in [[https://github.com/tobibeer/tw5-preview]], which has version 0.5.6 at several years ago, so maybe this plugin can be 0.5.7? 21 | 22 | See [[document of tobibeer/preview|https://tobibeer.github.io/tw5-plugins/#preview]] to get more usage and explaination. 23 | 24 | This plugin provides some new template, which depends on some other plugin to work, see plugin.info for detail. 25 | 26 | - [[$:/plugins/linonetwo/preview-glass/preview-template.css]] new styles 27 | - [[$:/plugins/linonetwo/preview-glass/template]] new template 28 | 29 | And some overrides: 30 | 31 | - [[$:/plugins/tobibeer/preview/link.js]] is override by this plugin, by providing a new js with same title 32 | - [[$:/plugins/tobibeer/preview/defaults/not]] set some link to not have pop up. 33 | - [[$:/plugins/tobibeer/preview/defaults/class]] and [[$:/plugins/tobibeer/preview/defaults/template]] override the template and style settings 34 | - [[$:/plugins/tobibeer/preview/defaults/delay]] change the popup delay 35 | -------------------------------------------------------------------------------- /src/preview-glass/template.tid: -------------------------------------------------------------------------------- 1 | created: 20200413014112868 2 | modified: 20200415101145651 3 | title: $:/plugins/linonetwo/preview-glass/template 4 | type: text/vnd.tiddlywiki 5 | 6 | {{||$:/plugins/linonetwo/inverse-link-and-folder/infobar}} 7 | 8 | <]" "modified created">> -------------------------------------------------------------------------------- /src/preview-glass/tree.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/preview-glass/tree 2 | type: text/vnd.tiddlywiki 3 | 4 | <> -------------------------------------------------------------------------------- /src/source-control-management/SideBarSCMTab.tid: -------------------------------------------------------------------------------- 1 | tags: $:/tags/SideBar 2 | title: $:/plugins/linonetwo/source-control-management/SideBarSCMTab 3 | type: text/vnd.tiddlywiki 4 | caption: SCM 5 | description: Source Control Management 6 | 7 | <$git-sync-scm-tab /> 8 | -------------------------------------------------------------------------------- /src/source-control-management/git-pull-request.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/source-control-management/git-pull-request.svg.meta: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/source-control-management/icons/git-pull-request.svg 2 | type: text/vnd.tiddlywiki -------------------------------------------------------------------------------- /src/source-control-management/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/plugins/linonetwo/source-control-management", 3 | "name": "Source Control Management (git) for TidGi Desktop", 4 | "description": "Use TidGi's NodeJS API to sync data to git on the cloud", 5 | "author": "LinOnetwo", 6 | "core-version": ">=5.1.22", 7 | "plugin-type": "plugin", 8 | "version": "0.3.0", 9 | "stability": "STABILITY_1_EXPERIMENTAL", 10 | "list": "readme tree" 11 | } -------------------------------------------------------------------------------- /src/source-control-management/readme.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/source-control-management/readme 2 | type: text/vnd.tiddlywiki 3 | 4 | !! 功能 5 | 6 | [[WebCatalog|https://webcatalogapp.com/]] 除了[[能将 TiddlyWiki 包装成桌面应用|https://onetwo.ren/%E7%94%A8tiddlywiki%E6%9B%BF%E4%BB%A3notion%E5%92%8Cevernote%E7%AE%A1%E7%90%86%E7%9F%A5%E8%AF%86/]]以外,还提供了自定义 API 并暴露给网页的功能,让我们可以在 Wiki 网页里使用一些高级功能。 7 | 8 | 本插件利用暴露的自定义 API 实现: 9 | 10 | # 查看本地 NodeJS 版 TiddlyWiki 是否完全与 Github 备份云同步了 11 | # 一键同步本地和云端 12 | 13 | !! 用法 14 | 15 | 当点开 SCM 标签页的时候,会进行一次 git 环境检查,因为使用的 git 库 dugite 比较卡,所以只进行一次检查,如果需要刷新,需要来回切换一下 tab。 16 | -------------------------------------------------------------------------------- /src/source-control-management/style.css: -------------------------------------------------------------------------------- 1 | span.tidgi-scm-count { 2 | position: relative; 3 | background: dimgrey; 4 | color: white; 5 | border-radius: 9999px; 6 | opacity: 0.5; 7 | min-width: 1.2em; 8 | margin-left: 0.5em; 9 | padding-left: 0.5em; 10 | padding-top: 0.1em; 11 | padding-right: 0.5em; 12 | width: fit-content; 13 | } 14 | span.tidgi-scm-count-small { 15 | font-size: 0.6em; 16 | padding-left: 0.2em; 17 | padding-right: 0.2em; 18 | line-height: 1.3em; 19 | margin-left: -1em; 20 | } 21 | 22 | div.tidgi-scm-file-info { 23 | margin-bottom: 5px; 24 | } 25 | span.tidgi-scm-file-changed-type { 26 | margin-right: 5px; 27 | } 28 | a.tidgi-scm-file-name { 29 | color: #333; 30 | cursor: pointer; 31 | } 32 | a.tidgi-scm-file-open-in-folder { 33 | color: #333; 34 | cursor: pointer; 35 | padding: 0; 36 | } 37 | a.tidgi-scm-file-open-in-folder > svg { 38 | padding: 0; 39 | height: 1em; 40 | } 41 | -------------------------------------------------------------------------------- /src/source-control-management/tab.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/strict-boolean-expressions */ 2 | import { widget as Widget } from '$:/core/modules/widgets/widget.js'; 3 | import { IParseTreeNode, IWidgetInitialiseOptions } from 'tiddlywiki'; 4 | import './style.css'; 5 | 6 | if ($tw.browser) { 7 | class NodeJSGitSyncSCMTabWidget extends Widget { 8 | state: { 9 | count: number; 10 | needSetUp: boolean; 11 | repoInfo: Record< 12 | string, 13 | Array<{ 14 | filePath: string; 15 | fileRelativePath: string; 16 | type: string; 17 | }> 18 | >; 19 | unsync: boolean; 20 | } = { 21 | /** 22 | * need to setup api, or just API missing 23 | */ 24 | needSetUp: false, 25 | 26 | /** 27 | * { 28 | * [folderName: string]: { 29 | * type: string, 30 | * fileRelativePath: string, 31 | * filePath: string, 32 | * }[] 33 | * } 34 | */ 35 | repoInfo: {}, 36 | /** 37 | * things need to commit 38 | */ 39 | count: 0, 40 | /** 41 | * need to push to github 42 | */ 43 | unsync: false, 44 | }; 45 | 46 | checkLoopTimeout: NodeJS.Timeout | undefined; 47 | 48 | /** 49 | * Lifecycle method: call this.initialise and super 50 | */ 51 | constructor(parseTreeNode: IParseTreeNode, options?: IWidgetInitialiseOptions) { 52 | super(parseTreeNode, options); 53 | this.initialise(parseTreeNode, options); 54 | void this.checkInLoop(); 55 | } 56 | 57 | async getWorkspaces() { 58 | const workspaces = await window?.service?.workspace?.getWorkspacesAsList?.(); 59 | const activeWorkspace = await window?.service?.workspace?.getActiveWorkspace?.(); 60 | if (activeWorkspace && workspaces) { 61 | return workspaces.filter((workspace) => workspace.id === activeWorkspace.id || (workspace.isSubWiki && workspace.mainWikiID === activeWorkspace.id)); 62 | } 63 | return []; 64 | } 65 | 66 | /** 67 | * Lifecycle method: Render this widget into the DOM 68 | */ 69 | render(parent: Element, nextSibling: Element | null) { 70 | // boilerplate 71 | this.parentDomNode = parent; 72 | this.computeAttributes(); 73 | 74 | // DOM 75 | const container = this.document.createElement('div'); 76 | container.className = ''; 77 | 78 | // workspaces 79 | for (const workspaceFullPath of Object.keys(this.state.repoInfo).sort((a, b) => a.length - b.length)) { 80 | /** 81 | * changed files 82 | * ```jsonl 83 | * {type: 'M', fileRelativePath: 'tiddlers/$__palette.tid', filePath: "C:\Users\linonetwo\Documents\repo-c\TidGi-Desktop\wiki-dev\wiki\tiddlers\$__language.tid"} 84 | {type: '??', fileRelativePath: 'tiddlers/$__plugins_Gk0Wk_CPL-Repo_config_popup-readme-at-startup.tid', filePath: 'C:\Users\linonetwo\Documents\repo-c\TidGi-Desktop\wiki-dev\wiki\tiddlers\$__plugins_Gk0Wk_CPL-Repo_config_popup-readme-at-startup.tid'} 85 | ``` 86 | */ 87 | const changedFileInfoList = this.state.repoInfo[workspaceFullPath]; 88 | 89 | const workspaceInfoContainer = this.document.createElement('div'); 90 | const workspaceTitle = this.document.createElement('h4'); 91 | const workspaceTitleChangedCount = this.document.createElement('span'); 92 | workspaceTitleChangedCount.className = 'tidgi-scm-count'; 93 | workspaceTitleChangedCount.innerText = String(changedFileInfoList.length); 94 | 95 | const workspaceName = workspaceFullPath.split('/').pop(); 96 | workspaceTitle.innerText = workspaceName ?? '-'; 97 | workspaceTitle.append(workspaceTitleChangedCount); 98 | workspaceInfoContainer.append(workspaceTitle); 99 | 100 | for (const changedFileInfo of changedFileInfoList) { 101 | const fileInfoContainer = this.document.createElement('div'); 102 | fileInfoContainer.className = 'tidgi-scm-file-info'; 103 | const fileChangedTypeElement = this.document.createElement('span'); 104 | fileChangedTypeElement.className = 'tidgi-scm-file-changed-type'; 105 | fileChangedTypeElement.innerText = this.mapChangeTypeToText(changedFileInfo.type); 106 | 107 | const fileNameElement = this.document.createElement('a'); 108 | fileNameElement.className = 'tidgi-scm-file-name tc-tiddlylink tc-tiddlylink-resolves tc-popup-handle tc-popup-absolute'; 109 | const tiddlerTitle = this.getTitleByPath(changedFileInfo.fileRelativePath); 110 | fileNameElement.innerText = tiddlerTitle; 111 | fileNameElement.addEventListener('click', () => { 112 | this.onChangedFileNameClicked(tiddlerTitle); 113 | }); 114 | const fileOpenInFolderElement = this.document.createElement('a'); 115 | fileOpenInFolderElement.className = 'tidgi-scm-file-open-in-folder tc-tiddlylink tc-tiddlylink-resolves tc-popup-handle tc-popup-absolute'; 116 | const openInFolderIcon = $tw.wiki.getTiddlerText('$:/plugins/linonetwo/open-in-external-app/icons/open-in-folder') ?? 'O'; 117 | fileOpenInFolderElement.innerHTML = openInFolderIcon; 118 | fileOpenInFolderElement.addEventListener('click', () => { 119 | this.onOpenInFolderClicked(changedFileInfo.filePath); 120 | }); 121 | 122 | fileInfoContainer.append(fileChangedTypeElement); 123 | fileInfoContainer.append(fileNameElement); 124 | fileInfoContainer.append(fileOpenInFolderElement); 125 | workspaceInfoContainer.append(fileInfoContainer); 126 | } 127 | 128 | container.append(workspaceInfoContainer); 129 | } 130 | 131 | parent.insertBefore(container, nextSibling); 132 | this.domNodes.push(container); 133 | } 134 | 135 | onChangedFileNameClicked(title: string): void { 136 | const workspaceID = window.meta?.()?.workspaceID; 137 | if (workspaceID) { 138 | void window?.service?.wiki?.wikiOperationInBrowser?.('wiki-open-tiddler', workspaceID, [title]); 139 | } 140 | } 141 | 142 | onOpenInFolderClicked(filePath: string): void { 143 | void window?.service?.native?.openPath?.(filePath, true); 144 | } 145 | 146 | getTitleByPath(fileRelativePath: string) { 147 | // TODO: use tiddlywiki's API to get title by path, to handle sub wiki case 148 | if (fileRelativePath.startsWith('plugins')) { 149 | return `$:/${fileRelativePath}`; 150 | } else if (fileRelativePath.startsWith('tiddlers/')) { 151 | return fileRelativePath.replace('tiddlers/', '').replace(/\.tid$/, ''); 152 | } else if (fileRelativePath.endsWith('.tid')) { 153 | return fileRelativePath.replace(/\.tid$/, ''); 154 | } 155 | return fileRelativePath; 156 | } 157 | 158 | async getFolderInfo() { 159 | const workspaces = await this.getWorkspaces(); 160 | return workspaces.map(({ wikiFolderLocation: wikiPath, gitUrl }) => ({ wikiPath, gitUrl })); 161 | } 162 | 163 | mapChangeTypeToText(changedType: string): string { 164 | switch (changedType) { 165 | case '??': { 166 | return '+'; 167 | } 168 | 169 | default: { 170 | return changedType; 171 | } 172 | } 173 | } 174 | 175 | /** 176 | * Check state every a few time 177 | */ 178 | async checkInLoop() { 179 | // check if API from TidGi is available, first time it is Server Side Rendening so window.xxx from the electron ContextBridge will be missing 180 | if ( 181 | !(window?.service?.git) || 182 | typeof window?.service?.git?.commitAndSync !== 'function' || 183 | typeof window?.service?.git?.getModifiedFileList !== 'function' || 184 | typeof window?.service?.workspace?.getWorkspacesAsList !== 'function' 185 | ) { 186 | this.state.needSetUp = true; 187 | } else { 188 | this.state.needSetUp = false; 189 | await this.checkGitState(); 190 | } 191 | // TODO: tab's parent won't connect to dom tree when render is called, make destroy logic difficult to implement 192 | /** 193 | * ``` 194 | * container tab
​ 195 | initialized tab 196 | this.state.initialized, connected true false 197 | destroy tab 198 | this.state.initialized, connected false true 199 | */ 200 | } 201 | 202 | /** 203 | * Check repo git sync state and count of uncommit things 204 | */ 205 | async checkGitState() { 206 | this.state.count = 0; 207 | this.state.unsync = false; 208 | this.state.repoInfo = {}; 209 | 210 | const folderInfo = await this.getFolderInfo(); 211 | const tasks = folderInfo.map(async ({ wikiPath }) => { 212 | const modifiedList = await window?.service?.git?.getModifiedFileList?.(wikiPath); 213 | if (!modifiedList) return; 214 | modifiedList.sort((changedFileInfoA, changedFileInfoB) => changedFileInfoA.fileRelativePath > changedFileInfoB.fileRelativePath ? 1 : -1); 215 | $tw.wiki.addTiddler({ 216 | title: `$:/state/scm-modified-file-list/${wikiPath}`, 217 | text: JSON.stringify(modifiedList), 218 | }); 219 | this.state.repoInfo[wikiPath] = modifiedList; 220 | }); 221 | await Promise.all(tasks); 222 | 223 | return this.refreshSelf(); // method from super class, this is like React forceUpdate, we use it because it is not fully reactive on this.state change 224 | } 225 | } 226 | 227 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 228 | exports['git-sync-scm-tab'] = NodeJSGitSyncSCMTabWidget; 229 | } 230 | -------------------------------------------------------------------------------- /src/source-control-management/tab.ts.meta: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/source-control-management/tab.js 2 | type: application/javascript 3 | module-type: widget 4 | -------------------------------------------------------------------------------- /src/source-control-management/tree.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/linonetwo/source-control-management/tree 2 | type: text/vnd.tiddlywiki 3 | 4 | <> -------------------------------------------------------------------------------- /src/type.ts: -------------------------------------------------------------------------------- 1 | import type { ModifiedFileList } from 'git-sync-js'; 2 | 3 | declare global { 4 | interface Window { 5 | // methods copy from TidGi-Desktop, should update if it changes 6 | meta: () => IBrowserViewMetaData; 7 | service: { 8 | auth: { 9 | getStorageServiceUserInfo(serviceName: SupportedStorageServices): Promise; 10 | }; 11 | git: { 12 | commitAndSync(workspace: IWorkspace, configs: ICommitAndSyncConfigs): Promise; 13 | getModifiedFileList(wikiFolderPath: string): Promise; 14 | }; 15 | native: { 16 | openPath(filePath: string, showItemInFolder?: boolean): Promise; 17 | }; 18 | sync: { 19 | syncWikiIfNeeded(workspace: IWorkspace): Promise; 20 | }; 21 | wiki: { 22 | getTiddlerFilePath(title: string, workspaceID?: string): Promise; 23 | wikiOperationInBrowser( 24 | operationType: OP, 25 | workspaceID: string, 26 | arguments_: Parameters, 27 | ): Promise>; 28 | }; 29 | workspace: { 30 | get(workspaceID: string): Promise< 31 | { 32 | wikiFolderLocation: string; 33 | } | undefined 34 | >; 35 | getActiveWorkspace: () => Promise; 36 | getWorkspacesAsList(): Promise; 37 | }; 38 | }; 39 | } 40 | } 41 | 42 | export interface IBrowserViewMetaData { 43 | isPopup?: boolean; 44 | workspaceID?: string; 45 | } 46 | 47 | interface ISendWikiOperationsToBrowser { 48 | readonly 'wiki-open-tiddler': (tiddlerName: string) => void; 49 | } 50 | 51 | export interface ICommitAndSyncConfigs { 52 | commitOnly?: boolean; 53 | remoteUrl?: string; 54 | userInfo?: IGitUserInfos; 55 | } 56 | export interface IGitUserInfos extends IGitUserInfosWithoutToken { 57 | /** Github Login: token */ 58 | accessToken: string; 59 | } 60 | 61 | export interface IGitUserInfosWithoutToken { 62 | branch: string; 63 | /** Git commit message email */ 64 | email: string | null | undefined; 65 | /** Github Login: username , this is also used to filter user's repo when searching repo */ 66 | gitUserName: string; 67 | } 68 | 69 | export interface IWorkspace { 70 | /** 71 | * Is this workspace selected by user, and showing corresponding webview? 72 | */ 73 | active: boolean; 74 | authToken?: string; 75 | /** 76 | * When this workspace is a local workspace, we can still use local git to backup 77 | */ 78 | backupOnInterval: boolean; 79 | disableAudio: boolean; 80 | disableNotifications: boolean; 81 | enableHTTPAPI: boolean; 82 | /** 83 | * List of plugins excluded on startup, for example `['$:/plugins/bimlas/kin-filter', '$:/plugins/dullroar/sitemap']` 84 | */ 85 | excludedPlugins: string[]; 86 | /** 87 | * The online repo to back data up to 88 | */ 89 | gitUrl: string | null; 90 | /** 91 | * Hibernate workspace on startup and when switch to another workspace. 92 | */ 93 | hibernateWhenUnused: boolean; 94 | /** 95 | * Is this workspace hibernated. You can hibernate workspace manually, without setting its hibernateWhenUnused. So we record this field in workspace. 96 | */ 97 | hibernated: boolean; 98 | /** 99 | * Localhost server url to load in the electron webview 100 | */ 101 | homeUrl: string; 102 | /** 103 | * Mostly used for deploying blog. Need tls-key and tls-cert. 104 | */ 105 | https?: { 106 | enabled: boolean; 107 | tlsCert?: string; 108 | tlsKey?: string; 109 | }; 110 | id: string; 111 | /** 112 | * Is this workspace a subwiki that link to a main wiki, and doesn't have its own webview? 113 | */ 114 | isSubWiki: boolean; 115 | /** 116 | * Nodejs start argument cli, used to start tiddlywiki server in terminal 117 | */ 118 | lastNodeJSArgv?: string[]; 119 | /** 120 | * Last visited url, used for rememberLastPageVisited in preferences 121 | */ 122 | lastUrl: string | null; 123 | /** 124 | * ID of main wiki of the sub-wiki. Only useful when isSubWiki === true 125 | */ 126 | mainWikiID: string | null; 127 | /** 128 | * Absolute path of main wiki of the sub-wiki. Only useful when isSubWiki === true , this is the wiki repo that this subwiki's folder soft links to 129 | */ 130 | mainWikiToLink: string | null; 131 | /** 132 | * Display name for this wiki workspace 133 | */ 134 | name: string; 135 | /** 136 | * You can drag workspaces to reorder them 137 | */ 138 | order: number; 139 | /** 140 | * workspace icon's path in file system 141 | */ 142 | picturePath: string | null; 143 | /** 144 | * Localhost tiddlywiki server port 145 | */ 146 | port: number; 147 | /** 148 | * Make wiki readonly if readonly is true. This is normally used for server mode, so also enable gzip. 149 | * 150 | * The principle is to configure anonymous reads, but writes require a login, and then give an unguessable username and password to. 151 | * 152 | * @url https://wiki.zhiheng.io/static/TiddlyWiki%253A%2520Readonly%2520for%2520Node.js%2520Server.html 153 | */ 154 | readOnlyMode: boolean; 155 | /** 156 | * The root tiddler for wiki. When missing, may use `$:/core/save/lazy-images` 157 | * @url https://tiddlywiki.com/#LazyLoading 158 | */ 159 | rootTiddler?: string; 160 | /** 161 | * Storage service this workspace sync to 162 | */ 163 | storageService: SupportedStorageServices; 164 | /** 165 | * We basically place sub-wiki in main wiki's `tiddlers/subwiki/` folder, but the `subwiki` part can be configured. Default is `subwiki` 166 | */ 167 | subWikiFolderName: string; 168 | /** 169 | * Sync wiki every interval. 170 | * If this is false (false by default to save the CPU usage from chokidar watch), then sync will only happen if user manually trigger by click sync button in the wiki, or sync at the app open. 171 | */ 172 | syncOnInterval: boolean; 173 | /** 174 | * Commit and Sync when App starts. 175 | */ 176 | syncOnStartup: boolean; 177 | /** 178 | * Tag name in tiddlywiki's filesystemPath, tiddler with this tag will be save into this subwiki 179 | */ 180 | tagName: string | null; 181 | /** 182 | * Use authenticated-user-header to provide `TIDGI_AUTH_TOKEN_HEADER` as header key to receive a value as username (we use it as token) 183 | */ 184 | tokenAuth: boolean; 185 | transparentBackground: boolean; 186 | userName: string; 187 | /** 188 | * folder path for this wiki workspace 189 | */ 190 | wikiFolderLocation: string; 191 | } 192 | export enum SupportedStorageServices { 193 | /** China's Collaboration platform for software development & code hosting, 194 | * with some official background, very secure in China, but have 500M storage limit */ 195 | gitee = 'gitee', 196 | /** High availability git service without storage limit, but is blocked by GFW in China somehow */ 197 | github = 'github', 198 | /** Open source git service */ 199 | gitlab = 'gitlab', 200 | local = 'local', 201 | /** SocialLinkedData, a privacy first DApp platform leading by Tim Berners-Lee, you can run a server by you own */ 202 | solid = 'solid', 203 | } 204 | 205 | export {}; 206 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ['./src/**/*.{mjs,cjs,js,ts,jsx,tsx}'], 3 | theme: { extend: {} }, 4 | plugins: [], 5 | }; 6 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true 5 | }, 6 | "include": [ 7 | "src/**/*.ts", 8 | "src/**/*.js", 9 | "src/**/*.tsx", 10 | "src/**/*.jsx", 11 | "public/**/*.ts", 12 | "public/**/*.js", 13 | "features/**/*.ts", 14 | "scripts/**/*.ts", 15 | "scripts/**/*.mjs", 16 | "src/**/*.d.ts", 17 | "public/**/*.d.ts", 18 | "./*.json", 19 | "./*.js", 20 | "./*.*.js" 21 | ], 22 | "exclude": ["wiki"] 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@modern-js/tsconfig/base.json", 3 | "compilerOptions": { 4 | "declaration": false, 5 | "jsx": "react-jsx", 6 | "baseUrl": "./", 7 | "typeRoots" : ["node_modules/@types", "node_modules/tw5-typed"], 8 | "lib": ["DOM", "ESNext"] 9 | }, 10 | "include": ["src"], 11 | "exclude": ["./**/*.js"] 12 | } 13 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__DefaultTiddlers.tid: -------------------------------------------------------------------------------- 1 | created: 20220426153828911 2 | modified: 20221228055915176 3 | title: $:/DefaultTiddlers 4 | type: text/vnd.tiddlywiki 5 | 6 | [list[$:/StoryList]] $:/plugins/Modern.TiddlyDev/doc 7 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__Modern.TiddlyDev_Startup.tid: -------------------------------------------------------------------------------- 1 | tags: $:/tags/StartupAction/Browser 2 | title: $:/Modern.TiddlyDev/Startup 3 | type: text/vnd.tiddlywiki 4 | 5 | 6 | <$action-setfield $tiddler="$:/language" text={{{ [{$:/info/browser/language}search:title[zh]then[zh-Hans]else[en-GB]addprefix[$:/languages/]] }}}/> 7 | 8 | 9 | <$reveal type="lt" state="$:/info/browser/screen/width" text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]] }}}><$action-setfield $tiddler="$:/state/sidebar" $value="no"/> 10 | <$reveal type="gteq" state="$:/info/browser/screen/width" text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]] }}}><$action-setfield $tiddler="$:/state/sidebar" $value="yes"/> 11 | 12 | 13 | <$action-setfield $tiddler="$:/palette" $value={{{ [{$:/info/darkmode}match[yes]then[$:/palettes/CupertinoDark]else[$:/palettes/Vanilla]] }}}/> 14 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__SiteSubtitle.tid: -------------------------------------------------------------------------------- 1 | title: $:/SiteSubtitle 2 | type: text/vnd.tiddlywiki 3 | 4 | <$list filter="[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]" variable="lang"><$list filter="[search[zh]]">现代太微插件开发框架<$list filter="[!search[zh]]">Modern ~TiddlyWiki plugin developing framework 5 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__SiteTitle.tid: -------------------------------------------------------------------------------- 1 | title: $:/SiteTitle 2 | type: text/vnd.tiddlywiki 3 | 4 | <$text text="Modern.TiddlyDev" /> 5 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiddly-gittly/tiddlywiki-plugins/d3b84f229ceb4b849ec79fc473c6bba4ec8830dd/wiki/tiddlers/$__favicon.ico -------------------------------------------------------------------------------- /wiki/tiddlers/$__favicon.ico.meta: -------------------------------------------------------------------------------- 1 | title: $:/favicon.ico 2 | type: image/x-icon 3 | -------------------------------------------------------------------------------- /wiki/tiddlers/$__palette.tid: -------------------------------------------------------------------------------- 1 | created: 20230112140506224 2 | modified: 20230112141220248 3 | title: $:/palette 4 | type: text/vnd.tiddlywiki 5 | 6 | $:/palettes/Blanca -------------------------------------------------------------------------------- /wiki/tiddlers/$__plugins_Gk0Wk_CPL-Repo.json: -------------------------------------------------------------------------------- 1 | {"tiddlers":{"$:/config/TiddlyWiki-CPL/GitHub":{"title":"$:/config/TiddlyWiki-CPL/GitHub","caption":"<$list filter=\"[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]\" variable=\"lang\"><$list filter=\"[search:title[zh]]\">太微中文社区插件源(~GitHub版)<$list filter=\"[!search:title[zh]]\">TiddlyWiki CPL(~GitHub Host)","tags":["$:/tags/PluginLibrary","$:/tags/PluginLibrary/CPL"],"type":"text/vnd.tiddlywiki","url":"https://tiddly-gittly.github.io/TiddlyWiki-CPL/library/index.html","text":"\n<$list filter=\"[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]\" variable=\"lang\">\n<$list filter=\"[search:title[zh]]\" variable=\"lang\">\n\n欢迎使用''【太微中文社区插件源】''!\n\n本插件源是由[[太微(TiddlyWiki)中文社区|https://github.com/tiddly-gittly]]维护的、致力于搜集网络上所有与 ~TiddlyWiki5 有关插件的、希望为中国以及全世界的太微用户提供一键安装、更新插件体验的公开插件源。\n\n如果还不了解该如何使用太微和本插件源,欢迎阅读[[中文社区共建的太微(TiddlyWiki)教程|https://tw-cn.netlify.app]]里插件相关的部分。如上提到的插件源和教程皆为开源项目,你可以在 [[GitHub|https://github.com/tiddly-gittly]] 中找到并参与贡献!如果乐意,可以通过QQ群等方式加入我们,详情请见如上提到的中文教程。\n\n要添加这个插件库到你的 Wiki 中,只需鼠标拖动这个链接到你的 Wiki 里即可:<$link to=<>>{{!!caption}}\n\n注意:本插件源版本为 ~GitHub Page 的版本,更新更快,但是可能需要科学上网手段。如果你在国内,而且不清楚什么是“科学上网”,请选用另一个经过 netlify.app 加速的[[版本|$:/config/TiddlyWiki-CPL/Netlify]],虽然更新有一定的延迟,但对国内用户更加友好。\n\n@@color:red;''安装任何插件前,请记得备份你的Wiki,本插件源无法为插件造成的个人损失负责!''@@\n\n\n\n<$list filter=\"[!search:title[zh]]\" variable=\"lang\">\n\nWelcome to the ''[TiddlyWiki Chinese Community Plugin Source]''!\n\nThis plugin source is maintained by the [[TiddlyWiki Chinese Community]] and is dedicated to collecting all TiddlyWiki5 related plugins on the web, hoping to provide a one-click installation and update plugin experience for TiddlyWiki users in China and around the world.\n\nIf you don't know how to use TiddlyWiki and this source, you are welcome to read the plugins related section in the [[TiddlyWiki Tutorials for Chinese Communities|https://tw-cn.netlify.app]]. As mentioned above, both the plugin source and the tutorial are open source projects, you can find them in [[GitHub|https://github.com/tiddly-gittly]] and participate in contributing! If you like, you can join us through QQ groups and other means, see the Chinese tutorials mentioned above for details.\n\nTo add this plugin library to your Wiki, just drag this link with your mouse into your Wiki: <$link to=<>>{{!!caption}}\n\nNote: The source version of this plugin is the ~GitHub Page version, which is faster to update, but may require scientific Internet access. If you are in China and are not sure what GFW is, please use another [[version|$:/config/TiddlyWiki-CPL/Netlify]] that is accelerated by netlify.app, although there is a certain delay in updating, but it is more friendly to domestic users more friendly.\n\n@@color:red;''Please remember to back up your Wiki before installing any plugins, this plugin source cannot be held responsible for personal losses caused by plugins!''@@\n\n\n\n"},"$:/config/TiddlyWiki-CPL/Netlify":{"title":"$:/config/TiddlyWiki-CPL/Netlify","caption":"<$list filter=\"[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]\" variable=\"lang\"><$list filter=\"[search:title[zh]]\">太微中文社区插件源(大陆加速版)<$list filter=\"[!search:title[zh]]\">TiddlyWiki CPL(Netlify Host)","tags":["$:/tags/PluginLibrary","$:/tags/PluginLibrary/CPL"],"type":"text/vnd.tiddlywiki","url":"https://tw-cpl.netlify.app/library/index.html","text":"\n<$list filter=\"[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]\" variable=\"lang\">\n<$list filter=\"[search:title[zh]]\" variable=\"lang\">\n\n欢迎使用''【太微中文社区插件源】''!\n\n本插件源是由[[太微(TiddlyWiki)中文社区|https://github.com/tiddly-gittly]]维护的、致力于搜集网络上所有与 ~TiddlyWiki5 有关插件的、希望为中国以及全世界的太微用户提供一键安装、更新插件体验的公开插件源。\n\n如果还不了解该如何使用太微和本插件源,欢迎阅读[[中文社区共建的太微(TiddlyWiki)教程|https://tw-cn.netlify.app]]里插件相关的部分。如上提到的插件源和教程皆为开源项目,你可以在 [[GitHub|https://github.com/tiddly-gittly]] 中找到并参与贡献!如果乐意,可以通过QQ群等方式加入我们,详情请见如上提到的中文教程。\n\n要添加这个插件库到你的 Wiki 中,只需鼠标拖动这个链接到你的 Wiki 里即可:<$link to=<>>{{!!caption}}\n\n注意:本插件源版本为经过 netlify.app 加速的版本,对国内用户更加友好,但是更新有一定的延迟。还提供另一版本,是直接使用 ~GitHub Page 服务器的版本,更新更快,但是可能需要科学上网手段。\n\n@@color:red;''安装任何插件前,请记得备份你的Wiki,本插件源无法为插件造成的个人损失负责!''@@\n\n\n\n<$list filter=\"[!search:title[zh]]\" variable=\"lang\">\n\nWelcome to the ''[TiddlyWiki Chinese Community Plugin Source]''!\n\nThis plugin source is maintained by the [[TiddlyWiki Chinese Community]] and is dedicated to collecting all TiddlyWiki5 related plugins on the web, hoping to provide a one-click installation and update plugin experience for TiddlyWiki users in China and around the world.\n\nIf you don't know how to use TiddlyWiki and this source, you are welcome to read the plugins related section in the [[TiddlyWiki Tutorials for Chinese Communities|https://tw-cn.netlify.app]]. As mentioned above, both the plugin source and the tutorial are open source projects, you can find them in [[GitHub|https://github.com/tiddly-gittly]] and participate in contributing! If you like, you can join us through QQ groups and other means, see the Chinese tutorials mentioned above for details.\n\nTo add this plugin library to your Wiki, just drag this link with your mouse into your Wiki: <$link to=<>>{{!!caption}}\n\nNote: The source version of this plugin is a version accelerated by netlify.app, which is more friendly to China mainland users, but there is a delay in updating. There is also another version that uses the GitHub Page server directly, which is faster to update, but may require technology to overturn the GFW.\n\n@@color:red;''Please remember to back up your Wiki before installing any plugins, this plugin source cannot be held responsible for personal losses caused by plugins!''@@\n\n\n\n"}}} -------------------------------------------------------------------------------- /wiki/tiddlers/$__plugins_Gk0Wk_CPL-Repo.json.meta: -------------------------------------------------------------------------------- 1 | author: Gk0Wk 2 | description: Repos for CPL 3 | name: CPL Repo 4 | plugin-type: plugin 5 | title: $:/plugins/Gk0Wk/CPL-Repo 6 | type: application/json 7 | version: 2022.12.28 -------------------------------------------------------------------------------- /wiki/tiddlers/$__plugins_linonetwo_prevent-edit.json: -------------------------------------------------------------------------------- 1 | {"tiddlers":{"$:/plugins/linonetwo/prevent-edit/preventPopUp.js":{"title":"$:/plugins/linonetwo/prevent-edit/preventPopUp.js","created":"20200414150455988","creator":"LinOnetwo","module-type":"startup","type":"application/javascript","text":"exports.startup = function() {\n $tw.unloadTasks = $tw.unloadTasks.filter(task => !task.toString().includes('confirmationMessage'));\n}\n"},"$:/plugins/linonetwo/prevent-edit/readme":{"title":"$:/plugins/linonetwo/prevent-edit/readme","created":"20200414135748497","modified":"20200602062349232","type":"text/vnd.tiddlywiki","text":"!! 功能\n\n这个插件主要是让在线部署后的 Wiki 不会弹出「有变动关闭网页前请保存」这样的对话框。\n\n!! 动机\n\n来自 TiddlyMap 的 [[$:/plugins/felixhayashi/tiddlymap/misc/defaultViewHolder]] 和来自系统的 [[$:/StoryList]] 老是自动变:\n\n```diff\ncreated: 20200409022623558\ncreator: Lin Onetwo - 林一二\n-modified: 20200414104033109\n+modified: 20200414135126182\nmodifier: Lin Onetwo - 林一二\ntitle: $:/plugins/felixhayashi/tiddlymap/misc/defaultViewHolder\ntype: text/vnd.tiddlywiki\n```\n\n没有实质性的变化,而且又经常发生在 wiki 部署后,这样在线版 wiki 就会弹出「This page is asking you to confirm that you want to leave - data you have entered may not be saved」。\n\n但我只是想做浏览不想做编辑啊,这让我觉得很烦。\n\n后来发现原来是 onbeforeunload 导致的,[[我去仓库里搜到了|https://github.com/Jermolene/TiddlyWiki5/search?q=beforeunload&unscoped_q=beforeunload]]是 `$tw.utils.each($tw.unloadTasks` 在用它,所以我就过滤了一下 `$tw.unloadTasks`。而且还不能立即做这个过滤,因为 `$:/tags/RawMarkup` 是在沙盒里执行的,不能修改 `$tw` 。\n\n所以最终我跟着 [[Adding Babel Polyfill to TiddlyWiki|https://tiddlywiki.com/dev/#Adding%20Babel%20Polyfill%20to%20TiddlyWiki]] 这篇教程,加了一个 startup script,在启动时、上述代码之后,就清理掉那个导致弹窗的 unloadTask,世界终于清静了。\n\n最终,我把它包装成了这个 [[prevent-edit|$:/plugins/linonetwo/prevent-edit]] 插件。\n"}}} -------------------------------------------------------------------------------- /wiki/tiddlers/$__plugins_linonetwo_prevent-edit.json.meta: -------------------------------------------------------------------------------- 1 | author: LinOnetwo 2 | core-version: >=5.1.22 3 | created: 20211017092918218 4 | dependents: 5 | description: Prevent "This page is asking you to confirm that you want to leave" in a read-only site 6 | list: readme 7 | modified: 20211017092918218 8 | plugin-type: plugin 9 | title: $:/plugins/linonetwo/prevent-edit 10 | type: application/json 11 | version: 0.0.1 -------------------------------------------------------------------------------- /wiki/tiddlers/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid: -------------------------------------------------------------------------------- 1 | created: 20221205070222671 2 | modified: 20221205070222671 3 | title: $:/themes/tiddlywiki/vanilla/options/sidebarlayout 4 | type: text/vnd.tiddlywiki 5 | 6 | fluid-fixed -------------------------------------------------------------------------------- /wiki/tiddlers/LanguageSwitcher.tid: -------------------------------------------------------------------------------- 1 | created: 20211209040935294 2 | creator: Sttot 3 | list-after: $:/core/ui/ViewTemplate/tags 4 | modified: 20211214150730666 5 | modifier: Sttot 6 | tags: ExcludeFromEmpty $:/tags/ViewTemplate 7 | title: LanguageSwitcher 8 | type: text/vnd.tiddlywiki 9 | 10 | <$list filter="[[$:/language]get[text]removeprefix[$:/languages/]else[en-GB]]" variable="lang"> 11 | <$list filter="[search[zh]]"> 12 | <$button set="$:/language" setTo="$:/languages/en-GB" style="">🇬🇧 Switch to English 13 | 14 | <$list filter="[!search[zh]]"> 15 | <$button set="$:/language" setTo="$:/languages/zh-Hans" style="">🇨🇳 切换至中文 16 | 17 | -------------------------------------------------------------------------------- /wiki/tiddlers/tests/example/filters.js: -------------------------------------------------------------------------------- 1 | describe('Filter tests', function() { 2 | // Test copy from https://github.com/Jermolene/TiddlyWiki5/blob/31ec1bdd50ce7fa58e4e2c8701106bd809c47dc3/editions/test/tiddlers/tests/test-filters.js 3 | it('should parse new-style rich operator suffixes', function() { 4 | expect($tw.wiki.parseFilter('[search:: four, , five,, six [operand]]')).toEqual( 5 | [{ prefix: '', operators: [{ operator: 'search', suffix: ': four, , five,, six ', suffixes: [[], ['four', 'five', 'six']], operands: [{ text: 'operand' }] }] }], 6 | ); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /wiki/tiddlers/tests/example/filters.js.meta: -------------------------------------------------------------------------------- 1 | title: tests/example/test-filters.js 2 | type: application/javascript 3 | tags: $:/tags/test-spec -------------------------------------------------------------------------------- /wiki/tiddlywiki.info: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Basic client-server edition", 3 | "plugins": [ 4 | "tiddlywiki/filesystem", 5 | "tiddlywiki/tiddlyweb", 6 | "tiddlywiki/pluginlibrary", 7 | "tiddlywiki/highlight" 8 | ], 9 | "themes": [ 10 | "tiddlywiki/vanilla" 11 | ], 12 | "languages": [ 13 | "zh-Hans" 14 | ], 15 | "build": {} 16 | } 17 | --------------------------------------------------------------------------------