1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-23 11:24:40 +00:00

Compare commits

..

33 Commits

Author SHA1 Message Date
Jeremy Ruston
9d9b00bdb5 Merge branch 'master' into single-tiddler-mode 2020-04-02 11:45:01 +01:00
Jeremy Ruston
b88bfda0b4 Merge branch 'master' into single-tiddler-mode 2020-01-20 13:15:39 +00:00
Jeremy Ruston
834610cdb9 Restore single tiddler mode handling for zoomin
Thus avoiding the problem that performance slows after browsing many tiddlers in zoomin mode.
2020-01-20 08:34:18 +00:00
Jeremy Ruston
5272b13af1 Revert zoomin to old behaviour
Otherwise we break the animations
2020-01-18 10:36:33 +00:00
Jeremy Ruston
5f25b21c0d Introduce new "solo" storyview
It's a single tiddler view with no animation, hopefully more suitable for things like @kookma's presentation plugin.
2020-01-18 10:36:10 +00:00
Jeremy Ruston
f256b7791d Merge branch 'master' into single-tiddler-mode 2020-01-17 13:06:07 +00:00
Jeremy Ruston
66fc63ed7f Revert "Merge branch 'master' into single-tiddler-mode"
This reverts commit f703330962.
2020-01-17 13:01:39 +00:00
Jeremy Ruston
f703330962 Merge branch 'master' into single-tiddler-mode 2020-01-17 12:54:51 +00:00
Jermolene
0ea4bfe99f Merge branch 'master' into single-tiddler-mode 2018-10-04 20:40:42 +01:00
Jermolene
7f99b8c32e Merge branch 'master' into single-tiddler-mode 2018-10-02 14:19:22 +01:00
Jermolene
95111db7ee Merge branch 'master' into single-tiddler-mode 2018-09-28 18:32:07 +01:00
Jermolene
5e148c1d26 Merge branch 'master' into single-tiddler-mode 2018-09-27 11:51:56 +01:00
Jermolene
1ff40c6b22 Merge branch 'master' into single-tiddler-mode 2018-09-27 10:12:09 +01:00
Jermolene
a0084eee9a Merge branch 'master' into single-tiddler-mode 2018-09-27 09:48:12 +01:00
Jermolene
55740fbfaf Merge branch 'master' into single-tiddler-mode 2018-09-21 10:56:43 +01:00
Jermolene
226a635c5c Merge branch 'master' into single-tiddler-mode 2018-09-13 20:42:52 +01:00
Jermolene
a5dca25078 Merge branch 'master' into single-tiddler-mode 2018-09-05 09:27:52 +01:00
Jermolene
a15a711d4a Merge branch 'master' into single-tiddler-mode 2018-09-01 13:19:40 +01:00
Jermolene
9bc8cbfe98 Refactor getstoryviewsingletiddlermode operator into getstoryviewmode
Thanks @pmario
2018-08-31 13:00:30 +01:00
Jermolene
f8b81616fb Merge branch 'master' into single-tiddler-mode 2018-08-31 09:59:46 +01:00
Jermolene
b7611e23b4 Improve prerelease notes 2018-08-30 14:06:31 +01:00
Jermolene
eacbb928e9 Merge branch 'master' into single-tiddler-mode 2018-08-30 14:00:59 +01:00
Jermolene
04d6677949 Temporarily default to Zoomin view, and make the switcher more accessible 2018-08-30 12:39:36 +01:00
Jermolene
ee25af758e Make "Open" tab mutate into "History" tab when in STM
Instead of introducing a new "History" tab to the sidebar we make the existing "Open" tab mutate into a "History" tab when in Single Tiddler Mode.
2018-08-30 12:38:13 +01:00
Jermolene
33aa37f7dc Merge branch 'master' into single-tiddler-mode 2018-08-29 19:03:50 +01:00
Jermolene
0d40b691e7 Make "close tiddler" button in STM go back to the previous tiddler in the history stack 2018-08-27 18:12:54 +01:00
Jermolene
81fda40486 Make single tiddler mode status available in tv-storyview-single-tiddler-mode 2018-08-27 12:19:28 +01:00
Jermolene
7a50edb56d Refactor navigator attribute handling
And fix a bug whereby we weren't refreshing when some attributes changed
2018-08-26 23:57:17 +01:00
Jermolene
f76e3f5d41 Update release note 2018-08-26 17:04:42 +01:00
Jermolene
9f2ce65a71 Merge branch 'master' into single-tiddler-mode 2018-08-26 16:49:17 +01:00
Jermolene
9a77ec4591 Docs update 2018-08-26 15:43:40 +01:00
Jermolene
8625d6cd01 Add "History" sidebar tab
Much more useful than the "open" tab when in single tiddler mode
2018-08-26 15:43:32 +01:00
Jermolene
aba835fb74 Basics of single tiddler mode
* Storyviews expose a static "singleTiddlerMode" property to determine if they require single tiddler mode
* Navigator widget adds a "singleTiddlerMode" attribute; when set to "yes", the story list is entirely replaced during navigation
* Navigator widget now updates "list" field of $:/HistoryList with a more accessible version of the history list
* Add a getstoryviewsingletiddlermode[] operator so that we can obtain the story view STM status for passing to the navigator widget
2018-08-26 15:43:06 +01:00
735 changed files with 2699 additions and 12643 deletions

View File

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

View File

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

View File

@@ -1,38 +0,0 @@
---
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.
**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,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for TiddlyWiki 5
title: "[IDEA]"
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,22 +0,0 @@
---
name: Pull Request
about: Propose a change to TiddlyWiki 5
title: ""
labels: ''
assignees: ''
---
**Is your PR related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you are proposing**
A clear and concise description of the changes you are proposing. Include images to show visual changes.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
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.

View File

@@ -1,74 +0,0 @@
on:
pull_request:
push:
branches:
- master
- tiddlywiki-com
env:
NODE_VERSION: "12"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/test.sh"
build-prerelease:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
needs: test
env:
TW5_BUILD_TIDDLYWIKI: "./tiddlywiki.js"
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
TW5_BUILD_OUTPUT: "./output/prerelease"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
# There's another near-duplicate "Set dynamic environment variables" step in
# the `build-tiddlywiki-com` job.
# These _could_ be extracted as a script (or moved into `ci-pre-build.sh`) to do away with the
# duplication, but, the visibility that comes from having these in the workflow file seems
# valuable. Environment variables are global variables and setting them at the top-level
# makes sense.
# Time to reconsider this decision might be when this setup turns out to be mistake-prone.
- name: "Set dynamic environment variables"
run: |
TW5_BUILD_BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
echo "TW5_BUILD_BRANCH=${TW5_BUILD_BRANCH}" >> $GITHUB_ENV
echo "TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)" >> $GITHUB_ENV
echo "TW5_BUILD_DETAILS=Prerelease built from branch '$TW5_BUILD_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')" >> $GITHUB_ENV
- run: "./bin/build-site.sh"
- run: "./bin/ci-push.sh"
env:
GH_TOKEN: ${{ secrets.GITHUBPUSHTOKEN }}
build-tiddlywiki-com:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/tiddlywiki-com'
needs: test
env:
TW5_BUILD_TIDDLYWIKI: "./node_modules/tiddlywiki/tiddlywiki.js"
TW5_BUILD_MAIN_EDITION: "./editions/tw5.com"
TW5_BUILD_OUTPUT: "./output"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
# When making a change here, don't forget to see if it also applies to the step
# with the same name in the `build-prerelease` job.
- name: "Set dynamic environment variables"
run: |
TW5_BUILD_BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
echo "TW5_BUILD_BRANCH=${TW5_BUILD_BRANCH}" >> $GITHUB_ENV
echo "TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)" >> $GITHUB_ENV
echo "TW5_BUILD_DETAILS=Built from branch '$TW5_BUILD_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')" >> $GITHUB_ENV
- run: "./bin/build-site.sh"
- run: "./bin/ci-push.sh"
env:
GH_TOKEN: ${{ secrets.GITHUBPUSHTOKEN }}

35
.travis.yml Normal file
View File

@@ -0,0 +1,35 @@
language: node_js
node_js:
- "12.4.0"
stages:
- name: test
- name: build-prerelease
if: branch = "master"
- name: build-tiddlywiki-com
if: branch = "tiddlywiki-com"
jobs:
include:
- stage: test
script: ./bin/test.sh
- stage: build-prerelease
script:
- ./bin/travis-pre-build.sh
- export TW5_BUILD_TIDDLYWIKI='./tiddlywiki.js'
- export TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)
- export TW5_BUILD_DETAILS="Prerelease built from branch '$TRAVIS_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')"
- export TW5_BUILD_MAIN_EDITION='./editions/prerelease'
- export TW5_BUILD_OUTPUT='./output/prerelease'
- ./bin/build-site.sh || travis_terminate 1
- ./bin/travis-push.sh || travis_terminate 1
- stage: build-tiddlywiki-com
script:
- ./bin/travis-pre-build.sh
- export TW5_BUILD_TIDDLYWIKI='./node_modules/tiddlywiki/tiddlywiki.js'
- export TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)
- export TW5_BUILD_DETAILS="Built from branch '$TRAVIS_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')"
- export TW5_BUILD_MAIN_EDITION='./editions/tw5.com'
- export TW5_BUILD_OUTPUT='./output'
- ./bin/build-site.sh || travis_terminate 1
- ./bin/travis-push.sh || travis_terminate 1

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.1.23
TW5_BUILD_VERSION=v5.1.21
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"

View File

@@ -1,15 +0,0 @@
#!/bin/bash
# Push output back to GitHub
# Exit script immediately if any command fails
set -e
cd 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/Jermolene/jermolene.github.io.git" &>/dev/null
git push deploy master &>/dev/null
cd ..

20
bin/travis-push.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
# Push output back to GitHub
cd output || exit 1
git config --global user.email "travis@travis-ci.org" || exit 1
git config --global user.name "Travis CI" || exit 1
git add -A . || exit 1
git commit --message "Travis build: $TRAVIS_BUILD_NUMBER of $TRAVIS_BRANCH ($(date +'%F %T %Z'))" || exit 1
git remote add deploy "https://$GH_TOKEN@github.com/Jermolene/jermolene.github.io.git" &>/dev/null || exit 1
git push deploy master &>/dev/null || exit 1
cd .. || exit 1

View File

@@ -1,25 +0,0 @@
#!/bin/bash
# Process translation updates made via the translators edition
# ./bin/update-translation-from-html-file.sh <language-code> <path-to-html-file>
# Assign and check parameters
LANGUAGE_CODE=$1
HTML_FILE_PATH=$2
if [ -z "$LANGUAGE_CODE" ]; then
echo "Missing parameter: language code"
exit 1
fi
if [ -z "$HTML_FILE_PATH" ]; then
echo "Missing parameter: path to HTML file"
exit 1
fi
./tiddlywiki.js editions/translators/ --verbose --unpackplugin $:/languages/$LANGUAGE_CODE --load $HTML_FILE_PATH --build output-files || exit 1
cp -R ./editions/translators/output/language/. ./languages/$LANGUAGE_CODE/ || exit 1

View File

@@ -267,16 +267,8 @@ $tw.utils.htmlDecode = function(s) {
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
*/
$tw.utils.getLocationHash = function() {
var href = window.location.href;
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(idx < href.length-1 && href[idx+1] === '#') {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
return href.substring(idx);
}
var parts = window.location.href.split('#');
return "#" + (parts.length > 1 ? parts[1] : "");
};
/*
@@ -305,21 +297,13 @@ $tw.utils.stringifyDate = function(value) {
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
$tw.utils.parseDate = function(value) {
if(typeof value === "string") {
var negative = 1;
if(value.charAt(0) === "-") {
negative = -1;
value = value.substr(1);
}
var year = parseInt(value.substr(0,4),10) * negative,
d = new Date(Date.UTC(year,
return new Date(Date.UTC(parseInt(value.substr(0,4),10),
parseInt(value.substr(4,2),10)-1,
parseInt(value.substr(6,2),10),
parseInt(value.substr(8,2)||"00",10),
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;
} else if($tw.utils.isDate(value)) {
return value;
} else {
@@ -425,10 +409,10 @@ $tw.utils.resolvePath = function(sourcepath,rootpath) {
};
/*
Parse a semantic version string into its constituent parts -- see https://semver.org
Parse a semantic version string into its constituent parts
*/
$tw.utils.parseVersion = function(version) {
var match = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/.exec(version);
var match = /^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/.exec(version);
if(match) {
return {
version: match[1],
@@ -443,37 +427,25 @@ $tw.utils.parseVersion = function(version) {
}
};
/*
Returns +1 if the version string A is greater than the version string B, 0 if they are the same, and +1 if B is greater than A.
Missing or malformed version strings are parsed as 0.0.0
*/
$tw.utils.compareVersions = function(versionStringA,versionStringB) {
var defaultVersion = {
major: 0,
minor: 0,
patch: 0
},
versionA = $tw.utils.parseVersion(versionStringA) || defaultVersion,
versionB = $tw.utils.parseVersion(versionStringB) || defaultVersion,
diff = [
versionA.major - versionB.major,
versionA.minor - versionB.minor,
versionA.patch - versionB.patch
];
if((diff[0] > 0) || (diff[0] === 0 && diff[1] > 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] > 0)) {
return +1;
} else if((diff[0] < 0) || (diff[0] === 0 && diff[1] < 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] < 0)) {
return -1;
} else {
return 0;
}
};
/*
Returns true if the version string A is greater than the version string B. Returns true if the versions are the same
*/
$tw.utils.checkVersions = function(versionStringA,versionStringB) {
return $tw.utils.compareVersions(versionStringA,versionStringB) !== -1;
var defaultVersion = {
major: 0,
minor: 0,
patch: 0
},
versionA = $tw.utils.parseVersion(versionStringA) || defaultVersion,
versionB = $tw.utils.parseVersion(versionStringB) || defaultVersion,
diff = [
versionA.major - versionB.major,
versionA.minor - versionB.minor,
versionA.patch - versionB.patch
];
return (diff[0] > 0) ||
(diff[0] === 0 && diff[1] > 0) ||
(diff[0] === 0 && diff[1] === 0 && diff[2] >= 0);
};
/*
@@ -668,13 +640,11 @@ $tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
var promptInfo = {
serviceName: options.serviceName,
callback: options.callback,
form: form,
owner: this
form: form
};
this.passwordPrompts.push(promptInfo);
// Make sure the wrapper is displayed
this.setWrapperDisplay();
return promptInfo;
};
$tw.utils.PasswordPrompt.prototype.removePrompt = function(promptInfo) {
@@ -1288,7 +1258,7 @@ $tw.Wiki = function(options) {
$tw.utils.each(titles || getTiddlerTitles(),function(title) {
var tiddler = tiddlers[title];
if(tiddler) {
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type") && tiddler.fields.text) {
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type")) {
pluginInfo[tiddler.fields.title] = JSON.parse(tiddler.fields.text);
results.modifiedPlugins.push(tiddler.fields.title);
}
@@ -1840,7 +1810,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
// Read the specification
var filesInfo = JSON.parse(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
var processFile = function(filename,isTiddlerFile,fields) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
type = (extInfo || {}).type || fields.type || "text/plain",
typeInfo = $tw.config.contentTypeInfo[type] || {},
@@ -1893,11 +1863,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
}
});
});
if(isEditableFile) {
tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, isEditableFile: true, tiddlers: fileTiddlers});
} else {
tiddlers.push({tiddlers: fileTiddlers});
}
tiddlers.push({tiddlers: fileTiddlers});
};
// Process the listed tiddlers
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
@@ -1920,21 +1886,15 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
}
} else {
// Process directory specifier
var dirPath = path.resolve(filepath,dirSpec.path);
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
var files = fs.readdirSync(dirPath),
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
metaRegExp = /^.*\.meta$/;
for(var t=0; t<files.length; t++) {
var filename = files[t];
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
}
var dirPath = path.resolve(filepath,dirSpec.path),
files = fs.readdirSync(dirPath),
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
metaRegExp = /^.*\.meta$/;
for(var t=0; t<files.length; t++) {
var filename = files[t];
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields);
}
} else {
console.log("Warning: a directory in a tiddlywiki.files file does not exist.");
console.log("dirPath: " + dirPath);
console.log("tiddlywiki.files location: " + filepath);
}
}
});
@@ -2074,11 +2034,6 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
} else {
return null;
}
// Save the path to the tiddlers folder for the filesystemadaptor
var config = wikiInfo.config || {};
if($tw.boot.wikiPath == wikiPath) {
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
}
// Load any parent wikis
if(wikiInfo.includeWikis) {
parentPaths = parentPaths.slice(0);
@@ -2112,30 +2067,27 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
$tw.boot.files[tiddler.title] = {
filepath: tiddlerFile.filepath,
type: tiddlerFile.type,
hasMetaFile: tiddlerFile.hasMetaFile,
isEditableFile: config["retain-original-tiddler-path"] || tiddlerFile.isEditableFile || tiddlerFile.filepath.indexOf($tw.boot.wikiTiddlersPath) !== 0
hasMetaFile: tiddlerFile.hasMetaFile
};
});
}
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
});
if ($tw.boot.wikiPath == wikiPath) {
// Save the original tiddler file locations if requested
var output = {}, relativePath, fileInfo;
// Save the original tiddler file locations if requested
var config = wikiInfo.config || {};
if(config["retain-original-tiddler-path"]) {
var output = {}, relativePath;
for(var title in $tw.boot.files) {
fileInfo = $tw.boot.files[title];
if(fileInfo.isEditableFile) {
relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath);
output[title] =
path.sep === "/" ?
relativePath :
relativePath.split(path.sep).join("/");
}
}
if(Object.keys(output).length > 0){
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
relativePath = path.relative(resolvedWikiPath,$tw.boot.files[title].filepath);
output[title] =
path.sep === "/" ?
relativePath :
relativePath.split(path.sep).join("/");
}
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
}
// Save the path to the tiddlers folder for the filesystemadaptor
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
// Load any plugins within the wiki folder
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
if(fs.existsSync(wikiPluginsPath)) {
@@ -2182,7 +2134,7 @@ $tw.loadTiddlersNode = function() {
// Load any extra plugins
$tw.utils.each($tw.boot.extraPlugins,function(name) {
if(name.charAt(0) === "+") { // Relative path to plugin
var pluginFields = $tw.loadPluginFolder(name.substring(1));
var pluginFields = $tw.loadPluginFolder(name.substring(1));;
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
@@ -2208,7 +2160,8 @@ $tw.loadTiddlersNode = function() {
/*
Startup TiddlyWiki
*/
$tw.boot.initStartup = function(options) {
$tw.boot.startup = function(options) {
options = options || {};
// Get the URL hash and check for safe mode
$tw.locationHash = "#";
if($tw.browser && !$tw.node) {
@@ -2294,7 +2247,6 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("application/zip","base64",".zip");
$tw.utils.registerFileType("application/x-zip-compressed","base64",".zip");
$tw.utils.registerFileType("image/jpeg","base64",[".jpg",".jpeg"],{flags:["image"]});
$tw.utils.registerFileType("image/jpg","base64",[".jpg",".jpeg"],{flags:["image"]});
$tw.utils.registerFileType("image/png","base64",".png",{flags:["image"]});
$tw.utils.registerFileType("image/gif","base64",".gif",{flags:["image"]});
$tw.utils.registerFileType("image/webp","base64",".webp",{flags:["image"]});
@@ -2304,7 +2256,6 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
$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("video/ogg","base64",[".ogm",".ogv",".ogg"]);
$tw.utils.registerFileType("video/webm","base64",".webm");
@@ -2342,9 +2293,6 @@ $tw.boot.initStartup = function(options) {
return result;
}
}
};
$tw.boot.loadStartup = function(options){
// Load tiddlers
if($tw.boot.tasks.readBrowserTiddlers) {
$tw.loadTiddlersBrowser();
@@ -2357,8 +2305,6 @@ $tw.boot.loadStartup = function(options){
}
// Give hooks a chance to modify the store
$tw.hooks.invokeHook("th-boot-tiddlers-loaded");
}
$tw.boot.execStartup = function(options){
// Unpack plugin tiddlers
$tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin",$tw.safeMode ? ["$:/core"] : undefined);
@@ -2387,16 +2333,6 @@ $tw.boot.execStartup = function(options){
$tw.boot.disabledStartupModules = $tw.boot.disabledStartupModules || [];
// Repeatedly execute the next eligible task
$tw.boot.executeNextStartupTask(options.callback);
}
/*
Startup TiddlyWiki
*/
$tw.boot.startup = function(options) {
options = options || {};
// Get the URL hash and check for safe mode
$tw.boot.initStartup(options);
$tw.boot.loadStartup(options);
$tw.boot.execStartup(options);
};
/*

View File

@@ -0,0 +1,4 @@
title: $:/core/images/storyview-solo
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-storyview-single tc-image-button" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16A8 8 0 0016 24.009V71.99C16 76.414 19.588 80 24 80h80a8 8 0 008-8.009V24.01c0-4.423-3.588-8.009-8-8.009H24z"/></svg>

View File

@@ -17,8 +17,6 @@ Basics/NewJournal/Tags/Prompt: Tags for new journal tiddlers
Basics/NewTiddler/Title/Prompt: Title of new tiddlers
Basics/NewTiddler/Tags/Prompt: Tags for new tiddlers
Basics/OverriddenShadowTiddlers/Prompt: Number of overridden shadow tiddlers
Basics/RemoveTags: Update to current format
Basics/RemoveTags/Hint: Update the tags configuration to the latest format
Basics/ShadowTiddlers/Prompt: Number of shadow tiddlers
Basics/Subtitle/Prompt: Subtitle
Basics/SystemTiddlers/Prompt: Number of system tiddlers
@@ -46,7 +44,6 @@ KeyboardShortcuts/Platform/Linux: Linux platform only
KeyboardShortcuts/Platform/NonLinux: Non-Linux platforms only
KeyboardShortcuts/Platform/Windows: Windows platform only
KeyboardShortcuts/Platform/NonWindows: Non-Windows platforms only
LayoutSwitcher/Caption: Layout
LoadedModules/Caption: Loaded Modules
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
Palette/Caption: Palette
@@ -73,7 +70,6 @@ Plugins/Caption: Plugins
Plugins/Disable/Caption: disable
Plugins/Disable/Hint: Disable this plugin when reloading page
Plugins/Disabled/Status: (disabled)
Plugins/Downgrade/Caption: downgrade
Plugins/Empty/Hint: None
Plugins/Enable/Caption: enable
Plugins/Enable/Hint: Enable this plugin when reloading page
@@ -91,11 +87,6 @@ Plugins/Plugins/Hint: Plugins
Plugins/Reinstall/Caption: reinstall
Plugins/Themes/Caption: Themes
Plugins/Themes/Hint: Theme plugins
Plugins/Update/Caption: update
Plugins/Updates/Caption: Updates
Plugins/Updates/Hint: Available updates to installed plugins
Plugins/Updates/UpdateAll/Caption: Update <<update-count>> plugins
Plugins/SubPluginPrompt: With <<count>> sub-plugins available
Saving/Caption: Saving
Saving/DownloadSaver/AutoSave/Description: Permit automatic saving for the download saver
Saving/DownloadSaver/AutoSave/Hint: Enable Autosave for Download Saver
@@ -120,7 +111,6 @@ Saving/GitService/Gitea/Caption: Gitea Saver
Saving/GitService/Gitea/Password: Personal access token for API (via Giteas web interface: `Settings | Applications | Generate New Token`)
Saving/TiddlySpot/Advanced/Heading: Advanced Settings
Saving/TiddlySpot/BackupDir: Backup Directory
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
Saving/TiddlySpot/Backups: Backups
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
Saving/TiddlySpot/Description: These settings are only used when saving to http://tiddlyspot.com or a compatible remote server
@@ -128,7 +118,6 @@ Saving/TiddlySpot/Filename: Upload Filename
Saving/TiddlySpot/Heading: ~TiddlySpot
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
Saving/TiddlySpot/Password: Password
Saving/TiddlySpot/ReadOnly: The ~TiddlySpot service is currently only available in read-only form. Please see http://tiddlyspot.com/ for the latest details. The ~TiddlySpot saver can still be used to save to compatible servers.
Saving/TiddlySpot/ServerURL: Server URL
Saving/TiddlySpot/UploadDir: Upload Directory
Saving/TiddlySpot/UserName: Wiki Name

View File

@@ -19,8 +19,6 @@ Shadow/OverriddenWarning: This is a modified shadow tiddler. You can revert to t
Tags/Add/Button: add
Tags/Add/Button/Hint: add tag
Tags/Add/Placeholder: tag name
Tags/ClearInput/Caption: clear input
Tags/ClearInput/Hint: Clear tag input
Tags/Dropdown/Caption: tag list
Tags/Dropdown/Hint: Show tag list
Title/BadCharacterWarning: Warning: avoid using any of the characters <<bad-chars>> in tiddler titles

View File

@@ -6,13 +6,13 @@ description: Render tiddlers matching a filter to a specified ContentType
Render a set of tiddlers matching a filter to separate files of a specified ContentType (defaults to `text/html`) and extension (defaults to `.html`).
```
--rendertiddlers '<filter>' <template> <pathname> [<type>] [<extension>] ["noclean"]
--rendertiddlers <filter> <template> <pathname> [<type>] [<extension>] ["noclean"]
```
For example:
```
--rendertiddlers '[!is[system]]' $:/core/templates/static.tiddler.html ./static text/plain
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain
```
By default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.

View File

@@ -13,16 +13,11 @@ Listing/Preview/TextRaw: Text (Raw)
Listing/Preview/Fields: Fields
Listing/Preview/Diff: Diff
Listing/Preview/DiffFields: Diff (Fields)
Listing/Rename/Tooltip: Rename tiddler before importing
Listing/Rename/Prompt: Rename to:
Listing/Rename/ConfirmRename: Rename tiddler
Listing/Rename/CancelRename: Cancel
Listing/Rename/OverwriteWarning: A tiddler with this title already exists.
Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin.
Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> not being newer than existing <<existing>>).
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>.
Upgrader/State/Suppressed: Blocked temporary state tiddler.
Upgrader/System/Suppressed: Blocked system tiddler.
Upgrader/System/Warning: Core module tiddler.
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable.
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>.
Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin
Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> being older than existing <<existing>>)
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>
Upgrader/State/Suppressed: Blocked temporary state tiddler
Upgrader/System/Suppressed: Blocked system tiddler
Upgrader/System/Warning: Core module tiddler
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>

View File

@@ -10,7 +10,6 @@ ConfirmCancelTiddler: Do you wish to discard changes to the tiddler "<$text text
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<<title>>/>"?
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"?
ConfirmEditShadowTiddler: You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit "<$text text=<<title>>/>"?
ConfirmAction: Do you wish to proceed?
Count: count
DefaultNewTiddlerTitle: New Tiddler
Diffs/CountMessage: <<diff-count>> differences
@@ -27,9 +26,7 @@ Error/Caption: Error
Error/EditConflict: File changed on server
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
Error/IsFilterOperator: Filter Error: Unknown operand for the 'is' filter operator
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
Error/LoadingPluginLibrary: Error loading plugin library
Error/NetworkErrorAlert: `<h2>''Network Error''</h2>It looks like the connection to the server has been lost. This may indicate a problem with your network connection. Please attempt to restore network connectivity before continuing.<br><br>''Any unsaved changes will be automatically synchronised when connectivity is restored''.`
Error/RecursiveTransclusion: Recursive transclusion error in transclude widget
@@ -40,7 +37,6 @@ Error/XMLHttpRequest: XMLHttpRequest error code
InternalJavaScriptError/Title: Internal JavaScript Error
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)
LayoutSwitcher/Description: Open the layout switcher
LazyLoadingWarning: <p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>
LoginToTiddlySpace: Login to TiddlySpace
Manager/Controls/FilterByTag/None: (none)
@@ -64,23 +60,8 @@ MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" -- click
No: No
OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library
OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
PageTemplate/Description: the default ~TiddlyWiki layout
PageTemplate/Name: Default ~PageTemplate
PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect
RecentChanges/DateFormat: DDth MMM YYYY
Shortcuts/Input/AdvancedSearch/Hint: Open the ~AdvancedSearch panel from within the sidebar search field
Shortcuts/Input/Accept/Hint: Accept the selected item
Shortcuts/Input/AcceptVariant/Hint: Accept the selected item (variant)
Shortcuts/Input/Cancel/Hint: Clear the input field
Shortcuts/Input/Down/Hint: Select the next item
Shortcuts/Input/Tab-Left/Hint: Select the previous Tab
Shortcuts/Input/Tab-Right/Hint: Select the next Tab
Shortcuts/Input/Up/Hint: Select the previous item
Shortcuts/SidebarLayout/Hint: Change the sidebar layout
Switcher/Subtitle/theme: Switch Theme
Switcher/Subtitle/layout: Switch Layout
Switcher/Subtitle/language: Switch Language
Switcher/Subtitle/palette: Switch Palette
SystemTiddler/Tooltip: This is a system tiddler
SystemTiddlers/Include/Prompt: Include system tiddlers
TagManager/Colour/Heading: Colour

View File

@@ -1,3 +1,2 @@
title: $:/config/NewJournal/Tags
Journal
tags: Journal

View File

@@ -4,6 +4,7 @@ All/Caption: All
Contents/Caption: Contents
Drafts/Caption: Drafts
Explorer/Caption: Explorer
History/Caption: History
Missing/Caption: Missing
More/Caption: More
Open/Caption: Open

View File

@@ -14,7 +14,7 @@ List/Caption: List
List/Empty: This tiddler does not have a list
Listed/Caption: Listed
Listed/Empty: This tiddler is not listed by any others
References/Caption: Backlinks
References/Caption: References
References/Empty: No tiddlers link to this one
Tagging/Caption: Tagging
Tagging/Empty: No tiddlers are tagged with this one

View File

@@ -71,7 +71,7 @@ Command.prototype.fetchFiles = function(options) {
if(options.url) {
urls = [options.url]
} else if(options.urlFilter) {
urls = this.commander.wiki.filterTiddlers(options.urlFilter);
urls = $tw.wiki.filterTiddlers(options.urlFilter);
} else {
return "Missing URL";
}

View File

@@ -33,7 +33,7 @@ Command.prototype.execute = function() {
tiddlers = {};
// Collect up the library plugins
var collectPlugins = function(folder) {
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
var pluginFolders = fs.readdirSync(folder);
for(var p=0; p<pluginFolders.length; p++) {
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
@@ -44,16 +44,16 @@ Command.prototype.execute = function() {
}
},
collectPublisherPlugins = function(folder) {
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
var publisherFolders = fs.readdirSync(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,$tw.config.pluginsEnvVar),collectPublisherPlugins);
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);
collectPublisherPlugins(path.resolve($tw.boot.corePath,$tw.config.pluginsPath));
collectPublisherPlugins(path.resolve($tw.boot.corePath,$tw.config.themesPath));
collectPlugins(path.resolve($tw.boot.corePath,$tw.config.languagesPath));
// Save the upgrade library tiddler
var pluginFields = {
title: upgradeLibraryTitle,

View File

@@ -5,12 +5,10 @@ module-type: command
Command to save the subtiddlers of a bundle tiddler as a series of JSON files
--savelibrarytiddlers <tiddler> <tiddler-filter> <pathname> <skinnylisting>
--savelibrarytiddlers <tiddler> <pathname> <skinnylisting>
The tiddler identifies the bundle tiddler that contains the subtiddlers.
The tiddler filter specifies the plugins to be included.
The pathname specifies the pathname to the folder in which the JSON files should be saved. The filename is the URL encoded title of the subtiddler.
The skinnylisting specifies the title of the tiddler to which a JSON catalogue of the subtiddlers will be saved. The JSON file contains the same data as the bundle tiddler but with the `text` field removed.
@@ -71,7 +69,7 @@ Command.prototype.execute = function() {
// Collect the skinny list data
var pluginTiddlers = JSON.parse(tiddler.text),
readmeContent = (pluginTiddlers.tiddlers[title + "/readme"] || {}).text,
doesRequireReload = !!self.commander.wiki.doesPluginInfoRequireReload(pluginTiddlers),
doesRequireReload = !!$tw.wiki.doesPluginInfoRequireReload(pluginTiddlers),
iconTiddler = pluginTiddlers.tiddlers[title + "/icon"] || {},
iconType = iconTiddler.type,
iconText = iconTiddler.text,

View File

@@ -42,6 +42,7 @@ function FramedEngine(options) {
this.iframeNode.style.border = "none";
this.iframeNode.style.padding = "0";
this.iframeNode.style.resize = "none";
this.iframeNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
this.iframeDoc.body.style.margin = "0";
this.iframeDoc.body.style.padding = "0";
this.widget.domNodes.push(this.iframeNode);
@@ -73,20 +74,13 @@ function FramedEngine(options) {
if(this.widget.editTabIndex) {
this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex);
}
if(this.widget.editAutoComplete) {
this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete);
}
if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true);
}
// Copy the styles from the dummy textarea
this.copyStyles();
// Add event listeners
$tw.utils.addEventListeners(this.domNode,[
{name: "click",handlerObject: this,handlerMethod: "handleClickEvent"},
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"}
]);
// Insert the element into the DOM
this.iframeDoc.body.appendChild(this.domNode);
@@ -102,6 +96,7 @@ FramedEngine.prototype.copyStyles = function() {
this.domNode.style.display = "block";
this.domNode.style.width = "100%";
this.domNode.style.margin = "0";
this.domNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
};
@@ -112,20 +107,13 @@ Set the text of the engine if it doesn't currently have focus
FramedEngine.prototype.setText = function(text,type) {
if(!this.domNode.isTiddlyWikiFakeDom) {
if(this.domNode.ownerDocument.activeElement !== this.domNode) {
this.updateDomNodeText(text);
this.domNode.value = text;
}
// Fix the height if needed
this.fixHeight();
}
};
/*
Update the DomNode with the new text
*/
FramedEngine.prototype.updateDomNodeText = function(text) {
this.domNode.value = text;
};
/*
Get the text of the engine
*/
@@ -165,15 +153,6 @@ FramedEngine.prototype.focus = function() {
}
};
/*
Handle a focus event
*/
FramedEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) {
$tw.popup.cancel(0);
}
};
/*
Handle a click
*/
@@ -188,9 +167,6 @@ Handle a dom "input" event which occurs when the text has changed
FramedEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
if(this.widget.editInputActions) {
this.widget.invokeActionString(this.widget.editInputActions);
}
return true;
};

View File

@@ -52,12 +52,6 @@ function SimpleEngine(options) {
if(this.widget.editTabIndex) {
this.domNode.setAttribute("tabindex",this.widget.editTabIndex);
}
if(this.widget.editAutoComplete) {
this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete);
}
if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true);
}
// Add an input event handler
$tw.utils.addEventListeners(this.domNode,[
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
@@ -74,20 +68,13 @@ Set the text of the engine if it doesn't currently have focus
SimpleEngine.prototype.setText = function(text,type) {
if(!this.domNode.isTiddlyWikiFakeDom) {
if(this.domNode.ownerDocument.activeElement !== this.domNode || text === "") {
this.updateDomNodeText(text);
this.domNode.value = text;
}
// Fix the height if needed
this.fixHeight();
}
};
/*
Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
this.domNode.value = text;
};
/*
Get the text of the engine
*/
@@ -128,9 +115,6 @@ Handle a dom "input" event which occurs when the text has changed
SimpleEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
if(this.widget.editInputActions) {
this.widget.invokeActionString(this.widget.editInputActions);
}
return true;
};
@@ -138,9 +122,6 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
Handle a dom "focus" event
*/
SimpleEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) {
$tw.popup.cancel(0);
}
if(this.widget.editFocusPopup) {
$tw.popup.triggerPopup({
domNode: this.domNode,

View File

@@ -177,11 +177,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editFocusPopup = this.getAttribute("focusPopup");
this.editFocus = this.getAttribute("focus");
this.editTabIndex = this.getAttribute("tabindex");
this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes";
this.editInputActions = this.getAttribute("inputActions");
this.editRefreshTitle = this.getAttribute("refreshTitle");
this.editAutoComplete = this.getAttribute("autocomplete");
this.isDisabled = this.getAttribute("disabled","no");
// Get the default editor element tag and type
var tag,type;
if(this.editField === "text") {
@@ -213,11 +208,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
this.engine.updateDomNodeText(this.getEditInfo().value);
} else if(changedTiddlers[this.editTitle]) {
var editInfo = this.getEditInfo();
this.updateEditor(editInfo.value,editInfo.type);

View File

@@ -1,25 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/all.js
type: application/javascript
module-type: filterrunprefix
Union of sets without de-duplication.
Equivalent to = filter run prefix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.all = function(operationSubFunction) {
return function(results,source,widget) {
results.push.apply(results, operationSubFunction(source,widget));
};
};
})();

View File

@@ -1,28 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/and.js
type: application/javascript
module-type: filterrunprefix
Intersection of sets.
Equivalent to + filter run prefix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.and = function(operationSubFunction,options) {
return function(results,source,widget) {
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved
source = options.wiki.makeTiddlerIterator(results.toArray());
results.clear();
results.pushTop(operationSubFunction(source,widget));
};
};
})();

View File

@@ -1,27 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/else.js
type: application/javascript
module-type: filterrunprefix
Equivalent to ~ filter run prefix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.else = function(operationSubFunction) {
return function(results,source,widget) {
if(results.length === 0) {
// Main result so far is empty
results.pushTop(operationSubFunction(source,widget));
}
};
};
})();

View File

@@ -1,25 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/except.js
type: application/javascript
module-type: filterrunprefix
Difference of sets.
Equivalent to - filter run prefix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.except = function(operationSubFunction) {
return function(results,source,widget) {
results.remove(operationSubFunction(source,widget));
};
};
})();

View File

@@ -1,31 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/filter.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.filter = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var resultsToRemove = [];
results.each(function(result) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([result]),widget);
if(filtered.length === 0) {
resultsToRemove.push(result);
}
});
results.remove(resultsToRemove);
}
}
};
})();

View File

@@ -1,31 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/intersection.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.intersection = function(operationSubFunction) {
return function(results,source,widget) {
if(results.length !== 0) {
var secondRunResults = operationSubFunction(source,widget);
var firstRunResults = results.toArray();
results.clear();
$tw.utils.each(firstRunResults,function(title) {
if(secondRunResults.indexOf(title) !== -1) {
results.push(title);
}
});
}
};
};
})();

View File

@@ -1,24 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/or.js
type: application/javascript
module-type: filterrunprefix
Equivalent to a filter run with no prefix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.or = function(operationSubFunction) {
return function(results,source,widget) {
results.pushTop(operationSubFunction(source,widget));
};
};
})();

View File

@@ -1,50 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/reduce.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.reduce = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var accumulator = "";
var index = 0;
results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return widget.getVariable(name);
}
}
});
if(list.length > 0) {
accumulator = "" + list[0];
}
++index;
});
results.clear();
results.push(accumulator);
}
}
};
})();

View File

@@ -62,61 +62,43 @@ function parseFilterOperation(operators,filterString,p) {
else if(operator.operator === "") {
operator.operator = "title";
}
operator.operands = [];
function parseOperand(bracketType) {
var operand = {};
switch (bracketType) {
case "{": // Curly brackets
operand.indirect = true;
nextBracketPos = filterString.indexOf("}",p);
break;
case "[": // Square brackets
nextBracketPos = filterString.indexOf("]",p);
break;
case "<": // Angle brackets
operand.variable = true;
nextBracketPos = filterString.indexOf(">",p);
break;
case "/": // regexp brackets
var rex = /^((?:[^\\\/]*|\\.)*)\/(?:\(([mygi]+)\))?/g,
rexMatch = rex.exec(filterString.substring(p));
if(rexMatch) {
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
// DEPRECATION WARNING
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
nextBracketPos = p + rex.lastIndex - 1;
}
else {
throw "Unterminated regular expression in filter expression";
}
break;
}
if(nextBracketPos === -1) {
throw "Missing closing bracket in filter expression";
}
if(!operator.regexp) {
operand.text = filterString.substring(p,nextBracketPos);
operator.operands.push(operand);
}
p = nextBracketPos + 1;
}
p = nextBracketPos + 1;
parseOperand(bracket);
// Check for multiple operands
while(filterString.charAt(p) === ",") {
p++;
if(/^[\[\{<\/]/.test(filterString.substring(p))) {
nextBracketPos = p;
p++;
parseOperand(filterString.charAt(nextBracketPos));
} else {
throw "Missing [ in filter expression";
}
switch (bracket) {
case "{": // Curly brackets
operator.indirect = true;
nextBracketPos = filterString.indexOf("}",p);
break;
case "[": // Square brackets
nextBracketPos = filterString.indexOf("]",p);
break;
case "<": // Angle brackets
operator.variable = true;
nextBracketPos = filterString.indexOf(">",p);
break;
case "/": // regexp brackets
var rex = /^((?:[^\\\/]*|\\.)*)\/(?:\(([mygi]+)\))?/g,
rexMatch = rex.exec(filterString.substring(p));
if(rexMatch) {
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
// DEPRECATION WARNING
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
nextBracketPos = p + rex.lastIndex - 1;
}
else {
throw "Unterminated regular expression in filter expression";
}
break;
}
if(nextBracketPos === -1) {
throw "Missing closing bracket in filter expression";
}
if(!operator.regexp) {
operator.operand = filterString.substring(p,nextBracketPos);
}
p = nextBracketPos + 1;
// Push this operator
operators.push(operator);
} while(filterString.charAt(p) !== "]");
@@ -137,7 +119,7 @@ exports.parseFilter = function(filterString) {
p = 0, // Current position in the filter string
match;
var whitespaceRegExp = /(\s+)/mg,
operandRegExp = /((?:\+|\-|~|=|\:(\w+))?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
operandRegExp = /((?:\+|\-|~|=)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -158,19 +140,16 @@ exports.parseFilter = function(filterString) {
};
if(match[1]) {
operation.prefix = match[1];
p = p + operation.prefix.length;
if(match[2]) {
operation.namedPrefix = match[2];
}
p++;
}
if(match[3]) { // Opening square bracket
if(match[2]) { // Opening square bracket
p = parseFilterOperation(operation.operators,filterString,p);
} else {
p = match.index + match[0].length;
}
if(match[4] || match[5] || match[6]) { // Double quoted string, single quoted string or unquoted title
if(match[3] || match[4] || match[5]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push(
{operator: "title", operands: [{text: match[4] || match[5] || match[6]}]}
{operator: "title", operand: match[3] || match[4] || match[5]}
);
}
results.push(operation);
@@ -187,14 +166,6 @@ exports.getFilterOperators = function() {
return this.filterOperators;
};
exports.getFilterRunPrefixes = function() {
if(!this.filterRunPrefixes) {
$tw.Wiki.prototype.filterRunPrefixes = {};
$tw.modules.applyMethods("filterrunprefix",this.filterRunPrefixes);
}
return this.filterRunPrefixes;
}
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
return fn.call(this,source,widget);
@@ -227,7 +198,7 @@ exports.compileFilter = function(filterString) {
results = [],
currTiddlerTitle = widget && widget.getVariable("currentTiddler");
$tw.utils.each(operation.operators,function(operator) {
var operands = [],
var operand = operator.operand,
operatorFunction;
if(!operator.operator) {
operatorFunction = filterOperators.title;
@@ -236,23 +207,16 @@ exports.compileFilter = function(filterString) {
} else {
operatorFunction = filterOperators[operator.operator];
}
$tw.utils.each(operator.operands,function(operand) {
if(operand.indirect) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
} else {
operand.value = operand.text;
}
operands.push(operand.value);
});
if(operator.indirect) {
operand = self.getTextReference(operator.operand,"",currTiddlerTitle);
}
if(operator.variable) {
operand = widget.getVariable(operator.operand,{defaultValue: ""});
}
// Invoke the appropriate filteroperator module
results = operatorFunction(accumulator,{
operator: operator.operator,
operand: operands.length > 0 ? operands[0] : undefined,
operands: operands,
operand: operand,
prefix: operator.prefix,
suffix: operator.suffix,
suffixes: operator.suffixes,
@@ -277,30 +241,35 @@ exports.compileFilter = function(filterString) {
return resultArray;
}
};
var filterRunPrefixes = self.getFilterRunPrefixes();
// Wrap the operator functions in a wrapper function that depends on the prefix
operationFunctions.push((function() {
var options = {wiki: self};
switch(operation.prefix || "") {
case "": // No prefix means that the operation is unioned into the result
return filterRunPrefixes["or"](operationSubFunction, options);
return function(results,source,widget) {
$tw.utils.pushTop(results,operationSubFunction(source,widget));
};
case "=": // The results of the operation are pushed into the result without deduplication
return filterRunPrefixes["all"](operationSubFunction, options);
return function(results,source,widget) {
Array.prototype.push.apply(results,operationSubFunction(source,widget));
};
case "-": // The results of this operation are removed from the main result
return filterRunPrefixes["except"](operationSubFunction, options);
return function(results,source,widget) {
$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));
};
case "+": // This operation is applied to the main results so far
return filterRunPrefixes["and"](operationSubFunction, options);
return function(results,source,widget) {
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved
source = self.makeTiddlerIterator(results);
results.splice(0,results.length);
$tw.utils.pushTop(results,operationSubFunction(source,widget));
};
case "~": // This operation is unioned into the result only if the main result so far is empty
return filterRunPrefixes["else"](operationSubFunction, options);
default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterRunPrefix"));
};
}
return function(results,source,widget) {
if(results.length === 0) {
// Main result so far is empty
$tw.utils.pushTop(results,operationSubFunction(source,widget));
}
};
}
})());
});
@@ -311,11 +280,11 @@ exports.compileFilter = function(filterString) {
} else if(typeof source === "object") { // Array or hashmap
source = self.makeTiddlerIterator(source);
}
var results = new $tw.utils.LinkedList();
var results = [];
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);
});
return results.toArray();
return results;
});
};

View File

@@ -1,40 +0,0 @@
/*\
title: $:/core/modules/filters/compare.js
type: application/javascript
module-type: filteroperator
General purpose comparison operator
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.compare = function(source,operator,options) {
var suffixes = operator.suffixes || [],
type = (suffixes[0] || [])[0],
mode = (suffixes[1] || [])[0],
typeFn = $tw.utils.makeCompareFunction(type,{defaultType: "number"}),
modeFn = modes[mode] || modes.eq,
invert = operator.prefix === "!",
results = [];
source(function(tiddler,title) {
if(modeFn(typeFn(title,operator.operand)) !== invert) {
results.push(title);
}
});
return results;
};
var modes = {
"eq": function(value) {return value === 0;},
"ne": function(value) {return value !== 0;},
"gteq": function(value) {return value >= 0;},
"gt": function(value) {return value > 0;},
"lteq": function(value) {return value <= 0;},
"lt": function(value) {return value < 0;}
}
})();

View File

@@ -1,36 +0,0 @@
/*\
title: $:/core/modules/filters/duplicateslugs.js
type: application/javascript
module-type: filteroperator
Filter function for [duplicateslugs[]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.duplicateslugs = function(source,operator,options) {
var slugs = Object.create(null), // Hashmap by slug of title, replaced with "true" if the duplicate title has already been output
results = [];
source(function(tiddler,title) {
var slug = options.wiki.slugify(title);
if(slug in slugs) {
if(slugs[slug] !== true) {
results.push(slugs[slug]);
slugs[slug] = true;
}
results.push(title);
} else {
slugs[slug] = title;
}
});
return results;
};
})();

View File

@@ -16,16 +16,14 @@ Filter operator for returning the descriptions of the specified edition names
Export our filter function
*/
exports.editiondescription = function(source,operator,options) {
var results = [];
if($tw.node) {
var editionInfo = $tw.utils.getEditionInfo();
if(editionInfo) {
source(function(tiddler,title) {
if($tw.utils.hop(editionInfo,title)) {
results.push(editionInfo[title].description || "");
}
});
}
var results = [],
editionInfo = $tw.utils.getEditionInfo();
if(editionInfo) {
source(function(tiddler,title) {
if($tw.utils.hop(editionInfo,title)) {
results.push(editionInfo[title].description || "");
}
});
}
return results;
};

View File

@@ -16,16 +16,14 @@ Filter operator for returning the names of the available editions in this wiki
Export our filter function
*/
exports.editions = function(source,operator,options) {
var results = [];
if($tw.node) {
var editionInfo = $tw.utils.getEditionInfo();
if(editionInfo) {
$tw.utils.each(editionInfo,function(info,name) {
results.push(name);
});
}
results.sort();
var results = [],
editionInfo = $tw.utils.getEditionInfo();
if(editionInfo) {
$tw.utils.each(editionInfo,function(info,name) {
results.push(name);
});
}
results.sort();
return results;
};

View File

@@ -77,7 +77,7 @@ exports.encodehtml = function(source,operator,options) {
exports.stringify = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.stringify(title,(operator.suffix === "rawunicode")));
results.push($tw.utils.stringify(title));
});
return results;
};
@@ -85,7 +85,7 @@ exports.stringify = function(source,operator,options) {
exports.jsonstringify = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.jsonStringify(title,(operator.suffix === "rawunicode")));
results.push($tw.utils.jsonStringify(title));
});
return results;
};

View File

@@ -16,28 +16,13 @@ Filter operator for returning the names of the fields on the selected tiddlers
Export our filter function
*/
exports.fields = function(source,operator,options) {
var results = [],
fieldName,
suffixes = (operator.suffixes || [])[0] || [],
operand = $tw.utils.parseStringArray(operator.operand);
var results = [];
source(function(tiddler,title) {
if(tiddler) {
if(suffixes.indexOf("include") !== -1) {
for(fieldName in tiddler.fields) {
(operand.indexOf(fieldName) !== -1) ? $tw.utils.pushTop(results,fieldName) : "";
}
} else if (suffixes.indexOf("exclude") !== -1) {
for(fieldName in tiddler.fields) {
(operand.indexOf(fieldName) !== -1) ? "" : $tw.utils.pushTop(results,fieldName);
}
} // else if
else {
for(fieldName in tiddler.fields) {
$tw.utils.pushTop(results,fieldName);
}
} // else
} // if (tiddler)
for(var fieldName in tiddler.fields) {
$tw.utils.pushTop(results,fieldName);
}
}
});
return results;
};

View File

@@ -1,31 +0,0 @@
/*\
title: $:/core/modules/filters/filter.js
type: application/javascript
module-type: filteroperator
Filter operator returning those input titles that pass a subfilter
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.filter = function(source,operator,options) {
var filterFn = options.wiki.compileFilter(operator.operand),
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]));
if((list.length > 0) === target) {
results.push(title);
}
});
return results;
};
})();

View File

@@ -1,46 +0,0 @@
/*\
title: $:/core/modules/filters/format.js
type: application/javascript
module-type: filteroperator
Filter operator for formatting strings
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var formatFilterOperators;
function getFormatFilterOperators() {
if(!formatFilterOperators) {
formatFilterOperators = {};
$tw.modules.applyMethods("formatfilteroperator",formatFilterOperators);
}
return formatFilterOperators;
}
/*
Export our filter function
*/
exports.format = function(source,operator,options) {
// Dispatch to the correct formatfilteroperator
var formatFilterOperators = getFormatFilterOperators();
if(operator.suffix) {
var formatFilterOperator = formatFilterOperators[operator.suffix];
if(formatFilterOperator) {
return formatFilterOperator(source,operator.operand,options);
} else {
return [$tw.language.getString("Error/FormatFilterOperator")];
}
} else {
// Return all unchanged if the suffix is missing
var results = [];
source(function(tiddler,title) {
results.push(title);
});
return results;
}
};
})();

View File

@@ -1,26 +0,0 @@
/*\
title: $:/core/modules/filters/format/date.js
type: application/javascript
module-type: formatfilteroperator
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.date = function(source,operand,options) {
var results = [];
source(function(tiddler,title) {
var value = $tw.utils.parseDate(title);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
results.push($tw.utils.formatDateString(value,operand || "YYYY MM DD 0hh:0mm"));
}
});
return results;
};
})();

View File

@@ -1,26 +0,0 @@
/*\
title: $:/core/modules/filters/format/relativedate.js
type: application/javascript
module-type: formatfilteroperator
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.relativedate = function(source,operand,options) {
var results = [];
source(function(tiddler,title) {
var value = $tw.utils.parseDate(title);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
results.push($tw.utils.getRelativeDate((new Date()) - (new Date(value))).description);
}
});
return results;
};
})();

View File

@@ -0,0 +1,38 @@
/*\
title: $:/core/modules/filters/getstoryviewmode.js
type: application/javascript
module-type: filteroperator
Filter operator for retrieving modes from a storyview. Only "singletiddlermode" is implemented at present
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter functions
*/
exports.getstoryviewmode = function(source,operator,options) {
// Initialise the storyviews if they've not been done already
var storyviews = {};
$tw.modules.applyMethods("storyview",storyviews);
if(operator.operand !== "singletiddlermode") {
return [];
}
var results = [];
source(function(tiddler,title) {
var storyview = storyviews[title];
if(storyview && storyview.singleTiddlerMode) {
results.push("yes");
} else {
results.push("no");
}
});
return results;
};
})();

View File

@@ -3,7 +3,7 @@ title: $:/core/modules/filters/has.js
type: application/javascript
module-type: filteroperator
Filter operator for checking if a tiddler has the specified field or index
Filter operator for checking if a tiddler has the specified field
\*/
(function(){
@@ -33,32 +33,16 @@ exports.has = function(source,operator,options) {
}
});
}
}
else if(operator.suffix === "index") {
} else {
if(invert) {
source(function(tiddler,title) {
if(!tiddler || (tiddler && (!$tw.utils.hop(options.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)))) {
if(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand] === "")) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(tiddler && $tw.utils.hop(options.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)) {
results.push(title);
}
});
}
}
else {
if(invert) {
source(function(tiddler,title) {
if(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand].length === 0)) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && (tiddler.fields[operator.operand].length !== 0)) {
if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === "" || tiddler.fields[operator.operand].length === 0)) {
results.push(title);
}
});

View File

@@ -1,36 +0,0 @@
/*\
title: $:/core/modules/filters/is/draft.js
type: application/javascript
module-type: isfilteroperator
Filter function for [is[draft]] analagous to [has[draft.of]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.draft = function(source,prefix,options) {
var results = [];
if(prefix === "!") {
source(function(tiddler,title) {
if(!tiddler || !$tw.utils.hop(tiddler.fields,"draft.of")) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.of") && (tiddler.fields["draft.of"].length !== 0)) {
results.push(title);
}
});
}
return results;
};
})();

View File

@@ -22,7 +22,7 @@ Export our filter function
exports.lookup = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix);
results.push(options.wiki.getTiddlerText(operator.operand + title) || options.wiki.getTiddlerText(operator.operand + operator.suffix));
});
return results;
};

View File

@@ -91,20 +91,6 @@ exports.exponential = makeNumericBinaryOperator(
function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}
);
exports.power = makeNumericBinaryOperator(
function(a,b) {return Math.pow(a,b);}
);
exports.log = makeNumericBinaryOperator(
function(a,b) {
if(b) {
return Math.log(a)/Math.log(b);
} else {
return Math.log(a);
}
}
);
exports.sum = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
0 // Initial value
@@ -128,9 +114,9 @@ exports.minall = makeNumericReducingOperator(
function makeNumericBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [],
numOperand = $tw.utils.parseNumber(operator.operand);
numOperand = parseNumber(operator.operand);
source(function(tiddler,title) {
result.push($tw.utils.stringifyNumber(fnCalc($tw.utils.parseNumber(title),numOperand)));
result.push(stringifyNumber(fnCalc(parseNumber(title),numOperand)));
});
return result;
};
@@ -143,10 +129,18 @@ function makeNumericReducingOperator(fnCalc,initialValue) {
source(function(tiddler,title) {
result.push(title);
});
return [$tw.utils.stringifyNumber(result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,$tw.utils.parseNumber(currentValue));
return [stringifyNumber(result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,parseNumber(currentValue));
},initialValue))];
};
}
function parseNumber(str) {
return parseFloat(str) || 0;
}
function stringifyNumber(num) {
return num + "";
}
})();

View File

@@ -1,58 +0,0 @@
/*\
title: $:/core/modules/filters/reduce.js
type: application/javascript
module-type: filteroperator
Filter operator evaluates a subfilter for each item, making the running total available in the variable `accumulator`, and the current index available in the variable `index`
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.reduce = function(source,operator,options) {
// Accumulate the list
var results = [];
source(function(tiddler,title) {
results.push(title);
});
// Run the filter over each item
var filterFn = options.wiki.compileFilter(operator.operand),
accumulator = operator.operands[1] || "";
for(var index=0; index<results.length; index++) {
var title = results[index],
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return options.widget.getVariable(name);
}
}
});
if(list.length > 0) {
accumulator = "" + list[0];
}
}
if(results.length > 0) {
return [accumulator];
} else {
return [];
}
};
})();

View File

@@ -1,23 +0,0 @@
/*\
title: $:/core/modules/filters/slugify.js
type: application/javascript
module-type: filteroperator
Filter operator for slugifying a tiddler title
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.slugify = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.slugify(title));
});
return results;
};
})();

View File

@@ -1,57 +0,0 @@
/*\
title: $:/core/modules/filters/sortsub.js
type: application/javascript
module-type: filteroperator
Filter operator for sorting by a subfilter
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.sortsub = function(source,operator,options) {
// Compile the subfilter
var filterFn = options.wiki.compileFilter(operator.operand);
// Collect the input titles and the corresponding sort keys
var inputTitles = [],
sortKeys = [];
source(function(tiddler,title) {
inputTitles.push(title);
var r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},{
getVariable: function(name) {
if(name === "currentTiddler") {
return title;
} else {
return options.widget.getVariable(name);
}
}
});
sortKeys.push(r[0] || "");
});
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays
var indexes = new Array(inputTitles.length);
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
// Sort the indexes
var compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
});
// Make the results array in order
var results = [];
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
return results;
};
})();

View File

@@ -34,36 +34,14 @@ exports.titlecase = makeStringBinaryOperator(
function(a) {return [$tw.utils.toTitleCase(a)];}
);
exports.trim = function(source,operator,options) {
var result = [],
suffix = operator.suffix || "",
operand = (operator.operand || ""),
fnCalc;
if(suffix === "prefix") {
fnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];}
} else if(suffix === "suffix") {
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];}
} else {
if(operand === "") {
fnCalc = function(a) {return [$tw.utils.trim(a)];}
} else {
fnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];}
}
}
source(function(tiddler,title) {
Array.prototype.push.apply(result,fnCalc(title,operand));
});
return result;
};
exports.trim = makeStringBinaryOperator(
function(a) {return [$tw.utils.trim(a)];}
);
exports.split = makeStringBinaryOperator(
function(a,b) {return ("" + a).split(b);}
);
exports["enlist-input"] = makeStringBinaryOperator(
function(a,o,s) {return $tw.utils.parseStringArray("" + a,(s === "raw"));}
);
exports.join = makeStringReducingOperator(
function(accumulator,value,operand) {
if(accumulator === null) {
@@ -78,7 +56,7 @@ function makeStringBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [];
source(function(tiddler,title) {
Array.prototype.push.apply(result,fnCalc(title,operator.operand || "",operator.suffix || ""));
Array.prototype.push.apply(result,fnCalc(title,operator.operand || ""));
});
return result;
};
@@ -90,12 +68,9 @@ function makeStringReducingOperator(fnCalc,initialValue) {
source(function(tiddler,title) {
result.push(title);
});
if(result.length === 0) {
return [];
}
return [result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,currentValue,operator.operand || "");
},initialValue) || ""];
},initialValue)];
};
}
@@ -115,61 +90,4 @@ exports.splitregexp = function(source,operator,options) {
return result;
};
exports["search-replace"] = function(source,operator,options) {
var results = [],
suffixes = operator.suffixes || [],
flagSuffix = (suffixes[0] ? (suffixes[0][0] || "") : ""),
flags = (flagSuffix.indexOf("g") !== -1 ? "g" : "") + (flagSuffix.indexOf("i") !== -1 ? "i" : ""),
isRegExp = (suffixes[1] && suffixes[1][0] === "regexp") ? true : false,
searchTerm,
regExp;
source(function(tiddler,title) {
if(title && (operator.operands.length > 1)) {
//Escape regexp characters if the operand is not a regular expression
searchTerm = isRegExp ? operator.operand : $tw.utils.escapeRegExp(operator.operand);
try {
regExp = new RegExp(searchTerm,flags);
} catch(ex) {
return ["RegExp error: " + ex];
}
results.push(
title.replace(regExp,operator.operands[1])
);
} else {
results.push(title);
}
});
return results;
};
exports.pad = function(source,operator,options) {
var results = [],
targetLength = operator.operand ? parseInt(operator.operand) : 0,
fill = operator.operands[1] || "0";
source(function(tiddler,title) {
if(title && title.length) {
if(title.length >= targetLength) {
results.push(title);
} else {
var padString = "",
padStringLength = targetLength - title.length;
while (padStringLength > padString.length) {
padString += fill;
}
//make sure we do not exceed the specified length
padString = padString.slice(0,padStringLength);
if(operator.suffix && (operator.suffix === "suffix")) {
title = title + padString;
} else {
title = padString + title;
}
results.push(title);
}
}
});
return results;
}
})();

View File

@@ -8,228 +8,183 @@ Extended filter operators to manipulate the current list.
\*/
(function () {
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Fetch titles from the current list
*/
var prepare_results = function (source) {
var results = [];
source(function (tiddler, title) {
results.push(title);
});
return results;
};
/*
Fetch titles from the current list
*/
var prepare_results = function (source) {
var results = [];
source(function (tiddler, title) {
results.push(title);
});
return results;
};
/*
Moves a number of items from the tail of the current list before the item named in the operand
*/
exports.putbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
};
/*
Moves a number of items from the tail of the current list before the item named in the operand
*/
exports.putbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
};
/*
Moves a number of items from the tail of the current list after the item named in the operand
*/
exports.putafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
Moves a number of items from the tail of the current list after the item named in the operand
*/
exports.putafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -1) :
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
Replaces the item named in the operand with a number of items from the tail of the current list
*/
exports.replace = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -count) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
Replaces the item named in the operand with a number of items from the tail of the current list
*/
exports.replace = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
results.slice(0, -count) :
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
};
/*
Moves a number of items from the tail of the current list to the head of the list
*/
exports.putfirst = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(-count).concat(results.slice(0, -count));
};
/*
Moves a number of items from the tail of the current list to the head of the list
*/
exports.putfirst = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(-count).concat(results.slice(0, -count));
};
/*
Moves a number of items from the head of the current list to the tail of the list
*/
exports.putlast = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(count).concat(results.slice(0, count));
};
/*
Moves a number of items from the head of the current list to the tail of the list
*/
exports.putlast = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return results.slice(count).concat(results.slice(0, count));
};
/*
Moves the item named in the operand a number of places forward or backward in the list
*/
exports.move = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1),
marker = results.splice(index, 1),
offset = (index + count) > 0 ? index + count : 0;
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
};
/*
Moves the item named in the operand a number of places forward or backward in the list
*/
exports.move = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1),
marker = results.splice(index, 1),
offset = (index + count) > 0 ? index + count : 0;
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
};
/*
Returns the items from the current list that are after the item named in the operand
*/
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
results.slice(index + 1);
};
/*
Returns the items from the current list that are after the item named in the operand
*/
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
results.slice(index + 1);
};
/*
Returns the items from the current list that are before the item named in the operand
*/
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
results.slice(0, index);
};
/*
Returns the items from the current list that are before the item named in the operand
*/
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
results.slice(0, index);
};
/*
Appends the items listed in the operand array to the tail of the current list
*/
exports.append = function (source, operator) {
var append = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || append.length;
return (append.length === 0) ? results :
(operator.prefix) ? results.concat(append.slice(-count)) :
results.concat(append.slice(0, count));
};
/*
Appends the items listed in the operand array to the tail of the current list
*/
exports.append = function (source, operator) {
var append = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || append.length;
return (append.length === 0) ? results :
(operator.prefix) ? results.concat(append.slice(-count)) :
results.concat(append.slice(0, count));
};
/*
Prepends the items listed in the operand array to the head of the current list
*/
exports.prepend = function (source, operator) {
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,prepend.length);
return (prepend.length === 0) ? results :
(operator.prefix) ? prepend.slice(-count).concat(results) :
prepend.slice(0, count).concat(results);
};
/*
Prepends the items listed in the operand array to the head of the current list
*/
exports.prepend = function (source, operator) {
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,prepend.length);
return (prepend.length === 0) ? results :
(operator.prefix) ? prepend.slice(-count).concat(results) :
prepend.slice(0, count).concat(results);
};
/*
Returns all items from the current list except the items listed in the operand array
*/
exports.remove = function (source, operator) {
var array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || array.length,
p,
len,
index;
len = array.length - 1;
for (p = 0; p < count; ++p) {
if (operator.prefix) {
index = results.indexOf(array[len - p]);
} else {
index = results.indexOf(array[p]);
}
if (index !== -1) {
results.splice(index, 1);
}
}
return results;
};
/*
Returns all items from the current list except the items listed in the operand array
*/
exports.remove = function (source, operator) {
var array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || array.length,
p,
len,
index;
len = array.length - 1;
for (p = 0; p < count; ++p) {
if (operator.prefix) {
index = results.indexOf(array[len - p]);
} else {
index = results.indexOf(array[p]);
}
if (index !== -1) {
results.splice(index, 1);
}
}
return results;
};
/*
Returns all items from the current list sorted in the order of the items in the operand array
*/
exports.sortby = function (source, operator) {
var results = prepare_results(source);
if (!results || results.length < 2) {
return results;
}
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
results.sort(function (a, b) {
return lookup.indexOf(a) - lookup.indexOf(b);
});
return results;
};
/*
Returns all items from the current list sorted in the order of the items in the operand array
*/
exports.sortby = function (source, operator) {
var results = prepare_results(source);
if (!results || results.length < 2) {
return results;
}
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
results.sort(function (a, b) {
return lookup.indexOf(a) - lookup.indexOf(b);
});
return results;
};
/*
Removes all duplicate items from the current list
*/
exports.unique = function (source, operator) {
var results = prepare_results(source);
var set = results.reduce(function (a, b) {
if (a.indexOf(b) < 0) {
a.push(b);
}
return a;
}, []);
return set;
};
var cycleValueInArray = function(results,operands,stepSize) {
var resultsIndex,
step = stepSize || 1,
i = 0,
opLength = operands.length,
nextOperandIndex;
for(i; i < opLength; i++) {
resultsIndex = results.indexOf(operands[i]);
if(resultsIndex !== -1) {
break;
}
}
if(resultsIndex !== -1) {
i = i + step;
nextOperandIndex = (i < opLength ? i : i - opLength);
if(operands.length > 1) {
results.splice(resultsIndex,1,operands[nextOperandIndex]);
} else {
results.splice(resultsIndex,1);
}
} else {
results.push(operands[0]);
}
return results;
}
/*
Toggles an item in the current list.
*/
exports.toggle = function(source,operator) {
return cycleValueInArray(prepare_results(source),operator.operands);
}
exports.cycle = function(source,operator) {
var results = prepare_results(source),
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
step = $tw.utils.getInt(operator.operands[1]||"",1);
if(step < 0) {
operands.reverse();
step = Math.abs(step);
}
return cycleValueInArray(results,operands,step);
}
/*
Removes all duplicate items from the current list
*/
exports.unique = function (source, operator) {
var results = prepare_results(source);
var set = results.reduce(function (a, b) {
if (a.indexOf(b) < 0) {
a.push(b);
}
return a;
}, []);
return set;
};
})();

View File

@@ -12,13 +12,12 @@ Initialise basic platform $:/info/ tiddlers
/*global $tw: false */
"use strict";
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
exports.getInfoTiddlerFields = function() {
var mapBoolean = function(value) {return value ? "yes" : "no";},
infoTiddlerFields = [];
// Basics
infoTiddlerFields.push({title: "$:/info/browser", text: mapBoolean(!!$tw.browser)});
infoTiddlerFields.push({title: "$:/info/node", text: mapBoolean(!!$tw.node)});
infoTiddlerFields.push({title: "$:/info/startup-timestamp", text: $tw.utils.stringifyDate(new Date())});
if($tw.browser) {
// Document location
var setLocationProperty = function(name,value) {
@@ -36,13 +35,6 @@ exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
// Screen size
infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()});
infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()});
// Dark mode through event listener on MediaQueryList
var mqList = window.matchMedia("(prefers-color-scheme: dark)"),
getDarkModeTiddler = function() {return {title: "$:/info/darkmode", text: mqList.matches ? "yes" : "no"};};
infoTiddlerFields.push(getDarkModeTiddler());
mqList.addListener(function(event) {
updateInfoTiddlersCallback([getDarkModeTiddler()]);
});
// Language
infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""});
}

View File

@@ -284,20 +284,6 @@ KeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {
return false;
};
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
return event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? "ctrl" :
event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey ? "shift" :
event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? "ctrl-shift" :
event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt" :
event.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt-shift" :
event.altKey && event.ctrlKey && !event.shiftKey && !event.metaKey ? "ctrl-alt" :
event.altKey && event.shiftKey && event.ctrlKey && !event.metaKey ? "ctrl-alt-shift" :
event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? "meta" :
event.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? "meta-ctrl" :
event.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? "meta-ctrl-shift" :
event.metaKey && event.ctrlKey & event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
};
KeyboardManager.prototype.getShortcutTiddlerList = function() {
return $tw.wiki.getTiddlersWithTag("$:/tags/KeyboardShortcut");
};

View File

@@ -27,7 +27,7 @@ exports.params = [
Run the macro
*/
exports.run = function(filter,spaces) {
return this.wiki.getTiddlersAsJson(filter,$tw.utils.parseInt(spaces));
return this.wiki.getTiddlersAsJson(filter,spaces);
};
})();

View File

@@ -60,7 +60,7 @@ var listTypes = {
"#": {listTag: "ol", itemTag: "li"},
";": {listTag: "dl", itemTag: "dt"},
":": {listTag: "dl", itemTag: "dd"},
">": {listTag: "blockquote", itemTag: "div"}
">": {listTag: "blockquote", itemTag: "p"}
};
/*

View File

@@ -386,18 +386,22 @@ Amend the rules used by this instance of the parser
WikiParser.prototype.amendRules = function(type,names) {
names = names || [];
// Define the filter function
var target;
var keepFilter;
if(type === "only") {
target = true;
keepFilter = function(name) {
return names.indexOf(name) !== -1;
};
} else if(type === "except") {
target = false;
keepFilter = function(name) {
return names.indexOf(name) === -1;
};
} else {
return;
}
// Define a function to process each of our rule arrays
var processRuleArray = function(ruleArray) {
for(var t=ruleArray.length-1; t>=0; t--) {
if((names.indexOf(ruleArray[t].rule.name) === -1) === target) {
if(!keepFilter(ruleArray[t].rule.name)) {
ruleArray.splice(t,1);
}
}

View File

@@ -153,7 +153,7 @@ SaverHandler.prototype.saveWiki = function(options) {
var self = this,
method = options.method || "save";
// Ignore autosave if disabled
if(method === "autosave" && ($tw.config.disableAutoSave || this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes")) {
if(method === "autosave" && this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes") {
return false;
}
var variables = options.variables || {},
@@ -197,12 +197,8 @@ SaverHandler.prototype.isDirty = function() {
Update the document body with the class "tc-dirty" if the wiki has unsaved/unsynced changes
*/
SaverHandler.prototype.updateDirtyStatus = function() {
var self = this;
if($tw.browser) {
$tw.utils.toggleClass(document.body,"tc-dirty",this.isDirty());
$tw.utils.each($tw.windows,function(win) {
$tw.utils.toggleClass(win.document.body,"tc-dirty",self.isDirty());
});
}
};

View File

@@ -1,60 +0,0 @@
/*\
title: $:/core/modules/savers/custom.js
type: application/javascript
module-type: saver
Looks for `window.$tw.customSaver` first on the current window, then
on the parent window (of an iframe). If present, the saver must define
save: function(text,method,callback) { ... }
and the saver may define
priority: number
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var findSaver = function(window) {
try {
return window && window.$tw && window.$tw.customSaver;
} catch (err) {
// Catching the exception is the most reliable way to detect cross-origin iframe errors.
// For example, instead of saying that `window.parent.$tw` is undefined, Firefox will throw
// Uncaught DOMException: Permission denied to access property "$tw" on cross-origin object
console.log({ msg: "custom saver is disabled", reason: err });
return null;
}
}
var saver = findSaver(window) || findSaver(window.parent) || {};
var CustomSaver = function(wiki) {
};
CustomSaver.prototype.save = function(text,method,callback) {
return saver.save(text, method, callback);
};
/*
Information about this saver
*/
CustomSaver.prototype.info = {
name: "custom",
priority: saver.priority || 4000,
capabilities: ["save","autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!(saver.save);
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new CustomSaver(wiki);
};
})();

View File

@@ -31,10 +31,10 @@ GiteaSaver.prototype.save = function(text,method,callback) {
headers = {
"Accept": "application/json",
"Content-Type": "application/json;charset=UTF-8",
"Authorization": "token " + password
"Authorization": "Basic " + window.btoa(username + ":" + password)
};
// Bail if we don't have everything we need
if(!username || !password || !repo || !filename) {
if(!username || !password || !repo || !path || !filename) {
return false;
}
// Make sure the path start and ends with a slash

View File

@@ -26,16 +26,15 @@ GitHubSaver.prototype.save = function(text,method,callback) {
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
path = this.wiki.getTiddlerText("$:/GitHub/Path",""),
filename = this.wiki.getTiddlerText("$:/GitHub/Filename"),
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "main",
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "master",
endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com",
headers = {
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json;charset=UTF-8",
"Authorization": "Basic " + window.btoa(username + ":" + password),
"If-None-Match": ""
"Authorization": "Basic " + window.btoa(username + ":" + password)
};
// Bail if we don't have everything we need
if(!username || !password || !repo || !filename) {
if(!username || !password || !repo || !path || !filename) {
return false;
}
// Make sure the path start and ends with a slash

View File

@@ -34,7 +34,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
"Private-Token": password
};
// Bail if we don't have everything we need
if(!username || !password || !repo || !filename) {
if(!username || !password || !repo || !path || !filename) {
return false;
}
// Make sure the path start and ends with a slash

View File

@@ -1,64 +0,0 @@
/*\
title: $:/core/modules/savers/hyperdrive.js
type: application/javascript
module-type: saver
Saves files using the Hyperdrive Protocol (https://hypercore-protocol.org/#hyperdrive) Beaker browser beta-1.0 and later (https://beakerbrowser.com)
Compatible with beaker >= V1.0.0
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Set up the saver
*/
var HyperdriveSaver = function(wiki) {
this.wiki = wiki;
};
HyperdriveSaver.prototype.save = function(text,method,callback) {
var dat = beaker.hyperdrive.drive("" + window.location),
pathname = ("" + window.location.pathname).split("#")[0];
dat.stat(pathname).then(function(value) {
if(value.isDirectory()) {
pathname = pathname + "/index.html";
}
dat.writeFile(pathname,text,"utf8").then(function(value) {
callback(null);
},function(reason) {
callback("Hyperdrive Saver Write Error: " + reason);
});
},function(reason) {
callback("Hyperdrive Saver Stat Error: " + reason);
});
return true;
};
/*
Information about this saver
*/
HyperdriveSaver.prototype.info = {
name: "beaker-1.x",
priority: 3000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!window.beaker && !!beaker.hyperdrive && location.protocol==="hyper:";
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new HyperdriveSaver(wiki);
};
})();

View File

@@ -31,7 +31,7 @@ BasicAuthenticator.prototype.init = function() {
// Read the credentials data
this.credentialsFilepath = this.server.get("credentials");
if(this.credentialsFilepath) {
var resolveCredentialsFilepath = path.resolve(this.server.boot.wikiPath,this.credentialsFilepath);
var resolveCredentialsFilepath = path.resolve($tw.boot.wikiPath,this.credentialsFilepath);
if(fs.existsSync(resolveCredentialsFilepath) && !fs.statSync(resolveCredentialsFilepath).isDirectory()) {
var credentialsText = fs.readFileSync(resolveCredentialsFilepath,"utf8"),
credentialsData = $tw.utils.parseCsvStringWithHeader(credentialsText);

View File

@@ -14,7 +14,7 @@ Authenticator for trusted header authentication
function HeaderAuthenticator(server) {
this.server = server;
this.header = server.get("authenticated-user-header") ? server.get("authenticated-user-header").toLowerCase() : undefined;
this.header = server.get("authenticated-user-header");
}
/*

View File

@@ -21,7 +21,7 @@ exports.handler = function(request,response,state) {
fs = require("fs"),
util = require("util"),
suppliedFilename = decodeURIComponent(state.params[0]),
filename = path.resolve(state.boot.wikiPath,"files",suppliedFilename),
filename = path.resolve($tw.boot.wikiPath,"files",suppliedFilename),
extension = path.extname(filename);
fs.readFile(filename,function(err,content) {
var status,content,type = "text/plain";

View File

@@ -3,7 +3,7 @@ title: $:/core/modules/server/routes/get-tiddlers-json.js
type: application/javascript
module-type: route
GET /recipes/default/tiddlers.json?filter=<filter>
GET /recipes/default/tiddlers/tiddlers.json?filter=<filter>
\*/
(function() {
@@ -20,17 +20,14 @@ exports.path = /^\/recipes\/default\/tiddlers.json$/;
exports.handler = function(request,response,state) {
var filter = state.queryParameters.filter || DEFAULT_FILTER;
if(state.wiki.getTiddlerText("$:/config/Server/AllowAllExternalFilters") !== "yes") {
if(state.wiki.getTiddlerText("$:/config/Server/ExternalFilters/" + filter) !== "yes") {
console.log("Blocked attempt to GET /recipes/default/tiddlers.json with filter: " + filter);
if($tw.wiki.getTiddlerText("$:/config/Server/AllowAllExternalFilters") !== "yes") {
if($tw.wiki.getTiddlerText("$:/config/Server/ExternalFilters/" + filter) !== "yes") {
console.log("Blocked attempt to GET /recipes/default/tiddlers/tiddlers.json with filter: " + filter);
response.writeHead(403);
response.end();
return;
}
}
if(state.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "no") {
filter += "+[!is[system]]";
}
var excludeFields = (state.queryParameters.exclude || "text").split(","),
titles = state.wiki.filterTiddlers(filter);
response.writeHead(200, {"Content-Type": "application/json"});

View File

@@ -31,7 +31,6 @@ function Server(options) {
this.routes = options.routes || [];
this.authenticators = options.authenticators || [];
this.wiki = options.wiki;
this.boot = options.boot || $tw.boot;
this.servername = $tw.utils.transliterateToSafeASCII(this.wiki.getTiddlerText("$:/SiteTitle") || "TiddlyWiki5");
// Initialise the variables
this.variables = $tw.utils.extend({},this.defaultVariables);
@@ -70,8 +69,8 @@ function Server(options) {
tlsCertFilepath = this.get("tls-cert");
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")
key: fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsKeyFilepath),"utf8"),
cert: fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsCertFilepath),"utf8")
};
this.protocol = "https";
}
@@ -113,14 +112,15 @@ Server.prototype.addAuthenticator = function(AuthenticatorClass) {
};
Server.prototype.findMatchingRoute = function(request,state) {
var pathprefix = this.get("path-prefix") || "";
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) || "/";
if(pathprefix) {
if(pathname.substr(0,pathprefix.length) === pathprefix) {
pathname = pathname.substr(pathprefix.length) || "/";
match = potentialRoute.path.exec(pathname);
} else {
match = false;
@@ -156,17 +156,14 @@ Server.prototype.isAuthorized = function(authorizationType,username) {
return principals.indexOf("(anon)") !== -1 || (username && (principals.indexOf("(authenticated)") !== -1 || principals.indexOf(username) !== -1));
}
Server.prototype.requestHandler = function(request,response,options) {
options = options || {};
Server.prototype.requestHandler = function(request,response) {
// Compose the state object
var self = this;
var state = {};
state.wiki = options.wiki || self.wiki;
state.boot = options.boot || self.boot;
state.wiki = self.wiki;
state.server = self;
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
// Get the principals authorized to access this resource
var authorizationType = this.methodMappings[request.method] || "readers";
// Check for the CSRF header if this is a write
@@ -251,7 +248,7 @@ Server.prototype.listen = function(port,host,prefix) {
port = process.env[port] || 8080;
}
// Warn if required plugins are missing
if(!this.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb") || !this.wiki.getTiddler("$:/plugins/tiddlywiki/filesystem")) {
if(!$tw.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb") || !$tw.wiki.getTiddler("$:/plugins/tiddlywiki/filesystem")) {
$tw.utils.warning("Warning: Plugins required for client-server operation (\"tiddlywiki/filesystem\" and \"tiddlywiki/tiddlyweb\") are missing from tiddlywiki.info file");
}
// Create the server

View File

@@ -36,7 +36,7 @@ function setFavicon() {
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
if(tiddler) {
var faviconLink = document.getElementById("faviconLink");
faviconLink.setAttribute("href",$tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri));
faviconLink.setAttribute("href","data:" + tiddler.fields.type + ";base64," + tiddler.fields.text);
}
}

View File

@@ -21,37 +21,29 @@ exports.synchronous = true;
var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
exports.startup = function() {
// Function to bake the info plugin with new tiddlers
var updateInfoPlugin = function(tiddlerFieldsArray) {
// Get the existing tiddlers
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
// Add the new ones
$tw.utils.each(tiddlerFieldsArray,function(fields) {
if(fields && fields.title) {
json.tiddlers[fields.title] = fields;
}
});
// Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically
var fields = {
title: TITLE_INFO_PLUGIN,
type: "application/json",
"plugin-type": "info",
text: JSON.stringify(json,null,$tw.config.preferences.jsonSpaces)
};
$tw.wiki.addTiddler(new $tw.Tiddler(fields));
};
// Collect up the info tiddlers
var tiddlerFieldsArray = [];
// Give each info module a chance to provide as many info tiddlers as they want as an array, and give them a callback for dynamically updating them
var infoTiddlerFields = {};
// Give each info module a chance to fill in as many info tiddlers as they want
$tw.modules.forEachModuleOfType("info",function(title,moduleExports) {
if(moduleExports && moduleExports.getInfoTiddlerFields) {
Array.prototype.push.apply(tiddlerFieldsArray,moduleExports.getInfoTiddlerFields(updateInfoPlugin));
var tiddlerFieldsArray = moduleExports.getInfoTiddlerFields(infoTiddlerFields);
$tw.utils.each(tiddlerFieldsArray,function(fields) {
if(fields) {
infoTiddlerFields[fields.title] = fields;
}
});
}
});
updateInfoPlugin(tiddlerFieldsArray);
var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
// Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically
var fields = {
title: TITLE_INFO_PLUGIN,
type: "application/json",
"plugin-type": "info",
text: JSON.stringify({tiddlers: infoTiddlerFields},null,$tw.config.preferences.jsonSpaces)
};
$tw.wiki.addTiddler(new $tw.Tiddler(fields));
$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
$tw.wiki.registerPluginTiddlers("info");
$tw.wiki.unpackPluginTiddlers();
};

View File

@@ -24,7 +24,6 @@ var PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = "$:/config/RegisterPluginType/";
exports.startup = function() {
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"});
$tw.wiki.addEventListener("change",function(changes) {
// Work out which of the changed tiddlers are plugins that we need to reregister
var changesToProcess = [],
requireReloadDueToPluginChange = false;
$tw.utils.each(Object.keys(changes),function(title) {
@@ -39,7 +38,6 @@ exports.startup = function() {
}
}
});
// Issue warning if any of the tiddlers require a reload
if(requireReloadDueToPluginChange) {
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"});
}
@@ -47,35 +45,12 @@ exports.startup = function() {
if(changesToProcess.length > 0) {
var changes = $tw.wiki.readPluginInfo(changesToProcess);
if(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {
var changedShadowTiddlers = {};
// Collect the shadow tiddlers of any deleted plugins
$tw.utils.each(changes.deletedPlugins,function(pluginTitle) {
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
if(pluginInfo) {
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
changedShadowTiddlers[title] = true;
});
}
});
// Collect the shadow tiddlers of any modified plugins
$tw.utils.each(changes.modifiedPlugins,function(pluginTitle) {
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
if(pluginInfo) {
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
changedShadowTiddlers[title] = false;
});
}
});
// (Re-)register any modified plugins
$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);
// Unregister any deleted plugins
$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);
// Unpack the shadow tiddlers
$tw.wiki.unpackPluginTiddlers();
// Queue change events for the changed shadow tiddlers
$tw.utils.each(Object.keys(changedShadowTiddlers),function(title) {
$tw.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title]);
});
}
}
});

View File

@@ -21,7 +21,7 @@ exports.synchronous = true;
// Default story and history lists
var PAGE_TITLE_TITLE = "$:/core/wiki/title";
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
var PAGE_TEMPLATE_TITLE = "$:/core/ui/RootTemplate";
var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageTemplate";
// Time (in ms) that we defer refreshing changes to draft tiddlers
var DRAFT_TIDDLER_TIMEOUT_TITLE = "$:/config/Drafts/TypingTimeout";
@@ -52,7 +52,7 @@ exports.startup = function() {
}));
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
$tw.perf.report("mainRender",function() {
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget, recursionMarker: "no"});
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});
$tw.pageContainer = document.createElement("div");
$tw.utils.addClass($tw.pageContainer,"tc-page-container-wrapper");
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
@@ -106,8 +106,6 @@ exports.startup = function() {
// Fix up the link between the root widget and the page container
$tw.rootWidget.domNodes = [$tw.pageContainer];
$tw.rootWidget.children = [$tw.pageWidgetNode];
// Run any post-render startup actions
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/PostRender");
};
})();

View File

@@ -25,9 +25,6 @@ exports.startup = function() {
$tw.rootWidget.addEventListener("tm-modal",function(event) {
$tw.modal.display(event.param,{variables: event.paramObject, event: event});
});
$tw.rootWidget.addEventListener("tm-show-switcher",function(event) {
$tw.modal.display("$:/core/ui/SwitcherModal",{variables: event.paramObject, event: event});
});
// Install the notification mechanism
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
$tw.rootWidget.addEventListener("tm-notify",function(event) {

View File

@@ -64,12 +64,17 @@ exports.startup = function() {
document: $tw.browser ? document : $tw.fakeDocument
});
// Execute any startup actions
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction");
var executeStartupTiddlers = function(tag) {
$tw.utils.each($tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[" + tag + "]!has[draft.of]]"),function(title) {
$tw.rootWidget.invokeActionString($tw.wiki.getTiddlerText(title),$tw.rootWidget);
});
};
executeStartupTiddlers("$:/tags/StartupAction");
if($tw.browser) {
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Browser");
executeStartupTiddlers("$:/tags/StartupAction/Browser");
}
if($tw.node) {
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Node");
executeStartupTiddlers("$:/tags/StartupAction/Node");
}
// Kick off the language manager and switcher
$tw.language = new $tw.Language();

View File

@@ -150,11 +150,6 @@ function openStartupTiddlers(options) {
// Save the story list
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
// Update history
var story = new $tw.Story({
wiki: $tw.wiki,
storyTitle: DEFAULT_STORY_TITLE,
historyTitle: DEFAULT_HISTORY_TITLE
});
if(!options.disableHistory) {
// If a target tiddler was specified add it to the history stack
if(target && target !== "") {
@@ -162,9 +157,9 @@ function openStartupTiddlers(options) {
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
target = target.substr(2,target.length - 4);
}
story.addToHistory(target);
$tw.wiki.addToHistory(target);
} else if(storyList.length > 0) {
story.addToHistory(storyList[0]);
$tw.wiki.addToHistory(storyList[0]);
}
}
}

View File

@@ -19,7 +19,7 @@ exports.after = ["startup"];
exports.synchronous = true;
// Global to keep track of open windows (hashmap by title)
$tw.windows = {};
var windows = {};
exports.startup = function() {
// Handle open window message
@@ -44,7 +44,7 @@ exports.startup = function() {
catch(e) {
return;
}
$tw.windows[title] = srcWindow;
windows[title] = srcWindow;
// Check for reopening the same window
if(srcWindow.haveInitialisedWindow) {
return;
@@ -54,7 +54,7 @@ exports.startup = function() {
srcDocument.close();
srcDocument.title = windowTitle;
srcWindow.addEventListener("beforeunload",function(event) {
delete $tw.windows[title];
delete windows[title];
$tw.wiki.removeEventListener("change",refreshHandler);
},false);
// Set up the styles
@@ -84,13 +84,16 @@ exports.startup = function() {
name: "keydown",
handlerObject: $tw.keyboardManager,
handlerMethod: "handleKeydownEvent"
},{
name: "click",
handlerObject: $tw.popup,
handlerMethod: "handleEvent"
}]);
srcWindow.document.documentElement.addEventListener("click",$tw.popup,true);
srcWindow.haveInitialisedWindow = true;
});
// Close open windows when unloading main window
$tw.addUnloadTask(function() {
$tw.utils.each($tw.windows,function(win) {
$tw.utils.each(windows,function(win) {
win.close();
});
});

View File

@@ -37,44 +37,48 @@ Story.prototype.getStoryList = function() {
Story.prototype.addToStory = function(navigateTo,navigateFromTitle,options) {
options = options || {};
var storyList = this.getStoryList();
// See if the tiddler is already there
var slot = storyList.indexOf(navigateTo);
// Quit if it already exists in the story river
if(slot >= 0) {
return;
}
// First we try to find the position of the story element we navigated from
var fromIndex = storyList.indexOf(navigateFromTitle);
if(fromIndex >= 0) {
// The tiddler is added from inside the river
// Determine where to insert the tiddler; Fallback is "below"
switch(options.openLinkFromInsideRiver) {
case "top":
slot = 0;
break;
case "bottom":
slot = storyList.length;
break;
case "above":
slot = fromIndex;
break;
case "below": // Intentional fall-through
default:
slot = fromIndex + 1;
break;
}
if(options.singleTiddlerMode) {
storyList = [navigateTo];
} else {
// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is "top"
if(options.openLinkFromOutsideRiver === "bottom") {
// Insert at bottom
slot = storyList.length;
} else {
// Insert at top
slot = 0;
// See if the tiddler is already there
var slot = storyList.indexOf(navigateTo);
// Quit if it already exists in the story river
if(slot >= 0) {
return;
}
// First we try to find the position of the story element we navigated from
var fromIndex = storyList.indexOf(navigateFromTitle);
if(fromIndex >= 0) {
// The tiddler is added from inside the river
// Determine where to insert the tiddler; Fallback is "below"
switch(options.openLinkFromInsideRiver) {
case "top":
slot = 0;
break;
case "bottom":
slot = storyList.length;
break;
case "above":
slot = fromIndex;
break;
case "below": // Intentional fall-through
default:
slot = fromIndex + 1;
break;
}
} else {
// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is "top"
if(options.openLinkFromOutsideRiver === "bottom") {
// Insert at bottom
slot = storyList.length;
} else {
// Insert at top
slot = 0;
}
}
// Add the tiddler
storyList.splice(slot,0,navigateTo);
}
// Add the tiddler
storyList.splice(slot,0,navigateTo);
// Save the story
this.saveStoryList(storyList);
};
@@ -93,11 +97,20 @@ Story.prototype.saveStoryList = function(storyList) {
Story.prototype.addToHistory = function(navigateTo,navigateFromClientRect) {
var titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo];
// Add a new record to the top of the history stack
var historyList = this.wiki.getTiddlerData(this.historyTitle,[]);
var historyList = this.wiki.getTiddlerData(this.historyTitle,[]),
historyTitles = this.wiki.getTiddlerList(this.historyTitle);
$tw.utils.each(titles,function(title) {
historyList.push({title: title, fromPageRect: navigateFromClientRect});
var p;
do {
p = historyTitles.indexOf(title);
if(p !== -1) {
historyTitles.splice(p,1);
}
} while(p !== -1);
historyTitles.unshift(title);
});
this.wiki.setTiddlerData(this.historyTitle,historyList,{"current-tiddler": titles[titles.length-1]});
this.wiki.setTiddlerData(this.historyTitle,historyList,{"current-tiddler": titles[titles.length-1], list: historyTitles});
};
Story.prototype.storyCloseTiddler = function(targetTitle) {

View File

@@ -0,0 +1,23 @@
/*\
title: $:/core/modules/storyviews/solo.js
type: application/javascript
module-type: storyview
Flip between individual tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var SoloListView = function(listWidget) {
};
// Engage single tiddler mode
SoloListView.singleTiddlerMode = true;
exports.solo = SoloListView;
})();

View File

@@ -39,6 +39,9 @@ var ZoominListView = function(listWidget) {
});
};
// Engage single tiddler mode
ZoominListView.singleTiddlerMode = true;
ZoominListView.prototype.navigateTo = function(historyInfo) {
var duration = $tw.utils.getAnimationDuration(),
listElementIndex = this.listWidget.findListItem(0,historyInfo.title);

View File

@@ -113,16 +113,8 @@ function Syncer(options) {
return confirmationMessage;
});
// Listen out for login/logout/refresh events in the browser
$tw.rootWidget.addEventListener("tm-login",function(event) {
var username = event && event.paramObject && event.paramObject.username,
password = event && event.paramObject && event.paramObject.password;
if(username && password) {
// Login with username and password
self.login(username,password,function() {});
} else {
// No username and password, so we display a prompt
self.handleLoginEvent();
}
$tw.rootWidget.addEventListener("tm-login",function() {
self.handleLoginEvent();
});
$tw.rootWidget.addEventListener("tm-logout",function() {
self.handleLogoutEvent();
@@ -135,7 +127,7 @@ function Syncer(options) {
});
}
// Listen out for lazyLoad events
if(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
if(!this.disableUI && $tw.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
this.wiki.addEventListener("lazyLoad",function(title) {
self.handleLazyLoadEvent(title);
});
@@ -188,14 +180,12 @@ Syncer.prototype.readTiddlerInfo = function() {
var self = this,
tiddlers = this.getSyncedTiddlers();
$tw.utils.each(tiddlers,function(title) {
var tiddler = self.wiki.getTiddler(title);
if(tiddler) {
self.tiddlerInfo[title] = {
revision: self.getTiddlerRevision(title),
adaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler),
changeCount: self.wiki.getChangeCount(title)
};
}
var tiddler = self.wiki.tiddlerExists(title) && self.wiki.getTiddler(title);
self.tiddlerInfo[title] = {
revision: self.getTiddlerRevision(title),
adaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler),
changeCount: self.wiki.getChangeCount(title)
};
});
};
@@ -212,7 +202,7 @@ Syncer.prototype.isDirty = function() {
if(this.wiki.tiddlerExists(title)) {
if(tiddlerInfo) {
// If the tiddler is known on the server and has been modified locally then it needs to be saved to the server
if(this.wiki.getChangeCount(title) > tiddlerInfo.changeCount) {
if($tw.wiki.getChangeCount(title) > tiddlerInfo.changeCount) {
return true;
}
} else {
@@ -305,8 +295,7 @@ Syncer.prototype.syncFromServer = function() {
self.pollTimerId = null;
self.syncFromServer.call(self);
},self.pollTimerInterval);
},
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes" ? true : false);
};
if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {
this.logger.log("Retrieving updated tiddler list");
cancelNextSync();
@@ -321,11 +310,9 @@ Syncer.prototype.syncFromServer = function() {
self.titlesToBeLoaded[title] = true;
});
$tw.utils.each(updates.deletions,function(title) {
if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {
delete self.tiddlerInfo[title];
self.logger.log("Deleting tiddler missing from server:",title);
self.wiki.deleteTiddler(title);
}
delete self.tiddlerInfo[title];
self.logger.log("Deleting tiddler missing from server:",title);
self.wiki.deleteTiddler(title);
});
if(updates.modifications.length > 0 || updates.deletions.length > 0) {
self.processTaskQueue();
@@ -368,11 +355,9 @@ Syncer.prototype.syncFromServer = function() {
}
// Delete any tiddlers that were previously reported but missing this time
$tw.utils.each(previousTitles,function(title) {
if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {
delete self.tiddlerInfo[title];
self.logger.log("Deleting tiddler missing from server:",title);
self.wiki.deleteTiddler(title);
}
delete self.tiddlerInfo[title];
self.logger.log("Deleting tiddler missing from server:",title);
self.wiki.deleteTiddler(title);
});
self.processTaskQueue();
});
@@ -413,27 +398,15 @@ Syncer.prototype.handleLoginEvent = function() {
var self = this;
this.getStatus(function(err,isLoggedIn,username) {
if(!err && !isLoggedIn) {
if(self.syncadaptor && self.syncadaptor.displayLoginPrompt) {
self.syncadaptor.displayLoginPrompt(self);
} else {
self.displayLoginPrompt();
}
}
});
};
/*
Dispay a password prompt
*/
Syncer.prototype.displayLoginPrompt = function() {
var self = this;
var promptInfo = $tw.passwordPrompt.createPrompt({
serviceName: $tw.language.getString("LoginToTiddlySpace"),
callback: function(data) {
self.login(data.username,data.password,function(err,isLoggedIn) {
self.syncFromServer();
$tw.passwordPrompt.createPrompt({
serviceName: $tw.language.getString("LoginToTiddlySpace"),
callback: function(data) {
self.login(data.username,data.password,function(err,isLoggedIn) {
self.syncFromServer();
});
return true; // Get rid of the password prompt
}
});
return true; // Get rid of the password prompt
}
});
};
@@ -551,7 +524,7 @@ Syncer.prototype.chooseNextTask = function() {
tiddlerInfo = this.tiddlerInfo[title];
if(tiddler) {
// If the tiddler is not known on the server, or has been modified locally no more recently than the threshold then it needs to be saved to the server
var hasChanged = !tiddlerInfo || this.wiki.getChangeCount(title) > tiddlerInfo.changeCount,
var hasChanged = !tiddlerInfo || $tw.wiki.getChangeCount(title) > tiddlerInfo.changeCount,
isReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;
if(hasChanged) {
if(isReadyToSave) {
@@ -608,8 +581,6 @@ SaveTiddlerTask.prototype.run = function(callback) {
};
// Invoke the callback
callback(null);
},{
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
});
} else {
this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist");
@@ -633,10 +604,6 @@ DeleteTiddlerTask.prototype.run = function(callback) {
}
// Remove the info stored about this tiddler
delete self.syncer.tiddlerInfo[self.title];
if($tw.boot.files){
// Remove the tiddler from $tw.boot.files
delete $tw.boot.files[self.title];
}
// Invoke the callback
callback(null);
},{

View File

@@ -41,7 +41,7 @@ exports.upgrade = function(wiki,titles,tiddlers) {
// Check if we're dealing with a plugin
if(incomingTiddler && incomingTiddler["plugin-type"]) {
// Check whether the plugin contains JS modules
var requiresReload = wiki.doesPluginInfoRequireReload(JSON.parse(incomingTiddler.text)) ? (wiki.getTiddlerText("$:/language/ControlPanel/Plugins/PluginWillRequireReload") + " ") : "";
var requiresReload = $tw.wiki.doesPluginInfoRequireReload(JSON.parse(incomingTiddler.text)) ? ($tw.wiki.getTiddlerText("$:/language/ControlPanel/Plugins/PluginWillRequireReload") + " ") : "";
messages[title] = requiresReload;
if(incomingTiddler.version) {
// Upgrade the incoming plugin if it is in the upgrade library
@@ -57,7 +57,7 @@ exports.upgrade = function(wiki,titles,tiddlers) {
// Reject the incoming plugin by blanking all its fields
if($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {
tiddlers[title] = Object.create(null);
messages[title] = $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});
messages[title] = requiresReload + $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});
return;
}
}

View File

@@ -20,27 +20,15 @@
for (i; i < string.length; i++) {
charCode = string.charCodeAt(i);
if (charCode < 128) {
if (charCode < 128)
output += String.fromCharCode(charCode);
} else if ((charCode > 127) && (charCode < 2048)) {
output += String.fromCharCode((charCode >> 6) | 192);
else if ((charCode > 127) && (charCode < 2048))
output += String.fromCharCode((charCode >> 6) | 192),
output += String.fromCharCode((charCode & 63) | 128);
} else if ((charCode > 55295) && (charCode < 57344) && string.length > i+1) {
// Surrogate pair
var hiSurrogate = charCode;
var loSurrogate = string.charCodeAt(i+1);
i++; // Skip the low surrogate on the next loop pass
var codePoint = (((hiSurrogate - 55296) << 10) | (loSurrogate - 56320)) + 65536;
output += String.fromCharCode((codePoint >> 18) | 240);
output += String.fromCharCode(((codePoint >> 12) & 63) | 128);
output += String.fromCharCode(((codePoint >> 6) & 63) | 128);
output += String.fromCharCode((codePoint & 63) | 128);
} else {
// Not a surrogate pair, or a dangling surrogate without its partner that we'll just encode as-is
output += String.fromCharCode((charCode >> 12) | 224);
output += String.fromCharCode(((charCode >> 6) & 63) | 128);
else
output += String.fromCharCode((charCode >> 12) | 224),
output += String.fromCharCode(((charCode >> 6) & 63) | 128),
output += String.fromCharCode((charCode & 63) | 128);
}
}
return output;
@@ -53,21 +41,15 @@
while (i < string.length) {
charCode = string.charCodeAt(i);
if (charCode < 128) {
if (charCode < 128)
output += String.fromCharCode(charCode),
i++;
} else if ((charCode > 191) && (charCode < 224)) {
output += String.fromCharCode(((charCode & 31) << 6) | (string.charCodeAt(i + 1) & 63));
else if ((charCode > 191) && (charCode < 224))
output += String.fromCharCode(((charCode & 31) << 6) | (string.charCodeAt(i + 1) & 63)),
i += 2;
} else if ((charCode > 223) && (charCode < 240)) {
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63));
else
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63)),
i += 3;
} else {
var codePoint = ((charCode & 7) << 18) | ((string.charCodeAt(i + 1) & 63) << 12) | ((string.charCodeAt(i + 2) & 63) << 6) | (string.charCodeAt(i + 3) & 63);
// output += String.fromCodePoint(codePoint); // Can't do this because Internet Explorer doesn't have String.fromCodePoint
output += String.fromCharCode(((codePoint - 65536) >> 10) + 55296) + String.fromCharCode(((codePoint - 65536) & 1023) + 56320); // So we do this instead
i += 4;
}
}
return output;

View File

@@ -6,4 +6,4 @@
//
// copyright: MIT
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&"function"===o.define&&o.define.amd?define("utf8",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if("string"!=typeof r)return r;r=r.replace(/\r\n/g,"\n");for(var e,o="",t=0;t<r.length;t++)if((e=r.charCodeAt(t))<128)o+=String.fromCharCode(e);else if(e>127&&e<2048)o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128);else if(e>55295&&e<57344&&r.length>t+1){var i=e,n=r.charCodeAt(t+1);t++;var d=65536+(i-55296<<10|n-56320);o+=String.fromCharCode(d>>18|240),o+=String.fromCharCode(d>>12&63|128),o+=String.fromCharCode(d>>6&63|128),o+=String.fromCharCode(63&d|128)}else o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128);return o},decode:function(r){if("string"!=typeof r)return r;for(var e="",o=0,t=0;o<r.length;)if((t=r.charCodeAt(o))<128)e+=String.fromCharCode(t),o++;else if(t>191&&t<224)e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2;else if(t>223&&t<240)e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3;else{var i=(7&t)<<18|(63&r.charCodeAt(o+1))<<12|(63&r.charCodeAt(o+2))<<6|63&r.charCodeAt(o+3);e+=String.fromCharCode(55296+(i-65536>>10))+String.fromCharCode(56320+(i-65536&1023)),o+=4}return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var i=0;i<t.length;i++)o[t[i]]=o.require(t[i]);o.module.exports=e.apply(o)}else void 0!==o.define&&"function"===o.define&&o.define.amd?define("base64",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=e.encode(r);for(var t,i,n,d,f,a,h,C="",c=0;c<r.length;)d=(t=r.charCodeAt(c++))>>2,f=(3&t)<<4|(i=r.charCodeAt(c++))>>4,a=(15&i)<<2|(n=r.charCodeAt(c++))>>6,h=63&n,isNaN(i)?a=h=64:isNaN(n)&&(h=64),C+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return C},decode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var t,i,n,d,f,a,h="",C=0;C<r.length;)t=o.indexOf(r.charAt(C++))<<2|(d=o.indexOf(r.charAt(C++)))>>4,i=(15&d)<<4|(f=o.indexOf(r.charAt(C++)))>>2,n=(3&f)<<6|(a=o.indexOf(r.charAt(C++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(i)),64!=a&&(h+=String.fromCharCode(n));return e.decode(h)}}},this,["utf8"]);
!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&"function"===o.define&&o.define.amd?define("utf8",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if("string"!=typeof r)return r;r=r.replace(/\r\n/g,"\n");for(var e,o="",t=0;t<r.length;t++)(e=r.charCodeAt(t))<128?o+=String.fromCharCode(e):e>127&&e<2048?(o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128)):(o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128));return o},decode:function(r){if("string"!=typeof r)return r;for(var e="",o=0,t=0;o<r.length;)(t=r.charCodeAt(o))<128?(e+=String.fromCharCode(t),o++):t>191&&t<224?(e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2):(e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3);return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var n=0;n<t.length;n++)o[t[n]]=o.require(t[n]);o.module.exports=e.apply(o)}else void 0!==o.define&&"function"===o.define&&o.define.amd?define("base64",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=e.encode(r);for(var t,n,i,d,f,a,h,c="",u=0;u<r.length;)d=(t=r.charCodeAt(u++))>>2,f=(3&t)<<4|(n=r.charCodeAt(u++))>>4,a=(15&n)<<2|(i=r.charCodeAt(u++))>>6,h=63&i,isNaN(n)?a=h=64:isNaN(i)&&(h=64),c+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return c},decode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var t,n,i,d,f,a,h="",c=0;c<r.length;)t=o.indexOf(r.charAt(c++))<<2|(d=o.indexOf(r.charAt(c++)))>>4,n=(15&d)<<4|(f=o.indexOf(r.charAt(c++)))>>2,i=(3&f)<<6|(a=o.indexOf(r.charAt(c++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(n)),64!=a&&(h+=String.fromCharCode(i));return e.decode(h)}}},this,["utf8"]);

View File

@@ -29,23 +29,23 @@ exports.removeChildren = function(node) {
};
exports.hasClass = function(el,className) {
return el && el.hasAttribute && el.hasAttribute("class") && el.getAttribute("class").split(" ").indexOf(className) !== -1;
return el && el.className && el.className.toString().split(" ").indexOf(className) !== -1;
};
exports.addClass = function(el,className) {
var c = (el.getAttribute("class") || "").split(" ");
var c = el.className.split(" ");
if(c.indexOf(className) === -1) {
c.push(className);
el.setAttribute("class",c.join(" "));
el.className = c.join(" ");
}
};
exports.removeClass = function(el,className) {
var c = (el.getAttribute("class") || "").split(" "),
var c = el.className.split(" "),
p = c.indexOf(className);
if(p !== -1) {
c.splice(p,1);
el.setAttribute("class",c.join(" "));
el.className = c.join(" ");
}
};

View File

@@ -24,16 +24,6 @@ exports.httpRequest = function(options) {
var type = options.type || "GET",
url = options.url,
headers = options.headers || {accept: "application/json"},
hasHeader = function(targetHeader) {
targetHeader = targetHeader.toLowerCase();
var result = false;
$tw.utils.each(headers,function(header,headerTitle,object) {
if(headerTitle.toLowerCase() === targetHeader) {
result = true;
}
});
return result;
},
returnProp = options.returnProp || "responseText",
request = new XMLHttpRequest(),
data = "",
@@ -73,10 +63,10 @@ exports.httpRequest = function(options) {
request.setRequestHeader(headerTitle,header);
});
}
if(data && !hasHeader("Content-Type")) {
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
if(data && !$tw.utils.hop(headers,"Content-type")) {
request.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8");
}
if(!hasHeader("X-Requested-With")) {
if(!$tw.utils.hop(headers,"X-Requested-With")) {
request.setRequestHeader("X-Requested-With","TiddlyWiki");
}
try {

View File

@@ -13,7 +13,6 @@ Modal message mechanism
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
var navigator = require("$:/core/modules/widgets/navigator.js");
var Modal = function(wiki) {
this.wiki = wiki;
@@ -42,12 +41,7 @@ Modal.prototype.display = function(title,options) {
return;
}
// Create the variables
var variables = $tw.utils.extend({
currentTiddler: title,
"tv-story-list": (options.event && options.event.widget ? options.event.widget.getVariable("tv-story-list") : ""),
"tv-history-list": (options.event && options.event.widget ? options.event.widget.getVariable("tv-history-list") : "")
},options.variables);
var variables = $tw.utils.extend({currentTiddler: title},options.variables);
// Create the wrapper divs
var wrapper = this.srcDocument.createElement("div"),
modalBackdrop = this.srcDocument.createElement("div"),
@@ -81,31 +75,6 @@ Modal.prototype.display = function(title,options) {
modalFooter.appendChild(modalFooterHelp);
modalFooter.appendChild(modalFooterButtons);
modalWrapper.appendChild(modalFooter);
var navigatorTree = {
"type": "navigator",
"attributes": {
"story": {
"name": "story",
"type": "string",
"value": variables["tv-story-list"]
},
"history": {
"name": "history",
"type": "string",
"value": variables["tv-history-list"]
}
},
"tag": "$navigator",
"isBlock": true,
"children": []
};
var navigatorWidgetNode = new navigator.navigator(navigatorTree, {
wiki: this.wiki,
document : this.srcDocument,
parentWidget: $tw.rootWidget
});
navigatorWidgetNode.render(modalBody,null);
// Render the title of the message
var headerWidgetNode = this.wiki.makeTranscludeWidget(title,{
field: "subtitle",
@@ -117,7 +86,7 @@ Modal.prototype.display = function(title,options) {
type: "string",
value: title
}}}],
parentWidget: navigatorWidgetNode,
parentWidget: $tw.rootWidget,
document: this.srcDocument,
variables: variables,
importPageMacros: true
@@ -125,12 +94,11 @@ Modal.prototype.display = function(title,options) {
headerWidgetNode.render(headerTitle,null);
// Render the body of the message
var bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{
parentWidget: navigatorWidgetNode,
parentWidget: $tw.rootWidget,
document: this.srcDocument,
variables: variables,
importPageMacros: true
});
bodyWidgetNode.render(modalBody,null);
// Setup the link if present
if(options.downloadLink) {
@@ -167,7 +135,7 @@ Modal.prototype.display = function(title,options) {
value: $tw.language.getString("Buttons/Close/Caption")
}}}
]}],
parentWidget: navigatorWidgetNode,
parentWidget: $tw.rootWidget,
document: this.srcDocument,
variables: variables,
importPageMacros: true

View File

@@ -49,12 +49,7 @@ Handle an event
*/
PageScroller.prototype.handleEvent = function(event) {
if(event.type === "tm-scroll") {
if(event.paramObject && event.paramObject.selector) {
this.scrollSelectorIntoView(null,event.paramObject.selector);
} else {
this.scrollIntoView(event.target);
}
return false; // Event was handled
return this.scrollIntoView(event.target);
}
return true;
};
@@ -122,14 +117,6 @@ PageScroller.prototype.scrollIntoView = function(element,callback) {
drawFrame();
};
PageScroller.prototype.scrollSelectorIntoView = function(baseElement,selector,callback) {
baseElement = baseElement || document.body;
var element = baseElement.querySelector(selector);
if(element) {
this.scrollIntoView(element,callback);
}
};
exports.PageScroller = PageScroller;
})();

View File

@@ -21,32 +21,14 @@ var bumpSequenceNumber = function(object) {
}
};
var TW_Node = function (){
throw TypeError("Illegal constructor");
};
Object.defineProperty(TW_Node.prototype, 'ELEMENT_NODE', {
get: function() {
return 1;
}
});
Object.defineProperty(TW_Node.prototype, 'TEXT_NODE', {
get: function() {
return 3;
}
});
var TW_TextNode = function(text) {
bumpSequenceNumber(this);
this.textContent = text + "";
};
TW_TextNode.prototype = Object.create(TW_Node.prototype);
Object.defineProperty(TW_TextNode.prototype, "nodeType", {
get: function() {
return this.TEXT_NODE;
return 3;
}
});
@@ -67,8 +49,6 @@ var TW_Element = function(tag,namespace) {
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
};
TW_Element.prototype = Object.create(TW_Node.prototype);
Object.defineProperty(TW_Element.prototype, "style", {
get: function() {
return this._style;
@@ -89,7 +69,7 @@ Object.defineProperty(TW_Element.prototype, "style", {
Object.defineProperty(TW_Element.prototype, "nodeType", {
get: function() {
return this.ELEMENT_NODE;
return 1;
}
});

View File

@@ -15,33 +15,13 @@ File system utilities
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";
}
srcPath = $tw.utils.removeTrailingSeparator(srcPath);
dstPath = $tw.utils.removeTrailingSeparator(dstPath);
// Create the destination directory
var err = $tw.utils.createDirectory(dstPath);
if(err) {
@@ -204,23 +184,15 @@ exports.deleteEmptyDirs = function(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)
type: the type of the tiddler file (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
originalpath: a preferred filepath if no pathFilters match
wiki: optional wiki for evaluating the pathFilters
*/
exports.generateTiddlerFileInfo = function(tiddler,options) {
var fileInfo = {}, metaExt;
// Propagate the isEditableFile flag
if(options.fileInfo) {
fileInfo.isEditableFile = options.fileInfo.isEditableFile || false;
}
var fileInfo = {};
// 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) {
@@ -246,69 +218,19 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
fileInfo.type = tiddlerType;
fileInfo.hasMetaFile = true;
}
if(options.extFilters) {
// Check for extension override
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
// Take the file extension from the tiddler content type
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
// Generate the filepath
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
extension: metaExt || contentTypeInfo.extension,
extension: contentTypeInfo.extension,
directory: options.directory,
pathFilters: options.pathFilters,
wiki: options.wiki,
fileInfo: options.fileInfo,
originalpath: options.originalpath
wiki: options.wiki
});
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 self = this,
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:
@@ -316,14 +238,12 @@ 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
wiki: optional wiki for evaluating the pathFilters
fileInfo: an existing fileInfo object to check against
*/
exports.generateTiddlerFilepath = function(title,options) {
var self = this,
directory = options.directory || "",
extension = options.extension || "",
originalpath = options.originalpath || "",
filepath;
filepath;
// Check if any of the pathFilters applies
if(options.pathFilters && options.wiki) {
$tw.utils.each(options.pathFilters,function(filter) {
@@ -336,11 +256,8 @@ exports.generateTiddlerFilepath = function(title,options) {
}
});
}
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) {
// If not, generate a base pathname
if(!filepath) {
filepath = title;
// If the filepath already ends in the extension then remove it
if(filepath.substring(filepath.length - extension.length) === extension) {
@@ -349,13 +266,10 @@ exports.generateTiddlerFilepath = function(title,options) {
// Remove any forward or backward slashes so we don't create directories
filepath = filepath.replace(/\/|\\/g,"_");
}
//If the path does not start with "." or ".." and 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,"_");
}
// Don't let the filename start with a dot because such files are invisible on *nix
filepath = filepath.replace(/^\./g,"_");
// Remove any characters that can't be used in cross-platform filenames
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
filepath = $tw.utils.transliterate(filepath.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_"));
// Truncate the filename if it is too long
if(filepath.length > 200) {
filepath = filepath.substr(0,200);
@@ -372,30 +286,12 @@ exports.generateTiddlerFilepath = function(title,options) {
});
}
// Add a uniquifier if the file already exists
var fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
var fullPath,
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, or the wikiTiddlersPath directory,
// then encodeURIComponent() and resolve to tiddler directory
var newPath = fullPath,
encode = (options.fileInfo || {writeError: false}).writeError == true;
if(!encode){
encode = !(fullPath.indexOf(path.resolve(directory)) == 0 ||
fullPath.indexOf(path.resolve($tw.boot.wikiPath)) == 0 ||
fullPath.indexOf($tw.boot.wikiTiddlersPath) == 0);
}
if(encode){
fullPath = path.resolve(directory, encodeURIComponent(fullPath));
}
// Call hook to allow plugins to modify the final path
fullPath = $tw.hooks.invokeHook("th-make-tiddler-path", newPath, fullPath);
// Return the full path to the file
return fullPath;
};
@@ -450,58 +346,4 @@ exports.saveTiddlerToFileSync = function(tiddler,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)) {
return callback(null);
}
// 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),callback);
});
} else {
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);
}
});
};
/*
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) {
return $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);
} else {
return callback(err);
}
}
return callback(null);
});
} else {
return callback(null);
}
};
})();

View File

@@ -1,118 +0,0 @@
/*\
module-type: utils
title: $:/core/modules/utils/linkedlist.js
type: application/javascript
This is a doubly-linked indexed list intended for manipulation, particularly
pushTop, which it does with significantly better performance than an array.
\*/
(function(){
function LinkedList() {
this.clear();
};
LinkedList.prototype.clear = function() {
this.index = Object.create(null);
// LinkedList performs the duty of both the head and tail node
this.next = this;
this.prev = this;
this.length = 0;
};
LinkedList.prototype.remove = function(value) {
if($tw.utils.isArray(value)) {
for(var t=0; t<value.length; t++) {
_removeOne(this,value[t]);
}
} else {
_removeOne(this,value);
}
};
LinkedList.prototype.push = function(/* values */) {
for(var i = 0; i < arguments.length; i++) {
var value = arguments[i];
var node = {value: value};
var preexistingNode = this.index[value];
_linkToEnd(this,node);
if(preexistingNode) {
// We want to keep pointing to the first instance, but we want
// to have that instance (or chain of instances) point to the
// new one.
while (preexistingNode.copy) {
preexistingNode = preexistingNode.copy;
}
preexistingNode.copy = node;
} else {
this.index[value] = node;
}
}
};
LinkedList.prototype.pushTop = function(value) {
if($tw.utils.isArray(value)) {
for(var t=0; t<value.length; t++) {
_removeOne(this,value[t]);
}
this.push.apply(this,value);
} else {
var node = _removeOne(this,value);
if(!node) {
node = {value: value};
this.index[value] = node;
} else {
// Put this node at the end of the copy chain.
var preexistingNode = node;
while(preexistingNode.copy) {
preexistingNode = preexistingNode.copy;
}
// The order of these three statements is important,
// because sometimes preexistingNode == node.
preexistingNode.copy = node;
this.index[value] = node.copy;
node.copy = undefined;
}
_linkToEnd(this,node);
}
};
LinkedList.prototype.each = function(callback) {
for(var ptr = this.next; ptr !== this; ptr = ptr.next) {
callback(ptr.value);
}
};
LinkedList.prototype.toArray = function() {
var output = [];
for(var ptr = this.next; ptr !== this; ptr = ptr.next) {
output.push(ptr.value);
}
return output;
};
function _removeOne(list,value) {
var node = list.index[value];
if(node) {
node.prev.next = node.next;
node.next.prev = node.prev;
list.length -= 1;
// Point index to the next instance of the same value, maybe nothing.
list.index[value] = node.copy;
}
return node;
};
function _linkToEnd(list,node) {
// Sticks the given node onto the end of the list.
list.prev.next = node;
node.prev = list.prev;
list.prev = node;
node.next = list;
list.length += 1;
};
exports.LinkedList = LinkedList;
})();

View File

@@ -53,19 +53,6 @@ exports.warning = function(text) {
exports.log(text,"brown/orange");
};
/*
Log a table of name: value pairs
*/
exports.logTable = function(data) {
if(console.table) {
console.table(data);
} else {
$tw.utils.each(data,function(value,name) {
console.log(name + ": " + value);
});
}
}
/*
Return the integer represented by the str (string).
Return the dflt (default) parameter if str is not a base-10 number.
@@ -107,36 +94,6 @@ exports.trim = function(str) {
}
};
exports.trimPrefix = function(str,unwanted) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/^\s\s*/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('^(' + unwanted + ')+');
return str.replace(regex, '');
}
} else {
return str;
}
};
exports.trimSuffix = function(str,unwanted) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/\s\s*$/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('(' + unwanted + ')+$');
return str.replace(regex, '');
}
} else {
return str;
}
};
/*
Convert a string to sentence case (ie capitalise first letter)
*/
@@ -302,7 +259,7 @@ exports.formatDateString = function(date,template) {
return $tw.utils.pad($tw.utils.getHours12(date));
}],
[/^wYYYY/, function() {
return $tw.utils.pad($tw.utils.getYearForWeekNo(date),4);
return $tw.utils.getYearForWeekNo(date);
}],
[/^hh12/, function() {
return $tw.utils.getHours12(date);
@@ -311,14 +268,7 @@ exports.formatDateString = function(date,template) {
return date.getDate() + $tw.utils.getDaySuffix(date);
}],
[/^YYYY/, function() {
return $tw.utils.pad(date.getFullYear(),4);
}],
[/^aYYYY/, function() {
return $tw.utils.pad(Math.abs(date.getFullYear()),4);
}],
[/^\{era:([^,\|}]*)\|([^}\|]*)\|([^}]*)\}/, function(match) {
var year = date.getFullYear();
return year === 0 ? match[2] : (year < 0 ? match[1] : match[3]);
return date.getFullYear();
}],
[/^0hh/, function() {
return $tw.utils.pad(date.getHours());
@@ -407,7 +357,7 @@ exports.formatDateString = function(date,template) {
$tw.utils.each(matches, function(m) {
var match = m[0].exec(t);
if(match) {
matchString = m[1].call(null,match);
matchString = m[1].call();
t = t.substr(match[0].length);
return false;
}
@@ -564,7 +514,7 @@ exports.escape = function(ch) {
// Turns a string into a legal JavaScript string
// Copied from peg.js, thanks to David Majda
exports.stringify = function(s, rawUnicode) {
exports.stringify = function(s) {
/*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
* literal except for the closing quote character, backslash, carriage return,
@@ -573,21 +523,19 @@ exports.stringify = function(s, rawUnicode) {
*
* For portability, we also escape all non-ASCII characters.
*/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
.replace(/'/g, "\\'") // single quote character
.replace(/\r/g, '\\r') // carriage return
.replace(/\n/g, '\\n') // line feed
.replace(regex, exports.escape); // non-ASCII characters
.replace(/[\x00-\x1f\x80-\uFFFF]/g, exports.escape); // non-ASCII characters
};
// Turns a string into a legal JSON string
// Derived from peg.js, thanks to David Majda
exports.jsonStringify = function(s, rawUnicode) {
exports.jsonStringify = function(s) {
// See http://www.json.org/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
@@ -596,7 +544,7 @@ exports.jsonStringify = function(s, rawUnicode) {
.replace(/\x08/g, '\\b') // backspace
.replace(/\x0c/g, '\\f') // formfeed
.replace(/\t/g, '\\t') // tab
.replace(regex,function(s) {
.replace(/[\x00-\x1f\x80-\uFFFF]/g,function(s) {
return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
}); // non-ASCII characters
};
@@ -853,57 +801,4 @@ exports.getSystemInfo = function(str,ending,position) {
return results.join("\n");
};
exports.parseNumber = function(str) {
return parseFloat(str) || 0;
};
exports.parseInt = function(str) {
return parseInt(str,10) || 0;
};
exports.stringifyNumber = function(num) {
return num + "";
};
exports.makeCompareFunction = function(type,options) {
options = options || {};
var gt = options.invert ? -1 : +1,
lt = options.invert ? +1 : -1,
compare = function(a,b) {
if(a > b) {
return gt ;
} else if(a < b) {
return lt;
} else {
return 0;
}
},
types = {
"number": function(a,b) {
return compare($tw.utils.parseNumber(a),$tw.utils.parseNumber(b));
},
"integer": function(a,b) {
return compare($tw.utils.parseInt(a),$tw.utils.parseInt(b));
},
"string": function(a,b) {
return compare("" + a,"" +b);
},
"date": function(a,b) {
var dateA = $tw.utils.parseDate(a),
dateB = $tw.utils.parseDate(b);
if(!isFinite(dateA)) {
dateA = new Date(0);
}
if(!isFinite(dateB)) {
dateB = new Date(0);
}
return compare(dateA,dateB);
},
"version": function(a,b) {
return $tw.utils.compareVersions(a,b);
}
};
return (types[type] || types[options.defaultType] || types.number);
};
})();

View File

@@ -1,77 +0,0 @@
/*\
title: $:/core/modules/widgets/action-confirm.js
type: application/javascript
module-type: widget
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ConfirmWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ConfirmWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ConfirmWidget.prototype.render = function(parent,nextSibling) {
this.computeAttributes();
this.execute();
this.parentDomNode = parent;
this.renderChildren(parent,nextSibling);
};
/*
Compute the internal state of the widget
*/
ConfirmWidget.prototype.execute = function() {
this.message = this.getAttribute("$message",$tw.language.getString("ConfirmAction"));
this.prompt = (this.getAttribute("$prompt","yes") == "no" ? false : true);
this.makeChildWidgets();
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
ConfirmWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$message"] || changedAttributes["$prompt"]) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
/*
Invoke the action associated with this widget
*/
ConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {
var invokeActions = true,
handled = true;
if(this.prompt) {
invokeActions = confirm(this.message);
}
if(invokeActions) {
handled = this.invokeActions(triggeringWidget,event);
}
return handled;
};
ConfirmWidget.prototype.allowActionPropagation = function() {
return false;
};
exports["action-confirm"] = ConfirmWidget;
})();

View File

@@ -9,7 +9,7 @@ Action widget to create a new tiddler with a unique name and specified fields.
(function(){
/*jslint node: true, browser: true */
/*global $tw:false, require:false, exports:false */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
@@ -36,15 +36,9 @@ Compute the internal state of the widget
*/
CreateTiddlerWidget.prototype.execute = function() {
this.actionBaseTitle = this.getAttribute("$basetitle");
this.hasBase = !!this.actionBaseTitle;
this.actionSaveTitle = this.getAttribute("$savetitle");
this.actionSaveDraftTitle = this.getAttribute("$savedrafttitle");
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
//Following params are new since 5.1.22
this.actionTemplate = this.getAttribute("$template");
this.useTemplate = !!this.actionTemplate;
this.actionOverwrite = this.getAttribute("$overwrite","no");
};
/*
@@ -63,7 +57,7 @@ CreateTiddlerWidget.prototype.refresh = function(changedTiddlers) {
Invoke the action associated with this widget
*/
CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
var title = this.wiki.getTiddlerText("$:/language/DefaultNewTiddlerTitle"), // Get the initial new-tiddler title
var title = this.wiki.generateNewTitle(this.actionBaseTitle),
fields = {},
creationFields,
modificationFields;
@@ -76,22 +70,7 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
creationFields = this.wiki.getCreationFields();
modificationFields = this.wiki.getModificationFields();
}
if(this.hasBase && this.actionOverwrite === "no") {
title = this.wiki.generateNewTitle(this.actionBaseTitle);
} else if (this.hasBase && this.actionOverwrite === "yes") {
title = this.actionBaseTitle
}
// NO $basetitle BUT $template parameter is available
// the title MUST be unique, otherwise the template would be overwritten
if (!this.hasBase && this.useTemplate) {
title = this.wiki.generateNewTitle(this.actionTemplate);
} else if (!this.hasBase && !this.useTemplate) {
// If NO $basetitle AND NO $template use initial title
// DON'T overwrite any stuff
title = this.wiki.generateNewTitle(title);
}
var templateTiddler = this.wiki.getTiddler(this.actionTemplate) || {};
var tiddler = this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));
var tiddler = this.wiki.addTiddler(new $tw.Tiddler(creationFields,fields,modificationFields,{title: title}));
if(this.actionSaveTitle) {
this.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable("currentTiddler"));
}

View File

@@ -1,93 +0,0 @@
/*\
title: $:/core/modules/widgets/action-log.js
type: application/javascript
module-type: widget
Action widget to log debug messages
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var LogWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
LogWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
LogWidget.prototype.render = function(parent,nextSibling) {
this.computeAttributes();
this.execute();
};
LogWidget.prototype.execute = function(){
this.message = this.getAttribute("$$message","debug");
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
this.filter = this.getAttribute("$$filter");
}
/*
Refresh the widget by ensuring our attributes are up to date
*/
LogWidget.prototype.refresh = function(changedTiddlers) {
this.refreshSelf();
return true;
};
/*
Invoke the action associated with this widget
*/
LogWidget.prototype.invokeAction = function(triggeringWidget,event) {
this.log();
return true; // Action was invoked
};
LogWidget.prototype.log = function() {
var data = {},
dataCount,
allVars = {},
filteredVars;
$tw.utils.each(this.attributes,function(attribute,name) {
if(name.substring(0,2) !== "$$") {
data[name] = attribute;
}
});
for(var v in this.variables) {
allVars[v] = this.getVariable(v,{defaultValue:""});
}
if(this.filter) {
filteredVars = this.wiki.compileFilter(this.filter).call(this.wiki,this.wiki.makeTiddlerIterator(allVars));
$tw.utils.each(filteredVars,function(name) {
data[name] = allVars[name];
});
}
dataCount = $tw.utils.count(data);
console.group(this.message);
if(dataCount > 0) {
$tw.utils.logTable(data);
}
if(this.logAll || !dataCount) {
console.groupCollapsed("All variables");
$tw.utils.logTable(allVars);
console.groupEnd();
}
console.groupEnd();
}
exports["action-log"] = LogWidget;
})();

View File

@@ -57,7 +57,7 @@ Invoke the action associated with this widget
ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
// Trigger the popup
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
match = popupLocationRegExp.exec(this.actionCoords || "");
match = popupLocationRegExp.exec(this.actionCoords);
if(match) {
$tw.popup.triggerPopup({
domNode: null,
@@ -70,8 +70,6 @@ ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
title: this.actionState,
wiki: this.wiki
});
} else {
$tw.popup.cancel(0);
}
return true; // Action was invoked
};

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