├── .nvmrc ├── src ├── plugins │ ├── index.d.ts │ ├── Gk0Wk │ │ ├── index.d.ts │ │ └── echarts │ │ │ └── index.d.ts │ └── tiddlywiki │ │ ├── index.d.ts │ │ └── codemirror │ │ └── index.d.ts ├── modules │ ├── utils │ │ ├── dom │ │ │ ├── index.d.ts │ │ │ ├── notifier.d.ts │ │ │ ├── modal.d.ts │ │ │ └── dom.d.ts │ │ ├── escapecss.d.ts │ │ ├── edition-info.d.ts │ │ ├── pluginmaker.d.ts │ │ ├── transliterate.d.ts │ │ ├── fakedom.d.ts │ │ ├── csv.d.ts │ │ ├── crypto.d.ts │ │ ├── performance.d.ts │ │ ├── index.d.ts │ │ ├── logger.d.ts │ │ ├── linked-list.d.ts │ │ ├── parsetree.d.ts │ │ ├── parseutils.d.ts │ │ ├── filesystem.d.ts │ │ └── utils.d.ts │ ├── widgets │ │ ├── edit.d.ts │ │ ├── navigator.d.ts │ │ └── index.d.ts │ ├── syncer │ │ ├── syncer.d.ts │ │ └── syncAdaptor.d.ts │ ├── story.d.ts │ ├── keyboard.d.ts │ ├── indexers │ │ └── index.d.ts │ ├── server │ │ └── index.d.ts │ ├── index.d.ts │ ├── parsers │ │ └── index.d.ts │ ├── filters │ │ └── index.d.ts │ └── wiki.d.ts ├── utils │ ├── Crypto.d.ts │ ├── PasswordPrompt.d.ts │ └── index.d.ts ├── index.d.ts ├── tiddler │ └── index.d.ts ├── hooks.d.ts └── boot │ ├── config.d.ts │ └── index.d.ts ├── .gitattributes ├── .npmrc ├── static ├── README.md ├── favicon.ico └── images │ └── Logo.png ├── pnpm-workspace.yaml ├── tsconfig.json ├── typedoc.json ├── .vscode └── settings.json ├── .npmignore ├── dprint.json ├── eslint.config.mjs ├── scripts └── copy-readme.mjs ├── .github └── workflows │ ├── check-docs.yml │ ├── test.yml │ └── deploy-docs-to-github-pages copy.yml ├── LICENSE ├── .gitignore ├── README.md ├── package.json ├── test └── tiddlywiki-test.ts └── docusaurus.config.ts /.nvmrc: -------------------------------------------------------------------------------- 1 | stable -------------------------------------------------------------------------------- /src/plugins/index.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /src/plugins/Gk0Wk/index.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/modules/utils/dom/index.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/plugins/tiddlywiki/index.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false 2 | public-hoist-pattern[]=*eslint* 3 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # Static 2 | 3 | Files used by doc site generated by `docusaurus.config.ts`. 4 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiddly-gittly/TW5-Typed/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /static/images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiddly-gittly/TW5-Typed/HEAD/static/images/Logo.png -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | onlyBuiltDependencies: 2 | - core-js 3 | - core-js-pure 4 | - dprint 5 | - unrs-resolver 6 | -------------------------------------------------------------------------------- /src/plugins/tiddlywiki/codemirror/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/plugins/tiddlywiki/codemirror/lib/codemirror.js' { 2 | import CodeMirror from 'codemirror'; 3 | export = CodeMirror; 4 | } 5 | -------------------------------------------------------------------------------- /src/plugins/Gk0Wk/echarts/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/plugins/Gk0Wk/echarts/echarts.min.js' { 2 | // eslint-disable-next-line import/no-unresolved 3 | import ECharts from 'echarts'; 4 | export = ECharts; 5 | } 6 | -------------------------------------------------------------------------------- /src/modules/utils/escapecss.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/escapecss.js' { 2 | /** 3 | * The onstalled event handler of the element 4 | * @returns The escaped string 5 | * @description 为在 CSS 选择器或标识符中使用而转义字符串 6 | */ 7 | export function escapeCSS(value: string): typeof window.CSS.escape; 8 | } 9 | -------------------------------------------------------------------------------- /src/modules/utils/edition-info.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/edition-info.js' { 2 | /** 3 | * Get the edition information. 4 | * @description 获取版本信息。 5 | * @returns An object containing the edition information. 6 | * @returns 包含版本信息的对象。 7 | */ 8 | export function getEditionInfo(): Record; 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/Crypto.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class Crypto { 3 | setPassword(newPassword: string): void; 4 | updateCryptoStateTiddler(): void; 5 | hasPassword(): boolean; 6 | encrypt(text: string, password: string): string | null; 7 | decrypt(text: string, password: string): string | null; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@modern-js/tsconfig/base.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "declaration": true, 6 | "jsx": "react-jsx", 7 | "baseUrl": "./", 8 | "lib": ["DOM", "ESNext"], 9 | "types": ["./src", "node"] 10 | }, 11 | "include": ["src", "test"], 12 | "exclude": ["./**/*.js"] 13 | } 14 | -------------------------------------------------------------------------------- /src/modules/utils/dom/notifier.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Notifier mechanism 3 | */ 4 | declare module 'tiddlywiki' { 5 | export interface Notifier { 6 | /** 7 | * Display a notification 8 | * * title: Title of tiddler containing the notification text 9 | * * options: see below 10 | * Options include: 11 | */ 12 | display(title: string, options?: Record): void; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["./src/*"], 4 | "exclude": ["./src/plugins"], 5 | "entryPointStrategy": "expand", 6 | "out": "docs/api", 7 | "compilerOptions": { 8 | "strictNullChecks": false, 9 | "skipLibCheck": true, 10 | "rootDir": ".", 11 | }, 12 | "readme": "none", 13 | "entryDocument": "API.md", 14 | "plugin": ["typedoc-plugin-markdown"] 15 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.format.enable": true, 3 | "[typescriptreact]": { 4 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 5 | }, 6 | "[javascript]": { 7 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 8 | }, 9 | "[jsonc]": { 10 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 11 | }, 12 | "[typescript]": { 13 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/widgets/edit.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class EditWidget extends Widget { 3 | editTitle: string; 4 | editField: string; 5 | editIndex: string; 6 | editClass: string; 7 | editPlaceholder: string; 8 | editTabIndex: string; 9 | editFocus: string; 10 | editCancelPopups: string; 11 | editInputActions: string; 12 | editRefreshTitle: string; 13 | editAutoComplete: string; 14 | editorType: string; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .pnp 4 | .pnp.js 5 | .env.local 6 | .env.*.local 7 | .history 8 | .rts* 9 | *.log* 10 | *.pid 11 | *.pid.* 12 | *.report 13 | *.lcov 14 | lib-cov 15 | 16 | node_modules/ 17 | .npm 18 | .lock-wscript 19 | .yarn-integrity 20 | .node_repl_history 21 | .nyc_output 22 | *.tsbuildinfo 23 | .eslintcache 24 | .sonarlint 25 | 26 | coverage/ 27 | release/ 28 | output/ 29 | output_resource/ 30 | tests/ 31 | 32 | .vscode/**/* 33 | !.vscode/settings.json 34 | !.vscode/extensions.json 35 | .idea/ 36 | 37 | **/*/api/typings/auto-generated 38 | -------------------------------------------------------------------------------- /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.95.13.wasm", 19 | "https://plugins.dprint.dev/json-0.21.0.wasm", 20 | "https://plugins.dprint.dev/markdown-0.20.0.wasm" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/utils/pluginmaker.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/pluginmaker.js' { 2 | /** 3 | * Repacks a plugin, and then deletes any non-shadow payload tiddlers. 4 | * @param title - The title of the plugin tiddler. 5 | * @param additionalTiddlers - An array of additional tiddlers to include in the plugin. 6 | * @param excludeTiddlers - An array of tiddlers to exclude from the plugin. 7 | * @returns A confirmation message. 8 | * @description 重新打包插件,然后删除任何非阴影有效负载 tiddlers。 9 | */ 10 | export function repackPlugin( 11 | title: string, 12 | additionalTiddlers?: string[], 13 | excludeTiddlers?: string[], 14 | ): string; 15 | } 16 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import tidgiConfig from 'eslint-config-tidgi'; 2 | import { dirname } from 'node:path'; 3 | import { fileURLToPath } from 'node:url'; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | export default [ 9 | ...tidgiConfig, 10 | { 11 | languageOptions: { 12 | parserOptions: { 13 | projectService: { 14 | allowDefaultProject: ['./*.js', './*.mjs'], 15 | }, 16 | tsconfigRootDir: __dirname, 17 | }, 18 | }, 19 | }, 20 | { 21 | files: ['src/index.d.ts'], 22 | rules: { 23 | '@typescript-eslint/triple-slash-reference': 'off', 24 | }, 25 | }, 26 | ]; 27 | -------------------------------------------------------------------------------- /src/modules/utils/dom/modal.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class Modal { 3 | constructor(wiki: Wiki); 4 | 5 | adjustPageClass: () => void; 6 | /** 7 | * @param title 8 | * @param options 9 | * variables: optional hashmap of variables to wrap around the widget 10 | * downloadLink: normally is used for "Right-click to save changes" 11 | */ 12 | display: ( 13 | title: string, 14 | options?: { 15 | downloadLink?: string; 16 | event?: IWidgetEvent; 17 | variables?: unknown; 18 | }, 19 | ) => void; 20 | } 21 | } 22 | 23 | declare module '$:/core/modules/utils/dom/modal.js' { 24 | export { Modal } from 'tiddlywiki'; 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/utils/transliterate.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/transliterate.js' { 2 | /** 3 | * An object containing pairs of characters to be transliterated. 4 | * @description 包含要转换的字符对的对象。 5 | */ 6 | export const transliterationPairs: Record; 7 | 8 | /** 9 | * Transliterates a string to ASCII. 10 | * @param str - The string to transliterate. 11 | * @returns The transliterated string. 12 | * @description 将字符串转换为 ASCII。 13 | */ 14 | export function transliterate(string_: string): string; 15 | 16 | /** 17 | * Transliterates a string to safe ASCII. 18 | * @param str - The string to transliterate. 19 | * @returns The transliterated string. 20 | * @description 将字符串转换为安全的 ASCII。 21 | */ 22 | export function transliterateToSafeASCII(string_: string): string; 23 | } 24 | -------------------------------------------------------------------------------- /scripts/copy-readme.mjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable security-node/detect-crlf */ 2 | import * as fs from 'fs'; 3 | 4 | const sourcePath = './README.md'; 5 | const destinationPath = './docs/README.md'; 6 | 7 | // Read the content of the source file 8 | fs.readFile(sourcePath, 'utf8', (err, data) => { 9 | if (err) { 10 | console.error('Error reading file:', err); 11 | return; 12 | } 13 | 14 | // Replace markdown links of the format '[text](./docs/xxx)' with '[text](xxx)' 15 | const updatedData = data.replaceAll(/]\(\.\/docs\/(.*?)\)/g, ']($1)'); 16 | 17 | // Write the updated content to the destination file 18 | fs.writeFile(destinationPath, updatedData, 'utf8', (err) => { 19 | if (err) { 20 | console.error('Error writing file:', err); 21 | return; 22 | } 23 | console.log(`File copied from ${sourcePath} to ${destinationPath} with internal links updated.`); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/modules/utils/fakedom.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class TW_Element extends HTMLElement { 3 | _style: Record; 4 | appendChild: (node: T) => T; 5 | isRaw: boolean; 6 | isTiddlyWikiFakeDom: boolean; 7 | namespaceURI: string; 8 | tag: string; 9 | } 10 | 11 | export class TW_TextNode extends Node { 12 | textContent: string; 13 | } 14 | 15 | export interface IFakeDocument { 16 | compatMode: string; 17 | createElement: (tag: string) => TW_Element; 18 | createElementNS: (namespace: string, tag: string) => TW_Element; 19 | createTextNode: (text: string) => TW_TextNode; 20 | isTiddlyWikiFakeDom: boolean; 21 | setSequenceNumber: (value: number) => void; 22 | } 23 | } 24 | 25 | declare module '$:/core/modules/utils/fakedom.js' { 26 | import type { IFakeDocument } from 'tiddlywiki'; 27 | export const fakeDocument: IFakeDocument; 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/check-docs.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Check Docs build 3 | 4 | on: 5 | # Only check if we can build the doc in PR 6 | pull_request: 7 | branches: 8 | - master 9 | 10 | env: 11 | # Hosted GitHub runners have 7 GB of memory available, let's use 6 GB 12 | NODE_OPTIONS: --max-old-space-size=6144 13 | 14 | jobs: 15 | # Single deploy job since we're just deploying 16 | check: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v3 21 | - uses: pnpm/action-setup@v2 22 | with: 23 | version: 8 24 | - name: Set up Node.js 25 | uses: actions/setup-node@v3 26 | with: 27 | node-version: 20.x 28 | cache: pnpm 29 | - name: Install dependencies 30 | run: pnpm i 31 | - name: Gen API Docs 32 | run: pnpm run docs:generate 33 | - name: Build Docs Site 34 | run: pnpm run docs:build -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test typing 2 | 3 | on: 4 | # Runs on pushes targeting the default branch 5 | push: 6 | branches: [master] 7 | paths-ignore: 8 | - 'docs/**' 9 | - 'README.md' 10 | - '.vscode' 11 | pull_request: 12 | branches: 13 | - master 14 | paths-ignore: 15 | - 'docs/**' 16 | - 'README.md' 17 | - '.vscode' 18 | # Allows you to run this workflow manually from the Actions tab 19 | workflow_dispatch: 20 | 21 | jobs: 22 | # Single deploy job since we're just deploying 23 | test: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | - uses: pnpm/action-setup@v2 29 | with: 30 | version: 8 31 | - name: Set up Node.js 32 | uses: actions/setup-node@v3 33 | with: 34 | node-version: 20.x 35 | cache: pnpm 36 | - name: Install dependencies 37 | run: pnpm i 38 | - name: Check TS and ESLint 39 | run: pnpm run check 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Tiddly Gittly 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 | -------------------------------------------------------------------------------- /src/modules/syncer/syncer.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class Syncer { 3 | pollTimerInterval: number; 4 | syncadaptor?: SyncAdaptor; 5 | /** 6 | Synchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date 7 | */ 8 | syncFromServer(): void; 9 | /** 10 | Process the next task 11 | */ 12 | processTaskQueue(): void; 13 | /** 14 | Update the document body with the class "tc-dirty" if the wiki has unsaved/unsynced changes 15 | */ 16 | updateDirtyStatus(): void; 17 | /** 18 | Checks whether the wiki is dirty (ie the window shouldn't be closed) 19 | */ 20 | isDirty(): boolean; 21 | /** 22 | * Return an array of the tiddler titles that are subjected to syncing 23 | */ 24 | getSyncedTiddlers(): string[]; 25 | /** 26 | * Get stringified revision number, for example, `'0'`. 27 | */ 28 | getTiddlerRevision(title: string): string; 29 | /** 30 | * Read (or re-read) the latest tiddler info from the store 31 | */ 32 | readTiddlerInfo(): void; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/modules/utils/csv.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/csv.js' { 2 | /** 3 | * Information about a CSV cell. 4 | * @property start - The start index of the cell in the CSV string. 5 | * @property end - The end index of the cell in the CSV string. 6 | * @property {boolean} isQuoted - Whether the cell is quoted. 7 | * @description CSV 单元格的信息。 8 | */ 9 | interface CellInfo { 10 | end: number; 11 | isQuoted: boolean; 12 | start: number; 13 | } 14 | 15 | /** 16 | * Parse a CSV string into an array of arrays. 17 | * @param text - The CSV string to parse. 18 | * @param options - The options for parsing the CSV string. 19 | * @returns An array of arrays representing the CSV data. 20 | * @description 将 CSV 字符串解析为数组的数组。 21 | */ 22 | export function parseCsvString( 23 | text: string, 24 | options?: { separator?: string }, 25 | ): unknown[][]; 26 | 27 | /** 28 | * Parse a CSV string with a header row and return an array of objects. 29 | * @param text - The CSV string to parse. 30 | * @param options - The options for parsing the CSV string. 31 | * @returns An array of objects representing the CSV data. 32 | * @description 解析具有标题行的 CSV 字符串并返回对象数组。 33 | */ 34 | export function parseCsvStringWithHeader( 35 | text: string, 36 | options?: { separator?: string }, 37 | ): object[]; 38 | } 39 | -------------------------------------------------------------------------------- /src/modules/story.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class Story { 3 | wiki: Wiki; 4 | storyTitle: string; 5 | historyTitle: string; 6 | 7 | constructor(options?: { 8 | historyTitle?: string; 9 | storyTitle?: string; 10 | wiki?: Wiki; 11 | }); 12 | 13 | getStoryList(): string[]; 14 | 15 | navigateTiddler( 16 | navigateTo: string, 17 | navigateFromTitle?: string, 18 | navigateFromClientRect?: DOMRect, 19 | ); 20 | 21 | addToStory( 22 | navigateTo: string, 23 | navigateFromTitle?: string, 24 | options?: { 25 | openLinkFromInsideRiver?: 'top' | 'bottom' | 'above' | 'below'; 26 | }, 27 | ); 28 | 29 | addToHistory( 30 | navigateTo: string | string[], 31 | navigateFromClientRect?: DOMRect, 32 | ); 33 | 34 | saveStoryList(storyList: string[] | string); 35 | 36 | storyCloseTiddler(targetTitle: string); 37 | 38 | storyCloseAllTiddlers(); 39 | 40 | storyCloseOtherTiddlers(targetTitle: string); 41 | 42 | storyEditTiddler(targetTitle: string); 43 | 44 | storyDeleteTiddler(targetTitle: string); 45 | 46 | storySaveTiddler(targetTitle: string); 47 | 48 | storyCancelTiddler(targetTitle: string); 49 | 50 | storyNewTiddler(targetTitle: string); 51 | } 52 | } 53 | 54 | declare module '$:/core/modules/story.js' { 55 | export { Story } from 'tiddlywiki'; 56 | } 57 | -------------------------------------------------------------------------------- /src/modules/utils/crypto.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/crypto.js' { 2 | /** 3 | * Extracts an encrypted store area from a TiddlyWiki file. 4 | * @param text - The text of the TiddlyWiki file. 5 | * @returns The extracted encrypted store area, or null if not found. 6 | */ 7 | export function extractEncryptedStoreArea(text: string): string | null; 8 | 9 | /** 10 | * Attempts to decrypt an encrypted store area using the provided password. 11 | * @param encryptedStoreArea - The encrypted store area to decrypt. 12 | * @param password - The password to use for decryption. 13 | * @returns An array of decrypted tiddlers, or null if decryption fails. 14 | */ 15 | export function decryptStoreArea( 16 | encryptedStoreArea: string, 17 | password?: string, 18 | ): unknown[] | null; 19 | 20 | /** 21 | * Prompts the user for a password and attempts to decrypt an encrypted store area using the provided password. 22 | * @param encryptedStoreArea - The encrypted store area to decrypt. 23 | * @param callback - The function to call with the decrypted tiddlers. 24 | * @param options - Configuration options. 25 | * @param options.usePasswordVault - Whether to store the password in the system password vault. 26 | */ 27 | export function decryptStoreAreaInteractive( 28 | encryptedStoreArea: string, 29 | callback: (tiddlers: unknown[]) => void, 30 | options?: { usePasswordVault?: boolean }, 31 | ): void; 32 | } 33 | -------------------------------------------------------------------------------- /src/modules/utils/performance.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/performance.js' { 2 | import { Logger } from '$:/core/modules/utils/logger.js'; 3 | /** 4 | * A performance measurement utility. 5 | * @param enabled - Whether performance measurements are enabled. 6 | * @description 性能测量实用程序。 7 | */ 8 | export class Performance { 9 | /** 10 | * Whether performance measurements are enabled. 11 | */ 12 | enabled: boolean; 13 | /** 14 | * Hashmap by measurement name of `{time:, invocations:}`. 15 | */ 16 | measures: Record; 17 | /** 18 | * A logger instance. 19 | */ 20 | logger: Logger; 21 | constructor(enabled: boolean); 22 | /** 23 | * Displays a greeting message. 24 | * @description 显示问候消息。 25 | */ 26 | showGreeting(): void; 27 | /** 28 | * Wraps performance reporting around top level functions. 29 | * @param name - The name of the function being wrapped. 30 | * @param fn - The function to wrap. 31 | * @returns The wrapped function. 32 | * @description 在顶层函数周围包装性能报告。 33 | */ 34 | report unknown>(name: string, function_: T): T; 35 | /** 36 | * Logs performance measurements. 37 | * @description 记录性能测量。 38 | */ 39 | log(): void; 40 | /** 41 | * Wraps performance measurements around a subfunction. 42 | * @param name - The name of the measurement. 43 | * @param fn - The function to wrap. 44 | * @returns The wrapped function. 45 | * @description 在子函数周围包装性能测量。 46 | */ 47 | measure unknown>(name: string, function_: T): T; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/modules/keyboard.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | // 定义键盘事件信息的接口 3 | export interface KeyInfo { 4 | altKey: boolean; 5 | ctrlKey: boolean; 6 | keyCode: number; 7 | metaKey: boolean; 8 | shiftKey: boolean; 9 | } 10 | 11 | // 定义键盘管理器类的接口 12 | export interface KeyboardManager { 13 | checkKeyDescriptor: (event: KeyboardEvent, keyInfo: KeyInfo) => boolean; 14 | checkKeyDescriptors: (event: KeyboardEvent, keyInfoArray: KeyInfo[]) => boolean; 15 | detectNewShortcuts: ( 16 | changedTiddlers: Record, 17 | ) => boolean | string[]; 18 | getEventModifierKeyDescriptor: (event: KeyboardEvent) => string; 19 | getMatchingKeyDescriptor: ( 20 | event: KeyboardEvent, 21 | keyInfoArray: KeyInfo[], 22 | ) => KeyInfo | null; 23 | getModifierKeys: () => number[]; 24 | getPrintableShortcuts: (keyInfoArray: KeyInfo[]) => string[]; 25 | getShortcutTiddlerList: () => string[]; 26 | handleKeydownEvent: ( 27 | event: KeyboardEvent, 28 | options?: { onlyPriority?: boolean }, 29 | ) => boolean; 30 | handleShortcutChanges: (changedTiddlers: Record) => void; 31 | keyNames: string[]; 32 | lookupNames: string[]; 33 | metaKeyName: string; 34 | namedKeys: Record; 35 | parseKeyDescriptor: ( 36 | keyDescriptor: string, 37 | options?: { keyDescriptor?: string }, 38 | ) => KeyInfo | null; 39 | parseKeyDescriptors: ( 40 | keyDescriptors: string[] | string, 41 | options?: { stack?: string[]; wiki?: Wiki }, 42 | ) => KeyInfo[]; 43 | shortcutActionList: string[]; 44 | shortcutKeysList: string[]; 45 | shortcutParsedList: Array; 46 | shortcutPriorityList: boolean[]; 47 | updateShortcutLists: (tiddlerList: string[]) => void; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | 29 | // Export something to make this a module (required for global declarations to work) 30 | export {}; 31 | 32 | declare module 'tiddlywiki' { 33 | export type TW5InitFunction = (baseObject?: Record) => ITiddlyWiki; 34 | export const TiddlyWiki: TW5InitFunction; 35 | } 36 | 37 | declare global { 38 | const $tw: import('tiddlywiki').ITiddlyWiki; 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs-to-github-pages copy.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy Docs to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: [master] 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | # Allow one concurrent deployment 18 | concurrency: 19 | group: "pages" 20 | cancel-in-progress: true 21 | 22 | env: 23 | # Hosted GitHub runners have 7 GB of memory available, let's use 6 GB 24 | NODE_OPTIONS: --max-old-space-size=6144 25 | 26 | jobs: 27 | # Single deploy job since we're just deploying 28 | deploy: 29 | environment: 30 | name: github-pages 31 | url: ${{ steps.deployment.outputs.page_url }} 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v3 36 | - uses: pnpm/action-setup@v2 37 | with: 38 | version: 8 39 | - name: Set up Node.js 40 | uses: actions/setup-node@v3 41 | with: 42 | node-version: 20.x 43 | cache: pnpm 44 | - name: Install dependencies 45 | run: pnpm i 46 | - name: Gen API Docs 47 | run: pnpm run docs:generate 48 | - name: Build Docs Site 49 | run: pnpm run docs:build 50 | - name: Setup Pages 51 | uses: actions/configure-pages@v3 52 | - name: Upload artifact 53 | uses: actions/upload-pages-artifact@v2 54 | with: 55 | # Upload the folder /build generated by docusaurus 56 | path: build 57 | - name: Deploy to GitHub Pages 58 | id: deployment 59 | uses: actions/deploy-pages@v2 60 | -------------------------------------------------------------------------------- /src/tiddler/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export type ITiddlerCache = Record; 3 | 4 | export interface ITiddlerFields { 5 | readonly [anyKey: string]: unknown; 6 | readonly color?: string; 7 | readonly 'color-scheme'?: 'dark' | 'light'; 8 | readonly created?: Date; 9 | readonly list?: string[]; 10 | readonly modified?: Date; 11 | readonly tags?: string[]; 12 | readonly text: string; 13 | readonly title: string; 14 | readonly type: string; 15 | } 16 | 17 | export class Tiddler { 18 | static fieldModules: Record; 19 | 20 | readonly cache: ITiddlerCache; 21 | 22 | readonly fields: ITiddlerFields; 23 | 24 | /** 25 | * @param tiddlers multiple tiddler fields or instances, will merge them to create a new one 26 | */ 27 | constructor(...tiddlers: Array | Tiddler>); 28 | 29 | hasTag(tag: string): boolean; 30 | hasField(field: string): boolean; 31 | isPlugin(): boolean; 32 | isDraft(): boolean; 33 | /** 34 | * Stringify the field with the associated tiddler field module (if any) 35 | */ 36 | getFieldString(field: string, defaultValue?: string): string; 37 | /** 38 | Get all the fields as a hashmap of strings. Options: 39 | exclude: an array of field names to exclude 40 | */ 41 | getFieldStrings(options?: { exclude?: string[] }): Record; 42 | getFieldDay(field: string): string; 43 | /** 44 | Get the value of a field as a list 45 | */ 46 | getFieldList(field: string, defaultValue?: string): string[]; 47 | /** 48 | Get all the fields as a name:value block. 49 | @param options: 50 | - exclude: an array of field names to exclude 51 | */ 52 | getFieldStringBlock(options: { exclude?: string[] }): string; 53 | 54 | isEqual(tiddler: Tiddler, excludeFields?: string[]): boolean; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/modules/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | // Thanks for GitHub Copilot, you has helped me a lot! 3 | import * as dom from '$:/core/modules/utils/dom.js'; 4 | import * as logger from '$:/core/modules/utils/logger.js'; 5 | import * as utils from '$:/core/modules/utils/utils.js'; 6 | import * as filesystem from '$:/core/modules/utils/filesystem.js'; 7 | import * as LinkedList from '$:/core/modules/utils/linked-list.js'; 8 | import * as performance from '$:/core/modules/utils/performance.js'; 9 | // import the class directly, to fix: Property 'log' does not exist on type 'typeof Logger'.ts(2339) 10 | import * as parseutils from '$:/core/modules/utils/parseutils.js'; 11 | import * as parsetree from '$:/core/modules/utils/parsetree.js'; 12 | import * as pluginMaker from '$:/core/modules/utils/pluginmaker.js'; 13 | import * as transliterate from '$:/core/modules/utils/transliterate.js'; 14 | import * as crypto from '$:/core/modules/utils/crypto.js'; 15 | import * as csv from '$:/core/modules/utils/csv.js'; 16 | import * as editionInfo from '$:/core/modules/utils/edition-info.js'; 17 | import * as escapecss from '$:/core/modules/utils/escapecss.js'; 18 | 19 | export type IUtilitiesModules = 20 | & Pick 21 | & Pick 22 | & Pick 23 | & Pick 24 | & Pick 25 | & Pick 26 | & Pick 27 | & Pick 28 | & Pick 29 | & Pick 30 | & Pick 31 | & Pick 32 | & Pick 33 | & Pick; 34 | } 35 | -------------------------------------------------------------------------------- /src/modules/indexers/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | /** 3 | * Abstract class representing an indexer in TiddlyWiki. Indexers maintain indexes of tiddlers organized efficiently for different types of access, improving the speed of certain filter operations. 4 | * @url https://tiddlywiki.com/dev/#indexer%20modules 5 | */ 6 | abstract class Indexer { 7 | protected wiki: Wiki; 8 | 9 | /** 10 | * Constructs an Indexer instance. 11 | * @param {Wiki} wiki - The wiki object associated with this indexer. 12 | */ 13 | constructor(wiki: Wiki) { 14 | this.wiki = wiki; 15 | } 16 | 17 | /** 18 | * Initializes the indexer, performing any necessary setup. 19 | */ 20 | abstract init(): void; 21 | 22 | /** 23 | * Rebuilds the indexer's index from scratch. Typically used after a significant number of changes in the wiki. 24 | */ 25 | abstract rebuild(): void; 26 | 27 | /** 28 | * Updates the index based on changes to a tiddler. 29 | * @param {Object} updateDescriptor - Describes the changes to the tiddler. 30 | * @param {Object} updateDescriptor.old - The state of the tiddler before the update. 31 | * @param {boolean} updateDescriptor.old.exists - Indicates if the tiddler existed before the update. 32 | * @param {boolean} updateDescriptor.old.shadow - Indicates if the tiddler was a shadow tiddler before the update. 33 | * @param {Tiddler} updateDescriptor.old.tiddler - The tiddler before the update. 34 | * @param {Object} updateDescriptor.new - The state of the tiddler after the update. 35 | * @param {boolean} updateDescriptor.new.exists - Indicates if the tiddler exists after the update. 36 | * @param {boolean} updateDescriptor.new.shadow - Indicates if the tiddler is a shadow tiddler after the update. 37 | * @param {Tiddler} updateDescriptor.new.tiddler - The tiddler after the update. 38 | */ 39 | abstract update(updateDescriptor: { 40 | new: { exists: boolean; shadow: boolean; tiddler: Tiddler }; 41 | old: { exists: boolean; shadow: boolean; tiddler: Tiddler }; 42 | }): void; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/utils/PasswordPrompt.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface PasswordPromptInfo { 3 | callback: PasswordPromptInfoCallback; 4 | form: TWDOMElement; 5 | owner: PasswordPrompt; 6 | serviceName: string; 7 | } 8 | 9 | export type PasswordPromptInfoCallback = ( 10 | data: { 11 | password: string; 12 | password2?: string; 13 | username: string; 14 | } | null, 15 | ) => boolean; 16 | 17 | export class PasswordPrompt { 18 | /** Store of pending password prompts */ 19 | passwordPrompts: PasswordPromptInfo[]; 20 | 21 | promptWrapper: TWDOMElement; 22 | /** Creates a PasswordPrompt object */ 23 | constructor(); 24 | /** Hides or shows the wrapper depending on whether there are any outstanding prompts */ 25 | setWrapperDisplay(): void; 26 | /** 27 | * Adds a new password prompt. Options are: 28 | * @param {{ 29 | * submitText: string; 30 | * serviceName: string; 31 | * noUserName: boolean; 32 | * canCancel: boolean; 33 | * repeatPassword: boolean; 34 | * callback: PasswordPromptInfoCallback; 35 | * }} options Options are: 36 | * * submitText: text to use for submit button (defaults to "Login") 37 | * * serviceName: text of the human readable service name 38 | * * noUserName: set true to disable username prompt 39 | * * canCancel: set true to enable a cancel button (callback called with null) 40 | * * repeatPassword: set true to prompt for the password twice 41 | * * callback: function to be called on submission with parameter of object `{username,password}`. Callback must return `true` to remove the password prompt 42 | * @returns {PasswordPromptInfo} 43 | * @memberof PasswordPrompt 44 | */ 45 | createPrompt(options: { 46 | callback: PasswordPromptInfoCallback; 47 | canCancel: boolean; 48 | noUserName: boolean; 49 | repeatPassword: boolean; 50 | serviceName: string; 51 | submitText: string; 52 | }): PasswordPromptInfo; 53 | removePrompt(promptInfo: PasswordPromptInfo): void; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | .DS_Store 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | 73 | # dotenv environment variables file 74 | .env 75 | .env.test 76 | 77 | # parcel-bundler cache (https://parceljs.org/) 78 | .cache 79 | 80 | # Next.js build output 81 | .next 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # doc 109 | docs/api 110 | docs/README.md 111 | .docusaurus 112 | build -------------------------------------------------------------------------------- /src/hooks.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | import type { Server as HttpServer } from 'node:http'; 3 | 4 | interface ImportFileInfo { 5 | callback: (tiddlerFieldsArray: unknown[]) => void; 6 | file: { lastModified?: number; lastModifiedDate?: Date; name: string; path?: string; size: number; type: string; webkitRelativePath?: string }; 7 | isBinary: boolean; 8 | type: string; 9 | } 10 | 11 | interface IHooks { 12 | /** Add hooks to the hashmap */ 13 | addHook( 14 | hookName: 'th-server-command-post-start', 15 | callback: ( 16 | server: unknown, 17 | nodeServer: HttpServer, 18 | who: 'tiddlywiki', 19 | ) => void, 20 | ): void; 21 | addHook( 22 | hookName: 'th-saving-tiddler' | 'th-renaming-tiddler' | 'th-relinking-tiddler', 23 | callback: (toTiddler: Tiddler, fromTiddler: Tiddler) => Tiddler | undefined, 24 | ); 25 | addHook( 26 | hookName: 'th-importing-tiddler' | 'th-before-importing', 27 | callback: (tiddler: Tiddler) => Tiddler | undefined, 28 | ); 29 | addHook( 30 | hookName: 'th-opening-default-tiddlers-list', 31 | callback: (storyList: string[]) => string[], 32 | ); 33 | addHook( 34 | hookName: 'th-make-tiddler-path', 35 | callback: (fullPath: string, fullPath: string) => string, 36 | ); 37 | addHook( 38 | hookName: 'th-rendering-element', 39 | callback: ( 40 | parseTreeNodes: IParseTreeNode | null, 41 | widget: Widget, 42 | ) => parseTreeNodes, 43 | ); 44 | addHook(hookName: 'th-navigating' | 'th-closing-tiddler' | 'th-editing-tiddler' | 'th-cancelling-tiddler' | 'th-new-tiddler', callback: (event: unknown) => unknown); 45 | addHook(hookName: 'th-deleting-tiddler', callback: (title: Tiddler) => void); 46 | addHook(hookName: 'th-page-refreshed' | 'th-boot-tiddlers-loaded' | 'th-page-refreshing', callback: () => void); 47 | addHook( 48 | hookName: 'th-importing-file', 49 | callback: (props: ImportFileInfo) => boolean | undefined, 50 | ); 51 | addHook(hookName: string, callback: (...arguments_: unknown[]) => unknown); 52 | /** 53 | * Invoke the hook by key 54 | */ 55 | invokeHook(hookName: string, event: IWidgetEvent): undefined | IWidgetEvent; 56 | names: Record unknown>>; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/modules/syncer/syncAdaptor.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | /** 3 | * SyncAdaptorModules 4 | * @url https://tiddlywiki.com/dev/#SyncAdaptorModules 5 | */ 6 | export interface SyncAdaptor { 7 | getTiddlerFileInfo( 8 | tiddler: Tiddler, 9 | callback: (error: Error | null | string, fileInfo: IFileInfo) => void, 10 | ): void; 11 | getTiddlerInfo(tiddler: Tiddler): IFileInfo | undefined; 12 | /** 13 | * Save a tiddler and invoke the callback with (err, adaptorInfo, revision) 14 | */ 15 | saveTiddler( 16 | tiddler: Tiddler, 17 | callback: (error: Error | null | string, adaptorInfo?: IFileInfo | null, revision?: string) => void, 18 | options?: { tiddlerInfo?: Record }, 19 | ): void; 20 | /** 21 | * Load a tiddler and invoke the callback with (err, tiddlerFields) 22 | */ 23 | loadTiddler( 24 | title: string, 25 | callback: (error: Error | null | string, tiddlerFields?: Record | null) => void, 26 | ): void; 27 | /** 28 | * Delete a tiddler and invoke the callback with (err) 29 | */ 30 | deleteTiddler( 31 | title: string, 32 | callback: (error: Error | null | string, adaptorInfo?: IFileInfo | null) => void, 33 | options?: unknown, 34 | ): void; 35 | /** 36 | * Retrieves the titles of tiddlers that need to be updated from the server. 37 | 38 | This method is optional. If an adaptor doesn't implement it then synchronisation will be unidirectional from the TiddlyWiki store to the adaptor, but not the other way. 39 | 40 | The syncer will use the `getUpdatedTiddlers()` method in preference to the `getSkinnyTiddlers()` method. 41 | 42 | |!Parameter |!Description | 43 | |syncer |Reference to the syncer object making the call | 44 | |callback |Callback function invoked with parameter `err,data` -- see below | 45 | 46 | The data provided by the callback is as follows: 47 | 48 | ``` 49 | { 50 | modifications: [], 51 | deletions: [], 52 | } 53 | ``` 54 | * @param syncer 55 | * @param callback 56 | */ 57 | getUpdatedTiddlers(syncer: Syncer, callback: (error: Error | null | undefined, changes: { deletions: string[]; modifications: string[] }) => void): void; 58 | isReady(): boolean; 59 | name: string; 60 | supportsLazyLoading: boolean; 61 | wiki: Wiki; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TW5-Typed 2 | 3 | TypeScript type definitions for TiddlyWiki5. 4 | 5 | [Doc Site - tiddly-gittly.github.io/TW5-Typed](https://tiddly-gittly.github.io/TW5-Typed/) 6 | 7 | ## Usage 8 | 9 | First, install it as dev-dependency: 10 | 11 | ```sh 12 | npm i -D tw5-typed 13 | ``` 14 | 15 | Add `tw5-typed` to your `tsconfig.json`'s `compilerOptions` 16 | 17 | ```json 18 | { 19 | "compilerOptions": { 20 | "types": ["node", "tw5-typed"] /* Type declaration files to be included in compilation. */ 21 | } 22 | } 23 | ``` 24 | 25 | Then you will have global types like `$tw` automatically. You can import the rest of the types using `import type` statement: 26 | 27 | ```typescript 28 | import type { ISearchOptions, SourceIterator, IFilterOperatorParamOperator } from 'tiddlywiki'; 29 | ``` 30 | 31 | ### Alias 32 | 33 | Sometimes you may want to use a modified version of tw, you can re-export types like this in your `src/type.d.ts`: 34 | 35 | ```typescript 36 | declare module '@tiddlygit/tiddlywiki' { 37 | export * from 'tiddlywiki'; 38 | } 39 | ``` 40 | 41 | ## Development 42 | 43 | Firstly, Install eslint using npm: 44 | 45 | ```sh 46 | npm i 47 | ``` 48 | 49 | You can add new `*.d.ts` file to contain your types: 50 | 51 | 1. use `declare module 'tiddlywiki' { }` to wrap all your types. 52 | 1. don't forget to `export` all your types. 53 | 1. to add type for global variable, add `global { }` inside that `declare module 'tiddlywiki' { }`, like `global { var $tw: I$TW; }` 54 | 1. add type import like `/// ` in the `tw.d.ts` 55 | 56 | ### Importing type from other files 57 | 58 | - add type import like `/// ` 59 | - using normal import, like `import { parse } from './parser';` will not work 60 | 61 | Could import from `"tiddlywiki"` inside `declare module` like 62 | 63 | ```ts 64 | declare module '$:/core/modules/utils/parsetree.js' { 65 | import { IParseTreeNode } from 'tiddlywiki'; 66 | ``` 67 | 68 | Import outside of `declare module` will cause error. 69 | 70 | ### Test in your node_modules 71 | 72 | To rapid prototype the type, just right click a type to open `.d.ts` file in the `node_modules`, and try create new file there, and copy to this repo after a success. 73 | 74 | ### Before publish 75 | 76 | Make sure doc build and test are passed. 77 | 78 | 1. Doc: `pnpm run docs:generate && pnpm run docs:dev`, see `.github\workflows\deploy-docs-to-github-pages.yml` 79 | 1. Tests: `pnpm run check`, see `.github\workflows\test.yml` 80 | -------------------------------------------------------------------------------- /src/boot/config.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface IContentTypeInfo { 3 | deserializerType: string; 4 | encoding: string; 5 | extension: string; 6 | flags: string[]; 7 | } 8 | 9 | export interface IFileExtensionInfo { 10 | type: string; 11 | } 12 | 13 | export type ITWConfig = IConfig; 14 | 15 | export interface IConfig { 16 | [configName: string]: unknown; 17 | /** Map type to file content type */ 18 | contentTypeInfo: Record; 19 | /** @default 'TIDDLYWIKI_EDITION_PATH' */ 20 | editionsEnvVar: string; 21 | /** @default '../editions/' */ 22 | editionsPath: string; 23 | /** Map file extension */ 24 | fileExtensionInfo: Record; 25 | htmlUnsafeElements: string[]; 26 | /** 27 | * @default '^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?) 28 | */ 29 | jsModuleHeaderRegExpString: string; 30 | /** @default 'TIDDLYWIKI_LANGUAGE_PATH' */ 31 | languagesEnvVar: string; 32 | /** @default '../languages/' */ 33 | languagesPath: string; 34 | // 35 | /** @default 'TIDDLYWIKI_PLUGIN_PATH' */ 36 | pluginsEnvVar: string; 37 | /** @default '../plugins/'' */ 38 | pluginsPath: string; 39 | /** @default 'TIDDLYWIKI_THEME_PATH' */ 40 | themesEnvVar: string; 41 | /** @default '../themes/' */ 42 | themesPath: string; 43 | /** @default './tiddlywiki.info' */ 44 | wikiInfo: string; 45 | /** @default './languages' */ 46 | wikiLanguagesSubDir: string; 47 | /** @default './output' */ 48 | wikiOutputSubDir: string; 49 | /** @default './plugins' */ 50 | wikiPluginsSubDir: string; 51 | /** @default './themes' */ 52 | wikiThemesSubDir: string; 53 | /** @default './tiddlers' */ 54 | wikiTiddlersSubDir: string; 55 | } 56 | 57 | export interface ITiddlyWikiInfoJSON { 58 | build: ITiddlyWikiInfoJSONBuild; 59 | config: ITiddlyWikiInfoJSONConfig; 60 | description: string; 61 | languages: unknown[]; 62 | plugins: string[]; 63 | themes: string[]; 64 | } 65 | 66 | export interface ITiddlyWikiInfoJSONBuild { 67 | empty: string[]; 68 | encrypted: string[]; 69 | 'external-js': string[]; 70 | favicon: string[]; 71 | index: string[]; 72 | readmes: string[]; 73 | static: string[]; 74 | tw2: string[]; 75 | } 76 | 77 | export interface ITiddlyWikiInfoJSONConfig { 78 | 'retain-original-tiddler-path': boolean; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/modules/utils/logger.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/logger.js' { 2 | /** 3 | * A logger utility. 4 | * @description 日志记录实用程序。 5 | */ 6 | export class Logger { 7 | constructor( 8 | componentName?: string, 9 | options?: { 10 | colour?: string; 11 | enable?: boolean; 12 | save?: boolean; 13 | saveLimit?: number; 14 | }, 15 | ); 16 | // This part is important for TypeScript to understand the constructor signature 17 | // fixes `Property 'prototype' is missing in type 'Logger' but required in type 'typeof Logger'.ts(2741)` 18 | new( 19 | componentName?: string, 20 | options?: { 21 | colour?: string; 22 | enable?: boolean; 23 | save?: boolean; 24 | saveLimit?: number; 25 | }, 26 | ); 27 | 28 | /** 29 | * The name of the component. 30 | */ 31 | componentName: string; 32 | /** 33 | * The color of the logger. 34 | */ 35 | colour: string; 36 | /** 37 | * Whether the logger is enabled. 38 | */ 39 | enable: boolean; 40 | /** 41 | * Whether to save the log. 42 | */ 43 | save: boolean; 44 | /** 45 | * The save limit of the logger. 46 | */ 47 | saveLimit: number; 48 | /** 49 | * The logger to save the buffer. 50 | */ 51 | saveBufferLogger: Logger; 52 | /** 53 | * The buffer of the logger. 54 | */ 55 | buffer: string; 56 | /** 57 | * The alert count of the logger. 58 | */ 59 | alertCount: number; 60 | /** 61 | * Set the logger to save the buffer. 62 | * @param logger - The logger to save the buffer. 63 | * @description 设置记录器以保存缓冲区。 64 | */ 65 | setSaveBuffer(logger: Logger): void; 66 | /** 67 | * Log a message. 68 | * @param args - The arguments to log. 69 | * @description 记录消息。 70 | */ 71 | log(...arguments_: unknown[]): void; 72 | /** 73 | * Get the message buffer. 74 | * @returns The message buffer. 75 | * @description 获取消息缓冲区。 76 | */ 77 | getBuffer(): string; 78 | /** 79 | * Log a structure as a table. 80 | * @param value - The value to log. 81 | * @description 将结构记录为表格。 82 | */ 83 | table(value: unknown): void; 84 | /** 85 | * Alert a message. 86 | * @param args - The arguments to alert. 87 | * @description 警报消息。 88 | */ 89 | alert(...arguments_: unknown[]): void; 90 | /** 91 | * Clear outstanding alerts. 92 | * @description 清除未处理的警报。 93 | */ 94 | clearAlerts(): void; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/modules/widgets/navigator.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export class NavigatorWidget extends Widget { 3 | getStoryList(): string[] | null; 4 | saveStoryList(storyList: string[]): void; 5 | removeTitleFromStory(storyList: string[], title: string): void; 6 | replaceFirstTitleInStory( 7 | storyList: string[], 8 | oldTitle: string, 9 | newTitle: string, 10 | ): void; 11 | addToStory(title: string, fromTitle?: string): void; 12 | /** 13 | Add a new record to the top of the history stack 14 | title: a title string or an array of title strings 15 | fromPageRect: page coordinates of the origin of the navigation 16 | */ 17 | addToHistory(title: string, fromPageRect?: DOMRect): void; 18 | handleNavigateEvent(event: IWidgetEvent): void; 19 | handleCloseTiddlerEvent(event: IWidgetEvent): void; 20 | handleCloseAllTiddlersEvent(event: IWidgetEvent): void; 21 | handleCloseOtherTiddlersEvent(event: IWidgetEvent): void; 22 | handleEditTiddlerEvent(event: IWidgetEvent): void; 23 | handleDeleteTiddlerEvent(event: IWidgetEvent): void; 24 | makeDraftTiddler(targetTitle): void; 25 | generateDraftTitle(title): void; 26 | handleSaveTiddlerEvent(event: IWidgetEvent): void; 27 | handleCancelTiddlerEvent(event: IWidgetEvent): void; 28 | /** 29 | * Create a new draft tiddler 30 | * event.param can either be the title of a template tiddler, or a hashmap of fields. 31 | * The title of the newly created tiddler follows these rules: 32 | * * If a hashmap was used and a title field was specified, use that title 33 | * * If a hashmap was used without a title field, use a default title, if necessary making it unique with a *numeric suffix 34 | * * If a template tiddler was used, use the title of the template, if necessary making it unique with a *numeric suffix 35 | * If a draft of the target tiddler already exists then it is reused 36 | */ 37 | handleNewTiddlerEvent(event: IWidgetEvent): void; 38 | /** 39 | * Import JSON tiddlers into a pending import tiddler 40 | */ 41 | handleImportTiddlersEvent(event: IWidgetEvent): void; 42 | handlePerformImportEvent(event: IWidgetEvent): void; 43 | handleFoldTiddlerEvent(event: IWidgetEvent): void; 44 | handleFoldOtherTiddlersEvent(event: IWidgetEvent): void; 45 | handleFoldAllTiddlersEvent(event: IWidgetEvent): void; 46 | handleUnfoldAllTiddlersEvent(event: IWidgetEvent): void; 47 | } 48 | } 49 | declare module '$:/core/modules/widgets/navigator.js' { 50 | } 51 | 52 | export { NavigatorWidget as navigator } from 'tiddlywiki'; 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tw5-typed", 3 | "version": "1.1.4", 4 | "scripts": { 5 | "check": "tsc --noEmit && eslint --max-warnings 0 \"src/**/*.ts\" \"src/**/*.d.ts\" \"test/**/*.ts\"", 6 | "docs": "docs-ts", 7 | "docs:build": "docusaurus build", 8 | "docs:dev": "docusaurus start", 9 | "docs:generate": "npm run docs:generate:api && npm run docs:generate:copy", 10 | "docs:generate:api": "rimraf docs/api && typedoc --options typedoc.json", 11 | "docs:generate:copy": "zx scripts/copy-readme.mjs", 12 | "update": "npm-check-updates -u && dprint config update", 13 | "prepublishOnly": "npm run check" 14 | }, 15 | "description": "Types for tiddlywiki", 16 | "license": "MIT", 17 | "url": "https://github.com/tiddly-gittly/tw5-typed", 18 | "homepage": "https://github.com/tiddly-gittly/tw5-typed", 19 | "bugs": { 20 | "url": "https://github.com/tiddly-gittly/tw5-typed/issues" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/tiddly-gittly/tw5-typed.git" 25 | }, 26 | "types": "src/index.d.ts", 27 | "exports": { 28 | ".": { 29 | "import": "./src/index.d.ts", 30 | "require": "./src/index.d.ts", 31 | "types": "./src/index.d.ts" 32 | } 33 | }, 34 | "files": [ 35 | "src/" 36 | ], 37 | "husky": { 38 | "hooks": { 39 | "pre-commit": "lint-staged" 40 | } 41 | }, 42 | "lint-staged": { 43 | "*.{ts,tsx}": [ 44 | "node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet" 45 | ], 46 | "*.{js,jsx,mjs,mjsx,cjs,cjsx}": [ 47 | "node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet" 48 | ] 49 | }, 50 | "dependencies": { 51 | "@types/codemirror": "^5.60.17", 52 | "@types/echarts": "^5.0.0", 53 | "@types/node": "^24.10.1" 54 | }, 55 | "devDependencies": { 56 | "@docusaurus/core": "^3.9.2", 57 | "@docusaurus/preset-classic": "^3.9.2", 58 | "@docusaurus/types": "^3.9.2", 59 | "@mdx-js/react": "^3.1.1", 60 | "@modern-js/eslint-config": "latest", 61 | "@modern-js/tsconfig": "latest", 62 | "docs-ts": "^0.8.0", 63 | "dprint": "^0.50.2", 64 | "eslint-config-tidgi": "^2.2.0", 65 | "husky": "^9.1.7", 66 | "lint-staged": "^16.2.7", 67 | "npm-check-updates": "^19.1.2", 68 | "prism-react-renderer": "^2.4.1", 69 | "react": "^19.2.0", 70 | "rimraf": "^6.1.2", 71 | "tiddlywiki": "^5.3.8", 72 | "type-fest": "^5.3.0", 73 | "typedoc": "^0.28.15", 74 | "typedoc-plugin-markdown": "^4.9.0", 75 | "typescript": "^5.9.3", 76 | "zx": "^8.8.5" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/modules/utils/linked-list.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/linked-list.js' { 2 | /** 3 | * A linked list implementation. 4 | * @description 链表实现。 5 | */ 6 | export class LinkedList { 7 | /** 8 | * The next node in the linked list. 9 | */ 10 | next: LLMap; 11 | /** 12 | * The previous node in the linked list. 13 | */ 14 | prev: LLMap; 15 | /** 16 | * The length of the linked list. 17 | */ 18 | length: number; 19 | constructor(); 20 | /** 21 | * Clear the linked list. 22 | * @description 清空链表。 23 | */ 24 | clear(): void; 25 | /** 26 | * Remove a value from the linked list. 27 | * @param value - The value to remove. 28 | * @description 从链表中删除值。 29 | */ 30 | remove(value: string | string[]): void; 31 | /** 32 | * Push a value to the end of the linked list. 33 | * @param values - The values to push. 34 | * @returns The length of the linked list. 35 | * @description 将值推送到链表的末尾。 36 | */ 37 | push(...values: string[] | string[][]): number; 38 | /** 39 | * Push a value to the top of the linked list. 40 | * @param value - The value to push. 41 | * @description 将值推送到链表的顶部。 42 | */ 43 | pushTop(value: string | string[]): void; 44 | /** 45 | * Iterate over each value in the linked list. 46 | * @param callback - The callback function to call for each value. 47 | * @description 迭代链表中的每个值。 48 | */ 49 | each(callback: (value: string) => void): void; 50 | /** 51 | * Convert the linked list to an array. 52 | * @returns The array representation of the linked list. 53 | * @description 将链表转换为数组。 54 | */ 55 | toArray(): string[]; 56 | /** 57 | * Create an iterator for the linked list. 58 | * @param wiki - The wiki to use for the iterator. 59 | * @returns The iterator function. 60 | * @description 创建链表的迭代器。 61 | */ 62 | makeTiddlerIterator( 63 | wiki: Wiki, 64 | ): (callback: (tiddler: Tiddler, title: string) => void) => void; 65 | } 66 | 67 | class LLMap { 68 | /** 69 | * The map object. 70 | */ 71 | map: Record; 72 | /** 73 | * The null value of the map. 74 | */ 75 | null: unknown; 76 | /** 77 | * Set a value in the map. 78 | * @param key - The key to set. 79 | * @param val - The value to set. 80 | * @description 在映射中设置值。 81 | */ 82 | set(key: string | null, value: unknown): void; 83 | /** 84 | * Get a value from the map. 85 | * @param key - The key to get. 86 | * @returns The value of the key. 87 | * @description 从映射中获取值。 88 | */ 89 | get(key: string | null): unknown; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/tiddlywiki-test.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { Modal } from '$:/core/modules/utils/dom/modal.js'; 3 | import { Logger } from '$:/core/modules/utils/logger.js'; 4 | import { widget as Widget } from '$:/core/modules/widgets/widget.js'; 5 | import { IParseTreeNode, Tiddler } from 'tiddlywiki'; 6 | 7 | export class ReactWidget extends Widget { 8 | logger: Logger; 9 | 10 | constructor(parseTreeNode: IParseTreeNode) { 11 | super(parseTreeNode); 12 | const logger = new $tw.utils.Logger('TidGiIPCSyncAdaptor'); 13 | logger.table({ a: 1, b: 2 }); 14 | logger.log('getUpdatedTiddlers'); 15 | this.logger = new $tw.utils.Logger('TidGiIPCSyncAdaptor'); 16 | this.logger.table({ a: 1, b: 2 }); 17 | this.logger.log('getUpdatedTiddlers'); 18 | $tw.modal.display('tiddler-title'); 19 | new Modal($tw.wiki).display('$:/plugins/linonetwo/tw-calendar/calendar-widget/tiddlywiki-ui/popup/CreateNewTiddlerPopup'); 20 | $tw.notifier.display('tiddler-title'); 21 | $tw.wiki.addIndexer((_tiddler: Tiddler) => {}, '$:/core/tiddler'); 22 | if ($tw.browser?.is?.mobile === true) { 23 | $tw.wiki.addTiddler({ title: 'aaa', text: 'bbb' }); 24 | } 25 | $tw.utils.parseFilterVariable('now DDMM UTC'); 26 | $tw.wiki.parseFilter('[search: one, two ,three :[operand]]'); 27 | 28 | // Test newly added methods 29 | const _list = $tw.wiki.getTiddlerList('MyTiddler', 'list'); 30 | const _textReference = $tw.wiki.getTextReference('MyTiddler!!field', 'default'); 31 | $tw.wiki.setTextReference('MyTiddler!!field', 'value'); 32 | const _count = $tw.wiki.countTiddlers('$:/tags/Exclude'); 33 | const _tagged = $tw.wiki.getTiddlersWithTag('$:/tags/KeyboardShortcut'); 34 | $tw.utils.copyToClipboard('itemUrl'); 35 | 36 | const _parsed = $tw.utils.parseStringArray('value value2 value3'); 37 | 38 | $tw.wiki.forEachTiddler({ includeSystem: false }, (title, tiddler) => { 39 | console.log(title, tiddler); 40 | }); 41 | 42 | const _searchResults = $tw.wiki.search('search term', { 43 | caseSensitive: false, 44 | field: 'text', 45 | }); 46 | 47 | const _links = $tw.wiki.extractLinks([]); 48 | const _transcludes = $tw.wiki.getTiddlerTranscludes('MyTiddler'); 49 | const _backlinks = $tw.wiki.getTiddlerBacklinks('MyTiddler'); 50 | 51 | const _subTiddler = $tw.wiki.getSubTiddler('$:/plugins/MyPlugin', 'readme'); 52 | const _orphans = $tw.wiki.getOrphanTitles(); 53 | const _missing = $tw.wiki.getMissingTitles(); 54 | const _tagMap = $tw.wiki.getTagMap(); 55 | const _draft = $tw.wiki.findDraft('MyTiddler'); 56 | const _slug = $tw.wiki.slugify('My Title'); 57 | 58 | $tw.wiki.sortTiddlers(['a', 'b', 'c'], 'title', false, false); 59 | } 60 | 61 | render(parent: Element, _nextSibling: Element): void { 62 | this.parentDomNode = parent; 63 | this.execute(); 64 | this.computeAttributes(); 65 | const containerElement = $tw.utils.domMaker('div', {}); 66 | this.domNodes.push(containerElement); 67 | parent.append(containerElement); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/modules/utils/parsetree.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A utility module for working with parse trees. 3 | * @description 用于处理解析树的实用程序模块。 4 | */ 5 | declare module '$:/core/modules/utils/parsetree.js' { 6 | import { IParseTreeNode } from 'tiddlywiki'; 7 | /** 8 | * Add attribute to parse tree node. 9 | * @param node - The parse tree node. 10 | * @param name - The name of the attribute. 11 | * @param value - The value of the attribute. 12 | * @description 向解析树节点添加属性。 13 | */ 14 | export function addAttributeToParseTreeNode( 15 | node: IParseTreeNode, 16 | name: string | object, 17 | value?: unknown, 18 | ): void; 19 | 20 | /** 21 | * Get ordered attributes from parse tree node. 22 | * @param node - The parse tree node. 23 | * @returns The ordered attributes. 24 | * @description 从解析树节点获取有序属性。 25 | */ 26 | export function getOrderedAttributesFromParseTreeNode(node: IParseTreeNode): unknown[]; 27 | 28 | /** 29 | * Get attribute value from parse tree node. 30 | * @param node - The parse tree node. 31 | * @param name - The name of the attribute. 32 | * @param defaultValue - The default value of the attribute. 33 | * @returns The value of the attribute. 34 | * @description 从解析树节点获取属性值。 35 | */ 36 | export function getAttributeValueFromParseTreeNode( 37 | node: IParseTreeNode, 38 | name: string, 39 | defaultValue?: unknown, 40 | ): unknown; 41 | 42 | /** 43 | * Add class to parse tree node. 44 | * @param node - The parse tree node. 45 | * @param classString - The class string to add. 46 | * @description 向解析树节点添加类。 47 | */ 48 | export function addClassToParseTreeNode(node: IParseTreeNode, classString: string): void; 49 | 50 | /** 51 | * Add style to parse tree node. 52 | * @param node - The parse tree node. 53 | * @param name - The name of the style. 54 | * @param value - The value of the style. 55 | * @description 向解析树节点添加样式。 56 | */ 57 | export function addStyleToParseTreeNode( 58 | node: IParseTreeNode, 59 | name: string, 60 | value: string, 61 | ): void; 62 | 63 | /** 64 | * Find parse tree node. 65 | * @param nodeArray - The array of parse tree nodes. 66 | * @param search - The search object. 67 | * @returns The parse tree node. 68 | * @description 查找解析树节点。 69 | */ 70 | export function findParseTreeNode( 71 | nodeArray: IParseTreeNode[], 72 | search: { tag: string; type: string }, 73 | ): IParseTreeNode | undefined; 74 | 75 | /** 76 | * Get the text of a parse tree node or array of nodes. 77 | * @param tree - The parse tree node or array of nodes. 78 | * @returns The text of the parse tree node or array of nodes. 79 | * @description 获取解析树节点或节点数组的文本。 80 | */ 81 | export function getParseTreeText(tree: IParseTreeNode | IParseTreeNode[]): string; 82 | /** 83 | * Serialize parse tree. 84 | * @param tree - The parse tree node or array of nodes. 85 | * @returns The serialized parse tree. 86 | * @description 序列化解析树。 87 | */ 88 | export function serializeParseTree(tree: IParseTreeNode | IParseTreeNode[]): string; 89 | } 90 | -------------------------------------------------------------------------------- /docusaurus.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from '@docusaurus/types'; 2 | 3 | import { themes } from 'prism-react-renderer'; 4 | 5 | const organizationName = 'tiddly-gittly'; 6 | const projectName = 'TW5-Typed'; 7 | 8 | export default { 9 | title: 'Tiddlywiki JS Docs', 10 | tagline: 'API and usage or tiddlywiki npm package.', 11 | url: `https://${organizationName}.github.io`, 12 | baseUrl: `/${projectName}/`, 13 | onBrokenLinks: 'throw', 14 | onBrokenMarkdownLinks: 'throw', 15 | favicon: 'favicon.ico', 16 | // GitHub Pages adds a trailing slash by default that I don't want 17 | trailingSlash: false, 18 | 19 | // GitHub pages deployment config. 20 | // If you aren't using GitHub pages, you don't need these. 21 | organizationName, // Usually your GitHub org/user name. 22 | projectName, // Usually your repo name. 23 | 24 | // Even if you don't use internalization, you can use this field to set useful 25 | // metadata like html lang. For example, if your site is Chinese, you may want 26 | // to replace "en" with "zh-Hans". 27 | i18n: { 28 | defaultLocale: 'en', 29 | locales: ['en'], 30 | }, 31 | 32 | presets: [ 33 | [ 34 | 'classic', 35 | /** @type {import('@docusaurus/preset-classic').Options} */ 36 | ({ 37 | docs: { 38 | // sidebarPath: require.resolve("./sidebars.js"), 39 | // Please change this to your repo. 40 | // Remove this to remove the "edit this page" links. 41 | editUrl: `https://github.com/${organizationName}/${projectName}/tree/master/docs/`, 42 | routeBasePath: '/', 43 | }, 44 | theme: { 45 | // customCss: require.resolve("./src/css/custom.css"), 46 | }, 47 | }), 48 | ], 49 | ], 50 | 51 | themeConfig: 52 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 53 | ({ 54 | navbar: { 55 | title: 'Tiddlywiki Docs', 56 | logo: { 57 | alt: 'Logo', 58 | // temporary logo, change this when we have a real one 59 | // it will try to load `static/images/Logo.png` if provided `"/images/Logo.png"`. 60 | src: '/images/Logo.webp', 61 | }, 62 | items: [ 63 | { to: 'api', label: 'API', position: 'left' }, 64 | { 65 | href: `https://github.com/${organizationName}/${projectName}`, 66 | label: 'GitHub', 67 | position: 'right', 68 | }, 69 | ], 70 | }, 71 | footer: { 72 | style: 'dark', 73 | links: [ 74 | { 75 | title: 'Community', 76 | items: [ 77 | { 78 | label: 'Stack Overflow', 79 | href: 'https://stackoverflow.com/questions/tagged/tiddlywiki', 80 | }, 81 | { 82 | label: 'Discord', 83 | href: 'https://discordapp.com/invite/tiddlywiki', 84 | }, 85 | { 86 | label: 'Twitter', 87 | href: 'https://twitter.com/tiddlywiki', 88 | }, 89 | ], 90 | }, 91 | { 92 | title: 'More', 93 | items: [ 94 | { 95 | label: 'API', 96 | to: 'api', 97 | }, 98 | { 99 | label: 'GitHub', 100 | href: `https://github.com/${organizationName}/${projectName}`, 101 | }, 102 | ], 103 | }, 104 | ], 105 | copyright: `Copyright © ${new Date().getFullYear()} ${organizationName}. Doc site built with Docusaurus.`, 106 | }, 107 | prism: { 108 | theme: themes.vsLight, 109 | darkTheme: themes.vsDark, 110 | }, 111 | }), 112 | } satisfies Config; 113 | -------------------------------------------------------------------------------- /src/modules/utils/parseutils.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility functions concerned with parsing text into tokens. 3 | * Most functions have the following pattern: 4 | * - The parameters are: 5 | * - `source`: the source string being parsed 6 | * - `pos`: the current parse position within the string 7 | * - Any further parameters are used to identify the token that is being parsed 8 | * - The return value is: 9 | * - null if the token was not found at the specified position 10 | * - an object representing the token with the following standard fields: 11 | * - `type`: string indicating the type of the token 12 | * - `start`: start position of the token in the source string 13 | * - `end`: end position of the token in the source string 14 | * - Any further fields required to describe the token 15 | * The exception is `skipWhiteSpace`, which just returns the position after the whitespace. 16 | */ 17 | declare module '$:/core/modules/utils/parseutils.js' { 18 | /** 19 | * Look for a whitespace token. Returns null if not found, otherwise returns an object. 20 | */ 21 | export function parseWhiteSpace(source: string, pos: number): { end: number; start: number; type: 'whitespace' } | null; 22 | 23 | /** 24 | * Convenience wrapper for parseWhiteSpace. Returns the position after the whitespace. 25 | */ 26 | export function skipWhiteSpace(source: string, pos: number): number; 27 | 28 | /** 29 | * Look for a given string token. Returns null if not found, otherwise returns an object. 30 | */ 31 | export function parseTokenString(source: string, pos: number, token: string): { end: number; start: number; type: 'token'; value: string } | null; 32 | 33 | /** 34 | * Look for a token matching a regex. Returns null if not found, otherwise returns an object. 35 | */ 36 | export function parseTokenRegExp(source: string, pos: number, reToken: RegExp): { end: number; match: RegExpExecArray; start: number; type: 'regexp' } | null; 37 | 38 | /** 39 | * Look for a string literal. Returns null if not found, otherwise returns an object. 40 | */ 41 | export function parseStringLiteral(source: string, pos: number): { end: number; start: number; type: 'string'; value: string } | null; 42 | 43 | /** 44 | * Returns an array of `{name:}` with an optional "default" property. Options include `requireParenthesis`. 45 | */ 46 | export function parseParameterDefinition(parameterString: string, options?: { requireParenthesis?: boolean }): Array<{ default?: string; name: string }>; 47 | 48 | /** 49 | * Process parameters for macro invocation. 50 | */ 51 | export function parseMacroParameters(node: IParseTreeNode, source: string, pos: number): unknown[]; 52 | 53 | /** 54 | * Look for a macro invocation parameter. Returns null if not found. 55 | */ 56 | export function parseMacroParameter(source: string, pos: number): { end: number; name?: string; start: number; type: 'macro-parameter'; value: string } | null; 57 | 58 | /** 59 | * Look for a macro invocation. Returns null if not found. 60 | */ 61 | export function parseMacroInvocation(source: string, pos: number): { end: number; name: string; params: unknown[]; start: number; type: 'macrocall' } | null; 62 | 63 | /** 64 | * Look for a macro invocation as transclusion. Returns null if not found. 65 | */ 66 | export function parseMacroInvocationAsTransclusion(source: string, pos: number): { attributes: Record; end: number; start: number; type: 'transclude' } | null; 67 | 68 | export interface FilterVariableParseTreeNode { 69 | name: string; 70 | params: FilterVariableParameterParseTreeNode[]; 71 | } 72 | export interface FilterVariableParameterParseTreeNode { 73 | end: number; 74 | start: number; 75 | type: string; 76 | value: string; 77 | } 78 | /** 79 | * Parse filter variable parameters. 80 | */ 81 | export function parseFilterVariable(source: string): FilterVariableParseTreeNode; 82 | 83 | /** 84 | * Look for an HTML attribute definition. Returns null if not found, otherwise returns an object. 85 | */ 86 | export function parseAttribute( 87 | source: string, 88 | pos: number, 89 | ): { end: number; filter?: string; name: string; start: number; textReference?: string; type: 'attribute'; value?: string } | null; 90 | } 91 | -------------------------------------------------------------------------------- /src/modules/server/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | import type Http from 'http'; 3 | export interface IServerStatus { 4 | anonymous: boolean; 5 | read_only: boolean; 6 | space: { 7 | recipe: string; 8 | }; 9 | tiddlywiki_version: string; 10 | username: string; 11 | } 12 | 13 | export interface IRoute { 14 | handler: ServerEndpointHandler; 15 | method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'OPTIONS' | 'HEAD'; 16 | path: RegExp; 17 | } 18 | 19 | export interface IServerOptions { 20 | routes: IRoute[]; 21 | variables?: Record; 22 | wiki: Wiki; 23 | } 24 | 25 | /** 26 | A simple HTTP server with regexp-based routes 27 | 28 | options: variables - optional hashmap of variables to set (a misnomer - they are really constant parameters) 29 | routes - optional array of routes to use 30 | wiki - reference to wiki object 31 | */ 32 | export class Server { 33 | /** 34 | * @example 35 | * ```json 36 | * { 37 | port: "8080", 38 | host: "127.0.0.1", 39 | "required-plugins": "$:/plugins/tiddlywiki/filesystem,$:/plugins/tiddlywiki/tiddlyweb", 40 | "root-tiddler": "$:/core/save/all", 41 | "root-render-type": "text/plain", 42 | "root-serve-type": "text/html", 43 | "tiddler-render-type": "text/html", 44 | "tiddler-render-template": "$:/core/templates/server/static.tiddler.html", 45 | "system-tiddler-render-type": "text/plain", 46 | "system-tiddler-render-template": "$:/core/templates/wikified-tiddler", 47 | "debug-level": "none", 48 | "gzip": "no", 49 | "use-browser-cache": "no" 50 | } 51 | ``` 52 | */ 53 | defaultVariables: { 54 | 'debug-level': string; 55 | gzip: string; 56 | host: string; 57 | port: string; 58 | 'required-plugins': string; 59 | 'root-render-type': string; 60 | 'root-serve-type': string; 61 | 'root-tiddler': string; 62 | 'system-tiddler-render-template': string; 63 | 'system-tiddler-render-type': string; 64 | 'tiddler-render-template': string; 65 | 'tiddler-render-type': string; 66 | 'use-browser-cache': string; 67 | }; 68 | 69 | requestHandler: ServerEndpointHandler; 70 | 71 | variables: Record; 72 | 73 | routes: IRoute[]; 74 | 75 | constructor(options: IServerOptions); 76 | addRoute(route: IRoute): void; 77 | get(variableName: string): unknown; 78 | /** 79 | Listen for requests 80 | port: optional port number (falls back to value of "port" variable) 81 | host: optional host address (falls back to value of "host" variable) 82 | prefix: optional prefix (falls back to value of "path-prefix" variable) 83 | */ 84 | listen(port?: string, host?: string, prefix?: string): void; 85 | 86 | on(eventName: 'error', callback: (error: Error) => void): void; 87 | on(eventName: 'listening', callback: () => void): void; 88 | on( 89 | eventName: string, 90 | callback: (...arguments_: unknown[]) => unknown, 91 | ): void; 92 | 93 | /** 94 | Check whether a given user is authorized for the specified authorizationType ("readers" or "writers"). Pass null or undefined as the username to check for anonymous access 95 | */ 96 | isAuthorized( 97 | authorizationType: 'readers' | 'writers', 98 | username?: string, 99 | ): boolean; 100 | close(): void; 101 | } 102 | 103 | export interface ServerEndpointContext { 104 | authenticatedUsername: string | undefined; 105 | data: string; 106 | /** 107 | * With `exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;` you can use: 108 | * 109 | * `title = $tw.utils.decodeURIComponentSafe(state.params[0])` 110 | */ 111 | params: string[]; 112 | server: Server; 113 | wiki: Wiki; 114 | } 115 | /** 116 | * @link https://talk.tiddlywiki.org/t/what-is-the-state-in-server-route-handler/2877 117 | */ 118 | export type ServerEndpointHandler> = ( 119 | request: Http.ClientRequest & Http.InformationEvent, 120 | response: Http.ServerResponse, 121 | context: ServerEndpointContext & T, 122 | ) => void | Promise; 123 | } 124 | -------------------------------------------------------------------------------- /src/modules/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface ITWModuleExports { 3 | [exportName: string]: unknown; 4 | name?: string; 5 | type?: string; 6 | } 7 | export interface IModuleInfo { 8 | definition: string | TWModuleDefinitionFucntion | ITWModuleExports; 9 | exports: ITWModuleExports | null; 10 | moduleType: string; 11 | } 12 | export interface ITWRequire { 13 | (title: string): ITWModuleExports; 14 | readonly main: NodeJS.Module | { TiddlyWiki: TW5InitFunction }; 15 | } 16 | export interface IEvalContent { 17 | $tw: ITiddlyWiki; 18 | Buffer?: Buffer; 19 | clearInterval: typeof clearInterval; 20 | clearTimeout: typeof clearTimeout; 21 | console: Console; 22 | exports: ITWModuleExports; 23 | module: { exports: ITWModuleExports; readonly id: string }; 24 | process?: NodeJS.Process; 25 | require: ITWRequire; 26 | setInterval: typeof setInterval; 27 | setTimeout: typeof setTimeout; 28 | } 29 | export type TWModuleDefinitionFucntion = ( 30 | moduleInfo: IModuleInfo, 31 | exports: ITWModuleExports, 32 | requireFunction: ITWRequire, 33 | ) => void; 34 | 35 | export type ITWModules = IModules; 36 | 37 | /** 38 | * Information about each module is kept in an object with these members: 39 | * 40 | * * moduleType: type of module 41 | * * definition: object, function or string defining the module; see below 42 | * * exports: exports of the module, filled in after execution 43 | * 44 | * The `definition` can be of several types: 45 | * 46 | * * An object can be used to directly specify the exports of the module 47 | * * A function with the arguments `module,require,exports` that returns `exports` 48 | * * A string function body with the same arguments 49 | * 50 | * Each moduleInfo object is stored in two hashmaps: $tw.modules.titles and $tw.modules.types. The first is indexed by title and the second is indexed by type and then title 51 | */ 52 | interface IModules { 53 | /** Apply the exports of the modules of a particular type to a target object */ 54 | applyMethods: ( 55 | moduleType: string, 56 | targetObject?: ITWModuleExports, 57 | ) => ITWModuleExports; 58 | /** Return a class created from a modules. The module should export the properties to be added to those of the optional base class */ 59 | createClassFromModule: ( 60 | moduleExports: ITWModuleExports, 61 | baseClass: new() => unknown, 62 | ) => ITWModuleExports; 63 | /** Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class */ 64 | createClassesFromModules: ( 65 | moduleType: string, 66 | subType: string | null | undefined, 67 | baseClass: new() => unknown, 68 | ) => Record; 69 | /** 70 | * Define a JavaScript tiddler module for later execution 71 | * @param {string} moduleName name of module being defined 72 | * @param {string} moduleType type of module 73 | * @param {(string | TWModuleDefinitionFucntion | ITWModuleExports)} definition module definition; see discussion above 74 | * @memberof ITWModules 75 | */ 76 | define: ( 77 | moduleName: string, 78 | moduleType: string, 79 | definition: string | TWModuleDefinitionFucntion | ITWModuleExports, 80 | ) => void; 81 | /** 82 | * Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot' 83 | * @memberof ITWModules 84 | */ 85 | execute: (moduleName: string, moduleRoot: string) => ITWModuleExports; 86 | /** 87 | * Apply a callback to each module of a particular type 88 | * 89 | * @param {string} moduleType type of modules to enumerate 90 | * @param {(title, moduleExports) => void} callback function called as callback(title,moduleExports) for each module 91 | * @memberof ITWModules 92 | */ 93 | forEachModuleOfType: ( 94 | moduleType: string, 95 | callback: (title: string, moduleExports: unknown) => void, 96 | ) => void; 97 | /** Get all the modules of a particular type in a hashmap by their `name` field */ 98 | getModulesByTypeAsHashmap: ( 99 | moduleType: string, 100 | nameField: string, 101 | ) => Record; 102 | /** hashmap by module name of moduleInfo */ 103 | titles: Record; 104 | /** hashmap by module type and then name of moduleInfo */ 105 | types: Record>; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/modules/parsers/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface IParseOptions { 3 | /** 4 | * Optional source uri, used in parseText 5 | */ 6 | _canonical_uri?: string; 7 | defaultType?: string; 8 | document?: TWDocument; 9 | parentWidget?: Widget; 10 | /** 11 | * While calling `getCacheForTiddler`, use inlineParseTree or blockParseTree 12 | */ 13 | parseAsInline?: boolean; 14 | } 15 | 16 | export class WikiParseRule { 17 | is: { block?: boolean; inline?: boolean }; 18 | 19 | match?: unknown; 20 | 21 | matchRegExp?: RegExp; 22 | 23 | parser?: WikiParser; 24 | 25 | nextTag?: unknown; 26 | 27 | /** `{type: 'macrocall', start: 261, params: Array(1), name: 'reuse-tiddler', end: 290}` */ 28 | nextCall?: { 29 | end: number; 30 | name: string; 31 | /** `{ type: 'macro-parameter'; start: 276; value: '快速创建新笔记按钮'; end: 288 }` */ 32 | params: { end: number; start: number; type: string; value: string }; 33 | start: number; 34 | type: string; 35 | }; 36 | } 37 | export class WikiParser { 38 | blockRules: Array<{ matchIndex?: number; rule: WikiParseRule }>; 39 | 40 | inlineRules: Array<{ matchIndex?: number; rule: WikiParseRule }>; 41 | 42 | pragmaRules: Array<{ matchIndex?: number; rule: WikiParseRule }>; 43 | 44 | configTrimWhiteSpace: boolean; 45 | 46 | pos: number; 47 | 48 | source: string; 49 | 50 | sourceLength: number; 51 | 52 | type: string; 53 | 54 | wiki: Wiki; 55 | 56 | tree: IParseTreeNode[]; 57 | } 58 | 59 | export interface IParseTreeAttribute { 60 | end?: number; 61 | name?: string; 62 | start?: number; 63 | type: 64 | | 'string' 65 | | 'number' 66 | | 'bigint' 67 | | 'boolean' 68 | | 'macro' 69 | | 'macro-parameter'; 70 | value: string | IMacroCallParseTreeNode; 71 | } 72 | 73 | export interface IWikiASTNode { 74 | attributes?: Record; 75 | children?: IParseTreeNode[]; 76 | end?: number; 77 | isBlock?: boolean; 78 | isMacroDefinition?: boolean; 79 | isSelfClosing?: boolean; 80 | orderedAttributes?: IParseTreeAttribute[]; 81 | /** If rule produce a multi-level tree, only top level node from a parse rule will have this. */ 82 | rule?: string; 83 | start?: number; 84 | type: string; 85 | } 86 | export interface IWikiASTTextNode { 87 | end?: number; 88 | start?: number; 89 | text: string; 90 | type: string; 91 | } 92 | export interface ITextParseTreeNode extends IWikiASTNode { 93 | text: string; 94 | type: 'text'; 95 | } 96 | export interface IImageParseTreeNode extends IWikiASTNode { 97 | type: 'image'; 98 | } 99 | export interface ITranscludeParseTreeNode extends IWikiASTNode { 100 | type: 'transclude'; 101 | } 102 | export interface ITiddlerParseTreeNode extends IWikiASTNode { 103 | type: 'tiddler'; 104 | } 105 | /** HTML tags and widget tags, like `$link` */ 106 | export type HTMLTags = keyof HTMLElementTagNameMap | 'strike' | `$${string}`; 107 | 108 | export interface IDomParseTreeNode extends IWikiASTNode { 109 | closeTagEnd?: number; 110 | closeTagStart?: number; 111 | openTagEnd?: number; 112 | openTagStart?: number; 113 | tag: HTMLTags; 114 | // TODO: only see `link` using this, probably all widgets is using this? 115 | type: 'element' | 'link'; 116 | } 117 | export interface ICodeBlockParseTreeNode extends IWikiASTNode { 118 | attributes: { 119 | code?: { 120 | type: 'string'; 121 | value: string; 122 | }; 123 | language?: { 124 | type: 'string'; 125 | value: string; 126 | }; 127 | } & IWikiASTNode['attributes']; 128 | type: 'codeblock'; 129 | } 130 | export interface IMacroParameterCallParseTreeNode extends IWikiASTNode { 131 | name?: string; 132 | type: 'macro-parameter'; 133 | value: string; 134 | } 135 | export interface IMacroCallParseTreeNode extends IWikiASTNode { 136 | name?: string; 137 | params?: IMacroParameterCallParseTreeNode[]; 138 | /** `tag: '$macrocall',` */ 139 | tag?: string; 140 | type: 'macrocall'; 141 | } 142 | export interface IMacroParseTreeNode extends IWikiASTNode { 143 | name: string; 144 | type: 'macro'; 145 | value: IMacroCallParseTreeNode; 146 | } 147 | export interface ICustomParseTreeNode extends IWikiASTNode { 148 | params: IMacroParameterCallParseTreeNode[]; 149 | tag?: string; 150 | text?: string; 151 | type: string; 152 | } 153 | export type IParseTreeNode = 154 | | IWikiASTNode 155 | | IWikiASTTextNode 156 | | IDomParseTreeNode 157 | | IMacroParameterCallParseTreeNode 158 | | IMacroCallParseTreeNode 159 | | ITextParseTreeNode 160 | | IImageParseTreeNode 161 | | ITranscludeParseTreeNode 162 | | ITiddlerParseTreeNode 163 | | ICodeBlockParseTreeNode 164 | | ICustomParseTreeNode 165 | | IMacroParseTreeNode 166 | | IParseTreeAttribute; 167 | 168 | export interface FilterParseTreeNode { 169 | operators: FilterOperatorParseTreeNode[]; 170 | prefix: string; 171 | } 172 | export interface FilterOperatorParseTreeNode { 173 | operands: FilterOperandParseTreeNode[]; 174 | operator: string; 175 | suffix: string; 176 | suffixes: string[][]; 177 | } 178 | export interface FilterOperandParseTreeNode { 179 | text: string; 180 | } 181 | 182 | export interface Wiki { 183 | /** 184 | * Parse a filter string 185 | */ 186 | parseFilter(filter: string): FilterParseTreeNode[]; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/modules/utils/filesystem.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | /** 3 | * File information for saving a tiddler 4 | */ 5 | export interface IFileInfo { 6 | filepath: string; 7 | type: string; 8 | hasMetaFile: boolean; 9 | isEditableFile?: boolean; 10 | originalpath?: string; 11 | overwrite?: boolean; 12 | writeError?: boolean; 13 | encoding?: string; 14 | } 15 | } 16 | 17 | declare module '$:/core/modules/utils/filesystem.js' { 18 | import type { IFileInfo, Tiddler, Wiki } from 'tiddlywiki'; 19 | 20 | /** 21 | * Return the subdirectories of a path 22 | * @param directoryPath - The path to the directory 23 | * @returns An array of subdirectories 24 | * @description 返回路径的子目录 25 | */ 26 | export function getSubdirectories(directoryPath: string): string[]; 27 | 28 | /** 29 | * Recursively (and synchronously) copy a directory and all its content 30 | * @param srcPath - The source path of the directory to copy 31 | * @param directoryPath - The destination path of the directory to copy 32 | * @returns An error message if there is an error, otherwise null 33 | * @description 递归地(同步地)复制目录及其所有内容 34 | */ 35 | export function copyDirectory(sourcePath: string, directoryPath: string): string; 36 | 37 | /** 38 | * Copy a file 39 | * @param srcPath - The source path of the file to copy 40 | * @param directoryPath - The destination path of the file to copy 41 | * @returns An error message if there is an error, otherwise null 42 | * @description 复制文件 43 | */ 44 | export function copyFile(sourcePath: string, directoryPath: string): string; 45 | 46 | /** 47 | * Remove trailing path separator 48 | * @param directoryPath - The directory path to remove the trailing separator from 49 | * @returns The directory path without the trailing separator 50 | * @description 移除路径末尾的分隔符 51 | */ 52 | export function removeTrailingSeparator(directoryPath: string): string; 53 | 54 | /** 55 | * Recursively create a directory 56 | * @param directoryPath - The path of the directory to create 57 | * @returns An error message if there is an error, otherwise null 58 | * @description 递归地创建目录 59 | */ 60 | export function createDirectory(directoryPath: string): string; 61 | 62 | /** 63 | * Recursively create directories needed to contain a specified file 64 | * @param filePath - The path of the file to create directories for 65 | * @returns An error message if there is an error, otherwise null 66 | * @description 递归地创建包含指定文件的目录 67 | */ 68 | export function createFileDirectories(filePath: string): string; 69 | 70 | /** 71 | * Recursively delete a directory 72 | * @param directoryPath - The path of the directory to delete 73 | * @returns An error message if there is an error, otherwise null 74 | * @description 递归地删除目录 75 | */ 76 | export function deleteDirectory(directoryPath: string): string; 77 | 78 | /** 79 | * Check if a path identifies a directory 80 | * @param directoryPath - The path to check 81 | * @returns True if the path identifies a directory, false otherwise 82 | * @description 检查路径是否标识目录 83 | */ 84 | export function isDirectory(directoryPath: string): boolean; 85 | 86 | /** 87 | * Check if a path identifies a directory that is empty 88 | * @param directoryPath - The path to check 89 | * @returns True if the path identifies an empty directory, false otherwise 90 | * @description 检查路径是否标识空目录 91 | */ 92 | export function isDirectoryEmpty(directoryPath: string): boolean; 93 | 94 | /** 95 | * Recursively delete a tree of empty directories 96 | * @param directoryPath - The path of the directory to delete 97 | * @param callback - A callback function to call when the operation is complete 98 | * @description 递归地删除空目录树 99 | */ 100 | export function deleteEmptyDirectories( 101 | directoryPath: string, 102 | callback: (error: Error | null) => void, 103 | ): void; 104 | 105 | /** 106 | * Generate a fileInfo object for saving a tiddler 107 | * @param tiddler - The tiddler to generate the fileInfo for 108 | * @param options - Options for generating the fileInfo 109 | * @returns A fileInfo object 110 | * @description 生成用于保存 tiddler 的 fileInfo 对象 111 | */ 112 | export function generateTiddlerFileInfo( 113 | tiddler: Tiddler, 114 | options: { 115 | directory: string; 116 | extFilters?: string[]; 117 | fileInfo?: IFileInfo; 118 | pathFilters?: string[]; 119 | wiki?: Wiki; 120 | }, 121 | ): IFileInfo; 122 | 123 | /** 124 | * Generate the file extension for saving a tiddler 125 | * @param title - The title of the tiddler 126 | * @param options - Options for generating the file extension 127 | * @returns The file extension 128 | * @description 生成用于保存 tiddler 的文件扩展名 129 | * 可选项包括: 130 | * extFilters:用于生成扩展名的可选过滤器数组 131 | * wiki:用于评估 extFilters 的可选 wiki 132 | */ 133 | export function generateTiddlerExtension( 134 | title: string, 135 | options: { 136 | extFilters?: string[]; 137 | wiki?: Wiki; 138 | }, 139 | ): string; 140 | /** 141 | * Generate the filepath for saving a tiddler 142 | * Options include: 143 | * * extension: file extension to be added the finished filepath 144 | * * directory: absolute path of root directory to which we are saving 145 | * * pathFilters: optional array of filters to be used to generate the base path 146 | * * wiki: optional wiki for evaluating the pathFilters 147 | * * fileInfo: an existing fileInfo object to check against 148 | * * fileInfo.overwrite: if true, turns off filename clash numbers (defaults to false) 149 | */ 150 | export function generateTiddlerFilepath( 151 | title: string, 152 | options: { 153 | directory?: string; 154 | extension?: string; 155 | extFilters?: string[]; 156 | fileInfo?: IFileInfo; 157 | pathFilters?: string[]; 158 | wiki?: Wiki; 159 | }, 160 | ): string; 161 | 162 | /** 163 | * Save a tiddler to a file described by the fileInfo 164 | * @param tiddler - The tiddler to save 165 | * @param fileInfo - File information including filepath, type, and hasMetaFile flag 166 | * @param callback - Callback function called when save is complete 167 | * @description 将 tiddler 保存到由 fileInfo 描述的文件 168 | */ 169 | export function saveTiddlerToFile( 170 | tiddler: Tiddler, 171 | fileInfo: IFileInfo, 172 | callback: (error: Error | null, fileInfo?: IFileInfo) => void, 173 | ): void; 174 | 175 | /** 176 | * Save a tiddler to a file described by the fileInfo (synchronous) 177 | * @param tiddler - The tiddler to save 178 | * @param fileInfo - File information including filepath, type, and hasMetaFile flag 179 | * @returns The fileInfo object 180 | * @description 同步地将 tiddler 保存到由 fileInfo 描述的文件 181 | */ 182 | export function saveTiddlerToFileSync(tiddler: Tiddler, fileInfo: IFileInfo): IFileInfo; 183 | 184 | /** 185 | * Delete a file described by the fileInfo if it exists 186 | * @param fileInfo - File information including filepath and hasMetaFile flag 187 | * @param callback - Callback function called when delete is complete 188 | * @description 删除由 fileInfo 描述的文件(如果存在) 189 | */ 190 | export function deleteTiddlerFile( 191 | fileInfo: IFileInfo, 192 | callback: (error: Error | null, fileInfo?: IFileInfo) => void, 193 | ): void; 194 | 195 | /** 196 | * Cleanup old files on disk by comparing adaptor info and boot info 197 | * @param options - Options object containing adaptorInfo, bootInfo, and title 198 | * @param callback - Callback function called when cleanup is complete 199 | * @description 通过比较 adaptor 信息和启动信息来清理磁盘上的旧文件 200 | */ 201 | export function cleanupTiddlerFiles( 202 | options: { 203 | adaptorInfo?: IFileInfo; 204 | bootInfo?: IFileInfo; 205 | title?: string; 206 | }, 207 | callback: (error: Error | null, fileInfo?: IFileInfo) => void, 208 | ): void; 209 | } 210 | -------------------------------------------------------------------------------- /src/modules/filters/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | /** 3 | * # Usage 4 | * 5 | * ```ts 6 | * const yourFilter: IFilterOperator = (source,operator) => { 7 | * var results = []; 8 | * source(function(tiddler,title) { 9 | * if (!tiddler.fields['xxx']) return; 10 | * results.push(title); 11 | * }); 12 | * return results; 13 | * } 14 | * ``` 15 | * 16 | * # Overview 17 | 18 | Filter operators are modules (tiddlers of type `application/javascript`) with their `module-type` field set to `filteroperator`, exporting one or more functions implementing a filter. 19 | 20 | Each function will be called with three arguments: 21 | 22 | * A [tiddler iterator](#Tiddler%20Iterators) representing the results of the previous filter step (or all tiddlers, if this filter appears first in an expression), conventionally named `source`. 23 | * An object, conventionally called `operator`, representing the arguments for this filter step, with the following keys: 24 | 25 | * *operator*: the name of the filter operator specified in the [WikiText](#WikiText); 26 | * *operand*: the operand for the filter step (as a string; if the filter specified it in angle brackets or braces, the text reference or variable name will have already been resolved); 27 | * *prefix*: (optional) a string containing a single exclamation mark if the filter operator is to be negated; 28 | * *suffix*: (optional) a string containing an additional filter argument (typically a tiddler field name) following the filter name (separated by a colon in the filter syntax); 29 | * *regexp*: (optional, deprecated) used instead of *operand* if the filter operand is a regexp. 30 | * An object, conventionally called `options`, with the following keys: 31 | 32 | * *wiki*: The `$tw.Wiki` object; 33 | * *widget*: (optional) a widget node. 34 | 35 | The function should return either a new [tiddler iterator](#Tiddler%20Iterators), or else an array of tiddler titles (as strings). The underlying filter mechanism will convert back and forth between iterators and arrays as needed. 36 | 37 | # References 38 | 39 | There are several filter operators built into the core which can serve as a jumping off point for your own filter operators: 40 | 41 | [https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/filters](https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/filters) 42 | 43 | # Example 44 | 45 | Suppose we want to make a filter operator that returns every other tiddler from the input list. A typical invocation might look like `[tags[interesting]everyother[]]`. 46 | 47 | We make a new tiddler, set its `type` and `module-type` appropriately, and begin writing the code: 48 | 49 | ```js 50 | (function(){ 51 | "use strict"; 52 | exports.everyother = function(source, operator, options) { 53 | // TODO 54 | } 55 | })(); 56 | ``` 57 | 58 | For the example filter syntax, our function will be called with 59 | 60 | * source: an iterator over all the tiddlers tagged as `interesting` 61 | * operator: an object `{operator: "everyother", operand: ""}` 62 | * options: an object with the current Wiki object and a widget object, neither of which we need 63 | 64 | As is usually the case, we don't care about `operator.operator` here (since that information has already been used to look up our function); we also don't care about `operator.operand`, since there is no meaningful operand for this operation. 65 | 66 | We could implement the operator by iterating over the input tiddlers and explicitly building a result array of titles: 67 | 68 | ```js 69 | (function(){ 70 | "use strict"; 71 | exports.everyother = function(source, operator, options) { 72 | var result = []; 73 | var include = true; 74 | source(function(tiddler, title) { 75 | if (include) { result.push(title); } 76 | include = !include; 77 | }); 78 | return result; 79 | } 80 | })(); 81 | ``` 82 | 83 | That is, we supply a callback to `source` that negates `include` each time through (in order to grab every other result) and pushes the `title` of every other tiddler onto the result. 84 | 85 | Alternatively, we can return our own iterator, by returning a function that accepts a similar callback and only calls it on every other tiddler: 86 | 87 | ```js 88 | (function(){ 89 | "use strict"; 90 | exports.everyother = function(source, operator, options) { 91 | return function(callback) { 92 | var include = true; 93 | source(function(tiddler, title) { 94 | if (include) { callback(tiddler, title); } 95 | include = !include; 96 | }); 97 | }; 98 | } 99 | })(); 100 | ``` 101 | 102 | Either way, we could interpret the `!` flag on the filter, if present, to mean that we want the *other* half of the tiddlers, by using it to set the initial value of `include`: `var include = operator.prefix !== "!";` 103 | 104 | # Filter Behaviour 105 | 106 | As with [JavaScript Macros](#JavaScript%20Macros), filter operators should not make modifications to tiddlers, but only return a list of tiddlers or a tiddler iterator. 107 | 108 | */ 109 | export type IFilterOperator = ( 110 | source: (iter: SourceIterator) => void, 111 | operator: IFilterOperatorParameterOperator, 112 | ) => string[] | ((iter: SourceIterator) => void); 113 | 114 | /** 115 | * A [tiddler iterator](#Tiddler%20Iterators) representing the results of the previous filter step (or all tiddlers, if this filter appears first in an expression), conventionally named `source`. 116 | * 117 | * For Example, with an iterator over all the tiddlers tagged as `interesting`, use it like this: 118 | * 119 | * ```js 120 | * var result = []; 121 | var include = true; 122 | source(function(tiddler, title) { 123 | if (include) { result.push(title); } 124 | include = !include; 125 | }); 126 | ``` 127 | 128 | Construct the iterator using $tw.wiki.makeTiddlerIterator 129 | */ 130 | export type SourceIterator = (tiddler: Tiddler | undefined, title: string) => void; 131 | export interface ISearchOptions { 132 | /** If true, forces all but regexp searches to be anchored to the start of text */ 133 | anchored?: boolean; 134 | /** If true forces a case sensitive search */ 135 | caseSensitive?: boolean; 136 | /** An array of tiddler titles to exclude from the search */ 137 | exclude?: string[]; 138 | /** If true, the field options are inverted to specify the fields that are not to be searched */ 139 | excludeField?: boolean; 140 | /** If specified, restricts the search to the specified field, or an array of field names */ 141 | field?: string | string[]; 142 | /** If true returns tiddlers that do not contain the specified string */ 143 | invert?: boolean; 144 | /** searches for literal string */ 145 | literal?: boolean; 146 | /** an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title) */ 147 | source?: (iter: SourceIterator) => void; 148 | /** same as literal except runs of whitespace are treated as a single space */ 149 | whitespace?: boolean; 150 | /** (default) treats search string as a list of tokens, and matches if all tokens are found, regardless of adjacency or ordering */ 151 | words?: boolean; 152 | } 153 | 154 | export interface IFilterOperatorParameterOperator { 155 | /** the operand for the filter step (as a string; if the filter specified it in angle brackets or braces, the text reference or letiable name will have already been resolved); */ 156 | operand: string; 157 | /** Filter can have one or more operands, like `charcode[13],[10]`. */ 158 | operands: string[]; 159 | /** the name of the filter operator specified in the WikiText; */ 160 | operator: string; 161 | /** (optional) a string containing a single exclamation mark if the filter operator is to be negated; */ 162 | prefix?: string; 163 | /** (optional, deprecated) used instead of `operand` if the filter operand is a regexp. */ 164 | regexp?: string; 165 | /** (optional) a string containing an additional filter argument (typically a tiddler field name) following the filter name (separated by a colon in the filter syntax); */ 166 | suffix?: string; 167 | /** multiple suffix 168 | * for example, in `search::[]`, you will get `` as suffixes[0], and `` as suffixes[1] 169 | */ 170 | suffixes?: string[][]; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/modules/utils/dom/dom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '$:/core/modules/utils/dom.js' { 2 | /** 3 | * Alternative to `element.classList.add`, add a css class name to an element, see issue for detail. 4 | * @link https://github.com/Jermolene/TiddlyWiki5/issues/6475 5 | * @param element 6 | * @param className 7 | */ 8 | export function addClass(element: Element, className: string): void; 9 | 10 | /** 11 | * Alternative to `element.classList.remove`, remove a css class name from an element, see issue for detail. 12 | * @link https://github.com/Jermolene/TiddlyWiki5/issues/6475 13 | * @param element 14 | * @param className 15 | */ 16 | export function removeClass(element: Element, className: string): void; 17 | 18 | /** 19 | * Attach specified event handlers to a DOM node 20 | * @param domNode: where to attach the event handlers 21 | * @param events: array of event handlers to be added (see below) 22 | * Each entry in the events array is an object with these properties: 23 | * * name: event name of `addEventListener` 24 | * * handlerFunction: optional event handler function 25 | * * handlerObject: optional event handler object 26 | * * handlerMethod: optionally specifies object handler method name (defaults to `handleEvent`) 27 | */ 28 | export function addEventListeners( 29 | domNode: Element, 30 | events: Array<{ 31 | handlerFunction?: (event: MouseEvent) => void; 32 | handlerMethod?: string; 33 | handlerObject?: Widget; 34 | name: string; 35 | }>, 36 | ): void; 37 | 38 | /** 39 | * Determines whether element 'a' contains element 'b'. 40 | * @param a The parent element. 41 | * @param b The child element. 42 | * @returns True if 'a' contains 'b', otherwise false. 43 | */ 44 | export function domContains(a: Element, b: Element): boolean; 45 | 46 | /** 47 | * Checks if a node matches a specific CSS selector. 48 | * @param node The DOM node to check. 49 | * @param selector The CSS selector to match against. 50 | * @returns True if the node matches the selector, otherwise false. 51 | */ 52 | export function domMatchesSelector(node: Element, selector: string): boolean; 53 | 54 | /** 55 | * Safely sets the selection range in an input or textarea element. 56 | * @param node The DOM node (input or textarea). 57 | * @param start The start position of the selection. 58 | * @param end The end position of the selection. 59 | * @param direction The direction of the selection. 60 | */ 61 | export function setSelectionRangeSafe( 62 | node: HTMLInputElement | HTMLTextAreaElement, 63 | start: number, 64 | end: number, 65 | direction?: 'forward' | 'backward' | 'none', 66 | ): void; 67 | 68 | /** 69 | * Selects text in an input or textarea by position. 70 | * @param node The DOM node (input or textarea). 71 | * @param selectFromStart Position from the start of the text. 72 | * @param selectFromEnd Position from the end of the text. 73 | */ 74 | export function setSelectionByPosition( 75 | node: HTMLInputElement | HTMLTextAreaElement, 76 | selectFromStart: number, 77 | selectFromEnd: number, 78 | ): void; 79 | 80 | /** 81 | * Removes all child nodes of a given DOM node. 82 | * @param node The parent DOM node. 83 | */ 84 | export function removeChildren(node: Node): void; 85 | 86 | /** 87 | * Checks if an element has a specific class. 88 | * @param el The element to check. 89 | * @param className The class name to look for. 90 | * @returns True if the element has the class, otherwise false. 91 | */ 92 | export function hasClass(element: Element, className: string): boolean; 93 | 94 | /** 95 | * Toggles a class on an element based on a given condition. 96 | * @param el The element to toggle the class on. 97 | * @param className The class name to toggle. 98 | * @param status If true, adds the class; if false, removes it. If undefined, toggles based on current state. 99 | */ 100 | export function toggleClass( 101 | element: Element, 102 | className: string, 103 | status?: boolean, 104 | ): void; 105 | 106 | /** 107 | * Gets the first parent element that has scrollbars or uses the body as a fallback. 108 | * @param el The starting element to search from. 109 | * @returns The first scrollable parent element, or the body if none are found. 110 | */ 111 | export function getScrollContainer(element: Element): Element; 112 | 113 | /** 114 | * Get the scroll position of the viewport. 115 | * @param srcWindow The source window to get the scroll position from, defaults to the current window if not specified. 116 | * @returns An object with 'x' and 'y' properties representing the horizontal and vertical scroll positions in pixels. 117 | */ 118 | export function getScrollPosition(sourceWindow?: Window): { 119 | x: number; 120 | y: number; 121 | }; 122 | 123 | /** 124 | * Adjusts the height of a textarea to fit its content, preserving scroll position, and returns the new height. 125 | * @param domNode The DOM node (textarea) to resize. 126 | * @param minHeight The minimum height to use for the textarea. 127 | * @returns The new height of the textarea. 128 | */ 129 | export function resizeTextAreaToFit( 130 | domNode: HTMLTextAreaElement, 131 | minHeight: string, 132 | ): number; 133 | 134 | /** 135 | * Gets the bounding rectangle of an element in absolute page coordinates. 136 | * @param element The element to get the bounding rectangle for. 137 | * @returns An object representing the bounding rectangle with properties: left, width, right, top, height, bottom. 138 | */ 139 | export function getBoundingPageRect(element: Element): { 140 | bottom: number; 141 | height: number; 142 | left: number; 143 | right: number; 144 | top: number; 145 | width: number; 146 | }; 147 | 148 | /** 149 | * Saves a named password in the browser. 150 | * @param name The name for the password. 151 | * @param password The password to save. 152 | */ 153 | export function savePassword(name: string, password: string): void; 154 | 155 | /** 156 | * Retrieves a named password from the browser. 157 | * @param name The name of the password to retrieve. 158 | * @returns The password, or an empty string if not found. 159 | */ 160 | export function getPassword(name: string): string; 161 | 162 | /** 163 | * Forces layout of a DOM node and its descendants. 164 | * @param element The DOM element to force layout on. 165 | */ 166 | export function forceLayout(element: Element): void; 167 | 168 | /** 169 | * Pulses an element for debugging purposes. 170 | * @param element The element to pulse. 171 | */ 172 | export function pulseElement(element: Element): void; 173 | 174 | /** 175 | * Get the computed styles applied to an element as an array of strings of individual CSS properties. 176 | * @param domNode The DOM node to get the computed styles for. 177 | * @returns An array of strings, each representing an individual CSS property and its value. 178 | */ 179 | export function getComputedStyles(domNode: Element): string[]; 180 | 181 | /** 182 | * Applies a set of styles to a DOM node, passed as an array of strings of individual CSS properties. 183 | * @param domNode The DOM node to apply the styles to. 184 | * @param styleDefs An array of strings, each representing an individual CSS property and its value. 185 | */ 186 | export function setStyles(domNode: Element, styleDefs: string[]): void; 187 | 188 | /** 189 | * Copies the computed styles from a source element to a destination element. 190 | * @param srcDomNode The source DOM node. 191 | * @param dstDomNode The destination DOM node. 192 | */ 193 | // eslint-disable-next-line unicorn/prevent-abbreviations 194 | export function copyStyles(sourceDomNode: Element, dstDomNode: Element): void; 195 | 196 | /** 197 | * Copies plain text to the clipboard on browsers that support it. 198 | * @param text The text to copy. 199 | * @param options Options for copying, including 'doNotNotify' to suppress notifications. 200 | * @returns True if the operation succeeded, otherwise false. 201 | */ 202 | export function copyToClipboard( 203 | text: string, 204 | options?: { 205 | doNotNotify?: boolean; 206 | successNotification?: string; // default is $:/language/Notifications/CopiedToClipboard/Succeeded 207 | failureNotification?: string; 208 | }, 209 | ): boolean; 210 | 211 | /** 212 | * Gets the path part of the current location. 213 | * @returns The path part of the current location URL. 214 | */ 215 | export function getLocationPath(): string; 216 | 217 | /** 218 | * Collects DOM variables from an event. 219 | * @param selectedNode The node selected. 220 | * @param domNode The DOM node catching the event. 221 | * @param event The event object. 222 | * @returns An object containing variables derived from the DOM and event. 223 | */ 224 | export function collectDOMVariables( 225 | selectedNode: Element, 226 | domNode: Element, 227 | event: Event, 228 | ): Record; 229 | 230 | /** 231 | * Safely executes a querySelector, avoiding exceptions on invalid selectors. 232 | * @param selector The CSS selector to query. 233 | * @param baseElement The base element to start the query from, defaults to document. 234 | * @returns The first element matching the selector, or null if none are found or the selector is invalid. 235 | */ 236 | export function querySelectorSafe( 237 | selector: string, 238 | baseElement?: Element, 239 | ): Element | null; 240 | 241 | /** 242 | * Safely executes a querySelectorAll, avoiding exceptions on invalid selectors. 243 | * @param selector The CSS selector to query. 244 | * @param baseElement The base element to start the query from, defaults to document. 245 | * @returns A NodeList of elements matching the selector, or an empty NodeList if none are found or the selector is invalid. 246 | */ 247 | export function querySelectorAllSafe( 248 | selector: string, 249 | baseElement?: Element, 250 | ): NodeList; 251 | } 252 | -------------------------------------------------------------------------------- /src/boot/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface IPluginInfo { 3 | [pluginProperty: string]: string; 4 | dependents: string; 5 | 'plugin-type': string; 6 | text: string; 7 | type: 'application/json'; 8 | version: string; 9 | } 10 | 11 | export interface ILanguage { 12 | getString(key: string, options: { variables: { title: string } }): string; 13 | } 14 | 15 | export interface IMacro { 16 | name: string; 17 | params: unknown[][]; 18 | run: (...arguments_: unknown[]) => unknown; 19 | } 20 | 21 | export type IWikiInfo = Record; 22 | 23 | export interface ITiddlersInFile { 24 | filepath?: string; 25 | hasMetaFile?: boolean; 26 | isEditableFile?: boolean; 27 | tiddlers: ITiddlerFields[]; 28 | type?: string | null; 29 | } 30 | 31 | export interface IBootFilesIndexItem { 32 | filepath: string; 33 | hasMetaFile: boolean; 34 | isEditableFile: boolean; 35 | type: string; 36 | } 37 | 38 | /** 39 | * Key is `tiddlerTitle: string;` 40 | */ 41 | export type IBootFilesIndex = Record; 42 | 43 | export interface IStartUpOption { 44 | bootPath?: string; 45 | callback?: () => unknown; 46 | } 47 | 48 | export interface IBoot { 49 | argv: string[]; 50 | boot: (callback?: () => void) => void; 51 | /** Absolute path to the boot directory (Node.js only) */ 52 | bootPath?: string; 53 | /** Absolute path to the core directory (Node.js only) */ 54 | corePath?: string; 55 | /** Absolute path to the core-server directory (Node.js only) */ 56 | coreServerPath?: string; 57 | decryptEncryptedTiddlers: (callback: () => void) => void; 58 | disabledStartupModules?: string[]; 59 | doesTaskMatchPlatform: (taskModule: unknown) => boolean; 60 | excludeRegExp: RegExp; 61 | execStartup: (options: IStartUpOption) => void; 62 | /** 63 | * Parse any extra plugin references from `$tw.boot.argv[0]` that with `+` prefix. 64 | */ 65 | extraPlugins: string[]; 66 | files: IBootFilesIndex; 67 | initStartup: (options: IStartUpOption) => void; 68 | isStartupTaskEligible: (taskModule: unknown) => boolean; 69 | loadStartup: (options: IStartUpOption) => void; 70 | log: (logString: string) => void; 71 | logMessages: string[]; 72 | remainingStartupModules?: unknown[]; 73 | startup: (options: IStartUpOption) => void; 74 | /** Default boot tasks */ 75 | tasks: { 76 | readBrowserTiddlers: boolean; 77 | trapErrors: boolean; 78 | }; 79 | /** Exist in nodejs wiki, Load the tiddlers from the wiki directory */ 80 | wikiInfo?: ITiddlyWikiInfoJSON; 81 | /** Exist in nodejs wiki, absolute path of wiki root folder */ 82 | wikiPath?: string; 83 | /** Exist in nodejs wiki, usually is `./tiddlers` */ 84 | wikiTiddlersPath?: string; 85 | } 86 | 87 | export interface ITiddlyWiki { 88 | Story: typeof Story; 89 | Syncer: new() => Syncer; 90 | Tiddler: typeof Tiddler; 91 | Wiki: typeof Wiki; 92 | /** 93 | * Add another unload task 94 | * @param task - Function to be called on unload 95 | */ 96 | addUnloadTask(task: () => void): void; 97 | boot: IBoot; 98 | 99 | browser: null | { 100 | is?: { 101 | android?: boolean; 102 | bada?: boolean; 103 | blackberry?: boolean; 104 | chrome?: boolean; 105 | firefox?: boolean; 106 | firefoxos?: boolean; 107 | gecko?: boolean; 108 | ios?: boolean; 109 | ipad?: boolean; 110 | iphone?: boolean; 111 | mobile?: boolean; 112 | name?: boolean; 113 | opera?: boolean; 114 | phantomjs?: boolean; 115 | safari?: boolean; 116 | sailfish?: boolean; 117 | seamonkey?: boolean; 118 | silk?: boolean; 119 | tizen?: boolean; 120 | version?: boolean; 121 | webkit?: boolean; 122 | webos?: boolean; 123 | windowsphone?: boolean; 124 | }; 125 | /** 126 | * @deprecated 127 | * Install `$:/plugins/tiddlywiki/browser-sniff` to use `browser.is` 128 | */ 129 | isFirefox: boolean; 130 | /** 131 | * @deprecated 132 | * Install `$:/plugins/tiddlywiki/browser-sniff` to use `browser.is` 133 | */ 134 | isIE: boolean; 135 | }; 136 | config: IConfig; 137 | crypto: Crypto; 138 | /** 139 | * Check for this window being the source of the drag. If true, some drop target widget will stop responding to the drop event, so you can handle drop event in your own widget. 140 | * Used by `DropZoneWidget.prototype.handleDropEvent` 141 | */ 142 | dragInProgress?: boolean; 143 | fakeDocument: IFakeDocument; 144 | /** 145 | * Find a library item (plugin/theme/language) by name in the given search paths 146 | * @param name - Name of the library item to find 147 | * @param paths - Array of file paths to search for it 148 | * @returns The path of the library item folder, or null if not found 149 | */ 150 | findLibraryItem(name: string, paths: string[]): string | null; 151 | /** 152 | * Get the search paths for library items (plugins/themes/languages) 153 | * @param libraryPath - Path of library folder relative to core path 154 | * @param environmentVariable - Optional environment variable name for additional paths 155 | * @returns Array of search paths 156 | */ 157 | getLibraryItemSearchPaths(libraryPath: string, environmentVariable?: string): string[]; 158 | /** 159 | * Global Hooks mechanism which allows plugins to modify default functionality 160 | */ 161 | hooks: IHooks; 162 | keyboardManager: KeyboardManager; 163 | language: ILanguage; 164 | /** 165 | * Load the metadata fields in the .meta file corresponding to a particular file 166 | * @param filepath - The path to the file 167 | * @returns The metadata fields or null if no .meta file exists 168 | */ 169 | loadMetadataForFile(filepath: string): ITiddlerFields | null; 170 | /** 171 | * Load a plugin by name from the given search paths 172 | * @param name - Name of the plugin (e.g., "tiddlywiki/filesystemadaptor") 173 | * @param paths - Array of file paths to search for it 174 | */ 175 | loadPlugin(name: string, paths: string[]): void; 176 | /** 177 | * Load the tiddlers from a plugin folder, and package them up into a proper JSON plugin tiddler 178 | * @param filepath - Path to the plugin folder 179 | * @param excludeRegExp - Optional regex for files to exclude 180 | * @returns Plugin info object or null if not a valid plugin 181 | */ 182 | loadPluginFolder( 183 | filepath: string, 184 | excludeRegExp?: RegExp, 185 | ): IPluginInfo | null; 186 | /** 187 | * Load multiple plugins 188 | * @param plugins - Array of plugin names (e.g., ["tiddlywiki/filesystemadaptor"]) 189 | * @param libraryPath - Path of library folder for these plugins (relative to core path) 190 | * @param environmentVariable - Environment variable name for these plugins 191 | */ 192 | loadPlugins(plugins: string[], libraryPath: string, environmentVariable?: string): void; 193 | /** 194 | * Load tiddlers in browser environment 195 | */ 196 | loadTiddlersBrowser(): void; 197 | /** 198 | * Load the tiddlers contained in a particular file (and optionally extract fields from the accompanying .meta file) 199 | * @param filepath - The path to the file to load 200 | * @param defaultFields - Optional default fields to apply to loaded tiddlers 201 | * @returns Object containing filepath, type, tiddlers array, and hasMetaFile flag 202 | */ 203 | loadTiddlersFromFile( 204 | filepath: string, 205 | defaultFields?: Record, 206 | ): ITiddlersInFile; 207 | /** 208 | * Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files 209 | * @param filepath - The path to load from 210 | * @param excludeRegExp - Optional regex for files to exclude 211 | * @returns Array of objects containing filepath, type, tiddlers array, and hasMetaFile flag 212 | * @description Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property. 213 | */ 214 | loadTiddlersFromPath( 215 | filepath: string, 216 | excludeRegExp?: RegExp, 217 | ): ITiddlersInFile[]; 218 | /** 219 | * Load all the tiddlers defined by a `tiddlywiki.files` specification file 220 | * @param filepath - Pathname of the directory containing the specification file 221 | * @param excludeRegExp - Optional regex for files to exclude 222 | * @returns Array of objects containing filepath, type, tiddlers array, and hasMetaFile flag 223 | */ 224 | loadTiddlersFromSpecification( 225 | filepath: string, 226 | excludeRegExp?: RegExp, 227 | ): ITiddlersInFile[]; 228 | 229 | /** 230 | * Load tiddlers in Node.js environment 231 | * @description Load boot tiddlers, core tiddlers, extra plugins, and wiki tiddlers 232 | */ 233 | loadTiddlersNode(): void; 234 | 235 | /** 236 | * Load wiki tiddlers from a wiki directory 237 | * @param wikiPath - Path to the wiki directory 238 | * @param options - Options for loading 239 | * @param options.parentPaths - Array of parent paths that we mustn't recurse into 240 | * @param options.readOnly - True if the tiddler file paths should not be retained 241 | * @returns Wiki info object or null if no tiddlywiki.info file exists 242 | */ 243 | loadWikiTiddlers( 244 | wikiPath: string, 245 | options?: { parentPaths?: string[]; readOnly?: boolean }, 246 | ): IWikiInfo | null; 247 | 248 | locationHash: string; 249 | 250 | macros: Record; 251 | 252 | modal: Modal; 253 | 254 | modules: IModules; 255 | 256 | /** NodeJS features, if tw isn't running on a NodeJS environment, the value will be `null` */ 257 | node: null | Record; 258 | /** Broswer features, if tw isn't running on a browser environment, the value will be `null` */ 259 | nodeWebKit: null | Record; 260 | notifier: Notifier; 261 | packageInfo: Record; 262 | passwordPrompt: PasswordPrompt; 263 | platform: { 264 | isLinux: boolean; 265 | isMac: boolean; 266 | isWindows: boolean; 267 | }; 268 | /** 269 | * Convenience function for pushing a tiddler onto the preloading array. 270 | * @param fields - The fields of the tiddler to push. 271 | * @description 方便地将一个 tiddler 推入预加载数组中。 272 | */ 273 | preloadTiddler(fields: Record): void; 274 | /** 275 | * Convenience function for pushing an array of tiddlers onto the preloading array. 276 | * @param fieldsArray - The array of tiddlers to push. 277 | * @description 方便地将若干 tiddler 数组推入预加载数组中。 278 | */ 279 | preloadTiddlerArray(fieldsArray: Array>): void; 280 | /** External JavaScript can populate this array before calling boot.js in order to preload tiddlers */ 281 | preloadTiddlers: Record>; 282 | rootWidget: Widget; 283 | safeMode: boolean; 284 | syncadaptor?: SyncAdaptor; 285 | 286 | /** 287 | * Presents when we have $tw.syncadaptor 288 | */ 289 | syncer?: Syncer; 290 | utils: IUtilities; 291 | version: string; 292 | wiki: Wiki; 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | import type { Logger } from '$:/core/modules/utils/logger.js'; 3 | import { Spread } from 'type-fest'; 4 | export type TWDocument = Document | IFakeDocument; 5 | export type TWElement = Element; 6 | export type TWDOMElement = TWElement; 7 | export type ITWUtilities = IUtilities; 8 | 9 | export interface IDomMakerOptions { 10 | /** 11 | * @en 12 | * hashmap of attribute values 13 | * @zh 14 | * 属性值的 map 15 | * 16 | * @type {Record} 17 | * @memberof IDomMakerOptions 18 | */ 19 | attributes?: Record; 20 | 21 | /** 22 | * @en 23 | * array of further child nodes 24 | * @zh 25 | * 其他子节点的数组 26 | * 27 | * @type {TWElement[]} 28 | * @memberof IDomMakerOptions 29 | */ 30 | children?: TWElement[]; 31 | 32 | /** 33 | * @en 34 | * class name(s) 35 | * @zh 36 | * 元素的 class,多个则以空格分隔 37 | * 38 | * @type {string} 39 | * @memberof IDomMakerOptions 40 | */ 41 | class?: string; 42 | 43 | /** 44 | * @en 45 | * defaults to current document 46 | * @zh 47 | * 默认为当前 document 48 | * 49 | * @type {TWDocument} 50 | * @memberof IDomMakerOptions 51 | */ 52 | document?: TWDocument; 53 | 54 | /** 55 | * @en 56 | * array of event listeners (this option won't work until `$tw.utils.addEventListeners()` has been loaded) 57 | * @zh 58 | * 事件监听器的数组(这个选项在`$tw.utils.addEventListeners()`被加载之前不会起作用)。 59 | * 60 | * @type {EventListener[]} 61 | * @memberof IDomMakerOptions 62 | */ 63 | eventListeners?: EventListener[]; 64 | 65 | /** 66 | * @en 67 | * optional HTML for element 68 | * @zh 69 | * 元素的 HTML 内容 70 | * 71 | * @type {string} 72 | * @memberof IDomMakerOptions 73 | */ 74 | innerHTML?: string; 75 | 76 | /** 77 | * @type {string} 78 | * @default 'http://www.w3.org/1999/xhtml' 79 | * @memberof IDomMakerOptions 80 | */ 81 | namespace?: string; 82 | 83 | /** 84 | * @en 85 | * Styles for Element 86 | * @zh 87 | * 元素的样式 88 | * 89 | * @type {CSSStyleDeclaration} 90 | * @memberof IDomMakerOptions 91 | */ 92 | style?: Partial; 93 | 94 | /** 95 | * @en 96 | * text to add as a child node 97 | * @zh 98 | * 添加为子节点的文本 99 | * 100 | * @type {string} 101 | * @memberof IDomMakerOptions 102 | */ 103 | text?: string; 104 | } 105 | 106 | interface IUtilitiesBoot { 107 | Crypto: typeof Crypto; 108 | PasswordPrompt: typeof PasswordPrompt; 109 | 110 | /** 111 | * @en 112 | * Returns true if the version string A is greater than the version string B. Returns true if the versions are the same 113 | * @zh 114 | * 如果版本字符串 A 大于版本字符串 B,返回 true;如果版本相同,返回 true。 115 | */ 116 | checkVersions: (versionStringA: string, versionStringB: string) => boolean; 117 | 118 | /** 119 | * @en 120 | * Returns +1 if the version string A is greater than the version string B, 0 if they are the same, and +1 if B is greater than A. 121 | * Missing or malformed version strings are parsed as 0.0.0 122 | * @zh 123 | * 如果版本字符串 A 大于版本字符串 B,则返回 +1;如果它们相同,则返回 0;如果 B 大于 A,则返回 +1; 124 | * 缺失或畸形的版本字符串被解析为 0.0.0 125 | */ 126 | compareVersions: ( 127 | versionStringA: string, 128 | versionStringB: string, 129 | ) => -1 | 0 | 1; 130 | 131 | /** 132 | * @en 133 | * Convert a URIComponent encoded string to a string safely 134 | * @zh 135 | * 将一个 URIComponent 编码的字符串安全地转换为一个字符串。 136 | */ 137 | decodeURIComponentSafe: (uri: string) => string; 138 | 139 | /** 140 | * @en 141 | * Convert a URI encoded string to a string safely 142 | * @zh 143 | * 将一个 URI 编码的字符串安全地转换为一个字符串 144 | */ 145 | decodeURISafe: (uri: string) => string; 146 | 147 | /** 148 | * @en 149 | * Fill in any null or undefined properties of an object with the properties from a list of source objects. Each property that is an object is called recursively 150 | * @zh 151 | * 用源对象列表中的属性来填充对象的任何空或未定义的属性。每个属于对象的属性都被递归地调用 152 | */ 153 | deepDefaults: ( 154 | origin: O, 155 | ...sources: [...S] 156 | ) => Spread; 157 | 158 | /** 159 | * @en 160 | * Helper for making DOM elements 161 | * @zh 162 | * 产生一个 DOM 元素 163 | * 164 | * @param {string} tag tag name 165 | * @param {IDomMakerOptions} options 166 | * @returns {TWElement} 167 | */ 168 | domMaker: ( 169 | tag: K, 170 | options: IDomMakerOptions, 171 | ) => K extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] 172 | : HTMLElement; 173 | domMaker: ( 174 | tag: string, 175 | options: IDomMakerOptions, 176 | ) => HTMLElement; 177 | 178 | /** 179 | * @en 180 | * Iterate through all the own properties of an object or array. 181 | * Callback is invoked with (element, index, object), if callback returns false, then the each loop will be terminated. 182 | * @zh 183 | * 遍历一个对象或数组的所有自身属性。 184 | * callback 被遍历调用 (element, index, object),如果回调返回 false,那么每个循环将被终止。 185 | * @param {T} object 186 | * @param {(element: T[keyof T], index: keyof T, object: T) => void | false} callback 187 | * @example 188 | * $tw.utils.each([1, 2, 3], element => console.log(element)); 189 | * $tw.utils.each({ a: 1, b: 2 }, (value, key) => console.log(key, value)); 190 | */ 191 | each: ( 192 | object: T, 193 | callback: (element: T[K], index: K, object: T) => false | undefined, 194 | ) => void; 195 | 196 | /** 197 | * @en 198 | * Display an error and exit 199 | * @zh 200 | * 打印一个错误,如果在 Node 环境下,会退出进程 201 | */ 202 | error: (error: Event | Error | string) => null | never; 203 | 204 | /** 205 | * @en 206 | * Run code globally with specified context variables in scope 207 | * @zh 208 | * 在全局范围内运行代码,范围内有指定的上下文变量 209 | */ 210 | evalGlobal: ( 211 | code: string, 212 | context: IEvalContent, 213 | filename: string, 214 | ) => unknown; 215 | 216 | /** 217 | * @en 218 | * Run code in a sandbox with only the specified context variables in scope 219 | * @zh 220 | * 在沙盒中运行代码,范围内只有指定的上下文变量 221 | */ 222 | evalSandboxed: ( 223 | code: string, 224 | context: IEvalContent, 225 | filename: string, 226 | ) => unknown; 227 | 228 | /** 229 | * @en 230 | * Extend an object with the properties from a list of source objects 231 | * @zh 232 | * 用源对象列表中的属性扩展一个对象 233 | */ 234 | extend: ( 235 | origin: O, 236 | ...sources: [...S] 237 | ) => Spread; 238 | 239 | /** 240 | * @en 241 | * Given an extension, always access the $tw.config.fileExtensionInfo using a lowercase extension only. 242 | * @zh 243 | * 给定一个扩展名,总是只使用小写的扩展名来访问$tw.config.fileExtensionInfo。 244 | */ 245 | getFileExtensionInfo: (extension: string) => IFileExtensionInfo | null; 246 | 247 | /** 248 | * @en 249 | * Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash) 250 | * @zh 251 | * 获取浏览器的 location.hash。我们不使用 location.hash,因为 Firefox 的自动解码方式(见 http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)。 252 | */ 253 | getLocationHash: () => string; 254 | 255 | /** 256 | * @en 257 | * Given an extension, get the correct encoding for that file. defaults to utf8 258 | * @zh 259 | * 给定一个扩展名,获得该文件的正确编码。默认为 utf8 260 | */ 261 | getTypeEncoding: (extension: string) => string; 262 | 263 | /** 264 | * @en 265 | * Check if an object has a property. 266 | * @zh 267 | * 检查一个对象是否有一个属性。 268 | */ 269 | hop: (object: Record, property: string | symbol) => boolean; 270 | 271 | /** 272 | * @en 273 | * Convert `&` to `&`, ` ` to ` `, `<` to `<`, `>` to `>` and `"` to `"` 274 | * @zh 275 | * 将`&`转换成`&`,` `转换成` `,`<`转换成`<`,`>`转换成`>`,`"`转换成`"` 276 | */ 277 | htmlDecode: (text: string) => string; 278 | 279 | /** 280 | * @en 281 | * Add an entry to a sorted array if it doesn't already exist, while maintaining the sort order 282 | * @zh 283 | * 如果一个已排序的数组中不存在一个条目,则添加该条目,同时保持排序顺序 284 | */ 285 | insertSortedArray: ( 286 | array: T, 287 | value: unknown, 288 | ) => T; 289 | 290 | /** 291 | * @en 292 | * Determine if a value is an array. 293 | * @zh 294 | * 判断对象是否是一个数组。 295 | */ 296 | isArray: (value: unknown) => boolean; 297 | 298 | /** 299 | * @en 300 | * Check if an array is equal by value and by reference. 301 | * @zh 302 | * 检查一个数组的值和引用是否相等。 303 | */ 304 | isArrayEqual: (array1: unknown[], array2: unknown[]) => boolean; 305 | 306 | /** 307 | * @en 308 | * Determine if a value is a date 309 | * @zh 310 | * 确定一个值是否是一个日期 311 | */ 312 | isDate: (value: unknown) => void; 313 | 314 | /** 315 | * @en 316 | * Pad a string to a given length with "0"s. Length defaults to 2 317 | * @zh 318 | * 用 "0 "将一个字符串填充到指定的长度。长度默认为 2 319 | */ 320 | pad: (value: number, length?: number) => string; 321 | 322 | /** 323 | * @en 324 | * Parse a date from a UTC `YYYYMMDDHHMMSSmmm` format string 325 | * @zh 326 | * 从 UTC `YYYYMMDDHHMMSSmmm` 格式字符串中解析一个日期 327 | */ 328 | parseDate: (value: string | Date) => Date | null; 329 | 330 | /** 331 | * @en 332 | * Parse a block of name:value fields. The `fields` object is used as the basis for the return value 333 | * @zh 334 | * 解析一个 name:value 字段的块。`fields`对象被用作返回值的基础。 335 | */ 336 | parseFields: (text: string, fields?: object) => Record; 337 | 338 | /** 339 | * @en 340 | * Safely parse a string as JSON 341 | * @zh 342 | * 安全地解析一个字符串为 JSON 对象 343 | */ 344 | parseJSONSafe: ( 345 | input: string, 346 | defaultJSON?: (error: Error) => T, 347 | ) => T; 348 | 349 | /** 350 | * @en 351 | * Parse a string array from a bracketted list. For example `OneTiddler [[Another Tiddler]] LastOne` 352 | * @zh 353 | * 从一个带括号的列表中解析一个字符串数组。例如,`OneTiddler [[Another Tiddler]] LastOne` 354 | * 355 | * @returns {string[]} An array of tiddler titles. null if input is not string or string array. This won't happened in TS. 356 | */ 357 | parseStringArray: ( 358 | value: string | string[], 359 | allowDuplicate?: boolean, 360 | ) => string[]; 361 | 362 | /** 363 | * @en 364 | * Parse a semantic version string into its constituent parts -- see https://semver.org 365 | * @zh 366 | * 将一个语义版本字符串解析为其构成部分 -- 见 https://semver.org 367 | */ 368 | parseVersion: (version: string) => { 369 | build?: string; 370 | major: number; 371 | minor: number; 372 | patch: number; 373 | prerelease?: string; 374 | version: string; 375 | } | null; 376 | 377 | /** 378 | * @en 379 | * Push entries onto an array, removing them first if they already exist in the array 380 | * @zh 381 | * 将条目推送到一个数组中,如果它们已经存在于数组中,则先将其删除。 382 | * 383 | * @param {unknown[]} array array to modify (assumed to be free of duplicates) 384 | * @param {unknown} value a single value to push or an array of values to push 385 | * @returns {unknown[]} 386 | */ 387 | pushTop: (array: T, value: unknown) => T; 388 | 389 | /** 390 | * @en 391 | * Register file type information 392 | * @zh 393 | * 注册文件类型信息 394 | * 395 | * @param {string} contentType 396 | * @param {string} encoding 397 | * @param {(string | string[])} extension 398 | * @param {{ 399 | * flags: string[]; 400 | * deserializerType: string; 401 | * }} [options] Options includes: 402 | * * flags:"image" for image types 403 | * * deserializerType: defaults to type if not specified 404 | */ 405 | registerFileType: ( 406 | contentType: string, 407 | encoding: string, 408 | extension: string | string[], 409 | options?: { 410 | deserializerType?: string; 411 | flags?: string[]; 412 | }, 413 | ) => void; 414 | 415 | /** 416 | * @en 417 | * Resolves a source filepath delimited with `/` relative to a specified absolute root filepath. 418 | * In relative paths, the special folder name `..` refers to immediate parent directory, and the 419 | * name `.` refers to the current directory 420 | * @zh 421 | * 将以`/`为界的源文件路径相对于指定的绝对根文件路径进行解析。 422 | * 在相对路径中,特殊的文件夹名称`...`指的是直接的父目录,而名称`.`指的是当前目录。 423 | */ 424 | resolvePath: (sourcepath: string, rootpath: string) => string; 425 | 426 | /** 427 | * @en 428 | * Convert a date into UTC `YYYYMMDDHHMMSSmmm` format 429 | * @zh 430 | * 将日期转换成 UTC `YYYYMMDDHMMSSmmm` 格式 431 | */ 432 | stringifyDate: (value: Date) => string; 433 | 434 | /** 435 | * @en 436 | * Stringify an array of tiddler titles into a list string 437 | * @zh 438 | * 将一个数组的 tiddler 标题字符串化为一个列表字符串 439 | */ 440 | stringifyList: (value: string[]) => string; 441 | /** 442 | * Remove any of the characters that are illegal in Windows filenames 443 | * See `$tw.utils.transliterationPairs` for the list of replacements 444 | */ 445 | transliterate: (string_: string) => string; 446 | /** 447 | * Remove any of the characters that are illegal in Windows filenames 448 | * See `$tw.utils.transliterationPairs` for the list of replacements 449 | */ 450 | transliterateToSafeASCII: (string_: string) => string; 451 | /** 452 | * Transliterate string to ASCII 453 | * (Some pairs taken from http://semplicewebsites.com/ removing-accents-javascript) 454 | */ 455 | transliterationPairs: Record; 456 | /** 457 | * Logger class constructor 458 | */ 459 | Logger: typeof Logger; 460 | /** 461 | * Parse a filter variable 462 | */ 463 | parseFilterVariable: (source: string) => unknown; 464 | /** 465 | * Create directory recursively 466 | */ 467 | createDirectory: (directoryPath: string) => void; 468 | /** 469 | * Generate tiddler file info for saving 470 | */ 471 | generateTiddlerFileInfo: ( 472 | tiddler: Tiddler, 473 | options: { 474 | directory: string; 475 | pathFilters?: string[]; 476 | extFilters?: string[]; 477 | wiki: Wiki; 478 | fileInfo?: Partial; 479 | }, 480 | ) => IFileInfo; 481 | /** 482 | * Save tiddler to file 483 | */ 484 | saveTiddlerToFile: (tiddler: Tiddler, fileInfo: IFileInfo, callback?: (error: Error | null) => void) => void; 485 | /** 486 | * Cleanup tiddler files (delete old files when tiddler is moved) 487 | */ 488 | cleanupTiddlerFiles: ( 489 | fileInfo: IFileInfo | Record, 490 | callback?: (error: Error | null, cleanedFileInfo?: IFileInfo) => void, 491 | ) => void; 492 | /** 493 | * Delete tiddler file 494 | */ 495 | deleteTiddlerFile: (fileInfo: IFileInfo, callback?: (error: Error | null, deletedFileInfo?: IFileInfo) => void) => void; 496 | /** 497 | * Format date string 498 | */ 499 | formatDateString: (date: Date, template: string) => string; 500 | } 501 | 502 | import type { IUtilitiesModules } from 'tiddlywiki'; 503 | export type IUtilities = IUtilitiesBoot & IUtilitiesModules; 504 | } 505 | -------------------------------------------------------------------------------- /src/modules/widgets/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | /** 3 | * Parameter of Widget.refresh 4 | * Key is tiddler title 5 | */ 6 | export type IChangedTiddlers = Record; 7 | /** Only one of these fields will be `true` */ 8 | export interface IChangedTiddlersMeta { 9 | deleted?: boolean; 10 | modified?: boolean; 11 | } 12 | export interface IWidgetVariableParameter { 13 | default: string; 14 | name: string; 15 | } 16 | 17 | export interface IWidgetVariable { 18 | isMacroDefinition: boolean; 19 | params?: IWidgetVariableParameter[]; 20 | value: string; 21 | } 22 | 23 | export interface IWidgetInitialiseOptions { 24 | document?: TWDocument; 25 | parentWidget?: Widget; 26 | wiki?: ITiddlyWiki; 27 | } 28 | 29 | export type IWidgetInitializeOptions = IWidgetInitialiseOptions; 30 | 31 | export interface IWidgetEvent { 32 | [extraKeys: string]: unknown; 33 | /** maybe a DOM click event, if trigger by button click */ 34 | event: UIEvent | Event; 35 | name: string; 36 | navigateFromTitle?: string; 37 | /** 38 | * Get `$param` 39 | */ 40 | param?: string | undefined; 41 | /** Optional hashmap of additional tiddler fields. Widget event can carry any other parameters 42 | * 43 | * For example, `<$action-sendmessage $message="tw-mobile-sync-set-active-server-and-sync" title={{!!title}} />` will produce `paramObject: { title: "xxxx" }` 44 | */ 45 | paramObject?: Record; 46 | tiddlerTitle?: string; 47 | /** the first parameter of addEventListener 48 | * 49 | * For example, the `'open-command-palette'` in `$tw.rootWidget.addEventListener('open-command-palette', (e: IWidgetEvent) => this.openPalette(e));` 50 | */ 51 | type: string; 52 | widget: Widget; 53 | } 54 | 55 | export interface IGetWidgetVariableOptions { 56 | allowSelfAssigned?: boolean; 57 | defaultValue?: string; 58 | params?: IWidgetVariableParameter[]; 59 | source?: (iter: SourceIterator) => void; 60 | } 61 | 62 | /** 63 | * @link https://tiddlywiki.com/dev/#Widgets 64 | * 65 | * Create a widget object for a parse tree node 66 | * * parseTreeNode: reference to the parse tree node to be rendered 67 | * * options: see below 68 | * 69 | * Options include: 70 | * * wiki: mandatory reference to wiki associated with this render tree 71 | * * parentWidget: optional reference to a parent renderer node for the context chain 72 | * * document: optional document object to use instead of global document 73 | */ 74 | export class Widget { 75 | parseTreeNode: IParseTreeNode; 76 | 77 | wiki: Wiki; 78 | 79 | document: IFakeDocument; 80 | 81 | parentWidget?: Widget; 82 | 83 | attributes: Record; 84 | 85 | domNodes: Element[]; 86 | 87 | parentDomNode?: Element; 88 | 89 | eventListeners: Record< 90 | string, 91 | Array<(event: IWidgetEvent) => undefined | Promise | boolean> 92 | >; 93 | 94 | /** 95 | * we can use $tw.rootWidget.widgetClasses.xxx to new a widget 96 | * 97 | * This is a set of all widgets defined in tiddlywiki. 98 | */ 99 | widgetClasses: Record; 100 | 101 | children: Widget[]; 102 | 103 | qualifiers?: Record; 104 | 105 | ancestorCount?: number; 106 | 107 | /** 108 | * Set the value of a context variable 109 | * * name: name of the variable 110 | * * value: value of the variable 111 | * * params: array of `{name: string, default: string}` for each parameter 112 | * * isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) 113 | */ 114 | variables: Record; 115 | 116 | constructor( 117 | parseTreeNode: IParseTreeNode, 118 | options?: IWidgetInitialiseOptions, 119 | ); 120 | 121 | /** 122 | * @en 123 | * Initialise widget properties. These steps are pulled out of the constructor so that we can reuse them in subclasses 124 | * @zh 125 | * 初始化 widget 属性。这些步骤被拉出构造函数,以便我们可以在子类中重复使用它们 126 | */ 127 | initialise( 128 | parseTreeNode: IParseTreeNode, 129 | options?: IWidgetInitialiseOptions, 130 | ): void; 131 | 132 | /** 133 | * @en 134 | * Lifecycle method: Render this widget into the DOM 135 | * @zh 136 | * 生命周期方法:将这个微件渲染到 DOM 中; 137 | * 只会在首次渲染、销毁后重新渲染时自动调用,或者通过 refreshSelf 等方法主动调用 138 | */ 139 | render(parent: Element, nextSibling: Element | null): void; 140 | 141 | /** 142 | * @en 143 | * Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering. 144 | * You can do some cleanup or buildup before return true. 145 | * @zh 146 | * 如果需要的话,有选择地刷新该微件。如果该微件或其任何子项需要重新渲染,则返回 true。 147 | * 你可以在返回 true 之前做一些清理或构建工作。 148 | * @param {IChangedTiddlers} changedTiddlers Object key is tiddler title, value is metadata about the change 149 | * @link https://tiddlywiki.com/dev/#Selective%20Update 150 | */ 151 | refresh(changedTiddlers: IChangedTiddlers): boolean | undefined; 152 | 153 | /** 154 | * Compute the internal state of the widget. 155 | * This will be automatically called in the `render` method. 156 | * 157 | * For example, `getAttribute` and set them to class members. 158 | */ 159 | execute(): void; 160 | 161 | /** 162 | * @en 163 | * Set the value of a context variable 164 | * @zh 165 | * 设置一个上下文变量的值 166 | * 167 | * @param {string } name name of the variable 168 | * @param {string} value value of the variable 169 | * @param {IWidgetVariableParam[]} [params=[]] array of `{name: string, default: string}` for each parameter 170 | * @param {boolean} [isMacroDefinition=false] true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) 171 | * @param {object} [options] Additional options 172 | * @param {boolean} [options.isProcedureDefinition] true if the variable is set via a \procedure pragma 173 | * @param {boolean} [options.isFunctionDefinition] true if the variable is set via a \function pragma 174 | * @param {boolean} [options.isWidgetDefinition] true if the variable is set via a \widget pragma 175 | * @param {boolean} [options.configTrimWhiteSpace] whether to trim whitespace 176 | */ 177 | setVariable( 178 | name: string, 179 | value: string, 180 | parameters?: IWidgetVariableParameter[], 181 | isMacroDefinition?: boolean, 182 | options?: { 183 | configTrimWhiteSpace?: boolean; 184 | isFunctionDefinition?: boolean; 185 | isProcedureDefinition?: boolean; 186 | isWidgetDefinition?: boolean; 187 | }, 188 | ): void; 189 | 190 | /** 191 | * Get the prevailing value of a context variable 192 | * @param name variable name, for example, `currentTiddler` in the widget context 193 | * @param options options for getVariableInfo() 194 | * 195 | * Options include 196 | * * params: array of `{name: string, default: string}` for each parameter 197 | * * defaultValue: default value if the variable is not defined 198 | * * source: optional source iterator for evaluating function invocations 199 | * * allowSelfAssigned: if true, includes the current widget in the context chain instead of just the parent 200 | * 201 | * Returns an object with the following fields: 202 | * * params: array of `{name:,value:}` of parameters passed to wikitext variables 203 | * * text: text of variable, with parameters properly substituted 204 | * * resultList: result of variable evaluation as an array 205 | * * srcVariable: reference to the object defining the variable 206 | */ 207 | getVariableInfo( 208 | name: string, 209 | options?: IGetWidgetVariableOptions, 210 | ): { 211 | isCacheable?: boolean; 212 | params?: IWidgetVariableParameter[]; 213 | srcVariable?: IWidgetVariable; 214 | text: string; 215 | }; 216 | 217 | /** 218 | * Simplified version of getVariableInfo() that just returns the text 219 | */ 220 | getVariable(name: string, options?: IGetWidgetVariableOptions): string; 221 | 222 | resolveVariableParameters( 223 | formalParameters?: IWidgetVariableParameter[], 224 | actualParameters?: IWidgetVariableParameter[], 225 | ): IWidgetVariableParameter[]; 226 | 227 | substituteVariableReferences( 228 | text: string, 229 | options: { variables: Record }, 230 | ): string; 231 | 232 | evaluateMacroModule( 233 | name: string, 234 | actualParameters: IWidgetVariableParameter[], 235 | defaultValue: string, 236 | ): string; 237 | 238 | /** 239 | * @en 240 | * Check whether a given context variable value exists in the parent chain 241 | * @zh 242 | * 检查一个给定的上下文变量值是否存在于父链中 243 | * 244 | * @param {string} name 245 | * @param {string} value 246 | * @memberof Widget 247 | */ 248 | hasVariable(name: string, value: string): boolean; 249 | 250 | /** 251 | * @en 252 | * Construct a qualifying string based on a hash of concatenating the values of a given variable in the parent chain 253 | * @zh 254 | * 在连接父链中给定变量值的哈希基础上构建一个限定字符串 255 | * 256 | * @param {string} name 257 | * @memberof Widget 258 | */ 259 | getStateQualifier(name: string): string; 260 | 261 | /** 262 | * @en 263 | * Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed 264 | * @zh 265 | * 计算微件的属性的当前值。返回一个已经改变的属性名称的哈希图 266 | * 267 | * @param {object} [options] Options 268 | * @param {Function} [options.filterFn] only include attributes where filterFn(name) returns true 269 | * @return Object with keys of the names of the attributes that have changed 270 | * @memberof Widget 271 | */ 272 | computeAttributes(options?: { 273 | filterFn?: (name: string) => boolean; 274 | }): Record; 275 | 276 | computeAttribute(attribute: string): string; 277 | 278 | /** 279 | * @en 280 | * Check for the presence of an evaluated attribute on the widget. Note that attributes set to a missing variable (ie `attr=<>`) will be treated as missing 281 | * @zh 282 | * 检查微件上是否存在一个已评估的属性。请注意,设置为缺失变量的属性(即`attr=<>`)将被视为缺失。 283 | * 284 | * @param {string} attribute 285 | * @memberof Widget 286 | */ 287 | hasAttribute(attribute: string): boolean; 288 | 289 | /** 290 | * @en 291 | * Check for the presence of a raw attribute on the widget parse tree node. Note that attributes set to a missing variable (ie `attr=<>`) will NOT be treated as missing 292 | * @zh 293 | * 检查微件解析树节点上是否存在原始属性。注意,设置为缺失变量的属性(即`ttr=<>`)不会被视为缺失。 294 | * 295 | * @param {string} attribute 296 | * @memberof Widget 297 | */ 298 | hasParseTreeNodeAttribute(attribute: string): boolean; 299 | 300 | /** 301 | * @en 302 | * Get parameters that user set in the widget 303 | * @zh 304 | * 获取用户在小组件中设置的参数 305 | * 306 | * @param {string} name attribute name, for example, `actions` in the button widget 307 | * @param {string} [fallbackText] default value if the attribute is not set 308 | * @return parameters 309 | * @memberof Widget 310 | */ 311 | getAttribute(name: string): string | undefined; 312 | getAttribute(name: string, fallbackText: string): string; 313 | 314 | /** 315 | * @en 316 | * Assign the computed attributes of the widget to a domNode 317 | * options include: 318 | * * `excludeEventAttributes`: ignores attributes whose name begins with "on" 319 | * * `sourcePrefix`: prefix of attributes that are to be directly assigned (defaults to the empty string) 320 | * * `destPrefix`: prefix to be applied to attribute names that are to be directly assigned (defaults to the empty string) 321 | * * `changedAttributes`: hashmap by attribute name of attributes to process (if missing, process all attributes) 322 | * @zh 323 | * 将微件的计算属性分配给一个 domNode, 选项包括: 324 | * * `excludeEventAttributes`: 忽略名称以 "on "开头的属性 325 | * * `sourcePrefix`: 要直接分配的属性的前缀(默认为空字符串) 326 | * * `destPrefix`: 要应用到直接分配的属性名称的前缀(默认为空字符串) 327 | * * `changedAttributes`: 按属性名称的哈希图,要处理的属性(如果缺失,处理所有属性) 328 | * 一些特殊的属性: 329 | * * `xlink:` 330 | * * `style.` 331 | * 332 | * @param {*} domNode 333 | * @param {*} options 334 | * @memberof Widget 335 | */ 336 | assignAttributes( 337 | domNode: Element, 338 | options?: { 339 | changedAttributes?: Record; 340 | destPrefix?: string; 341 | excludeEventAttributes?: boolean; 342 | sourcePrefix?: string; 343 | }, 344 | ); 345 | 346 | /** 347 | * @en 348 | * Get the number of ancestor widgets for this widget 349 | * @zh 350 | * 获取这个微件的祖先微件的数量 351 | * 352 | * @return number of ancestor widgets for this widget 353 | * @memberof Widget 354 | */ 355 | getAncestorCount(): number; 356 | 357 | /** 358 | * Make child widgets correspondng to specified parseTreeNodes 359 | * And push them to `this.children` 360 | * @param parseTreeNodes default to `this.parseTreeNode.children`, can be undefined 361 | */ 362 | makeChildWidgets( 363 | parseTreeNodes?: IParseTreeNode[], 364 | options?: { variables?: unknown }, 365 | ): void; 366 | 367 | /** 368 | * Construct the widget object for a parse tree node, and return the new widget 369 | * options include: 370 | * variables: optional hashmap of variables to wrap around the widget 371 | */ 372 | makeChildWidget( 373 | parseTreeNode: IParseTreeNode, 374 | options?: { variables?: unknown }, 375 | ): Widget; 376 | 377 | /** 378 | * @en 379 | * Get the next sibling of this widget 380 | * 381 | * @memberof Widget 382 | */ 383 | nextSibling(): Widget | null; 384 | 385 | /** 386 | * @en 387 | * Get the previous sibling of this widget 388 | * 389 | * @memberof Widget 390 | */ 391 | previousSibling(): Widget | null; 392 | 393 | /** 394 | * Render the children of this widget into the DOM 395 | */ 396 | renderChildren(parent: Element, nextSibling: Element | null): void; 397 | 398 | /** 399 | * Add a list of event listeners from an array `[{type:,handler:},...]` 400 | * See also `addEventListener`. 401 | */ 402 | addEventListeners( 403 | listeners: Array<{ 404 | handler: (event: IWidgetEvent) => undefined | Promise | boolean; 405 | type: string; 406 | }>, 407 | ): void; 408 | 409 | /** 410 | * Add an event listener. 411 | * If the handler is sync, then should return a boolean, `false` means the event is handled and don't propagate, and `true` will be dispatched to the parent widget. 412 | * If the handler is async, then it is always propagate to the parent widget. 413 | * @returns should propagate to parent widget 414 | */ 415 | addEventListener( 416 | type: string, 417 | handler: (event: IWidgetEvent) => undefined | Promise | boolean, 418 | ): void; 419 | 420 | /** 421 | * Remove an event listener 422 | */ 423 | removeEventListener( 424 | type: string, 425 | handler: (event: IWidgetEvent) => undefined | Promise | boolean, 426 | ): void; 427 | 428 | /** 429 | * Dispatch an event to a widget. If the widget doesn't handle the event then it is also dispatched to the parent widget 430 | * Events added via `addEventListener`, like `tm-notify`, can be invoked by this. 431 | */ 432 | dispatchEvent(widgetEvent: Omit & { widget?: IWidgetEvent['widget'] }): void; 433 | 434 | /** 435 | * Rebuild a previously rendered widget 436 | */ 437 | refreshSelf(): void; 438 | 439 | /** 440 | * Refresh all the children of a widget, will call `this.render`. 441 | * Need to call this after `setVariable` 442 | */ 443 | refreshChildren(changedTiddlers?: IChangedTiddlers): boolean; 444 | 445 | /** 446 | * Find the next sibling in the DOM to this widget. This is done by scanning the widget tree through all next siblings and their descendents that share the same parent DOM node 447 | * @param startIndex Refer to this widget by its index within its parents children 448 | */ 449 | findNextSiblingDomNode(startIndex?: number): Element | null; 450 | 451 | /** 452 | * Find the first DOM node generated by a widget or its children 453 | */ 454 | findFirstDomNode(): Element | null; 455 | 456 | /** 457 | * Remove any DOM nodes created by this widget or its children 458 | * 459 | * If this widget has directly created DOM nodes, delete them and exit. This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case. 460 | * Otherwise, ask the child widgets to delete their DOM nodes 461 | */ 462 | removeChildDomNodes(): void; 463 | 464 | /** 465 | * Invoke the action associated with this widget 466 | * 467 | * No every widget has this method, but some do, like `action-xxx` widget, e.g., `action-sendmessage` 468 | * @param triggeringWidget 469 | * @param event 470 | * @returns handled 471 | */ 472 | invokeAction?( 473 | triggeringWidget: Widget, 474 | event: IWidgetEvent | null, 475 | ): boolean | undefined; 476 | 477 | /** 478 | * @en 479 | * `invokeActions` will invoke the action widgets that are descendents of the current action widget, if this returns `true` (by default is `true`, invocation will propagate through through the child). 480 | * Override this method and return `false` to stop the propagation down, and handle the invocation of child widgets by yourself. 481 | */ 482 | allowActionPropagation(): boolean; 483 | 484 | /** 485 | * @en 486 | * Invoke the action widgets that are descendents of the current widget. The invocation will propagate through the child, unless some widget on the middle have `allowActionPropagation` to return `false`. 487 | * 488 | * @param {Widget} triggeringWidget 489 | * @param {IWidgetEvent} event 490 | * @memberof Widget 491 | * @returns `handled`, means some action is invoked. 492 | */ 493 | invokeActions(triggeringWidget: Widget, event: IWidgetEvent | null): boolean; 494 | 495 | /** 496 | * @en 497 | * Invoke the action widgets defined in a string 498 | * 499 | * This calls `invokeActions` under the hood 500 | * 501 | * @param {string} actions 502 | * @param {Widget} triggeringWidget (this is unused, passing `undefined` is OK) 503 | * @param {IWidgetEvent} event 504 | * @param {Record} variables 505 | * @memberof Widget 506 | * @returns `handled`, the return of `invokeActions`, means some action is invoked. 507 | */ 508 | invokeActionString( 509 | actions: string, 510 | triggeringWidget?: Widget, 511 | event?: IWidgetEvent | null, 512 | variables?: Record, 513 | ): boolean; 514 | 515 | /** 516 | * @en 517 | * Execute action tiddlers by tag 518 | * @zh 519 | * 按标签执行 action tiddlers 520 | * 521 | * @param {string} tag The tag to filter action tiddlers 522 | * @param {IWidgetEvent} event The widget event 523 | * @param {Record} variables Optional variables to pass to the action string 524 | * @memberof Widget 525 | */ 526 | invokeActionsByTag( 527 | tag: string, 528 | event?: IWidgetEvent | null, 529 | variables?: Record, 530 | ): void; 531 | 532 | /** 533 | * @en 534 | * Find child `<$data>` widgets recursively. The tag name allows aliased versions of the widget to be found too 535 | * @zh 536 | * 递归查找子 `<$data>` widgets。标签名称允许查找该 widget 的别名版本 537 | * 538 | * @param {Widget[]} children The children widgets to search 539 | * @param {string} tag The tag name to search for (e.g., "$data") 540 | * @param {Function} callback Callback function called for each found widget 541 | * @memberof Widget 542 | */ 543 | findChildrenDataWidgets( 544 | children: Widget[], 545 | tag: string, 546 | callback: (widget: Widget) => void, 547 | ): void; 548 | 549 | removeLocalDomNodes(): void; 550 | 551 | /** 552 | * Make a fake widget with specified variables, suitable for variable lookup in filters 553 | */ 554 | makeFakeWidgetWithVariables(variables: Record): Widget; 555 | 556 | /** 557 | * @en 558 | * Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings 559 | * @zh 560 | * 使用参数评估变量。这是一个静态便捷方法,尝试将变量作为函数评估,返回字符串数组 561 | * 562 | * @param {Widget} widget The widget context for variable lookup 563 | * @param {string} name The variable name to evaluate 564 | * @param {IGetWidgetVariableOptions} options Options for variable evaluation 565 | * @returns {string[]} Array of result strings 566 | * @static 567 | * @memberof Widget 568 | */ 569 | static evaluateVariable( 570 | widget: Widget, 571 | name: string, 572 | options?: IGetWidgetVariableOptions, 573 | ): string[]; 574 | } 575 | } 576 | 577 | declare module '$:/core/modules/widgets/widget.js' { 578 | export { Widget as widget } from 'tiddlywiki'; 579 | } 580 | -------------------------------------------------------------------------------- /src/modules/utils/utils.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/prevent-abbreviations */ 2 | declare module '$:/core/modules/utils/utils.js' { 3 | type TerminalColourName = 4 | | 'black' 5 | | 'red' 6 | | 'green' 7 | | 'brown/orange' 8 | | 'blue' 9 | | 'purple' 10 | | 'cyan' 11 | | 'light gray'; 12 | 13 | export const terminalColourLookup: Record< 14 | TerminalColourName, 15 | string 16 | >; 17 | 18 | /** 19 | * Displays a message, in color if we're on a terminal. 20 | * @param text - The text to display. 21 | * @param colour - The color to display the text in. 22 | * @description 在终端上显示消息,如果在终端上则以颜色显示。 23 | */ 24 | export function log(text: string, colour?: string): void; 25 | 26 | /** 27 | * Returns the terminal color code for a given color. 28 | * @param colour - The color to get the code for. 29 | * @returns The terminal color code for the given color. 30 | * @description 返回给定颜色的终端颜色代码。 31 | */ 32 | export function terminalColour(colour?: string): string; 33 | 34 | /** 35 | * Display a warning, in colour if we're on a terminal. 36 | * @param text - The text to display. 37 | * @description 在终端上显示警告,如果在终端上则以颜色显示。 38 | */ 39 | export function warning(text: string): void; 40 | 41 | /** 42 | * Log a table of name: value pairs. 43 | * @param data - The data to log. 44 | * @description 记录名称:值对的表格。 45 | */ 46 | export function logTable(data: object): void; 47 | 48 | /** 49 | * Return the integer represented by the str (string). 50 | * Return the dflt (default) parameter if str is not a base-10 number. 51 | * @param str - The string to parse. 52 | * @param deflt - The default value to return if the string is not a base-10 number. 53 | * @returns The integer represented by the string or the default value if the string is not a base-10 number. 54 | * @description 返回由 str(字符串)表示的整数。如果 str 不是十进制数字,则返回 dflt(默认)参数。 55 | */ 56 | export function getInt(string_: string, deflt: number): number; 57 | 58 | /** 59 | * Repeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string. 60 | * @param text - The text to search and replace. 61 | * @param search - The substring to search for. 62 | * @param replace - The replacement string. 63 | * @returns The modified string. 64 | * @description 反复替换字符串中的子字符串。类似于 String.prototype.replace,但不使用替换字符串中的 $ 序列的默认特殊处理。 65 | */ 66 | export function replaceString( 67 | text: string, 68 | search: string | RegExp, 69 | replace: string, 70 | ): string; 71 | 72 | /** 73 | * Repeats a string. 74 | * @param str - The string to repeat. 75 | * @param count - The number of times to repeat the string. 76 | * @returns The repeated string. 77 | * @description 重复一个字符串。 78 | */ 79 | export function repeat(string_: string, count: number): string; 80 | 81 | /** 82 | * Checks if a string starts with another string. 83 | * @param str - The string to check. 84 | * @param search - The string to search for. 85 | * @returns True if the string starts with the search string, false otherwise. 86 | * @description 检查字符串是否以另一个字符串开头。 87 | */ 88 | export function startsWith(string_: string, search: string): boolean; 89 | 90 | /** 91 | * Checks if a string ends with another string. 92 | * @param str - The string to check. 93 | * @param search - The string to search for. 94 | * @returns True if the string ends with the search string, false otherwise. 95 | * @description 检查字符串是否以另一个字符串结尾。 96 | */ 97 | export function endsWith(string_: string, search: string): boolean; 98 | 99 | /** 100 | * Trims whitespace from the start and end of a string. 101 | * @param str - The string to trim. 102 | * @returns The trimmed string. 103 | * @description 从字符串的开头和结尾修剪空格。 104 | */ 105 | export function trim(string_: string): string; 106 | 107 | /** 108 | * Trims a prefix from a string. 109 | * @param str - The string to trim. 110 | * @param unwanted - The prefix to remove. 111 | * @returns The trimmed string. 112 | * @description 从字符串中修剪前缀。 113 | */ 114 | export function trimPrefix(string_: string, unwanted: string): string; 115 | 116 | /** 117 | * Trims a suffix from a string. 118 | * @param str - The string to trim. 119 | * @param unwanted - The suffix to remove. 120 | * @returns The trimmed string. 121 | * @description 从字符串中修剪后缀。 122 | */ 123 | export function trimSuffix(string_: string, unwanted: string): string; 124 | 125 | /** 126 | * Converts a string to sentence case (i.e. capitalizes the first letter). 127 | * @param str - The string to convert. 128 | * @returns The converted string. 129 | * @description 将字符串转换为句子格式(即将第一个字母大写)。 130 | */ 131 | export function toSentenceCase(string_: string): string; 132 | 133 | /** 134 | * Converts a string to title case (i.e. capitalizes each initial letter). 135 | * @param str - The string to convert. 136 | * @returns The converted string. 137 | * @description 将字符串转换为标题格式(即将每个单词的第一个字母大写)。 138 | */ 139 | export function toTitleCase(string_: string): string; 140 | 141 | /** 142 | * Finds the line break preceding a given position in a string. 143 | * @param text - The string to search in. 144 | * @param pos - The position to search for. 145 | * @returns The position immediately after that line break, or the start of the string. 146 | * @description 查找字符串中给定位置之前的换行符。 147 | */ 148 | export function findPrecedingLineBreak(text: string, pos: number): number; 149 | 150 | /** 151 | * Finds the line break following a given position in a string. 152 | * @param text - The string to search in. 153 | * @param pos - The position to search for. 154 | * @returns The position of the following line break, or the end of the string. 155 | * @description 查找字符串中给定位置之后的换行符。 156 | */ 157 | export function findFollowingLineBreak(text: string, pos: number): number; 158 | 159 | /** 160 | * Returns the number of keys in an object. 161 | * @param object - The object to count the keys of. 162 | * @returns The number of keys in the object. 163 | * @description 返回对象中键的数量。 164 | */ 165 | export function count(object: object): number; 166 | 167 | /** 168 | * Determines whether an array item is an object property. 169 | * @param object - The object to check. 170 | * @param array - The array to check. 171 | * @returns True if the array item is an object property, false otherwise. 172 | * @description 确定数组项是否为对象属性。 173 | */ 174 | export function hopArray(object: object, array: unknown[]): boolean; 175 | 176 | /** 177 | * Removes entries from an array. 178 | * @param array - The array to modify. 179 | * @param value - A single value or an array of values to remove. 180 | * @returns The modified array. 181 | * @description 从数组中删除条目。 182 | */ 183 | export function removeArrayEntries(array: T[], value: T | T[]): T[]; 184 | 185 | /** 186 | * Checks whether any members of a hashmap are present in another hashmap. 187 | * @param dependencies - The hashmap to check for dependencies. 188 | * @param changes - The hashmap to check for changes. 189 | * @returns True if any members of the hashmap are present in another hashmap, false otherwise. 190 | * @description 检查哈希映射的任何成员是否存在于另一个哈希映射中。 191 | */ 192 | export function checkDependencies( 193 | dependencies: object, 194 | changes: object, 195 | ): boolean; 196 | 197 | /** 198 | * Extends an object with one or more sources. 199 | * @param object - The object to extend. 200 | * @param src - One or more sources to extend the object with. 201 | * @returns The extended object. 202 | * @description 使用一个或多个源扩展对象。 203 | */ 204 | export function extend(object: object, ...source: object[]): object; 205 | 206 | /** 207 | * Extend an object with properties from one or more sources. 208 | * @param object - The object to extend. 209 | * @param src - The source object(s) to copy properties from. 210 | * @returns The extended object. 211 | * @description 从一个或多个源中复制属性来扩展对象。 212 | */ 213 | export function extend(object: T, ...source: unknown[]): T; 214 | 215 | /** 216 | * Deep copy an object. 217 | * @param object - The object to copy. 218 | * @returns The copied object. 219 | * @description 深拷贝对象。 220 | */ 221 | export function deepCopy(object: T): T; 222 | 223 | /** 224 | * Extend an object with properties from one or more sources, and deep copy the extended properties. 225 | * @param object - The object to extend. 226 | * @param extendedProperties - The properties to extend and deep copy. 227 | * @returns The extended object. 228 | * @description 从一个或多个源中复制属性来扩展对象,并深拷贝扩展的属性。 229 | */ 230 | export function extendDeepCopy(object: T, extendedProperties: unknown): T; 231 | 232 | /** 233 | * Recursively freeze an object and its properties. 234 | * @param object - The object to freeze. 235 | * @description 递归地冻结对象及其属性。 236 | */ 237 | export function deepFreeze(object: unknown): void; 238 | 239 | /** 240 | * A slow-in, slow-out easing function. 241 | * @param t - The time value, between 0 and 1. 242 | * @returns The eased value. 243 | * @description 缓入缓出的缓动函数。 244 | */ 245 | export function slowInSlowOut(t: number): number; 246 | 247 | /** 248 | * Format a string template with options. 249 | * @param template - The string template to format. 250 | * @param options - The options to use for formatting. 251 | * @returns The formatted string. 252 | * @description 使用选项格式化字符串模板。 253 | */ 254 | export function formatTitleString( 255 | template: string, 256 | options: { base?: string; counter?: number; separator?: string }, 257 | ): string; 258 | 259 | /** 260 | * Format a date string based on a template. 261 | * Use `"[UTC]YYYY0MM0DD0hh0mm0ss0XXX"` to format a standard tiddlywiki date string. 262 | * See document for more formats. 263 | * 264 | * @url https://tiddlywiki.com/#DateFormat 265 | * @param date - The date object to format. 266 | * @param template - The template string to use for formatting. 267 | * @returns The formatted date string. 268 | */ 269 | export function formatDateString(date: Date, template: string): string; 270 | 271 | /** 272 | * Get the AM/PM period of a date. 273 | * @param date - The date object to get the period from. 274 | * @returns The period string (either "am" or "pm"). 275 | */ 276 | export function getAmPm(date: Date): string; 277 | 278 | /** 279 | * Get the suffix for the day of a date. 280 | * @param date - The date object to get the day suffix from. 281 | * @returns The day suffix string. 282 | */ 283 | export function getDaySuffix(date: Date): string; 284 | 285 | /** 286 | * Get the week number of a date. 287 | * @param date - The date object to get the week number from. 288 | * @returns The week number. 289 | */ 290 | export function getWeek(date: Date): number; 291 | 292 | /** 293 | * Get the year for a week number of a date. 294 | * @param date - The date object to get the year from. 295 | * @returns The year for the week number. 296 | */ 297 | export function getYearForWeekNo(date: Date): number; 298 | 299 | /** 300 | * Get the 12-hour format of the hour of a date. 301 | * @param date - The date object to get the hour from. 302 | * @returns The 12-hour format of the hour. 303 | */ 304 | export function getHours12(date: Date): number; 305 | 306 | /** 307 | * Convert a date delta in milliseconds into a string representation of "23 seconds ago", "27 minutes ago" etc. 308 | * @param delta - delta in milliseconds 309 | * @returns An object with these members: 310 | * - description: string describing the delta period 311 | * - updatePeriod: time in millisecond until the string will be inaccurate 312 | * @description 将以毫秒为单位的日期差转换为“23秒前”、“27分钟前”等字符串表示形式。 313 | */ 314 | export function getRelativeDate(delta: number): { 315 | description: string; 316 | updatePeriod: number; 317 | }; 318 | 319 | /** 320 | * Convert & to "&", < to "<", > to ">", " to """ 321 | * @param s - The string to encode. 322 | * @returns The encoded string. 323 | * @description 将 & 转换为 "&",< 转换为 "<",> 转换为 ">"," 转换为 """。 324 | */ 325 | export function htmlEncode(s: string): string; 326 | 327 | /** 328 | * Converts like htmlEncode, but forgets the double quote for brevity 329 | * @param s - The string to encode. 330 | * @returns The encoded string. 331 | * @description 类似于 htmlEncode,但为了简洁起见忽略了双引号。 332 | */ 333 | export function htmlTextEncode(s: string): string; 334 | 335 | /** 336 | * Converts all HTML entities to their character equivalents. 337 | * @param s - The string to decode. 338 | * @returns The decoded string. 339 | * @description 将所有 HTML 实体转换为它们的字符等价物。 340 | */ 341 | export function entityDecode(s: string): string; 342 | 343 | /** 344 | * Unescapes line breaks. 345 | * @param s - The string to unescape. 346 | * @returns The unescaped string. 347 | * @description 取消转义换行符。 348 | */ 349 | export function unescapeLineBreaks(s: string): string; 350 | 351 | /** 352 | * Returns an escape sequence for given character. Uses `\x` for characters `<=` 0xFF to save space, `\u` for the rest. 353 | * @param ch - The character to escape. 354 | * @returns The escaped character. 355 | * @description 返回给定字符的转义序列。对于字符 `<=` 0xFF,使用 `\x` 以节省空间,对于其余字符使用 `\u`。 356 | */ 357 | export function escape(ch: string): string; 358 | 359 | /** 360 | * Turns a string into a legal JavaScript string. 361 | * @param s - The string to stringify. 362 | * @param rawUnicode - Whether to escape non-ASCII characters. 363 | * @returns The stringified string. 364 | * @description 将字符串转换为合法的 JavaScript 字符串。 365 | */ 366 | export function stringify(s: string, rawUnicode?: boolean): string; 367 | 368 | /** 369 | * Turns a string into a legal JSON string. 370 | * @param s - The string to stringify. 371 | * @param rawUnicode - Whether to escape non-ASCII characters. 372 | * @returns The stringified JSON string. 373 | * @description 将字符串转换为合法的 JSON 字符串。 374 | */ 375 | export function jsonStringify(s: string, rawUnicode?: boolean): string; 376 | 377 | /** 378 | * Escapes the RegExp special characters with a preceding backslash. 379 | * @param s - The string to escape. 380 | * @returns The escaped string. 381 | * @description 使用反斜杠转义 RegExp 特殊字符。 382 | */ 383 | export function escapeRegExp(s: string): string; 384 | 385 | /** 386 | * An extended version of encodeURIComponent that encodes additional characters including those that are illegal within filepaths on various platforms including Windows. 387 | * @param s - The string to encode. 388 | * @returns The encoded string. 389 | * @description encodeURIComponent 的扩展版本,可编码包括在各种平台(包括 Windows)的文件路径中非法的其他字符。 390 | */ 391 | export function encodeURIComponentExtended(s: string): string; 392 | 393 | /** 394 | * Checks whether a link target is external, i.e. not a tiddler title. 395 | * @param to - The link target to check. 396 | * @returns True if the link target is external, false otherwise. 397 | * @description 检查链接目标是否为外部链接,即不是 tiddler 标题。 398 | */ 399 | export function isLinkExternal(to: string): boolean; 400 | 401 | /** 402 | * Executes a function on the next tick of the event loop. 403 | * @param fn - The function to execute. 404 | * @description 在事件循环的下一个时刻执行函数。 405 | */ 406 | export function nextTick(function_: () => void): void; 407 | 408 | /** 409 | * Converts a hyphenated CSS property name into a camel case one. 410 | * @param propName - The CSS property name to convert. 411 | * @returns The converted CSS property name. 412 | * @description 将连字符分隔的 CSS 属性名称转换为驼峰式。 413 | */ 414 | export function unHyphenateCss(propertyName: string): string; 415 | 416 | /** 417 | * Converts a camelcase CSS property name into a dashed one ("backgroundColor" --> "background-color"). 418 | * @param propName - The CSS property name to convert. 419 | * @returns The converted CSS property name. 420 | * @description 将驼峰式的 CSS 属性名称转换为连字符分隔的。 421 | */ 422 | export function hyphenateCss(propertyName: string): string; 423 | 424 | /** 425 | * Parses a text reference of one of these forms: 426 | * * title 427 | * * !!field 428 | * * title!!field 429 | * * title##index 430 | * * etc 431 | * Returns an object with the following fields, all optional: 432 | * * title: tiddler title 433 | * * field: tiddler field name 434 | * * index: JSON property index 435 | * @param textRef - The text reference to parse. 436 | * @returns An object with the parsed fields. 437 | * @description 解析文本引用,支持以下格式: 438 | * * title 439 | * * !!field 440 | * * title!!field 441 | * * title##index 442 | * * 等等 443 | * 返回一个包含以下字段的对象,所有字段都是可选的: 444 | * * title:tiddler 标题 445 | * * field:tiddler 字段名称 446 | * * index:JSON 属性索引 447 | */ 448 | export function parseTextReference(textReference: string): { 449 | field?: string; 450 | index?: string; 451 | title?: string; 452 | }; 453 | 454 | /** 455 | * Checks whether a string is a valid field name. 456 | * @param name - The string to check. 457 | * @returns True if the string is a valid field name, false otherwise. 458 | * @description 检查字符串是否为有效的字段名称。 459 | */ 460 | export function isValidFieldName(name: string): boolean; 461 | 462 | /** 463 | * Extracts the version number from the meta tag or from the boot file. 464 | * @returns The version number. 465 | * @description 从 meta 标签或启动文件中提取版本号。 466 | */ 467 | export function extractVersionInfo(): string | null; 468 | 469 | /** 470 | * Gets the animation duration in milliseconds. 471 | * @returns The animation duration. 472 | * @description 获取动画持续时间(以毫秒为单位)。 473 | */ 474 | export function getAnimationDuration(): number; 475 | 476 | /** 477 | * Hashes a string to a number. the function behind `<>` 478 | * @param str - The string to hash. 479 | * @returns The hashed number. 480 | * @description 将字符串哈希为数字。 481 | */ 482 | export function hashString(string_: string): number; 483 | 484 | /** 485 | * Decodes a base64 string. 486 | * @param string64 - The base64 string to decode. 487 | * @returns The decoded string. 488 | * @description 解码 base64 字符串。 489 | */ 490 | export function base64Decode(string64: string): string; 491 | 492 | /** 493 | * Encodes a string to base64. 494 | * @param string64 - The string to encode. 495 | * @returns The encoded base64 string. 496 | * @description 将字符串编码为 base64。 497 | */ 498 | export function base64Encode(string64: string): string; 499 | 500 | /** 501 | * Converts a hashmap into a tiddler dictionary format sequence of name:value pairs. 502 | * @param data - The hashmap to convert. 503 | * @returns The tiddler dictionary format sequence of name:value pairs. 504 | * @description 将 hashmap 转换为 tiddler 字典格式的 name:value 对序列。 505 | */ 506 | export function makeTiddlerDictionary(data: Record): string; 507 | 508 | /** 509 | * High resolution microsecond timer for profiling. 510 | * @param base - The base time to subtract from the current time. 511 | * @returns The current time in microseconds. 512 | * @description 用于分析的高分辨率微秒计时器。 513 | */ 514 | export function timer(base?: number): number; 515 | 516 | /** 517 | * Converts text and content type to a data URI. 518 | * @param text - The text to convert. 519 | * @param type - The content type of the text. 520 | * @param _canonical_uri - The canonical URI of the text. 521 | * @returns The data URI. 522 | * @description 将文本和内容类型转换为数据 URI。 523 | */ 524 | export function makeDataUri( 525 | text: string, 526 | type?: string, 527 | _canonical_uri?: string, 528 | ): string; 529 | 530 | /** 531 | * Converts a tag name to its fully escaped CSS selector equivalent. 532 | * @param tagName - The tag name to convert. 533 | * @returns The fully escaped CSS selector equivalent. 534 | * @description 将标签名称转换为其完全转义的 CSS 选择器等效项。 535 | */ 536 | export function tagToCssSelector(tagName: string): string; 537 | 538 | /** 539 | * Returns the sign of a number. 540 | * @param x - The number to check. 541 | * @returns 1 if the number is positive, -1 if it is negative, and 0 if it is zero or NaN. 542 | * @description 返回数字的符号。如果数字为正,则返回 1,如果数字为负,则返回 -1,如果数字为零或 NaN,则返回 0。 543 | */ 544 | export function sign(x: number): number; 545 | 546 | /** 547 | * Checks whether a string ends with a given substring. 548 | * @param str - The string to check. 549 | * @param ending - The substring to check for. 550 | * @param position - The position to start checking from. 551 | * @returns True if the string ends with the substring, false otherwise. 552 | * @description 检查字符串是否以给定的子字符串结尾。 553 | */ 554 | export function stringEndsWith( 555 | string_: string, 556 | ending: string, 557 | position?: number, 558 | ): boolean; 559 | 560 | /** 561 | * Returns system information useful for debugging. 562 | * @returns A string with system information. 563 | * @description 返回有用于调试的系统信息字符串。 564 | */ 565 | export function getSystemInfo(): string; 566 | 567 | /** 568 | * Parses a string into a number. 569 | * @param str - The string to parse. 570 | * @returns The parsed number or 0 if the string is not a valid number. 571 | * @description 将字符串解析为数字。 572 | */ 573 | export function parseNumber(string_: string): number; 574 | 575 | /** 576 | * Parses a string into an integer. 577 | * @param str - The string to parse. 578 | * @returns The parsed integer or 0 if the string is not a valid integer. 579 | * @description 将字符串解析为整数。 580 | */ 581 | export function parseInt(string_: string): number; 582 | 583 | /** 584 | * Converts a number to a string. 585 | * @param num - The number to convert. 586 | * @returns The converted string. 587 | * @description 将数字转换为字符串。 588 | */ 589 | export function stringifyNumber(number_: number): string; 590 | 591 | /** 592 | * Creates a comparison function for a given type. 593 | * @param type - The type of comparison function to create. 594 | * @param options - The options for the comparison function. 595 | * @returns The comparison function. 596 | * @description 创建给定类型的比较函数。 597 | */ 598 | export function makeCompareFunction( 599 | type: string, 600 | options?: { 601 | defaultType?: string; 602 | invert?: boolean; 603 | isCaseSensitive?: boolean; 604 | }, 605 | ): (a: string, b: string) => number; 606 | } 607 | -------------------------------------------------------------------------------- /src/modules/wiki.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'tiddlywiki' { 2 | export interface IMakeWidgetOptions { 3 | document?: TWDocument; 4 | variables?: Record; 5 | parentWidget?: Widget; 6 | } 7 | export type IRenderOptions = IMakeWidgetOptions & IParseOptions; 8 | 9 | export type OutputMimeTypes = 10 | | 'text/html' 11 | | 'text/plain-formatted' 12 | | 'text/plain'; 13 | export type TextMimeTypes = 14 | | 'text/html' 15 | | 'text/vnd.tiddlywiki' 16 | | 'text/plain'; 17 | export type ITiddlerFieldsParameter = 18 | & Omit< 19 | Partial, 20 | 'created' | 'modified' 21 | > 22 | & { created?: string; modified?: string }; 23 | export type ITiddlerJSONResult = 24 | & Omit< 25 | Partial, 26 | 'list' | 'tags' 27 | > 28 | & { list?: string; tags?: string }; 29 | export class Wiki { 30 | /** 31 | * Wiki constructor. State is stored in private members that only a small number of privileged accessor methods have direct access. Methods added via the prototype have to use these accessors and cannot access the state data directly. 32 | * @param {{ enableIndexers: unknown[] }} options options include: 33 | * * enableIndexers - Array of indexer names to enable, or null to use all available indexers 34 | * @memberof Wiki 35 | */ 36 | constructor(options: { enableIndexers: unknown[] }); 37 | addIndexer(indexer: unknown, name: string): void; 38 | getTiddler(title: string): Tiddler | undefined; 39 | /** 40 | * Get full list of tiddler titles in the wiki 41 | */ 42 | getTiddlers(): string[]; 43 | /** 44 | * Get JSON string of tiddlers. Note that this will make lists like tags/list to be string, instead of array. And result is a string, not an array. 45 | * @param filter Filter string 46 | * @param spaces Last arg of `JSON.stringify`, default is `' '` 47 | * @returns a stringified JSON with type ITiddlerJSONResult. You will need to use `JSON.parse` on it. 48 | */ 49 | getTiddlersAsJson(filter: string, spaces?: string): string; 50 | /** 51 | * Get JSON string of tiddler. Note that this will make lists like tags/list to be string, instead of array. And result is a string, not an object. 52 | * @param title 53 | * @returns a stringified JSON with type ITiddlerJSONResult. You will need to use `JSON.parse` on it. 54 | */ 55 | getTiddlerAsJson(title: string): string; 56 | deleteTiddler(title: string): void; 57 | each(callback: (tiddler: Tiddler, title: string) => void): void; 58 | /** 59 | * For every tiddler invoke a callback(title,tiddler) with `this` set to the wiki object. 60 | * @param options Options include sortField, excludeTag, includeSystem 61 | * @param callback Function to be called for each tiddler 62 | */ 63 | forEachTiddler(options: { sortField?: string; excludeTag?: string; includeSystem?: boolean }, callback: (title: string, tiddler: Tiddler) => void): void; 64 | forEachTiddler(callback: (title: string, tiddler: Tiddler) => void): void; 65 | /** 66 | * Sort an array of tiddler titles by a specified field 67 | * @param titles Array of titles (sorted in place) 68 | * @param sortField Name of field to sort by 69 | * @param isDescending True if the sort should be descending 70 | * @param isCaseSensitive True if the sort should consider upper and lower case letters to be different 71 | * @param isNumeric True if the sort should be numeric 72 | * @param isAlphaNumeric True if the sort should be alphanumeric 73 | */ 74 | sortTiddlers(titles: string[], sortField: string, isDescending?: boolean, isCaseSensitive?: boolean, isNumeric?: boolean, isAlphaNumeric?: boolean): void; 75 | /** 76 | * Return an array of tiddler titles that match a search string 77 | * @param text The text string to search for 78 | * @param options Search options 79 | */ 80 | search(text: string, options?: { 81 | /** An iterator function for the source tiddlers */ 82 | source?: (callback: (tiddler: Tiddler, title: string) => void) => void; 83 | /** An array of tiddler titles to exclude from the search */ 84 | exclude?: string[]; 85 | /** If true returns tiddlers that do not contain the specified string */ 86 | invert?: boolean; 87 | /** If true forces a case sensitive search */ 88 | caseSensitive?: boolean; 89 | /** If specified, restricts the search to the specified field, or an array of field names */ 90 | field?: string | string[]; 91 | /** If true, forces all but regexp searches to be anchored to the start of text */ 92 | anchored?: boolean; 93 | /** If true, the field options are inverted to specify the fields that are not to be searched */ 94 | excludeField?: boolean; 95 | /** Searches for literal string */ 96 | literal?: boolean; 97 | /** Same as literal except runs of whitespace are treated as a single space */ 98 | whitespace?: boolean; 99 | /** Treats the search term as a regular expression */ 100 | regexp?: boolean; 101 | /** Treats search string as a list of tokens, and matches if all tokens are found */ 102 | words?: boolean; 103 | /** Treats search string as a list of tokens, and matches if at least ONE token is found */ 104 | some?: boolean; 105 | }): string[]; 106 | /** 107 | * Check whether the text of a tiddler matches a given value 108 | * @param title Tiddler title 109 | * @param targetText Text to compare with 110 | * @param options Comparison options 111 | */ 112 | checkTiddlerText(title: string, targetText: string, options?: { noTrim?: boolean; caseSensitive?: boolean }): boolean; 113 | /** 114 | * Return the content of a tiddler as an array containing each line 115 | * @param title Title of the tiddler 116 | * @param field Field name (defaults to "list") 117 | * @param index Data index (key) to get, if you are getting a JSON data tiddler 118 | * @returns Array of strings parsed from the field/index value 119 | */ 120 | getTiddlerList(title: string, field?: string, index?: string): string[]; 121 | /** 122 | * Get the value of a text reference. Text references can have any of these forms: 123 | * - 124 | * - !! 125 | * - !! - specifies a field of the current tiddlers 126 | * - ## 127 | * @param textRef The text reference string 128 | * @param defaultText Default text to return if the reference is not found 129 | * @param currTiddlerTitle Current tiddler title for relative references 130 | */ 131 | getTextReference(textReference: string, defaultText?: string, currentTiddlerTitle?: string): string | undefined; 132 | /** 133 | * Set the value of a text reference 134 | * @param textRef The text reference string 135 | * @param value The value to set 136 | * @param currTiddlerTitle Current tiddler title for relative references 137 | */ 138 | setTextReference(textReference: string, value: string, currentTiddlerTitle?: string): void; 139 | /** 140 | * Delete a text reference 141 | * @param textRef The text reference string 142 | * @param currTiddlerTitle Current tiddler title for relative references 143 | */ 144 | deleteTextReference(textReference: string, currentTiddlerTitle?: string): void; 145 | /** 146 | * Count the number of tiddlers in the wiki 147 | * @param excludeTag Optional tag to exclude from the count 148 | */ 149 | countTiddlers(excludeTag?: string): number; 150 | /** 151 | * Return a named global cache object. Global cache objects are cleared whenever a tiddler change. 152 | * You can put anything into the cache. 153 | * @param cacheName key of the cache 154 | * @param initializer when cache miss, this will be called to get initial value 155 | */ 156 | getGlobalCache(cacheName: string, initializer: () => T): T; 157 | /** 158 | * Return the named cache object for a tiddler. If the cache doesn't exist then the initializer function is invoked to create it 159 | * @param cacheName key of the cache 160 | * @param initializer when cache miss, this will be called to get initial value 161 | */ 162 | getCacheForTiddler( 163 | title: string, 164 | cacheName: string, 165 | initializer: () => T, 166 | ): T; 167 | /** 168 | * clear all cache, will be called when a tiddler is changed 169 | */ 170 | clearGlobalCache(): void; 171 | /** 172 | * Clear all caches associated with a particular tiddler, or if the title is null, clear all caches for all tiddlers 173 | * @param title Tiddler title or null to clear all caches 174 | */ 175 | clearCache(title?: string | null): void; 176 | /** 177 | * Compile filter string to be a function that execute the filter in the wiki. 178 | * You can pass an optional iterator that provide the input to the returned function. If no iterator is provided, filter will use first operator to get input. 179 | * 180 | * @returns a function with the signature fn(source,widget) where: 181 | source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title) 182 | widget: an optional widget node for retrieving the current tiddler etc. 183 | */ 184 | compileFilter( 185 | filterString: string, 186 | ): ( 187 | source?: ((iterator: SourceIterator) => void) | string[] | Record, 188 | widget?: Widget, 189 | ) => string[]; 190 | /** 191 | * @param filterString 192 | * @param widget an optional widget node for retrieving the current tiddler etc. 193 | * @param source an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title) 194 | */ 195 | /** 196 | * Returns a function iterator(callback) that iterates through the specified titles, and invokes the callback with callback(tiddler,title) 197 | */ 198 | makeTiddlerIterator(titles: string[]): SourceIterator; 199 | /** 200 | * You can use this with `makeTiddlerIterator`: 201 | * 202 | * ```js 203 | * $tw.wiki.filterTiddlers(filter, undefined, $tw.wiki.makeTiddlerIterator(['title'])) 204 | * ``` 205 | * 206 | * This calls `compileFilter` 207 | * @param filterString 208 | * @param widget 209 | * @param source 210 | */ 211 | filterTiddlers( 212 | filterString: string, 213 | widget?: Widget, 214 | source?: SourceIterator, 215 | ): string[]; 216 | /** 217 | * Set JSON tiddler, Object in data field will be JSON.stringify and put into the text. 218 | * This will make tiddler to be JSON data tiddler `"type":"application/json"`, so if you just want to modify existed tiddler's data, use `addTiddler` instead. 219 | */ 220 | setTiddlerData( 221 | title: string, 222 | data?: object, 223 | fields?: ITiddlerFieldsParameter, 224 | options?: { suppressTimestamp?: boolean }, 225 | ): void; 226 | /** 227 | * Create or update tiddler. 228 | * Update existed tiddler based on the title field. 229 | */ 230 | addTiddler( 231 | tiddler: Tiddler | Partial | Partial, 232 | ): void; 233 | /** 234 | * Call `addTiddler` for each iton of the list, but should passing `tiddler.fields`, directly passing tiddler object may failed to add in some cases. 235 | */ 236 | addTiddlers( 237 | tiddler: Array | Partial>, 238 | ): void; 239 | /** 240 | * Get tiddler's text field, with an optional default text. 241 | * If have _is_skinny field, will just return null (this is a rare case, so not put in the return type for now). 242 | * 243 | * @param title will return undefined (or fallback) if the tiddler isn't found 244 | * @param fallbackText default text when text field is empty or undefined 245 | */ 246 | getTiddlerText(title: string, fallbackText: string): string; 247 | getTiddlerText(title: string, fallbackText?: string): string | undefined; 248 | /** 249 | Get the content of a tiddler as a JavaScript object. How this is done depends on the type of the tiddler: 250 | 251 | application/json: the tiddler JSON is parsed into an object 252 | application/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs 253 | 254 | Other types currently just return undefined or as same as fallbackData. 255 | 256 | titleOrTiddler: string tiddler title or a tiddler object 257 | defaultData: default data to be returned if the tiddler is missing or doesn't contain data 258 | 259 | Alternative, uncached version of getTiddlerDataCached(). The return value can be mutated freely and reused 260 | */ 261 | getTiddlerData | unknown[] | undefined>( 262 | titleOrTiddler: string | Tiddler, 263 | fallbackData?: D, 264 | ): D; 265 | /** 266 | * D is any JSON, like JSON object or JSON array 267 | * 268 | * Get the content of a tiddler as a JavaScript object. How this is done depends on the type of the tiddler: 269 | 270 | application/json: the tiddler JSON is parsed into an object 271 | application/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs 272 | 273 | Other types currently just return undefined or as same as fallbackData. 274 | 275 | titleOrTiddler: string tiddler title or a tiddler object 276 | defaultData: default data to be returned if the tiddler is missing or doesn't contain data 277 | 278 | Note that the same value is returned for repeated calls for the same tiddler data. The value is frozen to prevent modification; otherwise modifications would be visible to all callers 279 | */ 280 | getTiddlerDataCached( 281 | titleOrTiddler: string | Tiddler, 282 | fallbackData?: D, 283 | ): D; 284 | /** 285 | * Set tiddler text of any field. 286 | * 287 | * @param {string} title title of tiddler 288 | * @param {string} field field name to set 289 | * @param {string | undefined} index data index(key) to set, if you are setting a JSON data tiddler. Be `undefined` if you are just setting a normal tiddler's field, this will be most of the case. 290 | * @param {string} value text content to set 291 | * @param {object} options options, see tiddlywiki dev doc for details 292 | */ 293 | setText( 294 | title: string, 295 | field?: string, 296 | index?: string, 297 | value?: string, 298 | options?: { suppressTimestamp?: boolean }, 299 | ): void; 300 | /** 301 | Parse a tiddler according to its MIME type 302 | */ 303 | parseTiddler(title: string, options?: IParseOptions): WikiParser; 304 | /** 305 | Parse a block of text of a specified MIME type 306 | @param {string} type: MIME content type of text to be parsed 307 | @param {string} text: text 308 | @param {object}options: see below 309 | 310 | Options include: 311 | - parseAsInline: if true, the text of the tiddler will be parsed as an inline run 312 | - _canonical_uri: optional string of the canonical URI of this content 313 | */ 314 | parseText(type: string, text: string, options?: IParseOptions): WikiParser; 315 | /** 316 | * Extracts tiddlers from a typed block of text, specifying default field values 317 | * @param {string} type: MIME content type of text to be parsed 318 | * @param {string} text: text 319 | * @param {object} srcFields: default field values 320 | * @param {object} options: see below 321 | * 322 | * Options include: 323 | * - deserializer: string, key of `$tw.Wiki.tiddlerDeserializerModules` 324 | */ 325 | deserializeTiddlers( 326 | type: string, 327 | text: string, 328 | sourceFields?: ITiddlerFieldsParameter, 329 | options?: IParseOptions, 330 | ): ITiddlerFieldsParameter[]; 331 | /** 332 | Parse text from a tiddler and render it into another format 333 | outputType: content type for the output 334 | title: title of the tiddler to be rendered 335 | options: see below 336 | Options include: 337 | variables: hashmap of variables to set 338 | parentWidget: optional parent widget for the root node 339 | */ 340 | renderTiddler( 341 | outputType: OutputMimeTypes, 342 | title: string, 343 | options?: IRenderOptions, 344 | ): string; 345 | /** 346 | Parse text in a specified format and render it into another format 347 | @param outputType content type for the output 348 | @param textType content type of the input text 349 | @param text input text 350 | @param options see below, Options includes: 351 | - variables: hashmap of variables to set 352 | - parentWidget: optional parent widget for the root node 353 | */ 354 | renderText( 355 | outputType: OutputMimeTypes, 356 | textType: string, 357 | text: string, 358 | options?: Partial & IParseOptions, 359 | ): string; 360 | /** 361 | Make a widget tree for a parse tree 362 | @params parser: parser object 363 | @params options: see below 364 | Options include: 365 | document: optional document to use 366 | variables: hashmap of variables to set 367 | parentWidget: optional parent widget for the root node 368 | */ 369 | makeWidget( 370 | parser: { tree: IParseTreeNode[] }, 371 | options?: IMakeWidgetOptions, 372 | ): Widget; 373 | /** 374 | Make a widget tree for transclusion 375 | @params title: target tiddler title 376 | @params options: as for wiki.makeWidget() plus: 377 | 378 | - options.field: optional field to transclude (defaults to "text") 379 | - options.mode: transclusion mode "inline" or "block" 380 | - options.recursionMarker : optional flag to set a recursion marker, defaults to "yes" 381 | - options.children: optional array of children for the transclude widget 382 | - options.importVariables: optional importvariables filter string for macros to be included 383 | - options.importPageMacros: optional boolean; if true, equivalent to passing "[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]" to options.importVariables 384 | */ 385 | makeTranscludeWidget( 386 | title: string, 387 | options: { 388 | /** optional array of children for the transclude widget */ 389 | children?: Widget[]; 390 | /** optional field to transclude (defaults to "text") */ 391 | field?: string; 392 | /** optional boolean; if true, equivalent to passing "[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]" to options.importVariables */ 393 | importPageMacros?: boolean; 394 | /** optional importvariables filter string for macros to be included */ 395 | importVariables?: string; 396 | /** transclusion mode "inline" or "block" */ 397 | mode?: 'inline' | 'block'; 398 | /** optional flag to set a recursion marker, defaults to "yes" */ 399 | recursionMarker?: 'yes' | 'no'; 400 | } & IMakeWidgetOptions, 401 | ): Widget; 402 | /** Test for the existence of a tiddler (excludes shadow tiddlers) */ 403 | tiddlerExists(title: string): boolean; 404 | /** Determines if a tiddler is a shadow tiddler, regardless of whether it has been overridden by a real tiddler */ 405 | isShadowTiddler(title: string): boolean; 406 | isBinaryTiddler(title: string): boolean; 407 | isImageTiddler(title: string): boolean; 408 | isSystemTiddler(title: string): boolean; 409 | isTemporaryTiddler(title: string): boolean; 410 | isVolatileTiddler(title: string): boolean; 411 | /** 412 | * Like addTiddler() except it will silently reject any plugin tiddlers that are older than the currently loaded version. Returns true if the tiddler was imported 413 | */ 414 | importTiddler(title: string): boolean; 415 | /** return shadowTiddlers[title].source; */ 416 | getShadowSource(title: string): string | null; 417 | getTiddlerBacklinks(targetTitle: string): string[]; 418 | getTiddlerLinks(title: string): string[]; 419 | /** 420 | * Return an array of tiddler titles that are directly linked within the given parse tree 421 | * @param parseTreeRoot The parse tree root node 422 | */ 423 | extractLinks(parseTreeRoot: IParseTreeNode[]): string[]; 424 | /** 425 | * Return an array of tiddler titles that are directly transcluded within the given parse tree 426 | * @param parseTreeRoot The parse tree root node 427 | * @param title The tiddler being parsed (to ignore self-referential transclusions) 428 | */ 429 | extractTranscludes(parseTreeRoot: IParseTreeNode[], title?: string): string[]; 430 | /** 431 | * Return an array of tiddler titles that are transcluded from the specified tiddler 432 | * @param title Tiddler title 433 | */ 434 | getTiddlerTranscludes(title: string): string[]; 435 | /** 436 | * Return an array of tiddler titles that transclude to the specified tiddler 437 | * @param targetTitle Target tiddler title 438 | */ 439 | getTiddlerBacktranscludes(targetTitle: string): string[]; 440 | /** 441 | * Lookup a given tiddler and return a list of all the tiddlers that include it in the specified list field 442 | * @param targetTitle Target tiddler title 443 | * @param fieldName Field name (defaults to "list") 444 | */ 445 | findListingsOfTiddler(targetTitle: string, fieldName?: string): string[]; 446 | getPluginInfo(title: string): { tiddlers: Record }; 447 | getChangeCount(title: string): number; 448 | /** 449 | Generate an unused title from the specified base 450 | options.prefix must be a string 451 | */ 452 | generateNewTitle(baseTitle: string, options: { prefix?: string }): string; 453 | /** 454 | * Get a subtiddler from a plugin or data tiddler 455 | * @param title Title of the plugin or data tiddler 456 | * @param subTiddlerTitle Title of the subtiddler within the bundle 457 | */ 458 | getSubTiddler(title: string, subTiddlerTitle: string): Tiddler | null; 459 | /** 460 | * Return a hashmap of tiddler titles that are referenced but not defined 461 | */ 462 | /** 463 | * Return a hashmap of the fields that should be set when a tiddler is created 464 | */ 465 | getCreationFields(): { created?: Date; creator?: string }; 466 | /** 467 | * Return a hashmap of the fields that should be set when a tiddler is modified. 468 | * This is used for generating `modified` field when modify tiddler using actions like `action-setmultiplefields` 469 | */ 470 | getModificationFields(): { modified?: Date; modifier?: string }; 471 | /** 472 | * Retrieves a list of the tiddler titles that are tagged with a given tag 473 | */ 474 | getTiddlersWithTag(tag: string): string[]; 475 | 476 | getMissingTitles(): string[]; 477 | /** 478 | * Return an array of tiddler titles that are not linked from any other tiddler 479 | */ 480 | getOrphanTitles(): string[]; 481 | /** 482 | * Sorts an array of tiddler titles according to an ordered list 483 | * @param array Array of tiddler titles to sort 484 | * @param listTitle Title of tiddler containing the ordered list 485 | */ 486 | sortByList(array: string[], listTitle: string): string[]; 487 | /** 488 | * Get a hashmap by tag of arrays of tiddler titles 489 | */ 490 | getTagMap(): Record; 491 | /** 492 | * Find any existing draft of a specified tiddler 493 | * @param targetTitle Title of the target tiddler 494 | */ 495 | findDraft(targetTitle: string): string | undefined; 496 | /** 497 | * Check whether the specified draft tiddler has been modified 498 | * @param title Title of the draft tiddler 499 | */ 500 | isDraftModified(title: string): boolean; 501 | /** 502 | * Add a new tiddler to the story river 503 | * @param title A title string or an array of title strings 504 | * @param fromTitle The title of the tiddler from which the navigation originated 505 | * @param storyTitle Title of story tiddler (defaults to $:/StoryList) 506 | * @param options Additional options 507 | * @deprecated Use story.addToStory() from the story object instead 508 | */ 509 | addToStory(title: string | string[], fromTitle?: string, storyTitle?: string, options?: { openLinkFromInsideRiver?: boolean; openLinkFromOutsideRiver?: boolean }): void; 510 | /** 511 | * Add a new record to the top of the history stack 512 | * @param title A title string or an array of title strings 513 | * @param fromPageRect Page coordinates of the origin of the navigation 514 | * @param historyTitle Title of history tiddler (defaults to $:/HistoryList) 515 | * @deprecated Use story.addToHistory() from the story object instead 516 | */ 517 | addToHistory(title: string | string[], fromPageRect?: unknown, historyTitle?: string): void; 518 | /** 519 | * Generate a draft title for a given tiddler 520 | * @param title Title of the tiddler to create a draft for 521 | */ 522 | generateDraftTitle(title: string): string; 523 | /** 524 | * Convert a title to a URL-friendly slug 525 | * @param title Title to slugify 526 | * @param options Options (currently unused) 527 | */ 528 | slugify(title: string, options?: { separator?: string }): string; 529 | /** 530 | * Invoke the available upgrader modules 531 | * @param titles Array of tiddler titles to be processed 532 | * @param tiddlers Hashmap by title of tiddler fields of pending import tiddlers 533 | */ 534 | invokeUpgraders(titles: string[], tiddlers: Record): Record; 535 | /** 536 | * Determine whether a plugin by title is dynamically loadable 537 | * @param title Plugin title 538 | */ 539 | doesPluginRequireReload(title: string): boolean; 540 | /** 541 | * Determine whether a plugin info structure is dynamically loadable 542 | * @param pluginInfo Plugin info object 543 | */ 544 | doesPluginInfoRequireReload(pluginInfo: IPluginInfo): boolean | null; 545 | /** 546 | * Execute an action string without an associated context widget 547 | * @param actions Action string to execute 548 | * @param event Event object 549 | * @param variables Variables hashmap 550 | * @param options Options including parentWidget 551 | */ 552 | invokeActionString(actions: string, event?: IWidgetEvent | null, variables?: Record, options?: { parentWidget?: Widget }): void; 553 | /** 554 | * Read an array of browser File objects 555 | * @param files Array of File objects 556 | * @param options Options or callback function 557 | */ 558 | readFiles(files: File[], options?: { callback?: (tiddlerFieldsArray: ITiddlerFields[]) => void } | ((tiddlerFieldsArray: ITiddlerFields[]) => void)): number; 559 | /** 560 | * Read a browser File object 561 | * @param file File object 562 | * @param options Options or callback function 563 | */ 564 | readFile(file: File, options?: { callback?: (tiddlerFieldsArray: ITiddlerFields[]) => void; deserializer?: string } | ((tiddlerFieldsArray: ITiddlerFields[]) => void)): void; 565 | /** 566 | * Lower level utility to read the content of a browser File object 567 | * @param file File object 568 | * @param type MIME type 569 | * @param isBinary Whether the file is binary 570 | * @param deserializer Deserializer name 571 | * @param callback Callback function 572 | */ 573 | readFileContent(file: File, type: string, isBinary: boolean, deserializer: string | undefined, callback: (tiddlerFieldsArray: ITiddlerFields[]) => void): void; 574 | /** 575 | * Get substituted text with variable and filter replacements 576 | * @param text Text to perform substitutions on 577 | * @param widget Widget for context 578 | * @param options Options including substitutions array 579 | */ 580 | getSubstitutedText(text: string, widget: Widget, options?: { substitutions?: Array<{ name: string; value: string }> }): string; 581 | /** 582 | * Parse a text reference and get parser info 583 | * @param title Title of tiddler 584 | * @param field Field name 585 | * @param index Index name 586 | * @param options Options including subTiddler and defaultType 587 | */ 588 | getTextReferenceParserInfo( 589 | title: string, 590 | field?: string, 591 | index?: string, 592 | options?: { subTiddler?: string; defaultType?: string }, 593 | ): { parserType: string | null; sourceText: string | null }; 594 | /** 595 | * Parse a text reference 596 | * @param title Title of tiddler 597 | * @param field Field name 598 | * @param index Index name 599 | * @param options Parse options 600 | */ 601 | parseTextReference(title: string, field?: string, index?: string, options?: IParseOptions): WikiParser | null; 602 | /** 603 | * Get the size of tiddler event queue 604 | */ 605 | getSizeOfTiddlerEventQueue(): number; 606 | /** 607 | * Clear the tiddler event queue 608 | */ 609 | clearTiddlerEventQueue(): void; 610 | /** 611 | * Enqueue a tiddler event (internal method) 612 | * @param title Tiddler title 613 | * @param isDeleted Whether the tiddler was deleted 614 | * @param isShadow Whether this is a shadow tiddler change 615 | */ 616 | enqueueTiddlerEvent(title: string, isDeleted?: boolean, isShadow?: boolean): void; 617 | /** 618 | * Initialize parsers (internal method) 619 | * @param moduleType Module type 620 | */ 621 | initParsers(moduleType?: string): void; 622 | /** 623 | * Add indexers to this wiki (internal method) 624 | */ 625 | addIndexersToWiki(): void; 626 | 627 | removeEventListener( 628 | type: string, 629 | handler: (event: unknown) => void | Promise, 630 | ): void; 631 | 632 | addEventListener( 633 | type: string, 634 | handler: (event: unknown) => void | Promise, 635 | ): void; 636 | addEventListener( 637 | type: 'change', 638 | handler: (change: IChangedTiddlers) => void | Promise, 639 | ): void; 640 | addEventListener( 641 | type: 'lazyLoad', 642 | handler: (title: string) => void | Promise, 643 | ): void; 644 | 645 | dispatchEvent( 646 | type: string, 647 | dataOrEvent: unknown, 648 | ): void; 649 | dispatchEvent( 650 | type: 'change', 651 | change: IChangedTiddlers, 652 | ): void; 653 | dispatchEvent( 654 | type: 'lazyLoad', 655 | title: string, 656 | ): void; 657 | } 658 | } 659 | --------------------------------------------------------------------------------