1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-02-22 01:49:49 +00:00

Compare commits

..

25 Commits

Author SHA1 Message Date
Jeremy Ruston
c05400021c Merge branch 'master' into intrinsic-sub-plugins 2025-03-21 17:24:56 +00:00
Jeremy Ruston
5111be1953 Merge branch 'master' into intrinsic-sub-plugins 2025-02-27 17:36:41 +00:00
Jeremy Ruston
9dadd3fafb Display subplugins in control panel listing 2025-02-27 16:54:32 +00:00
Jeremy Ruston
12ced06d1d Add subplugins for codemirror languages
The French translation is just for demo purposes. It would be helpful to replace it with some real translations.
2025-02-27 12:49:24 +00:00
Jeremy Ruston
a4e8308e75 Add comment 2025-02-27 12:48:07 +00:00
Jeremy Ruston
9a2534fc5e Fix accidentally disabled test 2025-02-27 11:17:35 +00:00
Jeremy Ruston
2ae1e5aa09 Merge branch 'tiddlywiki-com' 2025-02-27 11:01:28 +00:00
Jeremy Ruston
e01c428a17 Add support for add-on language and theme plugins 2025-02-26 21:17:53 +00:00
Jeremy Ruston
752c5cfbda Cleaning up 2025-02-26 20:01:32 +00:00
Jeremy Ruston
094428b1ab Remove debug code 2025-02-26 18:07:39 +00:00
Jeremy Ruston
41cd335cf4 Add test for dynamically loading a language plugin 2025-02-26 17:20:03 +00:00
Jeremy Ruston
26b2768294 Fix testcase export to include plugins 2025-02-26 17:18:37 +00:00
Jeremy Ruston
4e3d07b16a Code typo 2025-02-22 10:19:57 +00:00
Jeremy Ruston
01beac1d7c Test for loading language plugins at startup 2025-02-21 16:47:00 +00:00
Jeremy Ruston
0c80e1b35c Move subplugin tests into their own folder 2025-02-21 10:59:38 +00:00
Jeremy Ruston
55c634692b Deal with dynamic loading and unloading of plugins
More enhancements needed for the test framework too in order to allow events to be processed manually, without relying on the nexttick handler which is awkward in Jasmine
2025-02-21 09:36:40 +00:00
Jeremy Ruston
7e2a8238b5 Clarify comment 2025-02-18 21:17:34 +00:00
Jeremy Ruston
ee90ad2fa6 Merge branch 'master' into intrinsic-sub-plugins 2025-02-18 21:15:39 +00:00
Jeremy Ruston
afabe5b714 More efficient checks if a tiddler is a plugin 2025-02-18 17:30:11 +00:00
Jeremy Ruston
3a60e0eb17 Merge branch 'master' into intrinsic-sub-plugins 2025-02-18 16:54:47 +00:00
Jeremy Ruston
6b0a13b8cc Basic loading of bundled subplugins
Very basic. Doesn't cope with any changes to the plugins after startup, and doesn't remove sub-plugins when the parent plugin is removed.
2025-02-18 09:14:54 +00:00
Jeremy Ruston
c142bfc50d Use "bundled" rather than "intrinsic" 2025-02-18 09:14:05 +00:00
Jeremy Ruston
e8de413fba More refactoring for clarity 2025-02-17 16:31:42 +00:00
Jeremy Ruston
4cbf1b4d91 Refactor some symbols for clarity
All these symbols are inaccessible outside the wiki class closure, and so no backwards compatibility issues
2025-02-16 19:32:56 +00:00
Jeremy Ruston
778e544f1c Initial Commit 2025-02-16 18:20:00 +00:00
2006 changed files with 16286 additions and 28477 deletions

317
.eslintrc.json Normal file
View File

@@ -0,0 +1,317 @@
{
"env": {
"browser": true,
"commonjs": true,
"node": true
},
"extends": [
"eslint:recommended"
],
"globals": {
"$tw": "writable"
},
"parserOptions": {
"ecmaVersion": 5
},
"plugins": [],
"rules": {
"array-bracket-newline": "off",
"array-bracket-spacing": "off",
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": [
"error",
"as-needed"
],
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-scoped-var": "off",
"block-spacing": "off",
"brace-style": "off",
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "error",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": "off",
"complexity": "off",
"computed-property-spacing": "off",
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "off",
"default-case-last": "error",
"default-param-last": "error",
"dot-location": "off",
"dot-notation": "off",
"eol-last": "off",
"eqeqeq": "off",
"func-call-spacing": "off",
"func-name-matching": "off",
"func-names": "off",
"func-style": "off",
"function-call-argument-newline": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"global-require": "off",
"grouped-accessor-pairs": "error",
"guard-for-in": "off",
"handle-callback-err": "off",
"id-blacklist": "error",
"id-denylist": "error",
"id-length": "off",
"id-match": "error",
"implicit-arrow-linebreak": "error",
"indent": "off",
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": [
"error",
{
"before": true,
"after": false,
"overrides": {
"case": {
"after": true
},
"do": {
"after": true
},
"else": {
"after": true
},
"return": {
"after": true
},
"throw": {
"after": true
},
"try": {
"after": true
},
"catch": {
"after": true
}
}
}
],
"line-comment-position": "off",
"linebreak-style": "off",
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": "error",
"max-classes-per-file": "error",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
"max-lines-per-function": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": "off",
"new-parens": "off",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "off",
"no-array-constructor": "off",
"no-await-in-loop": "error",
"no-bitwise": "off",
"no-buffer-constructor": "off",
"no-caller": "error",
"no-catch-shadow": "off",
"no-confusing-arrow": "error",
"no-console": "off",
"no-constant-condition": [
"error",
{
"checkLoops": false
}
],
"no-constructor-return": "error",
"no-continue": "off",
"no-div-regex": "off",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "off",
"no-eval": "off",
"no-extend-native": "off",
"no-extra-bind": "off",
"no-extra-label": "off",
"no-extra-parens": "off",
"no-floating-decimal": "off",
"no-implicit-coercion": [
"error",
{
"boolean": false,
"number": false,
"string": false
}
],
"no-implicit-globals": "off",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "off",
"no-labels": "off",
"no-lone-blocks": "off",
"no-lonely-if": "off",
"no-loop-func": "off",
"no-loss-of-precision": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "off",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": ["warn", { "max": 4, "maxEOF": 0 }],
"no-native-reassign": "off",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "off",
"no-new-func": "off",
"no-new-object": "off",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "off",
"no-promise-executor-return": "error",
"no-proto": "off",
"no-restricted-exports": "error",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "off",
"no-return-await": "error",
"no-script-url": "off",
"no-self-compare": "off",
"no-sequences": "off",
"no-shadow": "off",
"no-spaced-func": "off",
"no-sync": "off",
"no-tabs": "off",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "off",
"no-trailing-spaces": "error",
"no-undef-init": "off",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "off",
"no-unneeded-ternary": "off",
"no-unreachable-loop": "error",
"no-unused-expressions": "off",
"no-use-before-define": "off",
"no-useless-backreference": "error",
"no-useless-call": "off",
"no-useless-computed-key": "error",
"no-useless-concat": "off",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "off",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"nonblock-statement-body-position": [
"error",
"any"
],
"object-curly-newline": "off",
"object-curly-spacing": "off",
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
"prefer-exponentiation-operator": "off",
"prefer-named-capture-group": "off",
"prefer-numeric-literals": "error",
"prefer-object-spread": "off",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-regex-literals": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": "off",
"require-atomic-updates": "error",
"require-await": "error",
"require-jsdoc": "off",
"require-unicode-regexp": "off",
"rest-spread-spacing": "error",
"semi": "off",
"semi-spacing": "off",
"semi-style": "off",
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": "off",
"space-infix-ops": "off",
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"switch-colon-spacing": "off",
"symbol-description": "error",
"template-curly-spacing": "error",
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"valid-typeof": [
"error",
{
"requireStringLiterals": false
}
],
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": "off",
"no-useless-escape": "off",
"no-unused-vars": "off",
"no-empty": "off",
"no-extra-semi": "off",
"no-redeclare": "off",
"no-control-regex": "off",
"no-mixed-spaces-and-tabs": "off",
"no-extra-boolean-cast": "off",
"no-prototype-builtins": "off",
"no-undef": "off",
"no-unreachable": "off",
"no-self-assign": "off"
}
}

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
boot/** -linguist-generated
**/tiddlywiki.files linguist-language=JSON
**/tiddlywiki.info linguist-language=JSON
**/plugin.info linguist-language=JSON

View File

@@ -1,62 +0,0 @@
---
name: Bug report
about: Create a report to help us improve TiddlyWiki 5
title: "[Report] "
type: report
---
<!-- Remove elements, that you do not need -->
<!-- Add screenshots where needed -->
**Problem Description**
<!-- Describe your problem: A clear and concise description of what your problem is -->
**To Reproduce**
Steps to reproduce the behavior:
1. At https://tiddlywiki.com
2. Click on ...
3. Scroll down to ...
4. See ...
**Expected behavior**
As a user,
<!-- As a developer, -->
I would expect ...
**TiddlyWiki Configuration**
<!-- Please complete the following information -->
- Report created with: [Wiki Information](https://tiddlywiki.com/#%24%3A%2Fcore%2Fui%2FControlPanel%2FWikiInformation)
<!-- Your report comes here -->
<!-- or -->
<!-- Add it manually -->
- Version: <!-- e.g. v5.3.8 -->
- Saving mechanism: <!-- e.g. Node.js, TiddlyDesktop, TiddlyHost etc -->
- Plugins installed: <!-- e.g. Freelinks, TiddlyMap ... other 3rd party plugins -->
**Desktop**
<!-- Please complete the following information -->
- OS: <!-- e.g. iOS -->
- Browser: <!-- e.g. chrome, safari, FireFox -- Version: -->
**Smartphone**
<!-- Please complete the following information -->
- Device: <!-- e.g. iPhone6 -->
- OS: <!-- e.g. iOS8.1 -->
- Browser: <!-- e.g. stock browser, safari, FireFox -- Version: -->
**Additional context**
<!-- Add any other context about the problem here. -->

67
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: Bug report
description: Create a report to help us improve TiddlyWiki 5
title: "[BUG] "
body:
- type: textarea
id: Describe
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: Expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: false
- type: textarea
id: Reproduce
attributes:
label: To Reproduce
description: "Steps to reproduce the behavior:"
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: false
- type: textarea
id: Screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
placeholder: Drag image here to upload screenshot!
validations:
required: false
- type: textarea
id: Configuration
attributes:
label: TiddlyWiki Configuration
description: please complete the following information
placeholder: |
- Version [e.g. v5.1.24]
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
- Plugins installed [e.g. Freelinks, TiddlyMap]
### Desktop (please complete the following information):
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
### Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
validations:
required: true
- type: textarea
id: Context
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -4,23 +4,17 @@ about: Suggest an idea for TiddlyWiki 5
title: "[IDEA]"
labels: ''
assignees: ''
type: idea
---
**Is your idea related to a problem? Please describe.**
A clear and concise description of what the problem is. Eg:
As a user, I would like [...]
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -10,7 +10,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE_VERSION }}"
@@ -30,7 +30,7 @@ jobs:
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
TW5_BUILD_OUTPUT: "./output/prerelease"
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE_VERSION }}"
@@ -62,7 +62,7 @@ jobs:
TW5_BUILD_OUTPUT: "./output"
TW5_BUILD_ARCHIVE: "./output"
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE_VERSION }}"

View File

@@ -1,40 +0,0 @@
name: ESLint
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
concurrency:
group: lint-${{ github.event.pull_request.number || github.ref_name }}
cancel-in-progress: true
permissions:
contents: read
# Needed for GitHub Checks API
checks: write
jobs:
eslint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm install --include=dev
- name: Run ESLint with reviewdog (GitHub Checks)
uses: reviewdog/action-eslint@v1
with:
eslint_flags: '.'
reporter: github-pr-check
fail_level: error
level: error
tool_name: ESLint PR code

View File

@@ -1,55 +0,0 @@
name: Calculate PR build size
on:
pull_request_target:
types: [opened, reopened, synchronize]
paths:
- 'boot/**'
- 'core/**'
- 'themes/tiddlywiki/snowwhite/**'
- 'themes/tiddlywiki/vanilla/**'
jobs:
calculate-build-size:
runs-on: ubuntu-latest
permissions:
pull-requests: read
contents: read
outputs:
pr_size: ${{ steps.get_sizes.outputs.pr_size }}
base_size: ${{ steps.get_sizes.outputs.base_size }}
steps:
- name: build-size-check
id: get_sizes
uses: TiddlyWiki/cerebrus@v6
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.event.pull_request.base.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: size:calc
dispatch-followup:
needs: calculate-build-size
runs-on: ubuntu-latest
permissions:
actions: write # Required to dispatch another workflow
pull-requests: write
contents: read
steps:
- name: Trigger follow-up workflow
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'pr-comment-build-size.yml',
ref: 'master',
inputs: {
pr_number: '${{ github.event.pull_request.number }}',
base_ref: '${{ github.event.pull_request.base.ref }}',
pr_size: '${{ needs.calculate-build-size.outputs.pr_size }}',
base_size: '${{ needs.calculate-build-size.outputs.base_size }}'
}
});

View File

@@ -1,36 +0,0 @@
name: Comment on PR build size (Trusted workflow)
on:
workflow_dispatch:
inputs:
pr_number:
required: true
type: string
base_ref:
required: true
type: string
pr_size:
required: true
type: string
base_size:
required: true
type: string
jobs:
comment-on-pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Build and check size
uses: TiddlyWiki/cerebrus@v6
with:
pr_number: ${{ inputs.pr_number }}
repo: ${{ github.repository }}
base_ref: ${{ inputs.base_ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: size:comment
pr_size: ${{ inputs.pr_size }}
base_size: ${{ inputs.base_size }}

View File

@@ -1,37 +0,0 @@
name: PR Validation
on:
pull_request_target:
types: [opened, reopened, synchronize]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
validate-pr:
runs-on: ubuntu-latest
steps:
# Step 1: Validate PR paths
- name: Validate PR Paths
uses: TiddlyWiki/cerebrus@v6
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.event.pull_request.base.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: rules
continue-on-error: true
# Step 2: Validate change notes
- name: Validate Change Notes
uses: TiddlyWiki/cerebrus@v6
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.event.pull_request.base.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: changenotes
continue-on-error: false

View File

@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.4.0
TW5_BUILD_VERSION=v5.3.7
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -73,8 +73,10 @@ rm $TW5_BUILD_OUTPUT/dev/static/*
echo "<a href='./plugins/tiddlywiki/tw2parser/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tw2parser/index.html</a>" > $TW5_BUILD_OUTPUT/classicparserdemo.html
echo "<a href='./plugins/tiddlywiki/codemirror/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/codemirror/index.html</a>" > $TW5_BUILD_OUTPUT/codemirrordemo.html
echo "<a href='./plugins/tiddlywiki/d3/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/d3/index.html</a>" > $TW5_BUILD_OUTPUT/d3demo.html
echo "<a href='./plugins/tiddlywiki/highlight/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/highlight/index.html</a>" > $TW5_BUILD_OUTPUT/highlightdemo.html
echo "<a href='./plugins/tiddlywiki/markdown/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/markdown/index.html</a>" > $TW5_BUILD_OUTPUT/markdowndemo.html
echo "<a href='./plugins/tiddlywiki/tahoelafs/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tahoelafs/index.html</a>" > $TW5_BUILD_OUTPUT/tahoelafs.html
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
@@ -120,6 +122,7 @@ node $TW5_BUILD_TIDDLYWIKI \
|| exit 1
# /empty.html Empty
# /empty.hta For Internet Explorer
# /empty-external-core.html External core empty
# /tiddlywikicore-<version>.js Core plugin javascript
node $TW5_BUILD_TIDDLYWIKI \
@@ -153,14 +156,7 @@ node $TW5_BUILD_TIDDLYWIKI \
node $TW5_BUILD_TIDDLYWIKI \
./editions/tour \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js tour.html text/plain \
|| exit 1
# /surveys.html surveys edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/tiddlywiki-surveys \
--output $TW5_BUILD_OUTPUT \
--build index \
--rendertiddler $:/core/save/all tour.html text/plain \
|| exit 1
# /share.html Custom edition for sharing via the URL
@@ -199,7 +195,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/xlsx-utils \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/xlsx-utils/ \
--build external \
--build index \
|| exit 1
# /editions/resumebuilder/index.html Resume builder edition
@@ -215,7 +211,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/text-slicer \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/text-slicer/ \
--build external \
--build index \
|| exit 1
# /editions/translators/index.html Translators edition
@@ -247,7 +243,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/tw5.com-docs \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/tw5.com-docs/ \
--build external \
--build index \
|| exit 1
# /editions/twitter-archivist/index.html Twitter Archivist edition
@@ -270,7 +266,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/innerwikidemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/innerwiki/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/innerwiki/index.html text/plain \
|| exit 1
# /plugins/tiddlywiki/dynaview/index.html Demo wiki with DynaView plugin
@@ -280,7 +276,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/dynaviewdemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/dynaview/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/dynaview/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/dynaview/empty.html text/plain \
|| exit 1
@@ -294,17 +290,37 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/katexdemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/katex/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/katex/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
|| exit 1
# /plugins/tiddlywiki/tahoelafs/index.html Demo wiki with Tahoe-LAFS plugin
# /plugins/tiddlywiki/tahoelafs/empty.html Empty wiki with Tahoe-LAFS plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/tahoelafs \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/tahoelafs/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tahoelafs/empty.html text/plain \
|| exit 1
# /plugins/tiddlywiki/d3/index.html Demo wiki with D3 plugin
# /plugins/tiddlywiki/d3/empty.html Empty wiki with D3 plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/d3demo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/d3/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/d3/empty.html text/plain \
|| exit 1
# /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
# /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/codemirrordemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/codemirror/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/codemirror/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/codemirror/empty.html text/plain \
|| exit 1
@@ -314,7 +330,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/markdowndemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/markdown/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/markdown/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/markdown/empty.html text/plain \
|| exit 1
@@ -324,7 +340,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/classicparserdemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/tw2parser/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/tw2parser/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tw2parser/empty.html text/plain \
|| exit 1
@@ -334,7 +350,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/highlightdemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/highlight/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/highlight/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/highlight/empty.html text/plain \
|| exit 1
@@ -344,7 +360,7 @@ node $TW5_BUILD_TIDDLYWIKI \
./editions/geospatialdemo \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all-external-js plugins/tiddlywiki/geospatial/index.html text/plain \
--rendertiddler $:/core/save/all plugins/tiddlywiki/geospatial/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/geospatial/empty.html text/plain \
|| exit 1

View File

@@ -8,8 +8,6 @@ On the server this file is executed directly to boot TiddlyWiki. In the browser,
\*/
/* eslint-disable @stylistic/indent */
var _boot = (function($tw) {
/*jslint node: true, browser: true */
@@ -46,8 +44,12 @@ $tw.utils.hop = function(object,property) {
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
};
/** @deprecated Use Array.isArray instead */
$tw.utils.isArray = value => Array.isArray(value);
/*
Determine if a value is an array
*/
$tw.utils.isArray = function(value) {
return Object.prototype.toString.call(value) == "[object Array]";
};
/*
Check if an array is equal by value and by reference.
@@ -126,22 +128,35 @@ $tw.utils.pushTop = function(array,value) {
return array;
};
/** @deprecated Use instanceof Date instead */
$tw.utils.isDate = value => value instanceof Date;
/*
Determine if a value is a date
*/
$tw.utils.isDate = function(value) {
return Object.prototype.toString.call(value) === "[object Date]";
};
/** @deprecated Use array iterative methods instead */
/*
Iterate through all the own properties of an object or array. Callback is invoked with (element,title,object)
*/
$tw.utils.each = function(object,callback) {
var next,f,length;
if(object) {
if(Array.isArray(object)) {
object.every((element,index,array) => {
const next = callback(element,index,array);
return next !== false;
});
if(Object.prototype.toString.call(object) == "[object Array]") {
for(f=0, length=object.length; f<length; f++) {
next = callback(object[f],f,object);
if(next === false) {
break;
}
}
} else {
Object.entries(object).every(entry => {
const next = callback(entry[1], entry[0], object);
return next !== false;
});
var keys = Object.keys(object);
for(f=0, length=keys.length; f<length; f++) {
var key = keys[f];
next = callback(object[key],key,object);
if(next === false) {
break;
}
}
}
}
};
@@ -320,26 +335,28 @@ $tw.utils.htmlDecode = function(s) {
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)
*/
$tw.utils.getLocationHash = function() {
const href = window.location.href,
idx = href.indexOf("#");
var href = window.location.href;
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
}
const afterHash = href.substring(idx + 1);
if(afterHash.startsWith("#") || afterHash.startsWith("%23")) {
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
return href.substring(idx);
}
return href.substring(idx);
};
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
$tw.utils.pad = function(value,length = 2) {
const s = value.toString();
return s.padStart(length, "0");
/*
Pad a string to a given length with "0"s. Length defaults to 2
*/
$tw.utils.pad = function(value,length) {
length = length || 2;
var s = value.toString();
if(s.length < length) {
s = "000000000000000000000000000".substr(0,length - s.length) + s;
}
return s;
};
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
@@ -613,7 +630,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
// Compile the code into a function
var fn;
if($tw.browser) {
fn = Function("return " + code + "\n\n//# sourceURL=" + filename)(); // See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
if(sandbox){
fn = vm.runInContext(code,sandbox,filename)
@@ -624,7 +641,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
// Call the function and return the exports
return fn.apply(null,contextValues);
};
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
/*
Run code in a sandbox with only the specified context variables in scope
*/
@@ -782,13 +799,12 @@ the password, and to encrypt/decrypt a block of text
$tw.utils.Crypto = function() {
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
currentPassword = null,
callSjcl = function(method,inputText,password,options) {
options = options || {};
callSjcl = function(method,inputText,password) {
password = password || currentPassword;
var outputText;
try {
if(password) {
outputText = sjcl[method](password,inputText,options);
outputText = sjcl[method](password,inputText);
}
} catch(ex) {
console.log("Crypto error:" + ex);
@@ -814,8 +830,7 @@ $tw.utils.Crypto = function() {
return !!currentPassword;
}
this.encrypt = function(text,password) {
// set default ks:256 -- see: http://bitwiseshiftleft.github.io/sjcl/doc/convenience.js.html
return callSjcl("encrypt",text,password,{v:1,iter:10000,ks:256,ts:64,mode:"ccm",adata:"",cipher:"aes"});
return callSjcl("encrypt",text,password);
};
this.decrypt = function(text,password) {
return callSjcl("decrypt",text,password);
@@ -1053,6 +1068,10 @@ $tw.Tiddler.prototype.hasField = function(field) {
return $tw.utils.hop(this.fields,field);
};
$tw.Tiddler.prototype.isPlugin = function() {
return this.fields.type === "application/json" && this.hasField("plugin-type") && !this.hasField("draft.of");
};
/*
Compare two tiddlers for equality
tiddler: the tiddler to compare
@@ -1147,21 +1166,21 @@ enableIndexers - Array of indexer names to enable, or null to use all available
$tw.Wiki = function(options) {
options = options || {};
var self = this,
tiddlers = Object.create(null), // Hashmap of tiddlers
tiddlerTitles = null, // Array of tiddler titles
tiddlerStore = Object.create(null), // Hashmap of tiddlers
tiddlerTitles = null, // Array of tiddler titles, calculated and cached when needed
getTiddlerTitles = function() {
if(!tiddlerTitles) {
tiddlerTitles = Object.keys(tiddlers).sort(function(a,b) {return a.localeCompare(b);});
tiddlerTitles = Object.keys(tiddlerStore).sort(function(a,b) {return a.localeCompare(b);});
}
return tiddlerTitles;
},
pluginTiddlers = [], // Array of tiddlers containing registered plugins, ordered by priority
pluginInfo = Object.create(null), // Hashmap of parsed plugin content
shadowTiddlers = Object.create(null), // Hashmap by title of {source:, tiddler:}
shadowTiddlerTitles = null,
pluginTiddlersInfo = [], // Array of tiddler fields for all plugins and sub-plugins, ordered by priority
pluginContents = Object.create(null), // Hashmap by title of {contents:<parsed plugin contents>,fields:<fields>,subPluginTitles:<list>}
shadowTiddlerInfo = Object.create(null), // Hashmap by title of {source:, tiddler:}
shadowTiddlerTitles = null, // Array of tiddler titles, calculated and cached when needed
getShadowTiddlerTitles = function() {
if(!shadowTiddlerTitles) {
shadowTiddlerTitles = Object.keys(shadowTiddlers).sort(function(a,b) {return a.localeCompare(b);});
shadowTiddlerTitles = Object.keys(shadowTiddlerInfo).sort(function(a,b) {return a.localeCompare(b);});
}
return shadowTiddlerTitles;
},
@@ -1203,7 +1222,7 @@ $tw.Wiki = function(options) {
}
}
// Save the new tiddler
tiddlers[title] = tiddler;
tiddlerStore[title] = tiddler;
// Check we've got the title
tiddlerTitles = $tw.utils.insertSortedArray(tiddlerTitles || [],title);
// Record the new tiddler state
@@ -1228,7 +1247,7 @@ $tw.Wiki = function(options) {
this.deleteTiddler = function(title) {
// Uncomment the following line for detailed logs of all tiddler deletions
// console.log("Deleting",title)
if($tw.utils.hop(tiddlers,title)) {
if($tw.utils.hop(tiddlerStore,title)) {
// Record the old tiddler state
var updateDescriptor = {
old: {
@@ -1238,7 +1257,7 @@ $tw.Wiki = function(options) {
}
}
// Delete the tiddler
delete tiddlers[title];
delete tiddlerStore[title];
// Delete it from the list of titles
if(tiddlerTitles) {
var index = tiddlerTitles.indexOf(title);
@@ -1266,11 +1285,11 @@ $tw.Wiki = function(options) {
// Get a tiddler from the store
this.getTiddler = function(title) {
if(title) {
var t = tiddlers[title];
var t = tiddlerStore[title];
if(t !== undefined) {
return t;
} else {
var s = shadowTiddlers[title];
var s = shadowTiddlerInfo[title];
if(s !== undefined) {
return s.tiddler;
}
@@ -1290,7 +1309,7 @@ $tw.Wiki = function(options) {
index,titlesLength,title;
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
callback(tiddlers[title],title);
callback(tiddlerStore[title],title);
}
};
@@ -1305,10 +1324,10 @@ $tw.Wiki = function(options) {
index,titlesLength,title;
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(tiddlers[title]) {
callback(tiddlers[title],title);
if(tiddlerStore[title]) {
callback(tiddlerStore[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
var shadowInfo = shadowTiddlerInfo[title];
callback(shadowInfo.tiddler,title);
}
}
@@ -1320,13 +1339,13 @@ $tw.Wiki = function(options) {
titles = getTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
callback(tiddlers[title],title);
callback(tiddlerStore[title],title);
}
titles = getShadowTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(!tiddlers[title]) {
var shadowInfo = shadowTiddlers[title];
if(!tiddlerStore[title]) {
var shadowInfo = shadowTiddlerInfo[title];
callback(shadowInfo.tiddler,title);
}
}
@@ -1338,35 +1357,35 @@ $tw.Wiki = function(options) {
titles = getShadowTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(tiddlers[title]) {
callback(tiddlers[title],title);
if(tiddlerStore[title]) {
callback(tiddlerStore[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
var shadowInfo = shadowTiddlerInfo[title];
callback(shadowInfo.tiddler,title);
}
}
titles = getTiddlerTitles();
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(!shadowTiddlers[title]) {
callback(tiddlers[title],title);
if(!shadowTiddlerInfo[title]) {
callback(tiddlerStore[title],title);
}
}
};
// Test for the existence of a tiddler (excludes shadow tiddlers)
this.tiddlerExists = function(title) {
return !!$tw.utils.hop(tiddlers,title);
return !!$tw.utils.hop(tiddlerStore,title);
};
// Determines if a tiddler is a shadow tiddler, regardless of whether it has been overridden by a real tiddler
this.isShadowTiddler = function(title) {
return $tw.utils.hop(shadowTiddlers,title);
return $tw.utils.hop(shadowTiddlerInfo,title);
};
this.getShadowSource = function(title) {
if($tw.utils.hop(shadowTiddlers,title)) {
return shadowTiddlers[title].source;
if($tw.utils.hop(shadowTiddlerInfo,title)) {
return shadowTiddlerInfo[title].source;
}
return null;
};
@@ -1374,8 +1393,8 @@ $tw.Wiki = function(options) {
// Get an array of all the currently recognised plugin types
this.getPluginTypes = function() {
var types = [];
$tw.utils.each(pluginTiddlers,function(pluginTiddler) {
var pluginType = pluginTiddler.fields["plugin-type"];
$tw.utils.each(pluginTiddlersInfo,function(pluginTiddlerFields) {
var pluginType = pluginTiddlerFields["plugin-type"];
if(pluginType && types.indexOf(pluginType) === -1) {
types.push(pluginType);
}
@@ -1383,22 +1402,45 @@ $tw.Wiki = function(options) {
return types;
};
// Read plugin info for all plugins, or just an array of titles. Returns the number of plugins updated or deleted
// Read plugin contents for all plugins, or just an array of titles. Returns the list of updated plugin titles, the list of deleted plugin titles and
// a hashmap of the deleted plugin contents. Clears the pluginContents cache for any plugins that have been deleted
this.readPluginInfo = function(titles) {
var results = {
var self = this,
results = {
modifiedPlugins: [],
deletedPlugins: []
deletedPlugins: [],
deletedPluginContents: {}
};
$tw.utils.each(titles || getTiddlerTitles(),function(title) {
var tiddler = tiddlers[title];
var tiddler = self.getTiddler(title);
if(!tiddler) {
for(var t=0; t<pluginContents.length; t++) {
if(pluginContents[t].subPluginTitles.indexOf(title) !== -1) {
tiddler = new $tw.Tiddler(pluginContents[t].fields);
break;
}
}
}
if(tiddler) {
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type") && tiddler.fields.text) {
pluginInfo[tiddler.fields.title] = $tw.utils.parseJSONSafe(tiddler.fields.text);
results.modifiedPlugins.push(tiddler.fields.title);
if(tiddler.isPlugin() && tiddler.fields.text) {
var contents = $tw.utils.parseJSONSafe(tiddler.fields.text).tiddlers;
var subPluginTitles = [];
// Read any sub-plugins
$tw.utils.each(contents,function(subPluginFields,subPluginTitle) {
if(subPluginFields["plugin-type"] && subPluginFields["type"] === "application/json") {
var contents = $tw.utils.parseJSONSafe(subPluginFields.text).tiddlers
pluginContents[subPluginTitle] = {contents: contents,fields: subPluginFields};
results.modifiedPlugins.push(subPluginTitle);
subPluginTitles.push(subPluginTitle)
}
});
pluginContents[title] = {contents: contents,fields: tiddler.fields,subPluginTitles: subPluginTitles};
results.modifiedPlugins.push(title);
}
} else {
if(pluginInfo[title]) {
delete pluginInfo[title];
if(pluginContents[title]) {
results.deletedPluginContents[title] = {tiddlers: pluginContents[title].contents};
delete pluginContents[title];
results.deletedPlugins.push(title);
}
}
@@ -1406,34 +1448,42 @@ $tw.Wiki = function(options) {
return results;
};
this.isSubPlugin = function(title) {
for(var t=0; t<pluginContents.length; t++) {
if(pluginContents[t].subPluginTitles.indexOf(title) !== -1) {
return true;
}
}
return false;
};
// Get plugin info for a plugin
this.getPluginInfo = function(title) {
return pluginInfo[title];
var pluginContent = pluginContents[title];
if(pluginContent) {
return {tiddlers: pluginContent.contents, subPluginTitles: pluginContent.subPluginTitles, fields: pluginContent.fields};
} else {
return null;
}
};
// Register the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting registration to an array of tiddler titles. Return the array of titles affected
this.registerPluginTiddlers = function(pluginType,titles) {
var self = this,
registeredTitles = [],
checkTiddler = function(tiddler,title) {
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
if(title === "$:/core" || title === "$:/core-server" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
pluginTiddlers.push(tiddler);
registeredTitles.push(tiddler.fields.title);
registeredTitles = [];
$tw.utils.each(pluginContents,function(pluginContent,pluginTitle) {
var pluginFields = pluginContent.fields;
if(!titles || titles.indexOf(pluginTitle) !== -1) {
if(!pluginType || pluginFields["plugin-type"] === pluginType) {
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + pluginTitle);
if(pluginTitle === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
self.unregisterPluginTiddlers(null,[pluginTitle]); // Unregister the plugin if it's already registered
pluginTiddlersInfo.push(pluginFields);
registeredTitles.push(pluginTitle);
}
}
};
if(titles) {
$tw.utils.each(titles,function(title) {
checkTiddler(self.getTiddler(title),title);
});
} else {
this.each(function(tiddler,title) {
checkTiddler(tiddler,title);
});
}
}
});
return registeredTitles;
};
@@ -1442,11 +1492,11 @@ $tw.Wiki = function(options) {
var self = this,
unregisteredTitles = [];
// Remove any previous registered plugins of this type
for(var t=pluginTiddlers.length-1; t>=0; t--) {
var tiddler = pluginTiddlers[t];
if(tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType) && (!titles || titles.indexOf(tiddler.fields.title) !== -1)) {
unregisteredTitles.push(tiddler.fields.title);
pluginTiddlers.splice(t,1);
for(var t=pluginTiddlersInfo.length-1; t>=0; t--) {
var pluginFields = pluginTiddlersInfo[t];
if(pluginFields["plugin-type"] && (!pluginType || pluginFields["plugin-type"] === pluginType) && (!titles || titles.indexOf(pluginFields.title) !== -1)) {
unregisteredTitles.push(pluginFields.title);
pluginTiddlersInfo.splice(t,1);
}
}
return unregisteredTitles;
@@ -1456,36 +1506,33 @@ $tw.Wiki = function(options) {
this.unpackPluginTiddlers = function() {
var self = this;
// Sort the plugin titles by the `plugin-priority` field, if this field is missing, default to 1
pluginTiddlers.sort(function(a, b) {
var priorityA = "plugin-priority" in a.fields ? a.fields["plugin-priority"] : 1;
var priorityB = "plugin-priority" in b.fields ? b.fields["plugin-priority"] : 1;
pluginTiddlersInfo.sort(function(a, b) {
var priorityA = "plugin-priority" in a ? a["plugin-priority"] : 1,
priorityB = "plugin-priority" in b ? b["plugin-priority"] : 1;
if (priorityA !== priorityB) {
return priorityA - priorityB;
} else if (a.fields.title < b.fields.title) {
} else if (a.title < b.title) {
return -1;
} else if (a.fields.title === b.fields.title) {
} else if (a.title === b.title) {
return 0;
} else {
return +1;
}
});
// Now go through the plugins in ascending order and assign the shadows
shadowTiddlers = Object.create(null);
$tw.utils.each(pluginTiddlers,function(tiddler) {
shadowTiddlerInfo = Object.create(null);
$tw.utils.each(pluginTiddlersInfo,function(tiddlerFields) {
var contents = pluginContents[tiddlerFields.title].contents;
// Extract the constituent tiddlers
if($tw.utils.hop(pluginInfo,tiddler.fields.title)) {
$tw.utils.each(pluginInfo[tiddler.fields.title].tiddlers,function(constituentTiddler,constituentTitle) {
// Save the tiddler object
if(constituentTitle) {
shadowTiddlers[constituentTitle] = {
source: tiddler.fields.title,
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
};
}
});
}
$tw.utils.each(contents,function(constituentTiddler,constituentTitle) {
// Save the tiddler object
shadowTiddlerInfo[constituentTitle] = {
source: tiddlerFields.title,
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
};
});
});
shadowTiddlerTitles = null;
shadowTiddlerTitles = null; // Force regeneration of the shadow tiddler titles list
this.clearCache(null);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
@@ -1515,8 +1562,7 @@ Define all modules stored in ordinary tiddlers
*/
$tw.Wiki.prototype.defineTiddlerModules = function() {
this.each(function(tiddler,title) {
// Modules in draft tiddlers are disabled
if(tiddler.hasField("module-type") && (!tiddler.hasField("draft.of"))) {
if(tiddler.hasField("module-type")) {
switch(tiddler.fields.type) {
case "application/javascript":
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
@@ -1543,11 +1589,6 @@ $tw.Wiki.prototype.defineShadowModules = function() {
this.eachShadow(function(tiddler,title) {
// Don't define the module if it is overidden by an ordinary tiddler
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
if(tiddler.hasField("draft.of")) {
// Report a fundamental problem
console.warn(`TiddlyWiki: Plugins should not contain tiddlers with a 'draft.of' field: ${tiddler.fields.title}`);
return;
}
// Define the module
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
}
@@ -1896,7 +1937,7 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
fileSize = fs.statSync(filepath).size,
data;
if(fileSize > $tw.config.maxEditFileSize) {
data = "File " + filepath + " not loaded because it is too large";
data = "File " + filepath + "not loaded because it is too large";
console.log("Warning: " + data);
ext = ".txt";
} else {
@@ -1935,7 +1976,7 @@ $tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\
/*
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
*/
$tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
$tw.loadTiddlersFromPath = function(filepath,excludeRegExp,excludePluginInfo) {
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
var tiddlers = [];
if(fs.existsSync(filepath)) {
@@ -1945,11 +1986,17 @@ $tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
// Look for a tiddlywiki.files file
if(files.indexOf("tiddlywiki.files") !== -1) {
Array.prototype.push.apply(tiddlers,$tw.loadTiddlersFromSpecification(filepath,excludeRegExp));
} else if(files.indexOf("plugin.info") !== -1 && !excludePluginInfo) {
// Load sub-plugin
var tiddler = $tw.loadPluginFolder(filepath);
if(tiddler) {
tiddlers.push({tiddlers: [tiddler]});
}
} else {
// If not, read all the files in the directory
$tw.utils.each(files,function(file) {
if(!excludeRegExp.test(file) && file !== "plugin.info") {
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(filepath + path.sep + file,excludeRegExp));
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(path.join(filepath,file),excludeRegExp));
}
});
}
@@ -1967,41 +2014,22 @@ filepath: pathname of the directory containing the specification file
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var tiddlers = [];
// Read the specification
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"), function(e) {
console.log("Warning: tiddlywiki.files in " + filepath + " invalid: " + e.message);
return {};
});
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
type = (extInfo || {}).type || fields.type || "text/plain",
typeInfo = $tw.config.contentTypeInfo[type] || {},
pathname = path.resolve(filepath,filename),
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8"),
metadata = $tw.loadMetadataForFile(pathname) || {},
fileTooLarge = false,
text, fileTiddlers;
if("_canonical_uri" in fields) {
text = "";
} else if(fs.statSync(pathname).size > $tw.config.maxEditFileSize) {
var msg = "File " + pathname + " not loaded because it is too large";
console.log("Warning: " + msg);
fileTooLarge = true;
text = isTiddlerFile ? msg : "";
} else {
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8");
}
fileTiddlers;
if(isTiddlerFile) {
fileTiddlers = $tw.wiki.deserializeTiddlers(fileTooLarge ? ".txt" : path.extname(pathname),text,metadata) || [];
fileTiddlers = $tw.wiki.deserializeTiddlers(path.extname(pathname),text,metadata) || [];
} else {
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
}
var combinedFields = $tw.utils.extend({},fields,metadata);
if(fileTooLarge && isTiddlerFile) {
delete combinedFields.type; // type altered
}
$tw.utils.each(fileTiddlers,function(tiddler) {
$tw.utils.each(combinedFields,function(fieldInfo,name) {
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
@@ -2010,7 +2038,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var value = tiddler[name];
switch(fieldInfo.source) {
case "subdirectories":
value = $tw.utils.stringifyList(path.relative(rootPath, filename).split(path.sep).slice(0, -1));
value = path.relative(rootPath, filename).split(path.sep).slice(0, -1);
break;
case "filepath":
value = path.relative(rootPath, filename).split(path.sep).join('/');
@@ -2031,10 +2059,10 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
value = path.extname(filename);
break;
case "created":
value = $tw.utils.stringifyDate(new Date(fs.statSync(pathname).birthtime));
value = new Date(fs.statSync(pathname).birthtime);
break;
case "modified":
value = $tw.utils.stringifyDate(new Date(fs.statSync(pathname).mtime));
value = new Date(fs.statSync(pathname).mtime);
break;
}
if(fieldInfo.prefix) {
@@ -2076,7 +2104,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
} else if(tidInfo.suffix) {
tidInfo.fields.text = {suffix: tidInfo.suffix};
}
tidInfo.fields = tidInfo.fields || {};
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
});
// Process any listed directories
@@ -2098,7 +2125,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var thisPath = path.relative(filepath, files[t]),
filename = path.basename(thisPath);
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
dirSpec.fields = dirSpec.fields || {};
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
}
}
@@ -2117,54 +2143,69 @@ Load the tiddlers from a plugin folder, and package them up into a proper JSON p
*/
$tw.loadPluginFolder = function(filepath,excludeRegExp) {
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
var infoPath = filepath + path.sep + "plugin.info";
if(fs.existsSync(filepath) && fs.statSync(filepath).isDirectory()) {
// Read the plugin information
if(!fs.existsSync(infoPath) || !fs.statSync(infoPath).isFile()) {
console.log("Warning: missing plugin.info file in " + filepath);
function readPluginFields(filepath) {
if(!(fs.existsSync(filepath) && fs.statSync(filepath).isDirectory())) {
return null;
}
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"),function() {return null;});
if(!pluginInfo) {
console.log("warning: invalid JSON in plugin.info file at " + infoPath);
pluginInfo = {};
var infoPath = path.join(filepath,"plugin.info");
// Read the plugin information file
if(!fs.existsSync(infoPath) || !fs.statSync(infoPath).isFile()) {
return null;
}
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
pluginInfo.tiddlers = pluginInfo.tiddlers || Object.create(null);
var pluginFields = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"),{});
if(!(pluginFields.title && pluginFields.name)) {
return null;
}
// Give the plugin the same version number as the core if it doesn't have one
if(!("version" in pluginFields)) {
pluginFields.version = $tw.packageInfo.version;
}
// Use "plugin" as the plugin-type if we don't have one
if(!("plugin-type" in pluginFields)) {
pluginFields["plugin-type"] = "plugin";
}
// Set the dependents and type
pluginFields.dependents = pluginFields.dependents || [];
pluginFields.type = "application/json";
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginFields) {
if($tw.utils.isArray(pluginFields[field])) {
pluginFields[field] = $tw.utils.stringifyList(pluginFields[field]);
}
}
return pluginFields;
}
function readPluginTiddlers(tiddlersPath) {
var pluginFiles = $tw.loadTiddlersFromPath(tiddlersPath,excludeRegExp,true),
pluginTiddlers = {};
// Save the plugin tiddlers into the plugin payload
for(var f=0; f<pluginFiles.length; f++) {
var tiddlers = pluginFiles[f].tiddlers;
if(!tiddlers) {
console.log(`Gosh ${JSON.stringify(pluginFiles[f])}`)
}
for(var t=0; t<tiddlers.length; t++) {
var tiddler= tiddlers[t];
if(tiddler.title) {
pluginInfo.tiddlers[tiddler.title] = tiddler;
pluginTiddlers[tiddler.title] = tiddler;
}
}
}
// Give the plugin the same version number as the core if it doesn't have one
if(!("version" in pluginInfo)) {
pluginInfo.version = $tw.packageInfo.version;
}
// Use "plugin" as the plugin-type if we don't have one
if(!("plugin-type" in pluginInfo)) {
pluginInfo["plugin-type"] = "plugin";
}
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {
if($tw.utils.isArray(pluginInfo[field])) {
pluginInfo[field] = $tw.utils.stringifyList(pluginInfo[field]);
}
}
return pluginInfo;
} else {
return null;
return pluginTiddlers;
}
// Get the primary plugin fields
var pluginFields = readPluginFields(filepath);
if(!pluginFields) {
console.log("Warning: missing or invalid plugin.info file in " + filepath);
return null;
}
// The payload to be stored in the plugin text field in JSON
var pluginPayload = {tiddlers: {}};
// Get the constituent tiddlers of the plugin
pluginPayload.tiddlers = readPluginTiddlers(filepath);
// Set plugin text
pluginFields.text = JSON.stringify(pluginPayload);
return pluginFields;
};
/*
@@ -2362,7 +2403,6 @@ $tw.loadTiddlersNode = function() {
});
// Load the core tiddlers
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.coreServerPath));
// Load any extra plugins
$tw.utils.each($tw.boot.extraPlugins,function(name) {
if(name.charAt(0) === "+") { // Relative path to plugin
@@ -2436,7 +2476,6 @@ $tw.boot.initStartup = function(options) {
// System paths and filenames
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
$tw.boot.coreServerPath = path.resolve($tw.boot.bootPath,"../core-server");
// If there's no arguments then default to `--help`
if($tw.boot.argv.length === 0) {
$tw.boot.argv = ["--help"];
@@ -2561,10 +2600,10 @@ $tw.boot.execStartup = function(options){
if($tw.safeMode) {
$tw.wiki.processSafeMode();
}
// Register typed modules from the tiddlers we've just loaded and any modules within plugins
// Tiddlers should appear last so that they may overwrite shadows during module registration
$tw.wiki.defineShadowModules();
// Register typed modules from the tiddlers we've just loaded
$tw.wiki.defineTiddlerModules();
// And any modules within plugins
$tw.wiki.defineShadowModules();
// Make sure the crypto state tiddler is up to date
if($tw.crypto) {
$tw.crypto.updateCryptoStateTiddler();
@@ -2633,13 +2672,11 @@ $tw.boot.executeNextStartupTask = function(callback) {
$tw.boot.log(s.join(" "));
// Execute task
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
const thenable = task.startup();
if(thenable && typeof thenable.then === "function"){
thenable.then(asyncTaskCallback);
return true;
} else {
return asyncTaskCallback();
task.startup();
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask(callback);
} else {
task.startup(asyncTaskCallback);
return true;
@@ -2784,8 +2821,6 @@ return $tw;
});
/* eslint-enable @stylistic/indent */
if(typeof(exports) !== "undefined") {
exports.TiddlyWiki = _boot;
} else {

View File

@@ -12,8 +12,6 @@ See Boot.js for further details of the boot process.
\*/
/* eslint-disable @stylistic/indent */
var _bootprefix = (function($tw) {
"use strict";
@@ -116,8 +114,6 @@ return $tw;
});
/* eslint-enable @stylistic/indent */
if(typeof(exports) === "undefined") {
// Set up $tw global for the browser
window.$tw = _bootprefix(window.$tw);

View File

@@ -1,5 +0,0 @@
title: Community Cards Caveats
created: 20250909171928024
modified: 20250909171928024
''Please note that [[Community Cards]] are a new initiative started in September 2025. There is further work required to complete the team and people information.''

View File

@@ -1,11 +0,0 @@
title: Community Cards
tags: Community
modified: 20250909171928024
created: 20250909171928024
The purpose of Community Cards is to allow project plans and other community activities to be linked to the people who are involved in them. They also allow people to share their interests and activities in the TiddlyWiki community, and to help people in the TiddlyWiki community get to know each other better.
{{Community Cards Caveats}}
* [[Submitting a Community Card]]
* [[Displaying Community Cards]]

View File

@@ -1,26 +0,0 @@
title: Displaying Community Cards
tags: [[Community Cards]]
modified: 20250909171928024
created: 20250909171928024
!! Cards for people
This is an inline card for <<community-card-pill-person title:"@Jermolene">> and <<community-card-pill-person title:"@ericshulman">> which can be used in the middle of a sentence.
This is a stack of inline cards:
<<community-card-pill-stack-person>>
Here is a full format card:
<<community-card-person title:"@Jermolene">>
This is how the card looks when there is no such person:
<<community-card-person title:"@MissingPerson">>
!! Cards for teams
This is a card for a project team:
<<community-card-team title:"Project Team">>

View File

@@ -1,36 +0,0 @@
title: Submitting a Community Card
tags: [[Community Cards]]
modified: 20250909171928024
created: 20250909171928024
Anyone associated with the TiddlyWiki community can submit a Community Card. The submission process currently involves making a GitHub pull request but we intend to provide a more user-friendly submission process in the future.
Pull requests to add or update a community card should be made against the `tiddlywiki-com` branch of the [[TiddlyWiki repository|https://github.com/TiddlyWiki/TiddlyWiki5]] in the directory `community/people`.
The card should be a TiddlyWiki tiddler with the following fields:
|!Field |!Required|!Description |
|`title`|Yes |The username of the person represented by the card, starting with `@` (e.g. `@Jermolene`). This is the title of the card and should be unique |
|`tags`|Yes |The tags for the card, including `Community/Person` |
|`fullname`|Yes |The full name of the person or group represented by the card |
|`avatar`|Yes |The base64 representation of the 32x32 avatar image for the person represented by the card |
|`first-sighting`|No |The date of the first sighting in the community of the person represented by the card. This should be in ISO 8601 format (YYYY-MM-DD) |
|`talk.tiddlywiki.org`|Yes |The username of the person or group on the TiddlyWiki Talk forum |
|`github`|No |The username of the person or group on GitHub |
|`linkedin`|No |The URL of the LinkedIn profile for the person or group represented by the card |
|`flickr`|No |The URL of the Flickr profile for the person or group represented by the card |
|`homepage`|No |The URL of the homepage for the person or group represented by the card |
|`email`|No |The email address of the person or group represented by the card |
|`text`|Yes |The text of the card. This should include a brief description of the person or group represented by the card, and any other relevant information |
! Rules for Community Cards
Community cards must observe the following rules. It is intended to enforce them with an automated script, but for the moment they will be manually checked.
* `title` must be unique and start with `@`
* `tags` must include `Community/Person`
* `fullname` must be provided
* `avatar` must be a base64 representation of a 32x32 image, with a limit of 1KB. [[Squoosh|https://squoosh.app/]] is recommended for resizing and compressing images
* `first-sighting` should be in ISO 8601 format (YYYY-MM-DD)
* `talk.tiddlywiki.org` must be provided
* `text` total size must not exceed 2KB

View File

@@ -1,10 +0,0 @@
title: @Arlen22
tags: Community/Person
fullname: Arlen Beiler
first-sighting: 2011-06-20
talk.tiddlywiki.org: arlen22
github: Arlen22
homepage: arlen22.github.io
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wEEEAAVABUAFQAVABYAFQAYABoAGgAYACEAIwAfACMAIQAwAC0AKQApAC0AMABJADQAOAA0ADgANABJAG8ARQBRAEUARQBRAEUAbwBiAHcAYQBaAGEAdwBiALEAiwB7AHsAiwCxAMwArACiAKwAzAD4AN0A3QD4ATgBKAE4AZcBlwIkEQAVABUAFQAVABYAFQAYABoAGgAYACEAIwAfACMAIQAwAC0AKQApAC0AMABJADQAOAA0ADgANABJAG8ARQBRAEUARQBRAEUAbwBiAHcAYQBaAGEAdwBiALEAiwB7AHsAiwCxAMwArACiAKwAzAD4AN0A3QD4ATgBKAE4AZcBlwIk/8IAEQgAQABAAwEiAAIRAQMRAf/EADAAAAIDAQEAAAAAAAAAAAAAAAMFAQQGAgABAQEBAQEAAAAAAAAAAAAAAAIDAQAE/9oADAMBAAIQAxAAAADIRMd3XctQlXtCTTmB6RFvANDouy4DYwEEar6YVM7ocz57mcqnZys+V2azZU4XZSoiZqhQt9TKOlnO+GOl1HyoUPXLn//EACYQAAICAQQCAgEFAAAAAAAAAAECABEDBBIhMUFRECITFCMycZH/2gAIAQEAAT8AI4Bv4ryAeBAnANHuNidWogEwYHNRsdfA8iruVMOIu6iYtK4c714vgTDpXyOfrQHdifoArEXxM2mR0NeOhUzI+LJzYbuHszCm5hYseZh0gXYWFIai4cWJgFJuFKYvtr2sJRuB9fUzgDHlGMHia2757uYsYc0TNHpsSmzzMONjl9iu74iK6PbWT7gv/RMiZDk+qcA3NXkAVl3gE+ADU1PDVdiaDCGJZjQEyowKANS1ZMwK+HJ+3a0KUDqYnYINxJ3eItDk81M2cZD+NVIrmanU/wAl2gCZiGNiaFziJ3LYIHcXMrLvDABe17EN1vCgqR2TNPnGTBSBbDTeV3c2amdlxPuD2C3H9epqmV628xqsUYmdiuwkVVTSZ0Q/dxwYdScrgBRsqONi2KQX7mo1G4WCK20B6j6p/VpcfMXPVQ9mbhx9eLgZrFGDUZB1DqMrCma4xN8mDcR5qK5Rgw7Hx//EABwRAQEBAQACAwAAAAAAAAAAAAECABEDIhIxQf/aAAgBAgEBPwDVQYpfzd66qDeOSn7yEmH23ffDAi66mug6DM9N8HTAY3//xAAcEQEBAQEAAgMAAAAAAAAAAAABAAIREBIiQVH/2gAIAQMBAT8AglC+rJbdCT1vVC33l83tj2OPLS+AJ3+Tf//Z
I make random software.

View File

@@ -1,14 +0,0 @@
title: @Christian_Byron
tags: Community/Person
fullname: Christian Byron
talk.tiddlywiki.org: Christian_Byron
github: ceebeetree
linkedin: www.linkedin.com/in/christian-byron-b84a594/
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEBAAMBAAAAAAAAAAAAAAAHBgEDBQQBAAMBAAAAAAAAAAAAAAAAAAABAwX/2gAMAwEAAhADEAAAADv2xtJlY03sqePW3ARS1RSydIhcH//EACcQAAICAgIBAgYDAAAAAAAAAAECAwQFEQASMRMhBhBBk8HRIzJx/9oACAEBAAE/AMFQxs+NExqJLMCwYE+SOT4bF3qr+hAIpRsDQ6lWH0Yco4S/eVniRVQHXZzrZ5dwGQpQtNII2RfJVvHMRl5cbKxC94n/ALp+RxfiKpNcgMMUqPIwjcnWip/I5XtUowaL3Ujir/xt79Glb6/4OZ7MV5oEpUzuIa7MPB14A5jpoYLsEsydo1bbLre+CWEEEYab7Uf74ZYSSThpvtR/vmRmhnuzywp1jZtquta+VPM49qlcy24lf017At7g8uZnHrUsGK3Ez+m3UBvcnXy//8QAHhEAAgEFAAMAAAAAAAAAAAAAAQIDAAQRIkEyUaH/2gAIAQIBAT8AmiuVlZkLEeQOflJPcvMAF0z65V+h0YIW52rBDuxUrztf/8QAIxEBAAEDAwMFAAAAAAAAAAAAAgEAAxEEBSMSQcEiMVJxof/aAAgBAwEBPwC/Z1ZvNBOYz1Gc/lDUat3ySPRM/H2P3W4hcbIldpxnxW3BcjQk9oznzX//2Q==
Hello ~TiddlyWikiers - I have been a long time fan, recent contributor to the TW community.
Recently I have volunteered to run the [[TiddlyWiki Newsletter|https://tiddlywiki.substack.com/]] to spread the great news about TW.
I have been in the IT industry for about thirty years, mostly as a consultant and technical arcitect.
More recently I went back to study a masters in IT focussing on AI and data science.
Now my partner and I have started our own business ([[Sphere Innovations|https://sphere-innovations.com.au]]) - in consulting and building web applications for small to medium size businesses here in Australia.

View File

@@ -1,29 +0,0 @@
title: @ericshulman
tags: Community/Person Community/Team/Contributors
fullname: Eric Shulman
first-sighting: 2005-06-21
talk.tiddlywiki.org: ericshulman
github: ericshulman
homepage: tiddlytools.com
email: elsdesign@gmail.com
avatar: iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAD/ElEQVR42o2Tf2iUdRzH37e7rOa222233bab3mqKU9QihCAi+isKwX/sh5UQhGYQhNAvQowRUoghQWDOIJtQmOY0M92ZmVGm0WbTyZI1Nnft99S1jc3dPT9efffg/bHdLn19Hp4HPjzv9/fz+fL5aE58PwUkjzzFVC4P/G/k6E445Pc+uceeaqnv7Ogd6Rq68PPhrc+vkiERWOLT/+Ib8uQHNiXax3BIM0mC+CEtl2G7X9mIeCV+9Ejrr2MAtgkH14SNBRZXrYYPNF86nsXCkx/8dATAsp0JhknQTYJrTHg5SNI0qMekb+aw8Hr74WCKpNNu/0Kck5ymkRMcZz/1Jv5g2CUFbZYelrbMvlBMonHvJK3JuPsdTQxwExc8XG7SxF7OcxGScP6wRGCG/Asjf39VPydTzbQyRBrXBKToBCP/nQQ9VpIDO6SumU3EjUFLzX766HMG0mIvoJnXEbU47GGXc4TGBs3zWp5Jh7F47omdf56hy9lLIz3gyYfZSQMJztFEH3KEDg+bf1dkzkO9Savks7H9NLqnuEw3MEU314nTwABj/MV2R6y8JL+0wKdM8MtX23aFy04dF5mg08QI6XYsemmzRfiMDP5Mg1emK4ienZxi0p0gBfRwhSHAxgXGGeS6tYUdu6TPA3Ofr3Mfj9Bv4zHMDaCTMcBlnG4cJqx64sagN9Ngw3RJoa5R+MftI8k1Wm7NcSsH6KKPFGBbG1n1srQ+06DWpJ59cRhsGKGbo0wBFpDgNGcBcHGsl9BuSZmjfCRHWnv0BtgOcJVWwAZG2cw+3uErAKacZ6hq32PkGWuNSaxsHgIHxqjje5I4/Ms2dCt+BHpcUT4ai0j5sw22TCea2sCBbz3BOjaRFj+JeAE46IoHxlUmlfrmWuZT+8Ae935fjljDe3zpLdEJxGriLHdFtL8mKC2cbbAgIOXVBemwBhHibZq4xN/0YgPrESsRsiMs+C1zEwwFxqBqs4hY2yhlKeIUab5GLEM8SLlVRslu77jZhEwL/ofKKZ4uknxiiLO0cYFGFpJPMTGiRO0iQqtNrX7NxueTcahqv4/FTpgwFYinOcoxtiLKWEwF+U6Mqv5FuVlWSQHzvBWmKmUqIEg1YiMfIu6lhjKCRK0YkXelwoDmIjztWrCot5KQs5R5zKccIVZQwl3cTaVdQVGnfOkrzFbDuvuJWTVuBcXcQ5iFlFFAmBynlBKKH/f6z06pX6r6pJoSQlaeW2gsighi3na1E6HwNSkUUHbS45FXG7ajhIi68+1cO98qtqqJEHzTW6LbEfUstER1ef2llBKhiGqKW7VGUk6lT7dnmS/gnZMf1KPaoI16VWsrA1KhX3dObo5m9VqQpff/AFTcI4hMzFV+AAAAAElFTkSuQmCC
\define wiki(text,topic) [[$text$|https://en.wikipedia.org/wiki/$topic$]]
''Hello! My name is Eric Shulman''. I am the author of ''[[www.TiddlyTools.com|http://www.TiddlyTools.com]] (Small Tools for Big Ideas! &trade;)'', a popular collection of original plugins, macros, widgets, templates and stylesheets for TiddlyWiki that I have created and shared with the TiddlyWiki community.
<<<
Think of TiddlyTools as a ''virtual hardware store and "demonstration showroom"'', offering tools, parts and techniques that provide a rich variety of new functionality and feature enhancements to help you ''turn a general-purpose TiddlyWiki "info-house" into a comfortable, custom-built "info-home"''.
The TiddlyWiki core system provides the basic structure and utilities: the foundation, framing, walls, roof, windows/doors, plumbing, heating, and electrical systems. Then, TiddlyTools helps you with all the "finish work": the appliances, fixtures, lighting, cabinets, furniture, paint, wallpaper, carpeting, etc. ''to best suit your specific needs and personal style''.
<<<
Since the early days of TiddlyWiki (April 2005), I have worked closely with its inventor, [[Jeremy Ruston|https://jermolene.com/]], to help develop and improve TiddlyWiki's core functions. I am also a key contributor and administrator of the online TiddlyWiki [[Discourse|https://talk.TiddlyWiki.org]] and [[GoogleGroups|https://groups.google.com/forum/#!forum/tiddlywiki]] discussion forums, providing ongoing assistance to the worldwide TiddlyWiki community. I have written over 15,000 detailed responses to individual questions posted online. For several years I was also the lead developer and maintainer of the [[TiddlyWiki Classic|https://classic.tiddlywiki.com/]] codebase.
I was born and raised in suburban Long Island, NY, and attended [[Carnegie Mellon University (CMU)|https://www.cmu.edu/]] in Pittsburgh, PA, where I studied ''Computer Science, Cognitive Psychology, Sociology, Human Factors Design, and Artificial Intelligence''. As an undergraduate at CMU, I was privileged to work with some of the major luminaries in early software research and design, including <<wiki "Herbert Simon" "Herbert_A._Simon">>, <<wiki "Allen Newell" "Allen_Newell">>, <<wiki "James Gosling" "James_Gosling">>, and <<wiki "Raj Reddy" "Raj_Reddy">>. I was also employed in several Computer Science Department research projects, including the development of speech recognition technologies, graphical interface systems, and interactive applications for instruction in physics, art and music. I received a ''Bachelor of Science in "Interactive Systems Design"'' from CMU in 1985.
During my early post-graduate years, I worked for several notable software development companies, including
<<wiki "Honeywell Information Systems" "Honeywell#Honeywell_Information_Systems">> and <<wiki "Lotus Software" "Lotus_Software">>. I was an integral member of the <<wiki "1-2-3 spreadsheet"
"Lotus_1-2-3">> development team where I helped create the first GUI-based application interfaces for Microsoft Windows and IBM OS/2.
Since 1998, I have been an ''independent design consultant'', living and working in Silicon Valley, where I apply more than 40 years of experience to provide ''analysis, design and software development services'' for commercial companies and not-for-profit organizations, with emphasis on ''information architecture'' and ''interaction/visual design standards'' to improve ease-of-use for new and existing software products and online environments.

View File

@@ -1,21 +0,0 @@
title: @Jermolene
tags: Community/Person
fullname: Jeremy Ruston
first-sighting: 2004-09-20
talk.tiddlywiki.org: jeremyruston
github: Jermolene
linkedin: www.linkedin.com/in/jermy
flickr: www.flickr.com/photos/jermy/
bluesky: https://bsky.app/profile/jermolene.bsky.social
homepage: jermolene.com
email: jeremy@jermolene.com
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAtAAEBAAMAAAAAAAAAAAAAAAAHBgIEBQEBAQEBAAAAAAAAAAAAAAAAAgQBBf/aAAwDAQACEAMQAAAANF4uTuPRhD2nBLnUiJvKM0DtMKy//8QAKxAAAgIBAwMDAQkAAAAAAAAAAQIDBBEABRITITEiMkFxFEJRUmFicoGR/9oACAEBAAE/AInTA6gUGP4ZOQbW1bPsmyUq1q+gmvFPUzZPDkPamtwqU75ks04JakroVcg5RwRjg66NUx25KbzqJYyMngfqSuq0M3NZYIebJIvZozIvI/iNPcp/aalSdJXsS4VcKeIzlvU3jVTcYLNiaGISrjkhWQYDfQ63pYAzCDBsOiu7Dsx4EHH6r2w2ttimjd2IsNErhhJHKI04/uzqxuCxpBYVVWKSHqwMyMSQ33SB7dUJFmlkMYRgnqZgCMf7rf8AeEt3A9YOhjXAb2k8u7dtT1RZeOtXmYxiOPj4ZWY/lb51skqUNnNW/wBNzC7IpB6gQeeB/jq/fqGOaLbowuYn5MAQOw8LjW5Vmeo0qIsqYLLKjHIZmwv9fB1//8QAHxEAAQMEAwEAAAAAAAAAAAAAEQABAgMSIWExMkFR/9oACAECAQE/AD9iTy2lJmHUB8BVKM4SNSOj46a29saX/8QAHREAAgICAwEAAAAAAAAAAAAAAQIAAwQRITGBkf/aAAgBAwEBPwDHpFpJZtamVSiBWT2Yt7hmCDsb+TKtsKqpGg3M/9k=
I'm the original inventor of TiddlyWiki. You can hire me through my consultancy company [[Intertwingled Innovations|https://intertwingledinnovations.com]] or contact me directly.
Further information:
* A recording of the [[keynote I gave at QCon London in April 2024|https://www.infoq.com/presentations/bbc-micro/]], and the [[discussion on talk.tiddlywiki.org|https://talk.tiddlywiki.org/t/recording-of-jeremys-keynote-at-qcon-london-april-2024/10505]]. The talk mixes some nostalgia about my teenage activities with the BBC Micro with thoughts on the development of the software industry and insights gained from working with TiddlyWiki
* An [[interview with me in The Inquirer|https://web.archive.org/web/20111103225832/http://www.theinquirer.net/inquirer/feature/2105529/bt-software-engineer-tells-telco-source]] by Wendy Grossman
* A [[hilarious interview with me|https://www.youtube.com/watch?v=auyIhw8MTmQ]] from British television in 1983
* Here's a video of a presentation I did in 2007 called [["How to Start an Open Source Project"|http://vimeo.com/856110]].

View File

@@ -1,19 +0,0 @@
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEAAwEBAAAAAAAAAAAAAAAGAwQHAgUBAAMBAAAAAAAAAAAAAAAAAAACAwT/2gAMAwEAAhADEAAAAOfCWAMdKKetM4wOvY5OcvZnrYf/xAApEAACAQQBBAECBwAAAAAAAAABAgMABAURQQYSIVETFCIxMkJicYKh/9oACAEBAAE/AEtysaStr7mPaPeuazWdMM4gEnfPryW8hBUuZvou2RXRxyreBWPmgyNqs8f8MOQalhdY7Vz+R4/s/qfP+1edNi/zl7HDcFbmS3E8CcMR4INP0PkBhklIm+sZNtFtQiV0nj57Owl+dSrSTFgD6/CtH4VV9lU3oAbPngAVY389lc5URuUZkMxhnR4pvW0VwDqsP1FNmLWYqCpikMbngmliJNY+aKzyTxXS6lRAyg/u5rq+5x2RsuyTa3MQMlvKniRGThTUd1JYXUdzAwDvqVxGdRXMbfrVOD7HBrG3mNEsU8z98TRhl9eRzX//xAAcEQACAgIDAAAAAAAAAAAAAAABAgARAzESIVH/2gAIAQIBAT8ARuXZPsul3Eoje5lBQWBP/8QAGREAAwEBAQAAAAAAAAAAAAAAAAECEiER/9oACAEDAQE/AM98Lk7LJe20z//Z
created: 20251110102157310
first-sighting: 2019-03-01
fullname: Lin Onetwo
github: linonetwo
homepage: https://wiki.onetwo.website/
modified: 20251111184556193
tags: Community/Person Community/Team/Contributors
talk.tiddlywiki.org: linonetwo
title: @linonetwo
type: text/vnd.tiddlywiki
Since 2014, when I started college, I've been on a quest for a lifelong PKM tool. I cherish my life and all my experiences, and I dont want to forget any of them. When Im deeply focused on a task, its easy to lose sight of other important parts of my life—so I needed a system to help me stay balanced.
Early on, I tried TiddlyWiki several times, but I was initially put off by its save mechanism and markup editing. That changed when I discovered an auto-backup script, which gave me the confidence to fully commit. Over time, I improved the script and eventually transitioned to using TidGi-Desktop and TidGi-Mobile.
Today, my TiddlyWiki holds all my game design ideas and progress logs—it has truly become my second brain. With the help of LLM-powered programming tools, Ive enhanced it with numerous plugins, allowing me to manage my mind in a more programmable and structured way. As a game developer, TiddlyWiki isn't the core of my professional work; But I've invested so much time because it's fundamentally about upgrading my mind.
Most of my notes are open by default and shared publicly on my homepage as a digital garden.

View File

@@ -1,11 +0,0 @@
title: @MotovunJack
tags: Community/Person Community/Robot
fullname: Motovun Jack
first-sighting: 2012-01-12
github: MotovunJack
homepage: tiddlywiki.com
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wEEEAAYABgAGAAYABkAGAAaAB0AHQAaACUAKAAjACgAJQA2ADIALgAuADIANgBSADsAPwA7AD8AOwBSAH0ATgBbAE4ATgBbAE4AfQBuAIYAbQBlAG0AhgBuAMYAnACKAIoAnADGAOUAwQC2AMEA5QEWAPgA+AEWAV4BTAFeAckByQJmEQAYABgAGAAYABkAGAAaAB0AHQAaACUAKAAjACgAJQA2ADIALgAuADIANgBSADsAPwA7AD8AOwBSAH0ATgBbAE4ATgBbAE4AfQBuAIYAbQBlAG0AhgBuAMYAnACKAIoAnADGAOUAwQC2AMEA5QEWAPgA+AEWAV4BTAFeAckByQJm/8IAEQgAQABAAwEiAAIRAQMRAf/EADAAAAIDAQEAAAAAAAAAAAAAAAMEAQIFBgABAQEBAQEAAAAAAAAAAAAAAAIDAQAE/9oADAMBAAIQAxAAAADZCfn5vZJz+rnODGtpbpm6O8xzG9lCiszXtikQhtkTBputBxURJuVVYlEdBaQ284mPDj6GmkNUblMxRmi7dKw//8QAKxAAAgIBAgUCBgMBAAAAAAAAAQIAAxESIQQTIkFRFGEjMUJxgaEyNGLR/9oACAEBAAE/AMmX3ilMkjPaV3ragZDtNRmoxpvA2sEqQcHEwJxlwa98nYbCU8TymDfSTvPVKMbZHkQcTU4yDH46tTiE8RxjLXnQp7Dx5MACgKuyqMAS1xXU7kjYTiEbWp3y0IucYbGx6e05hDAqMH/k59o3DfxAE5hss1MNzODdVraxu50ieppH1Tivi8O6eYQ1j4B6guAftChDMNjBqycHcCYJqdj2s3idRBHfpi/1Kie7PDo95w/EMxYM22n9yy5AzBc/iLe7dIqx7kyy2ypyOWoYTofhCyDAZtx4MOmpK9sncyx1NdSq2kBBt3EKf6mgIzDUPIiByuqk7faMLbOyEjuuxEAyo56AgeTA3KL1AYRm1CcvmkgAs2wHjEvPxGIMJPmHUQCQNothr32A0ggeYluplcAK2PlLbTytZUkdwI7V3lAQMgbAfP8AMoCV1AKMOR+pdsc5yD595mMmNIGD4h0vsfupHyBlTKW9znMd+TQnljPWqHYIqhwD1zKsqtjBzCAVAyBicnqG6jbOe0//xAAbEQEBAAMBAQEAAAAAAAAAAAABAAIRIRASQf/aAAgBAgEBPwBYbZDuXvnLE5OrkWJzxI4g33ift//EABsRAAMBAQADAAAAAAAAAAAAAAABEQIhEBJB/9oACAEDAQE/AMqjzHwjGoZXPHTb6Zp1/TRp1khYjW01xHqz/9k=
Motovun Jack is a robot that helps maintain the TiddlyWiki project infrastructure. It is not a person, but rather a set of automated scripts and tools that assist in managing the various services and resources used by the TiddlyWiki community.
The origin of the name "Motovun Jack" is a lovable and playful kitten encountered by [[@Jermolene]] in the beautiful medieval hill town of Motovun in Croatia. Jack was [[first adopted|https://github.com/TiddlyWiki/TiddlyWiki5/commit/ecfbaaa5641f14e1766ef17ef6416bf9aa992863]] as the TiddlyWiki 5 mascot in 2012.

View File

@@ -1,25 +0,0 @@
avatar: UklGRiwIAABXRUJQVlA4WAoAAAAwAAAAPwAAPwAASUNDUCACAAAAAAIgbGNtcwRAAABtbnRyR1JBWVhZWiAH6QALAAoACwADAAZhY3NwTVNGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZkZXNjAAAAzAAAAG5jcHJ0AAABPAAAADZ3dHB0AAABdAAAABRrVFJDAAABiAAAACBkbW5kAAABqAAAACRkbWRkAAABzAAAAFJtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFIAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA81EAAQAAAAEWzHBhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbbWx1YwAAAAAAAAABAAAADGVuVVMAAAAIAAAAHABHAEkATQBQbWx1YwAAAAAAAAABAAAADGVuVVMAAAA2AAAAHABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAVlA4TOYFAAAvP8APEDWGgbRtWv+yt/0WImICOBvWn1C4dFi1bStbvpY8Qg2ePANNNAMh3N2db/7A91/7CHBvBBRr25ZFH+4k98ihkqi2CP4tsANvX8a+8y8Ct04dn0nuUt39ZiBJkowqt911M+MJ1G3bNiZJr1iP0DZ+2bbdadsqprOjAqmoUIX9hf3Fl5/uPYV7I3OMeoFzIvrvwG0kRUr3zPLdYMMXaqrMMsp0K4fufKO6c2hFV5Zh7kRROZX0PSCmB/3KWQwpuiekWelSRZDW94d0q750NrxavpFn1eLNQ9EV8nWlmAET6Q8lrCRTcjFLlLImluK3iXJW/hT47KGklS8OlzWUtXLFYDRCSS74ojUjxggqKMoxd6A1lTCyvsvyzC5/d7BsCHb7yIcHyrX2yR/NPnsAdRT2i0Pwp/o0Il6ix8hsRAuJmQgcr4KREfAiMgUVm9KqmfSxL5pOJspVwwTiV6jiIAg1RMhHpERhbvwgGI34Hc49T7UeKZtXwEqJ+BAaoBneperJH0POs1u4dufwv8Gf+qcOfjyvX6ZIVgxE0Rw87YF3BSc9c7jsXfdjOBG7FwmSb39pfGRwu8IuvUjJNoTpFzkEvDg6W3Qt/9nf99ZXPy8HM43IweTKyNR+WVatXcWWyakBksj9cqW+QetplcjsKElvZH/zuOO/PrCx//tL3/6x/O/C1PZZvSKuulLcS4l8M1ewGPR6ef5sllXW2eGQZ7hVSEZiPmcqrSS8e2ElX8o7t1fvB9LFetmEx5hx1Xuye2PpfjZnSjj7QfKTB3bZZo05Zvh6YuivX24cpc8+ddvADWG9odrSwFalVurxUiidDHmTiaoNkkh2gjbcpxMiAbd39aVP119/N9k4+euNKfcNjwaPhZEuUupUsJrHchw1LkPrRC9bQKa3M8Mj/xx903drdnHMpbirj1ENsUre0oo3N+7gat+2ZctKdsIUYc21sRu+Ucdhn+P7DyarftW00iu3Tmbv+hTfdCTmyaIPT4PrYZDFtBN2W8S9m4oTB5Z2P3Oe7weKjVBq86kXX/r0+WuvTAzfjqm1hsYRPWlbxm4n3IaeGOJEizv8orH9w5ejjmSrfOuEq/HxT6eDemtsZ/HTvvG1/8iVspxZILrlkz/cdsIbIroOgJileFSty2xiHNW5t9fbHJ3ze87bp5T9vc8RuqMB0ReDSt464R/BJxspvgpEsrVAJMTsYg2QovPTOHrvQ9et/S2Xx+40z7dY4JBX0Pz/ElH/T73U2DkK8EiqC9hM/zV3frQfzjaAqO16s1l6xCUXnBFlYxyIer3eEdth7u5xsHKxWoGLqzY3wIULt9G3K6soei9jZ+UcF+Ka3M/II9EUWrJ/LLxy+Q9xIh0vOl3NZCrVnBsuFUTOSnJnSioRWZ9q4g+ZDk5XVORoW2qX2hbIkna3JOrdR3jmpHVLovUkLES6grRO010u0GkDlX7SpH1DQ64Wl2zaSUJv1Mtti2G7kx5IyftWMhfDlGClcxvIUhP5crhp9LIb1Vne187oSAWxelcR/kXjYQTZboW+Oj1pqF0gmfZhSDD6bSgzGWrw3s7QLNtCV+2uatYrd/aFtjDI8R52e/DdyKgRKXBhEak3Ev50+GCUA9EFUor39htVMxmWvW8AM6ptG416rZvdWn+MarIEyH5r6ruZSrx8XrWDP370vbfTjqpmZGIbiFPFoihc4jcrlYi9p3ndSuymZ+XLaKza/P/HUWHn5Axdkd9OjBskY0+pIlz4AlFPFs+aStK5PBIRR4MVVJDihsy4JdEA4pVcrVqMZDyL2/8aYocikEAR9Xjc1BNG9zEiJG7n/cGyrtnblkClBhEgMW4Kx21BEBGJjLa0hcOGmTK64KsKLfKr9QyQELclxY3hqowTIZKdZNTSS5BWiBPlKxDWBVSS41bOepkhTkhGDajLfLyUBOKlkMHPgOhx3JoRN/cEiRgSWdgF2yCyDQu4IcbNo8ftTzxveOJ5y+h509h52+h549h569h587/M20f/b1AB
created: 20251110102157310
first-sighting: 2009-11-14
fullname: Mario Pietsch
github: pmario
homepage: https://wikilabs.github.io/
modified: 20251110124935183
tags: Community/Person Community/Team/Contributors
talk.tiddlywiki.org: pmario
title: @pmario
type: text/vnd.tiddlywiki
youtube: https://www.youtube.com/@pmario
''Hi, My name is Mario Pietsch''. Back in 2009 I was ''searching'' for ''a simple presentation tool'' and discovered ~TiddlyWiki Classic, Monkey Pirate ~TiddlyWiki ([[MPTW|https://mptw.tiddlyspot.com/]]) with ~TagglyTagging, Eric Shulman's ~TiddlyTools, Saq Imtiaz's navigation macros, and more. --- ''I was captivated''.
After a deep dive, I combined these elements into my own "Presentation Manager", along [[3 step by step tutorials|https://groups.google.com/g/tiddlywiki/c/qG_tZ1x0MEU/m/-vLA0luMicYJ]] to help others build it.
Thanks to ''the positive spirit'' of the ~TiddlyWiki community, I am proud to be part of it since 2009.
When Jeremy started developing ~TiddlyWiki 5 on ~GitHub, I joined in—opening [[issue no. 1|https://github.com/TiddlyWiki/TiddlyWiki5/issues/1]] all the way up to 13. For what thats good ;) Since then, I have submitted nearly 600 pull requests and more than 500 issues, many of which have been merged or resolved.
My ~TiddlyWiki 5 "laboratory" is at https://wikilabs.github.io, and I also share content on my ''~YouTube'' channel: https://www.youtube.com/@pmario
Have fun!<br>
Mario

View File

@@ -1,10 +0,0 @@
title: TiddlyWiki People
modified: 20250909171928024
created: 20250909171928024
tags: Community About
Members of the TiddlyWiki community who are involved in the development of TiddlyWiki and the running of the project are invited to [[create a Community Card|Submitting a Community Card]] so that they can be included in project plans and organisation charts. Community Cards can also showcase their interests and activities in the TiddlyWiki community.
{{Community Cards Caveats}}
<<community-card-pill-stack-person personFilter:"[tag[Community/Person]sort[title]]">>

View File

@@ -1,10 +0,0 @@
title: TiddlyWiki Project
modified: 20250909171928024
created: 20250909171928024
tags: Community About
The TiddlyWiki Project is the coordinated, ongoing effort to maintain and improve TiddlyWiki, and to support the TiddlyWiki community.
{{Community Cards Caveats}}
<$list filter="[tag[Community/Team]]" template="$:/tiddlywiki/community/cards/ViewTemplateBodyTemplateTeam"/>

View File

@@ -1,4 +0,0 @@
title: Vacant Positions
tags: [[TiddlyWiki Project]]
If you are interested in volunteering to help the project please get in touch with <<community-card-pill-person title:"@Jermolene">>.

View File

@@ -1,8 +0,0 @@
title: Core Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
leader: @Jermolene
team: @saqimtiaz
The core team is responsible for the maintenance and development of the TiddlyWiki core and official plugins.

View File

@@ -1,19 +0,0 @@
title: Developer Experience Team
tags: Community/Team
modified: 20251109200632671
created: 20251109200632671
leader: @pmario
team: @saqimtiaz
The Developer Experience Team improves the experience of software contributors to the TiddlyWiki project. This includes enhancing documentation, streamlining contribution processes, and providing tools and resources to help developers effectively contribute to TiddlyWiki.
Tools and resources managed by the Developer Experience Team include:
* Advising and assisting contributors, particularly new developers
* Maintenance of developer-focused documentation on the https://tiddlywiki.com/dev/ site, including:
** Development environment setup guides
** Code review processes and best practices
** Contribution guidelines and documentation
* Continuous integration and deployment scripts providing feedback on pull requests
* Devising and implementing labelling systems for issues and pull requests
* Automation scripts to simplify common development tasks

View File

@@ -1,15 +0,0 @@
created: 20250909171928024
modified: 20251110133437795
tags: Community/Team
team: @MotovunJack
title: Infrastructure Team
The Infrastructure Team is responsible for maintaining and improving the infrastructure that supports the TiddlyWiki project. This includes the hosting, deployment, and management of the TiddlyWiki websites and services, as well as the tools and systems used by the TiddlyWiki community.
The infrastructure includes:
* talk.tiddlywiki.org
* github.com/TiddlyWiki
* tiddlywiki.com DNS
* Netlify account for PR previews
* edit.tiddlywiki.com

View File

@@ -1,8 +0,0 @@
title: MultiWikiServer Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
leader: @Arlen22
team:
The MultiWikiServer development repository is at https://github.com/TiddlyWiki/MultiWikiServer

View File

@@ -1,15 +0,0 @@
title: Project Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
icon: $:/tiddlywiki/community/icons/project-team
leader: @Jermolene
team: @saqimtiaz @ericshulman
The project team is responsible for the overall TiddlyWiki project, its vision, mission and values, and ensuring that it meets the needs of the community.
Areas of responsibility include:
* Communicating and demonstrating the vision, mission and values of the project
* Continuously improve the development process and practices of the project
* more to come...

View File

@@ -1,11 +0,0 @@
title: Quality Assurance Team
created: 20251112125742296
modified: 20251112125742296
tags: Community/Team
team:
leader: @Leilei332
title: Quality Assurance Team
The Quality Assurance Team is responsible for ensuring the quality and reliability of TiddlyWiki releases. This includes reviewing code submissions, testing new features, identifying bugs, and verifying that fixes are effective.

View File

@@ -1,13 +0,0 @@
title: Succession Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
leader: @Jermolene
team: @saqimtiaz @ericshulman
The Succession Team is responsible for ensuring that personnel changes do not impact access to the external infrastructure used by the project.
* Work with the other teams to ensure that the project has a succession plan for key personnel
* Work with the other teams to ensure that they are using the appropriate, community-owned infrastructure
* Ensure that the members of the succession team share ownership of the key project resources (eg passwords and user accounts). The Succession Team is not expected to use their access rights apart from managing access in the event of personnel changes

View File

@@ -1,15 +0,0 @@
title: TiddlyWiki Newsletter Team
tags: Community/Team
modified: 20251219090709874
created: 20250909171928024
leader: @Christian_Byron
The Newsletter Team is responsible for producing the [[TiddlyWiki Newsletter]]. We would love to have your help if you would like to get involved.
! Audience
The newsletter is intended for TiddlyWiki end users who do not track all the discussions on https://talk.tiddlywiki.org/.
Coverage of developer topics such as JavaScript and intricate wikitext should be handled thoughtfully to avoid alienating the core audience of end users.
Subscribing to the newsletter is intended to give people confidence that they will not miss any important developments.

View File

@@ -1,5 +0,0 @@
title: Community/Team
modified: 20250909171928024
created: 20250909171928024
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[Quality Assurance Team]] [[Infrastructure Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Succession Team]]

View File

@@ -1,3 +0,0 @@
# Community Records and Resources
These raw tiddlers comprise the community records and resources for the TiddlyWiki project. They are packaged as a root directory outside of the usual "editions" folder so that they can be shared with other wikis.

View File

@@ -1,15 +0,0 @@
title: $:/config/DefaultColourMappings/
community-card-background: #ffffee
community-card-foreground: #441111
community-card-dark-shadow: rgba(188, 189, 189, 0.5)
community-card-shadow: rgba(212, 212, 213, 0.5)
community-card-header-background: #9e3060
community-card-header-foreground: #ddddee
community-card-team-header-background: #306090
community-card-team-header-foreground: #ddeedd
community-card-vacancy-header-background: #609030
community-card-vacancy-header-foreground: #eedddd
community-card-info-background: #f3f38b
community-card-info-foreground: #444411
community-card-field-name-foreground: #888844

View File

@@ -1,168 +0,0 @@
title: $:/tiddlywiki/community/cards/Procedures
tags: $:/tags/Global
\procedure community-card-display-jpeg-field(fieldName,mode:"block",default)
<$genesis $type={{{ [<mode>match[block]then[div]else[span]] }}} class={{{ tc-community-card-field-image [[tc-community-card-field-image-]addsuffix<fieldName>] +[join[ ]] }}}>
<%if [<currentTiddler>has<fieldName>] %>
<img src={{{ [<currentTiddler>get<fieldName>addprefix[data:image/jpeg;base64,]] }}} width="32"/>
<%else%>
<$transclude $tiddler=<<default>> $mode=<<mode>>/>
<%endif%>
</$genesis>
\end community-card-display-jpeg-field
\procedure community-card-display-transclusion(fieldName,mode:"inline",default)
<$genesis $type={{{ [<mode>match[block]then[div]else[span]] }}} class={{{ tc-community-card-field-image [[tc-community-card-field-image-]addsuffix<fieldName>] +[join[ ]] }}}>
<%if [<currentTiddler>has<fieldName>] %>
<$transclude $tiddler={{{ [<currentTiddler>get<fieldName>] }}} $mode=<<mode>>/>
<%else%>
<$transclude $tiddler=<<default>> $mode=<<mode>>/>
<%endif%>
</$genesis>
\end community-card-display-transclusion
\procedure community-card-display-text-field(fieldName,showLabel:"yes",linkPrefix,displayPrefix,mode:"block")
<%if [<currentTiddler>has<fieldName>] :or[<fieldName>match[title]] %>
<$genesis $type={{{ [<mode>match[block]then[div]else[span]] }}} class={{{ tc-community-card-field-text [[tc-community-card-field-text-]addsuffix<fieldName>] +[join[ ]] }}}>
<%if [<showLabel>match[yes]] %>
<span class="tc-community-card-field-text-name"><$text text=<<fieldName>>/></span>
<%endif%>
<%if [<linkPrefix>!match[]] %>
<a
href={{{ [<currentTiddler>get<fieldName>addprefix<linkPrefix>] }}}
class="tc-community-card-field-text-value"
rel="noopener noreferrer"
target="_blank"
>
<$text text={{{ [<currentTiddler>get<fieldName>] :else[<fieldName>match[title]then<currentTiddler>] +[addprefix<displayPrefix>] }}}/>
</a>
<%else%>
<span class="tc-community-card-field-text-value">
<$text text={{{ [<currentTiddler>get<fieldName>] :else[<fieldName>match[title]then<currentTiddler>] +[addprefix<displayPrefix>] }}}/>
</span>
<%endif%>
</$genesis>
<%endif%>
\end community-card-display-text-field
\procedure community-card-person(title)
<$let currentTiddler=<<title>>>
<div class="tc-community-card">
<$link to=<<currentTiddler>> class="tc-community-card-header-link">
<div class="tc-community-card-header">
<<community-card-display-jpeg-field "avatar" default:"$:/tiddlywiki/community/icons/person">>
<<community-card-display-text-field "title" showLabel:"no">>
</div>
</$link>
<div class="tc-community-card-info">
<<community-card-display-text-field "fullname">>
<<community-card-display-text-field "first-sighting">>
<<community-card-display-text-field "talk.tiddlywiki.org" linkPrefix:"https://talk.tiddlywiki.org/u/" displayPrefix:"@">>
<<community-card-display-text-field "github" linkPrefix:"https://github.com/" displayPrefix:"@">>
<<community-card-display-text-field "linkedin" linkPrefix:"https://">>
<<community-card-display-text-field "flickr" linkPrefix:"https://">>
<<community-card-display-text-field "homepage" linkPrefix:"https://">>
<<community-card-display-text-field "email" linkPrefix:"mailto:">>
<%if [all[tiddlers+shadows]tag[Community/Team]sort[title]] :filter[{!!leader}match<..currentTiddler>] +[count[]compare:number:gt[0]] %>
<div class="tc-community-card-field-text">
<span class="tc-community-card-field-text-name">leader</span>
<span class="tc-community-card-field-text-value">
<$list filter="[all[tiddlers+shadows]tag[Community/Team]sort[title]] :filter[{!!leader}match<..currentTiddler>]">
<$transclude $variable="community-card-pill-team" title=<<currentTiddler>>/>
</$list>
</span>
</div>
<%endif%>
<%if [all[tiddlers+shadows]tag[Community/Team]sort[title]] :filter[enlist{!!team}match<..currentTiddler>] +[count[]compare:number:gt[0]] %>
<div class="tc-community-card-field-text">
<span class="tc-community-card-field-text-name">member</span>
<span class="tc-community-card-field-text-value">
<$list filter="[all[tiddlers+shadows]tag[Community/Team]sort[title]] :filter[enlist{!!team}match<..currentTiddler>]">
<$transclude $variable="community-card-pill-team" title=<<currentTiddler>>/>
</$list>
</span>
</div>
<%endif%>
</div>
<div class="tc-community-card-body">
<$transclude $tiddler=<<currentTiddler>> $field="text" $mode="block"/>
</div>
</div>
</$let>
\end community-card-person
\procedure community-card-team(title)
<$let currentTiddler=<<title>>>
<div class="tc-community-card tc-community-card-team">
<$link to=<<currentTiddler>> class="tc-community-card-header-link">
<div class="tc-community-card-header">
<<community-card-display-transclusion fieldName:"icon" default:"$:/tiddlywiki/community/icons/team">>
<<community-card-display-text-field "title" showLabel:"no">>
</div>
</$link>
<div class="tc-community-card-info">
<div class="tc-community-card-field-text">
<span class="tc-community-card-field-text-name">leader</span>
<span class="tc-community-card-field-text-value">
<%if [<currentTiddler>has[leader]] %>
<$transclude $variable="community-card-pill-person" title={{!!leader}}/>
<%else%>
<$transclude $variable="community-card-vacancy"/>
<%endif%>
</span>
</div>
<div class="tc-community-card-field-text">
<span class="tc-community-card-field-text-name">team</span>
<span class="tc-community-card-field-text-value"><$transclude $variable="community-card-pill-stack-person" personFilter={{!!team}}/></span>
</div>
</div>
<div class="tc-community-card-body">
<$transclude $tiddler=<<currentTiddler>> $field="text" $mode="block"/>
</div>
</div>
</$let>
\end community-card-team
\procedure community-card-pill-person(title)
<$let currentTiddler=<<title>>>
<$link to=<<currentTiddler>> class="tc-community-card-pill">
<<community-card-display-jpeg-field "avatar" default:"$:/tiddlywiki/community/icons/person" mode="inline">>
<<community-card-display-text-field "title" showLabel:"no" mode:"inline">>
</$link>
</$let>
\end community-card-pill-person
\procedure community-card-pill-stack-person(personFilter:"[tag[Community/Person]]")
<div class="tc-community-card-pill-stack">
<$list filter=<<personFilter>>>
<$list-template>
<$transclude $variable="community-card-pill-person" title=<<currentTiddler>> mode="block"/>
</$list-template>
<$list-empty>
<$transclude $variable="community-card-vacancy"/>
</$list-empty>
</$list>
</div>
\end community-card-pill-stack-person
\procedure community-card-pill-team(title)
<$let currentTiddler=<<title>>>
<$link to=<<currentTiddler>> class="tc-community-card-pill">
<<community-card-display-transclusion fieldName:"icon" default:"$:/tiddlywiki/community/icons/team">>
<<community-card-display-text-field "title" showLabel:"no" mode:"inline">>
</$link>
</$let>
\end community-card-pill-team
\procedure community-card-vacancy()
<$link to="Vacant Positions" class="tc-community-card-pill tc-community-card-pill-vacancy">
<span class="tc-community-card-field-image tc-community-card-field-image-avatar">
{{$:/core/images/help}}
</span>
<span class="tc-community-card-field-text tc-community-card-field-text-title">
<span class="tc-community-card-field-text-value">
Vacant
</span>
</span>
</$link>
\end community-card-vacancy

View File

@@ -1,158 +0,0 @@
title: $:/tiddlywiki/community/cards/Styles
tags: $:/tags/Stylesheet
.tc-community-card {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
border-radius: 8px;
width: 100%;
margin-bottom: 8px;
background: <<colour community-card-background>>;
color: <<colour community-card-foreground>>;
fill: <<colour community-card-foreground>>;
box-shadow: 0 1px 3px 0 <<colour community-card-shadow>>, 0 0 0 1px <<colour community-card-shadow>>;
transition: box-shadow 0.3s ease,transform .3s ease;
}
.tc-community-card:hover {
box-shadow: 0 1px 6px 0 <<colour community-card-dark-shadow>>, 0 0 0 1px <<colour community-card-shadow>>;
transform: translateY(-2px);
}
.tc-community-card .tc-community-card-header-link {
background-color: <<colour community-card-header-background>>;
color: <<colour community-card-header-foreground>>;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.tc-community-card.tc-community-card-team .tc-community-card-header-link {
background: <<colour community-card-team-header-background>>;
color: <<colour community-card-team-header-foreground>>;
fill: <<colour community-card-team-header-foreground>>;
}
.tc-community-card .tc-community-card-header-link:hover {
text-decoration: none;
background-color: <<colour community-card-header-foreground>>;
color: <<colour community-card-header-background>>;
}
.tc-community-card-header {
margin: 0;
padding: 0.5em;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
line-height: 0;
}
.tc-community-card-header .tc-community-card-field-text-title {
font-size: 1.5em;
font-weight: bold;
}
.tc-community-card-header .tc-community-card-field-image {
display: table-row;
width: auto;
max-width: 100%;
margin-right: 12px;
}
.tc-community-card-info {
display: table;
width: auto;
max-width: 100%;
padding: 8px;
margin: 0;
background-color: <<colour community-card-info-background>>;
color: <<colour community-card-info-foreground>>;
}
.tc-community-card-body {
padding: 0 8px;
}
.tc-community-card .tc-community-card-field-text {
display: table-row;
}
.tc-community-card .tc-community-card-field-text-name,
.tc-community-card .tc-community-card-field-text-value {
display: table-cell;
padding: 2px 6px 2px 0;
vertical-align: top;
}
.tc-community-card .tc-community-card-field-text-name {
color: <<colour community-card-field-name-foreground>>;
white-space: nowrap;
text-align: right;
padding-right: 8px;
}
.tc-community-card .tc-community-card-field-text-value {
word-break: break-word;
font-weight: bold;
width: 100%;
}
a.tc-community-card-pill {
display: inline-flex;
align-items: center;
gap: 4px;
width: auto;
min-width:0;
max-width: none;
align-self: auto;
font-size: 0.9em;
line-height: 1;
vertical-align: middle;
padding: 4px;
border-radius: 4px;
background: <<colour community-card-header-background>>;
color: <<colour community-card-header-foreground>>;
fill: <<colour community-card-header-foreground>>;
box-shadow: 0 1px 3px 0 <<colour community-card-shadow>>, 0 0 0 1px <<colour community-card-shadow>>;
transition: box-shadow 0.3s ease,transform .3s ease;
}
a.tc-community-card-pill.tc-community-card-pill-vacancy {
background: <<colour community-card-vacancy-header-background>>;
color: <<colour community-card-vacancy-header-foreground>>;
fill: <<colour community-card-vacancy-header-foreground>>;
}
a.tc-community-card-pill:hover {
text-decoration: none;
box-shadow: 0 1px 6px 0 <<colour community-card-dark-shadow>>, 0 0 0 1px <<colour community-card-shadow>>;
transform: translateY(-2px);
background: <<colour community-card-header-foreground>>;
color: <<colour community-card-header-background>>;
fill: <<colour community-card-header-background>>;
}
a.tc-community-card-pill .tc-community-card-field-image img,
a.tc-community-card-pill .tc-community-card-field-image svg {
width: 16px;
height: 16px;
vertical-align: middle;
display: inline-block;
}
a.tc-community-card-pill .tc-community-card-field-text {
display: inline;
}
.tc-community-card-pill-stack {
display: inline-flex;
flex-direction: column;
align-items: stretch;
gap: 4px;
margin: 0;
padding: 0;
}

View File

@@ -1,6 +0,0 @@
title: $:/tiddlywiki/community/cards/ViewTemplateBodyCascade
tags: $:/tags/ViewTemplateBodyFilter
list-before:
[tag[Community/Person]then[$:/tiddlywiki/community/cards/ViewTemplateBodyTemplatePerson]]
[tag[Community/Team]then[$:/tiddlywiki/community/cards/ViewTemplateBodyTemplateTeam]]

View File

@@ -1,3 +0,0 @@
title: $:/tiddlywiki/community/cards/ViewTemplateBodyTemplatePerson
<$transclude $variable="community-card-person" title=<<currentTiddler>>/>

View File

@@ -1,3 +0,0 @@
title: $:/tiddlywiki/community/cards/ViewTemplateBodyTemplateTeam
<$transclude $variable="community-card-team" title=<<currentTiddler>>/>

View File

@@ -1,7 +0,0 @@
title: $:/tiddlywiki/community/icons/person
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> viewBox="0 0 64 64">
<path d="M43.127,29.612c-0.879,-0.378 -1.452,-1.25 -1.452,-2.207c-0.006,-0.678 0.27,-1.33 0.761,-1.797c0.147,-0.141 0.29,-0.28 0.397,-0.393c0.753,-0.791 1.416,-1.663 1.978,-2.6c1.392,-2.318 2.126,-4.974 2.126,-7.677c0,-8.196 -6.744,-14.938 -14.938,-14.938c-0.945,0 -1.886,0.088 -2.813,0.266c-5.891,1.031 -10.578,5.586 -11.781,11.446c-1.105,5.016 0.454,10.264 4.118,13.865c0.495,0.469 0.78,1.118 0.792,1.799l0,0.012c0.008,0.966 -0.567,1.848 -1.453,2.23c-5.949,2.466 -10.698,7.172 -13.217,13.099c-1.772,4.059 -2.66,8.45 -2.607,12.88l0,3.192c0,2.858 2.351,5.211 5.212,5.211l43.5,0c2.859,0 5.212,-2.353 5.212,-5.211l-0,-3.225c0.053,-4.427 -0.837,-8.816 -2.611,-12.873c-2.523,-5.922 -7.274,-10.621 -13.224,-13.079Z" style="fill-rule:nonzero;"/>
</svg>

View File

@@ -1,7 +0,0 @@
title: $:/tiddlywiki/community/icons/project-team
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> viewBox="0 0 64 64">
<path d="M24.891,49.399l-3.521,0c-1.398,0 -2.547,-1.15 -2.547,-2.547l0,-1.56c-0.026,-2.165 0.408,-4.311 1.274,-6.295c1.231,-2.897 3.552,-5.197 6.46,-6.402c0.433,-0.187 0.714,-0.618 0.71,-1.09l0,-0.006c-0.006,-0.333 -0.145,-0.65 -0.387,-0.879c-1.791,-1.76 -2.553,-4.325 -2.013,-6.777c0.588,-2.864 2.879,-5.09 5.758,-5.594c0.453,-0.087 0.913,-0.13 1.375,-0.13c4.005,0 7.301,3.295 7.301,7.301c0,1.321 -0.359,2.619 -1.039,3.752c-0.275,0.458 -0.599,0.884 -0.967,1.271c-0.052,0.055 -0.122,0.123 -0.194,0.192c-0.24,0.228 -0.375,0.547 -0.372,0.878c0,0.468 0.28,0.894 0.71,1.079c2.908,1.201 5.23,3.498 6.463,6.392c0.815,1.865 1.248,3.872 1.276,5.904c-0.179,0.006 -0.351,0.007 -0.514,0.003c-0.556,-0.016 -1.375,-0.294 -2.288,-0.512c-1.295,-0.308 -2.719,-0.543 -4.01,-0.396l-0.013,0.001c-1.056,0.128 -2.116,0.325 -3.097,0.76c-0.385,0.171 -1.216,0.753 -1.446,0.916c-1.157,0.297 -2.564,0.475 -3.797,0.312c-0.713,-0.094 -1.402,-0.225 -1.703,-0.778c-0.207,-0.382 -0.181,-0.896 -0.031,-1.565c0.068,-0.3 0.11,-0.593 0.118,-0.842l-0.106,-0.887l-0.212,-0.491l-0.258,-0.36l-0.669,-0.514l-0.832,-0.231l-0.491,0.017l-0.459,0.12l-0.417,0.211l-0.415,0.342l-0.546,0.802l-0.033,0.067c-1.174,2.499 -0.945,4.643 0.013,6.317c0.251,0.437 0.56,0.845 0.919,1.219Zm22.984,-4.722c-0.052,-2.344 -0.566,-4.656 -1.514,-6.805c-1.232,-2.86 -3.339,-5.257 -6.018,-6.845c0.955,-0.816 2.033,-1.473 3.195,-1.949c0.434,-0.187 0.715,-0.618 0.71,-1.09l-0,-0.006c-0.005,-0.333 -0.144,-0.651 -0.386,-0.88c-1.791,-1.76 -2.553,-4.324 -2.013,-6.776c0.587,-2.864 2.878,-5.09 5.758,-5.594c0.453,-0.087 0.913,-0.131 1.375,-0.131c4.005,0 7.3,3.296 7.3,7.301c-0,1.322 -0.359,2.619 -1.038,3.753c-0.276,0.457 -0.6,0.883 -0.968,1.27c-0.052,0.055 -0.121,0.123 -0.194,0.192c-0.24,0.229 -0.375,0.547 -0.372,0.878c-0,0.468 0.28,0.894 0.71,1.079c2.908,1.201 5.229,3.498 6.462,6.392c0.756,1.728 1.184,3.578 1.264,5.458c-0.577,-0.341 -1.293,-0.373 -1.904,-0.07c-0.961,0.475 -1.861,1.117 -2.911,1.371c-0.49,-0.133 -0.983,-0.245 -1.485,-0.308c-0.253,-0.326 -0.536,-0.66 -0.84,-0.911l-0.813,-0.51l-0.752,-0.225c-0.327,-0.051 -0.662,-0.021 -0.974,0.089l-0.67,0.321l-0.569,0.448c-0.403,0.393 -0.733,0.911 -0.979,1.569c-0.202,0.54 -0.344,1.222 -0.492,2.014c-0.244,-0.027 -0.49,-0.047 -0.737,-0.058c-0.333,-0.02 -0.725,-0.006 -1.145,0.023Zm-24.215,-13.651c-2.683,1.591 -4.793,3.994 -6.024,6.861c-1.026,2.332 -1.542,4.857 -1.513,7.405l0,0.59l-11.735,0c-1.397,0 -2.547,-1.15 -2.547,-2.547l0,-1.561c-0.026,-2.165 0.409,-4.31 1.274,-6.295c1.231,-2.897 3.553,-5.197 6.46,-6.401c0.434,-0.187 0.715,-0.618 0.71,-1.09l0,-0.006c-0.005,-0.333 -0.144,-0.651 -0.386,-0.88c-1.791,-1.76 -2.553,-4.324 -2.013,-6.776c0.588,-2.864 2.879,-5.09 5.758,-5.594c0.453,-0.087 0.914,-0.131 1.375,-0.131c4.005,0 7.301,3.296 7.301,7.301c0,1.322 -0.359,2.619 -1.039,3.753c-0.275,0.457 -0.6,0.883 -0.967,1.27c-0.052,0.055 -0.122,0.123 -0.194,0.192c-0.24,0.228 -0.375,0.547 -0.372,0.878c0,0.468 0.28,0.894 0.71,1.079c1.164,0.476 2.246,1.135 3.202,1.952Zm29.027,33.111c-1.417,-0.04 -2.04,-0.037 -2.761,-1.223l-0.563,0.016c-0.654,-0.029 -0.381,-0.016 -0.818,-0.038c-0.73,-0.028 -0.613,-0.722 -0.742,-1.089c-0.205,-1.244 0.272,-2.494 0.257,-3.739c-0.005,-0.442 -0.63,-2.005 -0.854,-2.564c-0.7,0.131 -1.404,0.157 -2.114,0.192c-1.637,-0.004 -3.263,-0.205 -4.878,-0.459c-0.314,1.299 -1.249,3.118 -0.476,4.439c0.938,1.366 1.596,1.745 2.617,1.827c1.02,0.082 1.251,1.234 1.004,1.646c-0.219,0.284 -0.603,0.336 -0.929,0.405l-0.653,0.03c-0.513,-0.017 -0.973,-0.155 -1.43,-0.369c-0.765,-0.427 -1.554,-1.314 -2.141,-1.951c0.137,0.254 0.218,0.751 0.095,0.982c-0.347,0.491 -1.847,0.488 -2.534,0.183c-0.78,-0.347 -2.665,-2.781 -2.957,-4.604c0.776,-1.467 1.905,-2.744 2.477,-4.341c-1.246,-0.795 -1.913,-2.089 -1.827,-3.555l0.032,-0.17c-1.226,0.23 -0.59,0.144 -1.909,0.244c-4.2,-0.013 -7.893,-2.86 -5.813,-7.286c0.135,-0.262 0.263,-0.5 0.493,-0.386c0.184,0.091 0.157,0.457 0.065,0.863c-1.189,5.288 4.621,5.329 8.192,4.35c0.355,-0.097 1.06,-0.751 1.548,-0.968c0.798,-0.354 1.665,-0.498 2.524,-0.602c2.139,-0.244 4.709,0.883 6.015,0.92c1.306,0.037 3.164,-0.313 4.305,-0.239c0.827,0.037 1.64,0.187 2.438,0.4c0.517,-2.519 0.554,-4.374 1.779,-4.804c0.719,0.113 1.273,1.093 1.683,1.617l0.002,-0c0.835,-0.033 1.63,0.178 2.42,0.414c1.431,-0.203 2.631,-1.007 3.895,-1.632c-0.004,0.02 -0.025,0.027 -0.037,0.04c-1.244,1.005 -1.417,2.706 -1.271,4.278c0.054,0.816 -0.176,1.702 -0.461,2.538c-0.534,1.361 -1.564,2.796 -2.759,2.722c-0.452,-0.014 -0.715,-0.27 -1.051,-0.543c-0.065,0.553 -0.321,1.047 -0.568,1.536c-0.57,1.086 -2.06,1.564 -3.44,2.723c-1.379,1.159 0.442,5.297 0.883,6.052c0.442,0.754 1.674,1.03 1.196,1.71c-0.147,0.225 -0.37,0.305 -0.609,0.393l-0.325,0.042Zm-15.735,-3.096l0.206,0.06c0.258,-0.115 0.778,0.064 1.054,0.151c-0.508,-0.563 -1.273,-1.389 -1.824,-1.91c-0.181,-0.631 -0.103,-1.266 -0.065,-1.91l0.008,-0.053c-0.217,0.515 -0.493,1.016 -0.641,1.559c-0.173,0.732 0.771,1.522 1.137,1.975l0.125,0.128Z"/>
</svg>

View File

@@ -1,9 +0,0 @@
title: $:/tiddlywiki/community/icons/team
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> viewBox="0 0 64 64">
<path d="M37.439,32.592c-0.43,-0.185 -0.71,-0.611 -0.71,-1.079c-0.003,-0.331 0.132,-0.65 0.372,-0.878c0.072,-0.069 0.142,-0.137 0.194,-0.192c0.368,-0.387 0.692,-0.813 0.967,-1.271c0.68,-1.133 1.039,-2.431 1.039,-3.752c-0,-4.006 -3.296,-7.301 -7.301,-7.301c-0.462,-0 -0.922,0.043 -1.375,0.13c-2.879,0.504 -5.17,2.73 -5.758,5.594c-0.54,2.452 0.222,5.017 2.013,6.777c0.242,0.229 0.381,0.546 0.387,0.879l-0,0.006c0.004,0.472 -0.277,0.903 -0.71,1.09c-2.908,1.205 -5.229,3.505 -6.46,6.402c-0.866,1.984 -1.3,4.13 -1.274,6.295l-0,1.56c-0,1.397 1.149,2.547 2.547,2.547c-0,-0 0,-0 0,-0l21.261,-0c1.397,-0 2.547,-1.15 2.547,-2.547l-0,-1.576c0.026,-2.164 -0.409,-4.309 -1.276,-6.292c-1.233,-2.894 -3.555,-5.191 -6.463,-6.392Z" style="fill-rule:nonzero;"/>
<path d="M60.882,35.466c-1.233,-2.894 -3.554,-5.191 -6.462,-6.392c-0.43,-0.185 -0.71,-0.611 -0.71,-1.079c-0.003,-0.331 0.132,-0.649 0.372,-0.878c0.073,-0.069 0.142,-0.137 0.194,-0.192c0.368,-0.387 0.692,-0.813 0.968,-1.27c0.679,-1.134 1.038,-2.431 1.038,-3.753c0,-4.005 -3.295,-7.301 -7.3,-7.301c-0.462,0 -0.922,0.044 -1.375,0.131c-2.88,0.504 -5.171,2.73 -5.758,5.594c-0.54,2.452 0.222,5.016 2.013,6.776c0.242,0.229 0.381,0.547 0.386,0.88l-0,0.006c0.005,0.472 -0.276,0.903 -0.71,1.09c-1.162,0.476 -2.24,1.133 -3.195,1.949c2.679,1.588 4.786,3.985 6.018,6.845c1.029,2.332 1.546,4.857 1.517,7.405l-0,0.605l11.734,-0c1.397,-0 2.547,-1.15 2.547,-2.547l-0,-1.576c0.026,-2.165 -0.409,-4.31 -1.277,-6.293Z" style="fill-rule:nonzero;"/>
<path d="M23.66,31.026c-0.956,-0.817 -2.038,-1.476 -3.202,-1.952c-0.43,-0.185 -0.71,-0.611 -0.71,-1.079c-0.003,-0.331 0.132,-0.65 0.372,-0.878c0.072,-0.069 0.142,-0.137 0.194,-0.192c0.367,-0.387 0.692,-0.813 0.967,-1.27c0.68,-1.134 1.039,-2.431 1.039,-3.753c-0,-4.005 -3.296,-7.301 -7.301,-7.301c-0.461,0 -0.922,0.044 -1.375,0.131c-2.879,0.504 -5.17,2.73 -5.758,5.594c-0.54,2.452 0.222,5.016 2.013,6.776c0.242,0.229 0.381,0.547 0.386,0.88l0,0.006c0.005,0.472 -0.276,0.903 -0.71,1.09c-2.907,1.204 -5.229,3.504 -6.46,6.401c-0.865,1.985 -1.3,4.13 -1.274,6.295c0,0 0,1.561 0,1.561c0,1.397 1.15,2.547 2.547,2.547c-0,-0 11.735,-0 11.735,-0l0,-0.59c-0.029,-2.548 0.487,-5.073 1.513,-7.405c1.231,-2.867 3.341,-5.27 6.024,-6.861Z" style="fill-rule:nonzero;"/>
</svg>

View File

@@ -1,11 +0,0 @@
{
"title": "$:/core-server",
"name": "Core Server Components",
"description": "TiddlyWiki5 core server components",
"author": "JeremyRuston",
"core-version": ">=5.0.0",
"platform": "server",
"plugin-priority": "0",
"list": "readme",
"stability": "STABILITY_2_STABLE"
}

View File

@@ -1,7 +0,0 @@
title: $:/core-server/readme
This plugin contains TiddlyWiki's core components that are only needed on the server, comprising:
* Commands
* HTTP server code
* Utility functions for server

View File

@@ -1,73 +0,0 @@
/*\
title: $:/core/modules/server/routes/get-file.js
type: application/javascript
module-type: route
GET /files/:filepath
\*/
"use strict";
exports.methods = ["GET"];
exports.path = /^\/files\/(.+)$/;
exports.info = {
priority: 100
};
exports.handler = function(request,response,state) {
var path = require("path"),
fs = require("fs"),
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
baseFilename = path.resolve(state.boot.wikiPath,"files"),
filename = path.resolve(baseFilename,suppliedFilename),
extension = path.extname(filename);
// Check that the filename is inside the wiki files folder
if(path.relative(baseFilename,filename).indexOf("..") === 0) {
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
}
fs.stat(filename, function(err, stats) {
if(err) {
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
} else {
var type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream"),
responseHeaders = {
"Content-Type": type,
"Accept-Ranges": "bytes"
};
var rangeHeader = request.headers.range,
stream;
if(rangeHeader) {
// Handle range requests
var parts = rangeHeader.replace(/bytes=/, "").split("-"),
start = parseInt(parts[0], 10),
end = parts[1] ? parseInt(parts[1], 10) : stats.size - 1;
// Validate start and end
if(isNaN(start) || isNaN(end) || start < 0 || end < start || end >= stats.size) {
responseHeaders["Content-Range"] = "bytes */" + stats.size;
return response.writeHead(416, responseHeaders).end();
}
var chunksize = (end - start) + 1;
responseHeaders["Content-Range"] = "bytes " + start + "-" + end + "/" + stats.size;
responseHeaders["Content-Length"] = chunksize;
response.writeHead(206, responseHeaders);
stream = fs.createReadStream(filename, {start: start, end: end});
} else {
responseHeaders["Content-Length"] = stats.size;
response.writeHead(200, responseHeaders);
stream = fs.createReadStream(filename);
}
// Common stream error handling
stream.on("error", function(err) {
if(!response.headersSent) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.end("Read error");
} else {
response.destroy();
}
});
stream.pipe(response);
}
});
};

View File

@@ -1,30 +0,0 @@
/*\
title: $:/core-modules/modules/utils/base64.js
type: application/javascript
module-type: utils-node
Base64 UTF-8 utlity functions.
\*/
"use strict";
const{ TextEncoder, TextDecoder } = require("node:util");
exports.btoa = binstr => Buffer.from(binstr, "binary").toString("base64");
exports.atob = b64 => Buffer.from(b64, "base64").toString("binary");
function base64ToBytes(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, m => m.codePointAt(0));
};
function bytesToBase64(bytes) {
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));

View File

@@ -1,95 +0,0 @@
/*\
title: $:/core-server/modules/utils/escapecss.js
type: application/javascript
module-type: utils-node
Provides CSS.escape() functionality.
\*/
"use strict";
exports.escapeCSS = (function() {
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
/* eslint-disable */
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
return function(value) {
if (arguments.length == 0) {
throw new TypeError('`CSS.escape` requires an argument.');
}
var string = String(value);
var length = string.length;
var index = -1;
var codeUnit;
var result = '';
var firstCodeUnit = string.charCodeAt(0);
while (++index < length) {
codeUnit = string.charCodeAt(index);
// Note: theres no need to special-case astral symbols, surrogate
// pairs, or lone surrogates.
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
// (U+FFFD).
if (codeUnit == 0x0000) {
result += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
// If the character is the first character and is in the range [0-9]
// (U+0030 to U+0039), […]
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
// If the character is the second character and is in the range [0-9]
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
(
index == 1 &&
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
firstCodeUnit == 0x002D
)
) {
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
result += '\\' + codeUnit.toString(16) + ' ';
continue;
}
if (
// If the character is the first character and is a `-` (U+002D), and
// there is no second character, […]
index == 0 &&
length == 1 &&
codeUnit == 0x002D
) {
result += '\\' + string.charAt(index);
continue;
}
// If the character is not handled by one of the above rules and is
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
// U+005A), or [a-z] (U+0061 to U+007A), […]
if (
codeUnit >= 0x0080 ||
codeUnit == 0x002D ||
codeUnit == 0x005F ||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
codeUnit >= 0x0061 && codeUnit <= 0x007A
) {
// the character itself
result += string.charAt(index);
continue;
}
// Otherwise, the escaped character.
// https://drafts.csswg.org/cssom/#escape-a-character
result += '\\' + string.charAt(index);
}
return result;
};
/* eslint-enable */
})();

View File

@@ -4,5 +4,4 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
* [[diff-match-patch-es by antfu|https://github.com/antfu/diff-match-patch-es]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]

View File

@@ -3,5 +3,8 @@ name: en-GB
description: English (British)
author: JeremyRuston
core-version: >=5.0.0"
plugin-type: language
type: application/json
hidden: yes
Stub pseudo-plugin for the default language
{tidddlers:{}}

View File

@@ -6,7 +6,6 @@ Appearance/Caption: Appearance
Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
Basics/AnimDuration/Prompt: Animation duration
Basics/AutoFocus/Prompt: Default focus field for new tiddlers
Basics/AutoFocusEdit/Prompt: Default focus field for existing tiddlers
Basics/Caption: Basics
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/Prompt: Default tiddlers
@@ -132,14 +131,15 @@ Saving/GitService/Gitea/Caption: Gitea Saver
Saving/GitService/Gitea/Password: Personal access token for API (via Giteas web interface: `Settings | Applications | Generate New Token`)
Saving/TiddlySpot/Advanced/Heading: Advanced Settings
Saving/TiddlySpot/BackupDir: Backup Directory
Saving/TiddlySpot/ControlPanel: ~TiddlyHost Control Panel
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
Saving/TiddlySpot/Backups: Backups
Saving/TiddlySpot/Caption: ~TiddlyHost Saver
Saving/TiddlySpot/Description: These settings are only used when saving to [[TiddlyHost|https://tiddlyhost.com]] or a compatible remote server. See [[here|https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot]] for information on ~TiddlyHost saving configuration
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
Saving/TiddlySpot/Description: These settings are only used when saving to [[TiddlySpot|http://tiddlyspot.com]], [[TiddlyHost|https://tiddlyhost.com]], or a compatible remote server. See [[here|https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot]] for information on ~TiddlySpot and ~TiddlyHost saving configuration.
Saving/TiddlySpot/Filename: Upload Filename
Saving/TiddlySpot/Heading: ~TiddlyHost
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
Saving/TiddlySpot/Heading: ~TiddlySpot
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
Saving/TiddlySpot/Password: Password
Saving/TiddlySpot/ReadOnly: Note that [[TiddlySpot|http://tiddlyspot.com]] no longer allows the creation of new sites. For new sites, you can use [[TiddlyHost|https://tiddlyhost.com]], a new hosting service that replaces ~TiddlySpot.
Saving/TiddlySpot/ServerURL: Server URL
Saving/TiddlySpot/UploadDir: Upload Directory
Saving/TiddlySpot/UserName: Wiki Name
@@ -148,7 +148,7 @@ Settings/AutoSave/Disabled/Description: Do not save changes automatically
Settings/AutoSave/Enabled/Description: Save changes automatically
Settings/AutoSave/Hint: Attempt to automatically save changes during editing when using a supporting saver
Settings/CamelCase/Caption: Camel Case Wiki Links
Settings/CamelCase/Hint: Requires reload to take effect
Settings/CamelCase/Hint: You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect
Settings/CamelCase/Description: Enable automatic ~CamelCase linking
Settings/Caption: Settings
Settings/EditorToolbar/Caption: Editor Toolbar
@@ -190,8 +190,6 @@ Settings/DefaultSidebarTab/Caption: Default Sidebar Tab
Settings/DefaultSidebarTab/Hint: Specify which sidebar tab is displayed by default
Settings/DefaultMoreSidebarTab/Caption: Default More Sidebar Tab
Settings/DefaultMoreSidebarTab/Hint: Specify which More sidebar tab is displayed by default
Settings/DefaultTiddlerInfoTab/Caption: Default Tiddler Info Tab
Settings/DefaultTiddlerInfoTab/Hint: Specify which tab is displayed by default when tiddler info panel is opened
Settings/LinkToBehaviour/Caption: Tiddler Opening Behaviour
Settings/LinkToBehaviour/InsideRiver/Hint: Navigation from //within// the story river
Settings/LinkToBehaviour/OutsideRiver/Hint: Navigation from //outside// the story river
@@ -253,6 +251,3 @@ ViewTemplateSubtitle/Caption: View Template Subtitle
ViewTemplateSubtitle/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the subtitle of a tiddler.
ViewTemplateTags/Caption: View Template Tags
ViewTemplateTags/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the tags area of a tiddler.
WikiInformation/Caption: Wiki Information
WikiInformation/Hint: This page summarises high level information about the configuration of this ~TiddlyWiki. It is designed to enable users to quickly share relevant aspects of the configuration of their ~TiddlyWiki with others, for example when seeking help in one of the forums. No private or personal information is included, and nothing is shared without being explicitly copied and pasted elsewhere
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki

View File

@@ -1,4 +0,0 @@
title: $:/language/Draft/
Attribution: Draft of '<<draft-title>>' by {{$:/status/UserName}}
Title: Draft of '<<draft-title>>'

View File

@@ -4,12 +4,12 @@ _canonical_uri: The full URI of an external image tiddler
author: Name of the author of a plugin
bag: The name of the bag from which a tiddler came
caption: The text to be displayed on a tab or button
class: The CSS class applied to a tiddler when rendering it. Also used for Modals
class: The CSS class applied to a tiddler when rendering it - see [[Custom styles by user-class]]. Also used for [[Modals]]
code-body: The view template will display the tiddler as code if set to ''yes''
color: The CSS color value associated with a tiddler
component: The name of the component responsible for an alert tiddler
component: The name of the component responsible for an [[alert tiddler|AlertMechanism]]
core-version: For a plugin, indicates what version of TiddlyWiki with which it is compatible
current-tiddler: Used to cache the top tiddler in a history list
current-tiddler: Used to cache the top tiddler in a [[history list|HistoryMechanism]]
created: The date a tiddler was created
creator: The name of the person who created a tiddler
dependents: For a plugin, lists the dependent plugin titles

View File

@@ -1,6 +1,5 @@
title: $:/language/
Alerts: Alerts
AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:
BinaryWarning/Prompt: This tiddler contains binary data
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details.

View File

@@ -9,11 +9,6 @@ Advanced/ShadowInfo/NotShadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text
Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler
Advanced/ShadowInfo/Shadow/Source: It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>
Advanced/ShadowInfo/OverriddenShadow/Hint: It is overridden by an ordinary tiddler
Advanced/CascadeInfo/Heading: Cascade Details
Advanced/CascadeInfo/Hint: These are the view template segments (tagged <<tag "$:/tags/ViewTemplate">>) using a cascade filter and their resulting template for the current tiddler.
Advanced/CascadeInfo/Detail/View: View
Advanced/CascadeInfo/Detail/ActiveCascadeFilter: Active cascade filter
Advanced/CascadeInfo/Detail/Template: Template
Fields/Caption: Fields
List/Caption: List
List/Empty: This tiddler does not have a list

View File

@@ -1,106 +0,0 @@
/*\
title: $:/core/modules/background-actions.js
type: application/javascript
module-type: global
\*/
"use strict";
class BackgroundActionDispatcher {
constructor(filterTracker, wiki) {
this.filterTracker = filterTracker;
this.wiki = wiki;
this.nextTrackedFilterId = 1;
this.trackedFilters = new Map(); // Use Map for better key management
this.filterTracker.track({
filterString: "[all[tiddlers+shadows]tag[$:/tags/BackgroundAction]!is[draft]]",
fnEnter: title => this.trackFilter(title),
fnLeave: (title, enterValue) => this.untrackFilter(enterValue),
fnChange: (title, enterValue) => {
this.untrackFilter(enterValue);
return this.trackFilter(title);
},
fnProcess: changes => this.process(changes)
});
}
trackFilter(title) {
const tiddler = this.wiki.getTiddler(title);
const id = this.nextTrackedFilterId++;
const tracker = new BackgroundActionTracker({
wiki: this.wiki,
title,
trackFilter: tiddler.fields["track-filter"],
actions: tiddler.fields.text
});
this.trackedFilters.set(id, tracker);
return id;
}
untrackFilter(enterValue) {
const tracker = this.trackedFilters.get(enterValue);
if(tracker) {
tracker.destroy();
}
this.trackedFilters.delete(enterValue);
}
process(changes) {
for(const tracker of this.trackedFilters.values()) {
tracker.process(changes);
}
}
}
class BackgroundActionTracker {
constructor({wiki, title, trackFilter, actions}) {
this.wiki = wiki;
this.title = title;
this.trackFilter = trackFilter;
this.actions = actions;
this.filterTracker = new $tw.FilterTracker(this.wiki);
this.hasChanged = false;
this.trackerID = this.filterTracker.track({
filterString: this.trackFilter,
fnEnter: () => { this.hasChanged = true; },
fnLeave: () => { this.hasChanged = true; },
fnProcess: changes => {
if(this.hasChanged) {
this.hasChanged = false;
console.log("Processing background action", this.title);
const tiddler = this.wiki.getTiddler(this.title);
let doActions = true;
if(tiddler && tiddler.fields.platforms) {
doActions = false;
const platforms = $tw.utils.parseStringArray(tiddler.fields.platforms);
if(($tw.browser && platforms.includes("browser")) || ($tw.node && platforms.includes("node"))) {
doActions = true;
}
}
if(doActions) {
this.wiki.invokeActionString(
this.actions,
null,
{
currentTiddler: this.title
},{
parentWidget: $tw.rootWidget
}
);
}
}
}
});
}
process(changes) {
this.filterTracker.handleChangeEvent(changes);
}
destroy() {
this.filterTracker.untrack(this.trackerID);
}
}
exports.BackgroundActionDispatcher = BackgroundActionDispatcher;

View File

@@ -99,18 +99,16 @@ Commander.prototype.executeNextCommand = function() {
}
}
if(command.info.synchronous) {
// Synchronous command (await thenables)
// Synchronous command
c = new command.Command(params,this);
err = c.execute();
if(err && typeof err.then === "function") {
err.then(e => { e ? this.callback(e) : this.executeNextCommand(); });
} else if(err) {
if(err) {
this.callback(err);
} else {
this.executeNextCommand();
}
} else {
// Asynchronous command (await thenables)
// Asynchronous command
c = new command.Command(params,this,function(err) {
if(err) {
self.callback(err);
@@ -119,9 +117,7 @@ Commander.prototype.executeNextCommand = function() {
}
});
err = c.execute();
if(err && typeof err.then === "function") {
err.then(e => { if(e) this.callback(e); });
} else if(err) {
if(err) {
this.callback(err);
}
}

View File

@@ -76,7 +76,6 @@ WikiFolderMaker.prototype.tiddlersToIgnore = [
"$:/boot/boot.js",
"$:/boot/bootprefix.js",
"$:/core",
"$:/core-server",
"$:/library/sjcl.js",
"$:/temp/info-plugin"
];

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/config.js
type: application/javascript
module-type: config
Core configuration constants
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/deserializers.js
type: application/javascript
module-type: tiddlerdeserializer
Functions to deserialise tiddlers from a block of text
\*/
"use strict";
@@ -34,6 +37,12 @@ exports["application/json"] = function(text,fields) {
return results;
};
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
var results = [];
// Check if we've got an old-style store area
@@ -51,11 +60,11 @@ exports["text/html"] = function(text,fields) {
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
}
// Return if we had either an old-style or a new-style store area
if(storeAreaMatch || haveHadNewStoreArea) {
return results;
}
// Otherwise, check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
@@ -115,18 +124,30 @@ function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
return results;
}
var deserializeTiddlerDiv = function(text) {
/*
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
<pre>The text of the tiddler (without the expected HTML encoding).
</pre>
</div>
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
*/
var deserializeTiddlerDiv = function(text /* [,fields] */) {
// Slot together the default results
var result = {};
if(arguments.length > 1) {
for(var f=1; f<arguments.length; f++) {
var fields = arguments[f];
for(var t in fields) {
result[t] = fields[t];
result[t] = fields[t];
}
}
}
// Parse the DIV body
var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi,
endRegExp,
match = startRegExp.exec(text);

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/engines/framed.js
type: application/javascript
module-type: library
Text editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea
\*/
"use strict";
@@ -31,7 +34,7 @@ function FramedEngine(options) {
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
this.iframeDoc.open();
this.iframeDoc.write("<!DOCTYPE html><html><head><meta name='color-scheme' content='" + colorScheme + "'></head><body></body></html>");
this.iframeDoc.write("<meta name='color-scheme' content='" + colorScheme + "'>");
this.iframeDoc.close();
// Style the iframe
this.iframeNode.className = this.dummyTextArea.className;
@@ -53,7 +56,7 @@ function FramedEngine(options) {
} else {
this.domNode.value = this.value;
}
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") {
this.domNode.setAttribute("type",this.widget.editType);
}
@@ -75,7 +78,7 @@ function FramedEngine(options) {
if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true);
}
// Copy the styles from the dummy textarea
this.copyStyles();
// Add event listeners
$tw.utils.addEventListeners(this.domNode,[
@@ -96,10 +99,13 @@ function FramedEngine(options) {
{name: "click",handlerObject: this.widget,handlerMethod: "handleClickEvent"}
]);
}
// Insert the element into the DOM
this.iframeDoc.body.appendChild(this.domNode);
}
/*
Copy styles from the dummy text area to the textarea in the iframe
*/
FramedEngine.prototype.copyStyles = function() {
// Copy all styles
$tw.utils.copyStyles(this.dummyTextArea,this.domNode);
@@ -121,11 +127,14 @@ FramedEngine.prototype.setText = function(text,type) {
if(this.domNode.ownerDocument.activeElement !== this.domNode) {
this.updateDomNodeText(text);
}
// Fix the height if needed
this.fixHeight();
}
};
/*
Update the DomNode with the new text
*/
FramedEngine.prototype.updateDomNodeText = function(text) {
try {
this.domNode.value = text;
@@ -134,15 +143,21 @@ FramedEngine.prototype.updateDomNodeText = function(text) {
}
};
/*
Get the text of the engine
*/
FramedEngine.prototype.getText = function() {
return this.domNode.value;
};
/*
Fix the height of textarea to fit content
*/
FramedEngine.prototype.fixHeight = function() {
// Make sure styles are updated
this.copyStyles();
// If .editRows is initialised, it takes precedence
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
// Adjust height
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
@@ -157,6 +172,9 @@ FramedEngine.prototype.fixHeight = function() {
}
};
/*
Focus the engine node
*/
FramedEngine.prototype.focus = function() {
if(this.domNode.focus) {
this.domNode.focus();
@@ -166,12 +184,18 @@ FramedEngine.prototype.focus = function() {
}
};
/*
Handle a focus event
*/
FramedEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) {
$tw.popup.cancel(0);
}
};
/*
Handle a keydown event
*/
FramedEngine.prototype.handleKeydownEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
@@ -180,11 +204,17 @@ FramedEngine.prototype.handleKeydownEvent = function(event) {
return this.widget.handleKeydownEvent(event);
};
/*
Handle a click
*/
FramedEngine.prototype.handleClickEvent = function(event) {
this.fixHeight();
return true;
};
/*
Handle a dom "input" event which occurs when the text has changed
*/
FramedEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
@@ -194,6 +224,9 @@ FramedEngine.prototype.handleInputEvent = function(event) {
return true;
};
/*
Create a blank structure representing a text operation
*/
FramedEngine.prototype.createTextOperation = function() {
var operation = {
text: this.domNode.value,
@@ -209,6 +242,9 @@ FramedEngine.prototype.createTextOperation = function() {
return operation;
};
/*
Execute a text operation
*/
FramedEngine.prototype.executeTextOperation = function(operation) {
// Perform the required changes to the text area and the underlying tiddler
var newText = operation.text;

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/engines/simple.js
type: application/javascript
module-type: library
Text editor engine based on a simple input or textarea tag
\*/
"use strict";
@@ -27,7 +30,7 @@ function SimpleEngine(options) {
} else {
this.domNode.value = this.value;
}
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") {
this.domNode.setAttribute("type",this.widget.editType);
}
@@ -52,7 +55,7 @@ function SimpleEngine(options) {
if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true);
}
// Add an input event handler
$tw.utils.addEventListeners(this.domNode,[
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
{name: "input", handlerObject: this, handlerMethod: "handleInputEvent"}
@@ -62,16 +65,22 @@ function SimpleEngine(options) {
this.widget.domNodes.push(this.domNode);
}
/*
Set the text of the engine if it doesn't currently have focus
*/
SimpleEngine.prototype.setText = function(text,type) {
if(!this.domNode.isTiddlyWikiFakeDom) {
if(this.domNode.ownerDocument.activeElement !== this.domNode || text === "") {
this.updateDomNodeText(text);
}
// Fix the height if needed
this.fixHeight();
}
};
/*
Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
try {
this.domNode.value = text;
@@ -80,13 +89,18 @@ SimpleEngine.prototype.updateDomNodeText = function(text) {
}
};
/*
Get the text of the engine
*/
SimpleEngine.prototype.getText = function() {
return this.domNode.value;
};
/*
Fix the height of textarea to fit content
*/
SimpleEngine.prototype.fixHeight = function() {
// If .editRows is initialised, it takes precedence
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
@@ -99,6 +113,9 @@ SimpleEngine.prototype.fixHeight = function() {
}
};
/*
Focus the engine node
*/
SimpleEngine.prototype.focus = function() {
if(this.domNode.focus) {
this.domNode.focus();
@@ -108,6 +125,9 @@ SimpleEngine.prototype.focus = function() {
}
};
/*
Handle a dom "input" event which occurs when the text has changed
*/
SimpleEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
@@ -117,6 +137,9 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
return true;
};
/*
Handle a dom "focus" event
*/
SimpleEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) {
$tw.popup.cancel(0);
@@ -132,10 +155,16 @@ SimpleEngine.prototype.handleFocusEvent = function(event) {
return true;
};
/*
Create a blank structure representing a text operation
*/
SimpleEngine.prototype.createTextOperation = function() {
return null;
};
/*
Execute a text operation
*/
SimpleEngine.prototype.executeTextOperation = function(operation) {
};

View File

@@ -2,12 +2,16 @@
title: $:/core/modules/editor/factory.js
type: application/javascript
module-type: library
Factory for constructing text editor widgets with specified engines for the toolbar and non-toolbar cases
\*/
"use strict";
var DEFAULT_MIN_TEXT_AREA_HEIGHT = "100px"; // Minimum height of textareas in pixels
// Configuration tiddlers
var HEIGHT_MODE_TITLE = "$:/config/TextEditor/EditorHeight/Mode";
var ENABLE_TOOLBAR_TITLE = "$:/config/TextEditor/EnableToolbar";
@@ -44,8 +48,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.toolbarNode = this.document.createElement("div");
this.toolbarNode.className = "tc-editor-toolbar";
parent.insertBefore(this.toolbarNode,nextSibling);
this.domNodes.push(this.toolbarNode);
this.renderChildren(this.toolbarNode,null);
this.domNodes.push(this.toolbarNode);
}
// Create our element
var editInfo = this.getEditInfo(),
@@ -64,7 +68,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
// Fix height
this.engine.fixHeight();
// Focus if required
if($tw.browser && (this.editFocus === "true" || this.editFocus === "yes") && !$tw.utils.hasClass(this.parentDomNode.ownerDocument.activeElement,"tc-keep-focus")) {
if(this.editFocus === "true" || this.editFocus === "yes") {
this.engine.focus();
}
// Add widget message listeners
@@ -137,6 +141,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
return {value: value || "", type: type, update: update};
};
/*
Handle an edit text operation message from the toolbar
*/
EditTextWidget.prototype.handleEditTextOperationMessage = function(event) {
// Prepare information about the operation
var operation = this.engine.createTextOperation();
@@ -145,13 +152,16 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
if(handler) {
handler.call(this,event,operation);
}
// Execute the operation via the engine
var newText = this.engine.executeTextOperation(operation);
// Fix the tiddler height and save changes
this.engine.fixHeight();
this.saveChanges(newText);
};
/*
Compute the internal state of the widget
*/
EditTextWidget.prototype.execute = function() {
// Get our parameters
this.editTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
@@ -191,7 +201,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
type = type || "text";
}
// Get the rest of our parameters
this.editTag = this.getAttribute("tag",tag) || "input";
this.editType = this.getAttribute("type",type);
// Make the child widgets
@@ -201,6 +211,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
@@ -221,14 +234,24 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
};
/*
Update the editor with new text. This method is separate from updateEditorDomNode()
so that subclasses can override updateEditor() and still use updateEditorDomNode()
*/
EditTextWidget.prototype.updateEditor = function(text,type) {
this.updateEditorDomNode(text,type);
};
/*
Update the editor dom node with new text
*/
EditTextWidget.prototype.updateEditorDomNode = function(text,type) {
this.engine.setText(text,type);
};
/*
Save changes back to the tiddler store
*/
EditTextWidget.prototype.saveChanges = function(text) {
var editInfo = this.getEditInfo();
if(text !== editInfo.value) {
@@ -236,6 +259,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
};
/*
Handle a dom "keydown" event, which we'll bubble up to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.handleKeydownEvent = function(event) {
// Check for a keyboard shortcut
if(this.toolbarNode) {
@@ -256,17 +282,20 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
}
}
// Propogate the event to the container
if(this.propogateKeydownEvent(event)) {
// Ignore the keydown if it was already handled
event.preventDefault();
event.stopPropagation();
return true;
}
// Otherwise, process the keydown normally
return false;
};
/*
Propogate keydown events to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent);
@@ -289,12 +318,16 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
return dispatchNode.dispatchEvent(newEvent);
};
/*
Propogate drag and drop events with File data to our container for the dropzone widgets benefit.
If there are no Files, let the browser handle it.
*/
EditTextWidget.prototype.handleDropEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
}
};
EditTextWidget.prototype.handlePasteEvent = function(event) {

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/bitmap/clear.js
type: application/javascript
module-type: bitmapeditoroperation
Bitmap editor operation to clear the image
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/bitmap/resize.js
type: application/javascript
module-type: bitmapeditoroperation
Bitmap editor operation to resize the image
\*/
"use strict";
@@ -14,7 +17,7 @@ exports["resize"] = function(event) {
if(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) {
this.changeCanvasSize(newWidth,newHeight);
}
// Update the input controls
this.refreshToolbar();
// Save the image into the tiddler
this.saveChanges();

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/bitmap/rotate-left.js
type: application/javascript
module-type: bitmapeditoroperation
Bitmap editor operation to rotate the image left by 90 degrees
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/text/excise.js
type: application/javascript
module-type: texteditoroperation
Text editor operation to excise the selection to a new tiddler
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/text/insert-text.js
type: application/javascript
module-type: texteditoroperation
Text editor operation insert text at the caret position. If there is a selection it is replaced.
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/text/make-link.js
type: application/javascript
module-type: texteditoroperation
Text editor operation to make a link
\*/
"use strict";

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/text/prefix-lines.js
type: application/javascript
module-type: texteditoroperation
Text editor operation to add a prefix to the selected lines
\*/
"use strict";
@@ -23,16 +26,16 @@ exports["prefix-lines"] = function(event,operation) {
line = line.substring(event.paramObject.character.length);
count++;
}
// Remove any whitespace
while(line.charAt(0) === " ") {
line = line.substring(1);
}
// We're done if we removed the exact required prefix, otherwise add it
if(count !== targetCount) {
// Apply the prefix
line = prefix + " " + line;
}
// Save the modified line
lines[index] = line;
});
// Stitch the replacement text together and set the selection

View File

@@ -2,6 +2,9 @@
title: $:/core/modules/editor/operations/text/replace-all.js
type: application/javascript
module-type: texteditoroperation
Text editor operation to replace the entire text
\*/
"use strict";

Some files were not shown because too many files have changed in this diff Show More