1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-23 19:34:39 +00:00

Compare commits

..

17 Commits

Author SHA1 Message Date
jeremy@jermolene.com
bbdf9bae89 Merge branch 'master' into publishing-framework 2021-07-14 15:48:54 +01:00
jeremy@jermolene.com
f1d76a1eee Merge branch 'master' into publishing-framework 2021-06-01 13:17:47 +01:00
jeremy@jermolene.com
160c154ef1 Merge branch 'master' into publishing-framework 2021-05-20 13:53:29 +01:00
jeremy@jermolene.com
184083ad1a Use variable definition in the job/sitemap/route text instead of from var-* fields 2021-04-10 17:42:35 +01:00
jeremy@jermolene.com
9c62bd8030 Fix typo in link widget 2021-04-10 17:41:41 +01:00
jeremy@jermolene.com
b7419dec3a Finish refactoring of server <-> sitemap interface
Continuing c4cdb1ed8c
2021-04-10 13:51:07 +01:00
jeremy@jermolene.com
02d390a673 Add support for slugify to the link widget's tv-wikilink-template handling 2021-04-10 10:58:55 +01:00
jeremy@jermolene.com
c4cdb1ed8c Refactor sitemap route handling
To avoid duplicating the rendering code
2021-04-10 10:58:26 +01:00
jeremy@jermolene.com
5fcff1f1a3 Refactor server route handling to handle default documents properly 2021-04-10 10:57:52 +01:00
jeremy@jermolene.com
a8770d7645 Revert changes to image widget 2021-04-08 14:27:30 +01:00
jeremy@jermolene.com
df2a3fdefd Refactor sitemap handling so we can reuse it in the webserver 2021-04-07 12:16:12 +01:00
jeremy@jermolene.com
a8c248eb3d Revert to using parameterised paths instead of filters
Because we will be able to run parameterised paths in reverse for HTTP serving, which we can't do with filters
2021-04-06 12:19:49 +01:00
jeremy@jermolene.com
96103d5d4c Link to the PR 2021-04-05 17:09:43 +01:00
jeremy@jermolene.com
a025bce21f Clean up before publishing a snapshot to TiddlyHost 2021-04-05 17:07:19 +01:00
jeremy@jermolene.com
45cdd7bdf7 Merge branch 'master' into publishing-framework 2021-04-05 12:31:46 +01:00
jeremy@jermolene.com
509356c696 Add Node.js support, refactor modelling of jobs and sitemaps, and use modals framework 2021-04-04 13:18:41 +01:00
jeremy@jermolene.com
42e10d030a First commit 2021-03-22 09:34:32 +00:00
5108 changed files with 57381 additions and 113592 deletions

15
.eslintignore Normal file
View File

@@ -0,0 +1,15 @@
# Known minified files
/boot/sjcl.js
/core/modules/utils/base64-utf8/base64-utf8.module.min.js
/core/modules/utils/diff-match-patch/diff_match_patch.js
/plugins/tiddlywiki/async/files/async.min.v1.5.0.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/anyword-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/css-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/html-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/javascript-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/show-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/xml-hint.js
/plugins/tiddlywiki/codemirror-closebrackets/files/addon/edit/closebrackets.js
/plugins/tiddlywiki/codemirror-closebrackets/files/addon/edit/matchbrackets.js
/plugins/tiddlywiki/codemirror-closetag/files/addon/edit/closetag.js
/plugins/tiddlywiki/codemirror-closetag/files/addon/fold/xml-fold.js

267
.eslintrc.yml Normal file
View File

@@ -0,0 +1,267 @@
env:
browser: true
commonjs: true
es2021: true
node: true
extends: 'eslint:recommended'
globals:
"$tw": "writable" # temporary
parserOptions:
ecmaVersion: 5
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: 'off'
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: 'off'
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: 'off'
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'
# temporary rules
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"

43
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,43 @@
---
name: Bug report
about: Create a report to help us improve TiddlyWiki 5
title: "[BUG]"
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**TiddlyWiki Configuration (please complete the following information):**
- 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]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,67 +0,0 @@
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

@@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Discuss feature request
url: https://github.com/TiddlyWiki/TiddlyWiki5/discussions
about: Open new discussion about new feature
- name: Talk.Tiddlywiki Forum
url: https://talk.tiddlywiki.org
about: Join the Forum

View File

@@ -20,11 +20,3 @@ A clear and concise description of any alternative solutions or features you've
Add any other context or screenshots about the feature request here.
If you link to discussions elsewhere then please copy and paste the important text, and don't expect readers to scan the entire discussion to find the relevant part.
## Checklist before requesting a review
- [ ] Illustrate any visual changes (however minor) with before/after screenshots
- [ ] Self-review of code
- [ ] Documentation updates (for user-visible changes)
- [ ] Tests (for core code changes)
- [ ] Complies with coding style guidelines (for JavaScript code)

View File

@@ -5,22 +5,16 @@ on:
- master
- tiddlywiki-com
env:
NODE_VERSION: "22"
NODE_VERSION: "12"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-test.sh"
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- run: "./bin/test.sh"
build-prerelease:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
@@ -30,8 +24,8 @@ jobs:
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
TW5_BUILD_OUTPUT: "./output/prerelease"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
@@ -60,10 +54,9 @@ jobs:
TW5_BUILD_TIDDLYWIKI: "./node_modules/tiddlywiki/tiddlywiki.js"
TW5_BUILD_MAIN_EDITION: "./editions/tw5.com"
TW5_BUILD_OUTPUT: "./output"
TW5_BUILD_ARCHIVE: "./output"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
@@ -79,6 +72,3 @@ jobs:
- run: "./bin/ci-push.sh"
env:
GH_TOKEN: ${{ secrets.GITHUBPUSHTOKEN }}
- run: "./bin/build-tw-org.sh"
env:
GH_TOKEN: ${{ secrets.GITHUBPUSHTOKEN }}

View File

@@ -1,30 +0,0 @@
name: Check CLA Signature
on:
pull_request_target:
types:
- opened
- reopened
paths-ignore:
- 'licenses/cla-individual.md'
jobs:
check_cla:
runs-on: ubuntu-latest
permissions:
pull-requests: write
if: ${{ (github.event.pull_request.user.login != github.repository_owner) }}
steps:
- run: |
if ! curl -s https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/tiddlywiki-com/licenses/cla-individual.md | grep -io "@$USER,"; then
echo "CLA not signed"
gh pr comment "$NUMBER" -b "@$USER It appears that this is your first contribution to the project, welcome.
With apologies for the bureaucracy, please could you prepare a separate PR to the 'tiddlywiki-com' branch with your signature for the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))."
else
echo "CLA already signed"
gh pr comment "$NUMBER" -b "Confirmed: **$USER** has already signed the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
USER: ${{ github.actor }}

View File

@@ -1,70 +0,0 @@
name: CLA Signed
on:
pull_request_target:
types:
- opened
- closed
paths:
- 'licenses/cla-individual.md'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
AUTHOR: ${{ github.event.pull_request.user.login }}
jobs:
# check if PRs updating the CLA are targetting the tiddlywiki-com branch
check-signature-branch:
if: (github.event.pull_request.merged != true) && (github.event.pull_request.user.login != github.repository_owner)
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- run: |
if [[ "$BRANCH" != "tiddlywiki-com" ]]; then
echo "This CLA signature targets the wrong branch: $BRANCH"
gh pr comment "$NUMBER" -b "@$AUTHOR Signatures to the CLA must target the 'tiddlywiki-com' branch."
fi
env:
BRANCH: ${{ github.event.pull_request.base.ref }}
# leave a comment on each open PR by a given author when their signature is added to the CLA
cla-signed:
if: (github.event.pull_request.merged == true) && (github.event.pull_request.user.login != github.repository_owner)
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: List open PRs by user
id: list-prs
uses: actions/github-script@v6
with:
result-encoding: string
script: |
const owner = context.repo.owner,
repo = context.repo.repo,
author = context.payload.pull_request.user.login;
const { data: pullRequests } = await github.rest.pulls.list({
owner: owner,
repo: repo,
state: 'open',
sort: 'created',
direction: 'desc',
per_page: 100
});
const userPullRequests = pullRequests.filter(pr => pr.user.login === author),
prNumbers = userPullRequests.map(pr => pr.number).join(',');
console.log(`Open pull requests by ${author}:${prNumbers}`);
return prNumbers;
- name: Comment open PRs by the same author
run: |
prs=($(echo ${{ steps.list-prs.outputs.result }} | tr "," "\n"))
for number in "${prs[@]}"
do
gh pr comment "$number" -b "**$AUTHOR** has signed the Contributor License Agreement (see [contributing.md](https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/contributing.md))"
done

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@v4
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@v4
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,18 +0,0 @@
name: Validate PR Paths
on:
pull_request_target:
types: [opened, reopened, synchronize]
jobs:
validate-pr:
runs-on: ubuntu-latest
steps:
- name: Validate PR
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.base_ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}

6
.gitignore vendored
View File

@@ -1,11 +1,5 @@
.DS_Store
.c9/
.vs/
.vscode/
tmp/
output/
node_modules/
/test-results/
/playwright-report/
/playwright/.cache/
$__StoryList.tid

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.2.0
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)
@@ -82,57 +84,40 @@ echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n"
######################################################
#
# Core distributions
# Core distribution
#
######################################################
# Conditionally build archive if $TW5_BUILD_ARCHIVE variable is set, otherwise do nothing
#
# /archive/Empty-TiddlyWiki-<version>.html Empty archived version
# /archive/TiddlyWiki-<version>.html Full archived version
if [ -n "$TW5_BUILD_ARCHIVE" ]; then
node $TW5_BUILD_TIDDLYWIKI \
$TW5_BUILD_MAIN_EDITION \
--version \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_ARCHIVE \
--build archive \
|| exit 1
fi
# /index.html Main site
# /external-(version).html External core version of main site
# /favicon.ico Favicon for main site
# /static.html Static rendering of default tiddlers
# /alltiddlers.html Static rendering of all tiddlers
# /static/* Static single tiddlers
# /static/static.css Static stylesheet
# /static/favicon.ico Favicon for static pages
node $TW5_BUILD_TIDDLYWIKI \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--version \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build favicon static index external-js \
--build favicon static index \
|| exit 1
# /empty.html Empty
# /empty.hta For Internet Explorer
# /empty-external-core.html External core empty
# /tiddlywikicore-<version>.js Core plugin javascript
# /empty.html Empty
# /empty.hta For Internet Explorer
node $TW5_BUILD_TIDDLYWIKI \
./editions/empty \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--output $TW5_BUILD_OUTPUT \
--build empty emptyexternalcore \
--build empty \
|| exit 1
# /test.html Test edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/test \
--verbose \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all test.html text/plain \
|| exit 1
@@ -145,28 +130,16 @@ node $TW5_BUILD_TIDDLYWIKI \
# /dev/static/static.css Static stylesheet
node $TW5_BUILD_TIDDLYWIKI \
./editions/dev \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/dev \
--build index favicon static \
|| exit 1
# /tour.html tour edition
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 \
|| exit 1
# /share.html Custom edition for sharing via the URL
node $TW5_BUILD_TIDDLYWIKI \
./editions/share \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build share \
@@ -175,6 +148,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /upgrade.html Custom edition for performing upgrades
node $TW5_BUILD_TIDDLYWIKI \
./editions/upgrade \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build upgrade \
@@ -183,6 +157,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /encrypted.html Copy of the main file encrypted with the password "password"
node $TW5_BUILD_TIDDLYWIKI \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build encrypted \
@@ -198,14 +173,16 @@ node $TW5_BUILD_TIDDLYWIKI \
# /editions/xlsx-utils/index.html xlsx-utils edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/xlsx-utils \
--verbose \
--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
node $TW5_BUILD_TIDDLYWIKI \
./editions/resumebuilder \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/resumebuilder/ \
--build index \
@@ -214,14 +191,16 @@ node $TW5_BUILD_TIDDLYWIKI \
# /editions/text-slicer/index.html Text slicer edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/text-slicer \
--verbose \
--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
node $TW5_BUILD_TIDDLYWIKI \
./editions/translators \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/translators/ \
--build index \
@@ -230,6 +209,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /editions/introduction/index.html Introduction edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/introduction \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/introduction/ \
--build index \
@@ -238,6 +218,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /editions/full/index.html Full edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/full \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/full/ \
--build index \
@@ -246,16 +227,9 @@ node $TW5_BUILD_TIDDLYWIKI \
# /editions/tw5.com-docs/index.html tiddlywiki.com docs edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/tw5.com-docs \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/tw5.com-docs/ \
--build external \
|| exit 1
# /editions/twitter-archivist/index.html Twitter Archivist edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/twitter-archivist \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/twitter-archivist/ \
--build index \
|| exit 1
@@ -269,9 +243,10 @@ node $TW5_BUILD_TIDDLYWIKI \
node $TW5_BUILD_TIDDLYWIKI \
./editions/innerwikidemo \
--verbose \
--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
@@ -279,9 +254,10 @@ node $TW5_BUILD_TIDDLYWIKI \
node $TW5_BUILD_TIDDLYWIKI \
./editions/dynaviewdemo \
--verbose \
--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
@@ -293,19 +269,43 @@ node $TW5_BUILD_TIDDLYWIKI \
node $TW5_BUILD_TIDDLYWIKI \
./editions/katexdemo \
--verbose \
--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 \
--verbose \
--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 \
--verbose \
--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 \
--verbose \
--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
@@ -313,9 +313,10 @@ node $TW5_BUILD_TIDDLYWIKI \
# /plugins/tiddlywiki/markdown/empty.html Empty wiki with Markdown plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/markdowndemo \
--verbose \
--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
@@ -323,9 +324,10 @@ node $TW5_BUILD_TIDDLYWIKI \
# /plugins/tiddlywiki/tw2parser/empty.html Empty wiki with tw2parser plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/classicparserdemo \
--verbose \
--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
@@ -333,22 +335,13 @@ node $TW5_BUILD_TIDDLYWIKI \
# /plugins/tiddlywiki/highlight/empty.html Empty wiki with highlight plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/highlightdemo \
--verbose \
--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
# /plugins/tiddlywiki/geospatial/index.html Demo wiki with geospatial plugin
# /plugins/tiddlywiki/geospatial/empty.html Empty wiki with geospatial plugin
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/empty plugins/tiddlywiki/geospatial/empty.html text/plain \
|| exit 1
######################################################
#
# Language editions
@@ -357,19 +350,20 @@ node $TW5_BUILD_TIDDLYWIKI \
# Delete any existing static content
rm -rf $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
rm $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
# /languages/de-AT/index.html Demo wiki with de-AT language
# /languages/de-AT/empty.html Empty wiki with de-AT language
node $TW5_BUILD_TIDDLYWIKI \
./editions/de-AT \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/de-AT \
--build favicon empty static index \
@@ -379,6 +373,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/de-DE/empty.html Empty wiki with de-DE language
node $TW5_BUILD_TIDDLYWIKI \
./editions/de-DE \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/de-DE \
--build favicon empty static index \
@@ -388,6 +383,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/es-ES/empty.html Empty wiki with es-ES language
node $TW5_BUILD_TIDDLYWIKI \
./editions/es-ES \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/es-ES \
--build favicon empty static index \
@@ -397,6 +393,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/fr-FR/empty.html Empty wiki with fr-FR language
node $TW5_BUILD_TIDDLYWIKI \
./editions/fr-FR \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/fr-FR \
--build favicon empty static index \
@@ -406,6 +403,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/ja-JP/empty.html Empty wiki with ja-JP language
node $TW5_BUILD_TIDDLYWIKI \
./editions/ja-JP \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/ja-JP \
--build empty index \
@@ -415,6 +413,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/ko-KR/empty.html Empty wiki with ko-KR language
node $TW5_BUILD_TIDDLYWIKI \
./editions/ko-KR \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/ko-KR \
--build favicon empty static index \
@@ -424,6 +423,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/zh-Hans/empty.html Empty wiki with zh-Hans language
node $TW5_BUILD_TIDDLYWIKI \
./editions/zh-Hans \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/zh-Hans \
--build empty index \
@@ -433,6 +433,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /languages/zh-Hant/empty.html Empty wiki with zh-Hant language
node $TW5_BUILD_TIDDLYWIKI \
./editions/zh-Hant \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/zh-Hant \
--build empty index \
@@ -446,9 +447,10 @@ node $TW5_BUILD_TIDDLYWIKI \
node $TW5_BUILD_TIDDLYWIKI \
./editions/pluginlibrary \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
--build library\
--build \
|| exit 1
# Delete the temporary build tiddler

View File

@@ -1,97 +0,0 @@
#!/bin/bash
# Build tiddlywiki.org assets.
# Default to the version of TiddlyWiki installed in this repo
if [ -z "$TWORG_BUILD_TIDDLYWIKI" ]; then
TWORG_BUILD_TIDDLYWIKI=./tiddlywiki.js
fi
echo "Using TWORG_BUILD_TIDDLYWIKI as [$TWORG_BUILD_TIDDLYWIKI]"
# Set up the build details
if [ -z "$TWORG_BUILD_DETAILS" ]; then
TWORG_BUILD_DETAILS="$(git symbolic-ref --short HEAD)-$(git rev-parse HEAD) from $(git remote get-url origin)"
fi
echo "Using TWORG_BUILD_DETAILS as [$TWORG_BUILD_DETAILS]"
if [ -z "$TWORG_BUILD_COMMIT" ]; then
TWORG_BUILD_COMMIT="$(git rev-parse HEAD)"
fi
echo "Using TWORG_BUILD_COMMIT as [$TWORG_BUILD_COMMIT]"
# Set up the build output directory
if [ -z "$TWORG_BUILD_OUTPUT" ]; then
TWORG_BUILD_OUTPUT=$(mktemp -d)
fi
mkdir -p $TWORG_BUILD_OUTPUT
if [ ! -d "$TWORG_BUILD_OUTPUT" ]; then
echo 'A valid TWORG_BUILD_OUTPUT environment variable must be set'
exit 1
fi
echo "Using TWORG_BUILD_OUTPUT as [$TWORG_BUILD_OUTPUT]"
# Pull existing GitHub pages content
git clone --depth=1 --branch=main "https://github.com/TiddlyWiki/tiddlywiki.org-gh-pages.git" $TWORG_BUILD_OUTPUT
# Make the CNAME file that GitHub Pages requires
echo "tiddlywiki.org" > $TWORG_BUILD_OUTPUT/CNAME
# Delete any existing static content
mkdir -p $TWORG_BUILD_OUTPUT/static
rm $TWORG_BUILD_OUTPUT/static/*
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
echo -e -n "title: $:/build\ncommit: $TWORG_BUILD_COMMIT\n\n$TWORG_BUILD_DETAILS\n" > $TWORG_BUILD_OUTPUT/build.tid
######################################################
#
# tiddlywiki.org distribution
#
######################################################
# /index.html Main site
# /favicon.ico Favicon for main site
# /static.html Static rendering of default tiddlers
# /alltiddlers.html Static rendering of all tiddlers
# /static/* Static single tiddlers
# /static/static.css Static stylesheet
# /static/favicon.ico Favicon for static pages
node $TWORG_BUILD_TIDDLYWIKI \
editions/tw.org \
--verbose \
--version \
--load $TWORG_BUILD_OUTPUT/build.tid \
--output $TWORG_BUILD_OUTPUT \
--build favicon static index \
|| exit 1
# Delete the temporary build tiddler
rm $TWORG_BUILD_OUTPUT/build.tid || exit 1
# Push output back to GitHub
# Exit script immediately if any command fails
set -e
pushd $TWORG_BUILD_OUTPUT
git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
git add -A .
git commit --message "GitHub build: $GITHUB_RUN_NUMBER of $TW5_BUILD_BRANCH ($(date +'%F %T %Z'))"
git remote add deploy "https://$GH_TOKEN@github.com/TiddlyWiki/tiddlywiki.org-gh-pages.git" &>/dev/null
git push deploy main &>/dev/null
popd

View File

@@ -7,4 +7,4 @@ npm --force install tiddlywiki || exit 1
# Pull existing GitHub pages content
git clone --depth=1 --branch=master "https://github.com/TiddlyWiki/tiddlywiki.com-gh-pages.git" output
git clone --depth=1 --branch=master "https://github.com/Jermolene/jermolene.github.io.git" output

View File

@@ -10,6 +10,6 @@ git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
git add -A .
git commit --message "GitHub build: $GITHUB_RUN_NUMBER of $TW5_BUILD_BRANCH ($(date +'%F %T %Z'))"
git remote add deploy "https://$GH_TOKEN@github.com/TiddlyWiki/tiddlywiki.com-gh-pages.git" &>/dev/null
git remote add deploy "https://$GH_TOKEN@github.com/Jermolene/jermolene.github.io.git" &>/dev/null
git push deploy master &>/dev/null
cd ..

View File

@@ -1,16 +0,0 @@
#!/bin/bash
# test TiddlyWiki5 for tiddlywiki.com
node ./tiddlywiki.js \
./editions/test \
--verbose \
--version \
--rendertiddler $:/core/save/all test.html text/plain \
--test \
|| exit 1
npm install playwright @playwright/test
npx playwright install chromium firefox --with-deps
npx playwright test

View File

@@ -2,4 +2,4 @@
# Remove any output files
find . -regex "^./editions/.*/output/.*" -delete
find . -regex "^./editions/[a-z0-9\.-]*/output/.*" -delete

View File

@@ -15,11 +15,3 @@ node $TW5_BUILD_TIDDLYWIKI \
--output . \
--build readmes \
|| exit 1
# tw.org readmes
node $TW5_BUILD_TIDDLYWIKI \
editions/tw.org \
--verbose \
--output . \
--build readmes \
|| exit 1

View File

@@ -9,7 +9,6 @@ node ./tiddlywiki.js \
--verbose \
--version \
--rendertiddler $:/core/save/all test.html text/plain \
--test \
|| exit 1
echo To run the tests in a browser, open "editions/test/output/test.html"

View File

@@ -68,26 +68,6 @@ $tw.utils.isArrayEqual = function(array1,array2) {
});
};
/*
Add an entry to a sorted array if it doesn't already exist, while maintaining the sort order
*/
$tw.utils.insertSortedArray = function(array,value) {
var low = 0, high = array.length - 1, mid, cmp;
while(low <= high) {
mid = (low + high) >> 1;
cmp = value.localeCompare(array[mid]);
if(cmp > 0) {
low = mid + 1;
} else if(cmp < 0) {
high = mid - 1;
} else {
return array;
}
}
array.splice(low,0,value);
return array;
};
/*
Push entries onto an array, removing them first if they already exist in the array
array: array to modify (assumed to be free of duplicates)
@@ -142,15 +122,15 @@ $tw.utils.each = function(object,callback) {
var next,f,length;
if(object) {
if(Object.prototype.toString.call(object) == "[object Array]") {
for(f=0, length=object.length; f<length; f++) {
for (f=0, length=object.length; f<length; f++) {
next = callback(object[f],f,object);
if(next === false) {
break;
}
}
}
} else {
var keys = Object.keys(object);
for(f=0, length=keys.length; f<length; f++) {
for (f=0, length=keys.length; f<length; f++) {
var key = keys[f];
next = callback(object[key],key,object);
if(next === false) {
@@ -177,7 +157,6 @@ document: defaults to current document
eventListeners: array of event listeners (this option won't work until $tw.utils.addEventListeners() has been loaded)
*/
$tw.utils.domMaker = function(tag,options) {
var options = options || {};
var doc = options.document || document;
var element = doc.createElementNS(options.namespace || "http://www.w3.org/1999/xhtml",tag);
if(options["class"]) {
@@ -219,34 +198,9 @@ $tw.utils.error = function(err) {
heading = dm("h1",{text: errHeading}),
prompt = dm("div",{text: promptMsg, "class": "tc-error-prompt"}),
message = dm("div",{text: err, "class":"tc-error-message"}),
closeButton = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
downloadButton = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "download tiddlers" : $tw.language.getString("Buttons/EmergencyDownload/Caption") )})], "class": "tc-error-prompt"}),
form = dm("form",{children: [heading,prompt,downloadButton,message,closeButton], "class": "tc-error-form"});
button = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
form = dm("form",{children: [heading,prompt,message,button], "class": "tc-error-form"});
document.body.insertBefore(form,document.body.firstChild);
downloadButton.addEventListener("click",function(event) {
if($tw && $tw.wiki) {
var tiddlers = [];
$tw.wiki.each(function(tiddler,title) {
tiddlers.push(tiddler.fields);
});
var link = dm("a"),
text = JSON.stringify(tiddlers);
if(Blob !== undefined) {
var blob = new Blob([text], {type: "application/json"});
link.setAttribute("href", URL.createObjectURL(blob));
} else {
link.setAttribute("href","data:application/json," + encodeURIComponent(text));
}
link.setAttribute("download","emergency-tiddlers-" + (new Date()) + ".json");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
alert("Emergency tiddler download is not available");
}
event.preventDefault();
return false;
},true);
form.addEventListener("submit",function(event) {
document.body.removeChild(form);
event.preventDefault();
@@ -275,7 +229,7 @@ Extend an object with the properties from a list of source objects
$tw.utils.extend = function(object /*, sourceObjectList */) {
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
if(source) {
for(var p in source) {
for (var p in source) {
object[p] = source[p];
}
}
@@ -289,7 +243,7 @@ Fill in any null or undefined properties of an object with the properties from a
$tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
if(source) {
for(var p in source) {
for (var p in source) {
if(object[p] === null || object[p] === undefined) {
object[p] = source[p];
}
@@ -302,28 +256,6 @@ $tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
return object;
};
/*
Convert a URIComponent encoded string to a string safely
*/
$tw.utils.decodeURIComponentSafe = function(s) {
var v = s;
try {
v = decodeURIComponent(s);
} catch(e) {}
return v;
};
/*
Convert a URI encoded string to a string safely
*/
$tw.utils.decodeURISafe = function(s) {
var v = s;
try {
v = decodeURI(s);
} catch(e) {}
return v;
};
/*
Convert "&amp;" to &, "&nbsp;" to nbsp, "&lt;" to <, "&gt;" to > and "&quot;" to "
*/
@@ -339,7 +271,7 @@ $tw.utils.getLocationHash = function() {
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
} else if(idx < href.length-1 && href[idx+1] === '#') {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
@@ -386,8 +318,8 @@ $tw.utils.parseDate = function(value) {
parseInt(value.substr(10,2)||"00",10),
parseInt(value.substr(12,2)||"00",10),
parseInt(value.substr(14,3)||"000",10)));
d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822
return d;
d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822
return d;
} else if($tw.utils.isDate(value)) {
return value;
} else {
@@ -401,7 +333,7 @@ $tw.utils.stringifyList = function(value) {
var result = new Array(value.length);
for(var t=0, l=value.length; t<l; t++) {
var entry = value[t] || "";
if(entry.match(/[^\S\xA0]/mg)) {
if(entry.indexOf(" ") !== -1) {
result[t] = "[[" + entry + "]]";
} else {
result[t] = entry;
@@ -455,19 +387,6 @@ $tw.utils.parseFields = function(text,fields) {
return fields;
};
// Safely parse a string as JSON
$tw.utils.parseJSONSafe = function(text,defaultJSON) {
try {
return JSON.parse(text);
} catch(e) {
if(typeof defaultJSON === "function") {
return defaultJSON(e);
} else {
return defaultJSON || {};
}
}
};
/*
Resolves a source filepath delimited with `/` relative to a specified absolute root filepath.
In relative paths, the special folder name `..` refers to immediate parent directory, and the
@@ -595,22 +514,10 @@ $tw.utils.getTypeEncoding = function(ext) {
return typeInfo ? typeInfo.encoding : "utf8";
};
var globalCheck =[
" Object.defineProperty(Object.prototype, '__temp__', {",
" get: function () { return this; },",
" configurable: true",
" });",
" if(Object.keys(__temp__).length){",
" console.log(\"Warning: Global assignment detected\",Object.keys(__temp__));",
" delete Object.prototype.__temp__;",
" }",
" delete Object.prototype.__temp__;",
].join('\n');
/*
Run code globally with specified context variables in scope
*/
$tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
$tw.utils.evalGlobal = function(code,context,filename) {
var contextCopy = $tw.utils.extend(Object.create(null),context);
// Get the context variables as a pair of arrays of names and values
var contextNames = [], contextValues = [];
@@ -619,38 +526,25 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
contextValues.push(value);
});
// Add the code prologue and epilogue
code = [
"(function(" + contextNames.join(",") + ") {",
" (function(){" + code + "\n;})();\n",
(!$tw.browser && sandbox && !allowGlobals) ? globalCheck : "",
"\nreturn exports;\n",
"})"
].join("");
code = "(function(" + contextNames.join(",") + ") {(function(){\n" + code + "\n;})();\nreturn exports;\n})\n";
// Compile the code into a function
var fn;
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
if(sandbox){
fn = vm.runInContext(code,sandbox,filename)
} else {
fn = vm.runInThisContext(code,filename);
}
fn = vm.runInThisContext(code,filename);
}
// Call the function and return the exports
return fn.apply(null,contextValues);
};
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
/*
Run code in a sandbox with only the specified context variables in scope
*/
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename,allowGlobals) {
return $tw.utils.evalGlobal(
code,context,filename,
allowGlobals ? vm.createContext({}) : $tw.utils.sandbox,
allowGlobals
);
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename) {
var sandbox = $tw.utils.extend(Object.create(null),context);
vm.runInNewContext(code,sandbox,filename);
return sandbox.exports;
};
/*
@@ -799,13 +693,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);
@@ -813,7 +706,6 @@ $tw.utils.Crypto = function() {
}
return outputText;
};
$tw.sjcl = sjcl;
this.setPassword = function(newPassword) {
currentPassword = newPassword;
this.updateCryptoStateTiddler();
@@ -831,8 +723,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);
@@ -866,7 +757,12 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
tiddler = $tw.wiki.getTiddler(name),
_exports = {},
sandbox = {
module: {exports: _exports},
module: {
exports: _exports,
setStringHandler: function(handler) {
moduleInfo.stringHandler = handler;
}
},
//moduleInfo: moduleInfo,
exports: _exports,
console: console,
@@ -895,8 +791,8 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
} else {
/*
CommonJS optional require.main property:
In a browser we offer a fake main module which points back to the boot function
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
In a browser we offer a fake main module which points back to the boot function
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
*/
Object.defineProperty(sandbox.require, "main", {
value: (typeof(require) !== "undefined") ? require.main : {TiddlyWiki: _boot},
@@ -930,7 +826,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
moduleInfo.definition(moduleInfo,moduleInfo.exports,sandbox.require);
} else if(typeof moduleInfo.definition === "string") { // String
moduleInfo.exports = _exports;
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,name);
if(sandbox.module.exports) {
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
}
@@ -938,9 +834,9 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
moduleInfo.exports = moduleInfo.definition;
}
} catch(e) {
if(e instanceof SyntaxError) {
if (e instanceof SyntaxError) {
var line = e.lineNumber || e.line; // Firefox || Safari
if(typeof(line) != "undefined" && line !== null) {
if (typeof(line) != "undefined" && line !== null) {
$tw.utils.error("Syntax error in boot module " + name + ":" + line + ":\n" + e.stack);
} else if(!$tw.browser) {
// this is the only way to get node.js to display the line at which the syntax error appeared,
@@ -954,7 +850,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
}
} else {
// line number should be included in e.stack for runtime errors
$tw.utils.error("Error executing boot module " + name + ": " + String(e) + "\n\n" + e.stack);
$tw.utils.error("Error executing boot module " + name + ": " + JSON.stringify(e) + "\n\n" + e.stack);
}
}
}
@@ -1027,6 +923,20 @@ $tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
return classes;
};
/*
Return a specified module string for a module, null if the module or string is missing
*/
$tw.modules.getModuleString = function(moduleName,stringName,language) {
if(moduleName in $tw.modules.titles) {
$tw.modules.execute(moduleName);
var stringHandler = $tw.modules.titles[moduleName].stringHandler;
if(stringHandler) {
return stringHandler(stringName,language);
}
}
return null;
};
/////////////////////////// Barebones tiddler object
/*
@@ -1168,7 +1078,7 @@ $tw.Wiki = function(options) {
tiddlerTitles = null, // Array of tiddler titles
getTiddlerTitles = function() {
if(!tiddlerTitles) {
tiddlerTitles = Object.keys(tiddlers).sort(function(a,b) {return a.localeCompare(b);});
tiddlerTitles = Object.keys(tiddlers);
}
return tiddlerTitles;
},
@@ -1178,7 +1088,7 @@ $tw.Wiki = function(options) {
shadowTiddlerTitles = null,
getShadowTiddlerTitles = function() {
if(!shadowTiddlerTitles) {
shadowTiddlerTitles = Object.keys(shadowTiddlers).sort(function(a,b) {return a.localeCompare(b);});
shadowTiddlerTitles = Object.keys(shadowTiddlers);
}
return shadowTiddlerTitles;
},
@@ -1221,8 +1131,10 @@ $tw.Wiki = function(options) {
}
// Save the new tiddler
tiddlers[title] = tiddler;
// Check we've got the title
tiddlerTitles = $tw.utils.insertSortedArray(tiddlerTitles || [],title);
// Check we've got it's title
if(tiddlerTitles && tiddlerTitles.indexOf(title) === -1) {
tiddlerTitles.push(title);
}
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: tiddler,
@@ -1284,16 +1196,13 @@ $tw.Wiki = function(options) {
this.getTiddler = function(title) {
if(title) {
var t = tiddlers[title];
if(t !== undefined) {
if(t instanceof $tw.Tiddler) {
return t;
} else {
var s = shadowTiddlers[title];
if(s !== undefined) {
return s.tiddler;
}
} else if(title !== undefined && shadowTiddlers[title]) {
return shadowTiddlers[title].tiddler;
}
return undefined;
}
return undefined;
};
// Get an array of all tiddler titles
@@ -1322,12 +1231,8 @@ $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);
} else {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
};
@@ -1410,7 +1315,7 @@ $tw.Wiki = function(options) {
var tiddler = tiddlers[title];
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);
pluginInfo[tiddler.fields.title] = JSON.parse(tiddler.fields.text);
results.modifiedPlugins.push(tiddler.fields.title);
}
} else {
@@ -1435,7 +1340,7 @@ $tw.Wiki = function(options) {
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") {
if(title === "$:/core" || !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);
@@ -1472,15 +1377,17 @@ $tw.Wiki = function(options) {
// Unpack the currently registered plugins, creating shadow tiddlers for their constituent tiddlers
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;
if (priorityA !== priorityB) {
return priorityA - priorityB;
} else if (a.fields.title < b.fields.title) {
// Sort the plugin titles by the `plugin-priority` field
pluginTiddlers.sort(function(a,b) {
if("plugin-priority" in a.fields && "plugin-priority" in b.fields) {
return a.fields["plugin-priority"] - b.fields["plugin-priority"];
} else if("plugin-priority" in a.fields) {
return -1;
} else if (a.fields.title === b.fields.title) {
} else if("plugin-priority" in b.fields) {
return +1;
} else if(a.fields.title < b.fields.title) {
return -1;
} else if(a.fields.title === b.fields.title) {
return 0;
} else {
return +1;
@@ -1532,9 +1439,8 @@ 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"))) {
switch(tiddler.fields.type) {
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
if(!$tw.utils.hop($tw.modules.titles,tiddler.fields.title)) {
@@ -1542,7 +1448,7 @@ $tw.Wiki.prototype.defineTiddlerModules = function() {
}
break;
case "application/json":
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseJSONSafe(tiddler.fields.text));
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],JSON.parse(tiddler.fields.text));
break;
case "application/x-tiddler-dictionary":
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseFields(tiddler.fields.text));
@@ -1560,11 +1466,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);
}
@@ -1720,8 +1621,8 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
}
for(var f in data) {
if($tw.utils.hop(data,f)) {
// Check field name doesn't contain control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F]/.test(f)) {
// Check field name doesn't contain whitespace or control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F\s]/.test(f)) {
return false;
}
}
@@ -1736,7 +1637,7 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
}
return true;
},
data = $tw.utils.parseJSONSafe(text);
data = JSON.parse(text);
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
return data;
} else if(isTiddlerValid(data)) {
@@ -1776,7 +1677,7 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) {
$tw.crypto.setPassword(data.password);
var decryptedText = $tw.crypto.decrypt(encryptedText);
if(decryptedText) {
var json = $tw.utils.parseJSONSafe(decryptedText);
var json = JSON.parse(decryptedText);
for(var title in json) {
$tw.preloadTiddler(json[title]);
}
@@ -1910,16 +1811,8 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
extensionInfo = $tw.utils.getFileExtensionInfo(ext),
type = extensionInfo ? extensionInfo.type : null,
typeInfo = type ? $tw.config.contentTypeInfo[type] : null,
fileSize = fs.statSync(filepath).size,
data;
if(fileSize > $tw.config.maxEditFileSize) {
data = "File " + filepath + " not loaded because it is too large";
console.log("Warning: " + data);
ext = ".txt";
} else {
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8");
}
var tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8"),
tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
metadata = $tw.loadMetadataForFile(filepath);
if(metadata) {
if(type === "application/json") {
@@ -1947,7 +1840,7 @@ A default set of files for TiddlyWiki to ignore during load.
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
metadata files.
*/
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.github$|^\.vscode$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
/*
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.
@@ -1984,41 +1877,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 = JSON.parse(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
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)) {
@@ -2026,32 +1900,26 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
} else {
var value = tiddler[name];
switch(fieldInfo.source) {
case "subdirectories":
value = $tw.utils.stringifyList(path.relative(rootPath, filename).split(path.sep).slice(0, -1));
break;
case "filepath":
value = path.relative(rootPath, filename).split(path.sep).join('/');
break;
case "filename":
value = path.basename(filename);
break;
case "filename-uri-decoded":
value = $tw.utils.decodeURIComponentSafe(path.basename(filename));
value = decodeURIComponent(path.basename(filename));
break;
case "basename":
value = path.basename(filename,path.extname(filename));
break;
case "basename-uri-decoded":
value = $tw.utils.decodeURIComponentSafe(path.basename(filename,path.extname(filename)));
value = decodeURIComponent(path.basename(filename,path.extname(filename)));
break;
case "extname":
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) {
@@ -2070,20 +1938,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
tiddlers.push({tiddlers: fileTiddlers});
}
};
// Helper to recursively search subdirectories
var getAllFiles = function(dirPath, recurse, arrayOfFiles) {
recurse = recurse || false;
arrayOfFiles = arrayOfFiles || [];
var files = fs.readdirSync(dirPath);
files.forEach(function(file) {
if(recurse && fs.statSync(dirPath + path.sep + file).isDirectory()) {
arrayOfFiles = getAllFiles(dirPath + path.sep + file, recurse, arrayOfFiles);
} else if(fs.statSync(dirPath + path.sep + file).isFile()){
arrayOfFiles.push(path.join(dirPath, path.sep, file));
}
});
return arrayOfFiles;
}
// Process the listed tiddlers
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
if(tidInfo.prefix && tidInfo.suffix) {
@@ -2093,7 +1947,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
@@ -2108,15 +1961,13 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
// Process directory specifier
var dirPath = path.resolve(filepath,dirSpec.path);
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
var files = getAllFiles(dirPath, dirSpec.searchSubdirectories),
var files = fs.readdirSync(dirPath),
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
metaRegExp = /^.*\.meta$/;
for(var t=0; t<files.length; t++) {
var thisPath = path.relative(filepath, files[t]),
filename = path.basename(thisPath);
var filename = files[t];
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
dirSpec.fields = dirSpec.fields || {};
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
}
}
} else {
@@ -2141,11 +1992,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
console.log("Warning: missing plugin.info file in " + filepath);
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 pluginInfo = JSON.parse(fs.readFileSync(infoPath,"utf8"));
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
@@ -2223,16 +2070,13 @@ Returns an array of search paths
*/
$tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
var pluginPaths = [path.resolve($tw.boot.corePath,libraryPath)],
env;
if(envVar) {
env = process.env[envVar];
if(env) {
env.split(path.delimiter).map(function(item) {
if(item) {
pluginPaths.push(item);
}
});
}
if(env) {
env.split(path.delimiter).map(function(item) {
if(item) {
pluginPaths.push(item);
}
});
}
return pluginPaths;
};
@@ -2265,11 +2109,7 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
pluginFields;
// Bail if we don't have a wiki info file
if(fs.existsSync(wikiInfoPath)) {
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"),function() {return null;});
if(!wikiInfo) {
console.log("warning: invalid JSON in tiddlywiki.info file at " + wikiInfoPath);
wikiInfo = {};
}
wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8"));
} else {
return null;
}
@@ -2318,7 +2158,7 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
}
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
});
if($tw.boot.wikiPath == wikiPath) {
if ($tw.boot.wikiPath == wikiPath) {
// Save the original tiddler file locations if requested
var output = {}, relativePath, fileInfo;
for(var title in $tw.boot.files) {
@@ -2379,7 +2219,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
@@ -2453,7 +2292,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"];
@@ -2502,38 +2340,30 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("image/webp","base64",".webp",{flags:["image"]});
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
$tw.utils.registerFileType("image/avif","base64",".avif",{flags:["image"]});
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
$tw.utils.registerFileType("image/vnd.microsoft.icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("application/wasm","base64",".wasm");
$tw.utils.registerFileType("font/woff","base64",".woff");
$tw.utils.registerFileType("font/woff2","base64",".woff2");
$tw.utils.registerFileType("font/ttf","base64",".ttf");
$tw.utils.registerFileType("font/otf","base64",".otf");
$tw.utils.registerFileType("application/font-woff","base64",".woff");
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
$tw.utils.registerFileType("application/font-woff2","base64",".woff2");
$tw.utils.registerFileType("audio/ogg","base64",".ogg");
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]);
$tw.utils.registerFileType("video/webm","base64",".webm");
$tw.utils.registerFileType("video/mp4","base64",".mp4");
$tw.utils.registerFileType("audio/mp3","base64",".mp3");
$tw.utils.registerFileType("audio/mpeg","base64",[".mp3",".m2a",".mp2",".mpa",".mpg",".mpga"]);
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.wordprocessingml.document","base64",".docx");
$tw.utils.registerFileType("application/msword","base64",".doc");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
$tw.utils.registerFileType("application/excel","base64",".xls");
$tw.utils.registerFileType("application/vnd.ms-excel","base64",".xls");
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.presentationml.presentation","base64",".pptx");
$tw.utils.registerFileType("application/mspowerpoint","base64",".ppt");
$tw.utils.registerFileType("text/x-bibtex","utf8",".bib",{deserializerType:"application/x-bibtex"});
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
$tw.utils.registerFileType("application/octet-stream","base64",".octet-stream");
// Create the wiki store for the app
$tw.wiki = new $tw.Wiki($tw.safeMode && {enableIndexers: []});
$tw.wiki = new $tw.Wiki();
// Install built in tiddler fields modules
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
// Install the tiddler deserializer modules
@@ -2578,10 +2408,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();
@@ -2650,13 +2480,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;
@@ -2678,14 +2506,14 @@ $tw.boot.doesTaskMatchPlatform = function(taskModule) {
var platforms = taskModule.platforms;
if(platforms) {
for(var t=0; t<platforms.length; t++) {
switch(platforms[t]) {
switch (platforms[t]) {
case "browser":
if($tw.browser) {
if ($tw.browser) {
return true;
}
break;
case "node":
if($tw.node) {
if ($tw.node) {
return true;
}
break;
@@ -2715,7 +2543,7 @@ $tw.boot.isStartupTaskEligible = function(taskModule) {
for(t=0; t<remaining.length; t++) {
var task = remaining[t];
if(task.before && task.before.indexOf(name) !== -1) {
if($tw.boot.doesTaskMatchPlatform(task) && (!task.name || $tw.boot.disabledStartupModules.indexOf(task.name) === -1)) {
if($tw.boot.doesTaskMatchPlatform(task) || (task.name && $tw.boot.disabledStartupModules.indexOf(name) !== -1)) {
return false;
}
}
@@ -2750,25 +2578,13 @@ $tw.hooks.addHook = function(hookName,definition) {
}
};
/*
Delete hooks from the hashmap
*/
$tw.hooks.removeHook = function(hookName,definition) {
if($tw.utils.hop($tw.hooks.names,hookName)) {
var p = $tw.hooks.names[hookName].indexOf(definition);
if(p !== -1) {
$tw.hooks.names[hookName].splice(p, 1);
}
}
};
/*
Invoke the hook by key
*/
$tw.hooks.invokeHook = function(hookName /*, value,... */) {
var args = Array.prototype.slice.call(arguments,1);
if($tw.utils.hop($tw.hooks.names,hookName)) {
for(var i = 0; i < $tw.hooks.names[hookName].length; i++) {
for (var i = 0; i < $tw.hooks.names[hookName].length; i++) {
args[0] = $tw.hooks.names[hookName][i].apply(null,args);
}
}
@@ -2806,4 +2622,3 @@ if(typeof(exports) !== "undefined") {
} else {
_boot(window.$tw);
}
//# sourceURL=$:/boot/boot.js

View File

@@ -19,13 +19,9 @@ var _bootprefix = (function($tw) {
$tw = $tw || Object.create(null);
$tw.boot = $tw.boot || Object.create(null);
// Config
$tw.config = $tw.config || Object.create(null);
$tw.config.maxEditFileSize = 100 * 1024 * 1024; // 100MB
// Detect platforms
if(!("browser" in $tw)) {
$tw.browser = typeof(window) !== "undefined" && typeof(document) !== "undefined" ? {} : null;
$tw.browser = typeof(window) !== "undefined" ? {} : null;
}
if(!("node" in $tw)) {
$tw.node = typeof(process) === "object" ? {} : null;
@@ -121,4 +117,3 @@ if(typeof(exports) === "undefined") {
// Export functionality as a module
exports.bootprefix = _bootprefix;
}
//# sourceURL=$:/boot/bootprefix.js

3
boot/sjcl.js.meta Normal file
View File

@@ -0,0 +1,3 @@
title: $:/library/sjcl.js
type: application/javascript
library: yes

View File

@@ -1,32 +0,0 @@
{
"tiddlers": [
{
"file": "sjcl.js",
"fields": {
"title": "$:/library/sjcl.js",
"type": "application/javascript",
"library": "yes"
},
"prefix": "(function(define) {\n",
"suffix": "\n})(function (_,defined){window.sjcl = defined()})\n"
},
{
"file": "boot.js",
"fields": {
"title": "$:/boot/boot.js",
"type": "application/javascript"
}
},
{
"file": "bootprefix.js",
"fields": {
"title": "$:/boot/bootprefix.js",
"type": "application/javascript"
}
},
{
"file": "boot.css.tid",
"isTiddlerFile": true
}
]
}

View File

@@ -1 +0,0 @@
<p>This community exists because TiddlyWiki is more useful when people share and work together.</p><p>This community is a beautiful but fragile thing: a collection of diverse people from all over the planet, united in their interest in the project, and their commitment to helping one another achieve and learn more.</p><p>We try to make the community as broad and welcoming as possible by remembering some basic principles of culture and behaviour.</p><p>These principles guide technical and non-technical decisions, and help contributors and leaders support our project and community.</p><ul><li>We are optimistic and hopeful</li><li>We aim to foster a learning environment that is collaborative and safe for everyone</li><li>We recognise that the motivation for sharing and helping is usually for appreciation, and not financial gain, and so we take care to acknowledge and <strong>thank the people who enrich the community by sharing what they have created</strong></li><li>While we are united in our interest in TiddlyWiki, we differ in every other conceivable way. We choose to focus on what unites us, and <strong>avoid unnecessarily mixing contentious topics like religion and politics</strong></li><li>We treat each other with respect, and start with the assumption that <strong>others are acting in good faith</strong></li><li>We avoid discriminatory language</li><li>We try to use our strength as a community to help others</li><li>We avoid responding when angry or upset because we try to de-escalate conflict</li><li>We make sure we critique ideas, not people</li><li>When we disagree with others we do so graciously, and treat others with dignity and respoect</li><li>We do not tolerate intolerance towards others</li><li>We seek first to understand others, and then to be understood</li><li>We have fun</li></ul><p>Our discussions are in English. It is not the first language of many people in the community, nor do we all share the same cultural background and reference points. So we take care to use language that is clear and unambigous, and avoid cultural references or jokes that will not be widely understood.</p><p>It is not acceptable to make jokes or other comments that discriminate by race, gender, sexuality, or other protected characteristic.</p><p>As an inclusive community, we are committed to making sure that TiddlyWiki is an accessible tool that understands the needs of people with disabilities.</p>

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,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,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,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,14 +0,0 @@
title: Infrastructure Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
team: @MotovunJack
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

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,6 +0,0 @@
title: Newsletter Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
The Newsletter Team is responsible for producing the TiddlyWiki Newsletter, a monthly email newsletter that highlights news, updates, and community contributions related to TiddlyWiki.

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,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,5 +0,0 @@
title: Community/Team
modified: 20250909171928024
created: 20250909171928024
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Infrastructure 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>

File diff suppressed because one or more lines are too long

View File

@@ -1,36 +0,0 @@
/*\
title: $:/core/modules/commands/commands.js
type: application/javascript
module-type: command
Runs the commands returned from a filter
\*/
"use strict";
exports.info = {
name: "commands",
synchronous: true
};
var Command = function(params, commander) {
this.params = params;
this.commander = commander;
};
Command.prototype.execute = function() {
// Parse the filter
var filter = this.params[0];
if(!filter) {
return "No filter specified";
}
var commands = this.commander.wiki.filterTiddlers(filter)
if(commands.length === 0) {
return "No tiddlers found for filter '" + filter + "'";
}
this.commander.addCommandTokens(commands);
return null;
};
exports.Command = Command;

View File

@@ -1,40 +0,0 @@
/*\
title: $:/core/modules/commands/makelibrary.js
type: application/javascript
module-type: command
Command to pack all of the plugins in the library into a plugin tiddler of type "library"
\*/
"use strict";
exports.info = {
name: "makelibrary",
synchronous: true
};
var UPGRADE_LIBRARY_TITLE = "$:/UpgradeLibrary";
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
var wiki = this.commander.wiki,
upgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,
tiddlers = $tw.utils.getAllPlugins();
// Save the upgrade library tiddler
var pluginFields = {
title: upgradeLibraryTitle,
type: "application/json",
"plugin-type": "library",
"text": JSON.stringify({tiddlers: tiddlers})
};
wiki.addTiddler(new $tw.Tiddler(pluginFields));
return null;
};
exports.Command = Command;

View File

@@ -1,65 +0,0 @@
/*\
title: $:/core/modules/commands/render.js
type: application/javascript
module-type: command
Render individual tiddlers and save the results to the specified files
\*/
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "render",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing tiddler filter";
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.utils.each(tiddlers,function(title) {
var filenameResults = wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]));
if(filenameResults.length > 0) {
var filepath = path.resolve(self.commander.outputPath,filenameResults[0]);
if(self.commander.verbose) {
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
}
var parser = wiki.parseTiddler(template || title),
widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title,storyTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent;
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,text,"utf8");
} else {
console.log("Not rendering \"" + title + "\" because the filename filter returned an empty result");
}
});
return null;
};
exports.Command = Command;

View File

@@ -1,63 +0,0 @@
/*\
title: $:/core/modules/commands/save.js
type: application/javascript
module-type: command
Saves individual tiddlers in their raw text or binary format to the specified files
\*/
"use strict";
exports.info = {
name: "save",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filename filter";
}
var self = this,
fs = require("fs"),
path = require("path"),
result = null,
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]]",
tiddlers = wiki.filterTiddlers(tiddlerFilter);
$tw.utils.each(tiddlers,function(title) {
if(!result) {
var tiddler = self.commander.wiki.getTiddler(title);
if(tiddler) {
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: path.resolve(self.commander.outputPath),
pathFilters: [filenameFilter],
wiki: wiki,
fileInfo: {
overwrite: true
}
});
if(self.commander.verbose) {
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
}
try {
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
} catch (err) {
result = "Error saving tiddler \"" + title + "\", to file: \"" + fileInfo.filepath + "\"";
}
} else {
result = "Tiddler '" + title + "' not found";
}
}
});
return result;
};
exports.Command = Command;

View File

@@ -1,50 +0,0 @@
/*\
title: $:/core/modules/commands/server.js
type: application/javascript
module-type: command
Deprecated legacy command for serving tiddlers
\*/
"use strict";
var Server = require("$:/core/modules/server/server.js").Server;
exports.info = {
name: "server",
synchronous: true
};
var Command = function(params,commander,callback) {
var self = this;
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(!$tw.boot.wikiTiddlersPath) {
$tw.utils.warning("Warning: Wiki folder '" + $tw.boot.wikiPath + "' does not exist or is missing a tiddlywiki.info file");
}
// Set up server
this.server = new Server({
wiki: this.commander.wiki,
variables: {
port: this.params[0],
host: this.params[6],
"root-tiddler": this.params[1],
"root-render-type": this.params[2],
"root-serve-type": this.params[3],
username: this.params[4],
password: this.params[5],
"path-prefix": this.params[7],
"debug-level": this.params[8]
}
});
var nodeServer = this.server.listen();
$tw.hooks.invokeHook("th-server-command-post-start",this.server,nodeServer,"tiddlywiki");
return null;
};
exports.Command = Command;

View File

@@ -1,542 +0,0 @@
/*\
title: $:/core/modules/utils/filesystem.js
type: application/javascript
module-type: utils-node
File system utilities
\*/
"use strict";
var fs = require("fs"),
path = require("path");
/*
Return the subdirectories of a path
*/
exports.getSubdirectories = function(dirPath) {
if(!$tw.utils.isDirectory(dirPath)) {
return null;
}
var subdirs = [];
$tw.utils.each(fs.readdirSync(dirPath),function(item) {
if($tw.utils.isDirectory(path.resolve(dirPath,item))) {
subdirs.push(item);
}
});
return subdirs;
}
/*
Recursively (and synchronously) copy a directory and all its content
*/
exports.copyDirectory = function(srcPath,dstPath) {
// Remove any trailing path separators
srcPath = path.resolve($tw.utils.removeTrailingSeparator(srcPath));
dstPath = path.resolve($tw.utils.removeTrailingSeparator(dstPath));
// Check that neither director is within the other
if(srcPath.substring(0,dstPath.length) === dstPath || dstPath.substring(0,srcPath.length) === srcPath) {
return "Cannot copy nested directories";
}
// Create the destination directory
var err = $tw.utils.createDirectory(dstPath);
if(err) {
return err;
}
// Function to copy a folder full of files
var copy = function(srcPath,dstPath) {
var srcStats = fs.lstatSync(srcPath),
dstExists = fs.existsSync(dstPath);
if(srcStats.isFile()) {
$tw.utils.copyFile(srcPath,dstPath);
} else if(srcStats.isDirectory()) {
var items = fs.readdirSync(srcPath);
for(var t=0; t<items.length; t++) {
var item = items[t],
err = copy(srcPath + path.sep + item,dstPath + path.sep + item);
if(err) {
return err;
}
}
}
};
copy(srcPath,dstPath);
return null;
};
/*
Copy a file
*/
var FILE_BUFFER_LENGTH = 64 * 1024,
fileBuffer;
exports.copyFile = function(srcPath,dstPath) {
// Create buffer if required
if(!fileBuffer) {
fileBuffer = Buffer.alloc(FILE_BUFFER_LENGTH);
}
// Create any directories in the destination
$tw.utils.createDirectory(path.dirname(dstPath));
// Copy the file
var srcFile = fs.openSync(srcPath,"r"),
dstFile = fs.openSync(dstPath,"w"),
bytesRead = 1,
pos = 0;
while (bytesRead > 0) {
bytesRead = fs.readSync(srcFile,fileBuffer,0,FILE_BUFFER_LENGTH,pos);
fs.writeSync(dstFile,fileBuffer,0,bytesRead);
pos += bytesRead;
}
fs.closeSync(srcFile);
fs.closeSync(dstFile);
return null;
};
/*
Remove trailing path separator
*/
exports.removeTrailingSeparator = function(dirPath) {
var len = dirPath.length;
if(dirPath.charAt(len-1) === path.sep) {
dirPath = dirPath.substr(0,len-1);
}
return dirPath;
};
/*
Recursively create a directory
*/
exports.createDirectory = function(dirPath) {
if(dirPath.substr(dirPath.length-1,1) !== path.sep) {
dirPath = dirPath + path.sep;
}
var pos = 1;
pos = dirPath.indexOf(path.sep,pos);
while(pos !== -1) {
var subDirPath = dirPath.substr(0,pos);
if(!$tw.utils.isDirectory(subDirPath)) {
try {
fs.mkdirSync(subDirPath);
} catch(e) {
return "Error creating directory '" + subDirPath + "'";
}
}
pos = dirPath.indexOf(path.sep,pos + 1);
}
return null;
};
/*
Recursively create directories needed to contain a specified file
*/
exports.createFileDirectories = function(filePath) {
return $tw.utils.createDirectory(path.dirname(filePath));
};
/*
Recursively delete a directory
*/
exports.deleteDirectory = function(dirPath) {
if(fs.existsSync(dirPath)) {
var entries = fs.readdirSync(dirPath);
for(var entryIndex=0; entryIndex<entries.length; entryIndex++) {
var currPath = dirPath + path.sep + entries[entryIndex];
if(fs.lstatSync(currPath).isDirectory()) {
$tw.utils.deleteDirectory(currPath);
} else {
fs.unlinkSync(currPath);
}
}
fs.rmdirSync(dirPath);
}
return null;
};
/*
Check if a path identifies a directory
*/
exports.isDirectory = function(dirPath) {
return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();
};
/*
Check if a path identifies a directory that is empty
*/
exports.isDirectoryEmpty = function(dirPath) {
if(!$tw.utils.isDirectory(dirPath)) {
return false;
}
var files = fs.readdirSync(dirPath),
empty = true;
$tw.utils.each(files,function(file,index) {
if(file.charAt(0) !== ".") {
empty = false;
}
});
return empty;
};
/*
Recursively delete a tree of empty directories
*/
exports.deleteEmptyDirs = function(dirpath,callback) {
var self = this;
fs.readdir(dirpath,function(err,files) {
if(err) {
return callback(err);
}
if(files.length > 0) {
return callback(null);
}
fs.rmdir(dirpath,function(err) {
if(err) {
return callback(err);
}
self.deleteEmptyDirs(path.dirname(dirpath),callback);
});
});
};
/*
Create a fileInfo object for saving a tiddler:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file on disk (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
isEditableFile: true if the tiddler was loaded via non-standard options & marked editable
Options include:
directory: absolute path of root directory to which we are saving
pathFilters: optional array of filters to be used to generate the base path
extFilters: optional array of filters to be used to generate the base path
wiki: optional wiki for evaluating the pathFilters,
fileInfo: an existing fileInfo to check against
*/
exports.generateTiddlerFileInfo = function(tiddler,options) {
var fileInfo = {}, metaExt;
// Propagate the isEditableFile flag
if(options.fileInfo && !!options.fileInfo.isEditableFile) {
fileInfo.isEditableFile = true;
fileInfo.originalpath = options.fileInfo.originalpath;
}
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
var hasUnsafeFields = false;
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
if(fieldName !== "text") {
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
}
hasUnsafeFields = hasUnsafeFields || /:|#/mg.test(fieldName);
});
// Check for field values
if(hasUnsafeFields) {
// Save as a JSON file
fileInfo.type = "application/json";
fileInfo.hasMetaFile = false;
} else {
// Save as a .tid or a text/binary file plus a .meta file
var tiddlerType = tiddler.fields.type || "text/vnd.tiddlywiki";
if(tiddlerType === "text/vnd.tiddlywiki" || tiddlerType === "text/vnd.tiddlywiki-multiple" || tiddler.hasField("_canonical_uri")) {
// Save as a .tid file
fileInfo.type = "application/x-tiddler";
fileInfo.hasMetaFile = false;
} else {
// Save as a text/binary file and a .meta file
fileInfo.type = tiddlerType;
fileInfo.hasMetaFile = true;
}
if(options.extFilters) {
// Check for extension overrides
metaExt = $tw.utils.generateTiddlerExtension(tiddler.fields.title,{
extFilters: options.extFilters,
wiki: options.wiki
});
if(metaExt) {
if(metaExt === ".tid") {
// Overriding to the .tid extension needs special handling
fileInfo.type = "application/x-tiddler";
fileInfo.hasMetaFile = false;
} else if (metaExt === ".json") {
// Overriding to the .json extension needs special handling
fileInfo.type = "application/json";
fileInfo.hasMetaFile = false;
} else {
//If the new type matches a known extention, use that MIME type's encoding
var extInfo = $tw.utils.getFileExtensionInfo(metaExt);
fileInfo.type = extInfo ? extInfo.type : null;
fileInfo.encoding = $tw.utils.getTypeEncoding(metaExt);
fileInfo.hasMetaFile = true;
}
}
}
}
// Take the file extension from the tiddler content type or metaExt
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
// Generate the filepath
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
extension: metaExt || contentTypeInfo.extension,
directory: options.directory,
pathFilters: options.pathFilters,
wiki: options.wiki,
fileInfo: options.fileInfo
});
return fileInfo;
};
/*
Generate the file extension for saving a tiddler
Options include:
extFilters: optional array of filters to be used to generate the extention
wiki: optional wiki for evaluating the extFilters
*/
exports.generateTiddlerExtension = function(title,options) {
var extension;
// Check if any of the extFilters applies
if(options.extFilters && options.wiki) {
$tw.utils.each(options.extFilters,function(filter) {
if(!extension) {
var source = options.wiki.makeTiddlerIterator([title]),
result = options.wiki.filterTiddlers(filter,null,source);
if(result.length > 0) {
extension = result[0];
}
}
});
}
return extension;
};
/*
Generate the filepath for saving a tiddler
Options include:
extension: file extension to be added the finished filepath
directory: absolute path of root directory to which we are saving
pathFilters: optional array of filters to be used to generate the base path
wiki: optional wiki for evaluating the pathFilters
fileInfo: an existing fileInfo object to check against
fileInfo.overwrite: if true, turns off filename clash numbers (defaults to false)
*/
exports.generateTiddlerFilepath = function(title,options) {
var directory = options.directory || "",
extension = options.extension || "",
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
overwrite = options.fileInfo && options.fileInfo.overwrite || false,
filepath;
// Check if any of the pathFilters applies
if(options.pathFilters && options.wiki) {
$tw.utils.each(options.pathFilters,function(filter) {
if(!filepath) {
var source = options.wiki.makeTiddlerIterator([title]),
result = options.wiki.filterTiddlers(filter,null,source);
if(result.length > 0) {
filepath = result[0];
}
}
});
}
if(!filepath && !!originalpath) {
//Use the originalpath without the extension
var ext = path.extname(originalpath);
filepath = originalpath.substring(0,originalpath.length - ext.length);
} else if(!filepath) {
filepath = title;
// Remove any forward or backward slashes so we don't create directories
filepath = filepath.replace(/\/|\\/g,"_");
}
// Replace any Windows control codes
filepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
// Replace any leading spaces with the same number of underscores
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_")});
//If the path does not start with "." or ".." && a path seperator, then
if(!/^\.{1,2}[/\\]/g.test(filepath)) {
// Don't let the filename start with any dots because such files are invisible on *nix
filepath = filepath.replace(/^\.+/g,function (u) { return u.replace(/\./g, "_")});
}
// Replace any Unicode control codes
filepath = filepath.replace(/[\x00-\x1f\x80-\x9f]/g,"_");
// Replace any characters that can't be used in cross-platform filenames
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
// Replace any dots or spaces at the end of the extension with the same number of underscores
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_")});
// Truncate the extension if it is too long
if(extension.length > 32) {
extension = extension.substr(0,32);
}
// If the filepath already ends in the extension then remove it
if(filepath.substring(filepath.length - extension.length) === extension) {
filepath = filepath.substring(0,filepath.length - extension.length);
}
// Truncate the filename if it is too long
if(filepath.length > 200) {
filepath = filepath.substr(0,200);
}
// If the resulting filename is blank (eg because the title is just punctuation)
if(!filepath || /^_+$/g.test(filepath)) {
// ...then just use the character codes of the title
filepath = "";
$tw.utils.each(title.split(""),function(char) {
if(filepath) {
filepath += "-";
}
filepath += char.charCodeAt(0).toString();
});
}
// Add a uniquifier if the file already exists (default)
var fullPath = path.resolve(directory, filepath + extension);
if (!overwrite) {
var oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
count = 0;
do {
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
if(oldPath && oldPath == fullPath) break;
count++;
} while(fs.existsSync(fullPath));
}
// If the last write failed with an error, or if path does not start with:
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to options.directory.
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
encode = (options.fileInfo || {writeError: false}).writeError == true;
if(!encode) {
encode = !(writePath.indexOf($tw.boot.wikiTiddlersPath) == 0 ||
writePath.indexOf(path.resolve(directory)) == 0 ||
writePath.indexOf(path.resolve($tw.boot.wikiPath)) == 0 ||
writePath.indexOf(path.resolve($tw.boot.wikiTiddlersPath,originalpath)) == 0 );
}
if(encode) {
writePath = path.resolve(directory,$tw.utils.encodeURIComponentExtended(fullPath));
}
// Return the full path to the file
return writePath;
};
/*
Save a tiddler to a file described by the fileInfo:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
*/
exports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
if(fileInfo.hasMetaFile) {
// Save the tiddler as a separate body and meta file
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
fs.writeFile(fileInfo.filepath,tiddler.fields.text || "",typeInfo.encoding,function(err) {
if(err) {
return callback(err);
}
fs.writeFile(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8",function(err) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
});
} else {
// Save the tiddler as a self contained templated file
if(fileInfo.type === "application/x-tiddler") {
fs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8",function(err) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
} else {
fs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8",function(err) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
}
}
};
/*
Save a tiddler to a file described by the fileInfo:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
*/
exports.saveTiddlerToFileSync = function(tiddler,fileInfo) {
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
if(fileInfo.hasMetaFile) {
// Save the tiddler as a separate body and meta file
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
fs.writeFileSync(fileInfo.filepath,tiddler.fields.text || "",typeInfo.encoding);
fs.writeFileSync(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8");
} else {
// Save the tiddler as a self contained templated file
if(fileInfo.type === "application/x-tiddler") {
fs.writeFileSync(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8");
} else {
fs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8");
}
}
return fileInfo;
};
/*
Delete a file described by the fileInfo if it exits
*/
exports.deleteTiddlerFile = function(fileInfo,callback) {
//Only attempt to delete files that exist on disk
if(!fileInfo.filepath || !fs.existsSync(fileInfo.filepath)) {
//For some reason, the tiddler is only in memory or we can't modify the file at this path
$tw.syncer.displayError("Server deleteTiddlerFile task failed for filepath: "+fileInfo.filepath);
return callback(null,fileInfo);
}
// Delete the file
fs.unlink(fileInfo.filepath,function(err) {
if(err) {
return callback(err);
}
// Delete the metafile if present
if(fileInfo.hasMetaFile && fs.existsSync(fileInfo.filepath + ".meta")) {
fs.unlink(fileInfo.filepath + ".meta",function(err) {
if(err) {
return callback(err);
}
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),function(err) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
});
} else {
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),function(err) {
if(err) {
return callback(err);
}
return callback(null,fileInfo);
});
}
});
};
/*
Cleanup old files on disk, by comparing the options values:
adaptorInfo from $tw.syncer.tiddlerInfo
bootInfo from $tw.boot.files
*/
exports.cleanupTiddlerFiles = function(options,callback) {
var adaptorInfo = options.adaptorInfo || {},
bootInfo = options.bootInfo || {},
title = options.title || "undefined";
if(adaptorInfo.filepath && bootInfo.filepath && adaptorInfo.filepath !== bootInfo.filepath) {
$tw.utils.deleteTiddlerFile(adaptorInfo,function(err) {
if(err) {
if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") {
// Error deleting the previous file on disk, should fail gracefully
$tw.syncer.displayError("Server desynchronized. Error cleaning up previous file for tiddler: \""+title+"\"",err);
return callback(null,bootInfo);
} else {
return callback(err);
}
}
return callback(null,bootInfo);
});
} else {
return callback(null,bootInfo);
}
};

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,26 +0,0 @@
/*\
title: $:/core/modules/server/routes/delete-tiddler.js
type: application/javascript
module-type: route
DELETE /recipes/default/tiddlers/:title
\*/
"use strict";
exports.methods = ["DELETE"];
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
exports.info = {
priority: 100
};
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
state.wiki.deleteTiddler(title);
response.writeHead(204, "OK", {
"Content-Type": "text/plain"
});
response.end();
};

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,50 +0,0 @@
/*\
title: $:/core/modules/server/routes/put-tiddler.js
type: application/javascript
module-type: route
PUT /recipes/default/tiddlers/:title
\*/
"use strict";
exports.methods = ["PUT"];
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
exports.info = {
priority: 100
};
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
fields = $tw.utils.parseJSONSafe(state.data);
// Pull up any subfields in the `fields` object
if(fields.fields) {
$tw.utils.each(fields.fields,function(field,name) {
fields[name] = field;
});
delete fields.fields;
}
// Remove any revision field
if(fields.revision) {
delete fields.revision;
}
// If this is a skinny tiddler, it means the client never got the full
// version of the tiddler to edit. So we must preserve whatever text
// already exists on the server, or else we'll inadvertently delete it.
if(fields._is_skinny !== undefined) {
var tiddler = state.wiki.getTiddler(title);
if(tiddler) {
fields.text = tiddler.fields.text;
}
delete fields._is_skinny;
}
state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title}));
var changeCount = state.wiki.getChangeCount(title).toString();
response.writeHead(204, "OK",{
Etag: "\"default/" + encodeURIComponent(title) + "/" + changeCount + ":\"",
"Content-Type": "text/plain"
});
response.end();
};

View File

@@ -1,378 +0,0 @@
/*\
title: $:/core/modules/server/server.js
type: application/javascript
module-type: library
Serve tiddlers over http
\*/
"use strict";
if($tw.node) {
var util = require("util"),
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
}
/*
A simple HTTP server with regexp-based routes
options: variables - optional hashmap of variables to set (a misnomer - they are really constant parameters)
routes - optional array of routes to use
wiki - reference to wiki object
*/
function Server(options) {
var self = this;
this.routes = options.routes || [];
this.authenticators = options.authenticators || [];
this.wiki = options.wiki;
this.boot = options.boot || $tw.boot;
// Initialise the variables
this.variables = $tw.utils.extend({},this.defaultVariables);
if(options.variables) {
for(var variable in options.variables) {
if(options.variables[variable]) {
this.variables[variable] = options.variables[variable];
}
}
}
// Setup the default required plugins
this.requiredPlugins = this.get("required-plugins").split(',');
// Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression
this.enableGzip = this.get("gzip") === "yes";
// Initialize browser-caching
this.enableBrowserCache = this.get("use-browser-cache") === "yes";
// Initialise authorization
var authorizedUserName;
if(this.get("username") && this.get("password")) {
authorizedUserName = this.get("username");
} else if(this.get("credentials")) {
authorizedUserName = "(authenticated)";
} else {
authorizedUserName = "(anon)";
}
this.authorizationPrincipals = {
readers: (this.get("readers") || authorizedUserName).split(",").map($tw.utils.trim),
writers: (this.get("writers") || authorizedUserName).split(",").map($tw.utils.trim)
}
if(this.get("admin") || authorizedUserName !== "(anon)") {
this.authorizationPrincipals["admin"] = (this.get("admin") || authorizedUserName).split(',').map($tw.utils.trim)
}
// Load and initialise authenticators
$tw.modules.forEachModuleOfType("authenticator", function(title,authenticatorDefinition) {
// console.log("Loading authenticator " + title);
self.addAuthenticator(authenticatorDefinition.AuthenticatorClass);
});
// Load route handlers
$tw.modules.forEachModuleOfType("route", function(title,routeDefinition) {
// console.log("Loading server route " + title);
self.addRoute(routeDefinition);
});
this.routes.sort((a, b) => {
const priorityA = a.info?.priority ?? 100,
priorityB = b.info?.priority ?? 100;
return priorityB - priorityA;
});
// Initialise the http vs https
this.listenOptions = null;
this.protocol = "http";
var tlsKeyFilepath = this.get("tls-key"),
tlsCertFilepath = this.get("tls-cert"),
tlsPassphrase = this.get("tls-passphrase");
if(tlsCertFilepath && tlsKeyFilepath) {
this.listenOptions = {
key: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsKeyFilepath),"utf8"),
cert: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsCertFilepath),"utf8"),
passphrase: tlsPassphrase || ''
};
this.protocol = "https";
}
this.transport = require(this.protocol);
// Name the server and init the boot state
this.servername = $tw.utils.transliterateToSafeASCII(this.get("server-name") || this.wiki.getTiddlerText("$:/SiteTitle") || "TiddlyWiki5");
this.boot.origin = this.get("origin")? this.get("origin"): this.protocol+"://"+this.get("host")+":"+this.get("port");
this.boot.pathPrefix = this.get("path-prefix") || "";
}
/*
Send a response to the client. This method checks if the response must be sent
or if the client alrady has the data cached. If that's the case only a 304
response will be transmitted and the browser will use the cached data.
Only requests with status code 200 are considdered for caching.
request: request instance passed to the handler
response: response instance passed to the handler
statusCode: stauts code to send to the browser
headers: response headers (they will be augmented with an `Etag` header)
data: the data to send (passed to the end method of the response instance)
encoding: the encoding of the data to send (passed to the end method of the response instance)
*/
function sendResponse(request,response,statusCode,headers,data,encoding) {
if(this.enableBrowserCache && (statusCode == 200)) {
var hash = crypto.createHash('md5');
// Put everything into the hash that could change and invalidate the data that
// the browser already stored. The headers the data and the encoding.
hash.update(data);
hash.update(JSON.stringify(headers));
if(encoding) {
hash.update(encoding);
}
var contentDigest = hash.digest("hex");
// RFC 7232 section 2.3 mandates for the etag to be enclosed in quotes
headers["Etag"] = '"' + contentDigest + '"';
headers["Cache-Control"] = "max-age=0, must-revalidate";
// Check if any of the hashes contained within the if-none-match header
// matches the current hash.
// If one matches, do not send the data but tell the browser to use the
// cached data.
// We do not implement "*" as it makes no sense here.
var ifNoneMatch = request.headers["if-none-match"];
if(ifNoneMatch) {
var matchParts = ifNoneMatch.split(",").map(function(etag) {
return etag.replace(/^[ "]+|[ "]+$/g, "");
});
if(matchParts.indexOf(contentDigest) != -1) {
response.writeHead(304,headers);
response.end();
return;
}
}
} else {
// RFC 7231, 6.1. Overview of Status Codes:
// Browser clients may cache 200, 203, 204, 206, 300, 301,
// 404, 405, 410, 414, and 501 unless given explicit cache controls
headers["Cache-Control"] = headers["Cache-Control"] || "no-store";
}
/*
If the gzip=yes is set, check if the user agent permits compression. If so,
compress our response if the raw data is bigger than 2k. Compressing less
data is inefficient. Note that we use the synchronous functions from zlib
to stay in the imperative style. The current `Server` doesn't depend on
this, and we may just as well use the async versions.
*/
if(this.enableGzip && (data.length > 2048)) {
var acceptEncoding = request.headers["accept-encoding"] || "";
if(/\bdeflate\b/.test(acceptEncoding)) {
headers["Content-Encoding"] = "deflate";
data = zlib.deflateSync(data);
} else if(/\bgzip\b/.test(acceptEncoding)) {
headers["Content-Encoding"] = "gzip";
data = zlib.gzipSync(data);
}
}
response.writeHead(statusCode,headers);
response.end(data,encoding);
}
Server.prototype.defaultVariables = {
port: "8080",
host: "127.0.0.1",
"required-plugins": "$:/plugins/tiddlywiki/filesystem,$:/plugins/tiddlywiki/tiddlyweb",
"root-tiddler": "$:/core/save/all",
"root-render-type": "text/plain",
"root-serve-type": "text/html",
"tiddler-render-type": "text/html",
"tiddler-render-template": "$:/core/templates/server/static.tiddler.html",
"system-tiddler-render-type": "text/plain",
"system-tiddler-render-template": "$:/core/templates/wikified-tiddler",
"debug-level": "none",
"gzip": "no",
"use-browser-cache": "no"
};
Server.prototype.get = function(name) {
return this.variables[name];
};
Server.prototype.addRoute = function(route) {
this.routes.push(route);
};
Server.prototype.addAuthenticator = function(AuthenticatorClass) {
// Instantiate and initialise the authenticator
var authenticator = new AuthenticatorClass(this),
result = authenticator.init();
if(typeof result === "string") {
$tw.utils.error("Error: " + result);
} else if(result) {
// Only use the authenticator if it initialised successfully
this.authenticators.push(authenticator);
}
};
Server.prototype.findMatchingRoute = function(request,state) {
for(var t=0; t<this.routes.length; t++) {
var potentialRoute = this.routes[t],
pathRegExp = potentialRoute.path,
pathname = state.urlInfo.pathname,
match;
if(state.pathPrefix) {
if(pathname.substr(0,state.pathPrefix.length) === state.pathPrefix) {
pathname = pathname.substr(state.pathPrefix.length) || "/";
match = potentialRoute.path.exec(pathname);
} else {
match = false;
}
} else {
match = potentialRoute.path.exec(pathname);
}
if(match && (potentialRoute.methods?.includes(request.method) || potentialRoute.method === request.method)) {
state.params = [];
for(var p=1; p<match.length; p++) {
state.params.push(match[p]);
}
return potentialRoute;
}
}
return null;
};
Server.prototype.methodMappings = {
"GET": "readers",
"OPTIONS": "readers",
"HEAD": "readers",
"PUT": "writers",
"POST": "writers",
"DELETE": "writers"
};
/*
Check whether a given user is authorized for the specified authorizationType ("readers" or "writers"). Pass null or undefined as the username to check for anonymous access
*/
Server.prototype.isAuthorized = function(authorizationType,username) {
var principals = this.authorizationPrincipals[authorizationType] || [];
return principals.indexOf("(anon)") !== -1 || (username && (principals.indexOf("(authenticated)") !== -1 || principals.indexOf(username) !== -1));
}
Server.prototype.requestHandler = function(request,response,options) {
options = options || {};
// Compose the state object
var self = this;
var state = {};
state.wiki = options.wiki || self.wiki;
state.boot = options.boot || self.boot;
state.server = self;
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
state.sendResponse = sendResponse.bind(self,request,response);
// Get the principals authorized to access this resource
state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers";
// Check for the CSRF header if this is a write
if(!this.csrfDisable && state.authorizationType === "writers" && request.headers["x-requested-with"] !== "TiddlyWiki") {
response.writeHead(403,"'X-Requested-With' header required to login to '" + this.servername + "'");
response.end();
return;
}
// Check whether anonymous access is granted
state.allowAnon = this.isAuthorized(state.authorizationType,null);
// Authenticate with the first active authenticator
if(this.authenticators.length > 0) {
if(!this.authenticators[0].authenticateRequest(request,response,state)) {
// Bail if we failed (the authenticator will have sent the response)
return;
}
}
// Authorize with the authenticated username
if(!this.isAuthorized(state.authorizationType,state.authenticatedUsername)) {
response.writeHead(401,"'" + state.authenticatedUsername + "' is not authorized to access '" + this.servername + "'");
response.end();
return;
}
// Find the route that matches this path
var route = self.findMatchingRoute(request,state);
// Optionally output debug info
if(self.get("debug-level") !== "none") {
console.log("Request path:",JSON.stringify(state.urlInfo));
console.log("Request headers:",JSON.stringify(request.headers));
console.log("authenticatedUsername:",state.authenticatedUsername);
}
// Return a 404 if we didn't find a route
if(!route) {
response.writeHead(404);
response.end();
return;
}
// Receive the request body if necessary and hand off to the route handler
if(route.bodyFormat === "stream" || request.method === "GET" || request.method === "HEAD") {
// Let the route handle the request stream itself
route.handler(request,response,state);
} else if(route.bodyFormat === "string" || !route.bodyFormat) {
// Set the encoding for the incoming request
request.setEncoding("utf8");
var data = "";
request.on("data",function(chunk) {
data += chunk.toString();
});
request.on("end",function() {
state.data = data;
route.handler(request,response,state);
});
} else if(route.bodyFormat === "buffer") {
var data = [];
request.on("data",function(chunk) {
data.push(chunk);
});
request.on("end",function() {
state.data = Buffer.concat(data);
route.handler(request,response,state);
})
} else {
response.writeHead(400,"Invalid bodyFormat " + route.bodyFormat + " in route " + route.method + " " + route.path.source);
response.end();
}
};
/*
Listen for requests
port: optional port number (falls back to value of "port" variable)
host: optional host address (falls back to value of "host" variable)
prefix: optional prefix (falls back to value of "path-prefix" variable)
*/
Server.prototype.listen = function(port,host,prefix) {
var self = this;
// Handle defaults for port and host
port = port || this.get("port");
host = host || this.get("host");
prefix = prefix || this.get("path-prefix") || "";
// Check for the port being a string and look it up as an environment variable
if(parseInt(port,10).toString() !== port) {
port = process.env[port] || 8080;
}
// Warn if required plugins are missing
var missing = [];
for (var index=0; index<this.requiredPlugins.length; index++) {
if (!this.wiki.getTiddler(this.requiredPlugins[index])) {
missing.push(this.requiredPlugins[index]);
}
}
if(missing.length > 0) {
var error = "Warning: Plugin(s) required for client-server operation are missing.\n"+
"\""+ missing.join("\", \"")+"\"";
$tw.utils.warning(error);
}
// Create the server
var server;
if(this.listenOptions) {
server = this.transport.createServer(this.listenOptions,this.requestHandler.bind(this));
} else {
server = this.transport.createServer(this.requestHandler.bind(this));
}
// Display the port number after we've started listening (the port number might have been specified as zero, in which case we will get an assigned port)
server.on("listening",function() {
var address = server.address(),
url = self.protocol + "://" + (address.family === "IPv6" ? "[" + address.address + "]" : address.address) + ":" + address.port + prefix;
$tw.utils.log("Serving on " + url,"brown/orange");
$tw.utils.log("(press ctrl-C to exit)","red");
});
// Listen
return server.listen(port,host);
};
exports.Server = Server;

View File

@@ -1,32 +0,0 @@
/*\
title: $:/core/modules/startup/commands.js
type: application/javascript
module-type: startup
Command processing
\*/
"use strict";
// Export name and synchronous status
exports.name = "commands";
exports.platforms = ["node"];
exports.after = ["story"];
exports.synchronous = false;
exports.startup = function(callback) {
// On the server, start a commander with the command line arguments
var commander = new $tw.Commander(
$tw.boot.argv,
function(err) {
if(err) {
return $tw.utils.error("Error: " + err);
}
callback();
},
$tw.wiki,
{output: process.stdout, error: process.stderr}
);
commander.execute();
};

View File

@@ -1,43 +0,0 @@
/*\
title: $:/core/modules/utils/edition-info.js
type: application/javascript
module-type: utils-node
Information about the available editions
\*/
"use strict";
var fs = require("fs"),
path = require("path");
var editionInfo;
exports.getEditionInfo = function() {
if(!editionInfo) {
// Enumerate the edition paths
var editionPaths = $tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar);
editionInfo = {};
for(var editionIndex=0; editionIndex<editionPaths.length; editionIndex++) {
var editionPath = editionPaths[editionIndex];
// Enumerate the folders
var entries = fs.readdirSync(editionPath);
for(var entryIndex=0; entryIndex<entries.length; entryIndex++) {
var entry = entries[entryIndex];
// Check if directories have a valid tiddlywiki.info
// Check if the entry is a hidden directory
if((entry.charAt(0) !== ".") && !editionInfo[entry] && $tw.utils.isDirectory(path.resolve(editionPath,entry))) {
var file=path.resolve(editionPath,entry,"tiddlywiki.info");
if(fs.existsSync(file)) {
var info = $tw.utils.parseJSONSafe(fs.readFileSync(file,"utf8"),null);
if(info) {
editionInfo[entry] = info;
}
}
}
}
}
}
return editionInfo;
};

View File

@@ -1,46 +0,0 @@
/*\
title: $:/core/modules/utils/repository.js
type: application/javascript
module-type: utils
Utilities for working with the TiddlyWiki repository file structure
\*/
"use strict";
/*
Get an object containing all the plugins as a hashmap by title of the JSON representation of the plugin
Options:
ignoreEnvironmentVariables: defaults to false
*/
exports.getAllPlugins = function(options) {
options = options || {};
var fs = require("fs"),
path = require("path"),
tiddlers = {};
// Collect up the library plugins
var collectPlugins = function(folder) {
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
for(var p=0; p<pluginFolders.length; p++) {
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
var pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
if(pluginFields && pluginFields.title) {
tiddlers[pluginFields.title] = pluginFields;
}
}
}
},
collectPublisherPlugins = function(folder) {
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
for(var t=0; t<publisherFolders.length; t++) {
if(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {
collectPlugins(path.resolve(folder,"./" + publisherFolders[t]));
}
}
};
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.pluginsEnvVar),collectPublisherPlugins);
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.themesEnvVar),collectPublisherPlugins);
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.languagesEnvVar),collectPlugins);
return tiddlers;
};

View File

@@ -3,5 +3,9 @@ title: $:/Acknowledgements
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]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
And media from these projects:
* World flag icons from [[Wikipedia|http://commons.wikimedia.org/wiki/Category:SVG_flags_by_country]]

View File

@@ -4,7 +4,7 @@ type: text/plain
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
Copyright (c) 2007-2025, UnaMesa Association
Copyright (c) 2007-2021, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,4 @@
title: $:/core/icon
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> viewBox="0 0 128 128"><path d="M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 15.594 1.114 1.94 4.226 2.652 3.02 4.406-.37.58-.936.785-1.54 1.01l-.82.11zm-40.097-8.85l.553.14c.694-.27 2.09.15 2.83.353-1.363-1.31-3.417-3.24-4.897-4.46-.485-1.47-.278-2.96-.174-4.46l.02-.123c-.582 1.205-1.322 2.376-1.72 3.645-.465 1.71 2.07 3.557 3.052 4.615l.336.3z" fill-rule="evenodd"/></svg>
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path d="M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 15.594 1.114 1.94 4.226 2.652 3.02 4.406-.37.58-.936.785-1.54 1.01l-.82.11zm-40.097-8.85l.553.14c.694-.27 2.09.15 2.83.353-1.363-1.31-3.417-3.24-4.897-4.46-.485-1.47-.278-2.96-.174-4.46l.02-.123c-.582 1.205-1.322 2.376-1.72 3.645-.465 1.71 2.07 3.557 3.052 4.615l.336.3z" fill-rule="evenodd"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/add-comment
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-add-comment tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M56 56H36a8 8 0 100 16h20v20a8 8 0 1016 0V72h20a8 8 0 100-16H72V36a8 8 0 10-16 0v20zm-12.595 58.362c-6.683 7.659-20.297 12.903-36.006 12.903-2.196 0-4.35-.102-6.451-.3 9.652-3.836 17.356-12.24 21.01-22.874C8.516 94.28 0 79.734 0 63.5 0 33.953 28.206 10 63 10s63 23.953 63 53.5S97.794 117 63 117c-6.841 0-13.428-.926-19.595-2.638z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-add-comment tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M56 56H36a8 8 0 100 16h20v20a8 8 0 1016 0V72h20a8 8 0 100-16H72V36a8 8 0 10-16 0v20zm-12.595 58.362c-6.683 7.659-20.297 12.903-36.006 12.903-2.196 0-4.35-.102-6.451-.3 9.652-3.836 17.356-12.24 21.01-22.874C8.516 94.28 0 79.734 0 63.5 0 33.953 28.206 10 63 10s63 23.953 63 53.5S97.794 117 63 117c-6.841 0-13.428-.926-19.595-2.638z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/advanced-search-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-advanced-search-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M74.565 87.985A47.776 47.776 0 0148 96C21.49 96 0 74.51 0 48S21.49 0 48 0s48 21.49 48 48c0 9.854-2.97 19.015-8.062 26.636l34.347 34.347a9.443 9.443 0 010 13.36 9.446 9.446 0 01-13.36 0l-34.36-34.358zM48 80c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z"/><circle cx="48" cy="48" r="8"/><circle cx="28" cy="48" r="8"/><circle cx="68" cy="48" r="8"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-advanced-search-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M74.565 87.985A47.776 47.776 0 0148 96C21.49 96 0 74.51 0 48S21.49 0 48 0s48 21.49 48 48c0 9.854-2.97 19.015-8.062 26.636l34.347 34.347a9.443 9.443 0 010 13.36 9.446 9.446 0 01-13.36 0l-34.36-34.358zM48 80c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z"/><circle cx="48" cy="48" r="8"/><circle cx="28" cy="48" r="8"/><circle cx="68" cy="48" r="8"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/auto-height
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-auto-height tc-image-button" viewBox="0 0 128 128"><path d="M67.987 114.356l-.029-14.477a4 4 0 00-2.067-3.494l-15.966-8.813-1.933 7.502H79.9c4.222 0 5.564-5.693 1.786-7.58L49.797 71.572 48.01 79.15h31.982c4.217 0 5.564-5.682 1.795-7.575L49.805 55.517l-1.795 7.575h31.982c4.212 0 5.563-5.67 1.805-7.57l-16.034-8.105 2.195 3.57V35.614l9.214 9.213a4 4 0 105.656-5.656l-16-16a4 4 0 00-5.656 0l-16 16a4 4 0 105.656 5.656l9.13-9.13v15.288a4 4 0 002.195 3.57l16.035 8.106 1.804-7.57H48.01c-4.217 0-5.564 5.682-1.795 7.574l31.982 16.059 1.795-7.575H48.01c-4.222 0-5.564 5.693-1.787 7.579l31.89 15.923 1.787-7.578H47.992c-4.133 0-5.552 5.504-1.933 7.501l15.966 8.813-2.067-3.494.029 14.436-9.159-9.158a4 4 0 00-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656l-9.185 9.184zM16 20h96a4 4 0 100-8H16a4 4 0 100 8z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-auto-height tc-image-button" viewBox="0 0 128 128"><path d="M67.987 114.356l-.029-14.477a4 4 0 00-2.067-3.494l-15.966-8.813-1.933 7.502H79.9c4.222 0 5.564-5.693 1.786-7.58L49.797 71.572 48.01 79.15h31.982c4.217 0 5.564-5.682 1.795-7.575L49.805 55.517l-1.795 7.575h31.982c4.212 0 5.563-5.67 1.805-7.57l-16.034-8.105 2.195 3.57V35.614l9.214 9.213a4 4 0 105.656-5.656l-16-16a4 4 0 00-5.656 0l-16 16a4 4 0 105.656 5.656l9.13-9.13v15.288a4 4 0 002.195 3.57l16.035 8.106 1.804-7.57H48.01c-4.217 0-5.564 5.682-1.795 7.574l31.982 16.059 1.795-7.575H48.01c-4.222 0-5.564 5.693-1.787 7.579l31.89 15.923 1.787-7.578H47.992c-4.133 0-5.552 5.504-1.933 7.501l15.966 8.813-2.067-3.494.029 14.436-9.159-9.158a4 4 0 00-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656l-9.185 9.184zM16 20h96a4 4 0 100-8H16a4 4 0 100 8z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/blank
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-blank tc-image-button" viewBox="0 0 128 128"/>
<svg width="22pt" height="22pt" class="tc-image-blank tc-image-button" viewBox="0 0 128 128"/>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/bold
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-bold tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M41.146 51.81V21.87h26.353c2.51 0 4.93.21 7.26.628 2.33.418 4.392 1.165 6.185 2.24 1.793 1.076 3.227 2.57 4.302 4.482 1.076 1.913 1.614 4.363 1.614 7.35 0 5.379-1.613 9.263-4.84 11.653-3.227 2.39-7.35 3.586-12.37 3.586H41.146zM13 0v128h62.028a65.45 65.45 0 0016.762-2.151c5.438-1.434 10.278-3.645 14.52-6.633 4.244-2.988 7.62-6.842 10.13-11.563 2.51-4.721 3.764-10.308 3.764-16.762 0-8.008-1.942-14.85-5.826-20.527-3.884-5.677-9.77-9.65-17.658-11.921 5.737-2.75 10.069-6.275 12.997-10.577 2.928-4.303 4.392-9.681 4.392-16.135 0-5.976-.986-10.995-2.958-15.059-1.972-4.063-4.75-7.32-8.336-9.77-3.585-2.45-7.888-4.213-12.907-5.289C84.888.538 79.33 0 73.235 0H13zm28.146 106.129V70.992H71.8c6.095 0 10.995 1.404 14.7 4.212 3.705 2.81 5.558 7.5 5.558 14.073 0 3.347-.568 6.096-1.703 8.247-1.136 2.151-2.66 3.854-4.572 5.11-1.912 1.254-4.123 2.15-6.633 2.688-2.51.538-5.139.807-7.888.807H41.146z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-bold tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M41.146 51.81V21.87h26.353c2.51 0 4.93.21 7.26.628 2.33.418 4.392 1.165 6.185 2.24 1.793 1.076 3.227 2.57 4.302 4.482 1.076 1.913 1.614 4.363 1.614 7.35 0 5.379-1.613 9.263-4.84 11.653-3.227 2.39-7.35 3.586-12.37 3.586H41.146zM13 0v128h62.028a65.45 65.45 0 0016.762-2.151c5.438-1.434 10.278-3.645 14.52-6.633 4.244-2.988 7.62-6.842 10.13-11.563 2.51-4.721 3.764-10.308 3.764-16.762 0-8.008-1.942-14.85-5.826-20.527-3.884-5.677-9.77-9.65-17.658-11.921 5.737-2.75 10.069-6.275 12.997-10.577 2.928-4.303 4.392-9.681 4.392-16.135 0-5.976-.986-10.995-2.958-15.059-1.972-4.063-4.75-7.32-8.336-9.77-3.585-2.45-7.888-4.213-12.907-5.289C84.888.538 79.33 0 73.235 0H13zm28.146 106.129V70.992H71.8c6.095 0 10.995 1.404 14.7 4.212 3.705 2.81 5.558 7.5 5.558 14.073 0 3.347-.568 6.096-1.703 8.247-1.136 2.151-2.66 3.854-4.572 5.11-1.912 1.254-4.123 2.15-6.633 2.688-2.51.538-5.139.807-7.888.807H41.146z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/cancel-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-cancel-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M64 76.314l-16.97 16.97a7.999 7.999 0 01-11.314 0c-3.118-3.118-3.124-8.19 0-11.313L52.686 65l-16.97-16.97a7.999 7.999 0 010-11.314c3.118-3.118 8.19-3.124 11.313 0L64 53.686l16.97-16.97a7.999 7.999 0 0111.314 0c3.118 3.118 3.124 8.19 0 11.313L75.314 65l16.97 16.97a7.999 7.999 0 010 11.314c-3.118 3.118-8.19 3.124-11.313 0L64 76.314zM64 129c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 1 0 29.654 0 65c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 17 64 17 16 38.49 16 65s21.49 48 48 48z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-cancel-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M64 76.314l-16.97 16.97a7.999 7.999 0 01-11.314 0c-3.118-3.118-3.124-8.19 0-11.313L52.686 65l-16.97-16.97a7.999 7.999 0 010-11.314c3.118-3.118 8.19-3.124 11.313 0L64 53.686l16.97-16.97a7.999 7.999 0 0111.314 0c3.118 3.118 3.124 8.19 0 11.313L75.314 65l16.97 16.97a7.999 7.999 0 010 11.314c-3.118 3.118-8.19 3.124-11.313 0L64 76.314zM64 129c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 1 0 29.654 0 65c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 17 64 17 16 38.49 16 65s21.49 48 48 48z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/chevron-down
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-chevron-down tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M64.053 85.456a7.889 7.889 0 01-5.6-2.316L2.473 27.16a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0L64.05 66.344l50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.105 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.317z"/><path d="M64.053 124.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-chevron-down tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M64.053 85.456a7.889 7.889 0 01-5.6-2.316L2.473 27.16a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0L64.05 66.344l50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.105 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.317z"/><path d="M64.053 124.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/chevron-left
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-chevron-left tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M47.544 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L66.656 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.105 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.317-5.595z"/><path d="M8.931 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L28.041 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.104 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.316-5.595z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-chevron-left tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M47.544 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L66.656 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.105 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.317-5.595z"/><path d="M8.931 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L28.041 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.104 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.316-5.595z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/chevron-right
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-chevron-right tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M83.456 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196L64.344 63.95 13.963 13.567a7.92 7.92 0 010-11.195c3.086-3.085 8.105-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.317 5.595z"/><path d="M122.069 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-chevron-right tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M83.456 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196L64.344 63.95 13.963 13.567a7.92 7.92 0 010-11.195c3.086-3.085 8.105-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.317 5.595z"/><path d="M122.069 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/chevron-up
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-chevron-up tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M63.947 44.544c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 63.656l-50.382 50.382a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.317z"/><path d="M63.947 5.931c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 25.041 13.567 75.423a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.104 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.316z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-chevron-up tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M63.947 44.544c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 63.656l-50.382 50.382a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.317z"/><path d="M63.947 5.931c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 25.041 13.567 75.423a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.104 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.316z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/clone-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-clone-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M32.265 96v24.002A7.996 7.996 0 0040.263 128h79.74a7.996 7.996 0 007.997-7.998v-79.74a7.996 7.996 0 00-7.998-7.997H96V48h12.859a2.99 2.99 0 012.994 2.994v57.865a2.99 2.99 0 01-2.994 2.994H50.994A2.99 2.99 0 0148 108.859V96H32.265z"/><path d="M40 56h-7.993C27.588 56 24 52.418 24 48c0-4.41 3.585-8 8.007-8H40v-7.993C40 27.588 43.582 24 48 24c4.41 0 8 3.585 8 8.007V40h7.993C68.412 40 72 43.582 72 48c0 4.41-3.585 8-8.007 8H56v7.993C56 68.412 52.418 72 48 72c-4.41 0-8-3.585-8-8.007V56zM8 0C3.58 0 0 3.588 0 8v80c0 4.419 3.588 8 8 8h80c4.419 0 8-3.588 8-8V8c0-4.419-3.588-8-8-8H8zM19 16A2.997 2.997 0 0016 19.001v57.998A2.997 2.997 0 0019.001 80h57.998A2.997 2.997 0 0080 76.999V19.001A2.997 2.997 0 0076.999 16H19.001z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-clone-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M32.265 96v24.002A7.996 7.996 0 0040.263 128h79.74a7.996 7.996 0 007.997-7.998v-79.74a7.996 7.996 0 00-7.998-7.997H96V48h12.859a2.99 2.99 0 012.994 2.994v57.865a2.99 2.99 0 01-2.994 2.994H50.994A2.99 2.99 0 0148 108.859V96H32.265z"/><path d="M40 56h-7.993C27.588 56 24 52.418 24 48c0-4.41 3.585-8 8.007-8H40v-7.993C40 27.588 43.582 24 48 24c4.41 0 8 3.585 8 8.007V40h7.993C68.412 40 72 43.582 72 48c0 4.41-3.585 8-8.007 8H56v7.993C56 68.412 52.418 72 48 72c-4.41 0-8-3.585-8-8.007V56zM8 0C3.58 0 0 3.588 0 8v80c0 4.419 3.588 8 8 8h80c4.419 0 8-3.588 8-8V8c0-4.419-3.588-8-8-8H8zM19 16A2.997 2.997 0 0016 19.001v57.998A2.997 2.997 0 0019.001 80h57.998A2.997 2.997 0 0080 76.999V19.001A2.997 2.997 0 0076.999 16H19.001z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/close-all-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-close-all-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M28 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L16.686 100 2.543 85.856a8 8 0 0111.313-11.313L28 88.686l14.144-14.143a8 8 0 0111.313 11.313L39.314 100l14.143 14.144a8 8 0 01-11.313 11.313L28 111.314zM28 39.314L13.856 53.457A8 8 0 012.543 42.144L16.686 28 2.543 13.856A8 8 0 0113.856 2.543L28 16.686 42.144 2.543a8 8 0 0111.313 11.313L39.314 28l14.143 14.144a8 8 0 01-11.313 11.313L28 39.314zM100 39.314L85.856 53.457a8 8 0 01-11.313-11.313L88.686 28 74.543 13.856A8 8 0 0185.856 2.543L100 16.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 28l14.143 14.144a8 8 0 01-11.313 11.313L100 39.314zM100 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L88.686 100 74.543 85.856a8 8 0 0111.313-11.313L100 88.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 100l14.143 14.144a8 8 0 01-11.313 11.313L100 111.314z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-close-all-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M28 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L16.686 100 2.543 85.856a8 8 0 0111.313-11.313L28 88.686l14.144-14.143a8 8 0 0111.313 11.313L39.314 100l14.143 14.144a8 8 0 01-11.313 11.313L28 111.314zM28 39.314L13.856 53.457A8 8 0 012.543 42.144L16.686 28 2.543 13.856A8 8 0 0113.856 2.543L28 16.686 42.144 2.543a8 8 0 0111.313 11.313L39.314 28l14.143 14.144a8 8 0 01-11.313 11.313L28 39.314zM100 39.314L85.856 53.457a8 8 0 01-11.313-11.313L88.686 28 74.543 13.856A8 8 0 0185.856 2.543L100 16.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 28l14.143 14.144a8 8 0 01-11.313 11.313L100 39.314zM100 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L88.686 100 74.543 85.856a8 8 0 0111.313-11.313L100 88.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 100l14.143 14.144a8 8 0 01-11.313 11.313L100 111.314z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/close-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-close-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M65.086 75.41l-50.113 50.113c-3.121 3.121-8.192 3.126-11.316.002-3.118-3.118-3.123-8.19.002-11.316l50.114-50.114L3.659 13.982C.538 10.86.533 5.79 3.657 2.666c3.118-3.118 8.19-3.123 11.316.002l50.113 50.114L115.2 2.668c3.121-3.121 8.192-3.126 11.316-.002 3.118 3.118 3.123 8.19-.002 11.316L76.4 64.095l50.114 50.114c3.121 3.121 3.126 8.192.002 11.316-3.118 3.118-8.19 3.123-11.316-.002L65.086 75.409z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-close-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M65.086 75.41l-50.113 50.113c-3.121 3.121-8.192 3.126-11.316.002-3.118-3.118-3.123-8.19.002-11.316l50.114-50.114L3.659 13.982C.538 10.86.533 5.79 3.657 2.666c3.118-3.118 8.19-3.123 11.316.002l50.113 50.114L115.2 2.668c3.121-3.121 8.192-3.126 11.316-.002 3.118 3.118 3.123 8.19-.002 11.316L76.4 64.095l50.114 50.114c3.121 3.121 3.126 8.192.002 11.316-3.118 3.118-8.19 3.123-11.316-.002L65.086 75.409z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/close-others-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-close-others-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48zm0-16c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32zm0-16c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-close-others-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48zm0-16c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32zm0-16c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/copy-clipboard
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-copy-clipboard tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><rect width="33" height="8" x="40" y="40" rx="4"/><rect width="17" height="8" x="40" y="82" rx="4"/><rect width="17" height="8" x="40" y="54" rx="4"/><rect width="33" height="8" x="40" y="96" rx="4"/><rect width="12" height="8" x="40" y="68" rx="4"/><path d="M40 16H24c-4.419 0-8 3.59-8 8a8.031 8.031 0 000 .01v95.98a8.03 8.03 0 000 .01c0 4.41 3.581 8 8 8h80a7.975 7.975 0 005.652-2.34 7.958 7.958 0 002.348-5.652v-16.016c0-4.414-3.582-7.992-8-7.992-4.41 0-8 3.578-8 7.992V112H32V32h64v8.008C96 44.422 99.582 48 104 48c4.41 0 8-3.578 8-7.992V23.992a7.963 7.963 0 00-2.343-5.651A7.995 7.995 0 00104.001 16H88c0-4.41-3.585-8-8.007-8H48.007C43.588 8 40 11.582 40 16zm4-1.004A4.001 4.001 0 0148 11h32c2.21 0 4 1.797 4 3.996v4.008A4.001 4.001 0 0180 23H48c-2.21 0-4-1.797-4-3.996v-4.008z"/><rect width="66" height="16" x="62" y="64" rx="8"/><path d="M84.657 82.343l-16-16v11.314l16-16a8 8 0 10-11.314-11.314l-16 16a8 8 0 000 11.314l16 16a8 8 0 1011.314-11.314z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-copy-clipboard tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><rect width="33" height="8" x="40" y="40" rx="4"/><rect width="17" height="8" x="40" y="82" rx="4"/><rect width="17" height="8" x="40" y="54" rx="4"/><rect width="33" height="8" x="40" y="96" rx="4"/><rect width="12" height="8" x="40" y="68" rx="4"/><path d="M40 16H24c-4.419 0-8 3.59-8 8a8.031 8.031 0 000 .01v95.98a8.03 8.03 0 000 .01c0 4.41 3.581 8 8 8h80a7.975 7.975 0 005.652-2.34 7.958 7.958 0 002.348-5.652v-16.016c0-4.414-3.582-7.992-8-7.992-4.41 0-8 3.578-8 7.992V112H32V32h64v8.008C96 44.422 99.582 48 104 48c4.41 0 8-3.578 8-7.992V23.992a7.963 7.963 0 00-2.343-5.651A7.995 7.995 0 00104.001 16H88c0-4.41-3.585-8-8.007-8H48.007C43.588 8 40 11.582 40 16zm4-1.004A4.001 4.001 0 0148 11h32c2.21 0 4 1.797 4 3.996v4.008A4.001 4.001 0 0180 23H48c-2.21 0-4-1.797-4-3.996v-4.008z"/><rect width="66" height="16" x="62" y="64" rx="8"/><path d="M84.657 82.343l-16-16v11.314l16-16a8 8 0 10-11.314-11.314l-16 16a8 8 0 000 11.314l16 16a8 8 0 1011.314-11.314z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/delete-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-delete-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd" transform="translate(12)"><rect width="105" height="16" y="11" rx="8"/><rect width="48" height="16" x="28" rx="8"/><rect width="16" height="112" x="8" y="16" rx="8"/><rect width="88" height="16" x="8" y="112" rx="8"/><rect width="16" height="112" x="80" y="16" rx="8"/><rect width="16" height="112" x="56" y="16" rx="8"/><rect width="16" height="112" x="32" y="16" rx="8"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-delete-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd" transform="translate(12)"><rect width="105" height="16" y="11" rx="8"/><rect width="48" height="16" x="28" rx="8"/><rect width="16" height="112" x="8" y="16" rx="8"/><rect width="88" height="16" x="8" y="112" rx="8"/><rect width="16" height="112" x="80" y="16" rx="8"/><rect width="16" height="112" x="56" y="16" rx="8"/><rect width="16" height="112" x="32" y="16" rx="8"/></g></svg>

View File

@@ -1,5 +0,0 @@
title: $:/core/images/discord
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-discord tc-image-button" viewBox="0 -28.5 256 256"><path d="M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/done-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-done-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M42.26 111.032c-2.051.001-4.103-.78-5.668-2.345L2.662 74.758a8 8 0 01-.005-11.32c3.118-3.117 8.192-3.12 11.32.007l28.278 28.278 72.124-72.124a8.002 8.002 0 0111.314-.001c3.118 3.118 3.124 8.19 0 11.315l-77.78 77.78a7.978 7.978 0 01-5.658 2.343z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-done-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M42.26 111.032c-2.051.001-4.103-.78-5.668-2.345L2.662 74.758a8 8 0 01-.005-11.32c3.118-3.117 8.192-3.12 11.32.007l28.278 28.278 72.124-72.124a8.002 8.002 0 0111.314-.001c3.118 3.118 3.124 8.19 0 11.315l-77.78 77.78a7.978 7.978 0 01-5.658 2.343z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/down-arrow
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-down-arrow tc-image-button" viewBox="0 0 128 128"><path d="M64.177 100.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.086 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-down-arrow tc-image-button" viewBox="0 0 128 128"><path d="M64.177 100.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.086 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/download-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-download-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z" class="tc-image-download-button-ring"/><path d="M34.35 66.43l26.892 27.205a4.57 4.57 0 006.516 0L94.65 66.43a4.7 4.7 0 000-6.593 4.581 4.581 0 00-3.258-1.365h-8.46c-2.545 0-4.608-2.087-4.608-4.661v-15.15c0-2.575-2.063-4.662-4.608-4.662H55.284c-2.545 0-4.608 2.087-4.608 4.662v15.15c0 2.574-2.063 4.661-4.608 4.661h-8.46c-2.545 0-4.608 2.087-4.608 4.662a4.69 4.69 0 001.35 3.296z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-download-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z" class="tc-image-download-button-ring"/><path d="M34.35 66.43l26.892 27.205a4.57 4.57 0 006.516 0L94.65 66.43a4.7 4.7 0 000-6.593 4.581 4.581 0 00-3.258-1.365h-8.46c-2.545 0-4.608-2.087-4.608-4.661v-15.15c0-2.575-2.063-4.662-4.608-4.662H55.284c-2.545 0-4.608 2.087-4.608 4.662v15.15c0 2.574-2.063 4.661-4.608 4.661h-8.46c-2.545 0-4.608 2.087-4.608 4.662a4.69 4.69 0 001.35 3.296z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/edit-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-edit-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M95.627 10.059l-5.656 5.657 11.313 11.313 5.657-5.656-11.314-11.314zm5.657-5.657l1.966-1.966c3.123-3.122 8.194-3.129 11.319-.005 3.117 3.118 3.122 8.192-.005 11.32l-1.966 1.965-11.314-11.314zm-16.97 16.97l-60.25 60.25a8.12 8.12 0 00-.322.342c-.1.087-.198.179-.295.275-5.735 5.735-10.702 22.016-10.702 22.016s16.405-5.09 22.016-10.702c.095-.096.186-.193.272-.292a8.12 8.12 0 00.345-.325l60.25-60.25-11.314-11.313zM35.171 124.19c6.788-.577 13.898-2.272 23.689-5.348 1.825-.573 3.57-1.136 6.336-2.04 16-5.226 21.877-6.807 28.745-7.146 8.358-.413 13.854 2.13 17.58 8.699a4 4 0 006.959-3.946c-5.334-9.406-13.745-13.296-24.933-12.744-7.875.39-14.057 2.052-30.835 7.533-2.739.894-4.46 1.45-6.25 2.012-19.46 6.112-30.77 7.072-39.597 1.747a4 4 0 10-4.132 6.85c6.333 3.82 13.754 5.12 22.438 4.383z"/></g></svg>
<svg width="22pt" height="22pt" class="tc-image-edit-button tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M95.627 10.059l-5.656 5.657 11.313 11.313 5.657-5.656-11.314-11.314zm5.657-5.657l1.966-1.966c3.123-3.122 8.194-3.129 11.319-.005 3.117 3.118 3.122 8.192-.005 11.32l-1.966 1.965-11.314-11.314zm-16.97 16.97l-60.25 60.25a8.12 8.12 0 00-.322.342c-.1.087-.198.179-.295.275-5.735 5.735-10.702 22.016-10.702 22.016s16.405-5.09 22.016-10.702c.095-.096.186-.193.272-.292a8.12 8.12 0 00.345-.325l60.25-60.25-11.314-11.313zM35.171 124.19c6.788-.577 13.898-2.272 23.689-5.348 1.825-.573 3.57-1.136 6.336-2.04 16-5.226 21.877-6.807 28.745-7.146 8.358-.413 13.854 2.13 17.58 8.699a4 4 0 006.959-3.946c-5.334-9.406-13.745-13.296-24.933-12.744-7.875.39-14.057 2.052-30.835 7.533-2.739.894-4.46 1.45-6.25 2.012-19.46 6.112-30.77 7.072-39.597 1.747a4 4 0 10-4.132 6.85c6.333 3.82 13.754 5.12 22.438 4.383z"/></g></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/erase
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-erase tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M60.087 127.996l63.015-63.015c6.535-6.535 6.528-17.115-.003-23.646L99.466 17.702c-6.539-6.538-17.117-6.532-23.646-.003L4.898 88.62c-6.535 6.534-6.528 17.115.003 23.646l15.73 15.73h39.456zm-34.95-7.313l-14.324-14.325c-3.267-3.268-3.268-8.564-.008-11.824L46.269 59.07l35.462 35.462-26.15 26.15H25.137z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-erase tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M60.087 127.996l63.015-63.015c6.535-6.535 6.528-17.115-.003-23.646L99.466 17.702c-6.539-6.538-17.117-6.532-23.646-.003L4.898 88.62c-6.535 6.534-6.528 17.115.003 23.646l15.73 15.73h39.456zm-34.95-7.313l-14.324-14.325c-3.267-3.268-3.268-8.564-.008-11.824L46.269 59.07l35.462 35.462-26.15 26.15H25.137z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/excise
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-excise tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M56 107.314l-2.343 2.343a8 8 0 11-11.314-11.314l16-16a8 8 0 0111.314 0l16 16a8 8 0 11-11.314 11.314L72 107.314v14.284c0 3.536-3.582 6.402-8 6.402s-8-2.866-8-6.402v-14.284zM0 40.007C0 35.585 3.59 32 8 32c4.418 0 8 3.588 8 8.007v31.986C16 76.415 12.41 80 8 80c-4.418 0-8-3.588-8-8.007V40.007zm32 0C32 35.585 35.59 32 40 32c4.418 0 8 3.588 8 8.007v31.986C48 76.415 44.41 80 40 80c-4.418 0-8-3.588-8-8.007V40.007zm48 0C80 35.585 83.59 32 88 32c4.418 0 8 3.588 8 8.007v31.986C96 76.415 92.41 80 88 80c-4.418 0-8-3.588-8-8.007V40.007zm-24-32C56 3.585 59.59 0 64 0c4.418 0 8 3.588 8 8.007v31.986C72 44.415 68.41 48 64 48c-4.418 0-8-3.588-8-8.007V8.007zm56 32c0-4.422 3.59-8.007 8-8.007 4.418 0 8 3.588 8 8.007v31.986c0 4.422-3.59 8.007-8 8.007-4.418 0-8-3.588-8-8.007V40.007z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-excise tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M56 107.314l-2.343 2.343a8 8 0 11-11.314-11.314l16-16a8 8 0 0111.314 0l16 16a8 8 0 11-11.314 11.314L72 107.314v14.284c0 3.536-3.582 6.402-8 6.402s-8-2.866-8-6.402v-14.284zM0 40.007C0 35.585 3.59 32 8 32c4.418 0 8 3.588 8 8.007v31.986C16 76.415 12.41 80 8 80c-4.418 0-8-3.588-8-8.007V40.007zm32 0C32 35.585 35.59 32 40 32c4.418 0 8 3.588 8 8.007v31.986C48 76.415 44.41 80 40 80c-4.418 0-8-3.588-8-8.007V40.007zm48 0C80 35.585 83.59 32 88 32c4.418 0 8 3.588 8 8.007v31.986C96 76.415 92.41 80 88 80c-4.418 0-8-3.588-8-8.007V40.007zm-24-32C56 3.585 59.59 0 64 0c4.418 0 8 3.588 8 8.007v31.986C72 44.415 68.41 48 64 48c-4.418 0-8-3.588-8-8.007V8.007zm56 32c0-4.422 3.59-8.007 8-8.007 4.418 0 8 3.588 8 8.007v31.986c0 4.422-3.59 8.007-8 8.007-4.418 0-8-3.588-8-8.007V40.007z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/export-button
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-export-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M8.003 128H119.993a7.984 7.984 0 005.664-2.349v.007A7.975 7.975 0 00128 120V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v56H16V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v64c0 4.418 3.59 8 8 8h.003zm48.62-100.689l-8.965 8.966c-3.125 3.125-8.195 3.13-11.319.005-3.118-3.118-3.122-8.192.005-11.319L58.962 2.346A7.986 7.986 0 0164.625 0l-.006.002c2.05-.001 4.102.78 5.666 2.344l22.618 22.617c3.124 3.125 3.129 8.195.005 11.319-3.118 3.118-8.192 3.122-11.319-.005l-8.965-8.966v61.256c0 4.411-3.582 8-8 8-4.41 0-8-3.582-8-8V27.311z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-export-button tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M8.003 128H119.993a7.984 7.984 0 005.664-2.349v.007A7.975 7.975 0 00128 120V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v56H16V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v64c0 4.418 3.59 8 8 8h.003zm48.62-100.689l-8.965 8.966c-3.125 3.125-8.195 3.13-11.319.005-3.118-3.118-3.122-8.192.005-11.319L58.962 2.346A7.986 7.986 0 0164.625 0l-.006.002c2.05-.001 4.102.78 5.666 2.344l22.618 22.617c3.124 3.125 3.129 8.195.005 11.319-3.118 3.118-8.192 3.122-11.319-.005l-8.965-8.966v61.256c0 4.411-3.582 8-8 8-4.41 0-8-3.582-8-8V27.311z"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/file
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-file tc-image-button" viewBox="0 0 128 128"><path d="M111.968 30.5H112V120a8 8 0 01-8 8H24a8 8 0 01-8-8V8a8 8 0 018-8h57v.02a7.978 7.978 0 015.998 2.337l22.627 22.627a7.975 7.975 0 012.343 5.516zM81 8H24v112h80V30.5H89c-4.418 0-8-3.578-8-8V8z"/><rect width="64" height="8" x="32" y="36" rx="4"/><rect width="64" height="8" x="32" y="52" rx="4"/><rect width="64" height="8" x="32" y="68" rx="4"/><rect width="64" height="8" x="32" y="84" rx="4"/><rect width="64" height="8" x="32" y="100" rx="4"/><rect width="40" height="8" x="32" y="20" rx="4"/></svg>
<svg width="22pt" height="22pt" class="tc-image-file tc-image-button" viewBox="0 0 128 128"><path d="M111.968 30.5H112V120a8 8 0 01-8 8H24a8 8 0 01-8-8V8a8 8 0 018-8h57v.02a7.978 7.978 0 015.998 2.337l22.627 22.627a7.975 7.975 0 012.343 5.516zM81 8H24v112h80V30.5H89c-4.418 0-8-3.578-8-8V8z"/><rect width="64" height="8" x="32" y="36" rx="4"/><rect width="64" height="8" x="32" y="52" rx="4"/><rect width="64" height="8" x="32" y="68" rx="4"/><rect width="64" height="8" x="32" y="84" rx="4"/><rect width="64" height="8" x="32" y="100" rx="4"/><rect width="40" height="8" x="32" y="20" rx="4"/></svg>

View File

@@ -1,5 +1,4 @@
title: $:/core/images/fixed-height
tags: $:/tags/Image
\parameters (size:"22pt")
<svg width=<<size>> height=<<size>> class="tc-image-fixed-height tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M60 35.657l-9.172 9.171a4 4 0 11-5.656-5.656l16-16a4 4 0 015.656 0l16 16a4 4 0 01-5.656 5.656L68 35.657v57.686l9.172-9.171a4 4 0 115.656 5.656l-16 16a4 4 0 01-5.656 0l-16-16a4 4 0 115.656-5.656L60 93.343V35.657zM16 116h96a4 4 0 100-8H16a4 4 0 100 8zm0-96h96a4 4 0 100-8H16a4 4 0 100 8z"/></svg>
<svg width="22pt" height="22pt" class="tc-image-fixed-height tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M60 35.657l-9.172 9.171a4 4 0 11-5.656-5.656l16-16a4 4 0 015.656 0l16 16a4 4 0 01-5.656 5.656L68 35.657v57.686l9.172-9.171a4 4 0 115.656 5.656l-16 16a4 4 0 01-5.656 0l-16-16a4 4 0 115.656-5.656L60 93.343V35.657zM16 116h96a4 4 0 100-8H16a4 4 0 100 8zm0-96h96a4 4 0 100-8H16a4 4 0 100 8z"/></svg>

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